ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
August 2006
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
19 participants
447 discussions
Start a n
N
ew thread
[mc] 23627: modified porting-tools/rdesktop-core-tester/activex.cpp modified porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp And from the chrysalis out came... the caterpillar. MissTosca stops just short of being demonstrable. I'll keep working on it, but the Google Summer of Code is, for all intent and purposes, over. The matter is in the hands of my judges now. Wish me luck modified rdesktop/iso.c modified rdesktop/proto.h modified rdesktop/rdesktop.h modified rdesktop/rdp.c Very m
by mc@svn.reactos.org
Author: mc Date: Mon Aug 21 01:02:10 2006 New Revision: 23627 URL:
http://svn.reactos.org/svn/reactos?rev=23627&view=rev
Log: modified porting-tools/rdesktop-core-tester/activex.cpp modified porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp And from the chrysalis out came... the caterpillar. MissTosca stops just short of being demonstrable. I'll keep working on it, but the Google Summer of Code is, for all intent and purposes, over. The matter is in the hands of my judges now. Wish me luck modified rdesktop/iso.c modified rdesktop/proto.h modified rdesktop/rdesktop.h modified rdesktop/rdp.c Very minor fixes modified rdesktop/tcp.c Use asynchronous I/O and alertable waits to allow aborting the protocol thread ASAP Modified: trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/activex.cpp trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp trunk/reactos/base/applications/tsclient/rdesktop/iso.c trunk/reactos/base/applications/tsclient/rdesktop/proto.h trunk/reactos/base/applications/tsclient/rdesktop/rdesktop.h trunk/reactos/base/applications/tsclient/rdesktop/rdp.c trunk/reactos/base/applications/tsclient/rdesktop/tcp.c Modified: trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/activex.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/activex.cpp (original) +++ trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/activex.cpp Mon Aug 21 01:02:10 2006 @@ -52,29 +52,53 @@ namespace { -LPSTR BstrToLpsz(BSTR bstr) -{ - int cch = WideCharToMultiByte(CP_ACP, 0, bstr, -1, NULL, 0, NULL, NULL); +void FreeLpsz(LPSTR lpsz) +{ + if(lpsz) + delete[] lpsz; +} + +LPSTR AllocLpsz(const CHAR * lpsz, size_t cb) +{ + LPSTR lpszNew = new CHAR[cb + 1]; + + if(lpszNew == NULL) + return NULL; + + CopyMemory(lpszNew, lpsz, cb); + lpszNew[cb] = 0; + + return lpszNew; +} + +LPSTR AllocLpsz(const WCHAR * lpwsz, int cchIn) +{ + int cch = WideCharToMultiByte(CP_ACP, 0, lpwsz, cchIn, NULL, 0, NULL, NULL); if(cch <= 0) return NULL; - LPSTR lpsz = new char[cch]; + LPSTR lpsz = new CHAR[cch]; if(lpsz == NULL) return NULL; - cch = WideCharToMultiByte(CP_ACP, 0, bstr, -1, lpsz, cch, NULL, NULL); + cch = WideCharToMultiByte(CP_ACP, 0, lpwsz, cchIn, lpsz, cch, NULL, NULL); if(cch <= 0) { - delete[] lpsz; + FreeLpsz(lpsz); return NULL; } return lpsz; } +LPSTR BstrToLpsz(BSTR bstr) +{ + return AllocLpsz(bstr, SysStringLen(bstr)); +} + BSTR LpszToBstr(LPSTR lpsz) { int cch = MultiByteToWideChar(CP_ACP, 0, lpsz, -1, NULL, 0); @@ -99,6 +123,168 @@ } } + +namespace +{ + +template<class T, class U> T aligndown(const T& X, const U& align) +{ + return X & ~(T(align) - 1); +} + +template<class T, class U> T alignup(const T& X, const U& align) +{ + return aligndown(X + (align - 1), align); +} + +/* Convert between bitmap formats */ +uint8 * win32_convert_scanlines(int width, int height, int bitcount, int fromalign, int toalign, const uint8 * data, uint8 ** buffer) +{ + // TBD: profile & optimize the most common cases + assert(width > 0); + assert(height); + assert(bitcount && bitcount <= 32); + assert(fromalign <= toalign); + assert(data); + assert(buffer); + + bool flipped = height < 0; + + if(flipped) + height = - height; + + int bytesperrow = alignup(width * bitcount, 8) / 8; + int fromstride = alignup(bytesperrow, fromalign); + int tostride = alignup(bytesperrow, toalign); + assert(fromstride <= tostride); + + int datasize = tostride * height; + + uint8 * dibits = new uint8[datasize]; + + const uint8 * src = data; + uint8 * dest = dibits; + + const int pad = tostride - fromstride; + + assert(pad < 4); + __assume(pad < 4); + + if(flipped) + { + dest += (height - 1) * tostride; + tostride = - tostride; + } + + for(int i = 0; i < height; ++ i) + { + memcpy(dest, src, fromstride); + memset(dest + fromstride, 0, pad); + src += fromstride; + dest += tostride; + } + + *buffer = dibits; + return dibits; +} + +/* Creates bitmaps */ +HBITMAP win32_create_dib(LONG width, LONG height, WORD bitcount, const BYTE * data) +{ + struct b_ + { + BITMAPINFO bmi; + RGBQUAD colormap[256 - ARRAYSIZE(RTL_FIELD_TYPE(BITMAPINFO, bmiColors))]; + } + b; + + b.bmi.bmiHeader.biSize = sizeof(b.bmi.bmiHeader); + b.bmi.bmiHeader.biWidth = width; + b.bmi.bmiHeader.biHeight = height; + b.bmi.bmiHeader.biPlanes = 1; + b.bmi.bmiHeader.biBitCount = bitcount; + b.bmi.bmiHeader.biCompression = BI_RGB; + b.bmi.bmiHeader.biSizeImage = 0; + b.bmi.bmiHeader.biXPelsPerMeter = 0; + b.bmi.bmiHeader.biYPelsPerMeter = 0; + + if(bitcount > 8) + { + b.bmi.bmiHeader.biClrUsed = 0; + b.bmi.bmiHeader.biClrImportant = 0; + } + else + { + b.bmi.bmiHeader.biClrUsed = 2 << bitcount; + b.bmi.bmiHeader.biClrImportant = 2 << bitcount; + + // TODO: palette + } + + // FIXME: beyond ugly + HDC hdc = CreateCompatibleDC(NULL); + + if(hdc == NULL) + return NULL; + + HBITMAP hbm = CreateDIBitmap(hdc, &b.bmi.bmiHeader, CBM_INIT, data, &b.bmi, DIB_RGB_COLORS); + + if(hbm == NULL) + error("CreateDIBitmap %dx%dx%d failed\n", width, height, bitcount); + + DeleteDC(hdc); + return hbm; +} + +/* Creates brushes */ +HBRUSH win32_create_brush(BRUSH * brush, COLORREF fgcolour) +{ + if(brush == NULL) + return (HBRUSH)GetStockObject(NULL_BRUSH); + + switch(brush->style) + { + case BS_SOLID: + case BS_NULL: + case BS_HATCHED: + case BS_PATTERN: + case BS_PATTERN8X8: + break; + + default: + return NULL; + } + + switch(brush->style) + { + case BS_SOLID: + return CreateSolidBrush(fgcolour); + + case BS_HATCHED: + return CreateHatchBrush(brush->pattern[0], fgcolour); + + case BS_NULL: + return (HBRUSH)GetStockObject(NULL_BRUSH); + + case BS_PATTERN: + case BS_PATTERN8X8: + { + uint16 pattern[8]; + + for(size_t i = 0; i < 8; ++ i) + pattern[i] = brush->pattern[i]; + + HBITMAP hpattern = CreateBitmap(8, 8, 1, 1, pattern); + HBRUSH hbr = CreatePatternBrush(hpattern); + DeleteObject(hpattern); + return hbr; + } + + DEFAULT_UNREACHABLE; + } +} +}; + /* "sealed" can improve optimizations by asserting a class cannot be derived from, optimizing out accesses to the v-table from inside the class @@ -109,9 +295,952 @@ #define SEALED_ #endif + +/* Class that implements the RDP client GUI */ +class RdpClientUI +{ +public: + // TODO: pass the client settings relevant to the GUI here + HRESULT Initialize(HWND hwndParent) + { + // TODO: create the various windows + // TODO: create display window thread + // TODO: create input thread + return E_FAIL; + } + +public: + static BOOL Startup() + { + WNDCLASSEX wcexUI = { sizeof(wcexUI) }; + WNDCLASSEX wcexConsole = { sizeof(wcexConsole) }; + WNDCLASSEX wcexDisplay = { sizeof(wcexDisplay) }; + WNDCLASSEX wcexInput = { sizeof(wcexInput) }; + + HBRUSH nullBrush = (HBRUSH)GetStockObject(HOLLOW_BRUSH); + + wcexUI.lpfnWndProc = NULL; // TODO + wcexUI.hInstance = GetCurrentModule(); + wcexUI.hCursor = LoadCursor(NULL, IDC_ARROW); + wcexUI.hbrBackground = nullBrush; + wcexUI.lpszClassName = TEXT("MissTosca_UI"); + + wcexConsole.style = CS_VREDRAW | CS_HREDRAW; + wcexConsole.lpfnWndProc = NULL; // TODO + wcexConsole.hInstance = GetCurrentModule(); + wcexConsole.hCursor = LoadCursor(NULL, IDC_ARROW); + wcexConsole.hbrBackground = nullBrush; + wcexConsole.lpszClassName = TEXT("MissTosca_Console"); + + wcexDisplay.style = CS_VREDRAW | CS_HREDRAW; + wcexDisplay.lpfnWndProc = NULL; // TODO + wcexDisplay.hInstance = GetCurrentModule(); + wcexDisplay.hCursor = LoadCursor(NULL, IDC_ARROW); + wcexDisplay.hbrBackground = nullBrush; + wcexDisplay.lpszClassName = TEXT("MissTosca_Display"); + + wcexInput.style = CS_VREDRAW | CS_HREDRAW; + wcexInput.lpfnWndProc = NULL; // TODO + wcexInput.hInstance = GetCurrentModule(); + wcexInput.hCursor = NULL; + wcexInput.hbrBackground = nullBrush; + wcexInput.lpszClassName = TEXT("MissTosca_Input"); + + return + RegisterClassEx(&wcexUI) && + RegisterClassEx(&wcexConsole) && + RegisterClassEx(&wcexDisplay) && + RegisterClassEx(&wcexInput); + } + + static void Shutdown() + { + // TODO + } + + /* + This is the main UI window. It's the direct child of the control + window, it fills its whole extent and it contains the scrollbars. + When activated, it will move keyboard focus to the input window + */ +private: + HWND m_uiWindow; + LONG m_scrollHPos; + LONG m_scrollVPos; + + LRESULT UIWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch(uMsg) + { + // Keep the keyboard focus on the input window + case WM_ACTIVATE: + switch(LOWORD(wParam)) + { + case WA_INACTIVE: + break; + + case WA_ACTIVE: + case WA_CLICKACTIVE: + if(!HIWORD(wParam)) + SetFocus(m_inputWindow); + } + + return 0; + + // Resized: rearrange children windows, adjust scrollbars + case WM_SIZE: + { + if(IsIconic(m_uiWindow)) + break; + + RECT rcClient; + GetWindowRect(m_uiWindow, &rcClient); + + if(m_smartSizing) + { + // we are not supposed to maintain aspect ratio. Container has to do that + m_consoleX = 0; + m_consoleY = 0; + m_consoleWidth = rcClient.right; + m_consoleHeight = rcClient.bottom; + } + else + { + // center horizontally, no horizontal scrollbar + if(rcClient.right >= m_consoleWidth) + m_consoleX = (m_consoleWidth - rcClient.right) / 2; + + // center vertically, no vertical scrollbar + if(rcClient.bottom >= m_consoleHeight) + m_consoleY = (m_consoleHeight - rcClient.right) / 2; + } + + SCROLLINFO scroll = { sizeof(scroll), SIF_ALL, 0 }; + + // update the horizontal scrollbar + scroll.nMax = m_consoleWidth; + scroll.nPage = rcClient.right; + scroll.nPos = 0 - m_consoleX; + SetScrollInfo(m_uiWindow, SB_HORZ, &scroll, TRUE); + + // update the vertical scrollbar + scroll.nMax = m_consoleHeight; + scroll.nPage = rcClient.bottom; + scroll.nPos = 0 - m_consoleY; + SetScrollInfo(m_uiWindow, SB_VERT, &scroll, TRUE); + + // move/resize the console window + MoveWindow(m_consoleWindow, m_consoleX, m_consoleY, m_consoleWidth, m_consoleHeight, TRUE); + } + + return 0; + + case WM_HSCROLL: + { + SCROLLINFO scroll = { sizeof(scroll), SIF_TRACKPOS }; + GetScrollInfo(m_uiWindow, SB_HORZ, &scroll); + m_consoleX = - scroll.nTrackPos; + MoveWindow(m_consoleWindow, m_consoleX, m_consoleY, m_consoleWidth, m_consoleHeight, TRUE); + } + + return 0; + + case WM_VSCROLL: + { + SCROLLINFO scroll = { sizeof(scroll), SIF_TRACKPOS }; + GetScrollInfo(m_uiWindow, SB_VERT, &scroll); + m_consoleY = - scroll.nTrackPos; + MoveWindow(m_consoleWindow, m_consoleX, m_consoleY, m_consoleWidth, m_consoleHeight, TRUE); + } + + return 0; + + default: + break; + } + + return DefWindowProc(m_uiWindow, uMsg, wParam, lParam); + } + + /* + This is the full-screen title bar. It's displayed at the top of the + main UI window while in full-screen mode, and it contains two toolbars + with the pin, minimize, restore and close buttons + */ + HWND m_fullScreenBarWindow; + + /* + This is the console window. It has the same extent as the display on + the remote computer, or it fills the UI window in smart resizing mode, + and it contains the input and display windows + */ +private: + HWND m_consoleWindow; + LONG m_consoleX; + LONG m_consoleY; + LONG m_consoleWidth; + LONG m_consoleHeight; + bool m_smartSizing; + + LRESULT ConsoleWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch(uMsg) + { + case WM_SIZE: + { + RECT rcClient; + GetClientRect(m_consoleWindow, &rcClient); + + MoveWindow(m_inputWindow, 0, 0, rcClient.right, rcClient.bottom, TRUE); + MoveWindow(m_displayWindow, 0, 0, rcClient.right, rcClient.bottom, TRUE); + } + + return 0; + + default: + break; + } + + return DefWindowProc(m_consoleWindow, uMsg, wParam, lParam); + } + + /* + This is the display window. It represents the virtual display of the + remote computer. It completely fills its parent, the console window, + and it runs in its own thread for performance reasons + */ +private: + HWND m_displayWindow; + LONG m_displayBufferWidth; + LONG m_displayBufferHeight; + HDC m_displayBuffer; + void * m_displayBufferRaw; + int m_displayBufferSave; + int m_displayBufferBitDepth; + int m_displayBufferByteDepth; + int m_displayBufferStride; + RECT m_displayBufferClip; + CRITICAL_SECTION m_displayBufferMutex; + + LRESULT DisplayWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch(uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_PRINTCLIENT: + if(wParam == 0) + break; + + case WM_PAINT: + { + HDC hdc = (HDC)wParam; + + EnterCriticalSection(&m_displayBufferMutex); + + if(hdc) + { + RECT rc; + GetClientRect(m_displayWindow, &rc); + BitBlt(hdc, 0, 0, rc.right, rc.bottom, m_displayBuffer, 0, 0, SRCCOPY); + } + else + { + PAINTSTRUCT ps; + hdc = BeginPaint(m_displayWindow, &ps); + + if(!m_smartSizing) + { + BitBlt + ( + hdc, + ps.rcPaint.left, + ps.rcPaint.top, + ps.rcPaint.right - ps.rcPaint.left, + ps.rcPaint.bottom - ps.rcPaint.top, + m_displayBuffer, + ps.rcPaint.left, + ps.rcPaint.top, + SRCCOPY + ); + } + else + { + // bleh. There has to be a better way + SetStretchBltMode(hdc, HALFTONE); + + StretchBlt + ( + hdc, + 0, + 0, + m_consoleWidth, + m_consoleHeight, + m_displayBuffer, + 0, + 0, + m_displayBufferWidth, + m_displayBufferHeight, + SRCCOPY + ); + } + + EndPaint(m_displayWindow, &ps); + } + + LeaveCriticalSection(&m_displayBufferMutex); + } + + return 0; + + default: + break; + } + + return DefWindowProc(m_displayWindow, uMsg, wParam, lParam); + } + + /* Screen repainting */ + void Display_RepaintRect(const RECT * lprc) + { + if(m_smartSizing) + return Display_RepaintAll(); + + RECT rcDamage; + IntersectRect(&rcDamage, lprc, &m_displayBufferClip); + InvalidateRect(m_displayWindow, &rcDamage, FALSE); + } + + void Display_RepaintArea(int x, int y, int cx, int cy) + { + if(m_smartSizing) + return Display_RepaintAll(); + + RECT rcDamage; + rcDamage.left = x; + rcDamage.top = y; + rcDamage.right = x + cx; + rcDamage.bottom = y + cy; + Display_RepaintRect(&rcDamage); + } + + void Display_RepaintPolygon(POINT * point, int npoints, int linewidth) + { + if(m_smartSizing) + return Display_RepaintAll(); + + RECT rcDamage; + + rcDamage.left = MAXLONG; + rcDamage.top = MAXLONG; + rcDamage.right = 0; + rcDamage.bottom = 0; + + for(int i = 0; i < npoints; ++ i) + { + if(point[i].x < rcDamage.left) + rcDamage.left = point[i].x; + + if(point[i].y < rcDamage.top) + rcDamage.top = point[i].y; + + if(point[i].x > rcDamage.right) + rcDamage.right = point[i].x; + + if(point[i].y > rcDamage.bottom) + rcDamage.bottom = point[i].y; + } + + InflateRect(&rcDamage, linewidth, linewidth); + Display_RepaintRect(&rcDamage); + } + + void Display_RepaintAll() + { + InvalidateRgn(m_displayWindow, NULL, FALSE); + } + +public: + void Display_SetClip(int x, int y, int cx, int cy) + { + m_displayBufferClip.left = x; + m_displayBufferClip.top = y; + m_displayBufferClip.right = x + cx + 1; + m_displayBufferClip.bottom = y + cy + 1; + + HRGN hrgn = CreateRectRgnIndirect(&m_displayBufferClip); + SelectClipRgn(m_displayBuffer, hrgn); + DeleteObject(hrgn); + } + + void Display_ResetClip() + { + m_displayBufferClip.left = 0; + m_displayBufferClip.top = 0; + m_displayBufferClip.right = m_displayBufferWidth; + m_displayBufferClip.bottom = m_displayBufferHeight; + SelectClipRgn(m_displayBuffer, NULL); + } + + void Display_PaintBitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data) + { + GdiFlush(); + + int fromstride = alignup(width * m_displayBufferByteDepth, 4); + int sizex = cx * m_displayBufferByteDepth; + + const uint8 * src = data; + + uint8 * dst = + (uint8 *)m_displayBufferRaw + + (m_displayBufferHeight - y - cy) * m_displayBufferStride + + x * m_displayBufferByteDepth; + + for(int i = 0; i < cy; ++ i) + { + memcpy(dst, src, sizex); + src += fromstride; + dst += m_displayBufferStride; + } + + Display_RepaintArea(x, y, cx, cy); + } + + void Display_DestBlt(uint8 opcode, int x, int y, int cx, int cy) + { + int dcsave = SaveDC(m_displayBuffer); + SelectObject(m_displayBuffer, GetStockObject(BLACK_BRUSH)); + PatBlt(m_displayBuffer, x, y, cx, cy, MAKELONG(0, opcode)); + RestoreDC(m_displayBuffer, dcsave); + Display_RepaintArea(x, y, cx, cy); + } + + void Display_PatBlt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour) + { + HBRUSH hbr = win32_create_brush(brush, fgcolour); + + int dcsave = SaveDC(m_displayBuffer); + + SetBkColor(m_displayBuffer, bgcolour); + SetTextColor(m_displayBuffer, fgcolour); + SetBrushOrgEx(m_displayBuffer, brush->xorigin, brush->yorigin, NULL); + SelectObject(m_displayBuffer, hbr); + + PatBlt(m_displayBuffer, x, y, cx, cy, MAKELONG(0, opcode)); + + RestoreDC(m_displayBuffer, dcsave); + + DeleteObject(hbr); + + Display_RepaintArea(x, y, cx, cy); + } + + void Display_ScreenBlt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy) + { + BitBlt(m_displayBuffer, x, y, cx, cy, m_displayBuffer, srcx, srcy, MAKELONG(0, opcode)); + Display_RepaintArea(x, y, cx, cy); + } + + void Display_MemBlt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy) + { + HDC hdcSrc = CreateCompatibleDC(m_displayBuffer); + HGDIOBJ hOld = SelectObject(hdcSrc, src); + + BitBlt(m_displayBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode)); + + SelectObject(hdcSrc, hOld); + DeleteDC(hdcSrc); + + Display_RepaintArea(x, y, cx, cy); + } + + 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) + { + // TODO + HDC hdcSrc = CreateCompatibleDC(m_displayBuffer); + HGDIOBJ hOld = SelectObject(hdcSrc, src); + + //SELECT_BRUSH(brush, bgcolour, fgcolour); + + BitBlt(m_displayBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode)); + + //RESET_BRUSH(); + + SelectObject(hdcSrc, hOld); + DeleteDC(hdcSrc); + + Display_RepaintArea(x, y, cx, cy); + } + + void Display_Line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen) + { + HPEN hpen = CreatePen(pen->style, pen->width, pen->colour); + + int dcsave = SaveDC(m_displayBuffer); + + SetROP2(m_displayBuffer, opcode); + SelectObject(m_displayBuffer, hpen); + MoveToEx(m_displayBuffer, startx, starty, NULL); + + LineTo(m_displayBuffer, endx, endy); + + RestoreDC(m_displayBuffer, dcsave); + + DeleteObject(hpen); + + RECT rcDamage; + + if(startx < endx) + { + rcDamage.left = startx; + rcDamage.right = endx; + } + else + { + rcDamage.left = endx; + rcDamage.right = startx; + } + + if(starty < endy) + { + rcDamage.top = starty; + rcDamage.bottom = endy; + } + else + { + rcDamage.top = endy; + rcDamage.bottom = starty; + } + + InflateRect(&rcDamage, pen->width, pen->width); + Display_RepaintRect(&rcDamage); + } + + void Display_Rect(int x, int y, int cx, int cy, int colour) + { + HBRUSH hbr = CreateSolidBrush(colour); + + int dcsave = SaveDC(m_displayBuffer); + + SelectObject(m_displayBuffer, hbr); + SelectObject(m_displayBuffer, GetStockObject(NULL_PEN)); + + Rectangle(m_displayBuffer, x, y, x + cx + 1, y + cy + 1); + + RestoreDC(m_displayBuffer, dcsave); + + DeleteObject(hbr); + + Display_RepaintArea(x, y, cx, cy); + } + + void Display_Polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, BRUSH * brush, int bgcolour, int fgcolour) + { + HBRUSH hbr = win32_create_brush(brush, fgcolour); + + int dcsave = SaveDC(m_displayBuffer); + + SetBkColor(m_displayBuffer, bgcolour); + SetTextColor(m_displayBuffer, fgcolour); + SetPolyFillMode(m_displayBuffer, fillmode); + SelectObject(m_displayBuffer, hbr); + + Polygon(m_displayBuffer, point, npoints); + + RestoreDC(m_displayBuffer, dcsave); + + Display_RepaintPolygon(point, npoints, 0); + } + + void Display_Polyline(uint8 opcode, POINT * points, int npoints, PEN * pen) + { + POINT last = points[0]; + + for(int i = 1; i < npoints; ++ i) + { + points[i].x += last.x; + points[i].y += last.y; + last = points[i]; + } + + HPEN hpen = CreatePen(pen->style, pen->width, pen->colour); + + int dcsave = SaveDC(m_displayBuffer); + + SetROP2(m_displayBuffer, opcode); + SelectObject(m_displayBuffer, hpen); + + Polyline(m_displayBuffer, points, npoints); + + RestoreDC(m_displayBuffer, dcsave); + + DeleteObject(hpen); + + Display_RepaintPolygon(points, npoints, pen->width); + } + + void Display_Ellypse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour) + { + // TODO + + Display_RepaintArea(x, y, cx, cy); + } + + // TBD: optimize text drawing + void Display_DrawGlyph(int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour) + { + HBITMAP hbmGlyph = (HBITMAP)glyph; + HDC hdcGlyph = CreateCompatibleDC(m_displayBuffer); + HGDIOBJ hOld = SelectObject(hdcGlyph, hbmGlyph); + + int dcsave = SaveDC(m_displayBuffer); + + switch(mixmode) + { + case MIX_TRANSPARENT: + { + /* + ROP is DSPDxax: + - where the glyph (S) is white, D is set to the foreground color (P) + - where the glyph (S) is black, D is left untouched + + This paints a transparent glyph in the specified color + */ + HBRUSH hbr = CreateSolidBrush(fgcolour); + SelectObject(m_displayBuffer, hbr); + BitBlt(m_displayBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, MAKELONG(0, 0xe2)); + DeleteObject(hbr); + } + + break; + + case MIX_OPAQUE: + { + /* Curiously, glyphs are inverted (white-on-black) */ + SetBkColor(m_displayBuffer, fgcolour); + SetTextColor(m_displayBuffer, bgcolour); + BitBlt(m_displayBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, SRCCOPY); + } + + break; + } + + RestoreDC(m_displayBuffer, dcsave); + + SelectObject(hdcGlyph, hOld); + DeleteDC(hdcGlyph); + + Display_RepaintArea(x, y, cx, cy); + } + + void Display_DoGlyph(uint8 font, uint8 flags, int mixmode, int& x, int& y, int bgcolour, int fgcolour, const uint8 * ttext, int& idx) + { + FONTGLYPH * glyph; + + glyph = cache_get_font(/*This*/NULL, font, ttext[idx]); + + if(!(flags & TEXT2_IMPLICIT_X)) + { + int xyoffset = ttext[++ idx]; + + if((xyoffset & 0x80)) + { + if (flags & TEXT2_VERTICAL) + y += ttext[idx + 1] | (ttext[idx + 2] << 8); + else + x += ttext[idx + 1] | (ttext[idx + 2] << 8); + + idx += 2; + } + else + { + if (flags & TEXT2_VERTICAL) + y += xyoffset; + else + x += xyoffset; + } + } + + if(glyph) + { + Display_DrawGlyph + ( + mixmode, + x + (short)glyph->offset, + y + (short)glyph->baseline, + glyph->width, + glyph->height, + glyph->pixmap, + 0, + 0, + bgcolour, + fgcolour + ); + + if(flags & TEXT2_IMPLICIT_X) + x += glyph->width; + } + } + + void Display_DrawText + ( + uint8 font, + uint8 flags, + uint8 opcode, + int mixmode, + int x, + int y, + int clipx, + int clipy, + int clipcx, + int clipcy, + int boxx, + int boxy, + int boxcx, + int boxcy, + BRUSH * brush, + int bgcolour, + int fgcolour, + uint8 * text, + uint8 length + ) + { + int i, j; + DATABLOB *entry; + + HBRUSH hbr = CreateSolidBrush(bgcolour); + HGDIOBJ holdbrush = SelectObject(m_displayBuffer, hbr); + HGDIOBJ holdpen = SelectObject(m_displayBuffer, GetStockObject(NULL_PEN)); + + if (boxcx > 1) + Rectangle(m_displayBuffer, boxx, boxy, boxx + boxcx + 1, boxy + boxcy + 1); + else if (mixmode == MIX_OPAQUE) + Rectangle(m_displayBuffer, clipx, clipy, clipx + clipcx + 1, clipy + clipcy + 1); + + SelectObject(m_displayBuffer, holdpen); + SelectObject(m_displayBuffer, holdbrush); + + DeleteObject(hbr); + + if(boxcx > 1) + Display_RepaintArea(boxx, boxy, boxcx, boxcy); + else + Display_RepaintArea(clipx, clipy, clipcx, clipcy); + + /* Paint text, character by character */ + for (i = 0; i < length;) + { + switch (text[i]) + { + case 0xff: + /* At least two bytes needs to follow */ + if (i + 3 > length) + { + warning("Skipping short 0xff command:"); + for (j = 0; j < length; j++) + fprintf(stderr, "%02x ", text[j]); + fprintf(stderr, "\n"); + i = length = 0; + break; + } + cache_put_text(NULL /* TODO */, text[i + 1], text, text[i + 2]); + i += 3; + length -= i; + /* this will move pointer from start to first character after FF command */ + text = &(text[i]); + i = 0; + break; + + case 0xfe: + /* At least one byte needs to follow */ + if (i + 2 > length) + { + warning("Skipping short 0xfe command:"); + for (j = 0; j < length; j++) + fprintf(stderr, "%02x ", text[j]); + fprintf(stderr, "\n"); + i = length = 0; + break; + } + entry = cache_get_text(/*This*/NULL, text[i + 1]); + if (entry->data != NULL) + { + if ((((uint8 *) (entry->data))[1] == 0) + && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length)) + { + if (flags & TEXT2_VERTICAL) + y += text[i + 2]; + else + x += text[i + 2]; + } + for (j = 0; j < entry->size; j++) + Display_DoGlyph(font, flags, mixmode, x, y, bgcolour, fgcolour, ((uint8 *) (entry->data)), j); + } + if (i + 2 < length) + i += 3; + else + i += 2; + length -= i; + /* this will move pointer from start to first character after FE command */ + text = &(text[i]); + i = 0; + break; + + default: + Display_DoGlyph(font, flags, mixmode, x, y, bgcolour, fgcolour, text, i); + i++; + break; + } + } + } + + void Display_SaveDesktop(uint32 offset, int x, int y, int cx, int cy) + { + GdiFlush(); + + uint8 * data = + (uint8 *)m_displayBufferRaw + + x * m_displayBufferByteDepth + + (m_displayBufferHeight - y - cy) * m_displayBufferStride; + + cache_put_desktop + ( + /*This*/NULL, + offset * m_displayBufferByteDepth, + cx, + cy, + m_displayBufferStride, + m_displayBufferByteDepth, + data + ); + } + + void Display_RestoreDesktop(uint32 offset, int x, int y, int cx, int cy) + { + int fromstride = cx * m_displayBufferByteDepth; + + const uint8 * src = cache_get_desktop(/*This*/NULL, offset, cx, cy, m_displayBufferByteDepth); + + uint8 * dst = + (uint8 *)m_displayBufferRaw + + x * m_displayBufferByteDepth + + (m_displayBufferHeight - y - cy) * m_displayBufferStride; + + GdiFlush(); + + for(int i = 0; i < cy; ++ i) + { + memcpy(dst, src, fromstride); + src += fromstride; + dst += m_displayBufferStride; + } + + Display_RepaintArea(x, y, cx, cy); + } + + + void Display_BeginUpdate() + { + EnterCriticalSection(&m_displayBufferMutex); + m_displayBufferSave = SaveDC(m_displayBuffer); + } + + void Display_EndUpdate() + { + RestoreDC(m_displayBuffer, m_displayBufferSave); + LeaveCriticalSection(&m_displayBufferMutex); + } + + /* + This is the input window. It receives the keyboard and mouse input from + the user, and it's the only window that can receive the keyboard focus. + It completely fills its parent, the console window, and it runs in its + own thread for performance reasons and because of technical reasons + involving keyboard hooks in full-screen mode + */ + HWND m_inputWindow; + HCURSOR m_inputCursor; + + LRESULT InputWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch(uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + /* Keyboard stuff */ + // TODO: we need a good way to post output cross-thread + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYPRESS | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0); + break; + + case WM_SYSKEYUP: + case WM_KEYUP: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYRELEASE | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0); + break; + + /* Mouse stuff */ + // Cursor shape + case WM_SETCURSOR: + if(LOWORD(lParam) == HTCLIENT) + { + SetCursor(m_inputCursor); + return TRUE; + } + + break; + + // Movement + case WM_MOUSEMOVE: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, LOWORD(lparam), HIWORD(lparam)); + break; + + // Buttons + // TODO: X buttons + case WM_LBUTTONDOWN: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_RBUTTONDOWN: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_MBUTTONDOWN: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_LBUTTONUP: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_RBUTTONUP: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_MBUTTONUP: + //rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, LOWORD(lparam), HIWORD(lparam)); + break; + + // Wheel + case WM_MOUSEWHEEL: + //mstsc_mousewheel(This, (SHORT)HIWORD(wparam), lparam); + break; + } + + return DefWindowProc(m_inputWindow, uMsg, wParam, lParam); + } + +public: +}; + #pragma warning(push) #pragma warning(disable: 4584) +/* The ActiveX control */ class RdpClient SEALED_: /* COM basics */ public IUnknown, @@ -137,7 +1266,7 @@ public IViewObject2, // NOTE: the original has a vestigial, non-functional implementation of this, which we omit - // public ISpecifyPropertyPages, + // ISpecifyPropertyPages // Hidden interfaces, not available through QueryInterface public IConnectionPoint, @@ -145,6 +1274,10 @@ /* RDP client interface */ public MSTSCLib::IMsRdpClient4, public MSTSCLib::IMsRdpClientNonScriptable2 + + // NOTE: implemented by inner classes due to requiring distinct IDispatch implementations + // IMsRdpClientAdvancedSettings4 + // IMsRdpClientSecuredSettings { private: /* An endless amount of COM glue */ @@ -224,8 +1357,13 @@ } /* Glue to interface to rdesktop-core */ + RdpClientUI * m_clientUI; RDPCLIENT m_protocolState; HANDLE m_protocolThread; + HANDLE m_protocolThreadWaitingReconnection; + bool m_reconnectAborted; + bool m_actuallyConnected; + bool m_loggedIn; /* Properties */ // Storage fields @@ -250,8 +1388,6 @@ long m_DesktopWidth; long m_DesktopHeight; long m_StartConnected; - long m_HorizontalScrollBarVisible; - long m_VerticalScrollBarVisible; long m_ColorDepth; long m_KeyboardHookMode; long m_AudioRedirectionMode; @@ -378,6 +1514,16 @@ return S_OK; } + HRESULT ReplaceProperty(BSTR& prop, BSTR newValue) + { + assert(InsideApartment()); + assert((prop == NULL && newValue == NULL) || prop != newValue); + + SysFreeString(prop); + prop = newValue; + return S_OK; + } + HRESULT SetProperty(LPSTR& prop, BSTR newValue) { assert(InsideApartment()); @@ -397,6 +1543,18 @@ else prop = NULL; + return S_OK; + } + + HRESULT ReplaceProperty(LPSTR& prop, LPSTR newValue) + { + assert(InsideApartment()); + assert((prop == NULL && newValue == NULL) || prop != newValue); + + if(prop) + delete[] prop; + + prop = newValue; return S_OK; } @@ -535,19 +1693,46 @@ AsyncEventCallback callback; }; + struct RedirectArguments + { + 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; + }; + enum { RDPC_WM_ = WM_USER, RDPC_WM_SYNC_EVENT, RDPC_WM_ASYNC_EVENT, RDPC_WM_DISCONNECT, + RDPC_WM_REQUEST_CLOSE, + RDPC_WM_REDIRECT, }; + static VOID CALLBACK DisconnectAPC(ULONG_PTR) + { + // no need to do anything. The interruption will be enough + } + bool HandleEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& result) { + result = 0; + switch(uMsg) { + /* Regular event to be dispatched to the container's sink */ case RDPC_WM_SYNC_EVENT: + assert(InSendMessage()); + case RDPC_WM_ASYNC_EVENT: { const EventArguments * eventArgs = reinterpret_cast<EventArguments *>(lParam); @@ -568,26 +1753,122 @@ break; + /* The protocol thread is about to die: prepare for disconnection */ case RDPC_WM_DISCONNECT: { assert(m_Connected); - - VARIANTARG arg = { }; - - arg.vt = VT_I4; - arg.lVal = static_cast<long>(wParam); - - FireEventInsideApartment(4, &arg, 1); - - if(m_protocolThread) + assert(InsideApartment()); + assert(InSendMessage()); + + // Unblock the protocol thread and wait for it to terminate + ReplyMessage(0); + JoinProtocolThread(); + + // Finish disconnecting + PerformDisconnect(static_cast<long>(wParam)); + } + + break; + + case RDPC_WM_REDIRECT: + { + assert(InSendMessage()); + assert(lParam); + assert(m_Connected); + assert(m_protocolState.redirect); + + RedirectArguments * redirectArgs = reinterpret_cast<RedirectArguments *>(lParam); + + // BUGBUG: this is extremely messy and more prone to out-of-memory than it should be + LPSTR lpszNewServer = NULL; + LPSTR lpszNewCookie = NULL; + BSTR strNewUsername = NULL; + BSTR strNewDomain = NULL; + BSTR strNewPassword = NULL; + HRESULT hr = S_OK; + + for(;;) { - WaitForSingleObject(m_protocolThread, INFINITE); - CloseHandle(m_protocolThread); + // Allocate the new properties + hr = E_OUTOFMEMORY; + + // FIXME: convert the hostname to Punycode, not the ANSI codepage + lpszNewServer = AllocLpsz(redirectArgs->server, redirectArgs->server_len / sizeof(OLECHAR)); + + if(lpszNewServer == NULL && redirectArgs->server_len) + break; + + lpszNewCookie = AllocLpsz(redirectArgs->cookie, redirectArgs->cookie_len); + + if(lpszNewCookie == NULL && redirectArgs->cookie_len) + break; + + strNewUsername = SysAllocStringLen(redirectArgs->username, redirectArgs->username_len / sizeof(OLECHAR)); + + if(strNewUsername == NULL && redirectArgs->username_len) + break; + + strNewDomain = SysAllocStringLen(redirectArgs->domain, redirectArgs->domain_len / sizeof(OLECHAR)); + + if(strNewDomain == NULL && redirectArgs->domain_len) + break; + + strNewPassword = SysAllocStringLen(redirectArgs->password, redirectArgs->password_len / sizeof(OLECHAR)); + + if(strNewPassword == NULL && redirectArgs->password_len) + break; + + hr = S_OK; + break; } - // TODO: do other disconnection work here... - - m_Connected = false; + // Success + if(SUCCEEDED(hr)) + { + // set the new properties + ReplaceProperty(m_Server, lpszNewServer); + ReplaceProperty(m_LoadBalanceInfo, lpszNewCookie); + ReplaceProperty(m_UserName, strNewUsername); + ReplaceProperty(m_Domain, strNewDomain); + ReplaceProperty(m_ClearTextPassword, strNewPassword); + } + // Failure + else + { + // free the buffers + FreeLpsz(lpszNewServer); + FreeLpsz(lpszNewCookie); + SysFreeString(strNewUsername); + SysFreeString(strNewDomain); + SysFreeString(strNewPassword); + + // signal the error + m_protocolState.disconnect_reason = 262; + m_protocolState.redirect = False; + result = -1; + } + } + + break; + + // BUGBUG: this could potentially disconnect an unrelated connection established later... + case RDPC_WM_REQUEST_CLOSE: + { + assert(!InSendMessage()); + + if(m_Connected) + { + // Ask confirmation to the container in case we are logged in + if(m_loggedIn && !FireConfirmClose()) + break; + + // For reentrancy (OnConfirmClose could deviously call Disconnect) + if(m_protocolThread == NULL) + break; + + // Terminate the protocol thread. It will fire the Disconnected event on exit + TerminateProtocolThread(); + } } break; @@ -595,6 +1876,10 @@ default: return false; } + + // If the calling thread is blocked, unblock it ASAP + if(InSendMessage()) + ReplyMessage(result); return true; } @@ -666,8 +1951,8 @@ void FireDisconnected(long reason) { - // Source: control or protocol. Special handling - SendNotifyMessage(m_controlWindow, RDPC_WM_DISCONNECT, reason, 0); + // Source: protocol. Special handling + SendMessage(m_controlWindow, RDPC_WM_DISCONNECT, reason, 0); } void FireEnterFullScreenMode() @@ -744,6 +2029,17 @@ FireEventOutsideApartment(10, &arg, 1); } + void FireFatalErrorFromApartment(long errorCode) + { + VARIANTARG arg = { }; + + arg.vt = VT_I4; + arg.lVal = errorCode; + + // Source: control + FireEventInsideApartment(10, &arg, 1); + } + void FireWarning(long warningCode) { VARIANTARG arg = { }; @@ -789,14 +2085,19 @@ retval.vt = VT_BYREF | VT_BOOL; retval.pboolVal = &allowClose; - // Source: ??? // BUGBUG: fix this! - FireEventOutsideApartment(15, NULL, 0, &retval); + // Source: control + FireEventInsideApartment(15, NULL, 0, &retval); return allowClose != VARIANT_FALSE; } HRESULT FireReceivedTSPublicKey(void * publicKey, unsigned int publicKeyLength) { + assert(m_Connected); + + if(!m_NotifyTSPublicKey) + return S_OK; + BSTR bstrPublicKey = SysAllocStringByteLen(NULL, publicKeyLength); if(bstrPublicKey == NULL) @@ -979,8 +2280,6 @@ m_DesktopWidth(), m_DesktopHeight(), m_StartConnected(), - m_HorizontalScrollBarVisible(), - m_VerticalScrollBarVisible(), m_ColorDepth(16), m_KeyboardHookMode(2), m_AudioRedirectionMode(0), @@ -1054,7 +2353,17 @@ { assert(m_refCount == 0); - // TODO: if connected, disconnect + if(m_Connected) + { + // Terminate the protocol thread + TerminateProtocolThread(); + + // Dispatch the RDPC_WM_DISCONNECT message sent by the dying thread + MSG msg; + PeekMessage(&msg, m_controlWindow, 0, 0, PM_NOREMOVE); + + assert(!m_Connected); + } DestroyControlWindow(); @@ -1094,11 +2403,8 @@ SysFreeString(m_RdpdrClipCleanTempDirString); SysFreeString(m_RdpdrClipPasteInfoString); - if(m_LoadBalanceInfo) - delete[] m_LoadBalanceInfo; - - if(m_Server) - delete[] m_Server; + FreeLpsz(m_LoadBalanceInfo); + FreeLpsz(m_Server); unlockServer(); } @@ -1678,7 +2984,7 @@ virtual STDMETHODIMP IMsRdpClientAdvancedSettings::put_overallConnectionTimeout(long poverallConnectionTimeout) { - if(poverallConnectionTimeout >= 600) + if(poverallConnectionTimeout < 0 || poverallConnectionTimeout >= 600) return E_INVALIDARG; return Outer()->SetProperty(Outer()->m_overallConnectionTimeout, poverallConnectionTimeout); @@ -2315,6 +3621,11 @@ return CONTAINING_RECORD(innerThis, RdpClient, m_securedSettings); } + static RdpClient * InnerToOuter(RDPCLIENT * innerThis) + { + return CONTAINING_RECORD(innerThis, RdpClient, m_protocolState); + } + static const RdpClient * InnerToOuter(const RdpClientInner * innerThis) { return CONTAINING_RECORD(innerThis, RdpClient, m_inner); @@ -2330,24 +3641,142 @@ return CONTAINING_RECORD(innerThis, RdpClient, m_securedSettings); } + static const RdpClient * InnerToOuter(const RDPCLIENT * innerThis) + { + return CONTAINING_RECORD(innerThis, RdpClient, m_protocolState); + } + + RdpClientUI * GetUI() const + { + assert(m_clientUI); + return m_clientUI; + } + + /* Glue for rdesktop-core */ +public: + static bool OnPublicKey(RDPCLIENT * This, unsigned char * key, unsigned int key_size) + { + return InnerToOuter(This)->OnPublicKey(key, key_size); + } + + static void OnLogon(RDPCLIENT * This) + { + return InnerToOuter(This)->OnLogon(); + } + + static bool OnRedirect + ( + 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 + ) + { + return InnerToOuter(This)->OnRedirect + ( + flags, + server_len, + server, + cookie_len, + cookie, + username_len, + username, + domain_len, + domain, + password_len, + password + ); + } + private: - /* Thread that hosts rdesktop-core */ + bool OnPublicKey(unsigned char * key, unsigned int key_size) + { + HRESULT hr = FireReceivedTSPublicKey(key, key_size); + + if(FAILED(hr)) + { + m_protocolState.disconnect_reason = 262; + return false; + } + + return hr == S_OK; + } + + void OnLogon() + { + m_loggedIn = true; + FireLoginComplete(); + } + + bool OnRedirect + ( + 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 + ) + { + assert(m_Connected); + assert(!InsideApartment()); + assert(IsWindow(m_controlWindow)); + + RedirectArguments redirectArgs = + { + flags, + server_len, + server, + cookie_len, + cookie, + username_len, + username, + domain_len, + domain, + password_len, + password + }; + + return SendMessage(m_controlWindow, RDPC_WM_REDIRECT, 0, reinterpret_cast<LPARAM>(&redirectArgs)) == 0; + } + +private: static DWORD WINAPI ProtocolLoopThreadProc(LPVOID lpParam) { static_cast<RdpClient *>(lpParam)->ProtocolLoop(); return 0; } + static VOID CALLBACK ConnectionTimerAPC(LPVOID, DWORD, DWORD) + { + } + + // FIXME: various potential inconsistencies due to lack of detailed documentation of expected semantics void ProtocolLoop() { + HANDLE waitingReconnection = NULL; + + // Retrieve the local hostname to be passed to the server WCHAR hostname[MAX_COMPUTERNAME_LENGTH + 1]; DWORD hostnameLen = ARRAYSIZE(hostname); if(!GetComputerNameW(hostname, &hostnameLen)) hostname[0] = 0; - FireConnecting(); - + // Set some connection flags uint32 flags = RDP_LOGON_NORMAL; if(m_Compress) @@ -2358,6 +3787,27 @@ if(m_ClearTextPassword) flags |= RDP_LOGON_AUTO; + + // Notify the container that the connection process is beginning now + FireConnecting(); + + // Set the overall connection timer, if a timeout is set + // BUGBUG: the timeout semantics are ambiguous and have been most probably misinterpreted + HANDLE overallConnectionTimer = NULL; + LARGE_INTEGER overallTimeout; + + if(m_overallConnectionTimeout) + { + overallTimeout.QuadPart = - ((m_overallConnectionTimeout * 1000 * 1000 * 1000) / 100); + + overallConnectionTimer = CreateWaitableTimer(NULL, FALSE, NULL); + + if(overallConnectionTimer == NULL) + goto l_Disconnect; + } + + if(overallConnectionTimer) + SetWaitableTimer(overallConnectionTimer, &overallTimeout, 0, ConnectionTimerAPC, NULL, FALSE); // Initial connection BOOL disconnected = rdp_connect @@ -2374,15 +3824,32 @@ m_LoadBalanceInfo ); - while(!disconnected) + if(overallConnectionTimer) + CancelWaitableTimer(overallConnectionTimer); + + if(disconnected) + goto l_Disconnect; + + // TODO: set the disconnect reason for every instance in which we abort the loop + for(;;) { BOOL deactivated = False; uint32 extendedDisconnectReason = 0; - // The main protocol loop + m_actuallyConnected = true; + + // Notify the container of the successful connection + FireConnected(); + + // Main protocol loop + m_loggedIn = false; rdp_main_loop(&m_protocolState, &deactivated, &extendedDisconnectReason); + rdp_disconnect(&m_protocolState); + + m_actuallyConnected = false; // Redirection + // BUGBUG: redirection is very messy and probably this implementation is not "canonical" if(m_protocolState.redirect) { m_protocolState.redirect = False; @@ -2420,15 +3887,34 @@ // do not reconnect if(reconnectMode == MSTSCLib::autoReconnectContinueStop) - { - disconnected = True; - break; - } - - // the container will reconnect manually with Connect or abort with Disconnect + goto l_Disconnect; + + // the container will reconnect or abort manually if(reconnectMode == MSTSCLib::autoReconnectContinueManual) { - // TODO: wait for a call to Connect or Disconnect + assert(!m_reconnectAborted); + assert(m_protocolThreadWaitingReconnection == NULL); + + if(waitingReconnection == NULL) + { + waitingReconnection = CreateEvent(NULL, TRUE, FALSE, NULL); + + if(waitingReconnection == NULL) + // TODO: fatal error + goto l_Disconnect; + } + + m_protocolThreadWaitingReconnection = waitingReconnection; + + WaitForSingleObject(waitingReconnection, INFINITE); + + m_protocolThreadWaitingReconnection = NULL; + + if(m_reconnectAborted) + { + // FIXME? do we set the disconnection status here? + goto l_Disconnect; + } } // reconnect automatically else @@ -2443,6 +3929,9 @@ ++ autoReconnections; } + + if(overallConnectionTimer) + SetWaitableTimer(overallConnectionTimer, &overallTimeout, 0, ConnectionTimerAPC, NULL, FALSE); // Reconnection success = rdp_reconnect @@ -2458,26 +3947,94 @@ hostname, m_LoadBalanceInfo ); + + if(overallConnectionTimer) + CancelWaitableTimer(overallConnectionTimer); } while(!success); } +l_Disconnect: // Disconnected - // TODO: clean up protocol state, clear "connected" flag FireDisconnected(m_protocolState.disconnect_reason); + + if(overallConnectionTimer) + CloseHandle(overallConnectionTimer); + } + + void JoinProtocolThread() + { + assert(m_protocolThread); + WaitForSingleObject(m_protocolThread, INFINITE); + CloseHandle(m_protocolThread); + m_protocolThread = NULL; + } + + void TerminateProtocolThread() + { + assert(m_protocolThread); + + // wake it up if it's waiting for a manual reconnection + if(m_protocolThreadWaitingReconnection) + { + assert(!m_reconnectAborted); + m_reconnectAborted = true; + SetEvent(m_protocolThreadWaitingReconnection); + } + // otherwise, attempt to interrupt any current blocking operation + else + { + // shutdown(m_protocolState.tcp.sock, SD_BOTH); // TBD: maybe in the future? + QueueUserAPC(DisconnectAPC, m_protocolThread, 0); + } + + assert(m_protocolThreadWaitingReconnection == NULL); + } + + void PerformDisconnect(long reason) + { + assert(InsideApartment()); + assert(m_Connected); + + // TODO: notify virtual channels + + // TODO: do any other disconnection work here... + + // Put the control in the disconnected state + m_Connected = false; + m_loggedIn = false; + + // Notify the container + VARIANTARG arg = { }; + + arg.vt = VT_I4; + arg.lVal = reason; + + FireEventInsideApartment(4, &arg, 1); } public: /* Startup initialization */ static BOOL Startup() { - // TODO: register control window class here - return TRUE; + if(!RdpClientUI::Startup()) + return FALSE; + + WNDCLASSEX wcex = { sizeof(wcex) }; + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = ControlWindowProc; + wcex.hInstance = GetCurrentModule(); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszClassName = TEXT("MissTosca_Control"); + + return RegisterClassEx(&wcex);; } static void Shutdown() { - // TODO + UnregisterClass(TEXT("MissTosca_Control"), GetCurrentModule()); } /* Class factory */ @@ -2609,11 +4166,128 @@ }; /* Pay no attention, ActiveX glue... */ - HRESULT CreateControlWindow() - { - // TODO + LRESULT ControlWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch(uMsg) + { + case WM_SIZE: + { + // TODO: resize UI + } + + return 0; + + case WM_PAINT: + { + LPCWSTR text = NULL; + + if(!m_Connected) + text = m_DisconnectedText; + else if(m_actuallyConnected) + text = m_ConnectedStatusText; + else + text = m_ConnectingText; + + RECT clientRect; + GetClientRect(m_controlWindow, &clientRect); + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(m_controlWindow, &ps); + + SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); + SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); + SelectObject(hdc, GetStockObject(SYSTEM_FONT)); + + RECT textRect = clientRect; + + DrawTextW + ( + hdc, + text, + -1, + &textRect, + DT_CENTER | DT_EDITCONTROL | DT_END_ELLIPSIS | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT + ); + + if(textRect.right > clientRect.right) + textRect.right = clientRect.right; + + if(textRect.bottom > clientRect.bottom) + textRect.bottom = clientRect.bottom; + + textRect.left = (clientRect.right - textRect.right) / 2; + textRect.right += textRect.left; + textRect.top = (clientRect.bottom - textRect.bottom) / 2; + textRect.bottom += textRect.top; + + DrawTextW + ( + hdc, + text, + -1, + &textRect, + DT_CENTER | DT_EDITCONTROL | DT_END_ELLIPSIS | DT_NOPREFIX | DT_WORDBREAK + ); + + EndPaint(m_controlWindow, &ps); + } + + return 0; + + default: + { + LRESULT result; + + if(HandleEvent(uMsg, wParam, lParam, result)) + return result; + } + + break; + } + + return DefWindowProc(m_controlWindow, uMsg, wParam, lParam); + } + + static LRESULT CALLBACK ControlWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + if(uMsg == WM_CREATE) + { + SetWindowLongPtr + ( + hwnd, + GWLP_USERDATA, + (LONG_PTR)reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams + ); + } + + RdpClient * Self = reinterpret_cast<RdpClient *>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + assert(Self); + + return Self->ControlWindowProc(uMsg, wParam, lParam); + } + + HRESULT CreateControlWindow(HWND hwndParent) + { + m_controlWindow = CreateWindow + ( + TEXT("MissTosca_Control"), + NULL, + WS_CHILD | WS_CLIPCHILDREN, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + hwndParent, + NULL, + GetCurrentModule(), + this + ); + + if(m_controlWindow == NULL) + return HRESULT_FROM_WIN32(GetLastError()); + m_UIParentWindowHandle = m_controlWindow; - return E_FAIL; + return S_OK; } HRESULT DestroyControlWindow() @@ -2679,7 +4353,7 @@ ShowWindow(m_controlWindow, SW_SHOW); else { - hr = CreateControlWindow(); + hr = CreateControlWindow(hwndParent); if(FAILED(hr)) break; @@ -2697,7 +4371,16 @@ if(FAILED(hr)) break; - // TODO: focus the control window + SetWindowPos + ( + m_controlWindow, + NULL, + lprcPosRect->left, + lprcPosRect->top, + lprcPosRect->right - lprcPosRect->left, + lprcPosRect->bottom - lprcPosRect->top, + SWP_SHOWWINDOW + ); if(frame) { @@ -3045,7 +4728,21 @@ virtual STDMETHODIMP IOleInPlaceObject::SetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect) { - // TODO: reposition the control window and set its region here + if(m_controlWindow == NULL) + return E_FAIL; + + MoveWindow + ( + m_controlWindow, + lprcPosRect->left, + lprcPosRect->top, + lprcPosRect->right - lprcPosRect->left, + lprcPosRect->bottom - lprcPosRect->top, + TRUE + ); + + SetWindowRgn(m_controlWindow, CreateRectRgnIndirect(lprcClipRect), TRUE); + return E_NOTIMPL; } @@ -3515,12 +5212,12 @@ virtual STDMETHODIMP IMsTscAx::get_HorizontalScrollBarVisible(long * pfHScrollVisible) const { - return GetProperty(m_HorizontalScrollBarVisible, pfHScrollVisible); + return E_NOTIMPL; // TODO } virtual STDMETHODIMP IMsTscAx::get_VerticalScrollBarVisible(long * pfVScrollVisible) const { - return GetProperty(m_VerticalScrollBarVisible, pfVScrollVisible); + return E_NOTIMPL; // TODO } virtual STDMETHODIMP IMsTscAx::put_FullScreenTitle(BSTR rhs) @@ -3576,17 +5273,24 @@ virtual STDMETHODIMP IMsTscAx::Connect() { if(m_Connected) + { + // Protocol thread waiting for a manual reconnection: wake it up + if(m_protocolThreadWaitingReconnection) + { + SetEvent(m_protocolThreadWaitingReconnection); + return S_OK; + } + return E_FAIL; + } m_Connected = true; - // TODO: if the protocol thread is waiting to reconnect, wake it up - HRESULT hr; if(m_controlWindow == NULL) { - hr = CreateControlWindow(); + hr = CreateControlWindow(NULL); if(FAILED(hr)) return hr; @@ -3595,6 +5299,16 @@ for(;;) { // TODO: initialize plugin DLLs/channels + + m_clientUI = new RdpClientUI(); + + if(m_clientUI == NULL) + { + hr = E_OUTOFMEMORY; + break; + } + + m_clientUI->Initialize(m_controlWindow); m_protocolState.licence_username = BstrToLpsz(m_UserName); @@ -3688,9 +5402,9 @@ if(!m_Connected) return E_FAIL; - // TODO: if the protocol thread is waiting to reconnect, wake it up - - return E_NOTIMPL; // TODO + // Terminate the protocol thread. On exit, it will fire the Disconnected event + TerminateProtocolThread(); + return S_OK; } virtual STDMETHODIMP IMsTscAx::CreateVirtualChannels(BSTR newVal) @@ -3776,7 +5490,21 @@ virtual STDMETHODIMP IMsRdpClient::RequestClose(MSTSCLib::ControlCloseStatus * pCloseStatus) { - return E_NOTIMPL; // TODO + if(pCloseStatus == NULL) + return E_POINTER; + + if(!m_Connected) + { + *pCloseStatus = MSTSCLib::controlCloseCanProceed; + return S_OK; + } + + *pCloseStatus = MSTSCLib::controlCloseWaitForEvents; + + if(!PostMessage(m_controlWindow, RDPC_WM_REQUEST_CLOSE, 0, 0)) + return HRESULT_FROM_WIN32(GetLastError()); + + return S_OK; } /* IMsRdpClient2 */ @@ -3884,6 +5612,330 @@ }; #pragma warning(pop) + +/* More glue to interface to the rdesktop code */ +extern "C" +{ + +/* Orders */ +/* support routines */ +void ui_begin_update(RDPCLIENT * This) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_BeginUpdate(); +} + +void ui_end_update(RDPCLIENT * This) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_EndUpdate(); +} + +void ui_set_clip(RDPCLIENT * This, int x, int y, int cx, int cy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_SetClip(x, y, cx, cy); +} + +void ui_reset_clip(RDPCLIENT * This) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_ResetClip(); +} + +/* blits */ +void ui_destblt(RDPCLIENT * This, uint8 opcode, int x, int y, int cx, int cy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_DestBlt(opcode, x, y, cx, cy); +} + +void ui_memblt(RDPCLIENT * This, uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_MemBlt(opcode, x, y, cx, cy, src, srcx, srcy); +} + +void ui_patblt(RDPCLIENT * This, uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_PatBlt(opcode, x, y, cx, cy, brush, bgcolour, fgcolour); +} + +void ui_screenblt(RDPCLIENT * This, uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_ScreenBlt(opcode, x, y, cx, cy, srcx, srcy); +} + +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) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_TriBlt(opcode, x, y, cx, cy, src, srcx, srcy, brush, bgcolour, fgcolour); +} + +void ui_paint_bitmap(RDPCLIENT * This, int x, int y, int cx, int cy, int width, int height, uint8 * data) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_PaintBitmap(x, y, cx, cy, width, height, data); +} + +/* shapes */ +void ui_ellipse(RDPCLIENT * This, uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, int fgcolour) +{ + // TODO +// RdpClient::InnerToOuter(This)->GetUI()->Display_Ellipse(opcode, fillmode, x, y, cx, cy, brush, bgcolour, fgcolour); +} + +void ui_line(RDPCLIENT * This, uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_Line(opcode, startx, starty, endx, endy, pen); +} + +void ui_polygon(RDPCLIENT * This, uint8 opcode, uint8 fillmode, POINT * point, int npoints, BRUSH * brush, int bgcolour, int fgcolour) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_Polygon(opcode, fillmode, point, npoints, brush, bgcolour, fgcolour); +} + +void ui_polyline(RDPCLIENT * This, uint8 opcode, POINT * points, int npoints, PEN * pen) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_Polyline(opcode, points, npoints, pen); +} + +void ui_rect(RDPCLIENT * This, int x, int y, int cx, int cy, int colour) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_Rect(x, y, cx, cy, colour); +} + +/* text */ +void ui_draw_text +( + RDPCLIENT * This, + uint8 font, + uint8 flags, + uint8 opcode, + int mixmode, + int x, + int y, + int clipx, + int clipy, + int clipcx, + int clipcy, + int boxx, + int boxy, + int boxcx, + int boxcy, + BRUSH * brush, + int bgcolour, + int fgcolour, + uint8 * text, + uint8 length +) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_DrawText + ( + font, + flags, + opcode, + mixmode, + x, + y, + clipx, + clipy, + clipcx, + clipcy, + boxx, + boxy, + boxcx, + boxcy, + brush, + bgcolour, + fgcolour, + text, + length + ); +} + +/* desktop save/restore */ +void ui_desktop_save(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_SaveDesktop(offset, x, y, cx, cy); +} + +void ui_desktop_restore(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy) +{ + RdpClient::InnerToOuter(This)->GetUI()->Display_RestoreDesktop(offset, x, y, cx, cy); +} + +/* Resources */ +/* bitmaps */ +HBITMAP ui_create_bitmap(RDPCLIENT * This, int width, int height, uint8 * data) +{ + return win32_create_dib(width, height, This->server_depth, data); +} + +void ui_destroy_bitmap(RDPCLIENT *, HBITMAP bmp) +{ + DeleteObject(bmp); +} + +/* palettes */ +HCOLOURMAP ui_create_colourmap(RDPCLIENT *, COLOURMAP * colours) +{ + return NULL; +} + +void ui_set_colourmap(RDPCLIENT * This, HCOLOURMAP map) +{ + // TODO +} + +/* cursors */ +HCURSOR ui_create_cursor(RDPCLIENT * This, unsigned int x, unsigned int y, int width, int height, uint8 * andmask, uint8 * xormask) +{ + uint8 * andbuf = NULL; + uint8 * xorbuf = NULL; + + uint8 * andbits = win32_convert_scanlines(width, - height, 1, 2, 4, andmask, &andbuf); + uint8 * xorbits = win32_convert_scanlines(width, height, 24, 2, 4, xormask, &xorbuf); + + HBITMAP hbmMask = CreateBitmap(width, height, 1, 1, andbits); + HBITMAP hbmColor = win32_create_dib(width, height, 24, xorbits); + + ICONINFO iconinfo; + iconinfo.fIcon = FALSE; + iconinfo.xHotspot = x; + iconinfo.yHotspot = y; + iconinfo.hbmMask = hbmMask; + iconinfo.hbmColor = hbmColor; + + HICON icon = CreateIconIndirect(&iconinfo); + + if(icon == NULL) + error("CreateIconIndirect %dx%d failed\n", width, height); + + if(andbuf) + delete[] andbuf; + + if(xorbuf) + delete[] xorbuf; + + DeleteObject(hbmMask); + DeleteObject(hbmColor); + + return icon; +} + +void ui_destroy_cursor(RDPCLIENT *, HCURSOR cursor) +{ + DestroyIcon(cursor); +} + +/* glyphs */ +HGLYPH ui_create_glyph(RDPCLIENT * This, int width, int height, const uint8 * data) +{ + uint8 * databuf = NULL; + uint8 * databits = win32_convert_scanlines(width, height, 1, 1, 2, data, &databuf); + + HBITMAP hbm = CreateBitmap(width, height, 1, 1, databits); + + if(databuf) + delete[] databuf; + + const uint8 * p = data; + int stride = alignup(alignup(width, 8) / 8, 1); + +#ifdef _DEBUG + printf("glyph %p\n", hbm); + + for(int i = 0; i < height; ++ i, p += stride) + { + for(int j = 0; j < width; ++ j) + { + int B = p[j / 8]; + int b = 8 - j % 8 - 1; + + if(B & (1 << b)) + fputs("##", stdout); + else + fputs("..", stdout); + } + + fputc('\n', stdout); + } + + fputc('\n', stdout); +#endif + + return hbm; +} + +void ui_destroy_glyph(RDPCLIENT *, HGLYPH glyph) +{ + DeleteObject(glyph); +} + +/* Input window */ +void ui_move_pointer(RDPCLIENT * This, int x, int y) +{ + // TODO +} + +void ui_set_cursor(RDPCLIENT * This, HCURSOR cursor) +{ + // TODO +} + +void ui_set_null_cursor(RDPCLIENT * This) +{ + // TODO +} + +/* Miscellaneous */ +void ui_resize_window(RDPCLIENT * This) +{ +} + +void ui_bell(RDPCLIENT *) +{ + MessageBeep(0); +} + +int ui_select(RDPCLIENT * This, SOCKET rdp_socket) +{ + return SleepEx(0, TRUE) == WAIT_IO_COMPLETION; +} + +/* Events */ +BOOL event_pubkey(RDPCLIENT * This, unsigned char * key, unsigned int key_size) +{ + if(!RdpClient::OnPublicKey(This, key, key_size)) + return FALSE; + else + return TRUE; +} + +void event_logon(RDPCLIENT * This) +{ + RdpClient::OnLogon(This); +} + +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) +{ + if + ( + !RdpClient::OnRedirect + ( + This, + flags, + server_len, + server, + cookie_len, + cookie, + username_len, + username, + domain_len, + domain, + password_len, + password + ) + ) + return FALSE; + else + return TRUE; +} + +} class ClassFactory: public IClassFactory { @@ -4017,8 +6069,6 @@ { DisableThreadLibraryCalls(hInstance); - InitCommonControls(); - if(!RdpClient::Startup()) return FALSE; } Modified: trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp (original) +++ trunk/reactos/base/applications/tsclient/porting-tools/rdesktop-core-tester/rdesktop-core-tester.cpp Mon Aug 21 01:02:10 2006 @@ -4,16 +4,6 @@ #include "rdesktop/rdesktop.h" #include "rdesktop/proto.h" - -template<class T, class U> T aligndown(const T& X, const U& align) -{ - return X & ~(T(align) - 1); -} - -template<class T, class U> T alignup(const T& X, const U& align) -{ - return aligndown(X + (align - 1), align); -} extern "C" { @@ -199,897 +189,6 @@ HDC hdcBuffer; UINT wmZMouseWheel; - static - HBITMAP - win32_create_dib(LONG width, LONG height, WORD bitcount, const BYTE * data) - { - struct b_ - { - BITMAPINFO bmi; - RGBQUAD colormap[256 - ARRAYSIZE(RTL_FIELD_TYPE(BITMAPINFO, bmiColors))]; - } - b; - - b.bmi.bmiHeader.biSize = sizeof(b.bmi.bmiHeader); - b.bmi.bmiHeader.biWidth = width; - b.bmi.bmiHeader.biHeight = height; - b.bmi.bmiHeader.biPlanes = 1; - b.bmi.bmiHeader.biBitCount = bitcount; - b.bmi.bmiHeader.biCompression = BI_RGB; - b.bmi.bmiHeader.biSizeImage = 0; - b.bmi.bmiHeader.biXPelsPerMeter = 0; - b.bmi.bmiHeader.biYPelsPerMeter = 0; - - if(bitcount > 8) - { - b.bmi.bmiHeader.biClrUsed = 0; - b.bmi.bmiHeader.biClrImportant = 0; - } - else - { - b.bmi.bmiHeader.biClrUsed = 2 << bitcount; - b.bmi.bmiHeader.biClrImportant = 2 << bitcount; - - // TODO: palette - } - - HBITMAP hbm = CreateDIBitmap(hdcBuffer, &b.bmi.bmiHeader, CBM_INIT, data, &b.bmi, DIB_RGB_COLORS); - - if(hbm == NULL) - error("CreateDIBitmap %dx%dx%d failed\n", width, height, bitcount); - - return hbm; - } - - static - uint8 * - win32_convert_scanlines(int width, int height, int bitcount, int fromalign, int toalign, const uint8 * data, uint8 ** buffer) - { - // TBD: profile & optimize the most common cases - assert(width > 0); - assert(height); - assert(bitcount && bitcount <= 32); - assert(fromalign <= toalign); - assert(data); - assert(buffer); - - bool flipped = height < 0; - - if(flipped) - height = - height; - - int bytesperrow = alignup(width * bitcount, 8) / 8; - int fromstride = alignup(bytesperrow, fromalign); - int tostride = alignup(bytesperrow, toalign); - assert(fromstride <= tostride); - - int datasize = tostride * height; - - uint8 * dibits = new(malloc(datasize)) uint8; - - if(dibits == NULL) - return NULL; - - const uint8 * src = data; - uint8 * dest = dibits; - - const int pad = tostride - fromstride; - - assert(pad < 4); - __assume(pad < 4); - - if(flipped) - { - dest += (height - 1) * tostride; - tostride = - tostride; - } - - for(int i = 0; i < height; ++ i) - { - memcpy(dest, src, fromstride); - memset(dest + fromstride, 0, pad); - src += fromstride; - dest += tostride; - } - - *buffer = dibits; - return dibits; - } - - void - ui_resize_window(RDPCLIENT * This) - { - // EVENT: OnRemoteDesktopSizeChange - // TODO: resize buffer - SetWindowPos(hwnd, NULL, 0, 0, This->width, This->height, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE); - } - - int - ui_select(RDPCLIENT * This, SOCKET rdp_socket) - { - return 1; // TODO: return 0 for user quit. Or just kill this silly function - } - - void - ui_move_pointer(RDPCLIENT * This, int x, int y) - { - POINT point; - point.x = x; - point.y = y; - - ClientToScreen(hwnd, &point); - SetCursorPos(point.x, point.y); - } - - HCURSOR hcursor; - - HBITMAP - ui_create_bitmap(RDPCLIENT * This, int width, int height, uint8 * data) - { - return win32_create_dib(width, height, This->server_depth, data); - } - - void - ui_destroy_bitmap(RDPCLIENT * This, HBITMAP bmp) - { - DeleteObject(bmp); - } - - HGLYPH - ui_create_glyph(RDPCLIENT * This, int width, int height, const uint8 * data) - { - uint8 * databuf = NULL; - uint8 * databits = win32_convert_scanlines(width, height, 1, 1, 2, data, &databuf); - - if(databits == NULL) - return NULL; - - HBITMAP hbm = CreateBitmap(width, height, 1, 1, databits); - - if(databuf) - free(databuf); - - const uint8 * p = data; - int stride = alignup(alignup(width, 8) / 8, 1); - - printf("glyph %p\n", hbm); - - for(int i = 0; i < height; ++ i, p += stride) - { - for(int j = 0; j < width; ++ j) - { - int B = p[j / 8]; - int b = 8 - j % 8 - 1; - - if(B & (1 << b)) - fputs("##", stdout); - else - fputs("..", stdout); - } - - fputc('\n', stdout); - } - - fputc('\n', stdout); - - return hbm; - } - - void - ui_destroy_glyph(RDPCLIENT * This, HGLYPH glyph) - { - DeleteObject(glyph); - } - - HCURSOR - ui_create_cursor(RDPCLIENT * This, unsigned int x, unsigned int y, int width, int height, - uint8 * andmask, uint8 * xormask) - { - uint8 * andbuf = NULL; - uint8 * xorbuf = NULL; - - uint8 * andbits = win32_convert_scanlines(width, - height, 1, 2, 4, andmask, &andbuf); - - if(andbits == NULL) - return NULL; - - uint8 * xorbits = win32_convert_scanlines(width, height, 24, 2, 4, xormask, &xorbuf); - - if(xorbits == NULL) - { - free(andbits); - return NULL; - } - - HBITMAP hbmMask = CreateBitmap(width, height, 1, 1, andbits); - HBITMAP hbmColor = win32_create_dib(width, height, 24, xorbits); - - ICONINFO iconinfo; - iconinfo.fIcon = FALSE; - iconinfo.xHotspot = x; - iconinfo.yHotspot = y; - iconinfo.hbmMask = hbmMask; - iconinfo.hbmColor = hbmColor; - - HICON icon = CreateIconIndirect(&iconinfo); - - if(icon == NULL) - error("CreateIconIndirect %dx%d failed\n", width, height); - - if(andbuf) - free(andbuf); - - if(xorbuf) - free(xorbuf); - - DeleteObject(hbmMask); - DeleteObject(hbmColor); - - return icon; - } - - void - ui_set_cursor(RDPCLIENT * This, HCURSOR cursor) - { - hcursor = cursor; - } - - void - ui_destroy_cursor(RDPCLIENT * This, HCURSOR cursor) - { - DestroyIcon(cursor); - } - - void - ui_set_null_cursor(RDPCLIENT * This) - { - hcursor = NULL; - } - - HCOLOURMAP - ui_create_colourmap(RDPCLIENT * This, COLOURMAP * colours) - { - // TODO - // TODO: kill HCOLOURMAP/COLOURMAP, use HPALETTE/LOGPALETTE - return 0; - } - - void - ui_destroy_colourmap(RDPCLIENT * This, HCOLOURMAP map) - { - // TODO: see above - } - - void - ui_set_colourmap(RDPCLIENT * This, HCOLOURMAP map) - { - // TODO - } - - RECT rcClip; // TODO: initialize - - void - ui_set_clip(RDPCLIENT * This, int x, int y, int cx, int cy) - { - rcClip.left = x; - rcClip.top = y; - rcClip.right = x + cx + 1; - rcClip.bottom = y + cy + 1; - - HRGN hrgn = CreateRectRgnIndirect(&rcClip); - SelectClipRgn(hdcBuffer, hrgn); - DeleteObject(hrgn); - } - - void - ui_reset_clip(RDPCLIENT * This) - { - rcClip.left = 0; - rcClip.top = 0; - rcClip.right = This->width + 1; - rcClip.bottom = This->height + 1; - SelectClipRgn(hdcBuffer, NULL); - } - - void - ui_bell(RDPCLIENT * This) - { - MessageBeep(MB_OK); // TODO? use Beep() on remote sessions? - } - - static - void - win32_repaint_rect(RDPCLIENT * This, const RECT * lprc) - { - RECT rcDamage; - IntersectRect(&rcDamage, lprc, &rcClip); - -#if 0 - HDC hdc = GetDC(hwnd); - SelectObject(hdc, GetStockObject(NULL_PEN)); - SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0))); - Rectangle(hdc, rcDamage.left, rcDamage.top, rcDamage.right + 1, rcDamage.bottom + 1); - ReleaseDC(hwnd, hdc); - Sleep(200); -#endif - - InvalidateRect(hwnd, &rcDamage, FALSE); - } - - static - void - win32_repaint_area(RDPCLIENT * This, int x, int y, int cx, int cy) - { - RECT rcDamage; - rcDamage.left = x; - rcDamage.top = y; - rcDamage.right = x + cx; - rcDamage.bottom = y + cy; - win32_repaint_rect(This, &rcDamage); - } - - static - void - win32_repaint_poly(RDPCLIENT * This, POINT * point, int npoints, int linewidth) - { - RECT rcDamage; - - rcDamage.left = MAXLONG; - rcDamage.top = MAXLONG; - rcDamage.right = 0; - rcDamage.bottom = 0; - - for(int i = 0; i < npoints; ++ i) - { - if(point[i].x < rcDamage.left) - rcDamage.left = point[i].x; - - if(point[i].y < rcDamage.top) - rcDamage.top = point[i].y; - - if(point[i].x > rcDamage.right) - rcDamage.right = point[i].x; - - if(point[i].y > rcDamage.bottom) - rcDamage.bottom = point[i].y; - } - - InflateRect(&rcDamage, linewidth, linewidth); - win32_repaint_rect(This, &rcDamage); - } - - static - void - win32_repaint_whole(RDPCLIENT * This) - { - InvalidateRgn(hwnd, NULL, FALSE); - } - - static - HBRUSH - win32_create_brush(RDPCLIENT * This, BRUSH * brush, COLORREF fgcolour) - { - if(brush == NULL) - return (HBRUSH)GetStockObject(NULL_BRUSH); - - switch(brush->style) - { - case BS_SOLID: - case BS_NULL: - case BS_HATCHED: - case BS_PATTERN: - case BS_PATTERN8X8: - break; - - default: - return NULL; - } - - switch(brush->style) - { - case BS_SOLID: - return CreateSolidBrush(fgcolour); - - case BS_HATCHED: - return CreateHatchBrush(brush->pattern[0], fgcolour); - - case BS_NULL: - return (HBRUSH)GetStockObject(NULL_BRUSH); - - case BS_PATTERN: - case BS_PATTERN8X8: - { - uint16 pattern[8]; - - for(size_t i = 0; i < 8; ++ i) - pattern[i] = brush->pattern[i]; - - HBITMAP hpattern = CreateBitmap(8, 8, 1, 1, pattern); - HBRUSH hbr = CreatePatternBrush(hpattern); - DeleteObject(hpattern); - return hbr; - } - - DEFAULT_UNREACHABLE; - } - } - - void - ui_paint_bitmap(RDPCLIENT * This, int x, int y, int cx, int cy, int width, int height, uint8 * data) - { - assert(This->server_depth >= 8); - assert(rcClip.left == 0 && rcClip.top == 0 && rcClip.right == This->width + 1 && rcClip.bottom == This->height + 1); - - GdiFlush(); - - // TBD: we can cache these values - int Bpp = alignup(This->server_depth, 8) / 8; - int tostride = alignup(This->width * Bpp, 4); - - int fromstride = alignup(width * Bpp, 4); - int sizex = cx * Bpp; - - const uint8 * src = data; - uint8 * dst = (uint8 *)pBuffer + (This->height - y - cy) * tostride + x * Bpp; - - for(int i = 0; i < cy; ++ i) - { - memcpy(dst, src, sizex); - src += fromstride; - dst += tostride; - } - - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_destblt(RDPCLIENT * This, uint8 opcode, - /* dest */ int x, int y, int cx, int cy) - { - int dcsave = SaveDC(hdcBuffer); - SelectObject(hdcBuffer, GetStockObject(BLACK_BRUSH)); - PatBlt(hdcBuffer, x, y, cx, cy, MAKELONG(0, opcode)); - RestoreDC(hdcBuffer, dcsave); - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_patblt(RDPCLIENT * This, uint8 opcode, - /* dest */ int x, int y, int cx, int cy, - /* brush */ BRUSH * brush, int bgcolour, int fgcolour) - { - HBRUSH hbr = win32_create_brush(This, brush, fgcolour); - - int dcsave = SaveDC(hdcBuffer); - - SetBkColor(hdcBuffer, bgcolour); - SetTextColor(hdcBuffer, fgcolour); - SetBrushOrgEx(hdcBuffer, brush->xorigin, brush->yorigin, NULL); - SelectObject(hdcBuffer, hbr); - - PatBlt(hdcBuffer, x, y, cx, cy, MAKELONG(0, opcode)); - - RestoreDC(hdcBuffer, dcsave); - - DeleteObject(hbr); - - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_screenblt(RDPCLIENT * This, uint8 opcode, - /* dest */ int x, int y, int cx, int cy, - /* src */ int srcx, int srcy) - { - BitBlt(hdcBuffer, x, y, cx, cy, hdcBuffer, srcx, srcy, MAKELONG(0, opcode)); - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_memblt(RDPCLIENT * This, uint8 opcode, - /* dest */ int x, int y, int cx, int cy, - /* src */ HBITMAP src, int srcx, int srcy) - { - HDC hdcSrc = CreateCompatibleDC(hdcBuffer); - HGDIOBJ hOld = SelectObject(hdcSrc, src); - - BitBlt(hdcBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode)); - - SelectObject(hdcSrc, hOld); - DeleteDC(hdcSrc); - - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_triblt(RDPCLIENT * This, uint8 opcode, - /* dest */ int x, int y, int cx, int cy, - /* src */ HBITMAP src, int srcx, int srcy, - /* brush */ BRUSH * brush, int bgcolour, int fgcolour) - { - // TODO - HDC hdcSrc = CreateCompatibleDC(hdcBuffer); - HGDIOBJ hOld = SelectObject(hdcSrc, src); - - //SELECT_BRUSH(brush, bgcolour, fgcolour); - - BitBlt(hdcBuffer, x, y, cx, cy, hdcSrc, srcx, srcy, MAKELONG(0, opcode)); - - //RESET_BRUSH(); - - SelectObject(hdcSrc, hOld); - DeleteDC(hdcSrc); - - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_line(RDPCLIENT * This, uint8 opcode, - /* dest */ int startx, int starty, int endx, int endy, - /* pen */ PEN * pen) - { - HPEN hpen = CreatePen(pen->style, pen->width, pen->colour); - - int dcsave = SaveDC(hdcBuffer); - - SetROP2(hdcBuffer, opcode); - SelectObject(hdcBuffer, hpen); - MoveToEx(hdcBuffer, startx, starty, NULL); - - LineTo(hdcBuffer, endx, endy); - - RestoreDC(hdcBuffer, dcsave); - - DeleteObject(hpen); - - RECT rcDamage; - - if(startx < endx) - { - rcDamage.left = startx; - rcDamage.right = endx; - } - else - { - rcDamage.left = endx; - rcDamage.right = startx; - } - - if(starty < endy) - { - rcDamage.top = starty; - rcDamage.bottom = endy; - } - else - { - rcDamage.top = endy; - rcDamage.bottom = starty; - } - - InflateRect(&rcDamage, pen->width, pen->width); - win32_repaint_rect(This, &rcDamage); - } - - void - ui_rect(RDPCLIENT * This, - /* dest */ int x, int y, int cx, int cy, - /* brush */ int colour) - { - HBRUSH hbr = CreateSolidBrush(colour); - - int dcsave = SaveDC(hdcBuffer); - - SelectObject(hdcBuffer, hbr); - SelectObject(hdcBuffer, GetStockObject(NULL_PEN)); - - Rectangle(hdcBuffer, x, y, x + cx + 1, y + cy + 1); - - RestoreDC(hdcBuffer, dcsave); - - DeleteObject(hbr); - - win32_repaint_area(This, x, y, cx, cy); - } - - void - ui_polygon(RDPCLIENT * This, uint8 opcode, - /* mode */ uint8 fillmode, - /* dest */ POINT * point, int npoints, - /* brush */ BRUSH * brush, int bgcolour, int fgcolour) - { - HBRUSH hbr = win32_create_brush(This, brush, fgcolour); - - int dcsave = SaveDC(hdcBuffer); - - SetBkColor(hdcBuffer, bgcolour); - SetTextColor(hdcBuffer, fgcolour); - SetPolyFillMode(hdcBuffer, fillmode); - SelectObject(hdcBuffer, hbr); - - Polygon(hdcBuffer, point, npoints); - - RestoreDC(hdcBuffer, dcsave); - - win32_repaint_poly(This, point, npoints, 0); - } - - void - ui_polyline(RDPCLIENT * This, uint8 opcode, - /* dest */ POINT * points, int npoints, - /* pen */ PEN * pen) - { - POINT last = points[0]; - - for(int i = 1; i < npoints; ++ i) - { - points[i].x += last.x; - points[i].y += last.y; - last = points[i]; - } - - HPEN hpen = CreatePen(pen->style, pen->width, pen->colour); - - int dcsave = SaveDC(hdcBuffer); - - SetROP2(hdcBuffer, opcode); - SelectObject(hdcBuffer, hpen); - - Polyline(hdcBuffer, points, npoints); - - RestoreDC(hdcBuffer, dcsave); - - DeleteObject(hpen); - - win32_repaint_poly(This, points, npoints, pen->width); - } - - void - ui_ellipse(RDPCLIENT * This, uint8 opcode, - /* mode */ uint8 fillmode, - /* dest */ int x, int y, int cx, int cy, - /* brush */ BRUSH * brush, int bgcolour, int fgcolour) - { - // TODO - - win32_repaint_area(This, x, y, cx, cy); - } - - // TBD: optimize text drawing - void - ui_draw_glyph(RDPCLIENT * This, int mixmode, - /* dest */ int x, int y, int cx, int cy, - /* src */ HGLYPH glyph, int srcx, int srcy, - int bgcolour, int fgcolour) - { - HBITMAP hbmGlyph = (HBITMAP)glyph; - HDC hdcGlyph = CreateCompatibleDC(hdcBuffer); - HGDIOBJ hOld = SelectObject(hdcGlyph, hbmGlyph); - - int dcsave = SaveDC(hdcBuffer); - - switch(mixmode) - { - case MIX_TRANSPARENT: - { - /* - ROP is DSPDxax: - - where the glyph (S) is white, D is set to the foreground color (P) - - where the glyph (S) is black, D is left untouched - - This paints a transparent glyph in the specified color - */ - HBRUSH hbr = CreateSolidBrush(fgcolour); - SelectObject(hdcBuffer, hbr); - BitBlt(hdcBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, MAKELONG(0, 0xe2)); - DeleteObject(hbr); - } - - break; - - case MIX_OPAQUE: - { - /* Curiously, glyphs are inverted (white-on-black) */ - SetBkColor(hdcBuffer, fgcolour); - SetTextColor(hdcBuffer, bgcolour); - BitBlt(hdcBuffer, x, y, cx, cy, hdcGlyph, srcx, srcy, SRCCOPY); - } - - break; - } - - RestoreDC(hdcBuffer, dcsave); - - SelectObject(hdcGlyph, hOld); - DeleteDC(hdcGlyph); - - win32_repaint_area(This, x, y, cx, cy); - } - - // TBD: a clean-up would be nice, too... -#define DO_GLYPH(ttext,idx) \ -{\ - glyph = cache_get_font (This, font, ttext[idx]);\ - if (!(flags & TEXT2_IMPLICIT_X))\ - {\ - xyoffset = ttext[++idx];\ - if ((xyoffset & 0x80))\ - {\ - if (flags & TEXT2_VERTICAL)\ - y += ttext[idx+1] | (ttext[idx+2] << 8);\ - else\ - x += ttext[idx+1] | (ttext[idx+2] << 8);\ - idx += 2;\ - }\ - else\ - {\ - if (flags & TEXT2_VERTICAL)\ - y += xyoffset;\ - else\ - x += xyoffset;\ - }\ - }\ - if (glyph != NULL)\ - {\ - ui_draw_glyph (This, mixmode, x + (short) glyph->offset,\ - y + (short) glyph->baseline,\ - glyph->width, glyph->height,\ - glyph->pixmap, 0, 0, bgcolour, fgcolour);\ - if (flags & TEXT2_IMPLICIT_X)\ - x += glyph->width;\ - }\ -} - - void - ui_draw_text(RDPCLIENT * This, uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y, - int clipx, int clipy, int clipcx, int clipcy, - int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush, - int bgcolour, int fgcolour, uint8 * text, uint8 length) - { - FONTGLYPH * glyph; - int i, j, xyoffset; - DATABLOB *entry; - - HBRUSH hbr = CreateSolidBrush(bgcolour); - HGDIOBJ holdbrush = SelectObject(hdcBuffer, hbr); - HGDIOBJ holdpen = SelectObject(hdcBuffer, GetStockObject(NULL_PEN)); - - if (boxcx > 1) - Rectangle(hdcBuffer, boxx, boxy, boxx + boxcx + 1, boxy + boxcy + 1); - else if (mixmode == MIX_OPAQUE) - Rectangle(hdcBuffer, clipx, clipy, clipx + clipcx + 1, clipy + clipcy + 1); - - SelectObject(hdcBuffer, holdpen); - SelectObject(hdcBuffer, holdbrush); - - DeleteObject(hbr); - - if(boxcx > 1) - win32_repaint_area(This, boxx, boxy, boxcx, boxcy); - else - win32_repaint_area(This, clipx, clipy, clipcx, clipcy); - - /* Paint text, character by character */ - for (i = 0; i < length;) - { - switch (text[i]) - { - case 0xff: - /* At least two bytes needs to follow */ - if (i + 3 > length) - { - warning("Skipping short 0xff command:"); - for (j = 0; j < length; j++) - fprintf(stderr, "%02x ", text[j]); - fprintf(stderr, "\n"); - i = length = 0; - break; - } - cache_put_text(This, text[i + 1], text, text[i + 2]); - i += 3; - length -= i; - /* this will move pointer from start to first character after FF command */ - text = &(text[i]); - i = 0; - break; - - case 0xfe: - /* At least one byte needs to follow */ - if (i + 2 > length) - { - warning("Skipping short 0xfe command:"); - for (j = 0; j < length; j++) - fprintf(stderr, "%02x ", text[j]); - fprintf(stderr, "\n"); - i = length = 0; - break; - } - entry = cache_get_text(This, text[i + 1]); - if (entry->data != NULL) - { - if ((((uint8 *) (entry->data))[1] == 0) - && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length)) - { - if (flags & TEXT2_VERTICAL) - y += text[i + 2]; - else - x += text[i + 2]; - } - for (j = 0; j < entry->size; j++) - DO_GLYPH(((uint8 *) (entry->data)), j); - } - if (i + 2 < length) - i += 3; - else - i += 2; - length -= i; - /* this will move pointer from start to first character after FE command */ - text = &(text[i]); - i = 0; - break; - - default: - DO_GLYPH(text, i); - i++; - break; - } - } - } - - void - ui_desktop_save(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy) - { - GdiFlush(); - int Bpp = alignup(This->server_depth, 8) / 8; - int stride = alignup(This->width * Bpp, 4); - uint8 * data = (uint8 *)pBuffer + x * Bpp + (This->height - y - cy) * stride; - cache_put_desktop(This, offset * Bpp, cx, cy, stride, Bpp, data); - } - - void - ui_desktop_restore(RDPCLIENT * This, uint32 offset, int x, int y, int cx, int cy) - { - // TBD: we can cache these values - int Bpp = alignup(This->server_depth, 8) / 8; - int tostride = alignup(This->width * Bpp, 4); - int fromstride = cx * Bpp; - - const uint8 * src = cache_get_desktop(This, offset, cx, cy, Bpp); - uint8 * dst = (uint8 *)pBuffer + x * Bpp + (This->height - y - cy) * tostride; - - GdiFlush(); - - for(int i = 0; i < cy; ++ i) - { - memcpy(dst, src, fromstride); - src += fromstride; - dst += tostride; - } - - win32_repaint_area(This, x, y, cx, cy); - } - - int nSavedDC; - - void - ui_begin_update(RDPCLIENT * This) - { - nSavedDC = SaveDC(hdcBuffer); - } - - void - ui_end_update(RDPCLIENT * This) - { - RestoreDC(hdcBuffer, nSavedDC); - } - - int event_pubkey(RDPCLIENT * This, const unsigned char * key, size_t key_size) - { - return True; - } - - void event_logon(RDPCLIENT * This) - { - } }; static @@ -1193,7 +292,7 @@ case WM_SETCURSOR: if(LOWORD(lparam) == HTCLIENT) { - SetCursor(hcursor); + //SetCursor(hcursor); return TRUE; } @@ -1291,10 +390,12 @@ SelectObject(hdcBuffer, hbmBuffer); +#if 0 rcClip.left = 0; rcClip.top = 0; rcClip.right = This->width + 1; rcClip.bottom = This->height + 1; +#endif BOOL deactivated; uint32 ext_disc_reason; @@ -1507,7 +608,7 @@ This->rdp.current_status = 1; - hcursor = NULL; + //hcursor = NULL; WNDCLASS wc; ZeroMemory(&wc, sizeof(wc)); Modified: trunk/reactos/base/applications/tsclient/rdesktop/iso.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/rdesktop/iso.c (original) +++ trunk/reactos/base/applications/tsclient/rdesktop/iso.c Mon Aug 21 01:02:10 2006 @@ -228,9 +228,7 @@ BOOL iso_disconnect(RDPCLIENT * This) { - if(!iso_send_msg(This, ISO_PDU_DR)) - return False; - + iso_send_msg(This, ISO_PDU_DR); return tcp_disconnect(This); } Modified: trunk/reactos/base/applications/tsclient/rdesktop/proto.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/rdesktop/proto.h (original) +++ trunk/reactos/base/applications/tsclient/rdesktop/proto.h Mon Aug 21 01:02:10 2006 @@ -310,8 +310,9 @@ unsigned int seamless_send_focus(RDPCLIENT * This, unsigned long id, unsigned long flags); /* events */ -int event_pubkey(RDPCLIENT * This, const unsigned char * key, size_t key_size); +BOOL event_pubkey(RDPCLIENT * This, unsigned char * key, unsigned int key_size); void event_logon(RDPCLIENT * This); +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); /* *INDENT-OFF* */ #ifdef __cplusplus Modified: trunk/reactos/base/applications/tsclient/rdesktop/rdesktop.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/rdesktop/rdesktop.h (original) +++ trunk/reactos/base/applications/tsclient/rdesktop/rdesktop.h Mon Aug 21 01:02:10 2006 @@ -303,6 +303,7 @@ SOCKET sock; struct stream in; struct stream out; + long connection_timeout; } tcp; }; Modified: trunk/reactos/base/applications/tsclient/rdesktop/rdp.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/rdesktop/rdp.c (original) +++ trunk/reactos/base/applications/tsclient/rdesktop/rdp.c Mon Aug 21 01:02:10 2006 @@ -1340,50 +1340,81 @@ static BOOL process_redirect_pdu(RDPCLIENT * This, STREAM s /*, uint32 * ext_disc_reason */ ) { - uint32 len; - - // FIXME!!! allocate the strings used here + 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; /* these 2 bytes are unknown, seem to be zeros */ in_uint8s(s, 2); /* read connection flags */ - in_uint32_le(s, This->redirect_flags); + in_uint32_le(s, flags); /* read length of ip string */ - in_uint32_le(s, len); + in_uint32_le(s, server_len); /* read ip string */ - rdp_in_unistr(This, s, This->redirect_server, len); + server = (wchar_t *)s->p; + in_uint8s(s, server_len); /* read length of cookie string */ - in_uint32_le(s, len); + in_uint32_le(s, cookie_len); /* read cookie string (plain ASCII) */ - in_uint8a(s, This->redirect_cookie, len); - This->redirect_cookie[len] = 0; + cookie = (char *)s->p; + in_uint8s(s, cookie_len); /* read length of username string */ - in_uint32_le(s, len); + in_uint32_le(s, username_len); /* read username string */ - rdp_in_unistr(This, s, This->redirect_username, len); + username = (wchar_t *)s->p; + in_uint8s(s, username_len); /* read length of domain string */ - in_uint32_le(s, len); + in_uint32_le(s, domain_len); /* read domain string */ - rdp_in_unistr(This, s, This->redirect_domain, len); + domain = (wchar_t *)s->p; + in_uint8s(s, domain_len); /* read length of password string */ - in_uint32_le(s, len); + in_uint32_le(s, password_len); /* read password string */ - rdp_in_unistr(This, s, This->redirect_password, len); + password = (wchar_t *)s->p; + in_uint8s(s, password_len); This->redirect = True; - return True; + return event_redirect + ( + This, + flags, + server_len, + server, + cookie_len, + cookie, + username_len, + username, + domain_len, + domain, + password_len, + password + ); } /* Process incoming packets */ Modified: trunk/reactos/base/applications/tsclient/rdesktop/tcp.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/tsclient…
============================================================================== --- trunk/reactos/base/applications/tsclient/rdesktop/tcp.c (original) +++ trunk/reactos/base/applications/tsclient/rdesktop/tcp.c Mon Aug 21 01:02:10 2006 @@ -68,17 +68,36 @@ tcp_send(RDPCLIENT * This, STREAM s) { int length = (int)(s->end - s->data); - int sent, total = 0; + int total = 0; + DWORD sent; + + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); while (total < length) { - sent = send(This->tcp.sock, s->data + total, length - total, 0); - if (sent <= 0) - { - // error("send: %s\n", strerror(errno)); // EOF + WriteFile((HANDLE)This->tcp.sock, s->data + total, length - total, NULL, &overlapped); + + switch(WaitForSingleObjectEx((HANDLE)This->tcp.sock, INFINITE, TRUE)) + { + /* Success */ + case WAIT_OBJECT_0: + break; + + /* Timeout or error */ + case WAIT_TIMEOUT: + default: This->disconnect_reason = 772; + + /* Aborted, must disconnect ASAP */ + case WAIT_IO_COMPLETION: + CancelIo((HANDLE)This->tcp.sock); + break; + } + + /* Wait for completion. We could hang here, but we shouldn't */ + if(!GetOverlappedResult((HANDLE)This->tcp.sock, &overlapped, &sent, TRUE)) return False; - } total += sent; } @@ -91,7 +110,7 @@ tcp_recv(RDPCLIENT * This, STREAM s, uint32 length) { unsigned int new_length, end_offset, p_offset; - int rcvd = 0; + DWORD rcvd = 0; if (s == NULL) { @@ -137,18 +156,37 @@ while (length > 0) { + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + if (!ui_select(This, This->tcp.sock)) /* User quit */ return NULL; - rcvd = recv(This->tcp.sock, s->end, length, 0); - if (rcvd < 0) - { - // error("recv: %s\n", strerror(errno)); // EOF + ReadFile((HANDLE)This->tcp.sock, s->end, length, NULL, &overlapped); + + switch(WaitForSingleObjectEx((HANDLE)This->tcp.sock, INFINITE, TRUE)) + { + /* Success */ + case WAIT_OBJECT_0: + break; + + /* Timeout or error */ + case WAIT_TIMEOUT: + default: This->disconnect_reason = 1028; - return NULL; - } - else if (rcvd == 0) + + /* Aborted, must disconnect ASAP */ + case WAIT_IO_COMPLETION: + CancelIo((HANDLE)This->tcp.sock); + break; + } + + /* Wait for completion. We could hang here, but we shouldn't */ + if(!GetOverlappedResult((HANDLE)This->tcp.sock, &overlapped, &rcvd, TRUE)) + return False; + + if (rcvd == 0) { error("Connection closed\n"); This->disconnect_reason = 2308; @@ -232,6 +270,8 @@ servaddr.sin_family = AF_INET; servaddr.sin_port = htons(This->tcp_port_rdp); + + // TODO: apply connection timeout here if (connect(This->tcp.sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0) {
18 years, 4 months
1
0
0
0
[arty] 23626: Add the ability to specify DNS servers and make adns work right in case they are specified.
by arty@svn.reactos.org
Author: arty Date: Mon Aug 21 00:51:54 2006 New Revision: 23626 URL:
http://svn.reactos.org/svn/reactos?rev=23626&view=rev
Log: Add the ability to specify DNS servers and make adns work right in case they are specified. Modified: trunk/reactos/dll/win32/dnsapi/dnsapi/query.c trunk/reactos/lib/3rdparty/adns/src/adns.h trunk/reactos/lib/3rdparty/adns/src/setup.c Modified: trunk/reactos/dll/win32/dnsapi/dnsapi/query.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dnsapi/dnsapi/qu…
============================================================================== --- trunk/reactos/dll/win32/dnsapi/dnsapi/query.c (original) +++ trunk/reactos/dll/win32/dnsapi/dnsapi/query.c Mon Aug 21 00:51:54 2006 @@ -49,7 +49,7 @@ PDNS_RECORD *QueryResultSet, PVOID *Reserved ) { adns_state astate; - int quflags = 0; + int quflags = 0, i; int adns_error; adns_answer *answer; LPSTR CurrentName; @@ -62,10 +62,18 @@ adns_error = adns_init( &astate, adns_if_noenv | adns_if_noerrprint | - adns_if_noserverwarn, + adns_if_noserverwarn | + (Servers ? adns_if_noserver : 0), 0 ); + if( adns_error != adns_s_ok ) { return DnsIntTranslateAdnsToDNS_STATUS( adns_error ); + } + + if (Servers) { + for( i = 0; i < Servers->AddrCount; i++ ) { + adns_addserver( astate, *((struct in_addr *)&Servers->AddrArray[i]) ); + } } /* Modified: trunk/reactos/lib/3rdparty/adns/src/adns.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/3rdparty/adns/src/adns…
============================================================================== --- trunk/reactos/lib/3rdparty/adns/src/adns.h (original) +++ trunk/reactos/lib/3rdparty/adns/src/adns.h Mon Aug 21 00:51:54 2006 @@ -95,7 +95,8 @@ adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */ adns_if_nosigpipe= 0x0040, /* applic has SIGPIPE set to SIG_IGN, do not protect */ adns_if_checkc_entex= 0x0100, /* do consistency checks on entry/exit to adns funcs */ - adns_if_checkc_freq= 0x0300 /* do consistency checks very frequently (slow!) */ + adns_if_checkc_freq= 0x0300, /* do consistency checks very frequently (slow!) */ + adns_if_noserver= 0x0800, /* do not get dns servers from the environment */ } adns_initflags; typedef enum { @@ -367,6 +368,9 @@ ADNS_API int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile /*0=>stderr*/); +/* ReactOS addition */ +ADNS_API void adns_addserver(adns_state state, struct in_addr server); + ADNS_API int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags, FILE *diagfile /*0=>discard*/, const char *configtext); Modified: trunk/reactos/lib/3rdparty/adns/src/setup.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/3rdparty/adns/src/setu…
============================================================================== --- trunk/reactos/lib/3rdparty/adns/src/setup.c (original) +++ trunk/reactos/lib/3rdparty/adns/src/setup.c Mon Aug 21 00:51:54 2006 @@ -525,7 +525,7 @@ struct protoent *proto; int r; - if (!ads->nservers) { + if (!ads->nservers && !(ads->iflags & adns_if_noserver)) { if (ads->diagfile && ads->iflags & adns_if_debug) fprintf(ads->diagfile,"adns: no nameservers, using localhost\n"); ia.s_addr= htonl(INADDR_LOOPBACK); @@ -589,33 +589,35 @@ ccf_options(ads,"ADNS_RES_OPTIONS",-1,adns_res_options); #ifdef ADNS_JGAA_WIN32 - GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); - strcat(PathBuf,"\\resolv.conf"); - readconfig(ads,PathBuf,1); - GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); - strcat(PathBuf,"\\resolv-adns.conf"); - readconfig(ads,PathBuf,0); - GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); - strcat(PathBuf,"\\System32\\Drivers\\etc\\resolv.conf"); - readconfig(ads,PathBuf,1); - GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); - strcat(PathBuf,"\\System32\\Drivers\\etc\\resolv-adns.conf"); - readconfig(ads,PathBuf,0); - network_info_result = GetNetworkParams(network_info, &network_info_blen); - if (network_info_result != ERROR_SUCCESS){ - switch(network_info_result) { - case ERROR_BUFFER_OVERFLOW: network_err_str = "ERROR_BUFFER_OVERFLOW"; break; - case ERROR_INVALID_PARAMETER: network_err_str = "ERROR_INVALID_PARAMETER"; break; - case ERROR_NO_DATA: network_err_str = "ERROR_NO_DATA"; break; - case ERROR_NOT_SUPPORTED: network_err_str = "ERROR_NOT_SUPPORTED"; break;} - adns__diag(ads,-1,0,"GetNetworkParams() failed with error [%d] %s", - network_info_result,network_err_str); - } - else { - for(pip = &(network_info->DnsServerList); pip; pip = pip->Next) { - addr.s_addr = inet_addr(pip->IpAddress.String); - if ((addr.s_addr != INADDR_ANY) && (addr.s_addr != INADDR_NONE)) - addserver(ads, addr); + if (!(flags & adns_if_noserver)) { + GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); + strcat(PathBuf,"\\resolv.conf"); + readconfig(ads,PathBuf,1); + GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); + strcat(PathBuf,"\\resolv-adns.conf"); + readconfig(ads,PathBuf,0); + GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); + strcat(PathBuf,"\\System32\\Drivers\\etc\\resolv.conf"); + readconfig(ads,PathBuf,1); + GetWindowsDirectory(PathBuf, SECURE_PATH_LEN); + strcat(PathBuf,"\\System32\\Drivers\\etc\\resolv-adns.conf"); + readconfig(ads,PathBuf,0); + network_info_result = GetNetworkParams(network_info, &network_info_blen); + if (network_info_result != ERROR_SUCCESS){ + switch(network_info_result) { + case ERROR_BUFFER_OVERFLOW: network_err_str = "ERROR_BUFFER_OVERFLOW"; break; + case ERROR_INVALID_PARAMETER: network_err_str = "ERROR_INVALID_PARAMETER"; break; + case ERROR_NO_DATA: network_err_str = "ERROR_NO_DATA"; break; + case ERROR_NOT_SUPPORTED: network_err_str = "ERROR_NOT_SUPPORTED"; break;} + adns__diag(ads,-1,0,"GetNetworkParams() failed with error [%d] %s", + network_info_result,network_err_str); + } + else { + for(pip = &(network_info->DnsServerList); pip; pip = pip->Next) { + addr.s_addr = inet_addr(pip->IpAddress.String); + if ((addr.s_addr != INADDR_ANY) && (addr.s_addr != INADDR_NONE)) + addserver(ads, addr); + } } } #else @@ -730,3 +732,8 @@ if (context_r) *context_r= qu->ctx.ext; return qu; } + +/* ReactOS addition */ +void adns_addserver(adns_state ads, struct in_addr addr) { + addserver(ads, addr); +}
18 years, 4 months
1
0
0
0
[ion] 23625: - Remove some FPU deprecated constants and use the new ones. - Deliver APCs on return from context switch with pending kernel APCs.
by ion@svn.reactos.org
Author: ion Date: Mon Aug 21 00:27:03 2006 New Revision: 23625 URL:
http://svn.reactos.org/svn/reactos?rev=23625&view=rev
Log: - Remove some FPU deprecated constants and use the new ones. - Deliver APCs on return from context switch with pending kernel APCs. Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/ke/i386/fpu.c trunk/reactos/ntoskrnl/ke/kthread.c Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h Mon Aug 21 00:27:03 2006 @@ -42,11 +42,6 @@ #define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */ -/* Possible values for KTHREAD's NpxState */ -#define NPX_STATE_INVALID 0x01 -#define NPX_STATE_VALID 0x02 -#define NPX_STATE_DIRTY 0x04 - #define FRAME_EDITED 0xFFF8 #ifndef __ASM__ Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/fpu.c?rev…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/fpu.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/fpu.c Mon Aug 21 00:27:03 2006 @@ -330,10 +330,10 @@ ULONG Cr0; KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - if (Thread->NpxState & NPX_STATE_VALID) + if (Thread->NpxState & NPX_STATE_LOADED) { FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof (FX_SAVE_AREA)); - if (Thread->NpxState & NPX_STATE_DIRTY) + if (Thread->NpxState & NPX_STATE_NOT_LOADED) { ASSERT(KeGetCurrentPrcb()->NpxThread == Thread); @@ -349,7 +349,7 @@ KeGetCurrentPrcb()->NpxThread = NULL; } Ke386SetCr0(Cr0); - Thread->NpxState = NPX_STATE_VALID; + Thread->NpxState = NPX_STATE_LOADED; } } KeLowerIrql(OldIrql); @@ -382,7 +382,7 @@ CurrentThread = KeGetCurrentThread(); ASSERT(CurrentThread != NULL); - CurrentThread->NpxState |= NPX_STATE_DIRTY; + CurrentThread->NpxState |= NPX_STATE_NOT_LOADED; KeLowerIrql(oldIrql); DPRINT("Device not present exception handled!\n"); Modified: trunk/reactos/ntoskrnl/ke/kthread.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/kthread.c?rev=…
============================================================================== --- trunk/reactos/ntoskrnl/ke/kthread.c (original) +++ trunk/reactos/ntoskrnl/ke/kthread.c Mon Aug 21 00:27:03 2006 @@ -210,7 +210,6 @@ DPRINT("Dispatching Thread as blocked\n"); ApcState = KiDispatchThreadNoLock(Waiting); -#if 0 /* Check if we need to deliver APCs */ if (ApcState) { @@ -221,7 +220,6 @@ KiDeliverApc(KernelMode, NULL, NULL); ASSERT(CurrentThread->WaitIrql == 0); } -#endif /* Lower IRQL back to what it was */ KfLowerIrql(CurrentThread->WaitIrql);
18 years, 4 months
1
0
0
0
[ion] 23624: - Don't use EFLAGS to store the Wait IRQL, just push directly, it's cleaner. - Detect if kernel APCs are pending and request APC_LEVEL software interrupt from HAL if they are, returning with the right apc status. - Also update INT21 VDM Descriptor handler when updating LDT descriptor.
by ion@svn.reactos.org
Author: ion Date: Mon Aug 21 00:09:25 2006 New Revision: 23624 URL:
http://svn.reactos.org/svn/reactos?rev=23624&view=rev
Log: - Don't use EFLAGS to store the Wait IRQL, just push directly, it's cleaner. - Detect if kernel APCs are pending and request APC_LEVEL software interrupt from HAL if they are, returning with the right apc status. - Also update INT21 VDM Descriptor handler when updating LDT descriptor. Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S trunk/reactos/ntoskrnl/ke/i386/thread.c Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Mon Aug 21 00:09:25 2006 @@ -115,14 +115,11 @@ .globl @KiSwapContextInternal@0 @KiSwapContextInternal@0: - /* Save WaitIrql APC-bypass in EFLAGS */ - or cl, cl - /* Set the Thread to running */ mov byte ptr [esi+KTHREAD_STATE], Running - /* Save the flags */ - pushf + /* Save the IRQL */ + push ecx /* Save the Exception list */ push [ebx+KPCR_EXCEPTION_LIST] @@ -224,11 +221,34 @@ /* Restore exception list */ pop [ebx+KPCR_EXCEPTION_LIST] - /* Retore EFLAGS */ - popf - - /* Return no APC pending */ + /* Restore IRQL */ + pop ecx + + /* Check if kernel APCs are pending */ + cmp byte ptr [esi+KTHREAD_PENDING_KERNEL_APC], 0 + jnz CheckApc + + /* No APCs, return */ xor eax, eax + ret + +CheckApc: + + /* Check if they're disabled */ + cmp word ptr [esi+KTHREAD_SPECIAL_APC_DISABLE], 0 + jnz ApcReturn + test cl, cl + jz ApcReturn + + /* Request APC Delivery */ + mov cl, APC_LEVEL + call @HalRequestSoftwareInterrupt@4 + or eax, esp + +ApcReturn: + + /* Return with APC pending */ + setz al ret LdtStuff: @@ -240,6 +260,13 @@ mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] mov [ecx+KGDT_LDT+4], eax + /* Write the INT21 handler */ + mov ecx, [ebx+KPCR_IDT] + mov eax, [ebp+KPROCESS_INT21_DESCRIPTOR0] + mov [ecx+0x108], eax + mov eax, [ebp+KPROCESS_INT21_DESCRIPTOR1] + mov [ecx+0x10C], eax + /* Save LDT Selector */ mov eax, KGDT_LDT jmp LoadLdt Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thread.c?…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/thread.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/thread.c Mon Aug 21 00:09:25 2006 @@ -15,7 +15,7 @@ typedef struct _KSHARED_CTXSWITCH_FRAME { PVOID ExceptionList; - ULONG Flags; + KIRQL WaitIrql; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME; @@ -231,7 +231,7 @@ /* And set up the Context Switch Frame */ CtxSwitchFrame->RetEip = KiThreadStartup; - CtxSwitchFrame->Flags = EFLAGS_INTERRUPT_MASK; + CtxSwitchFrame->WaitIrql = APC_LEVEL; CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF; /* Save back the new value of the kernel stack. */
18 years, 4 months
1
0
0
0
[ion] 23623: - Damn copy/paste bug.
by ion@svn.reactos.org
Author: ion Date: Mon Aug 21 00:02:18 2006 New Revision: 23623 URL:
http://svn.reactos.org/svn/reactos?rev=23623&view=rev
Log: - Damn copy/paste bug. Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/device.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/device.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/device.c Mon Aug 21 00:02:18 2006 @@ -1096,7 +1096,7 @@ else { /* It's not, so return failure */ - return STATUS_VOLUME_DISMOUNTED; + Status = STATUS_VOLUME_DISMOUNTED; } } else
18 years, 4 months
1
0
0
0
[ion] 23622: - Fix bug 1764 reported by alexvlas.
by ion@svn.reactos.org
Author: ion Date: Mon Aug 21 00:00:56 2006 New Revision: 23622 URL:
http://svn.reactos.org/svn/reactos?rev=23622&view=rev
Log: - Fix bug 1764 reported by alexvlas. Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c Modified: trunk/reactos/ntoskrnl/io/iomgr/device.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/device.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/device.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/device.c Mon Aug 21 00:00:56 2006 @@ -1067,6 +1067,7 @@ PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; PVPB Vpb; KIRQL OldIrql; + NTSTATUS Status; /* Make sure there's a VPB */ if (!FileSystemDeviceObject->Vpb) return STATUS_INVALID_PARAMETER; @@ -1079,21 +1080,34 @@ /* Make sure this one has a VPB too */ Vpb = DeviceExtension->Vpb; - if (!Vpb) return STATUS_INVALID_PARAMETER; - - /* Make sure that it's mounted */ - if ((!Vpb->ReferenceCount) || (Vpb->Flags & VPB_MOUNTED)) - { - /* It's not, so return failure */ - return STATUS_VOLUME_DISMOUNTED; - } - - /* Return the Disk Device Object */ - *DiskDeviceObject = Vpb->RealDevice; + if (Vpb) + { + /* Make sure that it's mounted */ + if ((Vpb->ReferenceCount) && + (Vpb->Flags & VPB_MOUNTED)) + { + /* Return the Disk Device Object */ + *DiskDeviceObject = Vpb->RealDevice; + + /* Reference it and return success */ + ObReferenceObject(Vpb->RealDevice); + Status = STATUS_SUCCESS; + } + else + { + /* It's not, so return failure */ + return STATUS_VOLUME_DISMOUNTED; + } + } + else + { + /* Fail */ + Status = STATUS_INVALID_PARAMETER; + } /* Release the lock */ IoReleaseVpbSpinLock(OldIrql); - return STATUS_SUCCESS; + return Status; } /*
18 years, 4 months
1
0
0
0
[ion] 23621: - Add support for APC-delivery after context-switch (not yet programmed) - Detect and crash if context switch is done inside a DPC. - Switch kernel stack a bit earlier - Don't switch address space if we're still in the same process, and fix some duplicated code that was mixed up together. - Move LDT setup out-of-line.
by ion@svn.reactos.org
Author: ion Date: Sun Aug 20 23:55:32 2006 New Revision: 23621 URL:
http://svn.reactos.org/svn/reactos?rev=23621&view=rev
Log: - Add support for APC-delivery after context-switch (not yet programmed) - Detect and crash if context switch is done inside a DPC. - Switch kernel stack a bit earlier - Don't switch address space if we're still in the same process, and fix some duplicated code that was mixed up together. - Move LDT setup out-of-line. Modified: trunk/reactos/include/ndk/asm.h trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S trunk/reactos/ntoskrnl/ke/i386/thread.c Modified: trunk/reactos/include/ndk/asm.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/asm.h?rev=2362…
============================================================================== --- trunk/reactos/include/ndk/asm.h (original) +++ trunk/reactos/include/ndk/asm.h Sun Aug 20 23:55:32 2006 @@ -148,6 +148,7 @@ #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C #define KPCR_SYSTEM_CALLS 0x6B8 +#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0x994 // // KGDTENTRY Offsets @@ -383,6 +384,7 @@ #define APC_INDEX_MISMATCH 0x01 #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A #define UNEXPECTED_KERNEL_MODE_TRAP 0x7F +#define ATTEMPTED_SWITCH_FROM_DPC 0xB8 #endif // Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Sun Aug 20 23:55:32 2006 @@ -115,19 +115,30 @@ .globl @KiSwapContextInternal@0 @KiSwapContextInternal@0: + /* Save WaitIrql APC-bypass in EFLAGS */ + or cl, cl + /* Set the Thread to running */ mov byte ptr [esi+KTHREAD_STATE], Running + /* Save the flags */ + pushf + /* Save the Exception list */ push [ebx+KPCR_EXCEPTION_LIST] - + + /* DPC shouldn't be active */ + cmp byte ptr [ebx+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0 + jnz BugCheckDpc + /* Switching, disable interrupts now */ cli - /* Save the initial stack in EAX */ + /* Update kernel stack */ + mov [edi+KTHREAD_KERNEL_STACK], esp + + /* Get stack pointers */ mov eax, [esi+KTHREAD_INITIAL_STACK] - - /* Save the stack limit in ecx */ mov ecx, [esi+KTHREAD_STACK_LIMIT] /* Make space for the NPX Frame */ @@ -137,8 +148,7 @@ mov [ebx+KPCR_INITIAL_STACK], eax mov [ebx+KPCR_STACK_LIMIT], ecx - /* Save the stack pointer in this processors TSS */ - mov ebp, [ebx+KPCR_TSS] + /* FIXME Check and update CR0 */ /* Check if this isn't V86 Mode, so we can bias the Esp0 */ test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM @@ -150,38 +160,22 @@ NoAdjust: /* Set new ESP0 */ - mov [ebp+KTSS_ESP0], eax + mov ecx, [ebx+KPCR_TSS] + mov [ecx+KTSS_ESP0], eax + + /* Switch to new stack */ + mov esp, [esi+KTHREAD_KERNEL_STACK] /* Set TEB pointer */ mov eax, [esi+KTHREAD_TEB] mov [ebx+KPCR_TEB], eax + /* Stack is OK, safe to enable interrupts now */ + sti + /* Check if address space switch is needed */ mov eax, [esi+KTHREAD_APCSTATE_PROCESS] cmp eax, [edi+KTHREAD_APCSTATE_PROCESS] - mov eax, [eax+KPROCESS_DIRECTORY_TABLE_BASE] - - /* Switch stacks */ - mov [edi+KTHREAD_KERNEL_STACK], esp - mov esp, [esi+KTHREAD_KERNEL_STACK] - - jz NoAddressSpaceSwitch - - /* Clear gs */ - xor ecx, ecx - mov gs, cx - - /* Switch address space */ - mov cr3, eax - mov [ebp+KTSS_CR3], eax - -NoAddressSpaceSwitch: - - /* Stack is OK, safe to enable interrupts now */ - sti - - /* Check if address space switch is needed (the result from above is valid) */ - /* If they match, then use the fast-path and skip all this */ jz SameProcess /* Get the new Process. */ @@ -190,31 +184,31 @@ /* Check if we need an LDT */ xor eax, eax cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax - jz NoLdt - - /* Write the LDT Selector */ - mov ecx, [ebx+KPCR_GDT] - mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0] - mov [ecx+KGDT_LDT], eax - mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] - mov [ecx+KGDT_LDT+4], eax - - /* Save LDT Selector */ - mov eax, KGDT_LDT - -NoLdt: - + jnz LdtStuff + +LoadLdt: /* Load LDT */ lldt ax - /* Get the IOPM */ + /* Clear gs */ + xor eax, eax + mov gs, ax + + /* Get the address space */ + mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE] + + /* Get the IOPM and TSS */ + mov ebp, [ebx+KPCR_TSS] mov ecx, [edi+KPROCESS_IOPM_OFFSET] + + /* Switch address space */ + mov [ebp+KTSS_CR3], eax + mov cr3, eax /* Set current IOPM offset in the TSS */ mov [ebp+KTSS_IOMAPBASE], cx SameProcess: - /* Set the TEB */ mov eax, [esi+KTHREAD_TEB] mov ecx, [ebx+KPCR_GDT] @@ -225,12 +219,34 @@ /* Increase context switches */ inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] + //inc dword ptr [esi+KPRC_PRCB_CONTEXT_SWITCHES] /* Restore exception list */ pop [ebx+KPCR_EXCEPTION_LIST] - /* Return */ + /* Retore EFLAGS */ + popf + + /* Return no APC pending */ + xor eax, eax ret + +LdtStuff: + + /* Write the LDT Selector */ + mov ecx, [ebx+KPCR_GDT] + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0] + mov [ecx+KGDT_LDT], eax + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] + mov [ecx+KGDT_LDT+4], eax + + /* Save LDT Selector */ + mov eax, KGDT_LDT + jmp LoadLdt + +BugCheckDpc: + push ATTEMPTED_SWITCH_FROM_DPC + call _KeBugCheck@4 /*++ * KiSwapContext @@ -275,11 +291,11 @@ /* Get the New Thread */ mov esi, edx + /* Save it as Current thread */ + mov fs:[KPCR_CURRENT_THREAD], esi + /* Get the wait IRQL */ movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL] - - /* Save it as Current thread */ - mov fs:[KPCR_CURRENT_THREAD], esi /* Do the swap with the registers correctly setup */ call @KiSwapContextInternal@0 Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thread.c?…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/thread.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/thread.c Sun Aug 20 23:55:32 2006 @@ -15,6 +15,7 @@ typedef struct _KSHARED_CTXSWITCH_FRAME { PVOID ExceptionList; + ULONG Flags; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME; @@ -230,6 +231,7 @@ /* And set up the Context Switch Frame */ CtxSwitchFrame->RetEip = KiThreadStartup; + CtxSwitchFrame->Flags = EFLAGS_INTERRUPT_MASK; CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF; /* Save back the new value of the kernel stack. */
18 years, 4 months
1
0
0
0
[janderwald] 23620: * implement debugger settings for Control Panel Applets for MSVC2005 * in order to use, start the vcproj save sln and restart && enjoy
by janderwald@svn.reactos.org
Author: janderwald Date: Sun Aug 20 23:19:21 2006 New Revision: 23620 URL:
http://svn.reactos.org/svn/reactos?rev=23620&view=rev
Log: * implement debugger settings for Control Panel Applets for MSVC2005 * in order to use, start the vcproj save sln and restart && enjoy Modified: trunk/reactos/tools/rbuild/backend/msvc/vcprojmaker.cpp Modified: trunk/reactos/tools/rbuild/backend/msvc/vcprojmaker.cpp URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/rbuild/backend/msvc/…
============================================================================== --- trunk/reactos/tools/rbuild/backend/msvc/vcprojmaker.cpp (original) +++ trunk/reactos/tools/rbuild/backend/msvc/vcprojmaker.cpp Sun Aug 20 23:19:21 2006 @@ -242,6 +242,14 @@ fprintf ( OUT, "\t\t\tConfigurationType=\"%d\"\r\n", exe ? 1 : dll ? 2 : lib ? 4 : -1 ); fprintf ( OUT, "\t\t\tCharacterSet=\"2\">\r\n" ); + + if ( module_type == ".cpl" && configuration.VSProjectVersion == "8.00") + { + fprintf ( OUT, "\t\t\t<DebugSettings\r\n" ); + fprintf ( OUT, "\t\t\t\tCommand=\"rundll32.exe\"\r\n" ); + fprintf ( OUT, "\t\t\t\tCommandArguments=\" shell32, Control_RunDLL $(TargetPath),@\"\r\n" ); + fprintf ( OUT, "\t\t\t/>" ); + } fprintf ( OUT, "\t\t\t<Tool\r\n" ); fprintf ( OUT, "\t\t\t\tName=\"VCCLCompilerTool\"\r\n" );
18 years, 4 months
1
0
0
0
[ion] 23619: - Some micro-architectural changes and cleanups.
by ion@svn.reactos.org
Author: ion Date: Sun Aug 20 23:08:57 2006 New Revision: 23619 URL:
http://svn.reactos.org/svn/reactos?rev=23619&view=rev
Log: - Some micro-architectural changes and cleanups. Modified: trunk/reactos/include/ndk/asm.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S trunk/reactos/ntoskrnl/ke/i386/thread.c trunk/reactos/ntoskrnl/ke/kthread.c Modified: trunk/reactos/include/ndk/asm.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/asm.h?rev=2361…
============================================================================== --- trunk/reactos/include/ndk/asm.h (original) +++ trunk/reactos/include/ndk/asm.h Sun Aug 20 23:08:57 2006 @@ -90,17 +90,20 @@ #define KTHREAD_STACK_LIMIT 0x1C #define KTHREAD_TEB 0x74 #define KTHREAD_KERNEL_STACK 0x20 +#define KTHREAD_STATE 0x4C #define KTHREAD_NPX_STATE 0x4D -#define KTHREAD_STATE 0x4C #define KTHREAD_ALERTED 0x5E #define KTHREAD_APCSTATE_PROCESS 0x28 + 0x10 #define KTHREAD_PENDING_USER_APC 0x28 + 0x16 #define KTHREAD_PENDING_KERNEL_APC 0x28 + 0x15 #define KTHREAD_CONTEXT_SWITCHES 0x48 #define KTHREAD_WAIT_IRQL 0x4E +#define KTHREAD_NEXT_PROCESSOR 0x40 +#define KTHREAD_SWAP_BUSY 0x5D #define KTHREAD_SERVICE_TABLE 0x118 #define KTHREAD_PREVIOUS_MODE 0xD7 #define KTHREAD_COMBINED_APC_DISABLE 0x70 +#define KTHREAD_SPECIAL_APC_DISABLE 0x72 #define KTHREAD_LARGE_STACK 0x107 #define KTHREAD_TRAP_FRAME 0x110 #define KTHREAD_CALLBACK_STACK 0x114 @@ -113,7 +116,10 @@ #define KPROCESS_DIRECTORY_TABLE_BASE 0x18 #define KPROCESS_LDT_DESCRIPTOR0 0x20 #define KPROCESS_LDT_DESCRIPTOR1 0x24 +#define KPROCESS_INT21_DESCRIPTOR0 0x28 +#define KPROCESS_INT21_DESCRIPTOR1 0x2C #define KPROCESS_IOPM_OFFSET 0x30 +#define KPROCESS_ACTIVE_PROCESSORS 0x34 // // KPCR Offsets @@ -121,12 +127,15 @@ #define KPCR_EXCEPTION_LIST 0x0 #define KPCR_INITIAL_STACK 0x4 #define KPCR_STACK_LIMIT 0x8 +#define KPCR_PERF_GLOBAL_GROUP_MASK 0x8 +#define KPCR_CONTEXT_SWITCHES 0x10 #define KPCR_SET_MEMBER_COPY 0x14 #define KPCR_TEB 0x18 #define KPCR_SELF 0x1C #define KPCR_PRCB 0x20 #define KPCR_IRQL 0x24 #define KPCR_KD_VERSION_BLOCK 0x34 +#define KPCR_IDT 0x38 #define KPCR_GDT 0x3C #define KPCR_TSS 0x40 #define KPCR_SET_MEMBER 0x48 @@ -134,6 +143,7 @@ #define KPCR_CURRENT_THREAD 0x124 #define KPCR_PROCESSOR_NUMBER 0x130 #define KPCR_PRCB_SET_MEMBER 0x134 +#define KPCR_PRCB_CPU_TYPE 0x138 #define KPCR_NPX_THREAD 0x640 #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h Sun Aug 20 23:08:57 2006 @@ -122,7 +122,7 @@ /* Thread Scheduler Functions */ /* Readies a Thread for Execution. */ -VOID +BOOLEAN STDCALL KiDispatchThreadNoLock(ULONG NewThreadStatus); @@ -148,7 +148,10 @@ NTSTATUS FASTCALL -KiSwapContext(PKTHREAD NewThread); +KiSwapContext( + IN PKTHREAD CurrentThread, + IN PKTHREAD NewThread +); VOID STDCALL Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S (original) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Sun Aug 20 23:08:57 2006 @@ -115,9 +115,6 @@ .globl @KiSwapContextInternal@0 @KiSwapContextInternal@0: - /* Get the PCR. It's faster to use ebx+offset then fs:offset */ - mov ebx, [fs:KPCR_SELF] - /* Set the Thread to running */ mov byte ptr [esi+KTHREAD_STATE], Running @@ -140,24 +137,6 @@ mov [ebx+KPCR_INITIAL_STACK], eax mov [ebx+KPCR_STACK_LIMIT], ecx -#ifdef CONFIG_SMP - /* Save FPU state if the thread has used it. */ - mov ecx, [edi+KTHREAD_INITIAL_STACK] - sub ecx, NPX_FRAME_LENGTH - mov dword ptr [ebx+KPCR_NPX_THREAD], 0 - test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY - jz 3f - cmp dword ptr _KeI386FxsrPresent, 0 - je 1f - fxsave [ecx] - jmp 2f -1: - fnsave [ecx] -2: - mov byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_VALID -3: -#endif /* CONFIG_SMP */ - /* Save the stack pointer in this processors TSS */ mov ebp, [ebx+KPCR_TSS] @@ -169,9 +148,6 @@ sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS NoAdjust: - - /* Save it */ - push [ebp+KTSS_ESP0] /* Set new ESP0 */ mov [ebp+KTSS_ESP0], eax @@ -250,28 +226,11 @@ /* Increase context switches */ inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] - /* Set TS in cr0 to catch FPU code and load the FPU state when needed */ -#ifndef CONFIG_SMP - cmp [ebx+KPCR_NPX_THREAD], esi - je 4f -#endif /* !CONFIG_SMP */ - mov eax, cr0 - or eax, X86_CR0_TS - mov cr0, eax -4: - - /* Restore ESP0 */ - pop [ebp+KTSS_ESP0] - /* Restore exception list */ pop [ebx+KPCR_EXCEPTION_LIST] /* Return */ -#ifdef CONFIG_SMP - mov ecx, offset _DispatcherDatabaseLock - call @KefReleaseSpinLockFromDpcLevel@4 -#endif - ret + ret /*++ * KiSwapContext @@ -294,37 +253,43 @@ * another thread switches to IT. * *--*/ -.globl @KiSwapContext@4 -@KiSwapContext@4: +.globl @KiSwapContext@8 +@KiSwapContext@8: /* Note, we CANNOT touch ebp */ /* Save 4 registers */ sub esp, 4 * 4 - + /* Save all the non-volatile ones */ mov [esp+12], ebx mov [esp+8], esi mov [esp+4], edi mov [esp+0], ebp - + + /* Get the current KPCR */ + mov ebx, fs:[KPCR_SELF] + /* Get the Current Thread */ - mov edi, fs:[KPCR_CURRENT_THREAD] - + mov edi, ecx + /* Get the New Thread */ - mov esi, ecx - + mov esi, edx + + /* Get the wait IRQL */ + movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL] + /* Save it as Current thread */ mov fs:[KPCR_CURRENT_THREAD], esi - + /* Do the swap with the registers correctly setup */ call @KiSwapContextInternal@0 - + /* Return the registers */ mov ebp, [esp+0] mov edi, [esp+4] mov esi, [esp+8] mov ebx, [esp+12] - + /* Clean stack */ add esp, 4 * 4 ret Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thread.c?…
============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/thread.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/thread.c Sun Aug 20 23:08:57 2006 @@ -14,7 +14,6 @@ typedef struct _KSHARED_CTXSWITCH_FRAME { - ULONG Esp0; PVOID ExceptionList; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME; @@ -94,7 +93,6 @@ /* Setup the Fx Area */ FxSaveArea = &InitFrame->FxSaveArea; - Thread->NpxState = NPX_STATE_INVALID; /* Check if we support FXsr */ if (KeI386FxsrPresent) @@ -108,7 +106,7 @@ FxSaveFormat->TagWord = 0; FxSaveFormat->ErrorOffset = 0; FxSaveFormat->ErrorSelector = 0; - FxSaveFormat->DataOffset =0; + FxSaveFormat->DataOffset = 0; FxSaveFormat->DataSelector = 0; FxSaveFormat->MXCsr = 0x1F80; } @@ -137,7 +135,7 @@ CONTEXT_FLOATING_POINT; /* Set the Thread's NPX State */ - Thread->NpxState = NPX_STATE_INVALID; + Thread->NpxState = NPX_STATE_NOT_LOADED; Thread->DispatcherHeader.NpxIrql = PASSIVE_LEVEL; } else @@ -232,9 +230,6 @@ /* And set up the Context Switch Frame */ CtxSwitchFrame->RetEip = KiThreadStartup; - CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack - - sizeof(FX_SAVE_AREA) - - 0x10; CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF; /* Save back the new value of the kernel stack. */ Modified: trunk/reactos/ntoskrnl/ke/kthread.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/kthread.c?rev=…
============================================================================== --- trunk/reactos/ntoskrnl/ke/kthread.c (original) +++ trunk/reactos/ntoskrnl/ke/kthread.c Sun Aug 20 23:08:57 2006 @@ -128,7 +128,7 @@ return(NULL); } -VOID +BOOLEAN STDCALL KiDispatchThreadNoLock(ULONG NewThreadStatus) { @@ -136,6 +136,7 @@ PKTHREAD Candidate; ULONG Affinity; PKTHREAD CurrentThread = KeGetCurrentThread(); + BOOLEAN ApcState; DPRINT("KiDispatchThreadNoLock() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(), CurrentThread, NewThreadStatus, CurrentThread->State); @@ -158,7 +159,7 @@ Candidate->State = Running; KeReleaseDispatcherDatabaseLockFromDpcLevel(); - return; + return FALSE; } if (Candidate != NULL) { @@ -186,15 +187,16 @@ MmUpdatePageDir((PEPROCESS)PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS)); /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */ - DPRINT("You are : %x, swapping to: %x\n", OldThread, CurrentThread); - KiSwapContext(CurrentThread); + DPRINT("You are : %x, swapping to: %x.\n", OldThread, CurrentThread); + ApcState = KiSwapContext(OldThread, CurrentThread); DPRINT("You are : %x, swapped from: %x\n", OldThread, CurrentThread); - return; + return ApcState; } } DPRINT1("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber()); KEBUGCHECK(0); + return FALSE; } NTSTATUS @@ -202,13 +204,26 @@ KiSwapThread(VOID) { PKTHREAD CurrentThread = KeGetCurrentThread(); + BOOLEAN ApcState; /* Find a new thread to run */ DPRINT("Dispatching Thread as blocked\n"); - KiDispatchThreadNoLock(Waiting); - - /* Lower IRQL back */ - DPRINT("Lowering IRQL \n"); + ApcState = KiDispatchThreadNoLock(Waiting); + +#if 0 + /* Check if we need to deliver APCs */ + if (ApcState) + { + /* Lower to APC_LEVEL */ + KeLowerIrql(APC_LEVEL); + + /* Deliver APCs */ + KiDeliverApc(KernelMode, NULL, NULL); + ASSERT(CurrentThread->WaitIrql == 0); + } +#endif + + /* Lower IRQL back to what it was */ KfLowerIrql(CurrentThread->WaitIrql); /* Return the wait status */
18 years, 4 months
1
0
0
0
[turner] 23618: add a batch file for basic qemu settings and a batch file for basic vm player settings
by turner@svn.reactos.org
Author: turner Date: Sun Aug 20 22:01:59 2006 New Revision: 23618 URL:
http://svn.reactos.org/svn/reactos?rev=23618&view=rev
Log: add a batch file for basic qemu settings and a batch file for basic vm player settings Added: trunk/tools/ReactOS.vmx trunk/tools/boot.bat Added: trunk/tools/ReactOS.vmx URL:
http://svn.reactos.org/svn/reactos/trunk/tools/ReactOS.vmx?rev=23618&view=a…
============================================================================== --- trunk/tools/ReactOS.vmx (added) +++ trunk/tools/ReactOS.vmx Sun Aug 20 22:01:59 2006 @@ -1,0 +1,56 @@ +config.version = "8" +virtualHW.version = "3" +memsize = "128" +ide0:0.present = "TRUE" +ide0:0.fileName = "ReactOS.vmdk" +floppy0.present = "FALSE" +floppy0.startConnected = "FALSE" +floppy0.fileName = "" +Ethernet0.present = "TRUE" +displayName = "ReactOS" +guestOS = "winxppro" +priority.grabbed = "normal" +priority.ungrabbed = "normal" +powerType.powerOff = "hard" +powerType.powerOn = "hard" +powerType.suspend = "hard" +powerType.reset = "hard" + +sound.present = "FALSE" +sound.virtualDev = "es1371" + +Ethernet0.addressType = "generated" +uuid.location = "56 4d f3 82 2e e6 c2 57-a8 3d d3 58 af 7c 4c 8b" +uuid.bios = "56 4d f3 82 2e e6 c2 57-a8 3d d3 58 af 7c 4c 8b" +ethernet0.generatedAddress = "00:0c:29:7c:4c:8b" +ethernet0.generatedAddressOffset = "0" + +tools.remindInstall = "TRUE" + +### CDROM ### +ide1:0.startConnected = "FALSE" +ide1:0.present = "FALSE" +ide1:0.fileName = "ReactOS.iso" +ide1:0.deviceType = "cdrom-image" + +ide0:0.deviceType = "disk" +usb.present = "FALSE" + +ide0:0.redo = "" + +nvram = "ReactOS.nvram" + +floppy0.fileType = "file" + +checkpoint.vmState = "" + +ethernet0.connectionType = "nat" + +serial0.present = "TRUE" +serial0.fileName = "debug.txt" +serial0.fileType = "file" +serial0.tryNoRxLoss = "FALSE" +serial0.yieldOnMsrRead = "TRUE" +serial0.startConnected = "TRUE" + +uuid.action = "create" Added: trunk/tools/boot.bat URL:
http://svn.reactos.org/svn/reactos/trunk/tools/boot.bat?rev=23618&view=auto
============================================================================== --- trunk/tools/boot.bat (added) +++ trunk/tools/boot.bat Sun Aug 20 22:01:59 2006 @@ -1,0 +1,2 @@ +qemu -boot c -m 128 -L . c.img +REM qemu -boot d -m 128 -L . c.img -cdrom ReactOS.iso
18 years, 4 months
1
0
0
0
← Newer
1
...
20
21
22
23
24
25
26
...
45
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Results per page:
10
25
50
100
200