From 3f0a7fb997a71b15e054839544f066cf77e356f9 Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Mon, 18 Sep 2006 22:25:00 +0000 Subject: [PATCH 01/54] - Add a cute custom control to sysdm allowing dialogs to display hyperlink style text which can open web pages and run exe's. - see the general page, and the user account dialog for examples. svn path=/trunk/; revision=24205 --- reactos/dll/cpl/sysdm/custclicklink.c | 209 ++++++++++++++++++++++++++ reactos/dll/cpl/sysdm/en.rc | 22 +-- reactos/dll/cpl/sysdm/general.c | 19 ++- reactos/dll/cpl/sysdm/precomp.h | 2 + reactos/dll/cpl/sysdm/resource.h | 7 +- reactos/dll/cpl/sysdm/sysdm.rbuild | 1 + reactos/dll/cpl/sysdm/userprofile.c | 7 + 7 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 reactos/dll/cpl/sysdm/custclicklink.c diff --git a/reactos/dll/cpl/sysdm/custclicklink.c b/reactos/dll/cpl/sysdm/custclicklink.c new file mode 100644 index 00000000000..8622d7f8d15 --- /dev/null +++ b/reactos/dll/cpl/sysdm/custclicklink.c @@ -0,0 +1,209 @@ +/* + * PROJECT: ReactOS System Control Panel Applet + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/cpl/sysdm/custclicklink.c + * PURPOSE: Subclass static control to link to apps + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +#define LINK_COLOR RGB(0,0,128) +#define MAX_PARAMS 256 + +typedef struct _LINKCTL +{ + HWND hSelf; + WNDPROC OldProc; + TCHAR szApp[MAX_PATH]; + TCHAR szParams[MAX_PARAMS]; + HFONT hFont; + BOOL bClicked; +} LINKCTL, *PLINKCTL; + + + +static VOID +DoLButtonUp(PLINKCTL pLink, LPARAM lParam) +{ + ReleaseCapture(); + if (pLink->bClicked) + { + POINT pt; + RECT rc; + + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + ClientToScreen(pLink->hSelf, &pt); + GetWindowRect(pLink->hSelf, &rc); + if (PtInRect(&rc, pt)) + { + ShellExecute(NULL, + _T("open"), + pLink->szApp, + pLink->szParams, + NULL, + SW_SHOWNORMAL); + } + + pLink->bClicked = FALSE; + } +} + + +static VOID +DoPaint(PLINKCTL pLink, HDC hdc) +{ + TCHAR szText[MAX_PATH]; + DWORD WinStyle, DrawStyle; + RECT rc; + HANDLE hOld; + + WinStyle = GetWindowLongPtr(pLink->hSelf, GWL_STYLE); + DrawStyle = DT_SINGLELINE; + + if (WinStyle & SS_CENTER) + DrawStyle |= DT_CENTER; + if (WinStyle & SS_RIGHT) + DrawStyle |= DT_RIGHT; + if (WinStyle & SS_CENTERIMAGE) + DrawStyle |= DT_VCENTER; + + SetTextColor(hdc, LINK_COLOR); + SetBkMode(hdc, TRANSPARENT); + hOld = SelectObject(hdc, pLink->hFont); + SetBkColor(hdc, GetSysColor(COLOR_3DFACE)); + + GetClientRect(pLink->hSelf, &rc); + + GetWindowText(pLink->hSelf, szText, sizeof(szText)); + DrawText(hdc, szText, -1, &rc, DrawStyle); + +} + + +static LRESULT CALLBACK +LinkCtlWndProc(HWND hwnd, + UINT msg, + WPARAM wParam, + LPARAM lParam) +{ + PLINKCTL pLink = (PLINKCTL)GetWindowLongPtr(hwnd, GWL_USERDATA); + WNDPROC oldproc = pLink->OldProc; + + switch(msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc; + + hdc = BeginPaint(hwnd, &ps); + DoPaint(pLink, hdc); + EndPaint(hwnd, &ps); + return 0; + } + + case WM_SETCURSOR: + { + HCURSOR hCur = LoadCursor(NULL, IDC_HAND); + SetCursor(hCur); + return TRUE; + } + + case WM_SETFONT: + { + LOGFONT LogFont; + HFONT hOldFont; + + hOldFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + GetObject(hOldFont, sizeof(LogFont), &LogFont); + LogFont.lfUnderline = TRUE; + if (pLink->hFont) DeleteObject(hwnd); + pLink->hFont = CreateFontIndirect(&LogFont); + + CallWindowProc(pLink->OldProc, hwnd, msg, wParam, lParam); + + if (LOWORD(lParam)) + { + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); + } + return 0; + } + + case WM_NCHITTEST: + return HTCLIENT; + + case WM_LBUTTONDOWN: + { + SetFocus(hwnd); + SetCapture(hwnd); + pLink->bClicked = TRUE; + } + break; + + case WM_LBUTTONUP: + { + DoLButtonUp(pLink, lParam); + } + break; + + case WM_NCDESTROY: + { + HeapFree(GetProcessHeap(), + 0, + pLink); + } + break; + } + + return CallWindowProc(oldproc, + hwnd, + msg, + wParam, + lParam); +} + + +BOOL +TextToLink(HWND hwnd, + LPTSTR lpApp, + LPTSTR lpParams) +{ + PLINKCTL pLink; + HFONT hFont; + + /* error checking */ + if (lstrlen(lpApp) >= (MAX_PATH - 1) || + lstrlen(lpParams) >= (MAX_PARAMS -1)) + { + return FALSE; + } + + pLink = (PLINKCTL)HeapAlloc(GetProcessHeap(), + 0, + sizeof(LINKCTL)); + if (pLink == NULL) + return FALSE; + + pLink->hSelf = hwnd; + lstrcpyn(pLink->szApp, lpApp, MAX_PATH); + lstrcpyn(pLink->szParams, lpParams, MAX_PARAMS); + pLink->bClicked = FALSE; + + hFont=(HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + + + pLink->OldProc = (WNDPROC)SetWindowLongPtr(hwnd, + GWL_WNDPROC, + (LONG_PTR)LinkCtlWndProc); + SetWindowLongPtr(hwnd, + GWL_USERDATA, + (LONG_PTR)pLink); + + SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, 0); + + return TRUE; +} diff --git a/reactos/dll/cpl/sysdm/en.rc b/reactos/dll/cpl/sysdm/en.rc index 109506f89b1..7c48d116693 100644 --- a/reactos/dll/cpl/sysdm/en.rc +++ b/reactos/dll/cpl/sysdm/en.rc @@ -15,7 +15,8 @@ BEGIN LTEXT "", IDC_PROCESSOR, 130, 153, 118, 9 LTEXT "", IDC_PROCESSORSPEED, 130, 162, 118, 9 LTEXT "", IDC_SYSTEMMEMORY, 130, 171, 118, 9 - PUSHBUTTON "View licence...", IDC_LICENCE, 90, 199, 78, 13 + LTEXT "Visit the ReactOS Homepage", IDC_ROSHOMEPAGE_LINK, 20, 200, 93, 8 + PUSHBUTTON "View licence...", IDC_LICENCE, 170, 199, 78, 13 END @@ -132,9 +133,9 @@ END IDD_USERPROFILE DIALOGEX 0, 0, 256, 218 -STYLE DS_FIXEDSYS | DS_MODALFRAME | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +STYLE DS_FIXEDSYS | DS_MODALFRAME | DS_CONTEXTHELP | DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "User Profiles" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 +FONT 8, "MS Shell Dlg" BEGIN ICON IDI_USERPROF, IDC_STATIC, 6, 11, 16, 16, SS_ICON LTEXT "User profiles contain desktop settings and other information related to your login. A different profile can be created on each computer you use, or you can select a roaming profile that is the same on every computer you use.", @@ -142,15 +143,16 @@ BEGIN LTEXT "Profiles stored on this computer:", IDC_STATIC, 16, 51, 204, 9 CONTROL "", IDC_USERPROFILE_LIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | WS_BORDER | WS_TABSTOP, 6, 66, 244, 85, WS_EX_CLIENTEDGE - PUSHBUTTON "Change Type...", IDC_USERPROFILE_CHANGE, 134, 156, 62, 13 + PUSHBUTTON "Change Type", IDC_USERPROFILE_CHANGE, 90, 156, 50, 13 + PUSHBUTTON "Delete", IDC_USERPROFILE_DELETE, 145, 156, 50, 13 + PUSHBUTTON "Copy To", IDC_USERPROFILE_COPY, 200, 156, 50, 13 - LTEXT "To create new user accounts, open ", IDC_STATIC, 10, 175, 116, 9 - // FIXME: needs custom control writing - //CONTROL "", IDC_CUST_LINK, "LinkCtlProc", WS_CHILD | VS_VISIBLE | WS_TABSTOP, 127, 175, 60, 9 - LTEXT "in Control Panel.", IDC_STATIC, 184, 175, 64, 9 + LTEXT "To create new user accounts, open ", IDC_STATIC, 7, 175, 116, 8 + LTEXT "User Accounts", IDC_USERACCOUNT_LINK, 123, 175, 48, 8 + LTEXT "in Control Panel.", IDC_STATIC, 173, 175, 64, 8 - DEFPUSHBUTTON "OK", IDOK, 134, 197, 54, 13 - PUSHBUTTON "Cancel", IDCANCEL, 196, 197, 54, 13 + DEFPUSHBUTTON "OK", IDOK, 134, 200, 54, 13 + PUSHBUTTON "Cancel", IDCANCEL, 196, 200, 54, 13 END diff --git a/reactos/dll/cpl/sysdm/general.c b/reactos/dll/cpl/sysdm/general.c index 84d66a745ff..26e56081f9c 100644 --- a/reactos/dll/cpl/sysdm/general.c +++ b/reactos/dll/cpl/sysdm/general.c @@ -95,6 +95,12 @@ GeneralPageProc(HWND hwndDlg, { case WM_INITDIALOG: { + HWND hLink = GetDlgItem(hwndDlg, IDC_ROSHOMEPAGE_LINK); + + TextToLink(hLink, + _T("http://www.reactos.org"), + NULL); + InitImageInfo(&ImgInfo); GetSystemInformation(hwndDlg); } @@ -108,6 +114,7 @@ GeneralPageProc(HWND hwndDlg, MAKEINTRESOURCE(IDD_LICENCE), hwndDlg, LicenceDlgProc); + return TRUE; } } @@ -129,21 +136,21 @@ GeneralPageProc(HWND hwndDlg, if (hdcMem != NULL) { SelectObject(hdcMem, ImgInfo.hBitmap); - BitBlt(lpDrawItem->hDC, - left, + BitBlt(lpDrawItem->hDC, + left, lpDrawItem->rcItem.top, lpDrawItem->rcItem.right - lpDrawItem->rcItem.left, lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, - hdcMem, - 0, - 0, + hdcMem, + 0, + 0, SRCCOPY); DeleteDC(hdcMem); } } return TRUE; } - + } return FALSE; diff --git a/reactos/dll/cpl/sysdm/precomp.h b/reactos/dll/cpl/sysdm/precomp.h index 0e3a8fb9207..3b5b31b591d 100644 --- a/reactos/dll/cpl/sysdm/precomp.h +++ b/reactos/dll/cpl/sysdm/precomp.h @@ -39,6 +39,8 @@ INT_PTR CALLBACK StartRecDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM INT_PTR CALLBACK VirtMemDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK LicenceDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +BOOL TextToLink(HWND hwnd, LPTSTR lpApp, LPTSTR lpParams); + typedef struct _PAGEFILE { TCHAR szDrive[3]; diff --git a/reactos/dll/cpl/sysdm/resource.h b/reactos/dll/cpl/sysdm/resource.h index 8b402c260f0..c1eb5ae4798 100644 --- a/reactos/dll/cpl/sysdm/resource.h +++ b/reactos/dll/cpl/sysdm/resource.h @@ -21,8 +21,9 @@ #define IDC_PROCESSOR 102 #define IDC_PROCESSORSPEED 103 #define IDC_SYSTEMMEMORY 104 -#define IDC_LICENCE 105 +#define IDC_LICENCE 105 #define IDC_ROSIMG 106 +#define IDC_ROSHOMEPAGE_LINK 107 /* propsheet - computer name */ @@ -56,7 +57,9 @@ #define IDD_USERPROFILE 500 #define IDC_USERPROFILE_LIST 501 #define IDC_USERPROFILE_CHANGE 503 -#define IDC_CUST_LINK 504 +#define IDC_USERPROFILE_DELETE 504 +#define IDC_USERPROFILE_COPY 505 +#define IDC_USERACCOUNT_LINK 506 /* environment variables */ diff --git a/reactos/dll/cpl/sysdm/sysdm.rbuild b/reactos/dll/cpl/sysdm/sysdm.rbuild index eb574d67635..40fd8dc0972 100644 --- a/reactos/dll/cpl/sysdm/sysdm.rbuild +++ b/reactos/dll/cpl/sysdm/sysdm.rbuild @@ -20,6 +20,7 @@ shell32 advanced.c computer.c + custclicklink.c environment.c general.c hardprof.c diff --git a/reactos/dll/cpl/sysdm/userprofile.c b/reactos/dll/cpl/sysdm/userprofile.c index c1ed603c542..da0fc8a833b 100644 --- a/reactos/dll/cpl/sysdm/userprofile.c +++ b/reactos/dll/cpl/sysdm/userprofile.c @@ -20,10 +20,17 @@ UserProfileDlgProc(HWND hwndDlg, UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(hwndDlg); + switch(uMsg) { case WM_INITDIALOG: { + HWND hLink = GetDlgItem(hwndDlg, IDC_USERACCOUNT_LINK); + + TextToLink(hLink, + _T("rundll32.exe"), + _T("shell32.dll, Control_RunDLL nusrmgr.cpl")); + MessageBox(hwndDlg, _T("Dialog not yet implemented!"), NULL, 0); } break; From f8fcca6f0647aa66ed403a1e2dba96a6765efbac Mon Sep 17 00:00:00 2001 From: James Tabor Date: Mon, 18 Sep 2006 23:37:22 +0000 Subject: [PATCH 02/54] Kill some warnings. svn path=/trunk/; revision=24208 --- reactos/tools/mkhive/cmi.c | 2 +- reactos/tools/mkhive/registry.c | 2 +- reactos/tools/mkhive/rtl.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reactos/tools/mkhive/cmi.c b/reactos/tools/mkhive/cmi.c index b84c1d25776..cb79a18c3b5 100644 --- a/reactos/tools/mkhive/cmi.c +++ b/reactos/tools/mkhive/cmi.c @@ -31,7 +31,7 @@ CmpAllocate( IN SIZE_T Size, IN BOOLEAN Paged) { - return malloc(Size); + return (PVOID) malloc(Size); } static VOID diff --git a/reactos/tools/mkhive/registry.c b/reactos/tools/mkhive/registry.c index 9a7aca0243a..fcae34a3602 100644 --- a/reactos/tools/mkhive/registry.c +++ b/reactos/tools/mkhive/registry.c @@ -122,7 +122,7 @@ RegpOpenOrCreateKey( LocalKeyName = (PWSTR)KeyName; for (;;) { - End = wcschr(LocalKeyName, '\\'); + End = (PWSTR) wcschr(LocalKeyName, '\\'); if (End) { KeyString.Buffer = LocalKeyName; diff --git a/reactos/tools/mkhive/rtl.c b/reactos/tools/mkhive/rtl.c index 4ff2be3dd50..08cdeb71deb 100644 --- a/reactos/tools/mkhive/rtl.c +++ b/reactos/tools/mkhive/rtl.c @@ -84,7 +84,7 @@ RtlAnsiStringToUnicodeString( if (AllocateDestinationString) { UniDest->MaximumLength = (USHORT)Length + sizeof(WCHAR); - UniDest->Buffer = malloc(UniDest->MaximumLength); + UniDest->Buffer = (PWSTR) malloc(UniDest->MaximumLength); if (!UniDest->Buffer) return STATUS_NO_MEMORY; } @@ -131,7 +131,7 @@ ExAllocatePool( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes) { - return malloc(NumberOfBytes); + return (PVOID) malloc(NumberOfBytes); } VOID NTAPI From 14d0c5f34afdf2f9e38340d536741baa3dd55e5f Mon Sep 17 00:00:00 2001 From: Andrew Munger Date: Tue, 19 Sep 2006 04:25:14 +0000 Subject: [PATCH 03/54] Initialize h_alises with a length 1 array containing a terminating null as specified. Patch by arty. (Fixes ncftp connection) svn path=/trunk/; revision=24209 --- reactos/dll/win32/ws2_32/misc/ns.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/reactos/dll/win32/ws2_32/misc/ns.c b/reactos/dll/win32/ws2_32/misc/ns.c index 9e166e65ef8..f6103b09c14 100644 --- a/reactos/dll/win32/ws2_32/misc/ns.c +++ b/reactos/dll/win32/ws2_32/misc/ns.c @@ -488,7 +488,10 @@ void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr) name, MAX_HOSTNAME_LEN); - he->h_aliases = 0; + if( !he->h_aliases ) { + he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *)); + he->h_aliases[0] = 0; + } he->h_addrtype = AF_INET; he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr); @@ -518,12 +521,20 @@ void free_hostent(struct hostent *he) { if(he) { + char *next = 0; HFREE(he->h_name); - char *next = he->h_aliases[0]; - while(next) { HFREE(next); next++; } - next = he->h_addr_list[0]; - while(next) { HFREE(next); next++; } + if(he->h_aliases) + { + next = he->h_aliases[0]; + while(next) { HFREE(next); next++; } + } + if(he->h_addr_list) + { + next = he->h_addr_list[0]; + while(next) { HFREE(next); next++; } + } HFREE(he->h_addr_list); + HFREE(he->h_aliases); HFREE(he); } } From d0e354f6c147be64206a447adf0c82bd02081248 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Wed, 20 Sep 2006 09:27:59 +0000 Subject: [PATCH 04/54] Fix warnings svn path=/trunk/; revision=24211 --- reactos/dll/cpl/sysdm/virtmem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reactos/dll/cpl/sysdm/virtmem.c b/reactos/dll/cpl/sysdm/virtmem.c index ac6acda2f3c..43563f6e737 100644 --- a/reactos/dll/cpl/sysdm/virtmem.c +++ b/reactos/dll/cpl/sysdm/virtmem.c @@ -138,7 +138,7 @@ ParseMemSettings(PVIRTMEM pVirtMem) Item.mask = LVIF_TEXT; Item.iItem = ListView_GetItemCount(pVirtMem->hListView); Item.pszText = szDrive; - ListView_InsertItem(pVirtMem->hListView, &Item); + (void)ListView_InsertItem(pVirtMem->hListView, &Item); /* set a volume label if there is one */ if (GetVolumeInformation(DrivePtr, @@ -158,7 +158,7 @@ ParseMemSettings(PVIRTMEM pVirtMem) Item.iSubItem = 1; Item.pszText = szVol; - ListView_InsertItem(pVirtMem->hListView, &Item); + (void)ListView_InsertItem(pVirtMem->hListView, &Item); } } @@ -170,7 +170,7 @@ ParseMemSettings(PVIRTMEM pVirtMem) Item.iSubItem = 2; Item.pszText = szSize; - ListView_InsertItem(pVirtMem->hListView, &Item); + (void)ListView_InsertItem(pVirtMem->hListView, &Item); } PgCnt++; From 8e90ccee4d3d613333c848fad1b855571ad0d33b Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Wed, 20 Sep 2006 09:54:00 +0000 Subject: [PATCH 05/54] Some tchar fixes svn path=/trunk/; revision=24212 --- reactos/dll/cpl/sysdm/precomp.h | 3 ++- reactos/dll/cpl/sysdm/sysdm.rbuild | 5 ++--- reactos/dll/cpl/sysdm/virtmem.c | 14 ++++++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/reactos/dll/cpl/sysdm/precomp.h b/reactos/dll/cpl/sysdm/precomp.h index 3b5b31b591d..9a8762c4a95 100644 --- a/reactos/dll/cpl/sysdm/precomp.h +++ b/reactos/dll/cpl/sysdm/precomp.h @@ -4,9 +4,10 @@ #include #include #include +#include #include #include -#include //shellexecute +#include #include "resource.h" #define NUM_APPLETS (1) diff --git a/reactos/dll/cpl/sysdm/sysdm.rbuild b/reactos/dll/cpl/sysdm/sysdm.rbuild index 40fd8dc0972..0bb5bea4b06 100644 --- a/reactos/dll/cpl/sysdm/sysdm.rbuild +++ b/reactos/dll/cpl/sysdm/sysdm.rbuild @@ -1,8 +1,6 @@ - + . - - 0x600 @@ -31,4 +29,5 @@ userprofile.c virtmem.c sysdm.rc + precomp.h diff --git a/reactos/dll/cpl/sysdm/virtmem.c b/reactos/dll/cpl/sysdm/virtmem.c index 43563f6e737..08da8ae65bc 100644 --- a/reactos/dll/cpl/sysdm/virtmem.c +++ b/reactos/dll/cpl/sysdm/virtmem.c @@ -41,6 +41,8 @@ ReadPageFileSettings(PVIRTMEM pVirtMem) dwDataSize); if (pVirtMem->szPagingFiles != NULL) { + ZeroMemory(pVirtMem->szPagingFiles, + dwDataSize); if(RegQueryValueEx(hkey, _T("PagingFiles"), NULL, @@ -154,7 +156,7 @@ ParseMemSettings(PVIRTMEM pVirtMem) { TCHAR szVol[MAX_PATH + 2]; - wsprintf(szVol, _T("[%s]"), szVolume); + _stprintf(szVol, _T("[%s]"), szVolume); Item.iSubItem = 1; Item.pszText = szVol; @@ -166,7 +168,7 @@ ParseMemSettings(PVIRTMEM pVirtMem) { TCHAR szSize[64]; - wsprintf(szSize, _T("%i - %i"), InitialSize, MaxSize); + _stprintf(szSize, _T("%i - %i"), InitialSize, MaxSize); Item.iSubItem = 2; Item.pszText = szSize; @@ -198,10 +200,10 @@ WritePageFileSettings(PVIRTMEM pVirtMem) { TCHAR szText[256]; - wsprintf(szText, _T("%s\\pagefile.sys %i %i"), - pVirtMem->Pagefile[i].szDrive, - pVirtMem->Pagefile[i].InitialValue, - pVirtMem->Pagefile[i].MaxValue); + _stprintf(szText, _T("%s\\pagefile.sys %i %i"), + pVirtMem->Pagefile[i].szDrive, + pVirtMem->Pagefile[i].InitialValue, + pVirtMem->Pagefile[i].MaxValue); /* Add it to our overall registry string */ lstrcat(szPagingFiles + nPos, szText); From 3138af456a36c43a8f280f46189d2c40f8eda7df Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Wed, 20 Sep 2006 14:38:37 +0000 Subject: [PATCH 06/54] commit rc languages to xml parser for the webservre and standalone. svn path=/trunk/; revision=24213 --- rosapps/devutils/directory.rbuild | 6 + rosapps/devutils/roswebparser/roswebparser.c | 1751 +++++++++++++++++ .../devutils/roswebparser/roswebparser.rbuild | 8 + 3 files changed, 1765 insertions(+) create mode 100644 rosapps/devutils/roswebparser/roswebparser.c create mode 100644 rosapps/devutils/roswebparser/roswebparser.rbuild diff --git a/rosapps/devutils/directory.rbuild b/rosapps/devutils/directory.rbuild index e96f8f60d66..df7afbbccb1 100644 --- a/rosapps/devutils/directory.rbuild +++ b/rosapps/devutils/directory.rbuild @@ -6,6 +6,12 @@ + + + + + + diff --git a/rosapps/devutils/roswebparser/roswebparser.c b/rosapps/devutils/roswebparser/roswebparser.c new file mode 100644 index 00000000000..5b345097f99 --- /dev/null +++ b/rosapps/devutils/roswebparser/roswebparser.c @@ -0,0 +1,1751 @@ +/* + * This is a standalone rc langues to xml parser + * do not use windows or linux specfiy syntax or functions + * use only pure ansi C, this program is also runing on + * linux apachie webserver and being use in ReactOS website + * + * CopyRight 20/9-2006 by Magnus Olsen (magnus@greatlord.com) + * Licen GPL version 2.0 + */ + + +#include +#include +#include +#include + +#define true 1 +#define false 0 + + +int paraser1(char *buf, long buf_size, char * output_text, char * output_resid, char * output_format, char *iso_type); + +void find_str(char asc,char *buf, long *foundPos); +void find_str2(char *asc,char *buf, long *foundPos, char * output_resid, char *output_text ); +void trim(char* buf); +void stringbugs(char *buf, int shift2); +void stringbugs2(char *buf, int shift2); + +void ParserCMD1(char *text, char *output_resid, char *output_text, char *output_format); +void ParserCMD2(char *text, char *output_resid, char *output_text, char *output_format); +void ParserCMD3(char *text, char *output_resid, char *output_text, char *output_format); + +void ParserComment(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format); +void ParserLang(char *text, char *output_resid, char *output_text, char *output_format); +void ParserString(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format); +void ParserDialog(char *text, long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format); +void DialogCMDBuild1(char *output_resid, char *output_format, long pos, char * text); +void DialogCMDBuild2(char *output_resid, char *output_format, long pos, char * text); +void DialogCMDBuild3(char *output_resid, char *output_format, long pos, char * text); +void ParserAccelerators(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format); +void ParserMenu(char *text, long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format); + +/* + return -1 : No file found + return -2 : Fail open file + return -3 : Fail seek + return -4 : Fail get size + return -5 : Fail size of the file is 0 bytes + return -6 : Fail malloc memory + return -7 : Fail to read the file +*/ + +int main(int argc, char * argv[]) +{ + FILE * fp; + char * buffer; + char * output_text; + char * output_resid; + char * output_format; + + long buf_size; + long buf_size_calc = 0; + + if (argc!=3) + { + printf("Help\n"); + printf("%s inputfile iso-type\n\n",argv[0]); + printf("example %s en.rc UTF-8\n\n",argv[0]); + printf("Contry table\n"); + printf("en (English = \n"); + printf("se (Swedish = \n"); + printf("jp (Japanice = \n"); + return -1; + } + + + if ((fp = fopen(argv[1],"rb"))==NULL) + { + printf("Fail open file %s by %s\n",argv[1],argv[0]); + return -2; + } + + + + fseek(fp,0,SEEK_END); + if (ferror(fp) !=0) + { + fclose(fp); + printf("Fail seek\n"); + return -3; + } + buf_size = ftell(fp); + if (ferror(fp) !=0) + { + fclose(fp); + printf("Fail get size\n"); + return -4; + } + + /* + We make sure it is least 4 times + 2K biger + for we can grow around 2-3 times biger + so it better to make safe assume how + much memory we need + */ + + buf_size_calc = (buf_size*4) + 2048; + + fseek(fp,0,SEEK_SET); + if (ferror(fp) !=0) + { + fclose(fp); + printf("Fail seek\n"); + return -3; + } + + if (buf_size==0) + { + fclose(fp); + printf("Fail size of the file is 0 bytes\n"); + return -5; + } + + buffer =(char *)malloc(buf_size_calc); + if (buffer == NULL) + { + fclose(fp); + printf("Fail malloc memory\n"); + return -6; + } + + output_text =(char *)malloc(buf_size_calc); + if (output_text == NULL) + { + free(buffer); + fclose(fp); + printf("Fail malloc memory\n"); + return -6; + } + + output_resid =(char *)malloc(buf_size_calc); + if (output_resid == NULL) + { + free(buffer); + free(output_text); + fclose(fp); + printf("Fail malloc memory\n"); + return -6; + } + + output_format =(char *)malloc(buf_size_calc); + if (output_format == NULL) + { + free(buffer); + free(output_text); + free(output_resid); + fclose(fp); + printf("Fail malloc memory\n"); + return -6; + } + + //fread(buffer,1,buf_size,fp); + fread(buffer,buf_size,1,fp); + if (ferror(fp) !=0) + { + fclose(fp); + printf("Fail to read the file\n"); + return -7; + } + fclose(fp); + + /* Now we can write our parser */ + + paraser1(buffer, buf_size, output_text, output_resid, output_format,argv[2]); + printf ("%s",output_format); + + + if(buffer!=NULL) + free(buffer); + if(output_text!=NULL) + free(output_text); + if(output_resid!=NULL) + free(output_resid); + if(output_format!=NULL) + free(output_format); + + + return 0; +} + +int paraser1(char *buf, long buf_size, char * output_text, char * output_resid, char * output_format, char *iso_type) +{ + char *row; + long foundPos=0; + long foundNextPos=0; + long row_size=0; + long pos=0; + + memset(output_text,0,buf_size); + memset(output_resid,0,buf_size); + memset(output_format,0,buf_size); + + sprintf(output_format,"\n\n",iso_type); + + row = output_text; + while(pos < buf_size) + { + foundPos=0; + foundNextPos=0; + row_size=0; + + /* create a row string so we can easy scan it */ + find_str('\n',&buf[pos],&foundPos); + + if (foundPos !=0) + { + row_size = foundPos - 1; + + /* found a new row */ + strncpy(row, &buf[pos], row_size); + pos+=foundPos; + if (foundPos >=2) + row[row_size -1]=0; + + } + else + { + row_size = buf_size - pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[pos], buf_size - pos); + pos= buf_size; + } + + trim(row); + foundPos=0; + + /* Detect Basic command and send it to own paraser */ + if (*row==0) + continue; + + if (strncmp("/*",row,2)==0) + { + ParserComment(&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + + if (strncmp("//",row,2)==0) + { + ParserComment(&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + if (strncmp("#",row,1)==0) + { + ParserComment(&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + + stringbugs(row,true); + + if (foundPos == 0) + { + find_str2 ("LANGUAGE ",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserLang("LANGUAGE", output_resid, output_text, output_format); + continue; + } + } + + if (foundPos == 0) + { + find_str2 ("STRINGTABLE ",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserCMD3("STRINGTABLE", output_resid, output_text, output_format); + ParserString(&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + } + + if (foundPos == 0) + { + find_str2 (" DIALOGEX ",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserCMD2("DIALOGEX", output_resid, output_text, output_format); + ParserDialog("DIALOGEX",&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + } + + if (foundPos == 0) + { + find_str2 (" DIALOG ",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserCMD2("DIALOG", output_resid, output_text, output_format); + ParserDialog("DIALOG",&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + } + + if (foundPos == 0) + { + find_str2 (" ACCELERATORS\0",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserCMD1("ACCELERATORS", output_resid, output_text, output_format); + ParserAccelerators(&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + } + + if (foundPos == 0) + { + find_str2 (" MENU\0",row,&foundPos,output_resid,output_text); + if (foundPos != 0) + { + ParserCMD1("MENU", output_resid, output_text, output_format); + ParserMenu("MENU",&pos, buf, buf_size, output_text, output_resid, output_format); + continue; + } + } + + + } // end while + sprintf(output_format,"%s\n",output_format); + return false; +} + +/* + ParserCMD + data + input : IDM_MDIFRAME MENU DISCARDABLE LANG LANG_TAG LANG_TAG + input : IDM_MDIFRAME MENU DISCARDABLE + input : IDM_MDIFRAME MENU + input : IDM_MDIFRAME ACCELERATORS DISCARDABLE LANG LANG_TAG LANG_TAG + input : IDM_MDIFRAME ACCELERATORS DISCARDABLE + input : IDM_MDIFRAME ACCELERATORS + + + output : DISCARDABLE + output : DISCARDABLE + output : + output : DISCARDABLE + output : DISCARDABLE + output : + + param : output_resid = rc_name ID + param : output_text = MENU DISCARDABLE LANG LANG_TAG LANG_TAG + param : text = type example MENU + param : output_format = xml data store buffer +*/ + +void ParserCMD1(char *text, char *output_resid, char *output_text, char *output_format) +{ + long le; + + stringbugs(output_resid,false); + stringbugs(output_text,false); + + le = strlen(text); + + if (strlen(output_text) == le) + { + sprintf(output_format,"%s\n \n",output_format,text,text,output_resid); + } + else if (output_text[le]==' ') + { + sprintf(output_format,"%s\n DISCARDABLE\n",output_format,text,text,output_resid); + } + +} + +/* + ParserCMD2 + data + input : IDM_MDIFRAME DIALOG DISCARDABLE 15, 13, 210, 63 LANG LANG_TAG LANG_TAG + input : IDM_MDIFRAME DIALOG DISCARDABLE 15, 13, 210, 63 + input : IDM_MDIFRAME DIALOGEX DISCARDABLE 15, 13, 210, 63 LANG LANG_TAG LANG_TAG + input : IDM_MDIFRAME DIALOGEX DISCARDABLE 15, 13, 210, 63 + + + output : DISCARDABLE + output : + output : DISCARDABLE + output : + + + param : output_resid = rc_name ID + param : output_text = DIALOG DISCARDABLE 15, 13, 210, 63 LANG LANG_TAG LANG_TAG + param : text = type example DIALOG + param : output_format = xml data store buffer + +*/ + +void ParserCMD2(char *text, char *output_resid, char *output_text, char *output_format) +{ + long le; + long flag = 0; + + stringbugs(output_resid,false); + stringbugs(output_text,false); + + le=strlen(text); + + sprintf(output_format,"%s\n \n",output_format,output_resid,output_text); + else + sprintf(output_format,"%swidth=\"%s\" height=\"%s\">DISCARDABLE\n",output_format,output_resid,output_text); +} + +/* + ParserCMD3 + data + input : STRINGTABLE DISCARDABLE LANG LANG_TAG LANG_TAG + input : STRINGTABLE DISCARDABLE LANG + input : STRINGTABLE LANG LANG_TAG LANG_TAG + input : STRINGTABLE + + + output : DISCARDABLE + output : DISCARDABLE + output : + output : + + + param : output_resid = empty + param : output_text = DIALOG DISCARDABLE 15, 13, 210, 63 LANG LANG_TAG LANG_TAG + param : text = type example DIALOG + param : output_format = xml data store buffer + +*/ +void ParserCMD3(char *text, char *output_resid, char *output_text, char *output_format) +{ + long foundPos=0; + + stringbugs(output_resid,false); + stringbugs(output_text,false); + + find_str2 (" ",output_text,&foundPos,output_resid,output_text); + trim(output_resid); + trim(output_text); + + if(strncmp("STRINGTABLE",output_text,11)) + sprintf(output_format,"%s\n DISCARDABLE\n",output_format,output_text,output_resid); + else + sprintf(output_format,"%s\n \n",output_format,output_resid,output_text); + +} +/* + ParserLang + data + input : LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + input : LANGUAGE LANG_ENGLISH SUBLANG_ENGLISH_US + output : lang + output : lang + + param : output_resid = not in use + param : output_text = LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + param : text = type example LANGUAGE + param : output_format = xml data store buffer +*/ + +void ParserLang(char *text, char *output_resid, char *output_text, char *output_format) +{ + long foundPos=0; + + stringbugs(output_resid,false); + stringbugs(output_text,false); + + sprintf(output_text,"%s",&output_text[strlen(text)+1]); + + /* split the lang into two string */ + find_str2 (" ",output_text,&foundPos,output_resid,output_text); + trim(output_resid); + trim(output_text); + sprintf(output_format,"%s\n %s\n\n",output_format,text,text,output_text,output_resid); +} + + +/* + ParserComment + data + input : / * sadasdas asdasd asdas ... * / + output : + + input : / * sadasdas asdasd asdas ... * / + output : + + input : #if x + output : + + input : // hi + output : + + param : pos = current buf position + param : buf = read in buffer from file rc + param : buf_size = buf max size + param : output_text = using internal instead alloc more memory + param : output_resid = using internal instead alloc more memory + param : output_format = xml data store buffer +*/ + +void ParserComment(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format) +{ + long foundPos=0; + long foundNextPos=0; + long row_size=0; + char *row = output_text; + + + row_size = strlen(row); + if (strncmp("//",&row[0],2)==0) + { + sprintf(output_format,"%s\n \n\n",output_format,row); + return; + } + if (strncmp("#",&row[0],1)==0) + { + sprintf(output_format,"%s\n \n\n",output_format,row); + return; + } + + for (foundNextPos=0;foundNextPos\n \n\n",output_format,row); + return; + } + + } + + + sprintf(output_format,"%s\n =2) + { + row[row_size -1]=0; + } + + } + else + { + row_size = buf_size - *pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[*pos], buf_size - *pos); + *pos= buf_size; + } + + /* Search now after end of comment */ + row_size=strlen(row); + for (foundNextPos=0;foundNextPos\n\n",output_format,row); + return; + } + } + sprintf(output_format,"%s%s\n",output_format,row); + } + +} + +/* + ParserAccelerators + data + input : BEGIN + input : "^A", CMD_SELECT_ALL + input : END + + output : + output : + output : + + param : pos = current buf position + param : buf = read in buffer from file rc + param : buf_size = buf max size + param : output_text = using internal instead alloc more memory + param : output_resid = using internal instead alloc more memory + param : output_format = xml data store buffer +*/ +void ParserAccelerators(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format) +{ + long foundPos=0; + long foundNextPos=0; + long row_size=0; + char *row = output_text; + int start=false; + long le; + + while(*pos < buf_size) + { + foundPos=0; + row_size=0; + + /* create a row string so we can easy scan it */ + find_str('\n',&buf[*pos],&foundPos); + if (foundPos !=0) + { + row_size = foundPos - 1; + + /* found a new row */ + strncpy(row, &buf[*pos], foundPos); + *pos+=foundPos; + if (foundPos >=2) + { + row[row_size -1]=0; + } + + } + else + { + row_size = buf_size - *pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[*pos], buf_size - *pos); + *pos= buf_size; + } + + stringbugs(row,true); + if (start == false) + { + if ((strcmp(row,"BEGIN")==0) || (strcmp(row,"{")==0)) + { + start=true; + sprintf(output_format,"%s \n",output_format); + + } + continue; + } + + if ((strcmp(row,"END")==0) || (strcmp(row,"}")==0)) + { + sprintf(output_format,"%s \n\n",output_format); + + *output_resid = '\0'; + break; + } + + foundPos=0; + foundNextPos=0; + find_str('"',row,&foundPos); + find_str('"',&row[foundPos],&foundNextPos); + + if ((foundPos!=0) && (foundNextPos!=0)) + { + + sprintf(output_format,"%s \n",output_format,row); + } + } +} + +/* + ParserString + data + input : BEGIN + input : IDS_HINT_BLANK "text" + input : END + + output : + output : text + output : + + param : pos = current buf position + param : buf = read in buffer from file rc + param : buf_size = buf max size + param : output_text = using internal instead alloc more memory + param : output_resid = using internal instead alloc more memory + param : output_format = xml data store buffer +*/ +void ParserString(long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format) +{ + long foundPos=0; + long row_size=0; + char *row = output_text; + int start=false; + + while(*pos < buf_size) + { + foundPos=0; + row_size=0; + + /* create a row string so we can easy scan it */ + find_str('\n',&buf[*pos],&foundPos); + + if (foundPos !=0) + { + row_size = foundPos - 1; + + /* found a new row */ + strncpy(row, &buf[*pos], foundPos); + *pos+=foundPos; + if (foundPos >=2) + { + row[row_size -1]=0; + } + + } + else + { + row_size = buf_size - *pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[*pos], buf_size - *pos); + *pos= buf_size; + } + + stringbugs(row,true); + + + if (start == false) + { + if ((strcmp(row,"BEGIN")==0) || (strcmp(row,"{")==0)) + { + + start=true; + sprintf(output_format,"%s \n",output_format); + } + continue; + } + + if ((strcmp(row,"END")==0) || (strcmp(row,"}")==0)) + { + sprintf(output_format,"%s \n\n",output_format); + + *output_resid = '\0'; + break; + } + + + + /* the split code here */ + foundPos=0; + find_str2 (" ",row,&foundPos,output_resid,output_text); + + if (foundPos != 0) + { + trim(output_text); + trim(output_resid); + + if (*output_resid!='\0') + sprintf(output_format,"%s \n",output_format,output_resid,output_text); + else + sprintf(output_format,"%s \n",output_format,output_resid); + } + + } +} + +/* + ParserDialog + data + + input : BEGIN + output : + output : + + input : END + output : + output : + + input : { + output : + output : + + input : } + output : + output : + + input : FONT 8, "MS Shell Dlg" + output : + + input : FONT 8, "MS Shell Dlg", 0, 0, 0x1 + output : 0 0 0x1 + + input : CONTROL "",101,"Static",SS_SIMPLE | SS_NOPREFIX,3,6,150,10 + output : + + + Builder1 + input : DEFPUSHBUTTON "&OK",1,158,6,47,14 xx + input : PUSHBUTTON "&Cancel",2,158,23,47,14 xx + input : LTEXT "&Tooltip Text:",IDC_LABEL1,7,44,40,8 xx + input : GROUPBOX "&Display Mode",IDC_LABEL4,7,96,157,28 xx + input : ICON "",IDC_PICTURE,173,101,21,20 xx + + input : EDITTEXT 201,3,29,134,12,ES_AUTOHSCROLL + input : LISTBOX IDC_LIST, 4, 16, 104, 46, WS_TABSTOP + input : COMBOBOX ID_EOLN,54,18,156,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + output : + output : + + output : + output : + + builder2 + input : CAPTION "Execute" + input : EXSTYLE WS_EX_APPWINDOW + input : STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU + + output : DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU + + param : pos = current buf position + param : buf = read in buffer from file rc + param : buf_size = buf max size + param : output_text = using internal instead alloc more memory + param : output_resid = using internal instead alloc more memory + param : output_format = xml data store buffer +*/ +void ParserDialog(char *text, long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format) +{ + long foundPos=0; + long foundNextPos=0; + long row_size=0; + char *row = output_text; + long commandfound=0; + long le; + + *output_resid='\0'; + le=0; + + while(*pos < buf_size) + { + foundPos=0; + row_size=0; + + /* create a row string so we can easy scan it */ + find_str('\n',&buf[*pos],&foundPos); + if (foundPos !=0) + { + row_size = foundPos - 1; + + /* found a new row */ + strncpy(row, &buf[*pos], foundPos); + *pos+=foundPos; + if (foundPos >=2) + { + row[row_size -1]=0; + } + + } + else + { + row_size = buf_size - *pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[*pos], buf_size - *pos); + *pos= buf_size; + } + + //stringbugs(row,true); + trim(row); + + if ((strcmp(row,"BEGIN")==0) || (strcmp(row,"{")==0)) + commandfound=1; + if ((strcmp(row,"END")==0) || (strcmp(row,"}")==0)) + commandfound=2; + + if (strncmp("STYLE ",row,6)==0) + commandfound=3; + if (strncmp("CAPTION ",row,8)==0) + commandfound=3; + if (strncmp("FONT ",row,5)==0) + commandfound=3; + if (strncmp("CONTROL ",row,8)==0) + commandfound=3; + if (strncmp("EDITTEXT ",row,9)==0) + commandfound=3; + if (strncmp("DEFPUSHBUTTON ",row,14)==0) + commandfound=3; + if (strncmp("PUSHBUTTON ",row,11)==0) + commandfound=3; + if (strncmp("LTEXT ",row,6)==0) + commandfound=3; + if (strncmp("GROUPBOX ",row,9)==0) + commandfound=3; + if (strncmp("ICON ",row,5)==0) + commandfound=3; + if (strncmp("EXSTYLE ",row,8)==0) + commandfound=3; + if (strncmp(row,"LISTBOX ",8)==0) + commandfound=3; + if (strncmp(row,"COMBOBOX ",9)==0) + commandfound=3; + + if ((*output_resid!=0) && (commandfound!=0)) + { + /* Builder 1*/ + if (strncmp(output_resid,"LTEXT ",6)==0) + DialogCMDBuild1(output_resid, output_format, 5, "LTEXT"); + if (strncmp(output_resid,"GROUPBOX ",9)==0) + DialogCMDBuild1(output_resid, output_format, 8, "GROUPBOX"); + if (strncmp(output_resid,"DEFPUSHBUTTON ",14)==0) + DialogCMDBuild1(output_resid, output_format, 13, "DEFPUSHBUTTON"); + if (strncmp(output_resid,"PUSHBUTTON ",11)==0) + DialogCMDBuild1(output_resid, output_format, 10, "PUSHBUTTON"); + if (strncmp("ICON ",output_resid,5)==0) + DialogCMDBuild1(output_resid, output_format, 4, "ICON"); + if (strncmp("EDITTEXT ",output_resid,9)==0) + DialogCMDBuild1(output_resid, output_format, 8, "EDITTEXT"); + if (strncmp("LISTBOX ",output_resid,8)==0) + DialogCMDBuild1(output_resid, output_format, 7, "LISTBOX"); + if (strncmp("COMBOBOX ",output_resid,9)==0) + DialogCMDBuild1(output_resid, output_format, 8, "COMBOBOX"); + + /* Builder 2*/ + if (strncmp("STYLE ",output_resid,6)==0) + DialogCMDBuild2(output_resid, output_format, 5, "STYLE"); + if (strncmp("EXSTYLE ",output_resid,8)==0) + DialogCMDBuild2(output_resid, output_format, 7, "EXSTYLE"); + if (strncmp("CAPTION ",output_resid,8)==0) + DialogCMDBuild2(output_resid, output_format, 7, "CAPTION"); + if (strncmp("CONTROL ",output_resid,8)==0) + DialogCMDBuild3(output_resid, output_format, 7, "CONTROL"); + + /* no builder */ + if (strncmp(output_resid,"FONT ",5)==0) + { + stringbugs(output_resid,true); + /* FONT */ + sprintf(output_resid,"%s",&output_resid[5]); + trim(output_resid); + sprintf(output_format,"%s \n",output_format); + } + else + { + sprintf(output_format,"%s\">%s\n",output_format,&output_resid[foundPos]); + } + + *output_resid=0; + } + + *output_resid='\0'; + } + + if (commandfound==1) + { + sprintf(output_format,"%s \n",output_format,text); + } + if (commandfound==2) + { + sprintf(output_format,"%s \n\n",output_format,text); + break; + } + + sprintf(output_resid,"%s%s",output_resid,row); + commandfound=0; + } + +} +////////////////////////// +/* + ParserDialog + data + + input : BEGIN + output : + output : + + input : END + output : + output : + + input : { + output : + output : + + input : } + output : + output : + + param : pos = current buf position + param : buf = read in buffer from file rc + param : buf_size = buf max size + param : output_text = using internal instead alloc more memory + param : output_resid = using internal instead alloc more memory + param : output_format = xml data store buffer +*/ +void ParserMenu(char *text, long *pos, char *buf, long buf_size, char * output_text, char * output_resid, char * output_format) +{ + long foundPos=0; + long foundNextPos=0; + long row_size=0; + char *row = output_text; + long commandfound=0; + long le; + long count=0; + + *output_resid='\0'; + le=0; + + while(*pos < buf_size) + { + foundPos=0; + row_size=0; + + /* create a row string so we can easy scan it */ + find_str('\n',&buf[*pos],&foundPos); + if (foundPos !=0) + { + row_size = foundPos - 1; + + /* found a new row */ + strncpy(row, &buf[*pos], foundPos); + *pos+=foundPos; + if (foundPos >=2) + { + row[row_size -1]=0; + } + + } + else + { + row_size = buf_size - *pos; + + /* no new row found in the buffer */ + strncpy(row, &buf[*pos], buf_size - *pos); + *pos= buf_size; + } + + //stringbugs(row,true); + stringbugs2(row,true); + + if ((strcmp(row,"BEGIN")==0) || (strcmp(row,"{")==0)) + commandfound=1; + if ((strcmp(row,"END")==0) || (strcmp(row,"}")==0)) + commandfound=2; + + if (strncmp("POPUP ",row,6)==0) + commandfound=3; + if (strncmp("MENUITEM ",row,8)==0) + commandfound=3; + + + if ((*output_resid!=0) && (commandfound!=0)) + { + if (strncmp(output_resid,"POPUP ",6)==0) + { + sprintf(output_resid,"%s",&output_resid[5]); + trim(output_resid); + sprintf(output_format,"%s\n",output_format,output_resid); + *output_resid='\0'; + } + + if (strncmp(output_resid,"MENUITEM ",9)==0) + { + sprintf(output_resid,"%s",&output_resid[8]); + trim(output_resid); + if (strcmp(output_resid,"SEPARATOR")==0) + { + sprintf(output_format,"%s\n",output_format); + *output_resid='\0'; + } + else + { + foundPos=0; + foundNextPos=0; + find_str('"',output_resid,&foundPos); + find_str('"',&output_resid[foundPos],&foundNextPos); + + stringbugs(&output_resid[foundPos+foundNextPos],true); + + if ((foundPos+foundNextPos)==0) + { + sprintf(output_format,"%s\n",output_format,&output_resid[foundPos+foundNextPos]); + } + else + { + sprintf(output_format,"%s",output_format,&output_resid[foundPos+foundNextPos]); + + output_resid[foundPos+foundNextPos]='\0'; + trim(output_resid); + + sprintf(output_format,"%s\n",output_format,output_resid); + } + + + + *output_resid='\0'; + } + } + + + + *output_resid='\0'; + } + + if (commandfound==1) + { + count++; + if (count==1) + sprintf(output_format,"%s\n",output_format,text); + else + sprintf(output_format,"%s\n",output_format); + + *output_resid='\0'; + } + if (commandfound==2) + { + count--; + *output_resid='\0'; + + if (count<1) + sprintf(output_format,"%s\n",output_format,text); + else + sprintf(output_format,"%s\n",output_format); + + if (count<1) + { + sprintf(output_format,"%s\n",output_format); + break; + } + } + + sprintf(output_resid,"%s%s",output_resid,row); + commandfound=0; + } + +} + +void stringbugs(char *buf, int shift2) +{ + long foundPos=0; + long foundNextPos=0; + long t=0; + + /* remove , */ + if (shift2== false) + { + for (t=0;t0) + { + + if (isspace(buf[le-1])!=0) + { + buf[le-1]=0; + le=strlen(buf); + } + else + { + break; + } + } + + le=strlen(buf); + while(le>0) + { + if (isspace(buf[0])!=0) + { + strncpy(&buf[0],&buf[1],le-1); + buf[le-1]=0; + le=strlen(buf); + } + else + { + break; + } + } +} +void find_str(char asc,char *buf, long *foundPos) +{ + int t; + size_t le; + + le=strlen(buf); + + for (t=0;t\n",output_format,output_resid); + else + sprintf(output_format,"%s\">\n",output_format); + + *output_resid='\0'; +} + + +void DialogCMDBuild2(char *output_resid, char *output_format, long pos, char * text) +{ + long le; + + stringbugs(output_resid,true); + sprintf(output_resid,"%s",&output_resid[pos]); + trim(output_resid); + + le = strlen(output_resid); + if (*output_resid=='"') + *output_resid=' '; + if (output_resid[le-1]=='"') + output_resid[le-1]=' '; + + trim(output_resid); + sprintf(output_format,"%s \n",output_format,text,output_resid); + *output_resid='\0'; +} + +// input : CONTROL "",101,"Static",SS_SIMPLE | SS_NOPREFIX,3,6,150,10 +void DialogCMDBuild3(char *output_resid, char *output_format, long pos, char * text) +{ + long foundPos=0; + long foundNextPos=0; + long le; + long count=0; + long save1; + long save2; + + sprintf(output_resid,"%s",&output_resid[pos]); + trim(output_resid); + + find_str('"',output_resid,&foundPos); + find_str('"',&output_resid[foundPos],&foundNextPos); + + save1=foundPos; + save2=foundNextPos; + + sprintf(output_format,"%s \n",output_format,output_resid); + else + sprintf(output_format,"%s\">\n",output_format); + + *output_resid='\0'; +} + diff --git a/rosapps/devutils/roswebparser/roswebparser.rbuild b/rosapps/devutils/roswebparser/roswebparser.rbuild new file mode 100644 index 00000000000..21af3157f59 --- /dev/null +++ b/rosapps/devutils/roswebparser/roswebparser.rbuild @@ -0,0 +1,8 @@ + + . + 0x0501 + 0x0501 + + kernel32 + roswebparser.c + From 9907e96a49ad01a41ae92463d408fa2330459df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 20 Sep 2006 14:46:21 +0000 Subject: [PATCH 07/54] Save correct boot resources lists in registry svn path=/trunk/; revision=24214 --- .../boot/freeldr/freeldr/arch/i386/hardware.c | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c index ad37d57fbe2..fdfa068d1e7 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c @@ -348,6 +348,8 @@ DetectPnpBios(FRLDRHKEY SystemKey, ULONG *BusNumber) /* Initialize resource descriptor */ FullResourceDescriptor->InterfaceType = Internal; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 1; FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; @@ -442,6 +444,8 @@ SetHarddiskConfigurationData(FRLDRHKEY DiskKey, memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 1; FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; @@ -630,6 +634,8 @@ DetectBiosDisks(FRLDRHKEY SystemKey, memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = InterfaceTypeUndefined; FullResourceDescriptor->BusNumber = -1; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 1; FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; @@ -798,6 +804,8 @@ DetectBiosFloppyPeripheral(FRLDRHKEY ControllerKey) memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 1; PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]; @@ -898,6 +906,8 @@ DetectBiosFloppyController(FRLDRHKEY SystemKey, /* Initialize resource descriptor */ FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 3; /* Set IO Port */ @@ -914,7 +924,7 @@ DetectBiosFloppyController(FRLDRHKEY SystemKey, PartialDescriptor->Type = CmResourceTypeInterrupt; PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = 6; + PartialDescriptor->u.Interrupt.Level = 0; PartialDescriptor->u.Interrupt.Vector = 6; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; @@ -1269,9 +1279,9 @@ DetectSerialPointerPeripheral(FRLDRHKEY ControllerKey, memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); FullResourceDescriptor.InterfaceType = Isa; FullResourceDescriptor.BusNumber = 0; - FullResourceDescriptor.PartialResourceList.Count = 0; FullResourceDescriptor.PartialResourceList.Version = 1; FullResourceDescriptor.PartialResourceList.Revision = 1; + FullResourceDescriptor.PartialResourceList.Count = 0; Error = RegSetValue(PeripheralKey, L"Configuration Data", @@ -1370,6 +1380,8 @@ DetectSerialPorts(FRLDRHKEY BusKey) /* Initialize resource descriptor */ FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 3; /* Set IO Port */ @@ -1386,7 +1398,7 @@ DetectSerialPorts(FRLDRHKEY BusKey) PartialDescriptor->Type = CmResourceTypeInterrupt; PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = Irq[i]; + PartialDescriptor->u.Interrupt.Level = 0; PartialDescriptor->u.Interrupt.Vector = Irq[i]; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; @@ -1514,6 +1526,8 @@ DetectParallelPorts(FRLDRHKEY BusKey) /* Initialize resource descriptor */ FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = (Irq[i] != (ULONG)-1) ? 2 : 1; /* Set IO Port */ @@ -1532,7 +1546,7 @@ DetectParallelPorts(FRLDRHKEY BusKey) PartialDescriptor->Type = CmResourceTypeInterrupt; PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = Irq[i]; + PartialDescriptor->u.Interrupt.Level = 0; PartialDescriptor->u.Interrupt.Vector = Irq[i]; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; } @@ -1682,6 +1696,8 @@ DetectKeyboardPeripheral(FRLDRHKEY ControllerKey) memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 1; PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]; @@ -1689,7 +1705,7 @@ DetectKeyboardPeripheral(FRLDRHKEY ControllerKey) PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(CM_KEYBOARD_DEVICE_DATA); - KeyboardData = (PVOID)(((ULONG_PTR)FullResourceDescriptor) + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); + KeyboardData = (PCM_KEYBOARD_DEVICE_DATA)(PartialDescriptor + 1); KeyboardData->Version = 1; KeyboardData->Revision = 1; KeyboardData->Type = 4; @@ -1767,6 +1783,8 @@ DetectKeyboardController(FRLDRHKEY BusKey) memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 3; /* Set Interrupt */ @@ -1774,7 +1792,7 @@ DetectKeyboardController(FRLDRHKEY BusKey) PartialDescriptor->Type = CmResourceTypeInterrupt; PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; - PartialDescriptor->u.Interrupt.Level = 1; + PartialDescriptor->u.Interrupt.Level = 0; PartialDescriptor->u.Interrupt.Vector = 1; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; @@ -1954,13 +1972,15 @@ DetectPS2Mouse(FRLDRHKEY BusKey) /* Initialize resource descriptor */ FullResourceDescriptor.InterfaceType = Isa; FullResourceDescriptor.BusNumber = 0; + FullResourceDescriptor.PartialResourceList.Version = 1; + FullResourceDescriptor.PartialResourceList.Revision = 1; FullResourceDescriptor.PartialResourceList.Count = 1; /* Set Interrupt */ FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeInterrupt; FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED; - FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12; + FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 0; FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12; FullResourceDescriptor.PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF; @@ -2004,6 +2024,8 @@ DetectPS2Mouse(FRLDRHKEY BusKey) memset(&FullResourceDescriptor, 0, sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); FullResourceDescriptor.InterfaceType = Isa; FullResourceDescriptor.BusNumber = 0; + FullResourceDescriptor.PartialResourceList.Version = 1; + FullResourceDescriptor.PartialResourceList.Revision = 1; FullResourceDescriptor.PartialResourceList.Count = 0; /* Set 'Configuration Data' value */ @@ -2165,6 +2187,8 @@ DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) memset(FullResourceDescriptor, 0, Size); FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; + FullResourceDescriptor->PartialResourceList.Version = 1; + FullResourceDescriptor->PartialResourceList.Revision = 1; FullResourceDescriptor->PartialResourceList.Count = 0; /* Set 'Configuration Data' value */ From b9ade034f9ad8bdeb8fe8d73bfaf40a5137eb439 Mon Sep 17 00:00:00 2001 From: Saveliy Tretiakov Date: Wed, 20 Sep 2006 15:00:17 +0000 Subject: [PATCH 08/54] Fix booting with /DEBUGPORT=GDB and Pice too. svn path=/trunk/; revision=24215 --- reactos/ntoskrnl/kd/kdinit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reactos/ntoskrnl/kd/kdinit.c b/reactos/ntoskrnl/kd/kdinit.c index 91112cf7064..52ee7f5992d 100644 --- a/reactos/ntoskrnl/kd/kdinit.c +++ b/reactos/ntoskrnl/kd/kdinit.c @@ -57,6 +57,7 @@ KdpGetWrapperDebugMode(PCHAR Currentp2, /* Enable Debugging */ KdDebuggerEnabled = TRUE; + KdDebuggerNotPresent = FALSE; WrapperInitRoutine = KdpGdbStubInit; } @@ -69,6 +70,7 @@ KdpGetWrapperDebugMode(PCHAR Currentp2, /* Enable Debugging */ KdDebuggerEnabled = TRUE; + KdDebuggerNotPresent = FALSE; } #ifdef KDBG @@ -136,7 +138,7 @@ KdpCallInitRoutine(ULONG BootPhase) { PLIST_ENTRY CurrentEntry; PKD_DISPATCH_TABLE CurrentTable; - + /* Call the registered handlers */ CurrentEntry = KdProviders.Flink; while (CurrentEntry != &KdProviders) From 364cdf195167d3443b6d2782c9edf1afeb31e8a1 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Wed, 20 Sep 2006 16:54:54 +0000 Subject: [PATCH 09/54] - Add ability to allocate either "low" or "high" pages - Don't display a warning to user if allocating memory at certain address fails - Change debug prints so they tell in which function allocation failed - Include RTL and LDR headers from NDK, so that it's possible to use functions from RTL in FreeLdr in future svn path=/trunk/; revision=24216 --- .../boot/freeldr/freeldr/include/freeldr.h | 3 ++ reactos/boot/freeldr/freeldr/include/mm.h | 8 ++- reactos/boot/freeldr/freeldr/mm/meminit.c | 52 ++++++++++++++----- reactos/boot/freeldr/freeldr/mm/mm.c | 32 ++++++++---- 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/include/freeldr.h b/reactos/boot/freeldr/freeldr/include/freeldr.h index 5aa3e5cbc6c..a094987de39 100644 --- a/reactos/boot/freeldr/freeldr/include/freeldr.h +++ b/reactos/boot/freeldr/freeldr/include/freeldr.h @@ -43,6 +43,9 @@ #include #include #include +/* NDK, needed for ReactOS/Windows loaders */ +#include +#include #include #include #include diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index f9e8f05d93e..d3b4369762a 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -38,6 +38,11 @@ typedef struct #if defined(__i386__) || defined(_PPC_) #define MM_PAGE_SIZE 4096 +#define MM_PAGE_MASK 0xFFF +#define MM_PAGE_SHIFT 12 + +#define MM_SIZE_TO_PAGES(a) \ + ( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) ) #endif // defined __i386__ or _PPC_ @@ -74,7 +79,7 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_ME VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, ULONG PageAllocated); // Marks the specified pages as allocated or free in the lookup table VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount); // Allocates the specified pages in the lookup table ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Returns the number of free pages in the lookup table -ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded); // Returns the page number of the first available page range from the end of memory +ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd); // Returns the page number of the first available page range from the beginning or end of memory ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage); // Returns the page number of the first available page range before the specified page VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount); // Removes entries in the memory map that describe memory above 4G VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount); // Sets the LastFreePageHint to the last usable page of memory @@ -87,6 +92,7 @@ ULONG GetSystemMemorySize(VOID); // Returns the amount of total memory i BOOLEAN MmInitializeMemoryManager(VOID); PVOID MmAllocateMemory(ULONG MemorySize); VOID MmFreeMemory(PVOID MemoryPointer); +VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd); //PVOID MmAllocateLowMemory(ULONG MemorySize); //VOID MmFreeLowMemory(PVOID MemoryPointer); PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress); diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 7c60ff64707..8f3668aa150 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/boot/freeldr/freeldr/mm/meminit.c @@ -311,7 +311,7 @@ ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount) return FreePageCount; } -ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded) +ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; ULONG AvailablePagesSoFar; @@ -323,21 +323,47 @@ ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, U } AvailablePagesSoFar = 0; - for (Index=LastFreePageHint-1; Index>0; Index--) + if (FromEnd) { - if (RealPageLookupTable[Index].PageAllocated != 0) + /* Allocate "high" (from end) pages */ + for (Index=LastFreePageHint-1; Index>0; Index--) { - AvailablePagesSoFar = 0; - continue; - } - else - { - AvailablePagesSoFar++; - } + if (RealPageLookupTable[Index].PageAllocated != 0) + { + AvailablePagesSoFar = 0; + continue; + } + else + { + AvailablePagesSoFar++; + } - if (AvailablePagesSoFar >= PagesNeeded) + if (AvailablePagesSoFar >= PagesNeeded) + { + return Index; + } + } + } + else + { + DbgPrint((DPRINT_MEMORY, "Alloc low memory, LastFreePageHint %d, TPC %d\n", LastFreePageHint, TotalPageCount)); + /* Allocate "low" pages */ + for (Index=1; Index < LastFreePageHint; Index++) { - return Index; + if (RealPageLookupTable[Index].PageAllocated != 0) + { + AvailablePagesSoFar = 0; + continue; + } + else + { + AvailablePagesSoFar++; + } + + if (AvailablePagesSoFar >= PagesNeeded) + { + return Index; + } } } @@ -352,7 +378,7 @@ ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount if (LastPage > TotalPageCount) { - return MmFindAvailablePagesFromEnd(PageLookupTable, TotalPageCount, PagesNeeded); + return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE); } AvailablePagesSoFar = 0; diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index 31513936882..928fe94e566 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -52,6 +52,13 @@ VOID MemAllocTest(VOID); static PVOID SubAllocationPage = NULL; static unsigned SubAllocationRest = 0; +BOOLEAN AllocateFromEnd = TRUE; + +VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd) +{ + AllocateFromEnd = PolicyAllocatePagesFromEnd; +} + PVOID MmAllocateMemory(ULONG MemorySize) { ULONG PagesNeeded; @@ -81,16 +88,16 @@ PVOID MmAllocateMemory(ULONG MemorySize) // then return NULL if (FreePagesInLookupTable < PagesNeeded) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } - FirstFreePageFromEnd = MmFindAvailablePagesFromEnd(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded); + FirstFreePageFromEnd = MmFindAvailablePages(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded, AllocateFromEnd); - if (FirstFreePageFromEnd == 0) + if (FirstFreePageFromEnd == (ULONG)-1) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } @@ -142,15 +149,22 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) // then return NULL if (FreePagesInLookupTable < PagesNeeded) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). " + "Not enough free memory to allocate %d bytes (requesting %d pages but have only %d). " + "AllocationCount: %d\n", MemorySize, PagesNeeded, FreePagesInLookupTable, AllocationCount)); UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } if (MmAreMemoryPagesAvailable(PageLookupTableAddress, TotalPagesInLookupTable, DesiredAddress, PagesNeeded) == FALSE) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); - UiMessageBoxCritical("Memory allocation failed: out of memory."); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). " + "Not enough free memory to allocate %d bytes at address %p. AllocationCount: %d\n", + MemorySize, DesiredAddress, AllocationCount)); + + // Don't tell this to user since caller should try to alloc this memory + // at a different address + //UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } @@ -195,7 +209,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress // then return NULL if (FreePagesInLookupTable < PagesNeeded) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } @@ -204,7 +218,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress if (FirstFreePageFromEnd == 0) { - DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); + DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount)); UiMessageBoxCritical("Memory allocation failed: out of memory."); return NULL; } From d2241f8ec437bf7873ae25a7a7bbc193d2495a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 20 Sep 2006 18:16:24 +0000 Subject: [PATCH 10/54] If boot resources are provided, use them instead of using resource requirements. In all cases, translate the resource list before calling the driver svn path=/trunk/; revision=24217 --- reactos/ntoskrnl/io/pnpmgr/pnpmgr.c | 506 +++++++++++++++++++--------- 1 file changed, 340 insertions(+), 166 deletions(-) diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index c0047ae1cca..9d664858a5b 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -132,12 +132,6 @@ IopStartDevice( Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList; Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated; - /* FIXME: Not sure of this! */ - if (!Stack.Parameters.StartDevice.AllocatedResources) - Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->BootResources; - if (!Stack.Parameters.StartDevice.AllocatedResourcesTranslated) - Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->BootResources; - Status = IopInitiatePnpIrp( Fdo, &IoStatusBlock, @@ -1229,30 +1223,70 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, } -NTSTATUS -IopAssignDeviceResources(PDEVICE_NODE DeviceNode) +static NTSTATUS +IopAssignDeviceResources( + IN PDEVICE_NODE DeviceNode, + OUT ULONG *pRequiredSize) { PIO_RESOURCE_LIST ResourceList; PIO_RESOURCE_DESCRIPTOR ResourceDescriptor; - PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; + PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw; + PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; ULONG NumberOfResources = 0; - ULONG i; + ULONG Size; + ULONG i, j; NTSTATUS Status; - /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated; - * by using DeviceNode->ResourceRequirements */ - - if (!DeviceNode->ResourceRequirements - || DeviceNode->ResourceRequirements->AlternativeLists == 0) + if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements) { - DeviceNode->ResourceList = DeviceNode->ResourceListTranslated = NULL; + /* No resource needed for this device */ + DeviceNode->ResourceList = NULL; return STATUS_SUCCESS; } + /* Fill DeviceNode->ResourceList + * FIXME: the PnP arbiter should go there! + * Actually, use the BootResources if provided, else the resource list #0 + */ + + IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); + + if (DeviceNode->BootResources) + { + /* Browse the boot resources to know if we have some custom structures */ + Size = FIELD_OFFSET(CM_RESOURCE_LIST, List); + for (i = 0; i < DeviceNode->BootResources->Count; i++) + { + pPartialResourceList = &DeviceNode->BootResources->List[i].PartialResourceList; + if (pPartialResourceList->Version != 1 || pPartialResourceList->Revision != 1) + { + Status = STATUS_REVISION_MISMATCH; + goto ByeBye; + } + Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors) + + pPartialResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); + for (j = 0; j < pPartialResourceList->Count; j++) + { + if (pPartialResourceList->PartialDescriptors[j].Type == CmResourceTypeDeviceSpecific) + Size += pPartialResourceList->PartialDescriptors[j].u.DeviceSpecificData.DataSize; + } + } + + DeviceNode->ResourceList = ExAllocatePool(PagedPool, Size); + if (!DeviceNode->ResourceList) + { + Status = STATUS_NO_MEMORY; + goto ByeBye; + } + RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, Size); + + *pRequiredSize = Size; + return STATUS_SUCCESS; + } + + /* Ok, here, we have to use the device requirement list */ IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); - /* FIXME: that's here that PnP arbiter should go */ - /* Actually, simply use resource list #0 as assigned resource list */ ResourceList = &DeviceNode->ResourceRequirements->List[0]; if (ResourceList->Version != 1 || ResourceList->Revision != 1) { @@ -1260,19 +1294,12 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode) goto ByeBye; } - DeviceNode->ResourceList = ExAllocatePool(PagedPool, - sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + Size = sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); + *pRequiredSize = Size; + DeviceNode->ResourceList = ExAllocatePool(PagedPool, Size); if (!DeviceNode->ResourceList) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto ByeBye; - } - - DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, - sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); - if (!DeviceNode->ResourceListTranslated) - { - Status = STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_NO_MEMORY; goto ByeBye; } @@ -1282,12 +1309,6 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode) DeviceNode->ResourceList->List[0].PartialResourceList.Version = 1; DeviceNode->ResourceList->List[0].PartialResourceList.Revision = 1; - DeviceNode->ResourceListTranslated->Count = 1; - DeviceNode->ResourceListTranslated->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType; - DeviceNode->ResourceListTranslated->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber; - DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Version = 1; - DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Revision = 1; - for (i = 0; i < ResourceList->Count; i++) { ResourceDescriptor = &ResourceList->Descriptors[i]; @@ -1295,31 +1316,18 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode) if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED) { DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources]; - DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[NumberOfResources]; NumberOfResources++; /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */ - DescriptorRaw->Type = DescriptorTranslated->Type = ResourceDescriptor->Type; - DescriptorRaw->ShareDisposition = DescriptorTranslated->ShareDisposition = ResourceDescriptor->ShareDisposition; - DescriptorRaw->Flags = DescriptorTranslated->Flags = ResourceDescriptor->Flags; + DescriptorRaw->Type = ResourceDescriptor->Type; + DescriptorRaw->ShareDisposition = ResourceDescriptor->ShareDisposition; + DescriptorRaw->Flags = ResourceDescriptor->Flags; switch (ResourceDescriptor->Type) { case CmResourceTypePort: { - ULONG AddressSpace = 0; /* IO space */ DescriptorRaw->u.Port.Start = ResourceDescriptor->u.Port.MinimumAddress; - DescriptorRaw->u.Port.Length = DescriptorTranslated->u.Port.Length - = ResourceDescriptor->u.Port.Length; - if (!HalTranslateBusAddress( - DeviceNode->ResourceRequirements->InterfaceType, - DeviceNode->ResourceRequirements->BusNumber, - DescriptorRaw->u.Port.Start, - &AddressSpace, - &DescriptorTranslated->u.Port.Start)) - { - Status = STATUS_UNSUCCESSFUL; - goto ByeBye; - } + DescriptorRaw->u.Port.Length = ResourceDescriptor->u.Port.Length; break; } case CmResourceTypeInterrupt: @@ -1379,54 +1387,26 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode) } } } - - DescriptorTranslated->u.Interrupt.Level = 0; - DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( - DeviceNode->ResourceRequirements->InterfaceType, - DeviceNode->ResourceRequirements->BusNumber, - DescriptorRaw->u.Interrupt.Level, - DescriptorRaw->u.Interrupt.Vector, - (PKIRQL)&DescriptorTranslated->u.Interrupt.Level, - &DescriptorRaw->u.Interrupt.Affinity); - DescriptorTranslated->u.Interrupt.Affinity = DescriptorRaw->u.Interrupt.Affinity; break; } case CmResourceTypeMemory: { - ULONG AddressSpace = 1; /* Memory space */ DescriptorRaw->u.Memory.Start = ResourceDescriptor->u.Memory.MinimumAddress; - DescriptorRaw->u.Memory.Length = DescriptorTranslated->u.Memory.Length - = ResourceDescriptor->u.Memory.Length; - if (!HalTranslateBusAddress( - DeviceNode->ResourceRequirements->InterfaceType, - DeviceNode->ResourceRequirements->BusNumber, - DescriptorRaw->u.Memory.Start, - &AddressSpace, - &DescriptorTranslated->u.Memory.Start)) - { - Status = STATUS_UNSUCCESSFUL; - goto ByeBye; - } + DescriptorRaw->u.Memory.Length = ResourceDescriptor->u.Memory.Length; break; } case CmResourceTypeDma: { - DescriptorRaw->u.Dma.Channel = DescriptorTranslated->u.Dma.Channel - = ResourceDescriptor->u.Dma.MinimumChannel; - DescriptorRaw->u.Dma.Port = DescriptorTranslated->u.Dma.Port - = 0; /* FIXME */ - DescriptorRaw->u.Dma.Reserved1 = DescriptorTranslated->u.Dma.Reserved1 - = 0; + DescriptorRaw->u.Dma.Channel = ResourceDescriptor->u.Dma.MinimumChannel; + DescriptorRaw->u.Dma.Port = 0; /* FIXME */ + DescriptorRaw->u.Dma.Reserved1 = 0; break; } case CmResourceTypeBusNumber: { - DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start - = ResourceDescriptor->u.BusNumber.MinBusNumber; - DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length - = ResourceDescriptor->u.BusNumber.Length; - DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved - = ResourceDescriptor->u.BusNumber.Reserved; + DescriptorRaw->u.BusNumber.Start = ResourceDescriptor->u.BusNumber.MinBusNumber; + DescriptorRaw->u.BusNumber.Length = ResourceDescriptor->u.BusNumber.Length; + DescriptorRaw->u.BusNumber.Reserved = ResourceDescriptor->u.BusNumber.Reserved; break; } /*CmResourceTypeDevicePrivate: @@ -1452,10 +1432,7 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode) } DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources; - DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Count = NumberOfResources; - IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); - IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED); return STATUS_SUCCESS; ByeBye: @@ -1464,13 +1441,111 @@ ByeBye: ExFreePool(DeviceNode->ResourceList); DeviceNode->ResourceList = NULL; } + return Status; +} + + +static NTSTATUS +IopTranslateDeviceResources( + IN PDEVICE_NODE DeviceNode, + IN ULONG RequiredSize) +{ + PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; + ULONG i, j; + NTSTATUS Status; + + if (!DeviceNode->ResourceList) + { + DeviceNode->ResourceListTranslated = NULL; + return STATUS_SUCCESS; + } + + /* That's easy to translate a resource list. Just copy the + * untranslated one and change few fields in the copy + */ + DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, RequiredSize); + if (!DeviceNode->ResourceListTranslated) + { + Status =STATUS_NO_MEMORY; + goto cleanup; + } + RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, RequiredSize); + + for (i = 0; i < DeviceNode->ResourceList->Count; i++) + { + pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList; + for (j = 0; j < pPartialResourceList->Count; j++) + { + DescriptorRaw = &pPartialResourceList->PartialDescriptors[j]; + DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j]; + switch (DescriptorRaw->Type) + { + case CmResourceTypePort: + { + ULONG AddressSpace = 0; /* IO space */ + if (!HalTranslateBusAddress( + DeviceNode->ResourceList->List[i].InterfaceType, + DeviceNode->ResourceList->List[i].BusNumber, + DescriptorRaw->u.Port.Start, + &AddressSpace, + &DescriptorTranslated->u.Port.Start)) + { + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + break; + } + case CmResourceTypeInterrupt: + { + DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( + DeviceNode->ResourceList->List[i].InterfaceType, + DeviceNode->ResourceList->List[i].BusNumber, + DescriptorRaw->u.Interrupt.Level, + DescriptorRaw->u.Interrupt.Vector, + (PKIRQL)&DescriptorTranslated->u.Interrupt.Level, + &DescriptorRaw->u.Interrupt.Affinity); + break; + } + case CmResourceTypeMemory: + { + ULONG AddressSpace = 1; /* Memory space */ + if (!HalTranslateBusAddress( + DeviceNode->ResourceList->List[i].InterfaceType, + DeviceNode->ResourceList->List[i].BusNumber, + DescriptorRaw->u.Memory.Start, + &AddressSpace, + &DescriptorTranslated->u.Memory.Start)) + { + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + } + + case CmResourceTypeDma: + case CmResourceTypeBusNumber: + case CmResourceTypeDeviceSpecific: + /* Nothing to do */ + break; + default: + DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type); + Status = STATUS_NOT_IMPLEMENTED; + goto cleanup; + } + } + } + return STATUS_SUCCESS; + +cleanup: + /* Yes! Also delete ResourceList because ResourceList and + * ResourceListTranslated should be a pair! */ + ExFreePool(DeviceNode->ResourceList); + DeviceNode->ResourceList = NULL; if (DeviceNode->ResourceListTranslated) { ExFreePool(DeviceNode->ResourceListTranslated); - DeviceNode->ResourceListTranslated = NULL; + DeviceNode->ResourceList = NULL; } - - IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); return Status; } @@ -2030,11 +2105,25 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, ZwClose(InstanceKey); - Status = IopAssignDeviceResources(DeviceNode); - if (!NT_SUCCESS(Status)) + IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); + Status = IopAssignDeviceResources(DeviceNode, &RequiredLength); + if (NT_SUCCESS(Status)) { - DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status); + Status = IopTranslateDeviceResources(DeviceNode, RequiredLength); + if (NT_SUCCESS(Status)) + { + IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED); + } + else + { + DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status); + } } + else + { + DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status); + } + IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); DeviceNode->Flags |= DNF_PROCESSED; @@ -2596,7 +2685,9 @@ IopEnumerateDetectedDevices( IN HANDLE hBaseKey, IN PUNICODE_STRING RelativePath, IN HANDLE hRootKey, - IN BOOLEAN EnumerateSubKeys) + IN BOOLEAN EnumerateSubKeys, + IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources, + IN ULONG ParentBootResourcesLength) { UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); UNICODE_STRING DeviceDescU = RTL_CONSTANT_STRING(L"DeviceDesc"); @@ -2618,6 +2709,8 @@ IopEnumerateDetectedDevices( ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); UNICODE_STRING DeviceName, ValueName; ULONG RequiredSize; + PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL; + ULONG BootResourcesLength; NTSTATUS Status; const UNICODE_STRING IdentifierPci = RTL_CONSTANT_STRING(L"PCI BIOS"); @@ -2701,6 +2794,87 @@ IopEnumerateDetectedDevices( goto cleanup; } + /* Read boot resources, and add then to parent ones */ + Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); + if (Status == STATUS_BUFFER_OVERFLOW) + { + ExFreePool(pValueInformation); + ValueInfoLength = RequiredSize; + pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); + if (!pValueInformation) + { + DPRINT("ExAllocatePool() failed\n"); + ZwDeleteKey(hLevel2Key); + Status = STATUS_NO_MEMORY; + goto cleanup; + } + Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); + } + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + BootResources = ParentBootResources; + BootResourcesLength = ParentBootResourcesLength; + } + else if (!NT_SUCCESS(Status)) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto nextdevice; + } + else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) + { + DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); + goto nextdevice; + } + else if (((PCM_FULL_RESOURCE_DESCRIPTOR)pValueInformation->Data)->PartialResourceList.Count == 0) + { + BootResources = ParentBootResources; + BootResourcesLength = ParentBootResourcesLength; + } + else + { + static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors); + + /* Concatenate current resources and parent ones */ + if (ParentBootResourcesLength == 0) + BootResourcesLength = pValueInformation->DataLength; + else + BootResourcesLength = ParentBootResourcesLength + + pValueInformation->DataLength + - Header; + BootResources = ExAllocatePool(PagedPool, BootResourcesLength); + if (!BootResources) + { + DPRINT("ExAllocatePool() failed\n"); + goto nextdevice; + } + if (ParentBootResourcesLength == 0) + { + RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); + } + else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific) + { + RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength), + (PVOID)((ULONG_PTR)ParentBootResources + Header), + ParentBootResourcesLength - Header); + BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; + } + else + { + RtlCopyMemory(BootResources, pValueInformation->Data, Header); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + Header), + (PVOID)((ULONG_PTR)ParentBootResources + Header), + ParentBootResourcesLength - Header); + RtlCopyMemory( + (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength), + pValueInformation->Data + Header, + pValueInformation->DataLength - Header); + BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; + } + } + if (EnumerateSubKeys) { IndexSubKey = 0; @@ -2731,7 +2905,13 @@ IopEnumerateDetectedDevices( DeviceName.Length = DeviceName.MaximumLength = pDeviceInformation->NameLength; DeviceName.Buffer = pDeviceInformation->Name; - Status = IopEnumerateDetectedDevices(hDeviceKey, &DeviceName, hRootKey, TRUE); + Status = IopEnumerateDetectedDevices( + hDeviceKey, + &DeviceName, + hRootKey, + TRUE, + BootResources, + BootResourcesLength); if (!NT_SUCCESS(Status)) goto cleanup; } @@ -2754,31 +2934,27 @@ IopEnumerateDetectedDevices( } if (!NT_SUCCESS(Status)) { - DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); - goto nextdevice; + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto nextdevice; + } } else if (pValueInformation->Type != REG_SZ) { DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ); goto nextdevice; } - - /* Assign hardware id to this device */ - ValueName.Length = ValueName.MaximumLength = pValueInformation->DataLength; - ValueName.Buffer = (PWCHAR)pValueInformation->Data; - if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) - ValueName.Length -= sizeof(WCHAR); - if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0) + else { - pHardwareId = &HardwareIdPci; - DeviceIndex = DeviceIndexPci++; + /* Assign hardware id to this device */ + ValueName.Length = ValueName.MaximumLength = pValueInformation->DataLength; + ValueName.Buffer = (PWCHAR)pValueInformation->Data; + if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) + ValueName.Length -= sizeof(WCHAR); } - /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0) - { - pHardwareId = &HardwareIdAcpi; - DeviceIndex = DeviceIndexAcpi++; - }*/ - else if (RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) + + if (RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) { pHardwareId = &HardwareIdSerial; DeviceIndex = DeviceIndexSerial++; @@ -2793,10 +2969,30 @@ IopEnumerateDetectedDevices( pHardwareId = &HardwareIdMouse; DeviceIndex = DeviceIndexMouse++; } + else if (NT_SUCCESS(Status)) + { + /* Try to also match the device identifier */ + if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0) + { + pHardwareId = &HardwareIdPci; + DeviceIndex = DeviceIndexPci++; + } + /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0) + { + pHardwareId = &HardwareIdAcpi; + DeviceIndex = DeviceIndexAcpi++; + }*/ + else + { + /* Unknown device */ + DPRINT("Unknown device '%wZ'\n", &ValueName); + goto nextdevice; + } + } else { - /* Unknown device */ - DPRINT("Unknown device %wZ in %wZ\n", &ValueName, RelativePath); + /* Unknown key path */ + DPRINT("Unknown key path %wZ\n", RelativePath); goto nextdevice; } @@ -2847,61 +3043,37 @@ IopEnumerateDetectedDevices( ZwDeleteKey(hLevel2Key); goto nextdevice; } - /* Copy 'Configuration Data' to 'LogConf\BootConfig' */ - Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - if (Status == STATUS_BUFFER_OVERFLOW) + if (BootResourcesLength > 0) { - ExFreePool(pValueInformation); - ValueInfoLength = RequiredSize; - pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); - if (!pValueInformation) + /* Save boot resources to 'LogConf\BootConfig' */ + InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); + Status = ZwCreateKey( + &hLogConf, + KEY_SET_VALUE, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + NULL); + if (!NT_SUCCESS(Status)) { - DPRINT("ExAllocatePool() failed\n"); + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ZwDeleteKey(hLevel2Key); - Status = STATUS_NO_MEMORY; - goto cleanup; + goto nextdevice; + } + Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_FULL_RESOURCE_DESCRIPTOR, BootResources, BootResourcesLength); + ZwClose(hLogConf); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ZwDeleteKey(hLevel2Key); + goto nextdevice; } - Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); - } - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - goto nextdevice; - else if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) - { - DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); - Status = ZwCreateKey( - &hLogConf, - KEY_SET_VALUE, - &ObjectAttributes, - 0, - NULL, - REG_OPTION_VOLATILE, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, pValueInformation->Type, pValueInformation->Data, pValueInformation->DataLength); - ZwClose(hLogConf); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; } nextdevice: + if (BootResources && BootResources != ParentBootResources) + ExFreePool(BootResources); if (hLevel2Key) { ZwClose(hLevel2Key); @@ -3119,7 +3291,9 @@ IopUpdateRootKey(VOID) NULL, &MultiKeyPathU, hRoot, - TRUE); + TRUE, + NULL, + 0); ZwClose(hRoot); return Status; } From f1cf836837652fa7002945ccd1744bb36bbb573c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 20 Sep 2006 18:56:04 +0000 Subject: [PATCH 11/54] Big update of i8042prt driver. The driver is now plug&play compliant and some mouse driver filters may be installed. svn path=/trunk/; revision=24218 --- reactos/boot/bootdata/hivesys.inf | 23 +- reactos/drivers/input/i8042prt/README.txt | 25 +- reactos/drivers/input/i8042prt/createclose.c | 55 + reactos/drivers/input/i8042prt/i8042prt.c | 1233 ++++-------- reactos/drivers/input/i8042prt/i8042prt.h | 628 +++--- .../drivers/input/i8042prt/i8042prt.rbuild | 6 +- reactos/drivers/input/i8042prt/i8042prt.rc | 2 +- reactos/drivers/input/i8042prt/keyboard.c | 1491 +++++++------- reactos/drivers/input/i8042prt/misc.c | 68 + reactos/drivers/input/i8042prt/mouse.c | 1744 +++++++++-------- reactos/drivers/input/i8042prt/pnp.c | 666 +++++++ reactos/drivers/input/i8042prt/ps2pp.c | 238 +-- reactos/drivers/input/i8042prt/readwrite.c | 218 +++ reactos/drivers/input/i8042prt/registry.c | 336 ++-- reactos/drivers/input/i8042prt/setup.c | 273 +++ 15 files changed, 4119 insertions(+), 2887 deletions(-) create mode 100644 reactos/drivers/input/i8042prt/createclose.c create mode 100644 reactos/drivers/input/i8042prt/misc.c create mode 100644 reactos/drivers/input/i8042prt/pnp.c create mode 100644 reactos/drivers/input/i8042prt/readwrite.c create mode 100644 reactos/drivers/input/i8042prt/setup.c diff --git a/reactos/boot/bootdata/hivesys.inf b/reactos/boot/bootdata/hivesys.inf index c0f44f258ed..4cb1a01bc29 100644 --- a/reactos/boot/bootdata/hivesys.inf +++ b/reactos/boot/bootdata/hivesys.inf @@ -564,13 +564,6 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","ImagePath",0x00020000,"system32 HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Start",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\Fs_Rec","Type",0x00010001,0x00000008 -; i8042 port driver -HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","ErrorControl",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Group",0x00000000,"Keyboard Port" -HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Start",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt","Type",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt\Parameters","BreakOnSysRq",0x00010001,0x00000001 - ; Kernel-Mode Tests ;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","ErrorControl",0x00010001,0x00000000 ;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Group",0x00000000,"Base" @@ -578,14 +571,8 @@ HKLM,"SYSTEM\CurrentControlSet\Services\i8042prt\Parameters","BreakOnSysRq",0x00 ;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Start",0x00010001,0x00000001 ;HKLM,"SYSTEM\CurrentControlSet\Services\Kmtest","Type",0x00010001,0x00000001 -; Keyboard class driver -HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ErrorControl",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Group",0x00000000,"Keyboard Class" -HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","ImagePath",0x00020000,"system32\drivers\kbdclass.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Start",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass","Type",0x00010001,0x00000001 +; Keyboard parameters HKLM,"SYSTEM\CurrentControlSet\Services\kbdclass\Parameters","ConnectMultiplePorts",0x00010001,1 -HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"kbdclass" ; SB16 driver HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base" @@ -610,14 +597,6 @@ HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys" -; Mouse class driver -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ErrorControl",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Group",0x00000000,"Pointer Class" -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","ImagePath",0x00020000,"system32\drivers\mouclass.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Start",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass" - ; Mailslot filesystem driver HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\Msfs","Group",0x00000000,"File System" diff --git a/reactos/drivers/input/i8042prt/README.txt b/reactos/drivers/input/i8042prt/README.txt index a8f09ff5f59..16bb6c791fb 100644 --- a/reactos/drivers/input/i8042prt/README.txt +++ b/reactos/drivers/input/i8042prt/README.txt @@ -7,18 +7,28 @@ not based on the i8042prt example driver that's included with the DDK. The directory contains these files: +createclose.c: open/close devices functionnality + i8042prt.c: Main controller functionality, things shared by keyboards and mice keyboard.c: keyboard functionality: detection, interrupt handling +misc.c: misc things, mostly related to Irp passing + mouse.c: mouse functionality: detection, interrupt handling, packet parsing for standard ps2 and microsoft mice +pnp.c: Plug&Play functionnality + ps2pp.c: logitech ps2++ mouse packat parsing (basic) +readwrite.c: read/write to the i8042 controller + registry.c: registry reading -makefile, i8042prt.rc: obvious +setup.c: add keyboard support during the 1st stage setup + +i8042prt.rc: obvious Some parts of the driver make little sense. This is because it implements @@ -33,7 +43,6 @@ Things to add: - General robustness: reset mouse if things go wrong - Handling all registry settings - ACPI -- Make it work more like a WDM driver Things not to add: @@ -49,18 +58,6 @@ Things requiring work elsewhere: hardcoded cases, this should not be hard to fix. - Class drivers: - I wrote a keyboard class driver, which does keycode translations. It - should not do this, win32k should get untranslated keycodes and do - the translation itself. - - I changed the mouse class driver (mouclass) to work like Microsofts mouclass. - Unfortunately this means that the original psaux driver doesn't work - anymore (the same holds for the other mice drivers, probably). - - The keyboard class driver passes on ioctls from win32k, so it can change - keyboard settings. As far as I could see, the mouse class driver does not - do this yet. - The class drivers should be able to handle reads for more than one packet at a time (kbdclass should, mouclass does not). Win32k should send such requests. diff --git a/reactos/drivers/input/i8042prt/createclose.c b/reactos/drivers/input/i8042prt/createclose.c new file mode 100644 index 00000000000..e895dbee3cc --- /dev/null +++ b/reactos/drivers/input/i8042prt/createclose.c @@ -0,0 +1,55 @@ +/* + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/createclose.c + * PURPOSE: IRP_MJ_CREATE, IRP_MJ_CLEANUP and IRP_MJ_CLOSE operations + * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "i8042prt.h" + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS NTAPI +i8042Create( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CREATE\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS NTAPI +i8042Cleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CLEANUP\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS NTAPI +i8042Close( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CLOSE\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/input/i8042prt/i8042prt.c b/reactos/drivers/input/i8042prt/i8042prt.c index 04625caa859..ebffde03621 100644 --- a/reactos/drivers/input/i8042prt/i8042prt.c +++ b/reactos/drivers/input/i8042prt/i8042prt.c @@ -1,927 +1,524 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/input/i8042prt/i8042prt.c - * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver - * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) - * Tinus + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/i8042prt.c + * PURPOSE: Driver entry function + * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) + Copyright Jason Filby (jasonfilby@yahoo.com) + Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ -/* INCLUDES ****************************************************************/ +/* INCLUDES ******************************************************************/ + +#define INITGUID +#include "i8042prt.h" #define NDEBUG #include -#include "i8042prt.h" - -/* GLOBALS *******************************************************************/ - -/* - * Driver data - */ -#define I8042_TIMEOUT 500000 - -#define I8042_MAX_COMMAND_LENGTH 16 -#define I8042_MAX_UPWARDS_STACK 5 - -UNICODE_STRING I8042RegistryPath; - /* FUNCTIONS *****************************************************************/ -/* - * FUNCTION: Write data to a port, waiting first for it to become ready - */ -BOOLEAN I8042Write(PDEVICE_EXTENSION DevExt, PUCHAR addr, UCHAR data) +NTSTATUS NTAPI +i8042AddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo) { - ULONG ResendIterations = DevExt->Settings.PollingIterations; + PI8042_DRIVER_EXTENSION DriverExtension; + PFDO_DEVICE_EXTENSION DeviceExtension = NULL; + PDEVICE_OBJECT Fdo = NULL; + ULONG DeviceExtensionSize; + NTSTATUS Status; - while ((KBD_IBF & READ_PORT_UCHAR(I8042_CTRL_PORT)) && - (ResendIterations--)) + DPRINT("i8042AddDevice(%p %p)\n", DriverObject, Pdo); + + DriverExtension = (PI8042_DRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject, DriverObject); + + if (Pdo == NULL) { - KeStallExecutionProcessor(50); + /* We're getting a NULL Pdo at the first call as + * we are a legacy driver. Ignore it */ + return STATUS_SUCCESS; } - if (ResendIterations) { - WRITE_PORT_UCHAR(addr,data); - DPRINT("Sent %x to %x\n", data, addr); - return TRUE; + /* Create new device object. As we don't know if the device would be a keyboard + * or a mouse, we have to allocate the biggest device extension. */ + DeviceExtensionSize = MAX(sizeof(I8042_KEYBOARD_EXTENSION), sizeof(I8042_MOUSE_EXTENSION)); + Status = IoCreateDevice( + DriverObject, + DeviceExtensionSize, + NULL, + Pdo->DeviceType, + FILE_DEVICE_SECURE_OPEN, + TRUE, + &Fdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); + goto cleanup; } - return FALSE; -} -#if 0 /* function is not needed */ -/* - * FUNCTION: Write data to a port, without waiting first - */ -static BOOLEAN I8042WriteNoWait(PDEVICE_EXTENSION DevExt, int addr, UCHAR data) -{ - WRITE_PORT_UCHAR((PUCHAR)addr,data); - DPRINT("Sent %x to %x\n", data, addr); - return TRUE; -} -#endif + DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, DeviceExtensionSize); + DeviceExtension->Type = Unknown; + DeviceExtension->Fdo = Fdo; + DeviceExtension->Pdo = Pdo; + DeviceExtension->PortDeviceExtension = &DriverExtension->Port; + Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); -/* - * FUNCTION: Read data from port 0x60 - */ -NTSTATUS I8042ReadData(UCHAR *Data) -{ - UCHAR Status; - Status=READ_PORT_UCHAR(I8042_CTRL_PORT); - - // If data is available - if ((Status & KBD_OBF)) { - Data[0]=READ_PORT_UCHAR((PUCHAR)I8042_DATA_PORT); - DPRINT("Read: %x (status: %x)\n", Data[0], Status); - - // If the data is valid (not timeout, not parity error) - if (0 == (Status & KBD_PERR)) - return STATUS_SUCCESS; - } - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS I8042ReadStatus(UCHAR *Status) -{ - Status[0]=READ_PORT_UCHAR(I8042_CTRL_PORT); + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; + +cleanup: + if (DeviceExtension && DeviceExtension->LowerDevice) + IoDetachDevice(DeviceExtension->LowerDevice); + if (Fdo) + IoDeleteDevice(Fdo); + return Status; } -/* - * FUNCTION: Read data from port 0x60 - */ -NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, UCHAR *Data) +VOID NTAPI +i8042SendHookWorkItem( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) { - ULONG Counter = DevExt->Settings.PollingIterations; + PI8042_HOOK_WORKITEM WorkItemData; + PFDO_DEVICE_EXTENSION FdoDeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + PDEVICE_OBJECT TopOfStack = NULL; + ULONG IoControlCode; + PVOID InputBuffer; + ULONG InputBufferLength; + IO_STATUS_BLOCK IoStatus; + KEVENT Event; + PIRP NewIrp; NTSTATUS Status; - while (Counter--) { - Status = I8042ReadData(Data); + DPRINT("i8042SendHookWorkItem(%p %p)\n", DeviceObject, Context); - if (STATUS_SUCCESS == Status) - return Status; + WorkItemData = (PI8042_HOOK_WORKITEM)Context; + FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PortDeviceExtension = FdoDeviceExtension->PortDeviceExtension; - KeStallExecutionProcessor(50); - } - // Timed out - return STATUS_IO_TIMEOUT; -} - -VOID I8042Flush() -{ - UCHAR Ignore; - - while (STATUS_SUCCESS == I8042ReadData(&Ignore)) { - DPRINT("Data flushed\n"); /* drop */ - } -} - -VOID STDCALL I8042IsrWritePort(PDEVICE_EXTENSION DevExt, - UCHAR Value, - UCHAR SelectCmd) -{ - if (SelectCmd) - if (!I8042Write(DevExt, I8042_CTRL_PORT, SelectCmd)) - return; - - I8042Write(DevExt, I8042_DATA_PORT, Value); -} - -/* - * These functions are callbacks for filter driver custom - * initialization routines. - */ -NTSTATUS STDCALL I8042SynchWritePort(PDEVICE_EXTENSION DevExt, - UCHAR Port, - UCHAR Value, - BOOLEAN WaitForAck) -{ - NTSTATUS Status; - UCHAR Ack; - ULONG ResendIterations = DevExt->Settings.ResendIterations + 1; - - do { - if (Port) - if (!I8042Write(DevExt, I8042_DATA_PORT, Port)) - { - DPRINT1("Failed to write Port\n"); - return STATUS_IO_TIMEOUT; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) + switch (FdoDeviceExtension->Type) + { + case Keyboard: { - DPRINT1("Failed to write Value\n"); - return STATUS_IO_TIMEOUT; + PI8042_KEYBOARD_EXTENSION DeviceExtension; + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)FdoDeviceExtension; + IoControlCode = IOCTL_INTERNAL_I8042_HOOK_KEYBOARD; + InputBuffer = &DeviceExtension->KeyboardHook; + InputBufferLength = sizeof(INTERNAL_I8042_HOOK_KEYBOARD); + break; } + case Mouse: + { + PI8042_MOUSE_EXTENSION DeviceExtension; + DeviceExtension = (PI8042_MOUSE_EXTENSION)FdoDeviceExtension; + IoControlCode = IOCTL_INTERNAL_I8042_HOOK_MOUSE; + InputBuffer = &DeviceExtension->MouseHook; + InputBufferLength = sizeof(INTERNAL_I8042_HOOK_MOUSE); + break; + } + default: + { + DPRINT1("Unknown FDO type %u\n", FdoDeviceExtension->Type); + ASSERT(FALSE); + WorkItemData->Irp->IoStatus.Status = STATUS_INTERNAL_ERROR; + goto cleanup; + } + } - if (WaitForAck) { - Status = I8042ReadDataWait(DevExt, &Ack); + KeInitializeEvent(&Event, NotificationEvent, FALSE); + TopOfStack = IoGetAttachedDeviceReference(DeviceObject); + + NewIrp = IoBuildDeviceIoControlRequest( + IoControlCode, + TopOfStack, + InputBuffer, + InputBufferLength, + NULL, + 0, + TRUE, + &Event, + &IoStatus); + + if (!NewIrp) + { + DPRINT("IoBuildDeviceIoControlRequest() failed\n"); + WorkItemData->Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = IoCallDriver(TopOfStack, NewIrp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject( + &Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatus.Status; + } + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCallDriver() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + if (FdoDeviceExtension->Type == Keyboard) + { + PI8042_KEYBOARD_EXTENSION DeviceExtension; + + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)FdoDeviceExtension; + /* Call the hooked initialization if it exists */ + if (DeviceExtension->KeyboardHook.InitializationRoutine) + { + Status = DeviceExtension->KeyboardHook.InitializationRoutine( + DeviceExtension->KeyboardHook.Context, + PortDeviceExtension, + i8042SynchReadPort, + i8042SynchWritePortKbd, + FALSE); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to read Ack\n"); - return Status; + DPRINT("KeyboardHook.InitializationRoutine() failed with status 0x%08lx\n", Status); + WorkItemData->Irp->IoStatus.Status = Status; + goto cleanup; } - if (Ack == KBD_ACK) - return STATUS_SUCCESS; - if (Ack != KBD_RESEND) - { - DPRINT1("Unexpected Ack 0x%x\n", Ack); - return STATUS_UNEXPECTED_IO_ERROR; - } - } else { - return STATUS_SUCCESS; } - DPRINT("Reiterating\n"); - ResendIterations--; - } while (ResendIterations); - return STATUS_IO_TIMEOUT; + } +#if 0 + else + { + /* Mouse doesn't have this, but we need to send a + * reset to start the detection. + */ + KIRQL Irql; + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + + i8042Write(PortDeviceExtension, PortDeviceExtension->ControlPort, CTRL_WRITE_MOUSE); + i8042Write(PortDeviceExtension, PortDeviceExtension->DataPort, MOU_CMD_RESET); + + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); + } +#endif + + WorkItemData->Irp->IoStatus.Status = STATUS_SUCCESS; + +cleanup: + if (TopOfStack != NULL) + ObDereferenceObject(TopOfStack); + WorkItemData->Irp->IoStatus.Information = 0; + IoCompleteRequest(WorkItemData->Irp, IO_NO_INCREMENT); + + IoFreeWorkItem(WorkItemData->WorkItem); + ExFreePool(WorkItemData); } -/* - * This one reads a value from the port; You don't have to specify - * which one, it'll always be from the one you talked to, so one function - * is enough this time. Note how MSDN specifies the - * WaitForAck parameter to be ignored. - */ -static NTSTATUS STDCALL I8042SynchReadPort(PVOID Context, - PUCHAR Value, - BOOLEAN WaitForAck) +static VOID NTAPI +i8042StartIo( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)Context; + PFDO_DEVICE_EXTENSION DeviceExtension; - return I8042ReadDataWait(DevExt, Value); + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + switch (DeviceExtension->Type) + { + case Keyboard: + i8042KbdStartIo(DeviceObject, Irp); + break; + default: + DPRINT1("Unknown FDO type %u\n", DeviceExtension->Type); + ASSERT(FALSE); + break; + } } /* Write the current byte of the packet. Returns FALSE in case * of problems. */ -static BOOLEAN STDCALL I8042PacketWrite(PDEVICE_EXTENSION DevExt) +static BOOLEAN +i8042PacketWrite( + IN PPORT_DEVICE_EXTENSION DeviceExtension) { - UCHAR Port = DevExt->PacketPort; + UCHAR Port = DeviceExtension->PacketPort; - if (Port) { - if (!I8042Write(DevExt, - I8042_CTRL_PORT, - Port)) { + if (Port) + { + if (!i8042Write(DeviceExtension, + DeviceExtension->ControlPort, + Port)) + { /* something is really wrong! */ DPRINT1("Failed to send packet byte!\n"); return FALSE; } } - return I8042Write(DevExt, - I8042_DATA_PORT, - DevExt->Packet.Bytes[DevExt->Packet.CurrentByte]); + return i8042Write(DeviceExtension, + DeviceExtension->DataPort, + DeviceExtension->Packet.Bytes[DeviceExtension->Packet.CurrentByte]); } +BOOLEAN +i8042PacketIsr( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Output) +{ + if (DeviceExtension->Packet.State == Idle) + return FALSE; + + switch (Output) + { + case KBD_RESEND: + DeviceExtension->PacketResends++; + if (DeviceExtension->PacketResends > DeviceExtension->Settings.ResendIterations) + { + DeviceExtension->Packet.State = Idle; + DeviceExtension->PacketComplete = TRUE; + DeviceExtension->PacketResult = STATUS_IO_TIMEOUT; + DeviceExtension->PacketResends = 0; + return TRUE; + } + DeviceExtension->Packet.CurrentByte--; + break; + + case KBD_NACK: + DeviceExtension->Packet.State = Idle; + DeviceExtension->PacketComplete = TRUE; + DeviceExtension->PacketResult = STATUS_UNEXPECTED_IO_ERROR; + DeviceExtension->PacketResends = 0; + return TRUE; + + default: + DeviceExtension->PacketResends = 0; + } + + if (DeviceExtension->Packet.CurrentByte >= DeviceExtension->Packet.ByteCount) + { + DeviceExtension->Packet.State = Idle; + DeviceExtension->PacketComplete = TRUE; + DeviceExtension->PacketResult = STATUS_SUCCESS; + return TRUE; + } + + if (!i8042PacketWrite(DeviceExtension)) + { + DeviceExtension->Packet.State = Idle; + DeviceExtension->PacketComplete = TRUE; + DeviceExtension->PacketResult = STATUS_IO_TIMEOUT; + return TRUE; + } + DeviceExtension->Packet.CurrentByte++; + + return TRUE; +} /* * This function starts a packet. It must be called with the * correct DIRQL. */ -NTSTATUS STDCALL I8042StartPacket(PDEVICE_EXTENSION DevExt, - PDEVICE_OBJECT Device, - PUCHAR Bytes, - ULONG ByteCount, - PIRP Irp) +NTSTATUS +i8042StartPacket( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN PFDO_DEVICE_EXTENSION FdoDeviceExtension, + IN PUCHAR Bytes, + IN ULONG ByteCount, + IN PIRP Irp) { KIRQL Irql; NTSTATUS Status; - PFDO_DEVICE_EXTENSION FdoDevExt = Device->DeviceExtension; - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); + Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); - DevExt->CurrentIrp = Irp; - DevExt->CurrentIrpDevice = Device; - - if (Idle != DevExt->Packet.State) { + if (DeviceExtension->Packet.State != Idle) + { Status = STATUS_DEVICE_BUSY; - goto startpacketdone; + goto done; } - DevExt->Packet.Bytes = Bytes; - DevExt->Packet.CurrentByte = 0; - DevExt->Packet.ByteCount = ByteCount; - DevExt->Packet.State = SendingBytes; - DevExt->PacketResult = Status = STATUS_PENDING; + switch (FdoDeviceExtension->Type) + { + case Keyboard: DeviceExtension->PacketPort = 0; break; + case Mouse: DeviceExtension->PacketPort = CTRL_WRITE_MOUSE; break; + default: + DPRINT1("Unknown FDO type %u\n", FdoDeviceExtension->Type); + ASSERT(FALSE); + Status = STATUS_INTERNAL_ERROR; + goto done; + } - if (Mouse == FdoDevExt->Type) - DevExt->PacketPort = 0xD4; - else - DevExt->PacketPort = 0; + DeviceExtension->Packet.Bytes = Bytes; + DeviceExtension->Packet.CurrentByte = 0; + DeviceExtension->Packet.ByteCount = ByteCount; + DeviceExtension->Packet.State = SendingBytes; + DeviceExtension->PacketResult = Status = STATUS_PENDING; + DeviceExtension->CurrentIrp = Irp; + DeviceExtension->CurrentIrpDevice = FdoDeviceExtension->Fdo; - if (!I8042PacketWrite(DevExt)) { + if (!i8042PacketWrite(DeviceExtension)) + { Status = STATUS_IO_TIMEOUT; - DevExt->Packet.State = Idle; - DevExt->PacketResult = STATUS_ABANDONED; - goto startpacketdone; + DeviceExtension->Packet.State = Idle; + DeviceExtension->PacketResult = STATUS_ABANDONED; + goto done; } - DevExt->Packet.CurrentByte++; + DeviceExtension->Packet.CurrentByte++; -startpacketdone: - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); +done: + KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); - if (STATUS_PENDING != Status) { - DevExt->CurrentIrp = NULL; - DevExt->CurrentIrpDevice = NULL; + if (Status != STATUS_PENDING) + { + DeviceExtension->CurrentIrp = NULL; + DeviceExtension->CurrentIrpDevice = NULL; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; } -BOOLEAN STDCALL I8042PacketIsr(PDEVICE_EXTENSION DevExt, - UCHAR Output) +static NTSTATUS NTAPI +IrpStub( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - if (Idle == DevExt->Packet.State) - return FALSE; - - switch (Output) { - case KBD_RESEND: - DevExt->PacketResends++; - if (DevExt->PacketResends > DevExt->Settings.ResendIterations) { - DevExt->Packet.State = Idle; - DevExt->PacketComplete = TRUE; - DevExt->PacketResult = STATUS_IO_TIMEOUT; - DevExt->PacketResends = 0; - return TRUE; - } - DevExt->Packet.CurrentByte--; - break; - - case KBD_NACK: - DevExt->Packet.State = Idle; - DevExt->PacketComplete = TRUE; - DevExt->PacketResult = STATUS_UNEXPECTED_IO_ERROR; - DevExt->PacketResends = 0; - return TRUE; - - default: - DevExt->PacketResends = 0; - } - - if (DevExt->Packet.CurrentByte >= DevExt->Packet.ByteCount) { - DevExt->Packet.State = Idle; - DevExt->PacketComplete = TRUE; - DevExt->PacketResult = STATUS_SUCCESS; - return TRUE; - } - - if (!I8042PacketWrite(DevExt)) { - DevExt->Packet.State = Idle; - DevExt->PacketComplete = TRUE; - DevExt->PacketResult = STATUS_IO_TIMEOUT; - return TRUE; - } - DevExt->Packet.CurrentByte++; - - return TRUE; + KEBUGCHECK(0); + return STATUS_NOT_IMPLEMENTED; } -VOID I8042PacketDpc(PDEVICE_EXTENSION DevExt) +static NTSTATUS NTAPI +i8042DeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - BOOLEAN FinishIrp = FALSE; - NTSTATUS Result = STATUS_INTERNAL_ERROR; /* Shouldn't happen */ - KIRQL Irql; - - /* If the interrupt happens before this is setup, the key - * was already in the buffer. Too bad! */ - if (!DevExt->HighestDIRQLInterrupt) - return; - - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); - - if (Idle == DevExt->Packet.State && - DevExt->PacketComplete) { - FinishIrp = TRUE; - Result = DevExt->PacketResult; - DevExt->PacketComplete = FALSE; - } - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, - Irql); - - if (!FinishIrp) - return; - - if (DevExt->CurrentIrp) { - DevExt->CurrentIrp->IoStatus.Status = Result; - IoCompleteRequest(DevExt->CurrentIrp, IO_NO_INCREMENT); - IoStartNextPacket(DevExt->CurrentIrpDevice, FALSE); - DevExt->CurrentIrp = NULL; - DevExt->CurrentIrpDevice = NULL; - } -} - -VOID STDCALL I8042SendHookWorkItem(PDEVICE_OBJECT DeviceObject, - PVOID Context) -{ - KEVENT Event; - IO_STATUS_BLOCK IoStatus; + PFDO_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; - PDEVICE_EXTENSION DevExt; - PFDO_DEVICE_EXTENSION FdoDevExt; - PIRP NewIrp; - PI8042_HOOK_WORKITEM WorkItemData = (PI8042_HOOK_WORKITEM)Context; - ULONG IoControlCode; - PVOID InputBuffer; - ULONG InputBufferLength; - BOOLEAN IsKbd; + DPRINT("i8042DeviceControl(%p %p)\n", DeviceObject, Irp); + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - DPRINT("HookWorkItem\n"); - - FdoDevExt = (PFDO_DEVICE_EXTENSION) - DeviceObject->DeviceExtension; - - DevExt = FdoDevExt->PortDevExt; - - if (WorkItemData->Target == DevExt->KeyboardData.ClassDeviceObject) { - IoControlCode = IOCTL_INTERNAL_I8042_HOOK_KEYBOARD; - InputBuffer = &DevExt->KeyboardHook; - InputBufferLength = sizeof(INTERNAL_I8042_HOOK_KEYBOARD); - IsKbd = TRUE; - DPRINT ("is for keyboard.\n"); - } else if (WorkItemData->Target == DevExt->MouseData.ClassDeviceObject){ - IoControlCode = IOCTL_INTERNAL_I8042_HOOK_MOUSE; - InputBuffer = &DevExt->MouseHook; - InputBufferLength = sizeof(INTERNAL_I8042_HOOK_MOUSE); - IsKbd = FALSE; - DPRINT ("is for mouse.\n"); - } else { - DPRINT1("I8042SendHookWorkItem: Can't find DeviceObject\n"); - WorkItemData->Irp->IoStatus.Status = STATUS_INTERNAL_ERROR; - goto hookworkitemdone; + switch (DeviceExtension->Type) + { + case Keyboard: + return i8042KbdDeviceControl(DeviceObject, Irp); + break; + default: + return IrpStub(DeviceObject, Irp); } - KeInitializeEvent(&Event, NotificationEvent, FALSE); + return Status; +} - NewIrp = IoBuildDeviceIoControlRequest( - IoControlCode, - WorkItemData->Target, - InputBuffer, - InputBufferLength, - NULL, - 0, - TRUE, - &Event, - &IoStatus); +static NTSTATUS NTAPI +i8042InternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + ULONG ControlCode; + NTSTATUS Status; - if (!NewIrp) { - DPRINT("IOCTL_INTERNAL_(device)_CONNECT: " - "Can't allocate IRP\n"); - WorkItemData->Irp->IoStatus.Status = - STATUS_INSUFFICIENT_RESOURCES; - goto hookworkitemdone; - } + DPRINT("i8042InternalDeviceControl(%p %p)\n", DeviceObject, Irp); + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; -#if 0 - Status = IoCallDriver( - WorkItemData->Target, - NewIrp); - - if (STATUS_PENDING == Status) - KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); -#endif - - if (IsKbd) { - /* Call the hooked initialization if it exists */ - if (DevExt->KeyboardHook.InitializationRoutine) { - Status = DevExt->KeyboardHook.InitializationRoutine( - DevExt->KeyboardHook.Context, - DevExt, - I8042SynchReadPort, - I8042SynchWritePortKbd, - FALSE); - if (!NT_SUCCESS(Status)) { - WorkItemData->Irp->IoStatus.Status = Status; - goto hookworkitemdone; + switch (DeviceExtension->Type) + { + case Unknown: + { + ControlCode = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode; + switch (ControlCode) + { + case IOCTL_INTERNAL_KEYBOARD_CONNECT: + Status = i8042KbdInternalDeviceControl(DeviceObject, Irp); + break; + case IOCTL_INTERNAL_MOUSE_CONNECT: + Status = i8042MouInternalDeviceControl(DeviceObject, Irp); + break; + default: + DPRINT1("Unknown IO control code 0x%lx\n", ControlCode); + ASSERT(FALSE); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; } + break; } - /* TODO: Now would be the right time to enable the interrupt */ - - DevExt->KeyboardClaimed = TRUE; - } else { - /* Mouse doesn't have this, but we need to send a - * reset to start the detection. - */ - KIRQL Irql; - - Irql = KeAcquireInterruptSpinLock( - DevExt->HighestDIRQLInterrupt); - - I8042Write(DevExt, I8042_CTRL_PORT, 0xD4); - I8042Write(DevExt, I8042_DATA_PORT, 0xFF); - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); + case Keyboard: + Status = i8042KbdInternalDeviceControl(DeviceObject, Irp); + break; + case Mouse: + Status = i8042MouInternalDeviceControl(DeviceObject, Irp); + break; + default: + DPRINT1("Unknown FDO type %u\n", DeviceExtension->Type); + ASSERT(FALSE); + Status = STATUS_INTERNAL_ERROR; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; } - WorkItemData->Irp->IoStatus.Status = STATUS_SUCCESS; - -hookworkitemdone: - WorkItemData->Irp->IoStatus.Information = 0; - IoCompleteRequest(WorkItemData->Irp, IO_NO_INCREMENT); - - IoFreeWorkItem(WorkItemData->WorkItem); - ExFreePool(WorkItemData); - DPRINT("HookWorkItem done\n"); -} - -static VOID STDCALL I8042StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (!I8042StartIoKbd(DeviceObject, Irp)) { - DPRINT1("Unhandled StartIo!\n"); - } -} - -static NTSTATUS STDCALL I8042InternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - - DPRINT("InternalDeviceControl\n"); - - switch (FdoDevExt->Type) { - case Keyboard: - Status = I8042InternalDeviceControlKbd(DeviceObject, Irp); - break; - case Mouse: - Status = I8042InternalDeviceControlMouse(DeviceObject, Irp); - break; - } - - if (Status == STATUS_INVALID_DEVICE_REQUEST) { - DPRINT1("Invalid internal device request!\n"); - } - - if (Status != STATUS_PENDING) - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; } -static NTSTATUS STDCALL I8042CreateDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +NTSTATUS NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) { + PI8042_DRIVER_EXTENSION DriverExtension; + ULONG i; NTSTATUS Status; - DPRINT ("I8042CreateDispatch\n"); - - Status = STATUS_SUCCESS; - - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} - -static NTSTATUS STDCALL I8042BasicDetect(PDEVICE_EXTENSION DevExt) -{ - NTSTATUS Status; - UCHAR Value = 0; - ULONG Counter; - - DevExt->MouseExists = FALSE; - DevExt->KeyboardExists = FALSE; - - I8042Flush(); - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST)) { - DPRINT1("Writing KBD_SELF_TEST command failed\n"); - return STATUS_IO_TIMEOUT; + Status = IoAllocateDriverObjectExtension( + DriverObject, + DriverObject, + sizeof(I8042_DRIVER_EXTENSION), + (PVOID*)&DriverExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status); + return Status; } + RtlZeroMemory(DriverExtension, sizeof(I8042_DRIVER_EXTENSION)); + KeInitializeSpinLock(&DriverExtension->Port.SpinLock); - // Wait longer? - Counter = 10; - do { - Status = I8042ReadDataWait(DevExt, &Value); - } while ((Counter--) && (STATUS_IO_TIMEOUT == Status)); - - if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to read KBD_SELF_TEST response, status 0x%x\n", - Status); + Status = RtlDuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + RegistryPath, + &DriverExtension->RegistryPath); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status); return Status; } - if (Value != 0x55) { - DPRINT1("Got %x instead of 55\n", Value); - return STATUS_IO_DEVICE_ERROR; - } - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value |= CCB_KBD_DISAB | CCB_MOUSE_DISAB; /* disable keyboard/mouse */ - Value &= ~(CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB); - /* don't enable keyboard and mouse interrupts */ - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - /* - * We used to send a KBD_LINE_TEST command here, but on at least HP - * Pavilion notebooks the response to that command was incorrect. - * So now we just assume that a keyboard is attached. - */ - DevExt->KeyboardExists = TRUE; - - if (I8042Write(DevExt, I8042_CTRL_PORT, MOUSE_LINE_TEST)) + Status = ReadRegistryEntries(RegistryPath, &DriverExtension->Port.Settings); + if (!NT_SUCCESS(Status)) { - Status = I8042ReadDataWait(DevExt, &Value); - if (NT_SUCCESS(Status) && Value == 0) - DevExt->MouseExists = TRUE; + DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status); + return Status; } + DriverObject->DriverExtension->AddDevice = i8042AddDevice; + DriverObject->DriverStartIo = i8042StartIo; + + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + DriverObject->MajorFunction[i] = IrpStub; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = i8042Create; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = i8042Cleanup; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = i8042Close; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = i8042DeviceControl; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = i8042InternalDeviceControl; + DriverObject->MajorFunction[IRP_MJ_PNP] = i8042Pnp; + + if (IsFirstStageSetup()) + return i8042AddLegacyKeyboard(DriverObject, RegistryPath); + return STATUS_SUCCESS; } - -static NTSTATUS STDCALL I8042Initialize(PDEVICE_EXTENSION DevExt) -{ - NTSTATUS Status; - - Status = I8042BasicDetect(DevExt); - if (!NT_SUCCESS(Status)) { - DPRINT1("Basic keyboard detection failed: %x\n", Status); - return Status; - } - - if (DevExt->MouseExists) { - DPRINT("Aux port detected\n"); - DevExt->MouseExists = I8042DetectMouse(DevExt); - } - - if (!DevExt->KeyboardExists) { - DPRINT("Keyboard port not detected\n"); - if (DevExt->Settings.Headless) - /* Act as if it exists regardless */ - DevExt->KeyboardExists = TRUE; - } else { - DPRINT("Keyboard port detected\n"); - DevExt->KeyboardExists = I8042DetectKeyboard(DevExt); - } - - if (DevExt->KeyboardExists) { - DPRINT("Keyboard detected\n"); - I8042KeyboardEnable(DevExt); - I8042KeyboardEnableInterrupt(DevExt); - } - - if (DevExt->MouseExists) { - DPRINT("Mouse detected\n"); - I8042MouseEnable(DevExt); - } - - return STATUS_SUCCESS; -} - -static NTSTATUS -AddRegistryEntry( - IN PCWSTR PortTypeName, - IN PUNICODE_STRING DeviceName, - IN PCWSTR RegistryPath) -{ - UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP"); - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hDeviceMapKey = (HANDLE)-1; - HANDLE hPortKey = (HANDLE)-1; - UNICODE_STRING PortTypeNameU; - NTSTATUS Status; - - InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - RtlInitUnicodeString(&PortTypeNameU, PortTypeName); - InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL); - Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - Status = STATUS_SUCCESS; - -cleanup: - if (hDeviceMapKey != (HANDLE)-1) - ZwClose(hDeviceMapKey); - if (hPortKey != (HANDLE)-1) - ZwClose(hPortKey); - return Status; -} - -static NTSTATUS STDCALL I8042AddDevice(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT Pdo) -{ - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPort8042"); - UNICODE_STRING MouseName = RTL_CONSTANT_STRING(L"\\Device\\PointerPort8042"); - ULONG MappedIrqKeyboard = 0, MappedIrqMouse = 0; - KIRQL DirqlKeyboard = 0; - KIRQL DirqlMouse = 0; - KIRQL DirqlMax; - KAFFINITY Affinity; - NTSTATUS Status; - PDEVICE_EXTENSION DevExt; - PFDO_DEVICE_EXTENSION FdoDevExt; - PDEVICE_OBJECT Fdo; - - DPRINT("I8042AddDevice\n"); - - if (Pdo != NULL) - { - /* Device detected by pnpmgr. Ignore it, as we already have - * detected the keyboard and mouse at first call */ - return STATUS_UNSUCCESSFUL; - } - - Status = IoCreateDevice(DriverObject, - sizeof(DEVICE_EXTENSION), - NULL, - FILE_DEVICE_8042_PORT, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (!NT_SUCCESS(Status)) - return Status; - - DevExt = Fdo->DeviceExtension; - - RtlZeroMemory(DevExt, sizeof(DEVICE_EXTENSION)); - - I8042ReadRegistry(DriverObject, DevExt); - - KeInitializeSpinLock(&DevExt->SpinLock); - InitializeListHead(&DevExt->BusDevices); - - KeInitializeDpc(&DevExt->DpcKbd, - I8042DpcRoutineKbd, - DevExt); - - KeInitializeDpc(&DevExt->DpcMouse, - I8042DpcRoutineMouse, - DevExt); - - KeInitializeDpc(&DevExt->DpcMouseTimeout, - I8042DpcRoutineMouseTimeout, - DevExt); - - KeInitializeTimer(&DevExt->TimerMouseTimeout); - - Status = I8042Initialize(DevExt); - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - if (!NT_SUCCESS(STATUS_SUCCESS)) { - DPRINT1("Initialization failure: %x\n", Status); - return Status; - } - - if (DevExt->KeyboardExists) { - MappedIrqKeyboard = HalGetInterruptVector(Internal, - 0, - 0, - KEYBOARD_IRQ, - &DirqlKeyboard, - &Affinity); - - Status = IoCreateDevice(DriverObject, - sizeof(FDO_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_8042_PORT, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (NT_SUCCESS(Status)) - { - AddRegistryEntry(L"KeyboardPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt"); - FdoDevExt = Fdo->DeviceExtension; - - RtlZeroMemory(FdoDevExt, sizeof(FDO_DEVICE_EXTENSION)); - - FdoDevExt->PortDevExt = DevExt; - FdoDevExt->Type = Keyboard; - FdoDevExt->DeviceObject = Fdo; - - Fdo->Flags |= DO_BUFFERED_IO; - - DevExt->DebugWorkItem = IoAllocateWorkItem(Fdo); - DevExt->KeyboardObject = Fdo; - - DevExt->KeyboardBuffer = ExAllocatePoolWithTag( - NonPagedPool, - DevExt->KeyboardAttributes.InputDataQueueLength * - sizeof(KEYBOARD_INPUT_DATA), - TAG_I8042); - - if (!DevExt->KeyboardBuffer) { - DPRINT1("No memory for keyboardbuffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - InsertTailList(&DevExt->BusDevices, &FdoDevExt->BusDevices); - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - } - else - DevExt->KeyboardExists = FALSE; - } - - if (DevExt->MouseExists) { - MappedIrqMouse = HalGetInterruptVector(Internal, - 0, - 0, - MOUSE_IRQ, - &DirqlMouse, - &Affinity); - - Status = IoCreateDevice(DriverObject, - sizeof(FDO_DEVICE_EXTENSION), - &MouseName, - FILE_DEVICE_8042_PORT, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (NT_SUCCESS(Status)) - { - AddRegistryEntry(L"PointerPort", &MouseName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt"); - FdoDevExt = Fdo->DeviceExtension; - - RtlZeroMemory(FdoDevExt, sizeof(FDO_DEVICE_EXTENSION)); - - FdoDevExt->PortDevExt = DevExt; - FdoDevExt->Type = Mouse; - FdoDevExt->DeviceObject = Fdo; - - Fdo->Flags |= DO_BUFFERED_IO; - DevExt->MouseObject = Fdo; - - DevExt->MouseBuffer = ExAllocatePoolWithTag( - NonPagedPool, - DevExt->MouseAttributes.InputDataQueueLength * - sizeof(MOUSE_INPUT_DATA), - TAG_I8042); - - if (!DevExt->MouseBuffer) { - ExFreePoolWithTag(DevExt->KeyboardBuffer, TAG_I8042); - DPRINT1("No memory for mouse buffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - InsertTailList(&DevExt->BusDevices, &FdoDevExt->BusDevices); - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - } - else - DevExt->MouseExists = FALSE; - } - - if (DirqlKeyboard > DirqlMouse) - DirqlMax = DirqlKeyboard; - else - DirqlMax = DirqlMouse; - - if (DevExt->KeyboardExists) { - Status = IoConnectInterrupt(&DevExt->KeyboardInterruptObject, - I8042InterruptServiceKbd, - (PVOID)DevExt, - &DevExt->SpinLock, - MappedIrqKeyboard, - DirqlKeyboard, - DirqlMax, - LevelSensitive, - FALSE, - Affinity, - FALSE); - - DPRINT("Keyboard Irq Status: %x\n", Status); - } - - if (DevExt->MouseExists) { - Status = IoConnectInterrupt(&DevExt->MouseInterruptObject, - I8042InterruptServiceMouse, - (PVOID)DevExt, - &DevExt->SpinLock, - MappedIrqMouse, - DirqlMouse, - DirqlMax, - LevelSensitive, - FALSE, - Affinity, - FALSE); - - DPRINT("Mouse Irq Status: %x\n", Status); - } - - if (DirqlKeyboard > DirqlMouse) - DevExt->HighestDIRQLInterrupt = DevExt->KeyboardInterruptObject; - else - DevExt->HighestDIRQLInterrupt = DevExt->MouseInterruptObject; - - DPRINT("I8042AddDevice done\n"); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) -/* - * FUNCTION: Module entry point - */ -{ - DPRINT("I8042 Driver 0.0.1\n"); - - I8042RegistryPath.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters"); - I8042RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, - I8042RegistryPath.MaximumLength, - TAG_I8042); - if (I8042RegistryPath.Buffer == NULL) { - - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyUnicodeString(&I8042RegistryPath, RegistryPath); - RtlAppendUnicodeToString(&I8042RegistryPath, L"\\Parameters"); - I8042RegistryPath.Buffer[I8042RegistryPath.Length / sizeof(WCHAR)] = 0; - - - - DriverObject->MajorFunction[IRP_MJ_CREATE] = I8042CreateDispatch; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = - I8042InternalDeviceControl; - - DriverObject->DriverStartIo = I8042StartIo; - DriverObject->DriverExtension->AddDevice = I8042AddDevice; - - return(STATUS_SUCCESS); -} diff --git a/reactos/drivers/input/i8042prt/i8042prt.h b/reactos/drivers/input/i8042prt/i8042prt.h index 9abf7a91883..9df68e61f2b 100644 --- a/reactos/drivers/input/i8042prt/i8042prt.h +++ b/reactos/drivers/input/i8042prt/i8042prt.h @@ -1,39 +1,45 @@ -#ifndef _I8042DRV_H -#define _I8042DRV_H +#ifndef _I8042PRT_H_ +#define _I8042PRT_H_ -#include +#include #include #include - -#ifdef _MSC_VER - #define STDCALL - #define DDKAPI -#endif - -#define KEYBOARD_IRQ 1 -#define MOUSE_IRQ 12 -#define KBD_BUFFER_SIZE 32 - -#define WHEEL_DELTA 120 +#include +#include +#include /*----------------------------------------------------- - * DeviceExtension + * Structures * --------------------------------------------------*/ -typedef struct _COMMAND_CONTEXT + +typedef enum { - int NumInput; - int CurInput; - UCHAR * Input; - int NumOutput; - int CurOutput; - UCHAR * Output; - NTSTATUS Status; + dsStopped, + dsStarted, + dsPaused, + dsRemoved, + dsSurpriseRemoved +} DEVICE_STATE; - BOOLEAN GotAck; - KEVENT Event; - - PVOID DevExt; -} COMMAND_CONTEXT, *PCOMMAND_CONTEXT; +typedef struct _I8042_SETTINGS +{ + /* Registry settings */ + ULONG KeyboardDataQueueSize; /* done */ + UNICODE_STRING KeyboardDeviceBaseName; + ULONG MouseDataQueueSize; /* done */ + ULONG MouseResolution; + ULONG MouseSynchIn100ns; + ULONG NumberOfButtons; + UNICODE_STRING PointerDeviceBaseName; + ULONG PollStatusIterations; /* done */ + ULONG OverrideKeyboardType; + ULONG OverrideKeyboardSubtype; + ULONG PollingIterations; /* done */ + ULONG PollingIterationsMaximum; + ULONG ResendIterations; /* done */ + ULONG SampleRate; + ULONG CrashOnCtrlScroll; /* done */ +} I8042_SETTINGS, *PI8042_SETTINGS; typedef enum _MOUSE_TIMEOUT_STATE { @@ -42,108 +48,47 @@ typedef enum _MOUSE_TIMEOUT_STATE TimeoutCancel } MOUSE_TIMEOUT_STATE, *PMOUSE_TIMEOUT_STATE; -/* TODO: part of this should be in the _ATTRIBUTES structs instead */ -typedef struct _I8042_SETTINGS +typedef struct _INTERRUPT_DATA { - ULONG Headless; /* done */ - ULONG CrashScroll; - ULONG CrashSysRq; /* done */ - ULONG ReportResetErrors; - ULONG PollStatusIterations; /* done */ - ULONG ResendIterations; /* done */ - ULONG PollingIterations; - ULONG PollingIterationsMaximum; - ULONG OverrideKeyboardType; - ULONG OverrideKeyboardSubtype; - ULONG MouseResendStallTime; - ULONG MouseSynchIn100ns; /* done */ - ULONG MouseResolution; /* done */ - ULONG NumberOfButtons; - ULONG EnableWheelDetection; -} I8042_SETTINGS, *PI8042_SETTINGS; + PKINTERRUPT Object; + ULONG Vector; + KIRQL Dirql; + KINTERRUPT_MODE InterruptMode; + BOOLEAN ShareInterrupt; + KAFFINITY Affinity; +} INTERRUPT_DATA, *PINTERRUPT_DATA; -typedef enum _I8042_MOUSE_TYPE +#define WHEEL_DELTA 120 + +struct _I8042_KEYBOARD_EXTENSION; +typedef struct _I8042_KEYBOARD_EXTENSION *PI8042_KEYBOARD_EXTENSION; +struct _I8042_MOUSE_EXTENSION; +typedef struct _I8042_MOUSE_EXTENSION *PI8042_MOUSE_EXTENSION; + +/* PORT_DEVICE_EXTENSION.Flags */ +#define KEYBOARD_PRESENT 0x01 /* A keyboard is attached */ +#define MOUSE_PRESENT 0x02 /* A mouse is attached */ +#define KEYBOARD_CONNECTED 0x04 /* Keyboard received IOCTL_INTERNAL_KEYBOARD_CONNECT */ +#define MOUSE_CONNECTED 0x08 /* Mouse received IOCTL_INTERNAL_MOUSE_CONNECT */ +#define KEYBOARD_STARTED 0x04 /* Keyboard FDO received IRP_MN_START_DEVICE */ +#define MOUSE_STARTED 0x08 /* Mouse FDO received IRP_MN_START_DEVICE */ +#define KEYBOARD_INITIALIZED 0x10 /* Keyboard interrupt is connected */ +#define MOUSE_INITIALIZED 0x20 /* Mouse interrupt is connected */ + +typedef struct _PORT_DEVICE_EXTENSION { - GenericPS2, - Intellimouse, - IntellimouseExplorer, - Ps2pp -} I8042_MOUSE_TYPE, *PI8042_MOUSE_TYPE; + PUCHAR DataPort; /* Usually 0x60 */ + PUCHAR ControlPort; /* Usually 0x64 */ + I8042_SETTINGS Settings; + ULONG Flags; -typedef enum _I8042_DEVICE_TYPE -{ - Keyboard, - Mouse -} I8042_DEVICE_TYPE, *PI8042_DEVICE_TYPE; - -typedef struct _I8042_DEVICE -{ - LIST_ENTRY ListEntry; - PDEVICE_OBJECT Pdo; -} I8042_DEVICE, *PI8042_DEVICE; - -typedef struct _DEVICE_EXTENSION -{ - PDEVICE_OBJECT KeyboardObject; - PDEVICE_OBJECT MouseObject; - - CONNECT_DATA KeyboardData; - CONNECT_DATA MouseData; - - BOOLEAN KeyboardExists; - BOOLEAN KeyboardIsAT; - BOOLEAN MouseExists; - - BOOLEAN KeyboardClaimed; - BOOLEAN MouseClaimed; - - ULONG BusNumber; - LIST_ENTRY BusDevices; - - INTERNAL_I8042_START_INFORMATION KeyboardStartInformation; - INTERNAL_I8042_START_INFORMATION MouseStartInformation; - - INTERNAL_I8042_HOOK_KEYBOARD KeyboardHook; - INTERNAL_I8042_HOOK_MOUSE MouseHook; - - PKINTERRUPT KeyboardInterruptObject; - PKINTERRUPT MouseInterruptObject; + PI8042_KEYBOARD_EXTENSION KeyboardExtension; + INTERRUPT_DATA KeyboardInterrupt; + PI8042_MOUSE_EXTENSION MouseExtension; + INTERRUPT_DATA MouseInterrupt; PKINTERRUPT HighestDIRQLInterrupt; KSPIN_LOCK SpinLock; - KDPC DpcKbd; - KDPC DpcMouse; - - KTIMER TimerMouseTimeout; - KDPC DpcMouseTimeout; - MOUSE_TIMEOUT_STATE MouseTimeoutState; - BOOLEAN MouseTimeoutActive; - - KEYBOARD_ATTRIBUTES KeyboardAttributes; - KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators; - KEYBOARD_TYPEMATIC_PARAMETERS KeyboardTypematic; - - BOOLEAN WantAck; - BOOLEAN WantOutput; - BOOLEAN SignalEvent; - - KEYBOARD_SCAN_STATE KeyboardScanState; - BOOLEAN KeyComplete; - KEYBOARD_INPUT_DATA *KeyboardBuffer; - ULONG KeysInBuffer; - - MOUSE_ATTRIBUTES MouseAttributes; - - MOUSE_STATE MouseState; - BOOLEAN MouseComplete; - MOUSE_RESET_SUBSTATE MouseResetState; - MOUSE_INPUT_DATA *MouseBuffer; - ULONG MouseInBuffer; - USHORT MouseButtonState; - ULARGE_INTEGER MousePacketStartTime; - - UCHAR MouseLogiBuffer[3]; - UCHAR MouseLogitechID; - I8042_MOUSE_TYPE MouseType; + KIRQL HighestDirql; OUTPUT_PACKET Packet; ULONG PacketResends; @@ -154,225 +99,390 @@ typedef struct _DEVICE_EXTENSION PIRP CurrentIrp; PDEVICE_OBJECT CurrentIrpDevice; +} PORT_DEVICE_EXTENSION, *PPORT_DEVICE_EXTENSION; - /* registry config values */ - I8042_SETTINGS Settings; +typedef struct _I8042_DRIVER_EXTENSION +{ + UNICODE_STRING RegistryPath; - /* Debugger stuff */ - BOOLEAN TabPressed; - ULONG DebugKey; - PIO_WORKITEM DebugWorkItem; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + PORT_DEVICE_EXTENSION Port; +} I8042_DRIVER_EXTENSION, *PI8042_DRIVER_EXTENSION; + +typedef enum _I8042_DEVICE_TYPE +{ + Unknown, + Keyboard, + Mouse, + PhysicalDeviceObject +} I8042_DEVICE_TYPE, *PI8042_DEVICE_TYPE; typedef struct _FDO_DEVICE_EXTENSION { - PDEVICE_EXTENSION PortDevExt; I8042_DEVICE_TYPE Type; - PDEVICE_OBJECT DeviceObject; + // Associated device object (FDO) + PDEVICE_OBJECT Fdo; + // Associated device object (PDO) + PDEVICE_OBJECT Pdo; + // Lower device object + PDEVICE_OBJECT LowerDevice; + // Current state of the driver + DEVICE_STATE PnpState; - LIST_ENTRY BusDevices; + PPORT_DEVICE_EXTENSION PortDeviceExtension; } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; +typedef struct _I8042_KEYBOARD_EXTENSION +{ + FDO_DEVICE_EXTENSION Common; + CONNECT_DATA KeyboardData; + INTERNAL_I8042_HOOK_KEYBOARD KeyboardHook; + KDPC DpcKeyboard; + + KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators; + + KEYBOARD_SCAN_STATE KeyboardScanState; + BOOLEAN KeyComplete; + PKEYBOARD_INPUT_DATA KeyboardBuffer; + ULONG KeysInBuffer; + + /* Power keys items */ + ULONG ReportedCaps; + ULONG NewCaps; + ULONG LastPowerKey; + UNICODE_STRING PowerInterfaceName; + PIO_WORKITEM PowerWorkItem; + PIRP PowerIrp; + + /* Debug items */ + ULONG ComboPosition; + PIO_WORKITEM DebugWorkItem; +#ifdef __REACTOS__ + ULONG DebugKey; + BOOLEAN TabPressed; +#endif +} I8042_KEYBOARD_EXTENSION; + +typedef enum _I8042_MOUSE_TYPE +{ + GenericPS2, + Intellimouse, + IntellimouseExplorer, + Ps2pp +} I8042_MOUSE_TYPE, *PI8042_MOUSE_TYPE; + +typedef struct _I8042_MOUSE_EXTENSION +{ + FDO_DEVICE_EXTENSION Common; + CONNECT_DATA MouseData; + INTERNAL_I8042_HOOK_MOUSE MouseHook; + KDPC DpcMouse; + + MOUSE_ATTRIBUTES MouseAttributes; + + MOUSE_STATE MouseState; + BOOLEAN MouseComplete; + MOUSE_RESET_SUBSTATE MouseResetState; + PMOUSE_INPUT_DATA MouseBuffer; + ULONG MouseInBuffer; + USHORT MouseButtonState; + ULARGE_INTEGER MousePacketStartTime; + + KTIMER TimerMouseTimeout; + KDPC DpcMouseTimeout; + MOUSE_TIMEOUT_STATE MouseTimeoutState; + BOOLEAN MouseTimeoutActive; + + UCHAR MouseLogiBuffer[3]; + I8042_MOUSE_TYPE MouseType; +} I8042_MOUSE_EXTENSION; + typedef struct _I8042_HOOK_WORKITEM { PIO_WORKITEM WorkItem; - PDEVICE_OBJECT Target; PIRP Irp; } I8042_HOOK_WORKITEM, *PI8042_HOOK_WORKITEM; -/* +/*----------------------------------------------------- * Some defines - */ -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) -#define TAG_I8042 TAG('8', '0', '4', '2') + * --------------------------------------------------*/ -#define KBD_WRAP_MASK 0x1F +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) -#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) -#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) +#define KEYBOARD_POWER_CODE 0x5E +#define KEYBOARD_SLEEP_CODE 0x5F +#define KEYBOARD_WAKE_CODE 0x63 - -/* - * Keyboard controller ports - */ - -#define I8042_DATA_PORT ((PUCHAR)0x60) -#define I8042_CTRL_PORT ((PUCHAR)0x64) - - -/* +/*----------------------------------------------------- * Controller commands - */ + * --------------------------------------------------*/ #define KBD_READ_MODE 0x20 #define KBD_WRITE_MODE 0x60 -#define KBD_SELF_TEST 0xAA #define KBD_LINE_TEST 0xAB -#define KBD_CTRL_ENABLE 0xAE - #define MOUSE_LINE_TEST 0xA9 -#define MOUSE_CTRL_ENABLE 0xA8 +#define CTRL_SELF_TEST 0xAA +#define CTRL_WRITE_MOUSE 0xD4 -#define KBD_READ_OUTPUT_PORT 0xD0 -#define KBD_WRITE_OUTPUT_PORT 0xD1 - -/* +/*----------------------------------------------------- * Keyboard commands - */ + * --------------------------------------------------*/ -#define KBD_SET_LEDS 0xED -#define KBD_GET_ID 0xF2 -#define KBD_ENABLE 0xF4 -#define KBD_DISABLE 0xF5 -#define KBD_RESET 0xFF +#define KBD_CMD_SET_LEDS 0xED +#define KBD_CMD_GET_ID 0xF2 +/*----------------------------------------------------- + * Keyboard responses + * --------------------------------------------------*/ -/* - * Keyboard responces - */ - -#define KBD_BATCC 0xAA #define KBD_ACK 0xFA #define KBD_NACK 0xFC #define KBD_RESEND 0xFE -/* +/*----------------------------------------------------- * Controller status register bits - */ + * --------------------------------------------------*/ #define KBD_OBF 0x01 #define KBD_IBF 0x02 -#define KBD_AUX 0x10 -#define KBD_GTO 0x40 +#define MOU_OBF 0x20 #define KBD_PERR 0x80 -/* +/*----------------------------------------------------- * Controller command byte bits - */ + * --------------------------------------------------*/ + #define CCB_KBD_INT_ENAB 0x01 #define CCB_MOUSE_INT_ENAB 0x02 #define CCB_SYSTEM_FLAG 0x04 -#define CCB_IGN_KEY_LOCK 0x08 #define CCB_KBD_DISAB 0x10 #define CCB_MOUSE_DISAB 0x20 #define CCB_TRANSLATE 0x40 - -/* +/*----------------------------------------------------- * LED bits - */ + * --------------------------------------------------*/ #define KBD_LED_SCROLL 0x01 #define KBD_LED_NUM 0x02 #define KBD_LED_CAPS 0x04 -/* +/*----------------------------------------------------- + * Mouse commands + * --------------------------------------------------*/ + +#define MOU_CMD_GET_ID 0xF2 +#define MOU_CMD_RESET 0xFF + +/*----------------------------------------------------- * Mouse responses - */ + * --------------------------------------------------*/ + #define MOUSE_ACK 0xFA #define MOUSE_ERROR 0xFC #define MOUSE_NACK 0xFE -/* i8042prt.c */ -extern UNICODE_STRING I8042RegistryPath; +/*----------------------------------------------------- + * Prototypes + * --------------------------------------------------*/ -NTSTATUS I8042ReadData(UCHAR *Data); +/* createclose.c */ -NTSTATUS I8042ReadStatus(UCHAR *Status); +VOID NTAPI +i8042SendHookWorkItem( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context); -NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, UCHAR *Data); +NTSTATUS NTAPI +i8042Create( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -VOID I8042Flush(); +NTSTATUS NTAPI +i8042Cleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -VOID STDCALL I8042IsrWritePort(PDEVICE_EXTENSION DevExt, - UCHAR Value, - UCHAR SelectCmd); - -NTSTATUS STDCALL I8042SynchWritePort(PDEVICE_EXTENSION DevExt, - UCHAR Port, - UCHAR Value, - BOOLEAN WaitForAck); - -NTSTATUS STDCALL I8042StartPacket(PDEVICE_EXTENSION DevExt, - PDEVICE_OBJECT Device, - PUCHAR Bytes, - ULONG ByteCount, - PIRP Irp); - -BOOLEAN STDCALL I8042PacketIsr(PDEVICE_EXTENSION DevExt, - UCHAR Output); - -VOID I8042PacketDpc(PDEVICE_EXTENSION DevExt); - -VOID STDCALL I8042SendHookWorkItem(PDEVICE_OBJECT DeviceObject, - PVOID Context); - -BOOLEAN I8042Write(PDEVICE_EXTENSION DevExt, PUCHAR addr, UCHAR data); - -NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath); +NTSTATUS NTAPI +i8042Close( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); /* keyboard.c */ -VOID STDCALL I8042IsrWritePortKbd(PVOID Context, - UCHAR Value); -NTSTATUS STDCALL I8042SynchWritePortKbd(PVOID Context, - UCHAR Value, - BOOLEAN WaitForAck); +NTSTATUS NTAPI +i8042SynchWritePortKbd( + IN PVOID Context, + IN UCHAR Value, + IN BOOLEAN WaitForAck); -BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt, - VOID * Context); +BOOLEAN +i8042KbdStartIo( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -VOID STDCALL I8042DpcRoutineKbd(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2); +NTSTATUS +i8042KbdDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -BOOLEAN STDCALL I8042StartIoKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS +i8042KbdInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -NTSTATUS STDCALL I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject, - PIRP Irp); +BOOLEAN NTAPI +i8042KbdInterruptService( + IN PKINTERRUPT Interrupt, + PVOID Context); -BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt); +/* i8042prt.c */ -BOOLEAN STDCALL I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt); +NTSTATUS NTAPI +i8042AddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo); -BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt); +BOOLEAN +i8042PacketIsr( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Output); -/* registry.c */ -VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject, - PDEVICE_EXTENSION DevExt); +NTSTATUS +i8042StartPacket( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN PFDO_DEVICE_EXTENSION FdoDeviceExtension, + IN PUCHAR Bytes, + IN ULONG ByteCount, + IN PIRP Irp); + +/* misc.c */ + +NTSTATUS NTAPI +ForwardIrpAndForget( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +ForwardIrpAndWait( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); /* mouse.c */ -VOID STDCALL I8042DpcRoutineMouse(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2); -VOID STDCALL I8042DpcRoutineMouseTimeout(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2); +VOID +i8042MouHandle( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Output); -BOOLEAN STDCALL I8042InterruptServiceMouse(struct _KINTERRUPT *Interrupt, - VOID *Context); +VOID +i8042MouHandleButtons( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN USHORT Mask); -NTSTATUS STDCALL I8042InternalDeviceControlMouse(PDEVICE_OBJECT DeviceObject, - PIRP Irp); +NTSTATUS +i8042MouInitialize( + IN PI8042_MOUSE_EXTENSION DeviceExtension); -VOID STDCALL I8042QueueMousePacket(PVOID Context); +NTSTATUS +i8042MouInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); -VOID STDCALL I8042MouseHandleButtons(PDEVICE_EXTENSION DevExt, - USHORT Mask); +BOOLEAN NTAPI +i8042MouInterruptService( + IN PKINTERRUPT Interrupt, + PVOID Context); -VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt, - UCHAR Output); +VOID NTAPI +i8042MouQueuePacket( + IN PVOID Context); -BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt); -BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt); -BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt); +/* pnp.c */ + +BOOLEAN +i8042ChangeMode( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR FlagsToDisable, + IN UCHAR FlagsToEnable); + +NTSTATUS NTAPI +i8042Pnp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); /* ps2pp.c */ -VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input); +VOID +i8042MouHandlePs2pp( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Input); -#endif // _KEYBOARD_H_ +/* readwrite.c */ + +VOID +i8042Flush( + IN PPORT_DEVICE_EXTENSION DeviceExtension); + +VOID +i8042IsrWritePort( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Value, + IN UCHAR SelectCmd OPTIONAL); + +NTSTATUS +i8042ReadData( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR StatusFlags, + OUT PUCHAR Data); +#define i8042ReadKeyboardData(DeviceExtension, Data) \ + i8042ReadData(DeviceExtension, KBD_OBF, Data) +#define i8042ReadMouseData(DeviceExtension, Data) \ + i8042ReadData(DeviceExtension, MOU_OBF, Data) + +NTSTATUS +i8042ReadDataWait( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + OUT PUCHAR Data); + +NTSTATUS +i8042ReadStatus( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + OUT PUCHAR Status); + +NTSTATUS NTAPI +i8042SynchReadPort( + IN PVOID Context, + IN PUCHAR Value, + IN BOOLEAN WaitForAck); + +NTSTATUS NTAPI +i8042SynchWritePort( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Port, + IN UCHAR Value, + IN BOOLEAN WaitForAck); + +BOOLEAN +i8042Write( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN PUCHAR addr, + IN UCHAR data); + +/* registry.c */ + +NTSTATUS +ReadRegistryEntries( + IN PUNICODE_STRING RegistryPath, + OUT PI8042_SETTINGS Settings); + +/* setup.c */ + +BOOLEAN +IsFirstStageSetup( + VOID); + +NTSTATUS +i8042AddLegacyKeyboard( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath); + +#endif // _I8042PRT_H_ diff --git a/reactos/drivers/input/i8042prt/i8042prt.rbuild b/reactos/drivers/input/i8042prt/i8042prt.rbuild index ca4085c16de..1c4a264012b 100644 --- a/reactos/drivers/input/i8042prt/i8042prt.rbuild +++ b/reactos/drivers/input/i8042prt/i8042prt.rbuild @@ -1,14 +1,18 @@ - . ntoskrnl hal + createclose.c i8042prt.c keyboard.c + misc.c mouse.c + pnp.c ps2pp.c + readwrite.c registry.c + setup.c i8042prt.rc diff --git a/reactos/drivers/input/i8042prt/i8042prt.rc b/reactos/drivers/input/i8042prt/i8042prt.rc index 6c44176265e..eaed77a9427 100644 --- a/reactos/drivers/input/i8042prt/i8042prt.rc +++ b/reactos/drivers/input/i8042prt/i8042prt.rc @@ -1,5 +1,5 @@ #define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "I8042 Port Device Driver\0" +#define REACTOS_STR_FILE_DESCRIPTION "i8042 Port Device Driver\0" #define REACTOS_STR_INTERNAL_NAME "i8042prt\0" #define REACTOS_STR_ORIGINAL_FILENAME "i8042prt.sys\0" #include diff --git a/reactos/drivers/input/i8042prt/keyboard.c b/reactos/drivers/input/i8042prt/keyboard.c index a301d2ee129..132ef7bd1ae 100644 --- a/reactos/drivers/input/i8042prt/keyboard.c +++ b/reactos/drivers/input/i8042prt/keyboard.c @@ -1,12 +1,12 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/input/i8042prt/keyboard.c - * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver - * keyboard specifics - * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) - * Tinus + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/keyboard.c + * PURPOSE: Keyboard specific functions + * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) + Copyright Jason Filby (jasonfilby@yahoo.com) + Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ /* INCLUDES ****************************************************************/ @@ -18,11 +18,7 @@ /* GLOBALS *******************************************************************/ -static UCHAR TypematicTable[] = { - 0x00, 0x00, 0x00, 0x05, 0x08, 0x0B, 0x0D, 0x0F, 0x10, 0x12, /* 0-9 */ - 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1A, /* 10-19 */ - 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E }; - +/* This structure starts with the same layout as KEYBOARD_INDICATOR_TRANSLATION */ typedef struct _LOCAL_KEYBOARD_INDICATOR_TRANSLATION { USHORT NumberOfIndicatorKeys; INDICATOR_LIST IndicatorList[3]; @@ -33,101 +29,803 @@ static LOCAL_KEYBOARD_INDICATOR_TRANSLATION IndicatorTranslation = { 3, { {0x45, KEYBOARD_NUM_LOCK_ON}, {0x46, KEYBOARD_SCROLL_LOCK_ON}}}; -static VOID STDCALL I8042DebugWorkItem(PDEVICE_OBJECT DeviceObject, - PVOID Context); - /* FUNCTIONS *****************************************************************/ +#ifdef __REACTOS__ +/* Debug stuff */ +VOID NTAPI +KdpServiceDispatcher(IN ULONG Code, IN PVOID Context1, IN PVOID Context2); +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +static VOID NTAPI +i8042DebugWorkItem( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + PI8042_KEYBOARD_EXTENSION DeviceExtension; + ULONG Key; + + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; + Key = InterlockedExchange((PLONG)&DeviceExtension->DebugKey, 0); + + DPRINT("Debug key: 0x%02x\n", Key); + + if (!Key) + return; + + /* We hope kernel would understand this. If + * that's not the case, nothing would happen. + */ + KdpServiceDispatcher(TAG('R', 'o', 's', ' '), (PVOID)Key, NULL); +} +#endif + /* * These functions are callbacks for filter driver custom interrupt * service routines. */ -VOID STDCALL I8042IsrWritePortKbd(PVOID Context, - UCHAR Value) +/*static VOID NTAPI +i8042KbdIsrWritePort( + IN PVOID Context, + IN UCHAR Value) { - I8042IsrWritePort(Context, Value, 0); -} + PI8042_KEYBOARD_EXTENSION DeviceExtension; -static VOID STDCALL I8042QueueKeyboardPacket(PVOID Context) + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; + + if (DeviceExtension->KeyboardHook.IsrWritePort) + { + DeviceExtension->KeyboardHook.IsrWritePort( + DeviceExtension->KeyboardHook.CallContext, + Value); + } + else + i8042IsrWritePort(Context, Value, 0); +}*/ + +static VOID NTAPI +i8042KbdQueuePacket( + IN PVOID Context) { - PDEVICE_OBJECT DeviceObject = Context; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; + PI8042_KEYBOARD_EXTENSION DeviceExtension; - DevExt->KeyComplete = TRUE; - DevExt->KeysInBuffer++; - if (DevExt->KeysInBuffer > - DevExt->KeyboardAttributes.InputDataQueueLength) { + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; + + if (DeviceExtension->KeyboardHook.QueueKeyboardPacket) + { + DeviceExtension->KeyboardHook.QueueKeyboardPacket( + DeviceExtension->KeyboardHook.CallContext); + return; + } + + DeviceExtension->KeyComplete = TRUE; + DeviceExtension->KeysInBuffer++; + if (DeviceExtension->KeysInBuffer > DeviceExtension->Common.PortDeviceExtension->Settings.KeyboardDataQueueSize) + { DPRINT1("Keyboard buffer overflow\n"); - DevExt->KeysInBuffer--; + DeviceExtension->KeysInBuffer--; } DPRINT("Irq completes key\n"); - KeInsertQueueDpc(&DevExt->DpcKbd, DevExt, NULL); + KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL); } /* * These functions are callbacks for filter driver custom * initialization routines. */ -NTSTATUS STDCALL I8042SynchWritePortKbd(PVOID Context, - UCHAR Value, - BOOLEAN WaitForAck) +NTSTATUS NTAPI +i8042SynchWritePortKbd( + IN PVOID Context, + IN UCHAR Value, + IN BOOLEAN WaitForAck) { - return I8042SynchWritePort((PDEVICE_EXTENSION)Context, - 0, - Value, - WaitForAck); + return i8042SynchWritePort( + (PPORT_DEVICE_EXTENSION)Context, + 0, + Value, + WaitForAck); } -BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt, - VOID * Context) +/* + * Process the keyboard internal device requests + * returns FALSE if it doesn't understand the + * call so someone else can handle it. + */ +BOOLEAN +i8042KbdStartIo( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UCHAR Output; - UCHAR PortStatus; + PIO_STACK_LOCATION Stack; + PI8042_KEYBOARD_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + BOOLEAN Result = FALSE; + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_KEYBOARD_SET_INDICATORS: + { + DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n"); + + PortDeviceExtension->PacketBuffer[0] = KBD_CMD_SET_LEDS; + PortDeviceExtension->PacketBuffer[1] = 0; + if (DeviceExtension->KeyboardIndicators.LedFlags & KEYBOARD_CAPS_LOCK_ON) + PortDeviceExtension->PacketBuffer[1] |= KBD_LED_CAPS; + + if (DeviceExtension->KeyboardIndicators.LedFlags & KEYBOARD_NUM_LOCK_ON) + PortDeviceExtension->PacketBuffer[1] |= KBD_LED_NUM; + + if (DeviceExtension->KeyboardIndicators.LedFlags & KEYBOARD_SCROLL_LOCK_ON) + PortDeviceExtension->PacketBuffer[1] |= KBD_LED_SCROLL; + + i8042StartPacket( + PortDeviceExtension, + &DeviceExtension->Common, + PortDeviceExtension->PacketBuffer, + 2, + Irp); + break; + } + default: + { + DPRINT("Unknown ioctl code 0x%lx\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + } + } + + return Result; +} + +static VOID +i8042PacketDpc( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + BOOLEAN FinishIrp = FALSE; + KIRQL Irql; + NTSTATUS Result = STATUS_INTERNAL_ERROR; /* Shouldn't happen */ + + /* If the interrupt happens before this is setup, the key + * was already in the buffer. Too bad! */ + if (!DeviceExtension->HighestDIRQLInterrupt) + return; + + Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); + + if (DeviceExtension->Packet.State == Idle + && DeviceExtension->PacketComplete) + { + FinishIrp = TRUE; + Result = DeviceExtension->PacketResult; + DeviceExtension->PacketComplete = FALSE; + } + + KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); + + if (!FinishIrp) + return; + + if (DeviceExtension->CurrentIrp) + { + DeviceExtension->CurrentIrp->IoStatus.Status = Result; + IoCompleteRequest(DeviceExtension->CurrentIrp, IO_NO_INCREMENT); + IoStartNextPacket(DeviceExtension->CurrentIrpDevice, FALSE); + DeviceExtension->CurrentIrp = NULL; + DeviceExtension->CurrentIrpDevice = NULL; + } +} + +static VOID NTAPI +i8042PowerWorkItem( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + PI8042_KEYBOARD_EXTENSION DeviceExtension; NTSTATUS Status; - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION) Context; - BOOLEAN HookContinue = FALSE, HookReturn; - ULONG Iterations = 0; - KEYBOARD_INPUT_DATA *InputData = - DevExt->KeyboardBuffer + DevExt->KeysInBuffer; + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; - do { - Status = I8042ReadStatus(&PortStatus); - DPRINT("PortStatus: %x\n", PortStatus); - Status = I8042ReadData(&Output); - Iterations++; - if (STATUS_SUCCESS == Status) + /* See http://blogs.msdn.com/doronh/archive/2006/09/08/746961.aspx */ + + /* Register GUID_DEVICE_SYS_BUTTON interface and report capability */ + if (DeviceExtension->NewCaps != DeviceExtension->ReportedCaps) + { + if (DeviceExtension->PowerInterfaceName.MaximumLength == 0) + { + /* We have never registred this interface ; do it */ + Status = IoRegisterDeviceInterface( + DeviceExtension->Common.Pdo, + &GUID_DEVICE_SYS_BUTTON, + NULL, + &DeviceExtension->PowerInterfaceName); + if (!NT_SUCCESS(Status)) + { + /* We can't do more yet, ignore the keypress... */ + DPRINT("IoRegisterDeviceInterface(GUID_DEVICE_SYS_BUTTON) failed with status 0x%08lx\n", + Status); + DeviceExtension->PowerInterfaceName.MaximumLength = 0; + return; + } + } + else + { + /* Disable the interface. Once activated again, capabilities would be asked again */ + Status = IoSetDeviceInterfaceState( + &DeviceExtension->PowerInterfaceName, + FALSE); + if (!NT_SUCCESS(Status)) + { + /* Ignore the key press... */ + DPRINT("Disabling interface %wZ failed with status 0x%08lx\n", + &DeviceExtension->PowerInterfaceName, Status); + return; + } + } + /* Enable the interface. This leads to receving a IOCTL_GET_SYS_BUTTON_CAPS, + * so we can report new capability */ + Status = IoSetDeviceInterfaceState( + &DeviceExtension->PowerInterfaceName, + TRUE); + if (!NT_SUCCESS(Status)) + { + /* Ignore the key press... */ + DPRINT("Enabling interface %wZ failed with status 0x%08lx\n", + &DeviceExtension->PowerInterfaceName, Status); + return; + } + } + + /* Directly complete the IOCTL_GET_SYS_BUTTON_EVENT Irp (if any) */ + if (DeviceExtension->PowerIrp) + { + PULONG pEvent = (PULONG)DeviceExtension->PowerIrp->AssociatedIrp.SystemBuffer; + + DeviceExtension->PowerIrp->IoStatus.Status = STATUS_SUCCESS; + DeviceExtension->PowerIrp->IoStatus.Information = sizeof(ULONG); + *pEvent = DeviceExtension->LastPowerKey; + + IoCompleteRequest(DeviceExtension->PowerIrp, IO_NO_INCREMENT); + DeviceExtension->PowerIrp = NULL; + } +} + +/* Return TRUE if it was a power key */ +static BOOLEAN +HandlePowerKeys( + IN PI8042_KEYBOARD_EXTENSION DeviceExtension) +{ + PKEYBOARD_INPUT_DATA InputData; + ULONG KeyPress; + + InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer - 1; + if (!(InputData->Flags & KEY_E0)) + return FALSE; + + if (InputData->Flags & KEY_BREAK) + /* We already took care of the key press */ + return TRUE; + + switch (InputData->MakeCode) + { + case 0x52: /* VK_INSERT */ + DPRINT1("FIXME: Remove debug code\n"); + case KEYBOARD_POWER_CODE: + KeyPress = SYS_BUTTON_POWER; + break; + case KEYBOARD_SLEEP_CODE: + KeyPress = SYS_BUTTON_SLEEP; + break; + + case KEYBOARD_WAKE_CODE: + KeyPress = SYS_BUTTON_WAKE; + break; + default: + return FALSE; + } + + /* Our work can only be done at passive level, so use a workitem */ + DeviceExtension->NewCaps |= KeyPress; + DeviceExtension->LastPowerKey = KeyPress; + IoQueueWorkItem( + DeviceExtension->PowerWorkItem, + &i8042PowerWorkItem, + DelayedWorkQueue, + DeviceExtension); + return TRUE; +} + +static VOID NTAPI +i8042KbdDpcRoutine( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PI8042_KEYBOARD_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + ULONG KeysTransferred = 0; + ULONG KeysInBufferCopy; + KIRQL Irql; + + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeferredContext; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + + if (HandlePowerKeys(DeviceExtension)) + { + DeviceExtension->KeyComplete = FALSE; + return; + } + + i8042PacketDpc(PortDeviceExtension); + if (!DeviceExtension->KeyComplete) + return; + /* We got the interrupt as it was being enabled, too bad */ + if (!PortDeviceExtension->HighestDIRQLInterrupt) + return; + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + + DeviceExtension->KeyComplete = FALSE; + KeysInBufferCopy = DeviceExtension->KeysInBuffer; + + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); + +#ifdef __REACTOS__ + if (PortDeviceExtension->Settings.CrashOnCtrlScroll) + { + PKEYBOARD_INPUT_DATA InputData; + InputData = DeviceExtension->KeyboardBuffer + KeysInBufferCopy - 1; + + /* Test for TAB + key combination */ + if (InputData->MakeCode == 0x0F) + DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK); + else if (DeviceExtension->TabPressed) + { + DeviceExtension->DebugKey = InputData->MakeCode; + DeviceExtension->TabPressed = FALSE; + + IoQueueWorkItem( + DeviceExtension->DebugWorkItem, + &i8042DebugWorkItem, + DelayedWorkQueue, + DeviceExtension); + } + } +#endif + + DPRINT("Send a key\n"); + + if (!DeviceExtension->KeyboardData.ClassService) + return; + + DPRINT("Sending %lu key(s)\n", KeysInBufferCopy); + (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->KeyboardData.ClassService)( + DeviceExtension->KeyboardData.ClassDeviceObject, + DeviceExtension->KeyboardBuffer, + DeviceExtension->KeyboardBuffer + KeysInBufferCopy, + &KeysTransferred); + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + DeviceExtension->KeysInBuffer -= KeysTransferred; + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); +} + +#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) + +/* + * Runs the keyboard IOCTL dispatch. + */ +NTSTATUS +i8042KbdDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PI8042_KEYBOARD_EXTENSION DeviceExtension; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + Irp->IoStatus.Information = 0; + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_GET_SYS_BUTTON_CAPS: + { + /* Part of GUID_DEVICE_SYS_BUTTON interface */ + PULONG pCaps; + DPRINT("IOCTL_GET_SYS_BUTTON_CAPS\n"); + + if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG)) + Status = STATUS_INVALID_PARAMETER; + else + { + pCaps = (PULONG)Irp->AssociatedIrp.SystemBuffer; + *pCaps = DeviceExtension->NewCaps; + DeviceExtension->ReportedCaps = DeviceExtension->NewCaps; + Irp->IoStatus.Information = sizeof(ULONG); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_GET_SYS_BUTTON_EVENT: + { + /* Part of GUID_DEVICE_SYS_BUTTON interface */ + PIRP WaitingIrp; + DPRINT("IOCTL_GET_SYS_BUTTON_EVENT\n"); + + if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG)) + Status = STATUS_INVALID_PARAMETER; + else + { + /* FIXME: Race condition here: + * If an interrupt comes before we can mark the Irp + * as pending, it might be possible to complete the + * Irp before pending it, leading to a crash! */ + WaitingIrp = InterlockedCompareExchangePointer( + &DeviceExtension->PowerIrp, + Irp, + NULL); + /* Check if an Irp is already pending */ + if (WaitingIrp != NULL) + { + /* Unable to have a 2nd pending IRP for this IOCTL */ + DPRINT("Unable to pend a second IRP for IOCTL_GET_SYS_BUTTON_EVENT\n"); + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = STATUS_PENDING; + } + } + break; + } + default: + { + DPRINT("IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + + Irp->IoStatus.Status = Status; + if (Status == STATUS_PENDING) + IoMarkIrpPending(Irp); + else + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Special case for IOCTL_GET_SYS_BUTTON_CAPS */ + if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_SYS_BUTTON_CAPS + && DeviceExtension->PowerIrp) + { + /* Also complete the pending IOCTL_GET_SYS_BUTTON_EVENT Irp */ + PULONG pEvent = (PULONG)DeviceExtension->PowerIrp->AssociatedIrp.SystemBuffer; + + DeviceExtension->PowerIrp->IoStatus.Status = STATUS_SUCCESS; + DeviceExtension->PowerIrp->IoStatus.Information = sizeof(ULONG); + *pEvent = DeviceExtension->LastPowerKey; + DeviceExtension->LastPowerKey = 0; + + IoCompleteRequest(DeviceExtension->PowerIrp, IO_NO_INCREMENT); + DeviceExtension->PowerIrp = NULL; + } + return Status; +} + +/* + * Runs the keyboard IOCTL_INTERNAL dispatch. + */ +NTSTATUS +i8042KbdInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PI8042_KEYBOARD_EXTENSION DeviceExtension; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + Irp->IoStatus.Information = 0; + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_KEYBOARD_CONNECT: + { + SIZE_T Size; + PIO_WORKITEM WorkItem = NULL; + PI8042_HOOK_WORKITEM WorkItemData = NULL; + + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n"); + if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CONNECT_DATA)) + { + Status = STATUS_INVALID_PARAMETER; + goto cleanup; + } + + DeviceExtension->KeyboardData = + *((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer); + + /* Send IOCTL_INTERNAL_I8042_HOOK_KEYBOARD to device stack */ + WorkItem = IoAllocateWorkItem(DeviceObject); + if (!WorkItem) + { + DPRINT("IoAllocateWorkItem() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + WorkItemData = ExAllocatePool( + NonPagedPool, + sizeof(I8042_HOOK_WORKITEM)); + if (!WorkItemData) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + WorkItemData->WorkItem = WorkItem; + WorkItemData->Irp = Irp; + + /* Initialize extension */ + DeviceExtension->Common.Type = Keyboard; + Size = DeviceExtension->Common.PortDeviceExtension->Settings.KeyboardDataQueueSize * sizeof(KEYBOARD_INPUT_DATA); + DeviceExtension->KeyboardBuffer = ExAllocatePool( + NonPagedPool, + Size); + if (!DeviceExtension->KeyboardBuffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlZeroMemory(DeviceExtension->KeyboardBuffer, Size); + KeInitializeDpc( + &DeviceExtension->DpcKeyboard, + i8042KbdDpcRoutine, + DeviceExtension); + DeviceExtension->PowerWorkItem = IoAllocateWorkItem(DeviceObject); + if (!DeviceExtension->PowerWorkItem) + { + DPRINT("IoAllocateWorkItem() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + DeviceExtension->DebugWorkItem = IoAllocateWorkItem(DeviceObject); + if (!DeviceExtension->DebugWorkItem) + { + DPRINT("IoAllocateWorkItem() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + DeviceExtension->Common.PortDeviceExtension->KeyboardExtension = DeviceExtension; + DeviceExtension->Common.PortDeviceExtension->Flags |= KEYBOARD_CONNECTED; + + IoMarkIrpPending(Irp); + IoQueueWorkItem(WorkItem, + i8042SendHookWorkItem, + DelayedWorkQueue, + WorkItemData); + Status = STATUS_PENDING; + break; + +cleanup: + if (DeviceExtension->KeyboardBuffer) + ExFreePool(DeviceExtension->KeyboardBuffer); + if (DeviceExtension->PowerWorkItem) + IoFreeWorkItem(DeviceExtension->PowerWorkItem); + if (DeviceExtension->DebugWorkItem) + IoFreeWorkItem(DeviceExtension->DebugWorkItem); + if (WorkItem) + IoFreeWorkItem(WorkItem); + if (WorkItemData) + ExFreePool(WorkItemData); + break; + } + case IOCTL_INTERNAL_KEYBOARD_DISCONNECT: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_DISCONNECT\n"); + /* MSDN says that operation is to implemented. + * To implement it, we just have to do: + * DeviceExtension->KeyboardData.ClassService = NULL; + */ + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_I8042_HOOK_KEYBOARD\n"); + /* Nothing to do here */ + Status = STATUS_SUCCESS; + break; + } + case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION\n"); + + /* We should check the UnitID, but it's kind of pointless as + * all keyboards are supposed to have the same one + */ + if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory( + Irp->AssociatedIrp.SystemBuffer, + &IndicatorTranslation, + sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)); + Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_KEYBOARD_QUERY_INDICATORS: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATORS\n"); + + if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory( + Irp->AssociatedIrp.SystemBuffer, + &DeviceExtension->KeyboardIndicators, + sizeof(KEYBOARD_INDICATOR_PARAMETERS)); + Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); + Status = STATUS_SUCCESS; + } + break; + } + case IOCTL_KEYBOARD_SET_INDICATORS: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_SET_INDICATORS\n"); + + if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory( + &DeviceExtension->KeyboardIndicators, + Irp->AssociatedIrp.SystemBuffer, + sizeof(KEYBOARD_INDICATOR_PARAMETERS)); + Status = STATUS_PENDING; + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + } + break; + } + default: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + + Irp->IoStatus.Status = Status; + if (Status != STATUS_PENDING) + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +/* + * Call the customization hook. The ToReturn parameter is about wether + * we should go on with the interrupt. The return value is what + * we should return (indicating to the system wether someone else + * should try to handle the interrupt) + */ +static BOOLEAN +i8042KbdCallIsrHook( + IN PI8042_KEYBOARD_EXTENSION DeviceExtension, + IN UCHAR Status, + IN UCHAR Input, + OUT PBOOLEAN ToReturn) +{ + BOOLEAN HookReturn, HookContinue; + + HookContinue = FALSE; + + if (DeviceExtension->KeyboardHook.IsrRoutine) + { + HookReturn = DeviceExtension->KeyboardHook.IsrRoutine( + DeviceExtension->KeyboardHook.Context, + DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer, + &DeviceExtension->Common.PortDeviceExtension->Packet, + Status, + &Input, + &HookContinue, + &DeviceExtension->KeyboardScanState); + + if (!HookContinue) + { + *ToReturn = HookReturn; + return TRUE; + } + } + return FALSE; +} + +BOOLEAN NTAPI +i8042KbdInterruptService( + IN PKINTERRUPT Interrupt, + PVOID Context) +{ + PI8042_KEYBOARD_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + PKEYBOARD_INPUT_DATA InputData; + ULONG Counter; + UCHAR PortStatus, Output; + BOOLEAN ToReturn = FALSE; + NTSTATUS Status; + + DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer; + Counter = PortDeviceExtension->Settings.PollStatusIterations; + + while (Counter) + { + Status = i8042ReadStatus(PortDeviceExtension, &PortStatus); + if (!NT_SUCCESS(Status)) + { + DPRINT("i8042ReadStatus() failed with status 0x%08lx\n", Status); + return FALSE; + } + Status = i8042ReadKeyboardData(PortDeviceExtension, &Output); + if (NT_SUCCESS(Status)) break; KeStallExecutionProcessor(1); - } while (Iterations < DevExt->Settings.PollStatusIterations); - - if (STATUS_SUCCESS != Status) { - DPRINT("Spurious I8042 interrupt\n"); + Counter--; + } + if (Counter == 0) + { + DPRINT("Spurious i8042 keyboard interrupt\n"); return FALSE; } - DPRINT("Got: %x\n", Output); + DPRINT("Got: 0x%02x\n", Output); - if (DevExt->KeyboardHook.IsrRoutine) { - HookReturn = DevExt->KeyboardHook.IsrRoutine( - DevExt->KeyboardHook.Context, - InputData, - &DevExt->Packet, - PortStatus, - &Output, - &HookContinue, - &DevExt->KeyboardScanState); + if (PortDeviceExtension->Settings.CrashOnCtrlScroll) + { + /* Test for CTRL + SCROLL LOCK twice */ + static UCHAR ScanCodes[] = { 0x1d, 0x46, 0x46, 0 }; - if (!HookContinue) - return HookReturn; + if (!(Output & 0x80)) + { + if ((Output & 0x7f) == ScanCodes[DeviceExtension->ComboPosition]) + { + DeviceExtension->ComboPosition++; + if (ScanCodes[DeviceExtension->ComboPosition] == 0) + KeBugCheck(MANUALLY_INITIATED_CRASH); + } + else if ((Output & 0x7f) == ScanCodes[0]) + DeviceExtension->ComboPosition = 1; + else + DeviceExtension->ComboPosition = 0; + } } - if (I8042PacketIsr(DevExt, Output)) { - if (DevExt->PacketComplete) { + if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn)) + return ToReturn; + + if (i8042PacketIsr(PortDeviceExtension, Output)) + { + if (PortDeviceExtension->PacketComplete) + { DPRINT("Packet complete\n"); - KeInsertQueueDpc(&DevExt->DpcKbd, DevExt, NULL); + KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL); } DPRINT("Irq eaten by packet\n"); return TRUE; @@ -135,642 +833,43 @@ BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt, DPRINT("Irq is keyboard input\n"); - if (Normal == DevExt->KeyboardScanState) { - switch (Output) { - case 0xe0: - DevExt->KeyboardScanState = GotE0; - return TRUE; - case 0xe1: - DevExt->KeyboardScanState = GotE1; - return TRUE; - default: - ;/* continue */ + if (DeviceExtension->KeyboardScanState == Normal) + { + switch (Output) + { + case 0xe0: + DeviceExtension->KeyboardScanState = GotE0; + return TRUE; + case 0xe1: + DeviceExtension->KeyboardScanState = GotE1; + return TRUE; + default: + break; } } + /* Update InputData */ InputData->Flags = 0; - - switch (DevExt->KeyboardScanState) { - case GotE0: - InputData->Flags |= KEY_E0; - break; - case GotE1: - InputData->Flags |= KEY_E1; - break; - default: - ; + switch (DeviceExtension->KeyboardScanState) + { + case GotE0: + InputData->Flags |= KEY_E0; + break; + case GotE1: + InputData->Flags |= KEY_E1; + break; + default: + break; } - DevExt->KeyboardScanState = Normal; - + DeviceExtension->KeyboardScanState = Normal; if (Output & 0x80) InputData->Flags |= KEY_BREAK; else InputData->Flags |= KEY_MAKE; - InputData->MakeCode = Output & 0x7f; + InputData->Reserved = 0; - I8042QueueKeyboardPacket(DevExt->KeyboardObject); + i8042KbdQueuePacket(DeviceExtension); return TRUE; } - -VOID STDCALL I8042DpcRoutineKbd(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) -{ - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)SystemArgument1; - ULONG KeysTransferred = 0; - ULONG KeysInBufferCopy; - KIRQL Irql; - - I8042PacketDpc(DevExt); - - if (!DevExt->KeyComplete) - return; - - /* We got the interrupt as it was being enabled, too bad */ - if (!DevExt->HighestDIRQLInterrupt) - return; - - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); - - DevExt->KeyComplete = FALSE; - KeysInBufferCopy = DevExt->KeysInBuffer; - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); - - /* Test for TAB (debugging) */ - if (DevExt->Settings.CrashSysRq) { - PKEYBOARD_INPUT_DATA InputData = DevExt->KeyboardBuffer + - KeysInBufferCopy - 1; - if (InputData->MakeCode == 0x0F) { - DPRINT("Tab!\n"); - DevExt->TabPressed = !(InputData->Flags & KEY_BREAK); - } else if (DevExt->TabPressed) { - DPRINT ("Queueing work item %x\n", DevExt->DebugWorkItem); - DevExt->DebugKey = InputData->MakeCode; - DevExt->TabPressed = FALSE; - - IoQueueWorkItem(DevExt->DebugWorkItem, - &(I8042DebugWorkItem), - DelayedWorkQueue, - DevExt); - } - } - - DPRINT ("Send a key\n"); - - if (!DevExt->KeyboardData.ClassService) - return; - - ((PSERVICE_CALLBACK_ROUTINE) DevExt->KeyboardData.ClassService)( - DevExt->KeyboardData.ClassDeviceObject, - DevExt->KeyboardBuffer, - DevExt->KeyboardBuffer + KeysInBufferCopy, - &KeysTransferred); - - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); - DevExt->KeysInBuffer -= KeysTransferred; - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); -} - -/* You have to send the rate/delay in a somewhat awkward format */ -static UCHAR I8042GetTypematicByte(USHORT Rate, USHORT Delay) -{ - UCHAR ret; - - if (Rate < 3) { - ret = 0x0; - } else if (Rate > 26) { - ret = 0x1F; - } else { - ret = TypematicTable[Rate]; - } - - if (Delay < 375) { - ; - } else if (Delay < 625) { - ret |= 0x20; - } else if (Delay < 875) { - ret |= 0x40; - } else { - ret |= 0x60; - } - return ret; -} -/* - * Process the keyboard internal device requests - * returns FALSE if it doesn't understand the - * call so someone else can handle it. - */ -BOOLEAN STDCALL I8042StartIoKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PIO_STACK_LOCATION Stk; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) { - case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER: - I8042StartPacket( - DevExt, - DeviceObject, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - Stk->Parameters.DeviceIoControl.InputBufferLength, - Irp); - break; - - case IOCTL_KEYBOARD_SET_INDICATORS: - DevExt->PacketBuffer[0] = 0xED; - DevExt->PacketBuffer[1] = 0; - if (DevExt->KeyboardIndicators.LedFlags & KEYBOARD_CAPS_LOCK_ON) - DevExt->PacketBuffer[1] |= 0x04; - - if (DevExt->KeyboardIndicators.LedFlags & KEYBOARD_NUM_LOCK_ON) - DevExt->PacketBuffer[1] |= 0x02; - - if (DevExt->KeyboardIndicators.LedFlags & KEYBOARD_SCROLL_LOCK_ON) - DevExt->PacketBuffer[1] |= 0x01; - - I8042StartPacket(DevExt, - DeviceObject, - DevExt->PacketBuffer, - 2, - Irp); - break; - case IOCTL_KEYBOARD_SET_TYPEMATIC: - DevExt->PacketBuffer[0] = 0xF3; - DevExt->PacketBuffer[1] = I8042GetTypematicByte( - DevExt->KeyboardTypematic.Rate, - DevExt->KeyboardTypematic.Delay); - - I8042StartPacket(DevExt, - DeviceObject, - DevExt->PacketBuffer, - 2, - Irp); - break; - default: - return FALSE; - } - - return TRUE; -} - -/* - * Runs the keyboard IOCTL_INTERNAL dispatch. - * Returns NTSTATUS_INVALID_DEVICE_REQUEST if it doesn't handle this request - * so someone else can have a try at it. - */ -NTSTATUS STDCALL I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PIO_STACK_LOCATION Stk; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - DPRINT("InternalDeviceControl\n"); - - Irp->IoStatus.Information = 0; - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) { - - case IOCTL_INTERNAL_KEYBOARD_CONNECT: - DPRINT("IOCTL_INTERNAL_KEYBOARD_CONNECT\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(CONNECT_DATA)) { - DPRINT1("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } - - if (!DevExt->KeyboardExists) { - Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; - goto intcontfailure; - } - - if (DevExt->KeyboardClaimed) { - DPRINT1("IOCTL_INTERNAL_KEYBOARD_CONNECT: " - "Keyboard is already claimed\n"); - Irp->IoStatus.Status = STATUS_SHARING_VIOLATION; - goto intcontfailure; - } - - memcpy(&DevExt->KeyboardData, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - DevExt->KeyboardHook.IsrWritePort = I8042IsrWritePortKbd; - DevExt->KeyboardHook.QueueKeyboardPacket = - I8042QueueKeyboardPacket; - DevExt->KeyboardHook.CallContext = DevExt; - - { - PIO_WORKITEM WorkItem; - PI8042_HOOK_WORKITEM WorkItemData; - - WorkItem = IoAllocateWorkItem(DeviceObject); - if (!WorkItem) { - DPRINT ("IOCTL_INTERNAL_KEYBOARD_CONNECT: " - "Can't allocate work item\n"); - Irp->IoStatus.Status = - STATUS_INSUFFICIENT_RESOURCES; - goto intcontfailure; - } - - WorkItemData = ExAllocatePoolWithTag( - NonPagedPool, - sizeof(I8042_HOOK_WORKITEM), - TAG_I8042); - if (!WorkItemData) { - DPRINT ("IOCTL_INTERNAL_KEYBOARD_CONNECT: " - "Can't allocate work item data\n"); - Irp->IoStatus.Status = - STATUS_INSUFFICIENT_RESOURCES; - IoFreeWorkItem(WorkItem); - goto intcontfailure; - } - WorkItemData->WorkItem = WorkItem; - WorkItemData->Target = - DevExt->KeyboardData.ClassDeviceObject; - WorkItemData->Irp = Irp; - - IoMarkIrpPending(Irp); - IoQueueWorkItem(WorkItem, - I8042SendHookWorkItem, - DelayedWorkQueue, - WorkItemData); - - Irp->IoStatus.Status = STATUS_PENDING; - } - - break; - case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER: - DPRINT("IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < 1) { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } - if (!DevExt->KeyboardInterruptObject) { - Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; - goto intcontfailure; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - Irp->IoStatus.Status = STATUS_PENDING; - - break; - case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: - DPRINT("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_ATTRIBUTES)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - memcpy(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardAttributes, - sizeof(KEYBOARD_ATTRIBUTES)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_INDICATORS: - DPRINT("IOCTL_KEYBOARD_QUERY_INDICATORS\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_INDICATORS " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - memcpy(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardIndicators, - sizeof(KEYBOARD_INDICATOR_PARAMETERS)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_TYPEMATIC: - DPRINT("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - memcpy(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardTypematic, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_SET_INDICATORS: - DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - - memcpy(&DevExt->KeyboardIndicators, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_INDICATOR_PARAMETERS)); - - DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags); - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - Irp->IoStatus.Status = STATUS_PENDING; - - break; - case IOCTL_KEYBOARD_SET_TYPEMATIC: - DPRINT("IOCTL_KEYBOARD_SET_TYPEMATIC\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - - memcpy(&DevExt->KeyboardTypematic, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)); - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - Irp->IoStatus.Status = STATUS_PENDING; - - break; - case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: - /* We should check the UnitID, but it's kind of pointless as - * all keyboards are supposed to have the same one - */ - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)) { - DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: " - "invalid buffer size (expected)\n"); - /* It's to query the buffer size */ - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - Irp->IoStatus.Information = - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); - - memcpy(Irp->AssociatedIrp.SystemBuffer, - &IndicatorTranslation, - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: - /* Nothing to do here */ - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - default: - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - -intcontfailure: - return Irp->IoStatus.Status; -} - -/* This is all pretty confusing. There's more than one way to - * disable/enable the keyboard. You can send KBD_ENABLE to the - * keyboard, and it will start scanning keys. Sending KBD_DISABLE - * will disable the key scanning but also reset the parameters to - * defaults. - * - * You can also send 0xAE to the controller for enabling the - * keyboard clock line and 0xAD for disabling it. Then it'll - * automatically get turned on at the next command. The last - * way is by modifying the bit that drives the clock line in the - * 'command byte' of the controller. This is almost, but not quite, - * the same as the AE/AD thing. The difference can be used to detect - * some really old broken keyboard controllers which I hope won't be - * necessary. - * - * We change the command byte, sending KBD_ENABLE/DISABLE seems to confuse - * some kvm switches. - */ - -BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt) -{ - UCHAR Value; - NTSTATUS Status; - - DPRINT("Enable keyboard\n"); - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value &= ~CCB_KBD_DISAB; // don't disable keyboard - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - return TRUE; -} - -static BOOLEAN STDCALL I8042KeyboardDefaultsAndDisable(PDEVICE_EXTENSION DevExt) -{ - UCHAR Value; - NTSTATUS Status; - - DPRINT("Disabling keyboard\n"); - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value |= CCB_KBD_DISAB; // disable keyboard - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - return TRUE; -} - -BOOLEAN STDCALL I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt) -{ - UCHAR Value; - NTSTATUS Status; - - DPRINT("Enabling keyboard interrupt\n"); - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value &= ~CCB_KBD_DISAB; // don't disable keyboard - Value |= CCB_KBD_INT_ENAB; // enable keyboard interrupts - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - return TRUE; -} - -BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt) -{ - NTSTATUS Status; - UCHAR Value; - UCHAR Value2; - ULONG RetryCount = 10; - - DPRINT("Detecting keyboard\n"); - - I8042KeyboardDefaultsAndDisable(DevExt); - - do { - I8042Flush(); - Status = I8042SynchWritePort(DevExt, 0, KBD_GET_ID, TRUE); - } while (STATUS_IO_TIMEOUT == Status && RetryCount--); - - if (!NT_SUCCESS(Status)) { - DPRINT1("Can't write GET_ID (%x)\n", Status); - /* Could be an AT keyboard */ - DevExt->KeyboardIsAT = TRUE; - goto detectsetleds; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after GET_ID\n"); - /* Could be an AT keyboard */ - DevExt->KeyboardIsAT = TRUE; - goto detectsetleds; - } - DevExt->KeyboardIsAT = FALSE; - - if (Value != 0xAB && Value != 0xAC) { - DPRINT("Bad ID: %x\n", Value); - /* This is certainly not a keyboard */ - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value2); - if (!NT_SUCCESS(Status)) { - DPRINT("Partial ID\n"); - return FALSE; - } - - DPRINT("Keyboard ID: 0x%x 0x%x\n", Value, Value2); - -detectsetleds: - I8042Flush(); /* Flush any bytes left over from GET_ID */ - - Status = I8042SynchWritePort(DevExt, 0, KBD_SET_LEDS, TRUE); - if (!NT_SUCCESS(Status)) { - DPRINT("Can't write SET_LEDS (%x)\n", Status); - return FALSE; - } - Status = I8042SynchWritePort(DevExt, 0, 0, TRUE); - if (!NT_SUCCESS(Status)) { - DPRINT("Can't finish SET_LEDS (%x)\n", Status); - return FALSE; - } - - // Turn on translation - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } - - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value |= 0x40; // enable keyboard translation - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - return TRUE; -} - -/* debug stuff */ -VOID STDCALL -KdpServiceDispatcher(ULONG Code, PVOID Context1, PVOID Context2); -#define EnterDebugger ((PVOID)0x25) - -static VOID STDCALL I8042DebugWorkItem(PDEVICE_OBJECT DeviceObject, - PVOID Context) -{ - ULONG Key; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - Key = InterlockedExchange((PLONG)&DevExt->DebugKey, 0); - DPRINT("Debug key: %x\n", Key); - - if (!Key) - return; - -#ifdef __REACTOS__ - /* We hope kernel would understand this. If - * that's not the case, nothing would happen. - */ - KdpServiceDispatcher(TAG('R', 'o', 's', ' '), (PVOID)Key, NULL); -#endif /* __REACTOS__ */ -} diff --git a/reactos/drivers/input/i8042prt/misc.c b/reactos/drivers/input/i8042prt/misc.c new file mode 100644 index 00000000000..82200c72d02 --- /dev/null +++ b/reactos/drivers/input/i8042prt/misc.c @@ -0,0 +1,68 @@ +/* + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/misc.c + * PURPOSE: Misceallenous operations + * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "i8042prt.h" + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS NTAPI +ForwardIrpAndWaitCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + if (Irp->PendingReturned) + KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +ForwardIrpAndWait( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; + KEVENT Event; + NTSTATUS Status; + + ASSERT(LowerDevice); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoCopyCurrentIrpStackLocationToNext(Irp); + + DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName); + IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); + + Status = IoCallDriver(LowerDevice, Irp); + if (Status == STATUS_PENDING) + { + Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + if (NT_SUCCESS(Status)) + Status = Irp->IoStatus.Status; + } + + return Status; +} + +NTSTATUS NTAPI +ForwardIrpAndForget( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; + + ASSERT(LowerDevice); + + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(LowerDevice, Irp); +} diff --git a/reactos/drivers/input/i8042prt/mouse.c b/reactos/drivers/input/i8042prt/mouse.c index 5a8afb5ebf3..1d7d65070d1 100644 --- a/reactos/drivers/input/i8042prt/mouse.c +++ b/reactos/drivers/input/i8042prt/mouse.c @@ -1,12 +1,12 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/input/i8042prt/mouse.c - * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver - * mouse specifics - * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) - * Tinus + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/mouse.c + * PURPOSE: Mouse specific functions + * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) + Copyright Jason Filby (jasonfilby@yahoo.com) + Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ /* INCLUDES ****************************************************************/ @@ -16,27 +16,474 @@ #define NDEBUG #include +/* FUNCTIONS *****************************************************************/ + /* * These functions are callbacks for filter driver custom interrupt * service routines. */ -static VOID STDCALL I8042IsrWritePortMouse(PVOID Context, - UCHAR Value) +static VOID NTAPI +i8042MouIsrWritePort( + IN PVOID Context, + IN UCHAR Value) { - I8042IsrWritePort(Context, Value, 0xD4); + PI8042_MOUSE_EXTENSION DeviceExtension; + + DeviceExtension = (PI8042_MOUSE_EXTENSION)Context; + + if (DeviceExtension->MouseHook.IsrWritePort) + { + DeviceExtension->MouseHook.IsrWritePort( + DeviceExtension->MouseHook.CallContext, + Value); + } + else + i8042IsrWritePort(Context, Value, 0xD4); } -#if 0 -static NTSTATUS STDCALL I8042SynchWritePortMouse(PVOID Context, - UCHAR Value, - BOOLEAN WaitForAck) +VOID NTAPI +i8042MouQueuePacket( + IN PVOID Context) { - return I8042SynchWritePort((PDEVICE_EXTENSION)Context, - 0xD4, - Value, - WaitForAck); + PI8042_MOUSE_EXTENSION DeviceExtension; + + DeviceExtension = (PI8042_MOUSE_EXTENSION)Context; + + if (DeviceExtension->MouseHook.QueueMousePacket) + { + DeviceExtension->MouseHook.QueueMousePacket( + DeviceExtension->MouseHook.CallContext); + return; + } + + DeviceExtension->MouseComplete = TRUE; + DeviceExtension->MouseInBuffer++; + if (DeviceExtension->MouseInBuffer > DeviceExtension->Common.PortDeviceExtension->Settings.MouseDataQueueSize) + { + DPRINT1("Mouse buffer overflow\n"); + DeviceExtension->MouseInBuffer--; + } + + DPRINT("Irq completes mouse packet\n"); + KeInsertQueueDpc(&DeviceExtension->DpcMouse, NULL, NULL); +} + +VOID +i8042MouHandle( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Output) +{ + PMOUSE_INPUT_DATA MouseInput; + CHAR Scroll; + + MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer; + + switch (DeviceExtension->MouseState) + { + case MouseIdle: + /* This bit should be 1, if not drop the packet, we + * might be lucky and get in sync again + */ + if (!(Output & 8)) { + DPRINT1("Bad input, dropping..\n"); + return; + } + + MouseInput->Buttons = 0; + MouseInput->RawButtons = 0; + MouseInput->Flags = MOUSE_MOVE_RELATIVE; + + /* Note how we ignore the overflow bits, like Windows + * is said to do. There's no reasonable thing to do + * anyway. + */ + + if (Output & 16) + MouseInput->LastX = 1; + else + MouseInput->LastX = 0; + if (Output & 32) + MouseInput->LastY = 1; + else + MouseInput->LastY = 0; + + if (Output & 1) + MouseInput->RawButtons |= MOUSE_LEFT_BUTTON_DOWN; + if (Output & 2) + MouseInput->RawButtons |= MOUSE_RIGHT_BUTTON_DOWN; + if (Output & 4) + MouseInput->RawButtons |= MOUSE_MIDDLE_BUTTON_DOWN; + + DeviceExtension->MouseState = XMovement; + break; + + case XMovement: + if (MouseInput->LastX) + MouseInput->LastX = (LONG) Output - 256; + else + MouseInput->LastX = Output; + + DeviceExtension->MouseState = YMovement; + break; + + case YMovement: + if (MouseInput->LastY) + MouseInput->LastY = (LONG)Output - 256; + else + MouseInput->LastY = (LONG)Output; + + /* Windows wants it the other way around */ + MouseInput->LastY = -MouseInput->LastY; + + if (DeviceExtension->MouseType == GenericPS2 || + DeviceExtension->MouseType == Ps2pp) + { + i8042MouHandleButtons( + DeviceExtension, + MOUSE_LEFT_BUTTON_DOWN | + MOUSE_RIGHT_BUTTON_DOWN | + MOUSE_MIDDLE_BUTTON_DOWN); + i8042MouQueuePacket(DeviceExtension); + DeviceExtension->MouseState = MouseIdle; + } + else + { + DeviceExtension->MouseState = ZMovement; + } + break; + + case ZMovement: + Scroll = Output & 0x0f; + if (Scroll & 8) + Scroll |= 0xf0; + + if (Scroll) + { + MouseInput->RawButtons |= MOUSE_WHEEL; + MouseInput->ButtonData = (USHORT)(Scroll * -WHEEL_DELTA); + } + + if (DeviceExtension->MouseType == IntellimouseExplorer) + { + if (Output & 16) + MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN; + if (Output & 32) + MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN; + } + i8042MouHandleButtons( + DeviceExtension, + MOUSE_LEFT_BUTTON_DOWN | + MOUSE_RIGHT_BUTTON_DOWN | + MOUSE_MIDDLE_BUTTON_DOWN | + MOUSE_BUTTON_4_DOWN | + MOUSE_BUTTON_5_DOWN); + i8042MouQueuePacket(DeviceExtension); + DeviceExtension->MouseState = MouseIdle; + break; + + default: + DPRINT1("Unexpected state 0x%u!\n", DeviceExtension->MouseState); + ASSERT(FALSE); + } +} + +/* + * Updates ButtonFlags according to RawButtons and a saved state; + * Only takes in account the bits that are set in Mask + */ +VOID +i8042MouHandleButtons( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN USHORT Mask) +{ + PMOUSE_INPUT_DATA MouseInput; + USHORT NewButtonData; + USHORT ButtonDiff; + + MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer; + NewButtonData = (USHORT)(MouseInput->RawButtons & Mask); + ButtonDiff = (NewButtonData ^ DeviceExtension->MouseButtonState) & Mask; + + /* Note that the defines are such: + * MOUSE_LEFT_BUTTON_DOWN 1 + * MOUSE_LEFT_BUTTON_UP 2 + */ + MouseInput->ButtonFlags |= (NewButtonData & ButtonDiff) | + (((~(NewButtonData)) << 1) & (ButtonDiff << 1)) | + (MouseInput->RawButtons & 0xfc00); + + DPRINT("Left raw/up/down: %u/%u/%u\n", + MouseInput->RawButtons & MOUSE_LEFT_BUTTON_DOWN, + MouseInput->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN, + MouseInput->ButtonFlags & MOUSE_LEFT_BUTTON_UP); + + DeviceExtension->MouseButtonState = + (DeviceExtension->MouseButtonState & ~Mask) | (NewButtonData & Mask); +} + +static NTSTATUS OldInitialization(PPORT_DEVICE_EXTENSION); /* FIXME */ + +/* Does lastest initializations for the mouse. This method + * is called just before connecting the interrupt. + */ +NTSTATUS +i8042MouInitialize( + IN PI8042_MOUSE_EXTENSION DeviceExtension) +{ + PPORT_DEVICE_EXTENSION PortDeviceExtension; + + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + +/* FIXME */ OldInitialization(PortDeviceExtension); + + return STATUS_SUCCESS; +} + +static VOID NTAPI +i8042MouDpcRoutine( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PI8042_MOUSE_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + ULONG MouseTransferred = 0; + ULONG MouseInBufferCopy; + KIRQL Irql; + LARGE_INTEGER Timeout; + + DeviceExtension = (PI8042_MOUSE_EXTENSION)DeferredContext; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + + switch (DeviceExtension->MouseTimeoutState) + { + case TimeoutStart: + { + DeviceExtension->MouseTimeoutState = NoChange; + if (DeviceExtension->MouseTimeoutActive && + !KeCancelTimer(&DeviceExtension->TimerMouseTimeout)) + { + /* The timer fired already, give up */ + DeviceExtension->MouseTimeoutActive = FALSE; + return; + } + + Timeout.QuadPart = -15000000; /* 1.5 seconds, should be enough */ + + KeSetTimer( + &DeviceExtension->TimerMouseTimeout, + Timeout, + &DeviceExtension->DpcMouseTimeout); + DeviceExtension->MouseTimeoutActive = TRUE; + return; + } + + case TimeoutCancel: + { + DeviceExtension->MouseTimeoutState = NoChange; + KeCancelTimer(&DeviceExtension->TimerMouseTimeout); + DeviceExtension->MouseTimeoutActive = FALSE; + } + + default: + ;/* nothing, don't want a warning */ + } + + /* Should be unlikely */ + if (!DeviceExtension->MouseComplete) + return; + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + + DeviceExtension->MouseComplete = FALSE; + MouseInBufferCopy = DeviceExtension->MouseInBuffer; + + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); + + DPRINT("Send a mouse packet\n"); + + if (!DeviceExtension->MouseData.ClassService) + return; + + DPRINT("Sending %lu mouse move(s)\n", MouseInBufferCopy); + (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->MouseData.ClassService)( + DeviceExtension->MouseData.ClassDeviceObject, + DeviceExtension->MouseBuffer, + DeviceExtension->MouseBuffer + MouseInBufferCopy, + &MouseTransferred); + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + DeviceExtension->MouseInBuffer -= MouseTransferred; + if (DeviceExtension->MouseInBuffer) + RtlMoveMemory( + DeviceExtension->MouseBuffer, + DeviceExtension->MouseBuffer + MouseTransferred, + DeviceExtension->MouseInBuffer * sizeof(MOUSE_INPUT_DATA)); + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); +} + +/* This timer DPC will be called when the mouse reset times out. + * I'll just send the 'disable mouse port' command to the controller + * and say the mouse doesn't exist. + */ +static VOID NTAPI +i8042DpcRoutineMouseTimeout( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PI8042_MOUSE_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + KIRQL Irql; + + DeviceExtension = (PI8042_MOUSE_EXTENSION)DeferredContext; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + + Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); + + DPRINT1("Mouse initialization timeout! (substate %x). Disabling mouse.\n", + DeviceExtension->MouseResetState); + + i8042Flush(PortDeviceExtension); + i8042ChangeMode(PortDeviceExtension, CCB_MOUSE_INT_ENAB, CCB_MOUSE_DISAB); + i8042Flush(PortDeviceExtension); + + PortDeviceExtension->Flags &= ~MOUSE_PRESENT; + + KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); +} + +/* + * Runs the mouse IOCTL_INTERNAL dispatch. + */ +NTSTATUS +i8042MouInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PI8042_MOUSE_EXTENSION DeviceExtension; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + Irp->IoStatus.Information = 0; + DeviceExtension = (PI8042_MOUSE_EXTENSION)DeviceObject->DeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_MOUSE_CONNECT: + { + SIZE_T Size; + PIO_WORKITEM WorkItem = NULL; + PI8042_HOOK_WORKITEM WorkItemData = NULL; + + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_MOUSE_CONNECT\n"); + if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CONNECT_DATA)) + { + Status = STATUS_INVALID_PARAMETER; + goto cleanup; + } + + DeviceExtension->MouseData = + *((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer); + + /* Send IOCTL_INTERNAL_I8042_HOOK_MOUSE to device stack */ + WorkItem = IoAllocateWorkItem(DeviceObject); + if (!WorkItem) + { + DPRINT("IoAllocateWorkItem() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + WorkItemData = ExAllocatePool( + NonPagedPool, + sizeof(I8042_HOOK_WORKITEM)); + if (!WorkItemData) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + WorkItemData->WorkItem = WorkItem; + WorkItemData->Irp = Irp; + + /* Initialize extension */ + DeviceExtension->Common.Type = Mouse; + Size = DeviceExtension->Common.PortDeviceExtension->Settings.MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA); + DeviceExtension->MouseBuffer = ExAllocatePool( + NonPagedPool, + Size); + if (!DeviceExtension->MouseBuffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlZeroMemory(DeviceExtension->MouseBuffer, Size); + DeviceExtension->MouseAttributes.InputDataQueueLength = + DeviceExtension->Common.PortDeviceExtension->Settings.MouseDataQueueSize; + KeInitializeDpc( + &DeviceExtension->DpcMouse, + i8042MouDpcRoutine, + DeviceExtension); + KeInitializeDpc( + &DeviceExtension->DpcMouseTimeout, + i8042DpcRoutineMouseTimeout, + DeviceExtension); + KeInitializeTimer(&DeviceExtension->TimerMouseTimeout); + DeviceExtension->Common.PortDeviceExtension->MouseExtension = DeviceExtension; + DeviceExtension->Common.PortDeviceExtension->Flags |= MOUSE_CONNECTED; + + IoMarkIrpPending(Irp); + IoQueueWorkItem(WorkItem, + i8042SendHookWorkItem, + DelayedWorkQueue, + WorkItemData); + Status = STATUS_PENDING; + break; + +cleanup: + if (DeviceExtension->MouseBuffer) + ExFreePool(DeviceExtension->MouseBuffer); + if (WorkItem) + IoFreeWorkItem(WorkItem); + if (WorkItemData) + ExFreePool(WorkItemData); + break; + } + case IOCTL_INTERNAL_MOUSE_DISCONNECT: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_MOUSE_DISCONNECT\n"); + /* MSDN says that operation is to implemented. + * To implement it, we just have to do: + * DeviceExtension->MouseData.ClassService = NULL; + */ + Status = STATUS_NOT_IMPLEMENTED; + break; + } + case IOCTL_INTERNAL_I8042_HOOK_MOUSE: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_I8042_HOOK_MOUSE\n"); + /* Nothing to do here */ + Status = STATUS_SUCCESS; + break; + } + default: + { + DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + + Irp->IoStatus.Status = Status; + if (Status != STATUS_PENDING) + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; } -#endif /* Test if packets are taking too long to come in. If they do, we * might have gotten out of sync and should just drop what we have. @@ -48,56 +495,71 @@ static NTSTATUS STDCALL I8042SynchWritePortMouse(PVOID Context, * generally unlucky). Also note the input parsing routine where we * drop invalid input packets. */ -static VOID STDCALL I8042MouseInputTestTimeout(PDEVICE_EXTENSION DevExt) +static VOID +i8042MouInputTestTimeout( + IN PI8042_MOUSE_EXTENSION DeviceExtension) { ULARGE_INTEGER Now; - if (DevExt->MouseState == MouseExpectingACK || - DevExt->MouseState == MouseResetting) + if (DeviceExtension->MouseState == MouseExpectingACK || + DeviceExtension->MouseState == MouseResetting) return; Now.QuadPart = KeQueryInterruptTime(); - if (DevExt->MouseState != MouseIdle) { + if (DeviceExtension->MouseState != MouseIdle) { /* Check if the last byte came too long ago */ - if (Now.QuadPart - DevExt->MousePacketStartTime.QuadPart > - DevExt->Settings.MouseSynchIn100ns) { + if (Now.QuadPart - DeviceExtension->MousePacketStartTime.QuadPart > + DeviceExtension->Common.PortDeviceExtension->Settings.MouseSynchIn100ns) + { DPRINT("Mouse input packet timeout\n"); - DevExt->MouseState = MouseIdle; + DeviceExtension->MouseState = MouseIdle; } } - if (DevExt->MouseState == MouseIdle) - DevExt->MousePacketStartTime.QuadPart = Now.QuadPart; + if (DeviceExtension->MouseState == MouseIdle) + DeviceExtension->MousePacketStartTime.QuadPart = Now.QuadPart; } /* - * Call the customization hook. The Ret2 parameter is about wether + * Call the customization hook. The ToReturn parameter is about wether * we should go on with the interrupt. The return value is what * we should return (indicating to the system wether someone else * should try to handle the interrupt) */ -static BOOLEAN STDCALL I8042MouseCallIsrHook(PDEVICE_EXTENSION DevExt, - UCHAR Status, - PUCHAR Input, - PBOOLEAN ToReturn) +static BOOLEAN +i8042MouCallIsrHook( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Status, + IN UCHAR Input, + OUT PBOOLEAN ToReturn) { BOOLEAN HookReturn, HookContinue; HookContinue = FALSE; - if (DevExt->MouseHook.IsrRoutine) { - HookReturn = DevExt->MouseHook.IsrRoutine( - DevExt->MouseHook.Context, - DevExt->MouseBuffer + DevExt->MouseInBuffer, - &DevExt->Packet, - Status, - Input, - &HookContinue, - &DevExt->MouseState, - &DevExt->MouseResetState); + if (DeviceExtension->MouseHook.IsrRoutine) + { + DPRINT1("IsrRoutine(%p %p %p 0x%x 0x%x %p %lu %lu)\n", + DeviceExtension->MouseHook.Context, DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer, + &DeviceExtension->Common.PortDeviceExtension->Packet, Status, &Input, &HookContinue, + DeviceExtension->MouseState, DeviceExtension->MouseResetState); + HookReturn = DeviceExtension->MouseHook.IsrRoutine( + DeviceExtension->MouseHook.Context, + DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer, + &DeviceExtension->Common.PortDeviceExtension->Packet, + Status, + &Input, + &HookContinue, + &DeviceExtension->MouseState, + &DeviceExtension->MouseResetState); + DPRINT1("IsrRoutine(%p %p %p 0x%x 0x%x %p %lu %lu)\n", + DeviceExtension->MouseHook.Context, DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer, + &DeviceExtension->Common.PortDeviceExtension->Packet, Status, &Input, &HookContinue, + DeviceExtension->MouseState, DeviceExtension->MouseResetState); - if (!HookContinue) { + if (!HookContinue) + { *ToReturn = HookReturn; return TRUE; } @@ -105,844 +567,504 @@ static BOOLEAN STDCALL I8042MouseCallIsrHook(PDEVICE_EXTENSION DevExt, return FALSE; } -static BOOLEAN STDCALL I8042MouseResetIsr(PDEVICE_EXTENSION DevExt, - UCHAR Status, - PUCHAR Value) +static BOOLEAN +i8042MouResetIsr( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Status, + IN UCHAR Value) { + PPORT_DEVICE_EXTENSION PortDeviceExtension; BOOLEAN ToReturn = FALSE; - if (I8042MouseCallIsrHook(DevExt, Status, Value, &ToReturn)) + if (i8042MouCallIsrHook(DeviceExtension, Status, Value, &ToReturn)) return ToReturn; - if (MouseResetting != DevExt->MouseState) { + if (MouseResetting != DeviceExtension->MouseState) return FALSE; - } - DevExt->MouseTimeoutState = TimeoutStart; + DeviceExtension->MouseTimeoutState = TimeoutStart; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; - switch (DevExt->MouseResetState) { - case 1100: /* the first ack, drop it. */ - DevExt->MouseResetState = ExpectingReset; - return TRUE; - /* First, 0xFF is sent. The mouse is supposed to say AA00 if ok, - * FC00 if not. - */ - case ExpectingReset: - if (0xAA == *Value) { - DevExt->MouseResetState++; - } else { - DevExt->MouseExists = FALSE; - DevExt->MouseState = MouseIdle; - DPRINT("Mouse returned bad reset reply: " - "%x (expected aa)\n", *Value); - } - return TRUE; - case ExpectingResetId: - if (0x00 == *Value) { - DevExt->MouseResetState++; - DevExt->MouseType = GenericPS2; - I8042IsrWritePortMouse(DevExt, 0xF2); - } else { - DevExt->MouseExists = FALSE; - DevExt->MouseState = MouseIdle; - DPRINT1("Mouse returned bad reset reply part two: " - "%x (expected 0)\n", *Value); - } - return TRUE; - case ExpectingGetDeviceIdACK: - if (MOUSE_ACK == *Value) { - DevExt->MouseResetState++; - } else if (MOUSE_NACK == *Value || - MOUSE_ERROR == *Value) { - DevExt->MouseResetState++; - /* Act as if 00 (normal mouse) was received */ - DPRINT("Mouse doesn't support 0xd2, " - "(returns %x, expected %x), faking.\n", - *Value, MOUSE_ACK); - *Value = 0; - I8042MouseResetIsr(DevExt, Status, Value); - } - return TRUE; - case ExpectingGetDeviceIdValue: - switch (*Value) { - case 0x02: - DevExt->MouseAttributes.MouseIdentifier = - BALLPOINT_I8042_HARDWARE; - break; - case 0x03: - case 0x04: - DevExt->MouseAttributes.MouseIdentifier = - WHEELMOUSE_I8042_HARDWARE; - break; + switch (DeviceExtension->MouseResetState) + { + case 1100: /* the first ack, drop it. */ + DeviceExtension->MouseResetState = ExpectingReset; + return TRUE; + case ExpectingReset: + /* First, 0xFF is sent. The mouse is supposed to say AA00 if ok, FC00 if not. */ + if (0xAA == Value) + { + DeviceExtension->MouseResetState++; + } + else + { + PortDeviceExtension->Flags &= ~MOUSE_PRESENT; + DeviceExtension->MouseState = MouseIdle; + DPRINT("Mouse returned bad reset reply: %x (expected aa)\n", Value); + } + return TRUE; + case ExpectingResetId: + if (0x00 == Value) + { + DeviceExtension->MouseResetState++; + DeviceExtension->MouseType = GenericPS2; + i8042MouIsrWritePort(PortDeviceExtension, 0xF2); + } + else + { + PortDeviceExtension->Flags &= ~MOUSE_PRESENT; + DeviceExtension->MouseState = MouseIdle; + DPRINT1("Mouse returned bad reset reply part two: %x (expected 0)\n", Value); + } + return TRUE; + case ExpectingGetDeviceIdACK: + if (MOUSE_ACK == Value) + { + DeviceExtension->MouseResetState++; + } + else if (MOUSE_NACK == Value || MOUSE_ERROR == Value) + { + DeviceExtension->MouseResetState++; + /* Act as if 00 (normal mouse) was received */ + DPRINT("Mouse doesn't support 0xd2, (returns %x, expected %x), faking\n", Value, MOUSE_ACK); + i8042MouResetIsr(DeviceExtension, Status, 0); + } + return TRUE; + case ExpectingGetDeviceIdValue: + switch (Value) + { + case 0x02: + DeviceExtension->MouseAttributes.MouseIdentifier = + BALLPOINT_I8042_HARDWARE; + break; + case 0x03: + case 0x04: + DeviceExtension->MouseAttributes.MouseIdentifier = + WHEELMOUSE_I8042_HARDWARE; + break; + default: + DeviceExtension->MouseAttributes.MouseIdentifier = + MOUSE_I8042_HARDWARE; + } + DeviceExtension->MouseResetState++; + i8042MouIsrWritePort(PortDeviceExtension, 0xE8); + return TRUE; + case ExpectingSetResolutionDefaultACK: + DeviceExtension->MouseResetState++; + i8042MouIsrWritePort(PortDeviceExtension, 0x00); + return TRUE; + case ExpectingSetResolutionDefaultValueACK: + DeviceExtension->MouseResetState = ExpectingSetScaling1to1ACK; + i8042MouIsrWritePort(PortDeviceExtension, 0xE6); + return TRUE; + case ExpectingSetScaling1to1ACK: + case ExpectingSetScaling1to1ACK2: + DeviceExtension->MouseResetState++; + i8042MouIsrWritePort(PortDeviceExtension, 0xE6); + return TRUE; + case ExpectingSetScaling1to1ACK3: + DeviceExtension->MouseResetState++; + i8042MouIsrWritePort(PortDeviceExtension, 0xE9); + return TRUE; + case ExpectingReadMouseStatusACK: + DeviceExtension->MouseResetState++; + return TRUE; + case ExpectingReadMouseStatusByte1: + DeviceExtension->MouseLogiBuffer[0] = Value; + DeviceExtension->MouseResetState++; + return TRUE; + case ExpectingReadMouseStatusByte2: + DeviceExtension->MouseLogiBuffer[1] = Value; + DeviceExtension->MouseResetState++; + return TRUE; + case ExpectingReadMouseStatusByte3: + DeviceExtension->MouseLogiBuffer[2] = Value; + /* Now MouseLogiBuffer is a set of info. If the second + * byte is 0, the mouse didn't understand the magic + * code. Otherwise, it it a Logitech and the second byte + * is the number of buttons, bit 7 of the first byte tells + * if it understands special E7 commands, the rest is an ID. + */ + if (DeviceExtension->MouseLogiBuffer[1]) + { + DeviceExtension->MouseAttributes.NumberOfButtons = + DeviceExtension->MouseLogiBuffer[1]; + DeviceExtension->MouseType = Ps2pp; + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState = ExpectingSetSamplingRateACK; + /* TODO: Go through EnableWheel and Enable5Buttons */ + return TRUE; + } + DeviceExtension->MouseResetState = EnableWheel; + i8042MouResetIsr(DeviceExtension, Status, Value); + return TRUE; + case EnableWheel: + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState = 1001; + return TRUE; + case 1001: + i8042MouIsrWritePort(PortDeviceExtension, 0xC8); + DeviceExtension->MouseResetState++; + return TRUE; + case 1002: + case 1004: + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState++; + return TRUE; + case 1003: + i8042MouIsrWritePort(PortDeviceExtension, 0x64); + DeviceExtension->MouseResetState++; + return TRUE; + case 1005: + i8042MouIsrWritePort(PortDeviceExtension, 0x50); + DeviceExtension->MouseResetState++; + return TRUE; + case 1006: + i8042MouIsrWritePort(PortDeviceExtension, 0xF2); + DeviceExtension->MouseResetState++; + return TRUE; + case 1007: + /* Ignore ACK */ + DeviceExtension->MouseResetState++; + return TRUE; + case 1008: + if (0x03 == Value) { + /* It's either an Intellimouse or Intellimouse Explorer. */ + DeviceExtension->MouseAttributes.NumberOfButtons = 3; + DeviceExtension->MouseAttributes.MouseIdentifier = + WHEELMOUSE_I8042_HARDWARE; + DeviceExtension->MouseType = Intellimouse; + DeviceExtension->MouseResetState = Enable5Buttons; + i8042MouResetIsr(DeviceExtension, Status, Value); + } + else + { + /* Just set the default settings and be done */ + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState = ExpectingSetSamplingRateACK; + } + return TRUE; + case Enable5Buttons: + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState = 1021; + return TRUE; + case 1022: + case 1024: + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState++; + return TRUE; + case 1021: + case 1023: + i8042MouIsrWritePort(PortDeviceExtension, 0xC8); + DeviceExtension->MouseResetState++; + return TRUE; + case 1025: + i8042MouIsrWritePort(PortDeviceExtension, 0x50); + DeviceExtension->MouseResetState++; + return TRUE; + case 1026: + i8042MouIsrWritePort(PortDeviceExtension, 0xF2); + DeviceExtension->MouseResetState++; + return TRUE; + case 1027: + if (0x04 == Value) + { + DeviceExtension->MouseAttributes.NumberOfButtons = 5; + DeviceExtension->MouseAttributes.MouseIdentifier = + WHEELMOUSE_I8042_HARDWARE; + DeviceExtension->MouseType = IntellimouseExplorer; + } + i8042MouIsrWritePort(PortDeviceExtension, 0xF3); + DeviceExtension->MouseResetState = ExpectingSetSamplingRateACK; + return TRUE; + case ExpectingSetSamplingRateACK: + i8042MouIsrWritePort(PortDeviceExtension, + (UCHAR)DeviceExtension->MouseAttributes.SampleRate); + DeviceExtension->MouseResetState++; + return TRUE; + case ExpectingSetSamplingRateValueACK: + if (MOUSE_NACK == Value) + { + i8042MouIsrWritePort(PortDeviceExtension, 0x3C); + DeviceExtension->MouseAttributes.SampleRate = PortDeviceExtension->Settings.SampleRate; + DeviceExtension->MouseResetState = 1040; + return TRUE; + } + case 1040: /* Fallthrough */ + i8042MouIsrWritePort(PortDeviceExtension, 0xE8); + DeviceExtension->MouseResetState = ExpectingFinalResolutionACK; + return TRUE; + case ExpectingFinalResolutionACK: + i8042MouIsrWritePort(PortDeviceExtension, + (UCHAR)(PortDeviceExtension->Settings.MouseResolution & 0xff)); + DPRINT("Mouse resolution %lu\n", + PortDeviceExtension->Settings.MouseResolution); + DeviceExtension->MouseResetState = ExpectingFinalResolutionValueACK; + return TRUE; + case ExpectingFinalResolutionValueACK: + i8042MouIsrWritePort(PortDeviceExtension, 0xF4); + DeviceExtension->MouseResetState = ExpectingEnableACK; + return TRUE; + case ExpectingEnableACK: + DeviceExtension->MouseState = MouseIdle; + DeviceExtension->MouseTimeoutState = TimeoutCancel; + DPRINT("Mouse type = %u\n", DeviceExtension->MouseType); + return TRUE; default: - DevExt->MouseAttributes.MouseIdentifier = - MOUSE_I8042_HARDWARE; - } - DevExt->MouseResetState++; - I8042IsrWritePortMouse(DevExt, 0xE8); - return TRUE; - case ExpectingSetResolutionDefaultACK: - DevExt->MouseResetState++; - I8042IsrWritePortMouse(DevExt, 0x00); - return TRUE; - case ExpectingSetResolutionDefaultValueACK: - DevExt->MouseResetState = ExpectingSetScaling1to1ACK; - I8042IsrWritePortMouse(DevExt, 0xE6); - return TRUE; - case ExpectingSetScaling1to1ACK: - case ExpectingSetScaling1to1ACK2: - DevExt->MouseResetState++; - I8042IsrWritePortMouse(DevExt, 0xE6); - return TRUE; - case ExpectingSetScaling1to1ACK3: - DevExt->MouseResetState++; - I8042IsrWritePortMouse(DevExt, 0xE9); - return TRUE; - case ExpectingReadMouseStatusACK: - DevExt->MouseResetState++; - return TRUE; - case ExpectingReadMouseStatusByte1: - DevExt->MouseLogiBuffer[0] = *Value; - DevExt->MouseResetState++; - return TRUE; - case ExpectingReadMouseStatusByte2: - DevExt->MouseLogiBuffer[1] = *Value; - DevExt->MouseResetState++; - return TRUE; - case ExpectingReadMouseStatusByte3: - DevExt->MouseLogiBuffer[2] = *Value; - /* Now MouseLogiBuffer is a set of info. If the second - * byte is 0, the mouse didn't understand the magic - * code. Otherwise, it it a Logitech and the second byte - * is the number of buttons, bit 7 of the first byte tells - * if it understands special E7 commands, the rest is an ID. - */ - if (DevExt->MouseLogiBuffer[1]) { - DevExt->MouseAttributes.NumberOfButtons = - DevExt->MouseLogiBuffer[1]; - /* For some reason the ID is the wrong way around */ - DevExt->MouseLogitechID = - ((DevExt->MouseLogiBuffer[0] >> 4) & 0x07) | - ((DevExt->MouseLogiBuffer[0] << 3) & 0x78); - DevExt->MouseType = Ps2pp; - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState = ExpectingSetSamplingRateACK; - return TRUE; - /* TODO: Go through EnableWheel and Enable5Buttons */ - } - DevExt->MouseResetState = EnableWheel; - I8042MouseResetIsr(DevExt, Status, Value); - return TRUE; - case EnableWheel: - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState = 1001; - return TRUE; - case 1001: - I8042IsrWritePortMouse(DevExt, 0xc8); - DevExt->MouseResetState++; - return TRUE; - case 1002: - case 1004: - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState++; - return TRUE; - case 1003: - I8042IsrWritePortMouse(DevExt, 0x64); - DevExt->MouseResetState++; - return TRUE; - case 1005: - I8042IsrWritePortMouse(DevExt, 0x50); - DevExt->MouseResetState++; - return TRUE; - case 1006: - I8042IsrWritePortMouse(DevExt, 0xf2); - DevExt->MouseResetState++; - return TRUE; - case 1007: - /* Ignore ACK */ - DevExt->MouseResetState++; - return TRUE; - case 1008: - /* Now if the value == 3, it's either an Intellimouse - * or Intellimouse Explorer. */ - if (0x03 == *Value) { - DevExt->MouseAttributes.NumberOfButtons = 3; - DevExt->MouseAttributes.MouseIdentifier = - WHEELMOUSE_I8042_HARDWARE; - DevExt->MouseType = Intellimouse; - DevExt->MouseResetState = Enable5Buttons; - I8042MouseResetIsr(DevExt, Status, Value); - return TRUE; - } /* Else, just set the default settings and be done */ - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState = ExpectingSetSamplingRateACK; - return TRUE; - case Enable5Buttons: - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState = 1021; - return TRUE; - case 1022: - case 1024: - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState++; - return TRUE; - case 1021: - case 1023: - I8042IsrWritePortMouse(DevExt, 0xc8); - DevExt->MouseResetState++; - return TRUE; - case 1025: - I8042IsrWritePortMouse(DevExt, 0x50); - DevExt->MouseResetState++; - return TRUE; - case 1026: - I8042IsrWritePortMouse(DevExt, 0xf2); - DevExt->MouseResetState++; - return TRUE; - case 1027: - if (0x04 == *Value) { - DevExt->MouseAttributes.NumberOfButtons = 5; - DevExt->MouseAttributes.MouseIdentifier = - WHEELMOUSE_I8042_HARDWARE; - DevExt->MouseType = IntellimouseExplorer; - } - I8042IsrWritePortMouse(DevExt, 0xf3); - DevExt->MouseResetState = ExpectingSetSamplingRateACK; - return TRUE; - case ExpectingSetSamplingRateACK: - I8042IsrWritePortMouse(DevExt, - (UCHAR)DevExt->MouseAttributes.SampleRate); - DevExt->MouseResetState++; - return TRUE; - case ExpectingSetSamplingRateValueACK: - if (MOUSE_NACK == *Value) { - I8042IsrWritePortMouse(DevExt, 0x3c); - DevExt->MouseAttributes.SampleRate = 60; - DevExt->MouseResetState = 1040; - return TRUE; - } - case 1040: /* Fallthrough */ - I8042IsrWritePortMouse(DevExt, 0xe8); - DevExt->MouseResetState = ExpectingFinalResolutionACK; - return TRUE; - case ExpectingFinalResolutionACK: - I8042IsrWritePortMouse(DevExt, - (UCHAR)(DevExt->Settings.MouseResolution & 0xff)); - DPRINT("%x\n", DevExt->Settings.MouseResolution); - DevExt->MouseResetState = ExpectingFinalResolutionValueACK; - return TRUE; - case ExpectingFinalResolutionValueACK: - I8042IsrWritePortMouse(DevExt, 0xf4); - DevExt->MouseResetState = ExpectingEnableACK; - return TRUE; - case ExpectingEnableACK: - DevExt->MouseState = MouseIdle; - DevExt->MouseTimeoutState = TimeoutCancel; - DPRINT("Mouse type = %d\n", DevExt->MouseType); - return TRUE; - default: - if (DevExt->MouseResetState < 100 || - DevExt->MouseResetState > 999) - DPRINT1("MouseResetState went out of range: %d\n", - DevExt->MouseResetState); - return FALSE; + if (DeviceExtension->MouseResetState < 100 || DeviceExtension->MouseResetState > 999) + DPRINT1("MouseResetState went out of range: %lu\n", DeviceExtension->MouseResetState); + return FALSE; } } -/* - * Prepare for reading the next packet and queue the dpc for handling - * this one. - * - * Context is the device object. - */ -VOID STDCALL I8042QueueMousePacket(PVOID Context) -{ - PDEVICE_OBJECT DeviceObject = Context; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - DevExt->MouseComplete = TRUE; - DevExt->MouseInBuffer++; - if (DevExt->MouseInBuffer > - DevExt->MouseAttributes.InputDataQueueLength) { - DPRINT1("Mouse buffer overflow\n"); - DevExt->MouseInBuffer--; - } - - DPRINT("Irq completes mouse packet\n"); - KeInsertQueueDpc(&DevExt->DpcMouse, DevExt, NULL); -} - -/* - * Updates ButtonFlags according to RawButtons and a saved state; - * Only takes in account the bits that are set in Mask - */ -VOID STDCALL I8042MouseHandleButtons(PDEVICE_EXTENSION DevExt, - USHORT Mask) -{ - PMOUSE_INPUT_DATA MouseInput = DevExt->MouseBuffer + - DevExt->MouseInBuffer; - USHORT NewButtonData = (USHORT)(MouseInput->RawButtons & Mask); - USHORT ButtonDiff = (NewButtonData ^ DevExt->MouseButtonState) & Mask; - - /* Note that the defines are such: - * MOUSE_LEFT_BUTTON_DOWN 1 - * MOUSE_LEFT_BUTTON_UP 2 - */ - MouseInput->ButtonFlags |= (NewButtonData & ButtonDiff) | - (((~(NewButtonData)) << 1) & - (ButtonDiff << 1)) | - (MouseInput->RawButtons & 0xfc00); - - DPRINT("Left raw/up/down: %d/%d/%d\n", MouseInput->RawButtons & MOUSE_LEFT_BUTTON_DOWN, - MouseInput->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN, - MouseInput->ButtonFlags & MOUSE_LEFT_BUTTON_UP); - - DevExt->MouseButtonState = (DevExt->MouseButtonState & ~Mask) | - (NewButtonData & Mask); -} - -VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt, - UCHAR Output) -{ - PMOUSE_INPUT_DATA MouseInput = DevExt->MouseBuffer + - DevExt->MouseInBuffer; - CHAR Scroll; - - switch (DevExt->MouseState) { - case MouseIdle: - /* This bit should be 1, if not drop the packet, we - * might be lucky and get in sync again - */ - if (!(Output & 8)) { - DPRINT1("Bad input, dropping..\n"); - return; - } - - MouseInput->Buttons = 0; - MouseInput->RawButtons = 0; - MouseInput->Flags = MOUSE_MOVE_RELATIVE; - - /* Note how we ignore the overflow bits, like Windows - * is said to do. There's no reasonable thing to do - * anyway. - */ - - if (Output & 16) - MouseInput->LastX = 1; - else - MouseInput->LastX = 0; - - if (Output & 32) - MouseInput->LastY = 1; - else - MouseInput->LastY = 0; - - if (Output & 1) { - MouseInput->RawButtons |= MOUSE_LEFT_BUTTON_DOWN; - } - - if (Output & 2) { - MouseInput->RawButtons |= MOUSE_RIGHT_BUTTON_DOWN; - } - - if (Output & 4) { - MouseInput->RawButtons |= MOUSE_MIDDLE_BUTTON_DOWN; - } - DevExt->MouseState = XMovement; - break; - case XMovement: - if (MouseInput->LastX) - MouseInput->LastX = (LONG) Output - 256; - else - MouseInput->LastX = Output; - - DevExt->MouseState = YMovement; - break; - case YMovement: - if (MouseInput->LastY) - MouseInput->LastY = (LONG)Output - 256; - else - MouseInput->LastY = (LONG)Output; - - /* Windows wants it the other way around */ - MouseInput->LastY = -MouseInput->LastY; - - if (DevExt->MouseType == GenericPS2 || - DevExt->MouseType == Ps2pp) { - I8042MouseHandleButtons(DevExt, - MOUSE_LEFT_BUTTON_DOWN | - MOUSE_RIGHT_BUTTON_DOWN | - MOUSE_MIDDLE_BUTTON_DOWN); - I8042QueueMousePacket( - DevExt->MouseObject); - DevExt->MouseState = MouseIdle; - } else { - DevExt->MouseState = ZMovement; - } - break; - case ZMovement: - Scroll = Output & 0x0f; - if (Scroll & 8) - Scroll |= 0xf0; - - if (Scroll) { - MouseInput->RawButtons |= MOUSE_WHEEL; - MouseInput->ButtonData = (USHORT)(Scroll * -WHEEL_DELTA); - } - - if (DevExt->MouseType == IntellimouseExplorer) { - if (Output & 16) - MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN; - - if (Output & 32) - MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN; - } - I8042MouseHandleButtons(DevExt, MOUSE_LEFT_BUTTON_DOWN | - MOUSE_RIGHT_BUTTON_DOWN | - MOUSE_MIDDLE_BUTTON_DOWN | - MOUSE_BUTTON_4_DOWN | - MOUSE_BUTTON_5_DOWN); - I8042QueueMousePacket(DevExt->MouseObject); - DevExt->MouseState = MouseIdle; - break; - default: - DPRINT1("Unexpected state!\n"); - } -} - -BOOLEAN STDCALL I8042InterruptServiceMouse(struct _KINTERRUPT *Interrupt, - VOID *Context) +BOOLEAN NTAPI +i8042MouInterruptService( + IN PKINTERRUPT Interrupt, + PVOID Context) { + PI8042_MOUSE_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + ULONG Counter; UCHAR Output, PortStatus; NTSTATUS Status; - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION) Context; - ULONG Iterations = 0; - do { - Status = I8042ReadStatus(&PortStatus); - Status = I8042ReadData(&Output); - Iterations++; - if (STATUS_SUCCESS == Status) + DeviceExtension = (PI8042_MOUSE_EXTENSION)Context; + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + Counter = PortDeviceExtension->Settings.PollStatusIterations; + + while (Counter) + { + Status = i8042ReadStatus(PortDeviceExtension, &PortStatus); + if (!NT_SUCCESS(Status)) + { + DPRINT("i8042ReadStatus() failed with status 0x%08lx\n", Status); + return FALSE; + } + Status = i8042ReadMouseData(PortDeviceExtension, &Output); + if (NT_SUCCESS(Status)) break; KeStallExecutionProcessor(1); - } while (Iterations < DevExt->Settings.PollStatusIterations); - - if (STATUS_SUCCESS != Status) { - DPRINT1("Spurious I8042 mouse interrupt\n"); + Counter--; + } + if (Counter == 0) + { + DPRINT("Spurious i8042 mouse interrupt\n"); return FALSE; } - DPRINT("Got: %x\n", Output); + DPRINT("Got: 0x%02x\n", Output); - if (I8042PacketIsr(DevExt, Output)) { - if (DevExt->PacketComplete) { + if (i8042PacketIsr(PortDeviceExtension, Output)) + { + if (PortDeviceExtension->PacketComplete) + { DPRINT("Packet complete\n"); - KeInsertQueueDpc(&DevExt->DpcKbd, DevExt, NULL); + KeInsertQueueDpc(&DeviceExtension->DpcMouse, NULL, NULL); } DPRINT("Irq eaten by packet\n"); return TRUE; } - I8042MouseInputTestTimeout(DevExt); + DPRINT("Irq is mouse input\n"); - if (I8042MouseResetIsr(DevExt, PortStatus, &Output)) { + i8042MouInputTestTimeout(DeviceExtension); + + if (i8042MouResetIsr(DeviceExtension, PortStatus, Output)) + { DPRINT("Handled by ResetIsr or hooked Isr\n"); - if (NoChange != DevExt->MouseTimeoutState) { - KeInsertQueueDpc(&DevExt->DpcMouse, DevExt, NULL); + if (NoChange != DeviceExtension->MouseTimeoutState) { + KeInsertQueueDpc(&DeviceExtension->DpcMouse, NULL, NULL); } return TRUE; } - if (DevExt->MouseType == Ps2pp) - I8042MouseHandlePs2pp(DevExt, Output); + if (DeviceExtension->MouseType == Ps2pp) + i8042MouHandlePs2pp(DeviceExtension, Output); else - I8042MouseHandle(DevExt, Output); + i8042MouHandle(DeviceExtension, Output); return TRUE; } -VOID STDCALL I8042DpcRoutineMouse(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) +/* ================================================ + * FIXME: this part is taken from psaux.sys driver, + * and doesn't follow the coding style of this file + * ===============================================*/ + +#define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8 +#define PSMOUSE_CMD_ENABLE 0x00f4 +#define PSMOUSE_CMD_GETID (0x0200 | MOU_CMD_GET_ID) +#define PSMOUSE_CMD_RESET_BAT (0x0200 | MOU_CMD_RESET) +#define PSMOUSE_RET_ACK MOUSE_ACK +#define PSMOUSE_RET_NAK MOUSE_NACK +#define MOUSE_INTERRUPTS_ON (CCB_TRANSLATE | \ + CCB_SYSTEM_FLAG | \ + CCB_MOUSE_INT_ENAB) + +typedef struct _I8042_MOUSE_EXTENSION_OLD { - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)SystemArgument1; - ULONG MouseTransferred = 0; - ULONG MouseInBufferCopy; - KIRQL Irql; - LARGE_INTEGER Timeout; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + UCHAR pkt[8]; + UCHAR ack; + UINT RepliesExpected; +} I8042_MOUSE_EXTENSION_OLD, *PI8042_MOUSE_EXTENSION_OLD; - switch (DevExt->MouseTimeoutState) { - case TimeoutStart: - DevExt->MouseTimeoutState = NoChange; - if (DevExt->MouseTimeoutActive && - !KeCancelTimer(&DevExt->TimerMouseTimeout)) { - /* The timer fired already, give up */ - DevExt->MouseTimeoutActive = FALSE; - return; - } - - Timeout.QuadPart = -15000000; - /* 1.5 seconds, should be enough */ - - KeSetTimer(&DevExt->TimerMouseTimeout, - Timeout, - &DevExt->DpcMouseTimeout); - DevExt->MouseTimeoutActive = TRUE; - return; - case TimeoutCancel: - DevExt->MouseTimeoutState = NoChange; - KeCancelTimer(&DevExt->TimerMouseTimeout); - DevExt->MouseTimeoutActive = FALSE; - default: - /* nothing, don't want a warning */ ; - } - - /* Should be unlikely */ - if (!DevExt->MouseComplete) - return; - - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); - - DevExt->MouseComplete = FALSE; - MouseInBufferCopy = DevExt->MouseInBuffer; - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); - - DPRINT ("Send a mouse packet\n"); - - if (!DevExt->MouseData.ClassService) - return; - - ((PSERVICE_CALLBACK_ROUTINE) DevExt->MouseData.ClassService)( - DevExt->MouseData.ClassDeviceObject, - DevExt->MouseBuffer, - DevExt->MouseBuffer + MouseInBufferCopy, - &MouseTransferred); - - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); - - DevExt->MouseInBuffer -= MouseTransferred; - if (DevExt->MouseInBuffer) - RtlMoveMemory(DevExt->MouseBuffer, - DevExt->MouseBuffer+MouseTransferred, - DevExt->MouseInBuffer * sizeof(MOUSE_INPUT_DATA)); - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); -} - -/* This timer DPC will be called when the mouse reset times out. - * I'll just send the 'disable mouse port' command to the controller - * and say the mouse doesn't exist. - */ -VOID STDCALL I8042DpcRoutineMouseTimeout(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) +/* Sends a byte to the mouse */ +static INT SendByte( + IN PI8042_MOUSE_EXTENSION_OLD DeviceExtension, + IN UCHAR byte) { - PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)DeferredContext; - KIRQL Irql; + INT timeout = 100; /* 100 msec */ + UCHAR scancode; + LARGE_INTEGER Millisecond_Timeout; - Irql = KeAcquireInterruptSpinLock(DevExt->HighestDIRQLInterrupt); + Millisecond_Timeout.QuadPart = -10000L; - DPRINT1("Mouse initialization timeout! (substate %x) " - "Disabling mouse.\n", - DevExt->MouseResetState); - - if (!I8042MouseDisable(DevExt)) { - DPRINT1("Failed to disable mouse.\n"); - } - - DevExt->MouseExists = FALSE; - - KeReleaseInterruptSpinLock(DevExt->HighestDIRQLInterrupt, Irql); -} - -/* - * Process the mouse internal device requests - * returns FALSE if it doesn't understand the - * call so someone else can handle it. - */ -#if 0 -static BOOLEAN STDCALL I8042StartIoMouse(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PIO_STACK_LOCATION Stk; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) { - case IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER: - I8042StartPacket( - DevExt, - DeviceObject, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - Stk->Parameters.DeviceIoControl.InputBufferLength, - Irp); - break; - - default: - return FALSE; - } - - return TRUE; -} -#endif - -/* - * Runs the mouse IOCTL_INTERNAL dispatch. - * Returns NTSTATUS_INVALID_DEVICE_REQUEST if it doesn't handle this request - * so someone else can have a try at it. - */ -NTSTATUS STDCALL I8042InternalDeviceControlMouse(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - PIO_STACK_LOCATION Stk; - PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION DevExt = FdoDevExt->PortDevExt; - - DPRINT("InternalDeviceControl\n"); - - Irp->IoStatus.Information = 0; - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) { - - case IOCTL_INTERNAL_MOUSE_CONNECT: - DPRINT("IOCTL_INTERNAL_MOUSE_CONNECT\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(CONNECT_DATA)) { - DPRINT1("Mouse IOCTL_INTERNAL_MOUSE_CONNECT " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } - - if (!DevExt->MouseExists) { - Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; - goto intcontfailure; - } - - if (DevExt->MouseClaimed) { - DPRINT1("IOCTL_INTERNAL_MOUSE_CONNECT: " - "Mouse is already claimed\n"); - Irp->IoStatus.Status = STATUS_SHARING_VIOLATION; - goto intcontfailure; - } - - memcpy(&DevExt->MouseData, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - DevExt->MouseHook.IsrWritePort = I8042IsrWritePortMouse; - DevExt->MouseHook.QueueMousePacket = - I8042QueueMousePacket; - DevExt->MouseHook.CallContext = DevExt; + DeviceExtension->ack = 0; + i8042IsrWritePort(DeviceExtension->PortDeviceExtension, byte, CTRL_WRITE_MOUSE); + while ((DeviceExtension->ack == 0) && timeout--) + { + if (i8042ReadKeyboardData(DeviceExtension->PortDeviceExtension, &scancode)) { - PIO_WORKITEM WorkItem; - PI8042_HOOK_WORKITEM WorkItemData; - - WorkItem = IoAllocateWorkItem(DeviceObject); - if (!WorkItem) { - DPRINT ("IOCTL_INTERNAL_MOUSE_CONNECT: " - "Can't allocate work item\n"); - Irp->IoStatus.Status = - STATUS_INSUFFICIENT_RESOURCES; - goto intcontfailure; + switch(scancode) + { + case PSMOUSE_RET_ACK: + DeviceExtension->ack = 1; + break; + case PSMOUSE_RET_NAK: + DeviceExtension->ack = -1; + break; + default: + DeviceExtension->ack = 1; /* Workaround for mice which don't ACK the Get ID command */ + if (DeviceExtension->RepliesExpected) + DeviceExtension->pkt[--DeviceExtension->RepliesExpected] = scancode; + break; } - - WorkItemData = ExAllocatePoolWithTag( - NonPagedPool, - sizeof(I8042_HOOK_WORKITEM), - TAG_I8042); - if (!WorkItemData) { - DPRINT ("IOCTL_INTERNAL_MOUSE_CONNECT: " - "Can't allocate work item data\n"); - Irp->IoStatus.Status = - STATUS_INSUFFICIENT_RESOURCES; - IoFreeWorkItem(WorkItem); - goto intcontfailure; - } - WorkItemData->WorkItem = WorkItem; - WorkItemData->Target = - DevExt->MouseData.ClassDeviceObject; - WorkItemData->Irp = Irp; - - IoMarkIrpPending(Irp); - DevExt->MouseState = MouseResetting; - DevExt->MouseResetState = 1100; - IoQueueWorkItem(WorkItem, - I8042SendHookWorkItem, - DelayedWorkQueue, - WorkItemData); - - Irp->IoStatus.Status = STATUS_PENDING; + return (INT)(-(DeviceExtension->ack <= 0)); } - - break; - case IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER: - DPRINT("IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < 1) { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } - if (!DevExt->MouseInterruptObject) { - Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; - goto intcontfailure; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - Irp->IoStatus.Status = STATUS_PENDING; - - break; - case IOCTL_MOUSE_QUERY_ATTRIBUTES: - DPRINT("IOCTL_MOUSE_QUERY_ATTRIBUTES\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(MOUSE_ATTRIBUTES)) { - DPRINT("Mouse IOCTL_MOUSE_QUERY_ATTRIBUTES " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - memcpy(Irp->AssociatedIrp.SystemBuffer, - &DevExt->MouseAttributes, - sizeof(MOUSE_ATTRIBUTES)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - default: - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - break; + KeDelayExecutionThread(KernelMode, FALSE, &Millisecond_Timeout); } - -intcontfailure: - return Irp->IoStatus.Status; + return (INT)(-(DeviceExtension->ack <= 0)); } -BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt) +/* Send a PS/2 command to the mouse. */ +static INT SendCommand( + IN PI8042_MOUSE_EXTENSION_OLD DeviceExtension, + IN PUCHAR param, + IN INT command) { - UCHAR Value; - NTSTATUS Status; + LARGE_INTEGER Millisecond_Timeout; + UCHAR scancode; + INT timeout = 500; /* 500 msec */ + UCHAR send = (command >> 12) & 0xf; + UCHAR receive = (command >> 8) & 0xf; + UCHAR i; - DPRINT("Enabling mouse\n"); + Millisecond_Timeout.QuadPart = -10000L; - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; + DeviceExtension->RepliesExpected = receive; + if (command == PSMOUSE_CMD_RESET_BAT) + timeout = 2000; /* 2 sec */ + + if (command & 0xff) + if (SendByte(DeviceExtension, command & 0xff)) + return (INT)(DeviceExtension->RepliesExpected = 0) - 1; + + for (i = 0; i < send; i++) + if (SendByte(DeviceExtension, param[i])) + return (INT)(DeviceExtension->RepliesExpected = 0) - 1; + + while (DeviceExtension->RepliesExpected && timeout--) + { + if (DeviceExtension->RepliesExpected == 1 && command == PSMOUSE_CMD_RESET_BAT) + timeout = 100; + + if (DeviceExtension->RepliesExpected == 1 && command == PSMOUSE_CMD_GETID && + DeviceExtension->pkt[1] != 0xab && DeviceExtension->pkt[1] != 0xac) + { + DeviceExtension->RepliesExpected = 0; + break; + } + + if (i8042ReadKeyboardData(DeviceExtension->PortDeviceExtension, &scancode)) + { + DeviceExtension->pkt[--DeviceExtension->RepliesExpected] = scancode; + } + + KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout); } - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } + for (i = 0; i < receive; i++) + param[i] = DeviceExtension->pkt[(receive - 1) - i]; - Value &= ~(0x20); // don't disable mouse - Value |= 0x02; // enable mouse interrupts + if (DeviceExtension->RepliesExpected) + return (int)(DeviceExtension->RepliesExpected = 0) - 1; - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - return TRUE; + return 0; } -BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt) +/* Detect if mouse is just a standard ps/2 mouse */ +static BOOLEAN TestMouse( + IN PI8042_MOUSE_EXTENSION_OLD DeviceExtension) { - UCHAR Value; - NTSTATUS Status; + UCHAR param[4]; - DPRINT("Disabling mouse\n"); + param[0] = param[1] = 0xa5; - I8042Flush(); /* Just to be (kind of) sure */ + /* + * First, we check if it's a mouse. It should send 0x00 or 0x03 + * in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer. + */ + if(SendCommand(DeviceExtension, param, PSMOUSE_CMD_GETID)) + return -1; - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) { - DPRINT1("Can't read i8042 mode\n"); - return FALSE; - } + if(param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04) + return -1; - Status = I8042ReadDataWait(DevExt, &Value); - if (!NT_SUCCESS(Status)) { - DPRINT1("No response after read i8042 mode\n"); - return FALSE; - } - - Value |= 0x20; // don't disable mouse - Value &= ~(0x02); // enable mouse interrupts - - if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) { - DPRINT1("Can't set i8042 mode\n"); - return FALSE; - } - - if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) { - DPRINT1("Can't send i8042 mode\n"); - return FALSE; - } - - I8042Flush(); - /* Just to be (kind of) sure; if the mouse would - * say something while we are disabling it, these bytes would - * block the keyboard. + /* + * Then we reset and disable the mouse so that it doesn't generate events. */ return TRUE; } -BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt) +/* Initialize the PS/2 mouse support */ +static BOOLEAN SetupMouse( + IN PI8042_MOUSE_EXTENSION_OLD DeviceExtension) { - BOOLEAN Ok = TRUE; - NTSTATUS Status; - UCHAR Value; - UCHAR ExpectedReply[] = { 0xFA, 0xAA, 0x00 }; - unsigned ReplyByte; + LARGE_INTEGER Millisecond_Timeout; - if (! I8042Write(DevExt, I8042_CTRL_PORT, 0xD4) || - ! I8042Write(DevExt, I8042_DATA_PORT, 0xFF)) + Millisecond_Timeout.QuadPart = -10000L; + + /* setup */ + DeviceExtension->RepliesExpected = 0; + DeviceExtension->ack = 0; + + /* Enable the PS/2 mouse port */ + i8042Write(DeviceExtension->PortDeviceExtension, DeviceExtension->PortDeviceExtension->ControlPort, CONTROLLER_COMMAND_MOUSE_ENABLE); + + if(TestMouse(DeviceExtension)) { - DPRINT1("Failed to write reset command to mouse\n"); - Ok = FALSE; + DPRINT("Detected Mouse\n"); + + if(SendCommand(DeviceExtension, NULL, PSMOUSE_CMD_ENABLE)) + DPRINT1("Failed to enable mouse!\n"); + + /* Enable controller interrupts */ + i8042Write(DeviceExtension->PortDeviceExtension, DeviceExtension->PortDeviceExtension->ControlPort, KBD_WRITE_MODE); + i8042Write(DeviceExtension->PortDeviceExtension, DeviceExtension->PortDeviceExtension->DataPort, MOUSE_INTERRUPTS_ON); } - for (ReplyByte = 0; - ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]) && Ok; - ReplyByte++) - { - Status = I8042ReadDataWait(DevExt, &Value); - if (! NT_SUCCESS(Status)) - { - DPRINT1("No ACK after mouse reset, status 0x%08x\n", - Status); - Ok = FALSE; - } - else if (Value != ExpectedReply[ReplyByte]) - { - DPRINT1("Unexpected reply: 0x%02x (expected 0x%02x)\n", - Value, ExpectedReply[ReplyByte]); - Ok = FALSE; - } - } - - if (! Ok) - { - /* There is probably no mouse present. On some systems, - the probe locks the entire keyboard controller. Let's - try to get access to the keyboard again by sending a - reset */ - I8042Flush(); - I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST); - I8042ReadDataWait(DevExt, &Value); - I8042Flush(); - } - - DPRINT("Mouse %sdetected\n", Ok ? "" : "not "); - - return Ok; + return TRUE; +} + +static NTSTATUS OldInitialization( + IN PPORT_DEVICE_EXTENSION PortDeviceExtension) +{ + I8042_MOUSE_EXTENSION_OLD DeviceExtension; + + RtlZeroMemory(&DeviceExtension, sizeof(I8042_MOUSE_EXTENSION_OLD)); + DeviceExtension.PortDeviceExtension = PortDeviceExtension; + SetupMouse(&DeviceExtension); + return STATUS_SUCCESS; } diff --git a/reactos/drivers/input/i8042prt/pnp.c b/reactos/drivers/input/i8042prt/pnp.c new file mode 100644 index 00000000000..b60fb1bc0d1 --- /dev/null +++ b/reactos/drivers/input/i8042prt/pnp.c @@ -0,0 +1,666 @@ +/* + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/pnp.c + * PURPOSE: IRP_MJ_PNP operations + * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "i8042prt.h" + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/* This is all pretty confusing. There's more than one way to + * disable/enable the keyboard. You can send KBD_ENABLE to the + * keyboard, and it will start scanning keys. Sending KBD_DISABLE + * will disable the key scanning but also reset the parameters to + * defaults. + * + * You can also send 0xAE to the controller for enabling the + * keyboard clock line and 0xAD for disabling it. Then it'll + * automatically get turned on at the next command. The last + * way is by modifying the bit that drives the clock line in the + * 'command byte' of the controller. This is almost, but not quite, + * the same as the AE/AD thing. The difference can be used to detect + * some really old broken keyboard controllers which I hope won't be + * necessary. + * + * We change the command byte, sending KBD_ENABLE/DISABLE seems to confuse + * some kvm switches. + */ +BOOLEAN +i8042ChangeMode( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR FlagsToDisable, + IN UCHAR FlagsToEnable) +{ + UCHAR Value; + NTSTATUS Status; + + if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_READ_MODE)) + { + DPRINT1("Can't read i8042 mode\n"); + return FALSE; + } + + Status = i8042ReadDataWait(DeviceExtension, &Value); + if (!NT_SUCCESS(Status)) + { + DPRINT1("No response after read i8042 mode\n"); + return FALSE; + } + + Value &= ~FlagsToDisable; + Value |= FlagsToEnable; + + if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_WRITE_MODE)) + { + DPRINT1("Can't set i8042 mode\n"); + return FALSE; + } + + if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value)) + { + DPRINT1("Can't send i8042 mode\n"); + return FALSE; + } + + return TRUE; +} + +static NTSTATUS +i8042BasicDetect( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + NTSTATUS Status; + UCHAR Value = 0; + + i8042Flush(DeviceExtension); + + if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST)) + { + DPRINT1("Writing CTRL_SELF_TEST command failed\n"); + return STATUS_IO_TIMEOUT; + } + + Status = i8042ReadDataWait(DeviceExtension, &Value); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to read CTRL_SELF_TEST response, status 0x%08lx\n", Status); + return Status; + } + + if (Value != 0x55) + { + DPRINT1("Got 0x%02x instead of 0x55\n", Value); + return STATUS_IO_DEVICE_ERROR; + } + + /* Don't enable keyboard and mouse interrupts, disable keyboard/mouse */ + if (!i8042ChangeMode(DeviceExtension, CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB, CCB_KBD_DISAB | CCB_MOUSE_DISAB)) + return STATUS_IO_DEVICE_ERROR; + + /* + * We used to send a KBD_LINE_TEST (0xAB) command here, but on at least HP + * Pavilion notebooks the response to that command was incorrect. + * So now we just assume that a keyboard is attached. + */ + DeviceExtension->Flags |= KEYBOARD_PRESENT; + + if (i8042Write(DeviceExtension, DeviceExtension->ControlPort, MOUSE_LINE_TEST)) + { + Status = i8042ReadDataWait(DeviceExtension, &Value); + if (NT_SUCCESS(Status) && Value == 0) + DeviceExtension->Flags |= MOUSE_PRESENT; + } + + if (IsFirstStageSetup()) + /* Ignore the mouse */ + DeviceExtension->Flags &= ~MOUSE_PRESENT; + + return STATUS_SUCCESS; +} + +static BOOLEAN +i8042DetectKeyboard( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + NTSTATUS Status; + + if (!i8042ChangeMode(DeviceExtension, 0, CCB_KBD_DISAB)) + return FALSE; + + i8042Flush(DeviceExtension); + + /* Set LEDs (that is not fatal if some error occurs) */ + Status = i8042SynchWritePort(DeviceExtension, 0, KBD_CMD_SET_LEDS, TRUE); + if (NT_SUCCESS(Status)) + { + Status = i8042SynchWritePort(DeviceExtension, 0, 0, TRUE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Can't finish SET_LEDS (0x%08lx)\n", Status); + return FALSE; + } + } + else + { + DPRINT("Warning: can't write SET_LEDS (0x%08lx)\n", Status); + } + + /* Turn on translation */ + if (!i8042ChangeMode(DeviceExtension, 0, CCB_TRANSLATE)) + return FALSE; + + return TRUE; +} + +static BOOLEAN +i8042DetectMouse( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + BOOLEAN Ok = FALSE; + NTSTATUS Status; + UCHAR Value; + UCHAR ExpectedReply[] = { MOUSE_ACK, 0xAA, 0x00 }; + UCHAR ReplyByte; + + i8042Flush(DeviceExtension); + + if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_WRITE_MOUSE) + ||!i8042Write(DeviceExtension, DeviceExtension->DataPort, MOU_CMD_RESET)) + { + DPRINT1("Failed to write reset command to mouse\n"); + goto cleanup; + } + + for (ReplyByte = 0; + ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]); + ReplyByte++) + { + Status = i8042ReadDataWait(DeviceExtension, &Value); + if (!NT_SUCCESS(Status)) + { + DPRINT1("No ACK after mouse reset, status 0x%08lx\n", Status); + goto cleanup; + } + else if (Value != ExpectedReply[ReplyByte]) + { + DPRINT1("Unexpected reply: 0x%02x (expected 0x%02x)\n", + Value, ExpectedReply[ReplyByte]); + goto cleanup; + } + } + + Ok = TRUE; + +cleanup: + if (!Ok) + { + /* There is probably no mouse present. On some systems, + the probe locks the entire keyboard controller. Let's + try to get access to the keyboard again by sending a + reset */ + i8042Flush(DeviceExtension); + i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST); + i8042ReadDataWait(DeviceExtension, &Value); + i8042Flush(DeviceExtension); + } + + DPRINT("Mouse %sdetected\n", Ok ? "" : "not "); + + return Ok; +} + +static NTSTATUS +i8042ConnectKeyboardInterrupt( + IN PI8042_KEYBOARD_EXTENSION DeviceExtension) +{ + PPORT_DEVICE_EXTENSION PortDeviceExtension; + KIRQL DirqlMax; + NTSTATUS Status; + + DPRINT("i8042ConnectKeyboardInterrupt()\n"); + + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + DirqlMax = MAX( + PortDeviceExtension->KeyboardInterrupt.Dirql, + PortDeviceExtension->MouseInterrupt.Dirql); + + DPRINT("KeyboardInterrupt.Vector %lu\n", + PortDeviceExtension->KeyboardInterrupt.Vector); + DPRINT("KeyboardInterrupt.Dirql %lu\n", + PortDeviceExtension->KeyboardInterrupt.Dirql); + DPRINT("KeyboardInterrupt.DirqlMax %lu\n", + DirqlMax); + DPRINT("KeyboardInterrupt.InterruptMode %s\n", + PortDeviceExtension->KeyboardInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched"); + DPRINT("KeyboardInterrupt.ShareInterrupt %s\n", + PortDeviceExtension->KeyboardInterrupt.ShareInterrupt ? "yes" : "no"); + DPRINT("KeyboardInterrupt.Affinity 0x%lx\n", + PortDeviceExtension->KeyboardInterrupt.Affinity); + Status = IoConnectInterrupt( + &PortDeviceExtension->KeyboardInterrupt.Object, + i8042KbdInterruptService, + DeviceExtension, &PortDeviceExtension->SpinLock, + PortDeviceExtension->KeyboardInterrupt.Vector, PortDeviceExtension->KeyboardInterrupt.Dirql, DirqlMax, + PortDeviceExtension->KeyboardInterrupt.InterruptMode, PortDeviceExtension->KeyboardInterrupt.ShareInterrupt, + PortDeviceExtension->KeyboardInterrupt.Affinity, FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoConnectInterrupt() failed with status 0x%08x\n", Status); + return Status; + } + + if (DirqlMax == PortDeviceExtension->KeyboardInterrupt.Dirql) + PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object; + PortDeviceExtension->Flags |= KEYBOARD_INITIALIZED; + return STATUS_SUCCESS; +} + +static NTSTATUS +i8042ConnectMouseInterrupt( + IN PI8042_MOUSE_EXTENSION DeviceExtension) +{ + PPORT_DEVICE_EXTENSION PortDeviceExtension; + KIRQL DirqlMax; + NTSTATUS Status; + + DPRINT("i8042ConnectMouseInterrupt()\n"); + + Status = i8042MouInitialize(DeviceExtension); + if (!NT_SUCCESS(Status)) + return Status; + + PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; + DirqlMax = MAX( + PortDeviceExtension->KeyboardInterrupt.Dirql, + PortDeviceExtension->MouseInterrupt.Dirql); + + DPRINT("MouseInterrupt.Vector %lu\n", + PortDeviceExtension->MouseInterrupt.Vector); + DPRINT("MouseInterrupt.Dirql %lu\n", + PortDeviceExtension->MouseInterrupt.Dirql); + DPRINT("MouseInterrupt.DirqlMax %lu\n", + DirqlMax); + DPRINT("MouseInterrupt.InterruptMode %s\n", + PortDeviceExtension->MouseInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched"); + DPRINT("MouseInterrupt.ShareInterrupt %s\n", + PortDeviceExtension->MouseInterrupt.ShareInterrupt ? "yes" : "no"); + DPRINT("MouseInterrupt.Affinity 0x%lx\n", + PortDeviceExtension->MouseInterrupt.Affinity); + Status = IoConnectInterrupt( + &PortDeviceExtension->MouseInterrupt.Object, + i8042MouInterruptService, + DeviceExtension, &PortDeviceExtension->SpinLock, + PortDeviceExtension->MouseInterrupt.Vector, PortDeviceExtension->MouseInterrupt.Dirql, DirqlMax, + PortDeviceExtension->MouseInterrupt.InterruptMode, PortDeviceExtension->MouseInterrupt.ShareInterrupt, + PortDeviceExtension->MouseInterrupt.Affinity, FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoConnectInterrupt() failed with status 0x%08x\n", Status); + goto cleanup; + } + + if (DirqlMax == PortDeviceExtension->MouseInterrupt.Dirql) + PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->MouseInterrupt.Object; + + PortDeviceExtension->Flags |= MOUSE_INITIALIZED; + Status = STATUS_SUCCESS; + +cleanup: + if (!NT_SUCCESS(Status)) + { + PortDeviceExtension->Flags &= ~MOUSE_INITIALIZED; + if (PortDeviceExtension->MouseInterrupt.Object) + { + IoDisconnectInterrupt(PortDeviceExtension->MouseInterrupt.Object); + PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object; + } + } + return Status; +} + +static NTSTATUS +EnableInterrupts( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + UCHAR FlagsToDisable = 0; + UCHAR FlagsToEnable = 0; + + /* Select the devices we have */ + if (DeviceExtension->Flags & KEYBOARD_PRESENT) + { + FlagsToDisable |= CCB_KBD_DISAB; + FlagsToEnable |= CCB_KBD_INT_ENAB; + } + if (DeviceExtension->Flags & MOUSE_PRESENT) + { + FlagsToDisable |= CCB_MOUSE_DISAB; + FlagsToEnable |= CCB_MOUSE_INT_ENAB; + } + if (!i8042ChangeMode(DeviceExtension, FlagsToDisable, FlagsToEnable)) + return STATUS_UNSUCCESSFUL; + + return STATUS_SUCCESS; +} + +static NTSTATUS +StartProcedure( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + NTSTATUS Status; + + if (DeviceExtension->DataPort == 0) + { + /* Unable to do something at the moment */ + return STATUS_SUCCESS; + } + + if (!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_PRESENT))) + { + /* Try to detect them */ + DPRINT("Check if the controller is really a i8042\n"); + Status = i8042BasicDetect(DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT("i8042BasicDetect() failed with status 0x%08lx\n", Status); + return STATUS_UNSUCCESSFUL; + } + DPRINT("Detecting keyboard\n"); + if (!i8042DetectKeyboard(DeviceExtension)) + return STATUS_UNSUCCESSFUL; + DPRINT("Detecting mouse\n"); + if (!i8042DetectMouse(DeviceExtension)) + return STATUS_UNSUCCESSFUL; + DPRINT("Keyboard present: %s\n", DeviceExtension->Flags & KEYBOARD_PRESENT ? "YES" : "NO"); + DPRINT("Mouse present : %s\n", DeviceExtension->Flags & MOUSE_PRESENT ? "YES" : "NO"); + } + + /* Connect interrupts */ + if (DeviceExtension->Flags & KEYBOARD_PRESENT && + DeviceExtension->Flags & KEYBOARD_CONNECTED && + DeviceExtension->Flags & KEYBOARD_STARTED && + !(DeviceExtension->Flags & (MOUSE_PRESENT | KEYBOARD_INITIALIZED))) + { + /* No mouse, and the keyboard is ready */ + Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension); + if (NT_SUCCESS(Status)) + { + DeviceExtension->Flags |= KEYBOARD_INITIALIZED; + Status = EnableInterrupts(DeviceExtension); + } + } + else if (DeviceExtension->Flags & MOUSE_PRESENT && + DeviceExtension->Flags & MOUSE_CONNECTED && + DeviceExtension->Flags & MOUSE_STARTED && + !(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_INITIALIZED))) + { + /* No keyboard, and the mouse is ready */ + Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension); + if (NT_SUCCESS(Status)) + { + DeviceExtension->Flags |= MOUSE_INITIALIZED; + Status = EnableInterrupts(DeviceExtension); + } + } + else if (DeviceExtension->Flags & KEYBOARD_PRESENT && + DeviceExtension->Flags & KEYBOARD_CONNECTED && + DeviceExtension->Flags & KEYBOARD_STARTED && + DeviceExtension->Flags & MOUSE_PRESENT && + DeviceExtension->Flags & MOUSE_CONNECTED && + DeviceExtension->Flags & MOUSE_STARTED && + !(DeviceExtension->Flags & (KEYBOARD_INITIALIZED | MOUSE_INITIALIZED))) + { + /* The keyboard and mouse are ready */ + Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension); + if (NT_SUCCESS(Status)) + { + DeviceExtension->Flags |= KEYBOARD_INITIALIZED; + Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension); + if (NT_SUCCESS(Status)) + { + DeviceExtension->Flags |= MOUSE_INITIALIZED; + Status = EnableInterrupts(DeviceExtension); + } + } + } + else + { + /* Nothing to do */ + Status = STATUS_SUCCESS; + } + + return Status; +} + +static NTSTATUS +i8042PnpStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PCM_RESOURCE_LIST AllocatedResources, + IN PCM_RESOURCE_LIST AllocatedResourcesTranslated) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + PPORT_DEVICE_EXTENSION PortDeviceExtension; + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor, ResourceDescriptorTranslated; + INTERRUPT_DATA InterruptData; + BOOLEAN FoundDataPort = FALSE; + BOOLEAN FoundControlPort = FALSE; + BOOLEAN FoundIrq = FALSE; + ULONG i; + NTSTATUS Status; + + DPRINT("i8042PnpStartDevice(%p)\n", DeviceObject); + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PortDeviceExtension = DeviceExtension->PortDeviceExtension; + + ASSERT(DeviceExtension->PnpState == dsStopped); + + if (!AllocatedResources) + { + DPRINT("No allocated resources sent to driver\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + if (AllocatedResources->Count != 1) + { + DPRINT("Wrong number of allocated resources sent to driver\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + if (AllocatedResources->List[0].PartialResourceList.Version != 1 + || AllocatedResources->List[0].PartialResourceList.Revision != 1 + || AllocatedResourcesTranslated->List[0].PartialResourceList.Version != 1 + || AllocatedResourcesTranslated->List[0].PartialResourceList.Revision != 1) + { + DPRINT("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n", + AllocatedResources->List[0].PartialResourceList.Version, + AllocatedResources->List[0].PartialResourceList.Revision, + AllocatedResourcesTranslated->List[0].PartialResourceList.Version, + AllocatedResourcesTranslated->List[0].PartialResourceList.Revision); + return STATUS_REVISION_MISMATCH; + } + + /* Get Irq and optionally control port and data port */ + for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++) + { + ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i]; + ResourceDescriptorTranslated = &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i]; + switch (ResourceDescriptor->Type) + { + case CmResourceTypePort: + { + if (ResourceDescriptor->u.Port.Length == 1) + { + /* We assume that the first ressource will + * be the control port and the second one + * will be the data port... + */ + if (!FoundDataPort) + { + PortDeviceExtension->DataPort = (PUCHAR)ResourceDescriptor->u.Port.Start.u.LowPart; + DPRINT("Found data port: 0x%lx\n", PortDeviceExtension->DataPort); + FoundDataPort = TRUE; + } + else if (!FoundControlPort) + { + PortDeviceExtension->ControlPort = (PUCHAR)ResourceDescriptor->u.Port.Start.u.LowPart; + DPRINT("Found control port: 0x%lx\n", PortDeviceExtension->ControlPort); + FoundControlPort = TRUE; + } + else + { + DPRINT("Too much I/O ranges provided\n", ResourceDescriptor->u.Port.Length); + return STATUS_INVALID_PARAMETER; + } + } + else + DPRINT1("Invalid I/O range length: 0x%lx\n", ResourceDescriptor->u.Port.Length); + break; + } + case CmResourceTypeInterrupt: + { + if (FoundIrq) + return STATUS_INVALID_PARAMETER; + InterruptData.Dirql = (KIRQL)ResourceDescriptorTranslated->u.Interrupt.Level; + InterruptData.Vector = ResourceDescriptorTranslated->u.Interrupt.Vector; + InterruptData.Affinity = ResourceDescriptorTranslated->u.Interrupt.Affinity; + if (ResourceDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) + InterruptData.InterruptMode = Latched; + else + InterruptData.InterruptMode = LevelSensitive; + InterruptData.ShareInterrupt = (ResourceDescriptorTranslated->ShareDisposition == CmResourceShareShared); + DPRINT("Found irq resource: %lu\n", ResourceDescriptor->u.Interrupt.Vector); + FoundIrq = TRUE; + break; + } + default: + DPRINT("Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type); + } + } + + if (!FoundIrq) + { + DPRINT("Interrupt resource was not found in allocated resources list\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + else if (DeviceExtension->Type == Keyboard && (!FoundDataPort || !FoundControlPort)) + { + DPRINT("Some required resources were not found in allocated resources list\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + else if (DeviceExtension->Type == Mouse && (FoundDataPort || FoundControlPort)) + { + DPRINT("Too much resources were provided in allocated resources list\n"); + return STATUS_INVALID_PARAMETER; + } + + switch (DeviceExtension->Type) + { + case Keyboard: + { + RtlCopyMemory( + &PortDeviceExtension->KeyboardInterrupt, + &InterruptData, + sizeof(INTERRUPT_DATA)); + PortDeviceExtension->Flags |= KEYBOARD_STARTED; + Status = StartProcedure(PortDeviceExtension); + break; + } + case Mouse: + { + RtlCopyMemory( + &PortDeviceExtension->MouseInterrupt, + &InterruptData, + sizeof(INTERRUPT_DATA)); + PortDeviceExtension->Flags |= MOUSE_STARTED; + Status = StartProcedure(PortDeviceExtension); + break; + } + default: + { + DPRINT1("Unknown FDO type %u\n", DeviceExtension->Type); + ASSERT(FALSE); + Status = STATUS_INVALID_DEVICE_REQUEST; + } + } + + if (NT_SUCCESS(Status)) + DeviceExtension->PnpState = dsStarted; + + return Status; +} + +NTSTATUS NTAPI +i8042Pnp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + ULONG MinorFunction; + I8042_DEVICE_TYPE DeviceType; + ULONG_PTR Information = 0; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + MinorFunction = Stack->MinorFunction; + DeviceType = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Type; + + switch (MinorFunction) + { + case IRP_MN_START_DEVICE: /* 0x0 */ + { + DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); + + /* Call lower driver (if any) */ + if (DeviceType != PhysicalDeviceObject) + { + Status = ForwardIrpAndWait(DeviceObject, Irp); + if (NT_SUCCESS(Status)) + Status = i8042PnpStartDevice( + DeviceObject, + Stack->Parameters.StartDevice.AllocatedResources, + Stack->Parameters.StartDevice.AllocatedResourcesTranslated); + } + else + Status = STATUS_SUCCESS; + break; + } + case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ + { + switch (Stack->Parameters.QueryDeviceRelations.Type) + { + case BusRelations: + { + DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); + return ForwardIrpAndForget(DeviceObject, Irp); + } + case RemovalRelations: + { + DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); + return ForwardIrpAndForget(DeviceObject, Irp); + } + default: + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", + Stack->Parameters.QueryDeviceRelations.Type); + ASSERT(FALSE); + return ForwardIrpAndForget(DeviceObject, Irp); + } + break; + } + default: + { + DPRINT1("IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction); + ASSERT(FALSE); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} diff --git a/reactos/drivers/input/i8042prt/ps2pp.c b/reactos/drivers/input/i8042prt/ps2pp.c index 3b183ec8617..c9746d70f43 100644 --- a/reactos/drivers/input/i8042prt/ps2pp.c +++ b/reactos/drivers/input/i8042prt/ps2pp.c @@ -1,137 +1,141 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/input/i8042prt/ps2pp.c - * PURPOSE: i8042prt driver - * ps2pp protocol handling - * PROGRAMMER: Tinus + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/ps2pp.c + * PURPOSE: ps2pp protocol handling + * PROGRAMMERS: Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + * Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ /* INCLUDES ****************************************************************/ -#ifndef NDEBUG -#define NDEBUG -#endif -#include - #include "i8042prt.h" +#define NDEBUG +#include -VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input) +/* FUNCTIONS *****************************************************************/ + +VOID +i8042MouHandlePs2pp( + IN PI8042_MOUSE_EXTENSION DeviceExtension, + IN UCHAR Input) { UCHAR PktType; - PMOUSE_INPUT_DATA MouseInput = DevExt->MouseBuffer + - DevExt->MouseInBuffer; + PMOUSE_INPUT_DATA MouseInput; -/* First, collect 3 bytes for a packet - * We can detect out-of-sync only by checking - * the whole packet anyway. - * - * If bit 7 and 8 of the first byte are 0, its - * a normal packet. - * - * Otherwise, the packet is different, like this: - * 1: E 1 b3 b2 x x x x - * 2: x x b1 b0 x1 x0 1 0 - * 3: x x x x x x x1 x0 - * - * b3-0 form a code that specifies the packet type: - * - * 0 Device Type - * 1 Rollers and buttons - * 2 Reserved - * 3 Reserved - * 4 Device ID - * 5 Channel & Battery - * 6 Wireless notifications - * 7 Reserved - * 8 ShortID LSB (ShortID is a number that is supposed to differentiate - * 9 ShortID MSB between your mouse and your neighbours') - * 10 Reserved - * 11 Mouse capabilities - * 12 Remote control LSB - * 13 Remote control MSB - * 14 Reserved - * 15 Extended packet - */ + MouseInput = DeviceExtension->MouseBuffer + DeviceExtension->MouseInBuffer; - switch (DevExt->MouseState) { - case MouseIdle: - case XMovement: - DevExt->MouseLogiBuffer[DevExt->MouseState] = Input; - DevExt->MouseState++; - break; + /* First, collect 3 bytes for a packet + * We can detect out-of-sync only by checking + * the whole packet anyway. + * + * If bit 7 and 8 of the first byte are 0, its + * a normal packet. + * + * Otherwise, the packet is different, like this: + * 1: E 1 b3 b2 x x x x + * 2: x x b1 b0 x1 x0 1 0 + * 3: x x x x x x x1 x0 + * + * b3-0 form a code that specifies the packet type: + * + * 0 Device Type + * 1 Rollers and buttons + * 2 Reserved + * 3 Reserved + * 4 Device ID + * 5 Channel & Battery + * 6 Wireless notifications + * 7 Reserved + * 8 ShortID LSB (ShortID is a number that is supposed to differentiate + * 9 ShortID MSB between your mouse and your neighbours') + * 10 Reserved + * 11 Mouse capabilities + * 12 Remote control LSB + * 13 Remote control MSB + * 14 Reserved + * 15 Extended packet + */ - case YMovement: - DevExt->MouseLogiBuffer[2] = Input; - DevExt->MouseState = MouseIdle; + switch (DeviceExtension->MouseState) + { + case MouseIdle: + case XMovement: + DeviceExtension->MouseLogiBuffer[DeviceExtension->MouseState] = Input; + DeviceExtension->MouseState++; + break; - /* first check if it's a normal packet */ + case YMovement: + DeviceExtension->MouseLogiBuffer[2] = Input; + DeviceExtension->MouseState = MouseIdle; - if (!(DevExt->MouseLogiBuffer[0] & 0xC0)) { - DevExt->MouseState = MouseIdle; - I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[0]); - I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[1]); - I8042MouseHandle(DevExt, DevExt->MouseLogiBuffer[2]); - /* We could care about wether MouseState really - * advances, but we don't need to because we're - * only doing three bytes anyway, so the packet - * will never complete if it's broken. - */ - return; - } + /* first check if it's a normal packet */ - /* sanity check */ - - if (((DevExt->MouseLogiBuffer[0] & 0x48) != 0x48) || - (((DevExt->MouseLogiBuffer[1] & 0x0C) >> 2) != - (DevExt->MouseLogiBuffer[2] & 0x03))) { - DPRINT1("Ps2pp packet fails sanity checks\n"); - return; - } - - /* Now get the packet type */ - - PktType = ((DevExt->MouseLogiBuffer[0] & 0x30) >> 4) & - ((DevExt->MouseLogiBuffer[1] & 0x30) >> 6); - - switch (PktType) { - case 0: - /* The packet contains the device ID, but we - * already read that in the initialization - * sequence. Ignore it. - */ - return; - case 1: - RtlZeroMemory(MouseInput, sizeof(MOUSE_INPUT_DATA)); - if (DevExt->MouseLogiBuffer[2] & 0x10) - MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN; - - if (DevExt->MouseLogiBuffer[2] & 0x20) - MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN; - - if (DevExt->MouseLogiBuffer[2] & 0x0F) { - MouseInput->ButtonFlags |= MOUSE_WHEEL; - if (DevExt->MouseLogiBuffer[2] & 0x08) - MouseInput->ButtonData = - (DevExt->MouseLogiBuffer[2] & 0x07) - - 8; - else - MouseInput->ButtonData = - DevExt->MouseLogiBuffer[2] & 0x07; + if (!(DeviceExtension->MouseLogiBuffer[0] & 0xC0)) + { + DeviceExtension->MouseState = MouseIdle; + i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[0]); + i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[1]); + i8042MouHandle(DeviceExtension, DeviceExtension->MouseLogiBuffer[2]); + /* We could care about wether MouseState really + * advances, but we don't need to because we're + * only doing three bytes anyway, so the packet + * will never complete if it's broken. + */ + return; } - I8042MouseHandleButtons(DevExt, MOUSE_BUTTON_4_DOWN | - MOUSE_BUTTON_5_DOWN); - I8042QueueMousePacket( - DevExt->MouseObject); - return; + + /* sanity check */ + if (((DeviceExtension->MouseLogiBuffer[0] & 0x48) != 0x48) || + (((DeviceExtension->MouseLogiBuffer[1] & 0x0C) >> 2) != + (DeviceExtension->MouseLogiBuffer[2] & 0x03))) + { + DPRINT1("Ps2pp packet fails sanity checks\n"); + return; + } + + /* Now get the packet type */ + PktType = ((DeviceExtension->MouseLogiBuffer[0] & 0x30) >> 4) & + ((DeviceExtension->MouseLogiBuffer[1] & 0x30) >> 6); + + switch (PktType) + { + case 0: + /* The packet contains the device ID, but we + * already read that in the initialization + * sequence. Ignore it. + */ + return; + case 1: + RtlZeroMemory(MouseInput, sizeof(MOUSE_INPUT_DATA)); + if (DeviceExtension->MouseLogiBuffer[2] & 0x10) + MouseInput->RawButtons |= MOUSE_BUTTON_4_DOWN; + + if (DeviceExtension->MouseLogiBuffer[2] & 0x20) + MouseInput->RawButtons |= MOUSE_BUTTON_5_DOWN; + + if (DeviceExtension->MouseLogiBuffer[2] & 0x0F) + { + MouseInput->ButtonFlags |= MOUSE_WHEEL; + if (DeviceExtension->MouseLogiBuffer[2] & 0x08) + MouseInput->ButtonData = (DeviceExtension->MouseLogiBuffer[2] & 0x07) - 8; + else + MouseInput->ButtonData = DeviceExtension->MouseLogiBuffer[2] & 0x07; + } + i8042MouHandleButtons( + DeviceExtension, + MOUSE_BUTTON_4_DOWN | MOUSE_BUTTON_5_DOWN); + i8042MouQueuePacket(DeviceExtension); + return; + default: + /* These are for things that would probably + * be handled by logitechs own driver. + */ + return; + } + default: - /* These are for things that would probably - * be handled by logitechs own driver. - */ - return; - } - default: - DPRINT1("Unexpected input state for ps2pp!\n"); + DPRINT1("Unexpected input state for ps2pp!\n"); } } diff --git a/reactos/drivers/input/i8042prt/readwrite.c b/reactos/drivers/input/i8042prt/readwrite.c new file mode 100644 index 00000000000..6ebf68e850c --- /dev/null +++ b/reactos/drivers/input/i8042prt/readwrite.c @@ -0,0 +1,218 @@ +/* + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/readwrite.c + * PURPOSE: Read/write port functions + * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) + Copyright Jason Filby (jasonfilby@yahoo.com) + Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "i8042prt.h" + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +i8042Flush( + IN PPORT_DEVICE_EXTENSION DeviceExtension) +{ + UCHAR Ignore; + + while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_OBF | MOU_OBF, &Ignore))) { + DPRINT("Data flushed\n"); /* drop */ + } +} + +VOID +i8042IsrWritePort( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Value, + IN UCHAR SelectCmd OPTIONAL) +{ + if (SelectCmd) + if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, SelectCmd)) + return; + + i8042Write(DeviceExtension, DeviceExtension->DataPort, Value); +} + +/* + * FUNCTION: Read data from port 0x60 + */ +NTSTATUS +i8042ReadData( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR StatusFlags, + OUT PUCHAR Data) +{ + UCHAR PortStatus; + NTSTATUS Status; + + Status = i8042ReadStatus(DeviceExtension, &PortStatus); + if (!NT_SUCCESS(Status)) + return Status; + + // If data is available + if (PortStatus & StatusFlags) + { + *Data = READ_PORT_UCHAR(DeviceExtension->DataPort); + DPRINT("Read: 0x%02x (status: 0x%x)\n", Data[0], PortStatus); + + // If the data is valid (not timeout, not parity error) + if ((PortStatus & KBD_PERR) == 0) + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS +i8042ReadStatus( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + OUT PUCHAR Status) +{ + ASSERT(DeviceExtension->ControlPort != NULL); + *Status = READ_PORT_UCHAR(DeviceExtension->ControlPort); + return STATUS_SUCCESS; +} + +/* + * FUNCTION: Read data from data port + */ +NTSTATUS +i8042ReadDataWait( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + OUT PUCHAR Data) +{ + ULONG Counter; + NTSTATUS Status; + + Counter = DeviceExtension->Settings.PollingIterations; + + while (Counter--) + { + Status = i8042ReadKeyboardData(DeviceExtension, Data); + + if (NT_SUCCESS(Status)) + return Status; + + KeStallExecutionProcessor(50); + } + + /* Timed out */ + return STATUS_IO_TIMEOUT; +} + +/* + * This one reads a value from the port; You don't have to specify + * which one, it'll always be from the one you talked to, so one function + * is enough this time. Note how MSDN specifies the + * WaitForAck parameter to be ignored. + */ +NTSTATUS NTAPI +i8042SynchReadPort( + IN PVOID Context, + OUT PUCHAR Value, + IN BOOLEAN WaitForAck) +{ + PPORT_DEVICE_EXTENSION DeviceExtension; + + DeviceExtension = (PPORT_DEVICE_EXTENSION)Context; + + return i8042ReadDataWait(DeviceExtension, Value); +} + +/* + * These functions are callbacks for filter driver custom + * initialization routines. + */ +NTSTATUS NTAPI +i8042SynchWritePort( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN UCHAR Port, + IN UCHAR Value, + IN BOOLEAN WaitForAck) +{ + NTSTATUS Status; + UCHAR Ack; + ULONG ResendIterations; + + ResendIterations = DeviceExtension->Settings.ResendIterations + 1; + + do + { + if (Port) + if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Port)) + { + DPRINT1("Failed to write Port\n"); + return STATUS_IO_TIMEOUT; + } + + if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value)) + { + DPRINT1("Failed to write Value\n"); + return STATUS_IO_TIMEOUT; + } + + if (WaitForAck) + { + Status = i8042ReadDataWait(DeviceExtension, &Ack); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to read Ack\n"); + return Status; + } + if (Ack == KBD_ACK) + return STATUS_SUCCESS; + if (Ack != KBD_RESEND) + { + DPRINT1("Unexpected Ack 0x%02x\n", Ack); + return STATUS_UNEXPECTED_IO_ERROR; + } + } + else + { + return STATUS_SUCCESS; + } + DPRINT("Reiterating\n"); + ResendIterations--; + } while (ResendIterations); + + return STATUS_IO_TIMEOUT; +} + +/* + * FUNCTION: Write data to a port, waiting first for it to become ready + */ +BOOLEAN +i8042Write( + IN PPORT_DEVICE_EXTENSION DeviceExtension, + IN PUCHAR addr, + IN UCHAR data) +{ + ULONG ResendIterations; + + ASSERT(addr); + ASSERT(DeviceExtension->ControlPort != NULL); + + ResendIterations = DeviceExtension->Settings.ResendIterations; + + while ((KBD_IBF & READ_PORT_UCHAR(DeviceExtension->ControlPort)) && + (ResendIterations--)) + { + KeStallExecutionProcessor(50); + } + + if (ResendIterations) + { + WRITE_PORT_UCHAR(addr, data); + DPRINT("Sent 0x%x to port 0x%x\n", data, addr); + return TRUE; + } + return FALSE; +} diff --git a/reactos/drivers/input/i8042prt/registry.c b/reactos/drivers/input/i8042prt/registry.c index 8c25872cd31..1e07ebff77d 100644 --- a/reactos/drivers/input/i8042prt/registry.c +++ b/reactos/drivers/input/i8042prt/registry.c @@ -1,211 +1,251 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: drivers/input/i8042prt/registry.c - * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver - * Reading the registry - * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) - * Tinus + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/i8042prt.c + * PURPOSE: Reading the registry + * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) + Copyright Jason Filby (jasonfilby@yahoo.com) + Copyright Martijn Vernooij (o112w8r02@sneakemail.com) + Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) */ -/* INCLUDES ****************************************************************/ - -#ifndef NDEBUG -#define NDEBUG -#endif -#include +/* INCLUDES ******************************************************************/ #include "i8042prt.h" +#define NDEBUG +#include + /* FUNCTIONS *****************************************************************/ -/* - * Read the registry keys associated with this device. The RegistryPath - * var is a hack. This should be more like what microsoft does, but I - * don't know exactly what they do except that it's a hack too... - */ -VOID STDCALL I8042ReadRegistry(PDRIVER_OBJECT DriverObject, - PDEVICE_EXTENSION DevExt) - +NTSTATUS +ReadRegistryEntries( + IN PUNICODE_STRING RegistryPath, + OUT PI8042_SETTINGS Settings) { - RTL_QUERY_REGISTRY_TABLE Parameters[19]; - + UNICODE_STRING ParametersRegistryKey; + RTL_QUERY_REGISTRY_TABLE Parameters[16]; NTSTATUS Status; - ULONG DefaultHeadless = 0; - ULONG DefaultCrashScroll = 0; - ULONG DefaultCrashSysRq = 0; - ULONG DefaultReportResetErrors = 0; - ULONG DefaultPollStatusIterations = 1; - ULONG DefaultResendIterations = 3; - ULONG DefaultPollingIterations = 12000; - ULONG DefaultPollingIterationsMaximum = 12000; - ULONG DefaultKeyboardDataQueueSize = 100; - ULONG DefaultOverrideKeyboardType = 0; - ULONG DefaultOverrideKeyboardSubtype = 0; - ULONG DefaultMouseDataQueueSize = 100; - ULONG DefaultMouseResendStallTime = 1000; - ULONG DefaultMouseSynchIn100ns = 20000000; + ULONG DefaultKeyboardDataQueueSize = 0x64; + UNICODE_STRING DefaultKeyboardDeviceBaseName = RTL_CONSTANT_STRING(L"KeyboardPort"); + ULONG DefaultMouseDataQueueSize = 0x64; ULONG DefaultMouseResolution = 3; - ULONG DefaultSampleRate = 60; + ULONG DefaultMouseSynchIn100ns = 20000000; ULONG DefaultNumberOfButtons = 2; - ULONG DefaultEnableWheelDetection = 1; + UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerPort"); + ULONG DefaultPollStatusIterations = 1; + ULONG DefaultOverrideKeyboardType = 4; + ULONG DefaultOverrideKeyboardSubtype = 0; + ULONG DefaultPollingIterations = 0x400; + ULONG DefaultPollingIterationsMaximum = 12000; + ULONG DefaultResendIterations = 0x3; + ULONG DefaultSampleRate = 60; + ULONG DefaultCrashOnCtrlScroll; + + /* Default value for CrashOnCtrlScroll depends if we're + * running a debug build or a normal build. + */ +#ifdef DBG + DefaultCrashOnCtrlScroll = 1; +#else + DefaultCrashOnCtrlScroll = 0; +#endif + + ParametersRegistryKey.Length = 0; + ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL); + ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength); + if (!ParametersRegistryKey.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath); + RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters"); + ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL; RtlZeroMemory(Parameters, sizeof(Parameters)); - Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[0].Name = L"Headless"; - Parameters[0].EntryContext = &DevExt->Settings.Headless; + Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[0].Name = L"KeyboardDataQueueSize"; + Parameters[0].EntryContext = &Settings->KeyboardDataQueueSize; Parameters[0].DefaultType = REG_DWORD; - Parameters[0].DefaultData = &DefaultHeadless; + Parameters[0].DefaultData = &DefaultKeyboardDataQueueSize; Parameters[0].DefaultLength = sizeof(ULONG); - Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[1].Name = L"CrashOnCtrlScroll"; - Parameters[1].EntryContext = &DevExt->Settings.CrashScroll; - Parameters[1].DefaultType = REG_DWORD; - Parameters[1].DefaultData = &DefaultCrashScroll; - Parameters[1].DefaultLength = sizeof(ULONG); + Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[1].Name = L"KeyboardDeviceBaseName"; + Parameters[1].EntryContext = &Settings->KeyboardDeviceBaseName; + Parameters[1].DefaultType = REG_SZ; + Parameters[1].DefaultData = &DefaultKeyboardDeviceBaseName; + Parameters[1].DefaultLength = 0; - Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[2].Name = L"BreakOnSysRq"; - Parameters[2].EntryContext = &DevExt->Settings.CrashSysRq; + Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[2].Name = L"MouseDataQueueSize"; + Parameters[2].EntryContext = &Settings->MouseDataQueueSize; Parameters[2].DefaultType = REG_DWORD; - Parameters[2].DefaultData = &DefaultCrashSysRq; + Parameters[2].DefaultData = &DefaultMouseDataQueueSize; Parameters[2].DefaultLength = sizeof(ULONG); - Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[3].Name = L"ReportResetErrors"; - Parameters[3].EntryContext = &DevExt->Settings.ReportResetErrors; + Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[3].Name = L"MouseResolution"; + Parameters[3].EntryContext = &Settings->MouseResolution; Parameters[3].DefaultType = REG_DWORD; - Parameters[3].DefaultData = &DefaultReportResetErrors; + Parameters[3].DefaultData = &DefaultMouseResolution; Parameters[3].DefaultLength = sizeof(ULONG); - Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[4].Name = L"PollStatusIterations"; - Parameters[4].EntryContext = &DevExt->Settings.PollStatusIterations; + Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[4].Name = L"MouseSynchIn100ns"; + Parameters[4].EntryContext = &Settings->MouseSynchIn100ns; Parameters[4].DefaultType = REG_DWORD; - Parameters[4].DefaultData = &DefaultPollStatusIterations; + Parameters[4].DefaultData = &DefaultMouseSynchIn100ns; Parameters[4].DefaultLength = sizeof(ULONG); - Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[5].Name = L"ResendIterations"; - Parameters[5].EntryContext = &DevExt->Settings.ResendIterations; + Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[5].Name = L"NumberOfButtons"; + Parameters[5].EntryContext = &Settings->NumberOfButtons; Parameters[5].DefaultType = REG_DWORD; - Parameters[5].DefaultData = &DefaultResendIterations; + Parameters[5].DefaultData = &DefaultNumberOfButtons; Parameters[5].DefaultLength = sizeof(ULONG); - Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[6].Name = L"PollingIterations"; - Parameters[6].EntryContext = &DevExt->Settings.PollingIterations; - Parameters[6].DefaultType = REG_DWORD; - Parameters[6].DefaultData = &DefaultPollingIterations; - Parameters[6].DefaultLength = sizeof(ULONG); + Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[6].Name = L"PointerDeviceBaseName"; + Parameters[6].EntryContext = &Settings->PointerDeviceBaseName; + Parameters[6].DefaultType = REG_SZ; + Parameters[6].DefaultData = &DefaultPointerDeviceBaseName; + Parameters[6].DefaultLength = 0; - Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[7].Name = L"PollingIterationsMaximum"; - Parameters[7].EntryContext = &DevExt->Settings.PollingIterationsMaximum; + Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[7].Name = L"PollStatusIterations"; + Parameters[7].EntryContext = &Settings->PollStatusIterations; Parameters[7].DefaultType = REG_DWORD; - Parameters[7].DefaultData = &DefaultPollingIterationsMaximum; + Parameters[7].DefaultData = &DefaultPollStatusIterations; Parameters[7].DefaultLength = sizeof(ULONG); - Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[8].Name = L"KeyboardDataQueueSize"; - Parameters[8].EntryContext = - &DevExt->KeyboardAttributes.InputDataQueueLength; + Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[8].Name = L"OverrideKeyboardType"; + Parameters[8].EntryContext = &Settings->OverrideKeyboardType; Parameters[8].DefaultType = REG_DWORD; - Parameters[8].DefaultData = &DefaultKeyboardDataQueueSize; + Parameters[8].DefaultData = &DefaultOverrideKeyboardType; Parameters[8].DefaultLength = sizeof(ULONG); - Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[9].Name = L"OverrideKeyboardType"; - Parameters[9].EntryContext = &DevExt->Settings.OverrideKeyboardType; + Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[9].Name = L"OverrideKeyboardSubtype"; + Parameters[9].EntryContext = &Settings->OverrideKeyboardSubtype; Parameters[9].DefaultType = REG_DWORD; - Parameters[9].DefaultData = &DefaultOverrideKeyboardType; + Parameters[9].DefaultData = &DefaultOverrideKeyboardSubtype; Parameters[9].DefaultLength = sizeof(ULONG); - Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[10].Name = L"OverrideKeyboardSubtype"; - Parameters[10].EntryContext = &DevExt->Settings.OverrideKeyboardSubtype; + Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[10].Name = L"PollingIterations"; + Parameters[10].EntryContext = &Settings->PollingIterations; Parameters[10].DefaultType = REG_DWORD; - Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype; + Parameters[10].DefaultData = &DefaultPollingIterations; Parameters[10].DefaultLength = sizeof(ULONG); - Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[11].Name = L"MouseDataQueueSize"; - Parameters[11].EntryContext = - &DevExt->MouseAttributes.InputDataQueueLength; + Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[11].Name = L"PollingIterationsMaximum"; + Parameters[11].EntryContext = &Settings->PollingIterationsMaximum; Parameters[11].DefaultType = REG_DWORD; - Parameters[11].DefaultData = &DefaultMouseDataQueueSize; + Parameters[11].DefaultData = &DefaultPollingIterationsMaximum; Parameters[11].DefaultLength = sizeof(ULONG); - Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[12].Name = L"MouseResendStallTime"; - Parameters[12].EntryContext = &DevExt->Settings.MouseResendStallTime; + Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[12].Name = L"ResendIterations"; + Parameters[12].EntryContext = &Settings->ResendIterations; Parameters[12].DefaultType = REG_DWORD; - Parameters[12].DefaultData = &DefaultMouseResendStallTime; + Parameters[12].DefaultData = &DefaultResendIterations; Parameters[12].DefaultLength = sizeof(ULONG); - Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[13].Name = L"MouseSynchIn100ns"; - Parameters[13].EntryContext = &DevExt->Settings.MouseSynchIn100ns; + Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[13].Name = L"SampleRate"; + Parameters[13].EntryContext = &Settings->SampleRate; Parameters[13].DefaultType = REG_DWORD; - Parameters[13].DefaultData = &DefaultMouseSynchIn100ns; + Parameters[13].DefaultData = &DefaultSampleRate; Parameters[13].DefaultLength = sizeof(ULONG); - Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[14].Name = L"MouseResolution"; - Parameters[14].EntryContext = &DevExt->Settings.MouseResolution; + Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[14].Name = L"CrashOnCtrlScroll"; + Parameters[14].EntryContext = &Settings->CrashOnCtrlScroll; Parameters[14].DefaultType = REG_DWORD; - Parameters[14].DefaultData = &DefaultMouseResolution; + Parameters[14].DefaultData = &DefaultCrashOnCtrlScroll; Parameters[14].DefaultLength = sizeof(ULONG); - Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[15].Name = L"SampleRate"; - Parameters[15].EntryContext = &DevExt->MouseAttributes.SampleRate; - Parameters[15].DefaultType = REG_DWORD; - Parameters[15].DefaultData = &DefaultSampleRate; - Parameters[15].DefaultLength = sizeof(ULONG); + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + ParametersRegistryKey.Buffer, + Parameters, + NULL, + NULL); - Parameters[16].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[16].Name = L"NumberOfButtons"; - Parameters[16].EntryContext = &DevExt->Settings.NumberOfButtons; - Parameters[16].DefaultType = REG_DWORD; - Parameters[16].DefaultData = &DefaultNumberOfButtons; - Parameters[16].DefaultLength = sizeof(ULONG); - - Parameters[17].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[17].Name = L"EnableWheelDetection"; - Parameters[17].EntryContext = &DevExt->Settings.EnableWheelDetection; - Parameters[17].DefaultType = REG_DWORD; - Parameters[17].DefaultData = &DefaultEnableWheelDetection; - Parameters[17].DefaultLength = sizeof(ULONG); - - Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - I8042RegistryPath.Buffer, - Parameters, - NULL, - NULL); - - if (!NT_SUCCESS(Status)) { - /* Actually, the defaults are not set when the function - * fails, as would happen during setup, so you have to - * set them manually anyway... - */ - RTL_QUERY_REGISTRY_TABLE *Current = Parameters; - DPRINT1 ("Can't read registry: %x\n", Status); - while (Current->Name) { - *((PULONG)Current->EntryContext) = - *((PULONG)Current->DefaultData); - Current++; + if (NT_SUCCESS(Status)) + { + /* Check values */ + if (Settings->KeyboardDataQueueSize < 1) + Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize; + if (Settings->MouseDataQueueSize < 1) + Settings->MouseDataQueueSize = DefaultMouseDataQueueSize; + if (Settings->NumberOfButtons < 1) + Settings->NumberOfButtons = DefaultNumberOfButtons; + if (Settings->PollingIterations < 0x400) + Settings->PollingIterations = DefaultPollingIterations; + if (Settings->PollingIterationsMaximum < 0x400) + Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum; + if (Settings->ResendIterations < 1) + Settings->ResendIterations = DefaultResendIterations; + } + else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* Registry path doesn't exist. Set defaults */ + Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize; + Settings->MouseDataQueueSize = DefaultMouseDataQueueSize; + Settings->MouseResolution = DefaultMouseResolution; + Settings->MouseSynchIn100ns = DefaultMouseSynchIn100ns; + Settings->NumberOfButtons = DefaultNumberOfButtons; + Settings->PollStatusIterations = DefaultPollStatusIterations; + Settings->OverrideKeyboardType = DefaultOverrideKeyboardType; + Settings->OverrideKeyboardSubtype = DefaultOverrideKeyboardSubtype; + Settings->PollingIterations = DefaultPollingIterations; + Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum; + Settings->ResendIterations = DefaultResendIterations; + Settings->SampleRate = DefaultSampleRate; + Settings->CrashOnCtrlScroll = DefaultCrashOnCtrlScroll; + Status = RtlDuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DefaultKeyboardDeviceBaseName, + &Settings->KeyboardDeviceBaseName); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status); + } + else + { + Status = RtlDuplicateUnicodeString( + RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DefaultPointerDeviceBaseName, + &Settings->PointerDeviceBaseName); + if (!NT_SUCCESS(Status)) + DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status); } - DPRINT1 ("Manually set defaults\n"); - } - if (DevExt->Settings.MouseResolution > 3) - DevExt->Settings.MouseResolution = 3; + if (NT_SUCCESS(Status)) + { + DPRINT("KeyboardDataQueueSize : 0x%lx\n", Settings->KeyboardDataQueueSize); + DPRINT("KeyboardDeviceBaseName : %wZ\n", &Settings->KeyboardDeviceBaseName); + DPRINT("MouseDataQueueSize : 0x%lx\n", Settings->MouseDataQueueSize); + DPRINT("MouseResolution : 0x%lx\n", Settings->MouseResolution); + DPRINT("MouseSynchIn100ns : %lu\n", Settings->MouseSynchIn100ns); + DPRINT("NumberOfButtons : 0x%lx\n", Settings->NumberOfButtons); + DPRINT("PointerDeviceBaseName : %wZ\n", &Settings->PointerDeviceBaseName); + DPRINT("PollStatusIterations : 0x%lx\n", Settings->PollStatusIterations); + DPRINT("OverrideKeyboardType : 0x%lx\n", Settings->OverrideKeyboardType); + DPRINT("OverrideKeyboardSubtype : 0x%lx\n", Settings->OverrideKeyboardSubtype); + DPRINT("PollingIterations : 0x%lx\n", Settings->PollingIterations); + DPRINT("PollingIterationsMaximum : %lu\n", Settings->PollingIterationsMaximum); + DPRINT("ResendIterations : 0x%lx\n", Settings->ResendIterations); + DPRINT("SampleRate : %lu\n", Settings->SampleRate); + } - DPRINT("Done reading registry\n"); + return Status; } diff --git a/reactos/drivers/input/i8042prt/setup.c b/reactos/drivers/input/i8042prt/setup.c new file mode 100644 index 00000000000..b33181c3f89 --- /dev/null +++ b/reactos/drivers/input/i8042prt/setup.c @@ -0,0 +1,273 @@ +/* + * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/input/i8042prt/setup.c + * PURPOSE: Create a legacy PDO during ReactOS installation + * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org) + */ + +/* NOTE: + * All this file is a big hack and should be removed one day... + */ + +/* INCLUDES ******************************************************************/ + +#include "i8042prt.h" + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define KEYBOARD_DATA_PORT 0x60 +#define KEYBOARD_CONTROL_PORT 0x64 +#define KEYBOARD_IRQ 1 + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +IsFirstStageSetup( + VOID) +{ + UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\Setup"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hSetupKey = (HANDLE)NULL; + NTSTATUS Status; + BOOLEAN ret = TRUE; + + InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&hSetupKey, KEY_QUERY_VALUE, &ObjectAttributes); + + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + ret = TRUE; + else + ret = FALSE; + + if (hSetupKey != (HANDLE)NULL) + ZwClose(hSetupKey); + DPRINT("IsFirstStageSetup() returns %s\n", ret ? "YES" : "NO"); + return ret; +} + +static VOID NTAPI +SendStartDevice( + IN PDRIVER_OBJECT DriverObject, + IN PVOID Context, + IN ULONG Count) +{ + PDEVICE_OBJECT Pdo; + PCM_RESOURCE_LIST AllocatedResources = NULL; + PCM_RESOURCE_LIST AllocatedResourcesTranslated = NULL; + PDEVICE_OBJECT TopDeviceObject = NULL; + KEVENT Event; + IO_STATUS_BLOCK IoStatusBlock; + PIRP Irp; + PIO_STACK_LOCATION Stack; + ULONG ResourceListSize; + NTSTATUS Status; + + Pdo = (PDEVICE_OBJECT)Context; + DPRINT("SendStartDevice(%p)\n", Pdo); + + /* Create default resource list */ + ResourceListSize = sizeof(CM_RESOURCE_LIST) + 3 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); + AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize); + if (!AllocatedResources) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + AllocatedResources->Count = 1; + AllocatedResources->List[0].PartialResourceList.Version = 1; + AllocatedResources->List[0].PartialResourceList.Revision = 1; + AllocatedResources->List[0].PartialResourceList.Count = 3; + /* Data port */ + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypePort; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].Flags = 0; /* FIXME */ + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start.u.HighPart = 0; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start.u.LowPart = KEYBOARD_DATA_PORT; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length = 1; + /* Control port */ + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].Type = CmResourceTypePort; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].ShareDisposition = CmResourceShareDeviceExclusive; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].Flags = 0; /* FIXME */ + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Start.u.HighPart = 0; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Start.u.LowPart = KEYBOARD_CONTROL_PORT; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[1].u.Port.Length = 1; + /* Interrupt */ + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].Type = CmResourceTypeInterrupt; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].ShareDisposition = CmResourceShareDeviceExclusive; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level = 0; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector = KEYBOARD_IRQ; + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Affinity = (KAFFINITY)-1; + + /* Create default resource list translated */ + AllocatedResourcesTranslated = ExAllocatePool(PagedPool, ResourceListSize); + if (!AllocatedResources) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlCopyMemory(AllocatedResourcesTranslated, AllocatedResources, ResourceListSize); + AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector = HalGetInterruptVector( + Internal, 0, + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level, + AllocatedResources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Vector, + (PKIRQL)&AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level, + &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Affinity); + + /* Send IRP_MN_START_DEVICE */ + TopDeviceObject = IoGetAttachedDeviceReference(Pdo); + KeInitializeEvent( + &Event, + NotificationEvent, + FALSE); + Irp = IoBuildSynchronousFsdRequest( + IRP_MJ_PNP, + TopDeviceObject, + NULL, + 0, + NULL, + &Event, + &IoStatusBlock); + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + Stack = IoGetNextIrpStackLocation(Irp); + Stack->MinorFunction = IRP_MN_START_DEVICE; + Stack->Parameters.StartDevice.AllocatedResources = AllocatedResources; + Stack->Parameters.StartDevice.AllocatedResourcesTranslated = AllocatedResourcesTranslated; + Status = IoCallDriver(TopDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject( + &Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCallDriver() failed with status 0x%08lx\n", Status); + goto cleanup; + } + +cleanup: + if (TopDeviceObject) + ObDereferenceObject(TopDeviceObject); + if (AllocatedResources) + ExFreePool(AllocatedResources); + if (AllocatedResourcesTranslated) + ExFreePool(AllocatedResourcesTranslated); +} + +static NTSTATUS +AddRegistryEntry( + IN PCWSTR PortTypeName, + IN PUNICODE_STRING DeviceName, + IN PCWSTR RegistryPath) +{ + UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hDeviceMapKey = (HANDLE)-1; + HANDLE hPortKey = (HANDLE)-1; + UNICODE_STRING PortTypeNameU; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + RtlInitUnicodeString(&PortTypeNameU, PortTypeName); + InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL); + Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + Status = STATUS_SUCCESS; + +cleanup: + if (hDeviceMapKey != (HANDLE)-1) + ZwClose(hDeviceMapKey); + if (hPortKey != (HANDLE)-1) + ZwClose(hPortKey); + return Status; +} + +NTSTATUS +i8042AddLegacyKeyboard( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPort8042"); + PI8042_DEVICE_TYPE DeviceExtension = NULL; + PDEVICE_OBJECT Pdo = NULL; + NTSTATUS Status; + + DPRINT("i8042AddLegacyKeyboard()\n"); + + /* Create a named PDO */ + Status = IoCreateDevice( + DriverObject, + sizeof(I8042_DEVICE_TYPE), + &KeyboardName, + FILE_DEVICE_8042_PORT, + FILE_DEVICE_SECURE_OPEN, + TRUE, + &Pdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* Initialize device extension */ + DeviceExtension = (PI8042_DEVICE_TYPE)Pdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, sizeof(I8042_DEVICE_TYPE)); + *DeviceExtension = PhysicalDeviceObject; + Pdo->Flags &= ~DO_DEVICE_INITIALIZING; + + /* Add FDO at the top of the PDO */ + Status = i8042AddDevice(DriverObject, Pdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("i8042AddDevice() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + /* We will send the IRP_MN_START_DEVICE later, once kbdclass is loaded */ + AddRegistryEntry(L"KeyboardPort", &KeyboardName, RegistryPath->Buffer); + IoRegisterBootDriverReinitialization( + DriverObject, + SendStartDevice, + Pdo); + + Status = STATUS_SUCCESS; + +cleanup: + if (!NT_SUCCESS(Status)) + { + if (Pdo) + IoDeleteDevice(Pdo); + } + return Status; +} From fff3bf11fa3e831dda7ba3dfbf49f12f9862e09c Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 20 Sep 2006 20:36:27 +0000 Subject: [PATCH 12/54] Gdi32 font.c: - Patch by Dmitry Timoshkov - If there is no space for strings GetOutlineTextMetricsA should not indicate that they present. svn path=/trunk/; revision=24219 --- reactos/dll/win32/gdi32/objects/font.c | 109 +++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/reactos/dll/win32/gdi32/objects/font.c b/reactos/dll/win32/gdi32/objects/font.c index 96e59690635..afac417e7ea 100644 --- a/reactos/dll/win32/gdi32/objects/font.c +++ b/reactos/dll/win32/gdi32/objects/font.c @@ -42,6 +42,31 @@ static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA ) ptmA->tmCharSet = ptmW->tmCharSet; } +/*********************************************************************** + * FONT_mbtowc + * + * Returns a Unicode translation of str. If count is -1 then str is + * assumed to be '\0' terminated, otherwise it contains the number of + * bytes to convert. If plenW is non-NULL, on return it will point to + * the number of WCHARs that have been written. The caller should free + * the returned LPWSTR from the process heap itself. + */ +static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW) +{ + UINT cp = CP_ACP; + INT lenW; + LPWSTR strW; + + if(count == -1) count = strlen(str); + lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); + strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, str, count, strW, lenW); + DPRINT1("mapped %s -> %s \n", str, strW); + if(plenW) *plenW = lenW; + return strW; +} + + static BOOL FASTCALL MetricsCharConvert(WCHAR w, UCHAR *b) { @@ -358,6 +383,8 @@ GetCharWidthA ( LPINT lpBuffer ) { +DPRINT1("GCWA iFirstChar %x\n",iFirstChar); + return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer ); } @@ -374,8 +401,35 @@ GetCharWidth32A( LPINT lpBuffer ) { - /* FIXME should be NtGdiGetCharWidthW */ - return NtGdiGetCharWidth32(hdc, iFirstChar, iLastChar, lpBuffer); + INT i, wlen, count = (INT)(iLastChar - iFirstChar + 1); + LPSTR str; + LPWSTR wstr; + BOOL ret = TRUE; +DPRINT1("GCW32A iFirstChar %x\n",iFirstChar); + + if(count <= 0) return FALSE; + + str = HeapAlloc(GetProcessHeap(), 0, count); + for(i = 0; i < count; i++) + str[i] = (BYTE)(iFirstChar + i); + + wstr = FONT_mbtowc(str, count, &wlen); + + for(i = 0; i < wlen; i++) + { + /* FIXME should be NtGdiGetCharWidthW */ + if(!NtGdiGetCharWidth32 (hdc, wstr[i], wstr[i], lpBuffer)) + { + ret = FALSE; + break; + } + lpBuffer++; + } + + HeapFree(GetProcessHeap(), 0, str); + HeapFree(GetProcessHeap(), 0, wstr); + + return ret; } @@ -391,6 +445,8 @@ GetCharWidthW ( LPINT lpBuffer ) { +DPRINT1("GCW32w uFirstChar %x\n",iFirstChar); + /* FIXME should be NtGdiGetCharWidthW */ return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer ); } @@ -496,7 +552,7 @@ GetCharWidthFloatA( /* - * @unimplemented + * @implemented */ BOOL APIENTRY @@ -507,8 +563,9 @@ GetCharABCWidthsA( LPABC lpabc ) { - /* FIXME what to do with uFirstChar and uLastChar ??? */ - return NtGdiGetCharABCWidths ( hdc, uFirstChar, uLastChar, lpabc ); +DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar); + +return NtGdiGetCharABCWidths(hdc, uFirstChar, uLastChar, lpabc); } @@ -524,6 +581,8 @@ GetCharABCWidthsFloatA( LPABCFLOAT lpABCF ) { +DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar); + /* FIXME what to do with iFirstChar and iLastChar ??? */ return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF ); } @@ -544,9 +603,32 @@ GetGlyphOutlineA( CONST MAT2 *lpmat2 ) { - return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); + + LPWSTR p = NULL; + DWORD ret; + UINT c; + DPRINT1("GetGlyphOutlineA uChar %x\n", uChar); + if(!(uFormat & GGO_GLYPH_INDEX)) { + int len; + char mbchs[2]; + if(uChar > 0xff) { /* but, 2 bytes character only */ + len = 2; + mbchs[0] = (uChar & 0xff00) >> 8; + mbchs[1] = (uChar & 0xff); + } else { + len = 1; + mbchs[0] = (uChar & 0xff); + } + p = FONT_mbtowc(mbchs, len, NULL); + c = p[0]; + } else + c = uChar; + ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); + HeapFree(GetProcessHeap(), 0, p); + return ret; } + /* * @implemented */ @@ -562,6 +644,7 @@ GetGlyphOutlineW( CONST MAT2 *lpmat2 ) { + DPRINT1("GetGlyphOutlineW uChar %x\n", uChar); return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); } @@ -696,6 +779,20 @@ GetOutlineTextMetricsA( if(output != lpOTM) { memcpy(lpOTM, output, cbData); HeapFree(GetProcessHeap(), 0, output); + + /* check if the string offsets really fit into the provided size */ + /* FIXME: should we check string length as well? */ + if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize) + lpOTM->otmpFamilyName = 0; /* doesn't fit */ + + if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize) + lpOTM->otmpFaceName = 0; /* doesn't fit */ + + if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize) + lpOTM->otmpStyleName = 0; /* doesn't fit */ + + if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize) + lpOTM->otmpFullName = 0; /* doesn't fit */ } end: From 18733c439795adcf6834269e84a575f7ff5ce960 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 20 Sep 2006 21:09:30 +0000 Subject: [PATCH 13/54] Kill debug prints. svn path=/trunk/; revision=24220 --- reactos/dll/win32/gdi32/objects/font.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/reactos/dll/win32/gdi32/objects/font.c b/reactos/dll/win32/gdi32/objects/font.c index afac417e7ea..ee5818ba8b7 100644 --- a/reactos/dll/win32/gdi32/objects/font.c +++ b/reactos/dll/win32/gdi32/objects/font.c @@ -61,7 +61,7 @@ static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW) lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR)); MultiByteToWideChar(cp, 0, str, count, strW, lenW); - DPRINT1("mapped %s -> %s \n", str, strW); + DPRINT("mapped %s -> %s \n", str, strW); if(plenW) *plenW = lenW; return strW; } @@ -383,7 +383,7 @@ GetCharWidthA ( LPINT lpBuffer ) { -DPRINT1("GCWA iFirstChar %x\n",iFirstChar); +DPRINT("GCWA iFirstChar %x\n",iFirstChar); return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer ); } @@ -405,7 +405,7 @@ GetCharWidth32A( LPSTR str; LPWSTR wstr; BOOL ret = TRUE; -DPRINT1("GCW32A iFirstChar %x\n",iFirstChar); +DPRINT("GCW32A iFirstChar %x\n",iFirstChar); if(count <= 0) return FALSE; @@ -445,7 +445,7 @@ GetCharWidthW ( LPINT lpBuffer ) { -DPRINT1("GCW32w uFirstChar %x\n",iFirstChar); +DPRINT("GCW32w uFirstChar %x\n",iFirstChar); /* FIXME should be NtGdiGetCharWidthW */ return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer ); @@ -563,7 +563,7 @@ GetCharABCWidthsA( LPABC lpabc ) { -DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar); +DPRINT("GCABCWA uFirstChar %x\n",uFirstChar); return NtGdiGetCharABCWidths(hdc, uFirstChar, uLastChar, lpabc); } @@ -581,7 +581,7 @@ GetCharABCWidthsFloatA( LPABCFLOAT lpABCF ) { -DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar); +DPRINT("GCABCWFA iFirstChar %x\n",iFirstChar); /* FIXME what to do with iFirstChar and iLastChar ??? */ return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF ); @@ -607,7 +607,7 @@ GetGlyphOutlineA( LPWSTR p = NULL; DWORD ret; UINT c; - DPRINT1("GetGlyphOutlineA uChar %x\n", uChar); + DPRINT("GetGlyphOutlineA uChar %x\n", uChar); if(!(uFormat & GGO_GLYPH_INDEX)) { int len; char mbchs[2]; @@ -644,7 +644,7 @@ GetGlyphOutlineW( CONST MAT2 *lpmat2 ) { - DPRINT1("GetGlyphOutlineW uChar %x\n", uChar); + DPRINT("GetGlyphOutlineW uChar %x\n", uChar); return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); } From 6d8ba42532a0cd2a0603652d106a2d9004b43de3 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 20 Sep 2006 21:34:08 +0000 Subject: [PATCH 14/54] Fix CreateFontIndirectA so it will not bigcheck with a null pointer. svn path=/trunk/; revision=24221 --- reactos/dll/win32/gdi32/objects/font.c | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/reactos/dll/win32/gdi32/objects/font.c b/reactos/dll/win32/gdi32/objects/font.c index ee5818ba8b7..a1f68fc846b 100644 --- a/reactos/dll/win32/gdi32/objects/font.c +++ b/reactos/dll/win32/gdi32/objects/font.c @@ -61,7 +61,7 @@ static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW) lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR)); MultiByteToWideChar(cp, 0, str, count, strW, lenW); - DPRINT("mapped %s -> %s \n", str, strW); + DPRINT1("mapped %s -> %s \n", str, strW); if(plenW) *plenW = lenW; return strW; } @@ -383,7 +383,7 @@ GetCharWidthA ( LPINT lpBuffer ) { -DPRINT("GCWA iFirstChar %x\n",iFirstChar); +DPRINT1("GCWA iFirstChar %x\n",iFirstChar); return GetCharWidth32A ( hdc, iFirstChar, iLastChar, lpBuffer ); } @@ -405,7 +405,7 @@ GetCharWidth32A( LPSTR str; LPWSTR wstr; BOOL ret = TRUE; -DPRINT("GCW32A iFirstChar %x\n",iFirstChar); +DPRINT1("GCW32A iFirstChar %x\n",iFirstChar); if(count <= 0) return FALSE; @@ -445,7 +445,7 @@ GetCharWidthW ( LPINT lpBuffer ) { -DPRINT("GCW32w uFirstChar %x\n",iFirstChar); +DPRINT1("GCW32w uFirstChar %x\n",iFirstChar); /* FIXME should be NtGdiGetCharWidthW */ return NtGdiGetCharWidth32 ( hdc, iFirstChar, iLastChar, lpBuffer ); @@ -563,7 +563,7 @@ GetCharABCWidthsA( LPABC lpabc ) { -DPRINT("GCABCWA uFirstChar %x\n",uFirstChar); +DPRINT1("GCABCWA uFirstChar %x\n",uFirstChar); return NtGdiGetCharABCWidths(hdc, uFirstChar, uLastChar, lpabc); } @@ -581,7 +581,7 @@ GetCharABCWidthsFloatA( LPABCFLOAT lpABCF ) { -DPRINT("GCABCWFA iFirstChar %x\n",iFirstChar); +DPRINT1("GCABCWFA iFirstChar %x\n",iFirstChar); /* FIXME what to do with iFirstChar and iLastChar ??? */ return NtGdiGetCharABCWidthsFloat ( hdc, iFirstChar, iLastChar, lpABCF ); @@ -607,7 +607,7 @@ GetGlyphOutlineA( LPWSTR p = NULL; DWORD ret; UINT c; - DPRINT("GetGlyphOutlineA uChar %x\n", uChar); + DPRINT1("GetGlyphOutlineA uChar %x\n", uChar); if(!(uFormat & GGO_GLYPH_INDEX)) { int len; char mbchs[2]; @@ -644,7 +644,7 @@ GetGlyphOutlineW( CONST MAT2 *lpmat2 ) { - DPRINT("GetGlyphOutlineW uChar %x\n", uChar); + DPRINT1("GetGlyphOutlineW uChar %x\n", uChar); return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); } @@ -828,10 +828,13 @@ CreateFontIndirectA( ) { LOGFONTW tlf; - - LogFontA2W(&tlf, lplf); - - return NtGdiCreateFontIndirect(&tlf); + + if (lplf) + { + LogFontA2W(&tlf, lplf); + return NtGdiCreateFontIndirect(&tlf); + } + else return (HFONT) 0; //or call NtGdiCreateFontIndirect(NULL)? } From d42d3c29c0f3d7d856d4cf6e2ac5921b3e778421 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Thu, 21 Sep 2006 02:47:37 +0000 Subject: [PATCH 15/54] set GetLastErrorMsg if CreateFontIndirectA(NULL) are use as inputparam . it make same beauvoir as CreateFontIndirectW svn path=/trunk/; revision=24222 --- reactos/dll/win32/gdi32/objects/font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/dll/win32/gdi32/objects/font.c b/reactos/dll/win32/gdi32/objects/font.c index a1f68fc846b..d4e5139bd27 100644 --- a/reactos/dll/win32/gdi32/objects/font.c +++ b/reactos/dll/win32/gdi32/objects/font.c @@ -834,7 +834,7 @@ CreateFontIndirectA( LogFontA2W(&tlf, lplf); return NtGdiCreateFontIndirect(&tlf); } - else return (HFONT) 0; //or call NtGdiCreateFontIndirect(NULL)? + else return NtGdiCreateFontIndirect(NULL); } From 7d1faef9eeadd2e14fe3d7e31f1df1a180947364 Mon Sep 17 00:00:00 2001 From: Saveliy Tretiakov Date: Thu, 21 Sep 2006 07:42:21 +0000 Subject: [PATCH 16/54] Fix boot with /DEBUGPORT=GDB and /DEBUGPORT=COM1. I don't know why, but this works... svn path=/trunk/; revision=24223 --- reactos/ntoskrnl/kd/kdio.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/reactos/ntoskrnl/kd/kdio.c b/reactos/ntoskrnl/kd/kdio.c index 811d22f7a64..e8c638325aa 100644 --- a/reactos/ntoskrnl/kd/kdio.c +++ b/reactos/ntoskrnl/kd/kdio.c @@ -188,13 +188,14 @@ KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable, /* Register as a Provider */ InsertTailList(&KdProviders, &DispatchTable->KdProvidersList); - - /* Display separator + ReactOS version at start of the debug log */ - DPRINT1("---------------------------------------------------------------\n"); - DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n"); } else if (BootPhase == 2) { + /* Display separator + ReactOS version at start of the debug log */ + DbgPrint("---------------------------------------------------------------\n"); + DbgPrint("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n"); + DbgPrint("---------------------------------------------------------------\n"); + HalDisplayString("\n Serial debugging enabled\n\n"); } } From 2a0160473e75af278ba1a031cf8cd0ba982efa0f Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Thu, 21 Sep 2006 17:25:41 +0000 Subject: [PATCH 17/54] Add an MM api to get the memory map from Freeldr's memory manager (as opposed to MachGetMemoryMap which gets architecture-specfic memory map returned by BIOS/firmware/etc). Currently this api is unused, it's going to be used by windows/reactos bootloader in future. svn path=/trunk/; revision=24224 --- reactos/boot/freeldr/freeldr/include/mm.h | 1 + reactos/boot/freeldr/freeldr/mm/mm.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index d3b4369762a..24fce2d4b33 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -86,6 +86,7 @@ VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount); // S BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount); // Returns TRUE if the specified pages of memory are available, otherwise FALSE ULONG GetSystemMemorySize(VOID); // Returns the amount of total memory in the system +PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries); // Returns a pointer to the memory mapping table and a number of entries in it //BOOLEAN MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength); diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index 928fe94e566..d5ad60f0c26 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -456,3 +456,12 @@ ULONG GetSystemMemorySize(VOID) { return (TotalPagesInLookupTable * MM_PAGE_SIZE); } + +PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries) +{ + PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress; + + *NoEntries = TotalPagesInLookupTable; + + return RealPageLookupTable; +} From 230edc01b6a20d2f980424d771f6a748a501ec3d Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Fri, 22 Sep 2006 08:10:11 +0000 Subject: [PATCH 18/54] merges ros-branch-0_3_1 r24226 to trunk with arty permission. "ARP query support. Thanks to WaxDragon for encouragement and debugging." svn path=/trunk/; revision=24227 --- reactos/dll/win32/iphlpapi/ifenum_reactos.c | 33 +++++- reactos/dll/win32/iphlpapi/iphlpapi_private.h | 5 +- reactos/dll/win32/iphlpapi/ipstats_reactos.c | 100 +++++++++++++++++- reactos/drivers/network/tcpip/include/info.h | 16 +++ .../drivers/network/tcpip/include/neighbor.h | 4 + .../drivers/network/tcpip/include/precomp.h | 2 +- reactos/drivers/network/tcpip/tcpip/iinfo.c | 51 ++++++++- reactos/drivers/network/tcpip/tcpip/info.c | 29 +++++ reactos/include/psdk/tcpioctl.h | 1 + reactos/lib/drivers/ip/network/neighbor.c | 40 +++++++ 10 files changed, 271 insertions(+), 10 deletions(-) diff --git a/reactos/dll/win32/iphlpapi/ifenum_reactos.c b/reactos/dll/win32/iphlpapi/ifenum_reactos.c index 69f7dbd204b..37425705880 100644 --- a/reactos/dll/win32/iphlpapi/ifenum_reactos.c +++ b/reactos/dll/win32/iphlpapi/ifenum_reactos.c @@ -40,7 +40,7 @@ #include "ifenum.h" #include -#define NDEBUG +//#define NDEBUG #include "debug.h" /* Globals */ @@ -124,6 +124,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, DWORD toiType, DWORD toiId, DWORD teiEntity, + DWORD teiInstance, DWORD fixedPart, DWORD entrySize, PVOID *tdiEntitySet, @@ -148,6 +149,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, req.ID.toi_type = toiType; req.ID.toi_id = toiId; req.ID.toi_entity.tei_entity = teiEntity; + req.ID.toi_entity.tei_instance = teiInstance; /* There's a subtle problem here... * If an interface is added at this exact instant, (as if by a PCMCIA @@ -168,7 +170,7 @@ NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, &allocationSizeForEntityArray, NULL ); - if(!status) + if(!NT_SUCCESS(status)) { DPRINT("IOCTL Failed\n"); return STATUS_UNSUCCESSFUL; @@ -285,6 +287,7 @@ NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, INFO_TYPE_PROVIDER, ENTITY_LIST_ID, GENERIC_ENTITY, + 0, 0, sizeof(TDIEntityID), (PVOID *)entitySet, @@ -303,7 +306,7 @@ NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, return status; } -static BOOL isInterface( TDIEntityID *if_maybe ) { +BOOL isInterface( TDIEntityID *if_maybe ) { return if_maybe->tei_entity == IF_ENTITY; } @@ -348,6 +351,30 @@ NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) { return (status ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); } +BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) { + TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT; + NTSTATUS status = STATUS_SUCCESS; + DWORD returnSize, type; + + req.ID.toi_class = INFO_CLASS_GENERIC; + req.ID.toi_type = INFO_TYPE_PROVIDER; + req.ID.toi_id = ENTITY_TYPE_ID; + req.ID.toi_entity.tei_entity = AT_ENTITY; + req.ID.toi_entity.tei_instance = arp_maybe->tei_instance; + + status = DeviceIoControl( tcpFile, + IOCTL_TCP_QUERY_INFORMATION_EX, + &req, + sizeof(req), + &type, + sizeof(type), + &returnSize, + NULL ); + + if( !NT_SUCCESS(status) ) return FALSE; + return type == AT_ENTITY; +} + static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile, IFInfo **infoSet, PDWORD numInterfaces ) { diff --git a/reactos/dll/win32/iphlpapi/iphlpapi_private.h b/reactos/dll/win32/iphlpapi/iphlpapi_private.h index 4d4fb1ed47c..40c4a0bd5d3 100644 --- a/reactos/dll/win32/iphlpapi/iphlpapi_private.h +++ b/reactos/dll/win32/iphlpapi/iphlpapi_private.h @@ -118,7 +118,8 @@ VOID closeTcpFile(HANDLE tcpFile); NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, TDIEntityID **entitySet, PDWORD numEntities ); NTSTATUS tdiGetSetOfThings( HANDLE tcpFile, DWORD toiClass, DWORD toiType, - DWORD toiId, DWORD teiEntity, DWORD fixedPart, + DWORD toiId, DWORD teiEntity, DWORD teiInstance, + DWORD fixedPart, DWORD entrySize, PVOID *tdiEntitySet, PDWORD numEntries ); VOID tdiFreeThingSet( PVOID things ); @@ -134,6 +135,8 @@ PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n ); void ConsumeChildKeyName( PWCHAR Name ); PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName ); void ConsumeRegValueString( PWCHAR NameServer ); +BOOL isInterface( TDIEntityID *if_maybe ); +BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ); #include /* This is here until we switch to version 2.5 of the mingw headers */ diff --git a/reactos/dll/win32/iphlpapi/ipstats_reactos.c b/reactos/dll/win32/iphlpapi/ipstats_reactos.c index 4322937fedb..b6b160c4fb7 100644 --- a/reactos/dll/win32/iphlpapi/ipstats_reactos.c +++ b/reactos/dll/win32/iphlpapi/ipstats_reactos.c @@ -183,6 +183,7 @@ NTSTATUS tdiGetRoutesForIpEntity INFO_TYPE_PROVIDER, IP_MIB_ROUTETABLE_ENTRY_ID, ent->tei_entity, + 0, 0, sizeof(IPRouteEntry), (PVOID *)routes, @@ -203,6 +204,7 @@ NTSTATUS tdiGetIpAddrsForIpEntity INFO_TYPE_PROVIDER, IP_MIB_ADDRTABLE_ENTRY_ID, ent->tei_entity, + 0, 0, sizeof(IPAddrEntry), (PVOID *)addrs, @@ -507,12 +509,106 @@ RouteTable *getRouteTable(void) DWORD getNumArpEntries(void) { - return getNumWithOneHeader("/proc/net/arp"); + DWORD numEntities; + TDIEntityID *entitySet = NULL; + HANDLE tcpFile; + int i, totalNumber = 0; + NTSTATUS status; + PMIB_IPNETROW IpArpTable = NULL; + DWORD returnSize; + + TRACE("called.\n"); + + status = openTcpFile( &tcpFile ); + + if( !NT_SUCCESS(status) ) { + TRACE("failure: %08x\n", (int)status ); + return 0; + } + + status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); + + for( i = 0; i < numEntities; i++ ) { + if( isInterface( &entitySet[i] ) && + hasArp( tcpFile, &entitySet[i] ) ) { + + status = tdiGetSetOfThings( tcpFile, + INFO_CLASS_PROTOCOL, + INFO_TYPE_PROVIDER, + IP_MIB_ARPTABLE_ENTRY_ID, + AT_ENTITY, + entitySet[i].tei_instance, + 0, + sizeof(MIB_IPNETROW), + (PVOID *)&IpArpTable, + &returnSize ); + + if( status == STATUS_SUCCESS ) totalNumber += returnSize; + if( IpArpTable ) tdiFreeThingSet( IpArpTable ); + } + } + + closeTcpFile( tcpFile ); + if( IpArpTable ) tdiFreeThingSet( IpArpTable ); + if( entitySet ) tdiFreeThingSet( entitySet ); + return totalNumber; } PMIB_IPNETTABLE getArpTable(void) { - return 0; + DWORD numEntities, returnSize; + TDIEntityID *entitySet; + HANDLE tcpFile; + int i, row = 0, totalNumber; + NTSTATUS status; + PMIB_IPNETTABLE IpArpTable = NULL; + PMIB_IPNETROW AdapterArpTable = NULL; + + TRACE("called.\n"); + + totalNumber = getNumArpEntries(); + + status = openTcpFile( &tcpFile ); + + if( !NT_SUCCESS(status) ) { + TRACE("failure: %08x\n", (int)status ); + return 0; + } + + IpArpTable = HeapAlloc + ( GetProcessHeap(), 0, + sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) ); + + status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); + + for( i = 0; i < numEntities; i++ ) { + if( isIpEntity( tcpFile, &entitySet[i] ) && + hasArp( tcpFile, &entitySet[i] ) ) { + + status = tdiGetSetOfThings( tcpFile, + INFO_CLASS_PROTOCOL, + INFO_TYPE_PROVIDER, + IP_MIB_ARPTABLE_ENTRY_ID, + AT_ENTITY, + entitySet[i].tei_instance, + 0, + sizeof(MIB_IPNETROW), + (PVOID *)&AdapterArpTable, + &returnSize ); + + if( status == STATUS_SUCCESS ) { + for( row = 0; row < returnSize; row++ ) + IpArpTable->table[row] = AdapterArpTable[row]; + } + + if( AdapterArpTable ) tdiFreeThingSet( AdapterArpTable ); + } + } + + tdiFreeThingSet( entitySet ); + IpArpTable->dwNumEntries = row; + + return IpArpTable; } DWORD getNumUdpEntries(void) diff --git a/reactos/drivers/network/tcpip/include/info.h b/reactos/drivers/network/tcpip/include/info.h index eb066773b21..50cfa9a5bc2 100644 --- a/reactos/drivers/network/tcpip/include/info.h +++ b/reactos/drivers/network/tcpip/include/info.h @@ -46,6 +46,19 @@ typedef struct IPADDR_ENTRY { USHORT Pad; } IPADDR_ENTRY, *PIPADDR_ENTRY; +#define ARP_ENTRY_STATIC 4 +#define ARP_ENTRY_DYNAMIC 3 +#define ARP_ENTRY_INVALID 2 +#define ARP_ENTRY_OTHER 1 + +typedef struct IPARP_ENTRY { + ULONG Index; + ULONG AddrSize; + UCHAR PhysAddr[8]; + ULONG LogAddr; + ULONG Type; +} IPARP_ENTRY, *PIPARP_ENTRY; + typedef struct IPROUTE_ENTRY { ULONG Dest; ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry @@ -96,6 +109,9 @@ typedef struct IFENTRY { #ifndef IP_MIB_ADDRTABLE_ENTRY_ID #define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 #endif +#ifndef IP_MIB_ARPTABLE_ENTRY_ID +#define IP_MIB_ARPTABLE_ENTRY_ID 0x101 +#endif #ifndef MAX_PHYSADDR_SIZE #define MAX_PHYSADDR_SIZE 8 #endif diff --git a/reactos/drivers/network/tcpip/include/neighbor.h b/reactos/drivers/network/tcpip/include/neighbor.h index 4d30cb346ec..aa1859426a9 100644 --- a/reactos/drivers/network/tcpip/include/neighbor.h +++ b/reactos/drivers/network/tcpip/include/neighbor.h @@ -107,6 +107,10 @@ BOOLEAN NBQueuePacket( VOID NBRemoveNeighbor( PNEIGHBOR_CACHE_ENTRY NCE); +DWORD NBCopyNeighbors( + PIP_INTERFACE Interface, + PIPARP_ENTRY ArpTable); + #endif /* __NEIGHBOR_H */ /* EOF */ diff --git a/reactos/drivers/network/tcpip/include/precomp.h b/reactos/drivers/network/tcpip/include/precomp.h index 680d9dd01ec..5906ced640f 100644 --- a/reactos/drivers/network/tcpip/include/precomp.h +++ b/reactos/drivers/network/tcpip/include/precomp.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/reactos/drivers/network/tcpip/tcpip/iinfo.c b/reactos/drivers/network/tcpip/tcpip/iinfo.c index 8e3eaf97e52..7a6fe06f49c 100644 --- a/reactos/drivers/network/tcpip/tcpip/iinfo.c +++ b/reactos/drivers/network/tcpip/tcpip/iinfo.c @@ -78,6 +78,42 @@ TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID, return Status; } +TDI_STATUS InfoTdiQueryGetArptableMIB(TDIEntityID *ID, + PIP_INTERFACE Interface, + PNDIS_BUFFER Buffer, + PUINT BufferSize) { + NTSTATUS Status; + DWORD NumNeighbors = NBCopyNeighbors( Interface, NULL ); + DWORD MemSize = NumNeighbors * sizeof(IPARP_ENTRY); + PIPARP_ENTRY ArpEntries = + ExAllocatePoolWithTag + ( NonPagedPool, MemSize, FOURCC('A','R','P','t') ); + + if( !ArpEntries ) return STATUS_NO_MEMORY; + NBCopyNeighbors( Interface, ArpEntries ); + + Status = InfoCopyOut( (PVOID)ArpEntries, MemSize, Buffer, BufferSize ); + + ExFreePool( ArpEntries ); + + return Status; +} + +TDI_STATUS InfoTdiQueryGetArpCapability(TDIEntityID *ID, + PIP_INTERFACE Interface, + PNDIS_BUFFER Buffer, + PUINT BufferSize) { + NTSTATUS Status; + DWORD Capability = 0x280; + + TI_DbgPrint(MID_TRACE,("Copying out %d bytes (AT_ENTITY capability)\n", + sizeof(Capability))); + Status = InfoCopyOut + ( (PVOID)&Capability, sizeof(Capability), Buffer, BufferSize ); + + return Status; +} + TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass, UINT InfoType, UINT InfoId, @@ -87,13 +123,22 @@ TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass, PUINT BufferSize ) { if( InfoClass == INFO_CLASS_GENERIC && InfoType == INFO_TYPE_PROVIDER && - InfoId == ENTITY_TYPE_ID ) { - ULONG Temp = IF_MIB; - return InfoCopyOut( (PCHAR)&Temp, sizeof(Temp), Buffer, BufferSize ); + InfoId == ENTITY_TYPE_ID && + id->tei_entity == AT_ENTITY ) { + return InfoTdiQueryGetArpCapability( id, Context, Buffer, BufferSize ); } else if( InfoClass == INFO_CLASS_PROTOCOL && InfoType == INFO_TYPE_PROVIDER && InfoId == IF_MIB_STATS_ID ) { return InfoTdiQueryGetInterfaceMIB( id, Context, Buffer, BufferSize ); + } else if( InfoClass == INFO_CLASS_GENERIC && + InfoType == INFO_TYPE_PROVIDER && + InfoId == ENTITY_TYPE_ID ) { + ULONG Temp = IF_MIB; + return InfoCopyOut( (PCHAR)&Temp, sizeof(Temp), Buffer, BufferSize ); + } else if( InfoClass == INFO_CLASS_PROTOCOL && + InfoType == INFO_TYPE_PROVIDER && + InfoId == IP_MIB_ARPTABLE_ENTRY_ID ) { + return InfoTdiQueryGetArptableMIB( id, Context, Buffer, BufferSize ); } else return TDI_INVALID_REQUEST; } diff --git a/reactos/drivers/network/tcpip/tcpip/info.c b/reactos/drivers/network/tcpip/tcpip/info.c index 10d466180cb..fb4305c5919 100644 --- a/reactos/drivers/network/tcpip/tcpip/info.c +++ b/reactos/drivers/network/tcpip/tcpip/info.c @@ -164,6 +164,35 @@ TDI_STATUS InfoTdiQueryInformationEx( Status = TDI_INVALID_PARAMETER; } else Status = InfoTdiQueryListEntities(Buffer, BufferSize); + } else if (ID->toi_entity.tei_entity == AT_ENTITY) { + TcpipAcquireSpinLock( &EntityListLock, &OldIrql ); + + for( i = 0; i < EntityCount; i++ ) { + if( EntityList[i].tei_entity == IF_ENTITY && + EntityList[i].tei_instance == ID->toi_entity.tei_instance ) { + InfoRequest = EntityList[i].info_req; + context = EntityList[i].context; + FoundEntity = TRUE; + break; + } + } + + TcpipReleaseSpinLock( &EntityListLock, OldIrql ); + + if( FoundEntity ) { + TI_DbgPrint(DEBUG_INFO, + ("Calling AT Entity %d (%04x:%d) InfoEx (%x,%x,%x)\n", + i, ID->toi_entity.tei_entity, + ID->toi_entity.tei_instance, + ID->toi_class, ID->toi_type, ID->toi_id)); + Status = InfoRequest( ID->toi_class, + ID->toi_type, + ID->toi_id, + context, + &ID->toi_entity, + Buffer, + BufferSize ); + } } else { TcpipAcquireSpinLock( &EntityListLock, &OldIrql ); diff --git a/reactos/include/psdk/tcpioctl.h b/reactos/include/psdk/tcpioctl.h index 708641d6faf..d04411ff707 100644 --- a/reactos/include/psdk/tcpioctl.h +++ b/reactos/include/psdk/tcpioctl.h @@ -45,6 +45,7 @@ #define IF_MIB_STATS_ID 1 #define IP_MIB_STATS_ID 1 +#define IP_MIB_ARPTABLE_ENTRY_ID 0x101 #define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 #define IP_INTFC_INFO_ID 0x103 #define MAX_PHYSADDR_SIZE 8 diff --git a/reactos/lib/drivers/ip/network/neighbor.c b/reactos/lib/drivers/ip/network/neighbor.c index 6d5248a67ae..330caa48117 100644 --- a/reactos/lib/drivers/ip/network/neighbor.c +++ b/reactos/lib/drivers/ip/network/neighbor.c @@ -514,3 +514,43 @@ VOID NBRemoveNeighbor( TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); } + +ULONG NBCopyNeighbors +(PIP_INTERFACE Interface, + PIPARP_ENTRY ArpTable) +{ + PNEIGHBOR_CACHE_ENTRY CurNCE; + KIRQL OldIrql; + UINT Size = 0, i; + + for (i = 0; i <= NB_HASHMASK; i++) { + TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); + for( CurNCE = NeighborCache[i].Cache; + CurNCE; + CurNCE = CurNCE->Next ) { + if( CurNCE->Interface == Interface ) { + if( ArpTable ) { + ArpTable[Size].Index = Interface->Index; + ArpTable[Size].AddrSize = CurNCE->LinkAddressLength; + RtlCopyMemory + (ArpTable[Size].PhysAddr, + CurNCE->LinkAddress, + CurNCE->LinkAddressLength); + ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address; + if( CurNCE->State & NUD_PERMANENT ) + ArpTable[Size].Type = ARP_ENTRY_STATIC; + else if( CurNCE->State & NUD_CONNECTED ) + ArpTable[Size].Type = ARP_ENTRY_DYNAMIC; + else if( !(CurNCE->State & NUD_VALID) ) + ArpTable[Size].Type = ARP_ENTRY_INVALID; + else + ArpTable[Size].Type = ARP_ENTRY_OTHER; + } + Size++; + } + } + TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); + } + + return Size; +} From 391e807b81adeb87916a102cbf86c75a2200a701 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Fri, 22 Sep 2006 17:26:20 +0000 Subject: [PATCH 19/54] finish implement NtGdiCloseEnhMetaFile it is not fully tested it can contain bugs svn path=/trunk/; revision=24228 --- .../win32/win32k/objects/metafile.c | 103 +++++++++++++----- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/reactos/subsystems/win32/win32k/objects/metafile.c b/reactos/subsystems/win32/win32k/objects/metafile.c index 908e2cdcfbd..fbe95b61bdc 100644 --- a/reactos/subsystems/win32/win32k/objects/metafile.c +++ b/reactos/subsystems/win32/win32k/objects/metafile.c @@ -37,21 +37,8 @@ NtGdiCloseEnhMetaFile(HDC hDC) IO_STATUS_BLOCK Iosb; NTSTATUS Status; - DPRINT1("NtGdiCloseEnhMetaFile\n"); - - /* Todo - Rewrite it to own api call IntGdiCloseEmhMetaFile - - Translate follow api to kernel api - // hMapping = CreateFileMappingW(Dc->hFile, NULL, PAGE_READONLY, 0, 0, NULL); - // Dc->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - // hmf = EMF_Create_HENHMETAFILE( Dc->emh, (Dc->hFile != 0) ); - - - DC_SetOwnership(hdc, - */ - - + + Dc = DC_LockDc(hDC); if (Dc == NULL) { @@ -121,34 +108,47 @@ NtGdiCloseEnhMetaFile(HDC hDC) LARGE_INTEGER Distance ; IO_STATUS_BLOCK IoStatusBlock; + POBJECT_ATTRIBUTES ObjectAttributes = NULL; + ACCESS_MASK DesiredAccess; + PLARGE_INTEGER SectionSize = NULL; + DWORD flProtect; + ULONG Attributes; + LARGE_INTEGER SectionOffset; + ULONG ViewSize; + ULONG Protect; + LPVOID ViewBase; + Distance.u.LowPart = 0; Distance.u.HighPart = 0; FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart; + DPRINT1("Trying write to metafile and map it\n"); + Status = NtSetInformationFile(Dc->hFile, &IoStatusBlock, &FilePosition, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); if (!NT_SUCCESS(Status)) { - /* FIXME */ - // SetLastErrorByStatus(errCode); + // SetLastErrorByStatus(Status); SetLastWin32Error(ERROR_INVALID_HANDLE); NtClose( Dc->hFile ); DC_UnlockDc(Dc); NtGdiDeleteObjectApp(hDC); + + DPRINT1("NtSetInformationFile fail\n"); return hmf; } if (FilePosition.CurrentByteOffset.u.LowPart != 0) { - /* FIXME */ - // SetLastErrorByStatus(errCode); + // SetLastErrorByStatus(Status); SetLastWin32Error(ERROR_INVALID_HANDLE); NtClose( Dc->hFile ); DC_UnlockDc(Dc); NtGdiDeleteObjectApp(hDC); + DPRINT1("FilePosition.CurrentByteOffset.u.LowPart is not 0\n"); return hmf; } @@ -166,19 +166,68 @@ NtGdiCloseEnhMetaFile(HDC hDC) { NtClose( Dc->hFile ); DC_UnlockDc(Dc); - NtGdiDeleteObjectApp(hDC); + NtGdiDeleteObjectApp(hDC); + DPRINT1("fail to write 0\n"); return hmf; } EngFreeMem(Dc->emh); - /* FIXME */ - // hMapping = CreateFileMappingW(Dc->hFile, NULL, PAGE_READONLY, 0, 0, NULL); - - /* FIXME */ - // Dc->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); - NtClose( hMapping ); - NtClose( Dc->hFile ); + /* create maping */ + DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ; + Attributes = (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT)); + flProtect = PAGE_READONLY ^ (PAGE_READONLY & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_NOCACHE | SEC_COMMIT)); + + if (!Attributes) Attributes = SEC_COMMIT; + + if (Dc->hFile == INVALID_HANDLE_VALUE) + { + Dc->hFile = NULL; + if (!SectionSize) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + hMapping = NULL; + DPRINT1("fail !SectionSize \n"); + } + } + else + { + Status = NtCreateSection(&hMapping, DesiredAccess, ObjectAttributes, SectionSize, flProtect, Attributes, Dc->hFile); + if (!NT_SUCCESS(Status)) + { + //SetLastErrorByStatus(Status); + SetLastWin32Error(ERROR_INVALID_HANDLE); + hMapping = NULL; + DPRINT1("fail NtCreateSection \n"); + } + } + + /* MapViewOfFile */ + SectionOffset.LowPart = 0; + SectionOffset.HighPart = 0; + ViewBase = NULL; + ViewSize = 0; + + Protect = PAGE_READONLY; + + Status = ZwMapViewOfSection(&hMapping, NtCurrentProcess(), &ViewBase, 0, + 0, &SectionOffset, &ViewSize, ViewShare, 0, Protect); + if (!NT_SUCCESS(Status)) + { + //SetLastErrorByStatus(Status); + SetLastWin32Error(ERROR_INVALID_HANDLE); + Dc->emh = NULL; + DPRINT1("fail ZwMapViewOfSection \n"); + } + else + { + Dc->emh = ViewBase; + } + /* Close */ + if (hMapping != NULL) + NtClose( hMapping ); + if (Dc->hFile != NULL) + NtClose( Dc->hFile ); } hmf = GDIOBJ_AllocObj(GdiHandleTable, GDI_OBJECT_TYPE_ENHMETAFILE); From cfe10b7a75ee9981318fc58070f9d84bb48eab02 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Fri, 22 Sep 2006 20:19:49 +0000 Subject: [PATCH 20/54] Implement BRUSH_GetObject it is not perfect, it return wrong color in some case. But we get down from 20 to 11 fails in wine test. Wine say GetObject (HANDLE obj, INT Count, PVOID * Buffer) if Buffer is NULL return the requeuer size in bytes svn path=/trunk/; revision=24229 --- reactos/subsystems/win32/win32k/include/brush.h | 2 ++ reactos/subsystems/win32/win32k/objects/brush.c | 13 +++++++++++++ reactos/subsystems/win32/win32k/objects/dc.c | 8 +++++--- reactos/subsystems/win32/win32k/objects/text.c | 15 +++++++++------ 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/brush.h b/reactos/subsystems/win32/win32k/include/brush.h index 54b2a4b7369..c1e854ab02a 100644 --- a/reactos/subsystems/win32/win32k/include/brush.h +++ b/reactos/subsystems/win32/win32k/include/brush.h @@ -72,6 +72,8 @@ typedef struct #define BRUSHOBJ_FreeBrush(hBrush) GDIOBJ_FreeObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH) #define BRUSHOBJ_LockBrush(hBrush) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH)) #define BRUSHOBJ_UnlockBrush(pBrush) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pBrush) + +INT FASTCALL BRUSH_GetObject (PGDIBRUSHOBJ GdiObject, INT Count, BRUSHOBJ * Buffer); BOOL INTERNAL_CALL BRUSH_Cleanup(PVOID ObjectBody); #endif diff --git a/reactos/subsystems/win32/win32k/objects/brush.c b/reactos/subsystems/win32/win32k/objects/brush.c index ca2dbdea09c..426a05774ad 100644 --- a/reactos/subsystems/win32/win32k/objects/brush.c +++ b/reactos/subsystems/win32/win32k/objects/brush.c @@ -49,6 +49,19 @@ BRUSH_Cleanup(PVOID ObjectBody) return TRUE; } +INT FASTCALL +BRUSH_GetObject (PGDIBRUSHOBJ BrushObj, INT Count, BRUSHOBJ * Buffer) +{ + if (Buffer) + { + Buffer->iSolidColor = BrushObj->BrushAttr.lbColor; + Buffer->pvRbrush = BrushObj->ulRealization; + Buffer->flColorType = 0; + } + return sizeof(BRUSHOBJ); +} + + XLATEOBJ* FASTCALL IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed) { diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index f3a43d4607e..4fd4a2bf545 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -1716,6 +1716,7 @@ NtGdiGetDeviceCaps(HDC hDC, DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode ) DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode ) + INT FASTCALL IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer) { @@ -1737,10 +1738,11 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer) case GDI_OBJECT_TYPE_PEN: Result = PEN_GetObject((PENOBJ *) GdiObject, Count, Buffer); break; - case GDI_OBJECT_TYPE_BRUSH: - Result = BRUSH_GetObject((BRUSHOBJ *) GdiObject, Count, Buffer); - break; #endif + case GDI_OBJECT_TYPE_BRUSH: + Result = BRUSH_GetObject((PGDIBRUSHOBJ ) GdiObject, Count, (BRUSHOBJ *)Buffer); + break; + case GDI_OBJECT_TYPE_BITMAP: Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer); break; diff --git a/reactos/subsystems/win32/win32k/objects/text.c b/reactos/subsystems/win32/win32k/objects/text.c index 9e5549c0022..84229a78d9c 100644 --- a/reactos/subsystems/win32/win32k/objects/text.c +++ b/reactos/subsystems/win32/win32k/objects/text.c @@ -3917,13 +3917,16 @@ TextIntRealizeFont(HFONT FontHandle) INT FASTCALL FontGetObject(PTEXTOBJ Font, INT Count, PVOID Buffer) { - if (Count < sizeof(LOGFONTW)) - { - SetLastWin32Error(ERROR_BUFFER_OVERFLOW); - return 0; - } + if (Buffer) + { + if (Count < sizeof(LOGFONTW)) + { + SetLastWin32Error(ERROR_BUFFER_OVERFLOW); + return 0; + } - RtlCopyMemory(Buffer, &Font->logfont, sizeof(LOGFONTW)); + RtlCopyMemory(Buffer, &Font->logfont, sizeof(LOGFONTW)); + } return sizeof(LOGFONTW); } From 63535f6e1594bbfd5b693a4d6c308bbb49d73ff3 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sat, 23 Sep 2006 06:19:28 +0000 Subject: [PATCH 21/54] remove folder gdi for all gdi test are in gdi32 svn path=/trunk/; revision=24231 --- reactos/regtests/winetests/gdi/.gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 reactos/regtests/winetests/gdi/.gitignore diff --git a/reactos/regtests/winetests/gdi/.gitignore b/reactos/regtests/winetests/gdi/.gitignore deleted file mode 100644 index e69de29bb2d..00000000000 From cc70b77eca1385ab525e275f8ce1877b8fd9d70a Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sat, 23 Sep 2006 07:28:44 +0000 Subject: [PATCH 22/54] add NULL termate on ansi string when WideCharToMultiByteCP doing wchar to ansi converting. svn path=/trunk/; revision=24232 --- reactos/dll/win32/kernel32/misc/nls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/reactos/dll/win32/kernel32/misc/nls.c b/reactos/dll/win32/kernel32/misc/nls.c index 6da28161557..e355ff7accf 100644 --- a/reactos/dll/win32/kernel32/misc/nls.c +++ b/reactos/dll/win32/kernel32/misc/nls.c @@ -569,7 +569,7 @@ IntWideCharToMultiByteCP(UINT CodePage, DWORD Flags, WideCharCount = MultiByteCount; SetLastError(ERROR_INSUFFICIENT_BUFFER); } - + for (TempLength = WideCharCount; TempLength > 0; WideCharString++, TempLength--) @@ -577,6 +577,12 @@ IntWideCharToMultiByteCP(UINT CodePage, DWORD Flags, *MultiByteString++ = ((PCHAR)CodePageTable->WideCharTable)[*WideCharString]; } + if (WideCharCount>2) + { + MultiByteString--; + *MultiByteString = 0; + } + /* FIXME */ if (UsedDefaultChar != NULL) *UsedDefaultChar = FALSE; From e126931cb050cbdd0d93b6f3af10913c86908ac2 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sat, 23 Sep 2006 09:34:34 +0000 Subject: [PATCH 23/54] - Issue a synchronous invalidate device relations request instead of asynchronous (eliminates the "can't open \SystemRoot\ bugcheck during 2nd stage startup) - Comment out usbport/usbhub/etc from bootcd, they will be enabled once they don't crash and/or slow down system. svn path=/trunk/; revision=24233 --- reactos/boot/bootdata/packages/reactos.dff | 8 ++++---- reactos/ntoskrnl/io/iomgr/iomgr.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index d78742bc0ef..f58d4ae39fb 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -265,10 +265,10 @@ drivers\network\dd\pcnet\pcnet.sys 2 drivers\storage\pciide\pciide.sys 2 drivers\storage\pciidex\pciidex.sys 2 -drivers\usb\miniport\usbohci\usbohci.sys 2 -drivers\usb\miniport\usbuhci\usbuhci.sys 2 -drivers\usb\usbhub\usbhub.sys 2 -drivers\usb\usbport\usbport.sys 2 +;drivers\usb\miniport\usbohci\usbohci.sys 2 +;drivers\usb\miniport\usbuhci\usbuhci.sys 2 +;drivers\usb\usbhub\usbhub.sys 2 +;drivers\usb\usbport\usbport.sys 2 drivers\video\displays\vga\vgaddi.dll 1 drivers\video\displays\framebuf\framebuf.dll 1 diff --git a/reactos/ntoskrnl/io/iomgr/iomgr.c b/reactos/ntoskrnl/io/iomgr/iomgr.c index 6e656d69600..2c1149fdc4e 100644 --- a/reactos/ntoskrnl/io/iomgr/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr/iomgr.c @@ -15,6 +15,15 @@ ULONG IopTraceLevel = IO_IRP_DEBUG; +// should go into a proper header +VOID +NTAPI +IoSynchronousInvalidateDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_RELATION_TYPE Type +); + + /* DATA ********************************************************************/ POBJECT_TYPE IoDeviceObjectType = NULL; @@ -448,7 +457,7 @@ IoInit2(BOOLEAN BootLog) /* * Initialize PnP root releations */ - IoInvalidateDeviceRelations( + IoSynchronousInvalidateDeviceRelations( IopRootDeviceNode->PhysicalDeviceObject, BusRelations); From 2d2431695997ad696bd13ec6178a9e335cc6cb84 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sat, 23 Sep 2006 12:33:54 +0000 Subject: [PATCH 24/54] fixed some more setpixel bugs svn path=/trunk/; revision=24234 --- .../subsystems/win32/win32k/objects/brush.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/reactos/subsystems/win32/win32k/objects/brush.c b/reactos/subsystems/win32/win32k/objects/brush.c index 426a05774ad..11c28689b83 100644 --- a/reactos/subsystems/win32/win32k/objects/brush.c +++ b/reactos/subsystems/win32/win32k/objects/brush.c @@ -415,6 +415,26 @@ IntGdiCreateSolidBrush( ASSERT(BrushObject != NULL); BrushObject->flAttrs |= GDIBRUSH_IS_SOLID; + + if (((Color>>24) & 0xff)==0x10) + { + if (Color == 0x10ff0002) + Color = 0xFF; + else if ((Color & 0xff) !=0) + Color = Color & 0xFFFFFF; + else if ((Color & 0xff) ==0x00) + Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); + else if ((Color & 0xff) ==0x01) + Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); + } + + + if (((Color>>24) & 0xff)==0xff) + { + Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); + } + + BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF; /* FIXME: Fill in the rest of fields!!! */ From 52b43f7ae9ef81eeb936870564964c670b60a501 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sat, 23 Sep 2006 15:54:11 +0000 Subject: [PATCH 25/54] IntGdiCreateSolidBrush Remove the if table I did. Remove Color = Color & 0xffffff to Color = Color that gave same result and pass equal many wine test. we still have some werid xlate bugs some where, for set/get pixel. I should have remove Color & 0xffffff in frist place. but the code did look right. svn path=/trunk/; revision=24235 --- .../subsystems/win32/win32k/objects/brush.c | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/reactos/subsystems/win32/win32k/objects/brush.c b/reactos/subsystems/win32/win32k/objects/brush.c index 11c28689b83..c004116305d 100644 --- a/reactos/subsystems/win32/win32k/objects/brush.c +++ b/reactos/subsystems/win32/win32k/objects/brush.c @@ -416,26 +416,7 @@ IntGdiCreateSolidBrush( BrushObject->flAttrs |= GDIBRUSH_IS_SOLID; - if (((Color>>24) & 0xff)==0x10) - { - if (Color == 0x10ff0002) - Color = 0xFF; - else if ((Color & 0xff) !=0) - Color = Color & 0xFFFFFF; - else if ((Color & 0xff) ==0x00) - Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); - else if ((Color & 0xff) ==0x01) - Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); - } - - - if (((Color>>24) & 0xff)==0xff) - { - Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); - } - - - BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF; + BrushObject->BrushAttr.lbColor = Color; /* FIXME: Fill in the rest of fields!!! */ BRUSHOBJ_UnlockBrush(BrushObject); From edeb548dd18ef31acfea2015cf8082e6e8d97721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 23 Sep 2006 16:01:02 +0000 Subject: [PATCH 26/54] Subkeys names should be case insensitive. Fixes the 'make install' problem, where shell was not starting at third boot svn path=/trunk/; revision=24236 --- reactos/tools/mkhive/registry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/tools/mkhive/registry.c b/reactos/tools/mkhive/registry.c index fcae34a3602..c1977544aa7 100644 --- a/reactos/tools/mkhive/registry.c +++ b/reactos/tools/mkhive/registry.c @@ -153,7 +153,7 @@ RegpOpenOrCreateKey( ParentKey->RegistryHive, ParentKey->KeyCell, &KeyString, - 0, + OBJ_CASE_INSENSITIVE, &SubKeyCell, &BlockOffset); if (AllowCreation && Status == STATUS_OBJECT_NAME_NOT_FOUND) From 0e779901fc805b9bb1ef8f20d1dc8f68b9494a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 23 Sep 2006 16:06:15 +0000 Subject: [PATCH 27/54] Do not display the group name of a service if it doesn't exists svn path=/trunk/; revision=24237 --- reactos/base/system/services/database.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reactos/base/system/services/database.c b/reactos/base/system/services/database.c index 4d75727f0cf..6cdccb65e0b 100644 --- a/reactos/base/system/services/database.c +++ b/reactos/base/system/services/database.c @@ -279,7 +279,10 @@ CreateServiceListEntry(LPWSTR lpServiceName, } DPRINT("ServiceName: '%S'\n", lpService->lpServiceName); - DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName); + if (lpService->lpGroup != NULL) + { + DPRINT("Group: '%S'\n", lpService->lpGroup->lpGroupName); + } DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n", lpService->dwStartType, lpService->Status.dwServiceType, From cd007816d8df3451771c35053f8eb2f1e596e272 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sat, 23 Sep 2006 16:50:39 +0000 Subject: [PATCH 28/54] Change #defines of bios memory types to a proper enum. Makes it easier to distinguish BIOS memory types and FreeLoader's memory types (in future). svn path=/trunk/; revision=24238 --- .../boot/freeldr/freeldr/arch/i386/pcmem.c | 4 ++-- .../boot/freeldr/freeldr/arch/i386/xboxmem.c | 4 ++-- .../boot/freeldr/freeldr/arch/powerpc/mach.c | 2 +- reactos/boot/freeldr/freeldr/include/mm.h | 12 +++++----- reactos/boot/freeldr/freeldr/mm/meminit.c | 22 +++++++++---------- reactos/boot/freeldr/freeldr/mm/mm.c | 6 ++--- .../boot/freeldr/freeldr/reactos/reactos.c | 4 ++-- .../boot/freeldr/freeldr/reactos/setupldr.c | 4 ++-- 8 files changed, 30 insertions(+), 28 deletions(-) diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c index 9a85fee3c48..a0c4d357782 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c @@ -235,11 +235,11 @@ PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) /* Conventional memory */ BiosMemoryMap[0].BaseAddress = 0; BiosMemoryMap[0].Length = PcMemGetConventionalMemorySize() * 1024; - BiosMemoryMap[0].Type = MEMTYPE_USABLE; + BiosMemoryMap[0].Type = BiosMemoryUsable; /* Extended memory */ BiosMemoryMap[1].BaseAddress = 1024 * 1024; BiosMemoryMap[1].Length = PcMemGetExtendedMemorySize() * 1024; - BiosMemoryMap[1].Type = MEMTYPE_USABLE; + BiosMemoryMap[1].Type = BiosMemoryUsable; EntryCount = 2; } diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c index 5c19934ef88..9efa0d35da3 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c @@ -86,7 +86,7 @@ XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) /* Available RAM block */ BiosMemoryMap[0].BaseAddress = 0; BiosMemoryMap[0].Length = AvailableMemoryMb * 1024 * 1024; - BiosMemoryMap[0].Type = MEMTYPE_USABLE; + BiosMemoryMap[0].Type = BiosMemoryUsable; EntryCount = 1; } @@ -95,7 +95,7 @@ XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) /* Video memory */ BiosMemoryMap[1].BaseAddress = AvailableMemoryMb * 1024 * 1024; BiosMemoryMap[1].Length = (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024; - BiosMemoryMap[1].Type = MEMTYPE_RESERVED; + BiosMemoryMap[1].Type = BiosMemoryReserved; EntryCount = 2; } diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c index 0f339440a27..c79d5062bc7 100644 --- a/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c @@ -256,7 +256,7 @@ ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize ) { printf("GetMemoryMap(chosen=%x)\n", chosen_package); - BiosMemoryMap[0].Type = MEMTYPE_USABLE; + BiosMemoryMap[0].Type = BiosMemoryUsable; BiosMemoryMap[0].BaseAddress = 0; BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */ diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index 24fce2d4b33..813bf2cc2eb 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -21,11 +21,13 @@ #ifndef __MEMORY_H #define __MEMORY_H - -#define MEMTYPE_USABLE 0x01 -#define MEMTYPE_RESERVED 0x02 -#define MEMTYPE_ACPI_RECLAIM 0x03 -#define MEMTYPE_ACPI_NVS 0x04 +typedef enum +{ + BiosMemoryUsable=1, + BiosMemoryReserved, + BiosMemoryAcpiReclaim, + BiosMemoryAcpiNvs +} BIOS_MEMORY_TYPE; typedef struct { diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 8f3668aa150..9fe607d615b 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/boot/freeldr/freeldr/mm/meminit.c @@ -27,16 +27,16 @@ typedef struct { ULONG Type; UCHAR TypeString[20]; -} MEMORY_TYPE, *PMEMORY_TYPE; +} FREELDR_MEMORY_TYPE, *PFREELDR_MEMORY_TYPE; ULONG MemoryTypeCount = 5; -MEMORY_TYPE MemoryTypeArray[] = +FREELDR_MEMORY_TYPE MemoryTypeArray[] = { { 0, "Unknown Memory" }, - { MEMTYPE_USABLE, "Usable Memory" }, - { MEMTYPE_RESERVED, "Reserved Memory" }, - { MEMTYPE_ACPI_RECLAIM, "ACPI Reclaim Memory" }, - { MEMTYPE_ACPI_NVS, "ACPI NVS Memory" }, + { BiosMemoryUsable, "Usable Memory" }, + { BiosMemoryReserved, "Reserved Memory" }, + { BiosMemoryAcpiReclaim, "ACPI Reclaim Memory" }, + { BiosMemoryAcpiNvs, "ACPI NVS Memory" }, }; #endif @@ -192,7 +192,7 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map { // If this is usable memory with a big enough length // then we'll put our page lookup table here - if (TempBiosMemoryMap[Index].Type == MEMTYPE_USABLE && TempBiosMemoryMap[Index].Length >= PageLookupTableSize) + if (TempBiosMemoryMap[Index].Type == BiosMemoryUsable && TempBiosMemoryMap[Index].Length >= PageLookupTableSize) { PageLookupTableMemAddress = (PVOID)(ULONG)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); break; @@ -248,20 +248,20 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_ME MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)(ULONG)BiosMemoryMap[Index].BaseAddress); MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(ULONG)(BiosMemoryMap[Index].BaseAddress + BiosMemoryMap[Index].Length - 1)); MemoryMapPageCount = (MemoryMapEndPage - MemoryMapStartPage) + 1; - MemoryMapPageAllocated = (BiosMemoryMap[Index].Type == MEMTYPE_USABLE) ? 0 : BiosMemoryMap[Index].Type; + MemoryMapPageAllocated = (BiosMemoryMap[Index].Type == BiosMemoryUsable) ? 0 : BiosMemoryMap[Index].Type; DbgPrint((DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryMapStartPage, MemoryMapPageCount)); MmMarkPagesInLookupTable(PageLookupTable, MemoryMapStartPage, MemoryMapPageCount, MemoryMapPageAllocated); } // Mark the low memory region below 1MB as reserved (256 pages in region) DbgPrint((DPRINT_MEMORY, "Marking the low 1MB region as reserved.\n")); - MmMarkPagesInLookupTable(PageLookupTable, 0, 256, MEMTYPE_RESERVED); + MmMarkPagesInLookupTable(PageLookupTable, 0, 256, BiosMemoryReserved); // Mark the pages that the lookup tabel occupies as reserved PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable); PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage; DbgPrint((DPRINT_MEMORY, "Marking the page lookup table pages as reserved StartPage: %d PageCount: %d\n", PageLookupTableStartPage, PageLookupTablePageCount)); - MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, MEMTYPE_RESERVED); + MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, BiosMemoryReserved); } VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, ULONG PageAllocated) @@ -414,7 +414,7 @@ VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount) // If the entry type isn't usable then remove // it from the memory map (this will help reduce // the size of our lookup table) - if (BiosMemoryMap[Index].Type != MEMTYPE_USABLE) + if (BiosMemoryMap[Index].Type != BiosMemoryUsable) { // Slide every entry after this down one for (Index2=Index; Index2<(*MapCount - 1); Index2++) diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index d5ad60f0c26..e1d7fcc7f3b 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -392,13 +392,13 @@ VOID DumpMemoryAllocMap(VOID) case 1: DbgPrint((DPRINT_MEMORY, "A")); break; - case MEMTYPE_RESERVED: + case BiosMemoryReserved: DbgPrint((DPRINT_MEMORY, "R")); break; - case MEMTYPE_ACPI_RECLAIM: + case BiosMemoryAcpiReclaim: DbgPrint((DPRINT_MEMORY, "M")); break; - case MEMTYPE_ACPI_NVS: + case BiosMemoryAcpiNvs: DbgPrint((DPRINT_MEMORY, "N")); break; default: diff --git a/reactos/boot/freeldr/freeldr/reactos/reactos.c b/reactos/boot/freeldr/freeldr/reactos/reactos.c index f76d8d280fe..15f0e90ffa4 100644 --- a/reactos/boot/freeldr/freeldr/reactos/reactos.c +++ b/reactos/boot/freeldr/freeldr/reactos/reactos.c @@ -615,7 +615,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName) DbgPrint((DPRINT_REACTOS, "dumping memory map:\n")); for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++) { - if (MEMTYPE_USABLE == reactos_memory_map[i].type && + if (BiosMemoryUsable == reactos_memory_map[i].type && 0 == reactos_memory_map[i].base_addr_low) { LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024; @@ -624,7 +624,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName) LoaderBlock.MemLower = 640; } } - if (MEMTYPE_USABLE == reactos_memory_map[i].type && + if (BiosMemoryUsable == reactos_memory_map[i].type && reactos_memory_map[i].base_addr_low <= 1024 * 1024 && 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) { diff --git a/reactos/boot/freeldr/freeldr/reactos/setupldr.c b/reactos/boot/freeldr/freeldr/reactos/setupldr.c index 369d9b824cf..a03b648f48e 100644 --- a/reactos/boot/freeldr/freeldr/reactos/setupldr.c +++ b/reactos/boot/freeldr/freeldr/reactos/setupldr.c @@ -325,7 +325,7 @@ VOID RunLoader(VOID) reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24 for (i = 0; i < (LoaderBlock.MmapLength / sizeof(memory_map_t)); i++) { - if (MEMTYPE_USABLE == reactos_memory_map[i].type && + if (BiosMemoryUsable == reactos_memory_map[i].type && 0 == reactos_memory_map[i].base_addr_low) { LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024; @@ -334,7 +334,7 @@ VOID RunLoader(VOID) LoaderBlock.MemLower = 640; } } - if (MEMTYPE_USABLE == reactos_memory_map[i].type && + if (BiosMemoryUsable == reactos_memory_map[i].type && reactos_memory_map[i].base_addr_low <= 1024 * 1024 && 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) { From 9e314810aece2a266a170a4ef85f222b15c8e765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 23 Sep 2006 20:21:41 +0000 Subject: [PATCH 29/54] Skip keyboard detection in freeldr, as it doesn't work in Qemu 0.8.2 svn path=/trunk/; revision=24239 --- reactos/boot/freeldr/freeldr/arch/i386/hardware.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c index fdfa068d1e7..a609304c3c2 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c @@ -1662,7 +1662,8 @@ DetectKeyboardPeripheral(FRLDRHKEY ControllerKey) ULONG Size; LONG Error; - if (DetectKeyboardDevice()) + /* HACK: don't call DetectKeyboardDevice() as it fails in Qemu 0.8.2 */ + if (TRUE || DetectKeyboardDevice()) { /* Create controller key */ Error = RegCreateKey(ControllerKey, From 68434f2227795cbd0fffe82db21e8f39c45d0855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 23 Sep 2006 22:09:18 +0000 Subject: [PATCH 30/54] Add default destination for driver files in keyboard.inf svn path=/trunk/; revision=24240 --- reactos/media/inf/keyboard.inf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/reactos/media/inf/keyboard.inf b/reactos/media/inf/keyboard.inf index ce57bf04671..b632f7d03d9 100644 --- a/reactos/media/inf/keyboard.inf +++ b/reactos/media/inf/keyboard.inf @@ -9,7 +9,10 @@ LayoutFile = layout.inf Class = Keyboard ClassGUID = {4D36E96B-E325-11CE-BFC1-08002BE10318} Provider = %ReactOS% -DriverVer = 04/30/2005,1.02 +DriverVer = 09/24/2006,1.03 + +[DestinationDirs] +DefaultDestDir = 12 [ClassInstall32.NT] AddReg = KeyboardClass.NT.AddReg @@ -25,13 +28,12 @@ HKR, , UpperFilters, 0x00010000, "kbdclass" %StdMfg% = StdMfg [StdMfg] -%*PNP0303.DeviceDesc% = PS2_Inst,*PNP0303 +%*PNP0303.DeviceDesc% = PS2_Inst.NT,*PNP0303 ;------------------------------ PS/2 DRIVER ----------------------------- [PS2_Inst.NT] CopyFiles = PS2_CopyFiles.NT, kbdclass_CopyFiles.NT -AddReg = PS2_AddReg [PS2_CopyFiles.NT] i8042prt.sys From 939cbfc4c7a032a5df2a97f030e4cfc253b7fb37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sat, 23 Sep 2006 22:26:28 +0000 Subject: [PATCH 31/54] Report correct interrupt resources to ntoskrnl svn path=/trunk/; revision=24241 --- reactos/drivers/bus/acpi/ospm/fdo.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/reactos/drivers/bus/acpi/ospm/fdo.c b/reactos/drivers/bus/acpi/ospm/fdo.c index 76657ae0a29..a628e0ad3e2 100644 --- a/reactos/drivers/bus/acpi/ospm/fdo.c +++ b/reactos/drivers/bus/acpi/ospm/fdo.c @@ -174,7 +174,6 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList, PIO_RESOURCE_DESCRIPTOR RequirementDescriptor; RESOURCE* resource; ULONG i; - KIRQL Dirql; /* Count number of resources */ Done = FALSE; @@ -263,11 +262,9 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList, (irq_data->shared_exclusive == SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive); ResourceDescriptor->Flags = (irq_data->edge_level == LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED); - ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector( - Internal, 0, 0, irq_data->interrupts[i], - &Dirql, - &ResourceDescriptor->u.Interrupt.Affinity); - ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql; + ResourceDescriptor->u.Interrupt.Level = 0; + ResourceDescriptor->u.Interrupt.Vector = irq_data->interrupts[i]; + ResourceDescriptor->u.Interrupt.Affinity = (KAFFINITY)(-1); RequirementDescriptor->Option = 0; /* Required */ RequirementDescriptor->Type = ResourceDescriptor->Type; From 5d46ef1a267a53263646d4e3e34307bbb6b06cdd Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sun, 24 Sep 2006 02:58:31 +0000 Subject: [PATCH 32/54] Fix mkhive on unix. svn path=/trunk/; revision=24242 --- reactos/Makefile | 4 ++++ reactos/tools/mkhive/mkhive.mak | 2 +- reactos/tools/mkhive/registry.c | 2 +- reactos/tools/mkhive/rtl.c | 20 +++++++++++++++++++- reactos/tools/widl/widl.mak | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/reactos/Makefile b/reactos/Makefile index 8ec2925c90c..b35d99fcce8 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -152,11 +152,15 @@ ifeq ($(word 1,$(shell gcc -dumpmachine)),mingw32) ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys) export OSTYPE = msys HOST=mingw32-linux +CFLAGS+=-fshort-wchar +CPPFLAGS+=-fshort-wchar else HOST=mingw32-windows endif else HOST=mingw32-linux +CFLAGS+=-fshort-wchar +CPPFLAGS+=-fshort-wchar endif endif diff --git a/reactos/tools/mkhive/mkhive.mak b/reactos/tools/mkhive/mkhive.mak index a4d20753d32..252bc80f7d9 100644 --- a/reactos/tools/mkhive/mkhive.mak +++ b/reactos/tools/mkhive/mkhive.mak @@ -30,7 +30,7 @@ MKHIVE_SOURCES = $(addprefix $(MKHIVE_BASE_), \ MKHIVE_OBJECTS = \ $(addprefix $(INTERMEDIATE_), $(MKHIVE_SOURCES:.c=.o)) -MKHIVE_HOST_CFLAGS = $(xTOOLS_CFLAGS) -I$(INFLIB_BASE) -I$(CMLIB_BASE) \ +MKHIVE_HOST_CFLAGS = -fshort-wchar $(xTOOLS_CFLAGS) -I$(INFLIB_BASE) -I$(CMLIB_BASE) \ -D_NTOSKRNL_ \ -Iinclude/reactos -Iinclude/ddk -Iinclude/ndk -Iinclude/psdk -Iinclude -Iinclude/crt -g3 diff --git a/reactos/tools/mkhive/registry.c b/reactos/tools/mkhive/registry.c index c1977544aa7..6ef405167b7 100644 --- a/reactos/tools/mkhive/registry.c +++ b/reactos/tools/mkhive/registry.c @@ -122,7 +122,7 @@ RegpOpenOrCreateKey( LocalKeyName = (PWSTR)KeyName; for (;;) { - End = (PWSTR) wcschr(LocalKeyName, '\\'); + End = (PWSTR) xwcschr(LocalKeyName, '\\'); if (End) { KeyString.Buffer = LocalKeyName; diff --git a/reactos/tools/mkhive/rtl.c b/reactos/tools/mkhive/rtl.c index 08cdeb71deb..ed6711dd075 100644 --- a/reactos/tools/mkhive/rtl.c +++ b/reactos/tools/mkhive/rtl.c @@ -11,6 +11,24 @@ #include #include +SIZE_T xwcslen( PWSTR String ) { + SIZE_T i; + + for( i = 0; String[i]; i++ ); + + return i; +} + +PWSTR xwcschr( PWSTR String, WCHAR Char ) +{ + SIZE_T i; + + for( i = 0; String[i] && String[i] != Char; i++ ); + + if( String[i] ) return &String[i]; + else return NULL; +} + /* * @implemented * @@ -54,7 +72,7 @@ RtlInitUnicodeString( if(SourceString) { - DestSize = wcslen(SourceString) * sizeof(WCHAR); + DestSize = xwcslen(SourceString) * sizeof(WCHAR); DestinationString->Length = (USHORT)DestSize; DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR); } diff --git a/reactos/tools/widl/widl.mak b/reactos/tools/widl/widl.mak index a93263d4c8e..4407d163c3c 100644 --- a/reactos/tools/widl/widl.mak +++ b/reactos/tools/widl/widl.mak @@ -55,7 +55,7 @@ WIDL_OBJECTS = \ $(addprefix $(INTERMEDIATE_), $(WIDL_SOURCES:.c=.o)) WIDL_HOST_CFLAGS = $(TOOLS_CFLAGS) \ - -DINT16=SHORT -D__USE_W32API -DYYDEBUG=1 \ + -DINT16=SHORT -D__USE_W32API -DYYDEBUG=1 -D__REACTOS__=1 \ -I$(WIDL_BASE) -I$(WPP_BASE) \ -Iinclude/reactos/wine -Iinclude/reactos -Iinclude -Iinclude/psdk From 7bfdc5ceb794838986cba7be4cd8f2d0bcb8e563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 06:25:49 +0000 Subject: [PATCH 33/54] Allow digits in computer name. http://www.reactos.org/bugzilla/show_bug.cgi?id=1806#c2 still needs to be checked See issue #1806 for more details. svn path=/trunk/; revision=24243 --- reactos/dll/win32/kernel32/misc/computername.c | 4 ++-- reactos/dll/win32/syssetup/wizard.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/reactos/dll/win32/kernel32/misc/computername.c b/reactos/dll/win32/kernel32/misc/computername.c index be065b96568..11351b91c37 100644 --- a/reactos/dll/win32/kernel32/misc/computername.c +++ b/reactos/dll/win32/kernel32/misc/computername.c @@ -298,7 +298,7 @@ IsValidComputerName ( p = (PWCHAR)lpComputerName; while (*p != 0) { - if (!(iswctype (*p, _ALPHA || _DIGIT) || + if ((!iswctype (*p, _ALPHA) && !iswctype (*p, _DIGIT)) || *p == L'!' || *p == L'@' || *p == L'#' || @@ -314,7 +314,7 @@ IsValidComputerName ( *p == L'_' || *p == L'{' || *p == L'}' || - *p == L'~')) + *p == L'~') return FALSE; Length++; diff --git a/reactos/dll/win32/syssetup/wizard.c b/reactos/dll/win32/syssetup/wizard.c index 4019a2870e6..fd72f546cc6 100644 --- a/reactos/dll/win32/syssetup/wizard.c +++ b/reactos/dll/win32/syssetup/wizard.c @@ -537,7 +537,7 @@ WriteComputerSettings(TCHAR * ComputerName, HWND hwndDlg) return FALSE; } - /* Try to also set DNS hostname */ + /* Try to also set DNS hostname */ SetComputerNameEx(ComputerNamePhysicalDnsHostname, ComputerName); return TRUE; @@ -612,7 +612,8 @@ ComputerPageDlgProc(HWND hwndDlg, return TRUE; } - /* FIXME: check computer name for invalid characters */ + /* No need to check computer name for invalid characters, + * SetComputerName() will do it for us */ if (!WriteComputerSettings(ComputerName, hwndDlg)) { From c32cdd8bfbc4e80bbe982a3dc675dad9a6154b88 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 07:30:43 +0000 Subject: [PATCH 34/54] revers 24232 for cause some other unknown regress. I need found a better way to solv the null termeting strings svn path=/trunk/; revision=24244 --- reactos/dll/win32/kernel32/misc/nls.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/reactos/dll/win32/kernel32/misc/nls.c b/reactos/dll/win32/kernel32/misc/nls.c index e355ff7accf..6da28161557 100644 --- a/reactos/dll/win32/kernel32/misc/nls.c +++ b/reactos/dll/win32/kernel32/misc/nls.c @@ -569,7 +569,7 @@ IntWideCharToMultiByteCP(UINT CodePage, DWORD Flags, WideCharCount = MultiByteCount; SetLastError(ERROR_INSUFFICIENT_BUFFER); } - + for (TempLength = WideCharCount; TempLength > 0; WideCharString++, TempLength--) @@ -577,12 +577,6 @@ IntWideCharToMultiByteCP(UINT CodePage, DWORD Flags, *MultiByteString++ = ((PCHAR)CodePageTable->WideCharTable)[*WideCharString]; } - if (WideCharCount>2) - { - MultiByteString--; - *MultiByteString = 0; - } - /* FIXME */ if (UsedDefaultChar != NULL) *UsedDefaultChar = FALSE; From 2abe11c82a856f32c2f1d5878086e3fc5638f30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 07:38:53 +0000 Subject: [PATCH 35/54] Revert r24233, which leads to have the header written too late in debug log and was preventing a crash during the first DbgPrint calls when using GDB Replace it by another fix (not tested) svn path=/trunk/; revision=24245 --- reactos/ntoskrnl/kd/kdinit.c | 1 - reactos/ntoskrnl/kd/kdio.c | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/reactos/ntoskrnl/kd/kdinit.c b/reactos/ntoskrnl/kd/kdinit.c index 52ee7f5992d..0cb5a8688a7 100644 --- a/reactos/ntoskrnl/kd/kdinit.c +++ b/reactos/ntoskrnl/kd/kdinit.c @@ -77,7 +77,6 @@ KdpGetWrapperDebugMode(PCHAR Currentp2, /* Get the KDBG Settings and enable it */ KdDebuggerEnabled = TRUE; KdDebuggerNotPresent = FALSE; - KdpDebugMode.Gdb = TRUE; KdbpGetCommandLineSettings((PCHAR)LoaderBlock->CommandLine); #endif return p2; diff --git a/reactos/ntoskrnl/kd/kdio.c b/reactos/ntoskrnl/kd/kdio.c index e8c638325aa..811d22f7a64 100644 --- a/reactos/ntoskrnl/kd/kdio.c +++ b/reactos/ntoskrnl/kd/kdio.c @@ -188,14 +188,13 @@ KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable, /* Register as a Provider */ InsertTailList(&KdProviders, &DispatchTable->KdProvidersList); + + /* Display separator + ReactOS version at start of the debug log */ + DPRINT1("---------------------------------------------------------------\n"); + DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n"); } else if (BootPhase == 2) { - /* Display separator + ReactOS version at start of the debug log */ - DbgPrint("---------------------------------------------------------------\n"); - DbgPrint("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n"); - DbgPrint("---------------------------------------------------------------\n"); - HalDisplayString("\n Serial debugging enabled\n\n"); } } From 7f9492fc2fe7d029d94dce376c97cf20b4b9a728 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 08:36:56 +0000 Subject: [PATCH 36/54] tested in dib16 Fixed all wine test for brush, zero fualt now passing all 32 test fine. gdi32 bitmap test only 7 fails now svn path=/trunk/; revision=24246 --- .../subsystems/win32/win32k/include/brush.h | 2 +- .../subsystems/win32/win32k/objects/bitmaps.c | 5 -- .../subsystems/win32/win32k/objects/brush.c | 56 +++++++++++++++++-- reactos/subsystems/win32/win32k/objects/dc.c | 2 +- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/brush.h b/reactos/subsystems/win32/win32k/include/brush.h index c1e854ab02a..e33e952fb90 100644 --- a/reactos/subsystems/win32/win32k/include/brush.h +++ b/reactos/subsystems/win32/win32k/include/brush.h @@ -73,7 +73,7 @@ typedef struct #define BRUSHOBJ_LockBrush(hBrush) ((PGDIBRUSHOBJ)GDIOBJ_LockObj(GdiHandleTable, (HGDIOBJ)hBrush, GDI_OBJECT_TYPE_BRUSH)) #define BRUSHOBJ_UnlockBrush(pBrush) GDIOBJ_UnlockObjByPtr(GdiHandleTable, pBrush) -INT FASTCALL BRUSH_GetObject (PGDIBRUSHOBJ GdiObject, INT Count, BRUSHOBJ * Buffer); +INT FASTCALL BRUSH_GetObject (PGDIBRUSHOBJ GdiObject, INT Count, LPLOGBRUSH Buffer); BOOL INTERNAL_CALL BRUSH_Cleanup(PVOID ObjectBody); #endif diff --git a/reactos/subsystems/win32/win32k/objects/bitmaps.c b/reactos/subsystems/win32/win32k/objects/bitmaps.c index f2cd1180f35..2040b81297f 100644 --- a/reactos/subsystems/win32/win32k/objects/bitmaps.c +++ b/reactos/subsystems/win32/win32k/objects/bitmaps.c @@ -1071,10 +1071,6 @@ NtGdiSetPixel( DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); - if (((Color>>24) & 0xff)<0x10) - { - Color = ((Color>>16) & 0x0000ff) | ((Color<<16) & 0xff0000) | (Color & 0x00ff00); - } DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); @@ -1083,7 +1079,6 @@ NtGdiSetPixel( Color = NtGdiGetPixel(hDC,X,Y); DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color); return Color; - } Color = ((COLORREF) -1); diff --git a/reactos/subsystems/win32/win32k/objects/brush.c b/reactos/subsystems/win32/win32k/objects/brush.c index c004116305d..4e74f8fc8f0 100644 --- a/reactos/subsystems/win32/win32k/objects/brush.c +++ b/reactos/subsystems/win32/win32k/objects/brush.c @@ -50,13 +50,61 @@ BRUSH_Cleanup(PVOID ObjectBody) } INT FASTCALL -BRUSH_GetObject (PGDIBRUSHOBJ BrushObj, INT Count, BRUSHOBJ * Buffer) +BRUSH_GetObject (PGDIBRUSHOBJ BrushObject, INT Count, LPLOGBRUSH Buffer) { if (Buffer) { - Buffer->iSolidColor = BrushObj->BrushAttr.lbColor; - Buffer->pvRbrush = BrushObj->ulRealization; - Buffer->flColorType = 0; + + /* Set colour */ + Buffer->lbColor = BrushObject->BrushAttr.lbColor; + + /* set Hatch */ + if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0) + { + /* FIXME : is this right value */ + Buffer->lbHatch = (LONG)BrushObject->hbmPattern; + } + else + { + Buffer->lbHatch = 0; + } + + Buffer->lbStyle = 0; + + /* Get the type of style */ + if ((BrushObject->flAttrs & GDIBRUSH_IS_SOLID)!=0) + { + Buffer->lbStyle = BS_SOLID; + } + else if ((BrushObject->flAttrs & GDIBRUSH_IS_NULL)!=0) + { + Buffer->lbStyle = BS_NULL; // BS_HOLLOW + } + else if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0) + { + Buffer->lbStyle = BS_HATCHED; + } + else if ((BrushObject->flAttrs & GDIBRUSH_IS_BITMAP)!=0) + { + Buffer->lbStyle = BS_PATTERN; + } + else if ((BrushObject->flAttrs & GDIBRUSH_IS_DIB)!=0) + { + Buffer->lbStyle = BS_DIBPATTERN; + } + + /* FIXME + else if ((BrushObject->flAttrs & )!=0) + { + Buffer->lbStyle = BS_INDEXED; + } + + else if ((BrushObject->flAttrs & )!=0) + { + Buffer->lbStyle = BS_DIBPATTERNPT; + } + */ + } return sizeof(BRUSHOBJ); } diff --git a/reactos/subsystems/win32/win32k/objects/dc.c b/reactos/subsystems/win32/win32k/objects/dc.c index 4fd4a2bf545..0f46955d9c0 100644 --- a/reactos/subsystems/win32/win32k/objects/dc.c +++ b/reactos/subsystems/win32/win32k/objects/dc.c @@ -1740,7 +1740,7 @@ IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer) break; #endif case GDI_OBJECT_TYPE_BRUSH: - Result = BRUSH_GetObject((PGDIBRUSHOBJ ) GdiObject, Count, (BRUSHOBJ *)Buffer); + Result = BRUSH_GetObject((PGDIBRUSHOBJ ) GdiObject, Count, (LPLOGBRUSH)Buffer); break; case GDI_OBJECT_TYPE_BITMAP: From 9f553707a1ff834d3e1dbedf881c1b95e0ee7d54 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 09:24:23 +0000 Subject: [PATCH 37/54] adding OBJ_COLORSPACE it was missing, need it soon svn path=/trunk/; revision=24247 --- reactos/include/psdk/wingdi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index 823b0c69f1e..7d0bb2c2f95 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -614,6 +614,7 @@ extern "C" { #define OBJ_METADC 4 #define OBJ_ENHMETAFILE 13 #define OBJ_ENHMETADC 12 +#define OBJ_COLORSPACE 14 #define DRIVERVERSION 0 #define TECHNOLOGY 2 #define DT_PLOTTER 0 From 9e99515740e5f09b88b44c1d32ee3720c931b5d7 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 09:41:28 +0000 Subject: [PATCH 38/54] adding two more missing define svn path=/trunk/; revision=24248 --- reactos/include/psdk/wingdi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index 7d0bb2c2f95..e3430bcbf6a 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -934,6 +934,8 @@ extern "C" { #define SP_NOTREPORTED 0x4000 #define PR_JOBSTATUS 0 #define ASPECT_FILTERING 1 +#define GS_8BIT_INDICES 0x00000001 +#define GGI_MARK_NONEXISTING_GLYPHS 0X0001 #define BS_SOLID 0 #define BS_NULL 1 #define BS_HOLLOW 1 From 595ffab5960845ce1e57197a92899a803db1ec96 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 09:43:16 +0000 Subject: [PATCH 39/54] Update some gdi32 winetest svn path=/trunk/; revision=24249 --- reactos/regtests/winetests/gdi32/bitmap.c | 885 ++++++++++++++- reactos/regtests/winetests/gdi32/brush.c | 4 +- reactos/regtests/winetests/gdi32/clipping.c | 125 ++ reactos/regtests/winetests/gdi32/dc.c | 180 +++ reactos/regtests/winetests/gdi32/font.c | 441 ++++++++ reactos/regtests/winetests/gdi32/gdi32.rbuild | 3 + reactos/regtests/winetests/gdi32/gdiobj.c | 381 +++---- reactos/regtests/winetests/gdi32/metafile.c | 1005 ++++++++++++++++- reactos/regtests/winetests/gdi32/testlist.c | 6 +- 9 files changed, 2747 insertions(+), 283 deletions(-) create mode 100644 reactos/regtests/winetests/gdi32/clipping.c create mode 100644 reactos/regtests/winetests/gdi32/dc.c create mode 100644 reactos/regtests/winetests/gdi32/font.c diff --git a/reactos/regtests/winetests/gdi32/bitmap.c b/reactos/regtests/winetests/gdi32/bitmap.c index dbbb81b8068..62a57ebf2da 100755 --- a/reactos/regtests/winetests/gdi32/bitmap.c +++ b/reactos/regtests/winetests/gdi32/bitmap.c @@ -2,6 +2,7 @@ * Unit test suite for bitmaps * * Copyright 2004 Huw Davies + * Copyright 2006 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -15,11 +16,12 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include +#include #include "windef.h" #include "winbase.h" @@ -31,11 +33,88 @@ static BOOL is_win9x; +static INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp ) +{ + switch(bpp) + { + case 1: + return 2 * ((bmWidth+15) >> 4); + + case 24: + bmWidth *= 3; /* fall through */ + case 8: + return bmWidth + (bmWidth & 1); + + case 32: + return bmWidth * 4; + + case 16: + case 15: + return bmWidth * 2; + + case 4: + return 2 * ((bmWidth+3) >> 2); + + default: + trace("Unknown depth %d, please report.\n", bpp ); + assert(0); + } + return -1; +} + +static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih) +{ + BITMAP bm; + INT ret, width_bytes; + char buf[512], buf_cmp[512]; + + ret = GetObject(hbm, sizeof(bm), &bm); + ok(ret == sizeof(bm), "GetObject returned %d\n", ret); + + ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType); + ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight); + width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel); + ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes); + ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes); + ok(bm.bmBitsPixel == expected_depth, "wrong bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, expected_depth); + ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits); + + assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight); + assert(sizeof(buf) == sizeof(buf_cmp)); + + ret = GetBitmapBits(hbm, 0, NULL); + ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + + memset(buf_cmp, 0xAA, sizeof(buf_cmp)); + memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight); + + memset(buf, 0xAA, sizeof(buf)); + ret = GetBitmapBits(hbm, sizeof(buf), buf); + ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n"); + + /* test various buffer sizes for GetObject */ + ret = GetObject(hbm, 0, NULL); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + ret = GetObject(hbm, sizeof(bm) * 2, &bm); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + ret = GetObject(hbm, sizeof(bm) / 2, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbm, 0, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbm, 1, &bm); + ok(ret == 0, "%d != 0\n", ret); +} + static void test_createdibitmap(void) { HDC hdc, hdcmem; BITMAPINFOHEADER bmih; - BITMAP bm; HBITMAP hbm, hbm_colour, hbm_old; INT screen_depth; @@ -56,27 +135,21 @@ static void test_createdibitmap(void) /* First try 32 bits */ hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); /* Then 16 */ bmih.biBitCount = 16; hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); /* Then 1 */ bmih.biBitCount = 1; hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); /* Now with a monochrome dc we expect a monochrome bitmap */ @@ -86,27 +159,21 @@ static void test_createdibitmap(void) bmih.biBitCount = 32; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1); + test_bitmap_info(hbm, 1, &bmih); DeleteObject(hbm); /* Then 16 */ bmih.biBitCount = 16; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1); + test_bitmap_info(hbm, 1, &bmih); DeleteObject(hbm); /* Then 1 */ bmih.biBitCount = 1; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1); + test_bitmap_info(hbm, 1, &bmih); DeleteObject(hbm); /* Now select a polychrome bitmap into the dc and we expect @@ -118,27 +185,21 @@ static void test_createdibitmap(void) bmih.biBitCount = 32; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); /* Then 16 */ bmih.biBitCount = 16; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); /* Then 1 */ bmih.biBitCount = 1; hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth); + test_bitmap_info(hbm, screen_depth, &bmih); DeleteObject(hbm); SelectObject(hdcmem, hbm_old); @@ -150,15 +211,124 @@ static void test_createdibitmap(void) bmih.biBitCount = 32; hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0); ok(hbm != NULL, "CreateDIBitmap failed\n"); - ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n"); - - ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1); + test_bitmap_info(hbm, 1, &bmih); DeleteObject(hbm); } ReleaseDC(0, hdc); } +static INT DIB_GetWidthBytes( int width, int bpp ) +{ + int words; + + switch (bpp) + { + case 1: words = (width + 31) / 32; break; + case 4: words = (width + 7) / 8; break; + case 8: words = (width + 3) / 4; break; + case 15: + case 16: words = (width + 1) / 2; break; + case 24: words = (width * 3 + 3)/4; break; + case 32: words = width; break; + + default: + words=0; + trace("Unknown depth %d, please report.\n", bpp ); + assert(0); + break; + } + return 4 * words; +} + +static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih) +{ + BITMAP bm; + DIBSECTION ds; + INT ret, width_bytes; + BYTE *buf; + + ret = GetObject(hbm, sizeof(bm), &bm); + ok(ret == sizeof(bm), "GetObject returned %d\n", ret); + + ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType); + ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight); + width_bytes = DIB_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel); + ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes); + ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes); + ok(bm.bmBitsPixel == bmih->biBitCount, "bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, bmih->biBitCount); + ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits); + + buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096); + + width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel); + + /* GetBitmapBits returns not 32-bit aligned data */ + ret = GetBitmapBits(hbm, 0, NULL); + ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight); + + memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096); + ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf); + ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight); + + HeapFree(GetProcessHeap(), 0, buf); + + /* test various buffer sizes for GetObject */ + memset(&ds, 0xAA, sizeof(ds)); + ret = GetObject(hbm, sizeof(bm) * 2, &bm); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight); + ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits); + + ret = GetObject(hbm, sizeof(bm) / 2, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbm, 0, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbm, 1, &bm); + ok(ret == 0, "%d != 0\n", ret); + + /* test various buffer sizes for GetObject */ + ret = GetObject(hbm, 0, NULL); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + memset(&ds, 0xAA, sizeof(ds)); + ret = GetObject(hbm, sizeof(ds) * 2, &ds); + ok(ret == sizeof(ds), "wrong size %d\n", ret); + + ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits, bits); + ok(ds.dsBmih.biSizeImage == ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight, "%lu != %u\n", + ds.dsBmih.biSizeImage, ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight); + ok(bmih->biSizeImage == 0, "%lu != 0\n", bmih->biSizeImage); + ds.dsBmih.biSizeImage = 0; + + ok(ds.dsBmih.biSize == bmih->biSize, "%lu != %lu\n", ds.dsBmih.biSize, bmih->biSize); + ok(ds.dsBmih.biWidth == bmih->biWidth, "%lu != %lu\n", ds.dsBmih.biWidth, bmih->biWidth); + ok(ds.dsBmih.biHeight == bmih->biHeight, "%lu != %lu\n", ds.dsBmih.biHeight, bmih->biHeight); + ok(ds.dsBmih.biPlanes == bmih->biPlanes, "%u != %u\n", ds.dsBmih.biPlanes, bmih->biPlanes); + ok(ds.dsBmih.biBitCount == bmih->biBitCount, "%u != %u\n", ds.dsBmih.biBitCount, bmih->biBitCount); + ok(ds.dsBmih.biCompression == bmih->biCompression, "%lu != %lu\n", ds.dsBmih.biCompression, bmih->biCompression); + ok(ds.dsBmih.biSizeImage == bmih->biSizeImage, "%lu != %lu\n", ds.dsBmih.biSizeImage, bmih->biSizeImage); + ok(ds.dsBmih.biXPelsPerMeter == bmih->biXPelsPerMeter, "%lu != %lu\n", ds.dsBmih.biXPelsPerMeter, bmih->biXPelsPerMeter); + ok(ds.dsBmih.biYPelsPerMeter == bmih->biYPelsPerMeter, "%lu != %lu\n", ds.dsBmih.biYPelsPerMeter, bmih->biYPelsPerMeter); + + memset(&ds, 0xAA, sizeof(ds)); + ret = GetObject(hbm, sizeof(ds) - 4, &ds); + ok(ret == sizeof(ds.dsBm), "wrong size %d\n", ret); + ok(ds.dsBm.bmWidth == bmih->biWidth, "%lu != %lu\n", ds.dsBmih.biWidth, bmih->biWidth); + ok(ds.dsBm.bmHeight == bmih->biHeight, "%lu != %lu\n", ds.dsBmih.biHeight, bmih->biHeight); + ok(ds.dsBm.bmBits == bits, "%p != %p\n", ds.dsBm.bmBits, bits); + + ret = GetObject(hbm, 0, &ds); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbm, 1, &ds); + ok(ret == 0, "%d != 0\n", ret); +} + #define test_color_todo(got, exp, txt, todo) \ if (!todo && got != exp && screen_depth < 24) { \ todo_wine ok(0, #txt " failed at %d-bit screen depth: got 0x%06x expected 0x%06x - skipping DIB tests\n", \ @@ -194,12 +364,73 @@ static void test_dibsections(void) WORD *index; DWORD *bits32; HPALETTE hpal, oldpal; + DIBSECTION dibsec; COLORREF c0, c1; int i; int screen_depth; + MEMORY_BASIC_INFORMATION info; hdc = GetDC(0); screen_depth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); + + memset(pbmi, 0, sizeof(bmibuf)); + pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); + pbmi->bmiHeader.biHeight = 100; + pbmi->bmiHeader.biWidth = 512; + pbmi->bmiHeader.biBitCount = 24; + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biCompression = BI_RGB; + + SetLastError(0xdeadbeef); + hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib != NULL, "CreateDIBSection error %ld\n", GetLastError()); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n"); + ok(dibsec.dsBm.bmBits == bits, "dibsec.dsBits %p != bits %p\n", dibsec.dsBm.bmBits, bits); + + /* test the DIB memory */ + ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info), + "VirtualQuery failed\n"); + ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits); + ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits); + ok(info.AllocationProtect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.AllocationProtect); + ok(info.RegionSize == 0x26000, "0x%lx != 0x26000\n", info.RegionSize); + ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); + ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect); + ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); + + test_dib_info(hdib, bits, &pbmi->bmiHeader); + DeleteObject(hdib); + + pbmi->bmiHeader.biBitCount = 8; + pbmi->bmiHeader.biCompression = BI_RLE8; + SetLastError(0xdeadbeef); + hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib == NULL, "CreateDIBSection should fail when asked to create a compressed DIB section\n"); + ok(GetLastError() == 0xdeadbeef, "wrong error %ld\n", GetLastError()); + + pbmi->bmiHeader.biBitCount = 16; + pbmi->bmiHeader.biCompression = BI_BITFIELDS; + ((PDWORD)pbmi->bmiColors)[0] = 0xf800; + ((PDWORD)pbmi->bmiColors)[1] = 0x07e0; + ((PDWORD)pbmi->bmiColors)[2] = 0x001f; + SetLastError(0xdeadbeef); + hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib != NULL, "CreateDIBSection error %ld\n", GetLastError()); + + /* test the DIB memory */ + ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info), + "VirtualQuery failed\n"); + ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits); + ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits); + ok(info.AllocationProtect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.AllocationProtect); + ok(info.RegionSize == 0x19000, "0x%lx != 0x19000\n", info.RegionSize); + ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); + ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect); + ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); + + test_dib_info(hdib, bits, &pbmi->bmiHeader); + DeleteObject(hdib); + memset(pbmi, 0, sizeof(bmibuf)); pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); pbmi->bmiHeader.biHeight = 16; @@ -216,6 +447,9 @@ static void test_dibsections(void) hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); ok(hdib != NULL, "CreateDIBSection failed\n"); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n"); + ok(dibsec.dsBmih.biClrUsed == 2, + "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 2); /* Test if the old BITMAPCOREINFO structure is supported */ @@ -280,6 +514,45 @@ static void test_dibsections(void) SelectObject(hdcmem, oldbm); DeleteObject(hdib); + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0xff; + pbmi->bmiColors[0].rgbBlue = 0xff; + pbmi->bmiColors[1].rgbRed = 0; + pbmi->bmiColors[1].rgbGreen = 0; + pbmi->bmiColors[1].rgbBlue = 0; + + hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib != NULL, "CreateDIBSection failed\n"); + + test_dib_info(hdib, bits, &pbmi->bmiHeader); + + oldbm = SelectObject(hdcmem, hdib); + + ret = GetDIBColorTable(hdcmem, 0, 2, rgb); + ok(ret == 2, "GetDIBColorTable returned %d\n", ret); + ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)), + "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n", + rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved, + rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved); + + SelectObject(hdcmem, oldbm); + test_dib_info(hdib, bits, &pbmi->bmiHeader); + DeleteObject(hdib); + + pbmi->bmiHeader.biBitCount = 4; + for (i = 0; i < 16; i++) { + pbmi->bmiColors[i].rgbRed = i; + pbmi->bmiColors[i].rgbGreen = 16-i; + pbmi->bmiColors[i].rgbBlue = 0; + } + hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ok(hdib != NULL, "CreateDIBSection failed\n"); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n"); + ok(dibsec.dsBmih.biClrUsed == 16, + "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 16); + test_dib_info(hdib, bits, &pbmi->bmiHeader); + DeleteObject(hdib); + pbmi->bmiHeader.biBitCount = 8; for (i = 0; i < 128; i++) { @@ -292,6 +565,10 @@ static void test_dibsections(void) } hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); ok(hdib != NULL, "CreateDIBSection failed\n"); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n"); + ok(dibsec.dsBmih.biClrUsed == 256, + "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 256); + oldbm = SelectObject(hdcmem, hdib); for (i = 0; i < 256; i++) { @@ -302,6 +579,7 @@ static void test_dibsections(void) } SelectObject(hdcmem, oldbm); + test_dib_info(hdib, bits, &pbmi->bmiHeader); DeleteObject(hdib); pbmi->bmiHeader.biBitCount = 1; @@ -322,6 +600,9 @@ static void test_dibsections(void) oldpal = SelectPalette(hdc, hpal, TRUE); hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0); ok(hdib != NULL, "CreateDIBSection failed\n"); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n"); + ok(dibsec.dsBmih.biClrUsed == 2, + "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 2); /* The colour table has already been grabbed from the dc, so we select back the old palette */ @@ -362,6 +643,7 @@ static void test_dibsections(void) bits[0] = bits[1] = 0xff; bits[13 * 4] = bits[13*4 + 1] = 0xff; + test_dib_info(hdib, bits, &pbmi->bmiHeader); pbmi->bmiHeader.biBitCount = 32; @@ -376,6 +658,7 @@ static void test_dibsections(void) ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08lx\n", bits32[17]); SelectObject(hdcmem2, oldbm2); + test_dib_info(hdib2, bits32, &pbmi->bmiHeader); DeleteObject(hdib2); SelectObject(hdcmem, oldbm); @@ -409,6 +692,11 @@ static void test_dibsections(void) oldpal = SelectPalette(hdc, hpal, TRUE); hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0); ok(hdib != NULL, "CreateDIBSection failed\n"); + ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n"); + ok(dibsec.dsBmih.biClrUsed == 256, + "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 256); + + test_dib_info(hdib, bits, &pbmi->bmiHeader); SelectPalette(hdc, oldpal, TRUE); oldbm = SelectObject(hdcmem, hdib); @@ -443,17 +731,534 @@ static void test_dibsections(void) ReleaseDC(0, hdc); } +void test_mono_dibsection(void) +{ + HDC hdc, memdc; + HBITMAP old_bm, mono_ds; + char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)]; + BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf; + BYTE bits[10 * 4]; + BYTE *ds_bits; + int num; + + hdc = GetDC(0); + + memdc = CreateCompatibleDC(hdc); + + memset(pbmi, 0, sizeof(bmibuf)); + pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); + pbmi->bmiHeader.biHeight = 10; + pbmi->bmiHeader.biWidth = 10; + pbmi->bmiHeader.biBitCount = 1; + pbmi->bmiHeader.biPlanes = 1; + pbmi->bmiHeader.biCompression = BI_RGB; + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0xff; + pbmi->bmiColors[0].rgbBlue = 0xff; + pbmi->bmiColors[1].rgbRed = 0x0; + pbmi->bmiColors[1].rgbGreen = 0x0; + pbmi->bmiColors[1].rgbBlue = 0x0; + + /* + * First dib section is 'inverted' ie color[0] is white, color[1] is black + */ + + mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0); + ok(mono_ds != NULL, "CreateDIBSection rets NULL\n"); + old_bm = SelectObject(memdc, mono_ds); + + /* black border, white interior */ + Rectangle(memdc, 0, 0, 10, 10); + ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]); + ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]); + + /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */ + + memset(bits, 0, sizeof(bits)); + bits[0] = 0xaa; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]); + + /* SetDIBitsToDevice with a normal bmi -> inverted dib section */ + + pbmi->bmiColors[0].rgbRed = 0x0; + pbmi->bmiColors[0].rgbGreen = 0x0; + pbmi->bmiColors[0].rgbBlue = 0x0; + pbmi->bmiColors[1].rgbRed = 0xff; + pbmi->bmiColors[1].rgbGreen = 0xff; + pbmi->bmiColors[1].rgbBlue = 0xff; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]); + + SelectObject(memdc, old_bm); + DeleteObject(mono_ds); + + /* + * Next dib section is 'normal' ie color[0] is black, color[1] is white + */ + + pbmi->bmiColors[0].rgbRed = 0x0; + pbmi->bmiColors[0].rgbGreen = 0x0; + pbmi->bmiColors[0].rgbBlue = 0x0; + pbmi->bmiColors[1].rgbRed = 0xff; + pbmi->bmiColors[1].rgbGreen = 0xff; + pbmi->bmiColors[1].rgbBlue = 0xff; + + mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0); + ok(mono_ds != NULL, "CreateDIBSection rets NULL\n"); + old_bm = SelectObject(memdc, mono_ds); + + /* black border, white interior */ + Rectangle(memdc, 0, 0, 10, 10); + ok(ds_bits[0] == 0x00, "out_bits %02x\n", ds_bits[0]); + ok(ds_bits[4] == 0x7f, "out_bits %02x\n", ds_bits[4]); + + /* SetDIBitsToDevice with a normal bmi -> normal dib section */ + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]); + + /* SetDIBitsToDevice with a inverted bmi -> normal dib section */ + + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0xff; + pbmi->bmiColors[0].rgbBlue = 0xff; + pbmi->bmiColors[1].rgbRed = 0x0; + pbmi->bmiColors[1].rgbGreen = 0x0; + pbmi->bmiColors[1].rgbBlue = 0x0; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]); + + /* + * Take that 'normal' dibsection and change its colour table to an 'inverted' one + */ + + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0xff; + pbmi->bmiColors[0].rgbBlue = 0xff; + pbmi->bmiColors[1].rgbRed = 0x0; + pbmi->bmiColors[1].rgbGreen = 0x0; + pbmi->bmiColors[1].rgbBlue = 0x0; + num = SetDIBColorTable(memdc, 0, 2, pbmi->bmiColors); + ok(num == 2, "num = %d\n", num); + + /* black border, white interior */ + Rectangle(memdc, 0, 0, 10, 10); +todo_wine { + ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]); + ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]); + } + /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */ + + memset(bits, 0, sizeof(bits)); + bits[0] = 0xaa; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]); + + /* SetDIBitsToDevice with a normal bmi -> inverted dib section */ + + pbmi->bmiColors[0].rgbRed = 0x0; + pbmi->bmiColors[0].rgbGreen = 0x0; + pbmi->bmiColors[0].rgbBlue = 0x0; + pbmi->bmiColors[1].rgbRed = 0xff; + pbmi->bmiColors[1].rgbGreen = 0xff; + pbmi->bmiColors[1].rgbBlue = 0xff; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]); + + SelectObject(memdc, old_bm); + DeleteObject(mono_ds); + + /* + * Now a dib section with a strange colour map just for fun. This behaves just like an inverted one. + */ + + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0x0; + pbmi->bmiColors[0].rgbBlue = 0x0; + pbmi->bmiColors[1].rgbRed = 0xfe; + pbmi->bmiColors[1].rgbGreen = 0x0; + pbmi->bmiColors[1].rgbBlue = 0x0; + + mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0); + ok(mono_ds != NULL, "CreateDIBSection rets NULL\n"); + old_bm = SelectObject(memdc, mono_ds); + + /* black border, white interior */ + Rectangle(memdc, 0, 0, 10, 10); + ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]); + ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]); + + /* SetDIBitsToDevice with a normal bmi -> inverted dib section */ + + pbmi->bmiColors[0].rgbRed = 0x0; + pbmi->bmiColors[0].rgbGreen = 0x0; + pbmi->bmiColors[0].rgbBlue = 0x0; + pbmi->bmiColors[1].rgbRed = 0xff; + pbmi->bmiColors[1].rgbGreen = 0xff; + pbmi->bmiColors[1].rgbBlue = 0xff; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]); + + /* SetDIBitsToDevice with a inverted bmi -> inverted dib section */ + + pbmi->bmiColors[0].rgbRed = 0xff; + pbmi->bmiColors[0].rgbGreen = 0xff; + pbmi->bmiColors[0].rgbBlue = 0xff; + pbmi->bmiColors[1].rgbRed = 0x0; + pbmi->bmiColors[1].rgbGreen = 0x0; + pbmi->bmiColors[1].rgbBlue = 0x0; + + SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS); + ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]); + + SelectObject(memdc, old_bm); + DeleteObject(mono_ds); + + DeleteDC(memdc); + ReleaseDC(0, hdc); +} + +static void test_bitmap(void) +{ + char buf[256], buf_cmp[256]; + HBITMAP hbmp, hbmp_old; + HDC hdc; + BITMAP bm; + INT ret; + + hdc = CreateCompatibleDC(0); + assert(hdc != 0); + + hbmp = CreateBitmap(15, 15, 1, 1, NULL); + assert(hbmp != NULL); + + ret = GetObject(hbmp, sizeof(bm), &bm); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType); + ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight); + ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes); + ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes); + ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel); + ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits); + + assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight); + assert(sizeof(buf) == sizeof(buf_cmp)); + + ret = GetBitmapBits(hbmp, 0, NULL); + ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + + memset(buf_cmp, 0xAA, sizeof(buf_cmp)); + memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight); + + memset(buf, 0xAA, sizeof(buf)); + ret = GetBitmapBits(hbmp, sizeof(buf), buf); + ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n"); + + hbmp_old = SelectObject(hdc, hbmp); + + ret = GetObject(hbmp, sizeof(bm), &bm); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType); + ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth); + ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight); + ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes); + ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes); + ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel); + ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits); + + memset(buf, 0xAA, sizeof(buf)); + ret = GetBitmapBits(hbmp, sizeof(buf), buf); + ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight); + ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n"); + + hbmp_old = SelectObject(hdc, hbmp_old); + ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old); + + /* test various buffer sizes for GetObject */ + ret = GetObject(hbmp, sizeof(bm) * 2, &bm); + ok(ret == sizeof(bm), "wrong size %d\n", ret); + + ret = GetObject(hbmp, sizeof(bm) / 2, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbmp, 0, &bm); + ok(ret == 0, "%d != 0\n", ret); + + ret = GetObject(hbmp, 1, &bm); + ok(ret == 0, "%d != 0\n", ret); + + DeleteObject(hbmp); + DeleteDC(hdc); +} + +static void test_bmBits(void) +{ + BYTE bits[4]; + HBITMAP hbmp; + BITMAP bmp; + + memset(bits, 0, sizeof(bits)); + hbmp = CreateBitmap(2, 2, 1, 4, bits); + ok(hbmp != NULL, "CreateBitmap failed\n"); + + memset(&bmp, 0xFF, sizeof(bmp)); + ok(GetObject(hbmp, sizeof(bmp), &bmp) == sizeof(bmp), + "GetObject failed or returned a wrong structure size\n"); + ok(!bmp.bmBits, "bmBits must be NULL for device-dependent bitmaps\n"); + + DeleteObject(hbmp); +} + +static void test_GetDIBits_selected_DIB(UINT bpp) +{ + HBITMAP dib; + BITMAPINFO * info; + BITMAPINFO * info2; + void * bits; + void * bits2; + UINT dib_size; + HDC dib_dc, dc; + HBITMAP old_bmp; + BOOL equalContents; + UINT i; + int res; + + /* Create a DIB section with a color table */ + + info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD)); + info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD)); + assert(info); + assert(info2); + + info->bmiHeader.biSize = sizeof(info->bmiHeader); + + /* Choose width and height such that the row length (in bytes) + is a multiple of 4 (makes things easier) */ + info->bmiHeader.biWidth = 32; + info->bmiHeader.biHeight = 32; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = bpp; + info->bmiHeader.biCompression = BI_RGB; + + for (i=0; i < (1 << bpp); i++) + { + BYTE c = i * (1 << (8 - bpp)); + info->bmiColors[i].rgbRed = c; + info->bmiColors[i].rgbGreen = c; + info->bmiColors[i].rgbBlue = c; + info->bmiColors[i].rgbReserved = 0; + } + + dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0); + assert(dib); + dib_size = bpp * (info->bmiHeader.biWidth * info->bmiHeader.biHeight) / 8; + + /* Set the bits of the DIB section */ + for (i=0; i < dib_size; i++) + { + ((BYTE *)bits)[i] = i % 256; + } + + /* Select the DIB into a DC */ + dib_dc = CreateCompatibleDC(NULL); + old_bmp = (HBITMAP) SelectObject(dib_dc, dib); + dc = CreateCompatibleDC(NULL); + bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size); + assert(bits2); + + /* Copy the DIB attributes but not the color table */ + memcpy(info2, info, sizeof(BITMAPINFOHEADER)); + + res = GetDIBits(dc, dib, 0, info->bmiHeader.biHeight, bits2, info2, DIB_RGB_COLORS); + ok(res, "GetDIBits failed\n"); + + /* Compare the color table and the bits */ + equalContents = TRUE; + for (i=0; i < (1 << bpp); i++) + { + if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed) + || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen) + || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue) + || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved)) + { + equalContents = FALSE; + break; + } + } + todo_wine + { + ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n"); + } + + equalContents = TRUE; + for (i=0; i < dib_size / sizeof(DWORD); i++) + { + if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i]) + { + equalContents = FALSE; + break; + } + } + todo_wine + { + ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB bits\n"); + } + + HeapFree(GetProcessHeap(), 0, bits2); + DeleteDC(dc); + + SelectObject(dib_dc, old_bmp); + DeleteDC(dib_dc); + DeleteObject(dib); + + HeapFree(GetProcessHeap(), 0, info2); + HeapFree(GetProcessHeap(), 0, info); +} + +static void test_GetDIBits_selected_DDB(BOOL monochrome) +{ + HBITMAP ddb; + BITMAPINFO * info; + BITMAPINFO * info2; + void * bits; + void * bits2; + HDC ddb_dc, dc; + HBITMAP old_bmp; + BOOL equalContents; + UINT width, height; + UINT bpp; + UINT i, j; + int res; + + width = height = 16; + + /* Create a DDB (device-dependent bitmap) */ + if (monochrome) + { + bpp = 1; + ddb = CreateBitmap(width, height, 1, 1, NULL); + } + else + { + HDC screen_dc = GetDC(NULL); + bpp = GetDeviceCaps(screen_dc, BITSPIXEL) * GetDeviceCaps(screen_dc, PLANES); + ddb = CreateCompatibleBitmap(screen_dc, width, height); + ReleaseDC(NULL, screen_dc); + } + + /* Set the pixels */ + ddb_dc = CreateCompatibleDC(NULL); + old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb); + for (i = 0; i < width; i++) + { + for (j=0; j < height; j++) + { + BYTE c = (i * width + j) % 256; + SetPixelV(ddb_dc, i, j, RGB(c, c, c)); + } + } + SelectObject(ddb_dc, old_bmp); + + info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + assert(info); + assert(info2); + + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = height; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = bpp; + info->bmiHeader.biCompression = BI_RGB; + + dc = CreateCompatibleDC(NULL); + + /* Fill in biSizeImage */ + GetDIBits(dc, ddb, 0, height, NULL, info, DIB_RGB_COLORS); + ok(info->bmiHeader.biSizeImage != 0, "GetDIBits failed to get the DIB attributes\n"); + + bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage); + bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage); + assert(bits); + assert(bits2); + + /* Get the bits */ + res = GetDIBits(dc, ddb, 0, height, bits, info, DIB_RGB_COLORS); + ok(res, "GetDIBits failed\n"); + + /* Copy the DIB attributes but not the color table */ + memcpy(info2, info, sizeof(BITMAPINFOHEADER)); + + /* Select the DDB into another DC */ + old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb); + + /* Get the bits */ + res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS); + ok(res, "GetDIBits failed\n"); + + /* Compare the color table and the bits */ + if (bpp <= 8) + { + equalContents = TRUE; + for (i=0; i < (1 << bpp); i++) + { + if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed) + || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen) + || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue) + || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved)) + { + equalContents = FALSE; + break; + } + } + ok(equalContents, "GetDIBits with DDB selected in DC: Got a different color table\n"); + } + + equalContents = TRUE; + for (i=0; i < info->bmiHeader.biSizeImage / sizeof(DWORD); i++) + { + if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i]) + { + equalContents = FALSE; + } + } + ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB bits\n"); + + HeapFree(GetProcessHeap(), 0, bits2); + HeapFree(GetProcessHeap(), 0, bits); + DeleteDC(dc); + + SelectObject(ddb_dc, old_bmp); + DeleteDC(ddb_dc); + DeleteObject(ddb); + + HeapFree(GetProcessHeap(), 0, info2); + HeapFree(GetProcessHeap(), 0, info); +} + START_TEST(bitmap) { - HWND hWnd; - - hWnd = CreateWindowExA(0, "EDIT", NULL, 0, - 10, 10, 300, 300, - NULL, NULL, NULL, NULL); - assert(hWnd); - is_win9x = GetWindowLongW(hWnd, GWL_WNDPROC) == 0; - DestroyWindow(hWnd); + is_win9x = GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC) == 0; test_createdibitmap(); test_dibsections(); + test_mono_dibsection(); + test_bitmap(); + test_bmBits(); + test_GetDIBits_selected_DIB(1); + test_GetDIBits_selected_DIB(4); + test_GetDIBits_selected_DIB(8); + test_GetDIBits_selected_DDB(TRUE); + test_GetDIBits_selected_DDB(FALSE); } diff --git a/reactos/regtests/winetests/gdi32/brush.c b/reactos/regtests/winetests/gdi32/brush.c index f4e22b6b30d..c2aee7c138e 100755 --- a/reactos/regtests/winetests/gdi32/brush.c +++ b/reactos/regtests/winetests/gdi32/brush.c @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -56,7 +56,7 @@ static void test_solidbrush(void) } else stockBrush = NULL; - memset(&br, sizeof(br), 0); + memset(&br, 0, sizeof(br)); ret = GetObject(solidBrush, sizeof(br), &br); ok( ret !=0, "GetObject on solid %s brush failed, error=%ld\n", stock[i].name, GetLastError()); ok(br.lbStyle==BS_SOLID, "%s brush has wrong style, got %d expected %d\n", stock[i].name, br.lbStyle, BS_SOLID); diff --git a/reactos/regtests/winetests/gdi32/clipping.c b/reactos/regtests/winetests/gdi32/clipping.c new file mode 100644 index 00000000000..079fbcc804c --- /dev/null +++ b/reactos/regtests/winetests/gdi32/clipping.c @@ -0,0 +1,125 @@ +/* + * Unit test suite for clipping + * + * Copyright 2005 Huw Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" + +static void test_GetRandomRgn(void) +{ + HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_VISIBLE|WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0); + HDC hdc; + HRGN hrgn = CreateRectRgn(0, 0, 0, 0); + int ret; + RECT rc, rc2; + RECT ret_rc, window_rc; + + ok( hwnd != 0, "CreateWindow failed\n" ); + + SetRect(&window_rc, 400, 300, 500, 400); + MoveWindow(hwnd, window_rc.left, window_rc.top, window_rc.right - window_rc.left, window_rc.bottom - window_rc.top, FALSE); + hdc = GetDC(hwnd); + + ret = GetRandomRgn(hdc, hrgn, 1); + ok(ret == 0, "GetRandomRgn rets %d\n", ret); + ret = GetRandomRgn(hdc, hrgn, 2); + ok(ret == 0, "GetRandomRgn rets %d\n", ret); + ret = GetRandomRgn(hdc, hrgn, 3); + ok(ret == 0, "GetRandomRgn rets %d\n", ret); + + /* Set a clip region */ + SetRect(&rc, 20, 20, 80, 80); + IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); + + ret = GetRandomRgn(hdc, hrgn, 1); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + ret = GetRandomRgn(hdc, hrgn, 2); + ok(ret == 0, "GetRandomRgn rets %d\n", ret); + + ret = GetRandomRgn(hdc, hrgn, 3); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + /* Move the clip to the meta and clear the clip */ + SetMetaRgn(hdc); + + ret = GetRandomRgn(hdc, hrgn, 1); + ok(ret == 0, "GetRandomRgn rets %d\n", ret); + ret = GetRandomRgn(hdc, hrgn, 2); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + ret = GetRandomRgn(hdc, hrgn, 3); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + /* Set a new clip (still got the meta) */ + SetRect(&rc2, 10, 30, 70, 90); + IntersectClipRect(hdc, rc2.left, rc2.top, rc2.right, rc2.bottom); + + ret = GetRandomRgn(hdc, hrgn, 1); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + ret = GetRandomRgn(hdc, hrgn, 2); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + IntersectRect(&rc2, &rc, &rc2); + + ret = GetRandomRgn(hdc, hrgn, 3); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + + ret = GetRandomRgn(hdc, hrgn, SYSRGN); + ok(ret != 0, "GetRandomRgn rets %d\n", ret); + GetRgnBox(hrgn, &ret_rc); + if(GetVersion() & 0x80000000) + OffsetRect(&window_rc, -window_rc.left, -window_rc.top); + ok(EqualRect(&window_rc, &ret_rc), "GetRandomRgn %ld,%ld - %ld,%ld\n", + ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom); + + DeleteObject(hrgn); + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); +} + +START_TEST(clipping) +{ + test_GetRandomRgn(); +} diff --git a/reactos/regtests/winetests/gdi32/dc.c b/reactos/regtests/winetests/gdi32/dc.c new file mode 100644 index 00000000000..5b50632750d --- /dev/null +++ b/reactos/regtests/winetests/gdi32/dc.c @@ -0,0 +1,180 @@ +/* + * Unit tests for dc functions + * + * Copyright (c) 2005 Huw Davies + * Copyright (c) 2005 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "wine/test.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winerror.h" + +static void dump_region(HRGN hrgn) +{ + DWORD i, size; + RGNDATA *data = NULL; + RECT *rect; + + if (!hrgn) + { + printf( "(null) region\n" ); + return; + } + if (!(size = GetRegionData( hrgn, 0, NULL ))) return; + if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; + GetRegionData( hrgn, size, data ); + printf( "%ld rects:", data->rdh.nCount ); + for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) + printf( " (%ld,%ld)-(%ld,%ld)", rect->left, rect->top, rect->right, rect->bottom ); + printf( "\n" ); + HeapFree( GetProcessHeap(), 0, data ); +} + +static void test_savedc_2(void) +{ + HWND hwnd; + HDC hdc; + HRGN hrgn; + RECT rc, rc_clip; + int ret; + + hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100, + 0, 0, 0, NULL); + assert(hwnd != 0); + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); + + hrgn = CreateRectRgn(0, 0, 0, 0); + assert(hrgn != 0); + + hdc = GetDC(hwnd); + ok(hdc != NULL, "CreateDC rets %p\n", hdc); + + ret = GetClipBox(hdc, &rc_clip); + ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret); + ret = GetClipRgn(hdc, hrgn); + ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret); + ret = GetRgnBox(hrgn, &rc); + ok(ret == NULLREGION, "GetRgnBox returned %d (%ld,%ld-%ld,%ld) instead of NULLREGION\n", + ret, rc.left, rc.top, rc.right, rc.bottom); + /*dump_region(hrgn);*/ + SetRect(&rc, 0, 0, 100, 100); + ok(EqualRect(&rc, &rc_clip), + "rects are not equal: (%ld,%ld-%ld,%ld) - (%ld,%ld-%ld,%ld)\n", + rc.left, rc.top, rc.right, rc.bottom, + rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); + + ret = SaveDC(hdc); +todo_wine +{ + ok(ret == 1, "ret = %d\n", ret); +} + + ret = IntersectClipRect(hdc, 0, 0, 50, 50); +#if 0 /* XP returns COMPLEXREGION although dump_region reports only 1 rect */ + ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret); +#endif + if (ret != SIMPLEREGION) + { + trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret); + /* let's make sure that it's a simple region */ + ret = GetClipRgn(hdc, hrgn); + ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret); + dump_region(hrgn); + } + + ret = GetClipBox(hdc, &rc_clip); + ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret); + SetRect(&rc, 0, 0, 50, 50); + ok(EqualRect(&rc, &rc_clip), "rects are not equal\n"); + + ret = RestoreDC(hdc, 1); + ok(ret, "ret = %d\n", ret); + + ret = GetClipBox(hdc, &rc_clip); + ok(ret == SIMPLEREGION, "GetClipBox returned %d instead of SIMPLEREGION\n", ret); + SetRect(&rc, 0, 0, 100, 100); + ok(EqualRect(&rc, &rc_clip), "rects are not equal\n"); + + DeleteObject(hrgn); + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); +} + +static void test_savedc(void) +{ + HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); + int ret; + + ok(hdc != NULL, "CreateDC rets %p\n", hdc); + + ret = SaveDC(hdc); + ok(ret == 1, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 2, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 3, "ret = %d\n", ret); + ret = RestoreDC(hdc, -1); + ok(ret, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 3, "ret = %d\n", ret); + ret = RestoreDC(hdc, 1); + ok(ret, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 1, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 2, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 3, "ret = %d\n", ret); + ret = RestoreDC(hdc, -2); + ok(ret, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 2, "ret = %d\n", ret); + ret = RestoreDC(hdc, -2); + ok(ret, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 1, "ret = %d\n", ret); + ret = SaveDC(hdc); + ok(ret == 2, "ret = %d\n", ret); + ret = RestoreDC(hdc, -4); + ok(!ret, "ret = %d\n", ret); + ret = RestoreDC(hdc, 3); + ok(!ret, "ret = %d\n", ret); + + /* Under win98 the following two succeed and both clear the save stack + ret = RestoreDC(hdc, -3); + ok(!ret, "ret = %d\n", ret); + ret = RestoreDC(hdc, 0); + ok(!ret, "ret = %d\n", ret); + */ + + ret = RestoreDC(hdc, 1); + ok(ret, "ret = %d\n", ret); + + DeleteDC(hdc); +} + +START_TEST(dc) +{ + test_savedc(); + test_savedc_2(); +} diff --git a/reactos/regtests/winetests/gdi32/font.c b/reactos/regtests/winetests/gdi32/font.c new file mode 100644 index 00000000000..699d9b28e08 --- /dev/null +++ b/reactos/regtests/winetests/gdi32/font.c @@ -0,0 +1,441 @@ +/* + * Unit test suite for fonts + * + * Copyright 2002 Mike McCormack + * Copyright 2004 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" + +#include "wine/test.h" + +static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont) +{ + LOGFONTA getobj_lf; + int ret, minlen = 0; + + if (!hfont) + return; + + ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf); + /* NT4 tries to be clever and only returns the minimum length */ + while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1) + minlen++; + minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1; + ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n", test, ret); + ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test); + ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName), + "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName); +} + +static HFONT create_font(const char* test, const LOGFONTA* lf) +{ + HFONT hfont = CreateFontIndirectA(lf); + ok(hfont != 0, "%s: CreateFontIndirect failed\n", test); + if (hfont) + check_font(test, lf, hfont); + return hfont; +} + +static void test_logfont(void) +{ + LOGFONTA lf; + HFONT hfont; + + memset(&lf, 0, sizeof lf); + + lf.lfCharSet = ANSI_CHARSET; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfWeight = FW_DONTCARE; + lf.lfHeight = 16; + lf.lfWidth = 16; + lf.lfQuality = DEFAULT_QUALITY; + + lstrcpyA(lf.lfFaceName, "Arial"); + hfont = create_font("Arial", &lf); + DeleteObject(hfont); + + memset(&lf, 'A', sizeof(lf)); + hfont = CreateFontIndirectA(&lf); + ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n"); + + lf.lfFaceName[LF_FACESIZE - 1] = 0; + check_font("AAA...", &lf, hfont); + DeleteObject(hfont); +} + +static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) +{ + if (type & RASTER_FONTTYPE) + { + LOGFONT *lf = (LOGFONT *)lParam; + *lf = *elf; + return 0; /* stop enumeration */ + } + + return 1; /* continue enumeration */ +} + +static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str, + INT test_str_len, const TEXTMETRICA *tm_orig, + const SIZE *size_orig, INT width_orig, + INT scale_x, INT scale_y) +{ + HFONT old_hfont; + TEXTMETRICA tm; + SIZE size; + INT width; + + if (!hfont) + return; + + old_hfont = SelectObject(hdc, hfont); + + GetTextMetricsA(hdc, &tm); + + ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y); + ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y); + ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y); + ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); + + GetTextExtentPoint32A(hdc, test_str, test_str_len, &size); + + ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x); + ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y); + + GetCharWidthA(hdc, 'A', 'A', &width); + + ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x); + + SelectObject(hdc, old_hfont); +} + +/* see whether GDI scales bitmap font metrics */ +static void test_bitmap_font(void) +{ + static const char test_str[11] = "Test String"; + HDC hdc; + LOGFONTA bitmap_lf; + HFONT hfont, old_hfont; + TEXTMETRICA tm_orig; + SIZE size_orig; + INT ret, i, width_orig, height_orig; + + hdc = GetDC(0); + + /* "System" has only 1 pixel size defined, otherwise the test breaks */ + ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf); + if (ret) + { + ReleaseDC(0, hdc); + trace("no bitmap fonts were found, skipping the test\n"); + return; + } + + trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight); + + height_orig = bitmap_lf.lfHeight; + hfont = create_font("bitmap", &bitmap_lf); + + old_hfont = SelectObject(hdc, hfont); + ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n"); + ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); + ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + /* test fractional scaling */ + for (i = 1; i < height_orig; i++) + { + hfont = create_font("fractional", &bitmap_lf); + test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1); + DeleteObject(hfont); + } + + /* test integer scaling 3x2 */ + bitmap_lf.lfHeight = height_orig * 2; + bitmap_lf.lfWidth *= 3; + hfont = create_font("3x2", &bitmap_lf); +todo_wine +{ + test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2); +} + DeleteObject(hfont); + + /* test integer scaling 3x3 */ + bitmap_lf.lfHeight = height_orig * 3; + bitmap_lf.lfWidth = 0; + hfont = create_font("3x3", &bitmap_lf); + +todo_wine +{ + test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3); +} + DeleteObject(hfont); + + ReleaseDC(0, hdc); +} + +static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) +{ + LOGFONT *lf = (LOGFONT *)lParam; + + if (elf->lfHeight == lf->lfHeight && !strcmp(elf->lfFaceName, lf->lfFaceName)) + { + *lf = *elf; + return 0; /* stop enumeration */ + } + return 1; /* continue enumeration */ +} + +static void test_bitmap_font_metrics(void) +{ + static const struct font_data + { + const char face_name[LF_FACESIZE]; + int weight, height, ascent, descent, int_leading, ext_leading; + int ave_char_width, max_char_width; + } fd[] = + { + { "MS Sans Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 11 }, + { "MS Sans Serif", FW_NORMAL, 16, 13, 3, 3, 0, 7, 14 }, + { "MS Sans Serif", FW_NORMAL, 20, 16, 4, 4, 0, 8, 16 }, + { "MS Sans Serif", FW_NORMAL, 24, 19, 5, 6, 0, 9, 20 }, + { "MS Sans Serif", FW_NORMAL, 29, 23, 6, 5, 0, 12, 25 }, + { "MS Sans Serif", FW_NORMAL, 37, 29, 8, 5, 0, 16, 32 }, + { "MS Serif", FW_NORMAL, 10, 8, 2, 2, 0, 5, 8 }, + { "MS Serif", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9 }, + { "MS Serif", FW_NORMAL, 13, 11, 2, 2, 0, 5, 12 }, + { "MS Serif", FW_NORMAL, 16, 13, 3, 3, 0, 6, 16 }, + { "MS Serif", FW_NORMAL, 19, 15, 4, 3, 0, 8, 19 }, + { "MS Serif", FW_NORMAL, 21, 16, 5, 3, 0, 9, 23 }, + { "MS Serif", FW_NORMAL, 27, 21, 6, 3, 0, 12, 27 }, + { "MS Serif", FW_NORMAL, 35, 27, 8, 3, 0, 16, 34 }, + { "Courier", FW_NORMAL, 13, 11, 2, 0, 0, 8, 8 }, + { "Courier", FW_NORMAL, 16, 13, 3, 0, 0, 9, 9 }, + { "Courier", FW_NORMAL, 20, 16, 4, 0, 0, 12, 12 }, + { "System", FW_BOLD, 16, 13, 3, 3, 0, 7, 15 }, + { "Small Fonts", FW_NORMAL, 3, 2, 1, 0, 0, 1, 2 }, + { "Small Fonts", FW_NORMAL, 5, 4, 1, 1, 0, 3, 4 }, + { "Small Fonts", FW_NORMAL, 6, 5, 1, 1, 0, 3, 13 }, + { "Small Fonts", FW_NORMAL, 8, 7, 1, 1, 0, 4, 7 }, + { "Small Fonts", FW_NORMAL, 10, 8, 2, 2, 0, 4, 8 }, + { "Small Fonts", FW_NORMAL, 11, 9, 2, 2, 0, 5, 9 } + /* FIXME: add "Fixedsys", "Terminal" */ + }; + HDC hdc; + LOGFONT lf; + HFONT hfont, old_hfont; + TEXTMETRIC tm; + INT ret, i; + + hdc = CreateCompatibleDC(0); + assert(hdc); + + for (i = 0; i < sizeof(fd)/sizeof(fd[0]); i++) + { + memset(&lf, 0, sizeof(lf)); + + lf.lfHeight = fd[i].height; + strcpy(lf.lfFaceName, fd[i].face_name); + ret = EnumFontFamilies(hdc, fd[i].face_name, find_font_proc, (LPARAM)&lf); + if (ret) + { + trace("font %s height %d not found\n", fd[i].face_name, fd[i].height); + continue; + } + + trace("found font %s, height %ld\n", lf.lfFaceName, lf.lfHeight); + + hfont = create_font(lf.lfFaceName, &lf); + old_hfont = SelectObject(hdc, hfont); + ok(GetTextMetrics(hdc, &tm), "GetTextMetrics error %ld\n", GetLastError()); + + ok(tm.tmWeight == fd[i].weight, "%s(%d): tm.tmWeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmWeight, fd[i].weight); + ok(tm.tmHeight == fd[i].height, "%s(%d): tm.tmHeight %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmHeight, fd[i].height); + ok(tm.tmAscent == fd[i].ascent, "%s(%d): tm.tmAscent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAscent, fd[i].ascent); + ok(tm.tmDescent == fd[i].descent, "%s(%d): tm.tmDescent %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmDescent, fd[i].descent); + ok(tm.tmInternalLeading == fd[i].int_leading, "%s(%d): tm.tmInternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmInternalLeading, fd[i].int_leading); + ok(tm.tmExternalLeading == fd[i].ext_leading, "%s(%d): tm.tmExternalLeading %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmExternalLeading, fd[i].ext_leading); + ok(tm.tmAveCharWidth == fd[i].ave_char_width, "%s(%d): tm.tmAveCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmAveCharWidth, fd[i].ave_char_width); + ok(tm.tmMaxCharWidth == fd[i].max_char_width, "%s(%d): tm.tmMaxCharWidth %ld != %d\n", fd[i].face_name, fd[i].height, tm.tmMaxCharWidth, fd[i].max_char_width); + + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + } + + DeleteDC(hdc); +} + +static void test_GdiGetCharDimensions(void) +{ + HDC hdc; + TEXTMETRICW tm; + LONG ret; + SIZE size; + LONG avgwidth, height; + static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + typedef LONG (WINAPI *fnGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); + fnGdiGetCharDimensions GdiGetCharDimensions = (fnGdiGetCharDimensions)GetProcAddress(LoadLibrary("gdi32"), "GdiGetCharDimensions"); + if (!GdiGetCharDimensions) return; + + hdc = CreateCompatibleDC(NULL); + + GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size); + avgwidth = ((size.cx / 26) + 1) / 2; + + ret = GdiGetCharDimensions(hdc, &tm, &height); + ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height); + + ret = GdiGetCharDimensions(hdc, &tm, NULL); + ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + + ret = GdiGetCharDimensions(hdc, NULL, NULL); + ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + + height = 0; + ret = GdiGetCharDimensions(hdc, NULL, &height); + ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height); + + DeleteDC(hdc); +} + +static void test_GetCharABCWidthsW(void) +{ + BOOL ret; + ABC abc[1]; + typedef BOOL (WINAPI *fnGetCharABCWidthsW)(HDC hdc, UINT first, UINT last, LPABC abc); + fnGetCharABCWidthsW GetCharABCWidthsW = (fnGetCharABCWidthsW)GetProcAddress(LoadLibrary("gdi32"), "GetCharABCWidthsW"); + if (!GetCharABCWidthsW) return; + + ret = GetCharABCWidthsW(NULL, 'a', 'a', abc); + ok(!ret, "GetCharABCWidthsW should have returned FALSE\n"); +} + +static void test_text_extents(void) +{ + static const WCHAR wt[] = {'O','n','e','\n','t','w','o',' ','3',0}; + LPINT extents; + INT i, len, fit1, fit2; + LOGFONTA lf; + TEXTMETRICA tm; + HDC hdc; + HFONT hfont; + SIZE sz; + SIZE sz1, sz2; + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Arial"); + lf.lfHeight = 20; + + hfont = CreateFontIndirectA(&lf); + hdc = GetDC(0); + hfont = SelectObject(hdc, hfont); + GetTextMetricsA(hdc, &tm); + GetTextExtentPointA(hdc, "o", 1, &sz); + ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight); + + len = lstrlenW(wt); + extents = HeapAlloc(GetProcessHeap(), 0, len * sizeof extents[0]); + memset(extents, 0, len * sizeof extents[0]); + extents[0] = 1; /* So that the increasing sequence test will fail + if the extents array is untouched. */ + GetTextExtentExPointW(hdc, wt, len, 32767, &fit1, extents, &sz1); + GetTextExtentPointW(hdc, wt, len, &sz2); + ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, + "results from GetTextExtentExPointW and GetTextExtentPointW differ\n"); + for (i = 1; i < len; ++i) + ok(extents[i-1] <= extents[i], + "GetTextExtentExPointW generated a non-increasing sequence of partial extents (at position %d)\n", + i); + ok(extents[len-1] == sz1.cx, "GetTextExtentExPointW extents and size don't match\n"); + ok(0 <= fit1 && fit1 <= len, "GetTextExtentExPointW generated illegal value %d for fit\n", fit1); + ok(0 < fit1, "GetTextExtentExPointW says we can't even fit one letter in 32767 logical units\n"); + GetTextExtentExPointW(hdc, wt, len, extents[2], &fit2, NULL, &sz2); + ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, "GetTextExtentExPointW returned different sizes for the same string\n"); + ok(fit2 == 3, "GetTextExtentExPointW extents isn't consistent with fit\n"); + GetTextExtentExPointW(hdc, wt, len, extents[2]-1, &fit2, NULL, &sz2); + ok(fit2 == 2, "GetTextExtentExPointW extents isn't consistent with fit\n"); + GetTextExtentExPointW(hdc, wt, 2, 0, NULL, extents + 2, &sz2); + ok(extents[0] == extents[2] && extents[1] == extents[3], + "GetTextExtentExPointW with lpnFit == NULL returns incorrect results\n"); + GetTextExtentExPointW(hdc, wt, 2, 0, NULL, NULL, &sz1); + ok(sz1.cx == sz2.cx && sz1.cy == sz2.cy, + "GetTextExtentExPointW with lpnFit and alpDx both NULL returns incorrect results\n"); + HeapFree(GetProcessHeap(), 0, extents); + + SelectObject(hdc, hfont); + DeleteObject(hfont); + ReleaseDC(NULL, hdc); +} + +static void test_GetGlyphIndices() +{ + HDC hdc; + HFONT hfont; + DWORD charcount; + LOGFONTA lf; + DWORD flags = 0; + WCHAR testtext[] = {'T','e','s','t',0xffff,0}; + WORD glyphs[(sizeof(testtext)/2)-1]; + TEXTMETRIC textm; + + typedef BOOL (WINAPI *fnGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags); + fnGetGlyphIndicesW GetGlyphIndicesW = (fnGetGlyphIndicesW)GetProcAddress(LoadLibrary("gdi32"), + "GetGlyphIndicesW"); + if (!GetGlyphIndicesW) { + trace("GetGlyphIndices not available on platform\n"); + return; + } + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Symbol"); + lf.lfHeight = 20; + + hfont = CreateFontIndirectA(&lf); + hdc = GetDC(0); + + ok(GetTextMetrics(hdc, &textm), "GetTextMetric failed\n"); + flags |= GGI_MARK_NONEXISTING_GLYPHS; + charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags); + ok(charcount == 5, "GetGlyphIndices count of glyphs should = 5 not %ld\n", charcount); + ok(glyphs[4] == 0x001f, "GetGlyphIndices should have returned a nonexistent char not %04x\n", glyphs[4]); + flags = 0; + charcount = GetGlyphIndicesW(hdc, testtext, (sizeof(testtext)/2)-1, glyphs, flags); + ok(charcount == 5, "GetGlyphIndices count of glyphs should = 5 not %ld\n", charcount); + ok(glyphs[4] == textm.tmDefaultChar, "GetGlyphIndices should have returned a %04x not %04x\n", + textm.tmDefaultChar, glyphs[4]); +} + +START_TEST(font) +{ + test_logfont(); + test_bitmap_font(); + test_bitmap_font_metrics(); + test_GdiGetCharDimensions(); + test_GetCharABCWidthsW(); + test_text_extents(); + test_GetGlyphIndices(); +} diff --git a/reactos/regtests/winetests/gdi32/gdi32.rbuild b/reactos/regtests/winetests/gdi32/gdi32.rbuild index d9d1e40945f..448a0fa8d16 100644 --- a/reactos/regtests/winetests/gdi32/gdi32.rbuild +++ b/reactos/regtests/winetests/gdi32/gdi32.rbuild @@ -8,7 +8,10 @@ advapi32 bitmap.c brush.c + clipping.c + dc.c gdiobj.c + font.c metafile.c testlist.c diff --git a/reactos/regtests/winetests/gdi32/gdiobj.c b/reactos/regtests/winetests/gdi32/gdiobj.c index deed86fc3b1..21310b11685 100755 --- a/reactos/regtests/winetests/gdi32/gdiobj.c +++ b/reactos/regtests/winetests/gdi32/gdiobj.c @@ -16,10 +16,11 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include +#include #include "windef.h" #include "winbase.h" @@ -28,175 +29,6 @@ #include "wine/test.h" - -static void check_font(const char* test, const LOGFONTA* lf, HFONT hfont) -{ - LOGFONTA getobj_lf; - int ret, minlen = 0; - - if (!hfont) - return; - - ret = GetObject(hfont, sizeof(getobj_lf), &getobj_lf); - /* NT4 tries to be clever and only returns the minimum length */ - while (lf->lfFaceName[minlen] && minlen < LF_FACESIZE-1) - minlen++; - minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1; - ok(ret == sizeof(LOGFONTA) || ret == minlen, - "%s: GetObject returned %d expected %d or %d\n", test, ret, sizeof(LOGFONTA), minlen); - ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts don't match\n", test); - ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName), - "%s: font names don't match: %s != %s\n", test, lf->lfFaceName, getobj_lf.lfFaceName); -} - -static HFONT create_font(const char* test, const LOGFONTA* lf) -{ - HFONT hfont = CreateFontIndirectA(lf); - ok(hfont != 0, "%s: CreateFontIndirect failed\n", test); - if (hfont) - check_font(test, lf, hfont); - return hfont; -} - -static void test_logfont(void) -{ - LOGFONTA lf; - HFONT hfont; - - memset(&lf, 0, sizeof lf); - - lf.lfCharSet = ANSI_CHARSET; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfWeight = FW_DONTCARE; - lf.lfHeight = 16; - lf.lfWidth = 16; - lf.lfQuality = DEFAULT_QUALITY; - - lstrcpyA(lf.lfFaceName, "Arial"); - hfont = create_font("Arial", &lf); - DeleteObject(hfont); - - memset(&lf, 'A', sizeof(lf)); - hfont = CreateFontIndirectA(&lf); - ok(hfont != 0, "CreateFontIndirectA with strange LOGFONT failed\n"); - - lf.lfFaceName[LF_FACESIZE - 1] = 0; - check_font("AAA...", &lf, hfont); - DeleteObject(hfont); -} - -static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) -{ - if (type & RASTER_FONTTYPE) - { - LOGFONT *lf = (LOGFONT *)lParam; - *lf = *elf; - return 0; /* stop enumeration */ - } - - return 1; /* continue enumeration */ -} - -static void test_font_metrics(HDC hdc, HFONT hfont, const char *test_str, - INT test_str_len, const TEXTMETRICA *tm_orig, - const SIZE *size_orig, INT width_orig, - INT scale_x, INT scale_y) -{ - HFONT old_hfont; - TEXTMETRICA tm; - SIZE size; - INT width; - - if (!hfont) - return; - - old_hfont = SelectObject(hdc, hfont); - - GetTextMetricsA(hdc, &tm); - - ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%ld != %ld\n", tm.tmHeight, tm_orig->tmHeight * scale_y); - ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%ld != %ld\n", tm.tmAscent, tm_orig->tmAscent * scale_y); - ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%ld != %ld\n", tm.tmDescent, tm_orig->tmDescent * scale_y); - ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%ld != %ld\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); - - GetTextExtentPoint32A(hdc, test_str, test_str_len, &size); - - ok(size.cx == size_orig->cx * scale_x, "%ld != %ld\n", size.cx, size_orig->cx * scale_x); - ok(size.cy == size_orig->cy * scale_y, "%ld != %ld\n", size.cy, size_orig->cy * scale_y); - - GetCharWidthA(hdc, 'A', 'A', &width); - - ok(width == width_orig * scale_x, "%d != %d\n", width, width_orig * scale_x); - - SelectObject(hdc, old_hfont); -} - -/* see whether GDI scales bitmap font metrics */ -static void test_bitmap_font(void) -{ - static const char test_str[11] = "Test String"; - HDC hdc; - LOGFONTA bitmap_lf; - HFONT hfont, old_hfont; - TEXTMETRICA tm_orig; - SIZE size_orig; - INT ret, i, width_orig, height_orig; - - hdc = GetDC(0); - - /* "System" has only 1 pixel size defined, otherwise the test breaks */ - ret = EnumFontFamiliesA(hdc, "System", font_enum_proc, (LPARAM)&bitmap_lf); - if (ret) - { - ReleaseDC(0, hdc); - trace("no bitmap fonts were found, skipping the test\n"); - return; - } - - trace("found bitmap font %s, height %ld\n", bitmap_lf.lfFaceName, bitmap_lf.lfHeight); - - height_orig = bitmap_lf.lfHeight; - hfont = create_font("bitmap", &bitmap_lf); - - old_hfont = SelectObject(hdc, hfont); - ok(GetTextMetricsA(hdc, &tm_orig), "GetTextMetricsA failed\n"); - ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); - ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); - SelectObject(hdc, old_hfont); - DeleteObject(hfont); - - /* test fractional scaling */ - for (i = 1; i < height_orig; i++) - { - hfont = create_font("fractional", &bitmap_lf); - test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 1, 1); - DeleteObject(hfont); - } - - /* test integer scaling 3x2 */ - bitmap_lf.lfHeight = height_orig * 2; - bitmap_lf.lfWidth *= 3; - hfont = create_font("3x2", &bitmap_lf); -todo_wine -{ - test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 2); -} - DeleteObject(hfont); - - /* test integer scaling 3x3 */ - bitmap_lf.lfHeight = height_orig * 3; - bitmap_lf.lfWidth = 0; - hfont = create_font("3x3", &bitmap_lf); - -todo_wine -{ - test_font_metrics(hdc, hfont, test_str, sizeof(test_str), &tm_orig, &size_orig, width_orig, 3, 3); -} - DeleteObject(hfont); - - ReleaseDC(0, hdc); -} - static void test_gdi_objects(void) { BYTE buff[256]; @@ -266,70 +98,177 @@ static void test_gdi_objects(void) ReleaseDC(NULL, hdc); } -static void test_GdiGetCharDimensions(void) +struct hgdiobj_event { HDC hdc; - TEXTMETRICW tm; - LONG ret; - SIZE size; - LONG avgwidth, height; - static const char szAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - typedef LONG (WINAPI *fnGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); - fnGdiGetCharDimensions GdiGetCharDimensions = (fnGdiGetCharDimensions)GetProcAddress(LoadLibrary("gdi32"), "GdiGetCharDimensions"); - if (!GdiGetCharDimensions) return; + HGDIOBJ hgdiobj1; + HGDIOBJ hgdiobj2; + HANDLE stop_event; + HANDLE ready_event; +}; - hdc = CreateCompatibleDC(NULL); +static DWORD WINAPI thread_proc(void *param) +{ + LOGPEN lp; + struct hgdiobj_event *hgdiobj_event = (struct hgdiobj_event *)param; - GetTextExtentPoint(hdc, szAlphabet, strlen(szAlphabet), &size); - avgwidth = ((size.cx / 26) + 1) / 2; + hgdiobj_event->hdc = CreateDC("display", NULL, NULL, NULL); + ok(hgdiobj_event->hdc != NULL, "CreateDC error %ld\n", GetLastError()); - ret = GdiGetCharDimensions(hdc, &tm, &height); - ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); - ok(height == tm.tmHeight, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", tm.tmHeight, height); + hgdiobj_event->hgdiobj1 = CreatePen(PS_DASHDOTDOT, 17, RGB(1, 2, 3)); + ok(hgdiobj_event->hgdiobj1 != 0, "Failed to create pen\n"); - ret = GdiGetCharDimensions(hdc, &tm, NULL); - ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + hgdiobj_event->hgdiobj2 = CreateRectRgn(0, 1, 12, 17); + ok(hgdiobj_event->hgdiobj2 != 0, "Failed to create pen\n"); - ret = GdiGetCharDimensions(hdc, NULL, NULL); - ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); + SetEvent(hgdiobj_event->ready_event); + ok(WaitForSingleObject(hgdiobj_event->stop_event, INFINITE) == WAIT_OBJECT_0, + "WaitForSingleObject error %ld\n", GetLastError()); - height = 0; - ret = GdiGetCharDimensions(hdc, NULL, &height); - ok(ret == avgwidth, "GdiGetCharDimensions should have returned width of %ld instead of %ld\n", avgwidth, ret); - ok(height == size.cy, "GdiGetCharDimensions should have set height to %ld instead of %ld\n", size.cy, height); + ok(!GetObject(hgdiobj_event->hgdiobj1, sizeof(lp), &lp), "GetObject should fail\n"); + + ok(!GetDeviceCaps(hgdiobj_event->hdc, TECHNOLOGY), "GetDeviceCaps(TECHNOLOGY) should fail\n"); + + return 0; +} + +static void test_thread_objects(void) +{ + LOGPEN lp; + DWORD tid, type; + HANDLE hthread; + struct hgdiobj_event hgdiobj_event; + INT ret; + + hgdiobj_event.stop_event = CreateEvent(NULL, 0, 0, NULL); + ok(hgdiobj_event.stop_event != NULL, "CreateEvent error %ld\n", GetLastError()); + hgdiobj_event.ready_event = CreateEvent(NULL, 0, 0, NULL); + ok(hgdiobj_event.ready_event != NULL, "CreateEvent error %ld\n", GetLastError()); + + hthread = CreateThread(NULL, 0, thread_proc, &hgdiobj_event, 0, &tid); + ok(hthread != NULL, "CreateThread error %ld\n", GetLastError()); + + ok(WaitForSingleObject(hgdiobj_event.ready_event, INFINITE) == WAIT_OBJECT_0, + "WaitForSingleObject error %ld\n", GetLastError()); + + ok(GetObject(hgdiobj_event.hgdiobj1, sizeof(lp), &lp) == sizeof(lp), + "GetObject error %ld\n", GetLastError()); + ok(lp.lopnStyle == PS_DASHDOTDOT, "wrong pen style %d\n", lp.lopnStyle); + ok(lp.lopnWidth.x == 17, "wrong pen width.y %ld\n", lp.lopnWidth.x); + ok(lp.lopnWidth.y == 0, "wrong pen width.y %ld\n", lp.lopnWidth.y); + ok(lp.lopnColor == RGB(1, 2, 3), "wrong pen width.y %08lx\n", lp.lopnColor); + + ret = GetDeviceCaps(hgdiobj_event.hdc, TECHNOLOGY); + ok(ret == DT_RASDISPLAY, "GetDeviceCaps(TECHNOLOGY) should return DT_RASDISPLAY not %d\n", ret); + + ok(DeleteObject(hgdiobj_event.hgdiobj1), "DeleteObject error %ld\n", GetLastError()); + ok(DeleteDC(hgdiobj_event.hdc), "DeleteDC error %ld\n", GetLastError()); + + type = GetObjectType(hgdiobj_event.hgdiobj2); + ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type); + + SetEvent(hgdiobj_event.stop_event); + ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, + "WaitForSingleObject error %ld\n", GetLastError()); + CloseHandle(hthread); + + type = GetObjectType(hgdiobj_event.hgdiobj2); + ok(type == OBJ_REGION, "GetObjectType returned %lu\n", type); + ok(DeleteObject(hgdiobj_event.hgdiobj2), "DeleteObject error %ld\n", GetLastError()); + + CloseHandle(hgdiobj_event.stop_event); + CloseHandle(hgdiobj_event.ready_event); +} + +static void test_GetCurrentObject(void) +{ + DWORD type; + HPEN hpen; + HBRUSH hbrush; + HPALETTE hpal; + HFONT hfont; + HBITMAP hbmp; + HRGN hrgn; + HDC hdc; + HCOLORSPACE hcs; + HGDIOBJ hobj; + LOGBRUSH lb; + LOGCOLORSPACEA lcs; + + hdc = CreateCompatibleDC(0); + assert(hdc != 0); + + type = GetObjectType(hdc); + ok(type == OBJ_MEMDC, "GetObjectType returned %lu\n", type); + + hpen = CreatePen(PS_SOLID, 10, RGB(10, 20, 30)); + assert(hpen != 0); + SelectObject(hdc, hpen); + hobj = GetCurrentObject(hdc, OBJ_PEN); + ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj); + hobj = GetCurrentObject(hdc, OBJ_EXTPEN); + ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj); + + hbrush = CreateSolidBrush(RGB(10, 20, 30)); + assert(hbrush != 0); + SelectObject(hdc, hbrush); + hobj = GetCurrentObject(hdc, OBJ_BRUSH); + ok(hobj == hbrush, "OBJ_BRUSH is wrong: %p\n", hobj); + + hpal = CreateHalftonePalette(hdc); + assert(hpal != 0); + SelectPalette(hdc, hpal, FALSE); + hobj = GetCurrentObject(hdc, OBJ_PAL); + ok(hobj == hpal, "OBJ_PAL is wrong: %p\n", hobj); + + hfont = CreateFontA(10, 5, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH, "MS Sans Serif"); + assert(hfont != 0); + SelectObject(hdc, hfont); + hobj = GetCurrentObject(hdc, OBJ_FONT); + ok(hobj == hfont, "OBJ_FONT is wrong: %p\n", hobj); + + hbmp = CreateBitmap(100, 100, 1, 1, NULL); + assert(hbmp != 0); + SelectObject(hdc, hbmp); + hobj = GetCurrentObject(hdc, OBJ_BITMAP); + ok(hobj == hbmp, "OBJ_BITMAP is wrong: %p\n", hobj); + + assert(GetObject(hbrush, sizeof(lb), &lb) == sizeof(lb)); + hpen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE | PS_JOIN_BEVEL, + 10, &lb, 0, NULL); + assert(hpen != 0); + SelectObject(hdc, hpen); + hobj = GetCurrentObject(hdc, OBJ_PEN); + ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj); + hobj = GetCurrentObject(hdc, OBJ_EXTPEN); + ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj); + + hcs = GetColorSpace(hdc); + if (hcs) + { + trace("current color space is not NULL\n"); + ok(GetLogColorSpaceA(hcs, &lcs, sizeof(lcs)), "GetLogColorSpace failed\n"); + hcs = CreateColorSpaceA(&lcs); + ok(hcs != 0, "CreateColorSpace failed\n"); + SelectObject(hdc, hcs); + hobj = GetCurrentObject(hdc, OBJ_COLORSPACE); + ok(hobj == hcs, "OBJ_COLORSPACE is wrong: %p\n", hobj); + } + + hrgn = CreateRectRgn(1, 1, 100, 100); + assert(hrgn != 0); + SelectObject(hdc, hrgn); + hobj = GetCurrentObject(hdc, OBJ_REGION); + ok(!hobj, "OBJ_REGION is wrong: %p\n", hobj); DeleteDC(hdc); } -static void test_text_extents(void) -{ - LOGFONTA lf; - TEXTMETRICA tm; - HDC hdc; - HFONT hfont; - SIZE sz; - - memset(&lf, 0, sizeof(lf)); - strcpy(lf.lfFaceName, "Arial"); - lf.lfHeight = 20; - - hfont = CreateFontIndirectA(&lf); - hdc = GetDC(0); - hfont = SelectObject(hdc, hfont); - GetTextMetricsA(hdc, &tm); - GetTextExtentPointA(hdc, "o", 1, &sz); - ok(sz.cy == tm.tmHeight, "cy %ld tmHeight %ld\n", sz.cy, tm.tmHeight); - - SelectObject(hdc, hfont); - DeleteObject(hfont); - ReleaseDC(NULL, hdc); -} - START_TEST(gdiobj) { - test_logfont(); - test_bitmap_font(); test_gdi_objects(); - test_GdiGetCharDimensions(); - test_text_extents(); + test_thread_objects(); + test_GetCurrentObject(); } diff --git a/reactos/regtests/winetests/gdi32/metafile.c b/reactos/regtests/winetests/gdi32/metafile.c index 17f0138c803..3610bf89265 100755 --- a/reactos/regtests/winetests/gdi32/metafile.c +++ b/reactos/regtests/winetests/gdi32/metafile.c @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -35,7 +35,28 @@ static BOOL emr_processed = FALSE; #define LINE_X 55.0f #define LINE_Y 15.0f -static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, +static INT (WINAPI * pGetRelAbs)(HDC, DWORD); +static INT (WINAPI * pSetRelAbs)(HDC, INT); + +#define GDI_GET_PROC(func) \ + p ## func = (void *)GetProcAddress(hGDI, #func); \ + if(!p ## func) \ + trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \ + +static void init_function_pointers(void) +{ + HMODULE hGDI; + + pGetRelAbs = NULL; + pSetRelAbs = NULL; + + hGDI = GetModuleHandleA("gdi32.dll"); + assert(hGDI); + GDI_GET_PROC(GetRelAbs); + GDI_GET_PROC(SetRelAbs); +} + +static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, const ENHMETARECORD *emr, int n_objs, LPARAM param) { static int n_record; @@ -55,6 +76,19 @@ static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, switch (emr->iType) { case EMR_HEADER: + ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc)); + ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08lx\n", GetBkColor(hdc)); + ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08lx\n", GetTextColor(hdc)); + ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc)); + ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc)); + ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc)); + ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc)); + + /* GetBkMode, GetRelAbs do not get reset to the default value */ + ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc)); + if(pSetRelAbs && pGetRelAbs) + ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0)); + n_record = 0; break; @@ -189,21 +223,147 @@ static void test_ExtTextOut(void) ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc); ok( ret, "PlayEnhMetaFile error %ld\n", GetLastError()); - ret = EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, &rc); + SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING ); + SetBkColor(hdcDisplay, RGB(0xff, 0, 0)); + SetTextColor(hdcDisplay, RGB(0, 0xff, 0)); + SetROP2(hdcDisplay, R2_NOT); + SetArcDirection(hdcDisplay, AD_CLOCKWISE); + SetPolyFillMode(hdcDisplay, WINDING); + SetStretchBltMode(hdcDisplay, HALFTONE); + + if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE); + SetBkMode(hdcDisplay, OPAQUE); + + ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc); ok( ret, "EnumEnhMetaFile error %ld\n", GetLastError()); + ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING), + "text align %08x\n", GetTextAlign(hdcDisplay)); + ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08lx\n", GetBkColor(hdcDisplay)); + ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08lx\n", GetTextColor(hdcDisplay)); + ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay)); + ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay)); + ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay)); + ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay)); + ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n"); - ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, NULL), + ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL), "A valid hdc has to require a valid rc\n"); - ok(EnumEnhMetaFile(NULL, hMetafile, emf_enum_proc, dx, NULL), + ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL), "A null hdc does not require a valid rc\n"); ret = DeleteEnhMetaFile(hMetafile); ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError()); ret = ReleaseDC(hwnd, hdcDisplay); ok( ret, "ReleaseDC error %ld\n", GetLastError()); + DestroyWindow(hwnd); +} + +static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, + const ENHMETARECORD *emr, int n_objs, LPARAM param) +{ + static int save_state; + static int restore_no; + + switch (emr->iType) + { + case EMR_HEADER: + save_state = 0; + restore_no = 0; + break; + + case EMR_SAVEDC: + save_state++; + break; + + case EMR_RESTOREDC: + { + EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr; + switch(++restore_no) + { + case 1: + ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative); + break; + + case 2: + ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative); + break; + case 3: + ok(restoredc->iRelative == -2, "third restore %ld\n", restoredc->iRelative); + break; + } + ok(restore_no <= 3, "restore_no %d\n", restore_no); + save_state += restoredc->iRelative; + break; + } + case EMR_EOF: + ok(save_state == 0, "EOF save_state %d\n", save_state); + break; + } + + + return 1; +} + +void test_SaveDC(void) +{ + HDC hdcMetafile, hdcDisplay; + HENHMETAFILE hMetafile; + HWND hwnd; + int ret; + static const RECT rc = { 0, 0, 100, 100 }; + + /* Win9x doesn't play EMFs on invisible windows */ + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 200, 200, 0, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError()); + + hdcDisplay = GetDC(hwnd); + ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError()); + + hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); + ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError()); + + /* Need to write something to the emf, otherwise Windows won't play it back */ + LineTo(hdcMetafile, 100, 100); + + ret = SaveDC(hdcMetafile); + ok(ret == 1, "ret = %d\n", ret); + + ret = SaveDC(hdcMetafile); + ok(ret == 2, "ret = %d\n", ret); + + ret = SaveDC(hdcMetafile); + ok(ret == 3, "ret = %d\n", ret); + + ret = RestoreDC(hdcMetafile, -1); + ok(ret, "ret = %d\n", ret); + + ret = SaveDC(hdcMetafile); + ok(ret == 3, "ret = %d\n", ret); + + ret = RestoreDC(hdcMetafile, 1); + ok(ret, "ret = %d\n", ret); + + ret = SaveDC(hdcMetafile); + ok(ret == 1, "ret = %d\n", ret); + + ret = SaveDC(hdcMetafile); + ok(ret == 2, "ret = %d\n", ret); + + hMetafile = CloseEnhMetaFile(hdcMetafile); + ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError()); + + ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc); + ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret); + + ret = DeleteEnhMetaFile(hMetafile); + ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError()); + ret = ReleaseDC(hwnd, hdcDisplay); + ok( ret, "ReleaseDC error %ld\n", GetLastError()); + DestroyWindow(hwnd); } /* Win-format metafile (mfdrv) tests */ @@ -211,7 +371,7 @@ static void test_ExtTextOut(void) /* with the nominal results. */ /* Maximum size of sample metafiles in bytes. */ -#define MF_BUFSIZE 256 +#define MF_BUFSIZE 512 /* 8x8 bitmap data for a pattern brush */ static const unsigned char SAMPLE_PATTERN_BRUSH[] = { @@ -262,22 +422,205 @@ static const unsigned char MF_PATTERN_BRUSH_BITS[] = { 0x00, 0x00 }; +static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] = +{ + 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a, + 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] = +{ + 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff, + 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, + 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, + 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41, + 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00 +}; + +static const unsigned char MF_LINETO_BITS[] = { + 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, + 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +static const unsigned char EMF_LINETO_BITS[] = { + 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, + 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, + 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, + 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, + 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80, + 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, + 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 +}; + +static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = { + 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, + 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, + 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, + 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, + 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80, + 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, + 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 +}; + +static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = { + 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, + 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00, + 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00, + 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, + 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80, + 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00 +}; + +/* For debugging or dumping the raw metafiles produced by + * new test functions. + */ +static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr, + INT nobj, LPARAM param) +{ + trace("hdc %p, mr->rdFunction %04x, mr->rdSize %lu, param %p\n", + hdc, mr->rdFunction, mr->rdSize, (void *)param); + return TRUE; +} + /* For debugging or dumping the raw metafiles produced by * new test functions. */ static void dump_mf_bits (const HMETAFILE mf, const char *desc) { - char buf[MF_BUFSIZE]; + BYTE buf[MF_BUFSIZE]; UINT mfsize, i; + if (!winetest_debug) return; + mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf); ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc); printf ("MetaFile %s has bits:\n{\n ", desc); for (i=0; i 0, "%s: GetEnhMetaFileBits failed\n", desc); + + printf("EMF %s has bits:\n{\n ", desc); + for (i = 0; i < mfsize; i++) + { + printf ("0x%02x", buf[i]); + if (i == mfsize-1) + printf ("\n"); + else if (i % 8 == 7) + printf (",\n "); + else + printf (", "); + } + printf ("};\n"); +} + +static void dump_emf_records(const HENHMETAFILE mf, const char *desc) +{ + BYTE *emf; + BYTE buf[MF_BUFSIZE]; + UINT mfsize, offset; + + if (!winetest_debug) return; + + mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); + ok (mfsize > 0, "%s: GetEnhMetaFileBits error %ld\n", desc, GetLastError()); + + printf("EMF %s has records:\n", desc); + + emf = buf; + offset = 0; + while(offset < mfsize) + { + EMR *emr = (EMR *)(emf + offset); + printf("emr->iType %ld, emr->nSize %lu\n", emr->iType, emr->nSize); + /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/ + offset += emr->nSize; + } +} + +/* Compare the EMF produced by a test function with the + * expected raw EMF data in "bits". + * Return value is 0 for a perfect match, + * -1 if lengths aren't equal, + * otherwise returns the number of non-matching bytes. + */ +static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits, + UINT bsize, const char *desc, BOOL todo) +{ + unsigned char buf[MF_BUFSIZE]; + UINT mfsize, i; + int diff; + + mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf); + ok (mfsize > 0, "%s: GetEnhMetaFileBits error %ld\n", desc, GetLastError()); + + if (mfsize < MF_BUFSIZE) + { + if (mfsize != bsize && todo) + { + todo_wine + ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); + } + else + ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize); + } + else + ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n", + desc, mfsize, bsize); + + if (mfsize != bsize) + return -1; + + diff = 0; + for (i = 0; i < bsize; i++) + { + if (buf[i] != bits[i]) + diff++; + } + if (diff != 0 && todo) + { + todo_wine + { + ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n", + desc, mfsize, bsize, diff); + } + return diff; + } + else + { + ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n", + desc, mfsize, bsize, diff); + + return diff; + } +} + /* Test a blank metafile. May be used as a template for new tests. */ static void test_mf_Blank(void) @@ -333,6 +820,7 @@ static void test_mf_Blank(void) HMETAFILE hMetafile; INT caps; BOOL ret; + INT type; hdcMetafile = CreateMetaFileA(NULL); ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError()); @@ -345,16 +833,155 @@ static void test_mf_Blank(void) hMetafile = CloseMetaFile(hdcMetafile); ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError()); + type = GetObjectType(hMetafile); + ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type); ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n"); if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0) - dump_mf_bits (hMetafile, "mf_Blank"); + { + dump_mf_bits(hMetafile, "mf_Blank"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } ret = DeleteMetaFile(hMetafile); ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError()); } +static void test_CopyMetaFile(void) +{ + HDC hdcMetafile; + HMETAFILE hMetafile, hmf_copy; + BOOL ret; + char temp_path[MAX_PATH]; + char mf_name[MAX_PATH]; + INT type; + + hdcMetafile = CreateMetaFileA(NULL); + ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError()); + trace("hdcMetafile %p\n", hdcMetafile); + + hMetafile = CloseMetaFile(hdcMetafile); + ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError()); + type = GetObjectType(hMetafile); + ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type); + + if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), + "mf_blank") != 0) + { + dump_mf_bits(hMetafile, "mf_Blank"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } + + GetTempPathA(MAX_PATH, temp_path); + GetTempFileNameA(temp_path, "wmf", 0, mf_name); + + hmf_copy = CopyMetaFileA(hMetafile, mf_name); + ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError()); + + type = GetObjectType(hmf_copy); + ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type); + + ret = DeleteMetaFile(hMetafile); + ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError()); + + if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0) + { + dump_mf_bits(hMetafile, "mf_Blank"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } + + ret = DeleteMetaFile(hmf_copy); + ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError()); + + DeleteFileA(mf_name); +} + +static void test_SetMetaFileBits(void) +{ + HMETAFILE hmf; + INT type; + BOOL ret; + BYTE buf[256]; + METAHEADER *mh; + + hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS); + ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError()); + type = GetObjectType(hmf); + ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type); + + if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) + { + dump_mf_bits(hmf, "mf_Graphics"); + EnumMetaFile(0, hmf, mf_enum_proc, 0); + } + + ret = DeleteMetaFile(hmf); + ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError()); + + /* NULL data crashes XP SP1 */ + /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/ + + /* Now with not zero size */ + SetLastError(0xdeadbeef); + hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS); + ok(!hmf, "SetMetaFileBitsEx should fail\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError()); + + /* Now with not even size */ + SetLastError(0xdeadbeef); + hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS); + ok(!hmf, "SetMetaFileBitsEx should fail\n"); + ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError()); + + /* Now with zeroed out or faked some header fields */ + assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS)); + memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); + mh = (METAHEADER *)buf; + /* corruption of any of the below fields leads to a failure */ + mh->mtType = 0; + mh->mtVersion = 0; + mh->mtHeaderSize = 0; + SetLastError(0xdeadbeef); + hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + ok(!hmf, "SetMetaFileBitsEx should fail\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError()); + + /* Now with corrupted mtSize field */ + memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); + mh = (METAHEADER *)buf; + /* corruption of mtSize doesn't lead to a failure */ + mh->mtSize *= 2; + hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError()); + + if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) + { + dump_mf_bits(hmf, "mf_Graphics"); + EnumMetaFile(0, hmf, mf_enum_proc, 0); + } + + ret = DeleteMetaFile(hmf); + ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError()); + + /* Now with zeroed out mtSize field */ + memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS)); + mh = (METAHEADER *)buf; + /* zeroing mtSize doesn't lead to a failure */ + mh->mtSize = 0; + hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf); + ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError()); + + if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) + { + dump_mf_bits(hmf, "mf_Graphics"); + EnumMetaFile(0, hmf, mf_enum_proc, 0); + } + + ret = DeleteMetaFile(hmf); + ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError()); +} + /* Simple APIs from mfdrv/graphics.c */ @@ -393,7 +1020,10 @@ static void test_mf_Graphics(void) if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0) - dump_mf_bits (hMetafile, "mf_Graphics"); + { + dump_mf_bits(hMetafile, "mf_Graphics"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } ret = DeleteMetaFile(hMetafile); ok( ret, "DeleteMetaFile(%p) error %ld\n", @@ -412,8 +1042,8 @@ static void test_mf_PatternBrush(void) orig_lb->lbStyle = BS_PATTERN; orig_lb->lbColor = RGB(0, 0, 0); - orig_lb->lbHatch = (INT) CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH); - ok((HBITMAP *)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError()); + orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH); + ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError()); hBrush = CreateBrushIndirect (orig_lb); ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError()); @@ -431,18 +1061,103 @@ static void test_mf_PatternBrush(void) if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS), "mf_Pattern_Brush") != 0) - dump_mf_bits (hMetafile, "mf_Pattern_Brush"); + { + dump_mf_bits(hMetafile, "mf_Pattern_Brush"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } ret = DeleteMetaFile(hMetafile); ok( ret, "DeleteMetaFile error %ld\n", GetLastError()); ret = DeleteObject(hBrush); ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError()); - ret = DeleteObject((HBITMAP *)orig_lb->lbHatch); + ret = DeleteObject((HBITMAP)orig_lb->lbHatch); ok( ret, "DeleteObject(HBITMAP) error %ld\n", GetLastError()); HeapFree (GetProcessHeap(), 0, orig_lb); } +static void test_mf_ExtTextOut_on_path(void) +{ + HDC hdcMetafile; + HMETAFILE hMetafile; + BOOL ret; + static const INT dx[4] = { 3, 5, 8, 12 }; + + hdcMetafile = CreateMetaFileA(NULL); + ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError()); + trace("hdcMetafile %p\n", hdcMetafile); + + ret = BeginPath(hdcMetafile); + ok(!ret, "BeginPath on metafile DC should fail\n"); + + ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx); + ok(ret, "ExtTextOut error %ld\n", GetLastError()); + + ret = EndPath(hdcMetafile); + ok(!ret, "EndPath on metafile DC should fail\n"); + + hMetafile = CloseMetaFile(hdcMetafile); + ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError()); + + if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS), + "mf_TextOut_on_path") != 0) + { + dump_mf_bits(hMetafile, "mf_TextOut_on_path"); + EnumMetaFile(0, hMetafile, mf_enum_proc, 0); + } + + ret = DeleteMetaFile(hMetafile); + ok(ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError()); +} + +static void test_emf_ExtTextOut_on_path(void) +{ + HWND hwnd; + HDC hdcDisplay, hdcMetafile; + HENHMETAFILE hMetafile; + BOOL ret; + static const INT dx[4] = { 3, 5, 8, 12 }; + + /* Win9x doesn't play EMFs on invisible windows */ + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 200, 200, 0, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError()); + + hdcDisplay = GetDC(hwnd); + ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError()); + + hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL); + ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError()); + + ret = BeginPath(hdcMetafile); + ok(ret, "BeginPath error %ld\n", GetLastError()); + + ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx); + ok(ret, "ExtTextOut error %ld\n", GetLastError()); + + ret = EndPath(hdcMetafile); + ok(ret, "EndPath error %ld\n", GetLastError()); + + hMetafile = CloseEnhMetaFile(hdcMetafile); + ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError()); + + /* this doesn't succeed yet: EMF has correct size, all EMF records + * are there, but their contents don't match for different reasons. + */ + if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS), + "emf_TextOut_on_path", TRUE) != 0) + { + dump_emf_bits(hMetafile, "emf_TextOut_on_path"); + dump_emf_records(hMetafile, "emf_TextOut_on_path"); + } + + ret = DeleteEnhMetaFile(hMetafile); + ok(ret, "DeleteEnhMetaFile error %ld\n", GetLastError()); + ret = ReleaseDC(hwnd, hdcDisplay); + ok(ret, "ReleaseDC error %ld\n", GetLastError()); + DestroyWindow(hwnd); +} + static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData) { LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData; @@ -451,7 +1166,10 @@ static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETAREC * until a record is played which actually outputs something */ PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj); LPtoDP(hdc, mapping, 2); - trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y); + trace("Meta record: iType %ld, nSize %ld, (%ld,%ld)-(%ld,%ld)\n", + lpEMFR->iType, lpEMFR->nSize, + mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y); + if (lpEMFR->iType == EMR_LINETO) { INT x0, y0, x1, y1; @@ -493,6 +1211,13 @@ static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp) ok(ret, "LineTo failed with error %ld\n", GetLastError()); hmf = CloseMetaFile(hdcMf); ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError()); + + if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0) + { + dump_mf_bits(hmf, "mf_LineTo"); + EnumMetaFile(0, hmf, mf_enum_proc, 0); + } + size = GetMetaFileBitsEx(hmf, 0, NULL); ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError()); pBits = HeapAlloc(GetProcessHeap(), 0, size); @@ -514,7 +1239,16 @@ static void test_mf_conversions(void) mfp.yExt = 100; mfp.hMF = NULL; hemf = create_converted_emf(&mfp); + + if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS), + "emf_LineTo MM_ANISOTROPIC", TRUE) != 0) + { + dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC"); + dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC"); + } + EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect); + DeleteEnhMetaFile(hemf); DeleteDC(hdcOffscreen); } @@ -530,7 +1264,16 @@ static void test_mf_conversions(void) mfp.yExt = 0; mfp.hMF = NULL; hemf = create_converted_emf(&mfp); + + if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS), + "emf_LineTo MM_TEXT", TRUE) != 0) + { + dump_emf_bits(hemf, "emf_LineTo MM_TEXT"); + dump_emf_records(hemf, "emf_LineTo MM_TEXT"); + } + EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect); + DeleteEnhMetaFile(hemf); DeleteDC(hdcOffscreen); } @@ -541,12 +1284,232 @@ static void test_mf_conversions(void) HENHMETAFILE hemf; RECT rect = { 0, 0, 100, 100 }; hemf = create_converted_emf(NULL); + + if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS), + "emf_LineTo NULL", TRUE) != 0) + { + dump_emf_bits(hemf, "emf_LineTo NULL"); + dump_emf_records(hemf, "emf_LineTo NULL"); + } + EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect); + DeleteEnhMetaFile(hemf); DeleteDC(hdcOffscreen); } } +static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull, + LONG mm, LONG xExt, LONG yExt, + RECTL * rclBounds, RECTL * rclFrame) +{ + METAFILEPICT mfp; + METAFILEPICT * mfpPtr = NULL; + HENHMETAFILE emf; + ENHMETAHEADER header; + UINT res; + + if (!mfpIsNull) + { + mfp.mm = mm; + mfp.xExt = xExt; + mfp.yExt = yExt; + mfpPtr = &mfp; + } + + emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr); + ok(emf != NULL, "SetWinMetaFileBits failed\n"); + if (!emf) return FALSE; + res = GetEnhMetaFileHeader(emf, sizeof(header), &header); + ok(res != 0, "GetEnhMetaHeader failed\n"); + DeleteEnhMetaFile(emf); + if (!res) return FALSE; + + *rclBounds = header.rclBounds; + *rclFrame = header.rclFrame; + return TRUE; +} + +static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull, + LONG mm, LONG xExt, LONG yExt, + RECTL * rclBoundsExpected, RECTL * rclFrameExpected) +{ + RECTL rclBounds, rclFrame; + + if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame)) + { + const char * msg; + char buf[64]; + + if (mfpIsNull) + { + msg = "mfp == NULL"; + } + else + { + const char * mm_str; + switch (mm) + { + case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break; + case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break; + default: mm_str = "Unexpected"; + } + sprintf(buf, "mm=%s, xExt=%ld, yExt=%ld", mm_str, xExt, yExt); + msg = buf; + } + + ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %ld, got %ld (%s)\n", rclBoundsExpected->left, rclBounds.left, msg); + ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %ld, got %ld (%s)\n", rclBoundsExpected->top, rclBounds.top, msg); + ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %ld, got %ld (%s)\n", rclBoundsExpected->right, rclBounds.right, msg); + ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %ld, got %ld (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg); + ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %ld, got %ld (%s)\n", rclFrameExpected->left, rclFrame.left, msg); + ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %ld, got %ld (%s)\n", rclFrameExpected->top, rclFrame.top, msg); + ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %ld, got %ld (%s)\n", rclFrameExpected->right, rclFrame.right, msg); + ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %ld, got %ld (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg); + } +} + +static void test_SetWinMetaFileBits(void) +{ + HMETAFILE wmf; + HDC wmfDC; + BYTE * buffer; + UINT buffer_size; + RECT rect; + UINT res; + RECTL rclBoundsAnisotropic, rclFrameAnisotropic; + RECTL rclBoundsIsotropic, rclFrameIsotropic; + RECTL rclBounds, rclFrame; + HDC dc; + LONG diffx, diffy; + + wmfDC = CreateMetaFile(NULL); + ok(wmfDC != NULL, "CreateMetaFile failed\n"); + if (!wmfDC) return; + + SetWindowExtEx(wmfDC, 100, 100, NULL); + rect.left = rect.top = 0; + rect.right = rect.bottom = 50; + FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH)); + wmf = CloseMetaFile(wmfDC); + ok(wmf != NULL, "Metafile creation failed\n"); + if (!wmf) return; + + buffer_size = GetMetaFileBitsEx(wmf, 0, NULL); + ok(buffer_size != 0, "GetMetaFileBitsEx failed\n"); + if (buffer_size == 0) + { + DeleteMetaFile(wmf); + return; + } + + buffer = (BYTE *)HeapAlloc(GetProcessHeap(), 0, buffer_size); + ok(buffer != NULL, "HeapAlloc failed\n"); + if (!buffer) + { + DeleteMetaFile(wmf); + return; + } + + res = GetMetaFileBitsEx(wmf, buffer_size, buffer); + ok(res == buffer_size, "GetMetaFileBitsEx failed\n"); + DeleteMetaFile(wmf); + if (res != buffer_size) + { + HeapFree(GetProcessHeap(), 0, buffer); + return; + } + + /* Get the reference bounds and frame */ + getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); + getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic); + + ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 && + rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0, + "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n"); + + ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n"); + ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n"); + diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom; + if (diffx < 0) diffx = -diffx; + ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n"); + + dc = CreateCompatibleDC(NULL); + todo_wine + { + ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 && + rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1, + "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n", + GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom); + } + + /* Allow 1 mm difference (rounding errors) */ + diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2; + diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2; + if (diffx < 0) diffx = -diffx; + if (diffy < 0) diffy = -diffy; + todo_wine + { + ok(diffx <= 1 && diffy <= 1, + "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n", + GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100); + } + DeleteDC(dc); + + /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */ + checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); + + /* If xExt or yExt is zero or negative, the whole device surface is used */ + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic); + + /* MSDN says that negative xExt and yExt values specify a ratio. + Check that this is wrong and the whole device surface is used */ + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic); + checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic); + + /* Ordinary conversions */ + + if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame)) + { + ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000, + "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n"); + ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom, + "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n"); + } + + if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame)) + { + ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000, + "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n"); + ok(rclBounds.left == 0 && rclBounds.top == 0, + "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n"); + + /* Wine has a rounding error */ + diffx = rclBounds.right - rclBounds.bottom; + if (diffx < 0) diffx = -diffx; + ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n"); + } + + if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame)) + { + ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000, + "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n"); + } + + HeapFree(GetProcessHeap(), 0, buffer); +} + static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC); static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC); static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC); @@ -597,16 +1560,24 @@ static void test_gdiis(void) START_TEST(metafile) { + init_function_pointers(); + /* For enhanced metafiles (enhmfdrv) */ test_ExtTextOut(); + test_SaveDC(); /* For win-format metafiles (mfdrv) */ test_mf_Blank(); test_mf_Graphics(); test_mf_PatternBrush(); + test_CopyMetaFile(); + test_SetMetaFileBits(); + test_mf_ExtTextOut_on_path(); + test_emf_ExtTextOut_on_path(); /* For metafile conversions */ test_mf_conversions(); + test_SetWinMetaFileBits(); test_gdiis(); } diff --git a/reactos/regtests/winetests/gdi32/testlist.c b/reactos/regtests/winetests/gdi32/testlist.c index cf5319b1b99..875e34863a8 100644 --- a/reactos/regtests/winetests/gdi32/testlist.c +++ b/reactos/regtests/winetests/gdi32/testlist.c @@ -22,9 +22,9 @@ const struct test winetest_testlist[] = { { "bitmap", func_bitmap }, { "brush", func_brush }, -// { "clipping", func_clipping }, -// { "dc", func_dc }, -// { "font", func_font }, + { "clipping", func_clipping }, + { "dc", func_dc }, + { "font", func_font }, { "gdiobj", func_gdiobj }, // { "generated", func_generated }, // { "mapping", func_mapping }, From 7c4cca987087814ed8f68725e56edf896ae12879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 10:39:43 +0000 Subject: [PATCH 40/54] Add a filter command in KDBG, which is a wrapper around NtSetDebugFilterState/NtSetDebugFilterState. svn path=/trunk/; revision=24250 --- reactos/ntoskrnl/kdbg/kdb_cli.c | 80 ++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/reactos/ntoskrnl/kdbg/kdb_cli.c b/reactos/ntoskrnl/kdbg/kdb_cli.c index 2eaf2647da7..de087a15813 100644 --- a/reactos/ntoskrnl/kdbg/kdb_cli.c +++ b/reactos/ntoskrnl/kdbg/kdb_cli.c @@ -16,8 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id$ - * +/* * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/kdb_cli.c * PURPOSE: Kernel debugger command line interface @@ -78,6 +77,7 @@ STATIC BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]); STATIC BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]); STATIC BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]); +STATIC BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]); STATIC BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]); STATIC BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]); @@ -146,6 +146,7 @@ STATIC CONST struct /* Others */ { NULL, NULL, "Others", NULL }, { "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck }, + { "filter", "filter [componentid] [error|warning|trace|info|level] [on|off]", "Enable/disable debug channels", KdbpCmdFilter }, { "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet }, { "help", "help", "Display help screen.", KdbpCmdHelp } }; @@ -244,6 +245,81 @@ KdbpCmdEvalExpression(ULONG Argc, PCHAR Argv[]) return TRUE; } +/*!\brief Display list of active debug channels + */ +STATIC BOOLEAN +KdbpCmdFilter(ULONG Argc, PCHAR Argv[]) +{ + ULONG ComponentId, Level; + BOOLEAN State; + PCHAR pend; + + if (Argc < 2) + { + KdbpPrint("filter: component id argument required!\n"); + return TRUE; + } + ComponentId = strtoul(Argv[1], &pend, 0); + if (Argv[1] == pend) + { + KdbpPrint("filter: '%s' is not a valid component id!\n", Argv[1]); + return TRUE; + } + + if (Argc < 3) + { + KdbpPrint("filter: level argument required!\n"); + return TRUE; + } + if (_stricmp(Argv[2], "error") == 0) + Level = DPFLTR_ERROR_LEVEL; + else if (_stricmp(Argv[2], "warning") == 0) + Level = DPFLTR_WARNING_LEVEL; + else if (_stricmp(Argv[2], "trace") == 0) + Level = DPFLTR_TRACE_LEVEL; + else if (_stricmp(Argv[2], "info") == 0) + Level = DPFLTR_INFO_LEVEL; + else + { + Level = strtoul(Argv[2], &pend, 0); + if (Argv[2] == pend) + { + KdbpPrint("filter: '%s' is not a valid level!\n", Argv[2]); + return TRUE; + } + } + if (Level < 31) + { + /* Interpret it as a bit shift */ + Level = 1 << Level; + } + + if (Argc < 4) + { + /* Display the state of the filter */ + if (NtQueryDebugFilterState(ComponentId, Level)) + KdbpPrint("Debug messages are enabled.\n"); + else + KdbpPrint("Debug messages are disabled.\n"); + return TRUE; + } + else + { + /* Set the filter state */ + if (_stricmp(Argv[3], "on") == 0) + State = TRUE; + else if (_stricmp(Argv[3], "off") == 0) + State = FALSE; + else + { + KdbpPrint("filter: '%s' is not a valid state!\n", Argv[3]); + return TRUE; + } + + return NT_SUCCESS(NtSetDebugFilterState(ComponentId, Level, State)); + } +} + /*!\brief Disassembles 10 instructions at eip or given address or * displays 16 dwords from memory at given address. */ From e84a6d47b1d30188d77748fc339c28fcf84e61d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 11:08:27 +0000 Subject: [PATCH 41/54] [FORMATTING] Replace spaces by tabs svn path=/trunk/; revision=24251 --- reactos/base/system/format/format.c | 79 ++++++++++++++--------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/reactos/base/system/format/format.c b/reactos/base/system/format/format.c index 1bdf1f25778..ea4de4d6e84 100755 --- a/reactos/base/system/format/format.c +++ b/reactos/base/system/format/format.c @@ -15,22 +15,22 @@ BOOL Error = FALSE; // switches BOOL QuickFormat = FALSE; -DWORD ClusterSize = 0; +DWORD ClusterSize = 0; BOOL CompressDrive = FALSE; -BOOL GotALabel = FALSE; -LPTSTR Label = _T(""); -LPTSTR Drive = NULL; -LPTSTR Format = _T("FAT"); +BOOL GotALabel = FALSE; +LPTSTR Label = _T(""); +LPTSTR Drive = NULL; +LPTSTR Format = _T("FAT"); -TCHAR RootDirectory[MAX_PATH]; -TCHAR LabelString[12]; +TCHAR RootDirectory[MAX_PATH]; +TCHAR LabelString[12]; // // Size array // typedef struct { - TCHAR SizeString[16]; - DWORD ClusterSize; + TCHAR SizeString[16]; + DWORD ClusterSize; } SIZEDEFINITION, *PSIZEDEFINITION; SIZEDEFINITION LegalSizes[] = { @@ -57,7 +57,7 @@ SIZEDEFINITION LegalSizes[] = { //---------------------------------------------------------------------- static VOID PrintWin32Error( LPTSTR Message, DWORD ErrorCode ) { - LPTSTR lpMsgBuf; + LPTSTR lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrorCode, @@ -169,9 +169,10 @@ static int ParseCommandLine( int argc, TCHAR *argv[] ) // //---------------------------------------------------------------------- BOOLEAN STDCALL -FormatExCallback (CALLBACKCOMMAND Command, - ULONG Modifier, - PVOID Argument) +FormatExCallback ( + CALLBACKCOMMAND Command, + ULONG Modifier, + PVOID Argument) { PDWORD percent; PTEXTOUTPUT output; @@ -185,8 +186,8 @@ FormatExCallback (CALLBACKCOMMAND Command, case PROGRESS: percent = (PDWORD) Argument; - LoadString( GetModuleHandle(NULL), STRING_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, *percent); + LoadString( GetModuleHandle(NULL), STRING_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + _tprintf(szMsg, *percent); break; case OUTPUT: @@ -199,7 +200,7 @@ FormatExCallback (CALLBACKCOMMAND Command, if( *status == FALSE ) { LoadString( GetModuleHandle(NULL), STRING_FORMAT_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); Error = TRUE; } break; @@ -217,7 +218,7 @@ FormatExCallback (CALLBACKCOMMAND Command, case UNKNOWND: case STRUCTUREPROGRESS: LoadString( GetModuleHandle(NULL), STRING_NO_SUPPORT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); return FALSE; } return TRUE; @@ -272,7 +273,7 @@ _tmain(int argc, TCHAR *argv[]) DWORD flags, maxComponent; ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes; #ifndef UNICODE - WCHAR RootDirectoryW[MAX_PATH], FormatW[MAX_PATH], LabelW[MAX_PATH]; + WCHAR RootDirectoryW[MAX_PATH], FormatW[MAX_PATH], LabelW[MAX_PATH]; #endif TCHAR szMsg[RC_STRING_MAX_SIZE]; @@ -280,9 +281,8 @@ _tmain(int argc, TCHAR *argv[]) // Get function pointers // if( !LoadFMIFSEntryPoints()) { - LoadString( GetModuleHandle(NULL), STRING_FMIFS_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); return -1; } @@ -292,7 +292,7 @@ _tmain(int argc, TCHAR *argv[]) if( (badArg = ParseCommandLine( argc, argv ))) { LoadString( GetModuleHandle(NULL), STRING_UNKNOW_ARG, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, argv[badArg] ); + _tprintf(szMsg, argv[badArg] ); Usage(argv[0]); return -1; @@ -304,7 +304,7 @@ _tmain(int argc, TCHAR *argv[]) if( !Drive ) { LoadString( GetModuleHandle(NULL), STRING_DRIVE_PARM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); Usage( argv[0] ); return -1; @@ -321,14 +321,14 @@ _tmain(int argc, TCHAR *argv[]) driveType = GetDriveType( RootDirectory ); if( driveType == 0 ) { - LoadString( GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + LoadString( GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error( szMsg, GetLastError()); return -1; } if( driveType != DRIVE_FIXED ) { LoadString( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, RootDirectory[0] ); + _tprintf(szMsg, RootDirectory[0] ); _fgetts( input, sizeof(input)/2, stdin ); media = FMIFS_FLOPPY; @@ -357,7 +357,7 @@ _tmain(int argc, TCHAR *argv[]) return -1; } LoadString( GetModuleHandle(NULL), STRING_FILESYSTEM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, fileSystem ); + _tprintf(szMsg, fileSystem ); // // Make sure they want to do this @@ -369,7 +369,7 @@ _tmain(int argc, TCHAR *argv[]) while(1 ) { LoadString( GetModuleHandle(NULL), STRING_LABEL_NAME_EDIT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, RootDirectory[0] ); + _tprintf(szMsg, RootDirectory[0] ); _fgetts( input, sizeof(input)/2, stdin ); input[ _tcslen( input ) - 1] = 0; @@ -378,21 +378,20 @@ _tmain(int argc, TCHAR *argv[]) break; } LoadString( GetModuleHandle(NULL), STRING_ERROR_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); } } while( 1 ) { LoadString( GetModuleHandle(NULL), STRING_YN_FORMAT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, RootDirectory[0] ); + _tprintf(szMsg, RootDirectory[0] ); - LoadString( GetModuleHandle(NULL), STRING_YES_NO_FAQ, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - - if( _strnicmp(&input[0],&szMsg[0],1)) break; - if( _strnicmp(&input[0],&szMsg[1],1) ) { + if(_strnicmp(&input[0],&szMsg[0],1)) break; + + if(_strnicmp(&input[0],&szMsg[1],1) ) { _tprintf(_T("\n")); return 0; @@ -417,7 +416,7 @@ _tmain(int argc, TCHAR *argv[]) _tprintf(_T("%s %.1fM\n"),szMsg, ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0)); } - } else { + } else { LoadString( GetModuleHandle(NULL), STRING_FAST_FMT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) { @@ -430,7 +429,7 @@ _tmain(int argc, TCHAR *argv[]) ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0)); } LoadString( GetModuleHandle(NULL), STRING_CREATE_FSYS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); } // @@ -448,7 +447,7 @@ _tmain(int argc, TCHAR *argv[]) #endif if( Error ) return -1; LoadString( GetModuleHandle(NULL), STRING_FMT_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); // // Enable compression if desired @@ -463,7 +462,7 @@ _tmain(int argc, TCHAR *argv[]) #endif LoadString( GetModuleHandle(NULL), STRING_VOL_COMPRESS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); } } @@ -473,7 +472,7 @@ _tmain(int argc, TCHAR *argv[]) if( !GotALabel ) { LoadString( GetModuleHandle(NULL), STRING_ENTER_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg); + _tprintf(szMsg); _fgetts( input, sizeof(LabelString)/2, stdin ); input[ _tcslen(input)-1] = 0; @@ -502,14 +501,14 @@ _tmain(int argc, TCHAR *argv[]) &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes )) { - + LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); PrintWin32Error(szMsg, GetLastError()); return -1; } LoadString( GetModuleHandle(NULL), STRING_FREE_SPACE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, totalNumberOfBytes.QuadPart, totalNumberOfFreeBytes.QuadPart ); + _tprintf(szMsg, totalNumberOfBytes.QuadPart, totalNumberOfFreeBytes.QuadPart ); // // Get the drive's serial number @@ -524,7 +523,7 @@ _tmain(int argc, TCHAR *argv[]) return -1; } LoadString( GetModuleHandle(NULL), STRING_SERIAL_NUMBER, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, (unsigned int)(serialNumber >> 16), + _tprintf(szMsg, (unsigned int)(serialNumber >> 16), (unsigned int)(serialNumber & 0xFFFF) ); return 0; From c492ac0ccc35047a23326463722990aba696fcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 11:55:58 +0000 Subject: [PATCH 42/54] Implement QueryAvailableFileSystemFormat and SetLabel in fmifs.dll Fix a few prototypes svn path=/trunk/; revision=24252 --- reactos/dll/win32/fmifs/fmifs.def | 6 +- reactos/dll/win32/fmifs/fmifs.rbuild | 2 +- reactos/dll/win32/fmifs/label.c | 18 ----- reactos/dll/win32/fmifs/media.c | 9 ++- reactos/dll/win32/fmifs/precomp.h | 92 +++++++++++----------- reactos/dll/win32/fmifs/query.c | 44 +++++++++++ reactos/include/reactos/libs/fmifs/fmifs.h | 33 +++++--- 7 files changed, 124 insertions(+), 80 deletions(-) delete mode 100644 reactos/dll/win32/fmifs/label.c create mode 100644 reactos/dll/win32/fmifs/query.c diff --git a/reactos/dll/win32/fmifs/fmifs.def b/reactos/dll/win32/fmifs/fmifs.def index 2391f1f56fb..e11b477941c 100644 --- a/reactos/dll/win32/fmifs/fmifs.def +++ b/reactos/dll/win32/fmifs/fmifs.def @@ -22,10 +22,10 @@ Format@0 FormatEx@28 ;FormatEx2 InitializeFmIfs@12 -;QueryAvailableFileSystemFormat +QueryAvailableFileSystemFormat@20 ;QueryDeviceInformation ;QueryDeviceInformationByHandle ;QueryFileSystemName ;QueryLatestFileSystemVersion -QuerySupportedMedia@0 -SetLabel@0 +QuerySupportedMedia@16 +SetLabel@8=KERNEL32.SetVolumeLabelW diff --git a/reactos/dll/win32/fmifs/fmifs.rbuild b/reactos/dll/win32/fmifs/fmifs.rbuild index d4498926012..6934bd39175 100644 --- a/reactos/dll/win32/fmifs/fmifs.rbuild +++ b/reactos/dll/win32/fmifs/fmifs.rbuild @@ -12,8 +12,8 @@ extend.c format.c init.c - label.c media.c + query.c fmifs.rc precomp.h diff --git a/reactos/dll/win32/fmifs/label.c b/reactos/dll/win32/fmifs/label.c deleted file mode 100644 index e4b0ee48e10..00000000000 --- a/reactos/dll/win32/fmifs/label.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: File Management IFS Utility functions - * FILE: reactos/dll/win32/fmifs/label.c - * PURPOSE: Set volume label - * - * PROGRAMMERS: (none) - */ - -#include "precomp.h" - -/* FMIFS.10 */ -VOID NTAPI -SetLabel (VOID) -{ -} - -/* EOF */ diff --git a/reactos/dll/win32/fmifs/media.c b/reactos/dll/win32/fmifs/media.c index 3837c99b2ff..0cdb32da7ba 100644 --- a/reactos/dll/win32/fmifs/media.c +++ b/reactos/dll/win32/fmifs/media.c @@ -10,9 +10,14 @@ #include "precomp.h" /* FMIFS.9 */ -VOID NTAPI -QuerySupportedMedia(VOID) +BOOL NTAPI +QuerySupportedMedia( + IN PWCHAR DriveRoot, + OUT FMIFS_MEDIA_FLAG *CurrentMedia OPTIONAL, + IN ULONG Unknown3, + OUT PULONG Unknown4) { + return FALSE; } /* EOF */ diff --git a/reactos/dll/win32/fmifs/precomp.h b/reactos/dll/win32/fmifs/precomp.h index 4e8d37713aa..647ce1c04f8 100644 --- a/reactos/dll/win32/fmifs/precomp.h +++ b/reactos/dll/win32/fmifs/precomp.h @@ -1,46 +1,46 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: File Management IFS Utility functions - * FILE: reactos/dll/win32/fmifs/precomp.h - * PURPOSE: Win32 FMIFS API Library Header - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - * Hervé Poussineau (hpoussin@reactos.org) - */ - -/* INCLUDES ******************************************************************/ - -#define WIN32_NO_STATUS -#define NTOS_MODE_USER -#define UNICODE -#define _UNICODE - -/* PSDK/NDK Headers */ -#include -#include - -/* FMIFS Public Header */ -#include - -/* VFATLIB Public Header */ -#include - -extern LIST_ENTRY ProviderListHead; - -typedef struct _IFS_PROVIDER -{ - LIST_ENTRY ListEntry; - - CHKDSKEX ChkdskEx; - PVOID Extend; - FORMATEX FormatEx; - - WCHAR Name[1]; -} IFS_PROVIDER, *PIFS_PROVIDER; - -/* init.c */ -PIFS_PROVIDER -GetProvider( - IN PWCHAR FileSytem); - -/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: File Management IFS Utility functions + * FILE: reactos/dll/win32/fmifs/precomp.h + * PURPOSE: Win32 FMIFS API Library Header + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Hervé Poussineau (hpoussin@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#define WIN32_NO_STATUS +#define NTOS_MODE_USER +#define UNICODE +#define _UNICODE + +/* PSDK/NDK Headers */ +#include +#include + +/* FMIFS Public Header */ +#include + +/* VFATLIB Public Header */ +#include + +extern LIST_ENTRY ProviderListHead; + +typedef struct _IFS_PROVIDER +{ + LIST_ENTRY ListEntry; + + CHKDSKEX ChkdskEx; + PVOID Extend; + FORMATEX FormatEx; + + WCHAR Name[1]; +} IFS_PROVIDER, *PIFS_PROVIDER; + +/* init.c */ +PIFS_PROVIDER +GetProvider( + IN PWCHAR FileSytem); + +/* EOF */ diff --git a/reactos/dll/win32/fmifs/query.c b/reactos/dll/win32/fmifs/query.c new file mode 100644 index 00000000000..93cfa8e00c9 --- /dev/null +++ b/reactos/dll/win32/fmifs/query.c @@ -0,0 +1,44 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: File Management IFS Utility functions + * FILE: reactos/dll/win32/fmifs/query.c + * PURPOSE: Query volume information + * + * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org) + */ + +#include "precomp.h" + +BOOLEAN NTAPI +QueryAvailableFileSystemFormat( + IN DWORD Index, + IN OUT PWCHAR FileSystem, /* FIXME: Probably one minimal size is mandatory, but which one? */ + OUT UCHAR* Major, + OUT UCHAR* Minor, + OUT BOOLEAN* LastestVersion) +{ + PLIST_ENTRY ListEntry; + PIFS_PROVIDER Provider; + + if (!FileSystem || !Major ||!Minor ||!LastestVersion) + return FALSE; + + ListEntry = ProviderListHead.Flink; + while (TRUE) + { + if (ListEntry == &ProviderListHead) + return FALSE; + if (Index == 0) + break; + ListEntry = ListEntry->Flink; + Index--; + } + + Provider = CONTAINING_RECORD(ListEntry, IFS_PROVIDER, ListEntry); + wcscpy(FileSystem, Provider->Name); + *Major = 0; /* FIXME */ + *Minor = 0; /* FIXME */ + *LastestVersion = TRUE; /* FIXME */ + + return TRUE; +} diff --git a/reactos/include/reactos/libs/fmifs/fmifs.h b/reactos/include/reactos/libs/fmifs/fmifs.h index 36a36c5fb0d..2296bee656b 100644 --- a/reactos/include/reactos/libs/fmifs/fmifs.h +++ b/reactos/include/reactos/libs/fmifs/fmifs.h @@ -43,7 +43,7 @@ typedef enum FMIFS_FLOPPY, FMIFS_UNKNOWN9, FMIFS_UNKNOWN10, - FMIFS_UNKNOWN11, + FMIFS_REMOVABLE, FMIFS_HARDDISK, FMIFS_UNKNOWN13, FMIFS_UNKNOWN14, @@ -140,10 +140,10 @@ FormatEx( BOOLEAN NTAPI QueryAvailableFileSystemFormat( IN DWORD Index, - IN OUT PWCHAR FileSystem OPTIONAL, /* FIXME: Probably one minimal size is mandatory, but which one? */ - OUT UCHAR* Major OPTIONAL, - OUT UCHAR* Minor OPTIONAL, - OUT BOOLEAN* LastestVersion OPTIONAL); + IN OUT PWCHAR FileSystem, /* FIXME: Probably one minimal size is mandatory, but which one? */ + OUT UCHAR* Major, + OUT UCHAR* Minor, + OUT BOOLEAN* LastestVersion); BOOL NTAPI QueryDeviceInformation( @@ -151,18 +151,31 @@ QueryDeviceInformation( OUT ULONG* Buffer, /* That is probably some 4-bytes structure */ IN ULONG BufferSize); /* 4 */ +BOOL NTAPI +QueryFileSystemName( + IN PWCHAR DriveRoot, + OUT PWCHAR FileSystem OPTIONAL, /* FIXME: Probably one minimal size is mandatory, but which one? */ + OUT UCHAR* Unknown2 OPTIONAL, /* Always 0? */ + OUT UCHAR* Unknown3 OPTIONAL, /* Always 0? */ + OUT ULONG* Unknown4 OPTIONAL); /* Always 0? */ + BOOLEAN NTAPI QueryLatestFileSystemVersion( IN PWCHAR FileSystem, OUT UCHAR* Major OPTIONAL, OUT UCHAR* Minor OPTIONAL); -/*ULONG NTAPI +BOOL NTAPI QuerySupportedMedia( - PVOID Unknown1, - ULONG Unknown2, - ULONG Unknown3, - ULONG Unknown4);*/ + IN PWCHAR DriveRoot, + OUT FMIFS_MEDIA_FLAG *CurrentMedia OPTIONAL, + IN ULONG Unknown3, + OUT PULONG Unknown4); /* Always 1? */ + +BOOL NTAPI +SetLabel( + IN PWCHAR DriveRoot, + IN PWCHAR Label); /* Functions provided by u*.dll */ From 9cea0fdddebe79aa1b34ce8e99f39b1f0845b31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 12:50:51 +0000 Subject: [PATCH 43/54] Display available file systems in usage screen svn path=/trunk/; revision=24253 --- reactos/base/system/format/De.rc | 2 +- reactos/base/system/format/En.rc | 2 +- reactos/base/system/format/Fr.rc | 8 ++-- reactos/base/system/format/Hu.rc | 2 +- reactos/base/system/format/Ja.rc | 2 +- reactos/base/system/format/No.rc | 2 +- reactos/base/system/format/format.c | 67 ++++++++++++++++++++++------- 7 files changed, 61 insertions(+), 24 deletions(-) diff --git a/reactos/base/system/format/De.rc b/reactos/base/system/format/De.rc index c018dba8fd7..53bce37afd7 100644 --- a/reactos/base/system/format/De.rc +++ b/reactos/base/system/format/De.rc @@ -14,7 +14,7 @@ STRINGTABLE DISCARDABLE STRING_HELP, "Usage: %S drive: [-FS:file-system] [-V:label] [-Q] [-A:size] [-C]\n\n\ [Datenträger:] Legt das Laufwerk zum Formatieren fest.\n\ - -FS:file-system Legt das Dateisystem fest (z.B. FAT).\n\ + -FS:file-system Legt das Dateisystem fest (%s).\n\ -V:label Legt den Datentraegernamen fest.\n\ -Q Fuehre Schnellformatierung durch.\n\ -A:size Ueberschreibe Anweisung fuer Standartblockgroesse. Es wird dringend\n\ diff --git a/reactos/base/system/format/En.rc b/reactos/base/system/format/En.rc index 039ee42003d..3cfc9dbdd9a 100644 --- a/reactos/base/system/format/En.rc +++ b/reactos/base/system/format/En.rc @@ -9,7 +9,7 @@ STRINGTABLE DISCARDABLE { STRING_HELP, "Usage: %S drive: [-FS:file-system] [-V:label] [-Q] [-A:size] [-C]\n\n\ [drive:] Specifies the drive to format.\n\ - -FS:file-system Specifies the type of file system (e.g. FAT).\n\ + -FS:file-system Specifies the type of file system (%s).\n\ -V:label Specifies volume label.\n\ -Q Performs a quick format.\n\ -A:size Overrides the default allocation unit size. Default settings\n\ diff --git a/reactos/base/system/format/Fr.rc b/reactos/base/system/format/Fr.rc index f63b971e023..c687c41b8c5 100644 --- a/reactos/base/system/format/Fr.rc +++ b/reactos/base/system/format/Fr.rc @@ -12,11 +12,11 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { STRING_HELP, "Utilisation : %S disque: [-FS:système de fichier] [-V:nom] [-Q] [-A:taille] [-C]\n\n\ - [disque:] Indique le disque à formater.\n\ - -FS:système de fichier Indique le type de système de fichier (p.e. FAT).\n\ - -V:nom Détermine le nom du disque.\n\ + [disque:] Indique le disque à formater.\n\ + -FS:système de fichier Indique le type de système de fichier (%s).\n\ + -V:nom Détermine le nom du disque.\n\ -Q Effectue un formatage rapide.\n\ - -A:taille Force une taille pour les unités d'allocations. Les valeurs par défaut\n\ + -A:taille Force une taille pour les unités d'allocations. Les valeurs par défaut\n\ sont fortement recommandées pour une utilisation courante\n\ NTFS peut utiliser 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K.\n\ FAT peut utiliser 8192, 16K, 32K, 64K, 128K, 256K.\n\ diff --git a/reactos/base/system/format/Hu.rc b/reactos/base/system/format/Hu.rc index d15faf7245a..e29b7906ff5 100644 --- a/reactos/base/system/format/Hu.rc +++ b/reactos/base/system/format/Hu.rc @@ -10,7 +10,7 @@ STRINGTABLE DISCARDABLE { STRING_HELP, "Használat: %S kötet: [-FS:állományrendszer] [-V:címke] [-Q] [-A:méret] [-C]\n\n\ [kötet:] A meghajtóbetûjelet adja meg (kettõsponttal a végén).\n\ - -FS:állományrendszer Az állományrendszer típusát adja meg (pl.: FAT).\n\ + -FS:állományrendszer Az állományrendszer típusát adja meg (%s).\n\ -V:címke A Kötetcímke neve.\n\ -Q Gyorsformázást hajt végre.\n\ -A:méret Felülbírálja az alapértelmezett szektorcsoport-\n\ diff --git a/reactos/base/system/format/Ja.rc b/reactos/base/system/format/Ja.rc index 8778d48fbce..8b5e1ac1375 100644 --- a/reactos/base/system/format/Ja.rc +++ b/reactos/base/system/format/Ja.rc @@ -10,7 +10,7 @@ STRINGTABLE DISCARDABLE STRING_HELP, "Žg—p–@: %S ƒhƒ‰ƒCƒu: [-FS:ƒtƒ@ƒCƒ‹ƒVƒXƒeƒ€] [-V:ƒ‰ƒxƒ‹] [-Q] [-A:ƒTƒCƒY] [-C]\n\n\ [ƒhƒ‰ƒCƒu:] ƒtƒH[ƒ}ƒbƒg‚·‚éƒhƒ‰ƒCƒu‚ðŽw’肵‚Ü‚·B\n\ -FS:ƒtƒ@ƒCƒ‹ƒVƒXƒeƒ€\n\ - ƒtƒ@ƒCƒ‹ƒVƒXƒeƒ€‚ÌŽí—Þ‚ðŽw’肵‚Ü‚· (—á: FAT)B\n\ + ƒtƒ@ƒCƒ‹ƒVƒXƒeƒ€‚ÌŽí—Þ‚ðŽw’肵‚Ü‚· (%s)B\n\ -V:ƒ‰ƒxƒ‹ ƒ{ƒŠƒ…[ƒ€ ƒ‰ƒxƒ‹‚ðŽw’肵‚Ü‚·B\n\ -Q ƒNƒCƒbƒN ƒtƒH[ƒ}ƒbƒg‚ðŽÀs‚µ‚Ü‚·B\n\ -A:ƒTƒCƒY ‹K’è‚̃AƒƒP[ƒVƒ‡ƒ“ ƒ†ƒjƒbƒg ƒTƒCƒY‚ðã‘‚«‚µ‚Ü‚·B\n\ diff --git a/reactos/base/system/format/No.rc b/reactos/base/system/format/No.rc index 198db869d33..8d71d4a4017 100644 --- a/reactos/base/system/format/No.rc +++ b/reactos/base/system/format/No.rc @@ -9,7 +9,7 @@ STRINGTABLE DISCARDABLE { STRING_HELP, "bruk: %S stasjon: [-FS:fil-system] [-V:merke] [-Q] [-A:størrelse] [-C]\n\n\ [stasjon:] Spesifisere stasjon til formater.\n\ - -FS:file-system Spesifisere typen av fil system (f.eks. FAT).\n\ + -FS:file-system Spesifisere typen av fil system (%s).\n\ -V:merke Spesifisere volum merke.\n\ -Q Fullføre en rask formatering.\n\ -A:størrelse Dominerende standard fordeling enhet størrelse. Standard innstilling\n\ diff --git a/reactos/base/system/format/format.c b/reactos/base/system/format/format.c index ea4de4d6e84..3e970647296 100755 --- a/reactos/base/system/format/format.c +++ b/reactos/base/system/format/format.c @@ -69,21 +69,6 @@ static VOID PrintWin32Error( LPTSTR Message, DWORD ErrorCode ) } -//---------------------------------------------------------------------- -// -// Usage -// -// Tell the user how to use the program -// -//---------------------------------------------------------------------- -static VOID Usage( LPTSTR ProgramName ) -{ - TCHAR szMsg[RC_STRING_MAX_SIZE]; - LoadString( GetModuleHandle(NULL), STRING_HELP, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); - _tprintf(szMsg, ProgramName); -} - - //---------------------------------------------------------------------- // // ParseCommandLine @@ -245,9 +230,61 @@ BOOLEAN LoadFMIFSEntryPoints() return FALSE; } + + if( !((void *) GetProcAddress( hFmifs, + "QueryAvailableFileSystemFormat" )) ) { + + return FALSE; + } + return TRUE; } + +//---------------------------------------------------------------------- +// +// Usage +// +// Tell the user how to use the program +// +//---------------------------------------------------------------------- +static VOID Usage( LPTSTR ProgramName ) +{ + TCHAR szMsg[RC_STRING_MAX_SIZE]; + TCHAR szFormats[MAX_PATH]; +#ifndef UNICODE + TCHAR szFormatA[MAX_PATH]; +#endif + WCHAR szFormatW[MAX_PATH]; + DWORD Index = 0; + BYTE dummy; + BOOLEAN lastestVersion; + + LoadString( GetModuleHandle(NULL), STRING_HELP, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + if (!LoadFMIFSEntryPoints()) + { + _tprintf(szMsg, ProgramName, ""); + return; + } + + szFormats[0] = 0; + while (QueryAvailableFileSystemFormat(Index++, szFormatW, &dummy, &dummy, &lastestVersion)) + { + if (!lastestVersion) + continue; + if (szFormats[0]) + _tcscat(szFormats, _T(", ")); +#ifdef UNICODE + _tcscat(szFormats, szFormatW); +#else + if (0 != WideCharToMultiByte(CP_ACP, 0, szFormatW, -1, szFormatA, sizeof(szFormatA), NULL, NULL)) + _tcscat(szFormats, szFormatA); +#endif + } + _tprintf(szMsg, ProgramName, szFormats); +} + + //---------------------------------------------------------------------- // // WMain From f1d365f7671b22b2bc7e89090efa68a5ecb95e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Sun, 24 Sep 2006 13:42:24 +0000 Subject: [PATCH 44/54] Don't hardcode the list of available filesystems in fmifs.dll, but store it in the registry. Adding a filesystem is now only a matter of creating a u{FS}.dll + one registry entry to be able to use normal format.exe/chkdsk.exe/... svn path=/trunk/; revision=24254 --- reactos/boot/bootdata/hivesft.inf | 4 ++ reactos/dll/win32/fmifs/init.c | 68 +++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/reactos/boot/bootdata/hivesft.inf b/reactos/boot/bootdata/hivesft.inf index 2d09fa12917..dcbe055c595 100644 --- a/reactos/boot/bootdata/hivesft.inf +++ b/reactos/boot/bootdata/hivesft.inf @@ -734,6 +734,10 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Tonga Standard Tim 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +; Available file systems +HKLM,"SOFTWARE\ReactOS\ReactOS\CurrentVersion\IFS","FAT",0x00000000,"ufat.dll" +HKLM,"SOFTWARE\ReactOS\ReactOS\CurrentVersion\IFS","FAT32",0x00000000,"ufat.dll" + HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","ConsoleShell",0x00020000,"%SystemRoot%\system32\cmd.exe" HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\explorer.exe" HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartServices",0x00010001,0x00000001 diff --git a/reactos/dll/win32/fmifs/init.c b/reactos/dll/win32/fmifs/init.c index b6a0c15c478..0b3489d4ba8 100644 --- a/reactos/dll/win32/fmifs/init.c +++ b/reactos/dll/win32/fmifs/init.c @@ -35,7 +35,7 @@ GetProvider( static BOOLEAN AddProvider( - IN PWCHAR FileSystem, + IN PCUNICODE_STRING FileSystem, IN PWCHAR DllFile) { PIFS_PROVIDER Provider = NULL; @@ -48,7 +48,7 @@ AddProvider( goto cleanup; RequiredSize = FIELD_OFFSET(IFS_PROVIDER, Name) - + wcslen(FileSystem) * sizeof(WCHAR) + sizeof(UNICODE_NULL); + + FileSystem->Length + sizeof(UNICODE_NULL); Provider = (PIFS_PROVIDER)RtlAllocateHeap( RtlGetProcessHeap(), 0, @@ -62,7 +62,7 @@ AddProvider( //Provider->Extend = (EXTEND)GetProcAddress(hMod, "Extend"); Provider->FormatEx = (FORMATEX)GetProcAddress(hMod, "FormatEx"); - wcscpy(Provider->Name, FileSystem); + RtlCopyMemory(Provider->Name, FileSystem->Buffer, FileSystem->Length); InsertTailList(&ProviderListHead, &Provider->ListEntry); ret = TRUE; @@ -81,14 +81,66 @@ cleanup: static BOOLEAN InitializeFmIfsOnce(void) { + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING RegistryPath + = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\SOFTWARE\\ReactOS\\ReactOS\\CurrentVersion\\IFS"); + HANDLE hKey = NULL; + PKEY_VALUE_FULL_INFORMATION Buffer; + ULONG BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH; + ULONG RequiredSize; + ULONG i = 0; + UNICODE_STRING Name; + UNICODE_STRING Data; + NTSTATUS Status; + InitializeListHead(&ProviderListHead); - /* Add default providers */ - AddProvider(L"FAT", L"ufat"); - AddProvider(L"FAT32", L"ufat"); + /* Read IFS providers from HKLM\SOFTWARE\ReactOS\ReactOS\CurrentVersion\IFS */ + InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, 0, NULL, NULL); + Status = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjectAttributes); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + return TRUE; + else if (!NT_SUCCESS(Status)) + return FALSE; - /* TODO: Check how many IFS are installed in the system */ - /* TODO: and register a descriptor for each one */ + Buffer = (PKEY_VALUE_FULL_INFORMATION)RtlAllocateHeap( + RtlGetProcessHeap(), + 0, + BufferSize); + if (!Buffer) + { + NtClose(hKey); + return FALSE; + } + + while (TRUE) + { + Status = NtEnumerateValueKey( + hKey, + i++, + KeyValueFullInformation, + Buffer, + BufferSize, + &RequiredSize); + if (Status == STATUS_BUFFER_OVERFLOW) + continue; + else if (!NT_SUCCESS(Status)) + break; + else if (Buffer->Type != REG_SZ) + continue; + + Name.Length = Name.MaximumLength = Buffer->NameLength; + Name.Buffer = Buffer->Name; + Data.Length = Data.MaximumLength = Buffer->DataLength; + Data.Buffer = (PWCHAR)((ULONG_PTR)Buffer + Buffer->DataOffset); + if (Data.Length > sizeof(WCHAR) && Data.Buffer[Data.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) + Data.Length -= sizeof(WCHAR); + + AddProvider(&Name, Data.Buffer); + } + + NtClose(hKey); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); return TRUE; } From a04da34bc07511a7fe48157c833d1812d71316ab Mon Sep 17 00:00:00 2001 From: Saveliy Tretiakov Date: Sun, 24 Sep 2006 17:01:46 +0000 Subject: [PATCH 45/54] More prototypes svn path=/trunk/; revision=24255 --- reactos/subsystems/win32/win32k/include/dc.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/dc.h b/reactos/subsystems/win32/win32k/include/dc.h index 00afe1ec3ea..c23f894f3ff 100644 --- a/reactos/subsystems/win32/win32k/include/dc.h +++ b/reactos/subsystems/win32/win32k/include/dc.h @@ -188,6 +188,11 @@ VOID FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner); VOID FASTCALL DC_UpdateXforms(PDC dc); BOOL FASTCALL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest); +VOID FASTCALL IntGetViewportExtEx(PDC dc, LPSIZE pt); +VOID FASTCALL IntGetViewportOrgEx(PDC dc, LPPOINT pt); +VOID FASTCALL IntGetWindowExtEx(PDC dc, LPSIZE pt); +VOID FASTCALL IntGetWindowOrgEx(PDC dc, LPPOINT pt); + /* For Metafile and MetaEnhFile not in windows this struct taken from wine cvs 15/9-2006*/ typedef struct { @@ -195,5 +200,4 @@ typedef struct BOOL on_disk; /* true if metafile is on disk */ } DD_ENHMETAFILEOBJ, *PDD_ENHMETAFILEOBJ; - -#endif +#endif /* __WIN32K_DC_H */ From a5b535fee4c32003a923920d7763ffb409300624 Mon Sep 17 00:00:00 2001 From: Saveliy Tretiakov Date: Sun, 24 Sep 2006 17:02:29 +0000 Subject: [PATCH 46/54] - Implement NtGdiStrokePath and NtGdiStrokeAndFillPath (based on wine) - Get rid of PATH_GetPathFromDc() svn path=/trunk/; revision=24256 --- .../subsystems/win32/win32k/objects/path.c | 374 ++++++++++++------ 1 file changed, 248 insertions(+), 126 deletions(-) diff --git a/reactos/subsystems/win32/win32k/objects/path.c b/reactos/subsystems/win32/win32k/objects/path.c index 27de4689ca5..91e41c1eda8 100644 --- a/reactos/subsystems/win32/win32k/objects/path.c +++ b/reactos/subsystems/win32/win32k/objects/path.c @@ -33,12 +33,11 @@ BOOL FASTCALL PATH_AddFlatBezier (GdiPath *pPath, POINT *pt, BOOL closed); BOOL FASTCALL PATH_DoArcPart (GdiPath *pPath, FLOAT_POINT corners[], double angleStart, double angleEnd, BOOL addMoveTo); BOOL FASTCALL PATH_FillPath( PDC dc, GdiPath *pPath ); BOOL FASTCALL PATH_FlattenPath (GdiPath *pPath); -VOID FASTCALL PATH_GetPathFromDC (PDC dc, GdiPath **ppPath); VOID FASTCALL PATH_NormalizePoint (FLOAT_POINT corners[], const FLOAT_POINT *pPoint, double *pX, double *pY); BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); BOOL FASTCALL PATH_ReserveEntries (GdiPath *pPath, INT numEntries); VOID FASTCALL PATH_ScaleNormalizedPoint (FLOAT_POINT corners[], double x, double y, POINT *pPoint); - +BOOL FASTCALL PATH_StrokePath(DC *dc, GdiPath *pPath); INT FASTCALL IntGdiGetArcDirection(DC *dc); @@ -51,16 +50,12 @@ BOOL STDCALL NtGdiAbortPath(HDC hDC) { - GdiPath *pPath; BOOL ret = TRUE; PDC dc = DC_LockDc ( hDC ); if( !dc ) return FALSE; - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - - PATH_EmptyPath( pPath ); + PATH_EmptyPath(&dc->w.path); DC_UnlockDc ( dc ); return ret; @@ -70,24 +65,20 @@ BOOL STDCALL NtGdiBeginPath( HDC hDC ) { - GdiPath *pPath; BOOL ret = TRUE; PDC dc = DC_LockDc ( hDC ); if( !dc ) return FALSE; - - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); /* If path is already open, do nothing */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) { /* Make sure that path is empty */ - PATH_EmptyPath( pPath ); + PATH_EmptyPath( &dc->w.path ); /* Initialize variables for new path */ - pPath->newStroke = TRUE; - pPath->state = PATH_Open; + dc->w.path.newStroke = TRUE; + dc->w.path.state = PATH_Open; } DC_UnlockDc ( dc ); @@ -142,22 +133,18 @@ BOOL STDCALL NtGdiEndPath(HDC hDC) { - GdiPath *pPath; BOOL ret = TRUE; PDC dc = DC_LockDc ( hDC ); if ( !dc ) return FALSE; - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is currently being constructed */ - if( pPath->state != PATH_Open ) + if( dc->w.path.state != PATH_Open ) { ret = FALSE; } /* Set flag to indicate that path is finished */ - else pPath->state = PATH_Closed; + else dc->w.path.state = PATH_Closed; DC_UnlockDc ( dc ); return ret; @@ -167,21 +154,17 @@ BOOL STDCALL NtGdiFillPath(HDC hDC) { - GdiPath *pPath; BOOL ret = TRUE; PDC dc = DC_LockDc ( hDC ); if ( !dc ) return FALSE; - - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - ret = PATH_FillPath( dc, pPath ); + ret = PATH_FillPath( dc, &dc->w.path ); if( ret ) { /* FIXME: Should the path be emptied even if conversion failed? */ - PATH_EmptyPath( pPath ); + PATH_EmptyPath( &dc->w.path ); } DC_UnlockDc ( dc ); @@ -323,18 +306,39 @@ NtGdiSetMiterLimit( BOOL STDCALL -NtGdiStrokeAndFillPath(HDC hDC) +NtGdiStrokeAndFillPath(HDC hDC) { - UNIMPLEMENTED; - return FALSE; + DC *pDc; + BOOL bRet = FALSE; + + DPRINT("Enter %s\n", __FUNCTION__); + + if(!(pDc = DC_LockDc(hDC))) return FALSE; + + bRet = PATH_FillPath(pDc, &pDc->w.path); + if(bRet) bRet = PATH_StrokePath(pDc, &pDc->w.path); + if(bRet) PATH_EmptyPath(&pDc->w.path); + + DC_UnlockDc(pDc); + return bRet; } BOOL STDCALL -NtGdiStrokePath(HDC hDC) +NtGdiStrokePath(HDC hDC) { - UNIMPLEMENTED; - return FALSE; + DC *pDc; + BOOL bRet = FALSE; + + DPRINT("Enter %s\n", __FUNCTION__); + + if(!(pDc = DC_LockDc(hDC))) return FALSE; + + bRet = PATH_StrokePath(pDc, &pDc->w.path); + PATH_EmptyPath(&pDc->w.path); + + DC_UnlockDc(pDc); + return bRet; } BOOL @@ -348,30 +352,27 @@ NtGdiWidenPath(HDC hDC) BOOL STDCALL NtGdiSelectClipPath(HDC hDC, int Mode) { - GdiPath *pPath; HRGN hrgnPath; BOOL success = FALSE; PDC dc = DC_LockDc ( hDC ); if( !dc ) return FALSE; - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is closed */ - if( pPath->state != PATH_Closed ) + if( dc->w.path.state != PATH_Closed ) { SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); return FALSE; } /* Construct a region from the path */ - else if( PATH_PathToRegion( pPath, dc->w.polyFillMode, &hrgnPath ) ) + else if( PATH_PathToRegion( &dc->w.path, dc->w.polyFillMode, &hrgnPath ) ) { success = IntGdiExtSelectClipRgn( dc, hrgnPath, Mode ) != ERROR; NtGdiDeleteObject( hrgnPath ); /* Empty the path */ if( success ) - PATH_EmptyPath( pPath ); + PATH_EmptyPath( &dc->w.path); /* FIXME: Should this function delete the path even if it failed? */ } @@ -532,18 +533,14 @@ BOOL FASTCALL PATH_MoveTo ( PDC dc ) { - GdiPath *pPath; - - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) /* FIXME: Do we have to call SetLastError? */ return FALSE; /* Start a new stroke */ - pPath->newStroke = TRUE; + dc->w.path.newStroke = TRUE; return TRUE; } @@ -559,14 +556,10 @@ BOOL FASTCALL PATH_LineTo ( PDC dc, INT x, INT y ) { - GdiPath *pPath; POINT point, pointCurPos; - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; /* Convert point to device coordinates */ @@ -575,17 +568,17 @@ PATH_LineTo ( PDC dc, INT x, INT y ) CoordLPtoDP ( dc, &point ); /* Add a PT_MOVETO if necessary */ - if ( pPath->newStroke ) + if ( dc->w.path.newStroke ) { - pPath->newStroke = FALSE; + dc->w.path.newStroke = FALSE; IntGetCurrentPositionEx ( dc, &pointCurPos ); CoordLPtoDP ( dc, &pointCurPos ); - if ( !PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO) ) + if ( !PATH_AddEntry(&dc->w.path, &pointCurPos, PT_MOVETO) ) return FALSE; } /* Add a PT_LINETO entry */ - return PATH_AddEntry(pPath, &point, PT_LINETO); + return PATH_AddEntry(&dc->w.path, &point, PT_LINETO); } /* PATH_Rectangle @@ -597,15 +590,11 @@ BOOL FASTCALL PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 ) { - GdiPath *pPath; POINT corners[2], pointTemp; INT temp; - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; /* Convert points to device coordinates */ @@ -642,15 +631,15 @@ PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 ) /* Add four points to the path */ pointTemp.x=corners[1].x; pointTemp.y=corners[0].y; - if ( !PATH_AddEntry(pPath, &pointTemp, PT_MOVETO) ) + if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_MOVETO) ) return FALSE; - if ( !PATH_AddEntry(pPath, corners, PT_LINETO) ) + if ( !PATH_AddEntry(&dc->w.path, corners, PT_LINETO) ) return FALSE; pointTemp.x=corners[0].x; pointTemp.y=corners[1].y; - if ( !PATH_AddEntry(pPath, &pointTemp, PT_LINETO) ) + if ( !PATH_AddEntry(&dc->w.path, &pointTemp, PT_LINETO) ) return FALSE; - if ( !PATH_AddEntry(pPath, corners+1, PT_LINETO) ) + if ( !PATH_AddEntry(&dc->w.path, corners+1, PT_LINETO) ) return FALSE; /* Close the rectangle figure */ @@ -693,7 +682,6 @@ FASTCALL PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, INT xStart, INT yStart, INT xEnd, INT yEnd) { - GdiPath *pPath; double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0; /* Initialize angleEndQuadrant to silence gcc's warning */ double x, y; @@ -709,11 +697,8 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE ); - /* Get pointer to path */ - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; /* FIXME: Do we have to close the current figure? */ @@ -817,7 +802,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, } /* Add the Bezier spline to the path */ - PATH_DoArcPart ( pPath, corners, angleStartQuadrant, angleEndQuadrant, start ); + PATH_DoArcPart ( &dc->w.path, corners, angleStartQuadrant, angleEndQuadrant, start ); start = FALSE; } while(!end); @@ -828,7 +813,6 @@ BOOL FASTCALL PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints ) { - GdiPath *pPath; POINT pt; ULONG i; @@ -836,19 +820,17 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints ) ASSERT ( pts ); ASSERT ( cbPoints ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; /* Add a PT_MOVETO if necessary */ - if ( pPath->newStroke ) + if ( dc->w.path.newStroke ) { - pPath->newStroke=FALSE; + dc->w.path.newStroke=FALSE; IntGetCurrentPositionEx ( dc, &pt ); CoordLPtoDP ( dc, &pt ); - if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) ) + if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) ) return FALSE; } @@ -856,7 +838,7 @@ PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints ) { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry(pPath, &pt, PT_BEZIERTO); + PATH_AddEntry(&dc->w.path, &pt, PT_BEZIERTO); } return TRUE; } @@ -865,7 +847,6 @@ BOOL FASTCALL PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints ) { - GdiPath *pPath; POINT pt; ULONG i; @@ -873,17 +854,15 @@ PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints ) ASSERT ( pts ); ASSERT ( cbPoints ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; for ( i = 0; i < cbPoints; i++ ) { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry ( pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO ); + PATH_AddEntry ( &dc->w.path, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO ); } return TRUE; @@ -893,7 +872,6 @@ BOOL FASTCALL PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints ) { - GdiPath *pPath; POINT pt; ULONG i; @@ -901,17 +879,15 @@ PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints ) ASSERT ( pts ); ASSERT ( cbPoints ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; for ( i = 0; i < cbPoints; i++ ) { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO); + PATH_AddEntry(&dc->w.path, &pt, (i == 0) ? PT_MOVETO : PT_LINETO); } return TRUE; } @@ -920,7 +896,6 @@ BOOL FASTCALL PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints ) { - GdiPath *pPath; POINT pt; ULONG i; @@ -928,19 +903,17 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints ) ASSERT ( pts ); ASSERT ( cbPoints ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; /* Add a PT_MOVETO if necessary */ - if ( pPath->newStroke ) + if ( dc->w.path.newStroke ) { - pPath->newStroke = FALSE; + dc->w.path.newStroke = FALSE; IntGetCurrentPositionEx ( dc, &pt ); CoordLPtoDP ( dc, &pt ); - if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) ) + if ( !PATH_AddEntry(&dc->w.path, &pt, PT_MOVETO) ) return FALSE; } @@ -948,7 +921,7 @@ PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints ) { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry(pPath, &pt, PT_LINETO); + PATH_AddEntry(&dc->w.path, &pt, PT_LINETO); } return TRUE; @@ -959,24 +932,21 @@ BOOL FASTCALL PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints ) { - GdiPath *pPath; POINT pt; ULONG i; ASSERT ( dc ); ASSERT ( pts ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; for(i = 0; i < cbPoints; i++) { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : + PATH_AddEntry(&dc->w.path, &pt, (i == 0) ? PT_MOVETO : ((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE : PT_LINETO)); } @@ -987,7 +957,6 @@ BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons ) { - GdiPath *pPath; POINT pt, startpt; ULONG poly, point, i; @@ -996,10 +965,8 @@ PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons ) ASSERT ( counts ); ASSERT ( polygons ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ); + if ( dc->w.path.state != PATH_Open ); return FALSE; for(i = 0, poly = 0; poly < polygons; poly++) @@ -1009,10 +976,10 @@ PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UINT polygons ) pt = pts[i]; CoordLPtoDP ( dc, &pt ); if(point == 0) startpt = pt; - PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); + PATH_AddEntry(&dc->w.path, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); } /* win98 adds an extra line to close the figure for some reason */ - PATH_AddEntry(pPath, &startpt, PT_LINETO | PT_CLOSEFIGURE); + PATH_AddEntry(&dc->w.path, &startpt, PT_LINETO | PT_CLOSEFIGURE); } return TRUE; } @@ -1021,7 +988,6 @@ BOOL FASTCALL PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines ) { - GdiPath *pPath; POINT pt; ULONG poly, point, i; @@ -1030,10 +996,8 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin ASSERT ( counts ); ASSERT ( polylines ); - PATH_GetPathFromDC ( dc, &pPath ); - /* Check that path is open */ - if ( pPath->state != PATH_Open ) + if ( dc->w.path.state != PATH_Open ) return FALSE; for(i = 0, poly = 0; poly < polylines; poly++) @@ -1042,7 +1006,7 @@ PATH_PolyPolyline ( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylin { pt = pts[i]; CoordLPtoDP ( dc, &pt ); - PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); + PATH_AddEntry(&dc->w.path, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); } } return TRUE; @@ -1085,7 +1049,7 @@ PATH_FlattenPath(GdiPath *pPath) GdiPath newPath; INT srcpt; - memset(&newPath, 0, sizeof(newPath)); + RtlZeroMemory(&newPath, sizeof(newPath)); newPath.state = PATH_Open; for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) { switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) { @@ -1289,20 +1253,6 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries ) return TRUE; } -/* PATH_GetPathFromDC - * - * Retrieves a pointer to the GdiPath structure contained in an HDC and - * places it in *ppPath. TRUE is returned if successful, FALSE otherwise. - */ -VOID -FASTCALL -PATH_GetPathFromDC ( PDC dc, GdiPath **ppPath ) -{ - ASSERT ( dc ); - ASSERT ( ppPath ); - *ppPath = &dc->w.path; -} - /* PATH_DoArcPart * * Creates a Bezier spline that corresponds to part of an arc and appends the @@ -1401,4 +1351,176 @@ PATH_NormalizePoint ( FLOAT_POINT corners[], *pX=(double)(pPoint->x-corners[0].x)/(double)(corners[1].x-corners[0].x) * 2.0 - 1.0; *pY=(double)(pPoint->y-corners[0].y)/(double)(corners[1].y-corners[0].y) * 2.0 - 1.0; } + + +BOOL FASTCALL PATH_StrokePath(DC *dc, GdiPath *pPath) +{ + BOOL ret = FALSE; + INT i=0; + INT nLinePts, nAlloc; + POINT *pLinePts = NULL; + POINT ptViewportOrg, ptWindowOrg; + SIZE szViewportExt, szWindowExt; + DWORD mapMode, graphicsMode; + XFORM xform; + + DPRINT("Enter %s\n", __FUNCTION__); + + if(pPath->state != PATH_Closed) + return FALSE; + + /* Save the mapping mode info */ + mapMode=dc->w.MapMode; + IntGetViewportExtEx(dc, &szViewportExt); + IntGetViewportOrgEx(dc, &ptViewportOrg); + IntGetWindowExtEx(dc, &szWindowExt); + IntGetWindowOrgEx(dc, &ptWindowOrg); + xform = dc->w.xformWorld2Wnd; + + /* Set MM_TEXT */ + dc->w.MapMode = MM_TEXT; + dc->vportOrgX = 0; + dc->vportOrgY = 0; + dc->wndOrgX = 0; + dc->wndOrgY = 0; + graphicsMode = dc->w.GraphicsMode; + dc->w.GraphicsMode = GM_ADVANCED; + IntGdiModifyWorldTransform(dc, &xform, MWT_IDENTITY); + dc->w.GraphicsMode = graphicsMode; + + /* Allocate enough memory for the worst case without beziers (one PT_MOVETO + * and the rest PT_LINETO with PT_CLOSEFIGURE at the end) plus some buffer + * space in case we get one to keep the number of reallocations small. */ + nAlloc = pPath->numEntriesUsed + 1 + 300; + pLinePts = ExAllocatePoolWithTag(PagedPool, nAlloc * sizeof(POINT), TAG_PATH); + if(!pLinePts) + { + DPRINT1("Can't allocate pool!\n"); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + goto end; + } + nLinePts = 0; + + for(i = 0; i < pPath->numEntriesUsed; i++) + { + if((i == 0 || (pPath->pFlags[i-1] & PT_CLOSEFIGURE)) + && (pPath->pFlags[i] != PT_MOVETO)) + { + DPRINT1("Expected PT_MOVETO %s, got path flag %d\n", + i == 0 ? "as first point" : "after PT_CLOSEFIGURE", + (INT)pPath->pFlags[i]); + goto end; + } + + switch(pPath->pFlags[i]) + { + case PT_MOVETO: + DPRINT("Got PT_MOVETO (%ld, %ld)\n", + pPath->pPoints[i].x, pPath->pPoints[i].y); + if(nLinePts >= 2) IntGdiPolyline(dc, pLinePts, nLinePts); + nLinePts = 0; + pLinePts[nLinePts++] = pPath->pPoints[i]; + break; + case PT_LINETO: + case (PT_LINETO | PT_CLOSEFIGURE): + DPRINT("Got PT_LINETO (%ld, %ld)\n", + pPath->pPoints[i].x, pPath->pPoints[i].y); + pLinePts[nLinePts++] = pPath->pPoints[i]; + break; + case PT_BEZIERTO: + DPRINT("Got PT_BEZIERTO\n"); + if(pPath->pFlags[i+1] != PT_BEZIERTO || + (pPath->pFlags[i+2] & ~PT_CLOSEFIGURE) != PT_BEZIERTO) + { + DPRINT1("Path didn't contain 3 successive PT_BEZIERTOs\n"); + ret = FALSE; + goto end; + } + else + { + INT nBzrPts, nMinAlloc; + POINT *pBzrPts = GDI_Bezier(&pPath->pPoints[i-1], 4, &nBzrPts); + /* Make sure we have allocated enough memory for the lines of + * this bezier and the rest of the path, assuming we won't get + * another one (since we won't reallocate again then). */ + nMinAlloc = nLinePts + (pPath->numEntriesUsed - i) + nBzrPts; + if(nAlloc < nMinAlloc) + { + // Reallocate memory + + POINT *Realloc = NULL; + nAlloc = nMinAlloc * 2; + + Realloc = ExAllocatePoolWithTag(PagedPool, + nAlloc * sizeof(POINT), + TAG_PATH); + + if(!Realloc) + { + DPRINT1("Can't allocate pool!\n"); + goto end; + } + + RtlCopyMemory(Realloc, pLinePts, nLinePts*sizeof(POINT)); + ExFreePool(pLinePts); + pLinePts = Realloc; + } + RtlCopyMemory(&pLinePts[nLinePts], &pBzrPts[1], (nBzrPts - 1) * sizeof(POINT)); + nLinePts += nBzrPts - 1; + ExFreePool(pBzrPts); + i += 2; + } + break; + default: + DPRINT1("Got path flag %d (not supported)\n", (INT)pPath->pFlags[i]); + goto end; + } + + if(pPath->pFlags[i] & PT_CLOSEFIGURE) + { + pLinePts[nLinePts++] = pLinePts[0]; + } + }//for + + if(nLinePts >= 2) + IntGdiPolyline(dc, pLinePts, nLinePts); + + ret = TRUE; + +end: + if(pLinePts)ExFreePool(pLinePts); + + /* Restore the old mapping mode */ + dc->w.MapMode = mapMode; + dc->wndExtX = szWindowExt.cx; + dc->wndExtY = szWindowExt.cy; + dc->wndOrgX = ptWindowOrg.x; + dc->wndOrgY = ptWindowOrg.y; + + dc->vportExtX = szViewportExt.cx; + dc->vportExtY = szViewportExt.cy; + dc->vportOrgX = ptViewportOrg.x; + dc->vportOrgY = ptViewportOrg.y; + + /* Restore the world transform */ + dc->w.xformWorld2Wnd = xform; + + /* If we've moved the current point then get its new position + which will be in device (MM_TEXT) co-ords, convert it to + logical co-ords and re-set it. This basically updates + dc->CurPosX|Y so that their values are in the correct mapping + mode. + */ + if(i > 0) + { + POINT pt; + IntGetCurrentPositionEx(dc, &pt); + IntDPtoLP(dc, &pt, 1); + IntGdiMoveToEx(dc, pt.x, pt.y, NULL); + } + + DPRINT("Leave %s, ret=%d\n", __FUNCTION__, ret); + return ret; +} + /* EOF */ From 2047460d026ac82d8da6e9a4b62e4171645685d7 Mon Sep 17 00:00:00 2001 From: Saveliy Tretiakov Date: Sun, 24 Sep 2006 17:10:58 +0000 Subject: [PATCH 47/54] memcpy -> RtlCopyMemory assert -> ASSERT svn path=/trunk/; revision=24257 --- .../subsystems/win32/win32k/objects/path.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/reactos/subsystems/win32/win32k/objects/path.c b/reactos/subsystems/win32/win32k/objects/path.c index 91e41c1eda8..67033a8f9f7 100644 --- a/reactos/subsystems/win32/win32k/objects/path.c +++ b/reactos/subsystems/win32/win32k/objects/path.c @@ -467,7 +467,7 @@ VOID FASTCALL PATH_InitGdiPath ( GdiPath *pPath ) { - assert(pPath!=NULL); + ASSERT(pPath!=NULL); pPath->state=PATH_Null; pPath->pPoints=NULL; @@ -484,7 +484,7 @@ VOID FASTCALL PATH_DestroyGdiPath ( GdiPath *pPath ) { - assert(pPath!=NULL); + ASSERT(pPath!=NULL); ExFreePool(pPath->pPoints); ExFreePool(pPath->pFlags); @@ -504,16 +504,16 @@ BOOL FASTCALL PATH_AssignGdiPath ( GdiPath *pPathDest, const GdiPath *pPathSrc ) { - assert(pPathDest!=NULL && pPathSrc!=NULL); + ASSERT(pPathDest!=NULL && pPathSrc!=NULL); /* Make sure destination arrays are big enough */ if ( !PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed) ) return FALSE; /* Perform the copy operation */ - memcpy(pPathDest->pPoints, pPathSrc->pPoints, + RtlCopyMemory(pPathDest->pPoints, pPathSrc->pPoints, sizeof(POINT)*pPathSrc->numEntriesUsed); - memcpy(pPathDest->pFlags, pPathSrc->pFlags, + RtlCopyMemory(pPathDest->pFlags, pPathSrc->pFlags, sizeof(BYTE)*pPathSrc->numEntriesUsed); pPathDest->state=pPathSrc->state; @@ -748,7 +748,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, if ( angleEnd <= angleStart ) { angleEnd+=2*M_PI; - assert(angleEnd>=angleStart); + ASSERT(angleEnd>=angleStart); } } else @@ -756,7 +756,7 @@ PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2, if(angleEnd>=angleStart) { angleEnd-=2*M_PI; - assert(angleEnd<=angleStart); + ASSERT(angleEnd<=angleStart); } } @@ -1087,8 +1087,8 @@ PATH_PathToRegion ( GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn ) INT *pNumPointsInStroke; HRGN hrgn = 0; - assert ( pPath!=NULL ); - assert ( pHrgn!=NULL ); + ASSERT(pPath!=NULL); + ASSERT(pHrgn!=NULL); PATH_FlattenPath ( pPath ); @@ -1148,7 +1148,7 @@ VOID FASTCALL PATH_EmptyPath ( GdiPath *pPath ) { - assert(pPath!=NULL); + ASSERT(pPath!=NULL); pPath->state=PATH_Null; pPath->numEntriesUsed=0; @@ -1164,7 +1164,7 @@ BOOL FASTCALL PATH_AddEntry ( GdiPath *pPath, const POINT *pPoint, BYTE flags ) { - assert(pPath!=NULL); + ASSERT(pPath!=NULL); /* FIXME: If newStroke is true, perhaps we want to check that we're * getting a PT_MOVETO @@ -1206,8 +1206,8 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries ) POINT *pPointsNew; BYTE *pFlagsNew; - assert(pPath!=NULL); - assert(numEntries>=0); + ASSERT(pPath!=NULL); + ASSERT(numEntries>=0); /* Do we have to allocate more memory? */ if(numEntries > pPath->numEntriesAllocated) @@ -1237,10 +1237,10 @@ PATH_ReserveEntries ( GdiPath *pPath, INT numEntries ) /* Copy old arrays to new arrays and discard old arrays */ if(pPath->pPoints) { - assert(pPath->pFlags); + ASSERT(pPath->pFlags); - memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed); - memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed); + RtlCopyMemory(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed); + RtlCopyMemory(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed); ExFreePool(pPath->pPoints); ExFreePool(pPath->pFlags); @@ -1272,7 +1272,7 @@ PATH_DoArcPart ( GdiPath *pPath, FLOAT_POINT corners[], POINT point; int i; - assert(fabs(angleEnd-angleStart)<=M_PI_2); + ASSERT(fabs(angleEnd-angleStart)<=M_PI_2); /* FIXME: Is there an easier way of computing this? */ From 29b494be5671df53726826b2629edc25a5c0922c Mon Sep 17 00:00:00 2001 From: "KJK::Hyperion" Date: Sun, 24 Sep 2006 18:07:21 +0000 Subject: [PATCH 48/54] Cosmetic changes svn path=/trunk/; revision=24258 --- reactos/include/psdk/intrin.h | 146 +++++++++++++++++----------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/reactos/include/psdk/intrin.h b/reactos/include/psdk/intrin.h index 6b68ef1776e..32179830262 100644 --- a/reactos/include/psdk/intrin.h +++ b/reactos/include/psdk/intrin.h @@ -47,7 +47,7 @@ first, but they're only "as wrong" as they would be on Visual C++. Our priority is compatibility - NOTE: unlike most people who write __inline__ asm for GCC, I didn't pull the + NOTE: unlike most people who write inline asm for GCC, I didn't pull the constraints and the uses of __volatile__ out of my... hat. Do not touch them. I hate cargo cult programming @@ -274,155 +274,155 @@ static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(vo static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask) { - char x; - char y; + char x; + char y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange8(value, x & mask, x); - } + x = y; + y = _InterlockedCompareExchange8(value, x & mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask) { - short x; - short y; + short x; + short y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange16(value, x & mask, x); - } + x = y; + y = _InterlockedCompareExchange16(value, x & mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask) { - long x; - long y; + long x; + long y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange(value, x & mask, x); - } + x = y; + y = _InterlockedCompareExchange(value, x & mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask) { - char x; - char y; + char x; + char y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange8(value, x | mask, x); - } + x = y; + y = _InterlockedCompareExchange8(value, x | mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask) { - short x; - short y; + short x; + short y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange16(value, x | mask, x); - } + x = y; + y = _InterlockedCompareExchange16(value, x | mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask) { - long x; - long y; + long x; + long y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange(value, x | mask, x); - } + x = y; + y = _InterlockedCompareExchange(value, x | mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask) { - char x; - char y; + char x; + char y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange8(value, x ^ mask, x); - } + x = y; + y = _InterlockedCompareExchange8(value, x ^ mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask) { - short x; - short y; + short x; + short y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange16(value, x ^ mask, x); - } + x = y; + y = _InterlockedCompareExchange16(value, x ^ mask, x); + } while(y != x); - return y; + return y; } static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask) { - long x; - long y; + long x; + long y; - y = *value; + y = *value; - do + do { - x = y; - y = _InterlockedCompareExchange(value, x ^ mask, x); - } + x = y; + y = _InterlockedCompareExchange(value, x ^ mask, x); + } while(y != x); - return y; + return y; } #endif From 350e281e1ceb1c3992bcdf9b709f567bfedc0f01 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sun, 24 Sep 2006 20:14:44 +0000 Subject: [PATCH 49/54] Fix use of unicode for unix host regardless of -fshort-wchar. svn path=/trunk/; revision=24259 --- reactos/tools/buildno/buildno.cpp | 37 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/reactos/tools/buildno/buildno.cpp b/reactos/tools/buildno/buildno.cpp index 9a49bbf6303..14e48e8acc7 100644 --- a/reactos/tools/buildno/buildno.cpp +++ b/reactos/tools/buildno/buildno.cpp @@ -38,6 +38,7 @@ static char * argv0 = ""; static char * filename = ""; +static char * kernel_version_build_type = 0; #ifdef DBG void @@ -55,6 +56,15 @@ tm_dump (const char *tag, struct tm * t) } #endif +int count_wide_string( wchar_t *str ) +{ + int i; + + for( i = 0; str[i]; i++ ); + + return i; +} + void write_h (int build, char *buildstr) { @@ -80,7 +90,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\\0\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\\0\"\n", kernel_version_build_type); s = s + sprintf (s, "#define KERNEL_RELEASE_STR\t\"%d.%d", KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR); @@ -88,7 +98,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\"\n", kernel_version_build_type); s = s + sprintf (s, "#define KERNEL_VERSION_RC\t\"%d.%d", KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR); @@ -96,7 +106,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\\0\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\\0\"\n", kernel_version_build_type); s = s + sprintf (s, "#define KERNEL_VERSION_STR\t\"%d.%d", KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR); @@ -104,7 +114,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\"\n", kernel_version_build_type); s = s + sprintf (s, "#define REACTOS_DLL_VERSION_MAJOR\t%d\n", dllversion); s = s + sprintf (s, "#define REACTOS_DLL_RELEASE_RC\t\"%d.%d", dllversion, KERNEL_VERSION_MINOR); @@ -112,7 +122,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\\0\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\\0\"\n", kernel_version_build_type); s = s + sprintf (s, "#define REACTOS_DLL_RELEASE_STR\t\"%d.%d", dllversion, KERNEL_VERSION_MINOR); @@ -120,7 +130,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\"\n", kernel_version_build_type); s = s + sprintf (s, "#define REACTOS_DLL_VERSION_RC\t\"%d.%d", dllversion, KERNEL_VERSION_MINOR); @@ -128,7 +138,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\\0\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\\0\"\n", kernel_version_build_type); s = s + sprintf (s, "#define REACTOS_DLL_VERSION_STR\t\"%d.%d", dllversion, KERNEL_VERSION_MINOR); @@ -136,7 +146,7 @@ write_h (int build, char *buildstr) { s = s + sprintf (s, ".%d", KERNEL_VERSION_PATCH_LEVEL); } - s = s + sprintf (s, "-%S\"\n", KERNEL_VERSION_BUILD_TYPE); + s = s + sprintf (s, "-%s\"\n", kernel_version_build_type); s = s + sprintf (s, "#endif\n/* EOF */\n"); h = fopen (filename, "wb"); @@ -284,6 +294,7 @@ usage (void) int main (int argc, char * argv []) { + int i, length; int print_only = FALSE; int quiet = FALSE; @@ -341,6 +352,14 @@ main (int argc, char * argv []) printf ( "\nReactOS Build Number Generator\n\n"); } + /* Convert kernel_version_build_type to a host-friendly string */ + length = count_wide_string(KERNEL_VERSION_BUILD_TYPE); + kernel_version_build_type = (char *)malloc(length+1); + for( i = 0; KERNEL_VERSION_BUILD_TYPE[i]; i++ ) { + kernel_version_build_type[i] = KERNEL_VERSION_BUILD_TYPE[i]; + } + kernel_version_build_type[i] = 0; + time (& t1); /* current build time */ t1_tm = gmtime (& t1); @@ -378,7 +397,7 @@ main (int argc, char * argv []) { printf(".%d", KERNEL_VERSION_PATCH_LEVEL); } - printf("-%S (Build %s)\n\n", KERNEL_VERSION_BUILD_TYPE, buildstr); + printf("-%s (Build %s)\n\n", kernel_version_build_type, buildstr); } /* * (Over)write the include file, unless From 235dd5fe2b10f023527b99b5ab002e89daf275e7 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 20:28:57 +0000 Subject: [PATCH 50/54] adding more missing struct svn path=/trunk/; revision=24260 --- reactos/include/psdk/wingdi.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index e3430bcbf6a..c759e50e049 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -1339,7 +1339,7 @@ typedef struct { typedef struct tagFONTSIGNATURE { DWORD fsUsb[4]; DWORD fsCsb[2]; -} FONTSIGNATURE,*LPFONTSIGNATURE; +} FONTSIGNATURE, *PFONTSIGNATURE,*LPFONTSIGNATURE; typedef struct { UINT ciCharset; UINT ciACP; @@ -2029,7 +2029,14 @@ typedef struct tagABORTPATH { typedef struct tagEMRSELECTCLIPPATH { EMR emr; DWORD iMode; -} EMRSELECTCLIPPATH,*PEMRSELECTCLIPPATH,EMRSETBKMODE,*PEMRSETBKMODE,EMRSETMAPMODE,*PEMRSETMAPMODE,EMRSETPOLYFILLMODE,*PEMRSETPOLYFILLMODE,EMRSETROP2,*PEMRSETROP2,EMRSETSTRETCHBLTMODE,*PEMRSETSTRETCHBLTMODE,EMRSETTEXTALIGN,*PEMRSETTEXTALIGN,EMRENABLEICM,*PEMRENABLEICM; +} EMRSELECTCLIPPATH,*PEMRSELECTCLIPPATH, EMRSETBKMODE,*PEMRSETBKMODE, EMRSETMAPMODE, *PEMRSETMAPMODE, + EMRSETPOLYFILLMODE, *PEMRSETPOLYFILLMODE, EMRSETROP2, *PEMRSETROP2, EMRSETSTRETCHBLTMODE, *PEMRSETSTRETCHBLTMODE, + EMRSETICMMODE, *PEMRSETICMMODE, EMRSETTEXTALIGN, +#if(WINVER >= 0x0500) + EMRSETLAYOUT, *PEMRSETLAYOUT, +#endif + *PEMRSETTEXTALIGN; + #include "pshpack2.h" typedef struct tagMETAHEADER { WORD mtType; @@ -2065,7 +2072,7 @@ typedef struct tagENHMETAHEADER { #if (WINVER >= 0x0500) SIZEL szlMicrometers; #endif -} ENHMETAHEADER,*LPENHMETAHEADER; +} ENHMETAHEADER,*PENHMETAHEADER,*LPENHMETAHEADER; typedef struct tagMETARECORD { DWORD rdSize; WORD rdFunction; @@ -2078,7 +2085,7 @@ typedef struct tagENHMETARECORD { } ENHMETARECORD,*LPENHMETARECORD; typedef struct tagHANDLETABLE { HGDIOBJ objectHandle[1]; -} HANDLETABLE,*LPHANDLETABLE; +} HANDLETABLE,*PHANDLETABLE, *LPHANDLETABLE; typedef struct tagTEXTMETRICA { LONG tmHeight; LONG tmAscent; @@ -2525,6 +2532,16 @@ typedef struct _DISPLAY_DEVICEW { WCHAR DeviceKey[128]; } DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW; +#if (_WIN32_WINNT >= 0x0500) +typedef struct _RGNDATAHEADER { + DWORD dwSize; + DWORD iType; + DWORD nCount; + DWORD nRgnSize; + RECT rcBound; +} RGNDATAHEADER, *PRGNDATAHEADER; +#endif + typedef BOOL (CALLBACK *ABORTPROC)(HDC,int); typedef int (CALLBACK *MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM); typedef int (CALLBACK *ENHMFENUMPROC)(HDC,HANDLETABLE*,ENHMETARECORD*,int,LPARAM); From 9b6f293ce52813cb1f5e8c5e521ee6ef551b71bf Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 20:53:47 +0000 Subject: [PATCH 51/54] adding more missing struct need them later in winetest svn path=/trunk/; revision=24261 --- reactos/include/psdk/wingdi.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index c759e50e049..574890c2f0d 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -1187,6 +1187,16 @@ extern "C" { #define CS_DISABLE 0x00000002 #define CS_DELETE_TRANSFORM 0x00000003 #endif + +#if(WINVER >= 0x0400) +typedef struct tagEMRGLSRECORD +{ + EMR emr; + DWORD cbData; + BYTE Data[1]; +} EMRGLSRECORD, *PEMRGLSRECORD; +#endif + #if (WINVER > 0x500) #define GRADIENT_FILL_RECT_H 0x00 #define GRADIENT_FILL_RECT_V 0x01 @@ -1760,6 +1770,19 @@ typedef struct tagEMRFORMAT { DWORD cbData; DWORD offData; } EMRFORMAT; + +typedef struct tagEMRPIXELFORMAT +{ + EMR emr; + PIXELFORMATDESCRIPTOR pfd; +} EMRPIXELFORMAT, *PEMRPIXELFORMAT; +typedef struct tagEMRSETCOLORSPACE +{ + EMR emr; + DWORD ihCS; +} EMRSETCOLORSPACE, *PEMRSETCOLORSPACE, EMRSELECTCOLORSPACE, *PEMRSELECTCOLORSPACE, + EMRDELETECOLORSPACE, *PEMRDELETECOLORSPACE; + typedef struct tagEMRFRAMERGN { EMR emr; RECTL rclBounds; From 08256d0670bbda41e6cbdd7683c48da0f6cdcd82 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 21:10:36 +0000 Subject: [PATCH 52/54] sorry I broken the build it fixed now svn path=/trunk/; revision=24262 --- reactos/include/psdk/wingdi.h | 37 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index 574890c2f0d..9ccc3b7a7e3 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -1188,14 +1188,7 @@ extern "C" { #define CS_DELETE_TRANSFORM 0x00000003 #endif -#if(WINVER >= 0x0400) -typedef struct tagEMRGLSRECORD -{ - EMR emr; - DWORD cbData; - BYTE Data[1]; -} EMRGLSRECORD, *PEMRGLSRECORD; -#endif + #if (WINVER > 0x500) #define GRADIENT_FILL_RECT_H 0x00 @@ -1496,6 +1489,15 @@ typedef struct tagEMR { DWORD iType; DWORD nSize; } EMR,*PEMR; + +#if(WINVER >= 0x0400) +typedef struct tagEMRGLSRECORD +{ + EMR emr; + DWORD cbData; + BYTE Data[1]; +} EMRGLSRECORD, *PEMRGLSRECORD; +#endif typedef struct tagEMRANGLEARC { EMR emr; POINTL ptlCenter; @@ -1771,11 +1773,7 @@ typedef struct tagEMRFORMAT { DWORD offData; } EMRFORMAT; -typedef struct tagEMRPIXELFORMAT -{ - EMR emr; - PIXELFORMATDESCRIPTOR pfd; -} EMRPIXELFORMAT, *PEMRPIXELFORMAT; + typedef struct tagEMRSETCOLORSPACE { EMR emr; @@ -1935,10 +1933,8 @@ typedef struct tagEMRSCALEVIEWPORTEXTEX { LONG yNum; LONG yDenom; } EMRSCALEVIEWPORTEXTEX,*PEMRSCALEVIEWPORTEXTEX,EMRSCALEWINDOWEXTEX,*PEMRSCALEWINDOWEXTEX; -typedef struct tagEMRSELECTCOLORSPACE { - EMR emr; - DWORD ihCS; -} EMRSELECTCOLORSPACE,*PEMRSELECTCOLORSPACE,EMRDELETECOLORSPACE,*PEMRDELETECOLORSPACE; + + typedef struct tagEMRSELECTOBJECT { EMR emr; DWORD ihObject; @@ -2344,6 +2340,13 @@ typedef struct tagPIXELFORMATDESCRIPTOR { DWORD dwVisibleMask; DWORD dwDamageMask; } PIXELFORMATDESCRIPTOR,*PPIXELFORMATDESCRIPTOR,*LPPIXELFORMATDESCRIPTOR; + +typedef struct tagEMRPIXELFORMAT +{ + EMR emr; + PIXELFORMATDESCRIPTOR pfd; +} EMRPIXELFORMAT, *PEMRPIXELFORMAT; + typedef struct tagMETAFILEPICT { LONG mm; LONG xExt; From 2b9e96e55879200f2d960330a27d1c3003949a1c Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 21:17:31 +0000 Subject: [PATCH 53/54] fixed another build break by me :( svn path=/trunk/; revision=24263 --- reactos/include/psdk/wingdi.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/reactos/include/psdk/wingdi.h b/reactos/include/psdk/wingdi.h index 9ccc3b7a7e3..0375635fdd8 100644 --- a/reactos/include/psdk/wingdi.h +++ b/reactos/include/psdk/wingdi.h @@ -2149,6 +2149,7 @@ typedef struct tagTEXTMETRICW { BYTE tmPitchAndFamily; BYTE tmCharSet; } TEXTMETRICW,*PTEXTMETRICW,*LPTEXTMETRICW; + typedef struct _RGNDATAHEADER { DWORD dwSize; DWORD iType; @@ -2558,15 +2559,7 @@ typedef struct _DISPLAY_DEVICEW { WCHAR DeviceKey[128]; } DISPLAY_DEVICEW, *PDISPLAY_DEVICEW, *LPDISPLAY_DEVICEW; -#if (_WIN32_WINNT >= 0x0500) -typedef struct _RGNDATAHEADER { - DWORD dwSize; - DWORD iType; - DWORD nCount; - DWORD nRgnSize; - RECT rcBound; -} RGNDATAHEADER, *PRGNDATAHEADER; -#endif + typedef BOOL (CALLBACK *ABORTPROC)(HDC,int); typedef int (CALLBACK *MFENUMPROC)(HDC,HANDLETABLE*,METARECORD*,int,LPARAM); From 6f10b47b941892118d49b26149290a01db654855 Mon Sep 17 00:00:00 2001 From: Magnus Olsen Date: Sun, 24 Sep 2006 22:27:00 +0000 Subject: [PATCH 54/54] update winetest gdi32 with more wine test svn path=/trunk/; revision=24264 --- reactos/regtests/winetests/gdi32/gdi32.rbuild | 2 + reactos/regtests/winetests/gdi32/mapping.c | 160 ++++++++++++++++++ reactos/regtests/winetests/gdi32/palette.c | 126 ++++++++++++++ reactos/regtests/winetests/gdi32/testlist.c | 4 +- 4 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 reactos/regtests/winetests/gdi32/mapping.c create mode 100644 reactos/regtests/winetests/gdi32/palette.c diff --git a/reactos/regtests/winetests/gdi32/gdi32.rbuild b/reactos/regtests/winetests/gdi32/gdi32.rbuild index 448a0fa8d16..e34147f9d60 100644 --- a/reactos/regtests/winetests/gdi32/gdi32.rbuild +++ b/reactos/regtests/winetests/gdi32/gdi32.rbuild @@ -12,6 +12,8 @@ dc.c gdiobj.c font.c + mapping.c metafile.c + palette.c testlist.c diff --git a/reactos/regtests/winetests/gdi32/mapping.c b/reactos/regtests/winetests/gdi32/mapping.c new file mode 100644 index 00000000000..2baeb2d8004 --- /dev/null +++ b/reactos/regtests/winetests/gdi32/mapping.c @@ -0,0 +1,160 @@ +/* + * Unit tests for mapping functions + * + * Copyright (c) 2005 Huw Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "wine/test.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winerror.h" + + +void test_modify_world_transform(void) +{ + HDC hdc = GetDC(0); + int ret; + + ret = SetGraphicsMode(hdc, GM_ADVANCED); + if(!ret) /* running in win9x so quit */ + { + ReleaseDC(0, hdc); + return; + } + + ret = ModifyWorldTransform(hdc, NULL, MWT_IDENTITY); + ok(ret, "ret = %d\n", ret); + + ret = ModifyWorldTransform(hdc, NULL, MWT_LEFTMULTIPLY); + ok(!ret, "ret = %d\n", ret); + + ret = ModifyWorldTransform(hdc, NULL, MWT_RIGHTMULTIPLY); + ok(!ret, "ret = %d\n", ret); + + ReleaseDC(0, hdc); +} + +void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy) +{ + SIZE windowExt, viewportExt; + POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter; + + GetWindowOrgEx(hdc, &windowOrg); + GetViewportOrgEx(hdc, &viewportOrg); + + SetWindowExtEx(hdc, cx, cy, NULL); + GetWindowExtEx(hdc, &windowExt); + ok(windowExt.cx == cx && windowExt.cy == cy, + "Window extension: Expected %ldx%ld, got %ldx%ld\n", + cx, cy, windowExt.cx, windowExt.cy); + + GetViewportExtEx(hdc, &viewportExt); + ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy, + "Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n", + expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy); + + GetWindowOrgEx(hdc, &windowOrgAfter); + ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y, + "Window origin changed from (%ld,%ld) to (%ld,%ld)\n", + windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y); + + GetViewportOrgEx(hdc, &viewportOrgAfter); + ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y, + "Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n", + viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y); +} + +void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy) +{ + SIZE windowExt, windowExtAfter, viewportExt; + POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter; + + GetWindowOrgEx(hdc, &windowOrg); + GetViewportOrgEx(hdc, &viewportOrg); + GetWindowExtEx(hdc, &windowExt); + + SetViewportExtEx(hdc, cx, cy, NULL); + GetViewportExtEx(hdc, &viewportExt); + ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy, + "Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n", + expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy); + + GetWindowExtEx(hdc, &windowExtAfter); + ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy, + "Window extension changed from %ldx%ld to %ldx%ld\n", + windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy); + + GetWindowOrgEx(hdc, &windowOrgAfter); + ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y, + "Window origin changed from (%ld,%ld) to (%ld,%ld)\n", + windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y); + + GetViewportOrgEx(hdc, &viewportOrgAfter); + ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y, + "Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n", + viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y); +} + +void test_isotropic_mapping(void) +{ + SIZE win, vp; + HDC hdc = GetDC(0); + + SetMapMode(hdc, MM_ISOTROPIC); + + /* MM_ISOTROPIC is set up like MM_LOMETRIC. + Initial values after SetMapMode(): + (1 inch = 25.4 mm) + + Windows 9x: Windows NT: + Window Ext: 254 x -254 HORZSIZE*10 x VERTSIZE*10 + Viewport Ext: LOGPIXELSX x LOGPIXELSY HORZRES x -VERTRES + + To test without rounding errors, we have to use multiples of + these values! + */ + + GetWindowExtEx(hdc, &win); + GetViewportExtEx(hdc, &vp); + + test_SetViewportExt(hdc, 10 * vp.cx, 10 * vp.cy, 10 * vp.cx, 10 * vp.cy); + test_SetWindowExt(hdc, win.cx, win.cy, 10 * vp.cx, 10 * vp.cy); + test_SetWindowExt(hdc, 2 * win.cx, win.cy, 10 * vp.cx, 5 * vp.cy); + test_SetWindowExt(hdc, win.cx, win.cy, 5 * vp.cx, 5 * vp.cy); + test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy); + test_SetViewportExt(hdc, vp.cx, 2 * vp.cy, vp.cx, vp.cy); + test_SetViewportExt(hdc, 2 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy); + test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy); + test_SetWindowExt(hdc, 4 * win.cx, 2 * win.cy, 2 * vp.cx, vp.cy); + test_SetViewportExt(hdc, -2 * vp.cx, -4 * vp.cy, -2 * vp.cx, -vp.cy); + test_SetViewportExt(hdc, -2 * vp.cx, -1 * vp.cy, -2 * vp.cx, -vp.cy); + test_SetWindowExt(hdc, -4 * win.cx, -2 * win.cy, -2 * vp.cx, -vp.cy); + test_SetWindowExt(hdc, 4 * win.cx, -4 * win.cy, -vp.cx, -vp.cy); + + ReleaseDC(0, hdc); +} + +START_TEST(mapping) +{ + test_modify_world_transform(); + test_isotropic_mapping(); +} diff --git a/reactos/regtests/winetests/gdi32/palette.c b/reactos/regtests/winetests/gdi32/palette.c new file mode 100644 index 00000000000..994763985f7 --- /dev/null +++ b/reactos/regtests/winetests/gdi32/palette.c @@ -0,0 +1,126 @@ +/* + * Unit test suite for palettes + * + * Copyright 2005 Glenn Wurster + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "mmsystem.h" + +#include "wine/test.h" + +static const PALETTEENTRY logpalettedata[8] = { + { 0x10, 0x20, 0x30, PC_NOCOLLAPSE }, + { 0x20, 0x30, 0x40, PC_NOCOLLAPSE }, + { 0x30, 0x40, 0x50, PC_NOCOLLAPSE }, + { 0x40, 0x50, 0x60, PC_NOCOLLAPSE }, + { 0x50, 0x60, 0x70, PC_NOCOLLAPSE }, + { 0x60, 0x70, 0x80, PC_NOCOLLAPSE }, + { 0x70, 0x80, 0x90, PC_NOCOLLAPSE }, + { 0x80, 0x90, 0xA0, PC_NOCOLLAPSE }, +}; + +static void test_DIB_PAL_COLORS(void) { + HDC hdc = GetDC( NULL ); + HDC memhdc = CreateCompatibleDC( hdc ); + HBITMAP hbmp, hbmpOld; + char bmpbuf[sizeof(BITMAPINFO) + 10 * sizeof(WORD)]; + PBITMAPINFO bmp = (PBITMAPINFO)bmpbuf; + WORD * bmpPalPtr; + char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)]; + PLOGPALETTE logpalette = (PLOGPALETTE)logpalettebuf; + HPALETTE hpal, hpalOld; + COLORREF setColor, chkColor, getColor; + int i; + + /* Initalize the logical palette with a few colours */ + logpalette->palVersion = 0x300; + logpalette->palNumEntries = 8; + memcpy( logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata) ); + hpal = CreatePalette( logpalette ); + hpalOld = SelectPalette( memhdc, hpal, FALSE ); + ok( hpalOld != NULL, "error=%ld\n", GetLastError() ); + + /* Create a DIB BMP which references colours in the logical palette */ + memset( bmp, 0x00, sizeof(BITMAPINFO) ); + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = 1; + bmp->bmiHeader.biHeight = 1; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = 8; + bmp->bmiHeader.biCompression = BI_RGB; + bmp->bmiHeader.biClrUsed = 10; + bmp->bmiHeader.biClrImportant = 0; + bmpPalPtr = (WORD *)&bmp->bmiColors; + for( i = 0; i < 8; i++ ) { + *bmpPalPtr++ = i; + } + *bmpPalPtr++ = 8; /* Pointer to logical palette index just outside range */ + *bmpPalPtr++ = 19; /* Pointer to bad logical palette index */ + + hbmp = CreateDIBSection( memhdc, bmp, DIB_PAL_COLORS, 0, 0, 0 ); + ok( hbmp != NULL, "error=%ld\n", GetLastError() ); + hbmpOld = SelectObject( memhdc, hbmp ); + ok( hbmpOld != NULL, "error=%ld\n", GetLastError() ); + + /* Test with a RGB to DIB_PAL_COLORS */ + setColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue ); + SetPixel( memhdc, 0, 0, setColor ); + chkColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue ); + getColor = GetPixel( memhdc, 0, 0 ); + ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor ); + + /* Test with a valid DIBINDEX to DIB_PAL_COLORS */ + setColor = DIBINDEX( 2 ); + SetPixel( memhdc, 0, 0, setColor ); + chkColor = RGB( logpalettedata[2].peRed, logpalettedata[2].peGreen, logpalettedata[2].peBlue ); + getColor = GetPixel( memhdc, 0, 0 ); + ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor ); + + /* Test with a invalid DIBINDEX to DIB_PAL_COLORS */ + setColor = DIBINDEX( 12 ); + SetPixel( memhdc, 0, 0, setColor ); + chkColor = RGB( 0, 0, 0 ); + getColor = GetPixel( memhdc, 0, 0 ); + ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor ); + + /* Test for double wraparound on logical palette references from */ + /* DIBINDEX by DIB_PAL_COLORS. */ + setColor = DIBINDEX( 9 ); + SetPixel( memhdc, 0, 0, setColor ); + chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen, logpalettedata[3].peBlue ); + getColor = GetPixel( memhdc, 0, 0 ); + ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor ); + + SelectPalette( memhdc, hpalOld, FALSE ); + DeleteObject( hpal ); + SelectObject( memhdc, hbmpOld ); + DeleteObject( hbmp ); + DeleteDC( memhdc ); + ReleaseDC( NULL, hdc ); +} + +START_TEST(palette) +{ + test_DIB_PAL_COLORS(); +} diff --git a/reactos/regtests/winetests/gdi32/testlist.c b/reactos/regtests/winetests/gdi32/testlist.c index 875e34863a8..139d5fa5339 100644 --- a/reactos/regtests/winetests/gdi32/testlist.c +++ b/reactos/regtests/winetests/gdi32/testlist.c @@ -27,9 +27,9 @@ const struct test winetest_testlist[] = { "font", func_font }, { "gdiobj", func_gdiobj }, // { "generated", func_generated }, -// { "mapping", func_mapping }, + { "mapping", func_mapping }, { "metafile", func_metafile }, -// { "palette", func_palette }, + { "palette", func_palette }, // { "pen", func_pen }, { 0, 0 } };