From 0746dc2644aa67eebd0ec6dd4426f18ec07b859a Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Mon, 18 Aug 2008 18:00:55 +0200 Subject: [PATCH] push 535a8035db5d709ef8f05977281c2f1a0c4cce0a --- dlls/advapi32/security.c | 62 +- dlls/advapi32/tests/security.c | 54 +- dlls/advapi32/tests/service.c | 3 +- dlls/appwiz.cpl/Nl.rc | 79 + dlls/appwiz.cpl/appwiz.c | 3 + dlls/appwiz.cpl/appwiz.rc | 1 + dlls/comctl32/tests/tooltips.c | 60 + dlls/comctl32/tooltips.c | 3 + dlls/comctl32/treeview.c | 2 +- dlls/crypt32/crypt32.spec | 2 +- dlls/crypt32/msg.c | 116 ++ dlls/crypt32/tests/msg.c | 117 ++ dlls/cryptnet/cryptnet_main.c | 3 +- dlls/d3d9/device.c | 7 +- dlls/dmime/performance.c | 8 +- dlls/dplayx/tests/dplayx.c | 94 +- dlls/gdi32/brush.c | 2 +- dlls/gdi32/tests/bitmap.c | 1 - dlls/gdiplus/gdiplus.c | 33 + dlls/gdiplus/gdiplus.spec | 6 +- dlls/gdiplus/gdiplus_private.h | 2 + dlls/gdiplus/graphics.c | 15 + dlls/gdiplus/graphicspath.c | 33 - dlls/gdiplus/pathiterator.c | 38 +- dlls/gdiplus/tests/pathiterator.c | 182 +++ dlls/hhctrl.ocx/help.c | 2 +- dlls/hhctrl.ocx/webbrowser.c | 6 +- dlls/kernel32/locale.c | 3 + dlls/kernel32/profile.c | 2 +- dlls/kernel32/sync.c | 2 +- dlls/kernel32/tests/profile.c | 22 + dlls/kernel32/time.c | 14 +- dlls/mshtml/htmlanchor.c | 15 +- dlls/mshtml/htmlelem.c | 15 +- dlls/mshtml/htmlelem2.c | 15 +- dlls/mshtml/htmlstyle.c | 21 +- dlls/msi/action.c | 4 + dlls/msi/msi.c | 59 +- dlls/msi/tests/install.c | 144 ++ dlls/msrle32/msrle32.c | 4 +- dlls/msxml3/domdoc.c | 4 +- dlls/ole32/compobj.c | 4 +- dlls/ole32/oleproxy.c | 6 +- dlls/ole32/storage32.c | 17 +- dlls/ole32/tests/ole2.c | 3 +- dlls/oleaut32/typelib.c | 42 +- dlls/oleaut32/variant.c | 4 +- dlls/oleaut32/vartype.c | 6 +- dlls/quartz/control.c | 2 +- dlls/quartz/mpegsplit.c | 2 +- dlls/riched20/Makefile.in | 1 + dlls/riched20/caret.c | 272 +++- dlls/riched20/editor.c | 524 +++++- dlls/riched20/editor.h | 25 +- dlls/riched20/editstr.h | 72 +- dlls/riched20/list.c | 15 +- dlls/riched20/paint.c | 374 ++++- dlls/riched20/para.c | 127 +- dlls/riched20/reader.c | 15 +- dlls/riched20/rtf.h | 66 +- dlls/riched20/run.c | 22 +- dlls/riched20/table.c | 618 ++++++++ dlls/riched20/tests/editor.c | 22 + dlls/riched20/undo.c | 34 +- dlls/riched20/wrap.c | 241 ++- dlls/riched20/writer.c | 173 +- dlls/rpcrt4/ndr_marshall.c | 3173 ++++++++++++++++++++----------------- dlls/rpcrt4/rpc_binding.c | 255 ++- dlls/rpcrt4/rpc_epmap.c | 4 +- dlls/rpcrt4/rpc_transport.c | 25 +- dlls/rpcrt4/tests/ndr_marshall.c | 100 ++ dlls/rpcrt4/tests/rpc.c | 31 +- dlls/shell32/shell32_Ru.rc | 4 +- dlls/shell32/shlexec.c | 33 +- dlls/shlwapi/ordinal.c | 6 +- dlls/shlwapi/string.c | 8 +- dlls/shlwapi/url.c | 2 +- dlls/urlmon/umon.c | 2 +- dlls/user32/dde_client.c | 7 + dlls/user32/dde_misc.c | 12 +- dlls/user32/tests/dde.c | 81 +- dlls/winealsa.drv/dsoutput.c | 8 +- dlls/wineps.drv/type1.c | 1 + dlls/winex11.drv/dib.c | 2 +- dlls/winmm/mci.c | 4 +- dlls/winmm/winmm.c | 18 + dlls/winmm/winmm.spec | 4 +- include/gdiplusflat.h | 3 + include/rpcdce.h | 2 +- include/wine/svcctl.idl | 3 - include/wine/wined3d_gl.h | 548 +++---- programs/rpcss/epmp.c | 1 + programs/rpcss/rpcss_main.c | 7 + programs/winedbg/symbol.c | 2 +- programs/winhlp32/hlpfile.c | 8 +- tools/widl/parser.y | 7 +- 96 files changed, 5936 insertions(+), 2370 deletions(-) create mode 100644 dlls/appwiz.cpl/Nl.rc create mode 100644 dlls/riched20/table.c diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 95b7a7b2bd6..6a19ef01612 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -2710,6 +2710,22 @@ BOOL WINAPI PrivilegedServiceAuditAlarmW( LPCWSTR SubsystemName, LPCWSTR Service /****************************************************************************** * GetSecurityInfo [ADVAPI32.@] + * + * Retrieves a copy of the security descriptor associated with an object. + * + * PARAMS + * hObject [I] A handle for the object. + * ObjectType [I] The type of object. + * SecurityInfo [I] A bitmask indicating what info to retrieve. + * ppsidOwner [O] If non-null, receives a pointer to the owner SID. + * ppsidGroup [O] If non-null, receives a pointer to the group SID. + * ppDacl [O] If non-null, receives a pointer to the DACL. + * ppSacl [O] If non-null, receives a pointer to the SACL. + * ppSecurityDescriptor [O] Receives a pointer to the security descriptor, + * which must be freed with LocalFree. + * + * RETURNS + * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise. */ DWORD WINAPI GetSecurityInfo( HANDLE hObject, SE_OBJECT_TYPE ObjectType, @@ -2718,8 +2734,50 @@ DWORD WINAPI GetSecurityInfo( PSECURITY_DESCRIPTOR *ppSecurityDescriptor ) { - FIXME("stub!\n"); - return ERROR_BAD_PROVIDER; + PSECURITY_DESCRIPTOR sd; + NTSTATUS status; + ULONG n1, n2; + BOOL present, defaulted; + + status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1); + if (status != STATUS_BUFFER_TOO_SMALL && status != STATUS_SUCCESS) + return RtlNtStatusToDosError(status); + + sd = LocalAlloc(0, n1); + if (!sd) + return ERROR_NOT_ENOUGH_MEMORY; + + status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2); + if (status != STATUS_SUCCESS) + { + LocalFree(sd); + return RtlNtStatusToDosError(status); + } + + if (ppsidOwner) + { + *ppsidOwner = NULL; + GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted); + } + if (ppsidGroup) + { + *ppsidGroup = NULL; + GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted); + } + if (ppDacl) + { + *ppDacl = NULL; + GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted); + } + if (ppSacl) + { + *ppSacl = NULL; + GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted); + } + if (ppSecurityDescriptor) + *ppSecurityDescriptor = sd; + + return ERROR_SUCCESS; } /****************************************************************************** diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index ea4d91250e7..6b0ecfada6f 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -586,8 +586,9 @@ static void test_lookupPrivilegeName(void) luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE; cchName = sizeof(buf); ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName); - ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE, - "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n", + ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE || + GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */, + "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n", GetLastError()); } @@ -644,8 +645,9 @@ static void test_lookupPrivilegeValue(void) /* check a bogus system name */ ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid); - ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE, - "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n", + ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE || + GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */, + "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n", GetLastError()); /* check a NULL string */ ret = pLookupPrivilegeValueA(NULL, 0, &luid); @@ -2483,6 +2485,49 @@ static void test_acls(void) ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError()); } +static void test_GetSecurityInfo(void) +{ + HANDLE obj; + PSECURITY_DESCRIPTOR sd; + PSID owner, group; + PACL dacl; + DWORD ret; + + /* Create something. Files have lots of associated security info. */ + obj = CreateFile(myARGV[0], GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (!obj) + { + skip("Couldn't create an object for GetSecurityInfo test\n"); + return; + } + + ret = GetSecurityInfo(obj, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &owner, &group, &dacl, NULL, &sd); + ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); + ok(sd != NULL, "GetSecurityInfo\n"); + ok(owner != NULL, "GetSecurityInfo\n"); + ok(group != NULL, "GetSecurityInfo\n"); + ok(dacl != NULL, "GetSecurityInfo\n"); + ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + + LocalFree(sd); + + /* If we don't ask for the security descriptor, Windows will still give us + the other stuff, leaving us no way to free it. */ + ret = GetSecurityInfo(obj, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &owner, &group, &dacl, NULL, NULL); + ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); + ok(owner != NULL, "GetSecurityInfo\n"); + ok(group != NULL, "GetSecurityInfo\n"); + ok(dacl != NULL, "GetSecurityInfo\n"); + ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + + CloseHandle(obj); +} + START_TEST(security) { init(); @@ -2511,4 +2556,5 @@ START_TEST(security) test_ConvertSecurityDescriptorToString(); test_PrivateObjectSecurity(); test_acls(); + test_GetSecurityInfo(); } diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index cd6d82c26b9..829cfe7bf94 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -66,7 +66,8 @@ static void test_open_scm(void) scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT); ok(!scm_handle, "Expected failure\n"); todo_wine - ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE, "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError()); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */, + "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError()); CloseServiceHandle(scm_handle); /* Just in case */ /* Proper call with an empty hostname */ diff --git a/dlls/appwiz.cpl/Nl.rc b/dlls/appwiz.cpl/Nl.rc new file mode 100644 index 00000000000..696dc20462e --- /dev/null +++ b/dlls/appwiz.cpl/Nl.rc @@ -0,0 +1,79 @@ +/* +* Add/Remove Programs Dutch resources +* +* Copyright 2008 Frans Kool +* +* 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 +* +*/ + +LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_CPL_TITLE, "Software" + IDS_CPL_DESC, "Hiermee installeert u nieuwe software, of verwijderd u bestaande software van uw computer." + IDS_TAB1_TITLE, "Programma's" + + IDS_UNINSTALL_FAILED, "Het programma '%s' kan niet verwijderd worden van het systeem. Wilt u het verwijderen uit het register?" + IDS_NOT_SPECIFIED, "Niet gespecificeerd" + + IDS_COLUMN_NAME, "Naam" + IDS_COLUMN_PUBLISHER, "Uitgever" + IDS_COLUMN_VERSION, "Versie" +} + +/* TODO: it's best to use the constant WC_LISTVIEW instead of SysListView32 directly, but the Wine resource compiler doesn't seem to like that... */ + +IDD_MAIN DIALOG 0, 0, 320, 220 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Installeren/Verwijderen" +FONT 8, "MS Sans Serif" +{ + CONTROL "Om een programma te installeren vanaf een floppy disk, CD-ROM drive, of uw hard disk, click op Installeren.", 1000, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 7, 270, 20 + CONTROL "&Installeren...", IDC_INSTALL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 246, 26, 64, 14 + CONTROL "", -1, "STATIC", SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE, 7, 46, 303, 1 + CONTROL 2, 1001, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 7, 7, 21, 20 + CONTROL "De volgende software kan automatisch verwijderd worden. Om het programma te verwijderen of de geinstalleerde onderdelen te wijzigen, selecteer het in de lijst en druk op Toevoegen/Verwijderen.", 1002, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 57, 270, 30 + CONTROL "", IDL_PROGRAMS, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 90, 303, 100 + CONTROL "Toevoegen/&Verwijderen...", IDC_ADDREMOVE, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 246, 198, 64, 14 + CONTROL "&Support Informatie...", IDC_SUPPORT_INFO, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 176, 198, 64, 14 + CONTROL 3, 1003, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 7, 57, 21, 20 +} + +IDD_INFO DIALOG 0, 0, 256, 138 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Support Informatie" +FONT 8, "MS Sans Serif" +{ + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 103, 116, 50, 14 + CONTROL "De volgende informatie kan gebruikt worden om technische ondersteuning te krijgen voor %s:", IDC_INFO_LABEL, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 12, 9, 228, 19 + CONTROL "Uitgever:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 30, 60, 8 + CONTROL "Versie:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 40, 60, 8 + CONTROL "Contact:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 50, 60, 8 + CONTROL "Support Informatie:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 60, 64, 8 + CONTROL "Support Telefoon:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 70, 68, 8 + CONTROL "Lees me:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 80, 60, 8 + CONTROL "Produkt Updates:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 90, 60, 8 + CONTROL "Commentaar:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 16, 100, 60, 8 + CONTROL "", IDC_INFO_PUBLISHER, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 30, 136, 8 + CONTROL "", IDC_INFO_VERSION, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 40, 136, 8 + CONTROL "", IDC_INFO_CONTACT, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 50, 136, 8 + CONTROL "", IDC_INFO_SUPPORT, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 60, 136, 8 + CONTROL "", IDC_INFO_PHONE, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 70, 136, 8 + CONTROL "", IDC_INFO_README, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 80, 136, 8 + CONTROL "", IDC_INFO_UPDATES, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 90, 136, 8 + CONTROL "", IDC_INFO_COMMENTS, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 104, 100, 136, 8 +} diff --git a/dlls/appwiz.cpl/appwiz.c b/dlls/appwiz.cpl/appwiz.c index 44bf3b24bdd..ce948636da2 100644 --- a/dlls/appwiz.cpl/appwiz.c +++ b/dlls/appwiz.cpl/appwiz.c @@ -404,8 +404,11 @@ static void UninstallProgram(int id) if (res) { + CloseHandle(info.hThread); + /* wait for the process to exit */ WaitForSingleObject(info.hProcess, INFINITE); + CloseHandle(info.hProcess); } else { diff --git a/dlls/appwiz.cpl/appwiz.rc b/dlls/appwiz.cpl/appwiz.rc index 8b839be3af2..8b88911b9b6 100644 --- a/dlls/appwiz.cpl/appwiz.rc +++ b/dlls/appwiz.cpl/appwiz.rc @@ -26,6 +26,7 @@ #include "res.h" #include "En.rc" +#include "Nl.rc" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/dlls/comctl32/tests/tooltips.c b/dlls/comctl32/tests/tooltips.c index e9bce637be8..c945a27f5db 100644 --- a/dlls/comctl32/tests/tooltips.c +++ b/dlls/comctl32/tests/tooltips.c @@ -232,10 +232,70 @@ static void test_customdraw(void) { } +static void test_gettext(void) +{ + HWND hwnd; + TTTOOLINFOA toolinfoA; + TTTOOLINFOW toolinfoW; + LRESULT r; + char bufA[10] = ""; + WCHAR bufW[10] = { 0 }; + + /* For bug 14790 - lpszText is NULL */ + hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, + 10, 10, 300, 100, + NULL, NULL, NULL, 0); + assert(hwnd); + + toolinfoA.cbSize = sizeof(TTTOOLINFOA); + toolinfoA.hwnd = NULL; + toolinfoA.hinst = GetModuleHandleA(NULL); + toolinfoA.uFlags = 0; + toolinfoA.uId = (UINT_PTR)0x1234ABCD; + toolinfoA.lpszText = NULL; + toolinfoA.lParam = 0xdeadbeef; + GetClientRect(hwnd, &toolinfoA.rect); + r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA); + ok(r, "Adding the tool to the tooltip failed\n"); + + toolinfoA.hwnd = NULL; + toolinfoA.uId = (UINT_PTR)0x1234ABCD; + toolinfoA.lpszText = bufA; + SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); + ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n"); + + DestroyWindow(hwnd); + + hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0, + 10, 10, 300, 100, + NULL, NULL, NULL, 0); + assert(hwnd); + + toolinfoW.cbSize = sizeof(TTTOOLINFOW); + toolinfoW.hwnd = NULL; + toolinfoW.hinst = GetModuleHandleA(NULL); + toolinfoW.uFlags = 0; + toolinfoW.uId = (UINT_PTR)0x1234ABCD; + toolinfoW.lpszText = NULL; + toolinfoW.lParam = 0xdeadbeef; + GetClientRect(hwnd, &toolinfoW.rect); + r = SendMessageW(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoW); + ok(r, "Adding the tool to the tooltip failed\n"); + + toolinfoW.hwnd = NULL; + toolinfoW.uId = (UINT_PTR)0x1234ABCD; + toolinfoW.lpszText = bufW; + SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW); + ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n"); + + DestroyWindow(hwnd); +} + START_TEST(tooltips) { InitCommonControls(); test_create_tooltip(); test_customdraw(); + test_gettext(); } diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c index f7e538b0f01..1149a07d96c 100644 --- a/dlls/comctl32/tooltips.c +++ b/dlls/comctl32/tooltips.c @@ -1574,6 +1574,9 @@ TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); if (nTool == -1) return 0; + if (infoPtr->tools[nTool].lpszText == NULL) + return 0; + strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText); return 0; diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index 51e11bfe3ba..a77792dd5e6 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -859,7 +859,7 @@ TREEVIEW_ComputeItemInternalMetrics(const TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM > TVS_LINESATROOT); #endif - item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1) + item->linesOffset = infoPtr->uIndent * (lar ? item->iLevel : item->iLevel - 1) - infoPtr->scrollX; item->stateOffset = item->linesOffset + infoPtr->uIndent; item->imageOffset = item->stateOffset diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index a5ef37dc2bf..485421f33da 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -148,7 +148,7 @@ @ stub CryptMsgCountersignEncoded @ stdcall CryptMsgDuplicate(ptr) @ stub CryptMsgEncodeAndSignCTL -@ stub CryptMsgGetAndVerifySigner +@ stdcall CryptMsgGetAndVerifySigner(ptr long ptr long ptr ptr) @ stdcall CryptMsgGetParam(ptr long long ptr ptr) @ stdcall CryptMsgOpenToDecode(long long long long ptr ptr) @ stdcall CryptMsgOpenToEncode(long long long ptr str ptr) diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 4571607e935..ff4e0f4f5a9 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -2445,3 +2445,119 @@ BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, pvCtrlPara); return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); } + +static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, + DWORD dwSignerIndex) +{ + CERT_INFO *certInfo = NULL; + DWORD size; + + if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, + &size)) + { + certInfo = CryptMemAlloc(size); + if (certInfo) + { + if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, + dwSignerIndex, certInfo, &size)) + { + CryptMemFree(certInfo); + certInfo = NULL; + } + } + } + return certInfo; +} + +BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore, + HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner, + DWORD *pdwSignerIndex) +{ + HCERTSTORE store; + DWORD i, signerIndex; + PCCERT_CONTEXT signerCert = NULL; + BOOL ret = FALSE; + + TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore, + rghSignerStore, dwFlags, ppSigner, pdwSignerIndex); + + /* Clear output parameters */ + if (ppSigner) + *ppSigner = NULL; + if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)) + *pdwSignerIndex = 0; + + /* Create store to search for signer certificates */ + store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG)) + { + HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, + hCryptMsg); + + CertAddStoreToCollection(store, msgStore, 0, 0); + CertCloseStore(msgStore, 0); + } + for (i = 0; i < cSignerStore; i++) + CertAddStoreToCollection(store, rghSignerStore[i], 0, 0); + + /* Find signer cert */ + if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG) + { + CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, + *pdwSignerIndex); + + if (signer) + { + signerIndex = *pdwSignerIndex; + signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING, + 0, CERT_FIND_SUBJECT_CERT, signer, NULL); + CryptMemFree(signer); + } + } + else + { + DWORD count, size = sizeof(count); + + if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count, + &size)) + { + for (i = 0; !signerCert && i < count; i++) + { + CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, + i); + + if (signer) + { + signerCert = CertFindCertificateInStore(store, + X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer, + NULL); + if (signerCert) + signerIndex = i; + CryptMemFree(signer); + } + } + } + if (!signerCert) + SetLastError(CRYPT_E_NO_TRUSTED_SIGNER); + } + if (signerCert) + { + if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG)) + ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, + signerCert->pCertInfo); + else + ret = TRUE; + if (ret) + { + if (ppSigner) + *ppSigner = CertDuplicateCertificateContext(signerCert); + if (pdwSignerIndex) + *pdwSignerIndex = signerIndex; + } + CertFreeCertificateContext(signerCert); + } + + CertCloseStore(store, 0); + return ret; +} diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index bfebeaada81..0f7dcb6860d 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -2561,6 +2561,121 @@ static BOOL detect_nt(void) return TRUE; } +static void test_msg_get_and_verify_signer(void) +{ + BOOL ret; + HCRYPTMSG msg; + PCCERT_CONTEXT signer; + DWORD signerIndex; + HCERTSTORE store; + + /* Crash */ + if (0) + { + ret = CryptMsgGetAndVerifySigner(NULL, 0, NULL, 0, NULL, NULL); + ret = CryptMsgGetAndVerifySigner(NULL, 0, NULL, 0, NULL, &signerIndex); + } + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + /* An empty message has no signer */ + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + /* The signer is cleared on error */ + signer = (PCCERT_CONTEXT)0xdeadbeef; + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + ok(!signer, "expected signer to be NULL\n"); + /* The signer index is also cleared on error */ + signerIndex = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + ok(!signerIndex, "expected 0, got %d\n", signerIndex); + /* An unsigned message (msgData isn't a signed message at all) + * likewise has no signer. + */ + CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + /* A "signed" message created with no signer cert likewise has no signer */ + CryptMsgUpdate(msg, signedEmptyContent, sizeof(signedEmptyContent), TRUE); + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + /* A signed message succeeds, .. */ + CryptMsgUpdate(msg, signedWithCertWithValidPubKeyContent, + sizeof(signedWithCertWithValidPubKeyContent), TRUE); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); + ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); + /* the signer index can be retrieved, .. */ + signerIndex = 0xdeadbeef; + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex); + ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); + ok(signerIndex == 0, "expected 0, got %d\n", signerIndex); + /* as can the signer cert. */ + signer = (PCCERT_CONTEXT)0xdeadbeef; + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL); + ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); + ok(signer != NULL && signer != (PCCERT_CONTEXT)0xdeadbeef, + "expected a valid signer\n"); + if (signer && signer != (PCCERT_CONTEXT)0xdeadbeef) + CertFreeCertificateContext(signer); + /* Specifying CMSG_USE_SIGNER_INDEX_FLAG and an invalid signer index fails + */ + signerIndex = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_USE_SIGNER_INDEX_FLAG, + NULL, &signerIndex); + ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX, + "expected CRYPT_E_INVALID_INDEX, got 0x%08x\n", GetLastError()); + /* Specifying CMSG_TRUSTED_SIGNER_FLAG and no cert stores causes the + * message signer not to be found. + */ + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_TRUSTED_SIGNER_FLAG, + NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + /* Specifying CMSG_TRUSTED_SIGNER_FLAG and an empty cert store also causes + * the message signer not to be found. + */ + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG, + NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, + "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); + ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, + v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey), + CERT_STORE_ADD_ALWAYS, NULL); + ok(ret, "CertAddEncodedCertificateToStore failed: 0x%08x\n", + GetLastError()); + /* Specifying CMSG_TRUSTED_SIGNER_FLAG with a cert store that contains + * the signer succeeds. + */ + SetLastError(0xdeadbeef); + ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG, + NULL, NULL); + ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); + CertCloseStore(store, 0); + CryptMsgClose(msg); +} + START_TEST(msg) { init_function_pointers(); @@ -2578,4 +2693,6 @@ START_TEST(msg) test_hash_msg(); test_signed_msg(); test_decode_msg(); + + test_msg_get_and_verify_signer(); } diff --git a/dlls/cryptnet/cryptnet_main.c b/dlls/cryptnet/cryptnet_main.c index 5bf1afe8be2..ffd4d64addf 100644 --- a/dlls/cryptnet/cryptnet_main.c +++ b/dlls/cryptnet/cryptnet_main.c @@ -219,8 +219,7 @@ static BOOL WINAPI CRYPT_GetUrlFromCertificateCRLDistPoint(LPCSTR pszUrlOid, pUrlArray->rgwszUrl[pUrlArray->cUrl++] = nextUrl; nextUrl += - (lstrlenW(name->rgAltEntry[j].u.pwszURL) + 1) - * sizeof(WCHAR); + (lstrlenW(name->rgAltEntry[j].u.pwszURL) + 1); } } } diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 7376525cda8..ddeaca30370 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1149,13 +1149,13 @@ static HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIREC static BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(LPDIRECT3DDEVICE9EX iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hr; + BOOL ret; TRACE("(%p) Relay\n" , This); EnterCriticalSection(&d3d9_cs); - hr = IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); + ret = IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); LeaveCriticalSection(&d3d9_cs); - return hr; + return ret; } static HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9EX iface, float nSegments) { @@ -1306,7 +1306,6 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9EX iface, DWORD FV EnterCriticalSection(&d3d9_cs); if (0 != FVF) { - HRESULT hr; IDirect3DVertexDeclaration9* pDecl = getConvertedDecl(This, FVF); if(!pDecl) { diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index ad3d7408608..2c4560e1d3c 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -620,13 +620,13 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam (LPDIRECTMUSIC TRACE("(%p, %s, %p, %d): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize); if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) - memcpy(pParam, &This->fAutoDownload, sizeof(&This->fAutoDownload)); + memcpy(pParam, &This->fAutoDownload, sizeof(This->fAutoDownload)); if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) - memcpy(pParam, &This->cMasterGrooveLevel, sizeof(&This->cMasterGrooveLevel)); + memcpy(pParam, &This->cMasterGrooveLevel, sizeof(This->cMasterGrooveLevel)); if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) - memcpy(pParam, &This->fMasterTempo, sizeof(&This->fMasterTempo)); + memcpy(pParam, &This->fMasterTempo, sizeof(This->fMasterTempo)); if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) - memcpy(pParam, &This->lMasterVolume, sizeof(&This->lMasterVolume)); + memcpy(pParam, &This->lMasterVolume, sizeof(This->lMasterVolume)); return S_OK; } diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index c1eb0376ae0..e8b7f21ef57 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1007,12 +1007,12 @@ static BOOL FAR PASCAL EnumSessions_cb2( LPCDPSESSIONDESC2 lpThisSD, if ( lpThisSD->dwFlags & DPSESSION_PASSWORDREQUIRED ) { /* Incorrect password */ - dpsd.lpszPasswordA = (LPSTR) "sonic boom"; + U2(dpsd).lpszPasswordA = (LPSTR) "sonic boom"; hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); checkHR( DPERR_INVALIDPASSWORD, hr ); /* Correct password */ - dpsd.lpszPasswordA = (LPSTR) "hadouken"; + U2(dpsd).lpszPasswordA = (LPSTR) "hadouken"; hr = IDirectPlayX_Open( pDP, &dpsd, DPOPEN_JOIN ); checkHR( DP_OK, hr ); } @@ -1138,7 +1138,7 @@ static void test_Open(void) /* Join to protected session */ IDirectPlayX_Close( pDP_server ); - dpsd_server.lpszPasswordA = (LPSTR) "hadouken"; + U2(dpsd_server).lpszPasswordA = (LPSTR) "hadouken"; hr = IDirectPlayX_Open( pDP_server, &dpsd_server, DPOPEN_CREATE ); todo_wine checkHR( DP_OK, hr ); @@ -1169,7 +1169,7 @@ static BOOL FAR PASCAL EnumSessions_cb( LPCDPSESSIONDESC2 lpThisSD, check( FALSE, lpThisSD == NULL ); - if ( lpThisSD->lpszPasswordA != NULL ) + if ( U2(*lpThisSD).lpszPasswordA != NULL ) { check( TRUE, (lpThisSD->dwFlags & DPSESSION_PASSWORDREQUIRED) != 0 ); } @@ -1180,7 +1180,7 @@ static BOOL FAR PASCAL EnumSessions_cb( LPCDPSESSIONDESC2 lpThisSD, } check( sizeof(*lpThisSD), lpThisSD->dwSize ); - checkLP( NULL, lpThisSD->lpszPasswordA ); + checkLP( NULL, U2(*lpThisSD).lpszPasswordA ); return TRUE; } @@ -1207,7 +1207,7 @@ static LPDIRECTPLAY4 create_session(DPSESSIONDESC2 *lpdpsd) { ZeroMemory( &name, sizeof(DPNAME) ); name.dwSize = sizeof(DPNAME); - name.lpszShortNameA = (LPSTR) "bofh"; + U1(name).lpszShortNameA = (LPSTR) "bofh"; hr = IDirectPlayX_CreatePlayer( pDP, &dpid, &name, NULL, NULL, 0, DPPLAYER_SERVERPLAYER ); @@ -1277,41 +1277,41 @@ static void test_EnumSessions(void) memcpy( &dpsd_server[i], &dpsd, sizeof(DPSESSIONDESC2) ); } - dpsd_server[0].lpszSessionNameA = (LPSTR) "normal"; + U1(dpsd_server[0]).lpszSessionNameA = (LPSTR) "normal"; dpsd_server[0].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL ); dpsd_server[0].dwMaxPlayers = 10; - dpsd_server[1].lpszSessionNameA = (LPSTR) "full"; + U1(dpsd_server[1]).lpszSessionNameA = (LPSTR) "full"; dpsd_server[1].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL ); dpsd_server[1].dwMaxPlayers = 1; - dpsd_server[2].lpszSessionNameA = (LPSTR) "no new"; + U1(dpsd_server[2]).lpszSessionNameA = (LPSTR) "no new"; dpsd_server[2].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_NEWPLAYERSDISABLED ); dpsd_server[2].dwMaxPlayers = 10; - dpsd_server[3].lpszSessionNameA = (LPSTR) "no join"; + U1(dpsd_server[3]).lpszSessionNameA = (LPSTR) "no join"; dpsd_server[3].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_JOINDISABLED ); dpsd_server[3].dwMaxPlayers = 10; - dpsd_server[4].lpszSessionNameA = (LPSTR) "private"; + U1(dpsd_server[4]).lpszSessionNameA = (LPSTR) "private"; dpsd_server[4].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_PRIVATE ); dpsd_server[4].dwMaxPlayers = 10; - dpsd_server[4].lpszPasswordA = (LPSTR) "password"; + U2(dpsd_server[4]).lpszPasswordA = (LPSTR) "password"; - dpsd_server[5].lpszSessionNameA = (LPSTR) "protected"; + U1(dpsd_server[5]).lpszSessionNameA = (LPSTR) "protected"; dpsd_server[5].dwFlags = ( DPSESSION_CLIENTSERVER | DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_PASSWORDREQUIRED ); dpsd_server[5].dwMaxPlayers = 10; - dpsd_server[5].lpszPasswordA = (LPSTR) "password"; + U2(dpsd_server[5]).lpszPasswordA = (LPSTR) "password"; for (i=0; iguidInstance, &lpData[1]->guidInstance ); /* Set: Regular operation */ - dpsd.lpszSessionNameA = (LPSTR) "Wahaa"; + U1(dpsd).lpszSessionNameA = (LPSTR) "Wahaa"; hr = IDirectPlayX_SetSessionDesc( pDP[0], &dpsd, 0 ); checkHR( DP_OK, hr ); dwDataSize = 1024; hr = IDirectPlayX_GetSessionDesc( pDP[1], lpData[1], &dwDataSize ); checkHR( DP_OK, hr ); - checkStr( dpsd.lpszSessionNameA, lpData[1]->lpszSessionNameA ); + checkStr( U1(dpsd).lpszSessionNameA, U1(*lpData[1]).lpszSessionNameA ); /* Set: Failing to modify a remote session */ @@ -1816,8 +1816,8 @@ static void test_CreatePlayer(void) name.dwSize = sizeof(DPNAME); - name.lpszShortNameA = (LPSTR) "test"; - name.lpszLongNameA = NULL; + U1(name).lpszShortNameA = (LPSTR) "test"; + U2(name).lpszLongNameA = NULL; hr = IDirectPlayX_CreatePlayer( pDP[0], &dpid, &name, NULL, NULL, @@ -2443,8 +2443,8 @@ static void test_PlayerName(void) playerName.dwSize = sizeof(DPNAME); - playerName.lpszShortNameA = (LPSTR) "player_name"; - playerName.lpszLongNameA = (LPSTR) "player_long_name"; + U1(playerName).lpszShortNameA = (LPSTR) "player_name"; + U2(playerName).lpszLongNameA = (LPSTR) "player_long_name"; /* Invalid parameters */ @@ -2480,8 +2480,8 @@ static void test_PlayerName(void) hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); checkHR( DP_OK, hr ); check( 45, dwDataSize ); - checkStr( playerName.lpszShortNameA, ((LPDPNAME)lpData)->lpszShortNameA ); - checkStr( playerName.lpszLongNameA, ((LPDPNAME)lpData)->lpszLongNameA ); + checkStr( U1(playerName).lpszShortNameA, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkStr( U2(playerName).lpszLongNameA, U2(*(LPDPNAME)lpData).lpszLongNameA ); check( 0, ((LPDPNAME)lpData)->dwFlags ); hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], NULL, 0 ); @@ -2490,8 +2490,8 @@ static void test_PlayerName(void) hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); checkHR( DP_OK, hr ); check( 16, dwDataSize ); - checkLP( NULL, ((LPDPNAME)lpData)->lpszShortNameA ); - checkLP( NULL, ((LPDPNAME)lpData)->lpszLongNameA ); + checkLP( NULL, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkLP( NULL, U2(*(LPDPNAME)lpData).lpszLongNameA ); check( 0, ((LPDPNAME)lpData)->dwFlags ); @@ -2509,8 +2509,8 @@ static void test_PlayerName(void) hr = IDirectPlayX_GetPlayerName( pDP[0], dpid[0], lpData, &dwDataSize ); checkHR( DP_OK, hr ); check( 16, dwDataSize ); - checkLP( NULL, ((LPDPNAME)lpData)->lpszShortNameA ); - checkLP( NULL, ((LPDPNAME)lpData)->lpszLongNameA ); + checkLP( NULL, U1(*(LPDPNAME)lpData).lpszShortNameA ); + checkLP( NULL, U2(*(LPDPNAME)lpData).lpszLongNameA ); check( 0, ((LPDPNAME)lpData)->dwFlags ); @@ -2520,7 +2520,7 @@ static void test_PlayerName(void) checkHR( DP_OK, hr ); /* - Local (no propagation) */ - playerName.lpszShortNameA = (LPSTR) "no_propagation"; + U1(playerName).lpszShortNameA = (LPSTR) "no_propagation"; hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, DPSET_LOCAL ); checkHR( DP_OK, hr ); @@ -2530,18 +2530,18 @@ static void test_PlayerName(void) lpData, &dwDataSize ); /* Local fetch */ checkHR( DP_OK, hr ); check( 48, dwDataSize ); - checkStr( "no_propagation", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "no_propagation", U1(*(LPDPNAME)lpData).lpszShortNameA ); dwDataSize = 1024; hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], lpData, &dwDataSize ); /* Remote fetch */ checkHR( DP_OK, hr ); check( 45, dwDataSize ); - checkStr( "player_name", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "player_name", U1(*(LPDPNAME)lpData).lpszShortNameA ); /* -- 2 */ - playerName.lpszShortNameA = (LPSTR) "no_propagation_2"; + U1(playerName).lpszShortNameA = (LPSTR) "no_propagation_2"; hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, DPSET_LOCAL | DPSET_REMOTE ); checkHR( DP_OK, hr ); @@ -2551,17 +2551,17 @@ static void test_PlayerName(void) lpData, &dwDataSize ); /* Local fetch */ checkHR( DP_OK, hr ); check( 50, dwDataSize ); - checkStr( "no_propagation_2", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "no_propagation_2", U1(*(LPDPNAME)lpData).lpszShortNameA ); dwDataSize = 1024; hr = IDirectPlayX_GetPlayerName( pDP[1], dpid[0], lpData, &dwDataSize ); /* Remote fetch */ checkHR( DP_OK, hr ); check( 45, dwDataSize ); - checkStr( "player_name", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "player_name", U1(*(LPDPNAME)lpData).lpszShortNameA ); /* - Remote (propagation, default) */ - playerName.lpszShortNameA = (LPSTR) "propagation"; + U1(playerName).lpszShortNameA = (LPSTR) "propagation"; hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, DPSET_REMOTE ); checkHR( DP_OK, hr ); @@ -2571,10 +2571,10 @@ static void test_PlayerName(void) lpData, &dwDataSize ); /* Remote fetch */ checkHR( DP_OK, hr ); check( 45, dwDataSize ); - checkStr( "propagation", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "propagation", U1(*(LPDPNAME)lpData).lpszShortNameA ); /* -- 2 */ - playerName.lpszShortNameA = (LPSTR) "propagation_2"; + U1(playerName).lpszShortNameA = (LPSTR) "propagation_2"; hr = IDirectPlayX_SetPlayerName( pDP[0], dpid[0], &playerName, 0 ); checkHR( DP_OK, hr ); @@ -2584,7 +2584,7 @@ static void test_PlayerName(void) lpData, &dwDataSize ); /* Remote fetch */ checkHR( DP_OK, hr ); check( 47, dwDataSize ); - checkStr( "propagation_2", ((LPDPNAME)lpData)->lpszShortNameA ); + checkStr( "propagation_2", U1(*(LPDPNAME)lpData).lpszShortNameA ); /* Checking system messages */ @@ -2628,8 +2628,8 @@ static BOOL FAR PASCAL EnumSessions_cb_join_secure( LPCDPSESSIONDESC2 lpThisSD, ZeroMemory( &dpCredentials, sizeof(DPCREDENTIALS) ); dpCredentials.dwSize = sizeof(DPCREDENTIALS); - dpCredentials.lpszUsernameA = (LPSTR) "user"; - dpCredentials.lpszPasswordA = (LPSTR) "pass"; + U1(dpCredentials).lpszUsernameA = (LPSTR) "user"; + U2(dpCredentials).lpszPasswordA = (LPSTR) "pass"; hr = IDirectPlayX_SecureOpen( pDP, &dpsd, DPOPEN_JOIN, NULL, &dpCredentials ); checkHR( DPERR_LOGONDENIED, hr ); /* TODO: Make this work */ diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index 01f69a8c599..908670e00b5 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -61,7 +61,7 @@ static HGLOBAL16 dib_copy(const BITMAPINFO *info, UINT coloruse) HGLOBAL16 hmem; INT size; - if (info->bmiHeader.biCompression) + if (info->bmiHeader.biCompression != BI_RGB && info->bmiHeader.biCompression != BI_BITFIELDS) size = info->bmiHeader.biSizeImage; else size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 4c4abe09150..12224c9110f 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -1552,7 +1552,6 @@ todo_wine } /* returned bits are DWORD aligned and upside down */ -todo_wine ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't match\n"); DeleteObject(hbmp); diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c index 070a80f993b..5e449e2f348 100644 --- a/dlls/gdiplus/gdiplus.c +++ b/dlls/gdiplus/gdiplus.c @@ -311,3 +311,36 @@ void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, *x = roundr(tension * (xadj - xend) + xend); *y = roundr(tension * (yadj - yend) + yend); } + +/* make sure path has enough space for len more points */ +BOOL lengthen_path(GpPath *path, INT len) +{ + /* initial allocation */ + if(path->datalen == 0){ + path->datalen = len * 2; + + path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF)); + if(!path->pathdata.Points) return FALSE; + + path->pathdata.Types = GdipAlloc(path->datalen); + if(!path->pathdata.Types){ + GdipFree(path->pathdata.Points); + return FALSE; + } + } + /* reallocation, double size of arrays */ + else if(path->datalen - path->pathdata.Count < len){ + while(path->datalen - path->pathdata.Count < len) + path->datalen *= 2; + + path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0, + path->pathdata.Points, path->datalen * sizeof(PointF)); + if(!path->pathdata.Points) return FALSE; + + path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0, + path->pathdata.Types, path->datalen); + if(!path->pathdata.Types) return FALSE; + } + + return TRUE; +} diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 57f9734251a..d3eaeb6ae5e 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -455,12 +455,12 @@ @ stdcall GdipPathIterGetCount(ptr ptr) @ stdcall GdipPathIterGetSubpathCount(ptr ptr) @ stdcall GdipPathIterHasCurve(ptr ptr) -@ stub GdipPathIterIsValid +@ stdcall GdipPathIterIsValid(ptr ptr) @ stdcall GdipPathIterNextMarker(ptr ptr ptr ptr) @ stub GdipPathIterNextMarkerPath @ stub GdipPathIterNextPathType @ stdcall GdipPathIterNextSubpath(ptr ptr ptr ptr ptr) -@ stub GdipPathIterNextSubpathPath +@ stdcall GdipPathIterNextSubpathPath(ptr ptr ptr ptr) @ stdcall GdipPathIterRewind(ptr) @ stub GdipPlayMetafileRecord @ stub GdipPlayTSClientRecord @@ -482,7 +482,7 @@ @ stub GdipResetPathGradientTransform @ stub GdipResetPenTransform @ stub GdipResetTextureTransform -@ stub GdipResetWorldTransform +@ stdcall GdipResetWorldTransform(ptr) @ stdcall GdipRestoreGraphics(ptr long) @ stdcall GdipReversePath(ptr) @ stub GdipRotateLineTransform diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 3611239f2b2..5a186602f2e 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -52,6 +52,8 @@ extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, REAL tension, REAL *x, REAL *y); +extern BOOL lengthen_path(GpPath *path, INT len); + static inline INT roundr(REAL x) { return (INT) floorf(x + 0.5); diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 2450b479504..3a7ffcee7d6 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -2343,6 +2343,21 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics, return Ok; } +GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics) +{ + if(!graphics) + return InvalidParameter; + + graphics->worldtrans->matrix[0] = 1.0; + graphics->worldtrans->matrix[1] = 0.0; + graphics->worldtrans->matrix[2] = 0.0; + graphics->worldtrans->matrix[3] = 1.0; + graphics->worldtrans->matrix[4] = 0.0; + graphics->worldtrans->matrix[5] = 0.0; + + return Ok; +} + GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state) { static int calls; diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 51407c71d82..d465aaf8bda 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -33,39 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); -/* make sure path has enough space for len more points */ -static BOOL lengthen_path(GpPath *path, INT len) -{ - /* initial allocation */ - if(path->datalen == 0){ - path->datalen = len * 2; - - path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF)); - if(!path->pathdata.Points) return FALSE; - - path->pathdata.Types = GdipAlloc(path->datalen); - if(!path->pathdata.Types){ - GdipFree(path->pathdata.Points); - return FALSE; - } - } - /* reallocation, double size of arrays */ - else if(path->datalen - path->pathdata.Count < len){ - while(path->datalen - path->pathdata.Count < len) - path->datalen *= 2; - - path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0, - path->pathdata.Points, path->datalen * sizeof(PointF)); - if(!path->pathdata.Points) return FALSE; - - path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0, - path->pathdata.Types, path->datalen); - if(!path->pathdata.Types) return FALSE; - } - - return TRUE; -} - GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle) { diff --git a/dlls/gdiplus/pathiterator.c b/dlls/gdiplus/pathiterator.c index 95f17748d64..afb4f34d2f4 100644 --- a/dlls/gdiplus/pathiterator.c +++ b/dlls/gdiplus/pathiterator.c @@ -164,8 +164,10 @@ GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator, count = iterator->pathdata.Count; /* iterator created with NULL path */ - if(count == 0) + if(count == 0){ + *resultCount = 0; return Ok; + } if(iterator->subpath_pos == count){ *startIndex = *endIndex = *resultCount = 0; @@ -225,3 +227,37 @@ GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator* iterator, INT* resultC return GdipPathIterCopyData(iterator, resultCount, points, types, 0, count-1); } + +GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid) +{ + if(!iterator || !valid) + return InvalidParameter; + + *valid = TRUE; + + return Ok; +} + +GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result, + GpPath* path, BOOL* closed) +{ + INT start, end; + + if(!iter || !result || !closed) + return InvalidParameter; + + GdipPathIterNextSubpath(iter, result, &start, &end, closed); + /* return path */ + if(((*result) > 0) && path){ + GdipResetPath(path); + + if(!lengthen_path(path, *result)) + return OutOfMemory; + + memcpy(path->pathdata.Points, &(iter->pathdata.Points[start]), sizeof(GpPointF)*(*result)); + memcpy(path->pathdata.Types, &(iter->pathdata.Types[start]), sizeof(BYTE)*(*result)); + path->pathdata.Count = *result; + } + + return Ok; +} diff --git a/dlls/gdiplus/tests/pathiterator.c b/dlls/gdiplus/tests/pathiterator.c index a6adb197c53..9cbed1390d0 100644 --- a/dlls/gdiplus/tests/pathiterator.c +++ b/dlls/gdiplus/tests/pathiterator.c @@ -214,6 +214,185 @@ static void test_getsubpathcount(void) GdipDeletePath(path); } +static void test_isvalid(void) +{ + GpPath *path; + GpPathIterator *iter; + GpStatus stat; + BOOL isvalid; + INT start, end, result; + + GdipCreatePath(FillModeAlternate, &path); + + /* NULL args */ + GdipCreatePathIter(&iter, path); + stat = GdipPathIterIsValid(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterIsValid(iter, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterIsValid(NULL, &isvalid); + expect(InvalidParameter, stat); + GdipDeletePathIter(iter); + + /* on empty path */ + GdipCreatePathIter(&iter, path); + isvalid = FALSE; + stat = GdipPathIterIsValid(iter, &isvalid); + expect(Ok, stat); + expect(TRUE, isvalid); + GdipDeletePathIter(iter); + + /* no markers */ + GdipAddPathLine(path, 50.0, 50.0, 110.0, 40.0); + GdipCreatePathIter(&iter, path); + GdipPathIterNextMarker(iter, &result, &start, &end); + isvalid = FALSE; + stat = GdipPathIterIsValid(iter, &isvalid); + expect(Ok, stat); + expect(TRUE, isvalid); + GdipDeletePathIter(iter); + + GdipDeletePath(path); +} + +static void test_nextsubpathpath(void) +{ + GpPath *path, *retpath; + GpPathIterator *iter; + GpStatus stat; + BOOL closed; + INT count, result; + + GdipCreatePath(FillModeAlternate, &path); + + /* NULL args */ + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + stat = GdipPathIterNextSubpathPath(NULL, NULL, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(NULL, &result, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, &result, NULL, &closed); + expect(Ok, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, &closed); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, retpath, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, NULL); + expect(InvalidParameter, stat); + GdipDeletePathIter(iter); + GdipDeletePath(retpath); + + /* empty path */ + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(0, count); + GdipDeletePathIter(iter); + GdipDeletePath(retpath); + + /* open figure */ + GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0); + + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(FALSE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + /* subsequent call */ + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + GdipDeletePathIter(iter); + + /* closed figure, check does it extend retpath or reset it */ + GdipAddPathLine(retpath, 50.0, 55.0, 200.0, 150.0); + + GdipClosePathFigure(path); + GdipAddPathLine(path, 50.0, 55.0, 200.0, 150.0); + GdipClosePathFigure(path); + + GdipCreatePathIter(&iter, path); + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + /* subsequent call */ + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + GdipDeletePathIter(iter); + + GdipDeletePath(retpath); + GdipDeletePath(path); +} + +static void test_nextsubpath(void) +{ + GpPath *path; + GpPathIterator *iter; + GpStatus stat; + INT start, end, result; + BOOL closed; + + GdipCreatePath(FillModeAlternate, &path); + + /* empty path */ + GdipCreatePath(FillModeAlternate, &path); + GdipCreatePathIter(&iter, path); + + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpath(iter, &result, &start, &end, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + GdipCreatePathIter(&iter, path); + + GdipDeletePath(path); +} + START_TEST(pathiterator) { struct GdiplusStartupInput gdiplusStartupInput; @@ -230,6 +409,9 @@ START_TEST(pathiterator) test_hascurve(); test_nextmarker(); test_getsubpathcount(); + test_isvalid(); + test_nextsubpathpath(); + test_nextsubpath(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/hhctrl.ocx/help.c b/dlls/hhctrl.ocx/help.c index 0e81a990f59..6a694a94619 100644 --- a/dlls/hhctrl.ocx/help.c +++ b/dlls/hhctrl.ocx/help.c @@ -89,7 +89,7 @@ BOOL NavigateToUrl(HHInfo *info, LPCWSTR surl) BOOL ret; HRESULT hres; - static const WCHAR url_indicator[] = {':', '/', '/'}; + static const WCHAR url_indicator[] = {':', '/', '/', 0}; TRACE("%s\n", debugstr_w(surl)); diff --git a/dlls/hhctrl.ocx/webbrowser.c b/dlls/hhctrl.ocx/webbrowser.c index c9caa38f1fa..5033197c0a8 100644 --- a/dlls/hhctrl.ocx/webbrowser.c +++ b/dlls/hhctrl.ocx/webbrowser.c @@ -365,8 +365,12 @@ static HRESULT STDMETHODCALLTYPE InPlace_OnPosRectChange(IOleInPlaceSite *iface, ICOM_THIS_MULTI(IOleClientSiteImpl, lpvtblOleInPlaceSite, iface); IOleInPlaceObject *inplace; - if (!IOleObject_QueryInterface(This->pBrowserObject, &IID_IOleInPlaceObject, (void **)&inplace)) + if (IOleObject_QueryInterface(This->pBrowserObject, &IID_IOleInPlaceObject, + (void **)&inplace) == S_OK) + { IOleInPlaceObject_SetObjectRects(inplace, lprcPosRect, lprcPosRect); + IOleInPlaceObject_Release(inplace); + } return S_OK; } diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 5fdb3073c65..03668945a21 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -2867,12 +2867,15 @@ void LOCALE_Init(void) CFArrayRef preferred_locales, all_locales; CFStringRef user_language_string_ref = NULL; char user_locale[50]; + char* p; CFLocaleRef user_locale_ref = CFLocaleCopyCurrent(); CFStringRef user_locale_string_ref = CFLocaleGetIdentifier( user_locale_ref ); CFStringGetCString( user_locale_string_ref, user_locale, sizeof(user_locale), kCFStringEncodingUTF8 ); CFRelease( user_locale_ref ); + /* Strip modifiers because setlocale() can't parse them. */ + if (p = strchr( user_locale, '@' )) *p = 0; if (!strchr( user_locale, '.' )) strcat( user_locale, ".UTF-8" ); unix_cp = CP_UTF8; /* default to utf-8 even if we don't get a valid locale */ setenv( "LANG", user_locale, 0 ); diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c index 74622ad5e08..ac983ffeedd 100644 --- a/dlls/kernel32/profile.c +++ b/dlls/kernel32/profile.c @@ -755,7 +755,7 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) TRACE("path: %s\n", debugstr_w(buffer)); hFile = CreateFileW(buffer, GENERIC_READ | (write_access ? GENERIC_WRITE : 0), - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_FILE_NOT_FOUND)) diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 52919042111..bd6dd05d84a 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -1342,7 +1342,7 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut) if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) || nt_name.Length < sizeof(leadin) || - strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(WCHAR) != 0)) + strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(WCHAR)) != 0) { RtlFreeUnicodeString( &nt_name ); SetLastError( ERROR_PATH_NOT_FOUND ); diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c index 2ea39555730..47b1ac1afa2 100644 --- a/dlls/kernel32/tests/profile.c +++ b/dlls/kernel32/tests/profile.c @@ -348,6 +348,27 @@ static void test_profile_existing(void) ok( DeleteFile(testfile2), "delete failed\n" ); } +static void test_profile_delete_on_close() +{ + static CHAR testfile[] = ".\\testwine5.ini"; + HANDLE h; + DWORD size, res; + static const char contents[] = "[" SECTION "]\n" KEY "=123\n"; + + h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); + ok( WriteFile( h, contents, sizeof contents - 1, &size, NULL ), + "Cannot write test file: %x\n", GetLastError() ); + ok( size == sizeof contents - 1, "Test file: partial write\n"); + + res = GetPrivateProfileInt(SECTION, KEY, 0, testfile); + + ok( res == 123, "Got %d instead of 123\n", res); + + /* This also deletes the file */ + CloseHandle(h); +} + static void create_test_file(LPCSTR name, LPCSTR data, DWORD size) { HANDLE hfile; @@ -615,5 +636,6 @@ START_TEST(profile) test_profile_sections(); test_profile_sections_names(); test_profile_existing(); + test_profile_delete_on_close(); test_GetPrivateProfileString(); } diff --git a/dlls/kernel32/time.c b/dlls/kernel32/time.c index 9f33af635f8..29b3dc8d286 100644 --- a/dlls/kernel32/time.c +++ b/dlls/kernel32/time.c @@ -651,16 +651,16 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, switch (CalType & ~(CAL_NOUSEROVERRIDE|CAL_RETURN_NUMBER|CAL_USE_CP_ACP)) { case CAL_ICALINTVALUE: FIXME("Unimplemented caltype %d\n", CalType & 0xffff); - return E_FAIL; + return 0; case CAL_SCALNAME: FIXME("Unimplemented caltype %d\n", CalType & 0xffff); - return E_FAIL; + return 0; case CAL_IYEAROFFSETRANGE: FIXME("Unimplemented caltype %d\n", CalType & 0xffff); - return E_FAIL; + return 0; case CAL_SERASTRING: FIXME("Unimplemented caltype %d\n", CalType & 0xffff); - return E_FAIL; + return 0; case CAL_SSHORTDATE: return GetLocaleInfoW(Locale, LOCALE_SSHORTDATE, lpCalData, cchData); case CAL_SLONGDATE: @@ -750,8 +750,10 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, case CAL_ITWODIGITYEARMAX: if (lpValue) *lpValue = CALINFO_MAX_YEAR; break; - default: MESSAGE("Unknown caltype %d\n",CalType & 0xffff); - return E_FAIL; + default: + FIXME("Unknown caltype %d\n",CalType & 0xffff); + SetLastError(ERROR_INVALID_FLAGS); + return 0; } return 0; } diff --git a/dlls/mshtml/htmlanchor.c b/dlls/mshtml/htmlanchor.c index 866329176eb..48095438bee 100644 --- a/dlls/mshtml/htmlanchor.c +++ b/dlls/mshtml/htmlanchor.c @@ -67,16 +67,14 @@ static ULONG WINAPI HTMLAnchorElement_Release(IHTMLAnchorElement *iface) static HRESULT WINAPI HTMLAnchorElement_GetTypeInfoCount(IHTMLAnchorElement *iface, UINT *pctinfo) { HTMLAnchorElement *This = HTMLANCHOR_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->element.node.dispex), pctinfo); } static HRESULT WINAPI HTMLAnchorElement_GetTypeInfo(IHTMLAnchorElement *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { HTMLAnchorElement *This = HTMLANCHOR_THIS(iface); - FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->element.node.dispex), iTInfo, lcid, ppTInfo); } static HRESULT WINAPI HTMLAnchorElement_GetIDsOfNames(IHTMLAnchorElement *iface, REFIID riid, @@ -84,9 +82,7 @@ static HRESULT WINAPI HTMLAnchorElement_GetIDsOfNames(IHTMLAnchorElement *iface, LCID lcid, DISPID *rgDispId) { HTMLAnchorElement *This = HTMLANCHOR_THIS(iface); - FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->element.node.dispex), riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI HTMLAnchorElement_Invoke(IHTMLAnchorElement *iface, DISPID dispIdMember, @@ -94,9 +90,8 @@ static HRESULT WINAPI HTMLAnchorElement_Invoke(IHTMLAnchorElement *iface, DISPID VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLAnchorElement *This = HTMLANCHOR_THIS(iface); - FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return E_NOTIMPL; + return IDispatchEx_Invoke(DISPATCHEX(&This->element.node.dispex), dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI HTMLAnchorElement_put_href(IHTMLAnchorElement *iface, BSTR v) diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 244661f9179..3aa5f29bc2a 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -103,16 +103,14 @@ static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface) static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->node.dispex), pctinfo); } static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->node.dispex), iTInfo, lcid, ppTInfo); } static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid, @@ -120,9 +118,7 @@ static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid LCID lcid, DISPID *rgDispId) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->node.dispex), riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember, @@ -130,9 +126,8 @@ static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMembe VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return E_NOTIMPL; + return IDispatchEx_Invoke(DISPATCHEX(&This->node.dispex), dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName, diff --git a/dlls/mshtml/htmlelem2.c b/dlls/mshtml/htmlelem2.c index 3455517d316..e7319efb74f 100644 --- a/dlls/mshtml/htmlelem2.c +++ b/dlls/mshtml/htmlelem2.c @@ -56,16 +56,14 @@ static ULONG WINAPI HTMLElement2_Release(IHTMLElement2 *iface) static HRESULT WINAPI HTMLElement2_GetTypeInfoCount(IHTMLElement2 *iface, UINT *pctinfo) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->node.dispex), pctinfo); } static HRESULT WINAPI HTMLElement2_GetTypeInfo(IHTMLElement2 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->node.dispex), iTInfo, lcid, ppTInfo); } static HRESULT WINAPI HTMLElement2_GetIDsOfNames(IHTMLElement2 *iface, REFIID riid, @@ -73,9 +71,7 @@ static HRESULT WINAPI HTMLElement2_GetIDsOfNames(IHTMLElement2 *iface, REFIID ri LCID lcid, DISPID *rgDispId) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->node.dispex), riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI HTMLElement2_Invoke(IHTMLElement2 *iface, DISPID dispIdMember, @@ -83,9 +79,8 @@ static HRESULT WINAPI HTMLElement2_Invoke(IHTMLElement2 *iface, DISPID dispIdMem VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return E_NOTIMPL; + return IDispatchEx_Invoke(DISPATCHEX(&This->node.dispex), dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI HTMLElement2_get_scopeName(IHTMLElement2 *iface, BSTR *p) diff --git a/dlls/mshtml/htmlstyle.c b/dlls/mshtml/htmlstyle.c index e4bc48329e3..b4c48d4376f 100644 --- a/dlls/mshtml/htmlstyle.c +++ b/dlls/mshtml/htmlstyle.c @@ -279,16 +279,14 @@ static ULONG WINAPI HTMLStyle_Release(IHTMLStyle *iface) static HRESULT WINAPI HTMLStyle_GetTypeInfoCount(IHTMLStyle *iface, UINT *pctinfo) { HTMLStyle *This = HTMLSTYLE_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo); } static HRESULT WINAPI HTMLStyle_GetTypeInfo(IHTMLStyle *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { HTMLStyle *This = HTMLSTYLE_THIS(iface); - FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo); } static HRESULT WINAPI HTMLStyle_GetIDsOfNames(IHTMLStyle *iface, REFIID riid, @@ -296,9 +294,7 @@ static HRESULT WINAPI HTMLStyle_GetIDsOfNames(IHTMLStyle *iface, REFIID riid, LCID lcid, DISPID *rgDispId) { HTMLStyle *This = HTMLSTYLE_THIS(iface); - FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI HTMLStyle_Invoke(IHTMLStyle *iface, DISPID dispIdMember, @@ -306,9 +302,8 @@ static HRESULT WINAPI HTMLStyle_Invoke(IHTMLStyle *iface, DISPID dispIdMember, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLStyle *This = HTMLSTYLE_THIS(iface); - FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return E_NOTIMPL; + return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI HTMLStyle_put_fontFamily(IHTMLStyle *iface, BSTR v) @@ -455,8 +450,10 @@ static HRESULT WINAPI HTMLStyle_put_background(IHTMLStyle *iface, BSTR v) static HRESULT WINAPI HTMLStyle_get_background(IHTMLStyle *iface, BSTR *p) { HTMLStyle *This = HTMLSTYLE_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + return get_style_attr(This, attrBackground, p); } static HRESULT WINAPI HTMLStyle_put_backgroundColor(IHTMLStyle *iface, VARIANT v) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 2d2fe6c1ce3..2c4ff141fc9 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -3771,7 +3771,11 @@ static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param) &si, &info); if (brc) + { + CloseHandle(info.hThread); msi_dialog_check_messages(info.hProcess); + CloseHandle(info.hProcess); + } msi_free(FullName); diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index c5dd57da07e..9055c599a79 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -372,6 +372,53 @@ done: return r; } +static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context, + MSIPACKAGE **package) +{ + UINT r; + DWORD sz; + HKEY props; + LPWSTR localpack; + WCHAR sourcepath[MAX_PATH]; + WCHAR filename[MAX_PATH]; + + static const WCHAR szLocalPackage[] = { + 'L','o','c','a','l','P','a','c','k','a','g','e',0}; + + if (context == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenLocalSystemInstallProps(product, &props, FALSE); + else + r = MSIREG_OpenCurrentUserInstallProps(product, &props, FALSE); + + if (r != ERROR_SUCCESS) + return ERROR_BAD_CONFIGURATION; + + localpack = msi_reg_get_val_str(props, szLocalPackage); + if (localpack) + { + lstrcpyW(sourcepath, localpack); + msi_free(localpack); + } + + if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES) + { + sz = sizeof(sourcepath); + MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT, + INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); + + sz = sizeof(filename); + MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT, + INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); + + lstrcatW(sourcepath, filename); + } + + if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES) + return ERROR_INSTALL_SOURCE_ABSENT; + + return MSI_OpenPackageW(sourcepath, package); +} + UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState, LPCWSTR szCommandLine) { @@ -380,7 +427,6 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, UINT r; DWORD sz; WCHAR sourcepath[MAX_PATH]; - WCHAR filename[MAX_PATH]; LPWSTR commandline; static const WCHAR szInstalled[] = { @@ -407,16 +453,7 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, if (r != ERROR_SUCCESS) return r; - sz = sizeof(sourcepath); - MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, - INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); - - sz = sizeof(filename); - MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, - INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); - - lstrcatW(sourcepath, filename); - r = MSI_OpenPackageW(sourcepath, &package); + r = msi_open_package(szProduct, context, &package); if (r != ERROR_SUCCESS) return r; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 6e91adc441d..6f15720036b 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -4987,6 +4987,11 @@ static void test_sourcepath(void) static void test_MsiConfigureProductEx(void) { UINT r; + LONG res; + DWORD type, size; + HKEY props, source; + CHAR keypath[MAX_PATH * 2]; + CHAR localpack[MAX_PATH]; CreateDirectoryA("msitest", NULL); create_file("msitest\\hydrogen", 500); @@ -5099,7 +5104,146 @@ static void test_MsiConfigureProductEx(void) ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + DeleteFileA(msifile); + + /* local msifile is removed */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "File not removed\n"); + } + + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + DeleteFileA(msifile); + + lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)"C:\\idontexist.msi", 18); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* LocalPackage is used to find the cached msi package */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_INSTALL_SOURCE_ABSENT, + "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + RegCloseKey(props); + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + /* LastUsedSource (local msi package) can be used as a last resort */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "File not removed\n"); + } + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)"C:\\idontexist.msi", 18); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &source); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + type = REG_SZ; + size = MAX_PATH; + res = RegQueryValueExA(source, "PackageName", NULL, &type, + (LPBYTE)localpack, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegSetValueExA(source, "PackageName", 0, REG_SZ, + (const BYTE *)"idontexist.msi", 15); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* SourceList is altered */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_INSTALL_SOURCE_ABSENT, + "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* restore the SourceList */ + res = RegSetValueExA(source, "PackageName", 0, REG_SZ, + (const BYTE *)localpack, lstrlenA(localpack) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* finally remove the product */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "File not removed\n"); + } + + DeleteFileA(msifile); + RegCloseKey(source); + RegCloseKey(props); DeleteFileA("msitest\\hydrogen"); DeleteFileA("msitest\\helium"); DeleteFileA("msitest\\lithium"); diff --git a/dlls/msrle32/msrle32.c b/dlls/msrle32/msrle32.c index 4f0226a1fb2..e5d2d5be603 100644 --- a/dlls/msrle32/msrle32.c +++ b/dlls/msrle32/msrle32.c @@ -395,7 +395,7 @@ static INT MSRLE32_CompressRLE4Line(const CodecInfo *pi, const WORD *lpP, INT i; INT size = min(count, 254); int bytes = ((size + 1) & (~1)) / 2; - BOOL extra_byte = bytes & 0x01; + int extra_byte = bytes & 0x01; *lpSizeImage += 2 + bytes + extra_byte; assert(((*lpSizeImage) % 2) == 0); @@ -488,7 +488,7 @@ static INT MSRLE32_CompressRLE8Line(const CodecInfo *pi, const WORD *lpP, while (count > 2) { INT i; INT size = min(count, 255); - BOOL extra_byte = size % 2; + int extra_byte = size % 2; *lpSizeImage += 2 + size + extra_byte; count -= size; diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 8e39391f950..61f01f1fdb7 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -1444,7 +1444,7 @@ static HRESULT WINAPI domdoc_save( HRESULT ret = S_OK; DWORD written; - TRACE("(%p)->(var(vt %x, %s))\n", This, V_VT(&destination), + TRACE("(%p)->(var(vt %d, %s))\n", This, V_VT(&destination), V_VT(&destination) == VT_BSTR ? debugstr_w(V_BSTR(&destination)) : NULL); if(V_VT(&destination) != VT_BSTR && V_VT(&destination) != VT_UNKNOWN) @@ -1475,6 +1475,8 @@ static HRESULT WINAPI domdoc_save( IXMLDOMDocument_Release(pDocument); } + TRACE("ret %d", ret); + return ret; } diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 64a99ecc10d..69f42fcc997 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1391,7 +1391,7 @@ HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR *idstr) return ret; ret=WINE_StringFromCLSID(id,buf); - if (!ret) { + if (ret == S_OK) { DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ); *idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len ); @@ -2806,7 +2806,7 @@ HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew) if (!memcmp( clsidOld, clsidNew, sizeof(*clsidOld) )) { if (!RegQueryValueW(hkey, wszAutoTreatAs, auto_treat_as, &auto_treat_as_size) && - !CLSIDFromString(auto_treat_as, &id)) + CLSIDFromString(auto_treat_as, &id) == S_OK) { if (RegSetValueW(hkey, wszTreatAs, REG_SZ, auto_treat_as, sizeof(auto_treat_as))) { diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c index 015d3fc3a1b..1add5e0c142 100644 --- a/dlls/ole32/oleproxy.c +++ b/dlls/ole32/oleproxy.c @@ -585,7 +585,7 @@ static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface, pMsg->cbBuffer = cIids * sizeof(HRESULT); IRpcChannelBuffer_GetBuffer(pChannel, pMsg, &IID_IRemUnknown); - if (!hr) + if (hr == S_OK) { buf = pMsg->Buffer; memcpy(buf, pResults, cIids * sizeof(HRESULT)); @@ -964,12 +964,12 @@ PSFacBuf_CreateStub( if (IsEqualIID(&IID_IClassFactory, riid) || IsEqualIID(&IID_IUnknown, riid) /* FIXME: fixup stub manager and remove this*/) { hres = CFStub_Construct(ppStub); - if (!hres) + if (hres == S_OK) IRpcStubBuffer_Connect((*ppStub),pUnkServer); return hres; } else if (IsEqualIID(&IID_IRemUnknown,riid)) { hres = RemUnkStub_Construct(ppStub); - if (!hres) + if (hres == S_OK) IRpcStubBuffer_Connect((*ppStub),pUnkServer); return hres; } diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 7d79a39cf6d..663ff4f0b16 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -2100,7 +2100,6 @@ static HRESULT findPlaceholder( INT typeOfRelation) { StgProperty storeProperty; - HRESULT hr = S_OK; BOOL res = TRUE; /* @@ -2162,12 +2161,12 @@ static HRESULT findPlaceholder( } } - hr = StorageImpl_WriteProperty( + res = StorageImpl_WriteProperty( storage->base.ancestorStorage, storePropertyIndex, &storeProperty); - if(! hr) + if(!res) { return E_FAIL; } @@ -3140,16 +3139,8 @@ static HRESULT StorageImpl_LoadFileHeader( /* * Make the bitwise arithmetic to get the size of the blocks in bytes. */ - if ((1 << 2) == 4) - { - This->bigBlockSize = 0x000000001 << (DWORD)This->bigBlockSizeBits; - This->smallBlockSize = 0x000000001 << (DWORD)This->smallBlockSizeBits; - } - else - { - This->bigBlockSize = 0x000000001 >> (DWORD)This->bigBlockSizeBits; - This->smallBlockSize = 0x000000001 >> (DWORD)This->smallBlockSizeBits; - } + This->bigBlockSize = 0x000000001 << (DWORD)This->bigBlockSizeBits; + This->smallBlockSize = 0x000000001 << (DWORD)This->smallBlockSizeBits; /* * Right now, the code is making some assumptions about the size of the diff --git a/dlls/ole32/tests/ole2.c b/dlls/ole32/tests/ole2.c index 5ca600945cc..cc3476d60f7 100644 --- a/dlls/ole32/tests/ole2.c +++ b/dlls/ole32/tests/ole2.c @@ -844,9 +844,8 @@ static void test_OleLoad(IStorage *pStorage) trace("OleLoad:\n"); hr = OleLoad(pStorage, &IID_IOleObject, (IOleClientSite *)0xdeadbeef, (void **)&pObject); ok(hr == S_OK || - broken(hr == E_INVALIDARG), /* win2k */ + broken(hr == E_INVALIDARG), /* win98 and win2k */ "OleLoad failed with error 0x%08x\n", hr); - ok_ole_success(hr, "OleLoad"); if (pObject) { IOleObject_Release(pObject); diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 45c5e13841d..d7139d23aa6 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -1436,6 +1436,18 @@ static inline void TLB_FreeCustData(TLBCustData *pCustData) } } +static BSTR TLB_MultiByteToBSTR(const char *ptr) +{ + DWORD len; + BSTR ret; + + len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len - 1); + if (!ret) return ret; + MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len); + return ret; +} + /********************************************************************** * * Functions for reading MSFT typelibs (those created by CreateTypeLib2) @@ -2699,7 +2711,6 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length) { char *name; - DWORD len; *ppImpLib = TLB_Alloc(sizeof(TLBImpLib)); (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset; @@ -2713,10 +2724,7 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) size >>= 2; name = TLB_Alloc(size+1); MSFT_Read(name, size, &cx, DO_NOT_SEEK); - len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 ); - (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len ); - TLB_Free(name); + (*ppImpLib)->name = TLB_MultiByteToBSTR(name); MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3; @@ -2750,20 +2758,6 @@ static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) } -static BSTR TLB_MultiByteToBSTR(const char *ptr) -{ - DWORD len; - WCHAR *nameW; - BSTR ret; - - len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0); - nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len); - ret = SysAllocString(nameW); - HeapFree(GetProcessHeap(), 0, nameW); - return ret; -} - static BOOL TLB_GUIDFromString(const char *str, GUID *guid) { char b[3]; @@ -2790,16 +2784,14 @@ static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr) { WORD bytelen; DWORD len; - WCHAR *nameW; *pBstr = NULL; bytelen = *(const WORD*)ptr; if(bytelen == 0xffff) return 2; len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0); - nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len); - *pBstr = SysAllocStringLen(nameW, len); - HeapFree(GetProcessHeap(), 0, nameW); + *pBstr = SysAllocStringLen(NULL, len - 1); + if (*pBstr) + len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len); return bytelen + 2; } @@ -3879,7 +3871,7 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) { if (pImpLib->pImpTypeLib) ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib); - TLB_Free(pImpLib->name); + SysFreeString(pImpLib->name); pImpLibNext = pImpLib->next; TLB_Free(pImpLib); diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index e6191d1c840..5c094e10278 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -1191,7 +1191,7 @@ INT WINAPI DosDateTimeToVariantTime(USHORT wDosDate, USHORT wDosTime, ud.st.wSecond = DOS_SECOND(wDosTime); ud.st.wDayOfWeek = ud.st.wMilliseconds = 0; - return !VarDateFromUdate(&ud, 0, pDateOut); + return VarDateFromUdate(&ud, 0, pDateOut) == S_OK; } /********************************************************************** @@ -1255,7 +1255,7 @@ INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut) return FALSE; ud.st = *lpSt; - return !VarDateFromUdate(&ud, 0, pDateOut); + return VarDateFromUdate(&ud, 0, pDateOut) == S_OK; } /*********************************************************************** diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c index daeac853873..5f697c8963a 100644 --- a/dlls/oleaut32/vartype.c +++ b/dlls/oleaut32/vartype.c @@ -5179,7 +5179,7 @@ static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * di to multiply quotient by 10 (without overflowing), while adjusting the scale, until scale is 0. If this cannot be done, it is a real overflow. */ - while (!r_overflow && quotientscale < 0) { + while (r_overflow == S_OK && quotientscale < 0) { memset(remainderplusquotient, 0, sizeof(remainderplusquotient)); memcpy(remainderplusquotient, quotient->bitsnum, sizeof(quotient->bitsnum)); VARIANT_int_mulbychar(remainderplusquotient, sizeof(remainderplusquotient)/sizeof(DWORD), 10); @@ -5189,7 +5189,7 @@ static HRESULT VARIANT_DI_div(const VARIANT_DI * dividend, const VARIANT_DI * di memcpy(quotient->bitsnum, remainderplusquotient, sizeof(quotient->bitsnum)); } else r_overflow = DISP_E_OVERFLOW; } - if (!r_overflow) { + if (r_overflow == S_OK) { if (quotientscale <= 255) quotient->scale = quotientscale; else VARIANT_DI_clear(quotient); } @@ -6516,7 +6516,7 @@ HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut) VARIANT_int_add(decVal.bitsnum, 3, &one, 1); } decVal.bitsnum[2] = 0; - VARIANT_DI_tostringW(&decVal, buff, sizeof(buff)); + VARIANT_DI_tostringW(&decVal, buff, sizeof(buff)/sizeof(buff[0])); if (dwFlags & LOCALE_USE_NLS) { diff --git a/dlls/quartz/control.c b/dlls/quartz/control.c index e7198319875..a2db24be786 100644 --- a/dlls/quartz/control.c +++ b/dlls/quartz/control.c @@ -254,7 +254,7 @@ static HRESULT ForwardCmdSeek( PCRITICAL_SECTION crit_sect, IBaseFilter* from, S IMediaSeeking *seek = NULL; hr_local = IPin_QueryInterface( connected, &IID_IMediaSeeking, (void**)&seek ); - if (!hr_local) + if (hr_local == S_OK) { foundend = TRUE; if (crit_sect) diff --git a/dlls/quartz/mpegsplit.c b/dlls/quartz/mpegsplit.c index ee93e2e98c5..8625277c875 100644 --- a/dlls/quartz/mpegsplit.c +++ b/dlls/quartz/mpegsplit.c @@ -471,7 +471,7 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO pos += 4; /* Skip ID3 v2 tag, if any */ - if (SUCCEEDED(hr) && !strncmp("ID3", (char*)header, 3)) + if (SUCCEEDED(hr) && !memcmp("ID3", header, 3)) do { UINT length; hr = IAsyncReader_SyncRead(pPin->pReader, pos, 6, header + 4); diff --git a/dlls/riched20/Makefile.in b/dlls/riched20/Makefile.in index 4e443a1a691..8bcf8edfbd0 100644 --- a/dlls/riched20/Makefile.in +++ b/dlls/riched20/Makefile.in @@ -20,6 +20,7 @@ C_SRCS = \ run.c \ string.c \ style.c \ + table.c \ txtsrv.c \ undo.c \ wrap.c \ diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 89cd132e1f2..376318e7309 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -215,7 +215,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; *x = run->member.run.pt.x + sz.cx; - *y = para->member.para.nYPos + row->member.row.nBaseline + run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor); + *y = para->member.para.pt.y + row->member.row.nBaseline + run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor); ME_DestroyContext(&c, editor->hWnd); return; } @@ -262,17 +262,49 @@ void ME_HideCaret(ME_TextEditor *ed) } } -void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, - int nChars) +BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, + BOOL bForce) { ME_Cursor c; int shift = 0; int totalChars = nChars; - + ME_DisplayItem *start_para; + + { + /* Prevent deletion past last end of paragraph run. */ + ME_DisplayItem *pTextEnd = editor->pBuffer->pLast; + int nMaxChars = pTextEnd->member.para.prev_para->member.para.nCharOfs; + nMaxChars += ME_FindItemBack(pTextEnd, diRun)->member.run.nCharOfs; + nMaxChars -= nOfs; + nChars = min(nChars, nMaxChars); + } + + ME_CursorFromCharOfs(editor, nOfs, &c); + start_para = ME_GetParagraph(c.pRun); + + if (!bForce) + { + ME_ProtectPartialTableDeletion(editor, nOfs, &nChars); + if (nChars == 0) + return FALSE; + } + while(nChars > 0) { ME_Run *run; - ME_CursorFromCharOfs(editor, nOfs, &c); + ME_CursorFromCharOfs(editor, nOfs+nChars, &c); + if (!c.nOffset && + nOfs+nChars == (c.pRun->member.run.nCharOfs + + ME_GetParagraph(c.pRun)->member.para.nCharOfs)) + { + /* We aren't deleting anything in this run, so we will go back to the + * last run we are deleting text in. */ + c.pRun = ME_FindItemBack(c.pRun, diRun); + if (c.pRun->member.run.nFlags & MERF_ENDPARA) + c.nOffset = c.pRun->member.run.nCR + c.pRun->member.run.nLF; + else + c.nOffset = c.pRun->member.run.strText->nLen; + } run = &c.pRun->member.run; if (run->nFlags & MERF_ENDPARA) { int eollen = run->nCR + run->nLF; @@ -280,10 +312,32 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, if (!ME_FindItemFwd(c.pRun, diParagraph)) { - return; + return TRUE; } keepFirstParaFormat = (totalChars == nChars && nChars <= eollen && run->nCharOfs); + if (!editor->bEmulateVersion10) /* v4.1 */ + { + ME_DisplayItem *next_para = ME_FindItemFwd(c.pRun, diParagraphOrEnd); + ME_DisplayItem *this_para = next_para->member.para.prev_para; + + /* The end of paragraph before a table row is only deleted if there + * is nothing else on the line before it. */ + if (this_para == start_para && + next_para->member.para.nFlags & MEPF_ROWSTART) + { + /* If the paragraph will be empty, then it should be deleted, however + * it still might have text right now which would inherit the + * MEPF_STARTROW property if we joined it right now. + * Instead we will delete it after the preceding text is deleted. */ + if (nOfs > this_para->member.para.nCharOfs) { + /* Skip this end of line. */ + nChars -= (eollen < nChars) ? eollen : nChars; + continue; + } + keepFirstParaFormat = TRUE; + } + } ME_JoinParagraphs(editor, ME_GetParagraph(c.pRun), keepFirstParaFormat); /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */ ME_CheckCharOffsets(editor); @@ -293,22 +347,21 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, else { ME_Cursor cursor; - int nIntendedChars = nChars; - int nCharsToDelete = nChars; + int nCharsToDelete = min(nChars, c.nOffset); int i; - int loc = c.nOffset; - + + c.nOffset -= nCharsToDelete; + ME_FindItemBack(c.pRun, diParagraph)->member.para.nFlags |= MEPF_REWRAP; - + cursor = c; - ME_StrRelPos(run->strText, loc, &nChars); /* nChars is the number of characters that should be deleted from the - FOLLOWING runs (these AFTER cursor.pRun) + PRECEDING runs (these BEFORE cursor.pRun) nCharsToDelete is a number of chars to delete from THIS run */ - nCharsToDelete -= nChars; + nChars -= nCharsToDelete; shift -= nCharsToDelete; - TRACE("Deleting %d (intended %d-remaning %d) chars at %d in '%s' (%d)\n", - nCharsToDelete, nIntendedChars, nChars, c.nOffset, + TRACE("Deleting %d (remaning %d) chars at %d in '%s' (%d)\n", + nCharsToDelete, nChars, c.nOffset, debugstr_w(run->strText->szData), run->strText->nLen); if (!c.nOffset && ME_StrVLen(run->strText) == nCharsToDelete) @@ -318,7 +371,7 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, to the current (deleted) run */ ME_UndoItem *pUndo = ME_AddUndoItem(editor, diUndoInsertRun, c.pRun); if (pUndo) - pUndo->di.member.run.nCharOfs = nOfs; + pUndo->di.member.run.nCharOfs = nOfs+nChars; } else { @@ -326,7 +379,7 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, ME_UndoItem *pUndo = ME_AddUndoItem(editor, diUndoInsertRun, c.pRun); if (pUndo) { ME_DestroyString(pUndo->di.member.run.strText); - pUndo->di.member.run.nCharOfs = nOfs; + pUndo->di.member.run.nCharOfs = nOfs+nChars; pUndo->di.member.run.strText = ME_MakeStringN(run->strText->szData+c.nOffset, nCharsToDelete); } } @@ -377,15 +430,16 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, continue; } } + return TRUE; } -void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, - int nChars) +BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars) { assert(nCursor>=0 && nCursornCursors); /* text operations set modified state */ editor->nModifyStep = 1; - ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars); + return ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars, + FALSE); } static ME_DisplayItem * @@ -551,7 +605,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, pos++; numCR = 1; numLF = 0; } - tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF); + tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 0); p->pRun = ME_FindItemFwd(tp, diRun); end_run = ME_FindItemBack(tp, diRun); ME_ReleaseStyle(end_run->member.run.style); @@ -598,7 +652,8 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) assert(pRun->type != diRun && pRun->type != diParagraph); return FALSE; } - } while (RUN_IS_HIDDEN(&pRun->member.run)); + } while (RUN_IS_HIDDEN(&pRun->member.run) || + pRun->member.run.nFlags & MERF_HIDDEN); pCursor->pRun = pRun; if (pRun->member.run.nFlags & MERF_ENDPARA) pCursor->nOffset = 0; @@ -624,7 +679,8 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) } do { pRun = ME_FindItemFwd(pRun, diRun); - } while (pRun && RUN_IS_HIDDEN(&pRun->member.run)); + } while (pRun && (RUN_IS_HIDDEN(&pRun->member.run) || + pRun->member.run.nFlags & MERF_HIDDEN)); if (pRun) { pCursor->pRun = pRun; @@ -669,9 +725,13 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { if (cursor->pRun == pRun && cursor->nOffset == 0) { + /* Skip empty start of table row paragraph */ + if (pOtherRun->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) + pOtherRun = pOtherRun->member.para.prev_para; /* Paragraph breaks are treated as separate words */ if (pOtherRun->member.para.prev_para->type == diTextStart) return FALSE; + pRun = ME_FindItemBack(pOtherRun, diRunOrParagraph); } break; @@ -702,6 +762,8 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) } else if (pOtherRun->type == diParagraph) { + if (pOtherRun->member.para.nFlags & MEPF_ROWSTART) + pOtherRun = pOtherRun->member.para.next_para; if (cursor->pRun == pRun) pRun = ME_FindItemFwd(pOtherRun, diRun); nOffset = 0; @@ -725,8 +787,8 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) void ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) { - /* pCursor[0] will be the start of the selection - * pCursor[1] is the other end of the selection range + /* pCursor[0] is the end of the selection + * pCursor[1] is the start of the selection (or the position selection anchor) * pCursor[2] and [3] are the selection anchors that are backed up * so they are kept when the selection changes for drag selection. */ @@ -737,9 +799,9 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) case stPosition: break; case stWord: - ME_MoveCursorWords(editor, &editor->pCursors[1], +1); - editor->pCursors[0] = editor->pCursors[1]; - ME_MoveCursorWords(editor, &editor->pCursors[0], -1); + ME_MoveCursorWords(editor, &editor->pCursors[0], +1); + editor->pCursors[1] = editor->pCursors[0]; + ME_MoveCursorWords(editor, &editor->pCursors[1], -1); break; case stLine: case stParagraph: @@ -753,16 +815,16 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) backSearchType = diStartRow; fwdSearchType = diStartRowOrParagraphOrEnd; } - pItem = ME_FindItemBack(editor->pCursors[0].pRun, backSearchType); - editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[0].nOffset = 0; - pItem = ME_FindItemFwd(editor->pCursors[0].pRun, fwdSearchType); assert(pItem); if (pItem->type == diTextEnd) - editor->pCursors[1].pRun = ME_FindItemBack(pItem, diRun); + editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); else - editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[0].nOffset = 0; + + pItem = ME_FindItemBack(pItem, backSearchType); + editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); editor->pCursors[1].nOffset = 0; break; } @@ -781,7 +843,6 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) editor->pCursors[3] = editor->pCursors[1]; } - int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor) { ME_Cursor *pCursor = &editor->pCursors[nCursor]; @@ -789,6 +850,45 @@ int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor) + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset; } +/* Helper function for ME_FindPixelPos to find paragraph within tables */ +static ME_DisplayItem* ME_FindPixelPosInTableRow(int x, int y, + ME_DisplayItem *para) +{ + ME_DisplayItem *cell, *next_cell; + assert(para->member.para.nFlags & MEPF_ROWSTART); + cell = para->member.para.next_para->member.para.pCell; + assert(cell); + + /* find the cell we are in */ + while ((next_cell = cell->member.cell.next_cell) != NULL) { + if (x < next_cell->member.cell.pt.x) + { + para = ME_FindItemFwd(cell, diParagraph); + /* Found the cell, but there might be multiple paragraphs in + * the cell, so need to search down the cell for the paragraph. */ + while (cell == para->member.para.pCell) { + if (y < para->member.para.pt.y + para->member.para.nHeight) + { + if (para->member.para.nFlags & MEPF_ROWSTART) + return ME_FindPixelPosInTableRow(x, y, para); + else + return para; + } + para = para->member.para.next_para; + } + /* Past the end of the cell, so go back to the last cell paragraph */ + return para->member.para.prev_para; + } + cell = next_cell; + } + /* Return table row delimiter */ + para = ME_FindItemFwd(cell, diParagraph); + assert(para->member.para.nFlags & MEPF_ROWEND); + assert(para->member.para.pFmt->dwMask & PFM_TABLEROWDELIMITER); + assert(para->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER); + return para; +} + /* Finds the run and offset from the pixel position. * * x & y are pixel positions in virtual coordinates into the rich edit control, @@ -812,11 +912,15 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, for (; p != editor->pBuffer->pLast; p = p->member.para.next_para) { assert(p->type == diParagraph); - if (y < p->member.para.nYPos + p->member.para.nHeight) + if (y < p->member.para.pt.y + p->member.para.nHeight) { - y -= p->member.para.nYPos; + if (p->member.para.nFlags & MEPF_ROWSTART) + p = ME_FindPixelPosInTableRow(x, y, p); + y -= p->member.para.pt.y; p = ME_FindItemFwd(p, diStartRow); break; + } else if (p->member.para.nFlags & MEPF_ROWSTART) { + p = ME_GetTableRowEnd(p); } } /* find row */ @@ -824,7 +928,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, { ME_DisplayItem *pp; assert(p->type == diStartRow); - if (y < p->member.row.nYPos + p->member.row.nHeight) + if (y < p->member.row.pt.y + p->member.row.nHeight) { p = ME_FindItemFwd(p, diRun); break; @@ -880,6 +984,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, if (is_eol) *is_eol = 1; rx = 0; /* FIXME not sure */ goto found_here; + case diCell: case diParagraph: case diTextEnd: isExact = FALSE; @@ -941,8 +1046,8 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) if (editor->nSelectionType == stPosition || editor->nSelectionType == stDocument) return; curOfs = ME_GetCursorOfs(editor, 0); - anchorStartOfs = ME_GetCursorOfs(editor, 2); - anchorEndOfs = ME_GetCursorOfs(editor, 3); + anchorStartOfs = ME_GetCursorOfs(editor, 3); + anchorEndOfs = ME_GetCursorOfs(editor, 2); tmp_cursor = editor->pCursors[0]; editor->pCursors[0] = editor->pCursors[2]; @@ -950,36 +1055,36 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) if (curOfs < anchorStartOfs) { /* Extend the left side of selection */ - editor->pCursors[0] = tmp_cursor; + editor->pCursors[1] = tmp_cursor; if (editor->nSelectionType == stWord) - ME_MoveCursorWords(editor, &editor->pCursors[0], -1); + ME_MoveCursorWords(editor, &editor->pCursors[1], -1); else { ME_DisplayItem *pItem; ME_DIType searchType = ((editor->nSelectionType == stLine) ? diStartRowOrParagraph:diParagraph); - pItem = ME_FindItemBack(editor->pCursors[0].pRun, searchType); - editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[0].nOffset = 0; + pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType); + editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[1].nOffset = 0; } } else if (curOfs >= anchorEndOfs) { /* Extend the right side of selection */ - editor->pCursors[1] = tmp_cursor; + editor->pCursors[0] = tmp_cursor; if (editor->nSelectionType == stWord) - ME_MoveCursorWords(editor, &editor->pCursors[1], +1); + ME_MoveCursorWords(editor, &editor->pCursors[0], +1); else { ME_DisplayItem *pItem; ME_DIType searchType = ((editor->nSelectionType == stLine) ? diStartRowOrParagraphOrEnd:diParagraphOrEnd); - pItem = ME_FindItemFwd(editor->pCursors[1].pRun, searchType); + pItem = ME_FindItemFwd(editor->pCursors[0].pRun, searchType); if (pItem->type == diTextEnd) - editor->pCursors[1].pRun = ME_FindItemBack(pItem, diRun); + editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); else - editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); - editor->pCursors[1].nOffset = 0; + editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[0].nOffset = 0; } } } @@ -1154,13 +1259,14 @@ static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) { ME_DisplayItem *pRun = pCursor->pRun; - ME_DisplayItem *pItem; + ME_DisplayItem *pItem, *pOldPara, *pNewPara; int x = ME_GetXForArrow(editor, pCursor); if (editor->bCaretAtEnd && !pCursor->nOffset) pRun = ME_FindItemBack(pRun, diRun); if (!pRun) return; + pOldPara = ME_GetParagraph(pRun); if (nRelOfs == -1) { /* start of this row */ @@ -1168,13 +1274,57 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) assert(pItem); /* start of the previous row */ pItem = ME_FindItemBack(pItem, diStartRow); + if (!pItem) + return; /* row not found - ignore */ + pNewPara = ME_GetParagraph(pItem); + if (pOldPara->member.para.nFlags & MEPF_ROWEND || + (pOldPara->member.para.pCell && + pOldPara->member.para.pCell != pNewPara->member.para.pCell)) + { + /* Brought out of a cell */ + pNewPara = ME_GetTableRowStart(pOldPara)->member.para.prev_para; + if (pNewPara->type == diTextStart) + return; /* At the top, so don't go anywhere. */ + pItem = ME_FindItemFwd(pNewPara, diStartRow); + } + if (pNewPara->member.para.nFlags & MEPF_ROWEND) + { + /* Brought into a table row */ + ME_Cell *cell = &ME_FindItemBack(pNewPara, diCell)->member.cell; + while (x < cell->pt.x && cell->prev_cell) + cell = &cell->prev_cell->member.cell; + if (cell->next_cell) /* else - we are still at the end of the row */ + pItem = ME_FindItemBack(cell->next_cell, diStartRow); + } } else { /* start of the next row */ pItem = ME_FindItemFwd(pRun, diStartRow); + if (!pItem) + return; /* row not found - ignore */ /* FIXME If diParagraph is before diStartRow, wrap the next paragraph? */ + pNewPara = ME_GetParagraph(pItem); + if (pOldPara->member.para.nFlags & MEPF_ROWSTART || + (pOldPara->member.para.pCell && + pOldPara->member.para.pCell != pNewPara->member.para.pCell)) + { + /* Brought out of a cell */ + pNewPara = ME_GetTableRowEnd(pOldPara)->member.para.next_para; + if (pNewPara->type == diTextEnd) + return; /* At the bottom, so don't go anywhere. */ + pItem = ME_FindItemFwd(pNewPara, diStartRow); + } + if (pNewPara->member.para.nFlags & MEPF_ROWSTART) + { + /* Brought into a table row */ + ME_DisplayItem *cell = ME_FindItemFwd(pNewPara, diCell); + while (cell->member.cell.next_cell && + x >= cell->member.cell.next_cell->member.cell.pt.x) + cell = cell->member.cell.next_cell; + pItem = ME_FindItemFwd(cell, diStartRow); + } } if (!pItem) { @@ -1200,8 +1350,8 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) p = ME_FindItemBack(pRun, diStartRowOrParagraph); assert(p->type == diStartRow); - yp = ME_FindItemBack(p, diParagraph)->member.para.nYPos; - yprev = ys = y = yp + p->member.row.nYPos; + yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y; + yprev = ys = y = yp + p->member.row.pt.y; yd = y - editor->sizeWindow.cy; pLast = p; @@ -1212,10 +1362,10 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) if (p->type == diParagraph) { /* crossing paragraphs */ if (p->member.para.prev_para == NULL) break; - yp = p->member.para.prev_para->member.para.nYPos; + yp = p->member.para.prev_para->member.para.pt.y; continue; } - y = yp + p->member.row.nYPos; + y = yp + p->member.row.pt.y; if (y < yd) break; pLast = p; @@ -1255,8 +1405,8 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) p = ME_FindItemBack(pRun, diStartRowOrParagraph); assert(p->type == diStartRow); - yp = ME_FindItemBack(p, diParagraph)->member.para.nYPos; - yprev = ys = y = yp + p->member.row.nYPos; + yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y; + yprev = ys = y = yp + p->member.row.pt.y; yd = y + editor->sizeWindow.cy; pLast = p; @@ -1265,10 +1415,10 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) if (!p) break; if (p->type == diParagraph) { - yp = p->member.para.nYPos; + yp = p->member.para.pt.y; continue; } - y = yp + p->member.row.nYPos; + y = yp + p->member.row.pt.y; if (y >= yd) break; pLast = p; diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index b5d1df5f279..aa5938326a3 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -320,6 +320,32 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea return 0; } +static void ME_ApplyBorderProperties(RTF_Info *info, + ME_BorderRect *borderRect, + RTFBorder *borderDef) +{ + int i, colorNum; + ME_Border *pBorders[] = {&borderRect->top, + &borderRect->left, + &borderRect->bottom, + &borderRect->right}; + for (i = 0; i < 4; i++) + { + RTFColor *colorDef = info->colorList; + pBorders[i]->width = borderDef[i].width; + colorNum = borderDef[i].color; + while (colorDef && colorDef->rtfCNum != colorNum) + colorDef = colorDef->rtfNextColor; + if (colorDef) + pBorders[i]->colorRef = RGB( + colorDef->rtfCRed >= 0 ? colorDef->rtfCRed : 0, + colorDef->rtfCGreen >= 0 ? colorDef->rtfCGreen : 0, + colorDef->rtfCBlue >= 0 ? colorDef->rtfCBlue : 0); + else + pBorders[i]->colorRef = RGB(0, 0, 0); + } +} + static void ME_RTFCharAttrHook(RTF_Info *info) { CHARFORMAT2W fmt; @@ -451,8 +477,13 @@ static void ME_RTFParAttrHook(RTF_Info *info) switch(info->rtfMinor) { case rtfParDef: /* restores default paragraph attributes */ - fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS | PFM_OFFSET | - PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE | PFM_STARTINDENT | PFM_TABLE; + if (!info->editor->bEmulateVersion10) /* v4.1 */ + info->borderType = RTFBorderParaLeft; + else /* v1.0 - 3.0 */ + info->borderType = RTFBorderParaTop; + fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS | + PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE | + PFM_STARTINDENT; /* TODO: numbering, shading */ fmt.wAlignment = PFA_LEFT; fmt.cTabCount = 0; @@ -462,26 +493,113 @@ static void ME_RTFParAttrHook(RTF_Info *info) fmt.bLineSpacingRule = 0; fmt.dySpaceBefore = fmt.dySpaceAfter = 0; fmt.dyLineSpacing = 0; - fmt.wEffects &= ~PFE_TABLE; + if (!info->editor->bEmulateVersion10) /* v4.1 */ + { + if (info->tableDef && info->tableDef->tableRowStart && + info->tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + { + ME_Cursor cursor; + ME_DisplayItem *para; + /* We are just after a table row. */ + RTFFlushOutputBuffer(info); + cursor = info->editor->pCursors[0]; + para = ME_GetParagraph(cursor.pRun); + if (para == info->tableDef->tableRowStart->member.para.next_para + && !cursor.nOffset && !cursor.pRun->member.run.nCharOfs) + { + /* Since the table row end, no text has been inserted, and the \intbl + * control word has not be used. We can confirm that we are not in a + * table anymore. + */ + info->tableDef->tableRowStart = NULL; + info->canInheritInTbl = FALSE; + } + } + } else { /* v1.0 - v3.0 */ + fmt.dwMask |= PFM_TABLE; + fmt.wEffects &= ~PFE_TABLE; + } + break; + case rtfNestLevel: + if (!info->editor->bEmulateVersion10) /* v4.1 */ + { + while (info->rtfParam > info->nestingLevel) { + RTFTable *tableDef = ALLOC_OBJ(RTFTable); + ZeroMemory(tableDef, sizeof(RTFTable)); + tableDef->parent = info->tableDef; + info->tableDef = tableDef; + + RTFFlushOutputBuffer(info); + if (tableDef->tableRowStart && + tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + { + ME_DisplayItem *para = tableDef->tableRowStart; + para = para->member.para.next_para; + para = ME_InsertTableRowStartAtParagraph(info->editor, para); + tableDef->tableRowStart = para; + } else { + ME_Cursor cursor; + WCHAR endl = '\r'; + cursor = info->editor->pCursors[0]; + if (cursor.nOffset || cursor.pRun->member.run.nCharOfs) + ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); + tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor); + } + + info->nestingLevel++; + } + info->canInheritInTbl = FALSE; + } break; case rtfInTable: { - fmt.dwMask |= PFM_TABLE; - fmt.wEffects |= PFE_TABLE; + if (!info->editor->bEmulateVersion10) /* v4.1 */ + { + if (info->nestingLevel < 1) + { + RTFTable *tableDef; + if (!info->tableDef) + { + info->tableDef = ALLOC_OBJ(RTFTable); + ZeroMemory(info->tableDef, sizeof(RTFTable)); + } + tableDef = info->tableDef; + RTFFlushOutputBuffer(info); + if (tableDef->tableRowStart && + tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + { + ME_DisplayItem *para = tableDef->tableRowStart; + para = para->member.para.next_para; + para = ME_InsertTableRowStartAtParagraph(info->editor, para); + tableDef->tableRowStart = para; + } else { + ME_Cursor cursor; + WCHAR endl = '\r'; + cursor = info->editor->pCursors[0]; + if (cursor.nOffset || cursor.pRun->member.run.nCharOfs) + ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); + tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor); + } + info->nestingLevel = 1; + info->canInheritInTbl = TRUE; + } + return; + } else { /* v1.0 - v3.0 */ + fmt.dwMask |= PFM_TABLE; + fmt.wEffects |= PFE_TABLE; + } break; } case rtfFirstIndent: ME_GetSelectionParaFormat(info->editor, &fmt); - fmt.dwMask |= PFM_STARTINDENT | PFM_OFFSET; - fmt.dxStartIndent += info->rtfParam; + fmt.dwMask = PFM_STARTINDENT | PFM_OFFSET; + fmt.dxStartIndent += fmt.dxOffset + info->rtfParam; fmt.dxOffset = -info->rtfParam; break; case rtfLeftIndent: - /* we assume rtfLeftIndent is always specified before rtfFirstIndent */ ME_GetSelectionParaFormat(info->editor, &fmt); - fmt.dwMask |= PFM_STARTINDENT; - fmt.dxStartIndent = info->rtfParam; - fmt.dxOffset = 0; + fmt.dwMask = PFM_STARTINDENT; + fmt.dxStartIndent = info->rtfParam - fmt.dxOffset; break; case rtfRightIndent: fmt.dwMask = PFM_RIGHTINDENT; @@ -504,11 +622,11 @@ static void ME_RTFParAttrHook(RTF_Info *info) ME_GetSelectionParaFormat(info->editor, &fmt); if (!(fmt.dwMask & PFM_TABSTOPS)) { - fmt.dwMask |= PFM_TABSTOPS; fmt.cTabCount = 0; } if (fmt.cTabCount < MAX_TAB_STOPS && info->rtfParam < 0x1000000) fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam; + fmt.dwMask = PFM_TABSTOPS; break; case rtfKeep: fmt.dwMask = PFM_KEEP; @@ -568,90 +686,138 @@ static void ME_RTFParAttrHook(RTF_Info *info) fmt.wNumberingStart = info->rtfParam; break; case rtfBorderLeft: + info->borderType = RTFBorderParaLeft; ME_GetSelectionParaFormat(info->editor, &fmt); if (!(fmt.dwMask & PFM_BORDER)) { - fmt.dwMask |= PFM_BORDER; fmt.wBorderSpace = 0; fmt.wBorderWidth = 1; fmt.wBorders = 0; } fmt.wBorders |= 1; + fmt.dwMask = PFM_BORDER; break; case rtfBorderRight: + info->borderType = RTFBorderParaRight; ME_GetSelectionParaFormat(info->editor, &fmt); if (!(fmt.dwMask & PFM_BORDER)) { - fmt.dwMask |= PFM_BORDER; fmt.wBorderSpace = 0; fmt.wBorderWidth = 1; fmt.wBorders = 0; } fmt.wBorders |= 2; + fmt.dwMask = PFM_BORDER; break; case rtfBorderTop: + info->borderType = RTFBorderParaTop; ME_GetSelectionParaFormat(info->editor, &fmt); if (!(fmt.dwMask & PFM_BORDER)) { - fmt.dwMask |= PFM_BORDER; fmt.wBorderSpace = 0; fmt.wBorderWidth = 1; fmt.wBorders = 0; } fmt.wBorders |= 4; + fmt.dwMask = PFM_BORDER; break; case rtfBorderBottom: + info->borderType = RTFBorderParaBottom; ME_GetSelectionParaFormat(info->editor, &fmt); if (!(fmt.dwMask & PFM_BORDER)) { - fmt.dwMask |= PFM_BORDER; fmt.wBorderSpace = 0; fmt.wBorderWidth = 1; fmt.wBorders = 0; } fmt.wBorders |= 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderSingle: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorders &= ~0x700; fmt.wBorders |= 1 << 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderThick: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorders &= ~0x700; fmt.wBorders |= 2 << 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderShadow: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorders &= ~0x700; fmt.wBorders |= 10 << 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderDouble: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorders &= ~0x700; fmt.wBorders |= 7 << 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderDot: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorders &= ~0x700; fmt.wBorders |= 11 << 8; + fmt.dwMask = PFM_BORDER; break; case rtfBorderWidth: + { + int borderSide = info->borderType & RTFBorderSideMask; + RTFTable *tableDef = info->tableDef; ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorderWidth |= ((info->rtfParam / 15) & 7) << 8; + if ((info->borderType & RTFBorderTypeMask) == RTFBorderTypeCell) + { + RTFBorder *border; + if (!tableDef || tableDef->numCellsDefined >= MAX_TABLE_CELLS) + break; + border = &tableDef->cells[tableDef->numCellsDefined].border[borderSide]; + border->width = info->rtfParam; + break; + } + fmt.dwMask = PFM_BORDER; break; + } case rtfBorderSpace: ME_GetSelectionParaFormat(info->editor, &fmt); /* we assume that borders have been created before (RTF spec) */ fmt.wBorderSpace = info->rtfParam; + fmt.dwMask = PFM_BORDER; break; - } + case rtfBorderColor: + { + RTFTable *tableDef = info->tableDef; + int borderSide = info->borderType & RTFBorderSideMask; + int borderType = info->borderType & RTFBorderTypeMask; + switch(borderType) + { + case RTFBorderTypePara: + if (!info->editor->bEmulateVersion10) /* v4.1 */ + break; + /* v1.0 - 3.0 treat paragraph and row borders the same. */ + case RTFBorderTypeRow: + if (tableDef) { + tableDef->border[borderSide].color = info->rtfParam; + } + break; + case RTFBorderTypeCell: + if (tableDef && tableDef->numCellsDefined < MAX_TABLE_CELLS) { + tableDef->cells[tableDef->numCellsDefined].border[borderSide].color = info->rtfParam; + } + break; + } + break; + } + } if (fmt.dwMask) { RTFFlushOutputBuffer(info); /* FIXME too slow ? how come ?*/ @@ -664,21 +830,29 @@ static void ME_RTFTblAttrHook(RTF_Info *info) switch (info->rtfMinor) { case rtfRowDef: - if (!info->tableDef) - info->tableDef = ALLOC_OBJ(RTFTable); - ZeroMemory(info->tableDef, sizeof(RTFTable)); + { + if (!info->editor->bEmulateVersion10) /* v4.1 */ + info->borderType = 0; /* Not sure */ + else /* v1.0 - 3.0 */ + info->borderType = RTFBorderRowTop; + if (!info->tableDef) { + info->tableDef = ME_MakeTableDef(info->editor); + } else { + ME_InitTableDef(info->editor, info->tableDef); + } break; + } case rtfCellPos: if (!info->tableDef) { - info->tableDef = ALLOC_OBJ(RTFTable); - ZeroMemory(info->tableDef, sizeof(RTFTable)); + info->tableDef = ME_MakeTableDef(info->editor); } if (info->tableDef->numCellsDefined >= MAX_TABLE_CELLS) break; info->tableDef->cells[info->tableDef->numCellsDefined].rightBoundary = info->rtfParam; { - /* Tab stops store the cell positions. */ + /* Tab stops were used to store cell positions before v4.1 but v4.1 + * still seems to set the tabstops without using them. */ ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); PARAFORMAT2 *pFmt = para->member.para.pFmt; int cellNum = info->tableDef->numCellsDefined; @@ -687,6 +861,38 @@ static void ME_RTFTblAttrHook(RTF_Info *info) } info->tableDef->numCellsDefined++; break; + case rtfRowBordTop: + info->borderType = RTFBorderRowTop; + break; + case rtfRowBordLeft: + info->borderType = RTFBorderRowLeft; + break; + case rtfRowBordBottom: + info->borderType = RTFBorderRowBottom; + break; + case rtfRowBordRight: + info->borderType = RTFBorderRowRight; + break; + case rtfCellBordTop: + info->borderType = RTFBorderCellTop; + break; + case rtfCellBordLeft: + info->borderType = RTFBorderCellLeft; + break; + case rtfCellBordBottom: + info->borderType = RTFBorderCellBottom; + break; + case rtfCellBordRight: + info->borderType = RTFBorderCellRight; + break; + case rtfRowGapH: + if (info->tableDef) + info->tableDef->gapH = info->rtfParam; + break; + case rtfRowLeftEdge: + if (info->tableDef) + info->tableDef->leftEdge = info->rtfParam; + break; } } @@ -695,11 +901,29 @@ static void ME_RTFSpecialCharHook(RTF_Info *info) RTFTable *tableDef = info->tableDef; switch (info->rtfMinor) { + case rtfNestCell: + if (info->editor->bEmulateVersion10) /* v1.0 - v3.0 */ + break; + /* else fall through since v4.1 treats rtfNestCell and rtfCell the same */ case rtfCell: if (!tableDef) break; RTFFlushOutputBuffer(info); - { + if (!info->editor->bEmulateVersion10) { /* v4.1 */ + if (tableDef->tableRowStart) + { + if (!info->nestingLevel && + tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + { + ME_DisplayItem *para = tableDef->tableRowStart; + para = para->member.para.next_para; + para = ME_InsertTableRowStartAtParagraph(info->editor, para); + tableDef->tableRowStart = para; + info->nestingLevel = 1; + } + ME_InsertTableCellFromCursor(info->editor); + } + } else { /* v1.0 - v3.0 */ ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); PARAFORMAT2 *pFmt = para->member.para.pFmt; if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE && @@ -711,16 +935,110 @@ static void ME_RTFSpecialCharHook(RTF_Info *info) } } break; + case rtfNestRow: + if (info->editor->bEmulateVersion10) /* v1.0 - v3.0 */ + break; + /* else fall through since v4.1 treats rtfNestRow and rtfRow the same */ case rtfRow: { + ME_DisplayItem *para, *cell, *run; + int i; + if (!tableDef) break; RTFFlushOutputBuffer(info); + if (!info->editor->bEmulateVersion10) { /* v4.1 */ + if (!tableDef->tableRowStart) + break; + if (!info->nestingLevel && + tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) + { + para = tableDef->tableRowStart; + para = para->member.para.next_para; + para = ME_InsertTableRowStartAtParagraph(info->editor, para); + tableDef->tableRowStart = para; + info->nestingLevel++; + } + para = tableDef->tableRowStart; + cell = ME_FindItemFwd(para, diCell); + assert(cell && !cell->member.cell.prev_cell); + if (tableDef->numCellsDefined < 1) + { + /* 2000 twips appears to be the cell size that native richedit uses + * when no cell sizes are specified. */ + const int defaultCellSize = 2000; + int nRightBoundary = defaultCellSize; + cell->member.cell.nRightBoundary = nRightBoundary; + while (cell->member.cell.next_cell) { + cell = cell->member.cell.next_cell; + nRightBoundary += defaultCellSize; + cell->member.cell.nRightBoundary = nRightBoundary; + } + para = ME_InsertTableCellFromCursor(info->editor); + cell = para->member.para.pCell; + cell->member.cell.nRightBoundary = nRightBoundary; + } else { + for (i = 0; i < tableDef->numCellsDefined; i++) + { + RTFCell *cellDef = &tableDef->cells[i]; + cell->member.cell.nRightBoundary = cellDef->rightBoundary; + ME_ApplyBorderProperties(info, &cell->member.cell.border, + cellDef->border); + cell = cell->member.cell.next_cell; + if (!cell) + { + para = ME_InsertTableCellFromCursor(info->editor); + cell = para->member.para.pCell; + } + } + /* Cell for table row delimiter is empty */ + cell->member.cell.nRightBoundary = tableDef->cells[i-1].rightBoundary; + } - { + run = ME_FindItemFwd(cell, diRun); + if (info->editor->pCursors[0].pRun != run || + info->editor->pCursors[0].nOffset) + { + int nOfs, nChars; + /* Delete inserted cells that aren't defined. */ + info->editor->pCursors[1].pRun = run; + info->editor->pCursors[1].nOffset = 0; + nOfs = ME_GetCursorOfs(info->editor, 1); + nChars = ME_GetCursorOfs(info->editor, 0) - nOfs; + ME_InternalDeleteText(info->editor, nOfs, nChars, TRUE); + } + + para = ME_InsertTableRowEndFromCursor(info->editor); + para->member.para.pFmt->dxOffset = abs(info->tableDef->gapH); + para->member.para.pFmt->dxStartIndent = info->tableDef->leftEdge; + ME_ApplyBorderProperties(info, ¶->member.para.border, + tableDef->border); + info->nestingLevel--; + if (!info->nestingLevel) + { + if (info->canInheritInTbl) { + tableDef->tableRowStart = para; + } else { + while (info->tableDef) { + tableDef = info->tableDef; + info->tableDef = tableDef->parent; + heap_free(tableDef); + } + } + } else { + info->tableDef = tableDef->parent; + heap_free(tableDef); + } + } else { /* v1.0 - v3.0 */ WCHAR endl = '\r'; ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); PARAFORMAT2 *pFmt = para->member.para.pFmt; + pFmt->dxOffset = info->tableDef->gapH; + pFmt->dxStartIndent = info->tableDef->leftEdge; + + para = ME_GetParagraph(info->editor->pCursors[0].pRun); + ME_ApplyBorderProperties(info, ¶->member.para.border, + tableDef->border); while (tableDef->numCellsInserted < tableDef->numCellsDefined) { WCHAR tab = '\t'; @@ -735,9 +1053,23 @@ static void ME_RTFSpecialCharHook(RTF_Info *info) } break; } + case rtfTab: case rtfPar: - if (tableDef) - tableDef->numCellsInserted = 0; + if (info->editor->bEmulateVersion10) { /* v1.0 - 3.0 */ + ME_DisplayItem *para; + PARAFORMAT2 *pFmt; + RTFFlushOutputBuffer(info); + para = ME_GetParagraph(info->editor->pCursors[0].pRun); + pFmt = para->member.para.pFmt; + if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + { + /* rtfPar is treated like a space within a table. */ + info->rtfClass = rtfText; + info->rtfMajor = ' '; + } + else if (info->rtfMinor == rtfPar && tableDef) + tableDef->numCellsInserted = 0; + } break; } } @@ -1077,14 +1409,14 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if ((format & SFF_SELECTION) && (editor->mode & TM_RICHTEXT)) { style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); } else { ME_DisplayItem *para_item; style = editor->pBuffer->pDefaultStyle; ME_AddRefStyle(style); SendMessageA(editor->hWnd, EM_SETSEL, 0, 0); - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); from = to = 0; ME_ClearTempStyle(editor); @@ -1123,6 +1455,8 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (!invalidRTF && !inStream.editstream->dwError) { if (format & SF_RTF) { + ME_DisplayItem *para; + /* setup the RTF parser */ memset(&parser, 0, sizeof parser); RTFSetEditStream(&parser, &inStream); @@ -1135,11 +1469,50 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre RTFSetReadHook(&parser, ME_RTFReadHook); RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup); RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup); + if (!parser.editor->bEmulateVersion10) /* v4.1 */ + RTFSetDestinationCallback(&parser, rtfNoNestTables, RTFSkipGroup); BeginFile(&parser); /* do the parsing */ RTFRead(&parser); RTFFlushOutputBuffer(&parser); + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (parser.tableDef && parser.tableDef->tableRowStart) + { + /* Delete any incomplete table row at the end of the rich text. */ + int nOfs, nChars; + ME_DisplayItem *pCell; + + para = parser.tableDef->tableRowStart; + + parser.rtfMinor = rtfRow; + /* Complete the table row before deleting it. + * By doing it this way we will have the current paragraph format set + * properly to reflect that is not in the complete table, and undo items + * will be added for this change to the current paragraph format. */ + if (parser.nestingLevel > 0) + { + while (parser.nestingLevel--) + ME_RTFSpecialCharHook(&parser); + } else if (parser.canInheritInTbl) { + ME_RTFSpecialCharHook(&parser); + } + if (parser.tableDef && parser.tableDef->tableRowStart && + para->member.para.nFlags & MEPF_ROWEND) + { + para = para->member.para.next_para; + } + pCell = para->member.para.pCell; + + editor->pCursors[1].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[1].nOffset = 0; + nOfs = ME_GetCursorOfs(editor, 1); + nChars = ME_GetCursorOfs(editor, 0) - nOfs; + ME_InternalDeleteText(editor, nOfs, nChars, TRUE); + parser.tableDef->tableRowStart = NULL; + } + } + ME_CheckTablesForCorruption(editor); RTFDestroy(&parser); if (parser.lpRichEditOle) IRichEditOle_Release(parser.lpRichEditOle); @@ -1160,7 +1533,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_GetTextW(editor, lastchar, newto - linebreakSize, linebreakSize, 0); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { - ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize); + ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize, FALSE); } } } @@ -1619,10 +1992,17 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) } else if (ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE)) { - /* Backspace can be grouped for a single undo */ - ME_ContinueCoalescingTransaction(editor); - ME_DeleteTextAtCursor(editor, 1, 1); - ME_CommitCoalescingUndo(editor); + BOOL bDeletionSucceeded; + /* Backspace can be grouped for a single undo */ + ME_ContinueCoalescingTransaction(editor); + bDeletionSucceeded = ME_DeleteTextAtCursor(editor, 1, 1); + if (!bDeletionSucceeded && !editor->bEmulateVersion10) { /* v4.1 */ + /* Deletion was prevented so the cursor is moved back to where it was. + * (e.g. this happens when trying to delete cell boundaries) + */ + ME_ArrowKey(editor, VK_RIGHT, FALSE, FALSE); + } + ME_CommitCoalescingUndo(editor); } else return TRUE; @@ -2348,7 +2728,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (pStruct->flags & ST_SELECTION) { ME_GetSelection(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to - from); + ME_InternalDeleteText(editor, from, to - from, FALSE); if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) ME_StreamInRTFString(editor, 1, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, style); @@ -2357,7 +2737,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor); } else { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) ME_StreamInRTFString(editor, 0, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle); @@ -2479,13 +2859,15 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return tmp.dwMask; } case EM_SETPARAFORMAT: - ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); + { + BOOL result = ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); ME_RewrapRepaint(editor); ME_CommitUndo(editor); - return 0; + return result; + } case EM_GETPARAFORMAT: ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); - return 0; + return ((PARAFORMAT2 *)lParam)->dwMask; case EM_GETFIRSTVISIBLELINE: { ME_DisplayItem *p = editor->pBuffer->pFirst; @@ -2498,10 +2880,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (p->type == diTextEnd) break; if (p->type == diParagraph) { - ypara = p->member.para.nYPos; + ypara = p->member.para.pt.y; continue; } - ystart = ypara + p->member.row.nYPos; + ystart = ypara + p->member.row.pt.y; yend = ystart + p->member.row.nHeight; if (y < yend) { break; @@ -2525,7 +2907,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, { int from, to; ME_GetSelection(editor, &from, &to); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); return 0; @@ -2540,7 +2922,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_GetSelection(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); ME_InsertTextFromCursor(editor, 0, wszText, len, style); ME_ReleaseStyle(style); /* drop temporary style if line end */ @@ -2567,7 +2949,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, nPos = ME_GetYScrollPos(editor); row = ME_RowStart(editor->pCursors[0].pRun); para = ME_GetParagraph(row); - top = para->member.para.nYPos + row->member.row.nYPos; + top = para->member.para.pt.y + row->member.row.pt.y; bottom = top + row->member.row.nHeight; if (top < nPos) /* caret above window */ @@ -2599,7 +2981,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } case WM_SETTEXT: { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); if (lParam) { TRACE("WM_SETTEXT lParam==%lx\n",lParam); @@ -2699,7 +3081,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } if (SUCCEEDED(hr) && msg == WM_CUT) { - ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin); + ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); } @@ -3084,10 +3466,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, assert(pRun->type == diRun); pt.y = pRun->member.run.pt.y; pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset); - pt.y += ME_GetParagraph(pRun)->member.para.nYPos; + pt.y += ME_GetParagraph(pRun)->member.para.pt.y; } else { pt.x = 0; - pt.y = editor->pBuffer->pLast->member.para.nYPos; + pt.y = editor->pBuffer->pLast->member.para.pt.y; } pt.x += editor->selofs; @@ -3281,10 +3663,35 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (((unsigned)wstr)>=' ' || (wstr=='\r' && (GetWindowLongW(hWnd, GWL_STYLE) & ES_MULTILINE)) || wstr=='\t') { - /* FIXME maybe it would make sense to call EM_REPLACESEL instead ? */ - /* WM_CHAR is restricted to nTextLimit */ int from, to; + BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; ME_GetSelection(editor, &from, &to); + if (wstr=='\t' + /* v4.1 allows tabs to be inserted with ctrl key down */ + && !(ctrl_is_down && !editor->bEmulateVersion10) + ) + { + ME_Cursor cursor = editor->pCursors[0]; + ME_DisplayItem *para; + BOOL bSelectedRow = FALSE; + + para = ME_GetParagraph(cursor.pRun); + if (ME_IsSelection(editor) && + cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 && + para->member.para.prev_para->type == diParagraph) + { + para = para->member.para.prev_para; + bSelectedRow = TRUE; + } + if (ME_IsInTable(para)) + { + ME_TabPressedInTable(editor, bSelectedRow); + ME_CommitUndo(editor); + return 0; + } + } + /* FIXME maybe it would make sense to call EM_REPLACESEL instead ? */ + /* WM_CHAR is restricted to nTextLimit */ if(editor->nTextLimit > ME_GetTextLength(editor) - (to-from)) { ME_Style *style = ME_GetInsertStyle(editor, 0); @@ -3701,7 +4108,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in if (nLen > nChars) nLen = nChars; - if (item->member.run.nFlags & MERF_ENDPARA) + if (item->member.run.nFlags & MERF_ENDCELL && + item->member.run.nFlags & MERF_ENDPARA) + { + *buffer = '\t'; + } + else if (item->member.run.nFlags & MERF_ENDPARA) { if (!ME_FindItemFwd(item, diRun)) /* No '\r' is appended to the last paragraph. */ @@ -3713,10 +4125,16 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in if (bCRLF) { /* richedit 2.0 case - actual line-break is \r but should report \r\n */ - assert(nLen == 1); + if (ME_GetParagraph(item)->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) + assert(nLen == 2); + else + assert(nLen == 1); *buffer++ = '\r'; *buffer = '\n'; /* Later updated by nLen==1 at the end of the loop */ - nWritten++; + if (nLen == 1) + nWritten++; + else + buffer--; } else { diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index a32811c8df9..5e6f4cb502c 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -182,7 +182,7 @@ void ME_MoveCaret(ME_TextEditor *ed); int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact); void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum); void ME_MouseMove(ME_TextEditor *editor, int x, int y); -void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars); +BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars); void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style); void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor); @@ -198,7 +198,7 @@ BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); -void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); +BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, BOOL bForce); int ME_GetTextLength(ME_TextEditor *editor); int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how); ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor); @@ -217,13 +217,13 @@ void ME_SendRequestResize(ME_TextEditor *editor, BOOL force); ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end); void ME_MakeFirstParagraph(ME_TextEditor *editor); -ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, int numCR, int numLF); +ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, int numCR, int numLF, int paraFlags); ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, BOOL keepFirstParaFormat); void ME_DumpParaStyle(ME_Paragraph *s); void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]); -void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt); -void ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt); +BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt); +BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt); void ME_GetParaFormat(ME_TextEditor *editor, const ME_DisplayItem *para, PARAFORMAT2 *pFmt); void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt); /* marks from first up to (but not including) last */ @@ -285,6 +285,21 @@ extern BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max); void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor); +/* table.c */ +BOOL ME_IsInTable(ME_DisplayItem *pItem); +ME_DisplayItem *ME_InsertTableRowStartFromCursor(ME_TextEditor *editor); +ME_DisplayItem *ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, + ME_DisplayItem *para); +ME_DisplayItem *ME_InsertTableCellFromCursor(ME_TextEditor *editor); +ME_DisplayItem *ME_InsertTableRowEndFromCursor(ME_TextEditor *editor); +ME_DisplayItem *ME_GetTableRowEnd(ME_DisplayItem *para); +ME_DisplayItem *ME_GetTableRowStart(ME_DisplayItem *para); +void ME_CheckTablesForCorruption(ME_TextEditor *editor); +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars); +void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow); +struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor); +void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef); + /* undo.c */ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi); void ME_CommitUndo(ME_TextEditor *editor); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 9e2e84fff12..edbeb131834 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -67,26 +67,27 @@ typedef enum { diInvalid, diTextStart, /* start of the text buffer */ diParagraph, /* paragraph start */ + diCell, /* cell start */ diRun, /* run (sequence of chars with the same character format) */ diStartRow, /* start of the row (line of text on the screen) */ diTextEnd, /* end of the text buffer */ /********************* these below are meant for finding only *********************/ - diStartRowOrParagraph, /* 5 */ + diStartRowOrParagraph, /* 7 */ diStartRowOrParagraphOrEnd, diRunOrParagraph, diRunOrStartRow, diParagraphOrEnd, - diRunOrParagraphOrEnd, /* 10 */ + diRunOrParagraphOrEnd, /* 12 */ - diUndoInsertRun, /* 11 */ - diUndoDeleteRun, /* 12 */ - diUndoJoinParagraphs, /* 13 */ - diUndoSplitParagraph, /* 14 */ - diUndoSetParagraphFormat, /* 15 */ - diUndoSetCharFormat, /* 16 */ - diUndoEndTransaction, /* 17 - marks the end of a group of changes for undo */ - diUndoPotentialEndTransaction, /* 18 - allows grouping typed chars for undo */ + diUndoInsertRun, /* 13 */ + diUndoDeleteRun, /* 14 */ + diUndoJoinParagraphs, /* 15 */ + diUndoSplitParagraph, /* 16 */ + diUndoSetParagraphFormat, /* 17 */ + diUndoSetCharFormat, /* 18 */ + diUndoEndTransaction, /* 19 - marks the end of a group of changes for undo */ + diUndoPotentialEndTransaction, /* 20 - allows grouping typed chars for undo */ } ME_DIType; #define SELECTIONBAR_WIDTH 9 @@ -97,8 +98,10 @@ typedef enum { #define MERF_GRAPHICS 0x001 /* run is a tab (or, in future, any kind of content whose size is dependent on run position) */ #define MERF_TAB 0x002 +/* run is a cell boundary */ +#define MERF_ENDCELL 0x004 /* v4.1 */ -#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB) +#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB | MERF_ENDCELL) /* run is splittable (contains white spaces in the middle or end) */ #define MERF_SPLITTABLE 0x001000 @@ -118,6 +121,8 @@ typedef enum { #define MERF_ENDROW 0x200000 /* run is hidden */ #define MERF_HIDDEN 0x400000 +/* start of a table row has an empty paragraph that should be skipped over. */ +#define MERF_TABLESTART 0x800000 /* v4.1 */ /* runs with any of these flags set cannot be joined */ #define MERF_NOJOIN (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA|MERF_ENDROW) @@ -130,8 +135,12 @@ typedef enum { /******************************** para flags *************************/ /* this paragraph was already wrapped and hasn't changed, every change resets that flag */ -#define MEPF_REWRAP 1 -#define MEPF_REPAINT 2 +#define MEPF_REWRAP 0x01 +#define MEPF_REPAINT 0x02 +/* v4.1 */ +#define MEPF_CELL 0x04 /* The paragraph is nested in a cell */ +#define MEPF_ROWSTART 0x08 /* Hidden empty paragraph at the start of the row */ +#define MEPF_ROWEND 0x10 /* Visible empty paragraph at the end of the row */ /******************************** structures *************************/ @@ -156,18 +165,47 @@ typedef struct tagME_Document { int last_wrapped_line; } ME_Document; +typedef struct tagME_Border +{ + int width; + COLORREF colorRef; +} ME_Border; + +typedef struct tagME_BorderRect +{ + ME_Border top; + ME_Border left; + ME_Border bottom; + ME_Border right; +} ME_BorderRect; + typedef struct tagME_Paragraph { PARAFORMAT2 *pFmt; + struct tagME_DisplayItem *pCell; /* v4.1 */ + ME_BorderRect border; + int nCharOfs; int nFlags; - int nYPos, nHeight; + POINT pt; + int nHeight; int nLastPaintYPos, nLastPaintHeight; int nRows; struct tagME_DisplayItem *prev_para, *next_para, *document; } ME_Paragraph; +typedef struct tagME_Cell /* v4.1 */ +{ + int nNestingLevel; /* 0 for normal cells, and greater for nested cells */ + int nRightBoundary; + ME_BorderRect border; + POINT pt; + int nHeight, nWidth; + int yTextOffset; /* The text offset is caused by the largest top border. */ + struct tagME_DisplayItem *prev_cell, *next_cell, *parent_cell; +} ME_Cell; + typedef struct tagME_Row { int nHeight; @@ -175,7 +213,7 @@ typedef struct tagME_Row int nWidth; int nLMargin; int nRMargin; - int nYPos; + POINT pt; } ME_Row; /* the display item list layout is like this: @@ -197,6 +235,7 @@ typedef struct tagME_DisplayItem union { ME_Run run; ME_Row row; + ME_Cell cell; ME_Paragraph para; ME_Document doc; /* not used */ ME_Style *ustyle; /* used by diUndoSetCharFormat */ @@ -270,6 +309,9 @@ typedef struct tagME_OutStream { COLORREF colortbl[STREAMOUT_COLORTBL_SIZE]; UINT nDefaultFont; UINT nDefaultCodePage; + /* nNestingLevel = 0 means we aren't in a cell, 1 means we are in a cell, + * an greater numbers mean we are in a cell nested within a cell. */ + UINT nNestingLevel; } ME_OutStream; typedef struct tagME_FontCacheItem diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index 87f55136b6c..092fde47332 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -121,8 +121,11 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) { if (item->type==diUndoSetCharFormat) { ME_ReleaseStyle(item->member.ustyle); } - if (item->type==diUndoSplitParagraph) + if (item->type==diUndoSplitParagraph) { FREE_OBJ(item->member.para.pFmt); + if (item->member.para.pCell) + FREE_OBJ(item->member.para.pCell); + } FREE_OBJ(item); } @@ -146,6 +149,7 @@ const char *ME_GetDITypeName(ME_DIType type) { case diParagraph: return "diParagraph"; case diRun: return "diRun"; + case diCell: return "diCell"; case diTextStart: return "diTextStart"; case diTextEnd: return "diTextEnd"; case diStartRow: return "diStartRow"; @@ -172,8 +176,17 @@ void ME_DumpDocument(ME_TextBuffer *buffer) case diTextStart: TRACE("Start\n"); break; + case diCell: + TRACE("Cell(level=%d%s)\n", pItem->member.cell.nNestingLevel, + !pItem->member.cell.next_cell ? ", END" : + (!pItem->member.cell.prev_cell ? ", START" :"")); + break; case diParagraph: TRACE("Paragraph(ofs=%d)\n", pItem->member.para.nCharOfs); + if (pItem->member.para.nFlags & MEPF_ROWSTART) + TRACE(" - (Table Row Start)\n"); + if (pItem->member.para.nFlags & MEPF_ROWEND) + TRACE(" - (Table Row End)\n"); break; case diStartRow: TRACE(" - StartRow\n"); diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 921d3faaed5..9cfc21ef640 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -32,13 +32,35 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT * yoffset = ME_GetYScrollPos(editor); ME_InitContext(&c, editor, hDC); SetBkMode(hDC, TRANSPARENT); - ME_MoveCaret(editor); + ME_MoveCaret(editor); /* Calls ME_WrapMarkedParagraphs */ item = editor->pBuffer->pFirst->next; c.pt.y -= yoffset; while(item != editor->pBuffer->pLast) { + int yTextOffset = 0; int ye; assert(item->type == diParagraph); - ye = c.pt.y + item->member.para.nHeight; + if (item->member.para.pCell + != item->member.para.next_para->member.para.pCell) + { + ME_Cell *cell = NULL; + cell = &ME_FindItemBack(item->member.para.next_para, diCell)->member.cell; + ye = cell->pt.y + cell->nHeight - yoffset; + } else { + ye = c.pt.y + item->member.para.nHeight; + } + if (!(item->member.para.nFlags & MEPF_ROWEND) && + item->member.para.pCell != item->member.para.prev_para->member.para.pCell) + { + ME_DisplayItem *cell; + if (item->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) + cell = item->member.para.pCell; + else + cell = item->member.para.prev_para->member.para.pCell; + assert(cell); + /* the border shifts the text down */ + yTextOffset = cell->member.cell.yTextOffset; + ye += yTextOffset; + } if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT)) { BOOL bPaint = (rcUpdate == NULL); @@ -46,12 +68,39 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT * bPaint = c.pt.ybottom && ye>rcUpdate->top; if (bPaint) { + c.pt.y += yTextOffset; ME_DrawParagraph(&c, item); - if (!rcUpdate || (rcUpdate->top<=c.pt.y && rcUpdate->bottom>=ye)) + if (!rcUpdate || (rcUpdate->top<=c.pt.y-yTextOffset && rcUpdate->bottom>=ye)) item->member.para.nFlags &= ~MEPF_REPAINT; } } - c.pt.y = ye; + if (item->member.para.pCell) + { + ME_Cell *cell = &item->member.para.pCell->member.cell; + ME_DisplayItem *next_para = item->member.para.next_para; + c.pt.x = cell->pt.x + cell->nWidth; + if (item->member.para.pCell == next_para->member.para.pCell && + !(next_para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND))) + { + c.pt.y = ye; + } else { + if (next_para->member.para.nFlags & MEPF_ROWSTART) + { + cell = &ME_FindItemFwd(next_para, diCell)->member.cell; + } + else if (next_para->member.para.nFlags & MEPF_ROWEND) + { + cell = &cell->next_cell->member.cell; + } + else + { + cell = &next_para->member.para.pCell->member.cell; + } + c.pt.y = cell->pt.y - yoffset; + } + } else if (!(item->member.para.nFlags & MEPF_ROWSTART)) { + c.pt.y = ye; + } item = item->member.para.next_para; } if (c.pt.y= nSelFrom && runofs < nSelTo) { ME_HighlightSpace(c, x, y, wszSpace, 1, run->style, 0, 0, 1, - c->pt.y + start->member.row.nYPos, + c->pt.y + start->member.row.pt.y, start->member.row.nHeight); } return; } - if (run->nFlags & MERF_TAB) + if (run->nFlags & (MERF_TAB | MERF_ENDCELL)) { /* wszSpace is used instead of the tab character because otherwise * an unwanted symbol can be inserted instead. */ ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, run->nWidth, nSelFrom-runofs,nSelTo-runofs, - c->pt.y + start->member.row.nYPos, + c->pt.y + start->member.row.pt.y, start->member.row.nHeight); return; } @@ -420,13 +469,13 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); ME_DrawTextWithStyle(c, x, y, szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth, - nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); + nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.pt.y, start->member.row.nHeight); ME_DestroyString(szMasked); } else ME_DrawTextWithStyle(c, x, y, run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth, - nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); + nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.pt.y, start->member.row.nHeight); } } @@ -516,14 +565,45 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT { int idx, border_width, top_border, bottom_border; RECT rc; + BOOL hasParaBorder; SetRectEmpty(bounds); if (!(para->pFmt->dwMask & (PFM_BORDER | PFM_SPACEBEFORE | PFM_SPACEAFTER))) return; border_width = top_border = bottom_border = 0; idx = (para->pFmt->wBorders >> 8) & 0xF; - if ((para->pFmt->dwMask & PFM_BORDER) && idx != 0 && (para->pFmt->wBorders & 0xF)) + hasParaBorder = (!(c->editor->bEmulateVersion10 && + para->pFmt->dwMask & PFM_TABLE && + para->pFmt->wEffects & PFE_TABLE) && + (para->pFmt->dwMask & PFM_BORDER) && + idx != 0 && + (para->pFmt->wBorders & 0xF)); + if (hasParaBorder) { + /* FIXME: wBorders is not stored as MSDN says in v1.0 - 4.1 of richedit + * controls. It actually stores the paragraph or row border style. Although + * the value isn't used for drawing, it is used for streaming out rich text. + * + * wBorders stores the border style for each side (top, left, bottom, right) + * using nibble (4 bits) to store each border style. The rich text format + * control words, and their associated value are the following: + * \brdrdash 0 + * \brdrdashsm 1 + * \brdrdb 2 + * \brdrdot 3 + * \brdrhair 4 + * \brdrs 5 + * \brdrth 6 + * \brdrtriple 7 + * + * The order of the sides stored actually differs from v1.0 to 3.0 and v4.1. + * The mask corresponding to each side for the version are the following: + * mask v1.0-3.0 v4.1 + * 0x000F top left + * 0x00F0 left top + * 0x0F00 bottom right + * 0xF000 right bottom + */ if (para->pFmt->wBorders & 0x00B0) FIXME("Unsupported border flags %x\n", para->pFmt->wBorders); border_width = ME_GetParaBorderWidth(c->editor, para->pFmt->wBorders); @@ -551,7 +631,9 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT FillRect(c->hDC, &rc, c->editor->hbrBackground); } - if ((para->pFmt->dwMask & PFM_BORDER) && idx != 0 && (para->pFmt->wBorders & 0xF)) { + /* Native richedit doesn't support paragraph borders in v1.0 - 4.1, + * but might support it in later versions. */ + if (hasParaBorder) { int pen_width; COLORREF pencr; HPEN pen = NULL, oldpen = NULL; @@ -630,28 +712,234 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT } } +static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) +{ + ME_Paragraph *para = ¶graph->member.para; + if (!c->editor->bEmulateVersion10) /* v4.1 */ + { + if (para->pCell) + { + RECT rc; + ME_Cell *cell = ¶->pCell->member.cell; + ME_DisplayItem *paraAfterRow; + HPEN pen, oldPen; + LOGBRUSH logBrush; + HBRUSH brush; + COLORREF color; + POINT oldPt; + int width; + BOOL atTop = (para->pCell != para->prev_para->member.para.pCell); + BOOL atBottom = (para->pCell != para->next_para->member.para.pCell); + int top = (atTop ? cell->pt.y : para->pt.y) - ME_GetYScrollPos(c->editor); + int bottom = (atBottom ? + cell->pt.y + cell->nHeight - ME_GetYScrollPos(c->editor): + top + para->nHeight + (atTop ? cell->yTextOffset : 0)); + rc.left = cell->pt.x; + rc.right = rc.left + cell->nWidth; + if (atTop) { + /* Erase gap before text if not all borders are the same height. */ + width = max(ME_twips2pointsY(c, cell->border.top.width), 1); + rc.top = top + width; + width = cell->yTextOffset - width; + rc.bottom = rc.top + width; + if (width) { + FillRect(c->hDC, &rc, c->editor->hbrBackground); + } + } + /* Draw cell borders. + * The borders borders are draw in is left, top, bottom, right in order + * to be consistent with native richedit. This is noticeable from the + * overlap of borders of different colours. */ + if (!(para->nFlags & MEPF_ROWEND)) { + rc.top = top; + rc.bottom = bottom; + if (cell->border.left.width > 0) + { + color = cell->border.left.colorRef; + width = max(ME_twips2pointsX(c, cell->border.left.width), 1); + } else { + color = RGB(192,192,192); + width = 1; + } + logBrush.lbStyle = BS_SOLID; + logBrush.lbColor = color; + logBrush.lbHatch = 0; + pen = ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER, + width, &logBrush, 0, NULL); + oldPen = SelectObject(c->hDC, pen); + MoveToEx(c->hDC, rc.left, rc.top, &oldPt); + LineTo(c->hDC, rc.left, rc.bottom); + SelectObject(c->hDC, oldPen); + DeleteObject(pen); + MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL); + } + + if (atTop) { + if (cell->border.top.width > 0) + { + brush = CreateSolidBrush(cell->border.top.colorRef); + width = max(ME_twips2pointsY(c, cell->border.top.width), 1); + } else { + brush = GetStockObject(LTGRAY_BRUSH); + width = 1; + } + rc.top = top; + rc.bottom = rc.top + width; + FillRect(c->hDC, &rc, brush); + if (cell->border.top.width > 0) + DeleteObject(brush); + } + + /* Draw the bottom border if at the last paragraph in the cell, and when + * in the last row of the table. */ + if (atBottom) { + int oldLeft = rc.left; + width = max(ME_twips2pointsY(c, cell->border.bottom.width), 1); + paraAfterRow = ME_GetTableRowEnd(paragraph)->member.para.next_para; + if (paraAfterRow->member.para.nFlags & MEPF_ROWSTART) { + ME_DisplayItem *nextEndCell; + nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell); + assert(nextEndCell && !nextEndCell->member.cell.next_cell); + rc.left = nextEndCell->member.cell.pt.x; + /* FIXME: Native draws FROM the bottom of the table rather than + * TO the bottom of the table in this case, but just doing so here + * will case the next row to erase the border. */ + /* + rc.top = bottom; + rc.bottom = rc.top + width; + */ + } + if (rc.left < rc.right) { + if (cell->border.bottom.width > 0) { + brush = CreateSolidBrush(cell->border.bottom.colorRef); + } else { + brush = GetStockObject(LTGRAY_BRUSH); + } + rc.bottom = bottom; + rc.top = rc.bottom - width; + FillRect(c->hDC, &rc, brush); + if (cell->border.bottom.width > 0) + DeleteObject(brush); + } + rc.left = oldLeft; + } + + /* Right border only drawn if at the end of the table row. */ + if (!cell->next_cell->member.cell.next_cell && + !(para->nFlags & MEPF_ROWSTART)) + { + rc.top = top; + rc.bottom = bottom; + if (cell->border.right.width > 0) { + color = cell->border.right.colorRef; + width = max(ME_twips2pointsX(c, cell->border.right.width), 1); + } else { + color = RGB(192,192,192); + width = 1; + } + logBrush.lbStyle = BS_SOLID; + logBrush.lbColor = color; + logBrush.lbHatch = 0; + pen = ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER, + width, &logBrush, 0, NULL); + oldPen = SelectObject(c->hDC, pen); + MoveToEx(c->hDC, rc.right - 1, rc.top, &oldPt); + LineTo(c->hDC, rc.right - 1, rc.bottom); + SelectObject(c->hDC, oldPen); + DeleteObject(pen); + MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL); + } + } + } else { /* v1.0 - 3.0 */ + /* Draw simple table border */ + if (para->pFmt->dwMask & PFM_TABLE && para->pFmt->wEffects & PFE_TABLE) { + HPEN pen = NULL, oldpen = NULL; + int i, firstX, startX, endX, rowY, rowBottom, nHeight; + POINT oldPt; + PARAFORMAT2 *pNextFmt; + + pen = CreatePen(PS_SOLID, 0, para->border.top.colorRef); + oldpen = SelectObject(c->hDC, pen); + + /* Find the start relative to the text */ + firstX = ME_FindItemFwd(paragraph, diRun)->member.run.pt.x; + /* Go back by the horizontal gap, which is stored in dxOffset */ + firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset); + /* The left edge, stored in dxStartIndent affected just the first edge */ + startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent); + rowY = c->pt.y; + if (para->pFmt->dwMask & PFM_SPACEBEFORE) + rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore); + nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight; + rowBottom = rowY + nHeight; + + /* Draw horizontal lines */ + MoveToEx(c->hDC, firstX, rowY, &oldPt); + i = para->pFmt->cTabCount - 1; + endX = startX + ME_twips2pointsX(c, para->pFmt->rgxTabs[i] & 0x00ffffff) + 1; + LineTo(c->hDC, endX, rowY); + pNextFmt = para->next_para->member.para.pFmt; + /* The bottom of the row only needs to be drawn if the next row is + * not a table. */ + if (!(pNextFmt && pNextFmt->dwMask & PFM_TABLE && pNextFmt->wEffects && + para->nRows == 1)) + { + /* Decrement rowBottom to draw the bottom line within the row, and + * to not draw over this line when drawing the vertical lines. */ + rowBottom--; + MoveToEx(c->hDC, firstX, rowBottom, NULL); + LineTo(c->hDC, endX, rowBottom); + } + + /* Draw vertical lines */ + MoveToEx(c->hDC, firstX, rowY, NULL); + LineTo(c->hDC, firstX, rowBottom); + for (i = 0; i < para->pFmt->cTabCount; i++) + { + int rightBoundary = para->pFmt->rgxTabs[i] & 0x00ffffff; + endX = startX + ME_twips2pointsX(c, rightBoundary); + MoveToEx(c->hDC, endX, rowY, NULL); + LineTo(c->hDC, endX, rowBottom); + } + + MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL); + SelectObject(c->hDC, oldpen); + DeleteObject(pen); + } + } +} + void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { int align = SetTextAlign(c->hDC, TA_BASELINE); ME_DisplayItem *p; ME_Run *run; ME_Paragraph *para = NULL; - RECT rc, rcPara, bounds; + RECT rc, bounds; int y = c->pt.y; - int height = 0, baseline = 0, no=0, pno = 0; - int xs = 0, xe = 0; + int height = 0, baseline = 0, no=0; BOOL visible = FALSE; c->pt.x = c->rcView.left; - rcPara.left = c->rcView.left; - rcPara.right = c->rcView.right; + rc.left = c->rcView.left; + rc.right = c->rcView.right; for (p = paragraph; p!=paragraph->member.para.next_para; p = p->next) { switch(p->type) { case diParagraph: para = &p->member.para; assert(para); - pno = 0; - xs = c->rcView.left + ME_twips2pointsX(c, para->pFmt->dxStartIndent); - xe = c->rcView.right - ME_twips2pointsX(c, para->pFmt->dxRightIndent); + if (para->pCell) + { + ME_Cell *cell = ¶->pCell->member.cell; + rc.left = cell->pt.x; + rc.right = rc.left + cell->nWidth; + } + if (para->nFlags & MEPF_ROWSTART) { + ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; + rc.right = cell->pt.x; + } else if (para->nFlags & MEPF_ROWEND) { + ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; + rc.left = cell->pt.x + cell->nWidth; + } ME_DrawParaDecoration(c, para, y, &bounds); y += bounds.top; break; @@ -659,22 +947,18 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { /* we should have seen a diParagraph before */ assert(para); y += height; - rcPara.top = y; - rcPara.bottom = y+p->member.row.nHeight; - visible = RectVisible(c->hDC, &rcPara); - if (visible) { - /* left margin */ - rc.left = c->rcView.left + bounds.left; - rc.right = xs; - rc.top = y; + rc.top = y; + if (para->nFlags & MEPF_ROWSTART) { + ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; + rc.bottom = y + cell->nHeight; + } else if (para->nFlags & MEPF_ROWEND) { + ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; + rc.bottom = y + cell->nHeight; + } else { rc.bottom = y+p->member.row.nHeight; - FillRect(c->hDC, &rc, c->editor->hbrBackground); - /* right margin */ - rc.left = xe; - rc.right = c->rcView.right - bounds.right; - FillRect(c->hDC, &rc, c->editor->hbrBackground); - rc.left = xs; - rc.right = xe; + } + visible = RectVisible(c->hDC, &rc); + if (visible) { FillRect(c->hDC, &rc, c->editor->hbrBackground); } if (me_debug) @@ -686,11 +970,9 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { pt.y = 12+y; ME_DebugWrite(c->hDC, &pt, buf); } - + height = p->member.row.nHeight; baseline = p->member.row.nBaseline; - if (!pno++) - xe += ME_twips2pointsX(c, para->pFmt->dxOffset); break; case diRun: assert(para); @@ -721,11 +1003,27 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { } /* c->pt.x += p->member.run.nWidth; */ break; + case diCell: + /* Clear any space at the bottom of the cell after the text. */ + if (para->nFlags & MEPF_ROWSTART) + break; + y += height; + rc.top = y; + rc.bottom = p->member.cell.pt.y + p->member.cell.nHeight + - ME_GetYScrollPos(c->editor); + if (RectVisible(c->hDC, &rc)) + { + FillRect(c->hDC, &rc, c->editor->hbrBackground); + } + break; default: break; } no++; } + + ME_DrawTableBorders(c, paragraph); + SetTextAlign(c->hDC, align); } @@ -867,7 +1165,7 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun) assert(pRow); assert(pPara); - y = pPara->member.para.nYPos+pRow->member.row.nYPos; + y = pPara->member.para.pt.y+pRow->member.row.pt.y; yheight = pRow->member.row.nHeight; yold = ME_GetYScrollPos(editor); yrel = y - yold; diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 5289fdd5771..dd745ffc18a 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -104,17 +104,51 @@ void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, const ME_D } } +static void ME_UpdateTableFlags(ME_DisplayItem *para) +{ + para->member.para.pFmt->dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; + if (para->member.para.pCell) { + para->member.para.nFlags |= MEPF_CELL; + } else { + para->member.para.nFlags &= ~MEPF_CELL; + } + if (para->member.para.nFlags & MEPF_ROWEND) { + para->member.para.pFmt->wEffects |= PFE_TABLEROWDELIMITER; + } else { + para->member.para.pFmt->wEffects &= ~PFE_TABLEROWDELIMITER; + } + if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND)) + para->member.para.pFmt->wEffects |= PFE_TABLE; + else + para->member.para.pFmt->wEffects &= ~PFE_TABLE; +} + /* split paragraph at the beginning of the run */ -ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME_Style *style, int numCR, int numLF) +ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, + ME_Style *style, int numCR, int numLF, + int paraFlags) { ME_DisplayItem *next_para = NULL; ME_DisplayItem *run_para = NULL; ME_DisplayItem *new_para = ME_MakeDI(diParagraph); - ME_DisplayItem *end_run = ME_MakeRun(style,ME_MakeString(wszParagraphSign), MERF_ENDPARA); + ME_DisplayItem *end_run; ME_UndoItem *undo = NULL; int ofs; ME_DisplayItem *pp; int end_len = numCR + numLF; + int run_flags = MERF_ENDPARA; + if (!editor->bEmulateVersion10) { /* v4.1 */ + /* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */ + assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); + assert(!(paraFlags & (paraFlags-1))); + if (paraFlags == MEPF_CELL) + run_flags |= MERF_ENDCELL; + else if (paraFlags == MEPF_ROWSTART) + run_flags |= MERF_TABLESTART|MERF_HIDDEN; + } else { /* v1.0 - v3.0 */ + assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); + } + end_run = ME_MakeRun(style,ME_MakeString(wszParagraphSign), run_flags); assert(run->type == diRun); @@ -139,11 +173,12 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME } new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs; new_para->member.para.nCharOfs += end_len; - - new_para->member.para.nFlags = MEPF_REWRAP; /* FIXME copy flags (if applicable) */ + new_para->member.para.nFlags = MEPF_REWRAP; + /* FIXME initialize format style and call ME_SetParaFormat blah blah */ *new_para->member.para.pFmt = *run_para->member.para.pFmt; - + new_para->member.para.border = run_para->member.para.border; + /* insert paragraph into paragraph double linked list */ new_para->member.para.prev_para = run_para; new_para->member.para.next_para = next_para; @@ -154,6 +189,44 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME ME_InsertBefore(run, new_para); ME_InsertBefore(new_para, end_run); + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (paraFlags & (MEPF_ROWSTART|MEPF_CELL)) + { + ME_DisplayItem *cell = ME_MakeDI(diCell); + ME_InsertBefore(new_para, cell); + new_para->member.para.pCell = cell; + cell->member.cell.next_cell = NULL; + if (paraFlags & MEPF_ROWSTART) + { + run_para->member.para.nFlags |= MEPF_ROWSTART; + cell->member.cell.prev_cell = NULL; + cell->member.cell.parent_cell = run_para->member.para.pCell; + if (run_para->member.para.pCell) + cell->member.cell.nNestingLevel = run_para->member.para.pCell->member.cell.nNestingLevel + 1; + else + cell->member.cell.nNestingLevel = 1; + } else { + cell->member.cell.prev_cell = run_para->member.para.pCell; + assert(cell->member.cell.prev_cell); + cell->member.cell.prev_cell->member.cell.next_cell = cell; + assert(run_para->member.para.nFlags & MEPF_CELL); + assert(!(run_para->member.para.nFlags & MEPF_ROWSTART)); + cell->member.cell.nNestingLevel = cell->member.cell.prev_cell->member.cell.nNestingLevel; + cell->member.cell.parent_cell = cell->member.cell.prev_cell->member.cell.parent_cell; + } + } else if (paraFlags & MEPF_ROWEND) { + run_para->member.para.nFlags |= MEPF_ROWEND; + run_para->member.para.pCell = run_para->member.para.pCell->member.cell.parent_cell; + new_para->member.para.pCell = run_para->member.para.pCell; + assert(run_para->member.para.prev_para->member.para.nFlags & MEPF_CELL); + assert(!(run_para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)); + } else { + new_para->member.para.pCell = run_para->member.para.pCell; + } + ME_UpdateTableFlags(run_para); + ME_UpdateTableFlags(new_para); + } + /* force rewrap of the */ run_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; @@ -208,6 +281,42 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, ME_AddUndoItem(editor, diUndoSetParagraphFormat, tp); *tp->member.para.pFmt = *pNext->member.para.pFmt; } + + if (!editor->bEmulateVersion10) { /* v4.1 */ + /* Table cell/row properties are always moved over from the removed para. */ + tp->member.para.nFlags = pNext->member.para.nFlags; + tp->member.para.pCell = pNext->member.para.pCell; + + /* Remove cell boundary if it is between the end paragraph run and the next + * paragraph display item. */ + pTmp = pRun->next; + while (pTmp != pNext) { + if (pTmp->type == diCell) + { + ME_Cell *pCell = &pTmp->member.cell; + if (undo) + { + assert(!(undo->di.member.para.nFlags & MEPF_ROWEND)); + if (!(undo->di.member.para.nFlags & MEPF_ROWSTART)) + undo->di.member.para.nFlags |= MEPF_CELL; + undo->di.member.para.pCell = ALLOC_OBJ(ME_DisplayItem); + *undo->di.member.para.pCell = *pTmp; + undo->di.member.para.pCell->next = NULL; + undo->di.member.para.pCell->prev = NULL; + undo->di.member.para.pCell->member.cell.next_cell = NULL; + undo->di.member.para.pCell->member.cell.prev_cell = NULL; + } + ME_Remove(pTmp); + if (pCell->prev_cell) + pCell->prev_cell->member.cell.next_cell = pCell->next_cell; + if (pCell->next_cell) + pCell->next_cell->member.cell.prev_cell = pCell->prev_cell; + ME_DestroyDisplayItem(pTmp); + break; + } + pTmp = pTmp->next; + } + } shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len; @@ -322,7 +431,7 @@ void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) #undef DUMP_EFFECT } -void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt) +BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt) { PARAFORMAT2 copy; assert(sizeof(*para->member.para.pFmt) == sizeof(PARAFORMAT2)); @@ -379,6 +488,8 @@ void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFOR if (memcmp(©, para->member.para.pFmt, sizeof(PARAFORMAT2))) para->member.para.nFlags |= MEPF_REWRAP; + + return TRUE; } @@ -406,7 +517,7 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte } -void ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) +BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) { ME_DisplayItem *para, *para_end; @@ -418,6 +529,8 @@ void ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) break; para = para->member.para.next_para; } while(1); + + return TRUE; } void ME_GetParaFormat(ME_TextEditor *editor, const ME_DisplayItem *para, PARAFORMAT2 *pFmt) diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index 82038f69cdf..8801137bc96 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -169,10 +169,11 @@ RTFDestroy(RTF_Info *info) } RTFDestroyAttrs(info); heap_free(info->cpOutputBuffer); - if (info->tableDef) + while (info->tableDef) { - heap_free(info->tableDef); - info->tableDef = NULL; + RTFTable *tableDef = info->tableDef; + info->tableDef = tableDef->parent; + heap_free(tableDef); } } @@ -244,6 +245,9 @@ void RTFInit(RTF_Info *info) if (info->tableDef) ZeroMemory(info->tableDef, sizeof(info->tableDef)); info->tableDef = NULL; + info->nestingLevel = 0; + info->canInheritInTbl = FALSE; + info->borderType = 0; } /* @@ -1447,6 +1451,8 @@ static RTFKey rtfKey[] = /* is this valid? */ { rtfSpecialChar, rtfCurHeadPict, "chpict", 0 }, { rtfSpecialChar, rtfUnicode, "u", 0 }, + { rtfSpecialChar, rtfNestCell, "nestcell", 0 }, + { rtfSpecialChar, rtfNestRow, "nestrow", 0 }, /* * Character formatting attributes @@ -1610,6 +1616,7 @@ static RTFKey rtfKey[] = { rtfParAttr, rtfDarkDiagHatchBgPat, "bgdkdcross", 0 }, { rtfParAttr, rtfBgPatLineColor, "cfpat", 0 }, { rtfParAttr, rtfBgPatColor, "cbpat", 0 }, + { rtfParAttr, rtfNestLevel, "itap", 0 }, /* * Section formatting attributes @@ -1912,6 +1919,8 @@ static RTFKey rtfKey[] = { rtfDestination, rtfIndexRange, "rxe", 0 }, { rtfDestination, rtfTOC, "tc", 0 }, { rtfDestination, rtfNeXTGraphic, "NeXTGraphic", 0 }, + { rtfDestination, rtfNestTableProps, "nesttableprops", 0 }, + { rtfDestination, rtfNoNestTables, "nonesttables", 0 }, /* * Font families diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h index 87bab166253..ec08161a94b 100644 --- a/dlls/riched20/rtf.h +++ b/dlls/riched20/rtf.h @@ -182,7 +182,9 @@ # define rtfTOC 72 # define rtfNeXTGraphic 73 # define rtfGenerator 74 -# define rtfMaxDestination 75 /* highest dest + 1 */ +# define rtfNestTableProps 75 +# define rtfNoNestTables 76 +# define rtfMaxDestination 77 /* highest dest + 1 */ # define rtfFontFamily 4 # define rtfFFNil 0 @@ -261,6 +263,8 @@ # define rtfCurHeadPict 57 /* valid? */ /*# define rtfCurAnnot 58*/ /* apparently not used */ # define rtfUnicode 58 /* no better category*/ +# define rtfNestCell 59 +# define rtfNestRow 60 # define rtfStyleAttr 7 # define rtfAdditive 0 /* new in 1.10 */ @@ -551,6 +555,7 @@ # define rtfDarkDiagHatchBgPat 101 # define rtfBgPatLineColor 102 # define rtfBgPatColor 103 +# define rtfNestLevel 104 # define rtfCharAttr 12 # define rtfPlain 0 @@ -945,6 +950,7 @@ typedef struct RTFFont RTFFont; typedef struct RTFColor RTFColor; typedef struct RTFStyle RTFStyle; typedef struct RTFStyleElt RTFStyleElt; +typedef struct RTFBorder RTFBorder; typedef struct RTFCell RTFCell; typedef struct RTFTable RTFTable; @@ -1001,10 +1007,16 @@ struct RTFStyleElt RTFStyleElt *rtfNextSE; /* next element in style */ }; +struct RTFBorder +{ + int width; + int color; +}; struct RTFCell { int rightBoundary; + RTFBorder border[4]; }; @@ -1012,9 +1024,58 @@ struct RTFTable { RTFCell cells[MAX_TABLE_CELLS]; int numCellsDefined; + + int gapH, leftEdge; + /* borders for the table row */ + RTFBorder border[6]; + + /* Used in v1.0 - v3.0 */ int numCellsInserted; + + /* v4.1 */ + /* tableRowStart may be the start row paragraph of the table row, + * or it may store the end of the previous row if it may still be + * continued, otherwise NULL is stored. */ + ME_DisplayItem *tableRowStart; + + /* Table definitions are stored as a stack to support nested tables. */ + RTFTable *parent; }; + +# define RTFBorderTypeNone 0x00 +# define RTFBorderTypePara 0x10 /* for \brdrX control words */ +# define RTFBorderTypeRow 0x20 /* for \trbrdrX control words */ +# define RTFBorderTypeCell 0x30 /* for \clbrdrX control words */ +# define RTFBorderTypeMask 0xf0 + +/* The X in the control words \brdrX \trbrdrX and \clbrdrX mentioned above + * should be one of t, l, b, r which stand for top, left, bottom, right + * respectively. */ +# define RTFBorderSideTop 0x00 +# define RTFBorderSideLeft 0x01 +# define RTFBorderSideBottom 0x02 +# define RTFBorderSideRight 0x03 +# define RTFBorderSideHorizontal 0x04 +# define RTFBorderSideVertical 0x05 +# define RTFBorderSideMask 0x0f + +/* Here are the values from the border types and sides put together. */ +# define RTFBorderParaTop 0x10 +# define RTFBorderParaLeft 0x11 +# define RTFBorderParaBottom 0x12 +# define RTFBorderParaRight 0x13 +# define RTFBorderRowTop 0x20 +# define RTFBorderRowLeft 0x21 +# define RTFBorderRowBottom 0x22 +# define RTFBorderRowRight 0x23 +# define RTFBorderRowHorizontal 0x24 +# define RTFBorderRowVertical 0x25 +# define RTFBorderCellTop 0x30 +# define RTFBorderCellLeft 0x31 +# define RTFBorderCellBottom 0x32 +# define RTFBorderCellRight 0x33 + /* * Return pointer to new element of type t, or NULL * if no memory available. @@ -1121,6 +1182,9 @@ struct _RTF_Info { LPRICHEDITOLE lpRichEditOle; RTFTable *tableDef; + int nestingLevel; + BOOL canInheritInTbl; + int borderType; /* value corresponds to the RTFBorder constants. */ }; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index e7ce035980c..bb34ad864ed 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -134,6 +134,9 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) else ofs += ME_StrLen(p->member.run.strText); break; + case diCell: + TRACE_(richedit_check)("cell\n"); + break; default: assert(0); } @@ -436,7 +439,7 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) { assert(run->nCharOfs != -1); - if (RUN_IS_HIDDEN(run)) + if (RUN_IS_HIDDEN(run) || run->nFlags & MERF_TABLESTART) run->nFlags |= MERF_HIDDEN; else run->nFlags &= ~MERF_HIDDEN; @@ -483,7 +486,8 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) if (!run->strText->nLen) return 0; - if (run->nFlags & MERF_TAB) + if (run->nFlags & MERF_TAB || + (run->nFlags & (MERF_ENDCELL|MERF_ENDPARA)) == MERF_ENDCELL) { if (cx < run->nWidth/2) return 0; @@ -540,7 +544,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) if (!run->strText->nLen) return 0; - if (run->nFlags & MERF_TAB) + if (run->nFlags & (MERF_TAB | MERF_ENDCELL)) { if (cx < run->nWidth/2) return 0; @@ -667,13 +671,21 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run if (run->nFlags & MERF_TAB) { - int pos = 0, i = 0, ppos; + int pos = 0, i = 0, ppos, shift = 0; PARAFORMAT2 *pFmt = para->pFmt; + if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + /* The horizontal gap shifts the tab positions to leave the gap. */ + shift = pFmt->dxOffset * 2; do { if (i < pFmt->cTabCount) { - pos = pFmt->rgxTabs[i]&0x00FFFFFF; + /* Only one side of the horizontal gap is needed at the end of + * the table row. */ + if (i == pFmt->cTabCount -1) + shift = shift >> 1; + pos = shift + (pFmt->rgxTabs[i]&0x00FFFFFF); i++; } else diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c new file mode 100644 index 00000000000..248ea11719f --- /dev/null +++ b/dlls/riched20/table.c @@ -0,0 +1,618 @@ +/* + * RichEdit functions dealing with on tables + * + * Copyright 2008 by Dylan Smith + * + * 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 + */ + +/* + * The implementation of tables differs greatly between version 3.0 + * (in riched20.dll) and version 4.1 (in msftedit.dll) of richedit controls. + * Currently Wine is not distinguishing between version 3.0 and version 4.1, + * so v4.1 is assumed unless v1.0 is being emulated (i.e. riched32.dll is used). + * If this lack of distinction causes a bug in a Windows application, then Wine + * will need to start making this distinction. + * + * Richedit version 1.0 - 3.0: + * Tables are implemented in these versions using tabs at the end of cells, + * and tab stops to position the cells. The paragraph format flag PFE_TABLE + * will indicate the the paragraph is a table row. Note that in this + * implementation there is one paragraph per table row. + * + * Richedit version 4.1: + * Tables are implemented such that cells can contain multiple paragraphs, + * each with it's own paragraph format, and cells may even contain tables + * nested within the cell. + * + * There are is also a paragraph at the start of each table row that contains + * the rows paragraph format (e.g. to change the row alignment to row), and a + * paragraph at the end of the table row with the PFE_TABLEROWDELIMITER flag + * set. The paragraphs at the start and end of the table row should always be + * empty, but should have a length of 2. + * + * Wine implements this using display items (ME_DisplayItem) with a type of + * diCell. These cell display items store the cell properties, and are + * inserted into the editors linked list before each cell, and at the end of + * the last cell. The cell display item for a cell comes before the paragraphs + * for the cell, but the last cell display item refers to no cell, so it is + * just a delimiter. + */ + +#include "editor.h" +#include "rtf.h" + +WINE_DEFAULT_DEBUG_CHANNEL(richedit); +WINE_DECLARE_DEBUG_CHANNEL(richedit_lists); + +static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor, + int nCursor, + int numCR, + int numLF, + int paraFlags) +{ + ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); + ME_DisplayItem *tp; + ME_Cursor* cursor = &editor->pCursors[nCursor]; + if (cursor->nOffset) { + ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset); + cursor = &editor->pCursors[nCursor]; + } + + tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, numCR, numLF, paraFlags); + cursor->pRun = ME_FindItemFwd(tp, diRun); + return tp; +} + +ME_DisplayItem* ME_InsertTableRowStartFromCursor(ME_TextEditor *editor) +{ + ME_DisplayItem *para; + para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWSTART); + return para->member.para.prev_para; +} + +ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, + ME_DisplayItem *para) +{ + ME_DisplayItem *prev_para, *end_para; + ME_Cursor savedCursor = editor->pCursors[0]; + ME_DisplayItem *startRowPara; + editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + startRowPara = ME_InsertTableRowStartFromCursor(editor); + editor->pCursors[0] = savedCursor; + editor->pCursors[1] = editor->pCursors[0]; + + end_para = ME_GetParagraph(editor->pCursors[0].pRun)->member.para.next_para; + prev_para = startRowPara->member.para.next_para; + para = prev_para->member.para.next_para; + while (para != end_para) + { + para->member.para.pCell = prev_para->member.para.pCell; + para->member.para.nFlags |= MEPF_CELL; + para->member.para.nFlags &= ~(MEPF_ROWSTART|MEPF_ROWEND); + para->member.para.pFmt->dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; + para->member.para.pFmt->wEffects |= PFE_TABLE; + para->member.para.pFmt->wEffects &= ~PFE_TABLEROWDELIMITER; + prev_para = para; + para = para->member.para.next_para; + } + return startRowPara; +} + +/* Inserts a diCell and starts a new paragraph for the next cell. + * + * Returns the first paragraph of the new cell. */ +ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor) +{ + ME_DisplayItem *para; + para = ME_InsertEndParaFromCursor(editor, 0, 1, 0, MEPF_CELL); + return para; +} + +ME_DisplayItem* ME_InsertTableRowEndFromCursor(ME_TextEditor *editor) +{ + ME_DisplayItem *para; + para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWEND); + return para->member.para.prev_para; +} + +ME_DisplayItem* ME_GetTableRowEnd(ME_DisplayItem *para) +{ + ME_DisplayItem *cell; + assert(para); + if (para->member.para.nFlags & MEPF_ROWEND) + return para; + if (para->member.para.nFlags & MEPF_ROWSTART) + para = para->member.para.next_para; + cell = para->member.para.pCell; + assert(cell && cell->type == diCell); + while (cell->member.cell.next_cell) + cell = cell->member.cell.next_cell; + + para = ME_FindItemFwd(cell, diParagraph); + assert(para && para->member.para.nFlags & MEPF_ROWEND); + return para; +} + +ME_DisplayItem* ME_GetTableRowStart(ME_DisplayItem *para) +{ + ME_DisplayItem *cell; + assert(para); + if (para->member.para.nFlags & MEPF_ROWSTART) + return para; + if (para->member.para.nFlags & MEPF_ROWEND) + para = para->member.para.prev_para; + cell = para->member.para.pCell; + assert(cell && cell->type == diCell); + while (cell->member.cell.prev_cell) + cell = cell->member.cell.prev_cell; + + para = ME_FindItemBack(cell, diParagraph); + assert(para && para->member.para.nFlags & MEPF_ROWSTART); + return para; +} + +/* Make a bunch of assertions to make sure tables haven't been corrupted. + * + * These invariants may not hold true in the middle of streaming in rich text + * or during an undo and redo of streaming in rich text. It should be safe to + * call this method after an event is processed. + */ +void ME_CheckTablesForCorruption(ME_TextEditor *editor) +{ + if(TRACE_ON(richedit_lists)) + { + TRACE_(richedit_lists)("---\n"); + ME_DumpDocument(editor->pBuffer); + } +#ifndef NDEBUG + { + ME_DisplayItem *p, *pPrev; + pPrev = editor->pBuffer->pFirst; + p = pPrev->next; + if (!editor->bEmulateVersion10) /* v4.1 */ + { + while (p->type == diParagraph) + { + assert(p->member.para.pFmt->dwMask & PFM_TABLE); + assert(p->member.para.pFmt->dwMask & PFM_TABLEROWDELIMITER); + if (p->member.para.pCell) + { + assert(p->member.para.nFlags & MEPF_CELL); + assert(p->member.para.pFmt->wEffects & PFE_TABLE); + } + if (p->member.para.pCell != pPrev->member.para.pCell) + { + /* There must be a diCell in between the paragraphs if pCell changes. */ + ME_DisplayItem *pCell = ME_FindItemBack(p, diCell); + assert(pCell); + assert(ME_FindItemBack(p, diRun) == ME_FindItemBack(pCell, diRun)); + } + if (p->member.para.nFlags & MEPF_ROWEND) + { + /* ROWEND must come after a cell. */ + assert(pPrev->member.para.pCell); + assert(p->member.para.pCell + == pPrev->member.para.pCell->member.cell.parent_cell); + assert(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER); + } + else if (p->member.para.pCell) + { + assert(!(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER)); + assert(pPrev->member.para.pCell || + pPrev->member.para.nFlags & MEPF_ROWSTART); + if (pPrev->member.para.pCell && + !(pPrev->member.para.nFlags & MEPF_ROWSTART)) + { + assert(p->member.para.pCell->member.cell.parent_cell + == pPrev->member.para.pCell->member.cell.parent_cell); + if (pPrev->member.para.pCell != p->member.para.pCell) + assert(pPrev->member.para.pCell + == p->member.para.pCell->member.cell.prev_cell); + } + } + else if (!(p->member.para.nFlags & MEPF_ROWSTART)) + { + assert(!(p->member.para.pFmt->wEffects & (PFE_TABLE|PFE_TABLEROWDELIMITER))); + /* ROWSTART must be followed by a cell. */ + assert(!(p->member.para.nFlags & MEPF_CELL)); + /* ROWSTART must be followed by a cell. */ + assert(!(pPrev->member.para.nFlags & MEPF_ROWSTART)); + } + pPrev = p; + p = p->member.para.next_para; + } + } else { /* v1.0 - 3.0 */ + while (p->type == diParagraph) + { + assert(!(p->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); + assert(p->member.para.pFmt->dwMask & PFM_TABLE); + assert(!(p->member.para.pFmt->wEffects & PFM_TABLEROWDELIMITER)); + assert(!p->member.para.pCell); + p = p->member.para.next_para; + } + return; + } + assert(p->type == diTextEnd); + assert(!pPrev->member.para.pCell); + } +#endif +} + +BOOL ME_IsInTable(ME_DisplayItem *pItem) +{ + PARAFORMAT2 *pFmt; + if (!pItem) + return FALSE; + if (pItem->type == diRun) + pItem = ME_GetParagraph(pItem); + if (pItem->type != diParagraph) + return FALSE; + pFmt = pItem->member.para.pFmt; + return pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE; +} + +/* Table rows should either be deleted completely or not at all. */ +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars) +{ + ME_Cursor c, c2; + ME_DisplayItem *this_para, *end_para; + ME_CursorFromCharOfs(editor, nOfs, &c); + this_para = ME_GetParagraph(c.pRun); + ME_CursorFromCharOfs(editor, nOfs + *nChars, &c2); + end_para = ME_GetParagraph(c2.pRun); + if (c2.pRun->member.run.nFlags & MERF_ENDPARA) { + /* End offset might be in the middle of the end paragraph run. + * If this is the case, then we need to use the next paragraph as the last + * paragraphs. + */ + int remaining = nOfs + *nChars - c2.pRun->member.run.nCharOfs + - end_para->member.para.nCharOfs; + if (remaining) + { + assert(remaining < c2.pRun->member.run.nCR + c2.pRun->member.run.nLF); + end_para = end_para->member.para.next_para; + } + } + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (this_para->member.para.pCell != end_para->member.para.pCell || + ((this_para->member.para.nFlags|end_para->member.para.nFlags) + & (MEPF_ROWSTART|MEPF_ROWEND))) + { + while (this_para != end_para) + { + ME_DisplayItem *next_para = this_para->member.para.next_para; + BOOL bTruancateDeletion = FALSE; + if (this_para->member.para.nFlags & MEPF_ROWSTART) { + /* The following while loop assumes that next_para is MEPF_ROWSTART, + * so moving back one paragraph let's it be processed as the start + * of the row. */ + next_para = this_para; + this_para = this_para->member.para.prev_para; + } else if (next_para->member.para.pCell != this_para->member.para.pCell + || this_para->member.para.nFlags & MEPF_ROWEND) + { + /* Start of the deletion from after the start of the table row. */ + bTruancateDeletion = TRUE; + } + while (!bTruancateDeletion && + next_para->member.para.nFlags & MEPF_ROWSTART) + { + next_para = ME_GetTableRowEnd(next_para)->member.para.next_para; + if (next_para->member.para.nCharOfs > nOfs + *nChars) + { + /* End of deletion is not past the end of the table row. */ + next_para = this_para->member.para.next_para; + /* Delete the end paragraph preceding the table row if the + * preceding table row will be empty. */ + if (this_para->member.para.nCharOfs >= nOfs) + { + next_para = next_para->member.para.next_para; + } + bTruancateDeletion = TRUE; + } else { + this_para = next_para->member.para.prev_para; + } + } + if (bTruancateDeletion) + { + ME_Run *end_run = &ME_FindItemBack(next_para, diRun)->member.run; + int nCharsNew = (next_para->member.para.nCharOfs - nOfs + - end_run->nCR - end_run->nLF); + nCharsNew = max(nCharsNew, 0); + assert(nCharsNew <= *nChars); + *nChars = nCharsNew; + break; + } + this_para = next_para; + } + } + } else { /* v1.0 - 3.0 */ + ME_DisplayItem *pRun; + int nCharsToBoundary; + + if (this_para->member.para.nCharOfs != nOfs && + this_para->member.para.pFmt->dwMask & PFM_TABLE && + this_para->member.para.pFmt->wEffects & PFE_TABLE) + { + pRun = c.pRun; + /* Find the next tab or end paragraph to use as a delete boundary */ + while (!(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) + pRun = ME_FindItemFwd(pRun, diRun); + nCharsToBoundary = pRun->member.run.nCharOfs + - c.pRun->member.run.nCharOfs + - c.nOffset; + *nChars = min(*nChars, nCharsToBoundary); + } else if (end_para->member.para.pFmt->dwMask & PFM_TABLE && + end_para->member.para.pFmt->wEffects & PFE_TABLE) + { + if (this_para == end_para) + { + pRun = c2.pRun; + /* Find the previous tab or end paragraph to use as a delete boundary */ + while (pRun && !(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) + pRun = ME_FindItemBack(pRun, diRun); + if (pRun && pRun->member.run.nFlags & MERF_ENDPARA) + { + /* We are in the first cell, and have gone back to the previous + * paragraph, so nothing needs to be protected. */ + pRun = NULL; + } + } else { + /* The deletion starts from before the row, so don't join it with + * previous non-empty paragraphs. */ + pRun = NULL; + if (nOfs > this_para->member.para.nCharOfs) + pRun = ME_FindItemBack(end_para, diRun); + if (!pRun) + pRun = ME_FindItemFwd(end_para, diRun); + } + if (pRun) + { + nCharsToBoundary = ME_GetParagraph(pRun)->member.para.nCharOfs + + pRun->member.run.nCharOfs + - nOfs; + if (nCharsToBoundary >= 0) + *nChars = min(*nChars, nCharsToBoundary); + } + } + if (*nChars < 0) + nChars = 0; + } +} + +static ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, + ME_DisplayItem *table_row) +{ + WCHAR endl = '\r', tab = '\t'; + ME_DisplayItem *run; + PARAFORMAT2 *pFmt; + int i; + + assert(table_row); + if (!editor->bEmulateVersion10) { /* v4.1 */ + ME_DisplayItem *insertedCell, *para, *cell; + cell = ME_FindItemFwd(table_row, diCell); + run = ME_GetTableRowEnd(table_row)->member.para.next_para; + run = ME_FindItemFwd(run, diRun); + editor->pCursors[0].pRun = run; + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + para = ME_InsertTableRowStartFromCursor(editor); + insertedCell = ME_FindItemFwd(para, diCell); + /* Copy cell properties */ + insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; + while (cell->member.cell.next_cell) { + cell = cell->member.cell.next_cell; + para = ME_InsertTableCellFromCursor(editor); + insertedCell = ME_FindItemBack(para, diCell); + /* Copy cell properties */ + insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; + }; + ME_InsertTableRowEndFromCursor(editor); + /* return the table row start for the inserted paragraph */ + return ME_FindItemFwd(cell, diParagraph)->member.para.next_para; + } else { /* v1.0 - 3.0 */ + run = ME_FindItemBack(table_row->member.para.next_para, diRun); + pFmt = table_row->member.para.pFmt; + assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE); + editor->pCursors[0].pRun = run; + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + ME_InsertTextFromCursor(editor, 0, &endl, 1, run->member.run.style); + run = editor->pCursors[0].pRun; + for (i = 0; i < pFmt->cTabCount; i++) { + ME_InsertTextFromCursor(editor, 0, &tab, 1, run->member.run.style); + } + return table_row->member.para.next_para; + } +} + +/* Selects the next table cell or appends a new table row if at end of table */ +static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, + ME_DisplayItem *run) +{ + ME_DisplayItem *para = ME_GetParagraph(run); + int i; + + assert(run && run->type == diRun); + assert(ME_IsInTable(run)); + if (!editor->bEmulateVersion10) { /* v4.1 */ + ME_DisplayItem *cell; + /* Get the initial cell */ + if (para->member.para.nFlags & MEPF_ROWSTART) { + cell = para->member.para.next_para->member.para.pCell; + } else if (para->member.para.nFlags & MEPF_ROWEND) { + cell = para->member.para.prev_para->member.para.pCell; + } else { + cell = para->member.para.pCell; + } + assert(cell); + /* Get the next cell. */ + if (cell->member.cell.next_cell && + cell->member.cell.next_cell->member.cell.next_cell) + { + cell = cell->member.cell.next_cell; + } else { + para = ME_GetTableRowEnd(ME_FindItemFwd(cell, diParagraph)); + para = para->member.para.next_para; + assert(para); + if (para->member.para.nFlags & MEPF_ROWSTART) { + cell = para->member.para.next_para->member.para.pCell; + } else { + /* Insert row */ + para = para->member.para.prev_para; + para = ME_AppendTableRow(editor, ME_GetTableRowStart(para)); + /* Put cursor at the start of the new table row */ + para = para->member.para.next_para; + editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + ME_WrapMarkedParagraphs(editor); + return; + } + } + /* Select cell */ + editor->pCursors[1].pRun = ME_FindItemFwd(cell, diRun); + editor->pCursors[1].nOffset = 0; + assert(editor->pCursors[0].pRun); + cell = cell->member.cell.next_cell; + editor->pCursors[0].pRun = ME_FindItemBack(cell, diRun); + editor->pCursors[0].nOffset = 0; + assert(editor->pCursors[1].pRun); + } else { /* v1.0 - 3.0 */ + if (run->member.run.nFlags & MERF_ENDPARA && + ME_IsInTable(ME_FindItemFwd(run, diParagraphOrEnd))) + { + run = ME_FindItemFwd(run, diRun); + assert(run); + } + for (i = 0; i < 2; i++) + { + while (!(run->member.run.nFlags & MERF_TAB)) + { + run = ME_FindItemFwd(run, diRunOrParagraphOrEnd); + if (run->type != diRun) + { + para = run; + if (ME_IsInTable(para)) + { + run = ME_FindItemFwd(para, diRun); + assert(run); + editor->pCursors[0].pRun = run; + editor->pCursors[0].nOffset = 0; + i = 1; + } else { + /* Insert table row */ + para = ME_AppendTableRow(editor, para->member.para.prev_para); + /* Put cursor at the start of the new table row */ + editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; + ME_WrapMarkedParagraphs(editor); + return; + } + } + } + if (i == 0) + run = ME_FindItemFwd(run, diRun); + editor->pCursors[i].pRun = run; + editor->pCursors[i].nOffset = 0; + } + } +} + + +void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) +{ + /* FIXME: Shift tab should move to the previous cell. */ + ME_Cursor fromCursor, toCursor; + ME_InvalidateSelection(editor); + { + int from, to; + from = ME_GetCursorOfs(editor, 0); + to = ME_GetCursorOfs(editor, 1); + if (from <= to) + { + fromCursor = editor->pCursors[0]; + toCursor = editor->pCursors[1]; + } else { + fromCursor = editor->pCursors[1]; + toCursor = editor->pCursors[0]; + } + } + if (!editor->bEmulateVersion10) /* v4.1 */ + { + if (!ME_IsInTable(toCursor.pRun)) + { + editor->pCursors[0] = toCursor; + editor->pCursors[1] = toCursor; + } else { + ME_SelectOrInsertNextCell(editor, toCursor.pRun); + } + } else { /* v1.0 - 3.0 */ + if (!ME_IsInTable(fromCursor.pRun)) { + editor->pCursors[0] = fromCursor; + editor->pCursors[1] = fromCursor; + /* FIXME: For some reason the caret is shown at the start of the + * previous paragraph in v1.0 to v3.0, and bCaretAtEnd only works + * within the paragraph for wrapped lines. */ + if (ME_FindItemBack(fromCursor.pRun, diRun)) + editor->bCaretAtEnd = TRUE; + } else if ((bSelectedRow || !ME_IsInTable(toCursor.pRun))) { + ME_SelectOrInsertNextCell(editor, fromCursor.pRun); + } else { + if (ME_IsSelection(editor) && !toCursor.nOffset) + { + ME_DisplayItem *run; + run = ME_FindItemBack(toCursor.pRun, diRunOrParagraphOrEnd); + if (run->type == diRun && run->member.run.nFlags & MERF_TAB) + ME_SelectOrInsertNextCell(editor, run); + else + ME_SelectOrInsertNextCell(editor, toCursor.pRun); + } else { + ME_SelectOrInsertNextCell(editor, toCursor.pRun); + } + } + } + ME_InvalidateSelection(editor); + ME_Repaint(editor); + HideCaret(editor->hWnd); + ME_ShowCaret(editor); + ME_SendSelChange(editor); +} + +struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor) +{ + RTFTable *tableDef = ALLOC_OBJ(RTFTable); + ZeroMemory(tableDef, sizeof(RTFTable)); + if (!editor->bEmulateVersion10) /* v4.1 */ + tableDef->gapH = 10; + return tableDef; +} + +void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) +{ + ZeroMemory(tableDef->cells, sizeof(tableDef->cells)); + ZeroMemory(tableDef->border, sizeof(tableDef->border)); + tableDef->numCellsDefined = 0; + tableDef->leftEdge = 0; + if (!editor->bEmulateVersion10) /* v4.1 */ + tableDef->gapH = 10; + else /* v1.0 - 3.0 */ + tableDef->gapH = 0; +} diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 15cef753388..765e8e27d3f 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -1087,6 +1087,27 @@ static void test_EM_SETTEXTMODE(void) DestroyWindow(hwndRichEdit); } +static void test_SETPARAFORMAT(void) +{ + HWND hwndRichEdit = new_richedit(NULL); + PARAFORMAT2 fmt; + HRESULT ret; + fmt.cbSize = sizeof(PARAFORMAT2); + fmt.dwMask = PFM_ALIGNMENT; + fmt.wAlignment = PFA_LEFT; + + ret = SendMessage(hwndRichEdit, EM_SETPARAFORMAT, 0, (LPARAM) &fmt); + ok(ret != 0, "expected non-zero got %d\n", ret); + + fmt.cbSize = sizeof(PARAFORMAT2); + fmt.dwMask = -1; + ret = SendMessage(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM) &fmt); + ok(ret == PFM_ALL2, "expected %x got %x\n", PFM_ALL2, ret); + ok(fmt.dwMask == PFM_ALL2, "expected %x got %x\n", PFM_ALL2, fmt.dwMask); + + DestroyWindow(hwndRichEdit); +} + static void test_TM_PLAINTEXT(void) { /*Tests plain text properties*/ @@ -5396,6 +5417,7 @@ START_TEST( editor ) test_undo_coalescing(); test_word_movement(); test_EM_CHARFROMPOS(); + test_SETPARAFORMAT(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging. diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index 9fcdc4b553a..3ab39d01526 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -89,10 +89,17 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp case diUndoJoinParagraphs: break; case diUndoSplitParagraph: + { + ME_DisplayItem *prev_para = pdi->member.para.prev_para; assert(pdi->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2); + pItem->member.para.pFmt->cbSize = sizeof(PARAFORMAT2); + pItem->member.para.pFmt->dwMask = 0; *pItem->member.para.pFmt = *pdi->member.para.pFmt; + pItem->member.para.nFlags = prev_para->member.para.nFlags & ~MEPF_CELL; + pItem->member.para.pCell = NULL; break; + } default: assert(0 == "AddUndoItem, unsupported item type"); return NULL; @@ -300,7 +307,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) } case diUndoDeleteRun: { - ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen); + ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen, TRUE); break; } case diUndoJoinParagraphs: @@ -314,16 +321,35 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) case diUndoSplitParagraph: { ME_Cursor tmp; - ME_DisplayItem *new_para; + ME_DisplayItem *this_para, *new_para; + BOOL bFixRowStart; + int paraFlags = pItem->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND); ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp); if (tmp.nOffset) tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset); assert(pUItem->nCR >= 0); assert(pUItem->nLF >= 0); + this_para = ME_GetParagraph(tmp.pRun); + bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART; + if (bFixRowStart) + { + /* Re-insert the paragraph before the table, making sure the nFlag value + * is correct. */ + this_para->member.para.nFlags &= ~MEPF_ROWSTART; + } new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style, - pUItem->nCR, pUItem->nLF); + pUItem->nCR, pUItem->nLF, paraFlags); + if (bFixRowStart) + new_para->member.para.nFlags |= MEPF_ROWSTART; assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); *new_para->member.para.pFmt = *pItem->member.para.pFmt; + if (pItem->member.para.pCell) + { + ME_DisplayItem *pItemCell, *pCell; + pItemCell = pItem->member.para.pCell; + pCell = new_para->member.para.pCell; + pCell->member.cell.nRightBoundary = pItemCell->member.cell.nRightBoundary; + } break; } default: @@ -361,6 +387,7 @@ BOOL ME_Undo(ME_TextEditor *editor) { if (p) p->prev = NULL; ME_AddUndoItem(editor, diUndoEndTransaction, NULL); + ME_CheckTablesForCorruption(editor); editor->nUndoStackSize--; editor->nUndoMode = nMode; ME_UpdateRepaint(editor); @@ -396,6 +423,7 @@ BOOL ME_Redo(ME_TextEditor *editor) { if (p) p->prev = NULL; ME_AddUndoItem(editor, diUndoEndTransaction, NULL); + ME_CheckTablesForCorruption(editor); editor->nUndoMode = nMode; ME_UpdateRepaint(editor); return TRUE; diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index 5fe2209c2b5..a3c5d544ff6 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -42,17 +42,48 @@ static ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) return item; } -static void ME_BeginRow(ME_WrapContext *wc) +static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para) { + PARAFORMAT2 *pFmt; + assert(para && para->type == diParagraph); + pFmt = para->member.para.pFmt; wc->pRowStart = NULL; wc->bOverflown = FALSE; wc->pLastSplittableRun = NULL; - if (wc->context->editor->bWordWrap) - wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left - - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; - else + if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) { + wc->nAvailWidth = 0; + if (para->member.para.nFlags & MEPF_ROWEND) + { + ME_Cell *cell = &ME_FindItemBack(para, diCell)->member.cell; + cell->nWidth = 0; + } + } else if (para->member.para.pCell) { + ME_Cell *cell = ¶->member.para.pCell->member.cell; + int width; + + width = cell->nRightBoundary; + if (cell->prev_cell) + width -= cell->prev_cell->member.cell.nRightBoundary; + if (!cell->prev_cell) + { + int rowIndent = ME_GetTableRowEnd(para)->member.para.pFmt->dxStartIndent; + width -= rowIndent; + } + cell->nWidth = max(ME_twips2pointsX(wc->context, width), 0); + + wc->nAvailWidth = cell->nWidth + - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; + } else if (wc->context->editor->bWordWrap) { + wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left + - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; + } else { wc->nAvailWidth = ~0u >> 1; - wc->pt.x = 0; + } + wc->pt.x = wc->context->pt.x; + if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + /* Shift the text down because of the border. */ + wc->pt.y++; } static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) @@ -60,8 +91,10 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) ME_DisplayItem *p, *row, *para; BOOL bSkippingSpaces = TRUE; int ascent = 0, descent = 0, width=0, shift = 0, align = 0; + PARAFORMAT2 *pFmt; /* wrap text */ para = ME_GetParagraph(wc->pRowStart); + pFmt = para->member.para.pFmt; for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev) { @@ -100,7 +133,16 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) } row = ME_MakeRow(ascent+descent, ascent, width); - row->member.row.nYPos = wc->pt.y; + if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + { + /* The text was shifted down in ME_BeginRow so move the wrap context + * back to where it should be. */ + wc->pt.y--; + /* The height of the row is increased by the borders. */ + row->member.row.nHeight += 2; + } + row->member.row.pt = wc->pt; row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin); row->member.row.nRMargin = wc->nRightMargin; assert(para->member.para.pFmt->dwMask & PFM_ALIGNMENT); @@ -117,14 +159,23 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) } ME_InsertBefore(wc->pRowStart, row); wc->nRow++; - wc->pt.y += ascent+descent; - ME_BeginRow(wc); + wc->pt.y += row->member.row.nHeight; + ME_BeginRow(wc, para); } static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) { + ME_DisplayItem *para = p->member.para.prev_para; + PARAFORMAT2 *pFmt = para->member.para.pFmt; if (wc->pRowStart) ME_InsertRowStart(wc, p); + if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + { + /* ME_BeginRow was called an extra time for the paragraph, and it shifts the + * text down by one pixel for the border, so fix up the wrap context. */ + wc->pt.y--; + } /* p = p->member.para.prev_para->next; @@ -326,9 +377,9 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) } /* will current run fit? */ - if (wc->pt.x + run->nWidth > wc->nAvailWidth) + if (wc->pt.x + run->nWidth > wc->context->pt.x + wc->nAvailWidth) { - int loc = wc->nAvailWidth - wc->pt.x; + int loc = wc->context->pt.x + wc->nAvailWidth - wc->pt.x; /* total white run ? */ if (run->nFlags & MERF_WHITESPACE) { /* let the overflow logic handle it */ @@ -407,40 +458,55 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD begino ME_WrapContext wc; int border = 0; int linespace = 0; + PARAFORMAT2 *pFmt; assert(tp->type == diParagraph); if (!(tp->member.para.nFlags & MEPF_REWRAP)) { return; } ME_PrepareParagraphForWrapping(c, tp); + pFmt = tp->member.para.pFmt; wc.context = c; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; - wc.nFirstMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxStartIndent) + beginofs; - wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, tp->member.para.pFmt->dxOffset); - wc.nRightMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxRightIndent); + if (tp->member.para.nFlags & MEPF_ROWEND) { + wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0; + } else { + int dxStartIndent = pFmt->dxStartIndent; + if (tp->member.para.pCell) { + dxStartIndent += ME_GetTableRowEnd(tp)->member.para.pFmt->dxOffset; + } + wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent); + wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, pFmt->dxOffset); + wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent); + } + if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + { + wc.nFirstMargin += ME_twips2pointsX(c, pFmt->dxOffset * 2); + } wc.nRow = 0; - wc.pt.x = 0; wc.pt.y = 0; - if (tp->member.para.pFmt->dwMask & PFM_SPACEBEFORE) - wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceBefore); - if (tp->member.para.pFmt->dwMask & PFM_BORDER) + if (pFmt->dwMask & PFM_SPACEBEFORE) + wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceBefore); + if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && + pFmt->dwMask & PFM_BORDER) { border = ME_GetParaBorderWidth(c->editor, tp->member.para.pFmt->wBorders); - if (tp->member.para.pFmt->wBorders & 1) { + if (pFmt->wBorders & 1) { wc.nFirstMargin += border; wc.nLeftMargin += border; } - if (tp->member.para.pFmt->wBorders & 2) + if (pFmt->wBorders & 2) wc.nRightMargin -= border; - if (tp->member.para.pFmt->wBorders & 4) + if (pFmt->wBorders & 4) wc.pt.y += border; } linespace = ME_GetParaLineSpace(c, &tp->member.para); - ME_BeginRow(&wc); + ME_BeginRow(&wc, tp); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); if (p->type == diRun) { @@ -451,10 +517,11 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD begino wc.pt.y += linespace; } ME_WrapEndParagraph(&wc, p); - if ((tp->member.para.pFmt->dwMask & PFM_BORDER) && (tp->member.para.pFmt->wBorders & 8)) + if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && + (pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8)) wc.pt.y += border; if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER) - wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceAfter); + wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceAfter); tp->member.para.nFlags &= ~MEPF_REWRAP; tp->member.para.nHeight = wc.pt.y; @@ -509,17 +576,18 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { int yLastPos = 0; ME_InitContext(&c, editor, GetDC(editor->hWnd)); + c.pt.x = editor->selofs; editor->nHeight = 0; item = editor->pBuffer->pFirst->next; while(item != editor->pBuffer->pLast) { BOOL bRedraw = FALSE; assert(item->type == diParagraph); - editor->nHeight = max(editor->nHeight, item->member.para.nYPos); + editor->nHeight = max(editor->nHeight, item->member.para.pt.y); if ((item->member.para.nFlags & MEPF_REWRAP) - || (item->member.para.nYPos != c.pt.y)) + || (item->member.para.pt.y != c.pt.y)) bRedraw = TRUE; - item->member.para.nYPos = c.pt.y; + item->member.para.pt = c.pt; ME_WrapTextParagraph(&c, item, editor->selofs); @@ -532,24 +600,129 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { bModified = bModified | bRedraw; - yLastPos = c.pt.y; - c.pt.y += item->member.para.nHeight; + yLastPos = max(yLastPos, c.pt.y); + + if (item->member.para.nFlags & MEPF_ROWSTART) + { + ME_DisplayItem *cell = ME_FindItemFwd(item, diCell); + ME_DisplayItem *endRowPara; + int borderWidth = 0; + cell->member.cell.pt = c.pt; + /* Offset the text by the largest top border width. */ + while (cell->member.cell.next_cell) { + borderWidth = max(borderWidth, cell->member.cell.border.top.width); + cell = cell->member.cell.next_cell; + } + endRowPara = ME_FindItemFwd(cell, diParagraph); + assert(endRowPara->member.para.nFlags & MEPF_ROWEND); + if (borderWidth > 0) + { + borderWidth = max(ME_twips2pointsY(&c, borderWidth), 1); + while (cell) { + cell->member.cell.yTextOffset = borderWidth; + cell = cell->member.cell.prev_cell; + } + c.pt.y += borderWidth; + } + if (endRowPara->member.para.pFmt->dxStartIndent > 0) + { + int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent; + cell = ME_FindItemFwd(item, diCell); + cell->member.cell.pt.x += ME_twips2pointsX(&c, dxStartIndent); + c.pt.x = cell->member.cell.pt.x; + } + } + else if (item->member.para.nFlags & MEPF_ROWEND) + { + /* Set all the cells to the height of the largest cell */ + ME_DisplayItem *startRowPara; + int prevHeight, nHeight, bottomBorder = 0; + ME_DisplayItem *cell = ME_FindItemBack(item, diCell); + if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART)) + { + /* Last row, the bottom border is added to the height. */ + cell = cell->member.cell.prev_cell; + while (cell) + { + bottomBorder = max(bottomBorder, cell->member.cell.border.bottom.width); + cell = cell->member.cell.prev_cell; + } + bottomBorder = ME_twips2pointsY(&c, bottomBorder); + cell = ME_FindItemBack(item, diCell); + } + prevHeight = cell->member.cell.nHeight; + nHeight = cell->member.cell.prev_cell->member.cell.nHeight + bottomBorder; + cell->member.cell.nHeight = nHeight; + item->member.para.nHeight = nHeight; + cell = cell->member.cell.prev_cell; + cell->member.cell.nHeight = nHeight; + while (cell->member.cell.prev_cell) + { + cell = cell->member.cell.prev_cell; + cell->member.cell.nHeight = nHeight; + } + /* Also set the height of the start row paragraph */ + startRowPara = ME_FindItemBack(cell, diParagraph); + startRowPara->member.para.nHeight = nHeight; + c.pt.x = startRowPara->member.para.pt.x; + c.pt.y = cell->member.cell.pt.y + nHeight; + if (prevHeight < nHeight) + { + /* The height of the cells has grown, so invalidate the bottom of + * the cells. */ + item->member.para.nFlags |= MEPF_REPAINT; + cell = ME_FindItemBack(item, diCell); + while (cell) { + ME_FindItemBack(cell, diParagraph)->member.para.nFlags |= MEPF_REPAINT; + cell = cell->member.cell.prev_cell; + } + } + } + else if (item->member.para.pCell && + item->member.para.pCell != item->member.para.next_para->member.para.pCell) + { + /* The next paragraph is in the next cell in the table row. */ + ME_Cell *cell = &item->member.para.pCell->member.cell; + cell->nHeight = c.pt.y + item->member.para.nHeight - cell->pt.y; + + /* Propagate the largest height to the end so that it can be easily + * sent back to all the cells at the end of the row. */ + if (cell->prev_cell) + cell->nHeight = max(cell->nHeight, cell->prev_cell->member.cell.nHeight); + + c.pt.x = cell->pt.x + cell->nWidth; + c.pt.y = cell->pt.y; + cell->next_cell->member.cell.pt = c.pt; + c.pt.y += cell->yTextOffset; + } + else + { + if (item->member.para.pCell) { + /* Next paragraph in the same cell. */ + c.pt.x = item->member.para.pCell->member.cell.pt.x; + } else { + /* Normal paragraph */ + c.pt.x = editor->selofs; + } + c.pt.y += item->member.para.nHeight; + } item = item->member.para.next_para; } editor->sizeWindow.cx = c.rcView.right-c.rcView.left; editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top; editor->nTotalLength = c.pt.y; - editor->pBuffer->pLast->member.para.nYPos = yLastPos; + editor->pBuffer->pLast->member.para.pt.x = 0; + editor->pBuffer->pLast->member.para.pt.y = yLastPos; ME_DestroyContext(&c, editor->hWnd); /* Each paragraph may contain multiple rows, which should be scrollable, even - if the containing paragraph has nYPos == 0 */ + if the containing paragraph has pt.y == 0 */ item = editor->pBuffer->pFirst; while ((item = ME_FindItemFwd(item, diStartRow)) != NULL) { assert(item->type == diStartRow); - editor->nHeight = max(editor->nHeight, item->member.row.nYPos); + editor->nHeight = max(editor->nHeight, item->member.row.pt.y); } if (bModified || editor->nTotalLength < editor->nLastTotalLength) @@ -569,8 +742,8 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) { ME_DisplayItem *item = editor->pBuffer->pFirst; while(item != editor->pBuffer->pLast) { if (item->member.para.nFlags & MEPF_REPAINT) { - rc.top = item->member.para.nYPos - ofs; - rc.bottom = item->member.para.nYPos + item->member.para.nHeight - ofs; + rc.top = item->member.para.pt.y - ofs; + rc.bottom = item->member.para.pt.y + item->member.para.nHeight - ofs; InvalidateRect(editor->hWnd, &rc, TRUE); } item = item->member.para.next_para; diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c index 13afb3cc4fd..912cae3f48e 100644 --- a/dlls/riched20/writer.c +++ b/dlls/riched20/writer.c @@ -41,6 +41,7 @@ ME_StreamOutInit(ME_TextEditor *editor, EDITSTREAM *stream) pStream->written = 0; pStream->nFontTblLen = 0; pStream->nColorTblLen = 1; + pStream->nNestingLevel = 0; return pStream; } @@ -284,28 +285,45 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, } static BOOL -ME_StreamOutRTFTableProps(ME_OutStream *pStream, const ME_DisplayItem *para) +ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream, + const ME_DisplayItem *para) { - PARAFORMAT2 *pFmt; + ME_DisplayItem *cell; char props[STREAMOUT_BUFFER_SIZE] = ""; - int i; if (!ME_StreamOutPrint(pStream, "\\trowd")) return FALSE; - pFmt = para->member.para.pFmt; - - for (i = 0; i < pFmt->cTabCount; i++) - { - sprintf(props, "\\cellx%d", pFmt->rgxTabs[i] & 0x00FFFFFF); - if (!ME_StreamOutPrint(pStream, props)) - return FALSE; + if (!editor->bEmulateVersion10) { /* v4.1 */ + assert(para->member.para.nFlags & MEPF_ROWSTART); + cell = para->member.para.next_para->member.para.pCell; + assert(cell); + do { + sprintf(props + strlen(props), "\\cellx%d", cell->member.cell.nRightBoundary); + cell = cell->member.cell.next_cell; + } while (cell->member.cell.next_cell); + } else { /* v1.0 - 3.0 */ + PARAFORMAT2 *pFmt = para->member.para.pFmt; + int i; + + assert(!(para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))); + if (pFmt->dxOffset) + sprintf(props + strlen(props), "\\trgaph%d", pFmt->dxOffset); + if (pFmt->dxStartIndent) + sprintf(props + strlen(props), "\\trleft%d", pFmt->dxStartIndent); + for (i = 0; i < pFmt->cTabCount; i++) + { + sprintf(props + strlen(props), "\\cellx%d", pFmt->rgxTabs[i] & 0x00FFFFFF); + } } + if (!ME_StreamOutPrint(pStream, props)) + return FALSE; props[0] = '\0'; return TRUE; } static BOOL -ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para) +ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream, + const ME_DisplayItem *para) { PARAFORMAT2 *fmt = para->member.para.pFmt; char props[STREAMOUT_BUFFER_SIZE] = ""; @@ -315,8 +333,15 @@ ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para) if (!ME_StreamOutPrint(pStream, "\\pard")) return FALSE; - if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE) - strcat(props, "\\intbl"); + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (pStream->nNestingLevel > 0) + strcat(props, "\\intbl"); + if (pStream->nNestingLevel > 1) + sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel); + } else { /* v1.0 - 3.0 */ + if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE) + strcat(props, "\\intbl"); + } /* TODO: PFM_BORDER. M$ does not emit any keywords for these properties, and * when streaming border keywords in, PFM_BORDER is set, but wBorder field is @@ -382,43 +407,45 @@ ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para) if (fmt->dwMask & PFM_SIDEBYSIDE && fmt->wEffects & PFE_SIDEBYSIDE) strcat(props, "\\sbys"); - if (fmt->dwMask & PFM_OFFSET) - sprintf(props + strlen(props), "\\li%d", fmt->dxOffset); - if (fmt->dwMask & PFM_OFFSETINDENT || fmt->dwMask & PFM_STARTINDENT) - sprintf(props + strlen(props), "\\fi%d", fmt->dxStartIndent); - if (fmt->dwMask & PFM_RIGHTINDENT) - sprintf(props + strlen(props), "\\ri%d", fmt->dxRightIndent); + if (!(editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE)) + { + if (fmt->dwMask & PFM_OFFSET) + sprintf(props + strlen(props), "\\li%d", fmt->dxOffset); + if (fmt->dwMask & PFM_OFFSETINDENT || fmt->dwMask & PFM_STARTINDENT) + sprintf(props + strlen(props), "\\fi%d", fmt->dxStartIndent); + if (fmt->dwMask & PFM_RIGHTINDENT) + sprintf(props + strlen(props), "\\ri%d", fmt->dxRightIndent); + if (fmt->dwMask & PFM_TABSTOPS) { + static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" }; + + for (i = 0; i < fmt->cTabCount; i++) { + switch ((fmt->rgxTabs[i] >> 24) & 0xF) { + case 1: + strcat(props, "\\tqc"); + break; + case 2: + strcat(props, "\\tqr"); + break; + case 3: + strcat(props, "\\tqdec"); + break; + case 4: + /* Word bar tab (vertical bar). Handled below */ + break; + } + if (fmt->rgxTabs[i] >> 28 <= 5) + strcat(props, leader[fmt->rgxTabs[i] >> 28]); + sprintf(props+strlen(props), "\\tx%d", fmt->rgxTabs[i]&0x00FFFFFF); + } + } + } if (fmt->dwMask & PFM_SPACEAFTER) sprintf(props + strlen(props), "\\sa%d", fmt->dySpaceAfter); if (fmt->dwMask & PFM_SPACEBEFORE) sprintf(props + strlen(props), "\\sb%d", fmt->dySpaceBefore); if (fmt->dwMask & PFM_STYLE) sprintf(props + strlen(props), "\\s%d", fmt->sStyle); - - if (fmt->dwMask & PFM_TABSTOPS) { - static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" }; - - for (i = 0; i < fmt->cTabCount; i++) { - switch ((fmt->rgxTabs[i] >> 24) & 0xF) { - case 1: - strcat(props, "\\tqc"); - break; - case 2: - strcat(props, "\\tqr"); - break; - case 3: - strcat(props, "\\tqdec"); - break; - case 4: - /* Word bar tab (vertical bar). Handled below */ - break; - } - if (fmt->rgxTabs[i] >> 28 <= 5) - strcat(props, leader[fmt->rgxTabs[i] >> 28]); - sprintf(props+strlen(props), "\\tx%d", fmt->rgxTabs[i]&0x00FFFFFF); - } - } - if (fmt->dwMask & PFM_SHADING) { static const char * const style[16] = { "", "\\bgdkhoriz", "\\bgdkvert", "\\bgdkfdiag", @@ -683,7 +710,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC /* TODO: section formatting properties */ - if (!ME_StreamOutRTFParaProps(pStream, ME_GetParagraph(p))) + if (!ME_StreamOutRTFParaProps(editor, pStream, ME_GetParagraph(p))) return FALSE; while(1) @@ -691,14 +718,39 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC switch(p->type) { case diParagraph: - if (p->member.para.pFmt->dwMask & PFM_TABLE && - p->member.para.pFmt->wEffects & PFE_TABLE) - { - if (!ME_StreamOutRTFTableProps(pStream, p)) + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (p->member.para.nFlags & MEPF_ROWSTART) { + pStream->nNestingLevel++; + if (pStream->nNestingLevel == 1) { + if (!ME_StreamOutRTFTableProps(editor, pStream, p)) + return FALSE; + } + } else if (p->member.para.nFlags & MEPF_ROWEND) { + pStream->nNestingLevel--; + if (pStream->nNestingLevel > 1) { + if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) + return FALSE; + if (!ME_StreamOutRTFTableProps(editor, pStream, p)) + return FALSE; + if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\\row \r\n")) + return FALSE; + } + } else if (!ME_StreamOutRTFParaProps(editor, pStream, p)) { + return FALSE; + } + } else { /* v1.0 - 3.0 */ + if (p->member.para.pFmt->dwMask & PFM_TABLE && + p->member.para.pFmt->wEffects & PFE_TABLE) + { + if (!ME_StreamOutRTFTableProps(editor, pStream, p)) + return FALSE; + } + if (!ME_StreamOutRTFParaProps(editor, pStream, p)) return FALSE; } - if (!ME_StreamOutRTFParaProps(pStream, p)) - return FALSE; pPara = p; break; case diRun: @@ -706,10 +758,13 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC break; TRACE("flags %xh\n", p->member.run.nFlags); /* TODO: emit embedded objects */ + if (pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) + break; if (p->member.run.nFlags & MERF_GRAPHICS) { FIXME("embedded objects are not handled\n"); } else if (p->member.run.nFlags & MERF_TAB) { - if (pPara->member.para.pFmt->dwMask & PFM_TABLE && + if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + pPara->member.para.pFmt->dwMask & PFM_TABLE && pPara->member.para.pFmt->wEffects & PFE_TABLE) { if (!ME_StreamOutPrint(pStream, "\\cell ")) @@ -718,9 +773,19 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC if (!ME_StreamOutPrint(pStream, "\\tab ")) return FALSE; } + } else if (p->member.run.nFlags & MERF_ENDCELL) { + if (pStream->nNestingLevel > 1) { + if (!ME_StreamOutPrint(pStream, "\\nestcell ")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\\cell ")) + return FALSE; + } + nChars--; } else if (p->member.run.nFlags & MERF_ENDPARA) { - if (pPara->member.para.pFmt->dwMask & PFM_TABLE - && pPara->member.para.pFmt->wEffects & PFE_TABLE) + if (pPara->member.para.pFmt->dwMask & PFM_TABLE && + pPara->member.para.pFmt->wEffects & PFE_TABLE && + !(pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))) { if (!ME_StreamOutPrint(pStream, "\\row \r\n")) return FALSE; diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c index 836410b5816..bda04be31f4 100644 --- a/dlls/rpcrt4/ndr_marshall.c +++ b/dlls/rpcrt4/ndr_marshall.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "windef.h" @@ -626,6 +625,19 @@ finish_conf: return pFormat+4; } +static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + if (IsConformanceOrVariancePresent(pFormat)) + { + if (pStubMsg->fHasNewCorrDesc) + pFormat += 6; + else + pFormat += 4; + } + return pFormat; +} + /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if * the result overflows 32-bits */ static inline ULONG safe_multiply(ULONG a, ULONG b) @@ -721,1398 +733,1811 @@ static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULO } } -/* - * NdrConformantString: - * - * What MS calls a ConformantString is, in DCE terminology, - * a Varying-Conformant String. - * [ - * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') - * offset: DWORD (actual string data begins at (offset) CHARTYPE's - * into unmarshalled string) - * length: DWORD (# of CHARTYPE characters, inclusive of '\0') - * [ - * data: CHARTYPE[maxlen] - * ] - * ], where CHARTYPE is the appropriate character type (specified externally) - * - */ - -/*********************************************************************** - * NdrConformantStringMarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, - unsigned char *pszMessage, PFORMAT_STRING pFormat) -{ - ULONG esize, size; - - TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pszMessage)); - pStubMsg->ActualCount = strlen((char*)pszMessage)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); - pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception. */ - return NULL; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - pStubMsg->Offset = 0; - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */ - - /* success */ - return NULL; /* is this always right? */ +static inline void dump_pointer_attr(unsigned char attr) +{ + if (attr & RPC_FC_P_ALLOCALLNODES) + TRACE(" RPC_FC_P_ALLOCALLNODES"); + if (attr & RPC_FC_P_DONTFREE) + TRACE(" RPC_FC_P_DONTFREE"); + if (attr & RPC_FC_P_ONSTACK) + TRACE(" RPC_FC_P_ONSTACK"); + if (attr & RPC_FC_P_SIMPLEPOINTER) + TRACE(" RPC_FC_P_SIMPLEPOINTER"); + if (attr & RPC_FC_P_DEREF) + TRACE(" RPC_FC_P_DEREF"); + TRACE("\n"); } /*********************************************************************** - * NdrConformantStringBufferSize [RPCRT4.@] + * PointerMarshall [internal] */ -void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat) +static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char *Pointer, + PFORMAT_STRING pFormat) { - ULONG esize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MARSHALL m; + ULONG pointer_id; + int pointer_needs_marshaling; - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); + TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pMemory)); - pStubMsg->ActualCount = strlen((char*)pMemory)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + pointer_needs_marshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - same as unique here */ + if (Pointer) + pointer_needs_marshaling = 1; + else + pointer_needs_marshaling = 0; + pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0; + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + case RPC_FC_FP: + pointer_needs_marshaling = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); return; } - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; + TRACE("calling marshaller for type 0x%x\n", (int)*desc); - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + if (pointer_needs_marshaling) { + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); + } + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no marshaller for data type=%02x\n", *desc); + } + + STD_OVERFLOW_CHECK(pStubMsg); } -/************************************************************************ - * NdrConformantStringMemorySize [RPCRT4.@] +/*********************************************************************** + * PointerUnmarshall [internal] */ -ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) +static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char **pPointer, + unsigned char *pSrcPointer, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) { - ULONG bufsize, memsize, esize; - - TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + DWORD pointer_id = 0; + int pointer_needs_unmarshaling; - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; - if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) - { - ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", - pStubMsg->ActualCount, pStubMsg->MaxCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - if (pStubMsg->Offset) - { - ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_unmarshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_unmarshaling = 1; + else { + *pPointer = NULL; + pointer_needs_unmarshaling = 0; + } + break; + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (!fMustAlloc && pSrcPointer) + { + FIXME("free object pointer %p\n", pSrcPointer); + fMustAlloc = TRUE; + } + if (pointer_id) + pointer_needs_unmarshaling = 1; + else + pointer_needs_unmarshaling = 0; + break; + case RPC_FC_FP: + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; } - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } + if (pointer_needs_unmarshaling) { + unsigned char *base_ptr_val = *pPointer; + unsigned char **current_ptr = pPointer; + if (pStubMsg->IsClient) { + TRACE("client\n"); + /* if we aren't forcing allocation of memory then try to use the existing + * (source) pointer to unmarshall the data into so that [in,out] + * parameters behave correctly. it doesn't matter if the parameter is + * [out] only since in that case the pointer will be NULL. we force + * allocation when the source pointer is NULL here instead of in the type + * unmarshalling routine for the benefit of the deref code below */ + if (!fMustAlloc) { + if (pSrcPointer) { + TRACE("setting *pPointer to %p\n", pSrcPointer); + *pPointer = base_ptr_val = pSrcPointer; + } else + fMustAlloc = TRUE; + } + } else { + TRACE("server\n"); + /* the memory in a stub is never initialised, so we have to work out here + * whether we have to initialise it so we can use the optimisation of + * setting the pointer to the buffer, if possible, or set fMustAlloc to + * TRUE. */ + if (attr & RPC_FC_P_DEREF) { + fMustAlloc = TRUE; + } else { + base_ptr_val = NULL; + *current_ptr = NULL; + } + } - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); + if (attr & RPC_FC_P_ALLOCALLNODES) + FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); - validate_string_data(pStubMsg, bufsize, esize); + if (attr & RPC_FC_P_DEREF) { + if (fMustAlloc) { + base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); + *pPointer = base_ptr_val; + current_ptr = (unsigned char **)base_ptr_val; + } else + current_ptr = *(unsigned char***)current_ptr; + TRACE("deref => %p\n", current_ptr); + if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; + } + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); + else FIXME("no unmarshaller for data type=%02x\n", *desc); - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; + if (type == RPC_FC_FP) + NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, + base_ptr_val); + } - return pStubMsg->MemorySize; + TRACE("pointer=%p\n", *pPointer); } -/************************************************************************ - * NdrConformantStringUnmarshall [RPCRT4.@] +/*********************************************************************** + * PointerBufferSize [internal] */ -unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) +static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) { - ULONG bufsize, memsize, esize; - - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); - - assert(pFormat && ppMemory && pStubMsg); - - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - - if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) - { - ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", - pStubMsg->ActualCount, pStubMsg->MaxCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - if (pStubMsg->Offset) - { - ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + int pointer_needs_sizing; + ULONG pointer_id; - validate_string_data(pStubMsg, bufsize, esize); + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - else - { - if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) - /* if the data in the RPC buffer is big enough, we just point straight - * into it */ - *ppMemory = pStubMsg->Buffer; - else if (!*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + break; + case RPC_FC_OP: + case RPC_FC_UP: + /* NULL pointer has no further representation */ + if (!Pointer) + return; + break; + case RPC_FC_FP: + pointer_needs_sizing = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); + if (!pointer_needs_sizing) + return; + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; } - if (*ppMemory == pStubMsg->Buffer) - safe_buffer_increment(pStubMsg, bufsize); - else - safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); } - return NULL; /* FIXME: is this always right? */ + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no buffersizer for data type=%02x\n", *desc); } /*********************************************************************** - * NdrNonConformantStringMarshall [RPCRT4.@] + * PointerMemorySize [internal] */ -unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + PFORMAT_STRING pFormat) { - ULONG esize, size, maxsize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MEMORYSIZE m; + DWORD pointer_id = 0; + int pointer_needs_sizing; - maxsize = *(USHORT *)&pFormat[2]; + TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; - if (*pFormat == RPC_FC_CSTRING) - { - ULONG i; - const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_an(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 1; - } - else if (*pFormat == RPC_FC_WSTRING) + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_sizing = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_sizing = 1; + else + pointer_needs_sizing = 0; + break; + case RPC_FC_FP: { - ULONG i; - const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_wn(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 2; + void *pointer; + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_sizing = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); + break; } - else - { - ERR("Unhandled string type: %#x\n", *pFormat); + default: + FIXME("unhandled ptr type=%02x\n", type); RpcRaiseException(RPC_X_BAD_STUB_DATA); + return 0; } - pStubMsg->Offset = 0; - WriteVariance(pStubMsg); + if (attr & RPC_FC_P_DEREF) { + TRACE("deref\n"); + } - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ + if (pointer_needs_sizing) { + m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, desc); + else FIXME("no memorysizer for data type=%02x\n", *desc); + } - return NULL; + return pStubMsg->MemorySize; } /*********************************************************************** - * NdrNonConformantStringUnmarshall [RPCRT4.@] + * PointerFree [internal] */ -unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) +static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) { - ULONG bufsize, memsize, esize, maxsize; + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_FREE m; + unsigned char *current_pointer = Pointer; - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + if (attr & RPC_FC_P_DONTFREE) return; + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; - maxsize = *(USHORT *)&pFormat[2]; + if (!Pointer) return; - ReadVariance(pStubMsg, NULL, maxsize); - if (pStubMsg->Offset) - { - ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); + if (type == RPC_FC_FP) { + int pointer_needs_freeing = NdrFullPointerFree( + pStubMsg->FullPtrXlatTables, Pointer); + if (!pointer_needs_freeing) + return; } - if (*pFormat == RPC_FC_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_WSTRING) esize = 2; - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); + if (attr & RPC_FC_P_DEREF) { + current_pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", current_pointer); } - memsize = esize * maxsize; - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - validate_string_data(pStubMsg, bufsize, esize); - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_pointer, desc); - safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + /* this check stops us from trying to free buffer memory. we don't have to + * worry about clients, since they won't call this function. + * we don't have to check for the buffer being reallocated because + * BufferStart and BufferEnd won't be reset when allocating memory for + * sending the response. we don't have to check for the new buffer here as + * it won't be used a type memory, only for buffer memory */ + if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd) + goto notfree; - if (*pFormat == RPC_FC_CSTRING) { - TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); - } - else if (*pFormat == RPC_FC_WSTRING) { - TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); + if (attr & RPC_FC_P_ONSTACK) { + TRACE("not freeing stack ptr %p\n", Pointer); + return; } - - return NULL; + TRACE("freeing %p\n", Pointer); + NdrFree(pStubMsg, Pointer); + return; +notfree: + TRACE("not freeing %p\n", Pointer); } /*********************************************************************** - * NdrNonConformantStringBufferSize [RPCRT4.@] + * EmbeddedPointerMarshall */ -void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - ULONG esize, maxsize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; - maxsize = *(USHORT *)&pFormat[2]; + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - SizeVariance(pStubMsg); + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; - if (*pFormat == RPC_FC_CSTRING) + if (pStubMsg->PointerBufferMark) { - ULONG i; - const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_an(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 1; - } - else if (*pFormat == RPC_FC_WSTRING) - { - ULONG i; - const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_wn(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 2; - } - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; } - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); -} - -/*********************************************************************** - * NdrNonConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG bufsize, memsize, esize, maxsize; - - TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - - maxsize = *(USHORT *)&pFormat[2]; + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; - ReadVariance(pStubMsg, NULL, maxsize); + for (u=0; uMemory; - if (pStubMsg->Offset) - { - ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); + pStubMsg->Memory = pMemory; + PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; } - if (*pFormat == RPC_FC_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_WSTRING) esize = 2; - else + if (saved_buffer) { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; } - memsize = esize * maxsize; - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - validate_string_data(pStubMsg, bufsize, esize); - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - return pStubMsg->MemorySize; -} + STD_OVERFLOW_CHECK(pStubMsg); -static inline void dump_pointer_attr(unsigned char attr) -{ - if (attr & RPC_FC_P_ALLOCALLNODES) - TRACE(" RPC_FC_P_ALLOCALLNODES"); - if (attr & RPC_FC_P_DONTFREE) - TRACE(" RPC_FC_P_DONTFREE"); - if (attr & RPC_FC_P_ONSTACK) - TRACE(" RPC_FC_P_ONSTACK"); - if (attr & RPC_FC_P_SIMPLEPOINTER) - TRACE(" RPC_FC_P_SIMPLEPOINTER"); - if (attr & RPC_FC_P_DEREF) - TRACE(" RPC_FC_P_DEREF"); - TRACE("\n"); + return NULL; } /*********************************************************************** - * PointerMarshall [internal] + * EmbeddedPointerUnmarshall */ -static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char *Pointer, - PFORMAT_STRING pFormat) +static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pDstBuffer, + unsigned char *pSrcMemoryPtrs, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) { - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MARSHALL m; - ULONG pointer_id; - int pointer_needs_marshaling; + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; - TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc); + + if (*pFormat != RPC_FC_PP) return NULL; pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - if (!Pointer) - { - ERR("NULL ref pointer is not allowed\n"); - RpcRaiseException(RPC_X_NULL_REF_POINTER); - } - pointer_needs_marshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - case RPC_FC_OP: /* object pointer - same as unique here */ - if (Pointer) - pointer_needs_marshaling = 1; - else - pointer_needs_marshaling = 0; - pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0; - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - case RPC_FC_FP: - pointer_needs_marshaling = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; } - TRACE("calling marshaller for type 0x%x\n", (int)*desc); + while (pFormat[0] != RPC_FC_END) { + TRACE("pFormat[0] = 0x%x\n", pFormat[0]); + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *bufdstbase = pDstBuffer + (i * stride); + unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; - if (pointer_needs_marshaling) { - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); + for (u=0; uPointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return NULL; } /*********************************************************************** - * PointerUnmarshall [internal] + * EmbeddedPointerBufferSize */ -static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char **pPointer, - unsigned char *pSrcPointer, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) +static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_UNMARSHALL m; - DWORD pointer_id = 0; - int pointer_needs_unmarshaling; + unsigned rep, count, stride; + unsigned i; + ULONG saved_buffer_length = 0; - TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return; + + if (*pFormat != RPC_FC_PP) return; pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - pointer_needs_unmarshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (pointer_id) - pointer_needs_unmarshaling = 1; - else { - *pPointer = NULL; - pointer_needs_unmarshaling = 0; - } - break; - case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (!fMustAlloc && pSrcPointer) - { - FIXME("free object pointer %p\n", pSrcPointer); - fMustAlloc = TRUE; - } - if (pointer_id) - pointer_needs_unmarshaling = 1; - else - pointer_needs_unmarshaling = 0; - break; - case RPC_FC_FP: - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( - pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; + if (pStubMsg->PointerLength) + { + saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; } - if (pointer_needs_unmarshaling) { - unsigned char *base_ptr_val = *pPointer; - unsigned char **current_ptr = pPointer; - if (pStubMsg->IsClient) { - TRACE("client\n"); - /* if we aren't forcing allocation of memory then try to use the existing - * (source) pointer to unmarshall the data into so that [in,out] - * parameters behave correctly. it doesn't matter if the parameter is - * [out] only since in that case the pointer will be NULL. we force - * allocation when the source pointer is NULL here instead of in the type - * unmarshalling routine for the benefit of the deref code below */ - if (!fMustAlloc) { - if (pSrcPointer) { - TRACE("setting *pPointer to %p\n", pSrcPointer); - *pPointer = base_ptr_val = pSrcPointer; - } else - fMustAlloc = TRUE; - } - } else { - TRACE("server\n"); - /* the memory in a stub is never initialised, so we have to work out here - * whether we have to initialise it so we can use the optimisation of - * setting the pointer to the buffer, if possible, or set fMustAlloc to - * TRUE. */ - if (attr & RPC_FC_P_DEREF) { - fMustAlloc = TRUE; - } else { - base_ptr_val = NULL; - *current_ptr = NULL; + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; } } + pFormat += 8 * count; + } - if (attr & RPC_FC_P_ALLOCALLNODES) - FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); + if (saved_buffer_length) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } +} - if (attr & RPC_FC_P_DEREF) { - if (fMustAlloc) { - base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); - *pPointer = base_ptr_val; - current_ptr = (unsigned char **)base_ptr_val; - } else - current_ptr = *(unsigned char***)current_ptr; - TRACE("deref => %p\n", current_ptr); - if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; +/*********************************************************************** + * EmbeddedPointerMemorySize [internal] + */ +static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return 0; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + if (*pFormat != RPC_FC_PP) return 0; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; } - m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); - else FIXME("no unmarshaller for data type=%02x\n", *desc); + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + for (u=0; uFullPtrXlatTables, pointer_id, - base_ptr_val); + if (saved_buffer) + { + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; } - TRACE("pointer=%p\n", *pPointer); + return 0; } /*********************************************************************** - * PointerBufferSize [internal] + * EmbeddedPointerFree [internal] */ -static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) +static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_BUFFERSIZE m; - int pointer_needs_sizing; - ULONG pointer_id; + unsigned rep, count, stride; + unsigned i; - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (*pFormat != RPC_FC_PP) return; pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - if (!Pointer) - { - ERR("NULL ref pointer is not allowed\n"); - RpcRaiseException(RPC_X_NULL_REF_POINTER); + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; } - break; - case RPC_FC_OP: - case RPC_FC_UP: - /* NULL pointer has no further representation */ - if (!Pointer) - return; - break; - case RPC_FC_FP: - pointer_needs_sizing = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); - if (!pointer_needs_sizing) - return; - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } +} + +/*********************************************************************** + * NdrPointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* Increment the buffer here instead of in PointerMarshall, + * as that is used by embedded pointers which already handle the incrementing + * the buffer, and shouldn't write any additional pointer data to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + /* Increment the buffer here instead of in PointerUnmarshall, + * as that is used by embedded pointers which already handle the incrementing + * the buffer, and shouldn't read any additional pointer data from the + * buffer */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* Increment the buffer length here instead of in PointerBufferSize, + * as that is used by embedded pointers which already handle the buffer + * length, and shouldn't write anything more to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, 4); } - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } + PointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrPointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); + return 0; +} + +/*********************************************************************** + * NdrPointerFree [RPCRT4.@] + */ +void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + PointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrSimpleTypeMarshall [RPCRT4.@] + */ +void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ + NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); +} + +/*********************************************************************** + * NdrSimpleTypeUnmarshall [RPCRT4.@] + * + * Unmarshall a base type. + * + * NOTES + * Doesn't check that the buffer is long enough before copying, so the caller + * should do this. + */ +void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ +#define BASE_TYPE_UNMARSHALL(type) \ + ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + TRACE("pMemory: %p\n", pMemory); \ + *(type *)pMemory = *(type *)pStubMsg->Buffer; \ + pStubMsg->Buffer += sizeof(type); + + switch(FormatChar) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + BASE_TYPE_UNMARSHALL(UCHAR); + TRACE("value: 0x%02x\n", *pMemory); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + BASE_TYPE_UNMARSHALL(USHORT); + TRACE("value: 0x%04x\n", *(USHORT *)pMemory); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + BASE_TYPE_UNMARSHALL(ULONG); + TRACE("value: 0x%08x\n", *(ULONG *)pMemory); + break; + case RPC_FC_FLOAT: + BASE_TYPE_UNMARSHALL(float); + TRACE("value: %f\n", *(float *)pMemory); + break; + case RPC_FC_DOUBLE: + BASE_TYPE_UNMARSHALL(double); + TRACE("value: %f\n", *(double *)pMemory); + break; + case RPC_FC_HYPER: + BASE_TYPE_UNMARSHALL(ULONGLONG); + TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory)); + break; + case RPC_FC_ENUM16: + ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + TRACE("pMemory: %p\n", pMemory); + /* 16-bits on the wire, but int in memory */ + *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(USHORT); + TRACE("value: 0x%08x\n", *(UINT *)pMemory); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", FormatChar); + } +#undef BASE_TYPE_UNMARSHALL +} + +/*********************************************************************** + * NdrSimpleStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - else FIXME("no buffersizer for data type=%02x\n", *desc); + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); + + return NULL; } /*********************************************************************** - * PointerMemorySize [internal] + * NdrSimpleStructUnmarshall [RPCRT4.@] */ -static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - PFORMAT_STRING pFormat) +unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) { - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MEMORYSIZE m; - DWORD pointer_id = 0; - int pointer_needs_sizing; + unsigned size = *(const WORD*)(pFormat+2); + unsigned char *saved_buffer; + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - pointer_needs_sizing = 1; - break; - case RPC_FC_UP: /* unique pointer */ - case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (pointer_id) - pointer_needs_sizing = 1; - else - pointer_needs_sizing = 0; - break; - case RPC_FC_FP: + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + else { - void *pointer; - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - pointer_needs_sizing = !NdrFullPointerQueryRefId( - pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); - break; - } - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return 0; + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; } - if (attr & RPC_FC_P_DEREF) { - TRACE("deref\n"); - } + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + if (pFormat[0] == RPC_FC_PSTRUCT) + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); - if (pointer_needs_sizing) { - m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, desc); - else FIXME("no memorysizer for data type=%02x\n", *desc); - } + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, size); - return pStubMsg->MemorySize; + return NULL; } /*********************************************************************** - * PointerFree [internal] + * NdrSimpleStructBufferSize [RPCRT4.@] */ -static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) +void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_FREE m; - unsigned char *current_pointer = Pointer; - - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - if (attr & RPC_FC_P_DONTFREE) return; - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (!Pointer) return; + ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); - if (type == RPC_FC_FP) { - int pointer_needs_freeing = NdrFullPointerFree( - pStubMsg->FullPtrXlatTables, Pointer); - if (!pointer_needs_freeing) - return; - } + safe_buffer_length_increment(pStubMsg, size); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); +} - if (attr & RPC_FC_P_DEREF) { - current_pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", current_pointer); - } +/*********************************************************************** + * NdrSimpleStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned short size = *(const WORD *)(pFormat+2); - m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, current_pointer, desc); + TRACE("(%p,%p)\n", pStubMsg, pFormat); - /* this check stops us from trying to free buffer memory. we don't have to - * worry about clients, since they won't call this function. - * we don't have to check for the buffer being reallocated because - * BufferStart and BufferEnd won't be reset when allocating memory for - * sending the response. we don't have to check for the new buffer here as - * it won't be used a type memory, only for buffer memory */ - if (Pointer >= pStubMsg->BufferStart && Pointer < pStubMsg->BufferEnd) - goto notfree; + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + pStubMsg->MemorySize += size; + safe_buffer_increment(pStubMsg, size); - if (attr & RPC_FC_P_ONSTACK) { - TRACE("not freeing stack ptr %p\n", Pointer); - return; - } - TRACE("freeing %p\n", Pointer); - NdrFree(pStubMsg, Pointer); - return; -notfree: - TRACE("not freeing %p\n", Pointer); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMemorySize(pStubMsg, pFormat+4); + return pStubMsg->MemorySize; } /*********************************************************************** - * EmbeddedPointerMarshall + * NdrSimpleStructFree [RPCRT4.@] */ -static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); +} - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; +/* Array helpers */ - if (pStubMsg->PointerBufferMark) +static inline void array_compute_and_size_conformance( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + switch (fc) { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; + case RPC_FC_CARRAY: + ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + SizeConformance(pStubMsg); + break; + case RPC_FC_CVARRAY: + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + SizeConformance(pStubMsg); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (pFormat[0] == RPC_FC_C_CSTRING) + { + TRACE("string=%s\n", debugstr_a((const char *)pMemory)); + pStubMsg->ActualCount = strlen((const char *)pMemory)+1; + } + else + { + TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); + pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned char *bufbase = Mark + (i * stride); - unsigned u; - for (u=0; uMemory; + if (fc == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; - pStubMsg->Memory = pMemory; - PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; + SizeConformance(pStubMsg); + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } +} + +static inline void array_buffer_size( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, unsigned char fHasPointers) +{ + DWORD size; + DWORD esize; + unsigned char alignment; + + switch (fc) + { + case RPC_FC_CARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; + + pFormat = SkipConformance(pStubMsg, pFormat + 4); - if (saved_buffer) - { - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - STD_OVERFLOW_CHECK(pStubMsg); + size = safe_multiply(esize, pStubMsg->MaxCount); + /* conformance value plus array */ + safe_buffer_length_increment(pStubMsg, size); - return NULL; -} + if (fHasPointers) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; -/*********************************************************************** - * EmbeddedPointerUnmarshall - */ -static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pDstBuffer, - unsigned char *pSrcMemoryPtrs, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + pFormat = SkipConformance(pStubMsg, pFormat); - TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc); + SizeVariance(pStubMsg); - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_buffer_length_increment(pStubMsg, size); - while (pFormat[0] != RPC_FC_END) { - TRACE("pFormat[0] = 0x%x\n", pFormat[0]); - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *bufdstbase = pDstBuffer + (i * stride); - unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); - unsigned char *bufbase = Mark + (i * stride); - unsigned u; + if (fHasPointers) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + esize = 1; + else + esize = 2; - for (u=0; uActualCount); + safe_buffer_length_increment(pStubMsg, size); + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } +} - if (saved_buffer) +static inline void array_compute_and_write_conformance( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + switch (fc) { - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; + case RPC_FC_CARRAY: + ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + WriteConformance(pStubMsg); + break; + case RPC_FC_CVARRAY: + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + WriteConformance(pStubMsg); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + { + TRACE("string=%s\n", debugstr_a((const char *)pMemory)); + pStubMsg->ActualCount = strlen((const char *)pMemory)+1; + } + else + { + TRACE("string=%s\n", debugstr_w((LPCWSTR)pMemory)); + pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; + } + if (pFormat[1] == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + pStubMsg->Offset = 0; + WriteConformance(pStubMsg); + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } - - return NULL; } -/*********************************************************************** - * EmbeddedPointerBufferSize - */ -static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +static inline void array_write_variance_and_marshall( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, unsigned char fHasPointers) { - unsigned rep, count, stride; - unsigned i; - ULONG saved_buffer_length = 0; + DWORD size; + DWORD esize; + unsigned char alignment; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + switch (fc) + { + case RPC_FC_CARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - if (pStubMsg->IgnoreEmbeddedPointers) return; + pFormat = SkipConformance(pStubMsg, pFormat + 4); - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - if (pStubMsg->PointerLength) - { - saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } + size = safe_multiply(esize, pStubMsg->MaxCount); + if (fHasPointers) + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned u; + if (fHasPointers) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - for (u=0; uMemory; + /* conformance */ + pFormat = SkipConformance(pStubMsg, pFormat + 4); + /* variance */ + pFormat = SkipConformance(pStubMsg, pFormat); - pStubMsg->Memory = pMemory; - PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + size = safe_multiply(esize, pStubMsg->ActualCount); + + if (fHasPointers) + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, size); + + if (fHasPointers) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + esize = 1; + else + esize = 2; + + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } +} - if (saved_buffer_length) +static inline ULONG array_read_conformance( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + DWORD esize; + + switch (fc) { - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; + case RPC_FC_CARRAY: + esize = *(const WORD*)(pFormat+2); + pFormat = ReadConformance(pStubMsg, pFormat+4); + return safe_multiply(esize, pStubMsg->MaxCount); + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pFormat+2); + pFormat = ReadConformance(pStubMsg, pFormat+4); + return safe_multiply(esize, pStubMsg->MaxCount); + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + esize = 1; + else + esize = 2; + + if (pFormat[1] == RPC_FC_STRING_SIZED) + ReadConformance(pStubMsg, pFormat + 2); + else + ReadConformance(pStubMsg, NULL); + return safe_multiply(esize, pStubMsg->MaxCount); + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } } -/*********************************************************************** - * EmbeddedPointerMemorySize [internal] - */ -static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) +static inline ULONG array_read_variance_and_unmarshall( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, + PFORMAT_STRING pFormat, unsigned char fMustAlloc, + unsigned char fUseBufferMemoryServer, unsigned char fUnmarshall) { - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; + ULONG bufsize, memsize; + WORD esize; + unsigned char alignment; + unsigned char *saved_buffer; + ULONG offset; - TRACE("(%p,%p)\n", pStubMsg, pFormat); + switch (fc) + { + case RPC_FC_CARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - if (pStubMsg->IgnoreEmbeddedPointers) return 0; + bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } + pFormat = SkipConformance(pStubMsg, pFormat + 4); - if (*pFormat != RPC_FC_PP) return 0; - pFormat += 2; + ALIGN_POINTER(pStubMsg->Buffer, alignment); - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *bufbase = Mark + (i * stride); - unsigned u; - for (u=0; uIsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; } + + saved_buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + pStubMsg->BufferMark = saved_buffer; + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, bufsize); } - pFormat += 8 * count; - } + return bufsize; + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - if (saved_buffer) - { - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } + pFormat = SkipConformance(pStubMsg, pFormat + 4); - return 0; -} + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); -/*********************************************************************** - * EmbeddedPointerFree [internal] - */ -static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned rep, count, stride; - unsigned i; + ALIGN_POINTER(pStubMsg->Buffer, alignment); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; + if (fUnmarshall) + { + offset = pStubMsg->Offset; + + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + saved_buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + pStubMsg->BufferMark = saved_buffer; + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, + fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned u; + return bufsize; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + esize = 1; + else + esize = 2; - for (u=0; uMemory; + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - pStubMsg->Memory = pMemory; - PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + validate_string_data(pStubMsg, bufsize, esize); + + if (fUnmarshall) + { + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + else + { + if (fUseBufferMemoryServer && !pStubMsg->IsClient && + !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) + /* if the data in the RPC buffer is big enough, we just point + * straight into it */ + *ppMemory = pStubMsg->Buffer; + else if (!*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); } + + if (*ppMemory == pStubMsg->Buffer) + safe_buffer_increment(pStubMsg, bufsize); + else + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_C_CSTRING) + TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); + else + TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); } - pFormat += 8 * count; + return bufsize; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } } -/*********************************************************************** - * NdrPointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +static inline void array_memory_size( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, + unsigned char fHasPointers) { - unsigned char *Buffer; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + ULONG bufsize, memsize; + DWORD esize; + unsigned char alignment; - /* Increment the buffer here instead of in PointerMarshall, - * as that is used by embedded pointers which already handle the incrementing - * the buffer, and shouldn't write any additional pointer data to the wire */ - if (*pFormat != RPC_FC_RP) + switch (fc) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - } - else - Buffer = pStubMsg->Buffer; + case RPC_FC_CARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); + pFormat = SkipConformance(pStubMsg, pFormat + 4); - return NULL; -} + bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += memsize; -/*********************************************************************** - * NdrPointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Buffer; + ALIGN_POINTER(pStubMsg->Buffer, alignment); + if (fHasPointers) + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (fHasPointers) + EmbeddedPointerMemorySize(pStubMsg, pFormat); + break; + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pFormat+2); + alignment = pFormat[1] + 1; - /* Increment the buffer here instead of in PointerUnmarshall, - * as that is used by embedded pointers which already handle the incrementing - * the buffer, and shouldn't read any additional pointer data from the - * buffer */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - } - else - Buffer = pStubMsg->Buffer; + pFormat = SkipConformance(pStubMsg, pFormat + 4); - PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - return NULL; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += memsize; + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + if (fHasPointers) + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + if (fHasPointers) + EmbeddedPointerMemorySize(pStubMsg, pFormat); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (fc == RPC_FC_C_CSTRING) + esize = 1; + else + esize = 2; + + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + validate_string_data(pStubMsg, bufsize, esize); + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } } -/*********************************************************************** - * NdrPointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +static inline void array_free( + unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - /* Increment the buffer length here instead of in PointerBufferSize, - * as that is used by embedded pointers which already handle the buffer - * length, and shouldn't write anything more to the wire */ - if (*pFormat != RPC_FC_RP) + switch (fc) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - safe_buffer_length_increment(pStubMsg, 4); + case RPC_FC_CARRAY: + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + if (fHasPointers) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_CVARRAY: + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if (fHasPointers) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + /* No embedded pointers so nothing to do */ + break; + default: + ERR("unknown array format 0x%x\n", fc); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } - - PointerBufferSize(pStubMsg, pMemory, pFormat); } +/* + * NdrConformantString: + * + * What MS calls a ConformantString is, in DCE terminology, + * a Varying-Conformant String. + * [ + * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') + * offset: DWORD (actual string data begins at (offset) CHARTYPE's + * into unmarshalled string) + * length: DWORD (# of CHARTYPE characters, inclusive of '\0') + * [ + * data: CHARTYPE[maxlen] + * ] + * ], where CHARTYPE is the appropriate character type (specified externally) + * + */ + /*********************************************************************** - * NdrPointerMemorySize [RPCRT4.@] + * NdrConformantStringMarshall [RPCRT4.@] */ -ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) +unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, + unsigned char *pszMessage, PFORMAT_STRING pFormat) { - /* unsigned size = *(LPWORD)(pFormat+2); */ - FIXME("(%p,%p): stub\n", pStubMsg, pFormat); - PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); - return 0; + TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); + + if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { + ERR("Unhandled string type: %#x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* allow compiler to optimise inline function by passing constant into + * these functions */ + if (pFormat[0] == RPC_FC_C_CSTRING) { + array_compute_and_write_conformance(RPC_FC_C_CSTRING, pStubMsg, pszMessage, + pFormat); + array_write_variance_and_marshall(RPC_FC_C_CSTRING, pStubMsg, pszMessage, + pFormat, TRUE /* fHasPointers */); + } else { + array_compute_and_write_conformance(RPC_FC_C_WSTRING, pStubMsg, pszMessage, + pFormat); + array_write_variance_and_marshall(RPC_FC_C_WSTRING, pStubMsg, pszMessage, + pFormat, TRUE /* fHasPointers */); + } + + return NULL; } /*********************************************************************** - * NdrPointerFree [RPCRT4.@] + * NdrConformantStringBufferSize [RPCRT4.@] */ -void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat) { - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - PointerFree(pStubMsg, pMemory, pFormat); + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { + ERR("Unhandled string type: %#x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* allow compiler to optimise inline function by passing constant into + * these functions */ + if (pFormat[0] == RPC_FC_C_CSTRING) { + array_compute_and_size_conformance(RPC_FC_C_CSTRING, pStubMsg, pMemory, + pFormat); + array_buffer_size(RPC_FC_C_CSTRING, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); + } else { + array_compute_and_size_conformance(RPC_FC_C_WSTRING, pStubMsg, pMemory, + pFormat); + array_buffer_size(RPC_FC_C_WSTRING, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); + } } -/*********************************************************************** - * NdrSimpleTypeMarshall [RPCRT4.@] +/************************************************************************ + * NdrConformantStringMemorySize [RPCRT4.@] */ -void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) +ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat ) { - NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); -} + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); -/*********************************************************************** - * NdrSimpleTypeUnmarshall [RPCRT4.@] - * - * Unmarshall a base type. - * - * NOTES - * Doesn't check that the buffer is long enough before copying, so the caller - * should do this. + if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { + ERR("Unhandled string type: %#x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* allow compiler to optimise inline function by passing constant into + * these functions */ + if (pFormat[0] == RPC_FC_C_CSTRING) { + array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat); + array_memory_size(RPC_FC_C_CSTRING, pStubMsg, pFormat, + TRUE /* fHasPointers */); + } else { + array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat); + array_memory_size(RPC_FC_C_WSTRING, pStubMsg, pFormat, + TRUE /* fHasPointers */); + } + + return pStubMsg->MemorySize; +} + +/************************************************************************ + * NdrConformantStringUnmarshall [RPCRT4.@] */ -void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) +unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { -#define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ - TRACE("pMemory: %p\n", pMemory); \ - *(type *)pMemory = *(type *)pStubMsg->Buffer; \ - pStubMsg->Buffer += sizeof(type); + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); - switch(FormatChar) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - BASE_TYPE_UNMARSHALL(UCHAR); - TRACE("value: 0x%02x\n", *pMemory); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - BASE_TYPE_UNMARSHALL(USHORT); - TRACE("value: 0x%04x\n", *(USHORT *)pMemory); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ERROR_STATUS_T: - case RPC_FC_ENUM32: - BASE_TYPE_UNMARSHALL(ULONG); - TRACE("value: 0x%08x\n", *(ULONG *)pMemory); - break; - case RPC_FC_FLOAT: - BASE_TYPE_UNMARSHALL(float); - TRACE("value: %f\n", *(float *)pMemory); - break; - case RPC_FC_DOUBLE: - BASE_TYPE_UNMARSHALL(double); - TRACE("value: %f\n", *(double *)pMemory); - break; - case RPC_FC_HYPER: - BASE_TYPE_UNMARSHALL(ULONGLONG); - TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory)); - break; - case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - TRACE("pMemory: %p\n", pMemory); - /* 16-bits on the wire, but int in memory */ - *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer; - pStubMsg->Buffer += sizeof(USHORT); - TRACE("value: 0x%08x\n", *(UINT *)pMemory); - break; - case RPC_FC_IGNORE: - break; - default: - FIXME("Unhandled base type: 0x%02x\n", FormatChar); - } -#undef BASE_TYPE_UNMARSHALL + if (pFormat[0] != RPC_FC_C_CSTRING && pFormat[0] != RPC_FC_C_WSTRING) { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* allow compiler to optimise inline function by passing constant into + * these functions */ + if (pFormat[0] == RPC_FC_C_CSTRING) { + array_read_conformance(RPC_FC_C_CSTRING, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_C_CSTRING, pStubMsg, ppMemory, + pFormat, fMustAlloc, + TRUE /* fUseBufferMemoryServer */, + TRUE /* fUnmarshall */); + } else { + array_read_conformance(RPC_FC_C_WSTRING, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_C_WSTRING, pStubMsg, ppMemory, + pFormat, fMustAlloc, + TRUE /* fUseBufferMemoryServer */, + TRUE /* fUnmarshall */); + } + + return NULL; } /*********************************************************************** - * NdrSimpleStructMarshall [RPCRT4.@] + * NdrNonConformantStringMarshall [RPCRT4.@] */ -unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + ULONG esize, size, maxsize; - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, size); + maxsize = *(USHORT *)&pFormat[2]; - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + pStubMsg->Offset = 0; + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ return NULL; } /*********************************************************************** - * NdrSimpleStructUnmarshall [RPCRT4.@] + * NdrNonConformantStringUnmarshall [RPCRT4.@] */ -unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) +unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) { - unsigned size = *(const WORD*)(pFormat+2); - unsigned char *saved_buffer; - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + ULONG bufsize, memsize, esize, maxsize; - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; else { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); - if (pFormat[0] == RPC_FC_PSTRUCT) - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, size); + validate_string_data(pStubMsg, bufsize, esize); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_CSTRING) { + TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); + } + else if (*pFormat == RPC_FC_WSTRING) { + TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); + } return NULL; } /*********************************************************************** - * NdrSimpleStructBufferSize [RPCRT4.@] + * NdrNonConformantStringBufferSize [RPCRT4.@] */ -void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) +void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) { - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + ULONG esize, maxsize; - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - safe_buffer_length_increment(pStubMsg, size); - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); + maxsize = *(USHORT *)&pFormat[2]; + + SizeVariance(pStubMsg); + + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); } /*********************************************************************** - * NdrSimpleStructMemorySize [RPCRT4.@] + * NdrNonConformantStringMemorySize [RPCRT4.@] */ -ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) +ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) { - unsigned short size = *(const WORD *)(pFormat+2); + ULONG bufsize, memsize, esize, maxsize; + + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); - TRACE("(%p,%p)\n", pStubMsg, pFormat); + validate_string_data(pStubMsg, bufsize, esize); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - pStubMsg->MemorySize += size; - safe_buffer_increment(pStubMsg, size); + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMemorySize(pStubMsg, pFormat+4); return pStubMsg->MemorySize; } -/*********************************************************************** - * NdrSimpleStructFree [RPCRT4.@] - */ -void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); -} - +/* Complex types */ #include "pshpack1.h" typedef struct @@ -2159,8 +2584,6 @@ static unsigned long EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg, return sizeof(double); case RPC_FC_HYPER: return sizeof(ULONGLONG); - case RPC_FC_ERROR_STATUS_T: - return sizeof(error_status_t); case RPC_FC_ENUM16: return sizeof(UINT); default: @@ -2823,6 +3246,9 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pointer_desc = NULL; unsigned char *OldMemory = pStubMsg->Memory; int pointer_buffer_mark_set = 0; + ULONG count = 0; + ULONG max_count = 0; + ULONG offset = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -2858,10 +3284,27 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Memory = pMemory; + if (conf_array) + { + unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat); + array_compute_and_write_conformance(conf_array[0], pStubMsg, + pMemory + struct_size, conf_array); + /* these could be changed in ComplexMarshall so save them for later */ + max_count = pStubMsg->MaxCount; + count = pStubMsg->ActualCount; + offset = pStubMsg->Offset; + } + pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); if (conf_array) - NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); + { + pStubMsg->MaxCount = max_count; + pStubMsg->ActualCount = count; + pStubMsg->Offset = offset; + array_write_variance_and_marshall(conf_array[0], pStubMsg, pMemory, + conf_array, TRUE /* fHasPointers */); + } pStubMsg->Memory = OldMemory; @@ -2889,6 +3332,10 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pointer_desc = NULL; unsigned char *pMemory; int pointer_buffer_mark_set = 0; + ULONG count = 0; + ULONG max_count = 0; + ULONG offset = 0; + ULONG array_size = 0; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); @@ -2915,19 +3362,40 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, size); - pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; pFormat += 2; if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; + if (conf_array) + { + array_size = array_read_conformance(conf_array[0], pStubMsg, conf_array); + size += array_size; + + /* these could be changed in ComplexMarshall so save them for later */ + max_count = pStubMsg->MaxCount; + count = pStubMsg->ActualCount; + offset = pStubMsg->Offset; + } + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, size); + pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc); if (conf_array) - NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); + { + pStubMsg->MaxCount = max_count; + pStubMsg->ActualCount = count; + pStubMsg->Offset = offset; + if (fMustAlloc) + memset(pMemory, 0, array_size); + array_read_variance_and_unmarshall(conf_array[0], pStubMsg, &pMemory, + conf_array, FALSE, + FALSE /* fUseBufferMemoryServer */, + TRUE /* fUnmarshall */); + } if (pointer_buffer_mark_set) { @@ -2949,6 +3417,9 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pointer_desc = NULL; unsigned char *OldMemory = pStubMsg->Memory; int pointer_length_set = 0; + ULONG count = 0; + ULONG max_count = 0; + ULONG offset = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -2982,10 +3453,28 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Memory = pMemory; + if (conf_array) + { + unsigned long struct_size = ComplexStructSize(pStubMsg, pFormat); + array_compute_and_size_conformance(conf_array[0], pStubMsg, pMemory + struct_size, + conf_array); + + /* these could be changed in ComplexMarshall so save them for later */ + max_count = pStubMsg->MaxCount; + count = pStubMsg->ActualCount; + offset = pStubMsg->Offset; + } + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); if (conf_array) - NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); + { + pStubMsg->MaxCount = max_count; + pStubMsg->ActualCount = count; + pStubMsg->Offset = offset; + array_buffer_size(conf_array[0], pStubMsg, pMemory, conf_array, + TRUE /* fHasPointers */); + } pStubMsg->Memory = OldMemory; @@ -3006,6 +3495,9 @@ ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, unsigned size = *(const WORD*)(pFormat+2); PFORMAT_STRING conf_array = NULL; PFORMAT_STRING pointer_desc = NULL; + ULONG count = 0; + ULONG max_count = 0; + ULONG offset = 0; TRACE("(%p,%p)\n", pStubMsg, pFormat); @@ -3017,10 +3509,27 @@ ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; pFormat += 2; + if (conf_array) + { + array_read_conformance(conf_array[0], pStubMsg, conf_array); + + /* these could be changed in ComplexStructMemorySize so save them for + * later */ + max_count = pStubMsg->MaxCount; + count = pStubMsg->ActualCount; + offset = pStubMsg->Offset; + } + ComplexStructMemorySize(pStubMsg, pFormat, pointer_desc); if (conf_array) - NdrConformantArrayMemorySize(pStubMsg, conf_array); + { + pStubMsg->MaxCount = max_count; + pStubMsg->ActualCount = count; + pStubMsg->Offset = offset; + array_memory_size(conf_array[0], pStubMsg, conf_array, + TRUE /* fHasPointers */); + } return size; } @@ -3049,7 +3558,8 @@ void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); if (conf_array) - NdrConformantArrayFree(pStubMsg, pMemory, conf_array); + array_free(conf_array[0], pStubMsg, pMemory, conf_array, + TRUE /* fHasPointers */); pStubMsg->Memory = OldMemory; } @@ -3061,23 +3571,17 @@ unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - WriteConformance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, size); + if (pFormat[0] != RPC_FC_CARRAY) + { + ERR("invalid format = 0x%x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + array_compute_and_write_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, + pFormat); + array_write_variance_and_marshall(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); return NULL; } @@ -3090,34 +3594,18 @@ unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - unsigned char *saved_buffer; - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - - size = safe_multiply(esize, pStubMsg->MaxCount); - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - else + if (pFormat[0] != RPC_FC_CARRAY) { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; + ERR("invalid format = 0x%x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); } - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, size); + array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_CARRAY, pStubMsg, ppMemory, pFormat, + fMustAlloc, + TRUE /* fUseBufferMemoryServer */, + TRUE /* fUnmarshall */); return NULL; } @@ -3129,23 +3617,16 @@ void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - /* conformance value plus array */ - safe_buffer_length_increment(pStubMsg, size); + if (pFormat[0] != RPC_FC_CARRAY) + { + ERR("invalid format = 0x%x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + array_compute_and_size_conformance(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat); + array_buffer_size(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); } /*********************************************************************** @@ -3154,21 +3635,15 @@ void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - TRACE("(%p,%p)\n", pStubMsg, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - size = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->MemorySize += size; - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); + if (pFormat[0] != RPC_FC_CARRAY) + { + ERR("invalid format = 0x%x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } - EmbeddedPointerMemorySize(pStubMsg, pFormat); + array_read_conformance(RPC_FC_CARRAY, pStubMsg, pFormat); + array_memory_size(RPC_FC_CARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */); return pStubMsg->MemorySize; } @@ -3181,11 +3656,14 @@ void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + if (pFormat[0] != RPC_FC_CARRAY) + { + ERR("invalid format = 0x%x\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); + array_free(RPC_FC_CARRAY, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); } @@ -3196,10 +3674,6 @@ unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStu unsigned char* pMemory, PFORMAT_STRING pFormat ) { - ULONG bufsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); if (pFormat[0] != RPC_FC_CVARRAY) @@ -3209,20 +3683,10 @@ unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStu return NULL; } - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + array_compute_and_write_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory, + pFormat); + array_write_variance_and_marshall(RPC_FC_CVARRAY, pStubMsg, pMemory, + pFormat, TRUE /* fHasPointers */); return NULL; } @@ -3236,12 +3700,6 @@ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pS PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { - ULONG bufsize, memsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - unsigned char *saved_buffer; - ULONG offset; - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); if (pFormat[0] != RPC_FC_CVARRAY) @@ -3251,23 +3709,11 @@ unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pS return NULL; } - pFormat = ReadConformance(pStubMsg, pFormat+4); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - offset = pStubMsg->Offset; - - if (!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); - - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - memcpy(*ppMemory + offset, saved_buffer, bufsize); + array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_CVARRAY, pStubMsg, ppMemory, + pFormat, fMustAlloc, + TRUE /* fUseBufferMemoryServer */, + TRUE /* fUnmarshall */); return NULL; } @@ -3289,10 +3735,8 @@ void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, return; } - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); + array_free(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); } @@ -3302,9 +3746,6 @@ void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat ) { - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); if (pFormat[0] != RPC_FC_CVARRAY) @@ -3314,19 +3755,10 @@ void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, return; } - /* compute size */ - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - /* compute length */ - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + array_compute_and_size_conformance(RPC_FC_CVARRAY, pStubMsg, pMemory, + pFormat); + array_buffer_size(RPC_FC_CVARRAY, pStubMsg, pMemory, pFormat, + TRUE /* fHasPointers */); } @@ -3336,10 +3768,6 @@ void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) { - ULONG bufsize, memsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - TRACE("(%p, %p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_CVARRAY) @@ -3349,18 +3777,9 @@ ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, return pStubMsg->MemorySize; } - pFormat = ReadConformance(pStubMsg, pFormat+4); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); + array_read_conformance(RPC_FC_CVARRAY, pStubMsg, pFormat); + array_memory_size(RPC_FC_CVARRAY, pStubMsg, pFormat, + TRUE /* fHasPointers */); return pStubMsg->MemorySize; } @@ -4171,7 +4590,6 @@ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pS { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); @@ -4185,43 +4603,10 @@ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pS pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - WriteConformance(pStubMsg); + array_compute_and_write_conformance(*pCVArrayFormat, pStubMsg, + pMemory + pCVStructFormat->memory_size, + pCVArrayFormat); ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); @@ -4231,12 +4616,9 @@ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pS pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size); - WriteVariance(pStubMsg); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* write array part */ - safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize); + array_write_variance_and_marshall(*pCVArrayFormat, pStubMsg, + pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, FALSE /* fHasPointers */); EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); @@ -4253,9 +4635,10 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; - unsigned char cvarray_type; + ULONG memsize, bufsize; unsigned char *saved_buffer, *saved_array_buffer; + ULONG offset; + unsigned char *array_memory; TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); @@ -4269,32 +4652,9 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } + + memsize = array_read_conformance(*pCVArrayFormat, pStubMsg, + pCVArrayFormat); ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); @@ -4303,7 +4663,7 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE /* work out how much memory to allocate if we need to do so */ if (!*ppMemory || fMustAlloc) { - SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + SIZE_T size = pCVStructFormat->memory_size + memsize; *ppMemory = NdrAllocate(pStubMsg, size); } @@ -4311,13 +4671,15 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); + array_memory = *ppMemory + pCVStructFormat->memory_size; + bufsize = array_read_variance_and_unmarshall(*pCVArrayFormat, pStubMsg, + &array_memory, pCVArrayFormat, + FALSE /* fMustAlloc */, + FALSE /* fUseServerBufferMemory */, + FALSE /* fUnmarshall */); - if ((cvarray_type == RPC_FC_C_CSTRING) || - (cvarray_type == RPC_FC_C_WSTRING)) - validate_string_data(pStubMsg, bufsize, esize); + /* save offset in case unmarshalling pointers changes it */ + offset = pStubMsg->Offset; /* mark the start of the array data */ saved_array_buffer = pStubMsg->Buffer; @@ -4329,11 +4691,12 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size); /* copy the array data */ TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size); - memcpy(*ppMemory + pCVStructFormat->memory_size, saved_array_buffer, bufsize); + memcpy(*ppMemory + pCVStructFormat->memory_size + offset, + saved_array_buffer, bufsize); - if (cvarray_type == RPC_FC_C_CSTRING) + if (*pCVArrayFormat == RPC_FC_C_CSTRING) TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); - else if (cvarray_type == RPC_FC_C_WSTRING) + else if (*pCVArrayFormat == RPC_FC_C_WSTRING) TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); return NULL; @@ -4348,7 +4711,6 @@ void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; - ULONG esize; TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); @@ -4362,51 +4724,19 @@ void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - SizeConformance(pStubMsg); + array_compute_and_size_conformance(*pCVArrayFormat, pStubMsg, + pMemory + pCVStructFormat->memory_size, + pCVArrayFormat); ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size); - SizeVariance(pStubMsg); - safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); + + array_buffer_size(*pCVArrayFormat, pStubMsg, + pMemory + pCVStructFormat->memory_size, pCVArrayFormat, + FALSE /* fHasPointers */); EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); } @@ -4419,8 +4749,6 @@ ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, { const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; PFORMAT_STRING pCVArrayFormat; - ULONG esize; - unsigned char cvarray_type; TRACE("(%p, %p)\n", pStubMsg, pFormat); @@ -4434,46 +4762,21 @@ ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } + array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + array_memory_size(*pCVArrayFormat, pStubMsg, pCVArrayFormat, + FALSE /* fHasPointers */); - pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += pCVStructFormat->memory_size; EmbeddedPointerMemorySize(pStubMsg, pFormat); - return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; + return pStubMsg->MemorySize; } /*********************************************************************** @@ -4498,37 +4801,9 @@ void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } + array_free(*pCVArrayFormat, pStubMsg, + pMemory + pCVStructFormat->memory_size, pCVArrayFormat, + FALSE /* fHasPointers */); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index a439bc371de..15f0e87a129 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -308,21 +308,6 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) } } -/* utility functions for string composing and parsing */ -static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src) -{ - unsigned len = strlen(src); - memcpy(data, src, len*sizeof(CHAR)); - return len; -} - -static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src) -{ - unsigned len = strlenW(src); - memcpy(data, src, len*sizeof(WCHAR)); - return len; -} - static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src) { DWORD len = strlen(dst), slen = strlen(src); @@ -351,6 +336,123 @@ static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) return ndst; } +/* Copies the escaped version of a component into a string binding. + * Note: doesn't nul-terminate the string */ +static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding, + const unsigned char *component) +{ + for (; *component; component++) { + switch (*component) { + case '@': + case ':': + case '[': + case ']': + case '\\': + *string_binding++ = '\\'; + *string_binding++ = *component; + break; + default: + *string_binding++ = *component; + break; + } + } + return string_binding; +} + +static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding, + const WCHAR *component) +{ + for (; *component; component++) { + switch (*component) { + case '@': + case ':': + case '[': + case ']': + case '\\': + *string_binding++ = '\\'; + *string_binding++ = *component; + break; + default: + *string_binding++ = *component; + break; + } + } + return string_binding; +} + +static const unsigned char *string_binding_find_delimiter( + const unsigned char *string_binding, unsigned char delim) +{ + const unsigned char *next; + for (next = string_binding; *next; next++) { + if (*next == '\\') { + next++; + continue; + } + if (*next == delim) + return next; + } + return NULL; +} + +static const WCHAR *string_binding_find_delimiterW( + const WCHAR *string_binding, WCHAR delim) +{ + const WCHAR *next; + for (next = string_binding; *next; next++) { + if (*next == '\\') { + next++; + continue; + } + if (*next == delim) + return next; + } + return NULL; +} + +static RPC_CSTR unescape_string_binding_component( + const unsigned char *string_binding, int len) +{ + RPC_CSTR component, p; + + if (len == -1) len = strlen((const char *)string_binding); + + component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component)); + if (!component) return NULL; + for (p = component; len > 0; string_binding++, len--) { + if (*string_binding == '\\') { + string_binding++; + len--; + *p++ = *string_binding; + } else { + *p++ = *string_binding; + } + } + *p = '\0'; + return component; +} + +static RPC_WSTR unescape_string_binding_componentW( + const WCHAR *string_binding, int len) +{ + RPC_WSTR component, p; + + if (len == -1) len = strlen((const char *)string_binding); + + component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component)); + if (!component) return NULL; + for (p = component; len > 0; string_binding++, len--) { + if (*string_binding == '\\') { + string_binding++; + len--; + *p++ = *string_binding; + } else { + *p++ = *string_binding; + } + } + *p = '\0'; + return component; +} /*********************************************************************** * RpcStringBindingComposeA (RPCRT4.@) @@ -360,42 +462,43 @@ RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq, RPC_CSTR Options, RPC_CSTR *StringBinding ) { DWORD len = 1; - LPSTR data; + RPC_CSTR data; TRACE( "(%s,%s,%s,%s,%s,%p)\n", debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ), debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ), debugstr_a( (char*)Options ), StringBinding ); - if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1; - if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1; - if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr); - if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2; - if (Options && *Options) len += strlen((char*)Options) + 2; + /* overestimate for each component for escaping of delimiters */ + if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1; + if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1; + if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2; + if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2; + if (Options && *Options) len += strlen((char*)Options) * 2 + 2; data = HeapAlloc(GetProcessHeap(), 0, len); - *StringBinding = (unsigned char*)data; + *StringBinding = data; if (ObjUuid && *ObjUuid) { - data += RPCRT4_strcopyA(data, (char*)ObjUuid); + data = escape_string_binding_component(data, ObjUuid); *data++ = '@'; } if (Protseq && *Protseq) { - data += RPCRT4_strcopyA(data, (char*)Protseq); + data = escape_string_binding_component(data, Protseq); *data++ = ':'; } if (NetworkAddr && *NetworkAddr) - data += RPCRT4_strcopyA(data, (char*)NetworkAddr); + data = escape_string_binding_component(data, NetworkAddr); if ((Endpoint && *Endpoint) || (Options && *Options)) { *data++ = '['; if (Endpoint && *Endpoint) { - data += RPCRT4_strcopyA(data, (char*)Endpoint); + data = escape_string_binding_component(data, Endpoint); if (Options && *Options) *data++ = ','; } if (Options && *Options) { - data += RPCRT4_strcopyA(data, (char*)Options); + data = escape_string_binding_component(data, Options); } *data++ = ']'; } @@ -419,35 +522,36 @@ RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq, debugstr_w( NetworkAddr ), debugstr_w( Endpoint ), debugstr_w( Options ), StringBinding); - if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1; - if (Protseq && *Protseq) len += strlenW(Protseq) + 1; - if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr); - if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2; - if (Options && *Options) len += strlenW(Options) + 2; + /* overestimate for each component for escaping of delimiters */ + if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1; + if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1; + if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2; + if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2; + if (Options && *Options) len += strlenW(Options) * 2 + 2; data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); *StringBinding = data; if (ObjUuid && *ObjUuid) { - data += RPCRT4_strcopyW(data, ObjUuid); + data = escape_string_binding_componentW(data, ObjUuid); *data++ = '@'; } if (Protseq && *Protseq) { - data += RPCRT4_strcopyW(data, Protseq); + data = escape_string_binding_componentW(data, Protseq); *data++ = ':'; } if (NetworkAddr && *NetworkAddr) { - data += RPCRT4_strcopyW(data, NetworkAddr); + data = escape_string_binding_componentW(data, NetworkAddr); } if ((Endpoint && *Endpoint) || (Options && *Options)) { *data++ = '['; if (Endpoint && *Endpoint) { - data += RPCRT4_strcopyW(data, Endpoint); + data = escape_string_binding_componentW(data, Endpoint); if (Options && *Options) *data++ = ','; } if (Options && *Options) { - data += RPCRT4_strcopyW(data, Options); + data = escape_string_binding_componentW(data, Options); } *data++ = ']'; } @@ -464,7 +568,7 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr, RPC_CSTR *Endpoint, RPC_CSTR *Options) { - CHAR *data, *next; + const unsigned char *data, *next; static const char ep_opt[] = "endpoint="; BOOL endpoint_already_found = FALSE; @@ -477,13 +581,13 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU if (Endpoint) *Endpoint = NULL; if (Options) *Options = NULL; - data = (char*) StringBinding; + data = StringBinding; - next = strchr(data, '@'); + next = string_binding_find_delimiter(data, '@'); if (next) { UUID uuid; RPC_STATUS status; - RPC_CSTR str_uuid = (unsigned char*)RPCRT4_strndupA(data, next - data); + RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data); status = UuidFromStringA(str_uuid, &uuid); if (status != RPC_S_OK) { HeapFree(GetProcessHeap(), 0, str_uuid); @@ -496,42 +600,43 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU data = next+1; } - next = strchr(data, ':'); + next = string_binding_find_delimiter(data, ':'); if (next) { - if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data); + if (Protseq) *Protseq = unescape_string_binding_component(data, next - data); data = next+1; } - next = strchr(data, '['); + next = string_binding_find_delimiter(data, '['); if (next) { - CHAR *close, *opt; + const unsigned char *close; + RPC_CSTR opt; - if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data); + if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data); data = next+1; - close = strchr(data, ']'); + close = string_binding_find_delimiter(data, ']'); if (!close) goto fail; /* tokenize options */ while (data < close) { - next = strchr(data, ','); + next = string_binding_find_delimiter(data, ','); if (!next || next > close) next = close; /* FIXME: this is kind of inefficient */ - opt = RPCRT4_strndupA(data, next - data); + opt = unescape_string_binding_component(data, next - data); data = next+1; /* parse option */ - next = strchr(opt, '='); + next = string_binding_find_delimiter(opt, '='); if (!next) { /* not an option, must be an endpoint */ if (endpoint_already_found) goto fail; - if (Endpoint) *Endpoint = (unsigned char*) opt; + if (Endpoint) *Endpoint = opt; else HeapFree(GetProcessHeap(), 0, opt); endpoint_already_found = TRUE; } else { - if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) { + if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) { /* endpoint option */ if (endpoint_already_found) goto fail; - if (Endpoint) *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1); + if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1); HeapFree(GetProcessHeap(), 0, opt); endpoint_already_found = TRUE; } else { @@ -539,10 +644,10 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU if (Options) { if (*Options) { /* FIXME: this is kind of inefficient */ - *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt); + *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt); HeapFree(GetProcessHeap(), 0, opt); } else - *Options = (unsigned char*) opt; + *Options = opt; } else HeapFree(GetProcessHeap(), 0, opt); } @@ -553,7 +658,7 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU if (*data) goto fail; } else if (NetworkAddr) - *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data); + *NetworkAddr = unescape_string_binding_component(data, -1); return RPC_S_OK; @@ -573,7 +678,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr, RPC_WSTR *Endpoint, RPC_WSTR *Options) { - WCHAR *data, *next; + const WCHAR *data, *next; static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0}; BOOL endpoint_already_found = FALSE; @@ -588,11 +693,11 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU data = StringBinding; - next = strchrW(data, '@'); + next = string_binding_find_delimiterW(data, '@'); if (next) { UUID uuid; RPC_STATUS status; - RPC_WSTR str_uuid = RPCRT4_strndupW(data, next - data); + RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data); status = UuidFromStringW(str_uuid, &uuid); if (status != RPC_S_OK) { HeapFree(GetProcessHeap(), 0, str_uuid); @@ -605,31 +710,32 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU data = next+1; } - next = strchrW(data, ':'); + next = string_binding_find_delimiterW(data, ':'); if (next) { - if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data); + if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data); data = next+1; } - next = strchrW(data, '['); + next = string_binding_find_delimiterW(data, '['); if (next) { - WCHAR *close, *opt; + const WCHAR *close; + RPC_WSTR opt; - if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data); + if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data); data = next+1; - close = strchrW(data, ']'); + close = string_binding_find_delimiterW(data, ']'); if (!close) goto fail; /* tokenize options */ while (data < close) { - next = strchrW(data, ','); + next = string_binding_find_delimiterW(data, ','); if (!next || next > close) next = close; /* FIXME: this is kind of inefficient */ - opt = RPCRT4_strndupW(data, next - data); + opt = unescape_string_binding_componentW(data, next - data); data = next+1; /* parse option */ - next = strchrW(opt, '='); + next = string_binding_find_delimiterW(opt, '='); if (!next) { /* not an option, must be an endpoint */ if (endpoint_already_found) goto fail; @@ -640,7 +746,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) { /* endpoint option */ if (endpoint_already_found) goto fail; - if (Endpoint) *Endpoint = RPCRT4_strdupW(next+1); + if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1); HeapFree(GetProcessHeap(), 0, opt); endpoint_already_found = TRUE; } else { @@ -661,7 +767,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU data = close+1; if (*data) goto fail; } else if (NetworkAddr) - *NetworkAddr = RPCRT4_strdupW(data); + *NetworkAddr = unescape_string_binding_componentW(data, -1); return RPC_S_OK; @@ -816,8 +922,13 @@ RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CS TRACE("(%p,%p)\n", Binding, StringBinding); - ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid); - if (ret != RPC_S_OK) return ret; + if (UuidIsNil(&bind->ObjectUuid, &ret)) + ObjectUuid = NULL; + else + { + ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid); + if (ret != RPC_S_OK) return ret; + } ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr, (unsigned char*) bind->Endpoint, NULL, StringBinding); diff --git a/dlls/rpcrt4/rpc_epmap.c b/dlls/rpcrt4/rpc_epmap.c index 19c11f880ca..6f77475513a 100644 --- a/dlls/rpcrt4/rpc_epmap.c +++ b/dlls/rpcrt4/rpc_epmap.c @@ -71,7 +71,7 @@ static const struct epm_endpoints { "ncacn_np", "\\pipe\\epmapper" }, { "ncacn_ip_tcp", "135" }, { "ncacn_ip_udp", "135" }, - { "ncalprc", "epmapper" }, + { "ncalrpc", "epmapper" }, { "ncacn_http", "593" }, }; @@ -153,7 +153,7 @@ static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_H static RPC_STATUS get_epm_handle_server(RPC_BINDING_HANDLE *epm_handle) { - unsigned char string_binding[] = "ncacn_np:.[\\pipe\\epmapper]"; + unsigned char string_binding[] = "ncacn_np:.[\\\\pipe\\\\epmapper]"; return RpcBindingFromStringBindingA(string_binding, epm_handle); } diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c index 86c4e4f28dd..adba3c897a4 100644 --- a/dlls/rpcrt4/rpc_transport.c +++ b/dlls/rpcrt4/rpc_transport.c @@ -210,9 +210,7 @@ static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, TRACE("connection failed, error=%x\n", err); return RPC_S_SERVER_TOO_BUSY; } - if (!wait) - return RPC_S_SERVER_UNAVAILABLE; - if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { + if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { err = GetLastError(); WARN("connection failed, error=%x\n", err); return RPC_S_SERVER_UNAVAILABLE; @@ -504,7 +502,8 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_ if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || (smb_floor->protid != EPM_PROTOCOL_SMB) || - (smb_floor->count_rhs > tower_size)) + (smb_floor->count_rhs > tower_size) || + (tower_data[smb_floor->count_rhs - 1] != '\0')) return EPT_S_NOT_REGISTERED; if (endpoint) @@ -527,7 +526,8 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_ if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || - (nb_floor->count_rhs > tower_size)) + (nb_floor->count_rhs > tower_size) || + (tower_data[nb_floor->count_rhs - 1] != '\0')) return EPT_S_NOT_REGISTERED; if (networkaddr) @@ -677,7 +677,7 @@ static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); - endpoint_size = strlen(networkaddr) + 1; + endpoint_size = strlen(endpoint) + 1; size = sizeof(*pipe_floor) + endpoint_size; if (!tower_data) @@ -688,7 +688,7 @@ static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, tower_data += sizeof(*pipe_floor); pipe_floor->count_lhs = sizeof(pipe_floor->protid); - pipe_floor->protid = EPM_PROTOCOL_SMB; + pipe_floor->protid = EPM_PROTOCOL_PIPE; pipe_floor->count_rhs = endpoint_size; memcpy(tower_data, endpoint, endpoint_size); @@ -706,9 +706,6 @@ static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_d TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); - *networkaddr = NULL; - *endpoint = NULL; - if (tower_size < sizeof(*pipe_floor)) return EPT_S_NOT_REGISTERED; @@ -716,10 +713,14 @@ static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_d tower_size -= sizeof(*pipe_floor); if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || - (pipe_floor->protid != EPM_PROTOCOL_SMB) || - (pipe_floor->count_rhs > tower_size)) + (pipe_floor->protid != EPM_PROTOCOL_PIPE) || + (pipe_floor->count_rhs > tower_size) || + (tower_data[pipe_floor->count_rhs - 1] != '\0')) return EPT_S_NOT_REGISTERED; + if (networkaddr) + *networkaddr = NULL; + if (endpoint) { *endpoint = I_RpcAllocate(pipe_floor->count_rhs); diff --git a/dlls/rpcrt4/tests/ndr_marshall.c b/dlls/rpcrt4/tests/ndr_marshall.c index 969cce2e261..7c538c60cdf 100644 --- a/dlls/rpcrt4/tests/ndr_marshall.c +++ b/dlls/rpcrt4/tests/ndr_marshall.c @@ -1807,6 +1807,105 @@ static void test_nonconformant_string(void) HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); } +static void test_conf_complex_struct(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + void *ptr; + unsigned int i; + struct conf_complex + { + unsigned int size; + unsigned int *array[1]; + }; + struct conf_complex *memsrc; + struct conf_complex *mem; + + static const unsigned char fmtstr_complex_struct[] = + { +/* 0 */ + 0x1b, /* FC_CARRAY */ + 0x3, /* 3 */ +/* 2 */ NdrFcShort( 0x4 ), /* 4 */ +/* 4 */ 0x8, /* Corr desc: FC_LONG */ + 0x0, /* */ +/* 6 */ NdrFcShort( 0xfffc ), /* -4 */ +/* 8 */ + 0x4b, /* FC_PP */ + 0x5c, /* FC_PAD */ +/* 10 */ + 0x48, /* FC_VARIABLE_REPEAT */ + 0x49, /* FC_FIXED_OFFSET */ +/* 12 */ NdrFcShort( 0x4 ), /* 4 */ +/* 14 */ NdrFcShort( 0x0 ), /* 0 */ +/* 16 */ NdrFcShort( 0x1 ), /* 1 */ +/* 18 */ NdrFcShort( 0x0 ), /* 0 */ +/* 20 */ NdrFcShort( 0x0 ), /* 0 */ +/* 22 */ 0x12, 0x8, /* FC_UP [simple_pointer] */ +/* 24 */ 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ +/* 26 */ + 0x5b, /* FC_END */ + + 0x8, /* FC_LONG */ +/* 28 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 30 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 32 */ NdrFcShort( 0x4 ), /* 4 */ +/* 34 */ NdrFcShort( 0xffffffde ), /* Offset= -34 (0) */ +/* 36 */ NdrFcShort( 0x0 ), /* Offset= 0 (36) */ +/* 38 */ 0x8, /* FC_LONG */ + 0x5b, /* FC_END */ + }; + + memsrc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + FIELD_OFFSET(struct conf_complex, array[20])); + memsrc->size = 20; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = fmtstr_complex_struct; + + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + NdrComplexStructBufferSize( &StubMsg, + (unsigned char *)memsrc, + &fmtstr_complex_struct[30] ); + ok(StubMsg.BufferLength >= 28, "length %d\n", StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)memsrc, + &fmtstr_complex_struct[30] ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(*(unsigned int *)StubMsg.BufferStart == 20, "Conformance should have been 20 instead of %d\n", (unsigned int)StubMsg.BufferStart); + ok(*(unsigned int *)(StubMsg.BufferStart + 4) == 20, "conf_complex.size should have been 20 instead of %d\n", (unsigned int)(StubMsg.BufferStart + 4)); + for (i = 0; i < 20; i++) + ok(*(unsigned int *)(StubMsg.BufferStart + 8 + i * 4) == 0, "pointer id for conf_complex.array[%d] should have been 0 instead of 0x%x\n", i, *(unsigned int *)(StubMsg.BufferStart + 8 + i * 4)); + + /* Server */ + my_alloc_called = 0; + StubMsg.IsClient = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_struct[30], 0); + ok(ptr == NULL, "ret %p\n", ptr); + ok(mem->size == 20, "mem->size wasn't unmarshalled correctly (%d)\n", mem->size); + ok(mem->array[0] == NULL, "mem->array[0] wasn't unmarshalled correctly (%p)\n", mem->array[0]); + StubMsg.pfnFree(mem); + + HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); +} + static void test_ndr_buffer(void) { static unsigned char ncalrpc[] = "ncalrpc"; @@ -1943,6 +2042,7 @@ START_TEST( ndr_marshall ) test_conformant_array(); test_conformant_string(); test_nonconformant_string(); + test_conf_complex_struct(); test_ndr_buffer(); test_NdrMapCommAndFaultStatus(); } diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c index 19a0a944743..7d8f7308aa9 100644 --- a/dlls/rpcrt4/tests/rpc.c +++ b/dlls/rpcrt4/tests/rpc.c @@ -577,7 +577,6 @@ static void test_RpcStringBindingParseA(void) ok(!strcmp((char *)uuid, "00000000-0000-0000-c000-000000000046"), "uuid should have been 00000000-0000-0000-C000-000000000046 instead of %s\n", uuid); ok(!strcmp((char *)protseq, "ncacn_np"), "protseq should have been ncacn_np instead of %s\n", protseq); ok(!strcmp((char *)network_addr, "."), "network_addr should have been . instead of %s\n", network_addr); - todo_wine ok(!strcmp((char *)endpoint, "pipetest"), "endpoint should have been pipetest instead of %s\n", endpoint); todo_wine ok(options && !strcmp((char *)options, ""), "options should have been \"\" of \"%s\"\n", options); @@ -593,7 +592,6 @@ static void test_RpcStringBindingParseA(void) ok(!strcmp((char *)uuid, "00000000-0000-0000-c000-000000000046"), "uuid should have been 00000000-0000-0000-C000-000000000046 instead of %s\n", uuid); ok(!strcmp((char *)protseq, "ncacn_np"), "protseq should have been ncacn_np instead of %s\n", protseq); ok(!strcmp((char *)network_addr, "."), "network_addr should have been . instead of %s\n", network_addr); - todo_wine ok(!strcmp((char *)endpoint, "pipetest"), "endpoint should have been pipetest instead of %s\n", endpoint); todo_wine ok(options && !strcmp((char *)options, ""), "options should have been \"\" of \"%s\"\n", options); @@ -722,6 +720,34 @@ static void test_endpoint_mapper(void) ok(status == RPC_S_OK, "RpcBindingVectorFree failed with error %lu\n", status); } +static void test_RpcStringBindingFromBinding(void) +{ + static unsigned char ncacn_np[] = "ncacn_np"; + static unsigned char address[] = "."; + static unsigned char endpoint[] = "\\pipe\\wine_rpc_test"; + RPC_STATUS status; + handle_t handle; + RPC_CSTR binding; + + status = RpcStringBindingCompose(NULL, ncacn_np, address, + endpoint, NULL, &binding); + ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%lu)\n", status); + + status = RpcBindingFromStringBinding(binding, &handle); + ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%lu)\n", status); + RpcStringFree(&binding); + + status = RpcBindingToStringBinding(handle, &binding); + ok(status == RPC_S_OK, "RpcStringBindingFromBinding failed with error %lu\n", status); + + ok(!strcmp((const char *)binding, "ncacn_np:.[\\\\pipe\\\\wine_rpc_test]"), + "binding string didn't match what was expected: \"%s\"\n", binding); + RpcStringFree(&binding); + + status = RpcBindingFree(&handle); + ok(status == RPC_S_OK, "RpcBindingFree failed with error %lu\n", status); +} + START_TEST( rpc ) { trace ( " ** Uuid Conversion and Comparison Tests **\n" ); @@ -734,4 +760,5 @@ START_TEST( rpc ) test_RpcStringBindingParseA(); test_I_RpcExceptionFilter(); test_endpoint_mapper(); + test_RpcStringBindingFromBinding(); } diff --git a/dlls/shell32/shell32_Ru.rc b/dlls/shell32/shell32_Ru.rc index 795be24f8d0..47dcd370190 100644 --- a/dlls/shell32/shell32_Ru.rc +++ b/dlls/shell32/shell32_Ru.rc @@ -142,8 +142,8 @@ FONT 8, "MS Shell Dlg" 12, 38, 194, 105 EDITTEXT IDD_FOLDERTEXT, 46, 150, 160, 14, WS_BORDER | WS_GROUP | WS_TABSTOP PUSHBUTTON "Ñîçäàòü &íîâóþ ïàïêó", IDD_MAKENEWFOLDER, 12, 174, 77, 14, WS_GROUP | WS_TABSTOP - DEFPUSHBUTTON "Äà", IDOK, 102, 174, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Îòìåíèòü", IDCANCEL, 156, 174, 50, 14, WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "OK", IDOK, 102, 174, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Îòìåíà", IDCANCEL, 156, 174, 50, 14, WS_GROUP | WS_TABSTOP } SHELL_YESTOALL_MSGBOX DIALOG 200, 100, 280, 90 diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c index fec78701d84..bf820ca6443 100644 --- a/dlls/shell32/shlexec.c +++ b/dlls/shell32/shlexec.c @@ -1091,10 +1091,11 @@ static IDataObject *shellex_get_dataobj( LPSHELLEXECUTEINFOW sei ) else { WCHAR fullpath[MAX_PATH]; + BOOL ret; fullpath[0] = 0; - r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL ); - if (!r) + ret = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL ); + if (!ret) goto end; pidl = ILCreateFromPathW( fullpath ); @@ -1755,6 +1756,34 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) sei, execfunc ); HeapFree( GetProcessHeap(), 0, env ); } + else if (PathIsDirectoryW(lpFile)) + { + static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r',0}; + static const WCHAR wQuote[] = {'"',0}; + WCHAR wExec[MAX_PATH]; + WCHAR * lpQuotedFile = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3) ); + + if (lpQuotedFile) + { + retval = SHELL_FindExecutable( sei_tmp.lpDirectory, wExplorer, + wszOpen, wExec, MAX_PATH, + NULL, &env, NULL, NULL ); + if (retval > 32) + { + strcpyW(lpQuotedFile, wQuote); + strcatW(lpQuotedFile, lpFile); + strcatW(lpQuotedFile, wQuote); + retval = SHELL_quote_and_execute( wExec, lpQuotedFile, + lpstrProtocol, + wszApplicationName, env, + &sei_tmp, sei, execfunc ); + HeapFree( GetProcessHeap(), 0, env ); + } + HeapFree( GetProcessHeap(), 0, lpQuotedFile ); + } + else + retval = 0; /* Out of memory */ + } else if (PathIsURLW(lpFile)) /* File not found, check for URL */ { retval = SHELL_execute_url( lpFile, wFile, wcmd, &sei_tmp, sei, execfunc ); diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c index d0bff7feb07..b7be1f1ffbd 100644 --- a/dlls/shlwapi/ordinal.c +++ b/dlls/shlwapi/ordinal.c @@ -422,11 +422,11 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown) pIEnumFormatEtc = NULL; hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (PVOID)&pIEnumFormatEtc); - if (!hRet && pIEnumFormatEtc) + if (hRet == S_OK && pIEnumFormatEtc) { /* Clone and register the enumerator */ hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone); - if (!hRet && pClone) + if (hRet == S_OK && pClone) { RegisterFormatEnumerator(lpBC, pClone, 0); @@ -1462,7 +1462,7 @@ HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID ri hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider, (LPVOID*)&pService); - if (!hRet && pService) + if (hRet == S_OK && pService) { TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService); diff --git a/dlls/shlwapi/string.c b/dlls/shlwapi/string.c index abbfdbafdae..89cf5efc237 100644 --- a/dlls/shlwapi/string.c +++ b/dlls/shlwapi/string.c @@ -2511,8 +2511,9 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, DWORD dwMode = 0; INT nWideCharCount = len - 1; - if (!ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr, - lpiLen)) + if (ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, + &nWideCharCount, lpDstStr, + lpiLen) == S_OK) return 0; if (nWideCharCount < len - 1) @@ -2523,7 +2524,8 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, *lpiLen = 0; - if (ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpiLen)) + if (ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, + mem, lpiLen) != S_OK) { SHTruncateString(mem, *lpiLen); lstrcpynA(lpDstStr, mem, *lpiLen + 1); diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c index 03941a911b7..18ebc41d928 100644 --- a/dlls/shlwapi/url.c +++ b/dlls/shlwapi/url.c @@ -2077,7 +2077,7 @@ HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags); ret = URL_ParseUrl(pszIn, &pl); - if (!ret) { + if (ret == S_OK) { schaddr = pl.pScheme; schsize = pl.szScheme; diff --git a/dlls/urlmon/umon.c b/dlls/urlmon/umon.c index f6ea4274f03..d6a42429821 100644 --- a/dlls/urlmon/umon.c +++ b/dlls/urlmon/umon.c @@ -189,7 +189,7 @@ static HRESULT Binding_MoreCacheData(Binding *This, const char *buf, DWORD dwByt BINDSTATUS_BEGINDOWNLOADDATA : BINDSTATUS_DOWNLOADINGDATA, This->URLName); - if (!hr) + if (hr == S_OK) { STGMEDIUM stg; FORMATETC fmt; diff --git a/dlls/user32/dde_client.c b/dlls/user32/dde_client.c index 6f7386d68e4..00b41c41d45 100644 --- a/dlls/user32/dde_client.c +++ b/dlls/user32/dde_client.c @@ -191,6 +191,7 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic, { WARN("Done with INITIATE, but no Server window available\n"); pConv = NULL; + pInstance->lastError = DMLERR_NO_CONV_ESTABLISHED; goto theEnd; } TRACE("Connected to Server window (%p)\n", pConv->hwndServer); @@ -921,6 +922,7 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h if (pConv->transactions) { + if (ack) *ack = DDE_FNOTPROCESSED; /* first check message against a pending transaction, if any */ switch (pXAct->ddeMsg) { @@ -1153,6 +1155,11 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS { case XTYP_EXECUTE: /* Windows simply ignores hszItem and wFmt in this case */ + if (pData == NULL) + { + pConv->instance->lastError = DMLERR_INVALIDPARAMETER; + return 0; + } pXAct = WDML_ClientQueueExecute(pConv, pData, cbData); break; case XTYP_POKE: diff --git a/dlls/user32/dde_misc.c b/dlls/user32/dde_misc.c index d99cdcf746f..227f874b152 100644 --- a/dlls/user32/dde_misc.c +++ b/dlls/user32/dde_misc.c @@ -348,8 +348,8 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback, UINT ret; WNDCLASSEXW wndclass; - TRACE("(%p,%p,0x%x,%d)\n", - pidInst, pfnCallback, afCmd, ulRes); + TRACE("(%p,%p,0x%x,%d,0x%x)\n", + pidInst, pfnCallback, afCmd, ulRes, bUnicode); if (ulRes) { @@ -999,6 +999,14 @@ static int WDML_QueryString(WDML_INSTANCE* pInstance, HSZ hsz, LPVOID ptr, DWORD cchMax = MAX_BUFFER_LEN; } + /* if there is no input windows returns a NULL string */ + if (hsz == NULL) + { + CHAR *t_ptr = ptr; + *t_ptr = '\0'; + return 1; + } + switch (codepage) { case CP_WINANSI: diff --git a/dlls/user32/tests/dde.c b/dlls/user32/tests/dde.c index 908d60a5924..d41ccddddb4 100644 --- a/dlls/user32/tests/dde.c +++ b/dlls/user32/tests/dde.c @@ -291,11 +291,8 @@ static void test_ddeml_client(void) DdeGetLastError(client_pid); hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); - ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); - todo_wine - { - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", res); - } + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %08x\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -313,11 +310,9 @@ static void test_ddeml_client(void) DdeGetLastError(client_pid); hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); +todo_wine + ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -336,10 +331,7 @@ static void test_ddeml_client(void) hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -441,10 +433,7 @@ static void test_ddeml_client(void) ret = DdeGetLastError(client_pid); ok(op == NULL, "Expected NULL, got %p\n", op); ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res); - todo_wine - { - ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); - } + ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); DdeFreeStringHandle(client_pid, topic); DdeFreeDataHandle(hdata); @@ -457,10 +446,7 @@ static void test_ddeml_client(void) hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); ret = DdeGetLastError(client_pid); ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); - todo_wine - { - ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); - } + ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res); if (hdata == NULL) ok(FALSE, "hdata is NULL\n"); else @@ -665,7 +651,6 @@ static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hcon if (msg_index == 5) { - todo_wine { ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str); ok(size == 1, "Expected 1, got %d\n", size); @@ -707,7 +692,6 @@ static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hcon size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI); if (msg_index == 7) { - todo_wine { ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str); ok(size == 1, "Expected 1, got %d\n", size); @@ -1388,6 +1372,53 @@ todo_wine { DestroyWindow(hwnd_server); } +static void test_initialisation(void) +{ + UINT ret; + DWORD res; + HDDEDATA hdata; + HSZ server, topic, item; + DWORD client_pid; + HCONV conversation; + + /* Initialise without a valid server window. */ + client_pid = 0; + ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0); + ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret); + + + server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI); + topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI); + + DdeGetLastError(client_pid); + + /* There is no server window so no conversation can be extracted */ + conversation = DdeConnect(client_pid, server, topic, NULL); + ok(conversation == NULL, "Expected NULL conversation, %p\n", conversation); + ret = DdeGetLastError(client_pid); + ok(ret == DMLERR_NO_CONV_ESTABLISHED, "Expected DMLERR_NO_CONV_ESTABLISHED, got %d\n", ret); + + DdeFreeStringHandle(client_pid, server); + + item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI); + + /* There is no converstation so an invalild parameter results */ + res = 0xdeadbeef; + DdeGetLastError(client_pid); + hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); + ret = DdeGetLastError(client_pid); +todo_wine + ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret); + ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res); + + DdeFreeStringHandle(client_pid, server); + ret = DdeDisconnect(conversation); + ok(ret == FALSE, "Expected FALSE, got %d\n", ret); + + ret = DdeUninitialize(client_pid); + ok(ret == TRUE, "Expected TRUE, got %d\n", ret); +} + static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage) { static const WCHAR dde_string[] = {'D','D','E',' ','S','t','r','i','n','g',0}; @@ -2104,6 +2135,8 @@ START_TEST(dde) return; } + test_initialisation(); + ZeroMemory(&startup, sizeof(STARTUPINFO)); sprintf(buffer, "%s dde ddeml", argv[0]); startup.cb = sizeof(startup); diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c index 130e1813ec9..72fc0a7c37d 100644 --- a/dlls/winealsa.drv/dsoutput.c +++ b/dlls/winealsa.drv/dsoutput.c @@ -548,7 +548,13 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface, } if (state == SND_PCM_STATE_RUNNING) { - snd_pcm_uframes_t used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); + snd_pcm_sframes_t used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); + + if (used < 0) + { + snd_pcm_forward(This->pcm, -used); + used = 0; + } if (This->mmap_pos > used) hw_pptr = This->mmap_pos - used; diff --git a/dlls/wineps.drv/type1.c b/dlls/wineps.drv/type1.c index 95534f8a9c0..9fe3b39da0d 100644 --- a/dlls/wineps.drv/type1.c +++ b/dlls/wineps.drv/type1.c @@ -221,6 +221,7 @@ BOOL T1_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, DWORD index, rc.top = t1->emsize; DPtoLP(physDev->hdc, (POINT*)&rc, 2); lf.lfHeight = -abs(rc.top - rc.bottom); + lf.lfWidth = 0; lf.lfOrientation = lf.lfEscapement = 0; unscaled_font = CreateFontIndirectW(&lf); old_font = SelectObject(physDev->hdc, unscaled_font); diff --git a/dlls/winex11.drv/dib.c b/dlls/winex11.drv/dib.c index 93482816587..b2a5b5ab071 100644 --- a/dlls/winex11.drv/dib.c +++ b/dlls/winex11.drv/dib.c @@ -4039,7 +4039,7 @@ INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, bitmap_type = DIB_GetBitmapInfo( (BITMAPINFOHEADER*)info, &width, &tempHeight, &descr.infoBpp, &descr.compression); - if (physDev->depth > 1) + if (physBitmap->pixmap_depth > 1) { GetPaletteEntries( GetCurrentObject( physDev->hdc, OBJ_PAL ), 0, 256, palette ); } diff --git a/dlls/winmm/mci.c b/dlls/winmm/mci.c index 411d28e0a1e..0053619352f 100644 --- a/dlls/winmm/mci.c +++ b/dlls/winmm/mci.c @@ -898,9 +898,7 @@ static DWORD MCI_LoadMciDriver(LPCWSTR _strDevTyp, LPWINE_MCIDRIVER* lpwmd) if (strcmpiW(strDevTyp, wszAll) == 0) { dwRet = MCIERR_CANNOT_USE_ALL; } else { - FIXME("Couldn't load driver for type %s.\n" - "If you don't have a windows installation accessible from Wine,\n" - "you perhaps forgot to create a [mci] section in system.ini\n", + FIXME("Couldn't load driver for type %s.\n", debugstr_w(strDevTyp)); dwRet = MCIERR_DEVICE_NOT_INSTALLED; } diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 8c37a181f31..389fff86350 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -1441,6 +1441,24 @@ UINT WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE); } +/************************************************************************** + * midiConnect [WINMM.@] + */ +MMRESULT WINAPI midiConnect(HMIDI hMidi, HMIDIOUT hmo, LPVOID pReserved) +{ + FIXME("(%p, %p, %p): Stub\n", hMidi, hmo, pReserved); + return MMSYSERR_ERROR; +} + +/************************************************************************** + * midiDisconnect [WINMM.@] + */ +MMRESULT WINAPI midiDisconnect(HMIDI hMidi, HMIDIOUT hmo, LPVOID pReserved) +{ + FIXME("(%p, %p, %p): Stub\n", hMidi, hmo, pReserved); + return MMSYSERR_ERROR; +} + typedef struct WINE_MIDIStream { HMIDIOUT hDevice; HANDLE hThread; diff --git a/dlls/winmm/winmm.spec b/dlls/winmm/winmm.spec index 9e216f35610..b4043c9130b 100644 --- a/dlls/winmm/winmm.spec +++ b/dlls/winmm/winmm.spec @@ -56,8 +56,8 @@ @ stdcall mciSendStringW(wstr ptr long long) @ stdcall mciSetDriverData(long long) @ stdcall mciSetYieldProc(long ptr long) -@ stub midiConnect -@ stub midiDisconnect +@ stdcall midiConnect(long long ptr) +@ stdcall midiDisconnect(long long ptr) @ stdcall midiInAddBuffer(long ptr long) @ stdcall midiInClose(long) @ stdcall midiInGetDevCapsA(long ptr long) diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index ed88096b9d5..3fc76572f84 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -166,6 +166,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics*, GDIPCONST WCHAR*, GpRegion**); GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics*,HDC); +GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics*); GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics*,GraphicsState); GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics*,REAL,GpMatrixOrder); GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics*,GraphicsState*); @@ -328,11 +329,13 @@ GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator*,INT*,GpPointF*,BYTE*, INT,INT); GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator*,INT*,INT*,INT*); GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator*,INT*,INT*,INT*,BOOL*); +GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator*,INT*,GpPath*,BOOL*); GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator*); GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator*,INT*); GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator*,INT*); GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator*,INT*,GpPointF*,BYTE*,INT); GpStatus WINGDIPAPI GdipPathIterHasCurve(GpPathIterator*,BOOL*); +GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator*,BOOL*); GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap*,GpCustomLineCap**); GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath*,GpPath*,GpLineCap,REAL, diff --git a/include/rpcdce.h b/include/rpcdce.h index 6bc656121d0..8c10233d9bd 100644 --- a/include/rpcdce.h +++ b/include/rpcdce.h @@ -329,7 +329,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ); RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding ); -#define RpcBindingFromStringBinding WINELIB_NAME_AW(RpcBindingFromStringBinding) +#define RpcBindingToStringBinding WINELIB_NAME_AW(RpcBindingToStringBinding) RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ); diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl index 65dfb6279ea..7e5a0a68418 100644 --- a/include/wine/svcctl.idl +++ b/include/wine/svcctl.idl @@ -63,9 +63,6 @@ interface svcctl /* undocumented access rights */ cpp_quote("#define SERVICE_SET_STATUS 0x8000") - /* undocumented access rights */ - cpp_quote("#define SERVICE_SET_STATUS 0x8000") - cpp_quote("#if 0 /* already defined in winsvc.h */") typedef struct _QUERY_SERVICE_CONFIGW { DWORD dwServiceType; diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h index 7f0b6408ba1..4c26c9b5e1d 100644 --- a/include/wine/wined3d_gl.h +++ b/include/wine/wined3d_gl.h @@ -3401,299 +3401,299 @@ typedef enum _GL_SupportedExt { #define GL_EXT_FUNCS_GEN \ /** ARB Extensions **/ \ /* GL_ARB_color_buffer_float */ \ - USE_GL_FUNC(PGLFNCLAMPCOLORARBPROC, glClampColorARB, ARB_COLOR_BUFFER_FLOAT, NULL );\ + USE_GL_FUNC(PGLFNCLAMPCOLORARBPROC, glClampColorARB, ARB_COLOR_BUFFER_FLOAT, NULL )\ /* GL_ARB_draw_buffers */ \ - USE_GL_FUNC(PGLFNDRAWBUFFERSARBPROC, glDrawBuffersARB, ARB_DRAW_BUFFERS, NULL );\ + USE_GL_FUNC(PGLFNDRAWBUFFERSARBPROC, glDrawBuffersARB, ARB_DRAW_BUFFERS, NULL )\ /* GL_ARB_imaging, GL_EXT_blend_minmax */ \ - USE_GL_FUNC(PGLFNBLENDCOLORPROC, glBlendColorEXT, EXT_BLEND_COLOR, NULL );\ - USE_GL_FUNC(PGLFNBLENDEQUATIONPROC, glBlendEquationEXT, EXT_BLEND_MINMAX, NULL );\ + USE_GL_FUNC(PGLFNBLENDCOLORPROC, glBlendColorEXT, EXT_BLEND_COLOR, NULL )\ + USE_GL_FUNC(PGLFNBLENDEQUATIONPROC, glBlendEquationEXT, EXT_BLEND_MINMAX, NULL )\ /* GL_ARB_multisample */ \ - USE_GL_FUNC(WINED3D_PFNGLSAMPLECOVERAGEARBPROC, glSampleCoverageARB, ARB_MULTISAMPLE, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLSAMPLECOVERAGEARBPROC, glSampleCoverageARB, ARB_MULTISAMPLE, NULL )\ /* GL_ARB_multitexture */ \ - USE_GL_FUNC(WINED3D_PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCLIENTACTIVETEXTUREARBPROC, glClientActiveTextureARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD1FARBPROC, glMultiTexCoord1fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD2FARBPROC, glMultiTexCoord2fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD3FARBPROC, glMultiTexCoord3fARB, ARB_MULTITEXTURE, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD4FARBPROC, glMultiTexCoord4fARB, ARB_MULTITEXTURE, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCLIENTACTIVETEXTUREARBPROC, glClientActiveTextureARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD1FARBPROC, glMultiTexCoord1fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD2FARBPROC, glMultiTexCoord2fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD3FARBPROC, glMultiTexCoord3fARB, ARB_MULTITEXTURE, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLMULTITEXCOORD4FARBPROC, glMultiTexCoord4fARB, ARB_MULTITEXTURE, NULL )\ /* GL_ARB_occlusion_query */ \ - USE_GL_FUNC(PGLFNGENQUERIESARBPROC, glGenQueriesARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNDELETEQUERIESARBPROC, glDeleteQueriesARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNBEGINQUERYARBPROC, glBeginQueryARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNENDQUERYARBPROC, glEndQueryARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB, ARB_OCCLUSION_QUERY, NULL );\ - USE_GL_FUNC(PGLFNGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB, ARB_OCCLUSION_QUERY, NULL );\ + USE_GL_FUNC(PGLFNGENQUERIESARBPROC, glGenQueriesARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNDELETEQUERIESARBPROC, glDeleteQueriesARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNBEGINQUERYARBPROC, glBeginQueryARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNENDQUERYARBPROC, glEndQueryARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNGETQUERYOBJECTIVARBPROC, glGetQueryObjectivARB, ARB_OCCLUSION_QUERY, NULL )\ + USE_GL_FUNC(PGLFNGETQUERYOBJECTUIVARBPROC, glGetQueryObjectuivARB, ARB_OCCLUSION_QUERY, NULL )\ /* GL_ARB_point_parameters */ \ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFARBPROC, glPointParameterfARB, ARB_POINT_PARAMETERS, NULL );\ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVARBPROC, glPointParameterfvARB, ARB_POINT_PARAMETERS, NULL );\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFARBPROC, glPointParameterfARB, ARB_POINT_PARAMETERS, NULL )\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVARBPROC, glPointParameterfvARB, ARB_POINT_PARAMETERS, NULL )\ /* GL_ARB_texture_compression */ \ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3DARB, ARB_TEXTURE_COMPRESSION,NULL );\ - USE_GL_FUNC(PGLFNGETCOMPRESSEDTEXIMAGEPROC, glGetCompressedTexImageARB, ARB_TEXTURE_COMPRESSION,NULL );\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3DARB, ARB_TEXTURE_COMPRESSION,NULL )\ + USE_GL_FUNC(PGLFNGETCOMPRESSEDTEXIMAGEPROC, glGetCompressedTexImageARB, ARB_TEXTURE_COMPRESSION,NULL )\ /* GL_ARB_vertex_blend */ \ - USE_GL_FUNC(PGLFNGLWEIGHTPOINTERARB, glWeightPointerARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTBV, glWeightbvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTSV, glWeightsvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTIV, glWeightivARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTFV, glWeightfvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTDV, glWeightdvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUBV, glWeightubvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUSV, glWeightusvARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLWEIGHTUIV, glWeightuivARB, ARB_VERTEX_BLEND, NULL );\ - USE_GL_FUNC(PGLFNGLVERTEXBLENDARB, glVertexBlendARB, ARB_VERTEX_BLEND, NULL );\ + USE_GL_FUNC(PGLFNGLWEIGHTPOINTERARB, glWeightPointerARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTBV, glWeightbvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTSV, glWeightsvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTIV, glWeightivARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTFV, glWeightfvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTDV, glWeightdvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUBV, glWeightubvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUSV, glWeightusvARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLWEIGHTUIV, glWeightuivARB, ARB_VERTEX_BLEND, NULL )\ + USE_GL_FUNC(PGLFNGLVERTEXBLENDARB, glVertexBlendARB, ARB_VERTEX_BLEND, NULL )\ /* GL_ARB_vertex_buffer_object */ \ - USE_GL_FUNC(PGLFNBINDBUFFERARBPROC, glBindBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNDELETEBUFFERSARBPROC, glDeleteBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGENBUFFERSARBPROC, glGenBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNISBUFFERARBPROC, glIsBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNBUFFERDATAARBPROC, glBufferDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNBUFFERSUBDATAARBPROC, glBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERSUBDATAARBPROC, glGetBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNMAPBUFFERARBPROC, glMapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNUNMAPBUFFERARBPROC, glUnmapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERPARAMETERIVARBPROC, glGetBufferParameterivARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ - USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC, glGetBufferPointervARB, ARB_VERTEX_BUFFER_OBJECT,NULL);\ + USE_GL_FUNC(PGLFNBINDBUFFERARBPROC, glBindBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNDELETEBUFFERSARBPROC, glDeleteBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGENBUFFERSARBPROC, glGenBuffersARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNISBUFFERARBPROC, glIsBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNBUFFERDATAARBPROC, glBufferDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNBUFFERSUBDATAARBPROC, glBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERSUBDATAARBPROC, glGetBufferSubDataARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNMAPBUFFERARBPROC, glMapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNUNMAPBUFFERARBPROC, glUnmapBufferARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERPARAMETERIVARBPROC, glGetBufferParameterivARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ + USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC, glGetBufferPointervARB, ARB_VERTEX_BUFFER_OBJECT,NULL)\ /** EXT Extensions **/ \ /* GL_EXT_blend_equation_separate */ \ - USE_GL_FUNC(PGLFNBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT, EXT_BLEND_FUNC_SEPARATE, NULL);\ + USE_GL_FUNC(PGLFNBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT, EXT_BLEND_FUNC_SEPARATE, NULL)\ /* GL_EXT_blend_func_separate */ \ - USE_GL_FUNC(PGLFNBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT, EXT_BLEND_EQUATION_SEPARATE, NULL);\ + USE_GL_FUNC(PGLFNBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT, EXT_BLEND_EQUATION_SEPARATE, NULL)\ /* GL_EXT_fog_coord */ \ - USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT, EXT_FOG_COORD, NULL );\ - USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT, EXT_FOG_COORD, NULL );\ + USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT, EXT_FOG_COORD, NULL )\ + USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT, EXT_FOG_COORD, NULL )\ /* GL_EXT_framebuffer_object */ \ - USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLISFRAMEBUFFEREXTPROC, glIsFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE1DEXTPROC, glFramebufferTexture1DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE3DEXTPROC, glFramebufferTexture3DEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGENERATEMIPMAPEXTPROC, glGenerateMipmapEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGETRENDERBUFFERPARAMETERIVEXTPROC, glGetRenderbufferParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ - USE_GL_FUNC(PGLFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC, glGetFramebufferAttachmentParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL );\ + USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLISFRAMEBUFFEREXTPROC, glIsFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE1DEXTPROC, glFramebufferTexture1DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERTEXTURE3DEXTPROC, glFramebufferTexture3DEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGENERATEMIPMAPEXTPROC, glGenerateMipmapEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGETRENDERBUFFERPARAMETERIVEXTPROC, glGetRenderbufferParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ + USE_GL_FUNC(PGLFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC, glGetFramebufferAttachmentParameterivEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\ /* GL_EXT_framebuffer_blit */ \ - USE_GL_FUNC(PGLFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT, EXT_FRAMEBUFFER_BLIT, NULL );\ + USE_GL_FUNC(PGLFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT, EXT_FRAMEBUFFER_BLIT, NULL )\ /* GL_EXT_paletted_texture */ \ - USE_GL_FUNC(PGLFNGLCOLORTABLEEXTPROC, glColorTableEXT, EXT_PALETTED_TEXTURE, NULL );\ + USE_GL_FUNC(PGLFNGLCOLORTABLEEXTPROC, glColorTableEXT, EXT_PALETTED_TEXTURE, NULL )\ /* GL_EXT_point_parameters */ \ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC, glPointParameterfEXT, EXT_POINT_PARAMETERS, NULL );\ - USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC, glPointParameterfvEXT, EXT_POINT_PARAMETERS, NULL );\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC, glPointParameterfEXT, EXT_POINT_PARAMETERS, NULL )\ + USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC, glPointParameterfvEXT, EXT_POINT_PARAMETERS, NULL )\ /* GL_EXT_secondary_color */ \ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC, glSecondaryColor3ubEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC, glSecondaryColor3fEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC, glSecondaryColor3fvEXT, EXT_SECONDARY_COLOR, NULL );\ - USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT, EXT_SECONDARY_COLOR, NULL );\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC, glSecondaryColor3ubEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC, glSecondaryColor3fEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC, glSecondaryColor3fvEXT, EXT_SECONDARY_COLOR, NULL )\ + USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT, EXT_SECONDARY_COLOR, NULL )\ /* GL_EXT_texture3D */ \ - USE_GL_FUNC(PGLFNGLTEXIMAGE3DEXTPROC, glTexImage3DEXT, EXT_TEXTURE3D, glTexImage3D);\ - USE_GL_FUNC(PGLFNGLTEXSUBIMAGE3DEXTPROC, glTexSubImage3DEXT, EXT_TEXTURE3D, glTexSubImage3D);\ + USE_GL_FUNC(PGLFNGLTEXIMAGE3DEXTPROC, glTexImage3DEXT, EXT_TEXTURE3D, glTexImage3D)\ + USE_GL_FUNC(PGLFNGLTEXSUBIMAGE3DEXTPROC, glTexSubImage3DEXT, EXT_TEXTURE3D, glTexSubImage3D)\ /* GL_ARB_vertex_program */ \ - USE_GL_FUNC(PGLFNGENPROGRAMSARBPROC, glGenProgramsARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNBINDPROGRAMARBPROC, glBindProgramARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNPROGRAMSTRINGARBPROC, glProgramStringARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNDELETEPROGRAMSARBPROC, glDeleteProgramsARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETER4FVARBPROC, glProgramLocalParameter4fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1DARBPROC, glVertexAttrib1dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1DVARBPROC, glVertexAttrib1dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1FARBPROC, glVertexAttrib1fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1FVARBPROC, glVertexAttrib1fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1SARBPROC, glVertexAttrib1sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1SVARBPROC, glVertexAttrib1svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2DARBPROC, glVertexAttrib2dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2DVARBPROC, glVertexAttrib2dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2FARBPROC, glVertexAttrib2fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2FVARBPROC, glVertexAttrib2fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2SARBPROC, glVertexAttrib2sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2SVARBPROC, glVertexAttrib2svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3DARBPROC, glVertexAttrib3dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3DVARBPROC, glVertexAttrib3dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3FARBPROC, glVertexAttrib3fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3FVARBPROC, glVertexAttrib3fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3SARBPROC, glVertexAttrib3sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3SVARBPROC, glVertexAttrib3svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NBVARBPROC, glVertexAttrib4NbvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NIVARBPROC, glVertexAttrib4NivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NSVARBPROC, glVertexAttrib4NsvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBARBPROC, glVertexAttrib4NubARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBVARBPROC, glVertexAttrib4NubvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUIVARBPROC, glVertexAttrib4NuivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4NUSVARBPROC, glVertexAttrib4NusvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4BVARBPROC, glVertexAttrib4bvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4DARBPROC, glVertexAttrib4dARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4DVARBPROC, glVertexAttrib4dvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4FARBPROC, glVertexAttrib4fARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4FVARBPROC, glVertexAttrib4fvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4IVARBPROC, glVertexAttrib4ivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4SARBPROC, glVertexAttrib4sARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4SVARBPROC, glVertexAttrib4svARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4UBVARBPROC, glVertexAttrib4ubvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4UIVARBPROC, glVertexAttrib4uivARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4USVARBPROC, glVertexAttrib4usvARB, ARB_VERTEX_PROGRAM, NULL );\ - USE_GL_FUNC(PGLFNGETPROGRAMIVARBPROC, glGetProgramivARB, ARB_VERTEX_PROGRAM, NULL );\ + USE_GL_FUNC(PGLFNGENPROGRAMSARBPROC, glGenProgramsARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNBINDPROGRAMARBPROC, glBindProgramARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMSTRINGARBPROC, glProgramStringARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNDELETEPROGRAMSARBPROC, glDeleteProgramsARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETER4FVARBPROC, glProgramLocalParameter4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1DARBPROC, glVertexAttrib1dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1DVARBPROC, glVertexAttrib1dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1FARBPROC, glVertexAttrib1fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1FVARBPROC, glVertexAttrib1fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1SARBPROC, glVertexAttrib1sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1SVARBPROC, glVertexAttrib1svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2DARBPROC, glVertexAttrib2dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2DVARBPROC, glVertexAttrib2dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2FARBPROC, glVertexAttrib2fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2FVARBPROC, glVertexAttrib2fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2SARBPROC, glVertexAttrib2sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2SVARBPROC, glVertexAttrib2svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3DARBPROC, glVertexAttrib3dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3DVARBPROC, glVertexAttrib3dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3FARBPROC, glVertexAttrib3fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3FVARBPROC, glVertexAttrib3fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3SARBPROC, glVertexAttrib3sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3SVARBPROC, glVertexAttrib3svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NBVARBPROC, glVertexAttrib4NbvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NIVARBPROC, glVertexAttrib4NivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NSVARBPROC, glVertexAttrib4NsvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBARBPROC, glVertexAttrib4NubARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUBVARBPROC, glVertexAttrib4NubvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUIVARBPROC, glVertexAttrib4NuivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4NUSVARBPROC, glVertexAttrib4NusvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4BVARBPROC, glVertexAttrib4bvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4DARBPROC, glVertexAttrib4dARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4DVARBPROC, glVertexAttrib4dvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4FARBPROC, glVertexAttrib4fARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4FVARBPROC, glVertexAttrib4fvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4IVARBPROC, glVertexAttrib4ivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4SARBPROC, glVertexAttrib4sARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4SVARBPROC, glVertexAttrib4svARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4UBVARBPROC, glVertexAttrib4ubvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4UIVARBPROC, glVertexAttrib4uivARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4USVARBPROC, glVertexAttrib4usvARB, ARB_VERTEX_PROGRAM, NULL )\ + USE_GL_FUNC(PGLFNGETPROGRAMIVARBPROC, glGetProgramivARB, ARB_VERTEX_PROGRAM, NULL )\ /* GL_ARB_shader_objects */ \ - USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERFVARBPROC, glGetObjectParameterfvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETACTIVEUNIFORMARBPROC, glGetActiveUniformARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IARBPROC, glUniform2iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IARBPROC, glUniform3iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IARBPROC, glUniform4iARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IVARBPROC, glUniform4ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX2FVARBPROC, glUniformMatrix2fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX3FVARBPROC, glUniformMatrix3fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX4FVARBPROC, glUniformMatrix4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniform4fvARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniform4ivARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETINFOLOGARBPROC, glGetInfoLogARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLSHADERSOURCEARBPROC, glShaderSourceARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCOMPILESHADERARBPROC, glCompileShaderARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLATTACHOBJECTARBPROC, glAttachObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLLINKPROGRAMARBPROC, glLinkProgramARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLDETACHOBJECTARBPROC, glDetachObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLDELETEOBJECTARBPROC, glDeleteObjectARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLVALIDATEPROGRAMARBPROC, glValidateProgramARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETATTACHEDOBJECTSARBPROC, glGetAttachedObjectsARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETHANDLEARBPROC, glGetHandleARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETSHADERSOURCEARBPROC, glGetShaderSourceARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLBINDATTRIBLOCATIONARBPROC, glBindAttribLocationARB, ARB_SHADER_OBJECTS, NULL );\ - USE_GL_FUNC(WINED3D_PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocationARB, ARB_SHADER_OBJECTS, NULL );\ + USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETOBJECTPARAMETERFVARBPROC, glGetObjectParameterfvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETACTIVEUNIFORMARBPROC, glGetActiveUniformARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IARBPROC, glUniform2iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IARBPROC, glUniform3iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IARBPROC, glUniform4iARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IARBPROC, glUniform1fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORM4IVARBPROC, glUniform4ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX2FVARBPROC, glUniformMatrix2fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX3FVARBPROC, glUniformMatrix3fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX4FVARBPROC, glUniformMatrix4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniform4fvARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniform4ivARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETINFOLOGARBPROC, glGetInfoLogARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLSHADERSOURCEARBPROC, glShaderSourceARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCOMPILESHADERARBPROC, glCompileShaderARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLATTACHOBJECTARBPROC, glAttachObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLLINKPROGRAMARBPROC, glLinkProgramARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLDETACHOBJECTARBPROC, glDetachObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLDELETEOBJECTARBPROC, glDeleteObjectARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLVALIDATEPROGRAMARBPROC, glValidateProgramARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETATTACHEDOBJECTSARBPROC, glGetAttachedObjectsARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETHANDLEARBPROC, glGetHandleARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETSHADERSOURCEARBPROC, glGetShaderSourceARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLBINDATTRIBLOCATIONARBPROC, glBindAttribLocationARB, ARB_SHADER_OBJECTS, NULL )\ + USE_GL_FUNC(WINED3D_PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocationARB, ARB_SHADER_OBJECTS, NULL )\ /* GL_EXT_stencil_two_side */ \ - USE_GL_FUNC(PGLFNACTIVESTENCILFACEEXTPROC, glActiveStencilFaceEXT, EXT_STENCIL_TWO_SIDE, NULL );\ + USE_GL_FUNC(PGLFNACTIVESTENCILFACEEXTPROC, glActiveStencilFaceEXT, EXT_STENCIL_TWO_SIDE, NULL )\ /* GL_ATI_separate_stencil */ \ - USE_GL_FUNC(PGLFNSTENCILOPSEPARATEATIPROC, glStencilOpSeparateATI, ATI_SEPARATE_STENCIL, NULL );\ - USE_GL_FUNC(PGLFNSTENCILFUNCSEPARATEATIPROC, glStencilFuncSeparateATI, ATI_SEPARATE_STENCIL, NULL );\ + USE_GL_FUNC(PGLFNSTENCILOPSEPARATEATIPROC, glStencilOpSeparateATI, ATI_SEPARATE_STENCIL, NULL )\ + USE_GL_FUNC(PGLFNSTENCILFUNCSEPARATEATIPROC, glStencilFuncSeparateATI, ATI_SEPARATE_STENCIL, NULL )\ /* GL_NV_half_float */ \ - USE_GL_FUNC(PGLFNVERTEX2HNVPROC, glVertex2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX2HVNVPROC, glVertex2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX3HNVPROC, glVertex3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX3HVNVPROC, glVertex3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX4HNVPROC, glVertex4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEX4HVNVPROC, glVertex4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNNORMAL3HNVPROC, glNormal3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNNORMAL3HVNVPROC, glNormal3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR3HNVPROC, glColor3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR3HVNVPROC, glColor3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR4HNVPROC, glColor4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNCOLOR4HVNVPROC, glColor4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD1HNVPROC, glTexCoord1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD1HVNVPROC, glTexCoord1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD2HNVPROC, glTexCoord2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD2HVNVPROC, glTexCoord2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD3HNVPROC, glTexCoord3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD3HVNVPROC, glTexCoord3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD4HNVPROC, glTexCoord4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNTEXCOORD4HVNVPROC, glTexCoord4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD1HNVPROC, glMultiTexCoord1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD1HVNVPROC, glMultiTexCoord1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD2HNVPROC, glMultiTexCoord2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD2HVNVPROC, glMultiTexCoord2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD3HNVPROC, glMultiTexCoord3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD3HVNVPROC, glMultiTexCoord3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD4HNVPROC, glMultiTexCoord4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNMULTITEXCOORD4HVNVPROC, glMultiTexCoord4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNFOGCOORDHNVPROC, glFogCoordhNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNFOGCOORDHVNVPROC, glFogCoordhvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNSECONDARYCOLOR3HNVPROC, glSecondaryColor3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNSECONDARYCOLOR3HVNVPROC, glSecondaryColor3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXWEIGHTHNVPROC, glVertexWeighthNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXWEIGHTHVNVPROC, glVertexWeighthvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1HNVPROC, glVertexAttrib1hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB1HVNVPROC, glVertexAttrib1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2HNVPROC, glVertexAttrib2hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB2HVNVPROC, glVertexAttrib2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3HNVPROC, glVertexAttrib3hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB3HVNVPROC, glVertexAttrib3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4HNVPROC, glVertexAttrib4hNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIB4HVNVPROC, glVertexAttrib4hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS1HVNVPROC, glVertexAttribs1hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS2HVNVPROC, glVertexAttribs2hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS3HVNVPROC, glVertexAttribs3hvNV, NV_HALF_FLOAT, NULL );\ - USE_GL_FUNC(PGLFNVERTEXATTRIBS4HVNVPROC, glVertexAttribs4hvNV, NV_HALF_FLOAT, NULL );\ + USE_GL_FUNC(PGLFNVERTEX2HNVPROC, glVertex2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX2HVNVPROC, glVertex2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX3HNVPROC, glVertex3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX3HVNVPROC, glVertex3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX4HNVPROC, glVertex4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEX4HVNVPROC, glVertex4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNNORMAL3HNVPROC, glNormal3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNNORMAL3HVNVPROC, glNormal3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR3HNVPROC, glColor3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR3HVNVPROC, glColor3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR4HNVPROC, glColor4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNCOLOR4HVNVPROC, glColor4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD1HNVPROC, glTexCoord1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD1HVNVPROC, glTexCoord1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD2HNVPROC, glTexCoord2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD2HVNVPROC, glTexCoord2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD3HNVPROC, glTexCoord3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD3HVNVPROC, glTexCoord3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD4HNVPROC, glTexCoord4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNTEXCOORD4HVNVPROC, glTexCoord4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD1HNVPROC, glMultiTexCoord1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD1HVNVPROC, glMultiTexCoord1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD2HNVPROC, glMultiTexCoord2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD2HVNVPROC, glMultiTexCoord2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD3HNVPROC, glMultiTexCoord3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD3HVNVPROC, glMultiTexCoord3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD4HNVPROC, glMultiTexCoord4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNMULTITEXCOORD4HVNVPROC, glMultiTexCoord4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNFOGCOORDHNVPROC, glFogCoordhNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNFOGCOORDHVNVPROC, glFogCoordhvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNSECONDARYCOLOR3HNVPROC, glSecondaryColor3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNSECONDARYCOLOR3HVNVPROC, glSecondaryColor3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXWEIGHTHNVPROC, glVertexWeighthNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXWEIGHTHVNVPROC, glVertexWeighthvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1HNVPROC, glVertexAttrib1hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB1HVNVPROC, glVertexAttrib1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2HNVPROC, glVertexAttrib2hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB2HVNVPROC, glVertexAttrib2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3HNVPROC, glVertexAttrib3hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB3HVNVPROC, glVertexAttrib3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4HNVPROC, glVertexAttrib4hNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIB4HVNVPROC, glVertexAttrib4hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS1HVNVPROC, glVertexAttribs1hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS2HVNVPROC, glVertexAttribs2hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS3HVNVPROC, glVertexAttribs3hvNV, NV_HALF_FLOAT, NULL )\ + USE_GL_FUNC(PGLFNVERTEXATTRIBS4HVNVPROC, glVertexAttribs4hvNV, NV_HALF_FLOAT, NULL )\ /* GL_NV_register_combiners */ \ - USE_GL_FUNC(PGLFNCOMBINERINPUTNVPROC, glCombinerInputNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINEROUTPUTNVPROC, glCombinerOutputNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERFNVPROC, glCombinerParameterfNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERFVNVPROC, glCombinerParameterfvNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERINVPROC, glCombinerParameteriNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNCOMBINERPARAMETERIVNVPROC, glCombinerParameterivNV, NV_REGISTER_COMBINERS, NULL );\ - USE_GL_FUNC(PGLFNFINALCOMBINERINPUTNVPROC, glFinalCombinerInputNV, NV_REGISTER_COMBINERS, NULL );\ + USE_GL_FUNC(PGLFNCOMBINERINPUTNVPROC, glCombinerInputNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINEROUTPUTNVPROC, glCombinerOutputNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERFNVPROC, glCombinerParameterfNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERFVNVPROC, glCombinerParameterfvNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERINVPROC, glCombinerParameteriNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNCOMBINERPARAMETERIVNVPROC, glCombinerParameterivNV, NV_REGISTER_COMBINERS, NULL )\ + USE_GL_FUNC(PGLFNFINALCOMBINERINPUTNVPROC, glFinalCombinerInputNV, NV_REGISTER_COMBINERS, NULL )\ /* GL_NV_fence */ \ - USE_GL_FUNC(PGLFNGENFENCESNVPROC, glGenFencesNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNDELETEFENCESNVPROC, glDeleteFencesNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNSETFENCENVPROC, glSetFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTFENCENVPROC, glTestFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHFENCENVPROC, glFinishFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNISFENCENVPROC, glIsFenceNV, NV_FENCE, NULL );\ - USE_GL_FUNC(PGLFNGETFENCEIVNVPROC, glGetFenceivNV, NV_FENCE, NULL );\ + USE_GL_FUNC(PGLFNGENFENCESNVPROC, glGenFencesNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNDELETEFENCESNVPROC, glDeleteFencesNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNSETFENCENVPROC, glSetFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTFENCENVPROC, glTestFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHFENCENVPROC, glFinishFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNISFENCENVPROC, glIsFenceNV, NV_FENCE, NULL )\ + USE_GL_FUNC(PGLFNGETFENCEIVNVPROC, glGetFenceivNV, NV_FENCE, NULL )\ /* GL_APPLE_fence */ \ - USE_GL_FUNC(PGLFNGENFENCESAPPLEPROC, glGenFencesAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNDELETEFENCESAPPLEPROC, glDeleteFencesAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNSETFENCEAPPLEPROC, glSetFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTFENCEAPPLEPROC, glTestFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHFENCEAPPLEPROC, glFinishFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNISFENCEAPPLEPROC, glIsFenceAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNTESTOBJECTAPPLEPROC, glTestObjectAPPLE, APPLE_FENCE, NULL );\ - USE_GL_FUNC(PGLFNFINISHOBJECTAPPLEPROC, glFinishObjectAPPLE, APPLE_FENCE, NULL );\ + USE_GL_FUNC(PGLFNGENFENCESAPPLEPROC, glGenFencesAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNDELETEFENCESAPPLEPROC, glDeleteFencesAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNSETFENCEAPPLEPROC, glSetFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTFENCEAPPLEPROC, glTestFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHFENCEAPPLEPROC, glFinishFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNISFENCEAPPLEPROC, glIsFenceAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNTESTOBJECTAPPLEPROC, glTestObjectAPPLE, APPLE_FENCE, NULL )\ + USE_GL_FUNC(PGLFNFINISHOBJECTAPPLEPROC, glFinishObjectAPPLE, APPLE_FENCE, NULL )\ /* GL_ATI_envmap_bumpmap */ \ - USE_GL_FUNC(PGLFNTEXBUMPPARAMETERIVATIPROC, glTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNTEXBUMPPARAMETERFVATIPROC, glTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERIVATIPROC, glGetTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL );\ - USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERFVATIPROC, glGetTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL );\ + USE_GL_FUNC(PGLFNTEXBUMPPARAMETERIVATIPROC, glTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNTEXBUMPPARAMETERFVATIPROC, glTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERIVATIPROC, glGetTexBumpParameterivATI, ATI_ENVMAP_BUMPMAP, NULL )\ + USE_GL_FUNC(PGLFNGETTEXBUMPPARAMETERFVATIPROC, glGetTexBumpParameterfvATI, ATI_ENVMAP_BUMPMAP, NULL )\ /* GLX_SGI_video_sync */ \ - USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI, SGI_VIDEO_SYNC, NULL );\ - USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI, SGI_VIDEO_SYNC, NULL );\ + USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\ + USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\ /* GL_APPLE_flush_render */ \ - USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderApple, APPLE_FLUSH_RENDER, NULL );\ - USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderApple, APPLE_FLUSH_RENDER, NULL );\ + USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderApple, APPLE_FLUSH_RENDER, NULL )\ + USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderApple, APPLE_FLUSH_RENDER, NULL )\ /* GL_EXT_gpu_program_parameters */ \ - USE_GL_FUNC(PGLFNPROGRAMENVPARAMETERS4FVEXTPROC, glProgramEnvParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL );\ - USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETERS4FVEXTPROC, glProgramLocalParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL );\ + USE_GL_FUNC(PGLFNPROGRAMENVPARAMETERS4FVEXTPROC, glProgramEnvParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\ + USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETERS4FVEXTPROC, glProgramLocalParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\ /* GL_ATI_fragment_shader */ \ - USE_GL_FUNC(PGLFNGENFRAGMENTSHADERSATI, glGenFragmentShadersATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNBINDFRAGMENTSHADERATI, glBindFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNDELETEFRAGMENTSHADERATI, glDeleteFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNBEGINFRAGMENTSHADERATI, glBeginFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNENDFRAGMENTSHADERATI, glEndFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNPASSTEXCOORDATI, glPassTexCoordATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNSAMPLEMAPATI, glSampleMapATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNCOLORFRAGMENTOP1ATI, glColorFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNCOLORFRAGMENTOP2ATI, glColorFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNCOLORFRAGMENTOP3ATI, glColorFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNALPHAFRAGMENTOP1ATI, glAlphaFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNALPHAFRAGMENTOP2ATI, glAlphaFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNALPHAFRAGMENTOP3ATI, glAlphaFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL );\ - USE_GL_FUNC(PGLFNSETFRAGMENTSHADERCONSTANTATI, glSetFragmentShaderConstantATI, ATI_FRAGMENT_SHADER, NULL ); + USE_GL_FUNC(PGLFNGENFRAGMENTSHADERSATI, glGenFragmentShadersATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNBINDFRAGMENTSHADERATI, glBindFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNDELETEFRAGMENTSHADERATI, glDeleteFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNBEGINFRAGMENTSHADERATI, glBeginFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNENDFRAGMENTSHADERATI, glEndFragmentShaderATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNPASSTEXCOORDATI, glPassTexCoordATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNSAMPLEMAPATI, glSampleMapATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP1ATI, glColorFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP2ATI, glColorFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNCOLORFRAGMENTOP3ATI, glColorFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP1ATI, glAlphaFragmentOp1ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP2ATI, glAlphaFragmentOp2ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNALPHAFRAGMENTOP3ATI, glAlphaFragmentOp3ATI, ATI_FRAGMENT_SHADER, NULL )\ + USE_GL_FUNC(PGLFNSETFRAGMENTSHADERCONSTANTATI, glSetFragmentShaderConstantATI, ATI_FRAGMENT_SHADER, NULL ) /**************************************************** * OpenGL WGL defines and functions pointer @@ -3791,18 +3791,18 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, typedef BOOL (WINAPI * WINED3D_PFNWGLSETPIXELFORMATWINE) (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR* ppfd); #define WGL_EXT_FUNCS_GEN \ - USE_GL_FUNC(WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBFVARBPROC, wglGetPixelFormatAttribfvARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLMAKECONTEXTCURRENTARBPROC, wglMakeContextCurrentARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLGETCURRENTREADDCARBPROC, wglGetCurrentReadDCARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLCREATEPBUFFERARBPROC, wglCreatePbufferARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB, 0, NULL); \ - USE_GL_FUNC(WINED3D_PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB, 0, NULL); \ + USE_GL_FUNC(WINED3D_PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLGETPIXELFORMATATTRIBFVARBPROC, wglGetPixelFormatAttribfvARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLMAKECONTEXTCURRENTARBPROC, wglMakeContextCurrentARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLGETCURRENTREADDCARBPROC, wglGetCurrentReadDCARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLCREATEPBUFFERARBPROC, wglCreatePbufferARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB, 0, NULL) \ + USE_GL_FUNC(WINED3D_PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB, 0, NULL) \ USE_GL_FUNC(WINED3D_PFNWGLQUERYPBUFFERARBPROC, wglQueryPbufferARB, 0, NULL) \ - USE_GL_FUNC(WINED3D_PFNWGLSETPIXELFORMATWINE, wglSetPixelFormatWINE, 0, NULL); + USE_GL_FUNC(WINED3D_PFNWGLSETPIXELFORMATWINE, wglSetPixelFormatWINE, 0, NULL) /**************************************************** @@ -3880,9 +3880,9 @@ typedef struct _WineD3D_GL_Info { BOOL supported[OPENGL_SUPPORTED_EXT_END + 1]; /** OpenGL EXT and ARB functions ptr */ - GL_EXT_FUNCS_GEN; + GL_EXT_FUNCS_GEN /** OpenGL WGL functions ptr */ - WGL_EXT_FUNCS_GEN; + WGL_EXT_FUNCS_GEN GlPixelFormatDesc *gl_formats; diff --git a/programs/rpcss/epmp.c b/programs/rpcss/epmp.c index e731e064272..d7712b9f4ea 100644 --- a/programs/rpcss/epmp.c +++ b/programs/rpcss/epmp.c @@ -120,6 +120,7 @@ void ept_insert(handle_t h, &entry->address); if (rpc_status != RPC_S_OK) { + WINE_WARN("TowerExplode failed %lu\n", rpc_status); *status = rpc_status; break; /* FIXME: more cleanup? */ } diff --git a/programs/rpcss/rpcss_main.c b/programs/rpcss/rpcss_main.c index 1722d5eaebd..c75138e51ed 100644 --- a/programs/rpcss/rpcss_main.c +++ b/programs/rpcss/rpcss_main.c @@ -68,6 +68,8 @@ static BOOL RPCSS_Initialize(void) static unsigned short irot_endpoint[] = IROT_ENDPOINT; static unsigned short epm_protseq[] = {'n','c','a','c','n','_','n','p',0}; static unsigned short epm_endpoint[] = {'\\','p','i','p','e','\\','e','p','m','a','p','p','e','r',0}; + static unsigned short epm_protseq_lrpc[] = {'n','c','a','l','r','p','c',0}; + static unsigned short epm_endpoint_lrpc[] = {'e','p','m','a','p','p','e','r',0}; RPC_STATUS status; WINE_TRACE("\n"); @@ -87,6 +89,11 @@ static BOOL RPCSS_Initialize(void) if (status != RPC_S_OK) goto fail; + status = RpcServerUseProtseqEpW(epm_protseq_lrpc, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + epm_endpoint_lrpc, NULL); + if (status != RPC_S_OK) + goto fail; + status = RpcServerUseProtseqEpW(irot_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, irot_endpoint, NULL); if (status != RPC_S_OK) diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index cd69a9c14ee..b4b04e62e1a 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -597,7 +597,7 @@ void symbol_print_local(const SYMBOL_INFO* sym, ULONG base, if (fill_sym_lvalue(sym, base, &lvalue, buffer, sizeof(buffer))) { - print_value(&lvalue, 'x', 1); + print_value(&lvalue, 0, 1); if (detailed) dbg_printf(" (%s%s)", (sym->Flags & SYMFLAG_PARAMETER) ? "parameter" : "local", diff --git a/programs/winhlp32/hlpfile.c b/programs/winhlp32/hlpfile.c index 7f1a931c12f..05d5347cef0 100644 --- a/programs/winhlp32/hlpfile.c +++ b/programs/winhlp32/hlpfile.c @@ -1290,12 +1290,14 @@ static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE* page, struct RtfData* rd, WINE_TRACE("Changing font to %d\n", font); format += 3; + /* Font size in hlpfile is given in the same units as + rtf control word \fs uses (half-points). */ switch (rd->font_scale) { - case 0: fs = (4 * page->file->fonts[font].LogFont.lfHeight - 13) / 5; break; + case 0: fs = page->file->fonts[font].LogFont.lfHeight - 4; break; default: - case 1: fs = (4 * page->file->fonts[font].LogFont.lfHeight - 3) / 5; break; - case 2: fs = (4 * page->file->fonts[font].LogFont.lfHeight + 17) / 5; break; + case 1: fs = page->file->fonts[font].LogFont.lfHeight; break; + case 2: fs = page->file->fonts[font].LogFont.lfHeight + 4; break; } /* FIXME: missing at least colors, also bold attribute looses information */ diff --git a/tools/widl/parser.y b/tools/widl/parser.y index f1a95d4d794..f6daa0edcb3 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1426,7 +1426,6 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl, { expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS); - int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); int sizeless, has_varconf; expr_t *dim; type_t *atype, **ptype; @@ -1457,13 +1456,15 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl, * pointer_default so we need to fix that up here */ if (!arr) { + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); const type_t *ptr = NULL; /* pointer attributes on the left side of the type belong to the function * pointer, if one is being declared */ type_t **pt = func_type ? &func_type : &v->type; - for (ptr = *pt; ptr; ) + for (ptr = *pt; ptr && !ptr_attr; ) { - if (ptr->kind == TKIND_ALIAS) + ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE); + if (!ptr_attr && ptr->kind == TKIND_ALIAS) ptr = ptr->orig; else break; -- 2.11.4.GIT