From e21b836be3f75d27c232e913f9f359cd9c27ebca Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Thu, 16 Apr 2009 04:05:11 +0200 Subject: [PATCH] push e4fb87785f42653a03d84664d7db014c69dd1260 --- configure | 9 ++ configure.ac | 1 + dlls/amstream/amstream.c | 10 +- dlls/amstream/tests/Makefile.in | 13 +++ dlls/amstream/tests/amstream.c | 91 +++++++++++++++ dlls/comctl32/listview.c | 78 +++++++------ dlls/comctl32/tests/listview.c | 82 ++++++++++++- dlls/msctf/documentmgr.c | 13 ++- dlls/msctf/tests/inputprocessor.c | 238 +++++++++++++++++++++++++++++++++++++- dlls/msctf/threadmgr.c | 10 +- dlls/msi/database.c | 20 +++- dlls/msi/msipriv.h | 1 + dlls/msi/suminfo.c | 225 +++++++++++++++++++++++++++++------ dlls/msvcrt/math.c | 38 +++++- dlls/msvcrt/tests/printf.c | 85 ++++++++++++++ dlls/oleaut32/tests/typelib.c | 5 + dlls/oleaut32/tests/vartest.c | 38 ++++-- dlls/oleaut32/typelib.c | 32 ++++- dlls/oleaut32/variant.c | 14 ++- dlls/oleaut32/variant.h | 3 + dlls/oleaut32/vartype.c | 8 +- dlls/opengl32/wgl.c | 8 +- dlls/quartz/mpegsplit.c | 1 - dlls/secur32/ntlm.c | 14 ++- dlls/secur32/secur32.c | 10 +- dlls/secur32/tests/secur32.c | 38 +++--- dlls/user32/tests/input.c | 14 +++ dlls/user32/tests/win.c | 10 +- dlls/usp10/tests/usp10.c | 6 + dlls/winecoreaudio.drv/audio.c | 212 ++++++++++++++++++++------------- dlls/wined3d/arb_program_shader.c | 49 ++++---- dlls/wined3d/baseshader.c | 1 - dlls/wined3d/directx.c | 80 ++++++++----- dlls/wined3d/glsl_shader.c | 47 ++++---- dlls/wined3d/pixelshader.c | 4 +- dlls/wined3d/vertexshader.c | 5 - dlls/wined3d/wined3d_gl.h | 1 + dlls/wined3d/wined3d_private.h | 5 +- dlls/winex11.drv/keyboard.c | 68 +++++++---- tools/c2man.pl | 22 ++-- 40 files changed, 1259 insertions(+), 350 deletions(-) create mode 100644 dlls/amstream/tests/Makefile.in create mode 100644 dlls/amstream/tests/amstream.c diff --git a/configure b/configure index dabdbb24820..d638dab62fe 100755 --- a/configure +++ b/configure @@ -23099,6 +23099,14 @@ dlls/amstream/Makefile: dlls/amstream/Makefile.in dlls/Makedll.rules" ac_config_files="$ac_config_files dlls/amstream/Makefile" ALL_MAKEFILES="$ALL_MAKEFILES \\ + dlls/amstream/tests/Makefile" +test "x$enable_tests" != xno && ALL_TEST_DIRS="$ALL_TEST_DIRS \\ + amstream/tests" +ALL_MAKEFILE_DEPENDS="$ALL_MAKEFILE_DEPENDS +dlls/amstream/tests/Makefile: dlls/amstream/tests/Makefile.in dlls/Maketest.rules" +ac_config_files="$ac_config_files dlls/amstream/tests/Makefile" + +ALL_MAKEFILES="$ALL_MAKEFILES \\ dlls/appwiz.cpl/Makefile" test "x$enable_appwiz_cpl" != xno && ALL_DLL_DIRS="$ALL_DLL_DIRS \\ appwiz.cpl" @@ -27602,6 +27610,7 @@ do "dlls/advpack/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/advpack/Makefile" ;; "dlls/advpack/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/advpack/tests/Makefile" ;; "dlls/amstream/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/amstream/Makefile" ;; + "dlls/amstream/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/amstream/tests/Makefile" ;; "dlls/appwiz.cpl/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/appwiz.cpl/Makefile" ;; "dlls/atl/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/atl/Makefile" ;; "dlls/authz/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/authz/Makefile" ;; diff --git a/configure.ac b/configure.ac index 361efcf5a9d..72c229f3906 100644 --- a/configure.ac +++ b/configure.ac @@ -1898,6 +1898,7 @@ WINE_CONFIG_MAKEFILE([dlls/advapi32/tests/Makefile],[dlls/Maketest.rules],[dlls] WINE_CONFIG_MAKEFILE([dlls/advpack/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/advpack/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests]) WINE_CONFIG_MAKEFILE([dlls/amstream/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) +WINE_CONFIG_MAKEFILE([dlls/amstream/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests]) WINE_CONFIG_MAKEFILE([dlls/appwiz.cpl/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/atl/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) WINE_CONFIG_MAKEFILE([dlls/authz/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS]) diff --git a/dlls/amstream/amstream.c b/dlls/amstream/amstream.c index a709c7b5b5b..81584d6e8c3 100644 --- a/dlls/amstream/amstream.c +++ b/dlls/amstream/amstream.c @@ -214,7 +214,7 @@ static HRESULT WINAPI IAMMultiMediaStreamImpl_Initialize(IAMMultiMediaStream* if IAMMultiMediaStreamImpl *This = (IAMMultiMediaStreamImpl *)iface; HRESULT hr = S_OK; - FIXME("(%p/%p)->(%x,%x,%p) partial stub!\n", This, iface, (DWORD)StreamType, dwFlags, pFilterGraph); + TRACE("(%p/%p)->(%x,%x,%p)\n", This, iface, (DWORD)StreamType, dwFlags, pFilterGraph); if (pFilterGraph) { @@ -349,6 +349,14 @@ static HRESULT WINAPI IAMMultiMediaStreamImpl_OpenFile(IAMMultiMediaStream* ifac goto end; } + /* If Initialize was not called before, we do it here */ + if (!This->pFilterGraph) + { + ret = IAMMultiMediaStream_Initialize(iface, STREAMTYPE_READ, 0, NULL); + if (FAILED(ret)) + goto end; + } + ret = IFilterGraph_QueryInterface(This->pFilterGraph, &IID_IGraphBuilder, (void**)&This->GraphBuilder); if(ret != S_OK) { diff --git a/dlls/amstream/tests/Makefile.in b/dlls/amstream/tests/Makefile.in new file mode 100644 index 00000000000..07e98b49ef6 --- /dev/null +++ b/dlls/amstream/tests/Makefile.in @@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +TESTDLL = amstream.dll +IMPORTS = kernel32 oleaut32 ole32 quartz strmiids + +CTESTS = \ + amstream.c + +@MAKE_TEST_RULES@ + +@DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c new file mode 100644 index 00000000000..15b8a7b2916 --- /dev/null +++ b/dlls/amstream/tests/amstream.c @@ -0,0 +1,91 @@ +/* + * Unit tests for MultiMedia Stream functions + * + * Copyright (C) 2009 Christian Costa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define COBJMACROS + +#include "wine/test.h" +#include "amstream.h" + +#define FILE_LEN 9 +static const char fileA[FILE_LEN] = "test.avi"; + +IAMMultiMediaStream* pams; + +static int create_ammultimediastream(void) +{ + return S_OK == CoCreateInstance( + &CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMultiMediaStream, (LPVOID*)&pams); +} + +static void release_ammultimediastream(void) +{ + IAMMultiMediaStream_Release(pams); +} + +static void renderfile(const char * fileA) +{ + HRESULT hr; + WCHAR fileW[FILE_LEN]; + IGraphBuilder* pgraph; + + MultiByteToWideChar(CP_ACP, 0, fileA, -1, fileW, FILE_LEN); + + hr = IAMMultiMediaStream_GetFilterGraph(pams, &pgraph); + ok(hr==S_OK, "GetFilterGraph returned: %x\n", hr); + ok(pgraph==NULL, "Filtergraph should not be created yet\n"); + + if (pgraph) + IGraphBuilder_Release(pgraph); + + hr = IAMMultiMediaStream_OpenFile(pams, fileW, 0); + ok(hr==S_OK, "OpenFile returned: %x\n", hr); + + hr = IAMMultiMediaStream_GetFilterGraph(pams, &pgraph); + ok(hr==S_OK, "GetFilterGraph returned: %x\n", hr); + ok(pgraph!=NULL, "Filtergraph should be created\n"); + + if (pgraph) + IGraphBuilder_Release(pgraph); +} + +static void test_render(void) +{ + HANDLE h; + + if (!create_ammultimediastream()) + return; + + h = CreateFileA(fileA, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (h != INVALID_HANDLE_VALUE) { + CloseHandle(h); + renderfile(fileA); + } + + release_ammultimediastream(); +} + +START_TEST(amstream) +{ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + test_render(); + CoUninitialize(); +} diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index e571f330cab..94ab7c9091f 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -57,7 +57,6 @@ * -- LISTVIEW_[GS]etColumnOrderArray stubs * -- LISTVIEW_SetColumnWidth ignores header images & bitmap * -- LISTVIEW_SetIconSpacing is incomplete - * -- LISTVIEW_SortItems is broken * -- LISTVIEW_StyleChanged doesn't handle some changes too well * * Speedups @@ -1399,6 +1398,8 @@ static INT LISTVIEW_CreateHeader(LISTVIEW_INFO *infoPtr) /* set header font */ SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, (LPARAM)TRUE); + LISTVIEW_UpdateSize(infoPtr); + return 0; } @@ -1674,6 +1675,8 @@ static void LISTVIEW_UpdateHeaderSize(const LISTVIEW_INFO *infoPtr, INT nNewScro TRACE("nNewScrollPos=%d\n", nNewScrollPos); + if (!infoPtr->hwndHeader) return; + GetWindowRect(infoPtr->hwndHeader, &winRect); point[0].x = winRect.left; point[0].y = winRect.top; @@ -3575,21 +3578,38 @@ static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL { if (infoPtr->dwStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem); ranges_additem(infoPtr->selectionRanges, lpLVItem->iItem); + lpItem->state |= LVIS_SELECTED; } else if (stateMask & LVIS_SELECTED) + { ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem); - + lpItem->state &= ~LVIS_SELECTED; + } /* if we are asked to change focus, and we manage it, do it */ if (stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED) { if (lpLVItem->state & LVIS_FOCUSED) { - LISTVIEW_SetItemFocus(infoPtr, -1); + if (infoPtr->nFocusedItem != -1) + { + /* remove current focus */ + item.mask = LVIF_STATE; + item.state = 0; + item.stateMask = LVIS_FOCUSED; + + /* recurse with redrawing an item */ + LISTVIEW_SetItemState(infoPtr, infoPtr->nFocusedItem, &item); + } + + lpItem->state |= LVIS_FOCUSED; infoPtr->nFocusedItem = lpLVItem->iItem; LISTVIEW_EnsureVisible(infoPtr, lpLVItem->iItem, uView == LVS_LIST); } else if (infoPtr->nFocusedItem == lpLVItem->iItem) - infoPtr->nFocusedItem = -1; + { + lpItem->state &= ~LVIS_FOCUSED; + infoPtr->nFocusedItem = -1; + } } } @@ -7487,7 +7507,7 @@ static BOOL LISTVIEW_SetItemCount(LISTVIEW_INFO *infoPtr, INT nItems, DWORD dwFl ranges_del(infoPtr->selectionRanges, range); if (infoPtr->nFocusedItem >= nItems) { - infoPtr->nFocusedItem = -1; + LISTVIEW_SetItemFocus(infoPtr, -1); SetRectEmpty(&infoPtr->rcFocus); } } @@ -7855,8 +7875,8 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; HDPA hdpaSubItems; ITEM_INFO *lpItem; - LPVOID selectionMarkItem; - LVITEMW item; + LPVOID selectionMarkItem = NULL; + LPVOID focusedItem = NULL; int i; TRACE("(pfnCompare=%p, lParamSort=%lx)\n", pfnCompare, lParamSort); @@ -7869,45 +7889,32 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, /* if there are 0 or 1 items, there is no need to sort */ if (infoPtr->nItemCount < 2) return TRUE; + /* clear selection */ + ranges_clear(infoPtr->selectionRanges); + + /* save selection mark and focused item */ + if (infoPtr->nSelectionMark >= 0) + selectionMarkItem = DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nSelectionMark); if (infoPtr->nFocusedItem >= 0) - { - hdpaSubItems = DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nFocusedItem); - lpItem = DPA_GetPtr(hdpaSubItems, 0); - if (lpItem) lpItem->state |= LVIS_FOCUSED; - } - /* FIXME: go thorugh selected items and mark them so in lpItem->state */ - /* clear the lpItem->state for non-selected ones */ - /* remove the selection ranges */ - + focusedItem = DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nFocusedItem); + infoPtr->pfnCompare = pfnCompare; infoPtr->lParamSort = lParamSort; DPA_Sort(infoPtr->hdpaItems, LISTVIEW_CallBackCompare, (LPARAM)infoPtr); - /* Adjust selections and indices so that they are the way they should - * be after the sort (otherwise, the list items move around, but - * whatever is at the item's previous original position will be - * selected instead) - */ - selectionMarkItem=(infoPtr->nSelectionMark>=0)?DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nSelectionMark):NULL; + /* restore selection ranges */ for (i=0; i < infoPtr->nItemCount; i++) { hdpaSubItems = DPA_GetPtr(infoPtr->hdpaItems, i); lpItem = DPA_GetPtr(hdpaSubItems, 0); if (lpItem->state & LVIS_SELECTED) - { - item.state = LVIS_SELECTED; - item.stateMask = LVIS_SELECTED; - LISTVIEW_SetItemState(infoPtr, i, &item); - } - if (lpItem->state & LVIS_FOCUSED) - { - infoPtr->nFocusedItem = i; - lpItem->state &= ~LVIS_FOCUSED; - } + ranges_additem(infoPtr->selectionRanges, i); } - if (selectionMarkItem != NULL) - infoPtr->nSelectionMark = DPA_GetPtrIndex(infoPtr->hdpaItems, selectionMarkItem); + /* restore selection mark and focused item */ + infoPtr->nSelectionMark = DPA_GetPtrIndex(infoPtr->hdpaItems, selectionMarkItem); + infoPtr->nFocusedItem = DPA_GetPtrIndex(infoPtr->hdpaItems, focusedItem); + /* I believe nHotItem should be left alone, see LISTVIEW_ShiftIndices */ /* refresh the display */ @@ -8140,7 +8147,6 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) { ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); } - LISTVIEW_UpdateSize(infoPtr); LISTVIEW_UpdateScroll(infoPtr); } @@ -9124,7 +9130,7 @@ static LRESULT LISTVIEW_Paint(LISTVIEW_INFO *infoPtr, HDC hdc) LISTVIEW_UpdateScroll(infoPtr); } - UpdateWindow(infoPtr->hwndHeader); + if (infoPtr->hwndHeader) UpdateWindow(infoPtr->hwndHeader); if (hdc) LISTVIEW_Refresh(infoPtr, hdc, NULL); diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 914be42d79d..d08ca2f8338 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -903,14 +903,14 @@ static void test_create(void) (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT); ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n"); hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0); - ok(IsWindow(hHeader), "Header shouldn't be created\n"); - ok(hHeader == GetDlgItem(hList, 0), "NULL dialog item expected\n"); + ok(IsWindow(hHeader), "Header should be created\n"); + ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); ret = SetWindowLongPtr(hList, GWL_STYLE, (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST); ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n"); hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0); - ok(IsWindow(hHeader), "Header shouldn't be created\n"); - ok(hHeader == GetDlgItem(hList, 0), "NULL dialog item expected\n"); + ok(IsWindow(hHeader), "Header should be created\n"); + ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); DestroyWindow(hList); /* LVS_REPORT without WS_VISIBLE */ @@ -941,6 +941,16 @@ static void test_create(void) ok(IsWindow(hHeader), "Header should be created\n"); ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); DestroyWindow(hList); + + /* LVS_REPORT with LVS_NOCOLUMNHEADER */ + hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE, + 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0); + hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0); + ok(IsWindow(hHeader), "Header should be created\n"); + ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); + /* HDS_DRAGDROP set by default */ + ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n"); + DestroyWindow(hList); } static void test_redraw(void) @@ -1441,6 +1451,69 @@ todo_wine{ DestroyWindow(hwnd); } +/* comparison callback for test_sorting */ +static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam) +{ + if (first == second) return 0; + return (first > second ? 1 : -1); +} + +static void test_sorting(void) +{ + HWND hwnd; + LVITEMA item = {0}; + DWORD r; + + hwnd = create_listview_control(); + ok(hwnd != NULL, "failed to create a listview window\n"); + + /* insert some items */ + item.mask = LVIF_PARAM | LVIF_STATE; + item.state = LVIS_SELECTED; + item.iItem = 0; + item.iSubItem = 0; + item.lParam = 3; + r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item); + expect(0, r); + + item.mask = LVIF_PARAM; + item.iItem = 1; + item.iSubItem = 0; + item.lParam = 2; + r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item); + expect(1, r); + + item.mask = LVIF_STATE | LVIF_PARAM; + item.state = LVIS_SELECTED; + item.iItem = 2; + item.iSubItem = 0; + item.lParam = 4; + r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item); + expect(2, r); + + r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0); + expect(-1, r); + + r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); + expect(2, r); + + r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare); + expect(TRUE, r); + + r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); + expect(2, r); + r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0); + expect(-1, r); + r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED); + expect(0, r); + r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED); + expect(LVIS_SELECTED, r); + r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED); + expect(LVIS_SELECTED, r); + + DestroyWindow(hwnd); +} + START_TEST(listview) { HMODULE hComctl32; @@ -1479,4 +1552,5 @@ START_TEST(listview) test_getorigin(); test_multiselect(); test_subitem_rect(); + test_sorting(); } diff --git a/dlls/msctf/documentmgr.c b/dlls/msctf/documentmgr.c index ab250cbb388..e1e5b193433 100644 --- a/dlls/msctf/documentmgr.c +++ b/dlls/msctf/documentmgr.c @@ -167,7 +167,7 @@ static HRESULT WINAPI DocumentMgr_Pop(ITfDocumentMgr *iface, DWORD dwFlags) if (dwFlags) return E_INVALIDARG; - if (This->contextStack[0] == NULL) /* Cannot pop last context */ + if (This->contextStack[1] == NULL) /* Cannot pop last context */ return E_FAIL; ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]); @@ -199,14 +199,21 @@ static HRESULT WINAPI DocumentMgr_GetTop(ITfDocumentMgr *iface, ITfContext **ppi static HRESULT WINAPI DocumentMgr_GetBase(ITfDocumentMgr *iface, ITfContext **ppic) { DocumentMgr *This = (DocumentMgr *)iface; + ITfContext *tgt; + TRACE("(%p)\n",This); if (!ppic) return E_INVALIDARG; if (This->contextStack[1]) - ITfContext_AddRef(This->contextStack[1]); + tgt = This->contextStack[1]; + else + tgt = This->contextStack[0]; + + if (tgt) + ITfContext_AddRef(tgt); - *ppic = This->contextStack[1]; + *ppic = tgt; return S_OK; } diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c index d6890344808..13b81c78585 100644 --- a/dlls/msctf/tests/inputprocessor.c +++ b/dlls/msctf/tests/inputprocessor.c @@ -23,15 +23,19 @@ #define COBJMACROS #include "wine/test.h" #include "winuser.h" +#include "initguid.h" #include "shlwapi.h" #include "shlguid.h" #include "comcat.h" -#include "initguid.h" #include "msctf.h" static ITfInputProcessorProfiles* g_ipp; static LANGID gLangid; -static ITfCategoryMgr * g_cm; +static ITfCategoryMgr * g_cm = NULL; +static ITfThreadMgr* g_tm = NULL; + +HRESULT RegisterTextService(REFCLSID rclsid); +HRESULT UnregisterTextService(); DEFINE_GUID(CLSID_FakeService, 0xEDE1A7AD,0x66DE,0x47E0,0xB6,0x20,0x3E,0x92,0xF8,0x24,0x6B,0xF3); DEFINE_GUID(CLSID_TF_InputProcessorProfiles, 0x33c53a50,0xf456,0x4884,0xb0,0x49,0x85,0xfd,0x64,0x3e,0xcf,0xed); @@ -41,6 +45,7 @@ DEFINE_GUID(GUID_TFCAT_TIP_SPEECH, 0xB5A73CD1,0x8355,0x426B,0xA1,0x61,0x25 DEFINE_GUID(GUID_TFCAT_TIP_HANDWRITING, 0x246ecb87,0xc2f2,0x4abe,0x90,0x5b,0xc8,0xb3,0x8a,0xdd,0x2c,0x43); DEFINE_GUID (GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, 0x046B8C80,0x1647,0x40F7,0x9B,0x21,0xB9,0x3B,0x81,0xAA,0xBC,0x1B); DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529a9e6b,0x6587,0x4f23,0xab,0x9e,0x9c,0x7d,0x68,0x3e,0x3c,0x50); static HRESULT initialize(void) @@ -52,6 +57,9 @@ static HRESULT initialize(void) if (SUCCEEDED(hr)) hr = CoCreateInstance (&CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfCategoryMgr, (void**)&g_cm); + if (SUCCEEDED(hr)) + hr = CoCreateInstance (&CLSID_TF_ThreadMgr, NULL, + CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (void**)&g_tm); return hr; } @@ -61,6 +69,8 @@ static void cleanup(void) ITfInputProcessorProfiles_Release(g_ipp); if (g_cm) ITfCategoryMgr_Release(g_cm); + if (g_tm) + ITfThreadMgr_Release(g_tm); CoUninitialize(); } @@ -71,6 +81,8 @@ static void test_Register(void) static const WCHAR szDesc[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',0}; static const WCHAR szFile[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',' ','F','i','l','e',0}; + hr = RegisterTextService(&CLSID_FakeService); + ok(SUCCEEDED(hr),"Unable to register COM for TextService\n"); hr = ITfInputProcessorProfiles_Register(g_ipp, &CLSID_FakeService); ok(SUCCEEDED(hr),"Unable to register text service(%x)\n",hr); hr = ITfInputProcessorProfiles_AddLanguageProfile(g_ipp, &CLSID_FakeService, gLangid, &CLSID_FakeService, szDesc, sizeof(szDesc)/sizeof(WCHAR), szFile, sizeof(szFile)/sizeof(WCHAR), 1); @@ -82,6 +94,7 @@ static void test_Unregister(void) HRESULT hr; hr = ITfInputProcessorProfiles_Unregister(g_ipp, &CLSID_FakeService); ok(SUCCEEDED(hr),"Unable to unregister text service(%x)\n",hr); + UnregisterTextService(); } static void test_EnumInputProcessorInfo(void) @@ -160,6 +173,27 @@ static void test_FindClosestCategory(void) ok(IsEqualGUID(&output,&GUID_TFCAT_TIP_KEYBOARD),"Wrong GUID\n"); } +static void test_Enable(void) +{ + HRESULT hr; + BOOL enabled = FALSE; + + hr = ITfInputProcessorProfiles_EnableLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, TRUE); + ok(SUCCEEDED(hr),"Failed to enable text service\n"); + hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, &enabled); + ok(SUCCEEDED(hr),"Failed to get enabled state\n"); + ok(enabled == TRUE,"enabled state incorrect\n"); +} + +static void test_Disable(void) +{ + HRESULT hr; + + trace("Disabling\n"); + hr = ITfInputProcessorProfiles_EnableLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, FALSE); + ok(SUCCEEDED(hr),"Failed to disable text service\n"); +} + START_TEST(inputprocessor) { if (SUCCEEDED(initialize())) @@ -168,8 +202,10 @@ START_TEST(inputprocessor) test_Register(); test_RegisterCategory(); test_EnumInputProcessorInfo(); + test_Enable(); test_EnumLanguageProfiles(); test_FindClosestCategory(); + test_Disable(); test_UnregisterCategory(); test_Unregister(); } @@ -177,3 +213,201 @@ START_TEST(inputprocessor) skip("Unable to create InputProcessor\n"); cleanup(); } + + + +/******************************************************************************************** + * Stub text service for testing + ********************************************************************************************/ + +static LONG TS_refCount; +static IClassFactory *cf; +static DWORD regid; + +typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut); + +typedef struct tagClassFactory +{ + const IClassFactoryVtbl *vtbl; + LONG ref; + LPFNCONSTRUCTOR ctor; +} ClassFactory; + +typedef struct tagTextService +{ + const ITfTextInputProcessorVtbl *TextInputProcessorVtbl; + LONG refCount; +} TextService; + +static void ClassFactory_Destructor(ClassFactory *This) +{ + HeapFree(GetProcessHeap(),0,This); + TS_refCount--; +} + +static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut) +{ + *ppvOut = NULL; + if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) + { + IClassFactory_AddRef(iface); + *ppvOut = iface; + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) +{ + ClassFactory *This = (ClassFactory *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) +{ + ClassFactory *This = (ClassFactory *)iface; + ULONG ret = InterlockedDecrement(&This->ref); + + if (ret == 0) + ClassFactory_Destructor(This); + return ret; +} + +static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID iid, LPVOID *ppvOut) +{ + ClassFactory *This = (ClassFactory *)iface; + HRESULT ret; + IUnknown *obj; + + ret = This->ctor(punkOuter, &obj); + if (FAILED(ret)) + return ret; + ret = IUnknown_QueryInterface(obj, iid, ppvOut); + IUnknown_Release(obj); + return ret; +} + +static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) +{ + if(fLock) + InterlockedIncrement(&TS_refCount); + else + InterlockedDecrement(&TS_refCount); + + return S_OK; +} + +static const IClassFactoryVtbl ClassFactoryVtbl = { + /* IUnknown */ + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + + /* IClassFactory*/ + ClassFactory_CreateInstance, + ClassFactory_LockServer +}; + +static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut) +{ + ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory)); + This->vtbl = &ClassFactoryVtbl; + This->ref = 1; + This->ctor = ctor; + *ppvOut = (LPVOID)This; + TS_refCount++; + return S_OK; +} + +static void TextService_Destructor(TextService *This) +{ + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI TextService_QueryInterface(ITfTextInputProcessor *iface, REFIID iid, LPVOID *ppvOut) +{ + TextService *This = (TextService *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfTextInputProcessor)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI TextService_AddRef(ITfTextInputProcessor *iface) +{ + TextService *This = (TextService *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI TextService_Release(ITfTextInputProcessor *iface) +{ + TextService *This = (TextService *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + TextService_Destructor(This); + return ret; +} + +static HRESULT WINAPI TextService_Activate(ITfTextInputProcessor *iface, + ITfThreadMgr *ptim, TfClientId id) +{ + trace("TextService_Activate\n"); + return S_OK; +} + +static HRESULT WINAPI TextService_Deactivate(ITfTextInputProcessor *iface) +{ + trace("TextService_Deactivate\n"); + return S_OK; +} + +static const ITfTextInputProcessorVtbl TextService_TextInputProcessorVtbl= +{ + TextService_QueryInterface, + TextService_AddRef, + TextService_Release, + + TextService_Activate, + TextService_Deactivate +}; + +HRESULT TextService_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) +{ + TextService *This; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextService)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->TextInputProcessorVtbl= &TextService_TextInputProcessorVtbl; + This->refCount = 1; + + *ppOut = (IUnknown *)This; + return S_OK; +} + +HRESULT RegisterTextService(REFCLSID rclsid) +{ + ClassFactory_Constructor( TextService_Constructor ,(LPVOID*)&cf); + return CoRegisterClassObject(rclsid, (IUnknown*) cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); +} + +HRESULT UnregisterTextService() +{ + return CoRevokeClassObject(regid); +} diff --git a/dlls/msctf/threadmgr.c b/dlls/msctf/threadmgr.c index 5461425a84c..a73beee86ef 100644 --- a/dlls/msctf/threadmgr.c +++ b/dlls/msctf/threadmgr.c @@ -196,6 +196,14 @@ static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface) { ThreadMgr *This = (ThreadMgr *)iface; FIXME("STUB:(%p)\n",This); + + if (This->focus) + { + ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus); + ITfDocumentMgr_Release(This->focus); + This->focus = 0; + } + return E_NOTIMPL; } @@ -246,7 +254,7 @@ static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *p if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check))) return E_INVALIDARG; - ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, This->focus, check); + ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus); if (This->focus) ITfDocumentMgr_Release(This->focus); diff --git a/dlls/msi/database.c b/dlls/msi/database.c index 8a9b0d7f5b4..70bcd90b49e 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -610,6 +610,8 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file) LPWSTR **temp_records; static const WCHAR backslash[] = {'\\',0}; + static const WCHAR suminfo[] = + {'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0}; TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) ); @@ -660,17 +662,29 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file) records = temp_records; } - if (!TABLE_Exists(db, labels[0])) + if (!strcmpW(labels[0], suminfo)) { - r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns ); + r = msi_add_suminfo( db, records, num_records, num_columns ); if (r != ERROR_SUCCESS) { r = ERROR_FUNCTION_FAILED; goto done; } } + else + { + if (!TABLE_Exists(db, labels[0])) + { + r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns ); + if (r != ERROR_SUCCESS) + { + r = ERROR_FUNCTION_FAILED; + goto done; + } + } - r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records ); + r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records ); + } done: msi_free(path); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 30955f238b0..ccfd6e3d5a8 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -819,6 +819,7 @@ extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ); extern MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount ); extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ); extern LPWSTR msi_get_suminfo_product( IStorage *stg ); +extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ); /* undocumented functions */ UINT WINAPI MsiCreateAndVerifyInstallerDirectory( DWORD ); diff --git a/dlls/msi/suminfo.c b/dlls/msi/suminfo.c index ca6b6d1cd7c..a02f949cb24 100644 --- a/dlls/msi/suminfo.c +++ b/dlls/msi/suminfo.c @@ -29,6 +29,7 @@ #include "winnls.h" #include "shlwapi.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "msi.h" #include "msiquery.h" #include "msidefs.h" @@ -694,43 +695,26 @@ UINT WINAPI MsiSummaryInfoGetPropertyW( pftValue, &str, pcchValueBuf ); } -static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, +static UINT set_prop( MSISUMMARYINFO *si, UINT uiProperty, UINT type, INT iValue, FILETIME* pftValue, awcstring *str ) { - MSISUMMARYINFO *si; PROPVARIANT *prop; - UINT type, len, ret = ERROR_SUCCESS; - - TRACE("%d %u %u %i %p %p\n", handle, uiProperty, uiDataType, - iValue, pftValue, str ); - - type = get_type( uiProperty ); - if( type == VT_EMPTY || type != uiDataType ) - return ERROR_DATATYPE_MISMATCH; - - if( uiDataType == VT_LPSTR && !str->str.w ) - return ERROR_INVALID_PARAMETER; + UINT len; - if( uiDataType == VT_FILETIME && !pftValue ) - return ERROR_INVALID_PARAMETER; - - si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); - if( !si ) - return ERROR_INVALID_HANDLE; + TRACE("%p %u %u %i %p %p\n", si, uiProperty, type, iValue, + pftValue, str ); prop = &si->property[uiProperty]; if( prop->vt == VT_EMPTY ) { if( !si->update_count ) - { - ret = ERROR_FUNCTION_FAILED; - goto end; - } + return ERROR_FUNCTION_FAILED; + si->update_count--; } else if( prop->vt != type ) - goto end; + return ERROR_SUCCESS; free_prop( prop ); prop->vt = type; @@ -763,50 +747,79 @@ static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, break; } -end: - msiobj_release( &si->hdr ); - return ret; + return ERROR_SUCCESS; } UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME* pftValue, LPCWSTR szValue ) { awcstring str; + MSISUMMARYINFO *si; + UINT type, ret; TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType, iValue, pftValue, debugstr_w(szValue) ); + type = get_type( uiProperty ); + if( type == VT_EMPTY || type != uiDataType ) + return ERROR_DATATYPE_MISMATCH; + + if( uiDataType == VT_LPSTR && !szValue ) + return ERROR_INVALID_PARAMETER; + + if( uiDataType == VT_FILETIME && !pftValue ) + return ERROR_INVALID_PARAMETER; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + str.unicode = TRUE; str.str.w = szValue; - return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); + ret = set_prop( si, uiProperty, type, iValue, pftValue, &str ); + + msiobj_release( &si->hdr ); + return ret; } UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME* pftValue, LPCSTR szValue ) { awcstring str; + MSISUMMARYINFO *si; + UINT type, ret; TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType, iValue, pftValue, debugstr_a(szValue) ); + type = get_type( uiProperty ); + if( type == VT_EMPTY || type != uiDataType ) + return ERROR_DATATYPE_MISMATCH; + + if( uiDataType == VT_LPSTR && !szValue ) + return ERROR_INVALID_PARAMETER; + + if( uiDataType == VT_FILETIME && !pftValue ) + return ERROR_INVALID_PARAMETER; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + str.unicode = FALSE; str.str.a = szValue; - return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); + ret = set_prop( si, uiProperty, uiDataType, iValue, pftValue, &str ); + + msiobj_release( &si->hdr ); + return ret; } -UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle ) +static UINT suminfo_persist( MSISUMMARYINFO *si ) { + UINT ret = ERROR_FUNCTION_FAILED; IStream *stm = NULL; - MSISUMMARYINFO *si; DWORD grfMode; HRESULT r; - UINT ret = ERROR_FUNCTION_FAILED; - - TRACE("%d\n", handle ); - - si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); - if( !si ) - return ERROR_INVALID_HANDLE; grfMode = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE; r = IStorage_CreateStream( si->storage, szSumInfo, grfMode, 0, 0, &stm ); @@ -815,7 +828,143 @@ UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle ) ret = save_summary_info( si, stm ); IStream_Release( stm ); } + return ret; +} + +static void parse_filetime( LPCWSTR str, FILETIME *ft ) +{ + SYSTEMTIME lt, utc; + const WCHAR *p = str; + WCHAR *end; + + memset( <, 0, sizeof(lt) ); + + /* YYYY/MM/DD hh:mm:ss */ + + while (isspaceW( *p )) p++; + + lt.wYear = strtolW( p, &end, 10 ); + if (*end != '/') return; + p = end + 1; + + lt.wMonth = strtolW( p, &end, 10 ); + if (*end != '/') return; + p = end + 1; + + lt.wDay = strtolW( p, &end, 10 ); + if (*end != ' ') return; + p = end + 1; + + while (isspaceW( *p )) p++; + + lt.wHour = strtolW( p, &end, 10 ); + if (*end != ':') return; + p = end + 1; + + lt.wMinute = strtolW( p, &end, 10 ); + if (*end != ':') return; + p = end + 1; + + lt.wSecond = strtolW( p, &end, 10 ); + + TzSpecificLocalTimeToSystemTime( NULL, <, &utc ); + SystemTimeToFileTime( &utc, ft ); +} + +static UINT parse_prop( LPCWSTR prop, LPCWSTR value, UINT *pid, INT *int_value, + FILETIME *ft_value, awcstring *str_value ) +{ + *pid = atoiW( prop ); + switch (*pid) + { + case PID_CODEPAGE: + case PID_WORDCOUNT: + case PID_CHARCOUNT: + case PID_SECURITY: + case PID_PAGECOUNT: + *int_value = atoiW( value ); + break; + + case PID_LASTPRINTED: + case PID_CREATE_DTM: + case PID_LASTSAVE_DTM: + parse_filetime( value, ft_value ); + break; + + case PID_SUBJECT: + case PID_AUTHOR: + case PID_KEYWORDS: + case PID_COMMENTS: + case PID_TEMPLATE: + case PID_LASTAUTHOR: + case PID_REVNUMBER: + case PID_APPNAME: + case PID_TITLE: + str_value->str.w = value; + str_value->unicode = TRUE; + break; + + default: + WARN("unhandled prop id %u\n", *pid); + return ERROR_FUNCTION_FAILED; + } + + return ERROR_SUCCESS; +} + +UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) +{ + UINT r = ERROR_FUNCTION_FAILED; + DWORD i, j; + MSISUMMARYINFO *si; + + si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) ); + if (!si) + { + ERR("no summary information!\n"); + return ERROR_FUNCTION_FAILED; + } + + for (i = 0; i < num_records; i++) + { + for (j = 0; j < num_columns; j += 2) + { + UINT pid; + INT int_value = 0; + FILETIME ft_value; + awcstring str_value; + + r = parse_prop( records[i][j], records[i][j + 1], &pid, &int_value, &ft_value, &str_value ); + if (r != ERROR_SUCCESS) + goto end; + + r = set_prop( si, pid, get_type(pid), int_value, &ft_value, &str_value ); + if (r != ERROR_SUCCESS) + goto end; + } + } + +end: + if (r == ERROR_SUCCESS) + r = suminfo_persist( si ); + msiobj_release( &si->hdr ); + return r; +} + +UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle ) +{ + MSISUMMARYINFO *si; + UINT ret; + + TRACE("%d\n", handle ); + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + + ret = suminfo_persist( si ); + + msiobj_release( &si->hdr ); return ret; } diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 0c6290c83b9..3b026a3d3a5 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -836,16 +836,42 @@ double CDECL _nextafter(double num, double next) */ char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign ) { + int prec; thread_data_t *data = msvcrt_get_thread_data(); - char *dec; - + /* FIXME: check better for overflow (native supports over 300 chars's) */ + ndigits = min( ndigits, 80 - 7); /* 7 : space for dec point, 1 for "e", + * 4 for exponent and one for + * terminating '\0' */ if (!data->efcvt_buffer) data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */ - snprintf(data->efcvt_buffer, 80, "%.*e", ndigits /* FIXME wrong */, number); - *sign = (number < 0); - dec = strchr(data->efcvt_buffer, '.'); - *decpt = (dec) ? dec - data->efcvt_buffer : -1; + if( number < 0) { + *sign = TRUE; + number = -number; + } else + *sign = FALSE; + /* handle cases with zero ndigits or less */ + prec = ndigits; + if( prec < 1) prec = 2; + snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number); + /* take the decimal "point away */ + if( prec != 1) + strcpy( data->efcvt_buffer + 1, data->efcvt_buffer + 2); + /* take the exponential "e" out */ + data->efcvt_buffer[ prec] = '\0'; + /* read the exponent */ + sscanf( data->efcvt_buffer + prec + 1, "%d", decpt); + (*decpt)++; + /* adjust for some border cases */ + if( data->efcvt_buffer[0] == '0')/* value is zero */ + *decpt = 0; + /* handle cases with zero ndigits or less */ + if( ndigits < 1){ + if( data->efcvt_buffer[ 0] >= '5') + (*decpt)++; + data->efcvt_buffer[ 0] = '\0'; + } + TRACE("out=\"%s\"\n",data->efcvt_buffer); return data->efcvt_buffer; } diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c index 5f72b47a80b..66bab153f6b 100644 --- a/dlls/msvcrt/tests/printf.c +++ b/dlls/msvcrt/tests/printf.c @@ -698,6 +698,90 @@ static void test_fcvt(void) ok( 0 == sign, "sign wrong\n"); } +static struct { + double value; + int nrdigits; + const char *expstr_e; + const char *expstr_f; + int expdecpt_e; + int expdecpt_f; + int expsign; +} test_cvt_testcases[] = { + { 45.0, 2, "45", "4500", 2, 2, 0 }, + /* Numbers less than 1.0 with different precisions */ + { 0.0001, 1, "1", "", -3, -3, 0 }, + { 0.0001, -10, "", "", -3, -3, 0 }, + { 0.0001, 10,"1000000000", "1000000", -3, -3, 0 }, + /* Basic sign test */ + { -111.0001, 5, "11100", "11100010", 3, 3, 1 }, + { 111.0001, 5, "11100", "11100010", 3, 3, 0 }, + /* big numbers with low precision */ + { 3333.3, 2, "33", "333330", 4, 4, 0 }, + {999999999999.9, 3, "100","999999999999900", 13, 12, 0 }, + /* 0.0 with different precisions */ + { 0.0, 5, "00000", "00000", 0, 0, 0 }, + { 0.0, 0, "", "", 0, 0, 0 }, + { 0.0, -1, "", "", 0, 0, 0 }, + /* Numbers > 1.0 with 0 or -ve precision */ + { -123.0001, 0, "", "123", 3, 3, 1 }, + { -123.0001, -1, "", "12", 3, 3, 1 }, + { -123.0001, -2, "", "1", 3, 3, 1 }, + { -123.0001, -3, "", "", 3, 3, 1 }, + /* Numbers > 1.0, but with rounding at the point of precision */ + { 99.99, 1, "1", "1000", 3, 3, 0 }, + /* Numbers < 1.0 where rounding occurs at the point of precision */ + { 0.0063, 2, "63", "1", -2, -1, 0 }, + { 0.0063, 3, "630", "6", -2, -2, 0 }, + { 0.09999999996, 2, "10", "10", 0, 0, 0 }, + { 0.6, 1, "6", "6", 0, 0, 0 }, + { 0.6, 0, "", "1", 1, 1, 0 }, + { 0.4, 0, "", "", 0, 0, 0 }, + { 0.49, 0, "", "", 0, 0, 0 }, + { 0.51, 0, "", "1", 1, 1, 0 }, + /* ask ridiculous amunt of precision, ruin formatting this table */ + { 1.0, 30, "100000000000000000000000000000", + "1000000000000000000000000000000", 1, 1, 0}, + { 123456789012345678901.0, 30, "123456789012345680000000000000", + "123456789012345680000000000000000000000000000000000", 21, 21, 0}, + /* end marker */ + { 0, 0, "END"} +}; + +static void test_xcvt(void) +{ + char *str; + int i, decpt, sign; + for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){ + decpt = sign = 100; + str = _ecvt( test_cvt_testcases[i].value, + test_cvt_testcases[i].nrdigits, + &decpt, + &sign); + ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15), + "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str, + test_cvt_testcases[i].expstr_e); + ok( decpt == test_cvt_testcases[i].expdecpt_e, + "_ecvt() decimal point wrong, got %d expected %d\n", decpt, + test_cvt_testcases[i].expdecpt_e); + } + for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){ + decpt = sign = 100; + str = _fcvt( test_cvt_testcases[i].value, + test_cvt_testcases[i].nrdigits, + &decpt, + &sign); + ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15), + "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str, + test_cvt_testcases[i].expstr_f); + ok( decpt == test_cvt_testcases[i].expdecpt_f, + "_fcvt() decimal point wrong, got %d expected %d\n", decpt, + test_cvt_testcases[i].expdecpt_f); + ok( sign == test_cvt_testcases[i].expsign, + "_ecvt() sign wrong, got %d expected %d\n", sign, + test_cvt_testcases[i].expsign); + } +} + static int _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...) { int ret; @@ -774,6 +858,7 @@ START_TEST(printf) test_swprintf(); test_snprintf(); test_fcvt(); + test_xcvt(); test_vsnwprintf(); p__vscprintf = (void *)GetProcAddress(GetModuleHandle("msvcrt.dll"), "_vscprintf"); diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 7c0e2c595b9..93920c5fa77 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -638,6 +638,10 @@ static void test_QueryPathOfRegTypeLib(void) { 3, 22, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } }, { 3, 37, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } }, { 3, 40, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } }, + { 0xffff, 0xffff, S_OK, {'f','a','k','e','_','5','_','3','7','.','d','l','l',0 } }, + { 0xffff, 0, TYPE_E_LIBNOTREGISTERED, { 0 } }, + { 3, 0xffff, TYPE_E_LIBNOTREGISTERED, { 0 } }, + { 5, 0xffff, TYPE_E_LIBNOTREGISTERED, { 0 } }, { 4, 0, TYPE_E_LIBNOTREGISTERED, { 0 } } }; static const WCHAR base[] = {'f','a','k','e',0}; @@ -657,6 +661,7 @@ static void test_QueryPathOfRegTypeLib(void) if (!do_typelib_reg_key(&uid, 3, 0, base, 0)) return; if (!do_typelib_reg_key(&uid, 3, 1, base, 0)) return; if (!do_typelib_reg_key(&uid, 3, 37, base, 0)) return; + if (!do_typelib_reg_key(&uid, 5, 37, base, 0)) return; for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) { diff --git a/dlls/oleaut32/tests/vartest.c b/dlls/oleaut32/tests/vartest.c index 648c959b691..24ef171d0d6 100644 --- a/dlls/oleaut32/tests/vartest.c +++ b/dlls/oleaut32/tests/vartest.c @@ -46,6 +46,11 @@ static INT (WINAPI *pVariantTimeToSystemTime)(double,LPSYSTEMTIME); static INT (WINAPI *pDosDateTimeToVariantTime)(USHORT,USHORT,double*); static INT (WINAPI *pVariantTimeToDosDateTime)(double,USHORT*,USHORT *); +static const WCHAR sz12[] = {'1','2','\0'}; +/* the strings are localized */ +static WCHAR sz12_false[32]; +static WCHAR sz12_true[32]; + /* Get a conversion function ptr, return if function not available */ #define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \ if (!p##func) { trace("function " # func " not available, not testing it\n"); return; } @@ -95,7 +100,24 @@ static int IS_ANCIENT = 0; static void init(void) { - hOleaut32 = GetModuleHandle("oleaut32.dll"); + BSTR bstr; + HRESULT res; + + res = VarBstrFromBool(VARIANT_TRUE, LANG_USER_DEFAULT, VAR_LOCALBOOL, &bstr); + ok(SUCCEEDED(res) && (lstrlenW(bstr) > 0), + "Expected localized string for 'True'\n"); + lstrcpyW(sz12_true, sz12); + if (bstr) lstrcatW(sz12_true, bstr); + SysFreeString(bstr); + + res = VarBstrFromBool(VARIANT_FALSE, LANG_USER_DEFAULT, VAR_LOCALBOOL, &bstr); + ok(SUCCEEDED(res) && (lstrlenW(bstr) > 0), + "Expected localized string for 'False'\n"); + lstrcpyW(sz12_false, sz12); + if (bstr) lstrcatW(sz12_false, bstr); + SysFreeString(bstr); + + hOleaut32 = GetModuleHandle("oleaut32.dll"); /* Is a given function exported from oleaut32? */ #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL) @@ -2007,7 +2029,6 @@ static HRESULT (WINAPI *pVarSub)(LPVARIANT,LPVARIANT,LPVARIANT); static void test_VarSub(void) { - static const WCHAR sz12[] = {'1','2','\0'}; VARIANT left, right, exp, result, cy, dec; VARTYPE i; BSTR lbstr, rbstr; @@ -4856,7 +4877,6 @@ static HRESULT (WINAPI *pVarMul)(LPVARIANT,LPVARIANT,LPVARIANT); static void test_VarMul(void) { - static const WCHAR sz12[] = {'1','2','\0'}; VARIANT left, right, exp, result, cy, dec; VARTYPE i; BSTR lbstr, rbstr; @@ -5028,7 +5048,6 @@ static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT); static void test_VarAdd(void) { - static const WCHAR sz12[] = {'1','2','\0'}; VARIANT left, right, exp, result, cy, dec; VARTYPE i; BSTR lbstr, rbstr; @@ -5215,14 +5234,11 @@ static void test_VarCat(void) { LCID lcid; VARIANT left, right, result, expected; - static const WCHAR sz12[] = {'1','2','\0'}; static const WCHAR sz34[] = {'3','4','\0'}; static const WCHAR sz1234[] = {'1','2','3','4','\0'}; static const WCHAR date_sz12[] = {'9','/','3','0','/','1','9','8','0','1','2','\0'}; static const WCHAR sz12_date[] = {'1','2','9','/','3','0','/','1','9','8','0','\0'}; static const WCHAR sz_empty[] = {'\0'}; - static const WCHAR sz12_true[] = {'1','2','T','r','u','e','\0'}; - static const WCHAR sz12_false[] = {'1','2','F','a','l','s','e','\0'}; TCHAR orig_date_format[128]; VARTYPE leftvt, rightvt, resultvt; HRESULT hres; @@ -5416,8 +5432,8 @@ static void test_VarCat(void) hres = VarCat(&left,&right,&result); ok(hres == S_OK, "VarCat failed with error 0x%08x\n", hres); hres = VarCmp(&result,&expected,lcid,0); - ok(hres == VARCMP_EQ || - broken(hres == VARCMP_GT), "Expected VARCMP_EQ, got %08x\n", hres); + ok(hres == VARCMP_EQ, "Expected VARCMP_EQ, got %08x for %s, %s\n", + hres, variantstr(&result), variantstr(&expected)); VariantClear(&left); VariantClear(&right); @@ -5433,8 +5449,8 @@ static void test_VarCat(void) hres = VarCat(&left,&right,&result); ok(hres == S_OK, "VarCat failed with error 0x%08x\n", hres); hres = VarCmp(&result,&expected,lcid,0); - ok(hres == VARCMP_EQ || - broken(hres == VARCMP_GT), "Expected VARCMP_EQ, got %08x\n", hres); + ok(hres == VARCMP_EQ, "Expected VARCMP_EQ, got %08x for %s, %s\n", + hres, variantstr(&result), variantstr(&expected)); VariantClear(&left); VariantClear(&right); diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 75a30d212ff..a0af8473c4e 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -168,13 +168,13 @@ static void FromLEDWords(void *p_Val, int p_iSize) /* * Find a typelib key which matches a requested maj.min version. */ -static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin ) +static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin ) { static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0}; WCHAR buffer[60]; char key_name[16]; DWORD len, i; - INT best_min = -1; + INT best_maj = -1, best_min = -1; HKEY hkey; memcpy( buffer, typelibW, sizeof(typelibW) ); @@ -193,20 +193,40 @@ static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin ) { TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min); - if (wMaj == v_maj) + if (*wMaj == 0xffff && *wMin == 0xffff) { + if (v_maj > best_maj) best_maj = v_maj; + if (v_min > best_min) best_min = v_min; + } + else if (*wMaj == v_maj) + { + best_maj = v_maj; + if (*wMin == v_min) { best_min = v_min; break; /* exact match */ } - if (v_min > best_min) best_min = v_min; + if (*wMin != 0xffff && v_min > best_min) best_min = v_min; } } len = sizeof(key_name); } RegCloseKey( hkey ); - if (best_min >= 0) + + TRACE("found best_maj %d, best_min %d\n", best_maj, best_min); + + if (*wMaj == 0xffff && *wMin == 0xffff) + { + if (best_maj >= 0 && best_min >= 0) + { + *wMaj = best_maj; + *wMin = best_min; + return TRUE; + } + } + + if (*wMaj == best_maj && best_min >= 0) { *wMin = best_min; return TRUE; @@ -295,7 +315,7 @@ HRESULT WINAPI QueryPathOfRegTypeLib( TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path); - if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED; + if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED; get_typelib_key( guid, wMaj, wMin, buffer ); res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ); diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c index 26a19bbbe85..909cf8a830c 100644 --- a/dlls/oleaut32/variant.c +++ b/dlls/oleaut32/variant.c @@ -40,6 +40,7 @@ #include "wine/unicode.h" #include "winerror.h" #include "variant.h" +#include "resource.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(variant); @@ -2467,8 +2468,8 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) { VARTYPE leftvt,rightvt,resultvt; HRESULT hres; - static const WCHAR str_true[] = {'T','r','u','e','\0'}; - static const WCHAR str_false[] = {'F','a','l','s','e','\0'}; + static WCHAR str_true[32]; + static WCHAR str_false[32]; static const WCHAR sz_empty[] = {'\0'}; leftvt = V_VT(left); rightvt = V_VT(right); @@ -2476,6 +2477,11 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), out); + if (!str_true[0]) { + VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_FALSE, str_false); + VARIANT_GetLocalisedText(LOCALE_USER_DEFAULT, IDS_TRUE, str_true); + } + /* when both left and right are NULL the result is NULL */ if (leftvt == VT_NULL && rightvt == VT_NULL) { @@ -2558,7 +2564,7 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) { if (leftvt == VT_BOOL) { - /* Bools are handled as True/False strings instead of 0/-1 as in MSDN */ + /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */ V_VT(&bstrvar_left) = VT_BSTR; if (V_BOOL(left) == TRUE) V_BSTR(&bstrvar_left) = SysAllocString(str_true); @@ -2598,7 +2604,7 @@ HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out) { if (rightvt == VT_BOOL) { - /* Bools are handled as True/False strings instead of 0/-1 as in MSDN */ + /* Bools are handled as localized True/False strings instead of 0/-1 as in MSDN */ V_VT(&bstrvar_right) = VT_BSTR; if (V_BOOL(right) == TRUE) V_BSTR(&bstrvar_right) = SysAllocString(str_true); diff --git a/dlls/oleaut32/variant.h b/dlls/oleaut32/variant.h index 41f8a9af6ee..c881b24d60f 100644 --- a/dlls/oleaut32/variant.h +++ b/dlls/oleaut32/variant.h @@ -123,3 +123,6 @@ typedef struct tagVARIANT_NUMBER_CHARS WCHAR cCurrencyDecimalPoint; WCHAR cCurrencyDigitSeparator; } VARIANT_NUMBER_CHARS; + + +BOOL VARIANT_GetLocalisedText(LANGID, DWORD, WCHAR *); diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c index 7843a7b1862..2d5ae7d8ea4 100644 --- a/dlls/oleaut32/vartype.c +++ b/dlls/oleaut32/vartype.c @@ -5961,7 +5961,13 @@ HRESULT WINAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL *pBoolOut) return S_OK; } -static BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest) +/************************************************************************ + * VARIANT_GetLocalisedText [internal] + * + * Get a localized string from the resources + * + */ +BOOL VARIANT_GetLocalisedText(LANGID langId, DWORD dwId, WCHAR *lpszDest) { HRSRC hrsrc; diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index b73cf60616e..34f7f078284 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -102,8 +102,8 @@ typedef struct wine_glcontext { void enter_gl(void) { - Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext; - + Wine_GLContext *curctx = NtCurrentTeb()->glContext; + if (curctx && curctx->do_escape) { enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP; @@ -230,8 +230,8 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) { /* After that, search in the thunks to find the real name of the extension */ ext.name = lpszProc; - ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry, - extension_registry_size, sizeof(OpenGL_extension), compar); + ext_ret = bsearch(&ext, extension_registry, extension_registry_size, + sizeof(OpenGL_extension), compar); /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */ if (ext_ret == NULL) { diff --git a/dlls/quartz/mpegsplit.c b/dlls/quartz/mpegsplit.c index 373e5372973..14d01a1590a 100644 --- a/dlls/quartz/mpegsplit.c +++ b/dlls/quartz/mpegsplit.c @@ -176,7 +176,6 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample) /* Find the next valid header.. it be right here */ assert(parse_header(fbuf, &length, &This->position) == S_OK); - assert(length == len || length + 4 == len); IMediaSample_SetActualDataLength(pCurrentSample, length); /* Queue the next sample */ diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c index 7e44dd7ddae..5e2450a4742 100644 --- a/dlls/secur32/ntlm.c +++ b/dlls/secur32/ntlm.c @@ -662,8 +662,20 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( ret = SEC_E_NO_CREDENTIALS; goto isc_end; } - else /* Just do a noop on the next run */ + else + { + /* Some versions of Samba have a broken ntlm_auth that can + * return "BH" here. Catch this and abort. */ + if(!strncmp(buffer, "BH", 2)) + { + ERR("ntlm_auth replied 'BH'. This should not happen. " + "Please fix your ntlm_auth install and try again.\n"); + ret = SEC_E_INTERNAL_ERROR; + goto isc_end; + } + /* Otherwise, just do a noop on the next run */ lstrcpynA(buffer, "OK", max_len-1); + } } else { diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index 73db3954f9c..8f599f0fb4c 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -1097,12 +1097,6 @@ BOOLEAN WINAPI GetUserNameExW( DWORD len; TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize); - if (NameFormat == NameUnknown) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - switch (NameFormat) { case NameSamCompatible: @@ -1135,6 +1129,7 @@ BOOLEAN WINAPI GetUserNameExW( status = FALSE; } break; + case NameUnknown: case NameFullyQualifiedDN: case NameDisplay: case NameUniqueId: @@ -1143,8 +1138,7 @@ BOOLEAN WINAPI GetUserNameExW( case NameCanonicalEx: case NameServicePrincipal: case NameDnsDomain: - FIXME("NameFormat %d not implemented\n", NameFormat); - SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO); + SetLastError(ERROR_NONE_MAPPED); status = FALSE; break; default: diff --git a/dlls/secur32/tests/secur32.c b/dlls/secur32/tests/secur32.c index 7e969bdb341..21bb83a5cba 100644 --- a/dlls/secur32/tests/secur32.c +++ b/dlls/secur32/tests/secur32.c @@ -107,14 +107,13 @@ static void testGetUserNameExA(void) size = sizeof(name); ZeroMemory(name, sizeof(name)); rc = pGetUserNameExA(formats[i], name, &size); - ok(rc || ((formats[i] == NameUnknown) && - (GetLastError() == ERROR_INVALID_PARAMETER)) || - (GetLastError() == ERROR_CANT_ACCESS_DOMAIN_INFO) || - (GetLastError() == ERROR_NO_SUCH_DOMAIN) || - (GetLastError() == ERROR_NO_SUCH_USER) || - (GetLastError() == ERROR_NONE_MAPPED) || - (GetLastError() == ERROR_ACCESS_DENIED), - "GetUserNameExA(%d) failed: %d\n", + ok(rc || + (formats[i] == NameUnknown && + GetLastError() == ERROR_NO_SUCH_USER) || + GetLastError() == ERROR_NONE_MAPPED || + broken(formats[i] == NameDnsDomain && + GetLastError() == ERROR_INVALID_PARAMETER), + "GetUserNameExW(%d) failed: %d\n", formats[i], GetLastError()); } @@ -155,13 +154,12 @@ static void testGetUserNameExW(void) size = sizeof(nameW); ZeroMemory(nameW, sizeof(nameW)); rc = pGetUserNameExW(formats[i], nameW, &size); - ok(rc || ((formats[i] == NameUnknown) && - (GetLastError() == ERROR_INVALID_PARAMETER)) || - (GetLastError() == ERROR_CANT_ACCESS_DOMAIN_INFO) || - (GetLastError() == ERROR_NO_SUCH_DOMAIN) || - (GetLastError() == ERROR_NO_SUCH_USER) || - (GetLastError() == ERROR_NONE_MAPPED) || - (GetLastError() == ERROR_ACCESS_DENIED), + ok(rc || + (formats[i] == NameUnknown && + GetLastError() == ERROR_NO_SUCH_USER) || + GetLastError() == ERROR_NONE_MAPPED || + broken(formats[i] == NameDnsDomain && + GetLastError() == ERROR_INVALID_PARAMETER), "GetUserNameExW(%d) failed: %d\n", formats[i], GetLastError()); } @@ -212,7 +210,7 @@ static void test_InitSecurityInterface(void) if (!pInitSecurityInterfaceW) { - skip("InitSecurityInterfaceW not exported by secur32.dll\n"); + win_skip("InitSecurityInterfaceW not exported by secur32.dll\n"); return; } @@ -242,15 +240,23 @@ START_TEST(secur32) if (pGetComputerObjectNameA) testGetComputerObjectNameA(); + else + win_skip("GetComputerObjectNameA not exported by secur32.dll\n"); if (pGetComputerObjectNameW) testGetComputerObjectNameW(); + else + win_skip("GetComputerObjectNameW not exported by secur32.dll\n"); if (pGetUserNameExA) testGetUserNameExA(); + else + win_skip("GetUserNameExA not exported by secur32.dll\n"); if (pGetUserNameExW) testGetUserNameExW(); + else + win_skip("GetUserNameExW not exported by secur32.dll\n"); test_InitSecurityInterface(); diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index e4ad1de77d0..4f3bd5630d1 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1284,6 +1284,19 @@ static void test_get_async_key_state(void) ok(0 == GetAsyncKeyState(-1000000), "GetAsyncKeyState did not return 0\n"); } +static void test_keyboard_layout_name(void) +{ + BOOL ret; + char klid[KL_NAMELENGTH]; + + if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409) return; + + klid[0] = 0; + ret = GetKeyboardLayoutNameA(klid); + ok(ret, "GetKeyboardLayoutNameA failed %u\n", GetLastError()); + ok(!strcmp(klid, "00000409"), "expected 00000409, got %s\n", klid); +} + START_TEST(input) { init_function_pointers(); @@ -1300,6 +1313,7 @@ START_TEST(input) test_key_map(); test_ToUnicode(); test_get_async_key_state(); + test_keyboard_layout_name(); if(pGetMouseMovePointsEx) test_GetMouseMovePointsEx(); diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 4aa36742d27..1f0420e1460 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -2662,7 +2662,10 @@ static void test_keyboard_input(HWND hwnd) ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); keybd_event(VK_SPACE, 0, 0, 0); - ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); + do + { + ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE); + } while (ret && msg.message >= 0xc000); if (!ret) { skip( "keybd_event didn't work, skipping keyboard test\n" ); @@ -4930,7 +4933,10 @@ static void test_GetWindowModuleFileName(void) ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd); SetLastError(0xdeadbeef); ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2)); - ok(!ret2 || ret1 == ret2 /* vista */, "expected 0 or %u, got %u %s\n", ret1, ret2, buf2); + ok(!ret2 || + ret1 == ret2 || /* vista */ + broken(ret2), /* some win98 return user.exe as file name */ + "expected 0 or %u, got %u %s\n", ret1, ret2, buf2); } } diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index d485fc85e96..1eefee0509a 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -1183,6 +1183,12 @@ static void test_digit_substitution(void) for (i = 0; i < sizeof(groups)/sizeof(groups[0]); i++) { ret = pEnumLanguageGroupLocalesA(enum_proc, groups[i], 0, 0); + if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("EnumLanguageGroupLocalesA not implemented on this platform\n"); + break; + } + ok(ret, "EnumLanguageGroupLocalesA failed unexpectedly: %u\n", GetLastError()); } } diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c index b6f55b84b41..10b66d00e18 100644 --- a/dlls/winecoreaudio.drv/audio.c +++ b/dlls/winecoreaudio.drv/audio.c @@ -32,6 +32,7 @@ # include #endif #include +#include #include "windef.h" #include "winbase.h" @@ -86,23 +87,24 @@ AudioUnitRender( AudioUnit ci, * +---------+-------------+---------------+---------------------------------+ * | state | function | event | new state | * +---------+-------------+---------------+---------------------------------+ -* | | open() | | STOPPED | +* | | open() | | PLAYING | * | PAUSED | write() | | PAUSED | -* | STOPPED | write() | | PLAYING | * | PLAYING | write() | HEADER | PLAYING | * | (other) | write() | | | * | (any) | pause() | PAUSING | PAUSED | -* | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) | -* | (any) | reset() | RESETTING | STOPPED | +* | PAUSED | restart() | RESTARTING | PLAYING | +* | (any) | reset() | RESETTING | PLAYING | * | (any) | close() | CLOSING | CLOSED | * +---------+-------------+---------------+---------------------------------+ */ /* states of the playing device */ -#define WINE_WS_PLAYING 0 +#define WINE_WS_PLAYING 0 /* for waveOut: lpPlayPtr == NULL -> stopped */ #define WINE_WS_PAUSED 1 -#define WINE_WS_STOPPED 2 +#define WINE_WS_STOPPED 2 /* Not used for waveOut */ #define WINE_WS_CLOSED 3 +#define WINE_WS_OPENING 4 +#define WINE_WS_CLOSING 5 typedef struct tagCoreAudio_Device { char dev_name[32]; @@ -771,9 +773,10 @@ static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPSW lpCaps, DWORD dwSize) static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) { WINE_WAVEOUT* wwo; - DWORD retval; DWORD ret; AudioStreamBasicDescription streamFormat; + AudioUnit audioUnit = NULL; + BOOL auInited = FALSE; TRACE("(%u, %p, %08x);\n", wDevID, lpDesc, dwFlags); if (lpDesc == NULL) @@ -808,7 +811,15 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) lpDesc->lpFormat->nSamplesPerSec); return MMSYSERR_NOERROR; } - + + /* We proceed in three phases: + * o Reserve the device for us, marking it as unavailable (not closed) + * o Create, configure, and start the Audio Unit. To avoid deadlock, + * this has to be done without holding wwo->lock. + * o If that was successful, finish setting up our device info and + * mark the device as ready. + * Otherwise, clean up and mark the device as available. + */ wwo = &WOutDev[wDevID]; if (!OSSpinLockTry(&wwo->lock)) return MMSYSERR_ALLOCATED; @@ -819,18 +830,18 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) return MMSYSERR_ALLOCATED; } - if (!AudioUnit_CreateDefaultAudioUnit((void *) wwo, &wwo->audioUnit)) + wwo->state = WINE_WS_OPENING; + wwo->audioUnit = NULL; + OSSpinLockUnlock(&wwo->lock); + + + if (!AudioUnit_CreateDefaultAudioUnit((void *) wwo, &audioUnit)) { ERR("CoreAudio_CreateDefaultAudioUnit(%p) failed\n", wwo); - OSSpinLockUnlock(&wwo->lock); - return MMSYSERR_ERROR; + ret = MMSYSERR_ERROR; + goto error; } - if ((dwFlags & WAVE_DIRECTSOUND) && - !(wwo->caps.dwSupport & WAVECAPS_DIRECTSOUND)) - /* not supported, ignore it */ - dwFlags &= ~WAVE_DIRECTSOUND; - streamFormat.mFormatID = kAudioFormatLinearPCM; streamFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked; /* FIXME check for 32bits float -> kLinearPCMFormatFlagIsFloat */ @@ -847,26 +858,36 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) streamFormat.mBytesPerFrame = streamFormat.mBitsPerChannel * streamFormat.mChannelsPerFrame / 8; streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame * streamFormat.mFramesPerPacket; - ret = AudioUnit_InitializeWithStreamDescription(wwo->audioUnit, &streamFormat); + ret = AudioUnit_InitializeWithStreamDescription(audioUnit, &streamFormat); if (!ret) { - AudioUnit_CloseAudioUnit(wwo->audioUnit); - OSSpinLockUnlock(&wwo->lock); - return WAVERR_BADFORMAT; /* FIXME return an error based on the OSStatus */ + ret = WAVERR_BADFORMAT; /* FIXME return an error based on the OSStatus */ + goto error; } - wwo->streamDescription = streamFormat; + auInited = TRUE; - ret = AudioOutputUnitStart(wwo->audioUnit); + /* Our render callback CoreAudio_woAudioUnitIOProc may be called before + * AudioOutputUnitStart returns. Core Audio will grab its own internal + * lock before calling it and the callback grabs wwo->lock. This would + * deadlock if we were holding wwo->lock. + * Also, the callback has to safely do nothing in that case, because + * wwo hasn't been completely filled out, yet. */ + ret = AudioOutputUnitStart(audioUnit); if (ret) { ERR("AudioOutputUnitStart failed: %08x\n", ret); - AudioUnitUninitialize(wwo->audioUnit); - AudioUnit_CloseAudioUnit(wwo->audioUnit); - OSSpinLockUnlock(&wwo->lock); - return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ + ret = MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ + goto error; } - wwo->state = WINE_WS_STOPPED; + + OSSpinLockLock(&wwo->lock); + assert(wwo->state == WINE_WS_OPENING); + + wwo->audioUnit = audioUnit; + wwo->streamDescription = streamFormat; + + wwo->state = WINE_WS_PLAYING; wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); @@ -890,9 +911,24 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) OSSpinLockUnlock(&wwo->lock); - retval = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L); + ret = wodNotifyClient(wwo, WOM_OPEN, 0L, 0L); - return retval; + return ret; + +error: + if (audioUnit) + { + if (auInited) + AudioUnitUninitialize(audioUnit); + AudioUnit_CloseAudioUnit(audioUnit); + } + + OSSpinLockLock(&wwo->lock); + assert(wwo->state == WINE_WS_OPENING); + wwo->state = WINE_WS_CLOSED; + OSSpinLockUnlock(&wwo->lock); + + return ret; } /************************************************************************** @@ -921,14 +957,17 @@ static DWORD wodClose(WORD wDevID) } else { OSStatus err; + AudioUnit audioUnit = wwo->audioUnit; + /* sanity check: this should not happen since the device must have been reset before */ if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n"); - wwo->state = WINE_WS_CLOSED; /* mark the device as closed */ + wwo->state = WINE_WS_CLOSING; /* mark the device as closing */ + wwo->audioUnit = NULL; OSSpinLockUnlock(&wwo->lock); - err = AudioUnitUninitialize(wwo->audioUnit); + err = AudioUnitUninitialize(audioUnit); if (err) { ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24), (char) (err >> 16), @@ -937,12 +976,17 @@ static DWORD wodClose(WORD wDevID) return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ } - if ( !AudioUnit_CloseAudioUnit(wwo->audioUnit) ) + if ( !AudioUnit_CloseAudioUnit(audioUnit) ) { ERR("Can't close AudioUnit\n"); return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */ } + OSSpinLockLock(&wwo->lock); + assert(wwo->state == WINE_WS_CLOSING); + wwo->state = WINE_WS_CLOSED; /* mark the device as closed */ + OSSpinLockUnlock(&wwo->lock); + ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L); } @@ -1056,9 +1100,7 @@ static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo) /* We didn't loop back. Advance to the next wave header */ wwo->lpPlayPtr = wwo->lpPlayPtr->lpNext; - if (!wwo->lpPlayPtr) - wwo->state = WINE_WS_STOPPED; - else + if (wwo->lpPlayPtr) wodHelper_CheckForLoopBegin(wwo); } } @@ -1183,9 +1225,6 @@ static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) { wwo->lpPlayPtr = lpWaveHdr; - if (wwo->state == WINE_WS_STOPPED) - wwo->state = WINE_WS_PLAYING; - wodHelper_CheckForLoopBegin(wwo); wwo->dwPartialOffset = 0; @@ -1214,9 +1253,9 @@ static DWORD wodPause(WORD wDevID) * the mutex while we make an Audio Unit call. Stop the Audio Unit before * setting the PAUSED state. In wodRestart, the order is reversed. This * guarantees that we can't get into a situation where the state is - * PLAYING or STOPPED but the Audio Unit isn't running. Although we can - * be in PAUSED state with the Audio Unit still running, that's harmless - * because the render callback will just produce silence. + * PLAYING but the Audio Unit isn't running. Although we can be in PAUSED + * state with the Audio Unit still running, that's harmless because the + * render callback will just produce silence. */ status = AudioOutputUnitStop(WOutDev[wDevID].audioUnit); if (status) { @@ -1225,7 +1264,7 @@ static DWORD wodPause(WORD wDevID) } OSSpinLockLock(&WOutDev[wDevID].lock); - if (WOutDev[wDevID].state == WINE_WS_PLAYING || WOutDev[wDevID].state == WINE_WS_STOPPED) + if (WOutDev[wDevID].state == WINE_WS_PLAYING) WOutDev[wDevID].state = WINE_WS_PAUSED; OSSpinLockUnlock(&WOutDev[wDevID].lock); @@ -1248,21 +1287,16 @@ static DWORD wodRestart(WORD wDevID) } /* The order of the following operations is important since we can't hold - * the mutex while we make an Audio Unit call. Set the PLAYING/STOPPED + * the mutex while we make an Audio Unit call. Set the PLAYING * state before starting the Audio Unit. In wodPause, the order is * reversed. This guarantees that we can't get into a situation where - * the state is PLAYING or STOPPED but the Audio Unit isn't running. + * the state is PLAYING but the Audio Unit isn't running. * Although we can be in PAUSED state with the Audio Unit still running, * that's harmless because the render callback will just produce silence. */ OSSpinLockLock(&WOutDev[wDevID].lock); if (WOutDev[wDevID].state == WINE_WS_PAUSED) - { - if (WOutDev[wDevID].lpPlayPtr) - WOutDev[wDevID].state = WINE_WS_PLAYING; - else - WOutDev[wDevID].state = WINE_WS_STOPPED; - } + WOutDev[wDevID].state = WINE_WS_PLAYING; OSSpinLockUnlock(&WOutDev[wDevID].lock); status = AudioOutputUnitStart(WOutDev[wDevID].audioUnit); @@ -1296,7 +1330,8 @@ static DWORD wodReset(WORD wDevID) OSSpinLockLock(&wwo->lock); - if (wwo->state == WINE_WS_CLOSED) + if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_CLOSING || + wwo->state == WINE_WS_OPENING) { OSSpinLockUnlock(&wwo->lock); WARN("resetting a closed device\n"); @@ -1305,7 +1340,7 @@ static DWORD wodReset(WORD wDevID) lpSavedQueuePtr = wwo->lpQueuePtr; wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL; - wwo->state = WINE_WS_STOPPED; + wwo->state = WINE_WS_PLAYING; wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0; wwo->dwPartialOffset = 0; /* Clear partial wavehdr */ @@ -1594,6 +1629,9 @@ OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon, OSSpinLockLock(&wwo->lock); + /* We might have been called before wwo has been completely filled out by + * wodOpen, or while it's being closed in wodClose. We have to do nothing + * in that case. The check of wwo->state below ensures that. */ while (dataNeeded > 0 && wwo->state == WINE_WS_PLAYING && wwo->lpPlayPtr) { unsigned int available = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset; @@ -1945,6 +1983,7 @@ static DWORD widClose(WORD wDevID) { DWORD ret = MMSYSERR_NOERROR; WINE_WAVEIN* wwi; + OSStatus err; TRACE("(%u);\n", wDevID); @@ -1956,7 +1995,7 @@ static DWORD widClose(WORD wDevID) wwi = &WInDev[wDevID]; OSSpinLockLock(&wwi->lock); - if (wwi->state == WINE_WS_CLOSED) + if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING) { WARN("Device already closed.\n"); ret = MMSYSERR_INVALHANDLE; @@ -1968,36 +2007,50 @@ static DWORD widClose(WORD wDevID) } else { - wwi->state = WINE_WS_CLOSED; + wwi->state = WINE_WS_CLOSING; } OSSpinLockUnlock(&wwi->lock); - if (ret == MMSYSERR_NOERROR) - { - OSStatus err = AudioUnitUninitialize(wwi->audioUnit); - if (err) - { - ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24), - (char) (err >> 16), - (char) (err >> 8), - (char) err); - } + if (ret != MMSYSERR_NOERROR) + return ret; - if (!AudioUnit_CloseAudioUnit(wwi->audioUnit)) - { - ERR("Can't close AudioUnit\n"); - } - /* Dellocate our audio buffers */ - widHelper_DestroyAudioBufferList(wwi->bufferList); - wwi->bufferList = NULL; - HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy); - wwi->bufferListCopy = NULL; + /* Clean up and close the audio unit. This has to be done without + * wwi->lock being held to avoid deadlock. AudioUnitUninitialize will + * grab an internal Core Audio lock while waiting for the device work + * thread to exit. Meanwhile the device work thread may be holding + * that lock and trying to grab the wwi->lock in the callback. */ + err = AudioUnitUninitialize(wwi->audioUnit); + if (err) + { + ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24), + (char) (err >> 16), + (char) (err >> 8), + (char) err); + } - ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L); + if (!AudioUnit_CloseAudioUnit(wwi->audioUnit)) + { + ERR("Can't close AudioUnit\n"); } + + OSSpinLockLock(&wwi->lock); + assert(wwi->state == WINE_WS_CLOSING); + + /* Dellocate our audio buffers */ + widHelper_DestroyAudioBufferList(wwi->bufferList); + wwi->bufferList = NULL; + HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy); + wwi->bufferListCopy = NULL; + + wwi->audioUnit = NULL; + wwi->state = WINE_WS_CLOSED; + OSSpinLockUnlock(&wwi->lock); + + ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L); + return ret; } @@ -2031,7 +2084,7 @@ static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) wwi = &WInDev[wDevID]; OSSpinLockLock(&wwi->lock); - if (wwi->state == WINE_WS_CLOSED) + if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING) { WARN("Trying to add buffer to closed device.\n"); ret = MMSYSERR_INVALHANDLE; @@ -2083,7 +2136,7 @@ static DWORD widStart(WORD wDevID) wwi = &WInDev[wDevID]; OSSpinLockLock(&wwi->lock); - if (wwi->state == WINE_WS_CLOSED) + if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING) { WARN("Trying to start closed device.\n"); ret = MMSYSERR_INVALHANDLE; @@ -2142,7 +2195,7 @@ static DWORD widStop(WORD wDevID) OSSpinLockLock(&wwi->lock); - if (wwi->state == WINE_WS_CLOSED) + if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING) { WARN("Trying to stop closed device.\n"); ret = MMSYSERR_INVALHANDLE; @@ -2215,7 +2268,7 @@ static DWORD widReset(WORD wDevID) wwi = &WInDev[wDevID]; OSSpinLockLock(&wwi->lock); - if (wwi->state == WINE_WS_CLOSED) + if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING) { WARN("Trying to reset a closed device.\n"); ret = MMSYSERR_INVALHANDLE; @@ -2403,6 +2456,9 @@ OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon, lpStorePtr = wwi->lpQueuePtr; + /* We might have been called while the waveIn device is being closed in + * widClose. We have to do nothing in that case. The check of wwi->state + * below ensures that. */ while (dataToStore > 0 && wwi->state == WINE_WS_PLAYING && lpStorePtr) { unsigned int room = lpStorePtr->dwBufferLength - lpStorePtr->dwBytesRecorded; diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 5cea411eb93..b5b5ad445e0 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -404,20 +404,23 @@ static const char * const shift_tab[] = { }; static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *ins, - const DWORD param, char *write_mask) + const struct wined3d_shader_dst_param *dst, char *write_mask) { char *ptr = write_mask; char vshader = shader_is_vshader_version(ins->reg_maps->shader_version); - if(vshader && shader_get_regtype(param) == WINED3DSPR_ADDR) { + if (vshader && dst->register_type == WINED3DSPR_ADDR) + { *ptr++ = '.'; *ptr++ = 'x'; - } else if ((param & WINED3DSP_WRITEMASK_ALL) != WINED3DSP_WRITEMASK_ALL) { + } + else if (dst->write_mask != WINED3DSP_WRITEMASK_ALL) + { *ptr++ = '.'; - if (param & WINED3DSP_WRITEMASK_0) *ptr++ = 'x'; - if (param & WINED3DSP_WRITEMASK_1) *ptr++ = 'y'; - if (param & WINED3DSP_WRITEMASK_2) *ptr++ = 'z'; - if (param & WINED3DSP_WRITEMASK_3) *ptr++ = 'w'; + if (dst->write_mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x'; + if (dst->write_mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y'; + if (dst->write_mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z'; + if (dst->write_mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w'; } *ptr = '\0'; @@ -577,7 +580,7 @@ static void shader_arb_add_dst_param(const struct wined3d_shader_instruction *in wined3d_dst->register_idx, wined3d_dst->has_rel_addr, register_name, &is_color); strcat(str, register_name); - shader_arb_get_write_mask(ins, wined3d_dst->token, write_mask); + shader_arb_get_write_mask(ins, wined3d_dst, write_mask); strcat(str, write_mask); } @@ -672,8 +675,8 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD } if(shader_is_pshader_version(ins->reg_maps->shader_version)) { const IWineD3DPixelShaderImpl* const ps = (const IWineD3DPixelShaderImpl*)This; - if(ps->cur_args->texrect_fixup & (1 << sampler_idx)) { - FIXME("NP2 texcoord fixup is currently not implemented in ARB mode (use GLSL instead)."); + if(ps->cur_args->np2_fixup & (1 << sampler_idx)) { + FIXME("NP2 texcoord fixup is currently not implemented in ARB mode (use GLSL instead).\n"); } } break; @@ -811,7 +814,7 @@ static void pshader_hw_bem(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); strcat(dst_name, dst_wmask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]); @@ -846,7 +849,7 @@ static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins) /* Handle output register */ shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); /* Generate input register names (with modifiers) */ pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]); @@ -882,7 +885,7 @@ static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins) /* Handle output register */ shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); /* Generate input register names (with modifiers) */ pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]); @@ -911,7 +914,7 @@ static void pshader_hw_dp2add(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name[0]); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[1], 1, src_name[1]); @@ -1015,7 +1018,7 @@ static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, output_rname, &is_color); strcpy(operands[0], output_rname); - shader_arb_get_write_mask(ins, dst->token, output_wmask); + shader_arb_get_write_mask(ins, dst, output_wmask); strcat(operands[0], output_wmask); arguments[0] = '\0'; @@ -1187,21 +1190,20 @@ static void pshader_hw_tex(const struct wined3d_shader_instruction *ins) static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins) { - DWORD dst = ins->dst[0].token; + const struct wined3d_shader_dst_param *dst = &ins->dst[0]; SHADER_BUFFER *buffer = ins->buffer; char tmp[20]; shader_arb_get_write_mask(ins, dst, tmp); if (ins->reg_maps->shader_version != WINED3DPS_VERSION(1,4)) { - DWORD reg = ins->dst[0].register_idx; + DWORD reg = dst->register_idx; shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg); } else { - DWORD reg1 = ins->dst[0].register_idx; char reg_src[40]; pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, reg_src); - shader_addline(buffer, "MOV R%u%s, %s;\n", reg1, tmp, reg_src); + shader_addline(buffer, "MOV R%u%s, %s;\n", dst->register_idx, tmp, reg_src); } } @@ -1526,7 +1528,7 @@ static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins) /* Handle output register */ shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_str, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_mask); + shader_arb_get_write_mask(ins, dst, dst_mask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0); shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dst->register_idx, src0); @@ -1547,7 +1549,7 @@ static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_str, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_mask); + shader_arb_get_write_mask(ins, dst, dst_mask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src0); shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst->register_idx, src0); @@ -1632,7 +1634,6 @@ static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins) tmp_dst = ins->dst[0]; for (i = 0; i < nComponents; i++) { tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i; - tmp_dst.token = (tmp_dst.token & ~WINED3DSP_WRITEMASK_ALL) | tmp_dst.write_mask; tmp_ins.src[1] = ins->src[1]+i; shader_hw_map2gl(&tmp_ins); } @@ -1683,7 +1684,7 @@ static void shader_hw_nrm(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name); shader_addline(buffer, "DP3 TMP, %s, %s;\n", src_name, src_name); @@ -1713,7 +1714,7 @@ static void shader_hw_sincos(const struct wined3d_shader_instruction *ins) shader_arb_get_register_name(ins->shader, dst->register_type, dst->register_idx, dst->has_rel_addr, dst_name, &is_color); - shader_arb_get_write_mask(ins, dst->token, dst_wmask); + shader_arb_get_write_mask(ins, dst, dst_wmask); pshader_gen_input_modifier_line(ins->shader, buffer, ins->src[0], 0, src_name); shader_addline(buffer, "SCS%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index f24f9bc9da1..08415c21035 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -221,7 +221,6 @@ static void shader_parse_dst_param(DWORD param, DWORD addr_param, struct wined3d dst->modifiers = param & WINED3DSP_DSTMOD_MASK; dst->shift = (param & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; dst->has_rel_addr = param & WINED3DSHADER_ADDRMODE_RELATIVE; - dst->token = param; dst->addr_token = addr_param; } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 99d37625520..3b46965d58c 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1708,7 +1708,10 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad /* Return the information requested */ TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n"); strcpy(pIdentifier->Driver, This->adapters[Adapter].driver); - strcpy(pIdentifier->Description, This->adapters[Adapter].description); + if(This->adapters[Adapter].gl_info.driver_description) + strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description); + else /* Copy default description "Direct3D HAL" */ + strcpy(pIdentifier->Description, This->adapters[Adapter].description); /* Note dx8 doesn't supply a DeviceName */ if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */ @@ -3944,41 +3947,59 @@ static void test_pbo_functionality(WineD3D_GL_Info *gl_info) { struct driver_version_information { WORD vendor; /* reported PCI card vendor ID */ WORD card; /* reported PCI card device ID */ + const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */ WORD hipart_hi, hipart_lo; /* driver hiword to report */ WORD lopart_hi, lopart_lo; /* driver loword to report */ }; static const struct driver_version_information driver_version_table[] = { - /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/ - /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */ - /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */ - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 }, - {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 }, + /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x) + * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown + * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89 + * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86 + * + * All version numbers used below are from the Linux nvidia drivers. + */ + {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 4, 3 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 4, 3 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 4, 3 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8044 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8044 }, /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */ - {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 }, - {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 }, - - /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */ + {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 }, + + /* TODO: Add information about legacy ATI hardware, Intel and other cards */ }; static void fixup_extensions(WineD3D_GL_Info *gl_info) { @@ -4080,6 +4101,7 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) { driver_version_table[i].lopart_lo); gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi, driver_version_table[i].hipart_lo); + strcpy(gl_info->driver_description, driver_version_table[i].description); break; } } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 5fa991520df..61c5701f02c 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -100,7 +100,7 @@ struct glsl_shader_prog_link { GLint vuniformI_locations[MAX_CONST_I]; GLint puniformI_locations[MAX_CONST_I]; GLint posFixup_location; - GLint rectFixup_location[MAX_FRAGMENT_SAMPLERS]; + GLint np2Fixup_location[MAX_FRAGMENT_SAMPLERS]; GLint bumpenvmat_location[MAX_TEXTURES]; GLint luminancescale_location[MAX_TEXTURES]; GLint luminanceoffset_location[MAX_TEXTURES]; @@ -503,21 +503,21 @@ static void shader_glsl_load_np2fixup_constants( return; } - if (prog->ps_args.texrect_fixup) { + if (prog->ps_args.np2_fixup) { UINT i; - UINT fixup = prog->ps_args.texrect_fixup; + UINT fixup = prog->ps_args.np2_fixup; const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; const IWineD3DStateBlockImpl* stateBlock = (const IWineD3DStateBlockImpl*) deviceImpl->stateBlock; for (i = 0; fixup; fixup >>= 1, ++i) { - if (-1 != prog->rectFixup_location[i]) { + if (-1 != prog->np2Fixup_location[i]) { const IWineD3DBaseTextureImpl* const tex = (const IWineD3DBaseTextureImpl*) stateBlock->textures[i]; if (!tex) { FIXME("Non-existant texture is flagged for NP2 texcoord fixup\n"); continue; } else { const float tex_dim[2] = {tex->baseTexture.pow2Matrix[0], tex->baseTexture.pow2Matrix[5]}; - GL_EXTCALL(glUniform2fvARB(prog->rectFixup_location[i], 1, tex_dim)); + GL_EXTCALL(glUniform2fvARB(prog->np2Fixup_location[i], 1, tex_dim)); } } } @@ -825,12 +825,12 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i); } - if(ps_args->texrect_fixup & (1 << i)) { - /* RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] + if(ps_args->np2_fixup & (1 << i)) { + /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] * while D3D has them in the (normalized) [0,1]x[0,1] range. - * samplerRectFixup stores texture dimensions and is updated through - * shader_glsl_load_constants when the sampler changes. */ - shader_addline(buffer, "uniform vec2 %csamplerRectFixup%u;\n", prefix, i); + * samplerNP2Fixup stores texture dimensions and is updated through + * shader_glsl_load_np2fixup_constants when the sampler changes. */ + shader_addline(buffer, "uniform vec2 %csamplerNP2Fixup%u;\n", prefix, i); } break; case WINED3DSTT_CUBE: @@ -1505,7 +1505,6 @@ static void shader_glsl_color_correction(const struct wined3d_shader_instruction dst = ins->dst[0]; dst.write_mask = mask; - dst.token = (dst.token & ~WINED3DSP_WRITEMASK_ALL) | dst.write_mask; shader_glsl_add_dst_param(ins, &dst, &dst_param); arguments[0] = '\0'; @@ -1549,7 +1548,7 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s const char *sampler_base; char dst_swizzle[6]; struct color_fixup_desc fixup; - BOOL rect_fixup = FALSE; + BOOL np2_fixup = FALSE; va_list args; shader_glsl_get_swizzle(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); @@ -1560,11 +1559,11 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s fixup = This->cur_args->color_fixup[sampler]; sampler_base = "Psampler"; - if(This->cur_args->texrect_fixup & (1 << sampler)) { + if(This->cur_args->np2_fixup & (1 << sampler)) { if(bias) { - FIXME("Biased sampling from RECT textures is unsupported\n"); + FIXME("Biased sampling from NP2 textures is unsupported\n"); } else { - rect_fixup = TRUE; + np2_fixup = TRUE; } } } else { @@ -1583,8 +1582,8 @@ static void PRINTF_ATTR(6, 7) shader_glsl_gen_sample_code(const struct wined3d_s if(bias) { shader_addline(ins->buffer, ", %s)%s);\n", bias, dst_swizzle); } else { - if (rect_fixup) { - shader_addline(ins->buffer, " * PsamplerRectFixup%u)%s);\n", sampler, dst_swizzle); + if (np2_fixup) { + shader_addline(ins->buffer, " * PsamplerNP2Fixup%u)%s);\n", sampler, dst_swizzle); } else { shader_addline(ins->buffer, ")%s);\n", dst_swizzle); } @@ -1976,9 +1975,7 @@ static void shader_glsl_cmp(const struct wined3d_shader_instruction *ins) cmp_channel = WINED3DSP_WRITEMASK_0 << j; } } - dst.write_mask = dst_mask & write_mask; - dst.token = (dst.token & ~WINED3DSP_WRITEMASK_ALL) | dst.write_mask; /* Splitting the cmp instruction up in multiple lines imposes a problem: * The first lines may overwrite source parameters of the following lines. @@ -2059,7 +2056,6 @@ static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins) } dst.write_mask = dst_mask & write_mask; - dst.token = (dst.token & ~WINED3DSP_WRITEMASK_ALL) | dst.write_mask; write_mask = shader_glsl_append_dst_ext(ins->buffer, ins, &dst); if (!write_mask) continue; @@ -2140,7 +2136,6 @@ static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) for (i = 0; i < nComponents; ++i) { tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i; - tmp_dst.token = (tmp_dst.token & ~WINED3DSP_WRITEMASK_ALL) | tmp_dst.write_mask; tmp_ins.src[1] = ins->src[1] + i; shader_glsl_dot(&tmp_ins); } @@ -3595,14 +3590,14 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use } } - if (use_ps && ps_compile_args.texrect_fixup) { + if (use_ps && ps_compile_args.np2_fixup) { char name[32]; for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (ps_compile_args.texrect_fixup & (1 << i)) { - sprintf(name, "PsamplerRectFixup%u", i); - entry->rectFixup_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); + if (ps_compile_args.np2_fixup & (1 << i)) { + sprintf(name, "PsamplerNP2Fixup%u", i); + entry->np2Fixup_location[i] = GL_EXTCALL(glGetUniformLocationARB(programId, name)); } else { - entry->rectFixup_location[i] = -1; + entry->np2Fixup_location[i] = -1; } } } diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index de609a7fc26..d1701f5c1a4 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -460,7 +460,7 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set */ args->srgb_correction = stateblock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0; - args->texrect_fixup = 0; + args->np2_fixup = 0; for(i = 0; i < MAX_FRAGMENT_SAMPLERS; i++) { if(shader->baseShader.reg_maps.samplers[i] == 0) continue; @@ -473,7 +473,7 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp /* Flag samplers that need NP2 texcoord fixup. */ if(!tex->baseTexture.pow2Matrix_identity) { - args->texrect_fixup |= (1 << i); + args->np2_fixup |= (1 << i); } } if (shader->baseShader.reg_maps.shader_version >= WINED3DPS_VERSION(3,0)) diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 32fba083c49..fdd8cd8b35e 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -174,10 +174,6 @@ static void vshader_set_input( unsigned int regnum, BYTE usage, BYTE usage_idx) { - /* Fake register; set reserved bit, regnum, type: input, wmask: all */ - DWORD reg_token = (0x1 << 31) | - WINED3DSP_WRITEMASK_ALL | (WINED3DSPR_INPUT << WINED3DSP_REGTYPE_SHIFT) | regnum; - This->semantics_in[regnum].usage = usage; This->semantics_in[regnum].usage_idx = usage_idx; This->semantics_in[regnum].reg.register_type = WINED3DSPR_INPUT; @@ -186,7 +182,6 @@ static void vshader_set_input( This->semantics_in[regnum].reg.modifiers = 0; This->semantics_in[regnum].reg.shift = 0; This->semantics_in[regnum].reg.has_rel_addr = FALSE; - This->semantics_in[regnum].reg.token = reg_token; This->semantics_in[regnum].reg.addr_token = 0; } diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index 6fc02ddd47b..cc760351af8 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -3908,6 +3908,7 @@ typedef struct _WineD3D_GL_Info { UINT vidmem; DWORD driver_version; DWORD driver_version_hipart; + CHAR driver_description[255]; CHAR gl_renderer[255]; /** * CAPS Constants diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a5ae4661bec..3d911de4821 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -452,7 +452,6 @@ struct wined3d_shader_dst_param DWORD modifiers; DWORD shift; BOOL has_rel_addr; - DWORD token; DWORD addr_token; }; @@ -538,8 +537,8 @@ struct ps_compile_args { /* Projected textures(ps 1.0-1.3) */ /* Texture types(2D, Cube, 3D) in ps 1.x */ BOOL srgb_correction; - WORD texrect_fixup; - /* Bitmap for texture rect coord fixups (16 samplers max currently). + WORD np2_fixup; + /* Bitmap for NP2 texcoord fixups (16 samplers max currently). D3D9 has a limit of 16 samplers and the fixup is superfluous in D3D10 (unconditional NP2 support mandatory). */ }; diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 36f1c5a4315..2f345e38d00 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -44,6 +44,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "winreg.h" #include "winnls.h" #include "x11drv.h" #include "wine/server.h" @@ -1618,6 +1619,48 @@ static HKL get_locale_kbd_layout(void) return (HKL)layout; } +/*********************************************************************** + * GetKeyboardLayoutName (X11DRV.@) + */ +BOOL CDECL X11DRV_GetKeyboardLayoutName(LPWSTR name) +{ + static const WCHAR formatW[] = {'%','0','8','l','x',0}; + DWORD layout; + LANGID langid; + + layout = main_key_tab[kbd_layout].lcid; + /* see comment for get_locale_kbd_layout */ + langid = PRIMARYLANGID(LANGIDFROMLCID(layout)); + if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) + layout |= 0xe001 << 16; /* FIXME */ + + sprintfW(name, formatW, layout); + TRACE("returning %s\n", debugstr_w(name)); + return TRUE; +} + +static void set_kbd_layout_preload_key(void) +{ + static const WCHAR preload[] = + {'K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','\\','P','r','e','l','o','a','d',0}; + static const WCHAR one[] = {'1',0}; + + HKEY hkey; + WCHAR layout[KL_NAMELENGTH]; + + if (RegCreateKeyExW(HKEY_CURRENT_USER, preload, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL)) + return; + + if (!RegQueryValueExW(hkey, one, NULL, NULL, NULL, NULL)) + { + RegCloseKey(hkey); + return; + } + if (X11DRV_GetKeyboardLayoutName(layout)) + RegSetValueExW(hkey, one, 0, REG_SZ, (const BYTE *)layout, sizeof(layout)); + + RegCloseKey(hkey); +} /********************************************************************** * X11DRV_InitKeyboard @@ -1635,6 +1678,8 @@ void X11DRV_InitKeyboard( Display *display ) const char (*lkey)[MAIN_LEN][4]; char vkey_used[256] = { 0 }; + set_kbd_layout_preload_key(); + wine_tsx11_lock(); XDisplayKeycodes(display, &min_keycode, &max_keycode); ksp = XGetKeyboardMapping(display, min_keycode, @@ -1906,29 +1951,6 @@ HKL CDECL X11DRV_GetKeyboardLayout(DWORD dwThreadid) /*********************************************************************** - * GetKeyboardLayoutName (X11DRV.@) - */ -BOOL CDECL X11DRV_GetKeyboardLayoutName(LPWSTR name) -{ - static const WCHAR formatW[] = {'%','0','8','l','x',0}; - DWORD layout; - LANGID langid; - - layout = main_key_tab[kbd_layout].lcid; - /* see comment for get_locale_kbd_layout */ - langid = PRIMARYLANGID(LANGIDFROMLCID(layout)); - if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) - layout |= 0xe001 << 16; /* FIXME */ - else - layout |= layout << 16; - - sprintfW(name, formatW, layout); - TRACE("returning %s\n", debugstr_w(name)); - return TRUE; -} - - -/*********************************************************************** * LoadKeyboardLayout (X11DRV.@) */ HKL CDECL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags) diff --git a/tools/c2man.pl b/tools/c2man.pl index 4272b734c68..b1fd0222f97 100755 --- a/tools/c2man.pl +++ b/tools/c2man.pl @@ -629,7 +629,7 @@ sub process_comment($) # When the function is exported twice we have the second name below the first # (you see this a lot in ntdll, but also in some other places). - my $first_line = ${@{$comment->{TEXT}}}[1]; + my $first_line = ${$comment->{TEXT}}[1]; if ( $first_line =~ /^(@|[A-Za-z0-9_]+) +(\(|\[)([A-Za-z0-9_]+)\.(([0-9]+)|@)(\)|\])$/ ) { @@ -644,14 +644,14 @@ sub process_comment($) my $alt_export = @{$spec_details->{EXPORTS}}[$alt_index]; @$alt_export[4] |= $FLAG_DOCUMENTED; $spec_details->{NUM_DOCS}++; - ${@{$comment->{TEXT}}}[1] = ""; + ${$comment->{TEXT}}[1] = ""; } } if (@{$spec_details->{CURRENT_EXTRA}}) { # We have an extra comment that might be related to this one - my $current_comment = ${@{$spec_details->{CURRENT_EXTRA}}}[0]; + my $current_comment = ${$spec_details->{CURRENT_EXTRA}}[0]; my $current_name = $current_comment->{COMMENT_NAME}; if ($comment->{COMMENT_NAME} =~ /^$current_name/ && $comment->{COMMENT_NAME} ne $current_name) { @@ -822,12 +822,12 @@ sub process_comment($) if ( $prototype =~ /(WINAPIV|WINAPI|__cdecl|PASCAL|CALLBACK|FARPROC16)/ ) { - $prototype =~ s/^(.*?) (WINAPIV|WINAPI|__cdecl|PASCAL|CALLBACK|FARPROC16) (.*?)\( *(.*)/$4/; + $prototype =~ s/^(.*?)\s+(WINAPIV|WINAPI|__cdecl|PASCAL|CALLBACK|FARPROC16)\s+(.*?)\(\s*(.*)/$4/; $comment->{RETURNS} = $1; } else { - $prototype =~ s/^(.*?)([A-Za-z0-9_]+)\( *(.*)/$3/; + $prototype =~ s/^(.*?)([A-Za-z0-9_]+)\s*\(\s*(.*)/$3/; $comment->{RETURNS} = $1; } @@ -988,7 +988,7 @@ sub process_extra_comment($) if (@{$spec_details->{CURRENT_EXTRA}}) { - my $current_comment = ${@{$spec_details->{CURRENT_EXTRA}}}[0]; + my $current_comment = ${$spec_details->{CURRENT_EXTRA}}[0]; if ($opt_verbose > 0) { @@ -1074,7 +1074,7 @@ sub process_index_files() if (@{$spec_details->{CURRENT_EXTRA}}) { # We have an unwritten extra comment, write it - my $current_comment = ${@{$spec_details->{CURRENT_EXTRA}}}[0]; + my $current_comment = ${$spec_details->{CURRENT_EXTRA}}[0]; process_extra_comment($current_comment); @{$spec_details->{CURRENT_EXTRA}} = (); } @@ -1470,7 +1470,7 @@ sub output_api_synopsis($) my $biggest_length = 0; for(my $i=0; $i < @{$comment->{PROTOTYPE}}; $i++) { - my $line = ${@{$comment->{PROTOTYPE}}}[$i]; + my $line = ${$comment->{PROTOTYPE}}[$i]; if ($line =~ /(.+?)([A-Za-z_][A-Za-z_0-9]*)$/) { my $length = length $1; @@ -1484,19 +1484,19 @@ sub output_api_synopsis($) # Now pad the string with blanks for(my $i=0; $i < @{$comment->{PROTOTYPE}}; $i++) { - my $line = ${@{$comment->{PROTOTYPE}}}[$i]; + my $line = ${$comment->{PROTOTYPE}}[$i]; if ($line =~ /(.+?)([A-Za-z_][A-Za-z_0-9]*)$/) { my $pad_len = $biggest_length - length $1; my $padding = " " x ($pad_len); - ${@{$comment->{PROTOTYPE}}}[$i] = $1.$padding.$2; + ${$comment->{PROTOTYPE}}[$i] = $1.$padding.$2; } } for(my $i=0; $i < @{$comment->{PROTOTYPE}}; $i++) { # Format the parameter name - my $line = ${@{$comment->{PROTOTYPE}}}[$i]; + my $line = ${$comment->{PROTOTYPE}}[$i]; my $comma = ($i == @{$comment->{PROTOTYPE}}-1) ? "" : ","; $line =~ s/(.+?)([A-Za-z_][A-Za-z_0-9]*)$/ $fmt[0]$1$fmt[2]$2$fmt[3]$comma$fmt[1]/; print OUTPUT $line; -- 2.11.4.GIT