3b8deeed94413356e36caea14ef071b533bab3e3
[platform/upstream/freerdp.git] / server / Windows / wf_info.c
1 /**\r
2  * FreeRDP: A Remote Desktop Protocol Client\r
3  * FreeRDP Windows Server\r
4  *\r
5  * Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>\r
6  *\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  *\r
11  *     http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  */\r
19 \r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include <stdlib.h>\r
25 \r
26 #include <winpr/tchar.h>\r
27 #include <winpr/windows.h>\r
28 \r
29 #include "wf_info.h"\r
30 #include "wf_update.h"\r
31 #include "wf_mirage.h"\r
32 #include "wf_dxgi.h"\r
33 \r
34 static wfInfo* wfInfoInstance = NULL;\r
35 \r
36 int wf_info_lock(wfInfo* wfi)\r
37 {\r
38         DWORD dRes;\r
39 \r
40         dRes = WaitForSingleObject(wfi->mutex, INFINITE);\r
41 \r
42         switch (dRes)\r
43         {\r
44                 case WAIT_ABANDONED:\r
45                 case WAIT_OBJECT_0:\r
46                         return TRUE;\r
47                         break;\r
48 \r
49                 case WAIT_TIMEOUT:\r
50                         return FALSE;\r
51                         break;\r
52 \r
53                 case WAIT_FAILED:\r
54                         printf("wf_info_lock failed with 0x%08X\n", GetLastError());\r
55                         return -1;\r
56                         break;\r
57         }\r
58 \r
59         return -1;\r
60 }\r
61 \r
62 int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds)\r
63 {\r
64         DWORD dRes;\r
65 \r
66         dRes = WaitForSingleObject(wfi->mutex, dwMilliseconds);\r
67 \r
68         switch (dRes)\r
69         {\r
70                 case WAIT_ABANDONED:\r
71                 case WAIT_OBJECT_0:\r
72                         return TRUE;\r
73                         break;\r
74 \r
75                 case WAIT_TIMEOUT:\r
76                         return FALSE;\r
77                         break;\r
78 \r
79                 case WAIT_FAILED:\r
80                         printf("wf_info_try_lock failed with 0x%08X\n", GetLastError());\r
81                         return -1;\r
82                         break;\r
83         }\r
84 \r
85         return -1;\r
86 }\r
87 \r
88 int wf_info_unlock(wfInfo* wfi)\r
89 {\r
90         if (ReleaseMutex(wfi->mutex) == 0)\r
91         {\r
92                 printf("wf_info_unlock failed with 0x%08X\n", GetLastError());\r
93                 return -1;\r
94         }\r
95 \r
96         return TRUE;\r
97 }\r
98 \r
99 wfInfo* wf_info_init()\r
100 {\r
101         wfInfo* wfi;\r
102 \r
103 /*\r
104         OSVERSIONINFOEX osvi;\r
105         SYSTEM_INFO si;\r
106         BOOL bOsVersionInfoEx;\r
107         */\r
108 \r
109         wfi = (wfInfo*) malloc(sizeof(wfInfo));\r
110         ZeroMemory(wfi, sizeof(wfInfo));\r
111 \r
112         if (wfi != NULL)\r
113         {\r
114                 HKEY hKey;\r
115                 LONG status;\r
116                 DWORD dwType;\r
117                 DWORD dwSize;\r
118                 DWORD dwValue;\r
119 \r
120                 wfi->mutex = CreateMutex(NULL, FALSE, NULL);\r
121 \r
122                 if (wfi->mutex == NULL) \r
123                 {\r
124                         _tprintf(_T("CreateMutex error: %d\n"), GetLastError());\r
125                 }\r
126 \r
127                 wfi->updateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
128                 printf("updateEvent created\n");\r
129 \r
130                 wfi->updateSemaphore = CreateSemaphore(NULL, 0, 32, NULL);\r
131 \r
132                 wfi->updateThread = CreateThread(NULL, 0, wf_update_thread, wfi, CREATE_SUSPENDED, NULL);\r
133 \r
134                 if (!wfi->updateThread)\r
135                 {\r
136                         _tprintf(_T("Failed to create update thread\n"));\r
137                 }\r
138 \r
139                 wfi->peers = (freerdp_peer**) malloc(sizeof(freerdp_peer*) * 32);\r
140 \r
141                 //Set FPS\r
142                 wfi->framesPerSecond = 24;\r
143 \r
144                 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);\r
145                 if (status == ERROR_SUCCESS)\r
146                 {\r
147                         if (RegQueryValueEx(hKey, _T("FramesPerSecond"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)\r
148                                 wfi->framesPerSecond = dwValue;         \r
149                 }\r
150                 RegCloseKey(hKey);\r
151 \r
152                 //Set input toggle\r
153                 wfi->input_disabled = FALSE;\r
154 \r
155                 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\Server"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);\r
156                 if (status == ERROR_SUCCESS)\r
157                 {\r
158                         if (RegQueryValueEx(hKey, _T("DisableInput"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)\r
159                         {\r
160                                 if (dwValue != 0)\r
161                                         wfi->input_disabled = TRUE;\r
162                         }\r
163                 }\r
164                 RegCloseKey(hKey);\r
165 \r
166                 //detect windows version\r
167                 /*\r
168                 ZeroMemory(&si, sizeof(SYSTEM_INFO));\r
169                 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));\r
170 \r
171                 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\r
172                 bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);\r
173 \r
174                 wfi->win8 = FALSE;\r
175                 if(bOsVersionInfoEx != 0 )\r
176                 {\r
177                         if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && \r
178                         osvi.dwMajorVersion > 4 )\r
179                         {\r
180                                 if ( osvi.dwMajorVersion == 6 && \r
181                                         osvi.dwMinorVersion == 2)\r
182                                 {\r
183                                         wfi->win8 = TRUE;\r
184                                 }\r
185                         }\r
186                 }\r
187                 */\r
188         }\r
189 \r
190         return wfi;\r
191 }\r
192 \r
193 wfInfo* wf_info_get_instance()\r
194 {\r
195         if (wfInfoInstance == NULL)\r
196                 wfInfoInstance = wf_info_init();\r
197 \r
198         return wfInfoInstance;\r
199 }\r
200 \r
201 void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)\r
202 {\r
203         if (wf_info_lock(wfi) > 0)\r
204         {\r
205                 context->info = wfi;\r
206                 context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
207 \r
208 #ifdef WITH_WIN8\r
209                 if (wfi->peerCount == 0)\r
210                         wf_dxgi_init(wfi);\r
211 #else\r
212                 wf_mirror_driver_activate(wfi);\r
213 #endif\r
214 \r
215                 wfi->peers[wfi->peerCount++] = ((rdpContext*) context)->peer;\r
216 \r
217                 printf("Registering Peer: %d\n", wfi->peerCount);\r
218 \r
219                 wf_info_unlock(wfi);\r
220         }\r
221 }\r
222 \r
223 void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context)\r
224 {\r
225         if (wf_info_lock(wfi) > 0)\r
226         {\r
227                 wfi->peers[--(wfi->peerCount)] = NULL;\r
228                 CloseHandle(context->updateEvent);\r
229 \r
230                 printf("Unregistering Peer: %d\n", wfi->peerCount);\r
231 \r
232 #ifdef WITH_WIN8\r
233                 if (wfi->peerCount == 0)\r
234                         wf_dxgi_cleanup(wfi);\r
235 #endif\r
236 \r
237                 wf_info_unlock(wfi);\r
238         }\r
239 }\r
240 \r
241 BOOL wf_info_have_updates(wfInfo* wfi)\r
242 {\r
243 #ifdef WITH_WIN8\r
244         if(wfi->framesWaiting == 0)\r
245                 return FALSE;\r
246 #else\r
247         if (wfi->nextUpdate == wfi->lastUpdate)\r
248                 return FALSE;\r
249 #endif\r
250         return TRUE;\r
251 }\r
252 \r
253 void wf_info_update_changes(wfInfo* wfi)\r
254 {\r
255 #ifdef WITH_WIN8\r
256         wf_dxgi_nextFrame(wfi, wfi->framesPerSecond / 1000);\r
257 #else\r
258         GETCHANGESBUF* buf;\r
259 \r
260         buf = (GETCHANGESBUF*) wfi->changeBuffer;\r
261         wfi->nextUpdate = buf->buffer->counter;\r
262 #endif\r
263 }\r
264 \r
265 void wf_info_find_invalid_region(wfInfo* wfi)\r
266 {\r
267 #ifdef WITH_WIN8\r
268         wf_dxgi_getInvalidRegion(&wfi->invalid);\r
269 #else\r
270         int i;\r
271         GETCHANGESBUF* buf;\r
272 \r
273         buf = (GETCHANGESBUF*) wfi->changeBuffer;\r
274 \r
275         for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF)\r
276         {\r
277                 UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect);\r
278         }\r
279 #endif\r
280 \r
281         if (wfi->invalid.left < 0)\r
282                 wfi->invalid.left = 0;\r
283 \r
284         if (wfi->invalid.top < 0)\r
285                 wfi->invalid.top = 0;\r
286 \r
287         if (wfi->invalid.right >= wfi->width)\r
288                 wfi->invalid.right = wfi->width - 1;\r
289 \r
290         if (wfi->invalid.bottom >= wfi->height)\r
291                 wfi->invalid.bottom = wfi->height - 1;\r
292 }\r
293 \r
294 void wf_info_clear_invalid_region(wfInfo* wfi)\r
295 {\r
296         wfi->lastUpdate = wfi->nextUpdate;\r
297         SetRectEmpty(&wfi->invalid);\r
298 }\r
299 \r
300 void wf_info_invalidate_full_screen(wfInfo* wfi)\r
301 {\r
302         SetRect(&wfi->invalid, 0, 0, wfi->width, wfi->height);\r
303 }\r
304 \r
305 BOOL wf_info_have_invalid_region(wfInfo* wfi)\r
306 {\r
307         return IsRectEmpty(&wfi->invalid);\r
308 }\r
309 \r
310 void wf_info_getScreenData(wfInfo* wfi, long* width, long* height, uint8** pBits, int* pitch)\r
311 {\r
312         *width = (wfi->invalid.right - wfi->invalid.left);\r
313         *height = (wfi->invalid.bottom - wfi->invalid.top);\r
314 \r
315 #ifdef WITH_WIN8\r
316         wf_dxgi_getPixelData(wfi, pBits, pitch, &wfi->invalid);\r
317 #else\r
318         {\r
319                 long offset;\r
320                 GETCHANGESBUF* changes;\r
321                 changes = (GETCHANGESBUF*) wfi->changeBuffer;\r
322 \r
323                 *width += 1;\r
324                 *height += 1;\r
325 \r
326                 offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4);\r
327                 *pBits = ((uint8*) (changes->Userbuffer)) + offset;\r
328                 *pitch = wfi->width * 4;\r
329         }\r
330 #endif\r
331 }\r