From dbd51933f2514fec0feaf432041cee4c15453dd9 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Fri, 27 Jul 2007 18:00:46 +0200 Subject: [PATCH] push 739d3025d82fc820f7a9c38697877dd3d18e8c13 --- ANNOUNCE | 998 +++++++++++---------- ChangeLog | 1735 +++++++++++++++++++++++++++++++++++++ VERSION | 2 +- configure | 18 +- dlls/advapi32/service.c | 65 +- dlls/advapi32/tests/service.c | 128 ++- dlls/comctl32/commctrl.c | 2 +- dlls/crypt32/crypt32_private.h | 4 + dlls/crypt32/decode.c | 97 ++- dlls/crypt32/encode.c | 32 +- dlls/crypt32/msg.c | 178 +++- dlls/crypt32/tests/encode.c | 55 ++ dlls/crypt32/tests/msg.c | 70 +- dlls/d3d9/texture.c | 2 +- dlls/dsound/dsound_main.c | 22 +- dlls/dsound/mixer.c | 49 +- dlls/gdiplus/gdiplus.c | 4 +- dlls/gdiplus/gdiplus.spec | 6 +- dlls/gdiplus/gdiplus_private.h | 2 + dlls/gdiplus/graphics.c | 1 + dlls/gdiplus/graphicspath.c | 30 + dlls/gdiplus/pen.c | 44 + dlls/gdiplus/tests/graphicspath.c | 71 ++ dlls/gdiplus/tests/pen.c | 68 ++ dlls/kernel32/actctx.c | 80 +- dlls/kernel32/tests/Makefile.in | 1 + dlls/kernel32/tests/actctx.c | 1058 ++++++++++++++++++++++ dlls/mshtml/editor.c | 36 +- dlls/mshtml/navigate.c | 17 +- dlls/mshtml/nsembed.c | 4 +- dlls/mshtml/nsiface.idl | 2 +- dlls/mshtml/nsservice.c | 2 +- dlls/msi/alter.c | 12 +- dlls/msi/create.c | 3 +- dlls/msi/custom.c | 1 + dlls/msi/delete.c | 3 +- dlls/msi/distinct.c | 5 +- dlls/msi/insert.c | 3 +- dlls/msi/join.c | 30 +- dlls/msi/msipriv.h | 10 +- dlls/msi/msiquery.c | 120 +-- dlls/msi/order.c | 19 +- dlls/msi/select.c | 81 +- dlls/msi/streams.c | 12 +- dlls/msi/table.c | 28 +- dlls/msi/tests/db.c | 174 ++++ dlls/msi/update.c | 3 +- dlls/msi/where.c | 22 +- dlls/msvcrt/dir.c | 12 +- dlls/msvcrt/heap.c | 2 +- dlls/msvcrt/msvcrt.h | 2 - dlls/msvcrt/string.c | 17 - dlls/msvcrt/wcs.c | 17 - dlls/ntdll/actctx.c | 662 ++++++++++++-- dlls/ntdll/loader.c | 119 +++ dlls/ntdll/ntdll.spec | 4 +- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/serial.c | 1 - dlls/oleaut32/tmarshal.c | 6 +- dlls/oleaut32/typelib2.c | 8 +- dlls/opengl32/wgl.c | 1 - dlls/urlmon/http.c | 76 +- dlls/urlmon/tests/protocol.c | 215 +++-- dlls/version/info.c | 6 + dlls/winealsa.drv/dsoutput.c | 9 +- dlls/wined3d/context.c | 2 + dlls/wined3d/device.c | 90 +- dlls/wined3d/directx.c | 20 +- dlls/wined3d/state.c | 7 +- dlls/wined3d/surface.c | 30 + dlls/wined3d/surface_gdi.c | 6 - dlls/wined3d/wined3d_main.c | 7 +- dlls/wineoss.drv/dsrender.c | 2 +- dlls/winex11.drv/opengl.c | 466 +++++----- dlls/wininet/http.c | 25 +- dlls/winmm/time.c | 6 +- dlls/winspool.drv/info.c | 366 +++++--- include/gdiplusflat.h | 3 + include/winternl.h | 4 + libs/wine/loader.c | 8 +- programs/winefile/winefile.c | 119 +-- 81 files changed, 6242 insertions(+), 1486 deletions(-) rewrite ANNOUNCE (93%) create mode 100644 dlls/kernel32/tests/actctx.c diff --git a/ANNOUNCE b/ANNOUNCE dissimilarity index 93% index 787c9880f30..afba9b2333c 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,478 +1,520 @@ -This is release 0.9.41 of Wine, a free implementation of Windows on Unix. - -What's new in this release: - - A number of gdiplus functions. - - More complete pdh.dll implementation. - - Support for MSI remote calls. - - Messaging support in crypt32.dll. - - Lots of bug fixes. - -Because of lags created by using mirrors, this message may reach you -before the release is available at the public sites. The sources will -be available from the following locations: - - http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.41.tar.bz2 - http://prdownloads.sourceforge.net/wine/wine-0.9.41.tar.bz2 - -Binary packages for various distributions will be available from: - - http://www.winehq.org/site/download - -You will find documentation on - - http://www.winehq.org/site/documentation - -You can also get the current source directly from the git or CVS -repositories. Check respectively http://www.winehq.org/site/git or -http://www.winehq.org/site/cvs for details. - -If you fix something, please submit a patch; instructions on how to do -this can be found at http://www.winehq.org/site/sending_patches - -Wine is available thanks to the work of many people. See the file -AUTHORS in the distribution for the complete list. - ----------------------------------------------------------------- - -Changes since 0.9.40: - -Alexander Nicolaysen Sørnes (3): - comdlg32: fontdlg: Respect the CF_NOSCRIPTSEL flag. - wordpad: Disable copy/cut in menu when appropriate. - wordpad: Prompt for saving file changes. - -Alexandre Julliard (41): - configure: Fix the strip command line for Mac OS. - configure: Export the shared library extension instead of hardcoding .so. - configure: Don't use a default soname if a library is not found, leave it undefined. - configure: Don't set LDPATH if not needed. - configure: Change WINE_GET_SONAME to allow it to be used as a replacement for AC_CHECK_LIB. - configure: Move the dll checks earlier in the file to make them available for library checks. - configure: Merge the libhal existence check with the soname check. - configure: Merge the libcurses existence check with the soname check. - configure: Merge the libcapi20 existence check with the soname check. - configure: Merge the libsane existence check with the soname check. - configure: Make the libcups soname check depend on the header check. - configure: Make the libjack soname check depend on the header check. - configure: Make the libfontconfig soname check depend on the header check. - configure: Make the libssl soname check depend on the header check. - configure: Make the libjpeg soname check depend on the header check. - configure: Added checks for libpng. - ntdll: Add check for null pointer in NtQuerySystemInformation(SystemModuleInformation). - configure: Merge the libGL existence check with the soname check. - configure: Merge the libXrandr existence check with the soname check. - configure: Merge the libXrender existence check with the soname check. - configure: Merge the libXinerama existence check with the soname check. - configure: Get rid of the no longer used check for libtxc_dxtn. - Maketest.rules: Add dependency on IDL headers for crosstest objects. - configure: Make the libXcursor soname check depend on the header check. - configure: Make the libXi soname check depend on the header check. - configure: Merge the libfreetype existence check with the soname check. - configure: Merge the libX11 and libXext existence check with the soname check. - configure: We no longer need the shared library extension. - aclocal: Add macros for logging messages about missing features. - configure: Move notices about missing features next to the corresponding checks. - configure: Add a few more notices for missing packages. - include: Add some definitions for manifest resources. - winedump: Add RT_MANIFEST resource type. - configure: Fix typo in liblcms notice check. - kernel32: Implemented GetTickCount64. - user32/tests: Flush messages more aggressively in a couple of tests. - msi/tests: Comment out call to function that is still a stub in Wine. - user32: Check both A and W proc for previously allocated winprocs. - user32: Allocate a dual A/W winproc for DefWindowProc. - dnsapi: Fix some potential infinite loops because of an unsigned loop counter. - wldap32: Fix some potential infinite loops because of an unsigned loop counter. - -Anatoly Lyutin (1): - cmd: Use toupperW instead of toupper. - -Andrew Talbot (10): - ole32: Constify some variables. - oleaut32: Constify some variables. - ole32: Constify some variables. - winelib: Cast-qual warnings fix. - ole32: Constify a variable (and fix a typo concerning its level of indirection). - ole32: Cast-qual warnings fix. - comdlg32: Cast-qual warning fix. - ole32: Cast-qual warning fix. - winedump: Cast-qual warnings fix. - winedump: Cast-qual warnings fix. - -Aric Stewart (4): - imm32: Implementation of GCS_CURSORPOS. - include: Add a ddk header for imm. - imm32: Implement Locking/Unlocking IMC and IMCC functions. - imm32: Use the COMPOSITIONSTRING in hCompStr. - -Ben Hodgetts (2): - ws2_32: Don't tell users to run Wine as root when sockets not creatable. - winecfg: Clean up Graphics tab and remove broken neutral translation. - -Bernd Buschinski (1): - gdiplus: Fix test typo/compile error. - -Chris Robinson (4): - winemp3: Check the right macro when defining TRUE. - winemp3: Use head_check to check for valid headers. - winemp3: Remove global mpstr pointer. - winemp3: Remove function declarations with no definition and unused macros. - -Damjan Jovanovic (2): - shell32: DragQueryFile doesn't count the null terminator. - ntdll: Use the win16 current directory for win16 processes. - -Detlef Riekenberg (4): - setupapi: Avoid crash in SetupCloseInfFile. - advpack+setupapi: Remove unneeded checks before SetupCloseInfFile. - ntdll: Avoid crash with WINEDEBUG=+snoop. - printui: Parse args for PrintUIEntryW. - -Dmitry Timoshkov (4): - gdi32: Do not report an error if a requested to add font is already loaded. - include: Add HandleToUlong, UlongToHandle, UintToPtr, UlongToPtr compatibility macros. - ntdll: Remove an artificial limitation in NtQuerySecurityObject. - shlwapi: Fix some spec entry definitions. - -Emmanuel Maillard (1): - winecoreaudio: MIDIIn_MessageHandler: Fix non-SysEx messages parsing. - -Evan Stade (50): - oleaut32: Added support for decoding some PNG files. - oleaut32: Save load time format of pictures. - gdiplus: Use SaveDC, RestoreDC in GdipDrawLineI. - gdiplus: Call EndPath() in GdipDrawLineI in case there is an open path. - gdi32: Don't access DC in PolyDraw after releasing handle. - gdiplus: Added SetPenEndCap. - gdiplus: Rendering of linecaps. - gdiplus: Added linecap rendering for GdipDrawBezier. - gdiplus: Public declaration of GdipSetPenEndCap. - gdiplus: Added GdipAddPathLine2. - gdiplus: Added GdipClosePathFigure. - gdiplus: Added GdipClosePathFigures. - gdiplus: Added GdipGetPointCount. - gdiplus: Added GdipGetPathPoints. - gdiplus: Added GdipGetPathTypes. - gdiplus: Updated draw_pie to use SaveDC/RestoreDC. - gdiplus: Updated GdipDrawRectangleI. - gdiplus: GdipDrawCurve2 now uses SaveDC()/RestoreDC() and end caps. - gdiplus: Fixed a bug in helper function draw_polybezier. - gdiplus: Make LineCapArrowAnchor look more like it does in windows. - gdiplus: Added constructor and destructor test for gdiplus paths. - gdiplus: Fixed bug in GdipGetPathPoints(). - gdiplus: Added a test for GdipAddPathLine2. - gdiplus: Changed calls to floor to floorf. - gdiplus: Moved two inline helpers to the header. - gdiplus: Added GdipAddPathArc. - gdiplus: Added GdipAddPathArc test. - gdiplus: Updated GdipDrawArc to use SaveDC()/RestoreDC()/line caps. - gdiplus: Updated GdipDrawLines to use SaveDC()/RestoreDC()/end caps. - gdiplus: Added GdipStartPathFigure. - gdiplus: Added GdipDrawPath. - gdiplus: Added draw_polybezier error checking. - gdiplus: Added draw_polyline error checking. - gdiplus: Added basic matrix implementation. - gdiplus: Added GdipTransformMatrixPoints. - gdiplus: Added GdipCreateMatrix2 test. - gdiplus: Added GdipTransformPath. - gdiplus: Added GdipGetPathWorldBounds. - gdiplus: Fixed memory leak in GdipDeletePath. - gdiplus: Added GdipTransformMatrixPoints test. - gdiplus: Added GdipGetPathWorldBounds test. - gdiplus: Changed the way the direction of the endcap is calculated to make LineCapArrowAnchor direction match Windows better. - gdiplus: Added GdipSetPenLineJoin. - gdiplus: Use passed pen in GdipAddPathWorldBound. - gdiplus: Added more GdipGetPathWorldBounds tests. - gdiplus: Improved GdipGetPathWorldBounds handling of both matrix and pen's effect on bounding box. - gdiplus: Added GdipGetPathFillMode. - gdiplus: Added GdipResetPath. - gdiplus: Added GdipAddPathPath. - gdiplus: Added GdipAddPathPath test. - -Francois Gouget (3): - ddraw/tests: Fix compilation on systems that don't support nameless unions. - Assorted spelling fixes. - ddraw/tests: Fix compilation on systems that don't support nameless unions. - -H. Verbeet (8): - wined3d: Call IWineD3DDeviceImpl_FindTexUnitMap for cards without support for NV_REGISTER_COMBINERS as well. - wined3d: Only call activate_dimensions() if the texture is used. - wined3d: Only set GL_SHADER_OPERATION_NV to GL_NONE for supported units. - wined3d: In tex_colorop() & tex_alphaop(), only check the mapped stage against GL_LIMITS(textures) if the texture is used. - wined3d: Cleanup shader_glsl_load_psamplers(). - wined3d: Implement dsx & dsy shader instructions. - wined3d: Advertise A32B32G32R32F render target support. - wined3d: Advertise VTF support. - -Hans Leidekker (9): - dwmapi: Add a stub implementation for DwmIsCompositionEnabled. - pdh: Add tests for opening and closing queries. - pdh: Add an uptime counter source based on GetTickCount. - pdh: Add tests for Pdh{Add, Remove}Counter and PdhCollectQueryData. - pdh: Implement and test PdhSetCounterScaleFactor and PdhGetFormattedCounterValue. - pdh: Implement and test PdhGetRawCounterValue. - pdh: Implement and test PdhGetCounterInfo{A, W} and PdhGetCounterTimeBase. - pdh: Use GetTickCount64 instead of GetTickCount. - pdh: Fix two typos. - -Huw Davies (6): - winex11.drv: Pass root_window to XCreatePixmap to avoid BadDrawable errors. - winex11.drv: Move the PictFormats into an array. - winex11.drv: Use global Pictures for the tiles. - gdi32: Using a bitmap font as the fallback sans serif is a very bad idea. - kernel32: Swap incorrect use of buffers. - kernel32: SetNamedPipeHandleState() is a stub, so for now don't check its return value. - -James Hawkins (56): - msi: Implement MsiSourceListGetInfoA. - msi: Add tests for MsiSourceListGetInfo. - msi: Validate MsiSourceListGetInfo parameters. - msi: Return ERROR_BAD_CONFIGURATION if the SourceList key does not exist. - msi: Return ERROR_SUCCESS if the PackageName property is not present. - msi: Add the IWineMsiRemotePackage interface. - msi: Add the IWineMsiRemoteCustomAction interface. - msi: Handle remote calls to MsiGetActiveDatabase. - msi: Handle remote calls to MsiGetProperty. - msi: Handle remote calls to MsiSetProperty. - msi: pcchValue represents the length of szValue in TCHARS, not bytes. - msi: Add support for the MSICODE_PATCH option. - msi: Add tests to show when the SourceList is published to the registry. - msi: PackagePath must also include the package name. - msi: Delay publishing of the SourceList until the PublishProduct action. - msi: Unpublish the product when it is entirely removed. - msi: Only publish the product if at least one feature is to be installed. - msi: Set the WindowsInstaller value in RegisterProduct instead of PublishProduct. - msi: Add tests for MsiQueryFeatureState. - msi: Open the correct key and return INSTALLSTATE_ADVERTISED if it's missing. - msi: Return INSTALLSTATE_ADVERTISED if the component list is empty. - msi: Return INSTALLSTATE_BADCONFIG if we can't decode the first component. - msi: Read the components state directly from the registry. - msi: Handle remote calls to MsiProcessMessage. - msi: Handle remote calls to MsiDoAction. - msi: Handle remote calls to MsiSequence. - msi: Handle remote calls to MsiGetTargetPath. - msi: Handle remote calls to MsiGetSourcePath. - msi: Handle remote calls to MsiSetTargetPath. - msi: Handle remote calls to MsiGetMode. - msi: Handle remote calls to MsiSetFeatureState. - msi: Handle remote calls to MsiGetFeatureState. - msi: Handle remote calls to MsiGetComponentState. - msi: Handle remote calls to MsiSetComponentState. - msi: Handle remote calls to MsiGetLanguage. - msi: Handle remote calls to MsiSetInstallLevel. - msi: Fix use of BSTRs. - msi: Handle remote calls to MsiFormatRecordW. - msi: Forward MsiFormatRecordA to MsiFormatRecordW. - msi: Handle remote calls to MsiEvaluateCondition. - msi: Enable remote custom actions. - msi: Match the changes made by the hand-generated and API-generated transforms. - msi: Delete msifile after the tests. - msi: Test adding columns with data in a transform. - msi: Handle adding columns in transforms. - msi: Check for NULL transform, as there may be no transforms for the _Columns or _Tables tables. - msi: Fix current _Property table tests and add more tests. - msi: Add tests for adding properties in a transform. - msi: Add tests for adding properties with a transform during an install. - msi: Fix a copy and paste error. - msi: Reload properties as they may have been changed by a transform. - msi: Fix automation.c compile for MSVC. - msi: Fix three tests that were failing in Windows. - msi: Fix compilation in MSVC. - msi: Add a test for installing from different current working directories. - msi: Add a test for running an ADMIN install. - -Juan Lang (44): - crypt32: Use skip to avoid failures where support is missing. - crypt32: Don't fail when CryptVerifyCertificateSignatureEx is missing, use skip (and get rid of unnecessary indenting). - crypt32: Accept OSS errors. - crypt32: Accept OSS errors as well. - crypt32: Accept ERROR_BADKEY in addition to ERROR_INVALID_HANDLE. - crypt32: Accept ERROR_INVALID_PARAMETER in addition to ERROR_PATH_NOT_FOUND (and remove no-longer-useful checkFileStoreFailure). - crypt32: Pass function pointers to CryptMsgBase_Init rather than rely on callers to initialize them. - crypt32: Add more tests for opening a data message for encoding. - crypt32: Make a copy of a passed-in stream info rather than assuming the pointer will live forever. - crypt32: Test that inner content OID is ignored for data messages. - crypt32: Add tests for streamed encoding of data messages. - crypt32: Test and fix CryptMsgGetParam for streamed messages. - crypt32: Add a stub decode message implementation. - crypt32: Implement getting the type of a decode message. - crypt32: Add some tests for updating decode messages. - crypt32: More decode message update tests. - crypt32: Implement CryptSIPLoad. - crypt32: Implement CryptSIPGetSignedDataMsg, CryptSIPPutSignedDataMsg, - rsaenh: Get rid of the hash idle state, native doesn't behave as though it has one. - crypt32: Make some encoding functions available outside encode.c. - crypt32: Implement streamed encoding of definite-length data messages. - crypt32: Add open tests for hash messages. - crypt32: Add tests for updating hash messages opened to encode. - crypt32: Test opening hash messages to encode with streaming. - crypt32: Add a stub hash message implementation. - crypt32: Add tests for getting hash message params. - crypt32: Implement getting a hash message's hash value. - crypt32: Simplify hash value tests. - crypt32: Test updating hash messages with NULL stream output function. - crypt32: Partially implement updating hash messages. - crypt32: Add more missing defines. - crypt32: Implement getting hash message version. - crypt32: Add tests for hash message encoding. - crypt32: Copy data in hash message update. - crypt32: Add a helper function to copy params. - crypt32: Don't check if msg is NULL, tests show native doesn't either. - crypt32: Detached hash messages don't contain the content, so don't make a copy of it. - crypt32: Add tests for retrieving the content of a non-finalized (detached) message. - crypt32: Introduce an algorithm id encoding function that encodes missing parameters as NULL - crypt32: Implement retrieving a hashed message's content. - crypt32: Relax a test, the specific error isn't so important. - crypt32: Change finalized from a boolean to a state and use it to simplify message updating. - crypt32: Introduce an updated state, and use it to remove boolean "begun". - crypt32: Update comments about hash message version numbers. - -Julio E. Gonzalez P (1): - ntdll: Add PYT and PYST time zones. - -Kai Blin (1): - ws2_32: Handle IPv6 in WSAStringToAddress. - -Ken Thomases (6): - winecoreaudio: Enable DirectSound HEL mode for output. - winecoreaudio: Enable DirectSound HEL mode for input. - winecoreaudio: Improve safety of iterations when returning WAVEHDRs to client. - winecoreaudio: Correct the AudioBufferList allocated for input. - winecoreaudio: Protect against AudioUnitRender clobbering our buffer list. - winecoreaudio: Report format error on sample rate mismatch when opening wave-in device. - -Kovács András (1): - d3d10: Add stub for d3d10.dll. - -Lei Zhang (2): - start.exe: Put double quotes around arguments with spaces. - winex11.drv: Remove old dnd code. - -Maarten Lankhorst (6): - winealsa: Silence the buffer warning more often. - dsound: Revert "dsound: Disable property sets if hardware doesn't support it.". - dsound: Clean up some unused variables. - dsound: Remove some more unused variables. - dsound: Fix division by zero in DSOUND_Calc3DBuffer. - dsound: Simplify IDirectSoundBufferImpl_GetCurrentPosition. - -Mark Adams (2): - iphlpapi: Add support for GetTcpTable on Mac OS X. - iphlpapi: Fix byte ordering of Linux ports. - -Markus Gömmel (2): - comctl32/datetime: Added a missing InvalidateRect to update display after WM_ENABLE. - user32: Center MessageBox dialogs to desktop, as Windows does. - -Michael Stefaniuc (2): - ntdll: Fix missing unlock on error path. Found by Smatch. - msvcrt: Remove superfluous casts of void pointers to other pointer types. - -Mikołaj Zalewski (2): - comctl32: toolbar: The iImage in TBN_GETDISPINFO should be initialized to -1. - comctl32: toolbar: We should send TBN_GETDISPINFOW even for ANSI controls (with testcase). - -Misha Koshelev (7): - gdi32: Slightly simplify result handling in PolyDraw. - urlmon/tests: Make http protocol mime type test pass on native. - urlmon: Improve ObtainUserAgentString conformance to native. - urlmon/tests: Add tests for ObtainUserAgentString. - urlmon: Implement HttpProtocol. - urlmon: Fix HttpProtocol_Start and strndupW to work properly with native wininet. - urlmon: Make HttpProtocol conform with native wininet on wine. - -Paul Vriens (29): - advapi32/tests: Add tests for OpenSCManagerA. - user32/tests: Use skip. - user32/tests: Use skip. - advapi32/tests: Use skip when we don't have enough rights. - advpack/tests: Create the temporary inf-file in a directory where we are allowed to write. - kernel32/tests: Use skip when functions are not available. - kernel32/tests: Don't crash on win98. - kernel32/tests 2/2: Use skip for not implemented function. - advapi32/tests: Use skip for not implemented function. - secur32/tests: Use skip when functions are not available. - advapi32/tests: Add tests for OpenServiceA. - advapi32/tests: Add tests for CloseServiceHandle. - ddraw/tests: Use skip instead of trace. - ddraw/tests: Use skip instead of trace. - kernel32/tests: Add a forgotten if statement. - advapi32: Handle to Service Control Manager is checked first. - advapi32: Create specific access rights for service control manager handles. - gdiplus: Don't use struct member before NULL check (Coverity). - advapi/service: Simplify DeleteService by using RegDeleteTree. - advapi/service: Fix possible handle leak. - advapi/service: First tests (and fixes) for CreateService. - advapi/service: Check if we have enough access rights to create a service. - advapi/service: Check for empty servicename and binaryname. - programs/cmd: Do the assignment after the return to avoid a missing free() (Coverity). - advapi/service: Create specific access rights for service handles. - advapi/service: Check servicetype and starttype. - advapi32/tests: Use skip instead of trace. - crypt32/tests: Skip test if we don't have enough rights. - mscms/tests: Skip tests if we don't have enough rights. - -Pedro Araujo Chaves Jr (1): - winspool.drv: Fallback to the first found printer as default printer. - -Peter Dons Tychsen (1): - winex11: Fix X11DRV_DIB_GetImageBits() when target bitmaps are larger than fetched. - -Rob Shearman (9): - secur32: Don't free the password in InitializeSecurityContextW to enable the credentials handle to be re-used in further InitializeSecurityContextW calls. - secur32: Add tests for multiple use of a credential handle. - rpcrt4: Translate between NCA and RPC status codes. - rpcrt4: Call RPCRT4_Send directly from PKT_RECEIVE handler in server. - rpcrt4: Return a fault packet if the proc num exceeds the index of the last function available for the interface. - ntdll: The impersonation level in NtDuplicateToken should be taken from the SecurityQualityOfService member of ObjectAttributes if present. - rpcrt4: Make binding to an interface a function of RpcAssoc instead of - msxml3: Implement IXMLDOMNode::get_text for CDATA, processing instruction and comment nodes. - mshtml: Implement HTMLElement_insertAdjacentHTML and HTMLElement_insertAdjacentText. - -Romain Iehl (3): - dsound: Fix bug preventing correct calculation of the sound parameters - dsound: Simplify the calculation of sound attenuation due to distance. - dsound: Correct field access. - -Stefan Dösinger (19): - wined3d: rsq and rcp use the .w component if no swizzle is given. - wined3d: Select onscreen contexts based on the thread id. - wined3d: Create multiple contexts for onscreen render targets. - ddraw: Z buffers can be attached to offscreen d3d devices. - ddraw: Fix an incorrect iface->impl cast. - ddraw: Materials in the execute buffer are handles. - ddraw: D3DOP_BRANCHFORWARD includes the current instruction size. - ddraw: Read the world matrix correctly. - ddraw: Implement IDirect3DViewport3::TransformVertices. - wined3d: Offscreen rendering from foreign threads. - ddraw: Update the wined3d matrix if a current matrix handle is modified. - ddraw: Y coords are inversed. - wined3d: Do not set streamIsUP in DrawPrimitiveStrided. - wined3d: Implement high order patches. - wined3d: Initialize surfaces at creation. - wined3d: Print the fixed and unfixed vertex warning only when needed. - wined3d: Add CTXUSAGE_CLEAR context usage. - wined3d: Make ActivateContext a bit smaller. - wined3d: Store the last active thread. - -Thomas Weidenmueller (2): - shell32: Set current directory when executing files in a shell view. - shlwapi: Use publicly defined structure DATABLOCK_HEADER instead of redefining it locally. - -Tim Schwartz (1): - net.exe: Converted strings to resources. - -Vitaliy Margolen (9): - dinput: Correct test - use appropriate mouse state structure. - dinput: Keep the list of all the dinput devices created for each IDIrectInput object. - dinput: Keep a list of all IDirectInput objects and check it instead of refcount to create/destroy hook thread. - dinput: Export Mouse and Keyboard GUIDs. - dinput: Handle multiple keyboard and mouse devices. - dinput: Rename set_dinput_hook and call it from the base class. - dinput: Clear static variables after releasing hooks. - dinput: Convert IDirectInput into multi-interface object. - dxdiagn: Add reporting of some display related information. - --- -Alexandre Julliard -julliard@winehq.org +This is release 0.9.42 of Wine, a free implementation of Windows on Unix. + +What's new in this release: + - Support for activation contexts and side-by-side assemblies. + - Many more gdiplus functions. + - More messaging support in crypt32.dll. + - Many HTTP protocol handling fixes. + - Lots of bug fixes. + +Because of lags created by using mirrors, this message may reach you +before the release is available at the public sites. The sources will +be available from the following locations: + + http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.42.tar.bz2 + http://prdownloads.sourceforge.net/wine/wine-0.9.42.tar.bz2 + +Binary packages for various distributions will be available from: + + http://www.winehq.org/site/download + +You will find documentation on + + http://www.winehq.org/site/documentation + +You can also get the current source directly from the git or CVS +repositories. Check respectively http://www.winehq.org/site/git or +http://www.winehq.org/site/cvs for details. + +If you fix something, please submit a patch; instructions on how to do +this can be found at http://www.winehq.org/site/sending_patches + +Wine is available thanks to the work of many people. See the file +AUTHORS in the distribution for the complete list. + +---------------------------------------------------------------- + +Changes since 0.9.41: + +Alec Berryman (1): + itss: Replace malloc/free with HeapAlloc/HeapFree. + +Alexander Nicolaysen Sørnes (3): + wordpad: Add date/time dialog. + wordpad: Add date/time toolbar button. + wordpad: Resize rebar control on window resize. + +Alexandre Julliard (38): + kernel32: Wait in overlapped Read/WriteFile even when no overlapped structure is passed. + server: Merge APC processing into the select request. + kernel32: Always clear the I/O status block count before calling ntdll functions. + widl: Added support for floating-point constants. + winealsa: Make sure we can set volume before reporting WAVECAPS_VOLUME. + ntdll: Move private data to make room in the TEB for the activation context data. + kernel32: Move activation context creation to ntdll (based on a patch by Eric Pouech). + ntdll: Implemented handling of the per-thread activation context stack. + ntdll: Add infrastructure for loading a manifest file or resource. + ntdll: Add parsing of the processor architecture in manifests. + ntdll: Add parsing of the version in manifests (based on a patch by Jacek Caban). + ntdll: Add infrastructure for loading manifest dependencies (based on a patch by Eric Pouech). + ntdll: Abstract the entity array type as we need it for assemblies too. + ntdll: Added manifest lookup in global winsxs directory (based on a patch by Jacek Caban). + ntdll: Skip xml comments in manifests. + ntdll: Cope with missing assemblyIdentity elements in manifests. + ntdll: Add support for optional flag in dependencies. + ntdll: Don't fail to load manifests that contain unknown elements or attributes. + ntdll: Add support for abbreviated empty elements in manifests. + gdi32/tests: Don't test default char, it doesn't have to be always the same. + user32/tests: Flush events more aggressively in mouse input test. + ntdll: Check existing dependencies in activation context before adding a new one. + ntdll: Don't add an empty assembly when creating an activation context. + ntdll: Create the process activation context at initialization time. + ntdll: Create the per-module activation context at module load time. + ntdll: Store the base directory for an assembly (based on a patch by Eric Pouech). + ntdll: Improve some activation context traces. + ntdll: Fix return status when failing to load the associated manifest for a module. + ntdll: Initial implementation of RtlQueryInformationActivationContext. + ntdll: Use activation contexts information to load dlls (based on a patch by Jacek Caban). + ntdll: Activate the module's activation context while resolving imports and attaching. + ntdll: Support single quotes around XML attribute values. + crypt32: Don't use off_t for memory offsets. + libwine: Get rid of the lookup in the top dlls/ dir, all dlls are named correctly now. + ntdll: Simply store the assembly type without interpreting it. + msvcrt: Fixed buffer allocation in _getcwd/_wgetcwd. + msvcrt: Fixed errno setting in malloc, HeapAlloc doesn't set last error. + msvcrt: Get rid of the now unused strndup/wstrndup functions. + +Anatoly Lyutin (3): + user32: Add comment to a function. + cmd: Use toupperW instead of toupper. + kernel32/tests: Add test for GetShortPathNameW. + +Andrew Talbot (11): + winedump: Cast-qual warnings fix. + comdlg32: Cast-qual warning fix. + dplayx: Cast-qual warning fix. + dbghelp: Cast-qual warnings fix. + comctl32: Cast-qual warning fix. + kernel32: Cast-qual warning fix. + comcat: Cast-qual warning fix. + msi: Cast-qual warning fix. + msxml3: Cast-qual warning fix. + oleaut32: Constify some variables. + oleaut32: Constify some variables. + +Aric Stewart (3): + user32: Change SetDeskWallPaper spec. + ws2_32: Initialize the address to 0 in ws_sockaddr_ws2u. + wininet: Strip Accept-Encoding from http/1.0 requests. + +Damjan Jovanovic (4): + ws2_32: Update WSASendTo's iovec properly. + tools: Associate wine with the application/x-executable MIME type. + tools: Add basic support for the startup notifications standard. + ws2_32: Sending 0 bytes shouldn't cause an infinite loop. + +Detlef Riekenberg (8): + include/winspool.h: Add missing struct. + spoolss: Add a stub for ImpersonatePrinterClient. + winspool: Use printenv_t for GetDriverInfoFromReg. + winspool: Use correct path for 16bit drivers. + winspool: Return the full path for the driver. + winspool: Enable all levels for EnumPrinterDrivers + GetPrinterDriver. + winspool: Return the full path in DRIVER_INFO_2 and 3. + winspool: Return most fields for DRIVER_INFO_4 and 6. + +Dmitry Timoshkov (6): + shlwapi: Fix parameter types of SHGetIniStringW. + shell32: Add a cache for queried shell folder interfaces. + rpcrt4: Fix the buffer bounds check. + winuser.h: Add RealChildWindowFromPoint declaration. + winex11.drv: Constify the pen dash data. + advapi32: Rename the test to better represent the tested functionality. + +Eric Pouech (14): + ntdll: Added basic structures for storing activation context assembly information. + ntdll: Added support for the assembly leaves of activation contexts. + ntdll: Added parsing of public key token in manifests. + ntdll: Added parsing of hash attributes in manifests. + ntdll: Added parsing of the inheritance flags in manifests. + ntdll: Added parsing of the language attribute in manifests. + ntdll: Added parsing of the description element in manifests. + ntdll: Added parsing of the external proxy element in manifests. + ntdll: Added parsing of the clrClass and clrSurrogate elements in manifests. + ntdll: Added parsing of the binding redirect element in manifests. + ntdll: Implemented ActivationContextDetailedInformation option in RtlQueryInformationActivationContext. + ntdll: Implemented AssemblyDetailedInformationInActivationContext option in RtlQueryInformationActivationContext. + ntdll: Implemented FileInformationInAssemblyOfAssemblyInActivationContext option in RtlQueryInformationActivationContext. + ntdll: Implemented RtlFindActivationContextSectionString. + +Evan Stade (73): + gdiplus: Added GdipSetPathFillMode. + gdiplus: Added smoothing modes. + gdiplus: Added compositing quality. + gdiplus: Added interpolation mode. + gdiplus: Added pixel offset mode. + gdiplus: GdipSaveGraphics/GdipRestoreGraphics stubs. + gdiplus: Constructor tests for GpGraphics. + gdiplus: Added GpGraphics save/restore tests. + gdiplus: Simplified GdipDrawPath by moving more of the code to the helpers. + gdiplus: Added GdipFillPath. + gdiplus: Added GdipSetPenLineCap197819. + gdiplus: Export GdipSetPenLineJoin. + gdiplus: Added GdipSetPenMiterLimit. + gdiplus: Initial path iterator implementation. + gdiplus: Added GdipPathIterCopyData. + gdiplus: Added GdipPathIterNextSubpath. + gdiplus: Added GdipPathIterRewind. + gdiplus: Added GdipSetPenDashStyle. + gdiplus: Added GdipAddPathBeziers. + gdi32: Added PolyDraw tests. + gdi32: Added PATH_PolyDraw. + gdiplus: Added GdipClonePen. + gdiplus: Added GdipGetPenDashStyle. + gdiplus: Added GdipMultiplyMatrix. + winex11.drv: Draw dashed lines for extended pens. + gdi32: Improved PolyDraw in path closed case. + gdiplus: Added GdipScaleMatrix. + gdiplus: Added GdipTranslateMatrix. + gdiplus: Added GdipRotateMatrix. + gdiplus: Added GdipCreateMatrix. + gdiplus: Initial custom line caps implementation. + gdiplus: Added GdipCloneCustomLineCap. + gdiplus: Added custom line cap setters. + gdiplus: Use atan2 instead of atan. + gdiplus: Added rendering of custom line caps. + gdiplus: Associate a brush with a pen. + gdiplus: Added GdipCloneBrush. + gdiplus: Updated GdipClonePen to clone pen's members by value, not reference. + gdiplus: Added GdipSetPenStartCap. + gdiplus: Added rendering of fill-path type custom line caps. + gdiplus: Use base inset for custom line caps. + gdiplus: Added startcap rendering. + gdiplus: Change atan2 to gdiplus_arctan2. + gdiplus: Added GdipSetPenBrushFill. + gdiplus: Added GdipGetPenColor stub. + gdiplus: Added GdipGetPenBrushFill. + gdiplus: Added GdipSetSolidFillColor and GdipGetSolidFillColor stubs. + gdiplus/tests: Added pen brush fill test. + gdiplus: Implemented GdipSetSolidFillColor/GdipGetSolidFillColor. + gdiplus: Implemented GdipSetPenColor. + gdiplus: Added GdipFillPolygonI. + gdiplus: Added GdipSetPageUnit. + gdiplus: Use page unit when drawing. + gdiplus: Added support for more page units. + gdiplus: Added GdipSetPageScale/GdipGetPageScale. + gdiplus: Added GdipCloneMatrix. + gdiplus: Added GdipSetWorldTransform/GdipGetWorldTransform. + gdiplus: Use world transform when drawing points. + gdiplus: Create gdi pen every time gdi+ pen is used. + gdiplus: Make pen width depend on world transform. + gdiplus: Added GdipCreateMetafileFromEmf stub. + gdiplus: Image getter stubs. + gdiplus: Limit fixme output. + gdiplus: Added GdipGetImageType stub. + gdiplus: Added GdipCreateMetafileFromWmf stub. + gdiplus: Added GdipDisposeImage stub. + gdiplus: Added GdipLoadImageFromStreamICM stub. + gdiplus: Fix memory leak. + gdiplus: Added GdipAddPathEllipse. + gdiplus/tests: Added GdipAddPathEllipse test. + gdiplus: Fix arc2polybezier. + gdiplus: Added GdipSetPenDashArray/GdipGetPenDashArray. + gdiplus/tests: Added pen dash array tests. + +H. Verbeet (10): + wined3d: Fix STATE_IS_ACTIVELIGHT. + wined3d: glXSwapBuffers needs a GLX context. + wined3d: Correctly handle normalized vertex declaration data types. + wined3d: Fix the shader version on some instruction tokens. + wined3d: Don't modify the blending parameters in state_blend(). + wined3d: Trace the declaration element type in primitiveDeclarationConvertToStridedData(). + wined3d: Pass the correct target to glMultiTexCoord. + wined3d: Fix the stretch_rect_fbo() declaration to match the implementation. + d3d9: Trace the Format parameter to IDirect3DDevice9Impl_CreateTexture as hexadecimal. + wined3d: Flip the scissor rect when rendering offscreen. + +Hans Leidekker (4): + pdh: Add a stub processor time counter. + pdh: Add more tests and make them pass. + pdh: Implement and test PdhLookupPerfIndexByName{A, W} and PdhLookupPerfNameByIndex{A, W}. + pdh: Implement and test PdhAddEnglishCounter{A, W} and PdhCollectQueryDataWithTime. + +Huw Davies (4): + kernel32: Overlapped pipe tests. + wininet: Certain options of InternetQueryOption can take a NULL handle, so don't do the NULL handle check at the beginning. + wininet: Stubs for IsUrlCacheEntryExpired[AW]. + wininet: Stub for InternetQueryFortezzaStatus(). + +Hwang YunSong(황윤성) (5): + cmd: Updated Korean resource. + wordpad: Updated Korean resource. + localui: New Korean resource. + wordpad: Updated Korean resource. + net: New Korean resource. + +Jacek Caban (10): + ntdll: Beginnings of manifest parsing. + ntdll: Add parsing of dependencies in manifests. + ntdll: Added parsing of file elements in manifests. + ntdll: Added parsing of the asmv2:hash element in manifests. + ntdll: Store the windows directory too. + kernel32: Added FindActCtxSectionStringA implementation. + urlmon: Change some gotos to return. + mshtml: Make sure we have associated listener before calling OnStopRequest. + kernel32: Added a number of activation context tests. + mshtml: Fixed a typo. + +James Hawkins (16): + msi: Load the AdminProperties stream if the package is an Admin package. + msi: Only call a custom action remotely if the type is msidbCustomActionTypeInScript. + vdmdbg: Add a stub implementation of VDMEnumTaskWOW. + Revert "msi: Only call a custom action remotely if the type is msidbCustomActionTypeInScript." + msi: Only double the size if the remote call is from MsiGetPropertyA. + msi: Add more tests for the ALTER command. + msi: Implement reference counting for tables, manipulated with the HOLD and FREE sql commands. + msi: Implement adding columns using the ALTER command. + msi: Ref count temporary columns and release them when necessary. + msi: Properly delete the columns view. + msi: Add tests for the MSIMODIFY_UPDATE command. + msi: Add handling for the MSIMODIFY_UPDATE command. + msi: Use a different separator as a semi-colon may separate values in the CustomActionData. + msi: Add more tests for MSIMODIFY_UPDATE. + msi: Initialize the size parameter. + msi: Implement the MSIMODIFY_UPDATE command in the SELECT view. + +Jason Edmeades (4): + user32: Correct trace to log calculated values rather than uninitialized ones. + user32: MDI tile and cascade should not resize non-resizable windows. + cmd: Fix trap when batch pgm runs another batch pgm. + comctl32: Fix missing toolbar button with HINST_COMMCTRL. + +Jeremy White (2): + gdi32: Do not fill in the color table if lpvBits is NULL. + gdi32: Added a test for the case where lpvBits in GetDIBits is NULL and the bitcount is 0. + +Juan Lang (51): + crypt32: Add test showing extra trailing bytes should be tolerated in encoded data. + crypt32: Fix decoding sequences with extra trailing data. + crypt32: Store crypt provider in decode message. + crypt32: Partially implement updating decode messages. + crypt32: Implement decoding data messages (when opened in non-streaming mode). + crypt32: Move digested data encoding to encode.c. + crypt32: Add tests for decoding a hash message. + crypt32: Remove a redundant line. + crypt32: Implement decoding hash messages. + crypt32: Fix a bad comment. + crypt32: Add a few tests for decoded message parameters. + crypt32: Implement getting content of a data message. + crypt32: Use property list for decoded message parameters. + crypt32: Fix typo. + crypt32: Add a couple more parameter tests for hash messages. + wincrypt: Add more missing definitions. + msi: Return FALSE from MsiGetMode for MSIRUNMODE_OPERATIONS. + crypt32: Store (most) parameters of a decoded hash message. + crypt32: Store hash algorithm ID along with other parameters when decoding a hash message. + crypt32: Implement querying computed hash of a decoded hash message. + crypt32: Move decoding hash messages to a helper function. + crypt32: Add tests for opening signed message to encode. + crypt32: Add stub encoded signed message. + crypt32: Introduce function to encode an array of items as a set. + crypt32: Check for and fail on indefinite-length encoding. + crypt32: Add tests for updating signed encoded messages. + crypt32: Add tests for signed message encoding. + crypt32: Add a partial stub for updating a signed encoded message. + crypt32: Add tests for opening non-detached signed messages, and clarify detached open. + crypt32: More parameter checking for opening signed encoded messages. + crypt32: Hash and sign data when updating signed messages. + crypt32: Implement getting the hash for each signer of a signed encoded message. + crypt32: Partially implement encoding signed messages. + crypt32: Implement getting outer content of a signed message. + crypt32: Separate signer handles from signer info to avoid unnecessary memory allocation. + crypt32: Use consistent types for storing and encoding signed encode data. + crypt32: Add tests for getting an encoded signed message's parameters. + crypt32: Implement getting version from an encoded signed message. + crypt32: Use set encoding function for encoding PKCS signed info. + crypt32: Test and implement encoding signed messages with certificates. + crypt32: Test and implement encoding signed data messages with CRLs. + crypt32: Test and implement getting the encoded signers from an encoded signed message. + crypt32: Test getting the hash from a hash message with an invalid index. + crypt32: Add initial tests for decoding signed messages. + crypt32: Remove redundant assignment. + crypt32: Actually skip content when skipping an item in a sequence. + crypt32: Don't check tag in CRYPT_DecodeDERArray, caller already does. + crypt32: Partially implement decoding of signed messages. + crypt32: Test and fix encoding and decoding of attributes in PKCS signers. + crypt32: Trace a few more items when decoding. + crypt32: Test and implement encoding signed messages with authenticated attributes. + +Kirill K. Smirnov (2): + shell32: Add support for SEE_MASK_NO_CONSOLE flag. + programs/start: use SEE_MASK_NO_CONSOLE flag as default. + +Konstantin Kondratyuk (1): + ntdll: Add Samara time zone. + +Kovács András (1): + include: Add some idl headers for d3d10. + +Maarten Lankhorst (7): + dsound: Make sure secondary_remainder and buflen are aligned to primary buffer in mixer. + dsound: Fix CheckEvent in mixer. + dsound: Some cosmetic changes. + winealsa: Minor fixes to ds output. + wineoss: Make sure writepos < buflen for dsrender. + winmm: Don't operate on freed data in timer. + dsound: Allow mixing the same buffer multiple times if we are looping. + +Marcus Meissner (1): + crypt32: Fixed wrong allocation size. + +Martin Fuchs (1): + shell32: Implementation of SheGetDirA/W and SheChangeDirA/W. + +Matt Jones (2): + kernel32: Added test for bad arguments to SetThreadPriority, test for correct error value. + server: Only commit SetThreadPriority if new priority is correct. + +Michael Stefaniuc (17): + shell32: Fix missing unlock on an error path. Found by Smatch. + wined3d: Remove unreachable code: break after return. Found by Smatch. + ntdll: Don't produce unreachable code during conditional compilation. Found by Smatch. + winhelp: Add missing case label "default". Found by Smatch (unreached code). + dlls: Remove unreachable break after return/break. Found by Smatch. + programs: Remove unreachable break after return/break. Found by Smatch. + tools: Remove unreachable break after return/break. Found by Smatch. + oleaut32: Remove a return after return. + winefile: Replace malloc with HeapAlloc. + wldap32: Don't produce unreachable code during conditional compilation. Found bySmatch. + winefile: Move some self contained functions to use explicit W functions. + winefile: Change the settings functions to use the W registry functions. + mscms: Don't produce unreachable code during conditional compilation. + wined3d: Remove a return after a return. Found by Smatch. + winefile: Move the font choosing code to a separate function. + winefile: Change choose_font() and init_output() to the W form. + ntdll: Remove a break after a break. Found by Smatch. + +Mikołaj Zalewski (4): + msxml3/tests: Avoid a crash that happens on some native systems. + comctl32: toolbar: Test and fix invalid indexes passed in TB_ISBUTTON*. + comctl32: tooltips: Remove broken support for non-NULL-terminated strings in TOOLTIPS_GetDispInfo[AW]. + user32/tests: Simplify a test. + +Misha Koshelev (31): + wininet/tests: Properly handle ERROR_IO_PENDING from InternetQueryDataAvailable. + wininet/tests: Add testing framework and tests for internet status callbacks. + urlmon: Fix HttpProtocol behavior when InternetQueryDataAvailable returns ERROR_IO_PENDING. + wininet: Fix behavior of InternetQueryDataAvailable if INTERNET_FLAG_ASYNC is set. + urlmon: Remove FLAG_CALLED_SWITCH, which is now redundant. + urlmon: Use InternetCloseHandle instead of CloseHandle. + urlmon/tests: Fix http_protocol tests to succeed on Win98. + urlmon/tests: Fix http_protocol tests to succeed when called more than once. + urlmon: Fix HttpProtocol behavior when it is called without the BINDF_FROMURLMON flag. + urlmon: Implement HttpProtocol::Terminate. + urlmon/tests: Add tests for HttpProtocol behavior when it is called without the BINDF_FROMURLMON flag. + urlmon/tests: Add test for BINDVERB_POST in http_protocol. + urlmon: Call HttpOpenRequest with INTERNET_FLAG_KEEP_CONNECTION, INTERNET_FLAG_NO_CACHE_WRITE if appropriate. + urlmon: Actually send the additional headers returned by IHttpNegotiate::BeginningTransaction. + urlmon: Add support for non-GET requests (e.g., POST) in HttpProtocol. + urlmon: Fix timing issue with FLAG_REQUEST_COMPLETE and InternetQueryDataAvailable in HttpProtocol. + urlmon: Don't ignore bytes read from IInternetProtocol_Read if hres is not S_OK (e.g., E_PENDING). + urlmon: ReleaseBindInfo in FileProtocol. + urlmon: Add a reference to the IUnknown for Release of STGMEDIUM to account for extra call to ReleaseBindInfo. + urlmon/tests: Add tests for calls to IBindStatusCallback_QueryInterface. + urlmon/tests: Add tests for calls to IHttpNegotiate interfaces as exposed by IBindStatusCallback. + urlmon: Wrap IHttpNegotiate2 interface exposed by IBindStatusCallback as done by native. + urlmon: If we are using an internal protocol ClassFactory, call its AddRef as the caller must Release the object. + urlmon: LockModule in create_binding_protocol as we ReleaseModule when the object is released. + urlmon: Release IInternetProtocolInfo returned from get_protocol_info when finished with it. + urlmon/tests: Release two objects that should be released but are not. + urlmon: Don't free structures that are used by asynchronous HttpSendRequest until we are sure they won't be used. + urlmon/tests: Fix http protocol tests with absence of BINDF_FROMURLMON to properly expect ReportData. + urlmon/tests: Don't proceed with POST operation (that will fail) if we run out of memory. + urlmon/tests: Rename received_data event to more general name event_complete. + urlmon/tests: Make http protocol tests refractory to timing issues. + +Nigel Liang (2): + winex11.drv: Implement XIMPreEditCaretCallback. + winex11.drv: Take into account position of preedit area in PreEditCaretCallback. + +Paul Vriens (18): + msi/tests: Don't create a directory that's not needed. + advapi32/service: Check combination of service-type and start-type. + advapi32/service: Test for duplicate displayname. + advapi32/service: Cleanup (long lines and a typo). + advapi32/service: Check for duplicate displayname. + advapi32/service: Some tests for DeleteService. + advapi32/service: lpBinaryPathName is mandatory. + advapi32/service: Some 'refcount' tests. + advapi32/tests: Run on NT4 again. + advapi32/service: Add tests for GetDisplayName. + advapi32/service: Handle is checked before servicename. + advapi32/service: Add another test for GetServiceDisplayName. + advapi32/service: Close a handle on failure. + advapi32/service: Add tests for GetServiceKeyName. + advapi32/service: More tests for GetServiceDisplayName. + advapi32/service: Test GetServiceDisplayNameA for service with no displayname. + advapi32/service: Forward GetServiceDisplayNameA to GetServiceDisplayNameW. + advapi32/service: Fix buffersize calculations for GetServiceDisplayNameW. + +Peter Dons Tychsen (1): + x11drv: Fix the special case where windows have WS_CHILD and WS_POPUP. + +Rob Shearman (18): + ole32: Remove some dead code. + rpcrt4: Even though FC_ENUM16 is an unsigned type, the highest allowable value that can be marshalled is SHRT_MAX, not USHRT_MAX. + rpcrt4: Check to make sure there is enough data in the buffer during unmarshalling, so that the code doesn't try to read beyound the end of the buffer. + rpcrt4: Never allocate memory for the discriminant in union_arm_unmarshall as the memory is part of the union and has already been allocated. + rpcrt4: Add some more RPC to NCA status code mappings. + advapi32: Fix ComputeStringSidSize to work with SIDs with one sub authority. + advapi32: Fix a typo in ParseStringAclToAcl which caused the ACE to be written inside of the ACL memory. + advapi32: Add the size of the security descriptor structure to the size of memory required in ParseStringSecurityDescriptorToSecurityDescriptor. + advapi32: Don't crash in ConvertStringSecurityDescriptorToSecurityDescriptorW if LocalAlloc fails. + advapi32: Set the right pointer so that StringAcl is updated correct in ParseAceStringRights. + advapi32: Add tests for ConvertStringSecurityDescriptorToSecurityDescriptor. + rpcrt4: Convert bind ack and nack reject reasons into RPC status codes when binding. + mshtml: OleDocumentView_UIActivate should call IOleInPlaceUIWindow_SetActiveObject and IOleInPlaceFrame_SetBorderSpace. + mshtml: Pass the correct DOCHOSTUITYPE value to IDocHostUIHandler_ShowUI. + mshtml: Call IDocHostUIHandler_HideUI and IDocHostUIHandler_ShowUI when changing an UI active window to be in edit mode. + mshtml: Set focus to the Gecko window in OleInPlaceActiveObject_OnFrameWindowActivate. + mshtml: Events are reset when a new document URI is loaded, so re-initialise them in start_binding. + mshtml: Handle Ctrl-Home and Ctrl-End in edit mode. + +Roderick Colenbrander (7): + opengl32: Relax extension checking. + opengl: WGL_ARB_render_texture support. + wgl: Set pbuffer dimensions in HDC. + wgl: Fill the format table with offscreen pixelformats which are needed for pbuffers. + wgl: Replace the GLXFBConfigIDs in the pixelformat list with real GLXFBConfigs. + wgl: Enable offscreen pixelformats for pbuffers. + wgl: Fix a typo in the WGL_TEXTURE_TARGET_ARB emulation code. + +Stefan Dösinger (7): + ddraw: Some d3d-only code fixes. + wined3d: Create the stateblock in Init3D. + wined3d: Attempt to clean up fbos only if a gl surface is destroyed. + wined3d: Allocate render target management members in Init3D. + wined3d: Find the shader constant limit at adapter init time. + wined3d: Set the pow2 sizes in gl surface private setup. + wined3d: Do not fail if the adapter info can't be initialized. + +Steven Edwards (1): + version: VerQueryValueA/W NULL pointer check. + +Tim Schwartz (1): + netapi32: Add NetUseAdd() stub. + +Vitaliy Margolen (9): + msvcrt: Preserve registers when calling unwind function. + pdh: Forward PdhOpenQuery to PdhOpenQueryW. + dinput: Use PostMessage instead of SendMessage. Remove message window. + dinput: Use CALLWINDPROC hook to monitor focus loses away from acquired windows. + user32/test: Destroy no longer needed test dialog windows. + user32: Add test for SetForegroundWindow(desktop). + server: Treat desktop as a top-level window. + winex11drv: Correctly react to focus loss away from Wine. + dinput: Use more messages as a possible indication of the foreground window changes. + +-- +Alexandre Julliard +julliard@winehq.org diff --git a/ChangeLog b/ChangeLog index 1920a10163f..adf0a8d8004 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1738 @@ +2007-07-26 Paul Vriens + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Fix buffersize calculations for GetServiceDisplayNameW. + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Forward GetServiceDisplayNameA to GetServiceDisplayNameW. + + * dlls/advapi32/tests/service.c: + advapi32/service: Test GetServiceDisplayNameA for service with no displayname. + + * dlls/advapi32/tests/service.c: + advapi32/service: More tests for GetServiceDisplayName. + +2007-07-26 Aric Stewart + + * dlls/wininet/http.c: + wininet: Strip Accept-Encoding from http/1.0 requests. + +2007-07-26 Detlef Riekenberg + + * dlls/winspool.drv/info.c: + winspool: Return most fields for DRIVER_INFO_4 and 6. + + * dlls/winspool.drv/info.c: + winspool: Return the full path in DRIVER_INFO_2 and 3. + + * dlls/winspool.drv/info.c: + winspool: Enable all levels for EnumPrinterDrivers + GetPrinterDriver. + + * dlls/winspool.drv/info.c: + winspool: Return the full path for the driver. + + * dlls/winspool.drv/info.c: + winspool: Use correct path for 16bit drivers. + +2007-07-27 Misha Koshelev + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Make http protocol tests refractory to timing issues. + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Rename received_data event to more general name event_complete. + +2007-07-27 Jacek Caban + + * dlls/mshtml/nsembed.c, dlls/mshtml/nsiface.idl, dlls/mshtml/nsservice.c: + mshtml: Fixed a typo. + +2007-07-26 James Hawkins + + * dlls/msi/alter.c, dlls/msi/create.c, dlls/msi/delete.c, + dlls/msi/distinct.c, dlls/msi/insert.c, dlls/msi/join.c, + dlls/msi/msipriv.h, dlls/msi/msiquery.c, dlls/msi/order.c, + dlls/msi/select.c, dlls/msi/streams.c, dlls/msi/table.c, + dlls/msi/tests/db.c, dlls/msi/update.c, dlls/msi/where.c: + msi: Implement the MSIMODIFY_UPDATE command in the SELECT view. + + * dlls/msi/custom.c: + msi: Initialize the size parameter. + + * dlls/msi/tests/db.c: + msi: Add more tests for MSIMODIFY_UPDATE. + +2007-07-12 Maarten Lankhorst + + * dlls/dsound/mixer.c: + dsound: Allow mixing the same buffer multiple times if we are looping. + +2007-07-19 Maarten Lankhorst + + * dlls/winmm/time.c: + winmm: Don't operate on freed data in timer. + +2007-07-24 Maarten Lankhorst + + * dlls/wineoss.drv/dsrender.c: + wineoss: Make sure writepos < buflen for dsrender. + +2007-07-19 Maarten Lankhorst + + * dlls/winealsa.drv/dsoutput.c: + winealsa: Minor fixes to ds output. + +2007-07-17 Maarten Lankhorst + + * dlls/dsound/dsound_main.c: + dsound: Some cosmetic changes. + +2007-07-12 Maarten Lankhorst + + * dlls/dsound/mixer.c: + dsound: Fix CheckEvent in mixer. + + * dlls/dsound/mixer.c: + dsound: Make sure secondary_remainder and buflen are aligned to primary buffer + in mixer. + +2007-07-26 Andrew Talbot + + * dlls/oleaut32/typelib2.c: + oleaut32: Constify some variables. + +2007-07-26 Steven Edwards + + * dlls/version/info.c: + version: VerQueryValueA/W NULL pointer check. + +2007-07-27 Roderick Colenbrander + + * dlls/winex11.drv/opengl.c: + wgl: Fix a typo in the WGL_TEXTURE_TARGET_ARB emulation code. + +2007-07-26 Roderick Colenbrander + + * dlls/winex11.drv/opengl.c: + wgl: Enable offscreen pixelformats for pbuffers. + + * dlls/winex11.drv/opengl.c: + wgl: Replace the GLXFBConfigIDs in the pixelformat list with real GLXFBConfigs. + + * dlls/winex11.drv/opengl.c: + wgl: Fill the format table with offscreen pixelformats which are needed for + pbuffers. + +2007-07-27 Alexandre Julliard + + * dlls/msvcrt/msvcrt.h, dlls/msvcrt/string.c, dlls/msvcrt/wcs.c: + msvcrt: Get rid of the now unused strndup/wstrndup functions. + + * dlls/msvcrt/heap.c: + msvcrt: Fixed errno setting in malloc, HeapAlloc doesn't set last error. + + * dlls/msvcrt/dir.c: + msvcrt: Fixed buffer allocation in _getcwd/_wgetcwd. + + * dlls/ntdll/actctx.c: + ntdll: Simply store the assembly type without interpreting it. + +2007-07-26 Jacek Caban + + * dlls/kernel32/tests/Makefile.in, dlls/kernel32/tests/actctx.c, + dlls/ntdll/actctx.c: + kernel32: Added a number of activation context tests. + +2007-07-25 Evan Stade + + * dlls/gdiplus/tests/pen.c: + gdiplus/tests: Added pen dash array tests. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPenDashArray/GdipGetPenDashArray. + + * dlls/gdiplus/gdiplus.c, dlls/gdiplus/tests/graphicspath.c: + gdiplus: Fix arc2polybezier. + + * dlls/gdiplus/tests/graphicspath.c: + gdiplus/tests: Added GdipAddPathEllipse test. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphicspath.c, + include/gdiplusflat.h: + gdiplus: Added GdipAddPathEllipse. + + * dlls/gdiplus/graphics.c: + gdiplus: Fix memory leak. + +2007-07-25 Juan Lang + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Test and implement encoding signed messages with authenticated + attributes. + + * dlls/crypt32/decode.c: + crypt32: Trace a few more items when decoding. + + * dlls/crypt32/decode.c, dlls/crypt32/encode.c, + dlls/crypt32/tests/encode.c: + crypt32: Test and fix encoding and decoding of attributes in PKCS signers. + + * dlls/crypt32/crypt32_private.h, dlls/crypt32/decode.c, + dlls/crypt32/msg.c: + crypt32: Partially implement decoding of signed messages. + + * dlls/crypt32/decode.c: + crypt32: Don't check tag in CRYPT_DecodeDERArray, caller already does. + + * dlls/crypt32/decode.c: + crypt32: Actually skip content when skipping an item in a sequence. + + * dlls/crypt32/msg.c: + crypt32: Remove redundant assignment. + + * dlls/crypt32/tests/msg.c: + crypt32: Add initial tests for decoding signed messages. + + * dlls/crypt32/tests/msg.c: + crypt32: Test getting the hash from a hash message with an invalid index. + +2007-07-26 Misha Koshelev + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Don't proceed with POST operation (that will fail) if we run + out of memory. + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Fix http protocol tests with absence of BINDF_FROMURLMON to + properly expect ReportData. + +2007-07-25 Misha Koshelev + + * dlls/urlmon/http.c: + urlmon: Don't free structures that are used by asynchronous HttpSendRequest + until we are sure they won't be used. + +2007-07-26 Alexandre Julliard + + * libs/wine/loader.c: + libwine: Get rid of the lookup in the top dlls/ dir, all dlls are named + correctly now. + + * dlls/crypt32/encode.c: + crypt32: Don't use off_t for memory offsets. + +2007-07-25 Rob Shearman + + * dlls/mshtml/editor.c: + mshtml: Handle Ctrl-Home and Ctrl-End in edit mode. + +2007-07-26 H. Verbeet + + * dlls/wined3d/context.c, dlls/wined3d/device.c, dlls/wined3d/state.c: + wined3d: Flip the scissor rect when rendering offscreen. + + * dlls/d3d9/texture.c: + d3d9: Trace the Format parameter to IDirect3DDevice9Impl_CreateTexture as + hexadecimal. + +2007-07-26 Jacek Caban + + * dlls/mshtml/navigate.c: + mshtml: Make sure we have associated listener before calling OnStopRequest. + + * dlls/urlmon/http.c: + urlmon: Change some gotos to return. + +2007-07-25 Michael Stefaniuc + + * dlls/ntdll/serial.c: + ntdll: Remove a break after a break. Found by Smatch. + + * programs/winefile/winefile.c: + winefile: Change choose_font() and init_output() to the W form. + + * programs/winefile/winefile.c: + winefile: Move the font choosing code to a separate function. + +2007-07-25 Roderick Colenbrander + + * dlls/winex11.drv/opengl.c: + wgl: Set pbuffer dimensions in HDC. + + * dlls/winex11.drv/opengl.c: + opengl: WGL_ARB_render_texture support. + + * dlls/opengl32/wgl.c: + opengl32: Relax extension checking. + +2007-07-25 Andrew Talbot + + * dlls/oleaut32/tmarshal.c: + oleaut32: Constify some variables. + +2007-07-25 Jason Edmeades + + * dlls/comctl32/commctrl.c: + comctl32: Fix missing toolbar button with HINST_COMMCTRL. + +2007-07-16 Stefan Dösinger + + * dlls/wined3d/device.c, dlls/wined3d/directx.c, + dlls/wined3d/wined3d_main.c: + wined3d: Do not fail if the adapter info can't be initialized. + + * dlls/wined3d/device.c, dlls/wined3d/surface.c, + dlls/wined3d/surface_gdi.c: + wined3d: Set the pow2 sizes in gl surface private setup. + + * dlls/wined3d/directx.c: + wined3d: Find the shader constant limit at adapter init time. + + * dlls/wined3d/device.c, dlls/wined3d/directx.c: + wined3d: Allocate render target management members in Init3D. + +2007-07-18 Stefan Dösinger + + * dlls/wined3d/device.c: + wined3d: Attempt to clean up fbos only if a gl surface is destroyed. + +2007-07-26 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Support single quotes around XML attribute values. + + * dlls/ntdll/loader.c: + ntdll: Activate the module's activation context while resolving imports and + attaching. + +2007-07-25 Alexandre Julliard + + * dlls/ntdll/loader.c: + ntdll: Use activation contexts information to load dlls (based on a patch by + Jacek Caban). + +2007-07-25 Jacek Caban + + * dlls/kernel32/actctx.c: + kernel32: Added FindActCtxSectionStringA implementation. + +2007-07-25 Eric Pouech + + * dlls/kernel32/actctx.c, dlls/ntdll/actctx.c, dlls/ntdll/ntdll.spec, + include/winternl.h: + ntdll: Implemented RtlFindActivationContextSectionString. + + * dlls/ntdll/actctx.c: + ntdll: Implemented FileInformationInAssemblyOfAssemblyInActivationContext + option in RtlQueryInformationActivationContext. + + * dlls/ntdll/actctx.c: + ntdll: Implemented AssemblyDetailedInformationInActivationContext option in + RtlQueryInformationActivationContext. + + * dlls/ntdll/actctx.c: + ntdll: Implemented ActivationContextDetailedInformation option in + RtlQueryInformationActivationContext. + +2007-07-25 Alexandre Julliard + + * dlls/kernel32/actctx.c, dlls/ntdll/actctx.c, dlls/ntdll/ntdll.spec, + include/winternl.h: + ntdll: Initial implementation of RtlQueryInformationActivationContext. + Partially based on a patch by Eric Pouech. + + * dlls/ntdll/actctx.c: + ntdll: Fix return status when failing to load the associated manifest for + a module. + +2007-07-26 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Improve some activation context traces. + +2007-07-25 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Store the base directory for an assembly (based on a patch by Eric + Pouech). + + * dlls/ntdll/loader.c, include/winternl.h: + ntdll: Create the per-module activation context at module load time. + + * dlls/ntdll/actctx.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll_misc.h: + ntdll: Create the process activation context at initialization time. + + * dlls/ntdll/actctx.c: + ntdll: Don't add an empty assembly when creating an activation context. + + * dlls/ntdll/actctx.c: + ntdll: Check existing dependencies in activation context before adding a new one. + +2007-07-25 Peter Dons Tychsen + + * dlls/winex11.drv/window.c: + x11drv: Fix the special case where windows have WS_CHILD and WS_POPUP. + +2007-07-24 Matt Jones + + * dlls/kernel32/tests/thread.c, server/thread.c: + server: Only commit SetThreadPriority if new priority is correct. + + * dlls/kernel32/tests/thread.c: + kernel32: Added test for bad arguments to SetThreadPriority, test for correct + error value. + +2007-07-24 Evan Stade + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/image.c: + gdiplus: Added GdipLoadImageFromStreamICM stub. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/image.c, include/gdiplusflat.h: + gdiplus: Added GdipDisposeImage stub. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphics.c, include/Makefile.in, + include/gdiplus.h, include/gdiplusflat.h, + include/gdiplusmetaheader.h: + gdiplus: Added GdipCreateMetafileFromWmf stub. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/image.c, include/gdiplusenums.h, + include/gdiplusflat.h: + gdiplus: Added GdipGetImageType stub. + + * dlls/gdiplus/graphics.c, dlls/gdiplus/pen.c: + gdiplus: Limit fixme output. + + * dlls/gdiplus/Makefile.in, dlls/gdiplus/gdiplus.spec, + dlls/gdiplus/image.c, include/gdiplusflat.h: + gdiplus: Image getter stubs. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphics.c, + include/gdiplusflat.h, include/gdiplusgpstubs.h: + gdiplus: Added GdipCreateMetafileFromEmf stub. + + * dlls/gdiplus/graphics.c: + gdiplus: Make pen width depend on world transform. + + * dlls/gdiplus/gdiplus_private.h, dlls/gdiplus/graphics.c, + dlls/gdiplus/pen.c: + gdiplus: Create gdi pen every time gdi+ pen is used. + + * dlls/gdiplus/graphics.c: + gdiplus: Use world transform when drawing points. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusflat.h: + gdiplus: Added GdipSetWorldTransform/GdipGetWorldTransform. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, include/gdiplusflat.h: + gdiplus: Added GdipCloneMatrix. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPageScale/GdipGetPageScale. + + * dlls/gdiplus/graphics.c: + gdiplus: Added support for more page units. + +2007-07-25 Alexandre Julliard + + * dlls/user32/tests/win.c: + user32/tests: Flush events more aggressively in mouse input test. + + * dlls/gdi32/tests/font.c: + gdi32/tests: Don't test default char, it doesn't have to be always the same. + +2007-07-24 Nigel Liang + + * dlls/winex11.drv/xim.c: + winex11.drv: Take into account position of preedit area in PreEditCaretCallback. + +2007-07-24 James Hawkins + + * dlls/msi/custom.c: + msi: Use a different separator as a semi-colon may separate values in the + CustomActionData. + +2007-07-24 Jason Edmeades + + * programs/cmd/batch.c: + cmd: Fix trap when batch pgm runs another batch pgm. + +2007-07-24 Rob Shearman + + * dlls/mshtml/navigate.c: + mshtml: Events are reset when a new document URI is loaded, so re-initialise + them in start_binding. + + * dlls/mshtml/olewnd.c: + mshtml: Set focus to the Gecko window in + OleInPlaceActiveObject_OnFrameWindowActivate. + + * dlls/mshtml/editor.c, dlls/mshtml/mshtml_private.h, + dlls/mshtml/nsevents.c, dlls/mshtml/tests/htmldoc.c: + mshtml: Call IDocHostUIHandler_HideUI and IDocHostUIHandler_ShowUI when changing + an UI active window to be in edit mode. + Add tests for the behaviour of changing edit mode when a UI window is active. + + * dlls/mshtml/view.c: + mshtml: Pass the correct DOCHOSTUITYPE value to IDocHostUIHandler_ShowUI. + Don't reset window_active in OleDocumentView_UIActivate. + + * dlls/mshtml/mshtml_private.h, dlls/mshtml/tests/htmldoc.c, + dlls/mshtml/view.c: + mshtml: OleDocumentView_UIActivate should call + IOleInPlaceUIWindow_SetActiveObject and IOleInPlaceFrame_SetBorderSpace. + Add a test to show this behaviour. + Don't call nsIWebBrowserFocus_Activate when just activating the window. + Instead call it when UI-activating the window. + +2007-07-24 H. Verbeet + + * dlls/wined3d/wined3d_private.h: + wined3d: Fix the stretch_rect_fbo() declaration to match the implementation. + + * dlls/wined3d/drawprim.c: + wined3d: Pass the correct target to glMultiTexCoord. + +2007-07-24 Michael Stefaniuc + + * dlls/wined3d/surface.c: + wined3d: Remove a return after a return. Found by Smatch. + + * dlls/mscms/profile.c: + mscms: Don't produce unreachable code during conditional compilation. + + * programs/winefile/winefile.c: + winefile: Change the settings functions to use the W registry functions. + +2007-07-24 Juan Lang + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Test and implement getting the encoded signers from an encoded + signed message. + +2007-07-24 Andrew Talbot + + * dlls/msxml3/xmlelem.c: + msxml3: Cast-qual warning fix. + +2007-07-24 Konstantin Kondratyuk + + * dlls/ntdll/time.c: + ntdll: Add Samara time zone. + +2007-07-24 Marcus Meissner + + * dlls/crypt32/encode.c: + crypt32: Fixed wrong allocation size. + +2007-07-24 Paul Vriens + + * dlls/advapi32/tests/service.c: + advapi32/service: Add tests for GetServiceKeyName. + + * dlls/advapi32/tests/service.c: + advapi32/service: Close a handle on failure. + + * dlls/advapi32/tests/service.c: + advapi32/service: Add another test for GetServiceDisplayName. + +2007-07-24 Aric Stewart + + * dlls/ws2_32/socket.c: + ws2_32: Initialize the address to 0 in ws_sockaddr_ws2u. + +2007-07-22 Stefan Dösinger + + * dlls/wined3d/device.c, dlls/wined3d/directx.c: + wined3d: Create the stateblock in Init3D. + +2007-07-23 Stefan Dösinger + + * dlls/ddraw/ddraw.c, dlls/ddraw/main.c, dlls/ddraw/surface.c: + ddraw: Some d3d-only code fixes. + Vertex declarations are a d3d feature, thus they should be destroyed + before d3d is shut down in wined3d. The surface type should be reset + afterwards to prevent avoid gl surface afterwards and before a new + render target is created. + +2007-07-24 Misha Koshelev + + * dlls/urlmon/tests/misc.c: + urlmon/tests: Release two objects that should be released but are not. + + * dlls/urlmon/internet.c: + urlmon: Release IInternetProtocolInfo returned from get_protocol_info when + finished with it. + + * dlls/urlmon/bindprot.c: + urlmon: LockModule in create_binding_protocol as we ReleaseModule when the + object is released. + + * dlls/urlmon/session.c: + urlmon: If we are using an internal protocol ClassFactory, call its AddRef as + the caller must Release the object. + +2007-07-23 Evan Stade + + * dlls/gdiplus/graphics.c: + gdiplus: Use page unit when drawing. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPageUnit. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphics.c, + include/gdiplusflat.h, include/gdiplusgpstubs.h, + include/gdiplustypes.h: + gdiplus: Added GdipFillPolygonI. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, dlls/gdiplus/pen.c, + dlls/gdiplus/tests/pen.c, include/gdiplusflat.h: + gdiplus: Implemented GdipSetPenColor. + + * dlls/gdiplus/brush.c, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/tests/pen.c: + gdiplus: Implemented GdipSetSolidFillColor/GdipGetSolidFillColor. + + * dlls/gdiplus/tests/pen.c: + gdiplus/tests: Added pen brush fill test. + + * dlls/gdiplus/brush.c, dlls/gdiplus/gdiplus.spec, include/gdiplusflat.h: + gdiplus: Added GdipSetSolidFillColor and GdipGetSolidFillColor stubs. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipGetPenBrushFill. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipGetPenColor stub. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPenBrushFill. + +2007-07-23 Misha Koshelev + + * dlls/urlmon/binding.c: + urlmon: Wrap IHttpNegotiate2 interface exposed by IBindStatusCallback as done + by native. + + * dlls/urlmon/tests/url.c: + urlmon/tests: Add tests for calls to IHttpNegotiate interfaces as exposed + by IBindStatusCallback. + Add more tests for specific arguments passed to IHttpNegotiate and + IHttpNegotiate2. Note that + for OnResponse pszAdditionalHeaders is NULL when called directly from + IInternetProtocol (for + example as seen in our protocol tests) but non-NULL when these interfaces are + exposed by + IBindStatusCallback as seen here. Tests conform on Win98 and Winxp. + + * dlls/urlmon/tests/url.c: + urlmon/tests: Add tests for calls to IBindStatusCallback_QueryInterface. + + * dlls/urlmon/binding.c: + urlmon: Add a reference to the IUnknown for Release of STGMEDIUM to account + for extra call to ReleaseBindInfo. + + * dlls/urlmon/file.c: + urlmon: ReleaseBindInfo in FileProtocol. + + * dlls/urlmon/binding.c: + urlmon: Don't ignore bytes read from IInternetProtocol_Read if hres is not S_OK + (e.g., E_PENDING). + Bytes can still be read with E_PENDING returned if the whole request could + not be satisfied, don't + ignore those. + + * dlls/urlmon/http.c: + urlmon: Fix timing issue with FLAG_REQUEST_COMPLETE and + InternetQueryDataAvailable in HttpProtocol. + +2007-07-24 Damjan Jovanovic + + * dlls/ws2_32/socket.c: + ws2_32: Sending 0 bytes shouldn't cause an infinite loop. + +2007-07-23 James Hawkins + + * dlls/msi/table.c, dlls/msi/tests/db.c: + msi: Add handling for the MSIMODIFY_UPDATE command. + + * dlls/msi/tests/db.c: + msi: Add tests for the MSIMODIFY_UPDATE command. + + * dlls/msi/alter.c, dlls/msi/table.c: + msi: Properly delete the columns view. + +2007-07-23 Juan Lang + + * dlls/crypt32/encode.c, dlls/crypt32/tests/msg.c: + crypt32: Test and implement encoding signed data messages with CRLs. + + * dlls/crypt32/encode.c, dlls/crypt32/tests/msg.c: + crypt32: Test and implement encoding signed messages with certificates. + + * dlls/crypt32/encode.c: + crypt32: Use set encoding function for encoding PKCS signed info. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement getting version from an encoded signed message. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for getting an encoded signed message's parameters. + + * dlls/crypt32/msg.c: + crypt32: Use consistent types for storing and encoding signed encode data. + + * dlls/crypt32/msg.c: + crypt32: Separate signer handles from signer info to avoid unnecessary memory + allocation. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement getting outer content of a signed message. + + * dlls/crypt32/crypt32_private.h, dlls/crypt32/encode.c, + dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Partially implement encoding signed messages. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement getting the hash for each signer of a signed encoded message. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Hash and sign data when updating signed messages. + + * dlls/crypt32/msg.c: + crypt32: More parameter checking for opening signed encoded messages. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for opening non-detached signed messages, and clarify + detached open. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Add a partial stub for updating a signed encoded message. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for signed message encoding. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for updating signed encoded messages. + + * dlls/crypt32/decode.c: + crypt32: Check for and fail on indefinite-length encoding. + + * dlls/crypt32/encode.c: + crypt32: Introduce function to encode an array of items as a set. + +2007-07-20 Juan Lang + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Add stub encoded signed message. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for opening signed message to encode. + +2007-07-23 Jason Edmeades + + * dlls/user32/mdi.c: + user32: MDI tile and cascade should not resize non-resizable windows. + + * dlls/user32/mdi.c: + user32: Correct trace to log calculated values rather than uninitialized ones. + +2007-07-23 Michael Stefaniuc + + * programs/winefile/winefile.c: + winefile: Move some self contained functions to use explicit W functions. + + * dlls/wldap32/init.c, dlls/wldap32/misc.c, dlls/wldap32/page.c, + dlls/wldap32/value.c: + wldap32: Don't produce unreachable code during conditional compilation. Found + bySmatch. + + * programs/winefile/winefile.c: + winefile: Replace malloc with HeapAlloc. + +2007-07-23 Paul Vriens + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Handle is checked before servicename. + +2007-07-23 H. Verbeet + + * dlls/wined3d/drawprim.c: + wined3d: Trace the declaration element type in + primitiveDeclarationConvertToStridedData(). + + * dlls/wined3d/state.c: + wined3d: Don't modify the blending parameters in state_blend(). + +2007-07-23 Andrew Talbot + + * dlls/msi/action.c: + msi: Cast-qual warning fix. + +2007-07-22 Vitaliy Margolen + + * dlls/dinput/dinput_main.c: + dinput: Use more messages as a possible indication of the foreground window + changes. + +2007-07-20 Evan Stade + + * dlls/gdiplus/gdiplus.c, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c: + gdiplus: Change atan2 to gdiplus_arctan2. + + * dlls/gdiplus/graphics.c: + gdiplus: Added startcap rendering. + + * dlls/gdiplus/graphics.c: + gdiplus: Use base inset for custom line caps. + + * dlls/gdiplus/customlinecap.c, dlls/gdiplus/graphics.c: + gdiplus: Added rendering of fill-path type custom line caps. + +2007-07-21 Hans Leidekker + + * dlls/pdh/pdh.spec, dlls/pdh/pdh_main.c, dlls/pdh/tests/pdh.c, + include/pdh.h: + pdh: Implement and test PdhAddEnglishCounter{A, W} and + PdhCollectQueryDataWithTime. + + * dlls/pdh/pdh.spec, dlls/pdh/pdh_main.c, dlls/pdh/tests/pdh.c, + include/pdh.h, include/pdhmsg.h: + pdh: Implement and test PdhLookupPerfIndexByName{A, W} and + PdhLookupPerfNameByIndex{A, W}. + + * dlls/pdh/pdh_main.c, dlls/pdh/tests/pdh.c: + pdh: Add more tests and make them pass. + + * dlls/pdh/pdh_main.c: + pdh: Add a stub processor time counter. + +2007-07-22 Detlef Riekenberg + + * dlls/winspool.drv/info.c: + winspool: Use printenv_t for GetDriverInfoFromReg. + +2007-07-22 H. Verbeet + + * dlls/wined3d/pixelshader.c: + wined3d: Fix the shader version on some instruction tokens. + + * dlls/wined3d/wined3d_private.h: + wined3d: Correctly handle normalized vertex declaration data types. + +2007-07-21 Hwang YunSong(황윤성) + + * programs/net/Ko.rc, programs/net/rsrc.rc: + net: New Korean resource. + + * programs/wordpad/Ko.rc: + wordpad: Updated Korean resource. + + * dlls/localui/localui.rc, dlls/localui/ui_Ko.rc: + localui: New Korean resource. + +2007-07-21 Damjan Jovanovic + + * tools/wineshelllink: + tools: Add basic support for the startup notifications standard. + + * tools/wine.desktop: + tools: Associate wine with the application/x-executable MIME type. + +2007-07-20 Misha Koshelev + + * dlls/urlmon/http.c, dlls/urlmon/tests/protocol.c: + urlmon: Add support for non-GET requests (e.g., POST) in HttpProtocol. + + * dlls/urlmon/http.c: + urlmon: Actually send the additional headers returned by + IHttpNegotiate::BeginningTransaction. + + * dlls/urlmon/http.c: + urlmon: Call HttpOpenRequest with INTERNET_FLAG_KEEP_CONNECTION, + INTERNET_FLAG_NO_CACHE_WRITE if appropriate. + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Add test for BINDVERB_POST in http_protocol. + +2007-07-20 James Hawkins + + * dlls/msi/alter.c, dlls/msi/create.c, dlls/msi/delete.c, + dlls/msi/distinct.c, dlls/msi/insert.c, dlls/msi/join.c, + dlls/msi/msipriv.h, dlls/msi/order.c, dlls/msi/select.c, + dlls/msi/sql.y, dlls/msi/streams.c, dlls/msi/table.c, + dlls/msi/tests/db.c, dlls/msi/update.c, dlls/msi/where.c: + msi: Ref count temporary columns and release them when necessary. + + * dlls/msi/alter.c, dlls/msi/create.c, dlls/msi/delete.c, + dlls/msi/distinct.c, dlls/msi/insert.c, dlls/msi/join.c, + dlls/msi/msipriv.h, dlls/msi/order.c, dlls/msi/query.h, + dlls/msi/select.c, dlls/msi/sql.y, dlls/msi/streams.c, + dlls/msi/table.c, dlls/msi/tests/db.c, dlls/msi/tests/package.c, + dlls/msi/tokenize.c, dlls/msi/update.c, dlls/msi/where.c: + msi: Implement adding columns using the ALTER command. + +2007-07-20 Juan Lang + + * dlls/crypt32/msg.c: + crypt32: Move decoding hash messages to a helper function. + +2007-07-20 Andrew Talbot + + * dlls/comcat/information.c: + comcat: Cast-qual warning fix. + + * dlls/kernel32/resource.c: + kernel32: Cast-qual warning fix. + +2007-07-20 Vitaliy Margolen + + * dlls/winex11.drv/event.c: + winex11drv: Correctly react to focus loss away from Wine. + + * dlls/user32/tests/msg.c, dlls/user32/tests/win.c, server/window.c: + server: Treat desktop as a top-level window. + + * dlls/user32/tests/win.c: + user32: Add test for SetForegroundWindow(desktop). + +2007-07-22 Paul Vriens + + * dlls/advapi32/tests/service.c: + advapi32/service: Add tests for GetDisplayName. + +2007-07-20 Paul Vriens + + * dlls/advapi32/tests/security.c: + advapi32/tests: Run on NT4 again. + +2007-07-20 Rob Shearman + + * dlls/rpcrt4/rpc_defs.h, dlls/rpcrt4/rpc_message.c, + dlls/rpcrt4/rpc_server.c, dlls/rpcrt4/rpc_transport.c: + rpcrt4: Convert bind ack and nack reject reasons into RPC status codes when + binding. + +2007-07-20 Dmitry Timoshkov + + * dlls/advapi32/tests/security.c: + advapi32: Rename the test to better represent the tested functionality. + + * dlls/winex11.drv/pen.c: + winex11.drv: Constify the pen dash data. + +2007-07-19 Nigel Liang + + * dlls/user32/edit.c, dlls/winex11.drv/xim.c: + winex11.drv: Implement XIMPreEditCaretCallback. + +2007-07-19 Evan Stade + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPenStartCap. + + * dlls/gdiplus/pen.c: + gdiplus: Updated GdipClonePen to clone pen's members by value, not reference. + + * dlls/gdiplus/brush.c, dlls/gdiplus/gdiplus.spec, include/gdiplusflat.h: + gdiplus: Added GdipCloneBrush. + + * dlls/gdiplus/brush.c, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/pen.c: + gdiplus: Associate a brush with a pen. + + * dlls/gdiplus/graphics.c: + gdiplus: Added rendering of custom line caps. + + * dlls/gdiplus/graphics.c: + gdiplus: Use atan2 instead of atan. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added custom line cap setters. + + * dlls/gdiplus/customlinecap.c, dlls/gdiplus/gdiplus.spec, + include/gdiplusflat.h: + gdiplus: Added GdipCloneCustomLineCap. + + * dlls/gdiplus/Makefile.in, dlls/gdiplus/customlinecap.c, + dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + include/gdiplusflat.h, include/gdiplusgpstubs.h: + gdiplus: Initial custom line caps implementation. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, include/gdiplusflat.h: + gdiplus: Added GdipCreateMatrix. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, include/gdiplusflat.h: + gdiplus: Added GdipRotateMatrix. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, include/gdiplusflat.h: + gdiplus: Added GdipTranslateMatrix. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, include/gdiplusflat.h: + gdiplus: Added GdipScaleMatrix. + +2007-07-19 Alexander Nicolaysen Sørnes + + * programs/wordpad/wordpad.c: + wordpad: Resize rebar control on window resize. + +2007-07-19 Andrew Talbot + + * dlls/comctl32/commctrl.c: + comctl32: Cast-qual warning fix. + + * dlls/dbghelp/dwarf.c: + dbghelp: Cast-qual warnings fix. + + * dlls/dplayx/dplobby.c: + dplayx: Cast-qual warning fix. + +2007-07-19 Michael Stefaniuc + + * dlls/oleaut32/vartype.c: + oleaut32: Remove a return after return. + +2007-07-19 Paul Vriens + + * dlls/advapi32/tests/service.c: + advapi32/service: Some 'refcount' tests. + + * dlls/advapi32/service.c: + advapi32/service: lpBinaryPathName is mandatory. + +2007-07-19 Anatoly Lyutin + + * dlls/kernel32/tests/path.c: + kernel32/tests: Add test for GetShortPathNameW. + + * programs/cmd/wcmdmain.c: + cmd: Use toupperW instead of toupper. + + * dlls/user32/painting.c: + user32: Add comment to a function. + +2007-07-19 Juan Lang + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement querying computed hash of a decoded hash message. + + * dlls/crypt32/msg.c: + crypt32: Store hash algorithm ID along with other parameters when decoding a + hash message. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Store (most) parameters of a decoded hash message. + +2007-07-19 Mikołaj Zalewski + + * dlls/user32/tests/class.c: + user32/tests: Simplify a test. + + * dlls/comctl32/comctl32.h, dlls/comctl32/comctl32undoc.c, + dlls/comctl32/tooltips.c: + comctl32: tooltips: Remove broken support for non-NULL-terminated strings in + TOOLTIPS_GetDispInfo[AW]. + + * dlls/comctl32/tests/toolbar.c, dlls/comctl32/toolbar.c: + comctl32: toolbar: Test and fix invalid indexes passed in TB_ISBUTTON*. + +2007-07-19 Dmitry Timoshkov + + * include/winuser.h: + winuser.h: Add RealChildWindowFromPoint declaration. + +2007-07-20 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Add support for abbreviated empty elements in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Don't fail to load manifests that contain unknown elements or attributes. + Print FIXMEs for errors that really cause the loading to fail. + +2007-07-19 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Add support for optional flag in dependencies. + + * dlls/ntdll/actctx.c: + ntdll: Cope with missing assemblyIdentity elements in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Skip xml comments in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added manifest lookup in global winsxs directory (based on a patch by + Jacek Caban). + +2007-07-19 Jacek Caban + + * dlls/ntdll/loader.c, dlls/ntdll/ntdll_misc.h: + ntdll: Store the windows directory too. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the asmv2:hash element in manifests. + +2007-07-19 Eric Pouech + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the binding redirect element in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the clrClass and clrSurrogate elements in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the external proxy element in manifests. + +2007-07-19 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Abstract the entity array type as we need it for assemblies too. + +2007-07-19 Eric Pouech + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the description element in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the language attribute in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of the inheritance flags in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of hash attributes in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of public key token in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Added support for the assembly leaves of activation contexts. + +2007-07-19 Jacek Caban + + * dlls/ntdll/actctx.c: + ntdll: Added parsing of file elements in manifests. + + * dlls/ntdll/actctx.c: + ntdll: Add parsing of dependencies in manifests. + +2007-07-19 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Add infrastructure for loading manifest dependencies (based on a patch + by Eric Pouech). + + * dlls/ntdll/actctx.c: + ntdll: Add parsing of the version in manifests (based on a patch by Jacek Caban). + + * dlls/ntdll/actctx.c: + ntdll: Add parsing of the processor architecture in manifests. + +2007-07-19 Jacek Caban + + * dlls/ntdll/actctx.c: + ntdll: Beginnings of manifest parsing. + +2007-07-19 Alexandre Julliard + + * dlls/ntdll/actctx.c: + ntdll: Add infrastructure for loading a manifest file or resource. + Partially based on a patch by Eric Pouech. + +2007-07-19 Eric Pouech + + * dlls/ntdll/actctx.c: + ntdll: Added basic structures for storing activation context assembly + information. + +2007-07-19 Alexandre Julliard + + * dlls/kernel32/actctx.c, dlls/kernel32/thread.c, dlls/ntdll/actctx.c, + dlls/ntdll/ntdll.spec, include/winternl.h: + ntdll: Implemented handling of the per-thread activation context stack. + + * dlls/kernel32/actctx.c, dlls/ntdll/Makefile.in, dlls/ntdll/actctx.c, + dlls/ntdll/ntdll.spec, include/winternl.h: + kernel32: Move activation context creation to ntdll (based on a patch by + Eric Pouech). + + * dlls/ntdll/ntdll_misc.h, dlls/ntdll/signal_i386.c, dlls/ntdll/thread.c, + include/thread.h, include/winternl.h, tools/winebuild/relay.c: + ntdll: Move private data to make room in the TEB for the activation context data. + +2007-07-18 Martin Fuchs + + * dlls/shell32/shlfileop.c: + shell32: Implementation of SheGetDirA/W and SheChangeDirA/W. + +2007-07-18 Alexander Nicolaysen Sørnes + + * .gitignore, programs/wordpad/Makefile.in, programs/wordpad/resource.h, + programs/wordpad/rsrc.rc, programs/wordpad/wordpad.c: + wordpad: Add date/time toolbar button. + + * programs/wordpad/De.rc, programs/wordpad/En.rc, programs/wordpad/Fr.rc, + programs/wordpad/Hu.rc, programs/wordpad/Ko.rc, + programs/wordpad/Nl.rc, programs/wordpad/No.rc, + programs/wordpad/Pl.rc, programs/wordpad/Ru.rc, + programs/wordpad/Tr.rc, programs/wordpad/resource.h, + programs/wordpad/wordpad.c: + wordpad: Add date/time dialog. + +2007-07-18 Evan Stade + + * dlls/gdi32/painting.c: + gdi32: Improved PolyDraw in path closed case. + +2007-07-19 Huw Davies + + * dlls/wininet/internet.c, dlls/wininet/wininet.spec: + wininet: Stub for InternetQueryFortezzaStatus(). + +2007-07-18 Juan Lang + + * dlls/msi/install.c: + msi: Return FALSE from MsiGetMode for MSIRUNMODE_OPERATIONS. + + * include/wincrypt.h: + wincrypt: Add more missing definitions. + +2007-07-12 Mikołaj Zalewski + + * dlls/msxml3/tests/xmldoc.c: + msxml3/tests: Avoid a crash that happens on some native systems. + +2007-07-18 Evan Stade + + * dlls/winex11.drv/graphics.c, dlls/winex11.drv/pen.c, + dlls/winex11.drv/x11drv.h: + winex11.drv: Draw dashed lines for extended pens. + +2007-07-19 Dmitry Timoshkov + + * dlls/rpcrt4/ndr_marshall.c: + rpcrt4: Fix the buffer bounds check. + +2007-07-18 James Hawkins + + * dlls/msi/alter.c, dlls/msi/create.c, dlls/msi/delete.c, + dlls/msi/distinct.c, dlls/msi/insert.c, dlls/msi/join.c, + dlls/msi/msipriv.h, dlls/msi/order.c, dlls/msi/select.c, + dlls/msi/streams.c, dlls/msi/table.c, dlls/msi/tests/db.c, + dlls/msi/update.c, dlls/msi/where.c: + msi: Implement reference counting for tables, manipulated with the HOLD and + FREE sql commands. + + * dlls/msi/tests/db.c: + msi: Add more tests for the ALTER command. + +2007-07-18 Misha Koshelev + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Add tests for HttpProtocol behavior when it is called without + the BINDF_FROMURLMON flag. + + * dlls/urlmon/http.c: + urlmon: Implement HttpProtocol::Terminate. + + * dlls/urlmon/http.c: + urlmon: Fix HttpProtocol behavior when it is called without the BINDF_FROMURLMON + flag. + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Fix http_protocol tests to succeed when called more than once. + + * dlls/urlmon/tests/protocol.c: + urlmon/tests: Fix http_protocol tests to succeed on Win98. + + * dlls/urlmon/http.c: + urlmon: Use InternetCloseHandle instead of CloseHandle. + + * dlls/urlmon/http.c: + urlmon: Remove FLAG_CALLED_SWITCH, which is now redundant. + +2007-07-19 Michael Stefaniuc + + * tools/winedump/msc.c, tools/winedump/msmangle.c: + tools: Remove unreachable break after return/break. Found by Smatch. + + * programs/notepad/dialog.c, programs/regedit/framewnd.c, + programs/regedit/listview.c, programs/taskmgr/taskmgr.c, + programs/winedbg/be_i386.c, programs/winedbg/gdbproxy.c, + programs/wordpad/wordpad.c: + programs: Remove unreachable break after return/break. Found by Smatch. + + * dlls/comctl32/ipaddress.c, dlls/msi/cond.y, dlls/sane.ds/ui.c, + dlls/user32/tests/win.c, dlls/winex11.drv/init.c: + dlls: Remove unreachable break after return/break. Found by Smatch. + +2007-07-18 Michael Stefaniuc + + * programs/winhelp/winhelp.c: + winhelp: Add missing case label "default". Found by Smatch (unreached code). + + * dlls/ntdll/cdrom.c, dlls/ntdll/serial.c: + ntdll: Don't produce unreachable code during conditional compilation. Found + by Smatch. + +2007-07-19 H. Verbeet + + * dlls/wined3d/swapchain.c: + wined3d: glXSwapBuffers needs a GLX context. + +2007-07-18 Detlef Riekenberg + + * dlls/spoolss/spoolss.spec, dlls/spoolss/spoolss_main.c: + spoolss: Add a stub for ImpersonatePrinterClient. + +2007-07-18 Paul Vriens + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Some tests for DeleteService. + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Check for duplicate displayname. + + * dlls/advapi32/tests/service.c: + advapi32/service: Cleanup (long lines and a typo). + +2007-07-18 Rob Shearman + + * dlls/advapi32/tests/security.c: + advapi32: Add tests for ConvertStringSecurityDescriptorToSecurityDescriptor. + + * dlls/advapi32/security.c: + advapi32: Set the right pointer so that StringAcl is updated correct in + ParseAceStringRights. + The number of allowed hex digits should be 8, not 6. + + * dlls/advapi32/security.c: + advapi32: Don't crash in ConvertStringSecurityDescriptorToSecurityDescriptorW + if LocalAlloc fails. + + * dlls/advapi32/security.c: + advapi32: Add the size of the security descriptor structure to the size of + memory required in ParseStringSecurityDescriptorToSecurityDescriptor. + + * dlls/advapi32/security.c: + advapi32: Fix a typo in ParseStringAclToAcl which caused the ACE to be written + inside of the ACL memory. + + * dlls/advapi32/security.c: + advapi32: Fix ComputeStringSidSize to work with SIDs with one sub authority. + Use GetSidLengthRequired instead of computing the length in a way that + won't always be correct. + +2007-07-18 Huw Davies + + * dlls/wininet/urlcache.c, dlls/wininet/wininet.spec: + wininet: Stubs for IsUrlCacheEntryExpired[AW]. + + * dlls/wininet/internet.c, dlls/wininet/tests/internet.c: + wininet: Certain options of InternetQueryOption can take a NULL handle, so + don't do the NULL handle check at the beginning. + +2007-07-18 Vitaliy Margolen + + * dlls/user32/tests/msg.c: + user32/test: Destroy no longer needed test dialog windows. + +2007-07-17 Paul Vriens + + * dlls/advapi32/tests/service.c: + advapi32/service: Test for duplicate displayname. + +2007-07-17 Hwang YunSong(황윤성) + + * programs/wordpad/Ko.rc: + wordpad: Updated Korean resource. + + * programs/cmd/Ko.rc: + cmd: Updated Korean resource. + +2007-07-17 Evan Stade + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/matrix.c, + include/gdiplusenums.h, include/gdiplusflat.h, + include/gdiplusgpstubs.h: + gdiplus: Added GdipMultiplyMatrix. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipGetPenDashStyle. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipClonePen. + +2007-07-18 Detlef Riekenberg + + * include/winspool.h: + include/winspool.h: Add missing struct. + +2007-07-17 James Hawkins + + * dlls/msi/package.c: + msi: Only double the size if the remote call is from MsiGetPropertyA. + + * dlls/msi/custom.c: + Revert "msi: Only call a custom action remotely if the type is + msidbCustomActionTypeInScript." + This reverts f2ae31000b6d6c105838fad36c17ba1fb1f5524b commit. + +2007-07-18 Michael Stefaniuc + + * dlls/wined3d/utils.c: + wined3d: Remove unreachable code: break after return. Found by Smatch. + +2007-07-17 Andrew Talbot + + * dlls/comdlg32/filedlg31.c: + comdlg32: Cast-qual warning fix. + +2007-07-17 Juan Lang + + * dlls/crypt32/tests/msg.c: + crypt32: Add a couple more parameter tests for hash messages. + + * include/wincrypt.h: + crypt32: Fix typo. + + * dlls/crypt32/msg.c: + crypt32: Use property list for decoded message parameters. + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement getting content of a data message. + + * dlls/crypt32/tests/msg.c: + crypt32: Add a few tests for decoded message parameters. + + * dlls/crypt32/decode.c: + crypt32: Fix a bad comment. + + * dlls/crypt32/crypt32_private.h, dlls/crypt32/decode.c, + dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement decoding hash messages. + + * dlls/crypt32/decode.c: + crypt32: Remove a redundant line. + + * dlls/crypt32/tests/msg.c: + crypt32: Add tests for decoding a hash message. + + * dlls/crypt32/crypt32_private.h, dlls/crypt32/encode.c, + dlls/crypt32/msg.c: + crypt32: Move digested data encoding to encode.c. + +2007-07-17 Rob Shearman + + * dlls/rpcrt4/rpc_message.c: + rpcrt4: Add some more RPC to NCA status code mappings. + Add RPC_S_SEC_PKG_ERROR to the list of "hard" errors. + +2007-07-16 Evan Stade + + * dlls/gdi32/gdi_private.h, dlls/gdi32/painting.c, dlls/gdi32/path.c, + dlls/gdi32/tests/path.c: + gdi32: Added PATH_PolyDraw. + + * dlls/gdi32/tests/path.c: + gdi32: Added PolyDraw tests. + +2007-07-17 Alexandre Julliard + + * dlls/winealsa.drv/waveinit.c: + winealsa: Make sure we can set volume before reporting WAVECAPS_VOLUME. + +2007-07-16 James Hawkins + + * dlls/vdmdbg/vdmdbg.c, dlls/vdmdbg/vdmdbg.spec, include/Makefile.in, + include/vdmdbg.h: + vdmdbg: Add a stub implementation of VDMEnumTaskWOW. + +2007-07-13 Kovács András + + * .gitignore, include/Makefile.in, include/d3d10.idl, include/dxgi.idl, + include/dxgitype.idl: + include: Add some idl headers for d3d10. + +2007-07-17 Alexandre Julliard + + * tools/widl/header.c, tools/widl/parser.l, tools/widl/parser.y, + tools/widl/typegen.c, tools/widl/widltypes.h: + widl: Added support for floating-point constants. + +2007-07-16 Evan Stade + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphicspath.c, + include/gdiplusflat.h: + gdiplus: Added GdipAddPathBeziers. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/pen.c, include/gdiplusenums.h, include/gdiplusflat.h, + include/gdiplusgpstubs.h: + gdiplus: Added GdipSetPenDashStyle. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pathiterator.c, + include/gdiplusflat.h: + gdiplus: Added GdipPathIterRewind. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pathiterator.c, + include/gdiplusflat.h: + gdiplus: Added GdipPathIterNextSubpath. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pathiterator.c, + include/gdiplusflat.h: + gdiplus: Added GdipPathIterCopyData. + + * dlls/gdiplus/Makefile.in, dlls/gdiplus/gdiplus.spec, + dlls/gdiplus/gdiplus_private.h, dlls/gdiplus/pathiterator.c, + include/gdiplusflat.h, include/gdiplusgpstubs.h: + gdiplus: Initial path iterator implementation. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusflat.h: + gdiplus: Added GdipSetPenMiterLimit. + + * dlls/gdiplus/gdiplus.spec: + gdiplus: Export GdipSetPenLineJoin. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/pen.c, include/gdiplusenums.h, include/gdiplusflat.h, + include/gdiplusgpstubs.h: + gdiplus: Added GdipSetPenLineCap197819. + +2007-07-16 James Hawkins + + * dlls/msi/custom.c: + msi: Only call a custom action remotely if the type is + msidbCustomActionTypeInScript. + + * dlls/msi/action.c, dlls/msi/msipriv.h, dlls/msi/package.c, + dlls/msi/string.c, dlls/msi/table.c, dlls/msi/tests/install.c: + msi: Load the AdminProperties stream if the package is an Admin package. + +2007-07-15 Vitaliy Margolen + + * dlls/dinput/dinput_main.c, dlls/dinput/tests/mouse.c: + dinput: Use CALLWINDPROC hook to monitor focus loses away from acquired windows. + + * dlls/dinput/dinput_main.c: + dinput: Use PostMessage instead of SendMessage. Remove message window. + +2007-07-16 Tim Schwartz + + * dlls/netapi32/access.c, dlls/netapi32/netapi32.spec: + netapi32: Add NetUseAdd() stub. + +2007-07-16 Kirill K. Smirnov + + * programs/start/start.c: + programs/start: use SEE_MASK_NO_CONSOLE flag as default. + Allows to start console applications in a new window (as Windows does). + + * dlls/shell32/shlexec.c: + shell32: Add support for SEE_MASK_NO_CONSOLE flag. + +2007-07-16 Michael Stefaniuc + + * dlls/shell32/shlfolder.c: + shell32: Fix missing unlock on an error path. Found by Smatch. + +2007-07-15 Paul Vriens + + * dlls/advapi32/service.c, dlls/advapi32/tests/service.c: + advapi32/service: Check combination of service-type and start-type. + +2007-07-16 Rob Shearman + + * dlls/rpcrt4/ndr_marshall.c: + rpcrt4: Never allocate memory for the discriminant in union_arm_unmarshall as + the memory is part of the union and has already been allocated. + + * dlls/rpcrt4/ndr_marshall.c: + rpcrt4: Check to make sure there is enough data in the buffer during + unmarshalling, so that the code doesn't try to read beyound the end of the + buffer. + + * dlls/rpcrt4/ndr_marshall.c, dlls/rpcrt4/tests/ndr_marshall.c: + rpcrt4: Even though FC_ENUM16 is an unsigned type, the highest allowable value + that can be marshalled is SHRT_MAX, not USHRT_MAX. + + * dlls/ole32/compobj.c: + ole32: Remove some dead code. + CoFreeUnusedLibraries doesn't do anything and COM_FlushMessageQueue + won't actually allow any RPCs to be processed as the apartment has + already been destroyed. + +2007-07-16 Vitaliy Margolen + + * dlls/pdh/pdh.spec: + pdh: Forward PdhOpenQuery to PdhOpenQueryW. + +2007-07-16 Alexandre Julliard + + * dlls/kernel32/file.c, dlls/kernel32/sync.c, dlls/kernel32/vxd.c: + kernel32: Always clear the I/O status block count before calling ntdll functions. + + * dlls/kernel32/tests/pipe.c, dlls/ntdll/sync.c, + include/wine/server_protocol.h, server/protocol.def, + server/request.h, server/thread.c, server/trace.c: + server: Merge APC processing into the select request. + This is needed to return the correct value when one of the handles + being waited on is set to signaled state by the APC. + + * dlls/kernel32/file.c, dlls/kernel32/tests/pipe.c: + kernel32: Wait in overlapped Read/WriteFile even when no overlapped structure + is passed. + +2007-07-13 Evan Stade + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphics.c, + include/gdiplusflat.h: + gdiplus: Added GdipFillPath. + + * dlls/gdiplus/graphics.c: + gdiplus: Simplified GdipDrawPath by moving more of the code to the helpers. + + * dlls/gdiplus/tests/graphics.c: + gdiplus: Added GpGraphics save/restore tests. + + * dlls/gdiplus/tests/Makefile.in, dlls/gdiplus/tests/graphics.c: + gdiplus: Constructor tests for GpGraphics. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphics.c, + include/gdiplusenums.h, include/gdiplusflat.h: + gdiplus: GdipSaveGraphics/GdipRestoreGraphics stubs. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusenums.h, + include/gdiplusflat.h: + gdiplus: Added pixel offset mode. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusenums.h, + include/gdiplusflat.h: + gdiplus: Added interpolation mode. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusenums.h, + include/gdiplusflat.h: + gdiplus: Added compositing quality. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/gdiplus_private.h, + dlls/gdiplus/graphics.c, include/gdiplusenums.h, + include/gdiplusflat.h: + gdiplus: Added smoothing modes. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/graphicspath.c, + include/gdiplusflat.h: + gdiplus: Added GdipSetPathFillMode. + +2007-07-16 Dmitry Timoshkov + + * dlls/shell32/shlfolder.c: + shell32: Add a cache for queried shell folder interfaces. + +2007-07-15 Misha Koshelev + + * dlls/wininet/internet.c: + wininet: Fix behavior of InternetQueryDataAvailable if INTERNET_FLAG_ASYNC + is set. + + * dlls/urlmon/http.c: + urlmon: Fix HttpProtocol behavior when InternetQueryDataAvailable returns + ERROR_IO_PENDING. + + * dlls/wininet/tests/http.c: + wininet/tests: Add testing framework and tests for internet status callbacks. + + * dlls/wininet/tests/http.c: + wininet/tests: Properly handle ERROR_IO_PENDING from InternetQueryDataAvailable. + +2007-07-14 Vitaliy Margolen + + * dlls/msvcrt/except.c: + msvcrt: Preserve registers when calling unwind function. + +2007-07-16 Huw Davies + + * dlls/kernel32/tests/pipe.c: + kernel32: Overlapped pipe tests. + +2007-07-16 Dmitry Timoshkov + + * dlls/shlwapi/ordinal.c, dlls/shlwapi/shlwapi.spec: + shlwapi: Fix parameter types of SHGetIniStringW. + +2007-07-15 H. Verbeet + + * dlls/wined3d/wined3d_private.h: + wined3d: Fix STATE_IS_ACTIVELIGHT. + +2007-07-14 Alec Berryman + + * dlls/itss/chm_lib.c: + itss: Replace malloc/free with HeapAlloc/HeapFree. + +2007-07-13 Juan Lang + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Implement decoding data messages (when opened in non-streaming mode). + + * dlls/crypt32/msg.c, dlls/crypt32/tests/msg.c: + crypt32: Partially implement updating decode messages. + + * dlls/crypt32/msg.c: + crypt32: Store crypt provider in decode message. + + * dlls/crypt32/decode.c, dlls/crypt32/tests/crl.c, + dlls/crypt32/tests/encode.c: + crypt32: Fix decoding sequences with extra trailing data. + + * dlls/crypt32/tests/encode.c: + crypt32: Add test showing extra trailing bytes should be tolerated in encoded + data. + +2007-07-15 Damjan Jovanovic + + * dlls/ws2_32/socket.c: + ws2_32: Update WSASendTo's iovec properly. + +2007-07-13 Jeremy White + + * dlls/gdi32/tests/bitmap.c: + gdi32: Added a test for the case where lpvBits in GetDIBits is NULL and the + bitcount is 0. + + * dlls/gdi32/dib.c: + gdi32: Do not fill in the color table if lpvBits is NULL. + +2007-07-13 Andrew Talbot + + * tools/winedump/search.c: + winedump: Cast-qual warnings fix. + +2007-07-13 Paul Vriens + + * dlls/msi/tests/install.c: + msi/tests: Don't create a directory that's not needed. + +2007-07-13 Aric Stewart + + * dlls/user32/user32.spec: + user32: Change SetDeskWallPaper spec. + +2007-07-13 Alexandre Julliard + + * ANNOUNCE, ChangeLog, VERSION, configure: + Release 0.9.41. + +---------------------------------------------------------------- 2007-07-13 Paul Vriens * dlls/mscms/tests/profile.c: diff --git a/VERSION b/VERSION index b0432b2251b..be63821680d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Wine version 0.9.41 +Wine version 0.9.42 diff --git a/configure b/configure index 75717a6bf61..144c12e9014 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for Wine 0.9.41. +# Generated by GNU Autoconf 2.61 for Wine 0.9.42. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='0.9.41' -PACKAGE_STRING='Wine 0.9.41' +PACKAGE_VERSION='0.9.42' +PACKAGE_STRING='Wine 0.9.42' PACKAGE_BUGREPORT='wine-devel@winehq.org' ac_unique_file="server/atom.c" @@ -1290,7 +1290,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Wine 0.9.41 to adapt to many kinds of systems. +\`configure' configures Wine 0.9.42 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1359,7 +1359,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 0.9.41:";; + short | recursive ) echo "Configuration of Wine 0.9.42:";; esac cat <<\_ACEOF @@ -1455,7 +1455,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Wine configure 0.9.41 +Wine configure 0.9.42 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1469,7 +1469,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Wine $as_me 0.9.41, which was +It was created by Wine $as_me 0.9.42, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -21306,7 +21306,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Wine $as_me 0.9.41, which was +This file was extended by Wine $as_me 0.9.42, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21359,7 +21359,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 0.9.41 +Wine config.status 0.9.42 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 1ecaf70b20f..0c373134c7c 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -2266,45 +2266,50 @@ BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager, BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPDWORD lpcchBuffer) { - struct sc_manager *hscm; - DWORD type, size; - LONG ret; + LPWSTR lpServiceNameW, lpDisplayNameW = NULL; + DWORD size, sizeW, GLE; + BOOL ret; TRACE("%p %s %p %p\n", hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer); - hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER); - if (!hscm) + lpServiceNameW = SERV_dup(lpServiceName); + lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR)); + + size = sizeW = *lpcchBuffer; + ret = GetServiceDisplayNameW(hSCManager, lpServiceNameW, + lpDisplayName ? lpDisplayNameW : NULL, + &sizeW); + /* Last error will be set by GetServiceDisplayNameW and must be preserved */ + GLE = GetLastError(); + + if (!lpDisplayName && lpcchBuffer && !ret && (GLE == ERROR_INSUFFICIENT_BUFFER)) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; + /* Request for buffersize. + * + * Only set the size for ERROR_INSUFFICIENT_BUFFER + */ + size = sizeW * 2; } - - if (!lpServiceName) + else if (lpDisplayName && lpcchBuffer && !ret) { - SetLastError(ERROR_INVALID_ADDRESS); - return FALSE; + /* Request for displayname. + * + * size only has to be set if this fails + */ + size = sizeW * 2; } - size = *lpcchBuffer; - ret = RegGetValueA(hscm->hkey, lpServiceName, "DisplayName", RRF_RT_REG_SZ, &type, lpDisplayName, &size); - if (!ret && !lpDisplayName && size) - ret = ERROR_MORE_DATA; + WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName, + *lpcchBuffer, NULL, NULL ); - if (ret) - { - if (lpDisplayName && *lpcchBuffer) *lpDisplayName = 0; + *lpcchBuffer = size; - if (ret == ERROR_MORE_DATA) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - *lpcchBuffer = size - 1; - } - else - SetLastError(ret); - return FALSE; - } - return TRUE; + HeapFree(GetProcessHeap(), 0, lpDisplayNameW); + SERV_free(lpServiceNameW); + + SetLastError(GLE); + return ret; } /****************************************************************************** @@ -2351,6 +2356,10 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, SetLastError(ret); return FALSE; } + + /* Always return the correct needed size on success */ + *lpcchBuffer = (size / sizeof(WCHAR)) - 1; + return TRUE; } diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 476c26e9ae5..8fc1af9222b 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -387,6 +387,8 @@ static void test_get_displayname(void) DWORD displaysize, tempsize, tempsizeW; static const CHAR deadbeef[] = "Deadbeef"; static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0}; + static const CHAR servicename[] = "Winetest"; + static const CHAR pathname[] = "we_dont_care.exe"; /* Having NULL for the size of the buffer will crash on W2K3 */ @@ -440,9 +442,44 @@ static void test_get_displayname(void) ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + /* Buffer is too small */ SetLastError(0xdeadbeef); tempsize = displaysize; - displaysize *= 2; + displaysize = (tempsize / 2); + ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); + ok(!ret, "Expected failure\n"); + ok(displaysize == tempsize, "Expected the needed buffersize\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + + /* First try with a buffer that should be big enough to hold + * the ANSI string (and terminating character). This succeeds on Windows + * although when asked (see above 2 tests) it will return twice the needed size. + */ + SetLastError(0xdeadbeef); + displaysize = (tempsize / 2) + 1; + ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); + ok(ret, "Expected success\n"); + ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n"); + ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ || + GetLastError() == ERROR_IO_PENDING /* W2K */ || + GetLastError() == 0xdeadbeef /* NT4, XP, Vista */, + "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); + + /* Now with the original returned size */ + SetLastError(0xdeadbeef); + displaysize = tempsize; + ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); + ok(ret, "Expected success\n"); + ok(displaysize == tempsize, "Expected no change for the needed buffer size\n"); + ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ || + GetLastError() == ERROR_IO_PENDING /* W2K */ || + GetLastError() == 0xdeadbeef /* NT4, XP, Vista */, + "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); + + /* And with a bigger then needed buffer */ + SetLastError(0xdeadbeef); + displaysize = tempsize * 2; ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); ok(ret, "Expected success\n"); ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ || @@ -450,12 +487,11 @@ static void test_get_displayname(void) GetLastError() == 0xdeadbeef /* NT4, XP, Vista */, "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); /* Test that shows that if the buffersize is enough, it's not changed */ - ok(displaysize == tempsize * 2, "Didn't expect a change in the needed size of the buffer\n"); - todo_wine + ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n"); ok(lstrlen(displayname) == tempsize/2, "Expected the buffer to be twice the length of the string\n") ; - /* Do the last 2 tests also for GetServiceDisplayNameW */ + /* Do the buffer(size) tests also for GetServiceDisplayNameW */ SetLastError(0xdeadbeef); displaysize = -1; ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize); @@ -463,26 +499,100 @@ static void test_get_displayname(void) ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + /* Buffer is too small */ SetLastError(0xdeadbeef); tempsizeW = displaysize; - displaysize *= 2; + displaysize = tempsizeW / 2; + ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); + ok(!ret, "Expected failure\n"); + ok(displaysize = tempsizeW, "Expected the needed buffersize\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + + /* Now with the original returned size */ + SetLastError(0xdeadbeef); + displaysize = tempsizeW; + ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); + ok(!ret, "Expected failure\n"); + ok(displaysize = tempsizeW, "Expected the needed buffersize\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + + /* And with a bigger then needed buffer */ + SetLastError(0xdeadbeef); + displaysize = tempsizeW + 1; /* This caters for the null terminating character */ ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); ok(ret, "Expected success\n"); ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ || GetLastError() == ERROR_IO_PENDING /* W2K */ || GetLastError() == 0xdeadbeef /* NT4, XP, Vista */, "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); - /* Test that shows that the buffersize is changed to the needed size */ - todo_wine - { - ok(displaysize == tempsizeW, "Did expect a change in the needed size of the buffer\n"); + ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); ok(lstrlenW(displaynameW) == displaysize, "Expected the buffer to be the length of the string\n") ; ok(tempsize / 2 == tempsizeW, "Expected the needed buffersize (in bytes) to be the same for the A and W call\n"); + + CloseServiceHandle(scm_handle); + + /* Test for a service without a displayname (which is valid). This should return + * the servicename itself. + */ + SetLastError(0xdeadbeef); + scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) + { + skip("Not enough rights to get a handle to the manager\n"); + return; } + SetLastError(0xdeadbeef); + svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE, + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); + ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError()); + if (!svc_handle) + { + CloseServiceHandle(scm_handle); + return; + } + + /* Retrieve the needed size for the buffer */ + SetLastError(0xdeadbeef); + displaysize = -1; + ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize); + ok(!ret, "Expected failure\n"); + todo_wine + { + ok(displaysize == lstrlen(servicename) * 2, + "Expected the displaysize to be twice the size of the servicename\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + } + + /* Get the displayname */ + SetLastError(0xdeadbeef); + ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize); + todo_wine + { + ok(ret, "Expected success\n"); + ok(!lstrcmpi(displayname, servicename), + "Expected displayname to be %s, got %s\n", servicename, displayname); + ok(GetLastError() == ERROR_SUCCESS /* W2K3 */ || + GetLastError() == ERROR_IO_PENDING /* W2K */ || + GetLastError() == 0xdeadbeef /* NT4, XP, Vista */, + "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); + } + + /* Delete the service */ + ret = DeleteService(svc_handle); + ok(ret, "Expected success\n"); + + CloseServiceHandle(svc_handle); CloseServiceHandle(scm_handle); + + /* Wait a while. Just in case one of the following tests does a CreateService again */ + Sleep(1000); } static void test_get_servicekeyname(void) diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index 086d0eda59a..c09bc04e445 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c @@ -704,7 +704,7 @@ CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps, /* add bitmaps */ - if (nBitmaps > 0) + if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL) { tbab.hInst = hBMInst; tbab.nID = wBMID; diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 9b1fc279ebb..14f081f891e 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -99,6 +99,10 @@ typedef struct _CRYPT_SIGNED_INFO BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *, void *pvData, DWORD *pcbData); +BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded, + DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, + CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo); + /* Helper function to check *pcbEncoded, set it to the required size, and * optionally to allocate memory. Assumes pbEncoded is not NULL. * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index 8a062cec3c4..de4de4aba71 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -366,6 +366,8 @@ static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType, items[i].size % sizeof(DWORD); ptr += 1 + nextItemLenBytes + nextItemLen; decoded += 1 + nextItemLenBytes + nextItemLen; + TRACE("item %d: decoded %d bytes\n", i, + 1 + nextItemLenBytes + nextItemLen); } else if (items[i].optional && GetLastError() == CRYPT_E_ASN1_BADTAG) @@ -381,6 +383,9 @@ static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType, } else { + TRACE("item %d: decoded %d bytes\n", i, + 1 + nextItemLenBytes + nextItemLen); + ptr += 1 + nextItemLenBytes + nextItemLen; decoded += 1 + nextItemLenBytes + nextItemLen; items[i].size = items[i].minSize; } @@ -392,8 +397,8 @@ static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType, } else { - TRACE("tag %02x doesn't match expected %02x\n", - ptr[0], items[i].tag); + TRACE("item %d: tag %02x doesn't match expected %02x\n", + i, ptr[0], items[i].tag); SetLastError(CRYPT_E_ASN1_BADTAG); ret = FALSE; } @@ -1846,9 +1851,8 @@ static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) { BOOL ret; - struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, - CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE, - offsetof(CRYPT_DER_BLOB, pbData) }; + struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes, + sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) }; struct GenericArray *array = (struct GenericArray *)pvStructInfo; TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, @@ -1896,9 +1900,8 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal( DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) { - struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, - CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE, - offsetof(CRYPT_ATTRIBUTE, pszObjId) }; + struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute, + sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) }; PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo; BOOL ret; @@ -1921,8 +1924,12 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType, { DWORD bytesNeeded; - if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType, - lpszStructType, pbEncoded, cbEncoded, + if (!cbEncoded) + SetLastError(CRYPT_E_ASN1_EOD); + else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF)) + SetLastError(CRYPT_E_ASN1_CORRUPT); + else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal( + dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) { if (!pvStructInfo) @@ -3813,19 +3820,21 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, + offsetof(CMSG_SIGNER_INFO, AuthAttrs), + CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), + TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm.pszObjId), 0 }, - { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs), - CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), - TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, - { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs), - CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), - TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash), CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, + offsetof(CMSG_SIGNER_INFO, UnauthAttrs), + CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), + TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, }; ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, @@ -3841,6 +3850,62 @@ static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType, return ret; } +static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType, + LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, + PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) +{ + BOOL ret; + struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, + CRYPT_AsnDecodePKCSSignerInfo, sizeof(CMSG_SIGNER_INFO), TRUE, + offsetof(CMSG_SIGNER_INFO, Issuer.pbData) }; + struct GenericArray *array = (struct GenericArray *)pvStructInfo; + + TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, + pDecodePara, pvStructInfo, *pcbStructInfo); + + ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, + pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL); + return ret; +} + +BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded, + DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, + CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo) +{ + BOOL ret = FALSE; + struct AsnDecodeSequenceItem items[] = { + { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt, + sizeof(DWORD), FALSE, FALSE, 0, 0 }, + /* Placeholder for the hash algorithms - redundant with those in the + * signers, so just ignore them. + */ + { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 }, + { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content), + CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO), + FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, + offsetof(CRYPT_SIGNED_INFO, cCertEncoded), + CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE, + offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 }, + { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, + offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray, + sizeof(struct GenericArray), TRUE, TRUE, + offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 }, + { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo), + CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE, + offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 }, + }; + + TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, + pDecodePara, signedInfo, *pcbSignedInfo); + + ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items, + sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, + pDecodePara, signedInfo, pcbSignedInfo, NULL); + TRACE("returning %d\n", ret); + return ret; +} + BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 7359ed88a64..b653a0dc644 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -1215,7 +1215,7 @@ struct DERSetDescriptor DWORD cItems; const void *items; size_t itemSize; - off_t itemOffset; + size_t itemOffset; CryptEncodeObjectExFunc encode; }; @@ -3201,26 +3201,36 @@ static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType, { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 }, { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, - { &info->HashEncryptionAlgorithm, - CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 }, }; - DWORD cItem = 4; + struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } }; + DWORD cItem = 3, cSwapped = 0; if (info->AuthAttrs.cAttr) { - items[cItem].pvStructInfo = &info->AuthAttrs; - items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0; + swapped[cSwapped].pvStructInfo = &info->AuthAttrs; + swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + items[cItem].pvStructInfo = &swapped[cSwapped]; + items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; + cSwapped++; cItem++; } + items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm; + items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams; + cItem++; + items[cItem].pvStructInfo = &info->EncryptedHash; + items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; + cItem++; if (info->UnauthAttrs.cAttr) { - items[cItem].pvStructInfo = &info->UnauthAttrs; - items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1; + swapped[cSwapped].pvStructInfo = &info->UnauthAttrs; + swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes; + items[cItem].pvStructInfo = &swapped[cSwapped]; + items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag; + cSwapped++; cItem++; } - items[cItem].pvStructInfo = &info->EncryptedHash; - items[cItem].encodeFunc = CRYPT_AsnEncodeOctets; - cItem++; ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded); } diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index ba75cb60a24..d932815ee4e 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -604,7 +604,8 @@ static BOOL CRYPT_IsValidSigner(CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer) typedef struct _CSignerHandles { HCRYPTPROV prov; - HCRYPTHASH hash; + HCRYPTHASH contentHash; + HCRYPTHASH authAttrHash; HCRYPTKEY key; } CSignerHandles; @@ -665,12 +666,18 @@ static void CRYPT_FreeBlobArray(BlobArray *array) static BOOL CRYPT_CopyAttribute(CRYPT_ATTRIBUTE *out, const CRYPT_ATTRIBUTE *in) { - /* Assumption: algorithm IDs will point to static strings, not stack-based - * ones, so copying the pointer values is safe. - */ - out->pszObjId = in->pszObjId; - return CRYPT_CopyBlobArray((BlobArray *)&out->cValue, - (const BlobArray *)&in->cValue); + BOOL ret; + + out->pszObjId = CryptMemAlloc(strlen(in->pszObjId) + 1); + if (out->pszObjId) + { + strcpy(out->pszObjId, in->pszObjId); + ret = CRYPT_CopyBlobArray((BlobArray *)&out->cValue, + (const BlobArray *)&in->cValue); + } + else + ret = FALSE; + return ret; } static BOOL CRYPT_CopyAttributes(CRYPT_ATTRIBUTES *out, @@ -711,7 +718,10 @@ static BOOL CSignerInfo_Construct(CSignerHandles *handles, if (!(open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)) CryptContextAddRef(handles->prov, NULL, 0); algID = CertOIDToAlgId(in->HashAlgorithm.pszObjId); - ret = CryptCreateHash(handles->prov, algID, 0, 0, &handles->hash); + ret = CryptCreateHash(handles->prov, algID, 0, 0, &handles->contentHash); + if (ret && in->cAuthAttr) + ret = CryptCreateHash(handles->prov, algID, 0, 0, + &handles->authAttrHash); if (ret) { /* Note: needs to change if CMS fields are supported */ @@ -752,6 +762,7 @@ static void CSignerInfo_Free(CMSG_SIGNER_INFO *info) for (j = 0; j < info->AuthAttrs.rgAttr[i].cValue; j++) CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue[j].pbData); CryptMemFree(info->AuthAttrs.rgAttr[i].rgValue); + CryptMemFree(info->AuthAttrs.rgAttr[i].pszObjId); } CryptMemFree(info->AuthAttrs.rgAttr); for (i = 0; i < info->UnauthAttrs.cAttr; i++) @@ -759,6 +770,7 @@ static void CSignerInfo_Free(CMSG_SIGNER_INFO *info) for (j = 0; j < info->UnauthAttrs.rgAttr[i].cValue; j++) CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue[j].pbData); CryptMemFree(info->UnauthAttrs.rgAttr[i].rgValue); + CryptMemFree(info->UnauthAttrs.rgAttr[i].pszObjId); } CryptMemFree(info->UnauthAttrs.rgAttr); } @@ -783,7 +795,8 @@ static void CSignedEncodeMsg_Close(HCRYPTMSG hCryptMsg) { CSignerInfo_Free(&msg->info.rgSignerInfo[i]); CryptDestroyKey(msg->signerHandles[i].key); - CryptDestroyHash(msg->signerHandles[i].hash); + CryptDestroyHash(msg->signerHandles[i].contentHash); + CryptDestroyHash(msg->signerHandles[i].authAttrHash); CryptReleaseContext(msg->signerHandles[i].prov, 0); } CryptMemFree(msg->signerHandles); @@ -862,7 +875,7 @@ static BOOL CSignedEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, if (dwIndex >= msg->info.cSignerInfo) SetLastError(CRYPT_E_INVALID_INDEX); else - ret = CryptGetHashParam(msg->signerHandles[dwIndex].hash, + ret = CryptGetHashParam(msg->signerHandles[dwIndex].contentHash, HP_HASHVAL, pvData, pcbData, 0); break; case CMSG_ENCODED_SIGNER: @@ -892,7 +905,103 @@ static BOOL CSignedEncodeMsg_UpdateHash(CSignedEncodeMsg *msg, TRACE("(%p, %p, %d)\n", msg, pbData, cbData); for (i = 0; ret && i < msg->info.cSignerInfo; i++) - ret = CryptHashData(msg->signerHandles[i].hash, pbData, cbData, 0); + ret = CryptHashData(msg->signerHandles[i].contentHash, pbData, cbData, + 0); + return ret; +} + +static BOOL CRYPT_AppendAttribute(CRYPT_ATTRIBUTES *out, + const CRYPT_ATTRIBUTE *in) +{ + BOOL ret = FALSE; + + out->rgAttr = CryptMemRealloc(out->rgAttr, + (out->cAttr + 1) * sizeof(CRYPT_ATTRIBUTE)); + if (out->rgAttr) + { + ret = CRYPT_CopyAttribute(&out->rgAttr[out->cAttr], in); + if (ret) + out->cAttr++; + } + return ret; +} + +static BOOL CSignedEncodeMsg_AppendMessageDigestAttribute(CSignedEncodeMsg *msg, + DWORD signerIndex) +{ + BOOL ret; + DWORD size; + CRYPT_HASH_BLOB hash = { 0, NULL }, encodedHash = { 0, NULL }; + char messageDigest[] = szOID_RSA_messageDigest; + CRYPT_ATTRIBUTE messageDigestAttr = { messageDigest, 1, &encodedHash }; + + size = sizeof(DWORD); + ret = CryptGetHashParam(msg->signerHandles[signerIndex].contentHash, + HP_HASHSIZE, (LPBYTE)&hash.cbData, &size, 0); + if (ret) + { + hash.pbData = CryptMemAlloc(hash.cbData); + ret = CryptGetHashParam(msg->signerHandles[signerIndex].contentHash, + HP_HASHVAL, hash.pbData, &hash.cbData, 0); + if (ret) + { + ret = CRYPT_AsnEncodeOctets(0, NULL, &hash, CRYPT_ENCODE_ALLOC_FLAG, + NULL, (LPBYTE)&encodedHash.pbData, &encodedHash.cbData); + if (ret) + { + ret = CRYPT_AppendAttribute( + &msg->info.rgSignerInfo[signerIndex].AuthAttrs, + &messageDigestAttr); + LocalFree(encodedHash.pbData); + } + } + CryptMemFree(hash.pbData); + } + return ret; +} + +static BOOL CSignedEncodeMsg_UpdateAuthenticatedAttributes( + CSignedEncodeMsg *msg) +{ + DWORD i; + BOOL ret = TRUE; + + TRACE("(%p)\n", msg); + + for (i = 0; ret && i < msg->info.cSignerInfo; i++) + { + if (msg->info.rgSignerInfo[i].AuthAttrs.cAttr) + { + BYTE oid_rsa_data_encoded[] = { 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, + 0x0d,0x01,0x07,0x01 }; + CRYPT_DATA_BLOB content = { sizeof(oid_rsa_data_encoded), + oid_rsa_data_encoded }; + char contentType[] = szOID_RSA_contentType; + CRYPT_ATTRIBUTE contentTypeAttr = { contentType, 1, &content }; + + /* FIXME: does this depend on inner OID? */ + ret = CRYPT_AppendAttribute(&msg->info.rgSignerInfo[i].AuthAttrs, + &contentTypeAttr); + if (ret) + ret = CSignedEncodeMsg_AppendMessageDigestAttribute(msg, i); + if (ret) + { + LPBYTE encodedAttrs; + DWORD size; + + ret = CryptEncodeObjectEx(X509_ASN_ENCODING, PKCS_ATTRIBUTES, + &msg->info.rgSignerInfo[i].AuthAttrs, CRYPT_ENCODE_ALLOC_FLAG, + NULL, (LPBYTE)&encodedAttrs, &size); + if (ret) + { + ret = CryptHashData(msg->signerHandles[i].authAttrHash, + encodedAttrs, size, 0); + LocalFree(encodedAttrs); + } + } + } + } + TRACE("returning %d\n", ret); return ret; } @@ -918,16 +1027,22 @@ static BOOL CSignedEncodeMsg_Sign(CSignedEncodeMsg *msg) for (i = 0; ret && i < msg->info.cSignerInfo; i++) { - ret = CryptSignHashW(msg->signerHandles[i].hash, AT_SIGNATURE, NULL, 0, - NULL, &msg->info.rgSignerInfo[i].EncryptedHash.cbData); + HCRYPTHASH hash; + + if (msg->info.rgSignerInfo[i].AuthAttrs.cAttr) + hash = msg->signerHandles[i].authAttrHash; + else + hash = msg->signerHandles[i].contentHash; + ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, NULL, + &msg->info.rgSignerInfo[i].EncryptedHash.cbData); if (ret) { msg->info.rgSignerInfo[i].EncryptedHash.pbData = CryptMemAlloc(msg->info.rgSignerInfo[i].EncryptedHash.cbData); if (msg->info.rgSignerInfo[i].EncryptedHash.pbData) { - ret = CryptSignHashW(msg->signerHandles[i].hash, AT_SIGNATURE, - NULL, 0, msg->info.rgSignerInfo[i].EncryptedHash.pbData, + ret = CryptSignHashW(hash, AT_SIGNATURE, NULL, 0, + msg->info.rgSignerInfo[i].EncryptedHash.pbData, &msg->info.rgSignerInfo[i].EncryptedHash.cbData); if (ret) CRYPT_ReverseBytes(&msg->info.rgSignerInfo[i].EncryptedHash); @@ -948,9 +1063,12 @@ static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, if (msg->base.streamed || (msg->base.open_flags & CMSG_DETACHED_FLAG)) { ret = CSignedEncodeMsg_UpdateHash(msg, pbData, cbData); - /* FIXME: hash authenticated attributes on final update */ if (ret && fFinal) - ret = CSignedEncodeMsg_Sign(msg); + { + ret = CSignedEncodeMsg_UpdateAuthenticatedAttributes(msg); + if (ret) + ret = CSignedEncodeMsg_Sign(msg); + } if (msg->base.streamed) FIXME("streamed partial stub\n"); } @@ -974,7 +1092,8 @@ static BOOL CSignedEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, ret = TRUE; if (ret) ret = CSignedEncodeMsg_UpdateHash(msg, pbData, cbData); - /* FIXME: hash authenticated attributes */ + if (ret) + ret = CSignedEncodeMsg_UpdateAuthenticatedAttributes(msg); if (ret) ret = CSignedEncodeMsg_Sign(msg); } @@ -1231,7 +1350,6 @@ static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg, &size); if (ret) { - msg->type = CMSG_HASHED; ContextPropertyList_SetProperty(msg->properties, CMSG_VERSION_PARAM, (const BYTE *)&digestedData->version, sizeof(digestedData->version)); CDecodeMsg_SaveAlgorithmID(msg, CMSG_HASH_ALGORITHM_PARAM, @@ -1254,6 +1372,23 @@ static BOOL CDecodeMsg_DecodeHashedContent(CDecodeMsg *msg, return ret; } +static BOOL CDecodeMsg_DecodeSignedContent(CDecodeMsg *msg, + CRYPT_DER_BLOB *blob) +{ + BOOL ret; + CRYPT_SIGNED_INFO *signedInfo; + DWORD size; + + ret = CRYPT_AsnDecodePKCSSignedInfo(blob->pbData, blob->cbData, + CRYPT_DECODE_ALLOC_FLAG, NULL, (CRYPT_SIGNED_INFO *)&signedInfo, + &size); + if (ret) + { + FIXME("store properties in message\n"); + LocalFree(signedInfo); + } + return ret; +} /* Decodes the content in blob as the type given, and updates the value * (type, parameters, etc.) of msg based on what blob contains. * It doesn't just use msg's type, to allow a recursive call from an implicitly @@ -1275,10 +1410,13 @@ static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob, msg->type = CMSG_HASHED; break; case CMSG_ENVELOPED: - case CMSG_SIGNED: FIXME("unimplemented for type %s\n", MSG_TYPE_STR(type)); ret = TRUE; break; + case CMSG_SIGNED: + if ((ret = CDecodeMsg_DecodeSignedContent(msg, blob))) + msg->type = CMSG_HASHED; + break; default: { CRYPT_CONTENT_INFO *info; diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 8173a128f25..467619a964b 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -4924,6 +4924,14 @@ static const BYTE PKCSSignerWithHash[] = { 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d, 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; +static const BYTE PKCSSignerWithAuthAttr[] = { +0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, +0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, +0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06, +0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55, +0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30, +0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05, +0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; static void test_encodePKCSSignerInfo(DWORD dwEncoding) { @@ -4932,6 +4940,10 @@ static void test_encodePKCSSignerInfo(DWORD dwEncoding) LPBYTE buf = NULL; DWORD size = 0; CMSG_SIGNER_INFO info = { 0 }; + char oid_common_name[] = szOID_COMMON_NAME; + CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName), + (LPBYTE)encodedCommonName }; + CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName }; SetLastError(0xdeadbeef); ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, @@ -5053,6 +5065,29 @@ static void test_encodePKCSSignerInfo(DWORD dwEncoding) LocalFree(buf); } } + info.AuthAttrs.cAttr = 1; + info.AuthAttrs.rgAttr = &attr; + SetLastError(0xdeadbeef); + ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (!(dwEncoding & PKCS_7_ASN_ENCODING)) + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + else + { + ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); + if (buf) + { + ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n", + size); + if (size == sizeof(PKCSSignerWithAuthAttr)) + ok(!memcmp(buf, PKCSSignerWithAuthAttr, size), + "Unexpected value\n"); + else + ok(0, "Unexpected value\n"); + LocalFree(buf); + } + } } static void test_decodePKCSSignerInfo(DWORD dwEncoding) @@ -5157,6 +5192,26 @@ static void test_decodePKCSSignerInfo(DWORD dwEncoding) "Unexpected value\n"); LocalFree(buf); } + ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, + PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr), + CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + if (buf) + { + info = (CMSG_SIGNER_INFO *)buf; + ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n", + info->AuthAttrs.cAttr); + ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME), + "Expected %s, got %s\n", szOID_COMMON_NAME, + info->AuthAttrs.rgAttr[0].pszObjId); + ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n", + info->AuthAttrs.rgAttr[0].cValue); + ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData == + sizeof(encodedCommonName), "Unexpected size %d\n", + info->AuthAttrs.rgAttr[0].rgValue[0].cbData); + ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData, + encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n"); + LocalFree(buf); + } } /* Free *pInfo with HeapFree */ diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index 3bd0882102b..8cfb72c8fde 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -1265,6 +1265,25 @@ static const BYTE signedEncodedSigner[] = { 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63, 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf, 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d }; +static const BYTE signedWithAuthAttrsBareContent[] = { +0x30,0x82,0x01,0x00,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86, +0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48, +0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31, +0x81,0xd5,0x30,0x81,0xd2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30, +0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, +0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7, +0x0d,0x02,0x05,0x05,0x00,0xa0,0x5b,0x30,0x18,0x06,0x09,0x2a,0x86,0x48,0x86, +0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x01,0x07,0x01,0x30,0x1e,0x06,0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31, +0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, +0x4c,0x61,0x6e,0x67,0x00,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79, +0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f,0x30,0x04,0x06,0x00,0x05,0x00,0x04, +0x40,0xbf,0x65,0xde,0x7a,0x3e,0xa2,0x19,0x59,0xc3,0xc7,0x02,0x53,0xc9,0x72, +0xcd,0x74,0x96,0x70,0x0b,0x3b,0xcf,0x8b,0xd9,0x17,0x5c,0xc5,0xd1,0x83,0x41, +0x32,0x93,0xa6,0xf3,0x52,0x83,0x94,0xa9,0x6b,0x0a,0x92,0xcf,0xaf,0x12,0xfa, +0x40,0x53,0x12,0x84,0x03,0xab,0x10,0xa2,0x3d,0xe6,0x9f,0x5a,0xbf,0xc5,0xb8, +0xff,0xc6,0x33,0x63,0x34 }; static BYTE cert[] = { 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11, 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, @@ -1393,6 +1412,10 @@ static void test_signed_msg_encoding(void) CERT_INFO certInfo = { 0 }; CERT_BLOB encodedCert = { sizeof(cert), cert }; CRL_BLOB encodedCrl = { sizeof(crl), crl }; + char oid_common_name[] = szOID_COMMON_NAME; + CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName), + encodedCommonName }; + CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName }; BOOL ret; HCRYPTKEY key; DWORD size; @@ -1458,6 +1481,20 @@ static void test_signed_msg_encoding(void) CryptMsgClose(msg); + signer.cAuthAttr = 1; + signer.rgAuthAttr = &attr; + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, + NULL, NULL); + ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); + + CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + check_param("signed with auth attrs bare content", msg, + CMSG_BARE_CONTENT_PARAM, signedWithAuthAttrsBareContent, + sizeof(signedWithAuthAttrsBareContent)); + + CryptMsgClose(msg); + + signer.cAuthAttr = 0; signInfo.rgCertEncoded = &encodedCert; signInfo.cCertEncoded = 1; msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo, @@ -1843,6 +1880,24 @@ static void test_decode_msg_update(void) ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE); ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError()); CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + ret = CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE); + ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent, + sizeof(signedWithCertAndCrlBareContent), TRUE); + ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL, + NULL); + ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent, + sizeof(signedWithCertAndCrlBareContent), TRUE); + ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError()); + CryptMsgClose(msg); } static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1, @@ -1853,6 +1908,7 @@ static void test_decode_msg_get_param(void) HCRYPTMSG msg; BOOL ret; DWORD size = 0, version; + LPBYTE buf; msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); SetLastError(0xdeadbeef); @@ -1879,7 +1935,19 @@ static void test_decode_msg_get_param(void) sizeof(hashParam)); check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM, hashParam, sizeof(hashParam)); - size = strlen(szOID_RSA_data) + 1; + /* Curiously, getting the hash of index 1 succeeds, even though there's + * only one hash. + */ + ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size); + ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError()); + buf = CryptMemAlloc(size); + if (buf) + { + ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, buf, &size); + ok(size == sizeof(hashParam), "Unexpected size %d\n", size); + ok(!memcmp(buf, hashParam, size), "Unexpected value\n"); + CryptMemFree(buf); + } check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM, (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1); version = CMSG_HASHED_DATA_V0; diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index d45385d4213..aa873ebfc72 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -333,7 +333,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9 iface, UIN IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hrc = D3D_OK; - TRACE("(%p) : W(%d) H(%d), Lvl(%d) d(%d), Fmt(%u), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool); + TRACE("(%p) : W(%d) H(%d), Lvl(%d) d(%d), Fmt(%#x), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool); /* Allocate the storage for the device */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture9Impl)); diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c index 791dd3075eb..de849fec7da 100644 --- a/dlls/dsound/dsound_main.c +++ b/dlls/dsound/dsound_main.c @@ -17,14 +17,10 @@ * 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 - */ -/* + * * Most thread locking is complete. There may be a few race * conditions still lurking. * - * Tested with a Soundblaster clone, a Gravis UltraSound Classic, - * and a Turtle Beach Tropez+. - * * TODO: * Implement SetCooperativeLevel properly (need to address focus issues) * Implement DirectSound3DBuffers (stubs in place) @@ -32,8 +28,8 @@ * Add critical section locking inside Release and AddRef methods * Handle static buffers - put those in hardware, non-static not in hardware * Hardware DuplicateSoundBuffer - * Proper volume calculation, and setting volume in HEL primary buffer - * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN + * Proper volume calculation for 3d buffers + * Remove DS_HEL_FRAGS and use mixer fragment length for it */ #include @@ -57,11 +53,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -/* these are eligible for tuning... they must be high on slow machines... */ -/* some stuff may get more responsive with lower values though... */ -#define DS_EMULDRIVER 0 /* some games (Quake 2, UT) refuse to accept - emulated dsound devices. set to 0 ! */ -#define DS_SND_QUEUE_MAX 10 /* max number of fragments to prebuffer */ +#define DS_SND_QUEUE_MAX 10 /* max number of fragments to prebuffer, each fragment is approximately 10 ms long */ DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS]; GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; @@ -94,7 +86,7 @@ HRESULT mmErr(UINT err) } } -int ds_emuldriver = DS_EMULDRIVER; +int ds_emuldriver = 0; int ds_snd_queue_max = DS_SND_QUEUE_MAX; int ds_hw_accel = DS_HW_ACCEL_FULL; int ds_default_playback = 0; @@ -181,8 +173,8 @@ void setup_dsound_options(void) if (appkey) RegCloseKey( appkey ); if (hkey) RegCloseKey( hkey ); - if (ds_emuldriver != DS_EMULDRIVER ) - WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER); + if (ds_emuldriver) + WARN("ds_emuldriver = %d (default=0)\n",ds_emuldriver); if (ds_snd_queue_max != DS_SND_QUEUE_MAX) WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX); if (ds_hw_accel != DS_HW_ACCEL_FULL) diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 7b4864e0311..b5af5fb8a6a 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -432,6 +432,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO int secondary_remainder = dsb->buflen - dsb->buf_mixpos; int adjusted_remainder = MulDiv(dsb->device->pwfx->nAvgBytesPerSec, secondary_remainder, dsb->nAvgBytesPerSec); assert(adjusted_remainder >= 0); + adjusted_remainder -= adjusted_remainder % dsb->device->pwfx->nBlockAlign; /* data alignment */ /* The adjusted remainder must be at least one sample, * otherwise we will never reach the end of the * secondary buffer, as there will perpetually be a @@ -542,6 +543,12 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO dsb->leadin = FALSE; } + /* check for notification positions */ + if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY && + dsb->state != STATE_STARTING) { + DSOUND_CheckEvent(dsb, dsb->buf_mixpos, ilen); + } + dsb->buf_mixpos += ilen; if (dsb->buf_mixpos >= dsb->buflen) { @@ -556,6 +563,9 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO } } + /* increase mix position */ + dsb->primary_mixpos += len; + dsb->primary_mixpos %= dsb->device->buflen; return len; } @@ -588,7 +598,7 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri { /* The buffer's primary_mixpos may be before or after the the device * buffer's mixpos, but both must be ahead of writepos. */ - DWORD primary_done; + DWORD primary_done, buflen = dsb->buflen / dsb->pwfx->nBlockAlign * dsb->device->pwfx->nBlockAlign; TRACE("(%p,%d,%d,%d)\n",dsb,playpos,writepos,mixlen); TRACE("writepos=%d, buf_mixpos=%d, primary_mixpos=%d, mixlen=%d\n", writepos, dsb->buf_mixpos, dsb->primary_mixpos, mixlen); @@ -606,27 +616,32 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri } /* take into acount already mixed data */ - mixlen = mixlen - primary_done; - - TRACE("mixlen (primary) = %i\n", mixlen); + mixlen -= primary_done; - /* clip to valid length */ - mixlen = (dsb->buflen < mixlen) ? dsb->buflen : mixlen; + TRACE("primary_done=%d, mixlen (primary) = %i\n", primary_done, mixlen); - TRACE("primary_done=%d, mixlen (buffer)=%d\n", primary_done, mixlen); - - /* mix more data */ - mixlen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen); + if ((dsb->playflags & DSBPLAY_LOOPING) && mixlen > buflen) + { + while (mixlen > buflen) + { + DWORD mixedlength = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, buflen); + mixlen -= buflen; + if (!mixedlength) + { + mixlen = 0; + break; + } + } - /* check for notification positions */ - if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY && - dsb->state != STATE_STARTING) { - DSOUND_CheckEvent(dsb, writepos, mixlen); } - /* increase mix position */ - dsb->primary_mixpos += mixlen; - dsb->primary_mixpos %= dsb->device->buflen; + /* clip to valid length */ + mixlen = (buflen < mixlen) ? buflen : mixlen; + TRACE("mixlen (buffer)=%d\n", mixlen); + + if (mixlen) + /* mix more data */ + mixlen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen); TRACE("new primary_mixpos=%d, mixed data len=%d, buffer left = %d\n", dsb->primary_mixpos, mixlen, (dsb->buflen - dsb->buf_mixpos)); diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c index ee1c49bc86b..80a4b9c4127 100644 --- a/dlls/gdiplus/gdiplus.c +++ b/dlls/gdiplus/gdiplus.c @@ -151,10 +151,10 @@ static void unstretch_angle(REAL * angle, REAL rad_x, REAL rad_y) *angle = deg2rad(*angle); - if(cos(*angle) == 0 || sin(*angle) == 0) + if(fabs(cos(*angle)) < 0.00001 || fabs(sin(*angle)) < 0.00001) return; - stretched = gdiplus_atan2(sin(*angle) / rad_y, cos(*angle) / rad_x); + stretched = gdiplus_atan2(sin(*angle) / fabs(rad_y), cos(*angle) / fabs(rad_x)); revs_off = roundr(*angle / (2.0 * M_PI)) - roundr(stretched / (2.0 * M_PI)); stretched += ((REAL)revs_off) * M_PI * 2.0; *angle = stretched; diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 74ba0473bf5..cf08c90d35e 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -14,7 +14,7 @@ @ stub GdipAddPathCurve3I @ stub GdipAddPathCurve @ stub GdipAddPathCurveI -@ stub GdipAddPathEllipse +@ stdcall GdipAddPathEllipse(ptr long long long long) @ stub GdipAddPathEllipseI @ stdcall GdipAddPathLine2(ptr ptr long) @ stub GdipAddPathLine2I @@ -338,7 +338,7 @@ @ stub GdipGetPenCompoundCount @ stub GdipGetPenCustomEndCap @ stub GdipGetPenCustomStartCap -@ stub GdipGetPenDashArray +@ stdcall GdipGetPenDashArray(ptr ptr long) @ stub GdipGetPenDashCap197819 @ stub GdipGetPenDashCount @ stub GdipGetPenDashOffset @@ -546,7 +546,7 @@ @ stub GdipSetPenCompoundArray @ stdcall GdipSetPenCustomEndCap(ptr ptr) @ stdcall GdipSetPenCustomStartCap(ptr ptr) -@ stub GdipSetPenDashArray +@ stdcall GdipSetPenDashArray(ptr ptr long) @ stub GdipSetPenDashCap197819 @ stub GdipSetPenDashOffset @ stdcall GdipSetPenDashStyle(ptr long) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 79800c29015..f20ea3d36b6 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -54,6 +54,8 @@ struct GpPen{ GpLineJoin join; REAL miterlimit; GpDashStyle dash; + REAL *dashes; + INT numdashes; GpBrush *brush; }; diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index f53ea4ce0ca..38364764c62 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -154,6 +154,7 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti, GdipCloneMatrix(graphics->worldtrans, &matrix); GdipScaleMatrix(matrix, unitscale, unitscale, MatrixOrderAppend); GdipTransformMatrixPoints(matrix, ptf, count); + GdipDeleteMatrix(matrix); for(i = 0; i < count; i++){ pti[i].x = roundr(ptf[i].X); diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index d0594822a34..4fe99e071c2 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -121,6 +121,36 @@ GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath *path, GDIPCONST GpPointF *points, return Ok; } +GpStatus WINGDIPAPI GdipAddPathEllipse(GpPath *path, REAL x, REAL y, REAL width, + REAL height) +{ + INT old_count, numpts; + + if(!path) + return InvalidParameter; + + if(!lengthen_path(path, MAX_ARC_PTS)) + return OutOfMemory; + + old_count = path->pathdata.Count; + if((numpts = arc2polybezier(&path->pathdata.Points[old_count], x, y, width, + height, 0.0, 360.0)) != MAX_ARC_PTS){ + ERR("expected %d points but got %d\n", MAX_ARC_PTS, numpts); + return GenericError; + } + + memset(&path->pathdata.Types[old_count + 1], PathPointTypeBezier, + MAX_ARC_PTS - 1); + + /* An ellipse is an instrinsic figure (always its own subpath). */ + path->pathdata.Types[old_count] = PathPointTypeStart; + path->pathdata.Types[old_count + MAX_ARC_PTS - 1] |= PathPointTypeCloseSubpath; + path->newfigure = TRUE; + path->pathdata.Count += MAX_ARC_PTS; + + return Ok; +} + GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points, INT count) { diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c index 3026d5242fe..e582f7644c6 100644 --- a/dlls/gdiplus/pen.c +++ b/dlls/gdiplus/pen.c @@ -123,6 +123,7 @@ GpStatus WINGDIPAPI GdipDeletePen(GpPen *pen) GdipDeleteBrush(pen->brush); GdipDeleteCustomLineCap(pen->customstart); GdipDeleteCustomLineCap(pen->customend); + GdipFree(pen->dashes); GdipFree(pen); return Ok; @@ -147,6 +148,20 @@ GpStatus WINGDIPAPI GdipGetPenColor(GpPen *pen, ARGB *argb) return GdipGetSolidFillColor(((GpSolidFill*)pen->brush), argb); } +GpStatus WINGDIPAPI GdipGetPenDashArray(GpPen *pen, REAL *dash, INT count) +{ + if(!pen || !dash || count > pen->numdashes) + return InvalidParameter; + + /* note: if you pass a negative value for count, it crashes native gdiplus. */ + if(count < 0) + return GenericError; + + memcpy(dash, pen->dashes, count * sizeof(REAL)); + + return Ok; +} + GpStatus WINGDIPAPI GdipGetPenDashStyle(GpPen *pen, GpDashStyle *dash) { if(!pen || !dash) @@ -209,11 +224,40 @@ GpStatus WINGDIPAPI GdipSetPenCustomStartCap(GpPen *pen, GpCustomLineCap* custom return ret; } +GpStatus WINGDIPAPI GdipSetPenDashArray(GpPen *pen, GDIPCONST REAL *dash, + INT count) +{ + if(!pen || !dash) + return InvalidParameter; + + GdipFree(pen->dashes); + pen->dashes = NULL; + + if(count > 0) + pen->dashes = GdipAlloc(count * sizeof(REAL)); + if(!pen->dashes){ + pen->numdashes = 0; + return OutOfMemory; + } + + pen->dash = DashStyleCustom; + memcpy(pen->dashes, dash, count * sizeof(REAL)); + pen->numdashes = count; + + return Ok; +} + GpStatus WINGDIPAPI GdipSetPenDashStyle(GpPen *pen, GpDashStyle dash) { if(!pen) return InvalidParameter; + if(dash != DashStyleCustom){ + GdipFree(pen->dashes); + pen->dashes = NULL; + pen->numdashes = 0; + } + pen->dash = dash; pen->style &= ~(PS_ALTERNATE | PS_SOLID | PS_DASH | PS_DOT | PS_DASHDOT | PS_DASHDOTDOT | PS_NULL | PS_USERSTYLE | PS_INSIDEFRAME); diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c index 729971eea28..5896fcd60c8 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -433,6 +433,76 @@ static void test_pathpath(void) GdipDeletePath(path2); } +static path_test_t ellipse_path[] = { + {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/ + {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/ + {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/ + {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/ + {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/ + {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/ + {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/ + {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/ + {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/ + {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/ + {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/ + {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/ + {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/ + {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/ + {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/ + {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/ + {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/ + {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/ + {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/ + {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/ + {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/ + {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/ + {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/ + {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/ + {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/ + {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/ + {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/ + {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/ + {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/ + {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/ + {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/ + {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/ + {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/ + {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/ + {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/ + {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/ + {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/ + }; + +static void test_ellipse(void) +{ + GpStatus status; + GpPath *path; + GpPointF points[2]; + + points[0].X = 7.0; + points[0].Y = 11.0; + points[1].X = 13.0; + points[1].Y = 17.0; + + GdipCreatePath(FillModeAlternate, &path); + status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5); + expect(Ok, status); + GdipAddPathLine2(path, points, 2); + status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0); + expect(Ok, status); + GdipClosePathFigure(path); + status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0); + expect(Ok, status); + + ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE); + + GdipDeletePath(path); +} + START_TEST(graphicspath) { struct GdiplusStartupInput gdiplusStartupInput; @@ -450,6 +520,7 @@ START_TEST(graphicspath) test_arc(); test_worldbounds(); test_pathpath(); + test_ellipse(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/gdiplus/tests/pen.c b/dlls/gdiplus/tests/pen.c index 0238aacf335..5221423172a 100644 --- a/dlls/gdiplus/tests/pen.c +++ b/dlls/gdiplus/tests/pen.c @@ -19,12 +19,14 @@ */ #include +#include #include "windef.h" #include "gdiplus.h" #include "wine/test.h" #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expectf(expected, got) ok(fabs(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got) static void test_startup(void) { @@ -116,6 +118,71 @@ static void test_brushfill(void) GdipDeletePen(pen); } +static void test_dasharray(void) +{ + GpPen *pen; + GpDashStyle style; + GpStatus status; + REAL dashes[12]; + + GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen); + dashes[0] = 10.0; + dashes[1] = 11.0; + dashes[2] = 12.0; + dashes[3] = 13.0; + dashes[4] = 14.0; + dashes[5] = -100.0; + dashes[6] = -100.0; + + /* setting the array sets the type to custom */ + GdipGetPenDashStyle(pen, &style); + expect(DashStyleSolid, style); + status = GdipSetPenDashArray(pen, dashes, 2); + expect(Ok, status); + GdipGetPenDashStyle(pen, &style); + expect(DashStyleCustom, style); + + /* Getting the array on a non-custom pen returns invalid parameter (unless + * you are getting 0 elements).*/ + GdipSetPenDashStyle(pen, DashStyleSolid); + status = GdipGetPenDashArray(pen, &dashes[5], 2); + expect(InvalidParameter, status); + status = GdipGetPenDashArray(pen, &dashes[5], 0); + expect(Ok, status); + + /* What does setting DashStyleCustom do to the array length? */ + GdipSetPenDashArray(pen, dashes, 2); + GdipSetPenDashStyle(pen, DashStyleCustom); + status = GdipGetPenDashArray(pen, &dashes[5], 2); + expect(Ok, status); + expectf(10.0, dashes[5]); + expectf(11.0, dashes[6]); + + /* Set the array, then get with different sized buffers. */ + status = GdipSetPenDashArray(pen, dashes, 5); + expect(Ok, status); + dashes[5] = -100.0; + dashes[6] = -100.0; + status = GdipGetPenDashArray(pen, &dashes[5], 1); + expect(Ok, status); /* not InsufficientBuffer! */ + expectf(10.0, dashes[5]); + expectf(-100.0, dashes[6]); + dashes[5] = -100.0; + status = GdipGetPenDashArray(pen, &dashes[5], 6); + expect(InvalidParameter, status); /* not Ok! */ + expectf(-100.0, dashes[5]); + expectf(-100.0, dashes[6]); + + /* Try to set with count = 0. */ + GdipSetPenDashStyle(pen, DashStyleDot); + status = GdipSetPenDashArray(pen, dashes, 0); + expect(OutOfMemory, status); + GdipGetPenDashStyle(pen, &style); + expect(DashStyleDot, style); + + GdipDeletePen(pen); +} + START_TEST(pen) { struct GdiplusStartupInput gdiplusStartupInput; @@ -132,6 +199,7 @@ START_TEST(pen) test_constructor_destructor(); test_brushfill(); + test_dasharray(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/kernel32/actctx.c b/dlls/kernel32/actctx.c index 84c29cdf7e6..4591d8bc22c 100644 --- a/dlls/kernel32/actctx.c +++ b/dlls/kernel32/actctx.c @@ -219,10 +219,27 @@ BOOL WINAPI FindActCtxSectionStringA(DWORD dwFlags, const GUID* lpExtGuid, ULONG ulId, LPCSTR lpSearchStr, PACTCTX_SECTION_KEYED_DATA pInfo) { - FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), - ulId, debugstr_a(lpSearchStr), pInfo); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + LPWSTR search_str; + DWORD len; + BOOL ret; + + TRACE("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), + ulId, debugstr_a(lpSearchStr), pInfo); + + if (!lpSearchStr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + len = MultiByteToWideChar(CP_ACP, 0, lpSearchStr, -1, NULL, 0); + search_str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpSearchStr, -1, search_str, len); + + ret = FindActCtxSectionStringW(dwFlags, lpExtGuid, ulId, search_str, pInfo); + + HeapFree(GetProcessHeap(), 0, search_str); + return ret; } /*********************************************************************** @@ -234,39 +251,16 @@ BOOL WINAPI FindActCtxSectionStringW(DWORD dwFlags, const GUID* lpExtGuid, ULONG ulId, LPCWSTR lpSearchStr, PACTCTX_SECTION_KEYED_DATA pInfo) { - FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid), - ulId, debugstr_w(lpSearchStr), pInfo); - - if (lpExtGuid) - { - FIXME("expected lpExtGuid == NULL\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (dwFlags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) - { - FIXME("unknown dwFlags %08x\n", dwFlags); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (!pInfo || pInfo->cbSize < sizeof (ACTCTX_SECTION_KEYED_DATA)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - pInfo->ulDataFormatVersion = 1; - pInfo->lpData = NULL; - pInfo->lpSectionGlobalData = NULL; - pInfo->ulSectionGlobalDataLength = 0; - pInfo->lpSectionBase = NULL; - pInfo->ulSectionTotalLength = 0; - pInfo->hActCtx = ACTCTX_FAKE_HANDLE; - pInfo->ulAssemblyRosterIndex = 0; + UNICODE_STRING us; + NTSTATUS status; - return TRUE; + RtlInitUnicodeString(&us, lpSearchStr); + if ((status = RtlFindActivationContextSectionString(dwFlags, lpExtGuid, ulId, &us, pInfo))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; } /*********************************************************************** @@ -293,9 +287,13 @@ BOOL WINAPI QueryActCtxW(DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInst, ULONG ulClass, PVOID pvBuff, SIZE_T cbBuff, SIZE_T *pcbLen) { - FIXME("%08x %p %p %u %p %ld %p\n", dwFlags, hActCtx, - pvSubInst, ulClass, pvBuff, cbBuff, pcbLen); - /* this makes Adobe Photoshop 7.0 happy */ - SetLastError( ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS status; + + if ((status = RtlQueryInformationActivationContext( dwFlags, hActCtx, pvSubInst, ulClass, + pvBuff, cbBuff, pcbLen ))) + { + SetLastError(RtlNtStatusToDosError(status)); + return FALSE; + } + return TRUE; } diff --git a/dlls/kernel32/tests/Makefile.in b/dlls/kernel32/tests/Makefile.in index 92d03670ba3..ca3c60899af 100644 --- a/dlls/kernel32/tests/Makefile.in +++ b/dlls/kernel32/tests/Makefile.in @@ -6,6 +6,7 @@ TESTDLL = kernel32.dll IMPORTS = advapi32 kernel32 CTESTS = \ + actctx.c \ alloc.c \ atom.c \ change.c \ diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c new file mode 100644 index 00000000000..417f4d4cd14 --- /dev/null +++ b/dlls/kernel32/tests/actctx.c @@ -0,0 +1,1058 @@ +/* + * Copyright 2007 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); +static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); +static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR); +static BOOL (WINAPI *pFindActCtxSectionStringW)(DWORD,const GUID *,ULONG,LPCWSTR,PACTCTX_SECTION_KEYED_DATA); +static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *); +static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,PVOID,ULONG,PVOID,SIZE_T,SIZE_T*); +static VOID (WINAPI *pReleaseActCtx)(HANDLE); + +static const char* strw(LPCWSTR x) +{ + static char buffer[1024]; + char* p = buffer; + + if (!x) return "(nil)"; + else while ((*p++ = *x++)); + return buffer; +} + +static const char manifest1[] = +"" +"" +""; + +static const char manifest2[] = +"" +"" +"" +"" +"" +"" +"" +"" +"" +""; + +static const char manifest3[] = +"" +"" +"" +"wndClass" +"" +""; + +static const char manifest4[] = +"" +"" +"" +"" +"" +"" +"" +"" +"" +""; + +static const char testdep_manifest1[] = +"" +"" +""; + +static const char testdep_manifest2[] = +"" +"" +"" +"" +""; + +static const char testdep_manifest3[] = +" " +"" +"" +"" +"wndClass" +"wndClass2" +"" +""; + +static const char wrong_manifest1[] = +"" +"" +""; + +static const char wrong_manifest2[] = +"" +"" +""; + +static const char wrong_manifest3[] = +"" +"" +""; + +static const char wrong_manifest4[] = +"" +"" +"" +""; + +static const char wrong_manifest5[] = +"" +"" +"" +""; + +static const char wrong_manifest6[] = +"" +"" +""; + +static const char wrong_manifest7[] = +"" +"" +"" +""; + +static const char wrong_manifest8[] = +"" +"" +"" +""; + +static const char wrong_depmanifest1[] = +"" +"" +""; + +static const WCHAR testlib_dll[] = + {'t','e','s','t','l','i','b','.','d','l','l',0}; +static const WCHAR testlib2_dll[] = + {'t','e','s','t','l','i','b','2','.','d','l','l',0}; +static const WCHAR wndClassW[] = + {'w','n','d','C','l','a','s','s',0}; +static const WCHAR wndClass2W[] = + {'w','n','d','C','l','a','s','s','2',0}; +static const WCHAR acr_manifest[] = + {'a','c','r','.','m','a','n','i','f','e','s','t',0}; + +static WCHAR app_dir[MAX_PATH], exe_path[MAX_PATH]; +static WCHAR app_manifest_path[MAX_PATH], manifest_path[MAX_PATH], depmanifest_path[MAX_PATH]; + +static int strcmp_aw(LPCWSTR strw, const char *stra) +{ + WCHAR buf[1024]; + + if (!stra) return 1; + MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)); + return lstrcmpW(strw, buf); +} + +static DWORD strlen_aw(const char *str) +{ + return MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0) - 1; +} + +static BOOL create_manifest_file(const char *filename, const char *manifest, + const char *depfile, const char *depmanifest) +{ + DWORD size; + HANDLE file; + WCHAR path[MAX_PATH]; + + MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); + GetFullPathNameW(path, sizeof(manifest_path)/sizeof(WCHAR), manifest_path, NULL); + + file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); + if(file == INVALID_HANDLE_VALUE) + return FALSE; + WriteFile(file, manifest, strlen(manifest), &size, NULL); + CloseHandle(file); + + if (depmanifest) + { + MultiByteToWideChar( CP_ACP, 0, depfile, -1, path, MAX_PATH ); + GetFullPathNameW(path, sizeof(depmanifest_path)/sizeof(WCHAR), depmanifest_path, NULL); + file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); + if(file == INVALID_HANDLE_VALUE) + return FALSE; + WriteFile(file, depmanifest, strlen(depmanifest), &size, NULL); + CloseHandle(file); + } + return TRUE; +} + +typedef struct { + ULONG format_version; + ULONG assembly_cnt; + ULONG root_manifest_type; + LPWSTR root_manifest_path; + ULONG root_config_type; + ULONG app_dir_type; + LPCWSTR app_dir; +} detailed_info_t; + +static const detailed_info_t detailed_info0 = { + 0, 0, 0, NULL, 0, 0, NULL +}; + +static const detailed_info_t detailed_info1 = { + 1, 1, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, manifest_path, + ACTIVATION_CONTEXT_PATH_TYPE_NONE, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, + app_dir, +}; + +static const detailed_info_t detailed_info1_child = { + 1, 1, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, app_manifest_path, + ACTIVATION_CONTEXT_PATH_TYPE_NONE, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, + app_dir, +}; + +static const detailed_info_t detailed_info2 = { + 1, 2, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, manifest_path, + ACTIVATION_CONTEXT_PATH_TYPE_NONE, ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, + app_dir, +}; + +static void test_detailed_info(HANDLE handle, const detailed_info_t *exinfo) +{ + ACTIVATION_CONTEXT_DETAILED_INFORMATION detailed_info_tmp, *detailed_info; + SIZE_T size, exsize, retsize; + BOOL b; + + exsize = sizeof(ACTIVATION_CONTEXT_DETAILED_INFORMATION) + + (exinfo->root_manifest_path ? (lstrlenW(exinfo->root_manifest_path)+1)*sizeof(WCHAR):0) + + (exinfo->app_dir ? (lstrlenW(app_dir)+1)*sizeof(WCHAR) : 0); + + if(exsize != sizeof(ACTIVATION_CONTEXT_DETAILED_INFORMATION)) { + size = 0xdeadbeef; + b = pQueryActCtxW(0, handle, NULL, + ActivationContextDetailedInformation, &detailed_info_tmp, + sizeof(detailed_info_tmp), &size); + ok(!b, "QueryActCtx succeeded\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() = %u\n", GetLastError()); + ok(size == exsize, "size=%ld, expected %ld\n", size, exsize); + }else { + size = sizeof(ACTIVATION_CONTEXT_DETAILED_INFORMATION); + } + + detailed_info = HeapAlloc(GetProcessHeap(), 0, size); + memset(detailed_info, 0xfe, size); + b = pQueryActCtxW(0, handle, NULL, + ActivationContextDetailedInformation, detailed_info, + size, &retsize); + ok(b, "QueryActCtx failed: %u\n", GetLastError()); + ok(retsize == exsize, "size=%ld, expected %ld\n", retsize, exsize); + + ok(detailed_info->dwFlags == 0, "detailed_info->dwFlags=%x\n", detailed_info->dwFlags); + ok(detailed_info->ulFormatVersion == exinfo->format_version, + "detailed_info->ulFormatVersion=%u, expected %u\n", detailed_info->ulFormatVersion, + exinfo->format_version); + ok(detailed_info->ulAssemblyCount == exinfo->assembly_cnt, + "detailed_info->ulAssemblyCount=%u, expected %u\n", detailed_info->ulAssemblyCount, + exinfo->assembly_cnt); + ok(detailed_info->ulRootManifestPathType == exinfo->root_manifest_type, + "detailed_info->ulRootManifestPathType=%u, expected %u\n", + detailed_info->ulRootManifestPathType, exinfo->root_manifest_type); + ok(detailed_info->ulRootManifestPathChars == + (exinfo->root_manifest_path ? lstrlenW(exinfo->root_manifest_path) : 0), + "detailed_info->ulRootManifestPathChars=%u, expected %u\n", + detailed_info->ulRootManifestPathChars, + exinfo->root_manifest_path ?lstrlenW(exinfo->root_manifest_path) : 0); + ok(detailed_info->ulRootConfigurationPathType == exinfo->root_config_type, + "detailed_info->ulRootConfigurationPathType=%u, expected %u\n", + detailed_info->ulRootConfigurationPathType, exinfo->root_config_type); + ok(detailed_info->ulRootConfigurationPathChars == 0, + "detailed_info->ulRootConfigurationPathChars=%d\n", detailed_info->ulRootConfigurationPathChars); + ok(detailed_info->ulAppDirPathType == exinfo->app_dir_type, + "detailed_info->ulAppDirPathType=%u, expected %u\n", detailed_info->ulAppDirPathType, + exinfo->app_dir_type); + ok(detailed_info->ulAppDirPathChars == (exinfo->app_dir ? lstrlenW(app_dir) : 0), + "detailed_info->ulAppDirPathChars=%u, expected %u\n", + detailed_info->ulAppDirPathChars, exinfo->app_dir ? lstrlenW(app_dir) : 0); + if(exinfo->root_manifest_path) { + ok(detailed_info->lpRootManifestPath != NULL, "detailed_info->lpRootManifestPath == NULL\n"); + if(detailed_info->lpRootManifestPath) + ok(!lstrcmpiW(detailed_info->lpRootManifestPath, exinfo->root_manifest_path), + "unexpected detailed_info->lpRootManifestPath\n"); + }else { + ok(detailed_info->lpRootManifestPath == NULL, "detailed_info->lpRootManifestPath != NULL\n"); + } + ok(detailed_info->lpRootConfigurationPath == NULL, + "detailed_info->lpRootConfigurationPath=%p\n", detailed_info->lpRootConfigurationPath); + if(exinfo->app_dir) { + ok(detailed_info->lpAppDirPath != NULL, "detailed_info->lpAppDirPath == NULL\n"); + if(detailed_info->lpAppDirPath) + ok(!lstrcmpiW(app_dir, detailed_info->lpAppDirPath), + "unexpected detailed_info->lpAppDirPath %s\n",strw(detailed_info->lpAppDirPath)); + }else { + ok(detailed_info->lpAppDirPath == NULL, "detailed_info->lpAppDirPath != NULL\n"); + } + + HeapFree(GetProcessHeap(), 0, detailed_info); +} + +typedef struct { + ULONG flags; +/* ULONG manifest_path_type; FIXME */ + LPCWSTR manifest_path; + LPCSTR encoded_assembly_id; + BOOL has_assembly_dir; +} info_in_assembly; + +static const info_in_assembly manifest1_info = { + 1, manifest_path, + "Wine.Test,type=\"win32\",version=\"1.0.0.0\"", + FALSE +}; + +static const info_in_assembly manifest1_child_info = { + 1, app_manifest_path, + "Wine.Test,type=\"win32\",version=\"1.0.0.0\"", + FALSE +}; + +static const info_in_assembly manifest2_info = { + 1, manifest_path, + "Wine.Test,type=\"win32\",version=\"1.2.3.4\"", + FALSE +}; + +static const info_in_assembly manifest3_info = { + 1, manifest_path, + "Wine.Test,publicKeyToken=\"6595b6414666f1df\",type=\"win32\",version=\"1.2.3.4\"", + FALSE +}; + +static const info_in_assembly manifest4_info = { + 1, manifest_path, + "Wine.Test,type=\"win32\",version=\"1.2.3.4\"", + FALSE +}; + +static const info_in_assembly depmanifest1_info = { + 0x10, depmanifest_path, + "testdep,processorArchitecture=\"x86\"," + "type=\"win32\",version=\"6.5.4.3\"", + TRUE +}; + +static const info_in_assembly depmanifest2_info = { + 0x10, depmanifest_path, + "testdep,processorArchitecture=\"x86\"," + "type=\"win32\",version=\"6.5.4.3\"", + TRUE +}; + +static const info_in_assembly depmanifest3_info = { + 0x10, depmanifest_path, + "testdep,processorArchitecture=\"x86\",type=\"win32\",version=\"6.5.4.3\"", + TRUE +}; + +static const info_in_assembly manifest_comctrl_info = { + 0, NULL, NULL, TRUE /* These values may differ between Windows installations */ +}; + +static void test_info_in_assembly(HANDLE handle, DWORD id, const info_in_assembly *exinfo) +{ + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info, info_tmp; + SIZE_T size, exsize; + ULONG len; + BOOL b; + + exsize = sizeof(ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION); + if (exinfo->manifest_path) exsize += (lstrlenW(exinfo->manifest_path)+1) * sizeof(WCHAR); + if (exinfo->encoded_assembly_id) exsize += (strlen_aw(exinfo->encoded_assembly_id) + 1) * sizeof(WCHAR); + + size = 0xdeadbeef; + b = pQueryActCtxW(0, handle, &id, + AssemblyDetailedInformationInActivationContext, &info_tmp, + sizeof(info_tmp), &size); + ok(!b, "QueryActCtx succeeded\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() = %u\n", GetLastError()); + + ok(size >= exsize, "size=%lu, expected %lu\n", size, exsize); + + if (size == 0xdeadbeef) + { + skip("bad size\n"); + return; + } + + info = HeapAlloc(GetProcessHeap(), 0, size); + memset(info, 0xfe, size); + + size = 0xdeadbeef; + b = pQueryActCtxW(0, handle, &id, + AssemblyDetailedInformationInActivationContext, info, size, &size); + ok(b, "QueryActCtx failed: %u\n", GetLastError()); + if (!exinfo->manifest_path) + exsize += info->ulManifestPathLength + sizeof(WCHAR); + if (!exinfo->encoded_assembly_id) + exsize += info->ulEncodedAssemblyIdentityLength + sizeof(WCHAR); + if (exinfo->has_assembly_dir) + exsize += info->ulAssemblyDirectoryNameLength + sizeof(WCHAR); + ok(size == exsize, "size=%lu, expected %lu\n", size, exsize); + + if (0) /* FIXME: flags meaning unknown */ + { + ok((info->ulFlags) == exinfo->flags, "info->ulFlags = %x, expected %x\n", + info->ulFlags, exinfo->flags); + } + if(exinfo->encoded_assembly_id) { + len = strlen_aw(exinfo->encoded_assembly_id)*sizeof(WCHAR); + ok(info->ulEncodedAssemblyIdentityLength == len, + "info->ulEncodedAssemblyIdentityLength = %u, expected %u\n", + info->ulEncodedAssemblyIdentityLength, len); + } else { + ok(info->ulEncodedAssemblyIdentityLength != 0, + "info->ulEncodedAssemblyIdentityLength == 0\n"); + } + ok(info->ulManifestPathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, + "info->ulManifestPathType = %x\n", info->ulManifestPathType); + if(exinfo->manifest_path) { + len = lstrlenW(exinfo->manifest_path)*sizeof(WCHAR); + ok(info->ulManifestPathLength == len, "info->ulManifestPathLength = %u, expected %u\n", + info->ulManifestPathLength, len); + } else { + ok(info->ulManifestPathLength != 0, "info->ulManifestPathLength == 0\n"); + } + + ok(info->ulPolicyPathType == ACTIVATION_CONTEXT_PATH_TYPE_NONE, + "info->ulPolicyPathType = %x\n", info->ulPolicyPathType); + ok(info->ulPolicyPathLength == 0, + "info->ulPolicyPathLength = %u, expected 0\n", info->ulPolicyPathLength); + ok(info->ulMetadataSatelliteRosterIndex == 0, "info->ulMetadataSatelliteRosterIndex = %x\n", + info->ulMetadataSatelliteRosterIndex); + ok(info->ulManifestVersionMajor == 1,"info->ulManifestVersionMajor = %x\n", + info->ulManifestVersionMajor); + ok(info->ulManifestVersionMinor == 0, "info->ulManifestVersionMinor = %x\n", + info->ulManifestVersionMinor); + ok(info->ulPolicyVersionMajor == 0, "info->ulPolicyVersionMajor = %x\n", + info->ulPolicyVersionMajor); + ok(info->ulPolicyVersionMinor == 0, "info->ulPolicyVersionMinor = %x\n", + info->ulPolicyVersionMinor); + if(exinfo->has_assembly_dir) + ok(info->ulAssemblyDirectoryNameLength != 0, + "info->ulAssemblyDirectoryNameLength == 0\n"); + else + ok(info->ulAssemblyDirectoryNameLength == 0, + "info->ulAssemblyDirectoryNameLength != 0\n"); + + ok(info->lpAssemblyEncodedAssemblyIdentity != NULL, + "info->lpAssemblyEncodedAssemblyIdentity == NULL\n"); + if(info->lpAssemblyEncodedAssemblyIdentity && exinfo->encoded_assembly_id) { + ok(!strcmp_aw(info->lpAssemblyEncodedAssemblyIdentity, exinfo->encoded_assembly_id), + "unexpected info->lpAssemblyEncodedAssemblyIdentity %s / %s\n", + strw(info->lpAssemblyEncodedAssemblyIdentity), exinfo->encoded_assembly_id); + } + if(exinfo->manifest_path) { + ok(info->lpAssemblyManifestPath != NULL, "info->lpAssemblyManifestPath == NULL\n"); + if(info->lpAssemblyManifestPath) + ok(!lstrcmpiW(info->lpAssemblyManifestPath, exinfo->manifest_path), + "unexpected info->lpAssemblyManifestPath\n"); + }else { + ok(info->lpAssemblyManifestPath != NULL, "info->lpAssemblyManifestPath == NULL\n"); + } + + ok(info->lpAssemblyPolicyPath == NULL, "info->lpAssemblyPolicyPath != NULL\n"); + if(info->lpAssemblyPolicyPath) + ok(*(WORD*)info->lpAssemblyPolicyPath == 0, "info->lpAssemblyPolicyPath is not empty\n"); + if(exinfo->has_assembly_dir) + ok(info->lpAssemblyDirectoryName != NULL, "info->lpAssemblyDirectoryName == NULL\n"); + else + ok(info->lpAssemblyDirectoryName == NULL, "info->lpAssemblyDirectoryName = %s\n", + strw(info->lpAssemblyDirectoryName)); +} + +static void test_file_info(HANDLE handle, ULONG assid, ULONG fileid, LPCWSTR filename) +{ + ASSEMBLY_FILE_DETAILED_INFORMATION *info, info_tmp; + ACTIVATION_CONTEXT_QUERY_INDEX index = {assid, fileid}; + SIZE_T size, exsize; + BOOL b; + + exsize = sizeof(ASSEMBLY_FILE_DETAILED_INFORMATION) + +(lstrlenW(filename)+1)*sizeof(WCHAR); + + size = 0xdeadbeef; + b = pQueryActCtxW(0, handle, &index, + FileInformationInAssemblyOfAssemblyInActivationContext, &info_tmp, + sizeof(info_tmp), &size); + ok(!b, "QueryActCtx succeeded\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() = %u\n", GetLastError()); + ok(size == exsize, "size=%lu, expected %lu\n", size, exsize); + + if(size == 0xdeadbeef) + { + skip("bad size\n"); + return; + } + + info = HeapAlloc(GetProcessHeap(), 0, size); + memset(info, 0xfe, size); + + b = pQueryActCtxW(0, handle, &index, + FileInformationInAssemblyOfAssemblyInActivationContext, info, size, &size); + ok(b, "QueryActCtx failed: %u\n", GetLastError()); + ok(!size, "size=%lu, expected 0\n", size); + + ok(info->ulFlags == 2, "info->ulFlags=%x, expected 2\n", info->ulFlags); + ok(info->ulFilenameLength == lstrlenW(filename)*sizeof(WCHAR), + "info->ulFilenameLength=%u, expected %u\n", + info->ulFilenameLength, lstrlenW(filename)*sizeof(WCHAR)); + ok(info->ulPathLength == 0, "info->ulPathLength=%u\n", info->ulPathLength); + ok(info->lpFileName != NULL, "info->lpFileName == NULL\n"); + if(info->lpFileName) + ok(!lstrcmpiW(info->lpFileName, filename), "unexpected info->lpFileName\n"); + ok(info->lpFilePath == NULL, "info->lpFilePath != NULL\n"); +} + +static HANDLE test_create(const char *file, const char *manifest) +{ + ACTCTXW actctx; + HANDLE handle; + WCHAR path[MAX_PATH]; + + MultiByteToWideChar( CP_ACP, 0, file, -1, path, MAX_PATH ); + memset(&actctx, 0, sizeof(ACTCTXW)); + actctx.cbSize = sizeof(ACTCTXW); + actctx.lpSource = path; + + handle = pCreateActCtxW(&actctx); + ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + + ok(actctx.cbSize == sizeof(actctx), "actctx.cbSize=%d\n", actctx.cbSize); + ok(actctx.dwFlags == 0, "actctx.=%d\n", actctx.dwFlags); + ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource); + ok(actctx.wProcessorArchitecture == 0, + "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); + ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId); + ok(actctx.lpAssemblyDirectory == NULL, + "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); + ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName); + ok(actctx.lpApplicationName == NULL, "actctx.lpApplocationName=%p\n", + actctx.lpApplicationName); + ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule); + + return handle; +} + +static void test_create_and_fail(const char *manifest, const char *depmanifest, int todo) +{ + ACTCTXW actctx; + HANDLE handle; + WCHAR path[MAX_PATH]; + + MultiByteToWideChar( CP_ACP, 0, "bad.manifest", -1, path, MAX_PATH ); + memset(&actctx, 0, sizeof(ACTCTXW)); + actctx.cbSize = sizeof(ACTCTXW); + actctx.lpSource = path; + + create_manifest_file("bad.manifest", manifest, "testdep.manifest", depmanifest); + handle = pCreateActCtxW(&actctx); + if (todo) todo_wine + { + ok(handle == INVALID_HANDLE_VALUE, "handle != INVALID_HANDLE_VALUE\n"); + ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX, "GetLastError == %u\n", GetLastError()); + } + else + { + ok(handle == INVALID_HANDLE_VALUE, "handle != INVALID_HANDLE_VALUE\n"); + ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX, "GetLastError == %u\n", GetLastError()); + } + if (handle != INVALID_HANDLE_VALUE) pReleaseActCtx( handle ); + DeleteFileA("bad.manifest"); + DeleteFileA("testdep.manifest"); +} + +static void test_create_fail(void) +{ + ACTCTXW actctx; + HANDLE handle; + WCHAR path[MAX_PATH]; + + MultiByteToWideChar( CP_ACP, 0, "nonexistent.manifest", -1, path, MAX_PATH ); + memset(&actctx, 0, sizeof(ACTCTXW)); + actctx.cbSize = sizeof(ACTCTXW); + actctx.lpSource = path; + + handle = pCreateActCtxW(&actctx); + ok(handle == INVALID_HANDLE_VALUE, "handle != INVALID_HANDLE_VALUE\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError == %u\n", GetLastError()); + + trace("wrong_manifest1\n"); + test_create_and_fail(wrong_manifest1, NULL, 0 ); + trace("wrong_manifest2\n"); + test_create_and_fail(wrong_manifest2, NULL, 0 ); + trace("wrong_manifest3\n"); + test_create_and_fail(wrong_manifest3, NULL, 1 ); + trace("wrong_manifest4\n"); + test_create_and_fail(wrong_manifest4, NULL, 1 ); + trace("wrong_manifest5\n"); + test_create_and_fail(wrong_manifest5, NULL, 0 ); + trace("wrong_manifest6\n"); + test_create_and_fail(wrong_manifest6, NULL, 0 ); + trace("wrong_manifest7\n"); + test_create_and_fail(wrong_manifest7, NULL, 1 ); + trace("wrong_manifest8\n"); + test_create_and_fail(wrong_manifest8, NULL, 0 ); + trace("manifest2\n"); + test_create_and_fail(manifest2, NULL, 0 ); + trace("manifest2+depmanifest1\n"); + test_create_and_fail(manifest2, wrong_depmanifest1, 0 ); +} + +static void test_find_dll_redirection(HANDLE handle, LPCWSTR libname, ULONG exid) +{ + ACTCTX_SECTION_KEYED_DATA data; + DWORD *p; + BOOL ret; + + memset(&data, 0xfe, sizeof(data)); + data.cbSize = sizeof(data); + + ret = pFindActCtxSectionStringW(0, NULL, + ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + libname, &data); + ok(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError()); + if(!ret) + { + skip("couldn't find %s\n",strw(libname)); + return; + } + + ok(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize); + ok(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion); + ok(data.lpData != NULL, "data.lpData == NULL\n"); + ok(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength); + + p = data.lpData; + if(ret && p) todo_wine { + ok(p[0] == 20 && p[1] == 2 && p[2] == 0 && p[3] == 0 && p[4] == 0, + "wrong data %u,%u,%u,%u,%u\n",p[0], p[1], p[2], p[3], p[4]); + } + + ok(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n"); + ok(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n", + data.ulSectionGlobalDataLength); + ok(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n"); + /* ok(data.ulSectionTotalLength == ??, "data.ulSectionTotalLength=%u\n", + data.ulSectionTotalLength); */ + ok(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx); + ok(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n", + data.ulAssemblyRosterIndex, exid); + + memset(&data, 0xfe, sizeof(data)); + data.cbSize = sizeof(data); + + ret = pFindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, + ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + libname, &data); + ok(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError()); + if(!ret) + { + skip("couldn't find\n"); + return; + } + + ok(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize); + ok(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion); + ok(data.lpData != NULL, "data.lpData == NULL\n"); + ok(data.ulLength == 20, "data.ulLength=%u\n", data.ulLength); + ok(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n"); + ok(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n", + data.ulSectionGlobalDataLength); + ok(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n"); + /* ok(data.ulSectionTotalLength == ?? , "data.ulSectionTotalLength=%u\n", + data.ulSectionTotalLength); */ + ok(data.hActCtx == handle, "data.hActCtx=%p\n", data.hActCtx); + ok(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n", + data.ulAssemblyRosterIndex, exid); + + pReleaseActCtx(handle); +} + +static void test_find_window_class(HANDLE handle, LPCWSTR clsname, ULONG exid) +{ + ACTCTX_SECTION_KEYED_DATA data; + BOOL ret; + + memset(&data, 0xfe, sizeof(data)); + data.cbSize = sizeof(data); + + ret = pFindActCtxSectionStringW(0, NULL, + ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, + clsname, &data); + ok(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError()); + if(!ret) + { + skip("couldn't find\n"); + return; + } + + ok(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize); + ok(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion); + ok(data.lpData != NULL, "data.lpData == NULL\n"); + /* ok(data.ulLength == ??, "data.ulLength=%u\n", data.ulLength); */ + ok(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n"); + ok(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n", + data.ulSectionGlobalDataLength); + ok(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n"); + /* ok(data.ulSectionTotalLength == 0, "data.ulSectionTotalLength=%u\n", + data.ulSectionTotalLength); FIXME */ + ok(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx); + ok(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n", + data.ulAssemblyRosterIndex, exid); + + memset(&data, 0xfe, sizeof(data)); + data.cbSize = sizeof(data); + + ret = pFindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, + ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, + clsname, &data); + ok(ret, "FindActCtxSectionStringW failed: %u\n", GetLastError()); + if(!ret) + { + skip("couldn't find\n"); + return; + } + + ok(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize); + ok(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion); + ok(data.lpData != NULL, "data.lpData == NULL\n"); + /* ok(data.ulLength == ??, "data.ulLength=%u\n", data.ulLength); FIXME */ + ok(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n"); + ok(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n", + data.ulSectionGlobalDataLength); + ok(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n"); + /* ok(data.ulSectionTotalLength == 0, "data.ulSectionTotalLength=%u\n", + data.ulSectionTotalLength); FIXME */ + ok(data.hActCtx == handle, "data.hActCtx=%p\n", data.hActCtx); + ok(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n", + data.ulAssemblyRosterIndex, exid); + + pReleaseActCtx(handle); +} + +static void test_find_string_fail(void) +{ + ACTCTX_SECTION_KEYED_DATA data = {sizeof(data)}; + BOOL ret; + + ret = pFindActCtxSectionStringW(0, NULL, 100, testlib_dll, &data); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_SXS_SECTION_NOT_FOUND, "GetLastError()=%u\n", GetLastError()); + + ret = pFindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + testlib2_dll, &data); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_SXS_KEY_NOT_FOUND, "GetLastError()=%u\n", GetLastError()); + + ret = pFindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + testlib_dll, NULL); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError()); + + ret = pFindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + NULL, &data); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError()); + + data.cbSize = 0; + ret = pFindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + testlib_dll, &data); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError()); + + data.cbSize = 35; + ret = pFindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + testlib_dll, &data); + ok(!ret, "FindActCtxSectionStringW succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError()); +} + +static void test_actctx(void) +{ + ULONG_PTR cookie; + HANDLE handle; + BOOL b; + + test_create_fail(); + + trace("default actctx\n"); + + b = pGetCurrentActCtx(&handle); + ok(handle == NULL, "handle = %p, expected NULL\n", handle); + ok(b, "GetCurrentActCtx failed: %u\n", GetLastError()); + if(b) { + test_detailed_info(handle, &detailed_info0); + pReleaseActCtx(handle); + } + + if(!create_manifest_file("test1.manifest", manifest1, NULL, NULL)) { + skip("Could not create manifest file\n"); + return; + } + + trace("manifest1\n"); + + handle = test_create("test1.manifest", manifest1); + DeleteFileA("test1.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info1); + test_info_in_assembly(handle, 1, &manifest1_info); + + b = CloseHandle(handle); + ok(!b, "CloseHandle succeeded\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() == %u\n", GetLastError()); + + pReleaseActCtx(handle); + } + + if(!create_manifest_file("test2.manifest", manifest2, "testdep.manifest", testdep_manifest1)) { + skip("Could not create manifest file\n"); + return; + } + + trace("manifest2 depmanifest1\n"); + + handle = test_create("test2.manifest", manifest2); + DeleteFileA("test2.manifest"); + DeleteFileA("testdep.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info2); + test_info_in_assembly(handle, 1, &manifest2_info); + test_info_in_assembly(handle, 2, &depmanifest1_info); + pReleaseActCtx(handle); + } + + if(!create_manifest_file("test3.manifest", manifest2, "testdep.manifest", testdep_manifest2)) { + skip("Could not create manifest file\n"); + return; + } + + trace("manifest2 depmanifest2\n"); + + handle = test_create("test3.manifest", manifest2); + DeleteFileA("test3.manifest"); + DeleteFileA("testdep.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info2); + test_info_in_assembly(handle, 1, &manifest2_info); + test_info_in_assembly(handle, 2, &depmanifest2_info); + test_file_info(handle, 1, 0, testlib_dll); + test_file_info(handle, 1, 1, testlib2_dll); + + b = pActivateActCtx(handle, &cookie); + ok(b, "ActivateActCtx failed: %u\n", GetLastError()); + test_find_dll_redirection(handle, testlib_dll, 2); + test_find_dll_redirection(handle, testlib2_dll, 2); + b = pDeactivateActCtx(0, cookie); + ok(b, "DeactivateActCtx failed: %u\n", GetLastError()); + + pReleaseActCtx(handle); + } + + trace("manifest2 depmanifest3\n"); + + if(!create_manifest_file("test2-3.manifest", manifest2, "testdep.manifest", testdep_manifest3)) { + skip("Could not create manifest file\n"); + return; + } + + handle = test_create("test2-3.manifest", manifest2); + DeleteFileA("test2-3.manifest"); + DeleteFileA("testdep.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info2); + test_info_in_assembly(handle, 1, &manifest2_info); + test_info_in_assembly(handle, 2, &depmanifest3_info); + test_file_info(handle, 1, 0, testlib_dll); + test_file_info(handle, 1, 1, testlib2_dll); + + b = pActivateActCtx(handle, &cookie); + ok(b, "ActivateActCtx failed: %u\n", GetLastError()); + test_find_dll_redirection(handle, testlib_dll, 2); + test_find_dll_redirection(handle, testlib2_dll, 2); + test_find_window_class(handle, wndClassW, 2); + test_find_window_class(handle, wndClass2W, 2); + b = pDeactivateActCtx(0, cookie); + ok(b, "DeactivateActCtx failed: %u\n", GetLastError()); + + pReleaseActCtx(handle); + } + + trace("manifest3\n"); + + if(!create_manifest_file("test3.manifest", manifest3, NULL, NULL)) { + skip("Could not create manifest file\n"); + return; + } + + handle = test_create("test3.manifest", manifest3); + DeleteFileA("test3.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info1); + test_info_in_assembly(handle, 1, &manifest3_info); + test_file_info(handle, 0, 0, testlib_dll); + + b = pActivateActCtx(handle, &cookie); + ok(b, "ActivateActCtx failed: %u\n", GetLastError()); + test_find_dll_redirection(handle, testlib_dll, 1); + test_find_dll_redirection(handle, testlib_dll, 1); + test_find_string_fail(); + b = pDeactivateActCtx(0, cookie); + ok(b, "DeactivateActCtx failed: %u\n", GetLastError()); + + pReleaseActCtx(handle); + } + + trace("manifest4\n"); + + if(!create_manifest_file("test4.manifest", manifest4, NULL, NULL)) { + skip("Could not create manifest file\n"); + return; + } + + handle = test_create("test4.manifest", manifest4); + DeleteFileA("test4.manifest"); + DeleteFileA("testdep.manifest"); + if(handle != INVALID_HANDLE_VALUE) { + test_detailed_info(handle, &detailed_info2); + test_info_in_assembly(handle, 1, &manifest4_info); + test_info_in_assembly(handle, 2, &manifest_comctrl_info); + pReleaseActCtx(handle); + } +} + +static void test_app_manifest(void) +{ + HANDLE handle; + BOOL b; + + trace("child process manifest1\n"); + + b = pGetCurrentActCtx(&handle); + ok(handle == NULL, "handle != NULL\n"); + ok(b, "GetCurrentActCtx failed: %u\n", GetLastError()); + if(b) { + test_detailed_info(handle, &detailed_info1_child); + test_info_in_assembly(handle, 1, &manifest1_child_info); + pReleaseActCtx(handle); + } +} + +static void run_child_process(void) +{ + char cmdline[MAX_PATH]; + char path[MAX_PATH]; + char **argv; + PROCESS_INFORMATION pi; + STARTUPINFO si = { 0 }; + + GetModuleFileNameA(NULL, path, MAX_PATH); + strcat(path, ".manifest"); + if(!create_manifest_file(path, manifest1, NULL, NULL)) { + skip("Could not create manifest file\n"); + return; + } + + si.cb = sizeof(si); + winetest_get_mainargs( &argv ); + sprintf(cmdline, "%s %s manifest1", argv[0], argv[1]); + ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, + &si, &pi) != 0, "Could not create process: %u\n", GetLastError()); + CloseHandle(pi.hThread); + + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + DeleteFileA(path); +} + +static void init_paths(void) +{ + LPWSTR ptr; + + static const WCHAR dot_manifest[] = {'.','M','a','n','i','f','e','s','t',0}; + + GetModuleFileNameW(NULL, exe_path, sizeof(exe_path)/sizeof(WCHAR)); + lstrcpyW(app_dir, exe_path); + for(ptr=app_dir+lstrlenW(app_dir); *ptr != '\\'; ptr--); + ptr[1] = 0; + + GetModuleFileNameW(NULL, app_manifest_path, sizeof(app_manifest_path)/sizeof(WCHAR)); + lstrcpyW(app_manifest_path+lstrlenW(app_manifest_path), dot_manifest); +} + +static BOOL init_funcs(void) +{ + HMODULE hKernel32 = GetModuleHandle("kernel32"); + +#define X(f) if (!(p##f = (void*)GetProcAddress(hKernel32, #f))) return FALSE; + X(ActivateActCtx); + X(CreateActCtxW); + X(DeactivateActCtx); + X(FindActCtxSectionStringW); + X(GetCurrentActCtx); + X(QueryActCtxW); + X(ReleaseActCtx); +#undef X + + return TRUE; +} + +START_TEST(actctx) +{ + int argc; + char **argv; + + argc = winetest_get_mainargs(&argv); + + init_paths(); + if (!init_funcs()) + { + skip("Couldn't load kernel32\n"); + return; + } + + if(argc > 2 && !strcmp(argv[2], "manifest1")) { + test_app_manifest(); + return; + } + + test_actctx(); + run_child_process(); +} diff --git a/dlls/mshtml/editor.c b/dlls/mshtml/editor.c index f9005b65920..5bf160ebb79 100644 --- a/dlls/mshtml/editor.c +++ b/dlls/mshtml/editor.c @@ -39,6 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NSCMD_ALIGN "cmd_align" +#define NSCMD_BEGINLINE "cmd_beginLine" #define NSCMD_BOLD "cmd_bold" #define NSCMD_CHARNEXT "cmd_charNext" #define NSCMD_CHARPREVIOUS "cmd_charPrevious" @@ -46,6 +47,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NSCMD_CUT "cmd_cut" #define NSCMD_DELETECHARFORWARD "cmd_deleteCharForward" #define NSCMD_DELETEWORDFORWARD "cmd_deleteWordForward" +#define NSCMD_ENDLINE "cmd_endLine" #define NSCMD_FONTCOLOR "cmd_fontColor" #define NSCMD_FONTFACE "cmd_fontFace" #define NSCMD_INDENT "cmd_indent" @@ -53,17 +55,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NSCMD_ITALIC "cmd_italic" #define NSCMD_LINENEXT "cmd_lineNext" #define NSCMD_LINEPREVIOUS "cmd_linePrevious" +#define NSCMD_MOVEBOTTOM "cmd_moveBottom" #define NSCMD_MOVEPAGEDOWN "cmd_movePageDown" #define NSCMD_MOVEPAGEUP "cmd_movePageUp" +#define NSCMD_MOVETOP "cmd_moveTop" #define NSCMD_OL "cmd_ol" #define NSCMD_OUTDENT "cmd_outdent" #define NSCMD_PASTE "cmd_paste" +#define NSCMD_SELECTBEGINLINE "cmd_selectBeginLine" +#define NSCMD_SELECTBOTTOM "cmd_selectBottom" #define NSCMD_SELECTCHARNEXT "cmd_selectCharNext" #define NSCMD_SELECTCHARPREVIOUS "cmd_selectCharPrevious" +#define NSCMD_SELECTENDLINE "cmd_selectEndLine" #define NSCMD_SELECTLINENEXT "cmd_selectLineNext" #define NSCMD_SELECTLINEPREVIOUS "cmd_selectLinePrevious" #define NSCMD_SELECTPAGEDOWN "cmd_selectPageDown" #define NSCMD_SELECTPAGEUP "cmd_selectPageUp" +#define NSCMD_SELECTTOP "cmd_selectTop" #define NSCMD_SELECTWORDNEXT "cmd_selectWordNext" #define NSCMD_SELECTWORDPREVIOUS "cmd_selectWordPrevious" #define NSCMD_UL "cmd_ul" @@ -83,6 +91,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define DOM_VK_RIGHT VK_RIGHT #define DOM_VK_DOWN VK_DOWN #define DOM_VK_DELETE VK_DELETE +#define DOM_VK_HOME VK_HOME +#define DOM_VK_END VK_END static const WCHAR wszFont[] = {'f','o','n','t',0}; static const WCHAR wszSize[] = {'s','i','z','e',0}; @@ -478,7 +488,7 @@ static nsIDOMNode *get_child_text_node(nsIDOMNode *node, BOOL first) return NULL; } -static void handle_arrow_key(HTMLDocument *This, nsIDOMKeyEvent *event, const char **cmds) +static void handle_arrow_key(HTMLDocument *This, nsIDOMKeyEvent *event, const char *cmds[4]) { int i=0; PRBool b; @@ -566,6 +576,30 @@ void handle_edit_event(HTMLDocument *This, nsIDOMEvent *event) handle_arrow_key(This, key_event, cmds); break; } + case DOM_VK_HOME: { + static const char *cmds[] = { + NSCMD_BEGINLINE, + NSCMD_MOVETOP, + NSCMD_SELECTBEGINLINE, + NSCMD_SELECTTOP + }; + + TRACE("home\n"); + handle_arrow_key(This, key_event, cmds); + break; + } + case DOM_VK_END: { + static const char *cmds[] = { + NSCMD_ENDLINE, + NSCMD_MOVEBOTTOM, + NSCMD_SELECTENDLINE, + NSCMD_SELECTBOTTOM + }; + + TRACE("end\n"); + handle_arrow_key(This, key_event, cmds); + break; + } } nsIDOMKeyEvent_Release(key_event); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 76fd5f257f5..014fcdb0026 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -249,6 +249,12 @@ static void add_nsrequest(BSCallback *This) } } +static void on_stop_nsrequest(BSCallback *This) { + if(This->nslistener) + nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel), + This->nscontext, NS_OK); +} + #define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface) static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, @@ -391,10 +397,9 @@ static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *ifac This->binding = NULL; } - if(This->nslistener) { - nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel), - This->nscontext, NS_OK); + on_stop_nsrequest(This); + if(This->nslistener) { if(This->nschannel->load_group) { nsresult nsres; @@ -796,8 +801,7 @@ HRESULT start_binding(BSCallback *bscallback) hres = CreateAsyncBindCtx(0, STATUSCLB(bscallback), NULL, &bctx); if(FAILED(hres)) { WARN("CreateAsyncBindCtx failed: %08x\n", hres); - nsIStreamListener_OnStopRequest(bscallback->nslistener, (nsIRequest*)NSCHANNEL(bscallback->nschannel), - bscallback->nscontext, NS_OK); + on_stop_nsrequest(bscallback); return hres; } @@ -805,8 +809,7 @@ HRESULT start_binding(BSCallback *bscallback) IBindCtx_Release(bctx); if(FAILED(hres)) { WARN("BindToStorage failed: %08x\n", hres); - nsIStreamListener_OnStopRequest(bscallback->nslistener, (nsIRequest*)NSCHANNEL(bscallback->nschannel), - bscallback->nscontext, NS_OK); + on_stop_nsrequest(bscallback); return hres; } diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 6b4e918eb94..0697d4dee88 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -259,8 +259,8 @@ static void set_profile(void) static const WCHAR wszMSHTML[] = {'M','S','H','T','M','L',0}; - nsres = nsIServiceManager_GetServiceByContactID(pServMgr, NS_PROFILE_CONTRACTID, - &IID_nsIProfile, (void**)&profile); + nsres = nsIServiceManager_GetServiceByContractID(pServMgr, NS_PROFILE_CONTRACTID, + &IID_nsIProfile, (void**)&profile); if(NS_FAILED(nsres)) { ERR("Could not get profile service: %08x\n", nsres); return; diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 983e38a3f75..78e030bc5c8 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -120,7 +120,7 @@ typedef nsISupports nsIControllerCommandTable; interface nsIServiceManager : nsISupports { nsresult GetService(nsCIDRef aClass, nsIIDRef aIID, void **result); - nsresult GetServiceByContactID(const char *aContactID, nsIIDRef aIID, void **result); + nsresult GetServiceByContractID(const char *aContractID, nsIIDRef aIID, void **result); nsresult IsServiceInstantiated(nsCIDRef aClass, nsIIDRef aIID, BOOL *_retval); nsresult IsServiceInstantiatedByContractID(const char *aContractID, nsIIDRef aIID, BOOL *_retval); } diff --git a/dlls/mshtml/nsservice.c b/dlls/mshtml/nsservice.c index d4c9d6b8683..8782306aea1 100644 --- a/dlls/mshtml/nsservice.c +++ b/dlls/mshtml/nsservice.c @@ -465,7 +465,7 @@ void register_nsservice(nsIComponentRegistrar *registrar, nsIServiceManager *ser if(NS_FAILED(nsres)) ERR("RegisterFactory failed: %08x\n", nsres); - nsres = nsIServiceManager_GetServiceByContactID(service_manager, NS_WINDOWWATCHER_CONTRACTID, + nsres = nsIServiceManager_GetServiceByContractID(service_manager, NS_WINDOWWATCHER_CONTRACTID, &IID_nsIWindowWatcher, (void**)&window_watcher); if(NS_SUCCEEDED(nsres)) { nsres = nsIWindowWatcher_SetWindowCreator(window_watcher, diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index cfb8ab4b325..587b4beaae6 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -61,6 +61,15 @@ static UINT ALTER_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt return ERROR_FUNCTION_FAILED; } +static UINT ALTER_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSIALTERVIEW *av = (MSIALTERVIEW*)view; + + TRACE("%p %d %p\n", av, row, rec ); + + return av->table->ops->get_row(av->table, row, rec); +} + static UINT ITERATE_columns(MSIRECORD *row, LPVOID param) { (*(UINT *)param)++; @@ -179,7 +188,7 @@ static UINT ALTER_get_column_info( struct tagMSIVIEW *view, } static UINT ALTER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIALTERVIEW *av = (MSIALTERVIEW*)view; @@ -211,6 +220,7 @@ static const MSIVIEWOPS alter_ops = { ALTER_fetch_int, ALTER_fetch_stream, + ALTER_get_row, NULL, NULL, NULL, diff --git a/dlls/msi/create.c b/dlls/msi/create.c index 8f33ec3845f..ed6b43a46c6 100644 --- a/dlls/msi/create.c +++ b/dlls/msi/create.c @@ -96,7 +96,7 @@ static UINT CREATE_get_column_info( struct tagMSIVIEW *view, } static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec) + MSIRECORD *rec, UINT row) { MSICREATEVIEW *cv = (MSICREATEVIEW*)view; @@ -124,6 +124,7 @@ static const MSIVIEWOPS create_ops = NULL, NULL, NULL, + NULL, CREATE_execute, CREATE_close, CREATE_get_dimensions, diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index cc08c2978e7..54efc85de50 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -842,6 +842,7 @@ static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source, static const WCHAR backslash[] = {'\\',0}; + size = MAX_PATH; MSI_GetPropertyW(package, cszSourceDir, package_path, &size); lstrcatW(package_path, backslash); lstrcatW(package_path, source); diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c index 7e004847f3d..57b0a2ec397 100644 --- a/dlls/msi/delete.c +++ b/dlls/msi/delete.c @@ -147,7 +147,7 @@ static UINT DELETE_get_column_info( struct tagMSIVIEW *view, } static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; @@ -186,6 +186,7 @@ static const MSIVIEWOPS delete_ops = NULL, NULL, NULL, + NULL, DELETE_execute, DELETE_close, DELETE_get_dimensions, diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c index 0da3c2e2767..2fe5eff54bc 100644 --- a/dlls/msi/distinct.c +++ b/dlls/msi/distinct.c @@ -218,7 +218,7 @@ static UINT DISTINCT_get_column_info( struct tagMSIVIEW *view, } static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; @@ -227,7 +227,7 @@ static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, if( !dv->table ) return ERROR_FUNCTION_FAILED; - return dv->table->ops->modify( dv->table, eModifyMode, rec ); + return dv->table->ops->modify( dv->table, eModifyMode, rec, row ); } static UINT DISTINCT_delete( struct tagMSIVIEW *view ) @@ -275,6 +275,7 @@ static const MSIVIEWOPS distinct_ops = NULL, NULL, NULL, + NULL, DISTINCT_execute, DISTINCT_close, DISTINCT_get_dimensions, diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index d122624b8b4..206c3d70238 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -185,7 +185,7 @@ static UINT INSERT_get_column_info( struct tagMSIVIEW *view, return sv->ops->get_column_info( sv, n, name, type ); } -static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec) +static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view; @@ -226,6 +226,7 @@ static const MSIVIEWOPS insert_ops = NULL, NULL, NULL, + NULL, INSERT_execute, INSERT_close, INSERT_get_dimensions, diff --git a/dlls/msi/join.c b/dlls/msi/join.c index fa31ad3f8ea..e0710789750 100644 --- a/dlls/msi/join.c +++ b/dlls/msi/join.c @@ -104,6 +104,33 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr return table->ops->fetch_stream( table, row, col, stm ); } +static UINT JOIN_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSIJOINVIEW *jv = (MSIJOINVIEW*)view; + MSIVIEW *table; + + TRACE("%p %d %p\n", jv, row, rec ); + + if( !jv->left || !jv->right ) + return ERROR_FUNCTION_FAILED; + + if( row >= jv->left_rows * jv->right_rows ) + return ERROR_FUNCTION_FAILED; + + if( row <= jv->left_count ) + { + table = jv->left; + row = (row/jv->right_rows); + } + else + { + table = jv->right; + row = (row % jv->right_rows); + } + + return table->ops->get_row(table, row, rec); +} + static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIJOINVIEW *jv = (MSIJOINVIEW*)view; @@ -201,7 +228,7 @@ static UINT JOIN_get_column_info( struct tagMSIVIEW *view, } static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIJOINVIEW *jv = (MSIJOINVIEW*)view; @@ -243,6 +270,7 @@ static const MSIVIEWOPS join_ops = { JOIN_fetch_int, JOIN_fetch_stream, + JOIN_get_row, NULL, NULL, NULL, diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 0036414cbff..d4ccd8034fd 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -157,6 +157,12 @@ typedef struct tagMSIVIEWOPS UINT (*fetch_stream)( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm ); /* + * get_row - gets values from a row + * + */ + UINT (*get_row)( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ); + + /* * set_row - sets values in a row as specified by mask * * Similar semantics to fetch_int @@ -203,7 +209,7 @@ typedef struct tagMSIVIEWOPS /* * modify - not yet implemented properly */ - UINT (*modify)( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record ); + UINT (*modify)( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record, UINT row ); /* * delete - destroys the structure completely @@ -690,7 +696,7 @@ extern UINT MSI_ViewClose( MSIQUERY* ); extern UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **); extern UINT MSI_ViewModify( MSIQUERY *, MSIMODIFY, MSIRECORD * ); extern UINT VIEW_find_column( MSIVIEW *, LPCWSTR, UINT * ); - +extern UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **); /* install internals */ extern UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel ); diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c index abec8d8d38a..32bbf973322 100644 --- a/dlls/msi/msiquery.c +++ b/dlls/msi/msiquery.c @@ -265,90 +265,102 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, return ret; } -UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec) +UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec) { - MSIVIEW *view; - MSIRECORD *rec; UINT row_count = 0, col_count = 0, i, ival, ret, type; - TRACE("%p %p\n", query, prec ); - - view = query->view; - if( !view ) - return ERROR_FUNCTION_FAILED; + TRACE("%p %p %d %p\n", db, view, row, rec); - ret = view->ops->get_dimensions( view, &row_count, &col_count ); - if( ret ) + ret = view->ops->get_dimensions(view, &row_count, &col_count); + if (ret) return ret; - if( !col_count ) + + if (!col_count) return ERROR_INVALID_PARAMETER; - if( query->row >= row_count ) + if (row >= row_count) return ERROR_NO_MORE_ITEMS; - rec = MSI_CreateRecord( col_count ); - if( !rec ) + *rec = MSI_CreateRecord(col_count); + if (!*rec) return ERROR_FUNCTION_FAILED; - for( i=1; i<=col_count; i++ ) + for (i = 1; i <= col_count; i++) { - ret = view->ops->get_column_info( view, i, NULL, &type ); - if( ret ) + ret = view->ops->get_column_info(view, i, NULL, &type); + if (ret) { - ERR("Error getting column type for %d\n", i ); + ERR("Error getting column type for %d\n", i); continue; } - if (!MSITYPE_IS_BINARY(type)) + + if (MSITYPE_IS_BINARY(type)) { - ret = view->ops->fetch_int( view, query->row, i, &ival ); - if( ret ) + IStream *stm = NULL; + + ret = view->ops->fetch_stream(view, row, i, &stm); + if ((ret == ERROR_SUCCESS) && stm) { - ERR("Error fetching data for %d\n", i ); - continue; + MSI_RecordSetIStream(*rec, i, stm); + IStream_Release(stm); } - if( ! (type & MSITYPE_VALID ) ) - ERR("Invalid type!\n"); + else + ERR("failed to get stream\n"); - /* check if it's nul (0) - if so, don't set anything */ - if( !ival ) - continue; + continue; + } - if( type & MSITYPE_STRING ) - { - LPCWSTR sval; + ret = view->ops->fetch_int(view, row, i, &ival); + if (ret) + { + ERR("Error fetching data for %d\n", i); + continue; + } - sval = msi_string_lookup_id( query->db->strings, ival ); - MSI_RecordSetStringW( rec, i, sval ); - } - else - { - if( (type & MSI_DATASIZEMASK) == 2 ) - MSI_RecordSetInteger( rec, i, ival - (1<<15) ); - else - MSI_RecordSetInteger( rec, i, ival - (1<<31) ); - } + if (! (type & MSITYPE_VALID)) + ERR("Invalid type!\n"); + + /* check if it's nul (0) - if so, don't set anything */ + if (!ival) + continue; + + if (type & MSITYPE_STRING) + { + LPCWSTR sval; + + sval = msi_string_lookup_id(db->strings, ival); + MSI_RecordSetStringW(*rec, i, sval); } else { - IStream *stm = NULL; - - ret = view->ops->fetch_stream( view, query->row, i, &stm ); - if( ( ret == ERROR_SUCCESS ) && stm ) - { - MSI_RecordSetIStream( rec, i, stm ); - IStream_Release( stm ); - } + if ((type & MSI_DATASIZEMASK) == 2) + MSI_RecordSetInteger(*rec, i, ival - (1<<15)); else - ERR("failed to get stream\n"); + MSI_RecordSetInteger(*rec, i, ival - (1<<31)); } } - query->row ++; - - *prec = rec; return ERROR_SUCCESS; } +UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec) +{ + MSIVIEW *view; + UINT r; + + TRACE("%p %p\n", query, prec ); + + view = query->view; + if( !view ) + return ERROR_FUNCTION_FAILED; + + r = msi_view_get_row(query->db, view, query->row, prec); + if (r == ERROR_SUCCESS) + query->row ++; + + return r; +} + UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record) { MSIQUERY *query; @@ -563,7 +575,7 @@ UINT MSI_ViewModify( MSIQUERY *query, MSIMODIFY mode, MSIRECORD *rec ) if ( !view || !view->ops->modify) return ERROR_FUNCTION_FAILED; - return view->ops->modify( view, mode, rec ); + return view->ops->modify( view, mode, rec, query->row ); } UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode, diff --git a/dlls/msi/order.c b/dlls/msi/order.c index c745be5cc81..e895d593b90 100644 --- a/dlls/msi/order.c +++ b/dlls/msi/order.c @@ -142,6 +142,20 @@ static UINT ORDER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT * return ov->table->ops->fetch_int( ov->table, row, col, val ); } +static UINT ORDER_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSIORDERVIEW *ov = (MSIORDERVIEW *)view; + + TRACE("%p %d %p\n", ov, row, rec ); + + if (!ov->table) + return ERROR_FUNCTION_FAILED; + + row = ov->reorder[row]; + + return ov->table->ops->get_row(ov->table, row, rec); +} + static UINT ORDER_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIORDERVIEW *ov = (MSIORDERVIEW*)view; @@ -219,7 +233,7 @@ static UINT ORDER_get_column_info( struct tagMSIVIEW *view, } static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIORDERVIEW *ov = (MSIORDERVIEW*)view; @@ -228,7 +242,7 @@ static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, if( !ov->table ) return ERROR_FUNCTION_FAILED; - return ov->table->ops->modify( ov->table, eModifyMode, rec ); + return ov->table->ops->modify( ov->table, eModifyMode, rec, row ); } static UINT ORDER_delete( struct tagMSIVIEW *view ) @@ -272,6 +286,7 @@ static const MSIVIEWOPS order_ops = { ORDER_fetch_int, NULL, + ORDER_get_row, NULL, NULL, NULL, diff --git a/dlls/msi/select.c b/dlls/msi/select.c index 0643f500828..9c5232ac1fb 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -82,6 +82,18 @@ static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IS return sv->table->ops->fetch_stream( sv->table, row, col, stm ); } +static UINT SELECT_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSISELECTVIEW *sv = (MSISELECTVIEW *)view; + + TRACE("%p %d %p\n", sv, row, rec ); + + if( !sv->table ) + return ERROR_FUNCTION_FAILED; + + return msi_view_get_row(sv->db, view, row, rec); +} + static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; @@ -214,17 +226,79 @@ static UINT SELECT_get_column_info( struct tagMSIVIEW *view, return sv->table->ops->get_column_info( sv->table, n, name, type ); } +static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) +{ + MSISELECTVIEW *sv = (MSISELECTVIEW*)view; + UINT r, i, num_columns, col, type, val; + LPWSTR name; + LPCWSTR str; + MSIRECORD *mod; + + r = SELECT_get_dimensions(view, NULL, &num_columns); + if (r != ERROR_SUCCESS) + return r; + + r = sv->table->ops->get_row(sv->table, row - 1, &mod); + if (r != ERROR_SUCCESS) + return r; + + for (i = 0; i < num_columns; i++) + { + col = sv->cols[i]; + + r = SELECT_get_column_info(view, i + 1, &name, &type); + msi_free(name); + if (r != ERROR_SUCCESS) + { + ERR("Failed to get column information: %d\n", r); + goto done; + } + + if (MSITYPE_IS_BINARY(type)) + { + ERR("Cannot modify binary data!\n"); + r = ERROR_FUNCTION_FAILED; + goto done; + } + else if (type & MSITYPE_STRING) + { + str = MSI_RecordGetString(rec, i + 1); + r = MSI_RecordSetStringW(mod, col, str); + } + else + { + val = MSI_RecordGetInteger(rec, i + 1); + r = MSI_RecordSetInteger(mod, col, val); + } + + if (r != ERROR_SUCCESS) + { + ERR("Failed to modify record: %d\n", r); + goto done; + } + } + + r = sv->table->ops->modify(sv->table, MSIMODIFY_UPDATE, mod, row); + +done: + msiobj_release(&mod->hdr); + return r; +} + static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; - TRACE("%p %d %p\n", sv, eModifyMode, rec ); + TRACE("%p %d %p %d\n", sv, eModifyMode, rec, row ); if( !sv->table ) return ERROR_FUNCTION_FAILED; - return sv->table->ops->modify( sv->table, eModifyMode, rec ); + if (eModifyMode == MSIMODIFY_UPDATE) + return msi_select_update(view, rec, row); + + return sv->table->ops->modify( sv->table, eModifyMode, rec, row ); } static UINT SELECT_delete( struct tagMSIVIEW *view ) @@ -265,6 +339,7 @@ static const MSIVIEWOPS select_ops = { SELECT_fetch_int, SELECT_fetch_stream, + SELECT_get_row, SELECT_set_row, SELECT_insert_row, NULL, diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index 229a34f235b..4a40a12e4ff 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -129,6 +129,15 @@ static UINT STREAMS_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IS return ERROR_SUCCESS; } +static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + + FIXME("%p %d %p\n", sv, row, rec); + + return ERROR_CALL_NOT_IMPLEMENTED; +} + static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) { FIXME("(%p, %d, %p, %d): stub!\n", view, row, rec, mask); @@ -269,7 +278,7 @@ static UINT STREAMS_get_column_info(struct tagMSIVIEW *view, return ERROR_SUCCESS; } -static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec) +static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { FIXME("(%p, %d, %p): stub!\n", view, eModifyMode, rec); return ERROR_SUCCESS; @@ -327,6 +336,7 @@ static const MSIVIEWOPS streams_ops = { STREAMS_fetch_int, STREAMS_fetch_stream, + STREAMS_get_row, STREAMS_set_row, STREAMS_insert_row, STREAMS_delete_row, diff --git a/dlls/msi/table.c b/dlls/msi/table.c index 533381714eb..bf7d70552b9 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -1277,6 +1277,16 @@ static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val ) return ERROR_SUCCESS; } +static UINT TABLE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW *)view; + + if (!tv->table) + return ERROR_INVALID_PARAMETER; + + return msi_view_get_row(tv->db, view, row, rec); +} + static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSITABLEVIEW *tv = (MSITABLEVIEW*)view; @@ -1532,10 +1542,10 @@ static UINT TABLE_delete_row( struct tagMSIVIEW *view, UINT row ) return ERROR_SUCCESS; } -static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec) +static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row) { MSITABLEVIEW *tv = (MSITABLEVIEW *)view; - UINT r, row; + UINT r, new_row; /* FIXME: MsiViewFetch should set rec index 0 to some ID that * sets the fetched record apart from other records @@ -1544,19 +1554,22 @@ static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec) if (!tv->table) return ERROR_INVALID_PARAMETER; - r = msi_table_find_row(tv, rec, &row); + r = msi_table_find_row(tv, rec, &new_row); if (r != ERROR_SUCCESS) + { + ERR("can't find row to modify\n"); return ERROR_SUCCESS; + } /* the row cannot be changed */ - if (row != 0) + if (row != new_row + 1) return ERROR_FUNCTION_FAILED; - return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1); + return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1); } static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec) + MSIRECORD *rec, UINT row) { MSITABLEVIEW *tv = (MSITABLEVIEW*)view; UINT r; @@ -1577,7 +1590,7 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, break; case MSIMODIFY_UPDATE: - r = msi_table_update( view, rec ); + r = msi_table_update( view, rec, row ); break; case MSIMODIFY_REFRESH: @@ -1826,6 +1839,7 @@ static const MSIVIEWOPS table_ops = { TABLE_fetch_int, TABLE_fetch_stream, + TABLE_get_row, TABLE_set_row, TABLE_insert_row, TABLE_delete_row, diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 5b011897a61..39ef6ac29dd 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -3781,6 +3781,179 @@ static void test_select_markers(void) DeleteFile(msifile); } +static void test_viewmodify_update(void) +{ + MSIHANDLE hdb = 0, hview = 0, hrec = 0; + const char *query; + UINT r; + + DeleteFile(msifile); + + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); + + query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)"; + r = run_query( hdb, 0, query ); + ok(r == ERROR_SUCCESS, "query failed\n"); + + query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)"; + r = run_query( hdb, 0, query ); + ok(r == ERROR_SUCCESS, "query failed\n"); + + query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)"; + r = run_query( hdb, 0, query ); + ok(r == ERROR_SUCCESS, "query failed\n"); + + query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)"; + r = run_query( hdb, 0, query ); + ok(r == ERROR_SUCCESS, "query failed\n"); + + query = "SELECT `B` FROM `table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordSetInteger(hrec, 1, 0); + ok(r == ERROR_SUCCESS, "failed to set integer\n"); + + r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); + ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + query = "SELECT * FROM `table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 1, "Expected 1, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 0, "Expected 0, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 3, "Expected 3, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 4, "Expected 4, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 5, "Expected 5, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 6, "Expected 6, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + /* loop through all elements */ + query = "SELECT `B` FROM `table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + + while (TRUE) + { + r = MsiViewFetch(hview, &hrec); + if (r != ERROR_SUCCESS) + break; + + r = MsiRecordSetInteger(hrec, 1, 0); + ok(r == ERROR_SUCCESS, "failed to set integer\n"); + + r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); + ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + } + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + query = "SELECT * FROM `table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 1, "Expected 1, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 0, "Expected 0, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 3, "Expected 3, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 0, "Expected 0, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 5, "Expected 5, got %d\n", r); + r = MsiRecordGetInteger(hrec, 2); + ok(r == 0, "Expected 0, got %d\n", r); + + r = MsiCloseHandle(hrec); + ok(r == ERROR_SUCCESS, "failed to close record\n"); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + r = MsiCloseHandle( hdb ); + ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); +} + START_TEST(db) { test_msidatabase(); @@ -3805,4 +3978,5 @@ START_TEST(db) test_update(); test_special_tables(); test_select_markers(); + test_viewmodify_update(); } diff --git a/dlls/msi/update.c b/dlls/msi/update.c index 10f7762a61c..23d7ab5f735 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -138,7 +138,7 @@ static UINT UPDATE_get_column_info( struct tagMSIVIEW *view, } static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; @@ -178,6 +178,7 @@ static const MSIVIEWOPS update_ops = NULL, NULL, NULL, + NULL, UPDATE_execute, UPDATE_close, UPDATE_get_dimensions, diff --git a/dlls/msi/where.c b/dlls/msi/where.c index fddb0e7a226..c6a118152ea 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -82,6 +82,23 @@ static UINT WHERE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt return wv->table->ops->fetch_stream( wv->table, row, col, stm ); } +static UINT WHERE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) +{ + MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view; + + TRACE("%p %d %p\n", wv, row, rec ); + + if (!wv->table) + return ERROR_FUNCTION_FAILED; + + if (row > wv->row_count) + return ERROR_NO_MORE_ITEMS; + + row = wv->reorder[row]; + + return wv->table->ops->get_row(view, row, rec); +} + static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask ) { MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; @@ -379,7 +396,7 @@ static UINT WHERE_get_column_info( struct tagMSIVIEW *view, } static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec ) + MSIRECORD *rec, UINT row ) { MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; @@ -388,7 +405,7 @@ static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, if( !wv->table ) return ERROR_FUNCTION_FAILED; - return wv->table->ops->modify( wv->table, eModifyMode, rec ); + return wv->table->ops->modify( wv->table, eModifyMode, rec, row ); } static UINT WHERE_delete( struct tagMSIVIEW *view ) @@ -437,6 +454,7 @@ static const MSIVIEWOPS where_ops = { WHERE_fetch_int, WHERE_fetch_stream, + WHERE_get_row, WHERE_set_row, NULL, NULL, diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c index 0232c4dae16..21a31153c8b 100644 --- a/dlls/msvcrt/dir.c +++ b/dlls/msvcrt/dir.c @@ -419,11 +419,10 @@ char* CDECL _getcwd(char * buf, int size) if (!buf) { - if (size < 0) - return _strdup(dir); - return msvcrt_strndup(dir,size); + if (size <= dir_len) size = dir_len + 1; + if (!(buf = MSVCRT_malloc( size ))) return NULL; } - if (dir_len >= size) + else if (dir_len >= size) { *MSVCRT__errno() = MSVCRT_ERANGE; return NULL; /* buf too small */ @@ -447,9 +446,8 @@ MSVCRT_wchar_t* CDECL _wgetcwd(MSVCRT_wchar_t * buf, int size) if (!buf) { - if (size < 0) - return _wcsdup(dir); - return msvcrt_wstrndup(dir,size); + if (size <= dir_len) size = dir_len + 1; + if (!(buf = MSVCRT_malloc( size * sizeof(WCHAR) ))) return NULL; } if (dir_len >= size) { diff --git a/dlls/msvcrt/heap.c b/dlls/msvcrt/heap.c index 0158435138c..ab6dd015d13 100644 --- a/dlls/msvcrt/heap.c +++ b/dlls/msvcrt/heap.c @@ -272,7 +272,7 @@ void* CDECL MSVCRT_malloc(MSVCRT_size_t size) { void *ret = HeapAlloc(GetProcessHeap(),0,size); if (!ret) - msvcrt_set_errno(GetLastError()); + msvcrt_set_errno(MSVCRT_ENOMEM); return ret; } diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index c0bebba6cee..cf3c53180e2 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -115,8 +115,6 @@ extern thread_data_t *msvcrt_get_thread_data(void); extern int MSVCRT___lc_codepage; void msvcrt_set_errno(int); -char* msvcrt_strndup(const char*,unsigned int); -MSVCRT_wchar_t *msvcrt_wstrndup(const MSVCRT_wchar_t*, unsigned int); void _purecall(void); void _amsg_exit(int errnum); diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index ec4bd703b77..d1973a34d84 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -30,23 +30,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); -/* INTERNAL: MSVCRT_malloc() based strndup */ -char* msvcrt_strndup(const char* buf, unsigned int size) -{ - char* ret; - unsigned int len = strlen(buf), max_len; - - max_len = size <= len? size : len + 1; - - ret = MSVCRT_malloc(max_len); - if (ret) - { - memcpy(ret,buf,max_len); - ret[max_len] = 0; - } - return ret; -} - /********************************************************************* * _mbsdup (MSVCRT.@) * _strdup (MSVCRT.@) diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c index 32668a3469d..92dd644a828 100644 --- a/dlls/msvcrt/wcs.c +++ b/dlls/msvcrt/wcs.c @@ -30,23 +30,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); -/* INTERNAL: MSVCRT_malloc() based wstrndup */ -MSVCRT_wchar_t* msvcrt_wstrndup(const MSVCRT_wchar_t *buf, unsigned int size) -{ - MSVCRT_wchar_t* ret; - unsigned int len = strlenW(buf), max_len; - - max_len = size <= len? size : len + 1; - - ret = MSVCRT_malloc(max_len * sizeof (MSVCRT_wchar_t)); - if (ret) - { - memcpy(ret,buf,max_len * sizeof (MSVCRT_wchar_t)); - ret[max_len] = 0; - } - return ret; -} - /********************************************************************* * _wcsdup (MSVCRT.@) */ diff --git a/dlls/ntdll/actctx.c b/dlls/ntdll/actctx.c index 08383e3b627..8cf5467f52f 100644 --- a/dlls/ntdll/actctx.c +++ b/dlls/ntdll/actctx.c @@ -80,20 +80,14 @@ struct version USHORT revision; }; -enum assembly_id_type -{ - TYPE_NONE, - TYPE_WIN32 -}; - struct assembly_identity { WCHAR *name; WCHAR *arch; WCHAR *public_key; WCHAR *language; + WCHAR *type; struct version version; - enum assembly_id_type type; BOOL optional; }; @@ -158,6 +152,7 @@ struct assembly enum assembly_type type; struct assembly_identity id; struct file_info manifest; + WCHAR *directory; BOOL no_inherit; struct dll_redirect *dlls; unsigned int num_dlls; @@ -226,13 +221,15 @@ struct actctx_loader #define MANIFESTV3_NAMESPACE "urn:schemas-microsoft-com:asm.v3" static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; +static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; +static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 }; +static ACTIVATION_CONTEXT *process_actctx = &system_actctx; static WCHAR *strdupW(const WCHAR* str) { WCHAR* ptr; - if (!str) return NULL; if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR)))) return NULL; return strcpyW(ptr, str); @@ -267,6 +264,11 @@ static inline const char* debugstr_xmlstr(const xmlstr_t* str) return debugstr_an(str->ptr, str->len); } +static inline const char* debugstr_version(const struct version *ver) +{ + return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision); +} + static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at) { struct assembly *assembly; @@ -394,10 +396,58 @@ static void free_entity_array(struct entity_array *array) RtlFreeHeap( GetProcessHeap(), 0, array->base ); } +static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 ) +{ + if (!str1) return !str2; + return str2 && !strcmpiW( str1, str2 ); +} + +static BOOL is_matching_identity( const struct assembly_identity *id1, + const struct assembly_identity *id2 ) +{ + if (!is_matching_string( id1->name, id2->name )) return FALSE; + if (!is_matching_string( id1->arch, id2->arch )) return FALSE; + if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE; + + if (id1->language && id2->language && strcmpiW( id1->language, id2->language )) + { + static const WCHAR wildcardW[] = {'*',0}; + if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language )) + return FALSE; + } + if (id1->version.major != id2->version.major) return FALSE; + if (id1->version.minor != id2->version.minor) return FALSE; + if (id1->version.build > id2->version.build) return FALSE; + if (id1->version.build == id2->version.build && + id1->version.revision > id2->version.revision) return FALSE; + return TRUE; +} + static BOOL add_dependent_assembly_id(struct actctx_loader* acl, struct assembly_identity* ai) { - /* FIXME: should check that the passed ai isn't already in the list */ + unsigned int i; + + /* check if we already have that assembly */ + + for (i = 0; i < acl->actctx->num_assemblies; i++) + if (is_matching_identity( ai, &acl->actctx->assemblies[i].id )) + { + TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n", + debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor, + ai->version.build, ai->version.revision ); + return TRUE; + } + + for (i = 0; i < acl->num_dependencies; i++) + if (is_matching_identity( ai, &acl->dependencies[i] )) + { + TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n", + debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor, + ai->version.build, ai->version.revision ); + return TRUE; + } + if (acl->num_dependencies == acl->allocated_dependencies) { void *ptr; @@ -430,6 +480,83 @@ static void free_depend_manifests(struct actctx_loader* acl) RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies); } +static WCHAR *build_assembly_dir(struct assembly_identity* ai) +{ + static const WCHAR undW[] = {'_',0}; + static const WCHAR noneW[] = {'n','o','n','e',0}; + static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0}; + + const WCHAR *key = ai->public_key ? ai->public_key : noneW; + const WCHAR *lang = ai->language ? ai->language : noneW; + SIZE_T size = (strlenW(ai->arch) + 1 + strlenW(ai->name) + 1 + strlenW(key) + 24 + 1 + + strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW); + WCHAR *ret; + + if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL; + + strcpyW( ret, ai->arch ); + strcatW( ret, undW ); + strcatW( ret, ai->name ); + strcatW( ret, undW ); + strcatW( ret, key ); + strcatW( ret, undW ); + sprintfW( ret + strlenW(ret), version_formatW, + ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); + strcatW( ret, undW ); + strcatW( ret, lang ); + strcatW( ret, undW ); + strcatW( ret, mskeyW ); + return ret; +} + +static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str ) +{ + WCHAR *p = buffer; + + if (!str) return; + strcatW( buffer, prefix ); + p += strlenW(p); + *p++ = '"'; + strcpyW( p, str ); + p += strlenW(p); + *p++ = '"'; + *p = 0; +} + +static WCHAR *build_assembly_id( const struct assembly_identity *ai ) +{ + static const WCHAR archW[] = + {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0}; + static const WCHAR public_keyW[] = + {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0}; + static const WCHAR typeW[] = + {',','t','y','p','e','=',0}; + static const WCHAR versionW[] = + {',','v','e','r','s','i','o','n','=',0}; + + WCHAR version[64], *ret; + SIZE_T size = 0; + + sprintfW( version, version_formatW, + ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); + if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR); + if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2; + if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2; + if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2; + size += strlenW(versionW) + strlenW(version) + 2; + + if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) ))) + return NULL; + + if (ai->name) strcpyW( ret, ai->name ); + else *ret = 0; + append_string( ret, archW, ai->arch ); + append_string( ret, public_keyW, ai->public_key ); + append_string( ret, typeW, ai->type ); + append_string( ret, versionW, version ); + return ret; +} + static ACTIVATION_CONTEXT *check_actctx( HANDLE h ) { ACTIVATION_CONTEXT *actctx = h; @@ -467,6 +594,7 @@ static void actctx_release( ACTIVATION_CONTEXT *actctx ) } RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls ); RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info ); + RtlFreeHeap( GetProcessHeap(), 0, assembly->directory ); free_entity_array( &assembly->entities ); free_assembly_identity(&assembly->id); } @@ -519,12 +647,12 @@ static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value, xmlbuf->ptr = ptr; ptr++; - if (ptr == xmlbuf->end || *ptr != '\"') return FALSE; + if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE; value->ptr = ++ptr; if (ptr == xmlbuf->end) return FALSE; - ptr = memchr(ptr, '\"', xmlbuf->end - ptr); + ptr = memchr(ptr, ptr[-1], xmlbuf->end - ptr); if (!ptr) { xmlbuf->ptr = xmlbuf->end; @@ -693,8 +821,6 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a xmlstr_t attr_name, attr_value; BOOL end = FALSE, error; - TRACE("\n"); - while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) { if (xmlstr_cmp(&attr_name, NAME_ATTR)) @@ -703,12 +829,7 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a } else if (xmlstr_cmp(&attr_name, TYPE_ATTR)) { - if (!xmlstr_cmp(&attr_value, "win32")) - { - FIXME("wrong type attr %s\n", debugstr_xmlstr(&attr_value)); - return FALSE; - } - ai->type = TYPE_WIN32; + if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE; } else if (xmlstr_cmp(&attr_name, VERSION_ATTR)) { @@ -735,6 +856,9 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a } } + TRACE( "name=%s version=%s arch=%s\n", + debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) ); + if (error || end) return end; return parse_expect_elem(xmlbuf, ELEM_END(ASSEMBLYIDENTITY_ELEM)) && parse_end_element(xmlbuf); } @@ -1016,7 +1140,8 @@ static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai)) return FALSE; - TRACE( "adding %s\n", debugstr_w(ai.name) ); + TRACE( "adding name=%s version=%s arch=%s\n", + debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) ); /* store the newly found identity for later loading */ if (!add_dependent_assembly_id(acl, &ai)) return FALSE; @@ -1047,8 +1172,6 @@ static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl) xmlstr_t attr_name, attr_value, elem; BOOL end = FALSE, ret = TRUE, error, optional = FALSE; - TRACE("\n"); - while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) { if (xmlstr_cmp(&attr_name, OPTIONAL_ATTR)) @@ -1286,16 +1409,19 @@ static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, } static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai, - LPCWSTR filename, xmlbuf_t* xmlbuf ) + LPCWSTR filename, LPCWSTR directory, xmlbuf_t* xmlbuf ) { xmlstr_t elem; struct assembly* assembly; - TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) ); + TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) ); if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST))) return STATUS_SXS_CANT_GEN_ACTCTX; + if (directory && !(assembly->directory = strdupW(directory))) + return STATUS_NO_MEMORY; + if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ); assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE : ACTIVATION_CONTEXT_PATH_TYPE_NONE; @@ -1370,7 +1496,8 @@ static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsign } static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, - LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang ) + LPCWSTR filename, LPCWSTR directory, HANDLE hModule, + LPCWSTR resname, ULONG lang ) { NTSTATUS status; UNICODE_STRING nameW; @@ -1378,7 +1505,17 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL; void *ptr; - TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), hModule, debugstr_w(filename) ); + if (TRACE_ON(actctx)) + { + if (!filename && !get_module_filename( hModule, &nameW, 0 )) + { + TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), + hModule, debugstr_w(nameW.Buffer) ); + RtlFreeUnicodeString( &nameW ); + } + else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), + hModule, debugstr_w(filename) ); + } if (!resname) return STATUS_INVALID_PARAMETER; @@ -1413,13 +1550,14 @@ static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assemb xmlbuf_t buf; buf.ptr = ptr; buf.end = buf.ptr + entry->Size; - status = parse_manifest(acl, ai, filename, &buf); + status = parse_manifest(acl, ai, filename, directory, &buf); } return status; } static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai, - LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang ) + LPCWSTR filename, LPCWSTR directory, HANDLE file, + LPCWSTR resname, ULONG lang ) { HANDLE mapping; OBJECT_ATTRIBUTES attr; @@ -1454,7 +1592,7 @@ static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assem if (RtlImageNtHeader(base)) /* we got a PE file */ { HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */ - status = get_manifest_in_module( acl, ai, filename, module, resname, lang ); + status = get_manifest_in_module( acl, ai, filename, directory, module, resname, lang ); } else status = STATUS_INVALID_IMAGE_FORMAT; @@ -1463,7 +1601,7 @@ static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assem } static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai, - LPCWSTR filename, HANDLE file ) + LPCWSTR filename, LPCWSTR directory, HANDLE file ) { HANDLE mapping; OBJECT_ATTRIBUTES attr; @@ -1498,7 +1636,7 @@ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct buf.ptr = base; buf.end = buf.ptr + count; - status = parse_manifest(acl, ai, filename, &buf); + status = parse_manifest(acl, ai, filename, directory, &buf); NtUnmapViewOfSection( GetCurrentProcess(), base ); return status; @@ -1506,7 +1644,7 @@ static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct /* try to load the .manifest file associated to the file */ static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai, - LPCWSTR filename, HMODULE module, LPCWSTR resname ) + LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname ) { static const WCHAR fmtW[] = { '.','%','l','u',0 }; WCHAR *buffer; @@ -1528,7 +1666,7 @@ static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid ); strcatW( name.Buffer, dotManifestW ); if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL )) - status = STATUS_NO_SUCH_FILE; + status = STATUS_RESOURCE_DATA_NOT_FOUND; RtlFreeUnicodeString( &name ); } if (status) return status; @@ -1544,12 +1682,12 @@ static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, RtlInitUnicodeString( &nameW, buffer ); } - status = open_nt_file( &file, &nameW ); - if (status == STATUS_SUCCESS) + if (!open_nt_file( &file, &nameW )) { - status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file ); + status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, file ); NtClose( file ); } + else status = STATUS_RESOURCE_DATA_NOT_FOUND; RtlFreeUnicodeString( &nameW ); return status; } @@ -1681,16 +1819,17 @@ static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identit path[path_us.Length/sizeof(WCHAR)] = '\\'; strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file ); - RtlFreeHeap( GetProcessHeap(), 0, file ); RtlInitUnicodeString( &path_us, path ); + *strrchrW(file, '.') = 0; /* remove .manifest extension */ if (!open_nt_file( &handle, &path_us )) { - io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, handle); + io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, handle); NtClose( handle ); } else io.u.Status = STATUS_NO_SUCH_FILE; + RtlFreeHeap( GetProcessHeap(), 0, file ); RtlFreeUnicodeString( &path_us ); return io.u.Status; } @@ -1700,11 +1839,14 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl, { static const WCHAR dotDllW[] = {'.','d','l','l',0}; unsigned int i; - WCHAR *buffer, *p; + WCHAR *buffer, *p, *directory; NTSTATUS status; UNICODE_STRING nameW; HANDLE file; + TRACE( "looking for name=%s version=%s arch=%s\n", + debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) ); + if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status; /* FIXME: add support for language specific lookup */ @@ -1714,6 +1856,12 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl, (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) ))) return STATUS_NO_MEMORY; + if (!(directory = build_assembly_dir( ai ))) + { + RtlFreeHeap( GetProcessHeap(), 0, buffer ); + return STATUS_NO_MEMORY; + } + /* lookup in appdir\name.dll * appdir\name.manifest * appdir\name\name.dll @@ -1733,7 +1881,7 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl, status = open_nt_file( &file, &nameW ); if (!status) { - status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file, + status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, file, (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 ); NtClose( file ); break; @@ -1747,15 +1895,18 @@ static NTSTATUS lookup_assembly(struct actctx_loader* acl, status = open_nt_file( &file, &nameW ); if (!status) { - status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file ); + status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, file ); NtClose( file ); break; } RtlFreeUnicodeString( &nameW ); } + status = STATUS_SXS_ASSEMBLY_NOT_FOUND; } RtlFreeUnicodeString( &nameW ); - return STATUS_SXS_ASSEMBLY_NOT_FOUND; + RtlFreeHeap( GetProcessHeap(), 0, directory ); + RtlFreeHeap( GetProcessHeap(), 0, buffer ); + return status; } static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) @@ -1779,6 +1930,148 @@ static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) return status; } +/* find the appropriate activation context for RtlQueryInformationActivationContext */ +static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags ) +{ + NTSTATUS status = STATUS_SUCCESS; + + if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX) + { + if (NtCurrentTeb()->ActivationContextStack.ActiveFrame) + *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext; + } + else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE)) + { + ULONG magic; + LDR_MODULE *pldr; + + LdrLockLoaderLock( 0, NULL, &magic ); + if (!LdrFindEntryForAddress( *handle, &pldr )) + { + if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress) + status = STATUS_DLL_NOT_FOUND; + else + *handle = pldr->ActivationContext; + } + else status = STATUS_DLL_NOT_FOUND; + LdrUnlockLoaderLock( 0, magic ); + } + else if (!*handle) *handle = process_actctx; + + return status; +} + +static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i) +{ + data->ulDataFormatVersion = 1; + data->lpData = v1; + data->ulLength = 20; /* FIXME */ + data->lpSectionGlobalData = NULL; /* FIXME */ + data->ulSectionGlobalDataLength = 0; /* FIXME */ + data->lpSectionBase = v2; + data->ulSectionTotalLength = 0; /* FIXME */ + data->hActCtx = NULL; + if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) + data->ulAssemblyRosterIndex = i + 1; + + return STATUS_SUCCESS; +} + +static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, + PACTCTX_SECTION_KEYED_DATA data) +{ + unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR); + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen]) + return fill_keyed_data(data, dll, assembly, i); + } + } + return STATUS_SXS_KEY_NOT_FOUND; +} + +static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, + PACTCTX_SECTION_KEYED_DATA data) +{ + unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR); + + for (i = 0; i < actctx->num_assemblies; i++) + { + struct assembly *assembly = &actctx->assemblies[i]; + for (j = 0; j < assembly->num_dlls; j++) + { + struct dll_redirect *dll = &assembly->dlls[j]; + for (k = 0; k < dll->entities.num; k++) + { + struct entity *entity = &dll->entities.base[k]; + if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) + { + if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen]) + return fill_keyed_data(data, entity, dll, i); + } + } + } + } + return STATUS_SXS_KEY_NOT_FOUND; +} + +static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, + const UNICODE_STRING *section_name, + DWORD flags, PACTCTX_SECTION_KEYED_DATA data) +{ + NTSTATUS status; + + switch (section_kind) + { + case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: + status = find_dll_redirection(actctx, section_name, data); + break; + case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: + status = find_window_class(actctx, section_name, data); + break; + case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: + case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: + case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: + case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: + case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: + case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: + FIXME("Unsupported yet section_kind %x\n", section_kind); + return STATUS_SXS_SECTION_NOT_FOUND; + default: + WARN("Unknown section_kind %x\n", section_kind); + return STATUS_SXS_SECTION_NOT_FOUND; + } + + if (status != STATUS_SUCCESS) return status; + + if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) + { + actctx_addref(actctx); + data->hActCtx = actctx; + } + return STATUS_SUCCESS; +} + +/* initialize the activation context for the current process */ +void actctx_init(void) +{ + ACTCTXW ctx; + HANDLE handle; + + ctx.cbSize = sizeof(ctx); + ctx.lpSource = NULL; + ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; + ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress; + ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; + + if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle); +} + /*********************************************************************** * RtlCreateActivationContext (NTDLL.@) @@ -1790,9 +2083,9 @@ static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr ) { const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */ + const WCHAR *directory = NULL; ACTIVATION_CONTEXT *actctx; UNICODE_STRING nameW; - struct assembly *assembly; ULONG lang = 0; NTSTATUS status = STATUS_NO_MEMORY; HANDLE file = 0; @@ -1809,17 +2102,6 @@ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr ) actctx->magic = ACTCTX_MAGIC; actctx->ref_count = 1; - - if (!(assembly = add_assembly( actctx, APPLICATION_MANIFEST ))) goto error; - if (!(assembly->id.name = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) ))) - goto error; - assembly->id.version.major = 1; - assembly->id.version.minor = 0; - assembly->id.version.build = 0; - assembly->id.version.revision = 0; - assembly->manifest.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; - assembly->manifest.info = NULL; - actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; actctx->config.info = NULL; actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; @@ -1834,7 +2116,7 @@ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr ) if ((status = get_module_filename( NtCurrentTeb()->Peb->ImageBaseAddress, &dir, 0 ))) goto error; - if ((p = strrchrW( dir.Buffer, '\\' ))) *p = 0; + if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0; actctx->appdir.info = dir.Buffer; } @@ -1860,32 +2142,33 @@ NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr ) acl.allocated_dependencies = 0; if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; + if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) { /* if we have a resource it's a PE file */ if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) { - status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule, + status = get_manifest_in_module( &acl, NULL, NULL, directory, pActCtx->hModule, pActCtx->lpResourceName, lang ); - if (status) + if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) /* FIXME: what to do if pActCtx->lpSource is set */ - status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule, - pActCtx->lpResourceName ); + status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, + pActCtx->hModule, pActCtx->lpResourceName ); } else if (pActCtx->lpSource) { - status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file, - pActCtx->lpResourceName, lang ); - if (status) - status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL, - pActCtx->lpResourceName ); + status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, + file, pActCtx->lpResourceName, lang ); + if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) + status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, + NULL, pActCtx->lpResourceName ); } else status = STATUS_INVALID_PARAMETER; } else { - status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file ); + status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, file ); } if (file) NtClose( file ); @@ -2030,3 +2313,252 @@ BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle ) if (frame->ActivationContext == handle) return TRUE; return FALSE; } + + +/*********************************************************************** + * RtlQueryInformationActivationContext (NTDLL.@) + * + * Get information about an activation context. + * FIXME: function signature/prototype may be wrong + */ +NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, + ULONG class, PVOID buffer, + SIZE_T bufsize, SIZE_T *retlen ) +{ + ACTIVATION_CONTEXT *actctx; + NTSTATUS status; + + TRACE("%08x %p %p %u %p %ld %p\n", flags, handle, + subinst, class, buffer, bufsize, retlen); + + if ((status = find_query_actctx( &handle, flags ))) return status; + + switch (class) + { + case ActivationContextBasicInformation: + { + ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; + + if (retlen) *retlen = sizeof(*info); + if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; + + info->hActCtx = handle; + info->dwFlags = 0; /* FIXME */ + if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle ); + } + break; + + case ActivationContextDetailedInformation: + { + ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; + struct assembly *assembly = NULL; + SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; + LPWSTR ptr; + + if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; + + if (actctx->num_assemblies) assembly = actctx->assemblies; + + if (assembly && assembly->manifest.info) + manifest_len = strlenW(assembly->manifest.info) + 1; + if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1; + if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1; + len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); + + if (retlen) *retlen = len; + if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; + + acdi->dwFlags = 0; + acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ + acdi->ulAssemblyCount = actctx->num_assemblies; + acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; + acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0; + acdi->ulRootConfigurationPathType = actctx->config.type; + acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0; + acdi->ulAppDirPathType = actctx->appdir.type; + acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0; + ptr = (LPWSTR)(acdi + 1); + if (manifest_len) + { + acdi->lpRootManifestPath = ptr; + memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); + ptr += manifest_len; + } + else acdi->lpRootManifestPath = NULL; + if (config_len) + { + acdi->lpRootConfigurationPath = ptr; + memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); + ptr += config_len; + } + else acdi->lpRootConfigurationPath = NULL; + if (appdir_len) + { + acdi->lpAppDirPath = ptr; + memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); + } + else acdi->lpAppDirPath = NULL; + } + break; + + case AssemblyDetailedInformationInActivationContext: + { + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; + struct assembly *assembly; + WCHAR *assembly_id; + DWORD index; + SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; + LPWSTR ptr; + + if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; + if (!subinst) return STATUS_INVALID_PARAMETER; + + index = *(DWORD*)subinst; + if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; + + assembly = &actctx->assemblies[index - 1]; + + if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; + id_len = strlenW(assembly_id) + 1; + if (assembly->directory) ad_len = strlenW(assembly->directory) + 1; + + if (assembly->manifest.info && assembly->type == ASSEMBLY_MANIFEST) + path_len = strlenW(assembly->manifest.info) + 1; + + len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); + + if (retlen) *retlen = len; + if (!buffer || bufsize < len) + { + RtlFreeHeap( GetProcessHeap(), 0, assembly_id ); + return STATUS_BUFFER_TOO_SMALL; + } + + afdi->ulFlags = 0; /* FIXME */ + afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR); + afdi->ulManifestPathType = assembly->manifest.type; + afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0; + /* FIXME afdi->liManifestLastWriteTime = 0; */ + afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ + afdi->ulPolicyPathLength = 0; + /* FIXME afdi->liPolicyLastWriteTime = 0; */ + afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ + afdi->ulManifestVersionMajor = 1; + afdi->ulManifestVersionMinor = 0; + afdi->ulPolicyVersionMajor = 0; /* FIXME */ + afdi->ulPolicyVersionMinor = 0; /* FIXME */ + afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0; + ptr = (LPWSTR)(afdi + 1); + afdi->lpAssemblyEncodedAssemblyIdentity = ptr; + memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); + ptr += id_len; + if (path_len) + { + afdi->lpAssemblyManifestPath = ptr; + memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); + ptr += path_len; + } else afdi->lpAssemblyManifestPath = NULL; + afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ + if (ad_len) + { + afdi->lpAssemblyDirectoryName = ptr; + memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); + ptr += ad_len; + } + else afdi->lpAssemblyDirectoryName = NULL; + RtlFreeHeap( GetProcessHeap(), 0, assembly_id ); + } + break; + + case FileInformationInAssemblyOfAssemblyInActivationContext: + { + const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; + ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; + struct assembly *assembly; + struct dll_redirect *dll; + SIZE_T len, dll_len = 0; + LPWSTR ptr; + + if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; + if (!acqi) return STATUS_INVALID_PARAMETER; + + if (acqi->ulAssemblyIndex >= actctx->num_assemblies) + return STATUS_INVALID_PARAMETER; + assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; + + if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) + return STATUS_INVALID_PARAMETER; + dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; + + if (dll->name) dll_len = strlenW(dll->name) + 1; + len = sizeof(*afdi) + dll_len * sizeof(WCHAR); + + if (!buffer || bufsize < len) + { + if (retlen) *retlen = len; + return STATUS_BUFFER_TOO_SMALL; + } + if (retlen) *retlen = 0; /* yes that's what native does !! */ + afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; + afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0; + afdi->ulPathLength = 0; /* FIXME */ + ptr = (LPWSTR)(afdi + 1); + if (dll_len) + { + afdi->lpFileName = ptr; + memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); + } else afdi->lpFileName = NULL; + afdi->lpFilePath = NULL; /* FIXME */ + } + break; + + default: + FIXME( "class %u not implemented\n", class ); + return STATUS_NOT_IMPLEMENTED; + } + return STATUS_SUCCESS; +} + +/*********************************************************************** + * RtlFindActivationContextSectionString (NTDLL.@) + * + * Find information about a string in an activation context. + * FIXME: function signature/prototype may be wrong + */ +NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, + const UNICODE_STRING *section_name, PVOID ptr ) +{ + PACTCTX_SECTION_KEYED_DATA data = ptr; + NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; + + TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind, + debugstr_us(section_name), data); + + if (guid) + { + FIXME("expected guid == NULL\n"); + return STATUS_INVALID_PARAMETER; + } + if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) + { + FIXME("unknown flags %08x\n", flags); + return STATUS_INVALID_PARAMETER; + } + if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || + !section_name || !section_name->Buffer) + { + WARN("invalid parameter\n"); + return STATUS_INVALID_PARAMETER; + } + + if (NtCurrentTeb()->ActivationContextStack.ActiveFrame) + { + ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext); + if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); + } + + if (status != STATUS_SUCCESS) + status = find_string( process_actctx, section_kind, section_name, flags, data ); + + return status; +} diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index ca06e8931ac..44647daa1bd 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -48,6 +48,10 @@ WINE_DECLARE_DEBUG_CHANNEL(snoop); WINE_DECLARE_DEBUG_CHANNEL(loaddll); WINE_DECLARE_DEBUG_CHANNEL(imports); +/* we don't want to include winuser.h */ +#define RT_MANIFEST ((ULONG_PTR)24) +#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID ((ULONG_PTR)2) + typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID); static int process_detaching = 0; /* set on process detach to avoid deadlocks with thread detach */ @@ -578,6 +582,32 @@ done: } +/*********************************************************************** + * create_module_activation_context + */ +static NTSTATUS create_module_activation_context( LDR_MODULE *module ) +{ + NTSTATUS status; + LDR_RESOURCE_INFO info; + const IMAGE_RESOURCE_DATA_ENTRY *entry; + + info.Type = RT_MANIFEST; + info.Name = ISOLATIONAWARE_MANIFEST_RESOURCE_ID; + info.Language = 0; + if (!(status = LdrFindResource_U( module->BaseAddress, &info, 3, &entry ))) + { + ACTCTXW ctx; + ctx.cbSize = sizeof(ctx); + ctx.lpSource = NULL; + ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; + ctx.hModule = module->BaseAddress; + ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID; + status = RtlCreateActivationContext( &module->ActivationContext, &ctx ); + } + return status; +} + + /**************************************************************** * fixup_imports * @@ -591,9 +621,12 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) WINE_MODREF *prev; DWORD size; NTSTATUS status; + ULONG_PTR cookie; if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */ wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS; + if (!create_module_activation_context( &wm->ldr )) + RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie ); if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size ))) @@ -620,6 +653,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) status = STATUS_DLL_NOT_FOUND; } current_modref = prev; + if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie ); return status; } @@ -651,6 +685,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename ) wm->ldr.SectionHandle = NULL; wm->ldr.CheckSum = 0; wm->ldr.TimeDateStamp = 0; + wm->ldr.ActivationContext = 0; RtlCreateUnicodeString( &wm->ldr.FullDllName, filename ); if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++; @@ -895,6 +930,7 @@ static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved ) static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved ) { NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR cookie; int i; if (process_detaching) return status; @@ -908,6 +944,7 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved ) /* Tag current MODREF to prevent recursive loop */ wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS; + if (wm->ldr.ActivationContext) RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie ); /* Recursively attach all DLLs this one depends on */ for ( i = 0; i < wm->nDeps; i++ ) @@ -939,6 +976,7 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved ) InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList, &wm->ldr.InInitializationOrderModuleList); + if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie ); /* Remove recursion flag */ wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS; @@ -1546,6 +1584,70 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file, /*********************************************************************** + * find_actctx_dll + * + * Find the full path (if any) of the dll from the activation context. + */ +static NTSTATUS find_actctx_dll( LPCWSTR libname, LPWSTR *fullname ) +{ + static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'}; + + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; + ACTCTX_SECTION_KEYED_DATA data; + UNICODE_STRING nameW; + NTSTATUS status; + SIZE_T needed, size = 1024; + WCHAR *p; + + RtlInitUnicodeString( &nameW, libname ); + data.cbSize = sizeof(data); + status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, + ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + &nameW, &data ); + if (status != STATUS_SUCCESS) return status; + + for (;;) + { + if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, size ))) + { + status = STATUS_NO_MEMORY; + goto done; + } + status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, + AssemblyDetailedInformationInActivationContext, + info, size, &needed ); + if (status == STATUS_SUCCESS) break; + if (status != STATUS_BUFFER_TOO_SMALL) goto done; + RtlFreeHeap( GetProcessHeap(), 0, info ); + size = needed; + /* restart with larger buffer */ + } + + needed = (windows_dir.Length + sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + + nameW.Length + 2*sizeof(WCHAR)); + + if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) + { + status = STATUS_NO_MEMORY; + goto done; + } + memcpy( p, windows_dir.Buffer, windows_dir.Length ); + p += windows_dir.Length / sizeof(WCHAR); + memcpy( p, winsxsW, sizeof(winsxsW) ); + p += sizeof(winsxsW) / sizeof(WCHAR); + memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength ); + p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); + *p++ = '\\'; + strcpyW( p, libname ); + TRACE ("found %s for %s\n", debugstr_w(*fullname), debugstr_w(libname) ); +done: + RtlFreeHeap( GetProcessHeap(), 0, info ); + RtlReleaseActivationContext( data.hActCtx ); + return status; +} + + +/*********************************************************************** * find_dll_file * * Find the file (or already loaded module) for a given dll name. @@ -1576,7 +1678,22 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, if (!contains_path( libname )) { + NTSTATUS status; + WCHAR *fullname; + if ((*pwm = find_basename_module( libname )) != NULL) goto found; + + status = find_actctx_dll( libname, &fullname ); + if (status == STATUS_SUCCESS) + { + RtlFreeHeap( GetProcessHeap(), 0, dllname ); + libname = dllname = fullname; + } + else if (status != STATUS_SXS_KEY_NOT_FOUND) + { + RtlFreeHeap( GetProcessHeap(), 0, dllname ); + return status; + } } if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) @@ -1983,6 +2100,7 @@ static void free_modref( WINE_MODREF *wm ) } SERVER_END_REQ; + RtlReleaseActivationContext( wm->ldr.ActivationContext ); NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress ); if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle ); if (cached_modref == wm) cached_modref = NULL; @@ -2166,6 +2284,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, RtlEnterCriticalSection( &loader_section ); + actctx_init(); load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error; if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error; diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 62e89c7f5e3..d12123a7d6b 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -574,7 +574,7 @@ @ stdcall RtlFillMemoryUlong(ptr long long) @ stub RtlFinalReleaseOutOfProcessMemoryStream @ stub RtlFindActivationContextSectionGuid -@ stub RtlFindActivationContextSectionString +@ stdcall RtlFindActivationContextSectionString(long ptr long ptr ptr) @ stdcall RtlFindCharInUnicodeString(long ptr ptr ptr) @ stdcall RtlFindClearBits(ptr long long) @ stdcall RtlFindClearBitsAndSet(ptr long long) @@ -767,7 +767,7 @@ @ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr) @ stub RtlQueryHeapInformation @ stdcall RtlQueryInformationAcl(ptr ptr long long) -@ stub RtlQueryInformationActivationContext +@ stdcall RtlQueryInformationActivationContext(long long ptr ptr long ptr long ptr) @ stub RtlQueryInformationActiveActivationContext @ stub RtlQueryInterfaceMemoryStream @ stub RtlQueryProcessBackTraceInformation diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 8f41ff87e31..05df50796e8 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -49,6 +49,7 @@ extern size_t get_signal_stack_total_size(void); extern void version_init( const WCHAR *appname ); extern void debug_init(void); extern HANDLE thread_init(void); +extern void actctx_init(void); extern void virtual_init(void); extern void virtual_init_threading(void); diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c index 6b2e7646a39..bd6f9cad39f 100644 --- a/dlls/ntdll/serial.c +++ b/dlls/ntdll/serial.c @@ -259,7 +259,6 @@ static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc) #ifdef CMSPAR case PARENB|CMSPAR: slc->Parity = MARKPARITY; break; case PARENB|PARODD|CMSPAR: slc->Parity = SPACEPARITY; break; - break; #endif } switch (port.c_cflag & CSIZE) diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c index 37729108db7..1a30aa371b2 100644 --- a/dlls/oleaut32/tmarshal.c +++ b/dlls/oleaut32/tmarshal.c @@ -96,7 +96,7 @@ xbuf_resize(marshal_state *buf, DWORD newsize) } static HRESULT -xbuf_add(marshal_state *buf, LPBYTE stuff, DWORD size) +xbuf_add(marshal_state *buf, const BYTE *stuff, DWORD size) { HRESULT hr; @@ -523,7 +523,7 @@ _argsize(DWORD vt) { } static int -_xsize(TYPEDESC *td) { +_xsize(const TYPEDESC *td) { switch (td->vt) { case VT_DATE: return sizeof(DATE); @@ -531,7 +531,7 @@ _xsize(TYPEDESC *td) { return sizeof(VARIANT)+3; case VT_CARRAY: { int i, arrsize = 1; - ARRAYDESC *adesc = td->u.lpadesc; + const ARRAYDESC *adesc = td->u.lpadesc; for (i=0;icDims;i++) arrsize *= adesc->rgbounds[i].cElements; diff --git a/dlls/oleaut32/typelib2.c b/dlls/oleaut32/typelib2.c index 874d8a8180f..41ee8e69df4 100644 --- a/dlls/oleaut32/typelib2.c +++ b/dlls/oleaut32/typelib2.c @@ -322,7 +322,7 @@ static int ctl2_find_guid( */ static int ctl2_find_name( ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */ - char *name) /* [I] The encoded name to find. */ + const char *name) /* [I] The encoded name to find. */ { int offset; int *namestruct; @@ -331,7 +331,7 @@ static int ctl2_find_name( while (offset != -1) { namestruct = (int *)&This->typelib_segment_data[MSFT_SEG_NAME][offset]; - if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) { + if (!((namestruct[2] ^ *((const int *)name)) & 0xffff00ff)) { /* hash codes and lengths match, final test */ if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break; } @@ -828,7 +828,7 @@ static HRESULT ctl2_set_custdata( */ static int ctl2_encode_typedesc( ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the TYPEDESC. */ - TYPEDESC *tdesc, /* [I] The type description to encode. */ + const TYPEDESC *tdesc, /* [I] The type description to encode. */ int *encoded_tdesc, /* [O] The encoded type description. */ int *width, /* [O] The width of the type, or NULL. */ int *alignment, /* [O] The alignment of the type, or NULL. */ @@ -3225,7 +3225,7 @@ static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 * iface, UIN return S_OK; } -static int ctl2_write_chunk(HANDLE hFile, void *segment, int length) +static int ctl2_write_chunk(HANDLE hFile, const void *segment, int length) { DWORD dwWritten; if (!WriteFile(hFile, segment, length, &dwWritten, 0)) { diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 5ab33d8ca55..029f3614bfc 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -250,7 +250,6 @@ PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) { /* Check if the GL extension required by the function is available */ if(!is_extension_supported(ext_ret->extension)) { WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc); - return NULL; } local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name); diff --git a/dlls/urlmon/http.c b/dlls/urlmon/http.c index a720651e9b6..8dc343264d9 100644 --- a/dlls/urlmon/http.c +++ b/dlls/urlmon/http.c @@ -74,9 +74,11 @@ typedef struct { const IInternetPriorityVtbl *lpInternetPriorityVtbl; DWORD flags, grfBINDF; + BINDINFO bind_info; IInternetProtocolSink *protocol_sink; IHttpNegotiate *http_negotiate; HINTERNET internet, connect, request; + LPWSTR full_header; HANDLE lock; ULONG current_position, content_length, available_bytes; LONG priority; @@ -84,6 +86,10 @@ typedef struct { LONG ref; } HttpProtocol; +/* Default headers from native */ +static const WCHAR wszHeaders[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g', + ':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0}; + /* * Helpers */ @@ -160,6 +166,17 @@ static void HTTPPROTOCOL_Close(HttpProtocol *This) InternetCloseHandle(This->internet); This->internet = 0; } + if (This->full_header) + { + if (This->full_header != wszHeaders) + HeapFree(GetProcessHeap(), 0, This->full_header); + This->full_header = 0; + } + if (This->bind_info.cbSize) + { + ReleaseBindInfo(&This->bind_info); + memset(&This->bind_info, 0, sizeof(This->bind_info)); + } This->flags = 0; } @@ -284,20 +301,17 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl { HttpProtocol *This = PROTOCOL_THIS(iface); URL_COMPONENTSW url; - BINDINFO bindinfo; DWORD len = 0, request_flags = INTERNET_FLAG_KEEP_CONNECTION; ULONG num = 0; IServiceProvider *service_provider = 0; IHttpNegotiate2 *http_negotiate2 = 0; LPWSTR host = 0, path = 0, user = 0, pass = 0, addl_header = 0, - full_header = 0, post_cookie = 0, optional = 0; + post_cookie = 0, optional = 0; BYTE security_id[512]; LPOLESTR user_agent, accept_mimes[257]; HRESULT hres; static const WCHAR wszHttp[] = {'h','t','t','p',':'}; - static const WCHAR wszHeaders[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g', - ':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0}; static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = {{'G','E','T',0}, {'P','O','S','T',0}, @@ -306,9 +320,9 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); - memset(&bindinfo, 0, sizeof(bindinfo)); - bindinfo.cbSize = sizeof(BINDINFO); - hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &This->grfBINDF, &bindinfo); + memset(&This->bind_info, 0, sizeof(This->bind_info)); + This->bind_info.cbSize = sizeof(BINDINFO); + hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &This->grfBINDF, &This->bind_info); if (hres != S_OK) { WARN("GetBindInfo failed: %08x\n", hres); @@ -407,8 +421,9 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl if (This->grfBINDF & BINDF_NOWRITECACHE) request_flags |= INTERNET_FLAG_NO_CACHE_WRITE; - This->request = HttpOpenRequestW(This->connect, bindinfo.dwBindVerb < BINDVERB_CUSTOM ? - wszBindVerb[bindinfo.dwBindVerb] : bindinfo.szCustomVerb, + This->request = HttpOpenRequestW(This->connect, This->bind_info.dwBindVerb < BINDVERB_CUSTOM ? + wszBindVerb[This->bind_info.dwBindVerb] : + This->bind_info.szCustomVerb, path, NULL, NULL, (LPCWSTR *)accept_mimes, request_flags, (DWORD)This); if (!This->request) @@ -443,20 +458,21 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl } else if (addl_header == NULL) { - full_header = (LPWSTR)wszHeaders; + This->full_header = (LPWSTR)wszHeaders; } else { - full_header = HeapAlloc(GetProcessHeap(), 0, - (lstrlenW(addl_header)+sizeof(wszHeaders))*sizeof(WCHAR)); - if (!full_header) + int len_addl_header = lstrlenW(addl_header); + This->full_header = HeapAlloc(GetProcessHeap(), 0, + len_addl_header*sizeof(WCHAR)+sizeof(wszHeaders)); + if (!This->full_header) { WARN("Out of memory\n"); hres = E_OUTOFMEMORY; goto done; } - lstrcpyW(full_header, addl_header); - lstrcpyW(&full_header[lstrlenW(addl_header)], wszHeaders); + lstrcpyW(This->full_header, addl_header); + lstrcpyW(&This->full_header[len_addl_header], wszHeaders); } hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2, @@ -479,7 +495,7 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */ - if (bindinfo.dwBindVerb == BINDVERB_POST) + if (This->bind_info.dwBindVerb == BINDVERB_POST) { num = 0; hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_POST_COOKIE, &post_cookie, @@ -493,18 +509,18 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl } } - if (bindinfo.dwBindVerb != BINDVERB_GET) + if (This->bind_info.dwBindVerb != BINDVERB_GET) { /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ - if (bindinfo.stgmedData.tymed != TYMED_HGLOBAL) - WARN("Expected bindinfo.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", - bindinfo.stgmedData.tymed); + if (This->bind_info.stgmedData.tymed != TYMED_HGLOBAL) + WARN("Expected This->bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", + This->bind_info.stgmedData.tymed); else - optional = (LPWSTR)bindinfo.stgmedData.hGlobal; + optional = (LPWSTR)This->bind_info.stgmedData.hGlobal; } - if (!HttpSendRequestW(This->request, full_header, lstrlenW(full_header), + if (!HttpSendRequestW(This->request, This->full_header, lstrlenW(This->full_header), optional, - optional ? bindinfo.cbstgmedData : 0) && + optional ? This->bind_info.cbstgmedData : 0) && GetLastError() != ERROR_IO_PENDING) { WARN("HttpSendRequest failed: %d\n", GetLastError()); @@ -521,8 +537,6 @@ done: } CoTaskMemFree(post_cookie); - if (full_header != wszHeaders) - HeapFree(GetProcessHeap(), 0, full_header); CoTaskMemFree(addl_header); if (http_negotiate2) IHttpNegotiate2_Release(http_negotiate2); @@ -539,8 +553,6 @@ done: HeapFree(GetProcessHeap(), 0, path); HeapFree(GetProcessHeap(), 0, host); - ReleaseBindInfo(&bindinfo); - return hres; } @@ -558,22 +570,22 @@ static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDA if (!pProtocolData) { WARN("Expected pProtocolData to be non-NULL\n"); - goto done; + return S_OK; } else if (!This->request) { WARN("Expected request to be non-NULL\n"); - goto done; + return S_OK; } else if (!This->http_negotiate) { WARN("Expected IHttpNegotiate pointer to be non-NULL\n"); - goto done; + return S_OK; } else if (!This->protocol_sink) { WARN("Expected IInternetProtocolSink pointer to be non-NULL\n"); - goto done; + return S_OK; } if (pProtocolData->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) @@ -904,9 +916,11 @@ HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) ret->lpInternetProtocolVtbl = &HttpProtocolVtbl; ret->lpInternetPriorityVtbl = &HttpPriorityVtbl; ret->flags = ret->grfBINDF = 0; + memset(&ret->bind_info, 0, sizeof(ret->bind_info)); ret->protocol_sink = 0; ret->http_negotiate = 0; ret->internet = ret->connect = ret->request = 0; + ret->full_header = 0; ret->lock = 0; ret->current_position = ret->content_length = ret->available_bytes = 0; ret->priority = 0; diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c index ebc06bf5c68..72cb2fceb19 100644 --- a/dlls/urlmon/tests/protocol.c +++ b/dlls/urlmon/tests/protocol.c @@ -99,11 +99,11 @@ static LPCWSTR file_name, http_url, expect_wsz; static IInternetProtocol *http_protocol = NULL; static BOOL first_data_notif = FALSE, http_is_first = FALSE, http_post_test = FALSE; -static HWND protocol_hwnd; static int state = 0; static DWORD bindf = 0; static IInternetBindInfo *prot_bind_info; static void *expect_pv; +static HANDLE event_complete; static enum { FILE_TEST, @@ -158,6 +158,7 @@ static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, addl_headers = CoTaskMemAlloc(sizeof(wszHeaders)); if (!addl_headers) { + http_post_test = FALSE; skip("Out of memory\n"); return E_OUTOFMEMORY; } @@ -276,9 +277,35 @@ static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface) static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData) { - CHECK_EXPECT2(Switch); + HRESULT hres; + + CHECK_EXPECT(Switch); ok(pProtocolData != NULL, "pProtocolData == NULL\n"); - SendMessage(protocol_hwnd, WM_USER, 0, (LPARAM)pProtocolData); + if (!state) { + if (http_is_first) { + CHECK_CALLED(ReportProgress_FINDINGRESOURCE); + CHECK_CALLED(ReportProgress_CONNECTING); + } else todo_wine { + CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE); + CHECK_NOT_CALLED(ReportProgress_CONNECTING); + } + CHECK_CALLED(ReportProgress_SENDINGREQUEST); + SET_EXPECT(OnResponse); + SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); + } + + SET_EXPECT(ReportData); + hres = IInternetProtocol_Continue(http_protocol, pProtocolData); + ok(hres == S_OK, "Continue failed: %08x\n", hres); + CHECK_CALLED(ReportData); + + if (!state) { + state = 1; + CHECK_CALLED(OnResponse); + CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + } + + SetEvent(event_complete); return S_OK; } @@ -416,9 +443,23 @@ static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWOR "grcfBSCF = %08x\n", grfBSCF); } - if (!(grfBSCF & BSCF_LASTDATANOTIFICATION) && - !(bindf & BINDF_FROMURLMON)) - SendMessage(protocol_hwnd, WM_USER, 0, 0); + if(!(bindf & BINDF_FROMURLMON) && + !(grfBSCF & BSCF_LASTDATANOTIFICATION)) { + if(!state) { + state = 1; + if(http_is_first) { + CHECK_CALLED(ReportProgress_FINDINGRESOURCE); + CHECK_CALLED(ReportProgress_CONNECTING); + } else todo_wine { + CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE); + CHECK_NOT_CALLED(ReportProgress_CONNECTING); + } + CHECK_CALLED(ReportProgress_SENDINGREQUEST); + CHECK_CALLED(OnResponse); + CHECK_CALLED(ReportProgress_RAWMIMETYPE); + } + SetEvent(event_complete); + } } return S_OK; } @@ -504,18 +545,19 @@ static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfB if (http_post_test) { - pbindinfo->dwBindVerb = BINDVERB_POST; - pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly * with urlmon on native (Win98 and WinXP) */ pbindinfo->stgmedData.hGlobal = GlobalAlloc(GPTR, sizeof(szPostData)); if (!pbindinfo->stgmedData.hGlobal) { + http_post_test = FALSE; skip("Out of memory\n"); return E_OUTOFMEMORY; } lstrcpy((LPSTR)pbindinfo->stgmedData.hGlobal, szPostData); pbindinfo->cbstgmedData = sizeof(szPostData)-1; + pbindinfo->dwBindVerb = BINDVERB_POST; + pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; } return S_OK; @@ -1214,43 +1256,87 @@ static void test_http_protocol_url(LPCWSTR url, BOOL is_first) (void**)&http_protocol); ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres); if(SUCCEEDED(hres)) { - BYTE buf[512]; + BYTE buf[3600]; DWORD cb; - MSG msg; + int *called = (bindf & BINDF_FROMURLMON) ? &called_Switch : &called_ReportData; test_priority(http_protocol); SET_EXPECT(ReportProgress_FINDINGRESOURCE); SET_EXPECT(ReportProgress_CONNECTING); SET_EXPECT(ReportProgress_SENDINGREQUEST); - if(!(bindf & BINDF_FROMURLMON)) - { + if(!(bindf & BINDF_FROMURLMON)) { SET_EXPECT(OnResponse); SET_EXPECT(ReportProgress_RAWMIMETYPE); SET_EXPECT(ReportData); + } else { + SET_EXPECT(Switch); } if(!http_protocol_start(url, is_first)) return; - hres = IInternetProtocol_Read(http_protocol, buf, 2, &cb); - ok(hres == E_PENDING, "Read failed: %08x, expected E_PENDING\n", hres); - ok(!cb, "cb=%d, expected 0\n", cb); - - if(bindf & BINDF_FROMURLMON) - SET_EXPECT(Switch); SET_EXPECT(ReportResult); expect_hrResult = S_OK; - GetMessage(&msg, NULL, 0, 0); + hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb); + ok((!*called && hres == E_PENDING && cb==0) || + (*called && hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb); + WaitForSingleObject(event_complete, INFINITE); if(bindf & BINDF_FROMURLMON) CHECK_CALLED(Switch); + else + CHECK_CALLED(ReportData); + + while(1) { + if(bindf & BINDF_FROMURLMON) + SET_EXPECT(Switch); + else + SET_EXPECT(ReportData); + hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb); + if(hres == E_PENDING) { + hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb); + ok((!*called && hres == E_PENDING && cb==0) || + (*called && hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb); + WaitForSingleObject(event_complete, INFINITE); + if(bindf & BINDF_FROMURLMON) + CHECK_CALLED(Switch); + else + CHECK_CALLED(ReportData); + } else { + if(bindf & BINDF_FROMURLMON) + CHECK_NOT_CALLED(Switch); + else + CHECK_NOT_CALLED(ReportData); + if(cb == 0) break; + } + } + ok(hres == S_FALSE, "Read failed: %08x\n", hres); CHECK_CALLED(ReportResult); + hres = IInternetProtocol_LockRequest(http_protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08x\n", hres); + + hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb); + ok(hres == S_FALSE, "Read failed: %08x\n", hres); + hres = IInternetProtocol_Terminate(http_protocol, 0); ok(hres == S_OK, "Terminate failed: %08x\n", hres); + /* This wait is to give the internet handles being freed in Terminate + * enough time to actually terminate in all cases. Internet handles + * terminate asynchronously and native reuses the main InternetOpen + * handle. The only case in which this seems to be necessary is on + * wine with native wininet and urlmon, resulting in the next time + * test_http_protocol_url being called the first data notification actually + * being an extra last data notification from the previous connection + * about once out of every ten times. */ + Sleep(100); + + hres = IInternetProtocol_UnlockRequest(http_protocol); + ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); + IInternetProtocol_Release(http_protocol); } @@ -1281,93 +1367,6 @@ static void test_http_protocol(void) http_post_test = FALSE; } -static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if(msg == WM_USER) { - BOOL first_call = FALSE; - HRESULT hres; - DWORD cb; - BYTE buf[3600]; - - if(!state) { - first_call = TRUE; - state = 1; - - if (http_is_first) - { - CHECK_CALLED(ReportProgress_FINDINGRESOURCE); - CHECK_CALLED(ReportProgress_CONNECTING); - } - else todo_wine - { - CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE); - CHECK_NOT_CALLED(ReportProgress_CONNECTING); - } - CHECK_CALLED(ReportProgress_SENDINGREQUEST); - if(!(bindf & BINDF_FROMURLMON)) - { - CHECK_CALLED(OnResponse); - CHECK_CALLED(ReportProgress_RAWMIMETYPE); - CHECK_CALLED(ReportData); - } - else - { - SET_EXPECT(OnResponse); - SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); - } - } - SET_EXPECT(ReportData); - - if (bindf & BINDF_FROMURLMON) - { - hres = IInternetProtocol_Continue(http_protocol, (PROTOCOLDATA*)lParam); - ok(hres == S_OK, "Continue failed: %08x\n", hres); - - CHECK_CALLED(ReportData); - if(first_call) { - CHECK_CALLED(OnResponse); - CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); - } - } - - do hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb); - while(cb); - - ok(hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres); - - if(hres == S_FALSE) - PostMessage(protocol_hwnd, WM_USER+1, 0, 0); - - if(first_call) { - hres = IInternetProtocol_LockRequest(http_protocol, 0); - ok(hres == S_OK, "LockRequest failed: %08x\n", hres); - - do hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb); - while(cb); - ok(hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres); - } - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -static HWND create_protocol_window(void) -{ - static WNDCLASSEX wndclass = { - sizeof(WNDCLASSEX), - 0, - wnd_proc, - 0, 0, NULL, NULL, NULL, NULL, NULL, - "ProtocolWindow", - NULL - }; - - RegisterClassEx(&wndclass); - return CreateWindow("ProtocolWindow", "ProtocolWindow", - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, NULL, NULL, NULL, NULL); -} - static void test_mk_protocol(void) { IInternetProtocolInfo *protocol_info; @@ -1533,14 +1532,14 @@ START_TEST(protocol) { OleInitialize(NULL); - protocol_hwnd = create_protocol_window(); + event_complete = CreateEvent(NULL, FALSE, FALSE, NULL); test_file_protocol(); test_http_protocol(); test_mk_protocol(); test_CreateBinding(); - DestroyWindow(protocol_hwnd); + CloseHandle(event_complete); OleUninitialize(); } diff --git a/dlls/version/info.c b/dlls/version/info.c index 82ca86f11a8..907cd23d779 100644 --- a/dlls/version/info.c +++ b/dlls/version/info.c @@ -771,6 +771,9 @@ BOOL WINAPI VerQueryValueA( LPCVOID pBlock, LPCSTR lpSubBlock, TRACE("(%p,%s,%p,%p)\n", pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen ); + if (!pBlock) + return FALSE; + if ( !VersionInfoIs16( info ) ) { BOOL ret; @@ -823,6 +826,9 @@ BOOL WINAPI VerQueryValueW( LPCVOID pBlock, LPCWSTR lpSubBlock, TRACE("(%p,%s,%p,%p)\n", pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen ); + if (!pBlock) + return FALSE; + if ( VersionInfoIs16( info ) ) { BOOL ret; diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c index 7990a0fa62a..dbac20088fc 100644 --- a/dlls/winealsa.drv/dsoutput.c +++ b/dlls/winealsa.drv/dsoutput.c @@ -157,7 +157,7 @@ static void CheckXRUN(IDsDriverBufferImpl* This) ERR("recovery from suspend failed, prepare failed: %s\n", snd_strerror(err)); } } else if ( state != SND_PCM_STATE_RUNNING ) { - WARN("Unhandled state: %d\n", state); + FIXME("Unhandled state: %d\n", state); } } @@ -490,9 +490,12 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface, state = snd_pcm_state(This->pcm); - if (state != SND_PCM_STATE_RUNNING) + if (state != SND_PCM_STATE_PREPARED && state != SND_PCM_STATE_RUNNING) + { CheckXRUN(This); - else + state = snd_pcm_state(This->pcm); + } + if (state == SND_PCM_STATE_RUNNING) { snd_pcm_uframes_t used = CommitAll(This); diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 32791b7ccb5..1c5abd07378 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -700,6 +700,7 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf Context_MarkStateDirty(context, WINED3DTS_PROJECTION); Context_MarkStateDirty(context, STATE_VDECL); Context_MarkStateDirty(context, STATE_VIEWPORT); + Context_MarkStateDirty(context, STATE_SCISSORRECT); } } else { @@ -787,6 +788,7 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf Context_MarkStateDirty(context, WINED3DTS_PROJECTION); Context_MarkStateDirty(context, STATE_VDECL); Context_MarkStateDirty(context, STATE_VIEWPORT); + Context_MarkStateDirty(context, STATE_SCISSORRECT); } } if (readTexture) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index dad264245fd..9c48582cb30 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -192,10 +192,6 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo)); } - HeapFree(GetProcessHeap(), 0, This->render_targets); - HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments); - HeapFree(GetProcessHeap(), 0, This->draw_buffers); - if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup); /* TODO: Clean up all the surfaces and textures! */ @@ -579,7 +575,6 @@ If this flag is set, the contents of the depth stencil buffer will be invalid af static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */ - unsigned int pow2Width, pow2Height; unsigned int Size = 1; const PixelFormatDesc *tableEntry = getFormatDescEntry(Format); TRACE("(%p) Create surface\n",This); @@ -620,27 +615,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U * by the device. *******************************/ - /* Non-power2 support */ - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { - pow2Width = Width; - pow2Height = Height; - } else { - /* Find the nearest pow2 match */ - pow2Width = pow2Height = 1; - while (pow2Width < Width) pow2Width <<= 1; - while (pow2Height < Height) pow2Height <<= 1; - } - - if (pow2Width > Width || pow2Height > Height) { - /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/ - if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 - || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) { - FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n", - This, Width, Height); - return WINED3DERR_NOTAVAILABLE; - } - } - /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since * it is based around 4x4 pixel blocks it requires padding, so allocate enough * space! @@ -679,13 +653,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U object->glDescription.level = Level; object->glDescription.target = GL_TEXTURE_2D; - /* Internal data */ - object->pow2Width = pow2Width; - object->pow2Height = pow2Height; - /* Flags */ object->Flags = 0; - object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0; object->Flags |= Discard ? SFLAG_DISCARD : 0; object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0; object->Flags |= Lockable ? SFLAG_LOCKABLE : 0; @@ -747,7 +716,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U /* Look at the implementation and set the correct Vtable */ switch(Impl) { case SURFACE_OPENGL: - /* Nothing to do, it's set already */ + /* Check if a 3D adapter is available when creating gl surfaces */ + if(!This->adapter) { + ERR("OpenGL surfaces are not available without opengl\n"); + HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory); + HeapFree(GetProcessHeap(), 0, object); + return WINED3DERR_NOTAVAILABLE; + } break; case SURFACE_GDI: @@ -1809,6 +1784,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR if (WINED3D_OK != hr) return hr; + This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); + This->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); + This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers)); + /* Initialize the texture unit mapping to a 1:1 mapping */ for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state) { if (state < GL_LIMITS(fragment_samplers)) { @@ -2010,6 +1989,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D } } + HeapFree(GetProcessHeap(), 0, This->render_targets); + HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments); + HeapFree(GetProcessHeap(), 0, This->draw_buffers); + This->render_targets = NULL; + This->fbo_color_attachments = NULL; + This->draw_buffers = NULL; + + This->d3d_initialized = FALSE; return WINED3D_OK; } @@ -4522,11 +4509,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun if (!curRect) { /* In drawable flag is set below */ - glScissor(This->stateBlock->viewport.X, - (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), - This->stateBlock->viewport.Width, - This->stateBlock->viewport.Height); + if (This->render_offscreen) { + glScissor(This->stateBlock->viewport.X, + This->stateBlock->viewport.Y, + This->stateBlock->viewport.Width, + This->stateBlock->viewport.Height); + } else { + glScissor(This->stateBlock->viewport.X, + (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - + (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)), + This->stateBlock->viewport.Width, + This->stateBlock->viewport.Height); + } checkGLcall("glScissor"); glClear(glMask); checkGLcall("glClear"); @@ -6448,19 +6442,21 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW case WINED3DRTYPE_SURFACE: { unsigned int i; - /* Cleanup any FBO attachments */ - for (i = 0; i < GL_LIMITS(buffers); ++i) { - if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) { + /* Cleanup any FBO attachments if d3d is enabled */ + if(This->d3d_initialized) { + for (i = 0; i < GL_LIMITS(buffers); ++i) { + if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) { + bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); + set_render_target_fbo(iface, i, NULL); + This->fbo_color_attachments[i] = NULL; + } + } + if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) { bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); - set_render_target_fbo(iface, i, NULL); - This->fbo_color_attachments[i] = NULL; + set_depth_stencil_fbo(iface, NULL); + This->fbo_depth_attachment = NULL; } } - if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) { - bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo); - set_depth_stencil_fbo(iface, NULL); - This->fbo_depth_attachment = NULL; - } break; } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index ebb07bf0618..1dfb16d43f4 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2418,8 +2418,10 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, HDC hDC; int i; - /* Validate the adapter number */ - if (Adapter >= IWineD3D_GetAdapterCount(iface)) { + /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter + * number and create a device without a 3D adapter for 2D only operation. + */ + if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) { return WINED3DERR_INVALIDCALL; } @@ -2435,7 +2437,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, object->lpVtbl = &IWineD3DDevice_Vtbl; object->ref = 1; object->wineD3D = iface; - object->adapter = &Adapters[Adapter]; + object->adapter = numAdapters ? &Adapters[Adapter] : NULL; IWineD3D_AddRef(object->wineD3D); object->parent = parent; @@ -2471,14 +2473,6 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, object->shader_backend = &none_shader_backend; } - /* This function should *not* be modifying GL caps - * TODO: move the functionality where it belongs */ - select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &GLINFO_LOCATION); - - object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); - object->fbo_color_attachments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); - object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers)); - /* set the state of the device to valid */ object->state = WINED3D_OK; @@ -2526,6 +2520,7 @@ ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) { BOOL InitAdapters(void) { HDC device_context; BOOL ret; + int ps_selected_mode, vs_selected_mode; /* No need to hold any lock. The calling library makes sure only one thread calls * wined3d simultaneously @@ -2563,6 +2558,9 @@ BOOL InitAdapters(void) { } Adapters[0].driver = "Display"; Adapters[0].description = "Direct3D HAL"; + + select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode); + select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info); } numAdapters = 1; TRACE("%d adapters successfully initialized\n", numAdapters); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 3d6101d132b..71a69161c92 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3442,7 +3442,12 @@ static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D winHeight = windowRect.bottom - windowRect.top; TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight, pRect->right - pRect->left, pRect->bottom - pRect->top); - glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); + + if (stateblock->wineD3DDevice->render_offscreen) { + glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); + } else { + glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); + } checkGLcall("glScissor"); } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 11e0fba9094..f0a2b4cbccf 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -3435,6 +3435,36 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Fla static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) { /** Check against the maximum texture sizes supported by the video card **/ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + unsigned int pow2Width, pow2Height; + + /* Non-power2 support */ + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { + pow2Width = This->currentDesc.Width; + pow2Height = This->currentDesc.Height; + } else { + /* Find the nearest pow2 match */ + pow2Width = pow2Height = 1; + while (pow2Width < This->currentDesc.Width) pow2Width <<= 1; + while (pow2Height < This->currentDesc.Height) pow2Height <<= 1; + } + This->pow2Width = pow2Width; + This->pow2Height = pow2Height; + + if (pow2Width > This->currentDesc.Width || pow2Height > This->currentDesc.Height) { + WINED3DFORMAT Format = This->resource.format; + /** TODO: add support for non power two compressed textures **/ + if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 + || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) { + FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n", + This, This->currentDesc.Width, This->currentDesc.Height); + return WINED3DERR_NOTAVAILABLE; + } + } + + if(pow2Width != This->currentDesc.Width || + pow2Height != This->currentDesc.Height) { + This->Flags |= SFLAG_NONPOW2; + } TRACE("%p\n", This); if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) { diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index c9940008b8b..f3a3feaa6c1 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -1513,7 +1513,6 @@ IWineGDISurfaceImpl_PrivateSetup(IWineD3DSurface *iface) IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; HRESULT hr; HDC hdc; - long oldsize = This->resource.size; if(This->resource.usage & WINED3DUSAGE_OVERLAY) { @@ -1527,13 +1526,8 @@ IWineGDISurfaceImpl_PrivateSetup(IWineD3DSurface *iface) This->resource.allocatedMemory = NULL; /* We don't mind the nonpow2 stuff in GDI */ - This->resource.size = IWineD3DSurface_GetPitch(iface) * This->currentDesc.Height; This->pow2Width = This->currentDesc.Width; This->pow2Height = This->currentDesc.Height; - This->Flags &= ~SFLAG_NONPOW2; - - /* Adjust the opengl mem counter */ - globalChangeGlRam(This->resource.size - oldsize); /* Call GetDC to create a DIB section. We will use that * DIB section for rendering diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index d232a2b85a2..d1cf28aa454 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -62,8 +62,11 @@ IWineD3D* WINAPI WineDirect3DCreate(UINT SDKVersion, UINT dxVersion, IUnknown *p IWineD3DImpl* object; if (!InitAdapters()) { - ERR("Failed to initialize direct3d adapters\n"); - return NULL; + WARN("Failed to initialize direct3d adapters, Direct3D will not be available\n"); + if(dxVersion > 7) { + ERR("Direct3D%d is not available without opengl\n", dxVersion); + return NULL; + } } object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DImpl)); diff --git a/dlls/wineoss.drv/dsrender.c b/dlls/wineoss.drv/dsrender.c index f73624eb46d..aa9d373cbe0 100644 --- a/dlls/wineoss.drv/dsrender.c +++ b/dlls/wineoss.drv/dsrender.c @@ -579,7 +579,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface, *lpdwWrite = ptr + 32; else *lpdwWrite = ptr + WOutDev[This->drv->wDevID].dwFragmentSize; - while (*lpdwWrite > This->buflen) + while (*lpdwWrite >= This->buflen) *lpdwWrite -= This->buflen; } TRACE("playpos=%d, writepos=%d\n", lpdwPlay?*lpdwPlay:0, lpdwWrite?*lpdwWrite:0); diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 02dfbffeb4f..d6202e53c8f 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -70,7 +70,7 @@ WINE_DECLARE_DEBUG_CHANNEL(fps); typedef struct wine_glcontext { HDC hdc; XVisualInfo *vis; - GLXFBConfig fb_conf; + GLXFBConfig fbconfig; GLXContext ctx; BOOL do_escape; X11DRV_PDEVICE *physDev; @@ -128,14 +128,15 @@ struct WineGLInfo { }; typedef struct wine_glpixelformat { - int iPixelFormat; - int fbconfig; - int fmt_index; + int iPixelFormat; + GLXFBConfig fbconfig; + int fmt_id; + BOOL offscreenOnly; } WineGLPixelFormat; static Wine_GLContext *context_list; static struct WineGLInfo WineGLInfo = { 0 }; -static int use_render_texture_emulation = 0; +static int use_render_texture_emulation = 1; static int use_render_texture_ati = 0; static int swap_interval = 1; @@ -143,8 +144,7 @@ static int swap_interval = 1; static const WineGLExtension *WineGLExtensionList[MAX_EXTENSIONS]; static int WineGLExtensionListSize; -#define MAX_GLPIXELFORMATS 32 -static WineGLPixelFormat WineGLPixelFormatList[MAX_GLPIXELFORMATS]; +static WineGLPixelFormat *WineGLPixelFormatList; static int WineGLPixelFormatListSize = 0; static void X11DRV_WineGL_LoadExtensions(void); @@ -207,6 +207,7 @@ MAKE_FUNCPTR(glXChooseVisual) MAKE_FUNCPTR(glXCreateContext) MAKE_FUNCPTR(glXCreateGLXPixmap) MAKE_FUNCPTR(glXGetCurrentContext) +MAKE_FUNCPTR(glXGetCurrentDrawable) MAKE_FUNCPTR(glXDestroyContext) MAKE_FUNCPTR(glXDestroyGLXPixmap) MAKE_FUNCPTR(glXGetConfig) @@ -226,6 +227,7 @@ MAKE_FUNCPTR(glXQueryServerString) MAKE_FUNCPTR(glXGetFBConfigs) MAKE_FUNCPTR(glXChooseFBConfig) MAKE_FUNCPTR(glXCreatePbuffer) +MAKE_FUNCPTR(glXCreateNewContext) MAKE_FUNCPTR(glXDestroyPbuffer) MAKE_FUNCPTR(glXGetFBConfigAttrib) MAKE_FUNCPTR(glXGetVisualFromFBConfig) @@ -259,7 +261,9 @@ MAKE_FUNCPTR(glGetString) MAKE_FUNCPTR(glIsEnabled) MAKE_FUNCPTR(glNewList) MAKE_FUNCPTR(glPixelStorei) +MAKE_FUNCPTR(glReadPixels) MAKE_FUNCPTR(glScissor) +MAKE_FUNCPTR(glTexImage2D) MAKE_FUNCPTR(glViewport) #undef MAKE_FUNCPTR @@ -364,6 +368,7 @@ LOAD_FUNCPTR(glXChooseVisual) LOAD_FUNCPTR(glXCreateContext) LOAD_FUNCPTR(glXCreateGLXPixmap) LOAD_FUNCPTR(glXGetCurrentContext) +LOAD_FUNCPTR(glXGetCurrentDrawable) LOAD_FUNCPTR(glXDestroyContext) LOAD_FUNCPTR(glXDestroyGLXPixmap) LOAD_FUNCPTR(glXGetConfig) @@ -381,6 +386,7 @@ LOAD_FUNCPTR(glXQueryServerString) /* GLX 1.3 */ LOAD_FUNCPTR(glXCreatePbuffer) +LOAD_FUNCPTR(glXCreateNewContext) LOAD_FUNCPTR(glXDestroyPbuffer) LOAD_FUNCPTR(glXMakeContextCurrent) LOAD_FUNCPTR(glXGetCurrentReadDrawable) @@ -401,7 +407,9 @@ LOAD_FUNCPTR(glGetString) LOAD_FUNCPTR(glIsEnabled) LOAD_FUNCPTR(glNewList) LOAD_FUNCPTR(glPixelStorei) +LOAD_FUNCPTR(glReadPixels) LOAD_FUNCPTR(glScissor) +LOAD_FUNCPTR(glTexImage2D) LOAD_FUNCPTR(glViewport) #undef LOAD_FUNCPTR @@ -558,9 +566,9 @@ static int describeContext(Wine_GLContext* ctx) { int tmp; int ctx_vis_id; TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis); - pglXGetFBConfigAttrib(gdi_display, ctx->fb_conf, GLX_FBCONFIG_ID, &tmp); + pglXGetFBConfigAttrib(gdi_display, ctx->fbconfig, GLX_FBCONFIG_ID, &tmp); TRACE(" - FBCONFIG_ID 0x%x\n", tmp); - pglXGetFBConfigAttrib(gdi_display, ctx->fb_conf, GLX_VISUAL_ID, &tmp); + pglXGetFBConfigAttrib(gdi_display, ctx->fbconfig, GLX_VISUAL_ID, &tmp); TRACE(" - VISUAL_ID 0x%x\n", tmp); ctx_vis_id = tmp; return ctx_vis_id; @@ -811,7 +819,7 @@ static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, Wine_GLPBuf return nAttribs; } -static BOOL get_fbconfig_from_visualid(Display *display, Visual *visual, int *fmt_id, int *fmt_index) +static BOOL get_fbconfig_from_visualid(Display *display, Visual *visual, GLXFBConfig *fbconfig, int *fmt_id) { GLXFBConfig* cfgs = NULL; int i; @@ -842,9 +850,9 @@ static BOOL get_fbconfig_from_visualid(Display *display, Visual *visual, int *fm /* We are looking up the GLX index of our main visual and have found it :) */ if(visualid == tmp_vis_id) { TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", tmp_fmt_id, i, tmp_vis_id); - XFree(cfgs); + *fbconfig = cfgs[i]; *fmt_id = tmp_fmt_id; - *fmt_index = i; + XFree(cfgs); return TRUE; } } @@ -856,21 +864,72 @@ static BOOL get_fbconfig_from_visualid(Display *display, Visual *visual, int *fm static BOOL init_formats(Display *display, int screen, Visual *visual) { - int fmt_id, fmt_index; + int fmt_id, tmp_vis_id, tmp_fmt_id, nCfgs, i; + GLXFBConfig* cfgs; + GLXFBConfig fbconfig; + int nOffscreenFormats = 0; /* Locate the fbconfig correspondig to our main visual */ - if(!get_fbconfig_from_visualid(display, visual, &fmt_id, &fmt_index)) { + if(!get_fbconfig_from_visualid(display, visual, &fbconfig, &fmt_id)) { ERR("Can't get the FBCONFIG_ID for the main visual, expect problems!\n"); return FALSE; } - /* Put Wine's internal format at the first index */ - WineGLPixelFormatList[0].iPixelFormat = 1; - WineGLPixelFormatList[0].fbconfig = fmt_id; - WineGLPixelFormatList[0].fmt_index = fmt_index; - WineGLPixelFormatListSize = 1; + /* As mentioned in various parts of the code only the format of the main visual can be used for onscreen rendering. + * Next to this format there are also so called offscreen rendering formats (used for pbuffers) which can be supported + * because they don't need a visual. Below we use glXGetFBConfigs instead of glXChooseFBConfig to enumerate the fb configurations + * because this call lists both types of formats instead of only onscreen ones. */ + cfgs = pglXGetFBConfigs(display, DefaultScreen(display), &nCfgs); + if (NULL == cfgs || 0 == nCfgs) { + WARN("glXChooseFBConfig returns NULL\n"); + if(cfgs != NULL) XFree(cfgs); + + /* We only have the single format of Wine's main visual */ + WineGLPixelFormatList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineGLPixelFormat)); + WineGLPixelFormatList[0].iPixelFormat = 1; + WineGLPixelFormatList[0].fbconfig = fbconfig; + WineGLPixelFormatList[0].fmt_id = fmt_id; + WineGLPixelFormatList[0].offscreenOnly = FALSE; + WineGLPixelFormatListSize = 1; + } + else { + /* Count the number of offscreen formats to determine the size for our pixelformat list */ + for(i=0; i WineGLPixelFormatListSize)) { ERR("invalid iPixelFormat %d\n", iPixelFormat); - ret = FALSE; - *fmt_index = -1; + if(AllowOffscreen) + *fmt_count = WineGLPixelFormatListSize; + else + *fmt_count = 1; /* Only show the format of our main visual */ } - else { - ret = TRUE; - *fmt_index = WineGLPixelFormatList[iPixelFormat-1].fmt_index; + else if(iPixelFormat == 1) { + res = &WineGLPixelFormatList[0]; + *fmt_count = 1; /* Only show the format of our main visual */ + } + else if((WineGLPixelFormatList[iPixelFormat-1].offscreenOnly == TRUE) && AllowOffscreen) { + res = &WineGLPixelFormatList[iPixelFormat-1]; + *fmt_count = WineGLPixelFormatListSize; + TRACE("Returning FBConfig=%p for iPixelFormat=%d\n", res->fbconfig, iPixelFormat); } - *fmt_count = WineGLPixelFormatListSize; - TRACE("Returning fmt_index=%d, fmt_count=%d for iPixelFormat=%d\n", *fmt_index, *fmt_count, iPixelFormat); + TRACE("Number of returned pixelformats=%d\n", *fmt_count); - return ret; + return res; } /* Search our internal pixelformat list for the WGL format corresponding to the given fbconfig */ -static int ConvertPixelFormatGLXtoWGL(Display *display, int fbconfig) +static int ConvertPixelFormatGLXtoWGL(Display *display, int fmt_id) { int i; @@ -915,12 +983,12 @@ static int ConvertPixelFormatGLXtoWGL(Display *display, int fbconfig) init_formats(display, DefaultScreen(display), visual); for(i=0; ivisualid); } else { int dwFlags = 0; @@ -970,7 +1030,7 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, int value = 0; /* Pixel type */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_RENDER_TYPE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value); if (value & GLX_RGBA_BIT) iPixelType = PFD_TYPE_RGBA; else @@ -982,7 +1042,7 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, } /* Doublebuffer */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DOUBLEBUFFER, &value); if (value) dwFlags |= PFD_DOUBLEBUFFER; + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value); if (value) dwFlags |= PFD_DOUBLEBUFFER; if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && (ppfd->dwFlags & PFD_DOUBLEBUFFER)) { if (!(dwFlags & PFD_DOUBLEBUFFER)) { TRACE("dbl buffer mismatch\n"); @@ -991,7 +1051,7 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, } /* Stereo */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STEREO, &value); if (value) dwFlags |= PFD_STEREO; + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) dwFlags |= PFD_STEREO; if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO)) { if (!(dwFlags & PFD_STEREO)) { TRACE("stereo mismatch\n"); @@ -1000,28 +1060,28 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, } /* Alpha bits */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_ALPHA_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &value); if (ppfd->iPixelType==PFD_TYPE_RGBA && ppfd->cAlphaBits && !value) { TRACE("alpha mismatch\n"); goto choose_exit; } /* Depth bits */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DEPTH_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value); if (ppfd->cDepthBits && !value) { TRACE("depth mismatch\n"); goto choose_exit; } /* Stencil bits */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STENCIL_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value); if (ppfd->cStencilBits && !value) { TRACE("stencil mismatch\n"); goto choose_exit; } /* Aux buffers */ - pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_AUX_BUFFERS, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_AUX_BUFFERS, &value); if (ppfd->cAuxBuffers && !value) { TRACE("aux mismatch\n"); goto choose_exit; @@ -1036,7 +1096,6 @@ choose_exit: if(!ret) TRACE("No matching mode was found returning 0\n"); - if (NULL != cfgs) XFree(cfgs); wine_tsx11_unlock(); return ret; } @@ -1053,14 +1112,9 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, /*XVisualInfo *vis;*/ int value; int rb,gb,bb,ab; - - GLXFBConfig* cfgs = NULL; - GLXFBConfig cur; - int nCfgs = 0; + WineGLPixelFormat *fmt; int ret = 0; int fmt_count = 0; - int fmt_index = 0; - BOOL res = FALSE; if (!has_opengl()) { ERR("No libGL on this box - disabling OpenGL support !\n"); @@ -1069,29 +1123,13 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd); - wine_tsx11_lock(); - cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs); - wine_tsx11_unlock(); - - if (NULL == cfgs || 0 == nCfgs) { - ERR("unexpected iPixelFormat(%d), returns NULL\n", iPixelFormat); - return 0; /* unespected error */ - } - /* Look for the iPixelFormat in our list of supported formats. If it is supported we get the index in the FBConfig table and the number of supported formats back */ - res = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &fmt_count); - + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &fmt_count); if (ppfd == NULL) { - /* The application is only querying the number of visuals */ - wine_tsx11_lock(); - if (NULL != cfgs) XFree(cfgs); - wine_tsx11_unlock(); + /* The application is only querying the number of pixelformats */ return fmt_count; - } else if(res == FALSE) { + } else if(fmt == NULL) { WARN("unexpected iPixelFormat(%d): not >=1 and <=nFormats(%d), returning NULL!\n", iPixelFormat, fmt_count); - wine_tsx11_lock(); - if (NULL != cfgs) XFree(cfgs); - wine_tsx11_unlock(); return 0; } @@ -1102,7 +1140,6 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, } ret = fmt_count; - cur = cfgs[fmt_index]; memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); @@ -1114,30 +1151,30 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, wine_tsx11_lock(); - pglXGetFBConfigAttrib(gdi_display, cur, GLX_CONFIG_CAVEAT, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_CONFIG_CAVEAT, &value); if(value == GLX_SLOW_CONFIG) ppfd->dwFlags |= PFD_GENERIC_ACCELERATED; - pglXGetFBConfigAttrib(gdi_display, cur, GLX_DOUBLEBUFFER, &value); if (value) ppfd->dwFlags |= PFD_DOUBLEBUFFER; - pglXGetFBConfigAttrib(gdi_display, cur, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO; + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DOUBLEBUFFER, &value); if (value) ppfd->dwFlags |= PFD_DOUBLEBUFFER; + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO; /* Pixel type */ - pglXGetFBConfigAttrib(gdi_display, cur, GLX_RENDER_TYPE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RENDER_TYPE, &value); if (value & GLX_RGBA_BIT) ppfd->iPixelType = PFD_TYPE_RGBA; else ppfd->iPixelType = PFD_TYPE_COLORINDEX; /* Color bits */ - pglXGetFBConfigAttrib(gdi_display, cur, GLX_BUFFER_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, &value); ppfd->cColorBits = value; /* Red, green, blue and alpha bits / shifts */ if (ppfd->iPixelType == PFD_TYPE_RGBA) { - pglXGetFBConfigAttrib(gdi_display, cur, GLX_RED_SIZE, &rb); - pglXGetFBConfigAttrib(gdi_display, cur, GLX_GREEN_SIZE, &gb); - pglXGetFBConfigAttrib(gdi_display, cur, GLX_BLUE_SIZE, &bb); - pglXGetFBConfigAttrib(gdi_display, cur, GLX_ALPHA_SIZE, &ab); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_RED_SIZE, &rb); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_GREEN_SIZE, &gb); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BLUE_SIZE, &bb); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &ab); ppfd->cRedBits = rb; ppfd->cRedShift = gb + bb + ab; @@ -1160,11 +1197,11 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, /* Accums : to do ... */ /* Depth bits */ - pglXGetFBConfigAttrib(gdi_display, cur, GLX_DEPTH_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DEPTH_SIZE, &value); ppfd->cDepthBits = value; /* stencil bits */ - pglXGetFBConfigAttrib(gdi_display, cur, GLX_STENCIL_SIZE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_STENCIL_SIZE, &value); ppfd->cStencilBits = value; wine_tsx11_unlock(); @@ -1177,10 +1214,6 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, dump_PIXELFORMATDESCRIPTOR(ppfd); } - wine_tsx11_lock(); - if (NULL != cfgs) XFree(cfgs); - wine_tsx11_unlock(); - return ret; } @@ -1203,7 +1236,7 @@ int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) { BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd) { - int fmt_index = 0; + WineGLPixelFormat *fmt; int value; TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd); @@ -1214,7 +1247,8 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, } /* Check if iPixelFormat is in our list of supported formats to see if it is supported. */ - if(!ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &value)) { + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, FALSE /* Offscreen */, &value); + if(!fmt) { ERR("Invalid iPixelFormat: %d\n", iPixelFormat); return 0; } @@ -1222,9 +1256,6 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, physDev->current_pf = iPixelFormat; if (TRACE_ON(opengl)) { - int nCfgs_fmt = 0; - GLXFBConfig* cfgs_fmt = NULL; - GLXFBConfig cur_cfg; int gl_test = 0; /* @@ -1243,20 +1274,17 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, pglXQueryDrawable(gdi_display, drawable, GLX_HEIGHT, (unsigned int*) &value); TRACE(" - HEIGHT as %d\n", tmp); */ - cfgs_fmt = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs_fmt); - cur_cfg = cfgs_fmt[fmt_index]; - gl_test = pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_FBCONFIG_ID, &value); + gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); } else { TRACE(" FBConfig have :\n"); TRACE(" - FBCONFIG_ID 0x%x\n", value); - pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_VISUAL_ID, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_VISUAL_ID, &value); TRACE(" - VISUAL_ID 0x%x\n", value); - pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_DRAWABLE_TYPE, &value); + pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &value); TRACE(" - DRAWABLE_TYPE 0x%x\n", value); } - XFree(cfgs_fmt); } return TRUE; } @@ -1269,12 +1297,9 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) { Wine_GLContext *ret; - GLXFBConfig* cfgs_fmt = NULL; - GLXFBConfig cur_cfg; + WineGLPixelFormat *fmt; int hdcPF = physDev->current_pf; int fmt_count = 0; - int fmt_index = 0; - int nCfgs_fmt = 0; int value = 0; int gl_test = 0; HDC hdc = physDev->hdc; @@ -1289,17 +1314,13 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) /* First, get the visual in use by the X11DRV */ if (!gdi_display) return 0; - /* We can only render using the iPixelFormat (1) of Wine's Main visual, we need to get the corresponding GLX format. - * If this fails something is very wrong on the system. */ - if(!ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, &fmt_index, &fmt_count)) { - ERR("Cannot get FB Config for main iPixelFormat 1, expect problems!\n"); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; - } - - cfgs_fmt = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs_fmt); - if (NULL == cfgs_fmt || 0 == nCfgs_fmt) { - ERR("Cannot get FB Configs, expect problems.\n"); + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count); + /* We can render using the iPixelFormat (1) of Wine's Main visual AND using some offscreen formats. + * Note that standard WGL-calls don't recognize offscreen-only formats. For that reason pbuffers + * use a sort of 'proxy' HDC (wglGetPbufferDCARB). + * If this fails something is very wrong on the system. */ + if(!fmt) { + ERR("Cannot get FB Config for iPixelFormat %d, expect problems!\n", hdcPF); SetLastError(ERROR_INVALID_PIXEL_FORMAT); return NULL; } @@ -1310,14 +1331,12 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) return NULL; } - cur_cfg = cfgs_fmt[fmt_index]; - gl_test = pglXGetFBConfigAttrib(gdi_display, cur_cfg, GLX_FBCONFIG_ID, &value); + gl_test = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_FBCONFIG_ID, &value); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); SetLastError(ERROR_INVALID_PIXEL_FORMAT); return NULL; } - XFree(cfgs_fmt); /* The context will be allocated in the wglMakeCurrent call */ wine_tsx11_lock(); @@ -1325,9 +1344,9 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) wine_tsx11_unlock(); ret->hdc = hdc; ret->physDev = physDev; - ret->fb_conf = cur_cfg; + ret->fbconfig = fmt->fbconfig; /*ret->vis = vis;*/ - ret->vis = pglXGetVisualFromFBConfig(gdi_display, cur_cfg); + ret->vis = pglXGetVisualFromFBConfig(gdi_display, fmt->fbconfig); TRACE(" creating context %p (GL context creation delayed)\n", ret); return (HGLRC) ret; @@ -1512,7 +1531,11 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { * We are certain that the drawable and context are compatible as we only allow compatible formats. */ TRACE(" Creating GLX Context\n"); - ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True); + if(ctx->vis) + ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True); + else /* Create a GLX Context for a pbuffer */ + ctx->ctx = pglXCreateNewContext(gdi_display, ctx->fbconfig, GLX_RGBA_TYPE, NULL, True); + TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx); } TRACE(" make current for dis %p, drawable %p, ctx %p\n", gdi_display, (void*) drawable, ctx->ctx); @@ -1602,7 +1625,11 @@ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { if (org->ctx == NULL) { wine_tsx11_lock(); describeContext(org); - org->ctx = pglXCreateContext(gdi_display, org->vis, NULL, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True); + + if(org->vis) + org->ctx = pglXCreateContext(gdi_display, org->vis, NULL, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True); + else /* Create a GLX Context for a pbuffer */ + org->ctx = pglXCreateNewContext(gdi_display, org->fbconfig, GLX_RGBA_TYPE, NULL, True); wine_tsx11_unlock(); TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org); } @@ -1610,7 +1637,10 @@ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { wine_tsx11_lock(); describeContext(dest); /* Create the destination context with display lists shared */ - dest->ctx = pglXCreateContext(gdi_display, dest->vis, org->ctx, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True); + if(dest->vis) + dest->ctx = pglXCreateContext(gdi_display, dest->vis, org->ctx, GetObjectType(org->physDev->hdc) == OBJ_MEMDC ? False : True); + else /* Create a GLX Context for a pbuffer */ + dest->ctx = pglXCreateNewContext(gdi_display, dest->fbconfig, GLX_RGBA_TYPE, org->ctx, True); wine_tsx11_unlock(); TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx); return TRUE; @@ -1845,7 +1875,7 @@ static void WINAPI X11DRV_wglGetIntegerv(GLenum pname, GLint* params) GLXContext gl_ctx = pglXGetCurrentContext(); Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx); - pglXGetFBConfigAttrib(gdi_display, ret->fb_conf, GLX_ALPHA_SIZE, params); + pglXGetFBConfigAttrib(gdi_display, ret->fbconfig, GLX_ALPHA_SIZE, params); TRACE("returns GL_ALPHA_BITS as '%d'\n", *params); break; } @@ -1924,11 +1954,10 @@ static const char * WINAPI X11DRV_wglGetExtensionsStringARB(HDC hdc) { static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) { Wine_GLPBuffer* object = NULL; - GLXFBConfig* cfgs = NULL; + WineGLPixelFormat *fmt = NULL; int nCfgs = 0; int attribs[256]; int nAttribs = 0; - int fmt_index = 0; TRACE("(%p, %d, %d, %d, %p)\n", hdc, iPixelFormat, iWidth, iHeight, piAttribList); @@ -1938,16 +1967,9 @@ static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, return NULL; /* unexpected error */ } - cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs); - - if (NULL == cfgs || 0 == nCfgs) { - ERR("(%p): Cannot get FB Configs for iPixelFormat(%d), returns NULL\n", hdc, iPixelFormat); - SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; /* unexpected error */ - } - /* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */ - if(!ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &nCfgs)) { + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nCfgs); + if(!fmt) { ERR("(%p): unexpected iPixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, iPixelFormat, nCfgs); SetLastError(ERROR_INVALID_PIXEL_FORMAT); goto create_failed; /* unexpected error */ @@ -2090,20 +2112,16 @@ static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, } PUSH1(attribs, None); - object->drawable = pglXCreatePbuffer(gdi_display, cfgs[fmt_index], attribs); + object->drawable = pglXCreatePbuffer(gdi_display, fmt->fbconfig, attribs); TRACE("new Pbuffer drawable as %p\n", (void*) object->drawable); if (!object->drawable) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); goto create_failed; /* unexpected error */ } TRACE("->(%p)\n", object); - - /** free list */ - XFree(cfgs); return (HPBUFFERARB) object; create_failed: - if (NULL != cfgs) XFree(cfgs); HeapFree(GetProcessHeap(), 0, object); TRACE("->(FAILED)\n"); return (HPBUFFERARB) NULL; @@ -2147,6 +2165,8 @@ HDC X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *physDev, HPBUFFERARB hPbuffer) * All formats in our pixelformat list are compatible with each other and the main drawable. */ physDev->current_pf = object->pixelFormat; physDev->drawable = object->drawable; + SetRect( &physDev->drawable_rect, 0, 0, object->width, object->height ); + physDev->dc_rect = physDev->drawable_rect; TRACE("(%p)->(%p)\n", hPbuffer, physDev->hdc); return physDev->hdc; @@ -2226,9 +2246,9 @@ static GLboolean WINAPI X11DRV_wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAtt return GL_FALSE; } switch (object->texture_target) { - case GL_TEXTURE_1D: *piValue = WGL_TEXTURE_CUBE_MAP_ARB; break; - case GL_TEXTURE_2D: *piValue = WGL_TEXTURE_1D_ARB; break; - case GL_TEXTURE_CUBE_MAP: *piValue = WGL_TEXTURE_2D_ARB; break; + case GL_TEXTURE_1D: *piValue = WGL_TEXTURE_1D_ARB; break; + case GL_TEXTURE_2D: *piValue = WGL_TEXTURE_2D_ARB; break; + case GL_TEXTURE_CUBE_MAP: *piValue = WGL_TEXTURE_CUBE_MAP_ARB; break; } } } @@ -2374,14 +2394,11 @@ static GLboolean WINAPI X11DRV_wglChoosePixelFormatARB(HDC hdc, const int *piAtt static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues) { UINT i; - GLXFBConfig* cfgs = NULL; - GLXFBConfig curCfg = NULL; - int nCfgs = 0; + WineGLPixelFormat *fmt = NULL; int hTest; int tmp; int curGLXAttr = 0; int nWGLFormats = 0; - int fmt_index = 0; TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); @@ -2390,16 +2407,11 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF return GL_FALSE; } - cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs); - if (NULL == cfgs) { - ERR("no FB Configs found for display(%p)\n", gdi_display); - return GL_FALSE; - } - /* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supoprted. * We don't have to fail yet as a program can specify an invaled iPixelFormat (lets say 0) if it wants to query * the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */ - if(!ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, &fmt_index, &nWGLFormats)) { + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, iPixelFormat, TRUE /* Offscreen */, &nWGLFormats); + if(!fmt) { WARN("Unable to convert iPixelFormat %d to a GLX one!\n", iPixelFormat); } @@ -2418,11 +2430,8 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF case WGL_ACCELERATION_ARB: curGLXAttr = GLX_CONFIG_CAVEAT; - - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; - - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, curGLXAttr, &tmp); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp); if (hTest) goto get_error; switch (tmp) { case GLX_NONE: piValues[i] = WGL_FULL_ACCELERATION_ARB; break; @@ -2436,11 +2445,8 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF case WGL_TRANSPARENT_ARB: curGLXAttr = GLX_TRANSPARENT_TYPE; - /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of - * supported WGLFormats and also check if the GLX fmt_index is valid. */ - if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; - curCfg = cfgs[fmt_index]; - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, curGLXAttr, &tmp); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp); if (hTest) goto get_error; piValues[i] = GL_FALSE; if (GLX_NONE != tmp) piValues[i] = GL_TRUE; @@ -2448,11 +2454,8 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF case WGL_PIXEL_TYPE_ARB: curGLXAttr = GLX_RENDER_TYPE; - /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of - * supported WGLFormats and also check if the GLX fmt_index is valid. */ - if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; - curCfg = cfgs[fmt_index]; - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, curGLXAttr, &tmp); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp); if (hTest) goto get_error; TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp); if (tmp & GLX_RGBA_BIT) { piValues[i] = WGL_TYPE_RGBA_ARB; } @@ -2467,14 +2470,11 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF case WGL_COLOR_BITS_ARB: /** see ConvertAttribWGLtoGLX for explain */ - /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of - * supported WGLFormats and also check if the GLX fmt_index is valid. */ - if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; - curCfg = cfgs[fmt_index]; - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, GLX_BUFFER_SIZE, piValues + i); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_BUFFER_SIZE, piValues + i); if (hTest) goto get_error; TRACE("WGL_COLOR_BITS_ARB: GLX_BUFFER_SIZE = %d\n", piValues[i]); - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, GLX_ALPHA_SIZE, &tmp); + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_ALPHA_SIZE, &tmp); if (hTest) goto get_error; TRACE("WGL_COLOR_BITS_ARB: GLX_ALPHA_SIZE = %d\n", tmp); piValues[i] = piValues[i] - tmp; @@ -2495,17 +2495,14 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF continue; } curGLXAttr = GLX_RENDER_TYPE; - /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of - * supported WGLFormats and also check if the GLX fmt_index is valid. */ - if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; - curCfg = cfgs[fmt_index]; - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, curGLXAttr, &tmp); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, &tmp); if (hTest) goto get_error; if (GLX_COLOR_INDEX_BIT == tmp) { piValues[i] = GL_FALSE; continue; } - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, GLX_DRAWABLE_TYPE, &tmp); + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp); if (hTest) goto get_error; piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE; continue; @@ -2544,7 +2541,7 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF piValues[i] = GL_TRUE; continue; case WGL_DRAW_TO_PBUFFER_ARB: - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, GLX_DRAWABLE_TYPE, &tmp); + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, GLX_DRAWABLE_TYPE, &tmp); if (hTest) goto get_error; piValues[i] = (tmp & GLX_PBUFFER_BIT) ? GL_TRUE : GL_FALSE; continue; @@ -2575,11 +2572,8 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF * mean that the behavior could differ between different vendors (ATI, Nvidia, ..). */ if (0 != curGLXAttr && iPixelFormat != 0) { - /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of - * supported WGLFormats and also check if the GLX fmt_index is valid. */ - if((iPixelFormat > 0) && ((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs))) goto pix_error; - curCfg = cfgs[fmt_index]; - hTest = pglXGetFBConfigAttrib(gdi_display, curCfg, curGLXAttr, piValues + i); + if (!fmt) goto pix_error; + hTest = pglXGetFBConfigAttrib(gdi_display, fmt->fbconfig, curGLXAttr, piValues + i); if (hTest) goto get_error; curGLXAttr = 0; } else { @@ -2590,12 +2584,10 @@ static GLboolean WINAPI X11DRV_wglGetPixelFormatAttribivARB(HDC hdc, int iPixelF get_error: ERR("(%p): unexpected failure on GetFBConfigAttrib(%x) returns FALSE\n", hdc, curGLXAttr); - XFree(cfgs); return GL_FALSE; pix_error: - ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nCfgs); - XFree(cfgs); + ERR("(%p): unexpected iPixelFormat(%d) vs nFormats(%d), returns FALSE\n", hdc, iPixelFormat, nWGLFormats); return GL_FALSE; } @@ -2650,37 +2642,39 @@ static GLboolean WINAPI X11DRV_wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuf SetLastError(ERROR_INVALID_HANDLE); return GL_FALSE; } -/* Disable WGL_ARB_render_texture support until it is implemented properly - * using pbuffers or FBOs */ -#if 0 + if (!use_render_texture_ati && 1 == use_render_texture_emulation) { - int do_init = 0; - GLint prev_binded_tex; - pglGetIntegerv(object->texture_target, &prev_binded_tex); - if (NULL == object->render_ctx) { - object->render_hdc = X11DRV_wglGetPbufferDCARB(hPbuffer); - /* FIXME: This is routed through gdi32.dll to winex11.drv, replace this with GLX calls */ - object->render_ctx = wglCreateContext(object->render_hdc); - do_init = 1; + void *buf; + static int init = 0; + GLXContext prev_context = pglXGetCurrentContext(); + Drawable prev_drawable = pglXGetCurrentDrawable(); + + /* Our render_texture emulation is basic and lacks some features (1D/Cube support). + This is mostly due to lack of demos/games using them. Further the use of glReadPixels + isn't ideal performance wise but I wasn't able to get other ways working. + */ + if(!init) { + init = 1; /* Only show the FIXME once for performance reasons */ + FIXME("partial stub!\n"); } - object->prev_hdc = wglGetCurrentDC(); - object->prev_ctx = wglGetCurrentContext(); - /* FIXME: This is routed through gdi32.dll to winex11.drv, replace this with GLX calls */ - wglMakeCurrent(object->render_hdc, object->render_ctx); - /* - if (do_init) { - glBindTexture(object->texture_target, object->texture); - if (GL_RGBA == object->use_render_texture) { - glTexImage2D(object->texture_target, 0, GL_RGBA8, object->width, object->height, 0, GL_RGBA, GL_FLOAT, NULL); - } else { - glTexImage2D(object->texture_target, 0, GL_RGB8, object->width, object->height, 0, GL_RGB, GL_FLOAT, NULL); - } + + buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 4*object->width*object->height); + if(!buf) { + ERR("Unable to allocate a buffer for render_texture emulation\n"); + return GL_FALSE; } - */ - object->texture = prev_binded_tex; - return GL_TRUE; + + /* Switch to our pbuffer and readback its contents */ + pglXMakeCurrent(gdi_display, object->drawable, prev_context); + pglReadPixels(0, 0, object->width, object->height, GL_RGBA, GL_UNSIGNED_BYTE, buf); + + /* Switch back to the original drawable and upload the pbuffer-texture */ + pglXMakeCurrent(object->display, prev_drawable, prev_context); + pglTexImage2D(object->texture_target, 0, GL_RGBA8, object->width, object->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + + HeapFree(GetProcessHeap(), 0, buf); } -#endif + if (NULL != pglXBindTexImageARB) { return pglXBindTexImageARB(object->display, object->drawable, iBuffer); } @@ -2705,26 +2699,6 @@ static GLboolean WINAPI X11DRV_wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int i return GL_FALSE; } if (!use_render_texture_ati && 1 == use_render_texture_emulation) { - /* - GLint prev_binded_tex; - glGetIntegerv(object->texture_target, &prev_binded_tex); - if (GL_TEXTURE_1D == object->texture_target) { - glCopyTexSubImage1D(object->texture_target, object->texture_level, 0, 0, 0, object->width); - } else { - glCopyTexSubImage2D(object->texture_target, object->texture_level, 0, 0, 0, 0, object->width, object->height); - } - glBindTexture(object->texture_target, prev_binded_tex); - SwapBuffers(object->render_hdc); - */ - pglBindTexture(object->texture_target, object->texture); - if (GL_TEXTURE_1D == object->texture_target) { - pglCopyTexSubImage1D(object->texture_target, object->texture_level, 0, 0, 0, object->width); - } else { - pglCopyTexSubImage2D(object->texture_target, object->texture_level, 0, 0, 0, 0, object->width, object->height); - } - - /* FIXME: This is routed through gdi32.dll to winex11.drv, replace this with GLX calls */ - wglMakeCurrent(object->prev_hdc, object->prev_ctx); return GL_TRUE; } if (NULL != pglXReleaseTexImageARB) { @@ -2965,8 +2939,10 @@ static void X11DRV_WineGL_LoadExtensions(void) register_extension(&WGL_ARB_pixel_format); + /* Support WGL_ARB_render_texture when there's support or pbuffer based emulation */ if (glxRequireExtension("GLX_ATI_render_texture") || - glxRequireExtension("GLX_ARB_render_texture")) + glxRequireExtension("GLX_ARB_render_texture") || + (glxRequireVersion(3) && glxRequireExtension("GLX_SGIX_pbuffer") && use_render_texture_emulation)) register_extension(&WGL_ARB_render_texture); /* EXT Extensions */ diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 71f78008703..8c50ec99b82 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -118,6 +118,7 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD lpdwIndex); static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl); static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin); +static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field); LPHTTPHEADERW HTTP_GetHeader(LPWININETHTTPREQW req, LPCWSTR head) @@ -636,8 +637,10 @@ static BOOL WINAPI HTTP_HttpAddRequestHeadersW(LPWININETHTTPREQW lpwhr, pFieldAndValue = HTTP_InterpretHttpHeader(lpszStart); if (pFieldAndValue) { - bSuccess = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], - pFieldAndValue[1], dwModifier | HTTP_ADDHDR_FLAG_REQ); + bSuccess = HTTP_VerifyValidHeader(lpwhr, pFieldAndValue[0]); + if (bSuccess) + bSuccess = HTTP_ProcessHeader(lpwhr, pFieldAndValue[0], + pFieldAndValue[1], dwModifier | HTTP_ADDHDR_FLAG_REQ); HTTP_FreeTokens(pFieldAndValue); } @@ -3516,6 +3519,24 @@ static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index) return TRUE; } + +/*********************************************************************** + * HTTP_VerifyValidHeader (internal) + * + * Verify the given header is not invalid for the given http request + * + */ +static BOOL HTTP_VerifyValidHeader(LPWININETHTTPREQW lpwhr, LPCWSTR field) +{ + BOOL rc = TRUE; + + /* Accept-Encoding is stripped from HTTP/1.0 requests. It is invalid */ + if (strcmpiW(field,szAccept_Encoding)==0) + return FALSE; + + return rc; +} + /*********************************************************************** * IsHostInProxyBypassList (@) * diff --git a/dlls/winmm/time.c b/dlls/winmm/time.c index 827f87a9acd..20925408c67 100644 --- a/dlls/winmm/time.c +++ b/dlls/winmm/time.c @@ -359,6 +359,7 @@ MMRESULT WINAPI timeSetEvent(UINT wDelay, UINT wResol, LPTIMECALLBACK lpFunc, MMRESULT WINAPI timeKillEvent(UINT wID) { WINE_TIMERENTRY *lpSelf = NULL, *lpTimer; + DWORD wFlags; TRACE("(%u)\n", wID); EnterCriticalSection(&WINMM_cs); @@ -378,10 +379,11 @@ MMRESULT WINAPI timeKillEvent(UINT wID) WARN("wID=%u is not a valid timer ID\n", wID); return MMSYSERR_INVALPARAM; } - if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS) + wFlags = lpSelf->wFlags; + if (wFlags & TIME_KILL_SYNCHRONOUS) EnterCriticalSection(&TIME_cbcrst); HeapFree(GetProcessHeap(), 0, lpSelf); - if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS) + if (wFlags & TIME_KILL_SYNCHRONOUS) LeaveCriticalSection(&TIME_cbcrst); return TIMERR_NOERROR; } diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index f5ed7ef1595..2d892a34590 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -192,38 +192,40 @@ static const WCHAR envname_win40W[] = {'W','i','n','d','o','w','s',' ','4','.',' static const WCHAR envname_x86W[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; static const WCHAR subdir_win40W[] = {'w','i','n','4','0',0}; static const WCHAR subdir_x86W[] = {'w','3','2','x','8','6',0}; +static const WCHAR Version0_RegPathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; +static const WCHAR Version0_SubdirW[] = {'\\','0',0}; static const WCHAR Version3_RegPathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; static const WCHAR Version3_SubdirW[] = {'\\','3',0}; static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0}; static const WCHAR spoolprtprocsW[] = {'\\','s','p','o','o','l','\\','p','r','t','p','r','o','c','s','\\',0}; +static const WCHAR backslashW[] = {'\\',0}; static const WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t', 'i','o','n',' ','F','i','l','e',0}; static const WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0}; static const WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0}; -static const WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v', - 'M','o','d','e',0}; -static const WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F', - 'i','l','e','s',0}; +static const WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}; +static const WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; static const WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; static const WCHAR DriverW[] = {'D','r','i','v','e','r',0}; +static const WCHAR HardwareIDW[] = {'H','a','r','d','w','a','r','e','I','D',0}; static const WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0}; static const WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0}; +static const WCHAR ManufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; static const WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0}; static const WCHAR MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; static const WCHAR NameW[] = {'N','a','m','e',0}; +static const WCHAR OEM_UrlW[] = {'O','E','M',' ','U','r','l',0}; static const WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0}; static const WCHAR PortW[] = {'P','o','r','t',0}; static const WCHAR bs_Ports_bsW[] = {'\\','P','o','r','t','s','\\',0}; -static const WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e', - 's','s','o','r',0}; -static const WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i', - 'v','e','r',0}; -static const WCHAR PrinterDriverDataW[] = {'P','r','i','n','t','e','r','D','r','i', - 'v','e','r','D','a','t','a',0}; -static const WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F', - 'i','l','e',0}; +static const WCHAR Previous_NamesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; +static const WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r',0}; +static const WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i','v','e','r',0}; +static const WCHAR PrinterDriverDataW[] = {'P','r','i','n','t','e','r','D','r','i','v','e','r','D','a','t','a',0}; +static const WCHAR ProviderW[] = {'P','r','o','v','i','d','e','r',0}; +static const WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F','i','l','e',0}; static const WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0}; static const WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0}; static const WCHAR deviceW[] = {'d','e','v','i','c','e',0}; @@ -242,6 +244,10 @@ static const WCHAR LPR_Port[] = {'L','P','R',':',0}; static const WCHAR default_doc_title[] = {'L','o','c','a','l',' ','D','o','w','n','l','e','v','e','l',' ', 'D','o','c','u','m','e','n','t',0}; +static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), + sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), + sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), + 0, sizeof(DRIVER_INFO_8W)}; /****************************************************************** * validate the user-supplied printing-environment [internal] @@ -264,7 +270,8 @@ static const printenv_t * validate_envW(LPCWSTR env) static const printenv_t env_x86 = {envname_x86W, subdir_x86W, 3, Version3_RegPathW, Version3_SubdirW}; static const printenv_t env_win40 = {envname_win40W, subdir_win40W, - 0, emptyStringW, emptyStringW}; + 0, Version0_RegPathW, Version0_SubdirW}; + static const printenv_t * const all_printenv[]={&env_x86, &env_win40}; const printenv_t *result = NULL; @@ -3413,6 +3420,112 @@ static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName) return value; } + +/***************************************************************************** + * get_filename_from_reg [internal] + * + * Get ValueName from hkey storing result in out + * when the Value in the registry has only a filename, use driverdir as prefix + * outlen is space left in out + * String is stored either as unicode or ascii + * + */ + +static BOOL get_filename_from_reg(HKEY hkey, LPCWSTR driverdir, DWORD dirlen, LPCWSTR ValueName, + LPBYTE out, DWORD outlen, LPDWORD needed, BOOL unicode) +{ + WCHAR filename[MAX_PATH]; + DWORD size; + DWORD type; + LONG ret; + LPWSTR buffer = filename; + LPWSTR ptr; + + *needed = 0; + size = sizeof(filename); + buffer[0] = '\0'; + ret = RegQueryValueExW(hkey, ValueName, NULL, &type, (LPBYTE) buffer, &size); + if (ret == ERROR_MORE_DATA) { + TRACE("need dynamic buffer: %u\n", size); + buffer = HeapAlloc(GetProcessHeap(), 0, size); + if (!buffer) { + /* No Memory is bad */ + return FALSE; + } + buffer[0] = '\0'; + ret = RegQueryValueExW(hkey, ValueName, NULL, &type, (LPBYTE) buffer, &size); + } + + if ((ret != ERROR_SUCCESS) || (!buffer[0])) { + if (buffer != filename) HeapFree(GetProcessHeap(), 0, buffer); + return FALSE; + } + + ptr = buffer; + while (ptr) { + /* do we have a full path ? */ + ret = (((buffer[0] == '\\') && (buffer[1] == '\\')) || + (buffer[0] && (buffer[1] == ':') && (buffer[2] == '\\')) ); + + if (!ret) { + /* we must build the full Path */ + *needed += dirlen; + if ((out) && (outlen > dirlen)) { + if (unicode) { + lstrcpyW((LPWSTR)out, driverdir); + } + else + { + WideCharToMultiByte(CP_ACP, 0, driverdir, -1, (LPSTR)out, outlen, NULL, NULL); + } + out += dirlen; + outlen -= dirlen; + } + else + out = NULL; + } + + /* write the filename */ + if (unicode) { + size = (lstrlenW(ptr) + 1) * sizeof(WCHAR); + if ((out) && (outlen >= size)) { + lstrcpyW((LPWSTR)out, ptr); + out += size; + outlen -= size; + } + else + out = NULL; + } + else + { + size = WideCharToMultiByte(CP_ACP, 0, ptr, -1, NULL, 0, NULL, NULL); + if ((out) && (outlen >= size)) { + WideCharToMultiByte(CP_ACP, 0, ptr, -1, (LPSTR)out, outlen, NULL, NULL); + out += size; + outlen -= size; + } + else + out = NULL; + } + *needed += size; + ptr += lstrlenW(ptr)+1; + if ((type != REG_MULTI_SZ) || (!ptr[0])) ptr = NULL; + } + + if (buffer != filename) HeapFree(GetProcessHeap(), 0, buffer); + + /* write the multisz-termination */ + if (type == REG_MULTI_SZ) { + size = (unicode) ? sizeof(WCHAR) : 1; + + *needed += size; + if (out && (outlen >= size)) { + memset (out, 0, size); + } + } + return TRUE; +} + /***************************************************************************** * WINSPOOL_GetStringFromReg * @@ -4252,6 +4365,8 @@ static BOOL WINSPOOL_GetDriverInfoFromReg( { DWORD size, tmp; HKEY hkeyDriver; + WCHAR driverdir[MAX_PATH]; + DWORD dirlen; LPBYTE strPtr = pDriverStrings; LPDRIVER_INFO_8W di = (LPDRIVER_INFO_8W) ptr; @@ -4259,6 +4374,8 @@ static BOOL WINSPOOL_GetDriverInfoFromReg( debugstr_w(DriverName), env, Level, di, pDriverStrings, cbBuf, unicode); + if (di) ZeroMemory(di, di_sizeof[Level]); + if (unicode) { *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR); if (*pcbNeeded <= cbBuf) @@ -4284,6 +4401,19 @@ static BOOL WINSPOOL_GetDriverInfoFromReg( strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; } + /* Reserve Space for the largest subdir and a Backslash*/ + size = sizeof(driverdir) - sizeof(Version3_SubdirW) - sizeof(WCHAR); + if (!GetPrinterDriverDirectoryW(NULL, (LPWSTR) env->envname, 1, (LPBYTE) driverdir, size, &size)) { + /* Should never Fail */ + return FALSE; + } + lstrcatW(driverdir, env->versionsubdir); + lstrcatW(driverdir, backslashW); + + /* dirlen must not include the terminating zero */ + dirlen = (unicode) ? lstrlenW(driverdir) * sizeof(WCHAR) : + WideCharToMultiByte(CP_ACP, 0, driverdir, -1, NULL, 0, NULL, NULL) -1; + if (!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) { ERR("Can't find driver %s in registry\n", debugstr_w(DriverName)); SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */ @@ -4309,90 +4439,162 @@ static BOOL WINSPOOL_GetDriverInfoFromReg( strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; } - - if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size, - unicode)) { + /* .pDriverPath is the Graphics rendering engine. + The full Path is required to avoid a crash in some apps */ + if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, DriverW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; - if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp, - unicode); - if(ptr) - ((PDRIVER_INFO_2W) ptr)->pDriverPath = (LPWSTR)strPtr; + if (*pcbNeeded <= cbBuf) + get_filename_from_reg(hkeyDriver, driverdir, dirlen, DriverW, strPtr, size, &tmp, unicode); + + if (di) di->pDriverPath = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; } - if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size, - unicode)) { + /* .pDataFile: For postscript-drivers, this is the ppd-file */ + if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Data_FileW, strPtr, 0, &size, unicode)) { + *pcbNeeded += size; + if (*pcbNeeded <= cbBuf) + get_filename_from_reg(hkeyDriver, driverdir, dirlen, Data_FileW, strPtr, size, &size, unicode); + + if (di) di->pDataFile = (LPWSTR)strPtr; + strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; + } + + /* .pConfigFile is the Driver user Interface */ + if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Configuration_FileW, strPtr, 0, &size, unicode)) { + *pcbNeeded += size; + if (*pcbNeeded <= cbBuf) + get_filename_from_reg(hkeyDriver, driverdir, dirlen, Configuration_FileW, strPtr, size, &size, unicode); + + if (di) di->pConfigFile = (LPWSTR)strPtr; + strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; + } + + if (Level == 2 ) { + RegCloseKey(hkeyDriver); + TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); + return TRUE; + } + + if (Level == 5 ) { + RegCloseKey(hkeyDriver); + FIXME("level 5: incomplete\n"); + return TRUE; + } + + /* .pHelpFile */ + if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Help_FileW, strPtr, 0, &size, unicode)) { + *pcbNeeded += size; + if (*pcbNeeded <= cbBuf) + get_filename_from_reg(hkeyDriver, driverdir, dirlen, Help_FileW, strPtr, size, &size, unicode); + + if (di) di->pHelpFile = (LPWSTR)strPtr; + strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; + } + + /* .pDependentFiles */ + if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Dependent_FilesW, strPtr, 0, &size, unicode)) { + *pcbNeeded += size; + if (*pcbNeeded <= cbBuf) + get_filename_from_reg(hkeyDriver, driverdir, dirlen, Dependent_FilesW, strPtr, size, &size, unicode); + + if (di) di->pDependentFiles = (LPWSTR)strPtr; + strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; + } + + /* .pMonitorName is the optional Language Monitor */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size, unicode)) { + *pcbNeeded += size; + if (*pcbNeeded <= cbBuf) + WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, size, &size, unicode); + + if (di) di->pMonitorName = (LPWSTR)strPtr; + strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; + } + + /* .pDefaultDataType */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size, - &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_2W) ptr)->pDataFile = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, size, &size, unicode); + + if (di) di->pDefaultDataType = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } - if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr, - 0, &size, unicode)) { + if (Level == 3 ) { + RegCloseKey(hkeyDriver); + TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); + return TRUE; + } + + /* .pszzPreviousNames */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, Previous_NamesW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr, - size, &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_2W) ptr)->pConfigFile = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, Previous_NamesW, strPtr, size, &size, unicode); + + if (di) di->pszzPreviousNames = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } - if(Level == 2 ) { + if (Level == 4 ) { RegCloseKey(hkeyDriver); TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); return TRUE; } - if (Level != 5 && WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size, - unicode)) { + /* support is missing, but not important enough for a FIXME */ + TRACE("%s: DriverDate + DriverVersion not supported\n", debugstr_w(DriverName)); + + /* .pszMfgName */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, ManufacturerW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, - size, &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, ManufacturerW, strPtr, size, &size, unicode); + + if (di) di->pszMfgName = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } - if (Level != 5 && WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0, - &size, unicode)) { + /* .pszOEMUrl */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, OEM_UrlW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, - size, &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, OEM_UrlW, strPtr, size, &size, unicode); + + if (di) di->pszOEMUrl = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } - if (Level != 5 && WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size, - unicode)) { + /* .pszHardwareID */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, HardwareIDW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, - size, &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, HardwareIDW, strPtr, size, &size, unicode); + + if (di) di->pszHardwareID = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } - if (Level != 5 && WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size, - unicode)) { + /* .pszProvider */ + if (WINSPOOL_GetStringFromReg(hkeyDriver, ProviderW, strPtr, 0, &size, unicode)) { *pcbNeeded += size; if(*pcbNeeded <= cbBuf) - WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, - size, &tmp, unicode); - if(ptr) - ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr; + WINSPOOL_GetStringFromReg(hkeyDriver, ProviderW, strPtr, size, &size, unicode); + + if (di) di->pszProvider = (LPWSTR)strPtr; strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; } + if (Level == 6 ) { + RegCloseKey(hkeyDriver); + return TRUE; + } + + /* support is missing, but not important enough for a FIXME */ + TRACE("level 8: incomplete\n"); + TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); RegCloseKey(hkeyDriver); return TRUE; @@ -4416,14 +4618,13 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPCWSTR pEnvironment, TRACE("(%p,%s,%d,%p,%d,%p)\n",hPrinter,debugstr_w(pEnvironment), Level,pDriverInfo,cbBuf, pcbNeeded); - ZeroMemory(pDriverInfo, cbBuf); if (!(name = get_opened_printer_name(hPrinter))) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - if(Level < 1 || Level > 6) { + if (Level < 1 || Level == 7 || Level > 8) { SetLastError(ERROR_INVALID_LEVEL); return FALSE; } @@ -4460,36 +4661,12 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPCWSTR pEnvironment, return FALSE; } - switch(Level) { - case 1: - size = sizeof(DRIVER_INFO_1W); - break; - case 2: - size = sizeof(DRIVER_INFO_2W); - break; - case 3: - size = sizeof(DRIVER_INFO_3W); - break; - case 4: - size = sizeof(DRIVER_INFO_4W); - break; - case 5: - size = sizeof(DRIVER_INFO_5W); - break; - case 6: - size = sizeof(DRIVER_INFO_6W); - break; - default: - ERR("Invalid level\n"); - return FALSE; - } - - if(size <= cbBuf) + size = di_sizeof[Level]; + if ((size <= cbBuf) && pDriverInfo) ptr = pDriverInfo + size; if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName, - env, Level, pDriverInfo, - (cbBuf < size) ? NULL : ptr, + env, Level, pDriverInfo, ptr, (cbBuf < size) ? 0 : cbBuf - size, &needed, unicode)) { RegCloseKey(hkeyDrivers); @@ -4920,8 +5097,7 @@ static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment, if (!env) return FALSE; /* SetLastError() is in validate_envW */ /* check input parameter */ - if((Level < 1) || (Level > 3)) { - ERR("unsupported level %d\n", Level); + if ((Level < 1) || (Level == 7) || (Level > 8)) { SetLastError(ERROR_INVALID_LEVEL); return FALSE; } @@ -4949,17 +5125,7 @@ static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment, /* get size of single struct * unicode and ascii structure have the same size */ - switch (Level) { - case 1: - size = sizeof(DRIVER_INFO_1A); - break; - case 2: - size = sizeof(DRIVER_INFO_2A); - break; - case 3: - size = sizeof(DRIVER_INFO_3A); - break; - } + size = di_sizeof[Level]; /* calculate required buffer size */ *pcbNeeded = size * number; diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index 816f32d7404..eabdbfbce34 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -32,11 +32,13 @@ GpStatus WINGDIPAPI GdipCreatePen1(ARGB,REAL,GpUnit,GpPen**); GpStatus WINGDIPAPI GdipDeletePen(GpPen*); GpStatus WINGDIPAPI GdipGetPenBrushFill(GpPen*,GpBrush**); GpStatus WINGDIPAPI GdipGetPenColor(GpPen*,ARGB*); +GpStatus WINGDIPAPI GdipGetPenDashArray(GpPen*,REAL*,INT); GpStatus WINGDIPAPI GdipGetPenDashStyle(GpPen*,GpDashStyle*); GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen*,GpBrush*); GpStatus WINGDIPAPI GdipSetPenColor(GpPen*,ARGB); GpStatus WINGDIPAPI GdipSetPenCustomEndCap(GpPen*,GpCustomLineCap*); GpStatus WINGDIPAPI GdipSetPenCustomStartCap(GpPen*,GpCustomLineCap*); +GpStatus WINGDIPAPI GdipSetPenDashArray(GpPen*,GDIPCONST REAL*,INT); GpStatus WINGDIPAPI GdipSetPenDashStyle(GpPen*,GpDashStyle); GpStatus WINGDIPAPI GdipSetPenEndCap(GpPen*,GpLineCap); GpStatus WINGDIPAPI GdipSetPenLineCap197819(GpPen*,GpLineCap,GpLineCap,GpDashCap); @@ -89,6 +91,7 @@ GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill*,ARGB); GpStatus WINGDIPAPI GdipAddPathArc(GpPath*,REAL,REAL,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath*,GDIPCONST GpPointF*,INT); +GpStatus WINGDIPAPI GdipAddPathEllipse(GpPath*,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipAddPathLine2(GpPath*,GDIPCONST GpPointF*,INT); GpStatus WINGDIPAPI GdipAddPathPath(GpPath*,GDIPCONST GpPath*,BOOL); GpStatus WINGDIPAPI GdipClosePathFigure(GpPath*); diff --git a/include/winternl.h b/include/winternl.h index bd9508f08ef..d1764cdd6a4 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2081,6 +2081,7 @@ LONGLONG WINAPI RtlExtendedMagicDivide(LONGLONG,LONGLONG,INT); LONGLONG WINAPI RtlExtendedIntegerMultiply(LONGLONG,INT); LONGLONG WINAPI RtlExtendedLargeIntegerDivide(LONGLONG,INT,INT *); +NTSTATUS WINAPI RtlFindActivationContextSectionString(ULONG,const GUID*,ULONG,const UNICODE_STRING*,PVOID); NTSTATUS WINAPI RtlFindCharInUnicodeString(int,const UNICODE_STRING*,const UNICODE_STRING*,USHORT*); ULONG WINAPI RtlFindClearBits(PCRTL_BITMAP,ULONG,ULONG); ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP,ULONG,ULONG); @@ -2195,10 +2196,12 @@ BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRI NTSTATUS WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,ULONG*,ULONG*,WCHAR*,ULONG*); NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR,PUNICODE_STRING,PUNICODE_STRING); NTSTATUS WINAPI RtlQueryInformationAcl(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS); +NTSTATUS WINAPI RtlQueryInformationActivationContext(ULONG,HANDLE,PVOID,ULONG,PVOID,SIZE_T,SIZE_T*); NTSTATUS WINAPI RtlQueryProcessDebugInformation(ULONG,ULONG,PDEBUG_BUFFER); NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID); NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION*); NTSTATUS WINAPI RtlQueueWorkItem(PRTL_WORK_ITEM_ROUTINE,PVOID,ULONG); + void WINAPI RtlRaiseException(PEXCEPTION_RECORD); void WINAPI RtlRaiseStatus(NTSTATUS); ULONG WINAPI RtlRandom(PULONG); @@ -2357,6 +2360,7 @@ typedef struct _LDR_MODULE HANDLE SectionHandle; ULONG CheckSum; ULONG TimeDateStamp; + HANDLE ActivationContext; } LDR_MODULE, *PLDR_MODULE; /* those defines are (some of the) regular LDR_MODULE.Flags values */ diff --git a/libs/wine/loader.c b/libs/wine/loader.c index a86da98b921..c7fcecec2b4 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -182,13 +182,11 @@ static char *next_dll_path( struct dll_path_context *context ) case 1: /* try dlls dir with subdir prefix */ if (namelen > 4 && !memcmp( context->name + namelen - 4, ".dll", 4 )) namelen -= 4; path = prepend( path, context->name, namelen ); - /* fall through */ - case 2: /* try dlls dir without prefix */ path = prepend( path, "/dlls", sizeof("/dlls") - 1 ); path = prepend( path, build_dir, strlen(build_dir) ); return path; default: - index -= 3; + index -= 2; if (index < nb_dll_paths) return prepend( context->name, dll_paths[index], strlen( dll_paths[index] )); break; @@ -204,7 +202,7 @@ static char *first_dll_path( const char *name, const char *ext, struct dll_path_ int namelen = strlen( name ); context->buffer = malloc( dll_path_maxlen + 2 * namelen + strlen(ext) + 3 ); - context->index = build_dir ? 0 : 3; /* if no build dir skip all the build dir magic cases */ + context->index = build_dir ? 0 : 2; /* if no build dir skip all the build dir magic cases */ context->name = context->buffer + dll_path_maxlen + namelen + 1; context->namelen = namelen + 1; @@ -655,7 +653,7 @@ void wine_init( int argc, char *argv[], char *error, int error_size ) if ((ntdll = wine_dlopen( path, RTLD_NOW, error, error_size ))) { /* if we didn't use the default dll dir, remove it from the search path */ - if (default_dlldir[0] && context.index < nb_dll_paths) nb_dll_paths--; + if (default_dlldir[0] && context.index < nb_dll_paths + 2) nb_dll_paths--; break; } } diff --git a/programs/winefile/winefile.c b/programs/winefile/winefile.c index f26b75b73d1..0574c3703cd 100644 --- a/programs/winefile/winefile.c +++ b/programs/winefile/winefile.c @@ -187,7 +187,7 @@ static int last_split; /* some common string constants */ static const TCHAR sEmpty[] = {'\0'}; -static const TCHAR sSpace[] = {' ', '\0'}; +static const WCHAR sSpace[] = {' ', '\0'}; static const TCHAR sNumFmt[] = {'%','d','\0'}; static const TCHAR sQMarks[] = {'?','?','?','\0'}; @@ -269,6 +269,59 @@ static inline INT set_check(HWND hwnd, INT id, BOOL on) return SendMessageW(GetDlgItem(hwnd, id), BM_SETCHECK, on?BST_CHECKED:BST_UNCHECKED, 0); } +static inline void choose_font(HWND hwnd) +{ + WCHAR dlg_name[BUFFER_LEN], dlg_info[BUFFER_LEN]; + CHOOSEFONTW chFont; + LOGFONTW lFont; + + HDC hdc = GetDC(hwnd); + chFont.lStructSize = sizeof(CHOOSEFONT); + chFont.hwndOwner = hwnd; + chFont.hDC = NULL; + chFont.lpLogFont = &lFont; + chFont.Flags = CF_SCREENFONTS | CF_FORCEFONTEXIST | CF_LIMITSIZE | CF_NOSCRIPTSEL; + chFont.rgbColors = RGB(0,0,0); + chFont.lCustData = 0; + chFont.lpfnHook = NULL; + chFont.lpTemplateName = NULL; + chFont.hInstance = Globals.hInstance; + chFont.lpszStyle = NULL; + chFont.nFontType = SIMULATED_FONTTYPE; + chFont.nSizeMin = 0; + chFont.nSizeMax = 24; + + if (ChooseFontW(&chFont)) { + HWND childWnd; + HFONT hFontOld; + + DeleteObject(Globals.hfont); + Globals.hfont = CreateFontIndirectW(&lFont); + hFontOld = SelectObject(hdc, Globals.hfont); + GetTextExtentPoint32W(hdc, sSpace, 1, &Globals.spaceSize); + + /* change font in all open child windows */ + for(childWnd=GetWindow(Globals.hmdiclient,GW_CHILD); childWnd; childWnd=GetNextWindow(childWnd,GW_HWNDNEXT)) { + ChildWnd* child = (ChildWnd*) GetWindowLongPtrW(childWnd, GWLP_USERDATA); + SendMessageW(child->left.hwnd, WM_SETFONT, (WPARAM)Globals.hfont, TRUE); + SendMessageW(child->right.hwnd, WM_SETFONT, (WPARAM)Globals.hfont, TRUE); + SendMessageW(child->left.hwnd, LB_SETITEMHEIGHT, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); + SendMessageW(child->right.hwnd, LB_SETITEMHEIGHT, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); + InvalidateRect(child->left.hwnd, NULL, TRUE); + InvalidateRect(child->right.hwnd, NULL, TRUE); + } + + SelectObject(hdc, hFontOld); + } + else if (CommDlgExtendedError()) { + LoadStringW(Globals.hInstance, IDS_FONT_SEL_DLG_NAME, dlg_name, BUFFER_LEN); + LoadStringW(Globals.hInstance, IDS_FONT_SEL_ERROR, dlg_info, BUFFER_LEN); + MessageBoxW(hwnd, dlg_info, dlg_name, MB_OK); + } + + ReleaseDC(hwnd, hdc); +} + #ifdef __WINE__ #ifdef UNICODE @@ -2328,58 +2381,9 @@ static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM SendMessage(Globals.hmdiclient, WM_MDIICONARRANGE, 0, 0); break; - case ID_SELECT_FONT: { - TCHAR dlg_name[BUFFER_LEN], dlg_info[BUFFER_LEN]; - CHOOSEFONT chFont; - LOGFONT lFont; - - HDC hdc = GetDC(hwnd); - chFont.lStructSize = sizeof(CHOOSEFONT); - chFont.hwndOwner = hwnd; - chFont.hDC = NULL; - chFont.lpLogFont = &lFont; - chFont.Flags = CF_SCREENFONTS | CF_FORCEFONTEXIST | CF_LIMITSIZE | CF_NOSCRIPTSEL; - chFont.rgbColors = RGB(0,0,0); - chFont.lCustData = 0; - chFont.lpfnHook = NULL; - chFont.lpTemplateName = NULL; - chFont.hInstance = Globals.hInstance; - chFont.lpszStyle = NULL; - chFont.nFontType = SIMULATED_FONTTYPE; - chFont.nSizeMin = 0; - chFont.nSizeMax = 24; - - if (ChooseFont(&chFont)) { - HWND childWnd; - HFONT hFontOld; - - DeleteObject(Globals.hfont); - Globals.hfont = CreateFontIndirect(&lFont); - hFontOld = SelectObject(hdc, Globals.hfont); - GetTextExtentPoint32(hdc, sSpace, 1, &Globals.spaceSize); - - /* change font in all open child windows */ - for(childWnd=GetWindow(Globals.hmdiclient,GW_CHILD); childWnd; childWnd=GetNextWindow(childWnd,GW_HWNDNEXT)) { - ChildWnd* child = (ChildWnd*) GetWindowLongPtr(childWnd, GWLP_USERDATA); - SendMessage(child->left.hwnd, WM_SETFONT, (WPARAM)Globals.hfont, TRUE); - SendMessage(child->right.hwnd, WM_SETFONT, (WPARAM)Globals.hfont, TRUE); - SendMessage(child->left.hwnd, LB_SETITEMHEIGHT, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); - SendMessage(child->right.hwnd, LB_SETITEMHEIGHT, 1, max(Globals.spaceSize.cy,IMAGE_HEIGHT+3)); - InvalidateRect(child->left.hwnd, NULL, TRUE); - InvalidateRect(child->right.hwnd, NULL, TRUE); - } - - SelectObject(hdc, hFontOld); - } - else if (CommDlgExtendedError()) { - LoadString(Globals.hInstance, IDS_FONT_SEL_DLG_NAME, dlg_name, BUFFER_LEN); - LoadString(Globals.hInstance, IDS_FONT_SEL_ERROR, dlg_info, BUFFER_LEN); - MessageBox(hwnd, dlg_info, dlg_name, MB_OK); - } - - ReleaseDC(hwnd, hdc); - break; - } + case ID_SELECT_FONT: + choose_font(hwnd); + break; case ID_VIEW_TOOL_BAR: toggle_child(hwnd, cmd, Globals.htoolbar); @@ -2642,19 +2646,18 @@ static HWND create_header(HWND parent, Pane* pane, int id) static void init_output(HWND hwnd) { - static const TCHAR s1000[] = {'1','0','0','0','\0'}; - - TCHAR b[16]; + static const WCHAR s1000[] = {'1','0','0','0','\0'}; + WCHAR b[16]; HFONT old_font; HDC hdc = GetDC(hwnd); - if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, s1000, 0, b, 16) > 4) + if (GetNumberFormatW(LOCALE_USER_DEFAULT, 0, s1000, 0, b, 16) > 4) Globals.num_sep = b[1]; else Globals.num_sep = '.'; old_font = SelectObject(hdc, Globals.hfont); - GetTextExtentPoint32(hdc, sSpace, 1, &Globals.spaceSize); + GetTextExtentPoint32W(hdc, sSpace, 1, &Globals.spaceSize); SelectObject(hdc, old_font); ReleaseDC(hwnd, hdc); } -- 2.11.4.GIT