5 #include "mstsclib_h.h"
8 namespace MSTSCLib_Redist
10 // extremely ew, but actually the cleanest way to import the alternate UUIDs
11 #include "mstsclib_redist_i.c"
14 #include "rdesktop/rdesktop.h"
15 #include "rdesktop/proto.h"
20 extern "C" char __ImageBase
;
23 HMODULE
GetCurrentModule()
25 return reinterpret_cast<HMODULE
>(&__ImageBase
);
33 LONG g_moduleRefCount
= 0;
37 InterlockedIncrement(&g_moduleRefCount
);
42 InterlockedDecrement(&g_moduleRefCount
);
45 bool canUnloadServer()
47 return g_moduleRefCount
== 0;
55 void FreeLpsz(LPSTR lpsz
)
61 LPSTR
AllocLpsz(const CHAR
* lpsz
, size_t cb
)
63 LPSTR lpszNew
= new CHAR
[cb
+ 1];
68 CopyMemory(lpszNew
, lpsz
, cb
);
74 LPSTR
AllocLpsz(const WCHAR
* lpwsz
, int cchIn
)
76 int cch
= WideCharToMultiByte(CP_ACP
, 0, lpwsz
, cchIn
, NULL
, 0, NULL
, NULL
);
81 LPSTR lpsz
= new CHAR
[cch
];
86 cch
= WideCharToMultiByte(CP_ACP
, 0, lpwsz
, cchIn
, lpsz
, cch
, NULL
, NULL
);
97 LPSTR
BstrToLpsz(BSTR bstr
)
99 return AllocLpsz(bstr
, SysStringLen(bstr
));
102 BSTR
LpszToBstr(LPSTR lpsz
)
104 int cch
= MultiByteToWideChar(CP_ACP
, 0, lpsz
, -1, NULL
, 0);
109 BSTR bstr
= SysAllocStringLen(NULL
, cch
);
114 cch
= MultiByteToWideChar(CP_ACP
, 0, lpsz
, -1, bstr
, cch
);
130 template<class T
, class U
> T
aligndown(const T
& X
, const U
& align
)
132 return X
& ~(T(align
) - 1);
135 template<class T
, class U
> T
alignup(const T
& X
, const U
& align
)
137 return aligndown(X
+ (align
- 1), align
);
140 /* Convert between bitmap formats */
141 uint8
* win32_convert_scanlines(int width
, int height
, int bitcount
, int fromalign
, int toalign
, const uint8
* data
, uint8
** buffer
)
143 // TBD: profile & optimize the most common cases
146 assert(bitcount
&& bitcount
<= 32);
147 assert(fromalign
<= toalign
);
151 bool flipped
= height
< 0;
156 int bytesperrow
= alignup(width
* bitcount
, 8) / 8;
157 int fromstride
= alignup(bytesperrow
, fromalign
);
158 int tostride
= alignup(bytesperrow
, toalign
);
159 assert(fromstride
<= tostride
);
161 int datasize
= tostride
* height
;
163 uint8
* dibits
= new uint8
[datasize
];
165 const uint8
* src
= data
;
166 uint8
* dest
= dibits
;
168 const int pad
= tostride
- fromstride
;
175 dest
+= (height
- 1) * tostride
;
176 tostride
= - tostride
;
179 for(int i
= 0; i
< height
; ++ i
)
181 memcpy(dest
, src
, fromstride
);
182 memset(dest
+ fromstride
, 0, pad
);
191 /* Creates bitmaps */
192 HBITMAP
win32_create_dib(LONG width
, LONG height
, WORD bitcount
, const BYTE
* data
)
197 RGBQUAD colormap
[256 - ARRAYSIZE(RTL_FIELD_TYPE(BITMAPINFO
, bmiColors
))];
201 b
.bmi
.bmiHeader
.biSize
= sizeof(b
.bmi
.bmiHeader
);
202 b
.bmi
.bmiHeader
.biWidth
= width
;
203 b
.bmi
.bmiHeader
.biHeight
= height
;
204 b
.bmi
.bmiHeader
.biPlanes
= 1;
205 b
.bmi
.bmiHeader
.biBitCount
= bitcount
;
206 b
.bmi
.bmiHeader
.biCompression
= BI_RGB
;
207 b
.bmi
.bmiHeader
.biSizeImage
= 0;
208 b
.bmi
.bmiHeader
.biXPelsPerMeter
= 0;
209 b
.bmi
.bmiHeader
.biYPelsPerMeter
= 0;
213 b
.bmi
.bmiHeader
.biClrUsed
= 0;
214 b
.bmi
.bmiHeader
.biClrImportant
= 0;
218 b
.bmi
.bmiHeader
.biClrUsed
= 2 << bitcount
;
219 b
.bmi
.bmiHeader
.biClrImportant
= 2 << bitcount
;
224 // FIXME: beyond ugly
225 HDC hdc
= CreateCompatibleDC(NULL
);
230 HBITMAP hbm
= CreateDIBitmap(hdc
, &b
.bmi
.bmiHeader
, CBM_INIT
, data
, &b
.bmi
, DIB_RGB_COLORS
);
233 error("CreateDIBitmap %dx%dx%d failed\n", width
, height
, bitcount
);
239 /* Creates brushes */
240 HBRUSH
win32_create_brush(BRUSH
* brush
, COLORREF fgcolour
)
243 return (HBRUSH
)GetStockObject(NULL_BRUSH
);
261 return CreateSolidBrush(fgcolour
);
264 return CreateHatchBrush(brush
->pattern
[0], fgcolour
);
267 return (HBRUSH
)GetStockObject(NULL_BRUSH
);
274 for(size_t i
= 0; i
< 8; ++ i
)
275 pattern
[i
] = brush
->pattern
[i
];
277 HBITMAP hpattern
= CreateBitmap(8, 8, 1, 1, pattern
);
278 HBRUSH hbr
= CreatePatternBrush(hpattern
);
279 DeleteObject(hpattern
);
289 "sealed" can improve optimizations by asserting a class cannot be derived
290 from, optimizing out accesses to the v-table from inside the class
292 #if defined(_MSC_VER) && _MSC_VER >= 1400
293 #define SEALED_ sealed
299 /* Class that implements the RDP client GUI */
303 // TODO: pass the client settings relevant to the GUI here
304 HRESULT
Initialize(HWND hwndParent
)
306 // TODO: create the various windows
307 // TODO: create display window thread
308 // TODO: create input thread
313 static BOOL
Startup()
315 WNDCLASSEX wcexUI
= { sizeof(wcexUI
) };
316 WNDCLASSEX wcexConsole
= { sizeof(wcexConsole
) };
317 WNDCLASSEX wcexDisplay
= { sizeof(wcexDisplay
) };
318 WNDCLASSEX wcexInput
= { sizeof(wcexInput
) };
320 HBRUSH nullBrush
= (HBRUSH
)GetStockObject(HOLLOW_BRUSH
);
322 wcexUI
.lpfnWndProc
= NULL
; // TODO
323 wcexUI
.hInstance
= GetCurrentModule();
324 wcexUI
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
325 wcexUI
.hbrBackground
= nullBrush
;
326 wcexUI
.lpszClassName
= TEXT("MissTosca_UI");
328 wcexConsole
.style
= CS_VREDRAW
| CS_HREDRAW
;
329 wcexConsole
.lpfnWndProc
= NULL
; // TODO
330 wcexConsole
.hInstance
= GetCurrentModule();
331 wcexConsole
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
332 wcexConsole
.hbrBackground
= nullBrush
;
333 wcexConsole
.lpszClassName
= TEXT("MissTosca_Console");
335 wcexDisplay
.style
= CS_VREDRAW
| CS_HREDRAW
;
336 wcexDisplay
.lpfnWndProc
= NULL
; // TODO
337 wcexDisplay
.hInstance
= GetCurrentModule();
338 wcexDisplay
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
339 wcexDisplay
.hbrBackground
= nullBrush
;
340 wcexDisplay
.lpszClassName
= TEXT("MissTosca_Display");
342 wcexInput
.style
= CS_VREDRAW
| CS_HREDRAW
;
343 wcexInput
.lpfnWndProc
= NULL
; // TODO
344 wcexInput
.hInstance
= GetCurrentModule();
345 wcexInput
.hCursor
= NULL
;
346 wcexInput
.hbrBackground
= nullBrush
;
347 wcexInput
.lpszClassName
= TEXT("MissTosca_Input");
350 RegisterClassEx(&wcexUI
) &&
351 RegisterClassEx(&wcexConsole
) &&
352 RegisterClassEx(&wcexDisplay
) &&
353 RegisterClassEx(&wcexInput
);
356 static void Shutdown()
362 This is the main UI window. It's the direct child of the control
363 window, it fills its whole extent and it contains the scrollbars.
364 When activated, it will move keyboard focus to the input window
371 LRESULT
UIWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
375 // Keep the keyboard focus on the input window
377 switch(LOWORD(wParam
))
385 SetFocus(m_inputWindow
);
390 // Resized: rearrange children windows, adjust scrollbars
393 if(IsIconic(m_uiWindow
))
397 GetWindowRect(m_uiWindow
, &rcClient
);
401 // we are not supposed to maintain aspect ratio. Container has to do that
404 m_consoleWidth
= rcClient
.right
;
405 m_consoleHeight
= rcClient
.bottom
;
409 // center horizontally, no horizontal scrollbar
410 if(rcClient
.right
>= m_consoleWidth
)
411 m_consoleX
= (m_consoleWidth
- rcClient
.right
) / 2;
413 // center vertically, no vertical scrollbar
414 if(rcClient
.bottom
>= m_consoleHeight
)
415 m_consoleY
= (m_consoleHeight
- rcClient
.right
) / 2;
418 SCROLLINFO scroll
= { sizeof(scroll
), SIF_ALL
, 0 };
420 // update the horizontal scrollbar
421 scroll
.nMax
= m_consoleWidth
;
422 scroll
.nPage
= rcClient
.right
;
423 scroll
.nPos
= 0 - m_consoleX
;
424 SetScrollInfo(m_uiWindow
, SB_HORZ
, &scroll
, TRUE
);
426 // update the vertical scrollbar
427 scroll
.nMax
= m_consoleHeight
;
428 scroll
.nPage
= rcClient
.bottom
;
429 scroll
.nPos
= 0 - m_consoleY
;
430 SetScrollInfo(m_uiWindow
, SB_VERT
, &scroll
, TRUE
);
432 // move/resize the console window
433 MoveWindow(m_consoleWindow
, m_consoleX
, m_consoleY
, m_consoleWidth
, m_consoleHeight
, TRUE
);
440 SCROLLINFO scroll
= { sizeof(scroll
), SIF_TRACKPOS
};
441 GetScrollInfo(m_uiWindow
, SB_HORZ
, &scroll
);
442 m_consoleX
= - scroll
.nTrackPos
;
443 MoveWindow(m_consoleWindow
, m_consoleX
, m_consoleY
, m_consoleWidth
, m_consoleHeight
, TRUE
);
450 SCROLLINFO scroll
= { sizeof(scroll
), SIF_TRACKPOS
};
451 GetScrollInfo(m_uiWindow
, SB_VERT
, &scroll
);
452 m_consoleY
= - scroll
.nTrackPos
;
453 MoveWindow(m_consoleWindow
, m_consoleX
, m_consoleY
, m_consoleWidth
, m_consoleHeight
, TRUE
);
462 return DefWindowProc(m_uiWindow
, uMsg
, wParam
, lParam
);
466 This is the full-screen title bar. It's displayed at the top of the
467 main UI window while in full-screen mode, and it contains two toolbars
468 with the pin, minimize, restore and close buttons
470 HWND m_fullScreenBarWindow
;
473 This is the console window. It has the same extent as the display on
474 the remote computer, or it fills the UI window in smart resizing mode,
475 and it contains the input and display windows
478 HWND m_consoleWindow
;
482 LONG m_consoleHeight
;
485 LRESULT
ConsoleWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
492 GetClientRect(m_consoleWindow
, &rcClient
);
494 MoveWindow(m_inputWindow
, 0, 0, rcClient
.right
, rcClient
.bottom
, TRUE
);
495 MoveWindow(m_displayWindow
, 0, 0, rcClient
.right
, rcClient
.bottom
, TRUE
);
504 return DefWindowProc(m_consoleWindow
, uMsg
, wParam
, lParam
);
508 This is the display window. It represents the virtual display of the
509 remote computer. It completely fills its parent, the console window,
510 and it runs in its own thread for performance reasons
513 HWND m_displayWindow
;
514 LONG m_displayBufferWidth
;
515 LONG m_displayBufferHeight
;
517 void * m_displayBufferRaw
;
518 int m_displayBufferSave
;
519 int m_displayBufferBitDepth
;
520 int m_displayBufferByteDepth
;
521 int m_displayBufferStride
;
522 RECT m_displayBufferClip
;
523 CRITICAL_SECTION m_displayBufferMutex
;
525 LRESULT
DisplayWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
539 HDC hdc
= (HDC
)wParam
;
541 EnterCriticalSection(&m_displayBufferMutex
);
546 GetClientRect(m_displayWindow
, &rc
);
547 BitBlt(hdc
, 0, 0, rc
.right
, rc
.bottom
, m_displayBuffer
, 0, 0, SRCCOPY
);
552 hdc
= BeginPaint(m_displayWindow
, &ps
);
561 ps
.rcPaint
.right
- ps
.rcPaint
.left
,
562 ps
.rcPaint
.bottom
- ps
.rcPaint
.top
,
571 // bleh. There has to be a better way
572 SetStretchBltMode(hdc
, HALFTONE
);
584 m_displayBufferWidth
,
585 m_displayBufferHeight
,
590 EndPaint(m_displayWindow
, &ps
);
593 LeaveCriticalSection(&m_displayBufferMutex
);
602 return DefWindowProc(m_displayWindow
, uMsg
, wParam
, lParam
);
605 /* Screen repainting */
606 void Display_RepaintRect(const RECT
* lprc
)
609 return Display_RepaintAll();
612 IntersectRect(&rcDamage
, lprc
, &m_displayBufferClip
);
613 InvalidateRect(m_displayWindow
, &rcDamage
, FALSE
);
616 void Display_RepaintArea(int x
, int y
, int cx
, int cy
)
619 return Display_RepaintAll();
624 rcDamage
.right
= x
+ cx
;
625 rcDamage
.bottom
= y
+ cy
;
626 Display_RepaintRect(&rcDamage
);
629 void Display_RepaintPolygon(POINT
* point
, int npoints
, int linewidth
)
632 return Display_RepaintAll();
636 rcDamage
.left
= MAXLONG
;
637 rcDamage
.top
= MAXLONG
;
641 for(int i
= 0; i
< npoints
; ++ i
)
643 if(point
[i
].x
< rcDamage
.left
)
644 rcDamage
.left
= point
[i
].x
;
646 if(point
[i
].y
< rcDamage
.top
)
647 rcDamage
.top
= point
[i
].y
;
649 if(point
[i
].x
> rcDamage
.right
)
650 rcDamage
.right
= point
[i
].x
;
652 if(point
[i
].y
> rcDamage
.bottom
)
653 rcDamage
.bottom
= point
[i
].y
;
656 InflateRect(&rcDamage
, linewidth
, linewidth
);
657 Display_RepaintRect(&rcDamage
);
660 void Display_RepaintAll()
662 InvalidateRgn(m_displayWindow
, NULL
, FALSE
);
666 void Display_SetClip(int x
, int y
, int cx
, int cy
)
668 m_displayBufferClip
.left
= x
;
669 m_displayBufferClip
.top
= y
;
670 m_displayBufferClip
.right
= x
+ cx
+ 1;
671 m_displayBufferClip
.bottom
= y
+ cy
+ 1;
673 HRGN hrgn
= CreateRectRgnIndirect(&m_displayBufferClip
);
674 SelectClipRgn(m_displayBuffer
, hrgn
);
678 void Display_ResetClip()
680 m_displayBufferClip
.left
= 0;
681 m_displayBufferClip
.top
= 0;
682 m_displayBufferClip
.right
= m_displayBufferWidth
;
683 m_displayBufferClip
.bottom
= m_displayBufferHeight
;
684 SelectClipRgn(m_displayBuffer
, NULL
);
687 void Display_PaintBitmap(int x
, int y
, int cx
, int cy
, int width
, int height
, uint8
* data
)
691 int fromstride
= alignup(width
* m_displayBufferByteDepth
, 4);
692 int sizex
= cx
* m_displayBufferByteDepth
;
694 const uint8
* src
= data
;
697 (uint8
*)m_displayBufferRaw
+
698 (m_displayBufferHeight
- y
- cy
) * m_displayBufferStride
+
699 x
* m_displayBufferByteDepth
;
701 for(int i
= 0; i
< cy
; ++ i
)
703 memcpy(dst
, src
, sizex
);
705 dst
+= m_displayBufferStride
;
708 Display_RepaintArea(x
, y
, cx
, cy
);
711 void Display_DestBlt(uint8 opcode
, int x
, int y
, int cx
, int cy
)
713 int dcsave
= SaveDC(m_displayBuffer
);
714 SelectObject(m_displayBuffer
, GetStockObject(BLACK_BRUSH
));
715 PatBlt(m_displayBuffer
, x
, y
, cx
, cy
, MAKELONG(0, opcode
));
716 RestoreDC(m_displayBuffer
, dcsave
);
717 Display_RepaintArea(x
, y
, cx
, cy
);
720 void Display_PatBlt(uint8 opcode
, int x
, int y
, int cx
, int cy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
722 HBRUSH hbr
= win32_create_brush(brush
, fgcolour
);
724 int dcsave
= SaveDC(m_displayBuffer
);
726 SetBkColor(m_displayBuffer
, bgcolour
);
727 SetTextColor(m_displayBuffer
, fgcolour
);
728 SetBrushOrgEx(m_displayBuffer
, brush
->xorigin
, brush
->yorigin
, NULL
);
729 SelectObject(m_displayBuffer
, hbr
);
731 PatBlt(m_displayBuffer
, x
, y
, cx
, cy
, MAKELONG(0, opcode
));
733 RestoreDC(m_displayBuffer
, dcsave
);
737 Display_RepaintArea(x
, y
, cx
, cy
);
740 void Display_ScreenBlt(uint8 opcode
, int x
, int y
, int cx
, int cy
, int srcx
, int srcy
)
742 BitBlt(m_displayBuffer
, x
, y
, cx
, cy
, m_displayBuffer
, srcx
, srcy
, MAKELONG(0, opcode
));
743 Display_RepaintArea(x
, y
, cx
, cy
);
746 void Display_MemBlt(uint8 opcode
, int x
, int y
, int cx
, int cy
, HBITMAP src
, int srcx
, int srcy
)
748 HDC hdcSrc
= CreateCompatibleDC(m_displayBuffer
);
749 HGDIOBJ hOld
= SelectObject(hdcSrc
, src
);
751 BitBlt(m_displayBuffer
, x
, y
, cx
, cy
, hdcSrc
, srcx
, srcy
, MAKELONG(0, opcode
));
753 SelectObject(hdcSrc
, hOld
);
756 Display_RepaintArea(x
, y
, cx
, cy
);
759 void Display_TriBlt(uint8 opcode
, int x
, int y
, int cx
, int cy
, HBITMAP src
, int srcx
, int srcy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
762 HDC hdcSrc
= CreateCompatibleDC(m_displayBuffer
);
763 HGDIOBJ hOld
= SelectObject(hdcSrc
, src
);
765 //SELECT_BRUSH(brush, bgcolour, fgcolour);
767 BitBlt(m_displayBuffer
, x
, y
, cx
, cy
, hdcSrc
, srcx
, srcy
, MAKELONG(0, opcode
));
771 SelectObject(hdcSrc
, hOld
);
774 Display_RepaintArea(x
, y
, cx
, cy
);
777 void Display_Line(uint8 opcode
, int startx
, int starty
, int endx
, int endy
, PEN
* pen
)
779 HPEN hpen
= CreatePen(pen
->style
, pen
->width
, pen
->colour
);
781 int dcsave
= SaveDC(m_displayBuffer
);
783 SetROP2(m_displayBuffer
, opcode
);
784 SelectObject(m_displayBuffer
, hpen
);
785 MoveToEx(m_displayBuffer
, startx
, starty
, NULL
);
787 LineTo(m_displayBuffer
, endx
, endy
);
789 RestoreDC(m_displayBuffer
, dcsave
);
797 rcDamage
.left
= startx
;
798 rcDamage
.right
= endx
;
802 rcDamage
.left
= endx
;
803 rcDamage
.right
= startx
;
808 rcDamage
.top
= starty
;
809 rcDamage
.bottom
= endy
;
814 rcDamage
.bottom
= starty
;
817 InflateRect(&rcDamage
, pen
->width
, pen
->width
);
818 Display_RepaintRect(&rcDamage
);
821 void Display_Rect(int x
, int y
, int cx
, int cy
, int colour
)
823 HBRUSH hbr
= CreateSolidBrush(colour
);
825 int dcsave
= SaveDC(m_displayBuffer
);
827 SelectObject(m_displayBuffer
, hbr
);
828 SelectObject(m_displayBuffer
, GetStockObject(NULL_PEN
));
830 Rectangle(m_displayBuffer
, x
, y
, x
+ cx
+ 1, y
+ cy
+ 1);
832 RestoreDC(m_displayBuffer
, dcsave
);
836 Display_RepaintArea(x
, y
, cx
, cy
);
839 void Display_Polygon(uint8 opcode
, uint8 fillmode
, POINT
* point
, int npoints
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
841 HBRUSH hbr
= win32_create_brush(brush
, fgcolour
);
843 int dcsave
= SaveDC(m_displayBuffer
);
845 SetBkColor(m_displayBuffer
, bgcolour
);
846 SetTextColor(m_displayBuffer
, fgcolour
);
847 SetPolyFillMode(m_displayBuffer
, fillmode
);
848 SelectObject(m_displayBuffer
, hbr
);
850 Polygon(m_displayBuffer
, point
, npoints
);
852 RestoreDC(m_displayBuffer
, dcsave
);
854 Display_RepaintPolygon(point
, npoints
, 0);
857 void Display_Polyline(uint8 opcode
, POINT
* points
, int npoints
, PEN
* pen
)
859 POINT last
= points
[0];
861 for(int i
= 1; i
< npoints
; ++ i
)
863 points
[i
].x
+= last
.x
;
864 points
[i
].y
+= last
.y
;
868 HPEN hpen
= CreatePen(pen
->style
, pen
->width
, pen
->colour
);
870 int dcsave
= SaveDC(m_displayBuffer
);
872 SetROP2(m_displayBuffer
, opcode
);
873 SelectObject(m_displayBuffer
, hpen
);
875 Polyline(m_displayBuffer
, points
, npoints
);
877 RestoreDC(m_displayBuffer
, dcsave
);
881 Display_RepaintPolygon(points
, npoints
, pen
->width
);
884 void Display_Ellypse(uint8 opcode
, uint8 fillmode
, int x
, int y
, int cx
, int cy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
888 Display_RepaintArea(x
, y
, cx
, cy
);
891 // TBD: optimize text drawing
892 void Display_DrawGlyph(int mixmode
, int x
, int y
, int cx
, int cy
, HGLYPH glyph
, int srcx
, int srcy
, int bgcolour
, int fgcolour
)
894 HBITMAP hbmGlyph
= (HBITMAP
)glyph
;
895 HDC hdcGlyph
= CreateCompatibleDC(m_displayBuffer
);
896 HGDIOBJ hOld
= SelectObject(hdcGlyph
, hbmGlyph
);
898 int dcsave
= SaveDC(m_displayBuffer
);
902 case MIX_TRANSPARENT
:
906 - where the glyph (S) is white, D is set to the foreground color (P)
907 - where the glyph (S) is black, D is left untouched
909 This paints a transparent glyph in the specified color
911 HBRUSH hbr
= CreateSolidBrush(fgcolour
);
912 SelectObject(m_displayBuffer
, hbr
);
913 BitBlt(m_displayBuffer
, x
, y
, cx
, cy
, hdcGlyph
, srcx
, srcy
, MAKELONG(0, 0xe2));
921 /* Curiously, glyphs are inverted (white-on-black) */
922 SetBkColor(m_displayBuffer
, fgcolour
);
923 SetTextColor(m_displayBuffer
, bgcolour
);
924 BitBlt(m_displayBuffer
, x
, y
, cx
, cy
, hdcGlyph
, srcx
, srcy
, SRCCOPY
);
930 RestoreDC(m_displayBuffer
, dcsave
);
932 SelectObject(hdcGlyph
, hOld
);
935 Display_RepaintArea(x
, y
, cx
, cy
);
938 void Display_DoGlyph(uint8 font
, uint8 flags
, int mixmode
, int& x
, int& y
, int bgcolour
, int fgcolour
, const uint8
* ttext
, int& idx
)
942 glyph
= cache_get_font(/*This*/NULL
, font
, ttext
[idx
]);
944 if(!(flags
& TEXT2_IMPLICIT_X
))
946 int xyoffset
= ttext
[++ idx
];
948 if((xyoffset
& 0x80))
950 if (flags
& TEXT2_VERTICAL
)
951 y
+= ttext
[idx
+ 1] | (ttext
[idx
+ 2] << 8);
953 x
+= ttext
[idx
+ 1] | (ttext
[idx
+ 2] << 8);
959 if (flags
& TEXT2_VERTICAL
)
971 x
+ (short)glyph
->offset
,
972 y
+ (short)glyph
->baseline
,
982 if(flags
& TEXT2_IMPLICIT_X
)
987 void Display_DrawText
1013 HBRUSH hbr
= CreateSolidBrush(bgcolour
);
1014 HGDIOBJ holdbrush
= SelectObject(m_displayBuffer
, hbr
);
1015 HGDIOBJ holdpen
= SelectObject(m_displayBuffer
, GetStockObject(NULL_PEN
));
1018 Rectangle(m_displayBuffer
, boxx
, boxy
, boxx
+ boxcx
+ 1, boxy
+ boxcy
+ 1);
1019 else if (mixmode
== MIX_OPAQUE
)
1020 Rectangle(m_displayBuffer
, clipx
, clipy
, clipx
+ clipcx
+ 1, clipy
+ clipcy
+ 1);
1022 SelectObject(m_displayBuffer
, holdpen
);
1023 SelectObject(m_displayBuffer
, holdbrush
);
1028 Display_RepaintArea(boxx
, boxy
, boxcx
, boxcy
);
1030 Display_RepaintArea(clipx
, clipy
, clipcx
, clipcy
);
1032 /* Paint text, character by character */
1033 for (i
= 0; i
< length
;)
1038 /* At least two bytes needs to follow */
1041 warning("Skipping short 0xff command:");
1042 for (j
= 0; j
< length
; j
++)
1043 fprintf(stderr
, "%02x ", text
[j
]);
1044 fprintf(stderr
, "\n");
1048 cache_put_text(NULL
/* TODO */, text
[i
+ 1], text
, text
[i
+ 2]);
1051 /* this will move pointer from start to first character after FF command */
1057 /* At least one byte needs to follow */
1060 warning("Skipping short 0xfe command:");
1061 for (j
= 0; j
< length
; j
++)
1062 fprintf(stderr
, "%02x ", text
[j
]);
1063 fprintf(stderr
, "\n");
1067 entry
= cache_get_text(/*This*/NULL
, text
[i
+ 1]);
1068 if (entry
->data
!= NULL
)
1070 if ((((uint8
*) (entry
->data
))[1] == 0)
1071 && (!(flags
& TEXT2_IMPLICIT_X
)) && (i
+ 2 < length
))
1073 if (flags
& TEXT2_VERTICAL
)
1078 for (j
= 0; j
< entry
->size
; j
++)
1079 Display_DoGlyph(font
, flags
, mixmode
, x
, y
, bgcolour
, fgcolour
, ((uint8
*) (entry
->data
)), j
);
1086 /* this will move pointer from start to first character after FE command */
1092 Display_DoGlyph(font
, flags
, mixmode
, x
, y
, bgcolour
, fgcolour
, text
, i
);
1099 void Display_SaveDesktop(uint32 offset
, int x
, int y
, int cx
, int cy
)
1104 (uint8
*)m_displayBufferRaw
+
1105 x
* m_displayBufferByteDepth
+
1106 (m_displayBufferHeight
- y
- cy
) * m_displayBufferStride
;
1111 offset
* m_displayBufferByteDepth
,
1114 m_displayBufferStride
,
1115 m_displayBufferByteDepth
,
1120 void Display_RestoreDesktop(uint32 offset
, int x
, int y
, int cx
, int cy
)
1122 int fromstride
= cx
* m_displayBufferByteDepth
;
1124 const uint8
* src
= cache_get_desktop(/*This*/NULL
, offset
, cx
, cy
, m_displayBufferByteDepth
);
1127 (uint8
*)m_displayBufferRaw
+
1128 x
* m_displayBufferByteDepth
+
1129 (m_displayBufferHeight
- y
- cy
) * m_displayBufferStride
;
1133 for(int i
= 0; i
< cy
; ++ i
)
1135 memcpy(dst
, src
, fromstride
);
1137 dst
+= m_displayBufferStride
;
1140 Display_RepaintArea(x
, y
, cx
, cy
);
1144 void Display_BeginUpdate()
1146 EnterCriticalSection(&m_displayBufferMutex
);
1147 m_displayBufferSave
= SaveDC(m_displayBuffer
);
1150 void Display_EndUpdate()
1152 RestoreDC(m_displayBuffer
, m_displayBufferSave
);
1153 LeaveCriticalSection(&m_displayBufferMutex
);
1157 This is the input window. It receives the keyboard and mouse input from
1158 the user, and it's the only window that can receive the keyboard focus.
1159 It completely fills its parent, the console window, and it runs in its
1160 own thread for performance reasons and because of technical reasons
1161 involving keyboard hooks in full-screen mode
1164 HCURSOR m_inputCursor
;
1166 LRESULT
InputWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1174 /* Keyboard stuff */
1175 // TODO: we need a good way to post output cross-thread
1178 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYPRESS | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0);
1183 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYRELEASE | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0);
1189 if(LOWORD(lParam
) == HTCLIENT
)
1191 SetCursor(m_inputCursor
);
1199 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, LOWORD(lparam), HIWORD(lparam));
1204 case WM_LBUTTONDOWN
:
1205 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
1208 case WM_RBUTTONDOWN
:
1209 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
1212 case WM_MBUTTONDOWN
:
1213 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
1217 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, LOWORD(lparam), HIWORD(lparam));
1221 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, LOWORD(lparam), HIWORD(lparam));
1225 //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, LOWORD(lparam), HIWORD(lparam));
1230 //mstsc_mousewheel(This, (SHORT)HIWORD(wparam), lparam);
1234 return DefWindowProc(m_inputWindow
, uMsg
, wParam
, lParam
);
1240 #pragma warning(push)
1241 #pragma warning(disable: 4584)
1243 /* The ActiveX control */
1244 class RdpClient SEALED_
:
1250 public IConnectionPointContainer
,
1252 public IObjectSafety
,
1254 public IOleInPlaceActiveObject
,
1255 public IOleInPlaceObject
,
1259 public IPersistPropertyBag
,
1260 public IPersistStorage
,
1261 public IPersistStreamInit
,
1262 public IProvideClassInfo
,
1263 public IProvideClassInfo2
,
1264 public IQuickActivate
,
1266 public IViewObject2
,
1268 // NOTE: the original has a vestigial, non-functional implementation of this, which we omit
1269 // ISpecifyPropertyPages
1271 // Hidden interfaces, not available through QueryInterface
1272 public IConnectionPoint
,
1274 /* RDP client interface */
1275 public MSTSCLib::IMsRdpClient4
,
1276 public MSTSCLib::IMsRdpClientNonScriptable2
1278 // NOTE: implemented by inner classes due to requiring distinct IDispatch implementations
1279 // IMsRdpClientAdvancedSettings4
1280 // IMsRdpClientSecuredSettings
1283 /* An endless amount of COM glue */
1284 // Reference counting
1288 DWORD m_apartmentThreadId
;
1290 bool InsideApartment() const
1292 return GetCurrentThreadId() == m_apartmentThreadId
;
1296 // Aggregation support
1297 IUnknown
* m_punkOuter
;
1299 class RdpClientInner
: public IUnknown
1304 return InnerToOuter(this);
1308 virtual STDMETHODIMP
IUnknown::QueryInterface(REFIID riid
, void ** ppvObject
)
1310 return Outer()->queryInterface(riid
, ppvObject
);
1313 virtual STDMETHODIMP_(ULONG
) IUnknown::AddRef()
1315 return Outer()->addRef();
1318 virtual STDMETHODIMP_(ULONG
) IUnknown::Release()
1320 return Outer()->release();
1326 // Persistence support
1329 // Late binding support
1330 unsigned m_typeLibIndex
;
1331 ITypeLib
* m_typeLib
;
1332 ITypeInfo
* m_dispTypeInfo
;
1335 size_t m_EventSinksCount
;
1339 MSTSCLib::IMsTscAxEvents
* m_EventSinksStatic
[1];
1340 MSTSCLib::IMsTscAxEvents
** m_EventSinks
;
1344 HWND m_controlWindow
;
1345 IOleClientSite
* m_clientSite
;
1346 IOleInPlaceSite
* m_inPlaceSite
;
1347 IOleAdviseHolder
* m_adviseHolder
;
1348 LONG m_freezeEvents
;
1352 DWORD m_SafetyOptions
;
1354 bool IsSafeForScripting() const
1356 return m_SafetyOptions
& INTERFACESAFE_FOR_UNTRUSTED_CALLER
;
1359 /* Glue to interface to rdesktop-core */
1360 RdpClientUI
* m_clientUI
;
1361 RDPCLIENT m_protocolState
;
1362 HANDLE m_protocolThread
;
1363 HANDLE m_protocolThreadWaitingReconnection
;
1364 bool m_reconnectAborted
;
1365 bool m_actuallyConnected
;
1370 // NOTE: keep sorted by alignment (pointers and handles, integers, enumerations, booleans)
1373 BSTR m_DisconnectedText
;
1374 BSTR m_ConnectingText
;
1375 BSTR m_FullScreenTitle
;
1376 BSTR m_StartProgram
;
1378 BSTR m_ConnectedStatusText
;
1379 BSTR m_ClearTextPassword
; // FIXME! dangerous, shouldn't store in cleartext!
1380 BSTR m_RdpdrLocalPrintingDocName
;
1381 BSTR m_RdpdrClipCleanTempDirString
;
1382 BSTR m_RdpdrClipPasteInfoString
;
1383 BSTR m_KeyboardLayoutString
;
1385 LPSTR m_LoadBalanceInfo
;
1386 // TODO: plugin DLLs
1387 HWND m_UIParentWindowHandle
;
1388 long m_DesktopWidth
;
1389 long m_DesktopHeight
;
1390 long m_StartConnected
;
1392 long m_KeyboardHookMode
;
1393 long m_AudioRedirectionMode
;
1394 long m_TransportType
;
1397 long m_HotKeyFullScreen
;
1398 long m_HotKeyAltEsc
;
1399 long m_HotKeyAltShiftTab
;
1400 long m_HotKeyAltSpace
;
1401 long m_HotKeyAltTab
;
1402 long m_HotKeyCtrlAltDel
;
1403 long m_HotKeyCtrlEsc
;
1404 long m_orderDrawThresold
;
1405 long m_BitmapCacheSize
;
1406 long m_BitmapVirtualCacheSize
;
1407 long m_NumBitmapCaches
;
1408 long m_brushSupportLevel
;
1409 long m_minInputSendInterval
;
1410 long m_InputEventsAtOnce
;
1411 long m_maxEventCount
;
1412 long m_keepAliveInternal
;
1413 long m_shutdownTimeout
;
1414 long m_overallConnectionTimeout
;
1415 long m_singleConnectionTimeout
;
1416 long m_MinutesToIdleTimeout
;
1417 long m_BitmapVirtualCache16BppSize
;
1418 long m_BitmapVirtualCache24BppSize
;
1419 long m_PerformanceFlags
;
1420 long m_MaxReconnectAttempts
;
1421 unsigned int m_AuthenticationLevel
;
1423 MSTSCLib::ExtendedDisconnectReasonCode m_ExtendedDisconnectReason
;
1427 bool m_BitmapPersistence
;
1428 bool m_allowBackgroundInput
;
1429 bool m_ContainerHandledFullScreen
;
1430 bool m_DisableRdpdr
;
1431 bool m_SecuredSettingsEnabled
;
1433 bool m_AcceleratorPassthrough
;
1434 bool m_ShadowBitmap
;
1435 bool m_EncryptionEnabled
;
1436 bool m_DedicatedTerminal
;
1437 bool m_DisableCtrlAltDel
;
1438 bool m_EnableWindowsKey
;
1439 bool m_DoubleClickDetect
;
1440 bool m_MaximizeShell
;
1441 bool m_ScaleBitmapCachesByBpp
;
1442 bool m_CachePersistenceActive
;
1443 bool m_ConnectToServerConsole
;
1444 bool m_SmartSizing
; // FIXME: this can be set while the control is connected
1445 bool m_DisplayConnectionBar
;
1446 bool m_PinConnectionBar
;
1447 bool m_GrabFocusOnConnect
;
1448 bool m_RedirectDrives
;
1449 bool m_RedirectPrinters
;
1450 bool m_RedirectPorts
;
1451 bool m_RedirectSmartCards
;
1452 bool m_NotifyTSPublicKey
;
1453 bool m_CanAutoReconnect
;
1454 bool m_EnableAutoReconnect
;
1455 bool m_ConnectionBarShowMinimizeButton
;
1456 bool m_ConnectionBarShowRestoreButton
;
1458 // Generic getters/setters
1459 HRESULT
GetProperty(BSTR
& prop
, BSTR
* retVal
) const
1461 assert(InsideApartment());
1466 *retVal
= SysAllocStringLen(prop
, SysStringLen(prop
));
1469 return E_OUTOFMEMORY
;
1474 HRESULT
GetProperty(LPSTR
& prop
, BSTR
* retVal
) const
1476 assert(InsideApartment());
1481 *retVal
= LpszToBstr(prop
);
1484 return E_OUTOFMEMORY
;
1489 HRESULT
SetProperty(BSTR
& prop
, BSTR newValue
)
1491 assert(InsideApartment());
1496 SysFreeString(prop
);
1498 UINT len
= SysStringLen(newValue
);
1502 // no embedded NULs, please
1503 if(len
!= lstrlenW(newValue
))
1504 return E_INVALIDARG
;
1506 prop
= SysAllocStringLen(newValue
, len
);
1509 return E_OUTOFMEMORY
;
1517 HRESULT
ReplaceProperty(BSTR
& prop
, BSTR newValue
)
1519 assert(InsideApartment());
1520 assert((prop
== NULL
&& newValue
== NULL
) || prop
!= newValue
);
1522 SysFreeString(prop
);
1527 HRESULT
SetProperty(LPSTR
& prop
, BSTR newValue
)
1529 assert(InsideApartment());
1536 if(SysStringLen(newValue
))
1538 prop
= BstrToLpsz(newValue
);
1541 return E_OUTOFMEMORY
;
1549 HRESULT
ReplaceProperty(LPSTR
& prop
, LPSTR newValue
)
1551 assert(InsideApartment());
1552 assert((prop
== NULL
&& newValue
== NULL
) || prop
!= newValue
);
1561 template<class Type
> HRESULT
SetProperty(bool& prop
, const Type
& newValue
)
1563 assert(InsideApartment());
1572 template<class Type
> HRESULT
SetProperty(Type
& prop
, const Type
& newValue
)
1574 assert(InsideApartment());
1583 template<class Type
> HRESULT
GetProperty(const bool& prop
, Type
* retVal
) const
1585 assert(InsideApartment());
1590 *retVal
= prop
? VARIANT_TRUE
: VARIANT_FALSE
;
1594 template<class Type
> HRESULT
GetProperty(const Type
& prop
, Type
* retVal
) const
1596 assert(InsideApartment());
1606 MSTSCLib::IMsTscAxEvents
** GetSinks() const
1608 if(m_EventSinksCount
> 1)
1609 return m_EventSinks
;
1611 return const_cast<MSTSCLib::IMsTscAxEvents
**>(m_EventSinksStatic
);
1615 void UnfreezeEvents()
1620 // Generic event riser & helpers
1621 void InvokeSinks(DISPID eventId
, VARIANTARG rgvarg
[], unsigned int cArgs
, VARIANTARG
* retval
)
1623 assert(InsideApartment());
1627 params
.rgvarg
= rgvarg
;
1628 params
.rgdispidNamedArgs
= NULL
;
1629 params
.cArgs
= cArgs
;
1630 params
.cNamedArgs
= 0;
1632 MSTSCLib::IMsTscAxEvents
** sinks
= GetSinks();
1634 for(size_t i
= 0; i
< m_EventSinksCount
; ++ i
)
1635 sinks
[i
]->Invoke(eventId
, IID_NULL
, 0, DISPATCH_METHOD
, ¶ms
, retval
, NULL
, NULL
);
1638 typedef void (RdpClient::* AsyncEventCallback
)
1641 VARIANTARG
* rgvarg
,
1646 void CleanupEventArgumentsCallback
1649 VARIANTARG
* rgvarg
,
1654 assert((rgvarg
== NULL
) == (cArgs
== 0));
1656 for(unsigned int i
= 0; i
< cArgs
; ++ i
)
1657 VariantClear(&rgvarg
[i
]);
1660 VariantClear(retVal
);
1663 // synchronous call from inside the apartment that owns the object
1664 void FireEventInsideApartment
1667 VARIANTARG
* rgvarg
= NULL
,
1668 unsigned int cArgs
= 0,
1669 VARIANTARG
* retval
= NULL
,
1670 AsyncEventCallback callback
= NULL
1673 assert(InsideApartment());
1675 if(retval
== NULL
&& callback
)
1677 VARIANTARG localRetval
= { };
1678 retval
= &localRetval
;
1681 InvokeSinks(eventId
, rgvarg
, cArgs
, retval
);
1684 (this->*callback
)(eventId
, rgvarg
, cArgs
, retval
);
1687 struct EventArguments
1690 VARIANTARG
* rgvarg
;
1692 VARIANTARG
* retval
;
1693 AsyncEventCallback callback
;
1696 struct RedirectArguments
1703 uint32 username_len
;
1707 uint32 password_len
;
1715 RDPC_WM_ASYNC_EVENT
,
1717 RDPC_WM_REQUEST_CLOSE
,
1721 static VOID CALLBACK
DisconnectAPC(ULONG_PTR
)
1723 // no need to do anything. The interruption will be enough
1726 bool HandleEvent(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
& result
)
1732 /* Regular event to be dispatched to the container's sink */
1733 case RDPC_WM_SYNC_EVENT
:
1734 assert(InSendMessage());
1736 case RDPC_WM_ASYNC_EVENT
:
1738 const EventArguments
* eventArgs
= reinterpret_cast<EventArguments
*>(lParam
);
1741 FireEventInsideApartment
1750 if(uMsg
== RDPC_WM_ASYNC_EVENT
)
1756 /* The protocol thread is about to die: prepare for disconnection */
1757 case RDPC_WM_DISCONNECT
:
1759 assert(m_Connected
);
1760 assert(InsideApartment());
1761 assert(InSendMessage());
1763 // Unblock the protocol thread and wait for it to terminate
1765 JoinProtocolThread();
1767 // Finish disconnecting
1768 PerformDisconnect(static_cast<long>(wParam
));
1773 case RDPC_WM_REDIRECT
:
1775 assert(InSendMessage());
1777 assert(m_Connected
);
1778 assert(m_protocolState
.redirect
);
1780 RedirectArguments
* redirectArgs
= reinterpret_cast<RedirectArguments
*>(lParam
);
1782 // BUGBUG: this is extremely messy and more prone to out-of-memory than it should be
1783 LPSTR lpszNewServer
= NULL
;
1784 LPSTR lpszNewCookie
= NULL
;
1785 BSTR strNewUsername
= NULL
;
1786 BSTR strNewDomain
= NULL
;
1787 BSTR strNewPassword
= NULL
;
1792 // Allocate the new properties
1795 // FIXME: convert the hostname to Punycode, not the ANSI codepage
1796 lpszNewServer
= AllocLpsz(redirectArgs
->server
, redirectArgs
->server_len
/ sizeof(OLECHAR
));
1798 if(lpszNewServer
== NULL
&& redirectArgs
->server_len
)
1801 lpszNewCookie
= AllocLpsz(redirectArgs
->cookie
, redirectArgs
->cookie_len
);
1803 if(lpszNewCookie
== NULL
&& redirectArgs
->cookie_len
)
1806 strNewUsername
= SysAllocStringLen(redirectArgs
->username
, redirectArgs
->username_len
/ sizeof(OLECHAR
));
1808 if(strNewUsername
== NULL
&& redirectArgs
->username_len
)
1811 strNewDomain
= SysAllocStringLen(redirectArgs
->domain
, redirectArgs
->domain_len
/ sizeof(OLECHAR
));
1813 if(strNewDomain
== NULL
&& redirectArgs
->domain_len
)
1816 strNewPassword
= SysAllocStringLen(redirectArgs
->password
, redirectArgs
->password_len
/ sizeof(OLECHAR
));
1818 if(strNewPassword
== NULL
&& redirectArgs
->password_len
)
1828 // set the new properties
1829 ReplaceProperty(m_Server
, lpszNewServer
);
1830 ReplaceProperty(m_LoadBalanceInfo
, lpszNewCookie
);
1831 ReplaceProperty(m_UserName
, strNewUsername
);
1832 ReplaceProperty(m_Domain
, strNewDomain
);
1833 ReplaceProperty(m_ClearTextPassword
, strNewPassword
);
1839 FreeLpsz(lpszNewServer
);
1840 FreeLpsz(lpszNewCookie
);
1841 SysFreeString(strNewUsername
);
1842 SysFreeString(strNewDomain
);
1843 SysFreeString(strNewPassword
);
1846 m_protocolState
.disconnect_reason
= 262;
1847 m_protocolState
.redirect
= False
;
1854 // BUGBUG: this could potentially disconnect an unrelated connection established later...
1855 case RDPC_WM_REQUEST_CLOSE
:
1857 assert(!InSendMessage());
1861 // Ask confirmation to the container in case we are logged in
1862 if(m_loggedIn
&& !FireConfirmClose())
1865 // For reentrancy (OnConfirmClose could deviously call Disconnect)
1866 if(m_protocolThread
== NULL
)
1869 // Terminate the protocol thread. It will fire the Disconnected event on exit
1870 TerminateProtocolThread();
1880 // If the calling thread is blocked, unblock it ASAP
1882 ReplyMessage(result
);
1887 // synchronous call from outside the apartment
1888 void FireEventOutsideApartment
1891 VARIANTARG
* rgvarg
= NULL
,
1892 unsigned int cArgs
= 0,
1893 VARIANTARG
* retval
= NULL
,
1894 AsyncEventCallback callback
= NULL
1897 assert(!InsideApartment());
1898 EventArguments syncEvent
= { eventId
, rgvarg
, cArgs
, retval
, callback
};
1899 SendMessage(m_controlWindow
, RDPC_WM_SYNC_EVENT
, 0, reinterpret_cast<LPARAM
>(&syncEvent
));
1902 // asynchronous call from outside the apartment
1903 HRESULT FireEventOutsideApartmentAsync
1906 VARIANTARG
* rgvarg
= NULL
,
1907 unsigned int cArgs
= 0,
1908 VARIANTARG
* retval
= NULL
,
1909 AsyncEventCallback callback
= NULL
1912 assert(!InsideApartment());
1914 EventArguments
* asyncEvent
= new EventArguments();
1916 if(asyncEvent
== NULL
)
1917 return E_OUTOFMEMORY
;
1919 asyncEvent
->eventId
= eventId
;
1920 asyncEvent
->rgvarg
= rgvarg
;
1921 asyncEvent
->cArgs
= cArgs
;
1922 asyncEvent
->retval
= NULL
;
1924 if(!PostMessage(m_controlWindow
, RDPC_WM_ASYNC_EVENT
, 0, reinterpret_cast<LPARAM
>(asyncEvent
)))
1927 return HRESULT_FROM_WIN32(GetLastError());
1934 void FireConnecting()
1937 FireEventOutsideApartment(1);
1940 void FireConnected()
1943 FireEventOutsideApartment(2);
1946 void FireLoginComplete()
1949 FireEventOutsideApartment(3);
1952 void FireDisconnected(long reason
)
1954 // Source: protocol. Special handling
1955 SendMessage(m_controlWindow
, RDPC_WM_DISCONNECT
, reason
, 0);
1958 void FireEnterFullScreenMode()
1960 // Source: UI window
1961 FireEventInsideApartment(5);
1964 void FireLeaveFullScreenMode()
1966 // Source: UI window
1967 FireEventInsideApartment(6);
1970 HRESULT
FireChannelReceivedData(char (& chanName
)[CHANNEL_NAME_LEN
+ 1], void * chanData
, unsigned int chanDataSize
)
1972 // BUGBUG: what to do when we run out of memory?
1974 OLECHAR wchanName
[ARRAYSIZE(chanName
)];
1975 std::copy(chanName
+ 0, chanName
+ ARRAYSIZE(chanName
), wchanName
);
1977 BSTR bstrChanName
= SysAllocString(wchanName
);
1979 if(bstrChanName
== NULL
)
1980 return E_OUTOFMEMORY
;
1982 BSTR bstrChanData
= SysAllocStringByteLen(NULL
, chanDataSize
);
1984 if(bstrChanData
== NULL
)
1986 SysFreeString(bstrChanName
);
1987 return E_OUTOFMEMORY
;
1990 CopyMemory(bstrChanData
, chanData
, chanDataSize
);
1992 VARIANTARG args
[2] = { };
1994 args
[1].vt
= VT_BSTR
;
1995 args
[1].bstrVal
= bstrChanName
;
1997 args
[0].vt
= VT_BSTR
;
1998 args
[0].bstrVal
= bstrChanData
;
2001 HRESULT hr
= FireEventOutsideApartmentAsync(7, args
, ARRAYSIZE(args
), NULL
, &RdpClient::CleanupEventArgumentsCallback
);
2004 CleanupEventArgumentsCallback(7, args
, ARRAYSIZE(args
), NULL
);
2009 void FireRequestGoFullScreen()
2011 // Source: UI window
2012 FireEventInsideApartment(8);
2015 void FireRequestLeaveFullScreen()
2017 // Source: UI window
2018 FireEventInsideApartment(9);
2021 void FireFatalError(long errorCode
)
2023 VARIANTARG arg
= { };
2026 arg
.lVal
= errorCode
;
2029 FireEventOutsideApartment(10, &arg
, 1);
2032 void FireFatalErrorFromApartment(long errorCode
)
2034 VARIANTARG arg
= { };
2037 arg
.lVal
= errorCode
;
2040 FireEventInsideApartment(10, &arg
, 1);
2043 void FireWarning(long warningCode
)
2045 VARIANTARG arg
= { };
2048 arg
.lVal
= warningCode
;
2051 FireEventOutsideApartment(11, &arg
, 1);
2054 void FireRemoteDesktopSizeChange(long width
, long height
)
2056 VARIANTARG args
[2] = { };
2059 args
[1].lVal
= width
;
2062 args
[0].lVal
= height
;
2064 // Source: UI window
2065 FireEventInsideApartment(12, args
, ARRAYSIZE(args
));
2068 void FireIdleTimeoutNotification()
2070 // Source: input thread
2071 FireEventOutsideApartment(13);
2074 void FireRequestContainerMinimize()
2076 // Source: UI window
2077 FireEventInsideApartment(14);
2080 bool FireConfirmClose()
2082 VARIANTARG retval
= { };
2083 VARIANT_BOOL allowClose
= VARIANT_TRUE
;
2085 retval
.vt
= VT_BYREF
| VT_BOOL
;
2086 retval
.pboolVal
= &allowClose
;
2089 FireEventInsideApartment(15, NULL
, 0, &retval
);
2091 return allowClose
!= VARIANT_FALSE
;
2094 HRESULT
FireReceivedTSPublicKey(void * publicKey
, unsigned int publicKeyLength
)
2096 assert(m_Connected
);
2098 if(!m_NotifyTSPublicKey
)
2101 BSTR bstrPublicKey
= SysAllocStringByteLen(NULL
, publicKeyLength
);
2103 if(bstrPublicKey
== NULL
)
2104 return E_OUTOFMEMORY
;
2106 CopyMemory(bstrPublicKey
, publicKey
, publicKeyLength
);
2108 VARIANT_BOOL continueLogon
= VARIANT_TRUE
;
2109 VARIANTARG arg
= { };
2110 VARIANTARG retval
= { };
2113 arg
.bstrVal
= bstrPublicKey
;
2115 retval
.vt
= VT_BYREF
| VT_BOOL
;
2116 retval
.pboolVal
= &continueLogon
;
2119 FireEventOutsideApartment(16, &arg
, 1, &retval
);
2121 return continueLogon
? S_OK
: S_FALSE
;
2124 LONG
FireAutoReconnecting(long disconnectReason
, long attemptCount
)
2126 LONG continueStatus
= MSTSCLib::autoReconnectContinueAutomatic
;
2127 VARIANTARG args
[2] = { };
2128 VARIANTARG retval
= { };
2131 args
[1].lVal
= disconnectReason
;
2134 args
[0].lVal
= attemptCount
;
2136 retval
.vt
= VT_BYREF
| VT_I4
;
2137 retval
.plVal
= &continueStatus
;
2140 FireEventOutsideApartment(17, args
, ARRAYSIZE(args
), &retval
);
2142 return continueStatus
;
2145 void FireAuthenticationWarningDisplayed()
2148 FireEventOutsideApartment(18);
2151 void FireAuthenticationWarningDismissed()
2154 FireEventOutsideApartment(19);
2157 /* Actual IUnknown implementation */
2158 HRESULT
queryInterface(REFIID riid
, void ** ppvObject
)
2160 IUnknown
* pvObject
= NULL
;
2162 using namespace MSTSCLib
;
2164 if(riid
== IID_IUnknown
)
2165 pvObject
= static_cast<IUnknown
*>(&m_inner
);
2166 else if(riid
== IID_IConnectionPointContainer
)
2167 pvObject
= static_cast<IConnectionPointContainer
*>(this);
2168 else if(riid
== IID_IDataObject
)
2169 pvObject
= static_cast<IDataObject
*>(this);
2170 else if(riid
== IID_IObjectSafety
)
2171 pvObject
= static_cast<IObjectSafety
*>(this);
2172 else if(riid
== IID_IOleControl
)
2173 pvObject
= static_cast<IOleControl
*>(this);
2174 else if(riid
== IID_IOleInPlaceActiveObject
)
2175 pvObject
= static_cast<IOleInPlaceActiveObject
*>(this);
2176 else if(riid
== IID_IOleInPlaceObject
)
2177 pvObject
= static_cast<IOleInPlaceObject
*>(this);
2178 else if(riid
== IID_IOleObject
)
2179 pvObject
= static_cast<IOleObject
*>(this);
2180 else if(riid
== IID_IOleWindow
)
2181 pvObject
= static_cast<IOleWindow
*>(this);
2182 else if(riid
== IID_IPersist
)
2183 pvObject
= static_cast<IPersist
*>(this);
2184 else if(riid
== IID_IPersistPropertyBag
)
2185 pvObject
= static_cast<IPersistPropertyBag
*>(this);
2186 else if(riid
== IID_IPersistStorage
)
2187 pvObject
= static_cast<IPersistStorage
*>(this);
2188 else if(riid
== IID_IPersistStreamInit
)
2189 pvObject
= static_cast<IPersistStreamInit
*>(this);
2190 else if(riid
== IID_IQuickActivate
)
2191 pvObject
= static_cast<IQuickActivate
*>(this);
2192 else if(riid
== IID_IViewObject
)
2193 pvObject
= static_cast<IViewObject
*>(this);
2194 else if(riid
== IID_IViewObject2
)
2195 pvObject
= static_cast<IViewObject2
*>(this);
2196 else if(riid
== IID_IMsTscAx
|| riid
== MSTSCLib_Redist::IID_IMsTscAx
)
2197 pvObject
= static_cast<IMsTscAx
*>(this);
2198 else if(riid
== IID_IMsRdpClient
)
2199 pvObject
= static_cast<IMsRdpClient
*>(this);
2200 else if(riid
== IID_IMsRdpClient2
)
2201 pvObject
= static_cast<IMsRdpClient2
*>(this);
2202 else if(riid
== IID_IMsRdpClient3
)
2203 pvObject
= static_cast<IMsRdpClient3
*>(this);
2204 else if(riid
== IID_IMsRdpClient4
)
2205 pvObject
= static_cast<IMsRdpClient4
*>(this);
2206 else if(riid
== IID_IMsTscNonScriptable
)
2207 pvObject
= static_cast<IMsTscNonScriptable
*>(this);
2208 else if(riid
== IID_IMsRdpClientNonScriptable
)
2209 pvObject
= static_cast<IMsRdpClientNonScriptable
*>(this);
2210 else if(riid
== IID_IMsRdpClientNonScriptable2
)
2211 pvObject
= static_cast<IMsRdpClientNonScriptable2
*>(this);
2213 *ppvObject
= pvObject
;
2221 return E_NOINTERFACE
;
2226 return InterlockedIncrement(&m_refCount
);
2231 LONG n
= InterlockedDecrement(&m_refCount
);
2240 RdpClient(REFCLSID classId
, unsigned libIndex
, IUnknown
* punkOuter
):
2241 // COM/OLE internals
2243 m_punkOuter(punkOuter
),
2245 m_typeLibIndex(libIndex
),
2248 m_controlWindow(NULL
),
2257 m_apartmentThreadId(GetCurrentThreadId()),
2260 // rdesktop-core interface
2268 m_DisconnectedText(),
2270 m_FullScreenTitle(),
2273 m_LoadBalanceInfo(),
2274 m_ConnectedStatusText(),
2275 m_ClearTextPassword(),
2276 m_RdpdrLocalPrintingDocName(),
2277 m_RdpdrClipCleanTempDirString(),
2278 m_RdpdrClipPasteInfoString(),
2279 m_UIParentWindowHandle(),
2284 m_KeyboardHookMode(2),
2285 m_AudioRedirectionMode(0),
2286 m_TransportType(1), // BUGBUG: ??? what's this ???
2287 m_SasSequence(0xAA03), // BUGBUG: ??? what's this ???
2289 m_HotKeyFullScreen(VK_CANCEL
),
2290 m_HotKeyAltEsc(VK_INSERT
),
2291 m_HotKeyAltShiftTab(VK_NEXT
),
2292 m_HotKeyAltSpace(VK_DELETE
),
2293 m_HotKeyAltTab(VK_PRIOR
),
2294 m_HotKeyCtrlAltDel(VK_END
),
2295 m_HotKeyCtrlEsc(VK_HOME
),
2296 m_orderDrawThresold(0),
2297 m_BitmapCacheSize(1500),
2298 m_BitmapVirtualCacheSize(10),
2299 m_brushSupportLevel(),
2300 m_minInputSendInterval(),
2301 m_InputEventsAtOnce(),
2303 m_keepAliveInternal(0),
2304 m_shutdownTimeout(10),
2305 m_overallConnectionTimeout(120),
2306 m_singleConnectionTimeout(30),
2307 m_MinutesToIdleTimeout(0),
2308 m_BitmapVirtualCache16BppSize(20),
2309 m_BitmapVirtualCache24BppSize(30),
2310 m_PerformanceFlags(),
2311 m_MaxReconnectAttempts(20),
2312 m_AuthenticationLevel(0),
2313 m_ExtendedDisconnectReason(MSTSCLib::exDiscReasonNoInfo
),
2316 m_BitmapPersistence(true),
2317 m_allowBackgroundInput(false),
2318 m_ContainerHandledFullScreen(false),
2319 m_DisableRdpdr(false),
2320 m_SecuredSettingsEnabled(true),
2321 m_FullScreen(false),
2322 m_AcceleratorPassthrough(true),
2323 m_ShadowBitmap(true),
2324 m_EncryptionEnabled(true),
2325 m_DedicatedTerminal(false),
2326 m_DisableCtrlAltDel(true),
2327 m_EnableWindowsKey(true),
2328 m_DoubleClickDetect(false),
2329 m_MaximizeShell(true),
2330 m_ScaleBitmapCachesByBpp(false),
2331 m_CachePersistenceActive(false),
2332 m_ConnectToServerConsole(false),
2333 m_SmartSizing(false),
2334 m_DisplayConnectionBar(true),
2335 m_PinConnectionBar(true),
2336 m_GrabFocusOnConnect(true),
2337 m_RedirectDrives(false),
2338 m_RedirectPrinters(false),
2339 m_RedirectPorts(false),
2340 m_RedirectSmartCards(false),
2341 m_NotifyTSPublicKey(false),
2342 m_CanAutoReconnect(false),
2343 m_EnableAutoReconnect(true),
2344 m_ConnectionBarShowMinimizeButton(true),
2345 m_ConnectionBarShowRestoreButton(true)
2347 if(m_punkOuter
== NULL
)
2348 m_punkOuter
= &m_inner
;
2354 assert(m_refCount
== 0);
2358 // Terminate the protocol thread
2359 TerminateProtocolThread();
2361 // Dispatch the RDPC_WM_DISCONNECT message sent by the dying thread
2363 PeekMessage(&msg
, m_controlWindow
, 0, 0, PM_NOREMOVE
);
2365 assert(!m_Connected
);
2368 DestroyControlWindow();
2371 m_typeLib
->Release();
2374 m_dispTypeInfo
->Release();
2376 MSTSCLib::IMsTscAxEvents
** sinks
= GetSinks();
2378 for(size_t i
= 0; i
< m_EventSinksCount
; ++ i
)
2379 sinks
[i
]->Release();
2381 if(m_EventSinksCount
> 1)
2382 delete[] m_EventSinks
;
2385 m_clientSite
->Release();
2388 m_inPlaceSite
->Release();
2391 m_adviseHolder
->Release();
2393 SysFreeString(m_Domain
);
2394 SysFreeString(m_UserName
);
2395 SysFreeString(m_DisconnectedText
);
2396 SysFreeString(m_DisconnectedText
);
2397 SysFreeString(m_FullScreenTitle
);
2398 SysFreeString(m_StartProgram
);
2399 SysFreeString(m_WorkDir
);
2400 SysFreeString(m_ConnectedStatusText
);
2401 SysFreeString(m_ClearTextPassword
);
2402 SysFreeString(m_RdpdrLocalPrintingDocName
);
2403 SysFreeString(m_RdpdrClipCleanTempDirString
);
2404 SysFreeString(m_RdpdrClipPasteInfoString
);
2406 FreeLpsz(m_LoadBalanceInfo
);
2412 /* Advanced settings wrapper */
2413 friend class AdvancedSettings
;
2415 class AdvancedSettings SEALED_
: public MSTSCLib::IMsRdpClientAdvancedSettings4
2420 return InnerToOuter(this);
2423 const RdpClient
* Outer() const
2425 return InnerToOuter(this);
2428 /* IDispatch type information */
2429 ITypeInfo
* m_dispTypeInfo
;
2431 HRESULT
LoadDispTypeInfo()
2436 HRESULT hr
= Outer()->LoadTypeLibrary();
2441 assert(MSTSCLib::IID_IMsRdpClientAdvancedSettings4
== MSTSCLib_Redist::IID_IMsRdpClientAdvancedSettings4
);
2443 hr
= Outer()->m_typeLib
->GetTypeInfoOfGuid(MSTSCLib::IID_IMsRdpClientAdvancedSettings4
, &m_dispTypeInfo
);
2448 assert(m_dispTypeInfo
);
2452 HRESULT
AcquireDispTypeInfo(ITypeInfo
** ppTI
)
2454 HRESULT hr
= LoadDispTypeInfo();
2459 m_dispTypeInfo
->AddRef();
2460 *ppTI
= m_dispTypeInfo
;
2468 m_dispTypeInfo
->Release();
2472 virtual STDMETHODIMP
IUnknown::QueryInterface(REFIID riid
, void ** ppvObject
)
2474 using namespace MSTSCLib
;
2478 riid
== IID_IUnknown
||
2479 riid
== IID_IDispatch
||
2480 riid
== IID_IMsTscAdvancedSettings
||
2481 riid
== IID_IMsRdpClientAdvancedSettings
||
2482 riid
== IID_IMsRdpClientAdvancedSettings2
||
2483 riid
== IID_IMsRdpClientAdvancedSettings3
||
2484 riid
== IID_IMsRdpClientAdvancedSettings4
2494 return E_NOINTERFACE
;
2498 virtual STDMETHODIMP_(ULONG
) IUnknown::AddRef()
2500 return Outer()->addRef();
2503 virtual STDMETHODIMP_(ULONG
) IUnknown::Release()
2505 return Outer()->release();
2509 virtual STDMETHODIMP
IDispatch::GetTypeInfoCount(UINT
* pctinfo
)
2515 virtual STDMETHODIMP
IDispatch::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
2518 return DISP_E_BADINDEX
;
2520 return AcquireDispTypeInfo(ppTInfo
);
2523 virtual STDMETHODIMP
IDispatch::GetIDsOfNames(REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
2525 HRESULT hr
= LoadDispTypeInfo();
2530 return m_dispTypeInfo
->GetIDsOfNames(rgszNames
, cNames
, rgDispId
);
2533 virtual STDMETHODIMP
IDispatch::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
, EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
2535 return m_dispTypeInfo
->Invoke
2537 static_cast<MSTSCLib::IMsRdpClientAdvancedSettings4
*>(this),
2547 /* IMsTscAdvancedSettings */
2548 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_Compress(long pcompress
)
2550 return Outer()->SetProperty(Outer()->m_Compress
, pcompress
);
2553 virtual STDMETHODIMP
IMsTscAdvancedSettings::get_Compress(long * pcompress
) const
2555 return Outer()->GetProperty(Outer()->m_Compress
, pcompress
);
2558 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_BitmapPeristence(long pbitmapPeristence
)
2560 return Outer()->SetProperty(Outer()->m_BitmapPersistence
, pbitmapPeristence
);
2563 virtual STDMETHODIMP
IMsTscAdvancedSettings::get_BitmapPeristence(long * pbitmapPeristence
) const
2565 return Outer()->GetProperty(Outer()->m_BitmapPersistence
, pbitmapPeristence
);
2568 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_allowBackgroundInput(long pallowBackgroundInput
)
2570 if(Outer()->IsSafeForScripting())
2573 return Outer()->SetProperty(Outer()->m_allowBackgroundInput
, pallowBackgroundInput
);
2576 virtual STDMETHODIMP
IMsTscAdvancedSettings::get_allowBackgroundInput(long * pallowBackgroundInput
) const
2578 return Outer()->GetProperty(Outer()->m_allowBackgroundInput
, pallowBackgroundInput
);
2581 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_KeyBoardLayoutStr(BSTR rhs
)
2583 return Outer()->SetProperty(Outer()->m_KeyboardLayoutString
, rhs
);
2586 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_PluginDlls(BSTR rhs
)
2588 // TODO: split rhs into an array
2590 // Control marked safe for scripting: only allow filenames
2591 if(Outer()->IsSafeForScripting())
2593 // TODO: validate entries
2594 // TODO: replace each entry with a full path based on the Virtual Channel DLL path
2597 return E_NOTIMPL
; // TODO
2600 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_IconFile(BSTR rhs
)
2605 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_IconIndex(long rhs
)
2610 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_ContainerHandledFullScreen(long pContainerHandledFullScreen
)
2612 if(Outer()->IsSafeForScripting())
2615 return Outer()->SetProperty(Outer()->m_ContainerHandledFullScreen
, pContainerHandledFullScreen
);
2618 virtual STDMETHODIMP
IMsTscAdvancedSettings::get_ContainerHandledFullScreen(long * pContainerHandledFullScreen
) const
2620 return Outer()->GetProperty(Outer()->m_ContainerHandledFullScreen
, pContainerHandledFullScreen
);
2623 virtual STDMETHODIMP
IMsTscAdvancedSettings::put_DisableRdpdr(long pDisableRdpdr
)
2625 return Outer()->SetProperty(Outer()->m_DisableRdpdr
, pDisableRdpdr
);
2628 virtual STDMETHODIMP
IMsTscAdvancedSettings::get_DisableRdpdr(long * pDisableRdpdr
) const
2630 return Outer()->GetProperty(Outer()->m_DisableRdpdr
, pDisableRdpdr
);
2633 /* IMsRdpClientAdvancedSettings */
2634 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_SmoothScroll(long psmoothScroll
)
2639 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_SmoothScroll(long * psmoothScroll
) const
2644 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_AcceleratorPassthrough(long pacceleratorPassthrough
)
2646 return Outer()->SetProperty(Outer()->m_AcceleratorPassthrough
, pacceleratorPassthrough
);
2649 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_AcceleratorPassthrough(long * pacceleratorPassthrough
) const
2651 return Outer()->GetProperty(Outer()->m_AcceleratorPassthrough
, pacceleratorPassthrough
);
2654 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_ShadowBitmap(long pshadowBitmap
)
2656 return Outer()->SetProperty(Outer()->m_ShadowBitmap
, pshadowBitmap
);
2659 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_ShadowBitmap(long * pshadowBitmap
) const
2661 return Outer()->GetProperty(Outer()->m_ShadowBitmap
, pshadowBitmap
);
2664 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_TransportType(long ptransportType
)
2667 return Outer()->SetProperty(Outer()->m_TransportType
, ptransportType
);
2670 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_TransportType(long * ptransportType
) const
2673 return Outer()->GetProperty(Outer()->m_TransportType
, ptransportType
);
2676 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_SasSequence(long psasSequence
)
2679 return Outer()->SetProperty(Outer()->m_SasSequence
, psasSequence
);
2682 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_SasSequence(long * psasSequence
) const
2685 return Outer()->GetProperty(Outer()->m_SasSequence
, psasSequence
);
2688 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_EncryptionEnabled(long pencryptionEnabled
)
2690 return Outer()->SetProperty(Outer()->m_EncryptionEnabled
, pencryptionEnabled
);
2693 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_EncryptionEnabled(long * pencryptionEnabled
) const
2695 return Outer()->GetProperty(Outer()->m_EncryptionEnabled
, pencryptionEnabled
);
2698 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_DedicatedTerminal(long pdedicatedTerminal
)
2700 return Outer()->SetProperty(Outer()->m_DedicatedTerminal
, pdedicatedTerminal
);
2703 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_DedicatedTerminal(long * pdedicatedTerminal
) const
2705 return Outer()->GetProperty(Outer()->m_DedicatedTerminal
, pdedicatedTerminal
);
2708 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RDPPort(long prdpPort
)
2710 if(prdpPort
== 0 || prdpPort
> 65535)
2711 return E_INVALIDARG
;
2713 return Outer()->SetProperty(Outer()->m_RDPPort
, prdpPort
);
2716 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RDPPort(long * prdpPort
) const
2718 return Outer()->GetProperty(Outer()->m_RDPPort
, prdpPort
);
2721 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_EnableMouse(long penableMouse
)
2723 return S_FALSE
; // TBD? implement?
2726 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_EnableMouse(long * penableMouse
) const
2728 return S_FALSE
; // TBD? implement?
2731 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_DisableCtrlAltDel(long pdisableCtrlAltDel
)
2733 return Outer()->SetProperty(Outer()->m_DisableCtrlAltDel
, pdisableCtrlAltDel
);
2736 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_DisableCtrlAltDel(long * pdisableCtrlAltDel
) const
2738 return Outer()->GetProperty(Outer()->m_DisableCtrlAltDel
, pdisableCtrlAltDel
);
2741 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_EnableWindowsKey(long penableWindowsKey
)
2743 return Outer()->SetProperty(Outer()->m_EnableWindowsKey
, penableWindowsKey
);
2746 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_EnableWindowsKey(long * penableWindowsKey
) const
2748 return Outer()->GetProperty(Outer()->m_EnableWindowsKey
, penableWindowsKey
);
2751 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_DoubleClickDetect(long pdoubleClickDetect
)
2753 return Outer()->SetProperty(Outer()->m_DoubleClickDetect
, pdoubleClickDetect
);
2756 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_DoubleClickDetect(long * pdoubleClickDetect
) const
2758 return Outer()->GetProperty(Outer()->m_DoubleClickDetect
, pdoubleClickDetect
);
2761 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_MaximizeShell(long pmaximizeShell
)
2763 return Outer()->SetProperty(Outer()->m_MaximizeShell
, pmaximizeShell
);
2766 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_MaximizeShell(long * pmaximizeShell
) const
2768 return Outer()->GetProperty(Outer()->m_MaximizeShell
, pmaximizeShell
);
2771 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyFullScreen(long photKeyFullScreen
)
2773 return Outer()->SetProperty(Outer()->m_HotKeyFullScreen
, photKeyFullScreen
);
2776 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyFullScreen(long * photKeyFullScreen
) const
2778 return Outer()->GetProperty(Outer()->m_HotKeyFullScreen
, photKeyFullScreen
);
2781 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyCtrlEsc(long photKeyCtrlEsc
)
2783 return Outer()->SetProperty(Outer()->m_HotKeyCtrlEsc
, photKeyCtrlEsc
);
2786 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyCtrlEsc(long * photKeyCtrlEsc
) const
2788 return Outer()->GetProperty(Outer()->m_HotKeyCtrlEsc
, photKeyCtrlEsc
);
2791 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyAltEsc(long photKeyAltEsc
)
2793 return Outer()->SetProperty(Outer()->m_HotKeyAltEsc
, photKeyAltEsc
);
2796 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyAltEsc(long * photKeyAltEsc
) const
2798 return Outer()->GetProperty(Outer()->m_HotKeyAltEsc
, photKeyAltEsc
);
2801 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyAltTab(long photKeyAltTab
)
2803 return Outer()->SetProperty(Outer()->m_HotKeyAltTab
, photKeyAltTab
);
2806 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyAltTab(long * photKeyAltTab
) const
2808 return Outer()->GetProperty(Outer()->m_HotKeyAltTab
, photKeyAltTab
);
2811 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyAltShiftTab(long photKeyAltShiftTab
)
2813 return Outer()->SetProperty(Outer()->m_HotKeyAltShiftTab
, photKeyAltShiftTab
);
2816 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyAltShiftTab(long * photKeyAltShiftTab
) const
2818 return Outer()->GetProperty(Outer()->m_HotKeyAltShiftTab
, photKeyAltShiftTab
);
2821 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyAltSpace(long photKeyAltSpace
)
2823 return Outer()->SetProperty(Outer()->m_HotKeyAltSpace
, photKeyAltSpace
);
2826 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyAltSpace(long * photKeyAltSpace
) const
2828 return Outer()->GetProperty(Outer()->m_HotKeyAltSpace
, photKeyAltSpace
);
2831 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_HotKeyCtrlAltDel(long photKeyCtrlAltDel
)
2833 return Outer()->SetProperty(Outer()->m_HotKeyCtrlAltDel
, photKeyCtrlAltDel
);
2836 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_HotKeyCtrlAltDel(long * photKeyCtrlAltDel
) const
2838 return Outer()->GetProperty(Outer()->m_HotKeyCtrlAltDel
, photKeyCtrlAltDel
);
2841 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_orderDrawThreshold(long porderDrawThreshold
)
2846 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_orderDrawThreshold(long * porderDrawThreshold
) const
2851 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_BitmapCacheSize(long pbitmapCacheSize
)
2853 // NOTE: the upper bound of "32" for a field with a default value of 1500 seems to be a bug
2854 if(pbitmapCacheSize
< 0 || pbitmapCacheSize
> 32)
2855 return E_INVALIDARG
;
2857 return Outer()->SetProperty(Outer()->m_BitmapCacheSize
, pbitmapCacheSize
);
2860 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_BitmapCacheSize(long * pbitmapCacheSize
) const
2862 return Outer()->GetProperty(Outer()->m_BitmapCacheSize
, pbitmapCacheSize
);
2865 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_BitmapVirtualCacheSize(long pbitmapVirtualCacheSize
)
2867 if(pbitmapVirtualCacheSize
< 0 || pbitmapVirtualCacheSize
> 32)
2868 return E_INVALIDARG
;
2870 return Outer()->SetProperty(Outer()->m_BitmapVirtualCacheSize
, pbitmapVirtualCacheSize
);
2873 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_BitmapVirtualCacheSize(long * pbitmapVirtualCacheSize
) const
2875 return Outer()->GetProperty(Outer()->m_BitmapVirtualCacheSize
, pbitmapVirtualCacheSize
);
2878 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_ScaleBitmapCachesByBPP(long pbScale
)
2883 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_ScaleBitmapCachesByBPP(long * pbScale
) const
2888 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_NumBitmapCaches(long pnumBitmapCaches
)
2890 return Outer()->SetProperty(Outer()->m_NumBitmapCaches
, pnumBitmapCaches
);
2893 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_NumBitmapCaches(long * pnumBitmapCaches
) const
2895 return Outer()->GetProperty(Outer()->m_NumBitmapCaches
, pnumBitmapCaches
);
2898 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_CachePersistenceActive(long pcachePersistenceActive
)
2900 return Outer()->SetProperty(Outer()->m_CachePersistenceActive
, pcachePersistenceActive
);
2903 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_CachePersistenceActive(long * pcachePersistenceActive
) const
2905 return Outer()->GetProperty(Outer()->m_CachePersistenceActive
, pcachePersistenceActive
);
2908 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_PersistCacheDirectory(BSTR rhs
)
2913 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_brushSupportLevel(long pbrushSupportLevel
)
2915 return Outer()->SetProperty(Outer()->m_brushSupportLevel
, pbrushSupportLevel
);
2918 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_brushSupportLevel(long * pbrushSupportLevel
) const
2920 return Outer()->GetProperty(Outer()->m_brushSupportLevel
, pbrushSupportLevel
);
2923 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_minInputSendInterval(long pminInputSendInterval
)
2929 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_minInputSendInterval(long * pminInputSendInterval
) const
2935 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_InputEventsAtOnce(long pinputEventsAtOnce
)
2941 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_InputEventsAtOnce(long * pinputEventsAtOnce
) const
2947 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_maxEventCount(long pmaxEventCount
)
2953 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_maxEventCount(long * pmaxEventCount
) const
2959 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_keepAliveInterval(long pkeepAliveInterval
)
2961 if(pkeepAliveInterval
&& pkeepAliveInterval
< 10)
2962 return E_INVALIDARG
;
2964 return Outer()->SetProperty(Outer()->m_keepAliveInternal
, pkeepAliveInterval
);
2967 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_keepAliveInterval(long * pkeepAliveInterval
) const
2969 return Outer()->GetProperty(Outer()->m_keepAliveInternal
, pkeepAliveInterval
);
2972 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_shutdownTimeout(long pshutdownTimeout
)
2974 if(pshutdownTimeout
>= 600)
2975 return E_INVALIDARG
;
2977 return Outer()->SetProperty(Outer()->m_shutdownTimeout
, pshutdownTimeout
);
2980 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_shutdownTimeout(long * pshutdownTimeout
) const
2982 return Outer()->GetProperty(Outer()->m_shutdownTimeout
, pshutdownTimeout
);
2985 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_overallConnectionTimeout(long poverallConnectionTimeout
)
2987 if(poverallConnectionTimeout
< 0 || poverallConnectionTimeout
>= 600)
2988 return E_INVALIDARG
;
2990 return Outer()->SetProperty(Outer()->m_overallConnectionTimeout
, poverallConnectionTimeout
);
2993 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_overallConnectionTimeout(long * poverallConnectionTimeout
) const
2995 return Outer()->GetProperty(Outer()->m_overallConnectionTimeout
, poverallConnectionTimeout
);
2998 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_singleConnectionTimeout(long psingleConnectionTimeout
)
3000 if(psingleConnectionTimeout
>= 600)
3001 return E_INVALIDARG
;
3003 return Outer()->SetProperty(Outer()->m_singleConnectionTimeout
, psingleConnectionTimeout
);
3006 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_singleConnectionTimeout(long * psingleConnectionTimeout
) const
3008 return Outer()->GetProperty(Outer()->m_singleConnectionTimeout
, psingleConnectionTimeout
);
3011 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_KeyboardType(long pkeyboardType
)
3016 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_KeyboardType(long * pkeyboardType
) const
3021 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_KeyboardSubType(long pkeyboardSubType
)
3026 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_KeyboardSubType(long * pkeyboardSubType
) const
3031 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_KeyboardFunctionKey(long pkeyboardFunctionKey
)
3036 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_KeyboardFunctionKey(long * pkeyboardFunctionKey
) const
3041 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_WinceFixedPalette(long pwinceFixedPalette
)
3046 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_WinceFixedPalette(long * pwinceFixedPalette
) const
3051 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_ConnectToServerConsole(VARIANT_BOOL pConnectToConsole
)
3053 return Outer()->SetProperty(Outer()->m_ConnectToServerConsole
, pConnectToConsole
);
3056 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_ConnectToServerConsole(VARIANT_BOOL
* pConnectToConsole
) const
3058 return Outer()->GetProperty(Outer()->m_ConnectToServerConsole
, pConnectToConsole
);
3061 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_BitmapPersistence(long pbitmapPersistence
)
3063 return put_BitmapPeristence(pbitmapPersistence
);
3066 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_BitmapPersistence(long * pbitmapPersistence
) const
3068 return get_BitmapPeristence(pbitmapPersistence
);
3071 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_MinutesToIdleTimeout(long pminutesToIdleTimeout
)
3073 if(pminutesToIdleTimeout
> 240)
3074 return E_INVALIDARG
;
3076 return Outer()->SetProperty(Outer()->m_MinutesToIdleTimeout
, pminutesToIdleTimeout
);
3079 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_MinutesToIdleTimeout(long * pminutesToIdleTimeout
) const
3081 return Outer()->GetProperty(Outer()->m_MinutesToIdleTimeout
, pminutesToIdleTimeout
);
3084 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_SmartSizing(VARIANT_BOOL pfSmartSizing
)
3086 return Outer()->SetProperty(Outer()->m_SmartSizing
, pfSmartSizing
);
3089 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_SmartSizing(VARIANT_BOOL
* pfSmartSizing
) const
3091 return Outer()->GetProperty(Outer()->m_SmartSizing
, pfSmartSizing
);
3094 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RdpdrLocalPrintingDocName(BSTR pLocalPrintingDocName
)
3096 return Outer()->SetProperty(Outer()->m_RdpdrLocalPrintingDocName
, pLocalPrintingDocName
);
3099 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RdpdrLocalPrintingDocName(BSTR
* pLocalPrintingDocName
) const
3101 return Outer()->GetProperty(Outer()->m_RdpdrLocalPrintingDocName
, pLocalPrintingDocName
);
3104 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RdpdrClipCleanTempDirString(BSTR clipCleanTempDirString
)
3106 return Outer()->SetProperty(Outer()->m_RdpdrClipCleanTempDirString
, clipCleanTempDirString
);
3109 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RdpdrClipCleanTempDirString(BSTR
* clipCleanTempDirString
) const
3111 return Outer()->GetProperty(Outer()->m_RdpdrClipCleanTempDirString
, clipCleanTempDirString
);
3114 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RdpdrClipPasteInfoString(BSTR clipPasteInfoString
)
3116 return Outer()->SetProperty(Outer()->m_RdpdrClipPasteInfoString
, clipPasteInfoString
);
3119 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RdpdrClipPasteInfoString(BSTR
* clipPasteInfoString
) const
3121 return Outer()->GetProperty(Outer()->m_RdpdrClipPasteInfoString
, clipPasteInfoString
);
3124 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_ClearTextPassword(BSTR rhs
)
3126 return Outer()->put_ClearTextPassword(rhs
);
3129 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_DisplayConnectionBar(VARIANT_BOOL pDisplayConnectionBar
)
3131 if(!pDisplayConnectionBar
&& Outer()->IsSafeForScripting())
3134 return Outer()->SetProperty(Outer()->m_DisplayConnectionBar
, pDisplayConnectionBar
);
3137 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_DisplayConnectionBar(VARIANT_BOOL
* pDisplayConnectionBar
) const
3139 return Outer()->GetProperty(Outer()->m_DisplayConnectionBar
, pDisplayConnectionBar
);
3142 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_PinConnectionBar(VARIANT_BOOL pPinConnectionBar
)
3144 if(Outer()->IsSafeForScripting())
3147 return Outer()->SetProperty(Outer()->m_PinConnectionBar
, pPinConnectionBar
);
3150 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_PinConnectionBar(VARIANT_BOOL
* pPinConnectionBar
) const
3152 return Outer()->GetProperty(Outer()->m_PinConnectionBar
, pPinConnectionBar
);
3155 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_GrabFocusOnConnect(VARIANT_BOOL pfGrabFocusOnConnect
)
3157 return Outer()->SetProperty(Outer()->m_GrabFocusOnConnect
, pfGrabFocusOnConnect
);
3160 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_GrabFocusOnConnect(VARIANT_BOOL
* pfGrabFocusOnConnect
) const
3162 return Outer()->GetProperty(Outer()->m_GrabFocusOnConnect
, pfGrabFocusOnConnect
);
3165 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_LoadBalanceInfo(BSTR pLBInfo
)
3167 return Outer()->SetProperty(Outer()->m_LoadBalanceInfo
, pLBInfo
);
3170 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_LoadBalanceInfo(BSTR
* pLBInfo
) const
3172 return Outer()->GetProperty(Outer()->m_LoadBalanceInfo
, pLBInfo
);
3175 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RedirectDrives(VARIANT_BOOL pRedirectDrives
)
3177 return Outer()->SetProperty(Outer()->m_RedirectDrives
, pRedirectDrives
);
3180 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RedirectDrives(VARIANT_BOOL
* pRedirectDrives
) const
3182 return Outer()->GetProperty(Outer()->m_RedirectDrives
, pRedirectDrives
);
3185 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RedirectPrinters(VARIANT_BOOL pRedirectPrinters
)
3187 return Outer()->SetProperty(Outer()->m_RedirectPrinters
, pRedirectPrinters
);
3190 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RedirectPrinters(VARIANT_BOOL
* pRedirectPrinters
) const
3192 return Outer()->GetProperty(Outer()->m_RedirectPrinters
, pRedirectPrinters
);
3195 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RedirectPorts(VARIANT_BOOL pRedirectPorts
)
3197 return Outer()->SetProperty(Outer()->m_RedirectPorts
, pRedirectPorts
);
3200 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RedirectPorts(VARIANT_BOOL
* pRedirectPorts
) const
3202 return Outer()->GetProperty(Outer()->m_RedirectPorts
, pRedirectPorts
);
3205 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_RedirectSmartCards(VARIANT_BOOL pRedirectSmartCards
)
3207 return Outer()->SetProperty(Outer()->m_RedirectSmartCards
, pRedirectSmartCards
);
3210 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_RedirectSmartCards(VARIANT_BOOL
* pRedirectSmartCards
) const
3212 return Outer()->GetProperty(Outer()->m_RedirectSmartCards
, pRedirectSmartCards
);
3215 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_BitmapVirtualCache16BppSize(long pBitmapVirtualCache16BppSize
)
3217 if(pBitmapVirtualCache16BppSize
< 0 || pBitmapVirtualCache16BppSize
> 32)
3218 return E_INVALIDARG
;
3220 return Outer()->SetProperty(Outer()->m_BitmapVirtualCache16BppSize
, pBitmapVirtualCache16BppSize
);
3223 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_BitmapVirtualCache16BppSize(long * pBitmapVirtualCache16BppSize
) const
3225 return Outer()->GetProperty(Outer()->m_BitmapVirtualCache16BppSize
, pBitmapVirtualCache16BppSize
);
3228 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_BitmapVirtualCache24BppSize(long pBitmapVirtualCache24BppSize
)
3230 if(pBitmapVirtualCache24BppSize
< 0 || pBitmapVirtualCache24BppSize
> 32)
3231 return E_INVALIDARG
;
3233 return Outer()->SetProperty(Outer()->m_BitmapVirtualCache24BppSize
, pBitmapVirtualCache24BppSize
);
3236 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_BitmapVirtualCache24BppSize(long * pBitmapVirtualCache24BppSize
) const
3238 return Outer()->GetProperty(Outer()->m_BitmapVirtualCache24BppSize
, pBitmapVirtualCache24BppSize
);
3241 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_PerformanceFlags(long pDisableList
)
3243 return Outer()->SetProperty(Outer()->m_PerformanceFlags
, pDisableList
);
3246 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_PerformanceFlags(long * pDisableList
) const
3248 return Outer()->GetProperty(Outer()->m_PerformanceFlags
, pDisableList
);
3251 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_ConnectWithEndpoint(VARIANT
* rhs
)
3253 // TBD? the Microsoft client implements this, but what does it mean?
3257 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::put_NotifyTSPublicKey(VARIANT_BOOL pfNotify
)
3259 return Outer()->SetProperty(Outer()->m_NotifyTSPublicKey
, pfNotify
);
3262 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings::get_NotifyTSPublicKey(VARIANT_BOOL
* pfNotify
) const
3264 return Outer()->GetProperty(Outer()->m_NotifyTSPublicKey
, pfNotify
);
3267 /* IMsRdpClientAdvancedSettings2 */
3268 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings2::get_CanAutoReconnect(VARIANT_BOOL
* pfCanAutoReconnect
) const
3270 return E_NOTIMPL
; // TODO
3273 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings2::put_EnableAutoReconnect(VARIANT_BOOL pfEnableAutoReconnect
)
3275 return Outer()->SetProperty(Outer()->m_EnableAutoReconnect
, pfEnableAutoReconnect
);
3278 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings2::get_EnableAutoReconnect(VARIANT_BOOL
* pfEnableAutoReconnect
) const
3280 return Outer()->GetProperty(Outer()->m_EnableAutoReconnect
, pfEnableAutoReconnect
);
3283 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings2::put_MaxReconnectAttempts(long pMaxReconnectAttempts
)
3285 if(pMaxReconnectAttempts
< 0 || pMaxReconnectAttempts
> 200)
3286 return E_INVALIDARG
;
3288 return Outer()->SetProperty(Outer()->m_MaxReconnectAttempts
, pMaxReconnectAttempts
);
3291 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings2::get_MaxReconnectAttempts(long * pMaxReconnectAttempts
) const
3293 return Outer()->GetProperty(Outer()->m_MaxReconnectAttempts
, pMaxReconnectAttempts
);
3296 /* IMsRdpClientAdvancedSettings3 */
3297 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings3::put_ConnectionBarShowMinimizeButton(VARIANT_BOOL pfShowMinimize
)
3299 return Outer()->SetProperty(Outer()->m_ConnectionBarShowMinimizeButton
, pfShowMinimize
);
3302 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings3::get_ConnectionBarShowMinimizeButton(VARIANT_BOOL
* pfShowMinimize
) const
3304 return Outer()->GetProperty(Outer()->m_ConnectionBarShowMinimizeButton
, pfShowMinimize
);
3307 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings3::put_ConnectionBarShowRestoreButton(VARIANT_BOOL pfShowRestore
)
3309 return Outer()->SetProperty(Outer()->m_ConnectionBarShowRestoreButton
, pfShowRestore
);
3312 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings3::get_ConnectionBarShowRestoreButton(VARIANT_BOOL
* pfShowRestore
) const
3314 return Outer()->GetProperty(Outer()->m_ConnectionBarShowRestoreButton
, pfShowRestore
);
3317 /* IMsRdpClientAdvancedSettings4 */
3318 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings4::put_AuthenticationLevel(unsigned int puiAuthLevel
)
3320 // TODO: this isn't implemented in rdesktop yet...
3321 return Outer()->SetProperty(Outer()->m_AuthenticationLevel
, puiAuthLevel
);
3324 virtual STDMETHODIMP
IMsRdpClientAdvancedSettings4::get_AuthenticationLevel(unsigned int * puiAuthLevel
) const
3326 return Outer()->GetProperty(Outer()->m_AuthenticationLevel
, puiAuthLevel
);
3331 template<class Interface
> HRESULT
GetAdvancedSettings(Interface
** ppAdvSettings
)
3334 *ppAdvSettings
= &m_advancedSettings
;
3338 /* Secured settings wrapper */
3339 friend class SecuredSettings
;
3341 class SecuredSettings SEALED_
: public MSTSCLib::IMsRdpClientSecuredSettings
3346 return InnerToOuter(this);
3349 const RdpClient
* Outer() const
3351 return InnerToOuter(this);
3354 /* IDispatch type information */
3355 ITypeInfo
* m_dispTypeInfo
;
3357 HRESULT
LoadDispTypeInfo()
3362 HRESULT hr
= Outer()->LoadTypeLibrary();
3367 assert(MSTSCLib::IID_IMsRdpClientSecuredSettings
== MSTSCLib_Redist::IID_IMsRdpClientSecuredSettings
);
3369 hr
= Outer()->m_typeLib
->GetTypeInfoOfGuid(MSTSCLib::IID_IMsRdpClientSecuredSettings
, &m_dispTypeInfo
);
3374 assert(m_dispTypeInfo
);
3378 HRESULT
AcquireDispTypeInfo(ITypeInfo
** ppTI
)
3380 HRESULT hr
= LoadDispTypeInfo();
3385 m_dispTypeInfo
->AddRef();
3386 *ppTI
= m_dispTypeInfo
;
3394 m_dispTypeInfo
->Release();
3398 virtual STDMETHODIMP
IUnknown::QueryInterface(REFIID riid
, void ** ppvObject
)
3400 using namespace MSTSCLib
;
3404 riid
== IID_IUnknown
||
3405 riid
== IID_IDispatch
||
3406 riid
== IID_IMsTscSecuredSettings
||
3407 riid
== IID_IMsRdpClientSecuredSettings
3417 return E_NOINTERFACE
;
3421 virtual STDMETHODIMP_(ULONG
) IUnknown::AddRef()
3423 return Outer()->addRef();
3426 virtual STDMETHODIMP_(ULONG
) IUnknown::Release()
3428 return Outer()->release();
3432 virtual STDMETHODIMP
IDispatch::GetTypeInfoCount(UINT
* pctinfo
)
3438 virtual STDMETHODIMP
IDispatch::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
3441 return DISP_E_BADINDEX
;
3443 return AcquireDispTypeInfo(ppTInfo
);
3446 virtual STDMETHODIMP
IDispatch::GetIDsOfNames(REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
3448 HRESULT hr
= LoadDispTypeInfo();
3453 return m_dispTypeInfo
->GetIDsOfNames(rgszNames
, cNames
, rgDispId
);
3456 virtual STDMETHODIMP
IDispatch::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
, EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
3458 return m_dispTypeInfo
->Invoke
3460 static_cast<MSTSCLib::IMsRdpClientSecuredSettings
*>(this),
3470 /* IMsTscSecuredSettings */
3471 virtual STDMETHODIMP
IMsTscSecuredSettings::put_StartProgram(BSTR pStartProgram
)
3473 return Outer()->SetProperty(Outer()->m_StartProgram
, pStartProgram
);
3476 virtual STDMETHODIMP
IMsTscSecuredSettings::get_StartProgram(BSTR
* pStartProgram
) const
3478 return Outer()->GetProperty(Outer()->m_StartProgram
, pStartProgram
);
3481 virtual STDMETHODIMP
IMsTscSecuredSettings::put_WorkDir(BSTR pWorkDir
)
3483 return Outer()->SetProperty(Outer()->m_WorkDir
, pWorkDir
);
3486 virtual STDMETHODIMP
IMsTscSecuredSettings::get_WorkDir(BSTR
* pWorkDir
) const
3488 return Outer()->GetProperty(Outer()->m_WorkDir
, pWorkDir
);
3491 virtual STDMETHODIMP
IMsTscSecuredSettings::put_FullScreen(long pfFullScreen
)
3493 return Outer()->put_FullScreen(!!pfFullScreen
);
3496 virtual STDMETHODIMP
IMsTscSecuredSettings::get_FullScreen(long * pfFullScreen
) const
3498 return Outer()->GetProperty(Outer()->m_FullScreen
, pfFullScreen
);
3501 /* IMsRdpClientSecuredSettings */
3502 virtual STDMETHODIMP
IMsRdpClientSecuredSettings::put_KeyboardHookMode(long pkeyboardHookMode
)
3504 if(pkeyboardHookMode
< 0 || pkeyboardHookMode
> 2)
3505 return E_INVALIDARG
;
3507 return Outer()->SetProperty(Outer()->m_KeyboardHookMode
, pkeyboardHookMode
);
3510 virtual STDMETHODIMP
IMsRdpClientSecuredSettings::get_KeyboardHookMode(long * pkeyboardHookMode
) const
3512 return Outer()->GetProperty(Outer()->m_KeyboardHookMode
, pkeyboardHookMode
);
3515 virtual STDMETHODIMP
IMsRdpClientSecuredSettings::put_AudioRedirectionMode(long pAudioRedirectionMode
)
3517 if(pAudioRedirectionMode
< 0 || pAudioRedirectionMode
> 2)
3518 return E_INVALIDARG
;
3520 return Outer()->SetProperty(Outer()->m_AudioRedirectionMode
, pAudioRedirectionMode
);
3523 virtual STDMETHODIMP
IMsRdpClientSecuredSettings::get_AudioRedirectionMode(long * pAudioRedirectionMode
) const
3525 return Outer()->GetProperty(Outer()->m_AudioRedirectionMode
, pAudioRedirectionMode
);
3530 template<class Interface
> HRESULT
GetSecuredSettings(Interface
** ppSecuredSettings
)
3532 if(!m_SecuredSettingsEnabled
)
3536 *ppSecuredSettings
= &m_securedSettings
;
3540 /* Type library loading */
3541 HRESULT
LoadTypeLibrary()
3546 // Get the DLL name of the ActiveX control
3547 WCHAR szPath
[MAX_PATH
+ 1];
3548 DWORD cchPathLen
= GetModuleFileNameW(GetCurrentModule(), szPath
, ARRAYSIZE(szPath
) - 1);
3551 return HRESULT_FROM_WIN32(GetLastError());
3553 if(cchPathLen
> ((ARRAYSIZE(szPath
) - 1) - 2))
3556 // Append the resource id of the type library
3557 assert(m_typeLibIndex
< 10);
3559 szPath
[cchPathLen
+ 0] = L
'\\';
3560 szPath
[cchPathLen
+ 1] = static_cast<WCHAR
>(L
'0' + m_typeLibIndex
);
3561 szPath
[cchPathLen
+ 2] = 0;
3563 // Load the type library
3564 HRESULT hr
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &m_typeLib
);
3573 /* IDispatch type information */
3574 HRESULT
LoadDispTypeInfo()
3579 HRESULT hr
= LoadTypeLibrary();
3584 assert(MSTSCLib::IID_IMsRdpClient4
== MSTSCLib_Redist::IID_IMsRdpClient4
);
3586 hr
= m_typeLib
->GetTypeInfoOfGuid(MSTSCLib::IID_IMsRdpClient4
, &m_dispTypeInfo
);
3591 assert(m_dispTypeInfo
);
3595 HRESULT
AcquireDispTypeInfo(ITypeInfo
** ppTI
)
3597 HRESULT hr
= LoadDispTypeInfo();
3602 m_dispTypeInfo
->AddRef();
3603 *ppTI
= m_dispTypeInfo
;
3608 /* Helpers for our various embedded children */
3609 static RdpClient
* InnerToOuter(RdpClientInner
* innerThis
)
3611 return CONTAINING_RECORD(innerThis
, RdpClient
, m_inner
);
3614 static RdpClient
* InnerToOuter(AdvancedSettings
* innerThis
)
3616 return CONTAINING_RECORD(innerThis
, RdpClient
, m_advancedSettings
);
3619 static RdpClient
* InnerToOuter(SecuredSettings
* innerThis
)
3621 return CONTAINING_RECORD(innerThis
, RdpClient
, m_securedSettings
);
3624 static RdpClient
* InnerToOuter(RDPCLIENT
* innerThis
)
3626 return CONTAINING_RECORD(innerThis
, RdpClient
, m_protocolState
);
3629 static const RdpClient
* InnerToOuter(const RdpClientInner
* innerThis
)
3631 return CONTAINING_RECORD(innerThis
, RdpClient
, m_inner
);
3634 static const RdpClient
* InnerToOuter(const AdvancedSettings
* innerThis
)
3636 return CONTAINING_RECORD(innerThis
, RdpClient
, m_advancedSettings
);
3639 static const RdpClient
* InnerToOuter(const SecuredSettings
* innerThis
)
3641 return CONTAINING_RECORD(innerThis
, RdpClient
, m_securedSettings
);
3644 static const RdpClient
* InnerToOuter(const RDPCLIENT
* innerThis
)
3646 return CONTAINING_RECORD(innerThis
, RdpClient
, m_protocolState
);
3649 RdpClientUI
* GetUI() const
3655 /* Glue for rdesktop-core */
3657 static bool OnPublicKey(RDPCLIENT
* This
, unsigned char * key
, unsigned int key_size
)
3659 return InnerToOuter(This
)->OnPublicKey(key
, key_size
);
3662 static void OnLogon(RDPCLIENT
* This
)
3664 return InnerToOuter(This
)->OnLogon();
3667 static bool OnRedirect
3675 uint32 username_len
,
3679 uint32 password_len
,
3683 return InnerToOuter(This
)->OnRedirect
3700 bool OnPublicKey(unsigned char * key
, unsigned int key_size
)
3702 HRESULT hr
= FireReceivedTSPublicKey(key
, key_size
);
3706 m_protocolState
.disconnect_reason
= 262;
3716 FireLoginComplete();
3726 uint32 username_len
,
3730 uint32 password_len
,
3734 assert(m_Connected
);
3735 assert(!InsideApartment());
3736 assert(IsWindow(m_controlWindow
));
3738 RedirectArguments redirectArgs
=
3753 return SendMessage(m_controlWindow
, RDPC_WM_REDIRECT
, 0, reinterpret_cast<LPARAM
>(&redirectArgs
)) == 0;
3757 static DWORD WINAPI
ProtocolLoopThreadProc(LPVOID lpParam
)
3759 static_cast<RdpClient
*>(lpParam
)->ProtocolLoop();
3763 static VOID CALLBACK
ConnectionTimerAPC(LPVOID
, DWORD
, DWORD
)
3767 // FIXME: various potential inconsistencies due to lack of detailed documentation of expected semantics
3770 HANDLE waitingReconnection
= NULL
;
3772 // Retrieve the local hostname to be passed to the server
3773 WCHAR hostname
[MAX_COMPUTERNAME_LENGTH
+ 1];
3774 DWORD hostnameLen
= ARRAYSIZE(hostname
);
3776 if(!GetComputerNameW(hostname
, &hostnameLen
))
3779 // Set some connection flags
3780 uint32 flags
= RDP_LOGON_NORMAL
;
3783 flags
|= RDP_LOGON_COMPRESSION
| RDP_LOGON_COMPRESSION2
;
3785 if(m_AudioRedirectionMode
== 1)
3786 flags
|= RDP_LOGON_LEAVE_AUDIO
;
3788 if(m_ClearTextPassword
)
3789 flags
|= RDP_LOGON_AUTO
;
3791 // Notify the container that the connection process is beginning now
3794 // Set the overall connection timer, if a timeout is set
3795 // BUGBUG: the timeout semantics are ambiguous and have been most probably misinterpreted
3796 HANDLE overallConnectionTimer
= NULL
;
3797 LARGE_INTEGER overallTimeout
;
3799 if(m_overallConnectionTimeout
)
3801 overallTimeout
.QuadPart
= - ((m_overallConnectionTimeout
* 1000 * 1000 * 1000) / 100);
3803 overallConnectionTimer
= CreateWaitableTimer(NULL
, FALSE
, NULL
);
3805 if(overallConnectionTimer
== NULL
)
3809 if(overallConnectionTimer
)
3810 SetWaitableTimer(overallConnectionTimer
, &overallTimeout
, 0, ConnectionTimerAPC
, NULL
, FALSE
);
3812 // Initial connection
3813 BOOL disconnected
= rdp_connect
3820 m_ClearTextPassword
,
3827 if(overallConnectionTimer
)
3828 CancelWaitableTimer(overallConnectionTimer
);
3833 // TODO: set the disconnect reason for every instance in which we abort the loop
3836 BOOL deactivated
= False
;
3837 uint32 extendedDisconnectReason
= 0;
3839 m_actuallyConnected
= true;
3841 // Notify the container of the successful connection
3844 // Main protocol loop
3846 rdp_main_loop(&m_protocolState
, &deactivated
, &extendedDisconnectReason
);
3847 rdp_disconnect(&m_protocolState
);
3849 m_actuallyConnected
= false;
3852 // BUGBUG: redirection is very messy and probably this implementation is not "canonical"
3853 if(m_protocolState
.redirect
)
3855 m_protocolState
.redirect
= False
;
3856 rdp_reset_state(&m_protocolState
);
3858 // TODO: reset connection parameters
3859 // This has to be done in the main thread, so use SendMessage on the control window
3861 flags
|= RDP_LOGON_AUTO
;
3868 m_ExtendedDisconnectReason
= static_cast<MSTSCLib::ExtendedDisconnectReasonCode
>(extendedDisconnectReason
);
3870 // Clean disconnection
3876 long autoReconnections
= 0;
3877 long totalReconnections
= 0;
3880 // BUGBUG: reconnection semantics may not be entirely accurate
3883 ++ totalReconnections
;
3885 // ask the container whether we should reconnect
3886 long reconnectMode
= FireAutoReconnecting(m_protocolState
.disconnect_reason
, totalReconnections
);
3889 if(reconnectMode
== MSTSCLib::autoReconnectContinueStop
)
3892 // the container will reconnect or abort manually
3893 if(reconnectMode
== MSTSCLib::autoReconnectContinueManual
)
3895 assert(!m_reconnectAborted
);
3896 assert(m_protocolThreadWaitingReconnection
== NULL
);
3898 if(waitingReconnection
== NULL
)
3900 waitingReconnection
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
3902 if(waitingReconnection
== NULL
)
3903 // TODO: fatal error
3907 m_protocolThreadWaitingReconnection
= waitingReconnection
;
3909 WaitForSingleObject(waitingReconnection
, INFINITE
);
3911 m_protocolThreadWaitingReconnection
= NULL
;
3913 if(m_reconnectAborted
)
3915 // FIXME? do we set the disconnection status here?
3919 // reconnect automatically
3922 // automatic reconnection is disabled
3923 if(m_EnableAutoReconnect
)
3926 // too many consecutive automatic reconnections
3927 if(autoReconnections
== m_MaxReconnectAttempts
)
3930 ++ autoReconnections
;
3933 if(overallConnectionTimer
)
3934 SetWaitableTimer(overallConnectionTimer
, &overallTimeout
, 0, ConnectionTimerAPC
, NULL
, FALSE
);
3937 success
= rdp_reconnect
3944 m_ClearTextPassword
,
3951 if(overallConnectionTimer
)
3952 CancelWaitableTimer(overallConnectionTimer
);
3959 FireDisconnected(m_protocolState
.disconnect_reason
);
3961 if(overallConnectionTimer
)
3962 CloseHandle(overallConnectionTimer
);
3965 void JoinProtocolThread()
3967 assert(m_protocolThread
);
3968 WaitForSingleObject(m_protocolThread
, INFINITE
);
3969 CloseHandle(m_protocolThread
);
3970 m_protocolThread
= NULL
;
3973 void TerminateProtocolThread()
3975 assert(m_protocolThread
);
3977 // wake it up if it's waiting for a manual reconnection
3978 if(m_protocolThreadWaitingReconnection
)
3980 assert(!m_reconnectAborted
);
3981 m_reconnectAborted
= true;
3982 SetEvent(m_protocolThreadWaitingReconnection
);
3984 // otherwise, attempt to interrupt any current blocking operation
3987 // shutdown(m_protocolState.tcp.sock, SD_BOTH); // TBD: maybe in the future?
3988 QueueUserAPC(DisconnectAPC
, m_protocolThread
, 0);
3991 assert(m_protocolThreadWaitingReconnection
== NULL
);
3994 void PerformDisconnect(long reason
)
3996 assert(InsideApartment());
3997 assert(m_Connected
);
3999 // TODO: notify virtual channels
4001 // TODO: do any other disconnection work here...
4003 // Put the control in the disconnected state
4004 m_Connected
= false;
4007 // Notify the container
4008 VARIANTARG arg
= { };
4013 FireEventInsideApartment(4, &arg
, 1);
4017 /* Startup initialization */
4018 static BOOL
Startup()
4020 if(!RdpClientUI::Startup())
4023 WNDCLASSEX wcex
= { sizeof(wcex
) };
4025 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
4026 wcex
.lpfnWndProc
= ControlWindowProc
;
4027 wcex
.hInstance
= GetCurrentModule();
4028 wcex
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
4029 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
4030 wcex
.lpszClassName
= TEXT("MissTosca_Control");
4032 return RegisterClassEx(&wcex
);;
4035 static void Shutdown()
4037 UnregisterClass(TEXT("MissTosca_Control"), GetCurrentModule());
4041 static HRESULT
CreateInstance(REFCLSID rclsid
, unsigned libIndex
, IUnknown
* punkOuter
, REFIID riid
, void ** ppObj
)
4043 RdpClient
* obj
= new RdpClient(rclsid
, libIndex
, punkOuter
);
4046 return E_OUTOFMEMORY
;
4048 HRESULT hr
= obj
->m_inner
.QueryInterface(riid
, ppObj
);
4056 assert(obj
->m_refCount
== 1);
4057 assert(*ppObj
!= NULL
);
4063 /* Connection point enumerator */
4064 class CEnumConnectionPoints
: public IEnumConnectionPoints
4068 IConnectionPoint
* m_cp
;
4072 CEnumConnectionPoints(IConnectionPoint
* cp
): m_refCount(1), m_cp(cp
), m_done(false)
4078 CEnumConnectionPoints(const CEnumConnectionPoints
& ecp
): m_refCount(1), m_cp(ecp
.m_cp
), m_done(ecp
.m_done
)
4084 ~CEnumConnectionPoints()
4090 virtual STDMETHODIMP
QueryInterface(REFIID riid
, void ** ppvObject
)
4092 if(riid
== IID_IUnknown
|| riid
== IID_IEnumConnectionPoints
)
4100 return E_NOINTERFACE
;
4104 virtual STDMETHODIMP_(ULONG
) AddRef()
4106 return InterlockedIncrement(&m_refCount
);
4109 virtual STDMETHODIMP_(ULONG
) Release()
4111 LONG n
= InterlockedDecrement(&m_refCount
);
4119 virtual STDMETHODIMP
Next(ULONG cConnections
, LPCONNECTIONPOINT
* ppCP
, ULONG
* pcFetched
)
4121 if(cConnections
== 0 || m_done
)
4132 virtual STDMETHODIMP
Skip(ULONG cConnections
)
4134 if(cConnections
== 0)
4137 if(cConnections
== 1 && !m_done
)
4143 assert(cConnections
> 1 || m_done
);
4148 virtual STDMETHODIMP
Reset()
4154 virtual STDMETHODIMP
Clone(IEnumConnectionPoints
** ppEnum
)
4159 *ppEnum
= new CEnumConnectionPoints(*this);
4162 return E_OUTOFMEMORY
;
4168 /* Pay no attention, ActiveX glue... */
4169 LRESULT
ControlWindowProc(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
4182 LPCWSTR text
= NULL
;
4185 text
= m_DisconnectedText
;
4186 else if(m_actuallyConnected
)
4187 text
= m_ConnectedStatusText
;
4189 text
= m_ConnectingText
;
4192 GetClientRect(m_controlWindow
, &clientRect
);
4195 HDC hdc
= BeginPaint(m_controlWindow
, &ps
);
4197 SetBkColor(hdc
, GetSysColor(COLOR_WINDOW
));
4198 SetTextColor(hdc
, GetSysColor(COLOR_WINDOWTEXT
));
4199 SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
4201 RECT textRect
= clientRect
;
4209 DT_CENTER
| DT_EDITCONTROL
| DT_END_ELLIPSIS
| DT_NOPREFIX
| DT_WORDBREAK
| DT_CALCRECT
4212 if(textRect
.right
> clientRect
.right
)
4213 textRect
.right
= clientRect
.right
;
4215 if(textRect
.bottom
> clientRect
.bottom
)
4216 textRect
.bottom
= clientRect
.bottom
;
4218 textRect
.left
= (clientRect
.right
- textRect
.right
) / 2;
4219 textRect
.right
+= textRect
.left
;
4220 textRect
.top
= (clientRect
.bottom
- textRect
.bottom
) / 2;
4221 textRect
.bottom
+= textRect
.top
;
4229 DT_CENTER
| DT_EDITCONTROL
| DT_END_ELLIPSIS
| DT_NOPREFIX
| DT_WORDBREAK
4232 EndPaint(m_controlWindow
, &ps
);
4241 if(HandleEvent(uMsg
, wParam
, lParam
, result
))
4248 return DefWindowProc(m_controlWindow
, uMsg
, wParam
, lParam
);
4251 static LRESULT CALLBACK
ControlWindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
4253 if(uMsg
== WM_CREATE
)
4259 (LONG_PTR
)reinterpret_cast<LPCREATESTRUCT
>(lParam
)->lpCreateParams
4263 RdpClient
* Self
= reinterpret_cast<RdpClient
*>(GetWindowLongPtr(hwnd
, GWLP_USERDATA
));
4266 return Self
->ControlWindowProc(uMsg
, wParam
, lParam
);
4269 HRESULT
CreateControlWindow(HWND hwndParent
)
4271 m_controlWindow
= CreateWindow
4273 TEXT("MissTosca_Control"),
4275 WS_CHILD
| WS_CLIPCHILDREN
,
4286 if(m_controlWindow
== NULL
)
4287 return HRESULT_FROM_WIN32(GetLastError());
4289 m_UIParentWindowHandle
= m_controlWindow
;
4293 HRESULT
DestroyControlWindow()
4295 if(m_controlWindow
== NULL
)
4298 HWND controlWindow
= NULL
;
4299 std::swap(controlWindow
, m_controlWindow
);
4300 DestroyWindow(controlWindow
);
4304 HRESULT
Activate(LONG iVerb
, IOleClientSite
* pActiveSite
, HWND hwndParent
, LPCRECT lprcPosRect
)
4306 if(pActiveSite
== NULL
)
4307 pActiveSite
= m_clientSite
;
4309 if(pActiveSite
== NULL
)
4312 // TODO: store this until we are closed or deactivated
4313 IOleInPlaceSite
* site
;
4315 HRESULT hr
= pActiveSite
->QueryInterface(&site
);
4320 IOleInPlaceFrame
* frame
= NULL
;
4321 IOleInPlaceUIWindow
* uiWindow
= NULL
;
4325 hr
= site
->CanInPlaceActivate();
4333 site
->OnInPlaceActivate();
4335 if(hwndParent
== NULL
)
4337 hr
= site
->GetWindow(&hwndParent
);
4345 OLEINPLACEFRAMEINFO frameInfo
= { sizeof(frameInfo
) };
4347 site
->GetWindowContext(&frame
, &uiWindow
, &rcPos
, &rcClip
, &frameInfo
);
4349 if(lprcPosRect
== NULL
)
4350 lprcPosRect
= &rcPos
;
4353 ShowWindow(m_controlWindow
, SW_SHOW
);
4356 hr
= CreateControlWindow(hwndParent
);
4362 SetObjectRects(lprcPosRect
, &rcClip
);
4365 if((iVerb
== OLEIVERB_PRIMARY
|| iVerb
== OLEIVERB_UIACTIVATE
) && !m_uiActive
)
4369 hr
= site
->OnUIActivate();
4380 lprcPosRect
->right
- lprcPosRect
->left
,
4381 lprcPosRect
->bottom
- lprcPosRect
->top
,
4387 frame
->SetActiveObject(this, NULL
);
4388 frame
->SetBorderSpace(NULL
);
4393 uiWindow
->SetActiveObject(this, NULL
);
4394 uiWindow
->SetBorderSpace(NULL
);
4402 uiWindow
->Release();
4410 pActiveSite
->ShowObject();
4418 NOTE: this is the delegating implementation, to support aggregation. The actual
4419 implementation is RdpClientInner, above
4421 virtual STDMETHODIMP
IUnknown::QueryInterface(REFIID riid
, void ** ppvObject
)
4423 return m_punkOuter
->QueryInterface(riid
, ppvObject
);
4426 virtual STDMETHODIMP_(ULONG
) IUnknown::AddRef()
4428 return m_punkOuter
->AddRef();
4431 virtual STDMETHODIMP_(ULONG
) IUnknown::Release()
4433 return m_punkOuter
->Release();
4437 virtual STDMETHODIMP
IDispatch::GetTypeInfoCount(UINT
* pctinfo
)
4443 virtual STDMETHODIMP
IDispatch::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
4446 return DISP_E_BADINDEX
;
4448 return AcquireDispTypeInfo(ppTInfo
);
4451 virtual STDMETHODIMP
IDispatch::GetIDsOfNames(REFIID riid
, LPOLESTR
* rgszNames
, UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
4453 HRESULT hr
= LoadDispTypeInfo();
4458 return m_dispTypeInfo
->GetIDsOfNames(rgszNames
, cNames
, rgDispId
);
4461 virtual STDMETHODIMP
IDispatch::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
, EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
4463 HRESULT hr
= LoadDispTypeInfo();
4468 return m_dispTypeInfo
->Invoke
4470 static_cast<MSTSCLib::IMsRdpClient4
*>(this),
4480 /* IConnectionPoint */
4481 virtual STDMETHODIMP
GetConnectionInterface(IID
* pIID
)
4486 *pIID
= MSTSCLib::DIID_IMsTscAxEvents
;
4490 virtual STDMETHODIMP
GetConnectionPointContainer(IConnectionPointContainer
** ppCPC
)
4500 virtual STDMETHODIMP
Advise(IUnknown
* pUnkSink
, DWORD
* pdwCookie
)
4502 MSTSCLib::IMsTscAxEvents
* sink
;
4504 if(FAILED(pUnkSink
->QueryInterface(&sink
)))
4505 return CONNECT_E_CANNOTCONNECT
;
4507 MSTSCLib::IMsTscAxEvents
** sinks
= GetSinks();
4510 if(m_EventSinksCount
)
4514 for(size_t i
= 0; i
< m_EventSinksCount
; ++ i
)
4516 found
= (sinks
[i
] == NULL
);
4520 cookie
= static_cast<DWORD
>(i
);
4527 MSTSCLib::IMsTscAxEvents
** newSinks
= new MSTSCLib::IMsTscAxEvents
*[m_EventSinksCount
+ 1];
4529 if(newSinks
== NULL
)
4532 return E_OUTOFMEMORY
;
4535 std::copy(sinks
, sinks
+ m_EventSinksCount
, newSinks
);
4537 m_EventSinks
= newSinks
;
4540 cookie
= static_cast<DWORD
>(m_EventSinksCount
);
4544 sinks
[cookie
] = sink
;
4545 *pdwCookie
= cookie
;
4550 virtual STDMETHODIMP
Unadvise(DWORD dwCookie
)
4552 MSTSCLib::IMsTscAxEvents
** sinks
= GetSinks();
4554 if(dwCookie
>= m_EventSinksCount
|| sinks
[dwCookie
] == NULL
)
4555 return CONNECT_E_NOCONNECTION
;
4557 sinks
[dwCookie
]->Release();
4558 sinks
[dwCookie
] = NULL
;
4560 // BUGBUG: the array currently grows forever. Trim it whenever possible
4565 virtual STDMETHODIMP
EnumConnections(IEnumConnections
** ppEnum
)
4567 // I see no real value in this
4571 /* IConnectionPointContainer */
4572 virtual STDMETHODIMP
IConnectionPointContainer::EnumConnectionPoints(IEnumConnectionPoints
** ppEnum
)
4574 *ppEnum
= new CEnumConnectionPoints(this);
4577 return E_OUTOFMEMORY
;
4582 virtual STDMETHODIMP
IConnectionPointContainer::FindConnectionPoint(REFIID riid
, IConnectionPoint
** ppCP
)
4584 if(riid
!= MSTSCLib::DIID_IMsTscAxEvents
)
4585 return CONNECT_E_NOCONNECTION
;
4593 /* IDataObject */ // 0/9
4594 virtual STDMETHODIMP
IDataObject::GetData(FORMATETC
* pformatetcIn
, STGMEDIUM
* pmedium
)
4599 virtual STDMETHODIMP
IDataObject::GetDataHere(FORMATETC
* pformatetc
, STGMEDIUM
* pmedium
)
4604 virtual STDMETHODIMP
IDataObject::QueryGetData(FORMATETC
* pformatetc
)
4609 virtual STDMETHODIMP
IDataObject::GetCanonicalFormatEtc(FORMATETC
* pformatectIn
, FORMATETC
* pformatetcOut
)
4614 virtual STDMETHODIMP
IDataObject::SetData(FORMATETC
* pformatetc
, STGMEDIUM
* pmedium
, BOOL fRelease
)
4619 virtual STDMETHODIMP
IDataObject::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatEtc
)
4624 virtual STDMETHODIMP
IDataObject::DAdvise(FORMATETC
* pformatetc
, DWORD advf
, IAdviseSink
* pAdvSink
, DWORD
* pdwConnection
)
4629 virtual STDMETHODIMP
IDataObject::DUnadvise(DWORD dwConnection
)
4634 virtual STDMETHODIMP
IDataObject::EnumDAdvise(IEnumSTATDATA
** ppenumAdvise
)
4640 virtual STDMETHODIMP
IObjectSafety::GetInterfaceSafetyOptions(REFIID riid
, DWORD
* pdwSupportedOptions
, DWORD
* pdwEnabledOptions
)
4642 if(pdwSupportedOptions
== NULL
|| pdwEnabledOptions
== NULL
)
4645 if(riid
!= IID_IDispatch
)
4646 return E_NOINTERFACE
;
4648 *pdwSupportedOptions
= INTERFACESAFE_FOR_UNTRUSTED_CALLER
;
4649 *pdwEnabledOptions
= m_SafetyOptions
;
4653 virtual STDMETHODIMP
IObjectSafety::SetInterfaceSafetyOptions(REFIID riid
, DWORD dwOptionSetMask
, DWORD dwEnabledOptions
)
4655 if(riid
!= IID_IDispatch
)
4656 return E_NOINTERFACE
;
4658 m_SafetyOptions
= dwEnabledOptions
& (dwOptionSetMask
& INTERFACESAFE_FOR_UNTRUSTED_CALLER
);
4662 /* IOleControl */ // 3/4
4663 virtual STDMETHODIMP
IOleControl::GetControlInfo(CONTROLINFO
* pCI
)
4668 virtual STDMETHODIMP
IOleControl::OnMnemonic(MSG
* pMsg
)
4673 virtual STDMETHODIMP
IOleControl::OnAmbientPropertyChange(DISPID dispID
)
4678 virtual STDMETHODIMP
IOleControl::FreezeEvents(BOOL bFreeze
)
4681 InterlockedIncrement(&m_freezeEvents
);
4682 else if(InterlockedDecrement(&m_freezeEvents
) == 0)
4688 /* IOleInPlaceActiveObject */ // 3/5
4689 virtual STDMETHODIMP
IOleInPlaceActiveObject::TranslateAccelerator(LPMSG lpmsg
)
4694 virtual STDMETHODIMP
IOleInPlaceActiveObject::OnFrameWindowActivate(BOOL fActivate
)
4700 virtual STDMETHODIMP
IOleInPlaceActiveObject::OnDocWindowActivate(BOOL fActivate
)
4706 virtual STDMETHODIMP
IOleInPlaceActiveObject::ResizeBorder(LPCRECT prcBorder
, IOleInPlaceUIWindow
* pUIWindow
, BOOL fFrameWindow
)
4711 virtual STDMETHODIMP
IOleInPlaceActiveObject::EnableModeless(BOOL fEnable
)
4716 /* IOleInPlaceObject */ // 1/4
4717 virtual STDMETHODIMP
IOleInPlaceObject::InPlaceDeactivate()
4719 // TODO: UIDeactivate, destroy window, inplacesite->OnInPlaceDeactivate
4723 virtual STDMETHODIMP
IOleInPlaceObject::UIDeactivate()
4729 virtual STDMETHODIMP
IOleInPlaceObject::SetObjectRects(LPCRECT lprcPosRect
, LPCRECT lprcClipRect
)
4731 if(m_controlWindow
== NULL
)
4739 lprcPosRect
->right
- lprcPosRect
->left
,
4740 lprcPosRect
->bottom
- lprcPosRect
->top
,
4744 SetWindowRgn(m_controlWindow
, CreateRectRgnIndirect(lprcClipRect
), TRUE
);
4749 virtual STDMETHODIMP
IOleInPlaceObject::ReactivateAndUndo()
4754 /* IOleObject */ // 18/21
4755 virtual STDMETHODIMP
IOleObject::SetClientSite(IOleClientSite
* pClientSite
)
4758 m_clientSite
->Release();
4760 m_clientSite
= pClientSite
;
4763 m_clientSite
->AddRef();
4768 virtual STDMETHODIMP
IOleObject::GetClientSite(IOleClientSite
** ppClientSite
)
4770 if(ppClientSite
== NULL
)
4774 m_clientSite
->AddRef();
4776 *ppClientSite
= m_clientSite
;
4780 virtual STDMETHODIMP
IOleObject::SetHostNames(LPCOLESTR szContainerApp
, LPCOLESTR szContainerObj
)
4785 virtual STDMETHODIMP
IOleObject::Close(DWORD dwSaveOption
)
4787 // TODO: deactivate, destroy window, release in-place site, release advise sink
4788 return E_NOTIMPL
; // TODO
4791 virtual STDMETHODIMP
IOleObject::SetMoniker(DWORD dwWhichMoniker
, IMoniker
* pmk
)
4796 virtual STDMETHODIMP
IOleObject::GetMoniker(DWORD dwAssign
, DWORD dwWhichMoniker
, IMoniker
** ppmk
)
4801 virtual STDMETHODIMP
IOleObject::InitFromData(IDataObject
* pDataObject
, BOOL fCreation
, DWORD dwReserved
)
4806 virtual STDMETHODIMP
IOleObject::GetClipboardData(DWORD dwReserved
, IDataObject
** ppDataObject
)
4811 virtual STDMETHODIMP
IOleObject::DoVerb(LONG iVerb
, LPMSG lpmsg
, IOleClientSite
* pActiveSite
, LONG lindex
, HWND hwndParent
, LPCRECT lprcPosRect
)
4817 case OLEIVERB_PRIMARY
:
4819 case OLEIVERB_UIACTIVATE
:
4820 case OLEIVERB_INPLACEACTIVATE
:
4826 hr
= OLEOBJ_S_INVALIDVERB
;
4834 HRESULT hrActivate
= Activate(iVerb
, pActiveSite
, hwndParent
, lprcPosRect
);
4836 if(FAILED(hrActivate
))
4842 virtual STDMETHODIMP
IOleObject::EnumVerbs(IEnumOLEVERB
** ppEnumOleVerb
)
4844 return OleRegEnumVerbs(m_classId
, ppEnumOleVerb
);
4847 virtual STDMETHODIMP
IOleObject::Update()
4852 virtual STDMETHODIMP
IOleObject::IsUpToDate()
4857 virtual STDMETHODIMP
IOleObject::GetUserClassID(CLSID
* pClsid
)
4859 *pClsid
= m_classId
;
4863 virtual STDMETHODIMP
IOleObject::GetUserType(DWORD dwFormOfType
, LPOLESTR
* pszUserType
)
4865 return OleRegGetUserType(m_classId
, dwFormOfType
, pszUserType
);
4868 virtual STDMETHODIMP
IOleObject::SetExtent(DWORD dwDrawAspect
, SIZEL
* psizel
)
4874 virtual STDMETHODIMP
IOleObject::GetExtent(DWORD dwDrawAspect
, SIZEL
* psizel
)
4876 // TODO: return size
4880 HRESULT
NeedAdviseHolder()
4885 return CreateOleAdviseHolder(&m_adviseHolder
);
4888 virtual STDMETHODIMP
IOleObject::Advise(IAdviseSink
* pAdvSink
, DWORD
* pdwConnection
)
4890 HRESULT hr
= NeedAdviseHolder();
4895 return m_adviseHolder
->Advise(pAdvSink
, pdwConnection
);
4898 virtual STDMETHODIMP
IOleObject::Unadvise(DWORD dwConnection
)
4900 HRESULT hr
= NeedAdviseHolder();
4905 return m_adviseHolder
->Unadvise(dwConnection
);
4908 virtual STDMETHODIMP
IOleObject::EnumAdvise(IEnumSTATDATA
** ppenumAdvise
)
4910 HRESULT hr
= NeedAdviseHolder();
4915 return m_adviseHolder
->EnumAdvise(ppenumAdvise
);
4918 virtual STDMETHODIMP
IOleObject::GetMiscStatus(DWORD dwAspect
, DWORD
* pdwStatus
)
4920 return OleRegGetMiscStatus(m_classId
, dwAspect
, pdwStatus
);
4923 virtual STDMETHODIMP
IOleObject::SetColorScheme(LOGPALETTE
* pLogpal
)
4929 virtual STDMETHODIMP
IOleWindow::GetWindow(HWND
* phwnd
)
4934 if(m_controlWindow
== NULL
)
4937 *phwnd
= m_controlWindow
;
4941 virtual STDMETHODIMP
IOleWindow::ContextSensitiveHelp(BOOL fEnterMode
)
4947 virtual STDMETHODIMP
IPersist::GetClassID(CLSID
* pClassID
)
4949 *pClassID
= m_classId
;
4953 /* IPersistPropertyBag */ // 0/3
4954 virtual STDMETHODIMP
IPersistPropertyBag::InitNew()
4959 virtual STDMETHODIMP
IPersistPropertyBag::Load(IPropertyBag
* pPropBag
, IErrorLog
* pErrorLog
)
4964 virtual STDMETHODIMP
IPersistPropertyBag::Save(IPropertyBag
* pPropBag
, BOOL fClearDirty
, BOOL fSaveAllProperties
)
4969 /* IPersistStorage */ // 0/6
4970 virtual STDMETHODIMP
IPersistStorage::IsDirty()
4975 virtual STDMETHODIMP
IPersistStorage::InitNew(IStorage
* pStg
)
4980 virtual STDMETHODIMP
IPersistStorage::Load(IStorage
* pStg
)
4985 virtual STDMETHODIMP
IPersistStorage::Save(IStorage
* pStgSave
, BOOL fSameAsLoad
)
4990 virtual STDMETHODIMP
IPersistStorage::SaveCompleted(IStorage
* pStgNew
)
4995 virtual STDMETHODIMP
IPersistStorage::HandsOffStorage()
5000 /* IPersistStreamInit */ // 0/5
5001 virtual STDMETHODIMP
IPersistStreamInit::IsDirty()
5006 virtual STDMETHODIMP
IPersistStreamInit::Load(LPSTREAM pStm
)
5011 virtual STDMETHODIMP
IPersistStreamInit::Save(LPSTREAM pStm
, BOOL fClearDirty
)
5016 virtual STDMETHODIMP
IPersistStreamInit::GetSizeMax(ULARGE_INTEGER
* pCbSize
)
5021 virtual STDMETHODIMP
IPersistStreamInit::InitNew()
5026 /* IProvideClassInfo */
5027 virtual STDMETHODIMP
IProvideClassInfo::GetClassInfo(ITypeInfo
** ppTI
)
5029 HRESULT hr
= LoadTypeLibrary();
5034 return m_typeLib
->GetTypeInfoOfGuid(m_classId
, ppTI
);
5037 /* IProvideClassInfo2 */
5038 virtual STDMETHODIMP
IProvideClassInfo2::GetGUID(DWORD dwGuidKind
, GUID
* pGUID
)
5040 if(dwGuidKind
!= GUIDKIND_DEFAULT_SOURCE_DISP_IID
)
5041 return E_INVALIDARG
;
5043 *pGUID
= MSTSCLib::DIID_IMsTscAxEvents
;
5047 /* IQuickActivate */
5048 virtual STDMETHODIMP
IQuickActivate::QuickActivate(QACONTAINER
* pQaContainer
, QACONTROL
* pQaControl
)
5050 if(pQaContainer
== NULL
|| pQaControl
== NULL
)
5053 if(pQaContainer
->cbSize
< sizeof(*pQaContainer
) || pQaControl
->cbSize
< sizeof(*pQaControl
))
5054 return E_INVALIDARG
;
5056 ULONG cb
= pQaControl
->cbSize
;
5057 ZeroMemory(pQaControl
, cb
);
5058 pQaControl
->cbSize
= cb
;
5060 SetClientSite(pQaContainer
->pClientSite
);
5062 if(pQaContainer
->pAdviseSink
)
5063 SetAdvise(DVASPECT_CONTENT
, 0, pQaContainer
->pAdviseSink
);
5065 if(pQaContainer
->pUnkEventSink
)
5066 Advise(pQaContainer
->pUnkEventSink
, &pQaControl
->dwEventCookie
);
5068 GetMiscStatus(DVASPECT_CONTENT
, &pQaControl
->dwMiscStatus
);
5073 virtual STDMETHODIMP
IQuickActivate::SetContentExtent(LPSIZEL pSizel
)
5075 return SetExtent(DVASPECT_CONTENT
, pSizel
);
5078 virtual STDMETHODIMP
IQuickActivate::GetContentExtent(LPSIZEL pSizel
)
5080 return GetExtent(DVASPECT_CONTENT
, pSizel
);
5083 /* IViewObject */ // 3/6
5084 virtual STDMETHODIMP
IViewObject::Draw(DWORD dwDrawAspect
, LONG lindex
, void * pvAspect
, DVTARGETDEVICE
* ptd
, HDC hdcTargetDev
, HDC hdcDraw
, LPCRECTL lprcBounds
, LPCRECTL lprcWBounds
, BOOL (STDMETHODCALLTYPE
* pfnContinue
)(ULONG_PTR dwContinue
), ULONG_PTR dwContinue
)
5086 return E_NOTIMPL
; // TODO
5089 virtual STDMETHODIMP
IViewObject::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void * pvAspect
, DVTARGETDEVICE
* ptd
, HDC hicTargetDev
, LOGPALETTE
** ppColorSet
)
5094 virtual STDMETHODIMP
IViewObject::Freeze(DWORD dwDrawAspect
, LONG lindex
, void * pvAspect
, DWORD
* pdwFreeze
)
5099 virtual STDMETHODIMP
IViewObject::Unfreeze(DWORD dwFreeze
)
5104 virtual STDMETHODIMP
IViewObject::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
* pAdvSink
)
5106 return E_NOTIMPL
; // TODO
5109 virtual STDMETHODIMP
IViewObject::GetAdvise(DWORD
* pAspects
, DWORD
* pAdvf
, IAdviseSink
** ppAdvSink
)
5111 return E_NOTIMPL
; // TODO
5114 /* IViewObject2 */ // 0/1
5115 virtual STDMETHODIMP
IViewObject2::GetExtent(DWORD dwDrawAspect
, LONG lindex
, DVTARGETDEVICE
* ptd
, LPSIZEL lpsizel
)
5117 return E_NOTIMPL
; // TODO
5120 /* IMsTscAx */ // 23/30
5121 virtual STDMETHODIMP
IMsTscAx::put_Server(BSTR pServer
)
5123 // FIXME: convert the hostname to Punycode, not the ANSI codepage
5124 return SetProperty(m_Server
, pServer
);
5127 virtual STDMETHODIMP
IMsTscAx::get_Server(BSTR
* pServer
) const
5129 return GetProperty(m_Server
, pServer
);
5132 virtual STDMETHODIMP
IMsTscAx::put_Domain(BSTR pDomain
)
5134 return SetProperty(m_Domain
, pDomain
);
5137 virtual STDMETHODIMP
IMsTscAx::get_Domain(BSTR
* pDomain
) const
5139 return GetProperty(m_Domain
, pDomain
);
5142 virtual STDMETHODIMP
IMsTscAx::put_UserName(BSTR pUserName
)
5144 return SetProperty(m_UserName
, pUserName
);
5147 virtual STDMETHODIMP
IMsTscAx::get_UserName(BSTR
* pUserName
) const
5149 return GetProperty(m_UserName
, pUserName
);
5152 virtual STDMETHODIMP
IMsTscAx::put_DisconnectedText(BSTR pDisconnectedText
)
5154 return SetProperty(m_DisconnectedText
, pDisconnectedText
);
5157 virtual STDMETHODIMP
IMsTscAx::get_DisconnectedText(BSTR
* pDisconnectedText
) const
5159 return GetProperty(m_DisconnectedText
, pDisconnectedText
);
5162 virtual STDMETHODIMP
IMsTscAx::put_ConnectingText(BSTR pConnectingText
)
5164 return SetProperty(m_ConnectingText
, pConnectingText
);
5167 virtual STDMETHODIMP
IMsTscAx::get_ConnectingText(BSTR
* pConnectingText
) const
5169 return GetProperty(m_ConnectingText
, pConnectingText
);
5172 virtual STDMETHODIMP
IMsTscAx::get_Connected(short * pIsConnected
) const
5174 return GetProperty(m_Connected
, pIsConnected
);
5177 virtual STDMETHODIMP
IMsTscAx::put_DesktopWidth(long pVal
)
5179 if(pVal
< 200 || pVal
> 1600)
5180 return E_INVALIDARG
;
5182 return SetProperty(m_DesktopWidth
, pVal
);
5185 virtual STDMETHODIMP
IMsTscAx::get_DesktopWidth(long * pVal
) const
5187 return GetProperty(m_DesktopWidth
, pVal
);
5190 virtual STDMETHODIMP
IMsTscAx::put_DesktopHeight(long pVal
)
5192 if(pVal
< 200 || pVal
> 1200)
5193 return E_INVALIDARG
;
5195 return SetProperty(m_DesktopHeight
, pVal
);
5198 virtual STDMETHODIMP
IMsTscAx::get_DesktopHeight(long * pVal
) const
5200 return GetProperty(m_DesktopHeight
, pVal
);
5203 virtual STDMETHODIMP
IMsTscAx::put_StartConnected(long pfStartConnected
)
5205 return SetProperty(m_StartConnected
, pfStartConnected
);
5208 virtual STDMETHODIMP
IMsTscAx::get_StartConnected(long * pfStartConnected
) const
5210 return GetProperty(m_StartConnected
, pfStartConnected
);
5213 virtual STDMETHODIMP
IMsTscAx::get_HorizontalScrollBarVisible(long * pfHScrollVisible
) const
5215 return E_NOTIMPL
; // TODO
5218 virtual STDMETHODIMP
IMsTscAx::get_VerticalScrollBarVisible(long * pfVScrollVisible
) const
5220 return E_NOTIMPL
; // TODO
5223 virtual STDMETHODIMP
IMsTscAx::put_FullScreenTitle(BSTR rhs
)
5229 virtual STDMETHODIMP
IMsTscAx::get_CipherStrength(long * pCipherStrength
) const
5231 if(pCipherStrength
== NULL
)
5232 return E_INVALIDARG
;
5234 *pCipherStrength
= 128; // BUGBUG: a later version may change this. Use a compile-time constant
5238 virtual STDMETHODIMP
IMsTscAx::get_Version(BSTR
* pVersion
) const
5240 if(pVersion
== NULL
)
5241 return E_INVALIDARG
;
5243 BSTR version
= SysAllocString(L
"5.2.3790.1830"); // BUGBUG: don't use hardcoded string
5246 return E_OUTOFMEMORY
;
5248 *pVersion
= version
;
5252 virtual STDMETHODIMP
IMsTscAx::get_SecuredSettingsEnabled(long * pSecuredSettingsEnabled
) const
5254 // TODO: initialize m_SecuredSettingsEnabled as soon as we have an OLE client site
5255 return GetProperty(m_SecuredSettingsEnabled
, pSecuredSettingsEnabled
);
5258 virtual STDMETHODIMP
IMsTscAx::get_SecuredSettings(MSTSCLib::IMsTscSecuredSettings
** ppSecuredSettings
) const
5260 return GetSecuredSettings(ppSecuredSettings
);
5263 virtual STDMETHODIMP
IMsTscAx::get_AdvancedSettings(MSTSCLib::IMsTscAdvancedSettings
** ppAdvSettings
) const
5265 return GetAdvancedSettings(ppAdvSettings
);
5268 virtual STDMETHODIMP
IMsTscAx::get_Debugger(MSTSCLib::IMsTscDebug
** ppDebugger
) const
5273 virtual STDMETHODIMP
IMsTscAx::Connect()
5277 // Protocol thread waiting for a manual reconnection: wake it up
5278 if(m_protocolThreadWaitingReconnection
)
5280 SetEvent(m_protocolThreadWaitingReconnection
);
5291 if(m_controlWindow
== NULL
)
5293 hr
= CreateControlWindow(NULL
);
5301 // TODO: initialize plugin DLLs/channels
5303 m_clientUI
= new RdpClientUI();
5305 if(m_clientUI
== NULL
)
5311 m_clientUI
->Initialize(m_controlWindow
);
5313 m_protocolState
.licence_username
= BstrToLpsz(m_UserName
);
5315 if(m_protocolState
.licence_username
== NULL
)
5321 DWORD dwSize
= ARRAYSIZE(m_protocolState
.licence_hostname
);
5323 if(!GetComputerNameA(m_protocolState
.licence_hostname
, &dwSize
))
5325 hr
= HRESULT_FROM_WIN32(GetLastError());
5330 // BUGBUG: not too sure about the semantics
5331 long keyboardLayout
= -1;
5332 WCHAR
* endPtr
= NULL
;
5334 if(m_KeyboardLayoutString
)
5335 keyboardLayout
= wcstol(m_KeyboardLayoutString
, &endPtr
, 0);
5337 // no keyboard layout specified or invalid keyboard layout: use current keyboard layout
5338 if(endPtr
== NULL
|| *endPtr
== 0 || keyboardLayout
== -1)
5339 keyboardLayout
= PtrToLong(GetKeyboardLayout(0)); // FIXME? use LOWORD()?
5341 m_protocolState
.keylayout
= keyboardLayout
;
5343 // in case of failure, assume English (US)
5344 if(m_protocolState
.keylayout
== 0)
5345 m_protocolState
.keylayout
= MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
5347 // Physical keyboard information
5348 m_protocolState
.keyboard_type
= GetKeyboardType(0);
5349 m_protocolState
.keyboard_subtype
= GetKeyboardType(1);
5350 m_protocolState
.keyboard_functionkeys
= GetKeyboardType(2);
5352 // in case of failure, assume an IBM Enhanced keyboard with 12 function keys
5353 if(m_protocolState
.keyboard_type
== 0 || m_protocolState
.keyboard_functionkeys
== 0)
5355 m_protocolState
.keyboard_type
= 4;
5356 m_protocolState
.keyboard_subtype
= 0;
5357 m_protocolState
.keyboard_functionkeys
= 12;
5360 // More initialization
5361 m_protocolState
.width
= m_DesktopWidth
;
5362 m_protocolState
.height
= m_DesktopHeight
;
5363 m_protocolState
.server_depth
= m_ColorDepth
;
5364 m_protocolState
.bitmap_compression
= m_Compress
? TRUE
: FALSE
;
5365 m_protocolState
.bitmap_cache
= True
; // TODO
5366 m_protocolState
.bitmap_cache_persist_enable
= False
; // TODO
5367 m_protocolState
.bitmap_cache_precache
= True
; // FIXME?
5368 m_protocolState
.encryption
= m_EncryptionEnabled
? TRUE
: FALSE
; // TBD: detect automatically
5369 m_protocolState
.packet_encryption
= m_EncryptionEnabled
? TRUE
: FALSE
;
5370 m_protocolState
.desktop_save
= True
; // FIXME? tie to bitmap cache setting?
5371 m_protocolState
.polygon_ellipse_orders
= True
;
5372 m_protocolState
.use_rdp5
= True
; // TBD: detect automatically
5373 m_protocolState
.console_session
= m_ConnectToServerConsole
? TRUE
: FALSE
;
5374 m_protocolState
.rdp5_performanceflags
= m_PerformanceFlags
;
5375 m_protocolState
.tcp_port_rdp
= m_RDPPort
;
5376 m_protocolState
.rdp
.current_status
= 1;
5378 // TODO: cache tuning based on the provided parameters
5380 m_protocolState
.cache
.bmpcache_lru
[0] = -1;
5381 m_protocolState
.cache
.bmpcache_lru
[1] = -1;
5382 m_protocolState
.cache
.bmpcache_lru
[2] = -1;
5383 m_protocolState
.cache
.bmpcache_mru
[0] = -1;
5384 m_protocolState
.cache
.bmpcache_mru
[1] = -1;
5385 m_protocolState
.cache
.bmpcache_mru
[2] = -1;
5388 m_protocolThread
= CreateThread(NULL
, 0, ProtocolLoopThreadProc
, this, 0, &dwIgnore
);
5395 m_Connected
= false;
5400 virtual STDMETHODIMP
IMsTscAx::Disconnect()
5405 // Terminate the protocol thread. On exit, it will fire the Disconnected event
5406 TerminateProtocolThread();
5410 virtual STDMETHODIMP
IMsTscAx::CreateVirtualChannels(BSTR newVal
)
5412 UINT strLength
= SysStringLen(newVal
);
5414 if(strLength
< 1 || strLength
> 300)
5415 return E_INVALIDARG
;
5417 return E_NOTIMPL
; // TODO
5420 virtual STDMETHODIMP
IMsTscAx::SendOnVirtualChannel(BSTR chanName
, BSTR ChanData
)
5422 return E_NOTIMPL
; // TODO
5425 /* IMsRdpClient */ // 6/10
5426 virtual STDMETHODIMP
IMsRdpClient::put_ColorDepth(long pcolorDepth
)
5438 return E_INVALIDARG
;
5441 return SetProperty(m_ColorDepth
, pcolorDepth
);
5444 virtual STDMETHODIMP
IMsRdpClient::get_ColorDepth(long * pcolorDepth
) const
5446 return GetProperty(m_ColorDepth
, pcolorDepth
);
5449 virtual STDMETHODIMP
IMsRdpClient::get_AdvancedSettings2(MSTSCLib::IMsRdpClientAdvancedSettings
** ppAdvSettings
) const
5451 return GetAdvancedSettings(ppAdvSettings
);
5454 virtual STDMETHODIMP
IMsRdpClient::get_SecuredSettings2(MSTSCLib::IMsRdpClientSecuredSettings
** ppSecuredSettings
) const
5456 return GetSecuredSettings(ppSecuredSettings
);
5459 virtual STDMETHODIMP
IMsRdpClient::get_ExtendedDisconnectReason(MSTSCLib::ExtendedDisconnectReasonCode
* pExtendedDisconnectReason
) const
5461 return GetProperty(m_ExtendedDisconnectReason
, pExtendedDisconnectReason
);
5464 virtual STDMETHODIMP
IMsRdpClient::put_FullScreen(VARIANT_BOOL pfFullScreen
)
5469 if(pfFullScreen
&& !m_SecuredSettingsEnabled
)
5476 virtual STDMETHODIMP
IMsRdpClient::get_FullScreen(VARIANT_BOOL
* pfFullScreen
) const
5478 return GetProperty(m_FullScreen
, pfFullScreen
);
5481 virtual STDMETHODIMP
IMsRdpClient::SetVirtualChannelOptions(BSTR chanName
, long chanOptions
)
5483 return E_NOTIMPL
; // TODO
5486 virtual STDMETHODIMP
IMsRdpClient::GetVirtualChannelOptions(BSTR chanName
, long * pChanOptions
)
5488 return E_NOTIMPL
; // TODO
5491 virtual STDMETHODIMP
IMsRdpClient::RequestClose(MSTSCLib::ControlCloseStatus
* pCloseStatus
)
5493 if(pCloseStatus
== NULL
)
5498 *pCloseStatus
= MSTSCLib::controlCloseCanProceed
;
5502 *pCloseStatus
= MSTSCLib::controlCloseWaitForEvents
;
5504 if(!PostMessage(m_controlWindow
, RDPC_WM_REQUEST_CLOSE
, 0, 0))
5505 return HRESULT_FROM_WIN32(GetLastError());
5511 virtual STDMETHODIMP
IMsRdpClient2::get_AdvancedSettings3(MSTSCLib::IMsRdpClientAdvancedSettings2
** ppAdvSettings
) const
5513 return GetAdvancedSettings(ppAdvSettings
);
5516 virtual STDMETHODIMP
IMsRdpClient2::put_ConnectedStatusText(BSTR pConnectedStatusText
)
5518 return SetProperty(m_ConnectedStatusText
, pConnectedStatusText
);
5521 virtual STDMETHODIMP
IMsRdpClient2::get_ConnectedStatusText(BSTR
* pConnectedStatusText
) const
5523 return GetProperty(m_ConnectedStatusText
, pConnectedStatusText
);
5527 virtual STDMETHODIMP
IMsRdpClient3::get_AdvancedSettings4(MSTSCLib::IMsRdpClientAdvancedSettings3
** ppAdvSettings
) const
5529 return GetAdvancedSettings(ppAdvSettings
);
5533 virtual STDMETHODIMP
IMsRdpClient4::get_AdvancedSettings5(MSTSCLib::IMsRdpClientAdvancedSettings4
** ppAdvSettings5
) const
5535 return GetAdvancedSettings(ppAdvSettings5
);
5538 /* IMsTscNonScriptable */
5539 virtual STDMETHODIMP
IMsTscNonScriptable::put_ClearTextPassword(BSTR rhs
)
5541 return SetProperty(m_ClearTextPassword
, rhs
);
5544 virtual STDMETHODIMP
IMsTscNonScriptable::put_PortablePassword(BSTR pPortablePass
)
5549 virtual STDMETHODIMP
IMsTscNonScriptable::get_PortablePassword(BSTR
* pPortablePass
) const
5554 virtual STDMETHODIMP
IMsTscNonScriptable::put_PortableSalt(BSTR pPortableSalt
)
5559 virtual STDMETHODIMP
IMsTscNonScriptable::get_PortableSalt(BSTR
* pPortableSalt
) const
5564 virtual STDMETHODIMP
IMsTscNonScriptable::put_BinaryPassword(BSTR pBinaryPassword
)
5569 virtual STDMETHODIMP
IMsTscNonScriptable::get_BinaryPassword(BSTR
* pBinaryPassword
) const
5574 virtual STDMETHODIMP
IMsTscNonScriptable::put_BinarySalt(BSTR pSalt
)
5579 virtual STDMETHODIMP
IMsTscNonScriptable::get_BinarySalt(BSTR
* pSalt
) const
5584 virtual STDMETHODIMP
IMsTscNonScriptable::ResetPassword()
5586 return SetProperty(m_ClearTextPassword
, NULL
);
5589 /* IMsRdpClientNonScriptable */ // 0/2
5590 virtual STDMETHODIMP
IMsRdpClientNonScriptable::NotifyRedirectDeviceChange(MSTSCLib::UINT_PTR wParam
, MSTSCLib::LONG_PTR lParam
)
5592 return E_NOTIMPL
; // TODO
5595 virtual STDMETHODIMP
IMsRdpClientNonScriptable::SendKeys(long numKeys
, VARIANT_BOOL
* pbArrayKeyUp
, long * plKeyData
)
5597 // NOTE: the keys must be sent in a single, atomic sequence
5598 // TODO: acquire the write lock
5599 return E_NOTIMPL
; // TODO
5602 /* IMsRdpClientNonScriptable2 */
5603 virtual STDMETHODIMP
IMsRdpClientNonScriptable2::put_UIParentWindowHandle(HWND phwndUIParentWindowHandle
)
5605 return SetProperty(m_UIParentWindowHandle
, phwndUIParentWindowHandle
);
5608 virtual STDMETHODIMP
IMsRdpClientNonScriptable2::get_UIParentWindowHandle(HWND
* phwndUIParentWindowHandle
) const
5610 return GetProperty(m_UIParentWindowHandle
, phwndUIParentWindowHandle
);
5614 #pragma warning(pop)
5616 /* More glue to interface to the rdesktop code */
5621 /* support routines */
5622 void ui_begin_update(RDPCLIENT
* This
)
5624 RdpClient::InnerToOuter(This
)->GetUI()->Display_BeginUpdate();
5627 void ui_end_update(RDPCLIENT
* This
)
5629 RdpClient::InnerToOuter(This
)->GetUI()->Display_EndUpdate();
5632 void ui_set_clip(RDPCLIENT
* This
, int x
, int y
, int cx
, int cy
)
5634 RdpClient::InnerToOuter(This
)->GetUI()->Display_SetClip(x
, y
, cx
, cy
);
5637 void ui_reset_clip(RDPCLIENT
* This
)
5639 RdpClient::InnerToOuter(This
)->GetUI()->Display_ResetClip();
5643 void ui_destblt(RDPCLIENT
* This
, uint8 opcode
, int x
, int y
, int cx
, int cy
)
5645 RdpClient::InnerToOuter(This
)->GetUI()->Display_DestBlt(opcode
, x
, y
, cx
, cy
);
5648 void ui_memblt(RDPCLIENT
* This
, uint8 opcode
, int x
, int y
, int cx
, int cy
, HBITMAP src
, int srcx
, int srcy
)
5650 RdpClient::InnerToOuter(This
)->GetUI()->Display_MemBlt(opcode
, x
, y
, cx
, cy
, src
, srcx
, srcy
);
5653 void ui_patblt(RDPCLIENT
* This
, uint8 opcode
, int x
, int y
, int cx
, int cy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
5655 RdpClient::InnerToOuter(This
)->GetUI()->Display_PatBlt(opcode
, x
, y
, cx
, cy
, brush
, bgcolour
, fgcolour
);
5658 void ui_screenblt(RDPCLIENT
* This
, uint8 opcode
, int x
, int y
, int cx
, int cy
, int srcx
, int srcy
)
5660 RdpClient::InnerToOuter(This
)->GetUI()->Display_ScreenBlt(opcode
, x
, y
, cx
, cy
, srcx
, srcy
);
5663 void ui_triblt(RDPCLIENT
* This
, uint8 opcode
, int x
, int y
, int cx
, int cy
, HBITMAP src
, int srcx
, int srcy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
5665 RdpClient::InnerToOuter(This
)->GetUI()->Display_TriBlt(opcode
, x
, y
, cx
, cy
, src
, srcx
, srcy
, brush
, bgcolour
, fgcolour
);
5668 void ui_paint_bitmap(RDPCLIENT
* This
, int x
, int y
, int cx
, int cy
, int width
, int height
, uint8
* data
)
5670 RdpClient::InnerToOuter(This
)->GetUI()->Display_PaintBitmap(x
, y
, cx
, cy
, width
, height
, data
);
5674 void ui_ellipse(RDPCLIENT
* This
, uint8 opcode
, uint8 fillmode
, int x
, int y
, int cx
, int cy
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
5677 // RdpClient::InnerToOuter(This)->GetUI()->Display_Ellipse(opcode, fillmode, x, y, cx, cy, brush, bgcolour, fgcolour);
5680 void ui_line(RDPCLIENT
* This
, uint8 opcode
, int startx
, int starty
, int endx
, int endy
, PEN
* pen
)
5682 RdpClient::InnerToOuter(This
)->GetUI()->Display_Line(opcode
, startx
, starty
, endx
, endy
, pen
);
5685 void ui_polygon(RDPCLIENT
* This
, uint8 opcode
, uint8 fillmode
, POINT
* point
, int npoints
, BRUSH
* brush
, int bgcolour
, int fgcolour
)
5687 RdpClient::InnerToOuter(This
)->GetUI()->Display_Polygon(opcode
, fillmode
, point
, npoints
, brush
, bgcolour
, fgcolour
);
5690 void ui_polyline(RDPCLIENT
* This
, uint8 opcode
, POINT
* points
, int npoints
, PEN
* pen
)
5692 RdpClient::InnerToOuter(This
)->GetUI()->Display_Polyline(opcode
, points
, npoints
, pen
);
5695 void ui_rect(RDPCLIENT
* This
, int x
, int y
, int cx
, int cy
, int colour
)
5697 RdpClient::InnerToOuter(This
)->GetUI()->Display_Rect(x
, y
, cx
, cy
, colour
);
5725 RdpClient::InnerToOuter(This
)->GetUI()->Display_DrawText
5749 /* desktop save/restore */
5750 void ui_desktop_save(RDPCLIENT
* This
, uint32 offset
, int x
, int y
, int cx
, int cy
)
5752 RdpClient::InnerToOuter(This
)->GetUI()->Display_SaveDesktop(offset
, x
, y
, cx
, cy
);
5755 void ui_desktop_restore(RDPCLIENT
* This
, uint32 offset
, int x
, int y
, int cx
, int cy
)
5757 RdpClient::InnerToOuter(This
)->GetUI()->Display_RestoreDesktop(offset
, x
, y
, cx
, cy
);
5762 HBITMAP
ui_create_bitmap(RDPCLIENT
* This
, int width
, int height
, uint8
* data
)
5764 return win32_create_dib(width
, height
, This
->server_depth
, data
);
5767 void ui_destroy_bitmap(RDPCLIENT
*, HBITMAP bmp
)
5773 HCOLOURMAP
ui_create_colourmap(RDPCLIENT
*, COLOURMAP
* colours
)
5778 void ui_set_colourmap(RDPCLIENT
* This
, HCOLOURMAP map
)
5784 HCURSOR
ui_create_cursor(RDPCLIENT
* This
, unsigned int x
, unsigned int y
, int width
, int height
, uint8
* andmask
, uint8
* xormask
)
5786 uint8
* andbuf
= NULL
;
5787 uint8
* xorbuf
= NULL
;
5789 uint8
* andbits
= win32_convert_scanlines(width
, - height
, 1, 2, 4, andmask
, &andbuf
);
5790 uint8
* xorbits
= win32_convert_scanlines(width
, height
, 24, 2, 4, xormask
, &xorbuf
);
5792 HBITMAP hbmMask
= CreateBitmap(width
, height
, 1, 1, andbits
);
5793 HBITMAP hbmColor
= win32_create_dib(width
, height
, 24, xorbits
);
5796 iconinfo
.fIcon
= FALSE
;
5797 iconinfo
.xHotspot
= x
;
5798 iconinfo
.yHotspot
= y
;
5799 iconinfo
.hbmMask
= hbmMask
;
5800 iconinfo
.hbmColor
= hbmColor
;
5802 HICON icon
= CreateIconIndirect(&iconinfo
);
5805 error("CreateIconIndirect %dx%d failed\n", width
, height
);
5813 DeleteObject(hbmMask
);
5814 DeleteObject(hbmColor
);
5819 void ui_destroy_cursor(RDPCLIENT
*, HCURSOR cursor
)
5821 DestroyIcon(cursor
);
5825 HGLYPH
ui_create_glyph(RDPCLIENT
* This
, int width
, int height
, const uint8
* data
)
5827 uint8
* databuf
= NULL
;
5828 uint8
* databits
= win32_convert_scanlines(width
, height
, 1, 1, 2, data
, &databuf
);
5830 HBITMAP hbm
= CreateBitmap(width
, height
, 1, 1, databits
);
5835 const uint8
* p
= data
;
5836 int stride
= alignup(alignup(width
, 8) / 8, 1);
5839 printf("glyph %p\n", hbm
);
5841 for(int i
= 0; i
< height
; ++ i
, p
+= stride
)
5843 for(int j
= 0; j
< width
; ++ j
)
5846 int b
= 8 - j
% 8 - 1;
5849 fputs("##", stdout
);
5851 fputs("..", stdout
);
5854 fputc('\n', stdout
);
5857 fputc('\n', stdout
);
5863 void ui_destroy_glyph(RDPCLIENT
*, HGLYPH glyph
)
5865 DeleteObject(glyph
);
5869 void ui_move_pointer(RDPCLIENT
* This
, int x
, int y
)
5874 void ui_set_cursor(RDPCLIENT
* This
, HCURSOR cursor
)
5879 void ui_set_null_cursor(RDPCLIENT
* This
)
5885 void ui_resize_window(RDPCLIENT
* This
)
5889 void ui_bell(RDPCLIENT
*)
5894 int ui_select(RDPCLIENT
* This
, SOCKET rdp_socket
)
5896 return SleepEx(0, TRUE
) == WAIT_IO_COMPLETION
;
5900 BOOL
event_pubkey(RDPCLIENT
* This
, unsigned char * key
, unsigned int key_size
)
5902 if(!RdpClient::OnPublicKey(This
, key
, key_size
))
5908 void event_logon(RDPCLIENT
* This
)
5910 RdpClient::OnLogon(This
);
5913 BOOL
event_redirect(RDPCLIENT
* This
, uint32 flags
, uint32 server_len
, wchar_t * server
, uint32 cookie_len
, char * cookie
, uint32 username_len
, wchar_t * username
, uint32 domain_len
, wchar_t * domain
, uint32 password_len
, wchar_t * password
)
5917 !RdpClient::OnRedirect
5940 class ClassFactory
: public IClassFactory
5945 unsigned m_libIndex
;
5948 ClassFactory(REFCLSID rclsid
, unsigned libIndex
):
5960 virtual STDMETHODIMP
QueryInterface(REFIID riid
, void ** ppvObject
)
5962 if(riid
== IID_IUnknown
|| riid
== IID_IClassFactory
)
5970 return E_NOINTERFACE
;
5974 virtual STDMETHODIMP_(ULONG
) AddRef()
5976 return InterlockedIncrement(&m_refCount
);
5979 virtual STDMETHODIMP_(ULONG
) Release()
5981 LONG n
= InterlockedDecrement(&m_refCount
);
5989 virtual STDMETHODIMP
CreateInstance(IUnknown
* pUnkOuter
, REFIID riid
, void ** ppvObject
)
5991 if(pUnkOuter
&& riid
!= IID_IUnknown
)
5992 return CLASS_E_NOAGGREGATION
;
5994 return RdpClient::CreateInstance(m_classId
, m_libIndex
, pUnkOuter
, riid
, ppvObject
);
5997 virtual STDMETHODIMP
LockServer(BOOL fLock
)
6011 STDAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
6017 rclsid
== MSTSCLib::CLSID_MsTscAx
||
6018 rclsid
== MSTSCLib::CLSID_MsRdpClient
||
6019 rclsid
== MSTSCLib::CLSID_MsRdpClient2
||
6020 rclsid
== MSTSCLib::CLSID_MsRdpClient3
||
6021 rclsid
== MSTSCLib::CLSID_MsRdpClient4
6026 rclsid
== MSTSCLib_Redist::CLSID_MsTscAx
||
6027 rclsid
== MSTSCLib_Redist::CLSID_MsRdpClient
||
6028 rclsid
== MSTSCLib_Redist::CLSID_MsRdpClient2
||
6029 rclsid
== MSTSCLib_Redist::CLSID_MsRdpClient3
// ||
6030 // rclsid != MSTSCLib::CLSID_MsRdpClient4
6034 return CLASS_E_CLASSNOTAVAILABLE
;
6036 ClassFactory
* p
= new ClassFactory(rclsid
, libindex
);
6039 return E_OUTOFMEMORY
;
6041 HRESULT hr
= p
->QueryInterface(riid
, ppv
);
6051 STDAPI
DllCanUnloadNow(void)
6053 return canUnloadServer() ? S_OK
: S_FALSE
;
6056 STDAPI_(ULONG
) DllGetTscCtlVer(void)
6058 // BUGBUG: don't hardcode this
6059 return 0x05020ECE; // 5.2.3790
6062 DWORD WINAPI
DllMain(HINSTANCE hInstance
, DWORD fdwReason
, LPVOID lpvReserved
)
6064 assert(hInstance
== GetCurrentModule());
6068 case DLL_PROCESS_ATTACH
:
6070 DisableThreadLibraryCalls(hInstance
);
6072 if(!RdpClient::Startup())
6078 case DLL_PROCESS_DETACH
:
6080 // Process is terminating, no need to clean up
6084 RdpClient::Shutdown();