1 /**************************************************************************
2 * Copyright (C) 2005-2020 by Oleksandr Shneyder *
3 * <o.shneyder@phoca-gmbh.de> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17
18 #ifndef _WIN32_WINDOWS
19 #define _WIN32_WINDOWS 0x0500
20 #define _WIN32_WINNT 0x0500
21 #define WINVER 0x0500
22 #endif
23 #include "x2goclientconfig.h"
24 #ifdef Q_OS_WIN
25 #include <winsock2.h>
26 #include <windows.h>
27 #include <winerror.h>
28 #include <sddl.h>
29 #include "wapi.h"
30 #include "x2gologdebug.h"
31
32
wapiSetFSWindow(HWND hWnd,const QRect & desktopGeometry)33 long wapiSetFSWindow ( HWND hWnd, const QRect& desktopGeometry )
34 {
35 SetWindowLong(hWnd, GWL_STYLE,
36 WS_VISIBLE);
37 SetWindowLong(hWnd, GWL_EXSTYLE,
38 0);
39 SetWindowPos ( hWnd, HWND_TOPMOST, desktopGeometry.x(),
40 desktopGeometry.y(),
41 desktopGeometry.width(),
42 desktopGeometry.height(),
43 0);
44 return WS_VISIBLE;
45 }
46
wapiRestoreWindow(HWND hWnd,long style,const QRect & desktopGeometry)47 void wapiRestoreWindow( HWND hWnd, long style, const QRect& desktopGeometry )
48 {
49 SetWindowLong ( hWnd, GWL_STYLE,style);
50 SetWindowPos ( hWnd, HWND_TOP, desktopGeometry.x(),
51 desktopGeometry.y(),
52 desktopGeometry.width(),
53 desktopGeometry.height(),
54 SWP_FRAMECHANGED );
55 }
56
wapiHideFromTaskBar(HWND wnd)57 void wapiHideFromTaskBar ( HWND wnd )
58 {
59 ShowWindow ( wnd, SW_HIDE ) ;
60 SetWindowLong ( wnd, GWL_EXSTYLE, GetWindowLong ( wnd, GWL_EXSTYLE ) &
61 ~WS_EX_APPWINDOW );
62 SetWindowLong ( wnd, GWL_EXSTYLE, GetWindowLong ( wnd, GWL_EXSTYLE ) |
63 WS_EX_TOOLWINDOW );
64 ShowWindow ( wnd, SW_SHOW ) ;
65 }
66
wapiSetParent(HWND child,HWND par)67 HWND wapiSetParent ( HWND child, HWND par )
68 {
69 HWND wn=SetParent ( child,par );
70 if ( par )
71 SetWindowLong ( child, GWL_STYLE,
72 GetWindowLong ( child, GWL_STYLE ) | WS_CHILD );
73 else
74 SetWindowLong (
75 child, GWL_STYLE,
76 GetWindowLong ( child, GWL_STYLE ) &~ WS_CHILD );
77 SetWindowLong ( child, GWL_STYLE,
78 GetWindowLong ( child, GWL_STYLE ) | WS_POPUP );
79 return wn;
80 }
81
wapiClientRect(HWND wnd,QRect & rect)82 bool wapiClientRect ( HWND wnd, QRect& rect )
83 {
84 RECT rcWindow;
85 if ( GetClientRect ( wnd,&rcWindow ) )
86 {
87 rect.setCoords ( rcWindow.left,
88 rcWindow.top,
89 rcWindow.right,rcWindow.bottom );
90 return true;
91 }
92 return false;
93 }
94
wapiWindowRectWithoutDecoration(HWND wnd,QRect & rect)95 bool wapiWindowRectWithoutDecoration ( HWND wnd, QRect& rect )
96 {
97 RECT rcWindow;
98 if ( GetClientRect ( wnd,&rcWindow ) )
99 {
100 POINT pnt;
101 pnt.x=0;
102 pnt.y=0;
103 ClientToScreen(wnd,&pnt);
104 rect.setRect ( pnt.x,
105 pnt.y,
106 rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top );
107 return true;
108 }
109 return false;
110 }
111
112
wapiWindowRect(HWND wnd,QRect & rect)113 bool wapiWindowRect ( HWND wnd, QRect& rect )
114 {
115 RECT rcWindow;
116 if ( GetWindowRect ( wnd,&rcWindow ) )
117 {
118 rect.setCoords ( rcWindow.left,
119 rcWindow.top,
120 rcWindow.right,rcWindow.bottom );
121 return true;
122 }
123 return false;
124 }
125
wapiGetBorders(HWND wnd,int & vBorder,int & hBorder,int & barHeight)126 bool wapiGetBorders ( HWND wnd, int& vBorder, int& hBorder, int& barHeight )
127 {
128 WINDOWINFO wifo;
129 wifo.cbSize=sizeof ( WINDOWINFO );
130 if ( !GetWindowInfo ( wnd,&wifo ) )
131 return false;
132 vBorder=wifo.cxWindowBorders;
133 hBorder=wifo.cyWindowBorders;
134 TITLEBARINFO bifo;
135 bifo.cbSize=sizeof ( TITLEBARINFO );
136 if ( !GetTitleBarInfo ( wnd,&bifo ) )
137 return false;
138 barHeight=bifo.rcTitleBar.bottom-bifo.rcTitleBar.top;
139
140 return true;
141
142 }
143
wapiShowWindow(HWND wnd,wapiCmdShow nCmdShow)144 bool wapiShowWindow ( HWND wnd, wapiCmdShow nCmdShow )
145 {
146 int cmd=WAPI_SHOWNORMAL;
147 switch ( nCmdShow )
148 {
149 case WAPI_FORCEMINIMIZE:
150 cmd=SW_FORCEMINIMIZE;
151 break;
152 case WAPI_HIDE:
153 cmd=SW_HIDE;
154 break;
155 case WAPI_MAXIMIZE:
156 cmd=SW_MAXIMIZE;
157 break;
158 case WAPI_MINIMIZE:
159 cmd=SW_MINIMIZE;
160 break;
161 case WAPI_RESTORE:
162 cmd=SW_RESTORE;
163 break;
164 case WAPI_SHOW:
165 cmd=SW_SHOW;
166 break;
167 case WAPI_SHOWDEFAULT:
168 cmd=SW_SHOWDEFAULT;
169 break;
170 case WAPI_SHOWMAXIMIZED:
171 cmd=SW_SHOWMAXIMIZED;
172 break;
173 case WAPI_SHOWMINIMIZED:
174 cmd=SW_SHOWMINIMIZED;
175 break;
176 case WAPI_SHOWMINNOACTIVE:
177 cmd=SW_SHOWMINNOACTIVE;
178 break;
179 case WAPI_SHOWNA:
180 cmd=SW_SHOWNA;
181 break;
182 case WAPI_SHOWNOACTIVATE:
183 cmd=SW_SHOWNOACTIVATE;
184 break;
185 case WAPI_SHOWNORMAL:
186 cmd=SW_SHOWNORMAL;
187 break;
188 }
189
190 return ShowWindow ( wnd, cmd );
191 }
192
wapiUpdateWindow(HWND wnd)193 bool wapiUpdateWindow ( HWND wnd )
194 {
195 return RedrawWindow ( wnd,0,0,RDW_INVALIDATE );
196 }
197
wapiMoveWindow(HWND wnd,int x,int y,int width,int height,bool repaint)198 bool wapiMoveWindow ( HWND wnd, int x, int y, int width, int height,
199 bool repaint )
200 {
201 return MoveWindow ( wnd, x, y, width, height, repaint );
202 }
203
wapiFindWindow(const ushort * className,const ushort * text)204 HWND wapiFindWindow ( const ushort * className, const ushort * text )
205 {
206 return FindWindowEx ( 0,0, ( LPCTSTR ) className, ( LPCTSTR ) text );
207 }
208
wapiSetWindowText(HWND wnd,const QString & text)209 bool wapiSetWindowText( HWND wnd, const QString& text)
210 {
211 return SetWindowText(wnd, (LPCTSTR)text.utf16() );
212 }
213
wapiSetWindowIcon(HWND wnd,const QPixmap & icon)214 void wapiSetWindowIcon ( HWND wnd, const QPixmap& icon)
215 {
216 int iconx=GetSystemMetrics(SM_CXICON);
217 int icony=GetSystemMetrics(SM_CYICON);
218 int smallx=GetSystemMetrics(SM_CXSMICON);
219 int smally=GetSystemMetrics(SM_CXSMICON);
220
221 HICON largeIcon=0;
222 HICON smallIcon=0;
223
224 largeIcon=icon.scaled(iconx,icony, Qt::IgnoreAspectRatio,Qt::SmoothTransformation).toWinHICON ();
225 smallIcon=icon.scaled(smallx,smally, Qt::IgnoreAspectRatio,Qt::SmoothTransformation).toWinHICON ();
226
227 x2goDebug<<"Large icon: "<<largeIcon<<iconx<<"x"<<icony;
228 x2goDebug<<"Small icon: "<<smallIcon<<smallx<<"x"<<smally;
229 int rez=SetClassLong(wnd,GCL_HICON, (LONG)largeIcon);
230 if (!rez)
231 x2goDebug<<"ERROR: "<<GetLastError()<<endl;
232 rez=SetClassLong(wnd,GCL_HICONSM,(LONG)smallIcon);
233 if (!rez)
234 x2goDebug<<"ERROR: "<<GetLastError()<<endl;
235 /* ShowWindow(wnd, SW_HIDE);
236 ShowWindow(wnd, SW_SHOW);*/
237 }
238
wapiShortFileName(const QString & longName)239 QString wapiShortFileName ( const QString& longName )
240 {
241 long length = 0;
242 TCHAR* buffer = NULL;
243
244 length = GetShortPathName ( ( LPCTSTR ) longName.utf16(), NULL, 0 );
245 if ( !length )
246 {
247 return QString::null;
248 }
249
250 buffer = new TCHAR[length];
251 length = GetShortPathName ( ( LPCTSTR ) longName.utf16(),
252 buffer,length );
253 if ( !length )
254 {
255 delete []buffer;
256 return QString::null;
257 }
258 QString spath=QString::fromUtf16 ( ( const ushort* ) buffer );
259 delete []buffer;
260 return spath;
261 }
262
263
wapiGetDriveByLabel(const QString & label)264 QString wapiGetDriveByLabel(const QString& label)
265 {
266 int len=GetLogicalDriveStrings(0,0);
267 if (len>0)
268 {
269 TCHAR* buf=new TCHAR[len+1];
270 len=GetLogicalDriveStrings(len,buf);
271 for (int i=0; i<len; i+=4)
272 {
273 QString drive=QString::fromUtf16 ( ( const ushort* ) buf+i );
274 x2goDebug<<"Drive: "<<drive;
275 TCHAR vol[MAX_PATH+1];
276 TCHAR fs[MAX_PATH+1];
277 GetVolumeInformation(buf+i,vol,MAX_PATH,0,0,0,fs,MAX_PATH);
278 QString volume=QString::fromUtf16 ( ( const ushort* ) vol );
279 x2goDebug<<"Volume: "<<volume<<
280 "; fs: "<<QString::fromUtf16 ( ( const ushort* ) fs );
281 if (!volume.compare(label,Qt::CaseInsensitive))
282 {
283 x2goDebug<<"matched! ";
284
285 delete []buf;
286 return drive.replace(":\\","");
287 }
288 }
289 delete []buf;
290 }
291
292 return label;
293 }
294
295
getNameFromSid(PSID psid,QString * systemName)296 QString getNameFromSid ( PSID psid, QString* systemName )
297 {
298 DWORD length=0;
299 DWORD dlength=0;
300 TCHAR* name=0;
301 TCHAR* sysName=0;
302 SID_NAME_USE eUse;
303
304 LookupAccountSid ( 0,psid,
305 name,&length,sysName,&dlength,&eUse );
306 if ( !length )
307 {
308 return QString::null;
309 }
310
311 name=new TCHAR[length];
312 sysName=new TCHAR[dlength];
313
314 if ( ! LookupAccountSid ( 0,psid,
315 name,&length,sysName,
316 &dlength,&eUse ) )
317 {
318 delete []name;
319 delete []sysName;
320 return QString::null;
321 }
322
323 QString strName=QString::fromUtf16 (
324 ( const ushort* ) name );
325 if ( systemName )
326 *systemName=QString::fromUtf16 (
327 ( const ushort* ) sysName );
328 delete []sysName;
329 delete []name;
330 return strName;
331 }
332
getStringFromSid(PSID psid)333 QString getStringFromSid ( PSID psid )
334 {
335 LPTSTR stringSid;
336 ConvertSidToStringSid ( psid,
337 &stringSid );
338 QString str=QString::fromUtf16 (
339 ( const ushort* ) stringSid );
340 LocalFree ( stringSid );
341 return str;
342 }
343
wapiAccountInfo(QString * retSid,QString * retUname,QString * primaryGroupSID,QString * primaryGroupName,QString * retSysName)344 bool wapiAccountInfo ( QString* retSid, QString* retUname,
345 QString* primaryGroupSID, QString* primaryGroupName,
346 QString* retSysName )
347 {
348 HANDLE hToken;
349 if ( !OpenProcessToken ( GetCurrentProcess(),
350 TOKEN_QUERY, &hToken ) )
351 {
352 return false;
353 }
354 if ( primaryGroupSID || primaryGroupName )
355 {
356 PTOKEN_PRIMARY_GROUP pGroupInfo=0;
357 DWORD dwResult=0;
358 DWORD dwSize=0;
359 if ( !GetTokenInformation ( hToken, TokenPrimaryGroup,
360 NULL, dwSize, &dwSize ) )
361 {
362 dwResult = GetLastError();
363 if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
364 {
365 CloseHandle ( hToken );
366 return false;
367 }
368 }
369 pGroupInfo = ( PTOKEN_PRIMARY_GROUP ) GlobalAlloc ( GPTR,
370 dwSize );
371
372 if ( ! GetTokenInformation ( hToken, TokenPrimaryGroup,
373 pGroupInfo,
374 dwSize, &dwSize ) )
375 {
376 if ( pGroupInfo )
377 GlobalFree ( pGroupInfo );
378 CloseHandle ( hToken );
379 return false;
380 }
381
382 if ( primaryGroupSID )
383 {
384 *primaryGroupSID=getStringFromSid (
385 pGroupInfo->PrimaryGroup );
386 }
387 if ( primaryGroupName )
388 {
389 *primaryGroupName=getNameFromSid (
390 pGroupInfo->PrimaryGroup,
391 retSysName );
392 }
393
394 if ( pGroupInfo )
395 GlobalFree ( pGroupInfo );
396 }
397 if ( retSid || retUname )
398 {
399 PTOKEN_USER pUserInfo=0;
400 DWORD dwResult=0;
401 DWORD dwSize=0;
402
403 if ( !GetTokenInformation ( hToken, TokenUser,
404 NULL, dwSize, &dwSize ) )
405 {
406 dwResult = GetLastError();
407 if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
408 {
409 CloseHandle ( hToken );
410 return false;
411 }
412 }
413 pUserInfo = ( PTOKEN_USER ) GlobalAlloc ( GPTR,
414 dwSize );
415
416 if ( ! GetTokenInformation ( hToken, TokenUser,
417 pUserInfo,
418 dwSize, &dwSize ) )
419 {
420 if ( pUserInfo )
421 GlobalFree ( pUserInfo );
422 CloseHandle ( hToken );
423 return false;
424 }
425
426 if ( retSid )
427 {
428 *retSid=getStringFromSid (
429 pUserInfo->User.Sid );
430 }
431 if ( retUname )
432 {
433 *retUname=getNameFromSid (
434 pUserInfo->User.Sid,
435 retSysName );
436 }
437 if ( pUserInfo )
438 GlobalFree ( pUserInfo );
439 }
440 CloseHandle ( hToken );
441 return true;
442 }
443
wapiShellExecute(const QString & operation,const QString & file,const QString & parameters,const QString & dir,HWND win)444 void wapiShellExecute ( const QString& operation, const QString& file,
445 const QString& parameters,
446 const QString& dir, HWND win )
447 {
448 if ( parameters==QString::null )
449 ShellExecute ( win, ( LPCTSTR ) ( operation.utf16() ),
450 ( LPCTSTR ) ( file.utf16() ),0,
451 ( LPCTSTR ) ( dir.utf16() ),SW_SHOWNORMAL );
452 else
453 ShellExecute ( win, ( LPCTSTR ) ( operation.utf16() ),
454 ( LPCTSTR ) ( file.utf16() ),
455 ( LPCTSTR ) ( parameters.utf16() ),
456 ( LPCTSTR ) ( dir.utf16() ),SW_SHOWNORMAL );
457 }
458
wapiGetDefaultPrinter()459 QString wapiGetDefaultPrinter()
460 {
461 TCHAR *prName;
462 DWORD length;
463 GetDefaultPrinter ( 0,&length );
464 if ( !length )
465 return QString::null;
466 prName=new TCHAR[length];
467 GetDefaultPrinter ( prName,&length );
468 if ( !length )
469 {
470 delete []prName;
471 return QString::null;
472 }
473 QString printer=QString::fromUtf16 ( ( const ushort* ) prName );
474 delete []prName;
475 return printer;
476
477 }
478
wapiGetLocalPrinters()479 QStringList wapiGetLocalPrinters()
480 {
481 QStringList printers;
482 PRINTER_INFO_4 *info_array;
483 DWORD sizeOfArray;
484 DWORD bufSize=0;
485 DWORD sizeNeeded=0;
486 EnumPrinters ( PRINTER_ENUM_LOCAL,0,4,NULL,bufSize,
487 &sizeNeeded,&sizeOfArray );
488 if ( !sizeNeeded )
489 {
490 return printers;
491 }
492 info_array= ( PRINTER_INFO_4* ) new char[sizeNeeded];
493 if ( !info_array )
494 return printers;
495 bufSize=sizeNeeded;
496 EnumPrinters ( PRINTER_ENUM_LOCAL,0,4, ( LPBYTE ) info_array,bufSize,
497 &sizeNeeded,&sizeOfArray );
498 if ( !sizeNeeded || !sizeOfArray )
499 {
500 delete []info_array;
501 return printers;
502 }
503 for ( uint i=0; i<sizeOfArray; ++i )
504 {
505 printers<<QString::fromUtf16 (
506 ( const ushort* ) ( info_array[i].pPrinterName ) );
507 }
508 delete []info_array;
509 return printers;
510 }
511
512 #define INFO_BUFFER_SIZE 32767
wapiGetUserName()513 QString wapiGetUserName()
514 {
515 TCHAR infoBuf[INFO_BUFFER_SIZE];
516 DWORD bufCharCount=INFO_BUFFER_SIZE;
517 if( !GetUserName( infoBuf, &bufCharCount ) )
518 return QString::null;
519 return QString::fromUtf16 ( ( const ushort* ) infoBuf);
520 }
521 #endif
522