diff -urN wine-20050211/ANNOUNCE wine-20050310/ANNOUNCE --- wine-20050211/ANNOUNCE 2005-02-11 14:34:17.000000000 +0100 +++ wine-20050310/ANNOUNCE 2005-03-10 21:10:32.000000000 +0100 @@ -1,12 +1,14 @@ -This is release 20050211 of Wine, a free implementation of Windows on +This is release 20050310 of Wine, a free implementation of Windows on Unix. This is still a developers only release. There are many bugs and unimplemented features. Most applications still do not work correctly. -WHAT'S NEW with Wine-20050211: (see ChangeLog for details) - - Still more work on the MSI dll. - - More OLE work, including a builtin stdole32.tlb. - - Fixed inter-process window resize and repaint. +WHAT'S NEW with Wine-20050310: (see ChangeLog for details) + - Initial implementation of a true Richedit control. + - Shell extension for browsing Unix directories. + - More MSI work. + - PBuffer support in OpenGL. + - Window painting regressions should be fixed. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -15,8 +17,8 @@ the release is available at the ftp sites. The sources will be available from the following locations: - http://www.ibiblio.org/pub/Linux/ALPHA/wine/development/Wine-20050211.tar.gz - http://prdownloads.sourceforge.net/wine/Wine-20050211.tar.gz + http://www.ibiblio.org/pub/Linux/ALPHA/wine/development/Wine-20050310.tar.gz + http://prdownloads.sourceforge.net/wine/Wine-20050310.tar.gz It should also be available from any other site that mirrors ibiblio.org. These locations also hold pre-built documentation packages in various diff -urN wine-20050211/ChangeLog wine-20050310/ChangeLog --- wine-20050211/ChangeLog 2005-02-11 14:34:17.000000000 +0100 +++ wine-20050310/ChangeLog 2005-03-10 21:10:32.000000000 +0100 @@ -1,4 +1,2028 @@ ---------------------------------------------------------------- +2005-03-10 Alexandre Julliard + + * dlls/shdocvw/shdocvw_main.c: Juan Lang + Fix a crash if the Mozilla ActiveX control doesn't implement + DllCanUnloadNow. + + * dlls/ole32/compobj.c: Juan Lang + Fix the calling convention of DllCanUnloadNow. + + * dlls/msi/appsearch.c: Juan Lang + Fix a regression in AppSearch. + + * dlls/msi/msipriv.h, dlls/msi/registry.c: + Juan Lang + Implement MsiEnumRelatedProducts. + + * dlls/user/message.c, server/window.c: + Clear the internal paint flag in the server before returning a + WM_PAINT message to avoid an extra server round-trip. + + * programs/winetest/main.c: Dmitry Timoshkov + Implement a test for the desktop visibility based on the MSDN article + pointed out by Robert Shearman. + + * dlls/user/tests/listbox.c, windows/winproc.c: + Marcus Meissner + Use 512 byte buffer for buffer of LB_GETTEXT and CB_GETLBTEXT. + Added testcase with > 256 byte string in listbox. + + * tools/wineshelllink: Brouard Nicolas + Fix menu backslash escaping. + + * dlls/kernel/tests/environ.c: + Uwe Bonnes + Test for %Systemroot%. + + * dlls/user/scroll.c, dlls/user/user32.spec: + Phil Krylov + Implemented GetScrollBarInfo() function and SBM_GETSCROLLBARINFO + message. + + * dlls/user/Makefile.in, dlls/user/message.c, dlls/user/message.h, + windows/message.c: + Merge the rest of the messaging code into dlls/user/message.c and get + rid of windows/message.c. + + * programs/uninstaller/En.rc, programs/uninstaller/main.c, + programs/uninstaller/main.h, programs/uninstaller/resource.h, + programs/uninstaller/rsrc.rc: + Jonathan Ernst + Use a dialog instead of a normal window. + + * dlls/user/message.c, include/wine/server_protocol.h, + server/protocol.def, server/queue.c, server/trace.c: + Properly cope with get_message being called recursively while + processing a hardware message. + + * dlls/x11drv/wintab.c: Raphael Junqueira + - XListInputDevices spec say that device list should be freed using + XFreeDeviceList + - better robustness on X11DRV_AttachEventQueueToTablet + + * dlls/msvcrt/scanf.h, dlls/msvcrt/tests/scanf.c: + C. Scott Ananian + Allow scanf to continue parsing format string after a '%n'. + + * windows/message.c: + Take message filtering into account when updating the static data for + double click support. + + * dlls/gdi/gdiobj.c: + Allocate fonts and regions from the large heap too. + + * server/registry.c: Peter Berg Larsen + Tmp was not freed in case of errors in save_branch(). + + * dlls/richedit/Makefile.in, dlls/richedit/ansi_gen.h, + dlls/richedit/ansi_sym.h, dlls/richedit/reader.c, + dlls/richedit/riched32.h, dlls/richedit/richedit.c, + dlls/richedit/rtf.h, dlls/richedit/rtf2text.h, + dlls/richedit/stdcharnames.h, dlls/richedit/text-writer.c, + dlls/richedit/text_map.h: + Mike McCormack + Forward the RichEdit 1.0 control to the RichEdit 2.0 control. + + * dlls/msi/action.c, dlls/msi/format.c, dlls/msi/msi.c, + dlls/msi/msiquery.c, dlls/msi/package.c, dlls/msi/preview.c, + dlls/msi/record.c, dlls/msi/suminfo.c: + Juan Lang + - make sure msihandle2msiinfo is correctly matched with msiobj_release + - don't do redundant NULL checks + + * include/propidl.idl: Juan Lang + Add some missing declarations. + + * dlls/wininet/http.c: Robert Shearman + - Fully delete custom headers on connection opening. + - Free unneeded memory on clearing of standard headers. + - Fix index sanity test in delete function. + + * dlls/advapi32/service.c: Alexander Yaworsky + Correct incorrect use of arguments to QueryServiceConfigA. Spotted by + Troy Rollo. + + * dlls/opengl32/wgl.c, dlls/opengl32/wgl_ext.c, + dlls/opengl32/wgl_ext.h: + Raphael Junqueira + - implements WGL_ARB_render_texture support (no more stubs) + - pass glXGetProcAddressARB ptr to initialise function + + * dlls/ddraw/dsurface/dib.c: Paul Vriens + Check always if destination surface is locked. + +2005-03-09 Alexandre Julliard + + * dlls/x11drv/event.c, dlls/x11drv/x11drv.h: + Added WM_X11DRV_DELETE_WINDOW message to handle close requests so that + we can send the WM_SYSCOMMAND with SendMessage instead of PostMessage. + Added missing NONAMELESSUNION define. + + * dlls/riched20/caret.c, dlls/riched20/editor.c, + dlls/riched20/editor.h, dlls/riched20/editstr.h, + dlls/riched20/paint.c, dlls/riched20/run.c, dlls/riched20/wrap.c: + Krzysztof Foltman + - Optimized repaint of the area below the text. + - ME_JoinRuns didn't mark the paragraph for rewrapping, fixed. + - Removed PostQuitMessage(0) from WM_DESTROY handler (duh!). + - Use of EM_GETOLEINTERFACE is reported with FIXME instead of TRACE + (any app using this message is likely to encounter major problems). + + * dlls/mscms/mscms.spec, dlls/mscms/mscms_main.c, dlls/mscms/profile.c, + dlls/mscms/stub.c: + Hans Leidekker + - Implementation stubs for GenerateCopyFilePaths, + SpoolerCopyFileEvent. + - Call DisableThreadLibraryCalls on process attach. + - Document more functions. + + * dlls/ddraw/dsurface/dib.c: Paul Vriens + Check for NULL before touching src. + + * dlls/user/user_main.c, dlls/user/user_private.h, dlls/x11drv/event.c, + dlls/x11drv/keyboard.c, dlls/x11drv/mouse.c, dlls/x11drv/x11drv.h, + dlls/x11drv/x11drv.spec, dlls/x11drv/x11drv_main.c, include/win.h, + windows/input.c: + Moved SendInput and related functions to the USER driver to avoid a + number of dll separation hacks. + + * windows/win.c: Remove a trace that's causing too much output. + + * programs/winecfg/Makefile.in, programs/winecfg/driveui.c, + programs/winecfg/main.c: + Michael Jung + Implemented 'Browse' functionality for the drive mapping property + sheet. + + * dlls/shell32/Makefile.in, dlls/shell32/regsvr.c, + dlls/shell32/shell32_main.h, dlls/shell32/shellole.c, + dlls/shell32/shfldr_unixfs.c: + Michael Jung + Beginning of a shell namespace extension to browse the unix + filesystem. + + * windows/defwnd.c: Krzysztof Foltman + WM_CANCELMODE resets menu flag in the default window procedure. + + * dlls/riched20/editor.c: Phil Krylov + Changed buffer size for EM_STREAMIN message to 4096, as it's what M$ + uses. + + * include/richedit.h: Robert Shearman + Remove duplicate message defines in header. + + * dlls/user/menu.c, include/winuser.h: + Maxime Bellengé + Implemented MIIM_BITMAP state. + Handle MNS_CHECKORBMP style. + + * dlls/user/sysparams.c, windows/input.c: + Make the SwapMouseButton function and the SPI_SETMOUSEBUTTONSWAP + parameter work on the same flag. + + * server/window.c: + Don't check children of minimized windows in get_update_region. + + * dlls/riched20/caret.c, dlls/riched20/editor.c, + dlls/riched20/editor.h, dlls/riched20/editstr.h, + dlls/riched20/list.c, dlls/riched20/paint.c, dlls/riched20/para.c, + dlls/riched20/run.c, dlls/riched20/wrap.c: + Krzysztof Foltman + The meaning of the rewrap flag got inverted (MEPF_REWRAP instead of + MEPF_WRAPPED) for consistency. + Major code cleanups in rewrap/repaint code, leading to "smarter" + behaviour wrt repainting selections. + + * dlls/dplayx/dplobby.c: Raphael Junqueira + Avoid ConvertToGlobalHandle calls. + + * dlls/ole32/storage32.c, dlls/ole32/tests/storage32.c: + Mike McCormack + Shared reading of storage files requires STGM_TRANSACTED. + + * dlls/kernel/console.c: Gabriel Buades Rubio + When sending multi-line boxes to console throgh WineConsoleOutputA, + only the first line was being translated into wide-chars. + + * dlls/oleaut32/recinfo.c: Jacek Caban + More implementation of IRecordInfo. + + * windows/spy.c: Robert Shearman + Add message spy support for RichEdit20W control. + +2005-03-08 Alexandre Julliard + + * dlls/user/painting.c: + Process only pending expose events during RDW_UPDATENOW, not all the + other X events. + + * dlls/x11drv/event.c: + Take into account the event mask passed to MsgWaitForMultipleObjectsEx + to allow processing only a subset of the available X events. + + * tools/wrc/parser.y: + Allow specifying extended control styles also in standard dialogs + (reported by Michael Lin). + + * dlls/riched20/caret.c, dlls/riched20/editor.c, + dlls/riched20/editor.h: + Krzysztof Foltman + - specialized handler for SF_TEXT (ANSI or Unicode), simple and fast + - clears control's text on EM_STREAMIN with no SFF_SELECTION + + * dlls/riched20/reader.c: Krzysztof Foltman + - Single quotes are now handled properly (previously they were + inserted as [[']]). + - Better handling of callback function's results. + + * dlls/mscms/lcms_api.h, dlls/mscms/mscms_main.c, dlls/mscms/stub.c, + dlls/mscms/transform.c: + Hans Leidekker + - Implement TranslateBitmapBits. + - Don't pass bogus intent values to lcms. + + * programs/winetest/main.c: Dmitry Timoshkov + Make running tests on a visible desktop a mandatory requirement. + + * dlls/x11drv/window.c: Maxime Bellengé + - Fix unmovable windows if the window style is set to WS_POPUP | + WS_VISIBLE and WS_EX_APPWINDOW. + - Fix metacity displaying decorations where it should not. + + * dlls/dinput/keyboard.c, dlls/user/message.c, + dlls/winmm/mciavi/mciavi.c, windows/queue.c: + Make sure to always pass valid QS_* flags to + MsgWaitForMultipleObjects. + + * Make.rules.in, dlls/Makedll.rules.in, dlls/gdi/Makefile.in, + dlls/kernel/Makefile.in, dlls/shell32/Makefile.in, + dlls/user/Makefile.in, tools/winebuild/main.c, + tools/winebuild/winebuild.man.in, tools/winegcc/winegcc.c: + Dimitrie O. Paun + Add support for .exe's with exported functions. + + * dlls/x11drv/xfont.c: Added support for iso8859-16 charset. + + * dlls/riched20/Makefile.in, dlls/riched20/editor.c, + dlls/riched20/editor.h, dlls/riched20/richole.c, dlls/uuid/uuid.c: + Aric Stewart + Implement EM_GETOLEINTERFACE. + + * dlls/msi/action.c: Ulrich Czekalla + Allocate space for terminating null. + + * dlls/riched20/editor.c, dlls/riched20/editor.h, + dlls/riched20/editstr.h, dlls/riched20/paint.c, dlls/riched20/run.c, + dlls/riched20/style.c, dlls/riched20/wrap.c: + Krzysztof Foltman + Old font management replaced by the cache-based one, which keeps + maximum of 10 HFONTs at once, instead of one per a couple of runs. + + * include/winsock.h: + Fixed WS_FD_CLR and WS_FD_SET macros (spotted by Thomas Kho). + + * dlls/urlmon/urlmon.spec: Francois Gouget + Add a comment explaining why CDLGetLongPathName[AW] and + IsJITInProgress have hardcoded ordinals. + + * dlls/msi/action.c: Ulrich Czekalla + Fix a memory leak. + +2005-03-07 Alexandre Julliard + + * dlls/x11drv/x11drv.h: Added a missing prototype. + + * dlls/x11drv/clipboard.c, dlls/x11drv/event.c, dlls/x11drv/x11drv.h, + dlls/x11drv/x11drv.spec, dlls/x11drv/x11drv_main.c, + include/wine/server_protocol.h, server/clipboard.c, + server/protocol.def: + Ulrich Czekalla + Create a thread-specific selection window to make sure we receive the + selection events in the correct thread. + + * dlls/kernel/ne_module.c, dlls/kernel/process.c, + programs/winevdm/Makefile.in, programs/winevdm/winevdm.c: + Rein Klazes + Support execution of pif files. + + * dlls/user/tests/sysparams.c: Justin Chevrier + Paul Vriens + - Consolidate error message handling. + - Add error checking to all initial SystemParametersInfoA calls in + each parameter test to make sure that if a given parameter isn't + supported or has failed in some other way that we return and don't + continue on with the test. + - SetLastError before calling test_error_msg. + - SPI_{GET,SET}ICONTITLEWRAP is supported on Win98. + + * dlls/oleaut32/Makefile.in, dlls/oleaut32/oleaut.c, + dlls/oleaut32/oleaut32.spec, dlls/oleaut32/recinfo.c: + Jacek Caban + - Implemented GetRecordInfoFromTypeInfo and GetRecordInfoFromGuid. + - Beginnig implementation of IRecordInfo. + + * dlls/user/message.c, dlls/user/user_main.c, dlls/user/user_private.h, + windows/message.c: + Moved TranslateMessage and DispatchMessage to dlls/user/message.c. + Added support for posting internal messages. + Added support for driver-specific internal messages. + + * dlls/user/sysparams.c: + Set SM_DBCSENABLED according to the current locale instead of + hardcoding it to 0 (found by Mike McCormack). + + * dlls/riched20/Makefile.in, dlls/riched20/editor.c, + dlls/riched20/reader.c, dlls/riched20/rtf.h: + Mike McCormack + Port the RTF parser to the richedit 2.0 control. + + * dlls/ole32/compobj_private.h, dlls/ole32/marshal.c: + Robert Shearman + Make each ifproxy have its own channel buffer to fix a bug where a + proxy with multiple interfaces could invoke the wrong stub buffer on + the server. + + * dlls/x11drv/window.c: Dmitry Timoshkov + Avoid unnecessary window locking in X11DRV_DestroyWindow. + + * dlls/user/tests/win.c, windows/input.c: + Dmitry Timoshkov + - Call SetCursorPos for an injected mouse message only if we really + need to move mouse pointer. + - Add a test case for mouse click handling. + + * programs/winedbg/winedbg.c: + Make output line-buffered to avoid messing up log files. + + * dlls/ole32/stg_bigblockfile.c, dlls/ole32/stg_stream.c, + dlls/ole32/storage32.c, dlls/ole32/storage32.h: + Mike McCormack + Fix more incorrect uses of STGM_ enumerations. + + * dlls/dbghelp/dbghelp.c: Eric Pouech + When initializing a live target, ask to load module file names, not + module names (spotted by Robert Reif). + + * dlls/ddraw/ddraw_private.h, dlls/ddraw/dsurface/dib.c, + dlls/ddraw/dsurface/main.c: + Matthew Mastracci + Added surface locking. + + * dlls/user/painting.c: + Retry sending a WM_PAINT in update_now after we sent an erase + message. + + * dlls/shell32/dialogs.c, dlls/shell32/folders.c, + dlls/shell32/shellpath.c, dlls/shell32/shlfolder.c, + dlls/shell32/shlview.c: + Mike McCormack + Use lstrcmpiA in preference to strcasecmp. + + * dlls/riched20/editor.c: + Fixed DLL_PROCESS_DETACH handler to actually unregister the window + classes. + + * tools/winedump/Makefile.in, tools/winedump/debug.c, + tools/winedump/dump.c, tools/winedump/minidump.c, + tools/winedump/pe.c, tools/winedump/pe.h, tools/winedump/winedump.h: + Eric Pouech + Created dump.c as a central point for file dumping (includes header + analysis, utility funcs...). + Added support for dumping minidump files. + + * dlls/dbghelp/dbghelp.spec, dlls/dbghelp/elf_module.c, + dlls/dbghelp/minidump.c, include/dbghelp.h: + Eric Pouech + Added support for minidump (read & write). + + * dlls/atl/atl.spec, dlls/atl/regsvr.c: + Jason Edmeades + Add stub for GetClassObject function. + + * dlls/ddraw/ddraw/user.c: Matthew Mastracci + Add DDCAPS_OVERLAY and DDCAPS_OVERLAYSTRETCH to GetCaps(). + + * dlls/msvcrt/file.c, dlls/msvcrt/msvcrt.h: + Jason Edmeades + Make msvcrt printf use the internal routines which understand %S and + %C. + + * dlls/advapi32/advapi32.spec, dlls/advapi32/security.c: + Jason Edmeades + Add stub for SetSecurityInfo. + + * dlls/riched20/paint.c: Krzysztof Foltman + Added a check for empty scrollbar range. + + * dlls/winmm/wineoss/mixer.c: + Vincent Béron + Make wineoss's mixer know about DST_HEADPHONES, DST_LINE and + DST_VOICEIN. Use proper constants instead of 0 and 1. + + * dlls/ole32/ole32.spec, dlls/ole32/storage32.c: + Juan Lang + Implement StgCreatePropSetStg. + + * programs/winetest/Makefile.in, programs/winetest/main.c: + Dmitry Timoshkov + Another attempt of a test for a visible desktop. + + * windows/msgbox.c: Dmitry Timoshkov + Call ReleaseDC() with correct window handle. + + * dlls/user/message.c: Ulrich Czekalla + Print out error message if we fail to remove message from queue. + +2005-03-05 Alexandre Julliard + + * dlls/riched20/richole.c: Fixed DOS line endings. + + * tools/winegcc/Makefile.in: + Vincent Béron + Create symlinks named wineg++ and winecpp while building winegcc. + + * configure, configure.ac, dlls/Makefile.in, dlls/riched20/.cvsignore, + dlls/riched20/Makefile.in, dlls/riched20/caret.c, + dlls/riched20/context.c, dlls/riched20/editor.c, + dlls/riched20/editor.h, dlls/riched20/editstr.h, + dlls/riched20/list.c, dlls/riched20/paint.c, dlls/riched20/para.c, + dlls/riched20/riched20.spec, dlls/riched20/richole.c, + dlls/riched20/row.c, dlls/riched20/run.c, dlls/riched20/string.c, + dlls/riched20/style.c, dlls/riched20/undo.c, dlls/riched20/wrap.c: + Krzysztof Foltman + Initial implementation of riched20. + + * dlls/dsound/tests/dsound.c: Robert Reif + Don't consider no sound device a failure. + + * server/queue.c: Avoid potential crash when freeing a message queue. + Properly initialize newly allocated messages. + + * windows/spy.c: Robert Shearman + WM_USER messages should be dumped in the format "WM_USER + %d" to make + it easier to see what message it is for unknown classes. + + * tools/widl/header.c, tools/widl/header.h, tools/widl/parser.y: + Jacek Caban + Write uuid of library in header. + + * dlls/dsound/tests/Makefile.in, dlls/dsound/tests/capture.c, + dlls/dsound/tests/ds3d.c, dlls/dsound/tests/ds3d8.c, + dlls/dsound/tests/dsound.c, dlls/dsound/tests/dsound8.c, + dlls/dsound/tests/dsound_test.h, dlls/dsound/tests/propset.c: + Robert Reif + Print dsound.dll version from file versioninfo resource. + + * dlls/ole32/storage32.c, dlls/ole32/tests/storage32.c: + Mike McCormack + Test and fix grfMode handling in StgOpenDocfile. + + * programs/Makeprog.rules.in: + Vincent Béron + APPMODE can now be one of -mwindows or -mconsole. + + * dlls/user/tests/sysparams.c: Paul Vriens + LastError is not set on failure for *MOUSEHOVER* on Win98. + + * dlls/advapi32/tests/security.c: Jakob Eriksson + Account for permissions on Win2k. + + * include/objbase.h: Mike McCormack + Declare the value of STGM_DIRECT_SWMR. + + * dlls/msvcrt/tests/printf.c, dlls/msvcrt/wcs.c: + Mike McCormack + Handle %ls in sprintf. + + * dlls/advapi32/security.c: Troy Rollo + Make GetFileSecurityW return a standard SECURITY_DESCRIPTOR instead of + an uninitialised (and invalid) one. + +2005-03-04 Alexandre Julliard + + * configure, configure.ac, dlls/kernel/sync.c, dlls/ntdll/sync.c, + dlls/winmm/wineoss/audio.c, dlls/winmm/wineoss/dscapture.c, + dlls/winmm/wineoss/dsrender.c, dlls/winmm/wineoss/midi.c, + dlls/winsock/socket.c, include/config.h.in, server/fd.c, + server/file.c, server/named_pipe.c, server/process.c, + server/request.c, server/serial.c, server/signal.c, server/thread.c: + Steven Edwards + Added a check for poll.h. + + * programs/winedbg/memory.c: Avoid a compiler warning. + + * dlls/advapi32/service.c: Troy Rollo + Return an empty string for service dependencies when there are no + dependencies, rather than a NULL pointer, which causes some apps to + SEGV. + + * dlls/msi/dialog.c: Ulrich Czekalla + Add support for radio buttons. + + * dlls/user/tests/sysparams.c: Justin Chevrier + Expand conformance registry entry test to handle registry entries that + differ both in Key and Value from the norm. + Take advantage of expanded registry test to allow + SPI_{GET,SET}SCREENREADER and SPI_{GET,SET}KEYBOARDPREFERENCE to pass + on Win9x. + + * dlls/ole32/rpc.c, dlls/ole32/tests/marshal.c: + Rob Shearman + Mike Hearn + - Add re-entrancy tests to the test suite. + - Run RPCs on a new thread client side so we can pump the message + loop. + + * dlls/oleaut32/Makefile.in, dlls/oleaut32/olepicture.c: + Maxime Bellengé + Implements OleLoadPicturePath. + + * dlls/user/message.c: + Support sending WM_PAINT across processes when it doesn't contain an + HDC. + + * dlls/ole32/storage32.c: Mike McCormack + Implement StgSetTimes. + + * dlls/richedit/richedit.c: Mike McCormack + Don't clear ES_AUTO[HV]SCROLL in the edit control created by + richedit. + + * dlls/advapi32/service.c: Troy Rollo + Correct incorrect use of arguments to QueryServiceConfigW. + + * dlls/msvcrt/tests/printf.c, dlls/msvcrt/wcs.c: + Mike McCormack + Handle the printf %F format modifier. + + * include/richedit.h: Krzysztof Foltman + - added missing CFM_ constants to make RichEdit 2.0 implementation + possible + - added a missing structure PARAFORMAT2 + + * dlls/kernel/profile.c, dlls/kernel/tests/profile.c: + Huw Davies + Fix regression in GetPrivateProfileSection for lines without an '='. + Add test. + + * dlls/rpcrt4/rpc_binding.c: Mike Hearn + Suppress some useless warnings in the RPC runtime, and make a few + TRACEs that were reporting problems into WARNs. + + * dlls/user/tests/sysparams.c: Paul Vriens + Better way of handling non-existent SystemParametersInfoW. + SetLastError if GetLastError is checked after a call. + +2005-03-03 Alexandre Julliard + + * programs/winedbg/dbg.y, programs/winedbg/debugger.h, + programs/winedbg/display.c, programs/winedbg/memory.c, + programs/winedbg/stack.c, programs/winedbg/winedbg.c: + Fixed a few regressions in the handling of segmented addresses. + + * dlls/d3d9/d3d9_private.h, dlls/d3d9/query.c, + dlls/wined3d/Makefile.in, dlls/wined3d/device.c, + dlls/wined3d/drawprim.c, dlls/wined3d/query.c, + dlls/wined3d/stateblock.c, dlls/wined3d/surface.c, + dlls/wined3d/utils.c, dlls/wined3d/wined3d_private.h, + include/d3d9types.h, include/wine/wined3d_interface.h, + include/wine/wined3d_types.h: + Oliver Stieber + Added a stubbed out version of query to d3d9 and wined3d. + Update the d3d9 headers and creates wined3d types where d3d9 and d3d8 + are incompatible. + + * dlls/shell32/classes.c: Huw Davies + Don't prepend '\\' to the subkey name. + + * dlls/comctl32/draglist.c, include/commctrl.h: + Dimitrie O. Paun + Unicodification. Small cleanups. + + * dlls/ntdll/heap.c: + Uwe Bonnes + Dump HeapWalk entries. + + * programs/winetest/main.c: Dmitry Timoshkov + Use IsWindowVisible instead of GetWindowLong(GWL_STYLE) & WS_VISIBLE + as a test for desktop visibility. + + * dlls/winmm/tests/wave.c: Francois Gouget + Warn the user if he is running the test in interactive mode but the + sound is turned off. + +2005-03-02 Alexandre Julliard + + * dlls/comctl32/rebar.c, dlls/comctl32/syslink.c, dlls/gdi/region.c, + dlls/kernel/process.c, dlls/kernel/tests/file.c, dlls/msi/action.c, + dlls/msi/msi.c, dlls/msvcrt/file.c, dlls/ntdll/reg.c, + dlls/ole32/clipboard.c, dlls/oleaut32/typelib.c, + dlls/oleaut32/varformat.c, dlls/richedit/reader.c, + dlls/richedit/richedit.c, dlls/shell32/clipboard.c, + dlls/shell32/shelllink.c, dlls/shell32/shfldr_fs.c, + dlls/user/dde/dde_private.h, dlls/user/tests/sysparams.c, + dlls/winedos/vxd.c, dlls/winmm/wineoss/audio.c, + documentation/architecture.sgml, documentation/getting.sgml, + include/objbase.h, programs/cmdlgtst/cmdlgtst.c, + programs/wcmd/wcmdmain.c, programs/wineboot/wineboot.c, + programs/winedbg/db_disasm.c, programs/winevdm/winevdm.c, + tools/widl/client.c, tools/winebuild/winebuild.man.in, + tools/winedump/pe.c, tools/winedump/symbol.c, tools/wrc/parser.y: + Francois Gouget + Assorted spelling fixes. + + * dlls/d3d9/d3d9_main.c, dlls/d3d9/surface.c, + dlls/wined3d/basetexture.c, dlls/wined3d/cubetexture.c, + dlls/wined3d/device.c, dlls/wined3d/directx.c, + dlls/wined3d/indexbuffer.c, dlls/wined3d/resource.c, + dlls/wined3d/stateblock.c, dlls/wined3d/texture.c, + dlls/wined3d/vertexbuffer.c, dlls/wined3d/vertexdeclaration.c, + dlls/wined3d/volume.c, dlls/wined3d/volumetexture.c, + dlls/wined3d/wined3d_main.c, include/wine/wined3d_interface.h: + Oliver Stieber + Implemented guids for wined3d. + + * dlls/winmm/winealsa/audio.c, dlls/winmm/winearts/audio.c, + dlls/winmm/wineaudioio/audio.c, dlls/winmm/winejack/audio.c, + dlls/winmm/winenas/audio.c: + Francois Gouget + Apply Jeremy White's SMPTE calculation fix to each audio driver. + + * dlls/d3d8/d3d8_private.h, dlls/kernel/local16.c, + dlls/kernel/tests/thread.c, dlls/mscms/mscms_main.c, + dlls/msi/action.c, dlls/ntdll/cdrom.c, dlls/ntdll/file.c, + dlls/ole32/clipboard.c, dlls/quartz/main.c, + dlls/rpcrt4/ndr_marshall.c, dlls/twain/twain.h, dlls/wined3d/utils.c, + dlls/wineps/graphics.c, dlls/winmm/joystick/joystick.c, + dlls/wsock32/socket.c, dlls/x11drv/clipboard.c, include/dmusicc.h, + include/wine/rpcfc.h, programs/rpcss/rpcss_main.c, + programs/taskmgr/perfdata.c, programs/taskmgr/procpage.c, + programs/wineconsole/curses.c, programs/winemine/main.h, + tools/wrc/parser.y: + Avoid spaces before preprocessor directives, that's not portable. + + * Makefile.in, tools/Makefile.in: + wineprefixcreate and related files need to be installed when doing an + install-lib. + + * dlls/winmm/wavemap/wavemap.c: Jeremy White + Aggressively round up to the proper alignment when reporting position + on streams where we are converting up. + + * windows/mdi.c, windows/win.c: + Dmitry Timoshkov + Ask for an MDI child id in all cases. + + * dlls/user/menu.c: Dmitry Timoshkov + DestroyMenu should not destroy system menu popup owner. + + * dlls/d3d9/d3d9_private.h, dlls/d3d9/device.c, dlls/d3d9/surface.c, + dlls/d3d9/vertexdeclaration.c, dlls/wined3d/device.c, + dlls/wined3d/surface.c, dlls/wined3d/vertexshader.c, + dlls/wined3d/wined3d_private.h, include/wine/wined3d_interface.h: + Oliver Stieber + Put all the stubs in wined3d in place, with some functionality copied + across from d3d9. + Make sure all d3d9 device function call their wined3d counterpart (or + perform a function). + + * include/dce.h, windows/dce.c: + Beginnings of inter-process GetDC support. + Use a standard list for the DCE list. + Small cleanups. + + * server/debugger.c, server/process.c, server/process.h: + Convert the process dll list to a standard list. + + * dlls/shell32/shfldr.h, dlls/shell32/shfldr_desktop.c, + dlls/shell32/shfldr_fs.c, dlls/shell32/shfldr_mycomp.c: + Juan Lang + Convert more API calls to Unicode. + + * tools/wine.desktop: Scott Ritchie + Add all known windows executables to MIME type in wine.desktop. + + * dlls/comctl32/rebar.c: Robert Shearman + - Fix one more place where the code assumes row indices are + zero-based. + - Document a known bug in the layout code. + + * dlls/winmm/wineoss/audio.c, dlls/winmm/wineoss/dsrender.c: + Jeremy White + More correctly establish cases where the OSS input buffer should not + be enabled. + + * dlls/quartz/avisplit.c, dlls/quartz/dsoundrender.c, + dlls/quartz/filtergraph.c, dlls/quartz/pin.c, + dlls/quartz/tests/filtergraph.c, dlls/quartz/transform.c, + dlls/quartz/videorenderer.c, dlls/quartz/waveparser.c: + Christian Costa + Handle End Of Stream notifications. + Some AVI Splitter fixes. + + * dlls/rsaenh/tests/rsaenh.c: + Stefan Leichter + Make rsaenh_crosstest.exe loadable on NT 4.0. + + * dlls/kernel/tests/locale.c: Jakob Eriksson + Accept (shorter) date format in Win NT and Win 95. + + * dlls/user/tests/msg.c, dlls/user/tests/win.c, windows/win.c: + Dmitry Timoshkov + Protect SetParent from creating circular window dependencies. + Add a test case. + + * dlls/comctl32/status.c: Dimitrie O. Paun + Fix indentation for consistency with the rest of the file. + + * dlls/kernel/profile.c, dlls/kernel/tests/profile.c: + Rein Klazes + When enumerating keys using Get(Private)ProfileString do not include + lines without an '=' character. Added a test that shows the behavior. + +2005-03-01 Alexandre Julliard + + * dlls/x11drv/event.c, dlls/x11drv/x11drv.h, dlls/x11drv/xdnd.c: + Use a dispatch table to handle X client messages. + + * server/fd.c, server/object.c, server/object.h, server/queue.c, + server/thread.c: + Convert the object wait queue to a standard list. + + * programs/regedit/Cs.rc, programs/regedit/De.rc, + programs/regedit/En.rc, programs/regedit/Es.rc, + programs/regedit/Fr.rc, programs/regedit/It.rc, + programs/regedit/Ja.rc, programs/regedit/Nl.rc, + programs/regedit/Pl.rc, programs/regedit/Pt.rc, + programs/regedit/Ru.rc, programs/regedit/Si.rc, + programs/regedit/resource.h: + Paul Vriens + Change Favourite(s) into Favorite(s). + Change variables containing FAVOURITE into FAVORITE. + + * dlls/user/tests/sysparams.c: Justin Chevrier + - Created SPI_{GET,SET}KEYBOARDPREF and SPI_{GET,SET}SCREENREADER unit + tests. + - Removed a trace that shouldn't have been there. + - Add return checking to SPI_{GET,SET}WHEELSCROLLLINES and + SPI_{GET,SET}MENUSHOWDELAY unit tests so they no longer run on + Windows 95 where they aren't supported. + - Changed minimum hovertime in SPI_{GET,SET}MOUSEHOVERTIME to 10 as + Windows XP defaults to 10 any value below that. + + * dlls/shell32/brsfolder.c: Michael Jung + Fixed parsing of ITEMIDLIST in InitializeTreeView. + Added some documentation. + Fixed a crash occuring when the user double-clicks a leaf item. + + * dlls/msi/action.c: Aric Stewart + Text reformatting patch to clean up all the static strings. + + * dlls/comctl32/status.c: Filip Navara + Implement SB_SETBORDERS. + + * dlls/setupapi/devinst.c, include/winioctl.h: + Juan Lang + Implement SetupDiGetClassDevsA/W, SetupDiEnumDeviceInterfaces, + SetupDiDestroyDeviceInfoList, and SetupDiGetDeviceInterfaceDetailA for + serial ports. + + * server/request.c: Francois Gouget + Fix a race condition in create_dir(). + + * server/console.c, server/debugger.c, server/process.c, + server/process.h, server/ptrace.c, server/request.c, server/thread.h: + Convert the per-process thread list to a standard list. + + * configure, configure.ac: Emmanuel Maillard + Add '-read_only_relocs warning' to LDDLLFLAGS on Darwin. + + * dlls/comctl32/rebar.c: Robert Shearman + - Make row number be zero-based. + - Improvements to dumping functions to not dump out fields that may + not have been filled in. + + * dlls/x11drv/clipboard.c: Ulrich Czekalla + If unexpected condition occurs just report an error. + + * dlls/x11drv/bitmap.c, dlls/x11drv/dib.c: + Huw Davies + If the dibsection is based on a file-mapping object, then make sure + that the section is in sync when the dibsection is deleted. + + * dlls/kernel/path.c: Marcelo Duarte + CopyFile needs to retain timestamp. + + * dlls/kernel/tests/file.c: Dmitry Timoshkov + Add another test case for file sharing. + + * dlls/msi/action.c: Juan Lang + Don't hardcode windows or system directories, correct a typo. + + * dlls/ole32/stg_prop.c: Juan Lang + Move vtbl to end of file and get rid of unnecessary prototypes. + + * dlls/shell32/shfldr_fs.c: Juan Lang + Convert tabs to space, wrap long lines, make indenting consistent. + + * dlls/dbghelp/dbghelp.c, dlls/dbghelp/dbghelp_private.h, + dlls/dbghelp/elf_module.c, dlls/dbghelp/module.c, + dlls/dbghelp/pe_module.c, dlls/dbghelp/stabs.c: + Eric Pouech + Memory consumption optimization while loading ELF debug info: + - don't map twice an ELF file for symbol lookup (in non deferred mode) + - no longer entirely map an ELF file into memory, but only the + sections we need. + Added support for loading ELF modules thru SymLoadModule in a non life + process. + Factorisation of code for ELF module handling. + Fixes to ELF symbol loading + - drops symbols from symtab which are neither funcs nor global + variables + - fixes some incorrect size computation for latest GCC versions. + Several cleanups and fixes. + + * tools/wineinstall: Jeff Smith + Avoids a shift warning thrown by older versions of bash. + +2005-02-26 Alexandre Julliard + + * dlls/x11drv/clipboard.c, dlls/x11drv/dga2.c, dlls/x11drv/event.c, + dlls/x11drv/keyboard.c, dlls/x11drv/mouse.c, dlls/x11drv/winpos.c, + dlls/x11drv/wintab.c, dlls/x11drv/x11drv.h: + Use a table of handlers to dispatch X events and get rid of the + special casing for DGA and tablet events. + Unify the declarations of all the event handlers. + + * dlls/kernel/volume.c: + Fixed regression in QueryDosDeviceA when passed a NULL device name. + + * server/debugger.c: + Converted the debug event queue to a standard list. + + * configure, configure.ac: Pierre d'Herbemont + Syntax fix in configure.ac. + + * dlls/msi/tests/db.c: Dmitry Timoshkov + Remove a temporary msi database file. + + * dlls/shell32/shfldr_mycomp.c: Juan Lang + Convert a few calls to Unicode. + + * dlls/winmm/mci.c: Christian Costa + Added some more cases to MCI_MapMsgAtoW. + + * windows/cursoricon.c: Jason Edmeades + Make LR_LOADTRANSPARENT work and give transparent images. + +2005-02-25 Alexandre Julliard + + * server/console.c: + Converted the global screen buffer list to a standard list. + + * server/queue.c: + Replaced the message_list structure by a standard list. + + * dlls/x11drv/clipboard.c, dlls/x11drv/event.c, dlls/x11drv/x11drv.h: + Moved clipboard event handling functions and some private data + structures to clipboard.c. + + * server/thread.c, server/thread.h: + Convert the global thread list to a standard list. + + * server/process.c, server/process.h: + Convert the global process list to a standard list. + + * dlls/dsound/tests/ds3d.c, dlls/dsound/tests/dsound.c, + dlls/dsound/tests/dsound_test.h: + Robert Reif + Add secondary buffer SetFrequency test. + + * dlls/dsound/mixer.c: Robert Reif + Use nBlockAlign rather than calculating it. + Add a buffer length alignment error message. + + * dlls/msvcrt/tests/printf.c, dlls/msvcrt/wcs.c: + Uwe Bonnes + Advance over * argument for precision. + Honor precision argument for strings. + + * server/mutex.c, server/thread.c, server/thread.h: + Convert the per-thread mutex list to a standard list. + + * dlls/advapi32/registry.c, dlls/advapi32/tests/registry.c: + James Hawkins + Fix RegOpen/CloseKey. + + * dlls/user/edit.c: Lauri Tulmin + Make sure that last line is at the bottom of the edit control. + + * dlls/dsound/dsound.c: Robert Reif + Change SetCooperativeLevel FIXME to WARN. + + * tools/winedump/lnk.c: Mike McCormack + Dump the pidl of a lnk file. + + * dlls/shell32/shelllink.c, dlls/shell32/tests/shelllink.c: + Mike McCormack + - implement loading and saving of MSI advertised shortcut info + - make more test cases pass + - read and write the location block + - improve the binary compatibility of lnk files + + * libs/wpp/ppl.l: Ge van Geldorp + Treat already preprocessed code just like normal #include'ed code. + + * dlls/version/tests/info.c: + Stefan Leichter + Exclude two tests crashing on WinNT4. + + * dlls/comctl32/tab.c: Jon Griffiths + Remove unneeded calls to TAB_GetInfoPtr(), const fixes, inline small + funcs & remove unused parameters. + + * dlls/comctl32/string.c, dlls/commdlg/cdlg32.c, dlls/kernel/comm.c, + dlls/kernel/editline.c, dlls/kernel/process.c, dlls/kernel/thunk.c, + dlls/kernel/time.c, dlls/msi/msi.c, dlls/msvcrt/mbcs.c, + dlls/ntdll/heap.c, dlls/ntdll/large_int.c, dlls/ntdll/rtlbitmap.c, + dlls/ntdll/rtlstr.c, dlls/ntdll/sec.c, dlls/ole32/ole2.c, + dlls/oleaut32/olepicture.c, dlls/oleaut32/tests/vartype.c, + dlls/oleaut32/typelib.c, dlls/oleaut32/typelib2.c, + dlls/oleaut32/varformat.c, dlls/shell32/shell32_main.c, + dlls/shlwapi/assoc.c, dlls/shlwapi/string.c, dlls/win32s/w32sys.c, + dlls/wineps/graphics.c, dlls/wininet/netconnection.c, + programs/regedit/regproc.c, programs/rundll32/rundll32.c, + programs/winefile/winefile.c, tools/widl/write_msft.c, + tools/wrc/newstruc.c, windows/cursoricon.c, windows/spy.c, + windows/user.c: + Jon Griffiths + Documentation spelling fixes. + + * server/fd.c: + Regular files are always ready for I/O, no need to poll on them. + + * server/thread.c, server/thread.h: + Convert the APC queues to use standard lists. + + * dlls/commdlg/fontdlg.c: Troy Rollo + Fix stack object overrun when an application calls ChooseFontA. + + * dlls/msi/action.c: Aric Stewart + Implement the action RegisterFonts. + + * dlls/user/edit.c: Lauri Tulmin + Implemented !ES_AUTO[HV]SCROLL. + + * dlls/gdi/freetype.c: + TANABE Hiroshi wrote: + Remove (buf && !buflen) checking. + Fixed outline rendering with GGO_GRAY?_BITMAP option. + Improved fixed-pitch fonts detection. + + * programs/winecfg/drivedetect.c, programs/winecfg/properties.h: + Paul van Schayck + As last option for drive type detection we try the device node name. + + * dlls/ole32/storage32.c: Paul Vriens + Added some TRACE statements. + +2005-02-24 Alexandre Julliard + + * server/registry.c: + Convert the key notifications list to a standard list. + + * dlls/user/painting.c: + Repaint the non-client area to work around broken WM_PAINT handlers + also when doing a synchronous update with RDW_UPDATENOW. + + * dlls/ole32/stg_prop.c, dlls/ole32/storage32.c, + dlls/ole32/storage32.h: + Mike McCormack + Add struct StorageBaseImpl at the start of derived structures instead + of trying to keep the first members the same. + + * dlls/user/scroll.c: Vitaly Lipatov + - Fix scrollbar show/update conditions in SCROLL_SetScrollInfo: we DO + NOT show scroll bar if only page parameter changing when scrollbar + is disabled. + - Removed bChangeParams from SCROLL_SetScrollInfo as unneeded flag. + + * documentation/faq.sgml: Dimitrie O. Paun + Shorten the id of the question to avoid jade error. + + * programs/taskmgr/Fr.rc, programs/taskmgr/taskmgr.rc, + programs/winecfg/Fr.rc, programs/winecfg/winecfg.rc: + Jonathan Ernst + French localization. + + * server/fd.c, server/file.c, server/file.h, server/serial.c, + server/sock.c: + Convert async I/O queues to standard lists. + + * dlls/richedit/richedit.c: Mike McCormack + Remove unused declaration. + + * dlls/user/tests/msg.c, windows/win.c: + Mike McCormack + Dmitry Timoshkov + Release capture before sending WM_NCDESTROY message, do not send + WM_CAPTURECHANGED in that case. Add a test case for that behaviour. + + * dlls/user/tests/win.c: Dmitry Timoshkov + GetWindowRect and GetClientRect do not change RECT contents if the + passed window handle is invalid. + + * dlls/dsound/tests/capture.c: Robert Reif + Try old buffer description structure on failure with new one. + + * dlls/kernel/except.c, dlls/ntdll/critsection.c, + dlls/ntdll/exception.c, dlls/ntdll/loader.c, + dlls/ntdll/signal_i386.c, dlls/ntdll/signal_powerpc.c, + dlls/ntdll/signal_sparc.c, dlls/ntdll/tests/generated.c, + include/winbase.h, include/winnt.h: + Dmitry Timoshkov + Match RaiseException and EXCEPTION_RECORD to SDK definitions. + + * dlls/opengl32/wgl_ext.c: Raphael Junqueira + - implement partial PBuffer support + - minimal pixel format support + + * dlls/msdmo/dmort.c: Mike McCormack + Remove tabs, reformat, merge comments. + + * dlls/msi/action.c, dlls/msi/action.h, dlls/msi/msipriv.h: + Aric Stewart + Add the ExecuteAction handler. + Store the keypath, and do refcounting and registration of SharedDLLs. + Fix a bug with handing dword values in the registry. + Fix bugs with writing registry keys where value == NULL. + Make use of msidefs.h. + Lay some groundwork for uninstalls. + + * dlls/comctl32/imagelist.c: Michael Stefaniuc + - ImageList_LoadImage{A,W} were basicaly a cut'n'paste of each + other. Removed the A variant and did a A->W translation. + - ImageList_LoadImageW: get the bitmap size from the image itself and + not from the mask (ImageList_LoadImageA did that). + + * documentation/winedev-kernel.sgml: Brian Vincent + Clean up references to threading in Developer's Guide. + + * documentation/faq.sgml: Dimitrie O. Paun + Can we bundle everthing together? + Suggested by Graham Toal . + + * documentation/debugging.sgml: Dimitrie O. Paun + Add info on building dynamic strings for logging. + Reorder some points for a more logical organization. + + * dlls/msi/msi.c: Aric Stewart + Do some basic work with registry component paths. + + * include/msidefs.h: Aric Stewart + Define msidbComponentAttributes. + + * dlls/msi/action.c: Ulrich Czekalla + Prevent accessing freed memory in failure case. + + * dlls/d3d8/directx.c, dlls/wined3d/device.c: + Jason Edmeades + Correct handling of unusual vendor strings in d3d8, and check for a + stateblock before trying to release it in wined3d. + + * dlls/user/edit.c: Lauri Tulmin + Controls with ES_RIGHT or ES_CENTER shouldn't have ES_AUTOHSCROLL. + +2005-02-23 Alexandre Julliard + + * dlls/x11drv/event.c: + Revert SC_CLOSE change, this is causing deadlocks. + + * documentation/threading.sgml: Removed no longer used threading.sgml. + + * documentation/winedev-kernel.sgml: + Bill Medland + Correct a couple of minor documentation typos. + + * tools/widl/client.c, tools/widl/parser.y, tools/widl/proxy.h, + tools/widl/server.c, tools/widl/widl.c, tools/widl/widl.h: + Removed the useless proxy.h header file. + Fixed a couple of warnings. + + * dlls/winmm/wineoss/audio.c, dlls/winmm/wineoss/audio.h: + Jeremy White + More correct fix for dsp empty case. + + * programs/winefile/De.rc: Henning Gerhardt + Small fix for the German resource file. + + * programs/taskmgr/De.rc, programs/taskmgr/taskmgr.rc, + programs/winecfg/De.rc, programs/winecfg/winecfg.rc: + Henning Gerhardt + Added German language support. + + * tools/wineinstall: Jon Griffiths + Suggest make uninstall in case the user tried make install. + + * tools/widl/Makefile.in, tools/widl/client.c, tools/widl/header.c, + tools/widl/parser.l, tools/widl/parser.y, tools/widl/server.c, + tools/widl/widl.c, tools/widl/widl.h, tools/widl/widltypes.h: + Eric Kohl + - Add basic support for creating client and server stub files. + - Support implicit_handle attribute in IDL files. + - Build mixed-mode stub files. + + * dlls/rsabase/Makefile.in, dlls/rsabase/main.c, + dlls/rsabase/rsabase.spec: + Michael Jung + Made rsabase forward everything to rsaenh. + + * dlls/kernel/cpu.c, dlls/ntdll/nt.c: Rein Klazes + NtQueryPerformanceCounter should return a frequency of 1193182Hz and + counts like in Windows. Some applications depend on that. + Simplify QueryPerformanceCounter a bit. + + * dlls/winmm/tests/wave.c: Jeremy White + An interactive test should have volume, else a rational user will + decide it is broken. + + * dlls/shell32/shfldr_mycomp.c, dlls/shell32/shlfsbind.c: + Mike McCormack + Remove tabs and reformat. + + * dlls/comctl32/comctl32.spec, dlls/shell32/shell32.spec: + Francois Gouget + Add the -noname flag to match the Platform SDK. + + * dlls/winmm/wineoss/audio.c: Jeremy White + In calculating the SMPTE time, we would round incorrectly (0:0:4.30 + instead of 0:0:5.0 [the last column only goes to 29]). + + * dlls/shell32/enumidlist.c, dlls/shell32/enumidlist.h, + dlls/shell32/pidl.h, dlls/shell32/shfldr.h, + dlls/shell32/shfldr_desktop.c, dlls/shell32/shfldr_fs.c: + Mike McCormack + - handle IFileSystemBindData in ISF_Desktop_fnParseDisplayName + - more Unicode conversion + + * dlls/shell32/shell32.spec: Francois Gouget + Don't hardcode ordinals if which are not hardcoded on Windows. + + * dlls/msi/format.c: Aric Stewart + Make sure formats like [\\]] and [\\[] work properly. + + * dlls/advapi32/tests/crypt.c: Jakob Eriksson + Apparently NT4 can also return ERROR_ENVVAR_NOT_FOUND. + + * dlls/user/tests/msg.c: Dmitry Timoshkov + - Pass original wParam to CallNextHookEx. + - Avoid playing games with focus in a newly created thread, that leads + to all kinds of misbehaviours and failures in window activation + under Windows. + + * dlls/dsound/tests/capture.c, dlls/dsound/tests/ds3d.c, + dlls/dsound/tests/ds3d8.c, dlls/dsound/tests/dsound.c, + dlls/dsound/tests/dsound8.c, dlls/dsound/tests/propset.c: + Robert Reif + Fix tests for win9x and old versions of DirectX. + + * dlls/wintrust/wintrust.spec, dlls/wintrust/wintrust_main.c: + Michael Stefaniuc + Stub for CryptCATAdminReleaseContext. + + * dlls/winmm/wineoss/audio.c: Jeremy White + When we get down to the last fragment or two in our output to the DSP, + we should use the SND_DSP_POST ioctl to let the sound card know to + flush those fragments. This allows us to precisely know when the + buffer is empty, and fixes another set of winmm tests. + + * dlls/winmm/tests/wave.c: Jeremy White + When testing the WAVE_MAPPER device, it seems inappropriate (to me) to + demand WAVE_FORMAT_DIRECT; this fixes another slew of tests. + + * dlls/winmm/wavemap/wavemap.c: Jeremy White + When we are converting from one sample rate to another, we do have to + adjust when calculating TIME_SAMPLES. + + * dlls/x11drv/xrender.c: Jason Edmeades + Take into account additional requested spacing on break characters. + + * dlls/wined3d/directx.c: Jason Edmeades + Enable parsing of vendor strings not matching the expected template. + + * dlls/comctl32/header.c: Maxime Bellengé + Correctly displays the text with ellipsis when there is not enough + room in a header item and an image from an imagelist is displayed on + the right of the text. + + * programs/winemine/Pl.rc: Jacek Caban + Translation update. + + * dlls/msi/msi.rc, dlls/msi/msi_Es.rc: + José Manuel Ferrer Ortiz + Added MSI Spanish resources. + +2005-02-22 Alexandre Julliard + + * server/region.c, server/user.h: + Removed no longer used create_region function, and directly export + create_empty_region instead. + + * dlls/user/tests/win.c, dlls/x11drv/window.c, dlls/x11drv/winpos.c, + server/window.c: + Allow the client rectangle to be of arbitrary size and dimensions, + regardless of the window rectangle. + + * dlls/gdi/font.c: TANABE Hiroshi + Added Multibyte character set support in GetGlyphOutlineA. + + * dlls/gdi/dib.c: Huw Davies + Don't hold the GDI lock when calling DC_GetDCUpdate. + + * dlls/cryptdll/Makefile.in, dlls/cryptdll/cryptdll.spec: + Hans Leidekker + Forward MD5{Final,Init,Update} to advapi32. + + * dlls/ntdll/handletable.c, dlls/ntdll/heap.c, dlls/ntdll/loader.c, + dlls/ntdll/relay.c, dlls/ntdll/thread.c, dlls/ntdll/virtual.c: + Ivan Leo Puoti + Replace GetCurrentProcess() with NtCurrentProcess() in ntdll. + + * include/winbase.h, include/winnt.h: + Ivan Leo Puoti + Added a couple of defines. + + * dlls/msi/action.c: Mike McCormack + Make sure strings are null terminated. + + * programs/winemenubuilder/winemenubuilder.c: + Mike McCormack + When running a second time, don't fail if we can't extract an icon. + + * dlls/comctl32/treeview.c: Martijn Vernooij + Scroll instead of repainting when expanding/collapsing trees. + Don't repaint on hover if 'hot tracking' isn't on. + + * dlls/itss/itss.c: Jacek Caban + Added implementation of LockServer. + + * dlls/oleaut32/typelib.c: Huw Davies + The typelib cache should take the typelib resource index into + account. + + * dlls/user/tests/msg.c: Cosmetic fixes. + + * dlls/kernel/string.c, dlls/shell32/shell32.spec, include/winbase.h: + Mike McCormack + Make lstr* functions inline inside Wine. + + * dlls/shell32/pidl.h, dlls/shell32/shfldr_fs.c: + Mike McCormack + - handle IFileSystemBindData in IShellFolder::ParseDisplayName + - convert IShellFolder::ParseDisplayName to use Unicode + + * dlls/msi/action.c: Aric Stewart + Update the installed state for components during CostFinalize. Laying + groundwork to be able to start processing uninstall logic as well. + + * dlls/user/tests/win.c, windows/nonclient.c: + Rein Klazes + DefWindowProc's WM_NCCALC handler must not subtract space for + scrollbars if there is not enough space for it anyway. With tests to + confirm the behavior. + + * dlls/user/tests/msg.c: Stefan Leichter + Make user32_crosstest.exe loadable on NT 3.51. + + * dlls/user/tests/msg.c, windows/message.c: + DispatchMessage needs to repaint the non-client area if the WM_PAINT + handler didn't do it. + + * dlls/user/tests/class.c, windows/class.c: + Jason Edmeades + Make RegisterClassExA check that reserved bytes is a valid value. + Tests to confirm this behaviour. + + * dlls/user/sysparams.c: Justin Chevrier + Point KEYBOARDPREF and SCREENREADER to registry keys and values that + match native. + + * dlls/oleaut32/olepicture.c, dlls/oleaut32/typelib.c, + dlls/oleaut32/usrmarshal.c, dlls/oleaut32/variant.c: + Jon Griffiths + Use variant macros instead of accessing the union directly. + + * dlls/msi/action.c: Steven Edwards + Correct typo. + + * programs/winedbg/dbg.y, tools/winedump/emf.c, tools/winedump/lnk.c: + Jon Griffiths + Use config.h & HAVE_ where needed, -W fixes. + + * dlls/mapi32/prop.c: Jon Griffiths + Fix race in IMAPIProp_Release(), -W fixes. + + * dlls/shell32/pidl.c: Mike McCormack + Cleanup, create unicode versions of _ILCreateFromPath, + _ILCreateGuidFromStr, and _ILCreateFromFindData. + + * dlls/quartz/acmwrapper.c: Christian Costa + Fixed ACM Wrapper. + + * dlls/ntdll/time.c: + Darryl Dixon + Added support for NZDT (New Zealand Daylight Time) to TZ_INFO. + + * dlls/unicows/Makefile.in, dlls/unicows/main.c, + dlls/unicows/unicows.spec: + Hans Leidekker + Add IsDestinationReachableW. + +2005-02-21 Alexandre Julliard + + * dlls/kernel/kernel32.spec, dlls/kernel/thread.c: + Hans Leidekker + Implementation stub for QueueUserWorkItem. + + * dlls/ole32/Makefile.in, dlls/ole32/stg_prop.c, + dlls/ole32/storage32.c, dlls/ole32/storage32.h, + dlls/ole32/tests/storage32.c: + Mike McCormack + Implement and test IPropertySetStorage. + + * dlls/kernel/kernel32.spec, dlls/kernel/toolhelp.c: + Lionel Ulmer + Implement 'W' variants of Process32First / Next APIs + + * dlls/gdi/font.c, dlls/gdi/gdi16.c: + Alex Villacís Lasso + Implemented GetGlyphOutline16. + + * dlls/user/sysparams.c, dlls/user/tests/sysparams.c: + Justin Chevrier + - Implement SPI_{GET,SET}POWEROFFACTIVE and SPI_SETLOWPOWERACTIVE. + - Corrected SPI_GETLOWPOWERACTIVE to use an index (instead of its SPI + value) to avoid an out of bounds condition. + - Created unit tests for SPI_{GET,SET}POWEROFFACTIVE and + SPI_{GET,SET)SETLOWPOWERACTIVE. + + * include/winuser.h: Vincent Béron + Add a definition for OpenInputDesktop(). + Add constants for PBT_APM* parameters. + + * dlls/user/edit.c: Lauri Tulmin + Horizontal scrollbar is hidden when edit control is emptied. + + * programs/winemine/Pl.rc: Marcelo Duarte + Sync Polish resources. + + * dlls/comctl32/listview.c: + Maxime Bellengé + Take into account the new size of a column when the header size + change. + + * dlls/quartz/acmwrapper.c, dlls/quartz/avidec.c, + dlls/quartz/transform.c, dlls/quartz/transform.h: + Christian Costa + Improved AVIDec. + Added 2 new callback functions to the transform template and moved all + of them into a funcs table. + + * dlls/advapi32/registry.c, dlls/advapi32/tests/registry.c: + James Hawkins + Add RegOpenKey, RegCloseKey tests. + + * dlls/mpr/mpr_De.rc, dlls/mpr/mpr_En.rc, dlls/mpr/mpr_Fr.rc, + dlls/mpr/mpr_Pt.rc, dlls/shdocvw/De.rc, dlls/shdocvw/En.rc, + dlls/shdocvw/Fr.rc, dlls/shdocvw/Pt.rc, + dlls/user/resources/user32_Si.rc, programs/winecfg/En.rc, + programs/winecfg/Nl.rc: + Marcelo Duarte + Use "MS Shell Dlg" everywhere except for Japanese. + + * dlls/mscms/Makefile.in, dlls/mscms/handle.c, dlls/mscms/lcms_api.h, + dlls/mscms/mscms_main.c, dlls/mscms/mscms_priv.h, + dlls/mscms/profile.c, dlls/mscms/stub.c, dlls/mscms/transform.c, + include/icm.h: + Hans Leidekker + - Add support for color transform handles. + - Implement CreateColorTransform{A,W}, CreateMultiProfileTransform, + DeleteColorTransform. + - Don't depend on lcms for the implementation of + IsColorProfileTagPresent. + + * dlls/shell32/shell32.spec, dlls/shell32/shell32_main.c, + dlls/shell32/shlfileop.c: + Hans Leidekker + - Revert wrong -noname markup for Drag*, DoEnvironmentSubst and + SHGetNewLinkInfo{A,W}. + - Also mark stub exports -noname when they are exported by ordinal + only on win98/2k. + - Implementation level stubs for SheChangeDirA, SheGetDirA, + SHHelpShortcuts_RunDLL{A,W}. + - New spec file stubs for Control_RunDLLAsUserW, + FixupOptionalComponents, OCInstall, SHChangeNotifySuspendResume, + SHCreateProcessAsUserW, SHExtractIconsW, + SHInvokePrinterCommand{A,W}, SHIsFileAvailableOffline, + SHLoadNonloadedIconOverlayIdentifiers, SHPathPrepareForWrite{A,W}, + ShellExec_RunDLL{,A,W}, SHGetIconOverlayIndex{A,W}. + + * dlls/shell32/pidl.c, dlls/shell32/shfldr_desktop.c: + Mike McCormack + Remove tabs and make formatting consistent. + + * dlls/oleaut32/oleaut32.spec, dlls/oleaut32/olepicture.c, + include/olectl.h: + Vincent Béron + Add a stub for OleLoadPicturePath(). + + * include/winuser.h: Vincent Béron + Add LWA_ constants, used in {S/G}LayeredWindowAttributes(). + + * dlls/ole32/marshal.c: Mike Hearn + Avoid infinite loop when doing a typelib marshalled + IUnknown::QueryInterface by only doing an extra QI if requested IID is + not equal to marshalled IID. + + * dlls/oleaut32/typelib.c: Mike Hearn + Allow loading of builtin typelibs. + + * dlls/comctl32/header.c: Maxime Bellengé + Fix SetItem so that items don't get wrongly re-ordered. + + * dlls/winspool/info.c, dlls/winspool/winspool.drv.spec, + include/winspool.h: + Hans Leidekker + Stub implementations for AbortPrinter, AddPortEx{A,W}, + AddPrinterConnection{A,W}, ConnectToPrinterDlg, + DeletePrinterConnection{A,W}, EnumForms{A,W}, EnumPrinterData{A,W], + ExtDeviceMode, Find{Close,First,Next}PrinterChangeNotification, + FreePrinterNotifyInfo, ScheduleJob. + + * dlls/user/menu.c, dlls/user/tests/msg.c, dlls/user/tests/resource.rc: + Dmitry Timoshkov + Take Shift key state into account while processing an accelerator. + Add a couple of test cases. + + * programs/taskmgr/En.rc, programs/taskmgr/taskmgr.rc: + Marcelo Duarte + Cleanup taskmgr resource file (get rid of C++ style coments, use "MS + Shell Dlg" for dialogs, etc). + Preparation for translators (move english resources to En.rc). + + * dlls/user/listbox.c: Maxime Bellengé + Reverse the order for deleting the items in resetcontent to correctly + empty a comboboxex. + + * include/wtypes.idl: Vincent Béron + Added LPDWORD definition. + + * tools/winemaker: Francois Gouget + Only 'fix' the names of source files and directories (this way + documentation files are unharmed). + Better handle Makefiles generated by Winemaker. In particular, don't + rename them to makefile.win! + + * programs/msiexec/msiexec.c: Aric Stewart + The values are quoted and spaces added, so having spaces in the + properties results in spaces in the values which is incorrect. + + * include/richole.idl: Vincent Béron + Added IRichEditOleCallback. + + * include/commctrl.h: Vincent Béron + Correct the number of args of SNDMSGA in ListView_GetSubItemRect. + + * dlls/ntdll/nt.c: Juan Lang + Fix NtQueryPerformanceCounter parameter checking. Spotted by Alex + Woods. + +2005-02-18 Alexandre Julliard + + * dlls/ole32/filemoniker.c, dlls/ole32/itemmoniker.c: + Robert Shearman + - Better tracing. + - Small cleanup of creation functions. + + * dlls/shell32/shell32.spec: Hans Leidekker + Mark exports -noname when they are exported by ordinal only on + win98/2k. + + * Makefile.in: Francois Gouget + dlls/__install-lib__ and programs/__install__ should not force the + installation of the Wine headers as this is contrary to the purpose of + install-lib. + + * dlls/ole32/compobj_private.h, dlls/ole32/marshal.c, + dlls/ole32/stubmanager.c, dlls/ole32/tests/marshal.c: + Robert Shearman + - Move marshaling state machine into stub manager from ifstub. + - Add additional needed states for table-weak marshaling, as shown by + tests. + - Protect external reference count from underflows/overflows. + + * server/queue.c: Krzysztof Foltman + Ensure that caret position is not reset to (0, 0) when CreateCaret is + called second time with the same window. + + * dlls/user/tests/msg.c, windows/win.c: + Dmitry Timoshkov + - Always unlink children before sending WM_NCDESTROY message. + - Fix order of WM_DESTROY messages for the children's recursion. + - DestroyWindow should hide only visible windows. + - Add a test case for the above fixes. + + * dlls/x11drv/event.c: Ulrich Czekalla + Duplicate Windows behaviour and use SendMessage for the SC_CLOSE + system command instead of PostMessage. + + * dlls/msi/action.c: Aric Stewart + Fixed problems with my code for finding the PackageCode. + + * tools/winedump/lnk.c: Gerald Pfeifer + Use stdlib.h instead of non-standard malloc.h. + + * include/basetsd.h, include/winnt.h: James Hawkins + Conditionally add DECLSPEC_ALIGN(8) to wine's 64-bit types and leave + the modifier off when compiling with msvc. + + * dlls/winmm/mci.c: Christian Costa + Fixed offsets calculations. + + * tools/winedump/lnk.c: Mike McCormack + Dump out more details on the target of a link. + + * include/Makefile.in, include/odbcinst.h: + Mike McCormack + Added odbcinst.h. + + * programs/winemenubuilder/winemenubuilder.c: + Mike McCormack + Small indentation fixes. + + * dlls/dsound/tests/capture.c: Robert Reif + Fix capture test to pass on windows 98 when no sound card present or + device already in use. + + * dlls/winmm/tests/timer.c: Robert Reif + Fix timer tests to pass on windows 98. + + * dlls/dsound/tests/dsound.c: Robert Reif + Fix block align test. + + * dlls/oleaut32/olefont.c: + Alex Villacís Lasso + Implement OleFontImpl_QueryTextMetrics. + + * dlls/msvcrt/dir.c: Gunnar Dalsnes + When getting current directory on a drive different from the working + drive, _getdcwd incorrectly passed "X:\" (X = any drive) as path to + GetFullPathName. "X:" (without the backslash) is the correct thing to + use. + +2005-02-17 Alexandre Julliard + + * dlls/user/scroll.c: Vitaly Lipatov + Rename SCROLL_GetScrollBarInfo to SCROLL_GetInternalInfo and make + allocation of a new info structure optional. + Add some descriptions. + + * dlls/shell32/shelllink.c, programs/winemenubuilder/winemenubuilder.c: + Dmitry Timoshkov + Convert winemenubuilder to unicode. + + * tools/winedump/Makefile.in, tools/winedump/lnk.c, + tools/winedump/main.c, tools/winedump/winedump.h: + Mike McCormack + Add dumping of lnk files. + + * dlls/msvideo/msvideo_main.c: David Smith + Fix for ICInfo() in msvideo when it is used to ask for a codec by + index. + + * dlls/advapi32/tests/crypt.c: Jakob Eriksson + Apparently NT4 can also return ERROR_ENVVAR_NOT_FOUND. + + * dlls/shell32/shlfileop.c: Joris Huizer + - renamed file_operation_delete and to shfileops_delete + - renamed file_operation_checkFlags to shfileops_check_flags + - added helper function shfileops_do_operation() + - added helper function shfileops_get_parent_attr() + - added helper function shfileops_get_parent_attr2() + - various cleanups in SHFileOperationW using these functions + +2005-02-16 Alexandre Julliard + + * dlls/avifil32/avifile_Es.rc, dlls/comctl32/comctl_Es.rc, + dlls/commdlg/cdlg_Es.rc, dlls/mpr/mpr_Es.rc, dlls/msacm/msacm_Es.rc, + dlls/msrle32/msrle_Es.rc, dlls/oleaut32/oleaut32_Es.rc, + dlls/oledlg/oledlg_Es.rc, dlls/serialui/Es.rc, dlls/setupapi/Es.rc, + dlls/shell32/shell32_Es.rc, dlls/shlwapi/shlwapi_Es.rc, + dlls/user/resources/user32_Es.rc, dlls/wineps/wps_Es.rc, + dlls/wininet/wininet_Es.rc, dlls/winmm/winmm_Es.rc, + programs/clock/Es.rc, programs/cmdlgtst/Es.rc, + programs/notepad/Es.rc, programs/progman/Es.rc, + programs/regedit/Es.rc, programs/start/Es.rc, programs/view/Es.rc, + programs/wcmd/Es.rc, programs/winecfg/Es.rc, + programs/wineconsole/wineconsole_Es.rc, programs/winefile/Es.rc, + programs/winemine/Es.rc, programs/winhelp/Es.rc: + Alex Villacís Lasso + Change SUBLANG_DEFAULT to SUBLANG_NEUTRAL for LANG_SPANISH in all + resources, so that Spanish locales other than Spain also use Spanish + resources. + + * dlls/msi/msi.rc, dlls/msi/msi_Fr.rc, dlls/shdocvw/Fr.rc, + dlls/shdocvw/shdocvw.rc: + Jonathan Ernst + Add French resources. + + * dlls/msi/msi.c, dlls/msi/registry.c: + Mike McCormack + Move product, feature and component enumeration functions to + registry.c. + + * dlls/winmm/tests/wave.c: James Hawkins + Fix improper type-conversions. + + * include/winnt.h: Ivan Leo Puoti + Add EVENT_QUERY_STATE define. + + * dlls/user/painting.c, dlls/user/tests/win.c: + Rein Klazes + Calling ValidateRect or ValidateRgn on a windows also validates the + children. Add a test to show the behavior. + + * programs/winecfg/audio.c: Paul van Schayck + Change detection order to: OSS-ALSA-ARTS-JACK. + + * dlls/user/edit.c: Ulrich Czekalla + Implement ES_CENTER and ES_RIGHT alignment styles. + + * dlls/shell32/shelllink.c, dlls/shell32/tests/shelllink.c: + Huw Davies + SetPath("") should return S_OK. + SetPath("nonexistent_path") should return S_FALSE. + + * dlls/shlwapi/ordinal.c, dlls/shlwapi/shlwapi.spec: + Thomas Weidenmueller + Forward to user32 when appropriate. + + * dlls/dsound/mixer.c, dlls/dsound/primary.c: + Robert Reif + Some block align cleanups. + + * dlls/msi/dialog.c: Mike McCormack + Add a border to the edit control, add some more controls. + + * dlls/msi/suminfo.c: Mike McCormack + Fix up the summary information code a little. + + * dlls/msi/msi.c, dlls/msi/msi.spec: + Aric Stewart + Stubs for MsiUseFeature. + + * dlls/dsound/buffer.c, dlls/dsound/tests/ds3d.c, + dlls/dsound/tests/ds3d8.c, dlls/dsound/tests/dsound.c, + dlls/dsound/tests/dsound8.c, dlls/dsound/tests/dsound_test.h: + Robert Reif + Fixed invalid buffer size by rounding up to next multiple of + nBlockAlign. + Added test to verify buffer rounding behavior. + + * dlls/x11drv/winpos.c: Lauri Tulmin + Make minimized windows stay minimized. + + * dlls/msi/package.c: Mike McCormack + Remove const declaration from non-const function. + + * dlls/msi/table.c, dlls/msi/where.c: + Mike McCormack + Allow MsiViewExecute to be called twice on the same query. + + * dlls/msi/msiquery.c: Mike McCormack + Implement MsiDatabaseGetPrimaryKeys. + + * dlls/msi/msi.c: Mike McCormack + MsiGetComponentPath should allow null pointers for pcchBuf and + lpPathBuf. + + * programs/winemenubuilder/winemenubuilder.c: + Mike McCormack + Small fixes, indentation and comments. + +2005-02-15 Alexandre Julliard + + * dlls/comctl32/listview.c, dlls/commdlg/colordlg.c, + dlls/commdlg/colordlg16.c, dlls/commdlg/filedlg.c, + dlls/commdlg/finddlg.c, dlls/commdlg/fontdlg16.c, + dlls/serialui/confdlg.c, dlls/shell32/dialogs.c, + dlls/shlwapi/msgbox.c, dlls/shlwapi/ordinal.c, dlls/user/controls.h, + dlls/user/desktop.c, dlls/user/dialog16.c, dlls/user/icontitle.c, + dlls/wineps/driver.c, dlls/x11drv/window.c, dlls/x11drv/winpos.c, + include/windowsx.h, include/winuser.h, programs/taskmgr/applpage.c, + programs/taskmgr/proclist.c, programs/winecfg/appdefaults.c, + programs/winecfg/audio.c, programs/winecfg/driveui.c, + programs/winecfg/x11drvdlg.c, programs/wineconsole/dialog.c, + windows/class.c, windows/defdlg.c, windows/defwnd.c, + windows/dialog.c, windows/mdi.c, windows/nonclient.c, windows/win.c, + windows/winproc.c: + Dmitry Timoshkov + - Fix prototypes of GetClassLongA/W, GetClassLongPtrA/W and + SetClassLongA/W according to SDK definitions. + - Add prototypes for SetClassLongPtrA/W, protect some GWL_ and GCL_ + constants from using in Wine or in _WIN64 mode. + - Fix all places in Wine affected by the above changes. + + * dlls/ole32/compobj.c, dlls/ole32/oleproxy.c, dlls/ole32/rpc.c: + Robert Shearman + - Use I_RpcGetBuffer, instead of our own buffer routines to fix an + occasional test crash caused by heap corruption. + - Zero the memory block passed to RpcServerRegisterIfEx so we don't + pass garbage in some of the fields we don't fill in. + - Return the correct error code from create_server and fix two handle + leaks. + - TODO update. + + * dlls/ntdll/rtlstr.c: + Uwe Bonnes + Use local buffer in RtlUpcaseUnicodeStringToCountedOemString, if + appropriate. + + * dlls/ntdll/reg.c, dlls/ntdll/tests/reg.c, include/winternl.h: + Ivan Leo Puoti + Move Rtl*Registry* structs, defines and prototypes to winternl.h. + Fix two function declarations. + + * dlls/msi/msi.rc, dlls/msi/msi_De.rc, dlls/shdocvw/De.rc, + dlls/shdocvw/shdocvw.rc, programs/winefile/De.rc: + Henning Gerhardt + Add/updated German resources. + + * dlls/shell32/shell32_main.c: Mike McCormack + Reindent some code to improve readability. + + * dlls/rpcrt4/rpc_binding.c, dlls/rpcrt4/rpc_message.c, + dlls/rpcrt4/rpcrt4.spec: + Robert Shearman + - Add a stub implementation of RpcImpersonateClient. + - More tracing, particularly on error paths. + + * dlls/kernel/volume.c: Paul van Schayck + Only stop writing a volume label if we found a non writable fat + partition. + + * dlls/ole32/git.c: Robert Shearman + The Global Interface Table should do table-strong marshaling instead + of normal marshaling so that an interface can be retrieved more than + one time. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/rpc.c: + Robert Shearman + - Remove cruft left over from previous RPC backend implementation in + the apartment structure. + - Don't pass an IPID by value for proxy_manager_create_ifproxy. + - Disable more of RPC_UnregisterInterface to prevent the RPC runtime + using freed memory. + - Rename various external RPC backend functions so that they all have + the same "RPC_" prefix. + - Reduce the timeout of the function that connects to a local server + to 30s, like native. + + * dlls/shell32/shell32_main.c, include/shellapi.h: + Mike McCormack + Define some extra SHFGI values. + + * dlls/user/sysparams.c, include/winuser.h: + Mike McCormack + Add some more SPI values. + + * dlls/rpcrt4/rpc_server.c: Robert Shearman + Fix RPC server thread race. + + * dlls/rpcrt4/rpc_binding.c: Robert Shearman + ERROR_IO_PENDING is expected, so don't return an error. + + * dlls/dinput/joystick_linuxinput.c, dlls/dinput/keyboard.c, + dlls/dinput/mouse.c: + Christian Costa + Implemented GetProperty method for keyboard device. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c: + Robert Shearman + Make COM use the RPC runtime as the backend for RPC calls. Based on a + patch by Ove Kåven. + +2005-02-14 Alexandre Julliard + + * dlls/ntdll/tests/.cvsignore, dlls/ntdll/tests/Makefile.in, + dlls/ntdll/tests/reg.c: + Brad DeMorrow + Tests for the ntdll registry functions. + + * dlls/ntdll/ntdll.spec, dlls/ntdll/reg.c: + Ivan Leo Puoti + Add implementation for RtlQueryRegistryValues, RtlCheckRegistryKey and + RtlDeleteRegistryValue. + + * dlls/advapi32/tests/security.c, dlls/gdi/tests/metafile.c, + dlls/mlang/tests/mlang.c, dlls/msvcrt/tests/file.c, + dlls/ntdll/tests/path.c: + Francois Gouget + Cast the GetProcAddress() return value to avoid warnings about the + function pointer being of the wrong type. + Fix assorted signed/unsigned comparison warnings. + + * dlls/richedit/reader.c, dlls/richedit/rtf.h, + dlls/richedit/stdcharnames.h, dlls/richedit/text_map.h: + Rémi Assailly + char -> const char fixes. + + * programs/winecfg/main.c: Michael Jung + Added support for command line parameter '/D' to do drive detection + from wineprefixcreate. + + * programs/winecfg/drivedetect.c: + Michael Jung + Include config.h to reenable reading /etc/fstab on platforms that + support it. + Implemented a black list of mount directories, which should not be + mapped. + Ensure that the user's home directory is mapped. + + * dlls/rsaenh/rsaenh.c: Michael Jung + Check pdwDataLen param for non NULL'ness. + Implemented PP_IMPLTYPE and PP_VERSION provider params. + + * programs/winecfg/drive.c: Michael Jung + Set pointers to NULL in delete_drive to prevent heap corruption in + load_drives. + + * dlls/winmm/tests/timer.c: Robert Reif + Add some missing \ns. + + * dlls/mscms/handle.c, dlls/mscms/icc.c, dlls/mscms/mscms_priv.h, + dlls/mscms/profile.c, dlls/mscms/tests/profile.c: + Hans Leidekker + Implement and test access flags for color profiles. + Write the color profile back to disk when it was opened for writing. + + * dlls/msvcrt/msvcrt.spec, dlls/msvcrt/tests/printf.c, + dlls/msvcrt/wcs.c: + Mike McCormack + Add handling of %ws, %S and %C to _vns(w)printf, improve sprintf + tests. + + * dlls/user/dde/client.c, dlls/user/dde/dde_private.h, + dlls/user/dde/ddeml16.c, dlls/user/dde/misc.c, + dlls/user/dde/server.c: + Dmitry Timoshkov + Make DDE implementation always work internally in Unicode. + + * dlls/advapi32/tests/security.c: + Vincent Béron + Suppress a warning. + + * dlls/shell32/tests/shelllink.c: + Francois Gouget + Test the interaction between IShellLink::SetIDList() and + IShellLink::SetPath(). + Check what default values one gets on a fresh IShellLink object. + Add some more tests verifying nothing is lost in an IShellLink + save/load cycle. Merged the empty shelllink test with these. + + * dlls/gdi/region.c: Rein Klazes + REGION_FrameRgn computes the frame region inside the original region. + + * dlls/user/edit.c: Lauri Tulmin + Update scroll info on WM_SETTEXT. + + * programs/notepad/dialog.c: Lauri Tulmin + Implement word wrap. + + * documentation/README.pt, documentation/README.pt_br: + Marcelo Duarte + Update README for Pt_br and Pt. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, dlls/ole32/rpc.c, + dlls/ole32/stubmanager.c: + Robert Shearman + Invoke objects in STA's in the correct thread by sending messages to + the hidden apartment window. + + * dlls/richedit/richedit.c: + Jason Edmeades + Make the edit field created from a richedit control which was created + with ES_DISABLENOSCROLL, not have the ES_NUMBER style and hence accept + alphanumeric input. + + * dlls/commdlg/cdlg_En.rc, dlls/commdlg/cdlg_Pt.rc, + dlls/commdlg/cdlg_xx.rc, dlls/mpr/mpr_Pt.rc, dlls/msi/msi.rc, + dlls/msi/msi_Pt.rc, dlls/oleaut32/oleaut32.rc, dlls/shdocvw/En.rc, + dlls/shdocvw/Pt.rc, dlls/shdocvw/shdocvw.rc, + dlls/shell32/shell32_Pt.rc, dlls/wininet/wininet_Pt.rc, + programs/winecfg/Pt.rc, programs/winefile/Pt.rc: + Marcelo Duarte + Update the resources for Portuguese. + + * dlls/ddraw/d3d_private.h, dlls/ddraw/d3ddevice/main.c, + dlls/ddraw/mesa.c, dlls/ddraw/mesa_private.h, + dlls/ddraw/d3ddevice/mesa.c, dlls/ddraw/direct3d/mesa.c, + dlls/ddraw/dsurface/main.c: + Christian Costa + Handle more properly versions for Direct3D and Direct3DDevice + objects. + + * documentation/getting.sgml: + Vincent Béron + Add 2 missing tags in getting.sgml. + + * dlls/gdi/dib.c, dlls/oleaut32/olepicture.c, dlls/wineps/ps.c, + windows/cursoricon.c: + Marcus Meissner + Check for overflows with ClrUsed. + + * dlls/msi/action.c, dlls/ole32/errorinfo.c, dlls/shell32/shellpath.c: + Marcus Meissner + Output some more informations. + Mark one global variable static. + + * dlls/msi/Makefile.in, dlls/msi/delete.c, dlls/msi/query.h, + dlls/msi/sql.y: + Mike McCormack + Implement SQL delete query. + + * dlls/shell32/shlview.c: Filip Navara + Don't crash if ShellFolder doesn't implement the IID_ISFHelper + interface. + + * dlls/advapi32/tests/crypt.c, dlls/advapi32/tests/security.c: + Stefan Leichter + Make advapi32_test.exe loadable on NT 3.51. + + * tools/widl/typelib.c: Vincent Béron + A RPC_FC_ENUM16 is a VT_USERDEFINED. + + * dlls/setupapi/misc.c, dlls/setupapi/setupapi.spec, + include/setupapi.h: + Eric Kohl + Implement DelayedMove and FileExists. + + * programs/winedbg/info.c: Oliver Stieber + Mention bt [all | ]. + + * dlls/gdi/tests/brush.c: Rémi Assailly + Small char -> const char fix. + + * dlls/shell32/shlexec.c: Ge van Geldorp + Error numbers >= 32 are to be expected. + + * dlls/ntdll/time.c: Marcelo Duarte + - Correct time zone for BRT and BRST. + - Better explained fixme. + + * dlls/advpack/tests/Makefile.in, dlls/advpack/tests/advpack.c: + Francois Gouget + Load advpack.dll at runtime to avoid link problems with the platform + sdk. + + * dlls/winsock/tests/protocol.c: + Francois Gouget + Tests cannot use wine/debug.h because it does not exist on Windows. + + * dlls/user/tests/edit.c: Francois Gouget + ES_COMBO is not defined in the Windows headers. So define it if + necessary so the test can be compiled on Windows. + + * dlls/ole32/tests/marshal.c: Robert Shearman + Make Ole tests run on Windows 95. + + * programs/wcmd/builtins.c: + Jason Edmeades + Make 'exist' in wcmd handle both file and directories. + + * programs/winecfg/drivedetect.c, programs/winecfg/winecfg.h: + Michael Jung + Fixed automatic drive detection for the case that the root directory + is not already mapped. + + * dlls/winmm/tests/.cvsignore, dlls/winmm/tests/Makefile.in, + dlls/winmm/tests/timer.c, dlls/winmm/time.c: + Robert Reif + Added parameter checking to timeGetDevCaps. + Added timer tests. + + * dlls/commdlg/fontdlg.c: Mike Hearn + Respect the flags member of the CHOOSEFONT structure, and don't + attempt to process bogus strings. + +2005-02-11 Alexandre Julliard + + * VERSION, configure, ANNOUNCE, ChangeLog: Release 20050211. + +---------------------------------------------------------------- 2005-02-11 Alexandre Julliard * documentation/Makefile.in, documentation/compiling.sgml, diff -urN wine-20050211/Make.rules.in wine-20050310/Make.rules.in --- wine-20050211/Make.rules.in 2005-02-08 13:13:10.000000000 +0100 +++ wine-20050310/Make.rules.in 2005-03-08 17:55:26.000000000 +0100 @@ -131,10 +131,10 @@ $(WINDRES) -i $< -o $@ .spec.spec.c: - $(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $< + $(WINEBUILD) $(DEFS) --dll -o $@ --main-module $(MODULE) --export $< .spec.spec.def: - $(WINEBUILD) -w $(DEFS) -o $@ --def $< + $(WINEBUILD) -w $(DEFS) --def -o $@ --export $< .idl.h: $(WIDL) $(IDLFLAGS) -h -H $@ $< diff -urN wine-20050211/Makefile.in wine-20050310/Makefile.in --- wine-20050211/Makefile.in 2004-10-07 05:12:44.000000000 +0200 +++ wine-20050310/Makefile.in 2005-03-02 13:18:55.000000000 +0100 @@ -49,10 +49,10 @@ server # Sub-directories to install for install-dev -INSTALLDEVSUBDIRS = include tools +INSTALLDEVSUBDIRS = include # Sub-directories to install for both install-lib and install-dev -INSTALLBOTHSUBDIRS = dlls libs +INSTALLBOTHSUBDIRS = dlls libs tools INSTALLSUBDIRS = $(INSTALLDEVSUBDIRS) $(INSTALLLIBSUBDIRS) @@ -114,12 +114,12 @@ include: libs tools tools: libs -dlls/__install-lib__ dlls/__install-dev__: libs tools include/__install__ +dlls/__install-lib__ dlls/__install-dev__: libs tools include include/__install__: include libs tools libs/__install-lib__ libs/__install-dev__: libs fonts/__install__ loader/__install__ server/__install__: libs tools -programs/__install__: libs tools include/__install__ dlls/__install-lib__ -tools/__install__: tools +programs/__install__: libs tools include dlls/__install-lib__ +tools/__install-lib__ tools/__install-dev__: tools $(SUBDIRS:%=%/__depend__): tools include diff -urN wine-20050211/VERSION wine-20050310/VERSION --- wine-20050211/VERSION 2005-02-11 14:34:18.000000000 +0100 +++ wine-20050310/VERSION 2005-03-10 21:10:33.000000000 +0100 @@ -1 +1 @@ -Wine version 20050211 +Wine version 20050310 diff -urN wine-20050211/configure wine-20050310/configure --- wine-20050211/configure 2005-02-11 14:34:18.000000000 +0100 +++ wine-20050310/configure 2005-03-10 21:10:33.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for Wine 20050211. +# Generated by GNU Autoconf 2.59 for Wine 20050310. # # Report bugs to . # @@ -269,8 +269,8 @@ # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='20050211' -PACKAGE_STRING='Wine 20050211' +PACKAGE_VERSION='20050310' +PACKAGE_STRING='Wine 20050310' PACKAGE_BUGREPORT='wine-devel@winehq.org' ac_unique_file="server/atom.c" @@ -788,7 +788,7 @@ # 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 20050211 to adapt to many kinds of systems. +\`configure' configures Wine 20050310 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -853,7 +853,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 20050211:";; + short | recursive ) echo "Configuration of Wine 20050310:";; esac cat <<\_ACEOF @@ -984,7 +984,7 @@ test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -Wine configure 20050211 +Wine configure 20050310 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. @@ -998,7 +998,7 @@ 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 20050211, which was +It was created by Wine $as_me 20050310, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -7261,6 +7261,7 @@ + for ac_header in \ arpa/inet.h \ arpa/nameser.h \ @@ -7296,6 +7297,7 @@ netinet/tcp.h \ netinet/tcp_fsm.h \ openssl/ssl.h \ + poll.h \ process.h \ pthread.h \ pwd.h \ @@ -14109,7 +14111,7 @@ if test "$ac_cv_c_dll_macho" = "yes" then LIBEXT="dylib" - LDDLLFLAGS="-bundle -flat_namespace -undefined suppress" + LDDLLFLAGS="-bundle -flat_namespace -undefined suppress -read_only_relocs warning" LDSHARED="\$(CC) -dynamiclib" CFLAGS="$CFLAGS -ffixed-r13 -no-cpp-precomp" STRIP="$STRIP -u -r" @@ -14121,7 +14123,7 @@ IOKITLIB="-framework IOKit" - IOKITLIB = "$IOKITLIB $COREFOUNDATIONLIB" + IOKITLIB="$IOKITLIB $COREFOUNDATIONLIB" else echo "$as_me:$LINENO: checking whether we can build an HP-UX dll" >&5 echo $ECHO_N "checking whether we can build an HP-UX dll... $ECHO_C" >&6 @@ -19986,7 +19988,7 @@ MAKE_PROG_RULES=programs/Makeprog.rules - ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/advpack/Makefile dlls/advpack/tests/Makefile dlls/amstream/Makefile dlls/atl/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/cryptdll/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3drm/Makefile dlls/d3dx8/Makefile dlls/d3dxof/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/itss/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/lzexpand/tests/Makefile dlls/mapi32/Makefile dlls/mapi32/tests/Makefile dlls/mlang/Makefile dlls/mlang/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msacm/tests/Makefile dlls/mscms/Makefile dlls/mscms/tests/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msi/tests/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvcrtd/tests/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/ole32/tests/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/psapi/tests/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/quartz/tests/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/rsabase/tests/Makefile dlls/rsaenh/Makefile dlls/rsaenh/tests/Makefile dlls/secur32/Makefile dlls/sensapi/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/stdole32.tlb/Makefile dlls/sti/Makefile dlls/strmiids/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/wtsapi32/Makefile dlls/x11drv/Makefile documentation/Makefile fonts/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/msiexec/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" + ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/advpack/Makefile dlls/advpack/tests/Makefile dlls/amstream/Makefile dlls/atl/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/cryptdll/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3drm/Makefile dlls/d3dx8/Makefile dlls/d3dxof/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/itss/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/lzexpand/tests/Makefile dlls/mapi32/Makefile dlls/mapi32/tests/Makefile dlls/mlang/Makefile dlls/mlang/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msacm/tests/Makefile dlls/mscms/Makefile dlls/mscms/tests/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msi/tests/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvcrtd/tests/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/ole32/tests/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/psapi/tests/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/quartz/tests/Makefile dlls/rasapi32/Makefile dlls/riched20/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/rsabase/tests/Makefile dlls/rsaenh/Makefile dlls/rsaenh/tests/Makefile dlls/secur32/Makefile dlls/sensapi/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/stdole32.tlb/Makefile dlls/sti/Makefile dlls/strmiids/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/wtsapi32/Makefile dlls/x11drv/Makefile documentation/Makefile fonts/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/msiexec/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" cat >confcache <<\_ACEOF @@ -20351,7 +20353,7 @@ } >&5 cat >&5 <<_CSEOF -This file was extended by Wine $as_me 20050211, which was +This file was extended by Wine $as_me 20050310, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -20414,7 +20416,7 @@ cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 20050211 +Wine config.status 20050310 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" @@ -20648,6 +20650,7 @@ "dlls/quartz/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/quartz/Makefile" ;; "dlls/quartz/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/quartz/tests/Makefile" ;; "dlls/rasapi32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/rasapi32/Makefile" ;; + "dlls/riched20/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/riched20/Makefile" ;; "dlls/richedit/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/richedit/Makefile" ;; "dlls/rpcrt4/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/rpcrt4/Makefile" ;; "dlls/rpcrt4/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/rpcrt4/tests/Makefile" ;; diff -urN wine-20050211/configure.ac wine-20050310/configure.ac --- wine-20050211/configure.ac 2005-02-10 20:09:08.000000000 +0100 +++ wine-20050310/configure.ac 2005-03-05 12:19:14.000000000 +0100 @@ -199,6 +199,7 @@ netinet/tcp.h \ netinet/tcp_fsm.h \ openssl/ssl.h \ + poll.h \ process.h \ pthread.h \ pwd.h \ @@ -1005,7 +1006,7 @@ if test "$ac_cv_c_dll_macho" = "yes" then LIBEXT="dylib" - LDDLLFLAGS="-bundle -flat_namespace -undefined suppress" + LDDLLFLAGS="-bundle -flat_namespace -undefined suppress -read_only_relocs warning" LDSHARED="\$(CC) -dynamiclib" CFLAGS="$CFLAGS -ffixed-r13 -no-cpp-precomp" STRIP="$STRIP -u -r" @@ -1017,7 +1018,7 @@ AC_SUBST(COREFOUNDATIONLIB,"-framework CoreFoundation") AC_SUBST(IOKITLIB,"-framework IOKit") dnl using IOKit imply we use CoreFoundation too - IOKITLIB = "$IOKITLIB $COREFOUNDATIONLIB" + IOKITLIB="$IOKITLIB $COREFOUNDATIONLIB" else AC_CACHE_CHECK(whether we can build an HP-UX dll, ac_cv_c_dll_hpux, [WINE_TRY_SHLIB_FLAGS([-shared], ac_cv_c_dll_hpux="yes", ac_cv_c_dll_hpux="no")]) @@ -1633,6 +1634,7 @@ dlls/quartz/Makefile dlls/quartz/tests/Makefile dlls/rasapi32/Makefile +dlls/riched20/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile diff -urN wine-20050211/dlls/Makedll.rules.in wine-20050310/dlls/Makedll.rules.in --- wine-20050211/dlls/Makedll.rules.in 2005-01-07 18:15:47.000000000 +0100 +++ wine-20050310/dlls/Makedll.rules.in 2005-03-08 17:55:26.000000000 +0100 @@ -56,7 +56,7 @@ # Rule to explicitly generate the .spec.c for debugging $(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD) - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) + $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --export $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) # Rules for auto documentation diff -urN wine-20050211/dlls/Makefile.in wine-20050310/dlls/Makefile.in --- wine-20050211/dlls/Makefile.in 2005-01-28 15:13:08.000000000 +0100 +++ wine-20050310/dlls/Makefile.in 2005-03-05 12:19:14.000000000 +0100 @@ -108,6 +108,7 @@ qcap \ quartz \ rasapi32 \ + riched20 \ richedit \ rpcrt4 \ rsabase \ @@ -351,6 +352,7 @@ qcap.dll.so \ quartz.dll.so \ rasapi32.dll.so \ + riched20.dll.so \ riched32.dll.so \ rpcrt4.dll.so \ rsabase.dll.so \ @@ -781,6 +783,9 @@ rasapi16.dll.so : rasapi32.dll.so $(RM) $@ && $(LN_S) rasapi32.dll.so $@ +riched20.dll.so: riched20/riched20.dll.so + $(RM) $@ && $(LN_S) riched20/riched20.dll.so $@ + riched32.dll.so: richedit/riched32.dll.so $(RM) $@ && $(LN_S) richedit/riched32.dll.so $@ @@ -1092,6 +1097,7 @@ libqcap.$(IMPLIBEXT) \ libquartz.$(IMPLIBEXT) \ librasapi32.$(IMPLIBEXT) \ + libriched20.$(IMPLIBEXT) \ libriched32.$(IMPLIBEXT) \ librpcrt4.$(IMPLIBEXT) \ librsabase.$(IMPLIBEXT) \ @@ -1590,6 +1596,11 @@ librasapi32.a: rasapi32/rasapi32.spec.def $(DLLTOOL) -k -l $@ -d rasapi32/rasapi32.spec.def +libriched20.def: riched20/riched20.spec.def + $(RM) $@ && $(LN_S) riched20/riched20.spec.def $@ +libriched20.a: riched20/riched20.spec.def + $(DLLTOOL) -k -l $@ -d riched20/riched20.spec.def + libriched32.def: richedit/riched32.spec.def $(RM) $@ && $(LN_S) richedit/riched32.spec.def $@ libriched32.a: richedit/riched32.spec.def @@ -1880,6 +1891,7 @@ qcap/qcap.spec.def: $(WINEBUILD) quartz/quartz.spec.def: $(WINEBUILD) rasapi32/rasapi32.spec.def: $(WINEBUILD) +riched20/riched20.spec.def: $(WINEBUILD) richedit/riched32.spec.def: $(WINEBUILD) rpcrt4/rpcrt4.spec.def: $(WINEBUILD) rsabase/rsabase.spec.def: $(WINEBUILD) @@ -2032,6 +2044,7 @@ qcap/qcap.dll.so: qcap quartz/quartz.dll.so: quartz rasapi32/rasapi32.dll.so: rasapi32 +riched20/riched20.dll.so: riched20 richedit/riched32.dll.so: richedit rpcrt4/rpcrt4.dll.so: rpcrt4 rsabase/rsabase.dll.so: rsabase diff -urN wine-20050211/dlls/advapi32/advapi32.spec wine-20050310/dlls/advapi32/advapi32.spec --- wine-20050211/dlls/advapi32/advapi32.spec 2005-01-03 21:10:45.000000000 +0100 +++ wine-20050310/dlls/advapi32/advapi32.spec 2005-03-07 12:00:24.000000000 +0100 @@ -288,7 +288,7 @@ @ stdcall SetSecurityDescriptorGroup (ptr ptr long) @ stdcall SetSecurityDescriptorOwner (ptr ptr long) @ stdcall SetSecurityDescriptorSacl(ptr long ptr long) -@ stub SetSecurityInfo #(ptr long ptr ptr ptr ptr ptr ptr) +@ stdcall SetSecurityInfo (long long long ptr ptr ptr ptr) @ stdcall SetServiceBits(long long long long) @ stdcall SetServiceObjectSecurity(long long ptr) @ stdcall SetServiceStatus(long long) diff -urN wine-20050211/dlls/advapi32/registry.c wine-20050310/dlls/advapi32/registry.c --- wine-20050211/dlls/advapi32/registry.c 2005-01-07 16:40:09.000000000 +0100 +++ wine-20050310/dlls/advapi32/registry.c 2005-02-25 17:52:10.000000000 +0100 @@ -344,6 +344,11 @@ */ DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, PHKEY retkey ) { + if (!name || !*name) + { + *retkey = hkey; + return ERROR_SUCCESS; + } return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey ); } @@ -364,6 +369,11 @@ */ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, PHKEY retkey ) { + if (!name || !*name) + { + *retkey = hkey; + return ERROR_SUCCESS; + } return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey ); } @@ -845,7 +855,8 @@ */ DWORD WINAPI RegCloseKey( HKEY hkey ) { - if (!hkey || hkey >= (HKEY)0x80000000) return ERROR_SUCCESS; + if (!hkey) return ERROR_INVALID_HANDLE; + if (hkey >= (HKEY)0x80000000) return ERROR_SUCCESS; return RtlNtStatusToDosError( NtClose( hkey ) ); } diff -urN wine-20050211/dlls/advapi32/security.c wine-20050310/dlls/advapi32/security.c --- wine-20050211/dlls/advapi32/security.c 2005-02-11 12:52:07.000000000 +0100 +++ wine-20050310/dlls/advapi32/security.c 2005-03-07 12:00:24.000000000 +0100 @@ -57,6 +57,8 @@ DWORD value; } ACEFLAG, *LPACEFLAG; +static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } }; + /* * ACE access rights */ @@ -111,6 +113,25 @@ } } +#define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD)) + +static void GetWorldAccessACL(PACL pACL) +{ + PACCESS_ALLOWED_ACE pACE = (PACCESS_ALLOWED_ACE) (pACL + 1); + + pACL->AclRevision = ACL_REVISION; + pACL->Sbz1 = 0; + pACL->AclSize = WINE_SIZE_OF_WORLD_ACCESS_ACL; + pACL->AceCount = 1; + pACL->Sbz2 = 0; + + pACE->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; + pACE->Header.AceFlags = CONTAINER_INHERIT_ACE; + pACE->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD); + pACE->Mask = 0xf3ffffff; /* Everything except reserved bits */ + memcpy(&pACE->SidStart, &sidWorld, sizeof(sidWorld)); +} + /************************************************************ * ADVAPI_IsLocalComputer * @@ -1297,8 +1318,61 @@ PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded ) { - FIXME("(%s) : stub\n", debugstr_w(lpFileName) ); - return TRUE; + DWORD nNeeded; + LPBYTE pBuffer; + DWORD iLocNow; + SECURITY_DESCRIPTOR_RELATIVE *pSDRelative; + + FIXME("(%s) : returns fake SECURITY_DESCRIPTOR\n", debugstr_w(lpFileName) ); + + nNeeded = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + if (RequestedInformation & OWNER_SECURITY_INFORMATION) + nNeeded += sizeof(sidWorld); + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + nNeeded += sizeof(sidWorld); + if (RequestedInformation & DACL_SECURITY_INFORMATION) + nNeeded += WINE_SIZE_OF_WORLD_ACCESS_ACL; + if (RequestedInformation & SACL_SECURITY_INFORMATION) + nNeeded += WINE_SIZE_OF_WORLD_ACCESS_ACL; + + *lpnLengthNeeded = nNeeded; + + if (nNeeded > nLength) + return TRUE; + + if (!InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) + return FALSE; + + pSDRelative = (PISECURITY_DESCRIPTOR_RELATIVE) pSecurityDescriptor; + pSDRelative->Control |= SE_SELF_RELATIVE; + pBuffer = (LPBYTE) pSDRelative; + iLocNow = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + + if (RequestedInformation & OWNER_SECURITY_INFORMATION) + { + memcpy(pBuffer + iLocNow, &sidWorld, sizeof(sidWorld)); + pSDRelative->Owner = iLocNow; + iLocNow += sizeof(sidWorld); + } + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + { + memcpy(pBuffer + iLocNow, &sidWorld, sizeof(sidWorld)); + pSDRelative->Group = iLocNow; + iLocNow += sizeof(sidWorld); + } + if (RequestedInformation & DACL_SECURITY_INFORMATION) + { + GetWorldAccessACL((PACL) (pBuffer + iLocNow)); + pSDRelative->Dacl = iLocNow; + iLocNow += WINE_SIZE_OF_WORLD_ACCESS_ACL; + } + if (RequestedInformation & SACL_SECURITY_INFORMATION) + { + GetWorldAccessACL((PACL) (pBuffer + iLocNow)); + pSDRelative->Sacl = iLocNow; + /* iLocNow += WINE_SIZE_OF_WORLD_ACCESS_ACL; */ + } + return TRUE; } @@ -3242,3 +3316,13 @@ FIXME("%s\n", debugstr_a(lpFileName)); return TRUE; } + +/****************************************************************************** + * SetSecurityInfo [ADVAPI32.@] + */ +DWORD SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, + SECURITY_INFORMATION SecurityInfo, PSID psidOwner, + PSID psidGroup, PACL pDacl, PACL pSacl) { + FIXME("stub\n"); + return ERROR_SUCCESS; +} diff -urN wine-20050211/dlls/advapi32/service.c wine-20050310/dlls/advapi32/service.c --- wine-20050211/dlls/advapi32/service.c 2005-01-24 20:33:43.000000000 +0100 +++ wine-20050310/dlls/advapi32/service.c 2005-03-10 12:14:04.000000000 +0100 @@ -1655,15 +1655,15 @@ if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) total += sz; + *pcbBytesNeeded = total; + /* if there's not enough memory, return an error */ - if( total > *pcbBytesNeeded ) + if( total > cbBufSize ) { - *pcbBytesNeeded = total; SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - *pcbBytesNeeded = total; ZeroMemory( lpServiceConfig, total ); sz = sizeof val; @@ -1792,6 +1792,8 @@ r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz ); if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) ) total += sz; + else + total += sizeof(WCHAR); sz = 0; r = RegQueryValueExW( hKey, szStart, 0, &type, NULL, &sz ); @@ -1803,15 +1805,15 @@ if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) total += sz; + *pcbBytesNeeded = total; + /* if there's not enough memory, return an error */ - if( total > *pcbBytesNeeded ) + if( total > cbBufSize ) { - *pcbBytesNeeded = total; SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - *pcbBytesNeeded = total; ZeroMemory( lpServiceConfig, total ); sz = sizeof val; @@ -1862,12 +1864,18 @@ sz = n; r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz ); + lpServiceConfig->lpDependencies = (LPWSTR) p; if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) { - lpServiceConfig->lpDependencies = (LPWSTR) p; p += sz; n -= sz; } + else + { + *(WCHAR *) p = 0; + p += sizeof(WCHAR); + n -= sizeof(WCHAR); + } if( n < 0 ) ERR("Buffer overflow!\n"); diff -urN wine-20050211/dlls/advapi32/tests/crypt.c wine-20050310/dlls/advapi32/tests/crypt.c --- wine-20050211/dlls/advapi32/tests/crypt.c 2005-02-10 20:19:36.000000000 +0100 +++ wine-20050310/dlls/advapi32/tests/crypt.c 2005-02-23 13:44:15.000000000 +0100 @@ -35,9 +35,11 @@ #define NON_DEF_PROV_TYPE 999 static HMODULE hadvapi32; +static BOOL (WINAPI *pCryptAcquireContextA)(HCRYPTPROV*,LPCSTR,LPCSTR,DWORD,DWORD); static BOOL (WINAPI *pCryptEnumProviderTypesA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*); static BOOL (WINAPI *pCryptEnumProvidersA)(DWORD, DWORD*, DWORD, DWORD*, LPSTR, DWORD*); static BOOL (WINAPI *pCryptGetDefaultProviderA)(DWORD, DWORD*, DWORD, LPSTR, DWORD*); +static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV, DWORD); static BOOL (WINAPI *pCryptSetProviderExA)(LPCSTR, DWORD, DWORD*, DWORD); static void init_function_pointers(void) @@ -46,9 +48,11 @@ if(hadvapi32) { + pCryptAcquireContextA = (void*)GetProcAddress(hadvapi32, "CryptAcquireContextA"); pCryptEnumProviderTypesA = (void*)GetProcAddress(hadvapi32, "CryptEnumProviderTypesA"); pCryptEnumProvidersA = (void*)GetProcAddress(hadvapi32, "CryptEnumProvidersA"); pCryptGetDefaultProviderA = (void*)GetProcAddress(hadvapi32, "CryptGetDefaultProviderA"); + pCryptReleaseContext = (void*)GetProcAddress(hadvapi32, "CryptReleaseContext"); pCryptSetProviderExA = (void*)GetProcAddress(hadvapi32, "CryptSetProviderExA"); } } @@ -59,24 +63,24 @@ HCRYPTPROV hProv; /* Ensure that container "wine_test_keyset" does exist */ - if (!CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) + if (!pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) { - CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_NEWKEYSET); + pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_NEWKEYSET); } - CryptReleaseContext(hProv, 0); + pCryptReleaseContext(hProv, 0); /* Ensure that container "wine_test_keyset" does exist in default PROV_RSA_FULL type provider */ - if (!CryptAcquireContext(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0)) + if (!pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0)) { - CryptAcquireContext(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); + pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); } - CryptReleaseContext(hProv, 0); + pCryptReleaseContext(hProv, 0); /* Ensure that container "wine_test_bad_keyset" does not exist. */ - if (CryptAcquireContext(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) + if (pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) { - CryptReleaseContext(hProv, 0); - CryptAcquireContext(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + pCryptReleaseContext(hProv, 0); + pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } } @@ -85,17 +89,17 @@ HCRYPTPROV hProv; /* Remove container "wine_test_keyset" */ - if (CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) + if (pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) { - CryptReleaseContext(hProv, 0); - CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + pCryptReleaseContext(hProv, 0); + pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } /* Remove container "wine_test_keyset" from default PROV_RSA_FULL type provider */ - if (CryptAcquireContext(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0)) + if (pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, 0)) { - CryptReleaseContext(hProv, 0); - CryptAcquireContext(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + pCryptReleaseContext(hProv, 0); + pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } } @@ -108,45 +112,45 @@ * The order of the error tests seems to match Windows XP's rsaenh.dll CSP, * but since this is likely to change between CSP versions, we don't check * this. Please don't change the order of tests. */ - result = CryptAcquireContext(&hProv, NULL, NULL, 0, 0); + result = pCryptAcquireContextA(&hProv, NULL, NULL, 0, 0); ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError()); - result = CryptAcquireContext(&hProv, NULL, NULL, 1000, 0); + result = pCryptAcquireContextA(&hProv, NULL, NULL, 1000, 0); ok(!result && GetLastError()==NTE_BAD_PROV_TYPE, "%ld\n", GetLastError()); - result = CryptAcquireContext(&hProv, NULL, NULL, NON_DEF_PROV_TYPE, 0); + result = pCryptAcquireContextA(&hProv, NULL, NULL, NON_DEF_PROV_TYPE, 0); ok(!result && GetLastError()==NTE_PROV_TYPE_NOT_DEF, "%ld\n", GetLastError()); - result = CryptAcquireContext(&hProv, szKeySet, szNonExistentProv, PROV_RSA_FULL, 0); + result = pCryptAcquireContextA(&hProv, szKeySet, szNonExistentProv, PROV_RSA_FULL, 0); ok(!result && GetLastError()==NTE_KEYSET_NOT_DEF, "%ld\n", GetLastError()); - result = CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, NON_DEF_PROV_TYPE, 0); + result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, NON_DEF_PROV_TYPE, 0); ok(!result && GetLastError()==NTE_PROV_TYPE_NO_MATCH, "%ld\n", GetLastError()); /* This test fails under Win2k SP4: result = TRUE, GetLastError() == ERROR_INVALID_PARAMETER SetLastError(0xdeadbeef); - result = CryptAcquireContext(NULL, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0); + result = pCryptAcquireContextA(NULL, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0); ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%d/%ld\n", result, GetLastError()); */ /* Last not least, try to really acquire a context. */ hProv = 0; SetLastError(0xdeadbeef); - result = CryptAcquireContext(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0); - ok(result && (GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE), "%d/%ld\n", result, GetLastError()); + result = pCryptAcquireContextA(&hProv, szKeySet, szRsaBaseProv, PROV_RSA_FULL, 0); + ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE), "%d/%ld\n", result, GetLastError()); if (hProv) - CryptReleaseContext(hProv, 0); + pCryptReleaseContext(hProv, 0); /* Try again, witch an empty ("\0") szProvider parameter */ hProv = 0; SetLastError(0xdeadbeef); - result = CryptAcquireContext(&hProv, szKeySet, "", PROV_RSA_FULL, 0); - ok(result && (GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE), "%d/%ld\n", result, GetLastError()); + result = pCryptAcquireContextA(&hProv, szKeySet, "", PROV_RSA_FULL, 0); + ok(result && (GetLastError() == ERROR_ENVVAR_NOT_FOUND || GetLastError() == ERROR_SUCCESS || GetLastError() == ERROR_RING2_STACK_IN_USE), "%d/%ld\n", result, GetLastError()); if (hProv) - CryptReleaseContext(hProv, 0); + pCryptReleaseContext(hProv, 0); } static BOOL FindProvRegVals(DWORD dwIndex, DWORD *pdwProvType, LPSTR *pszProvName, @@ -558,9 +562,11 @@ START_TEST(crypt) { init_function_pointers(); + if(pCryptAcquireContextA && pCryptReleaseContext) { init_environment(); test_acquire_context(); clean_up_environment(); + } test_enum_providers(); test_enum_provider_types(); diff -urN wine-20050211/dlls/advapi32/tests/registry.c wine-20050310/dlls/advapi32/tests/registry.c --- wine-20050211/dlls/advapi32/tests/registry.c 2005-01-27 12:15:00.000000000 +0100 +++ wine-20050310/dlls/advapi32/tests/registry.c 2005-02-25 17:52:10.000000000 +0100 @@ -254,12 +254,104 @@ ok(type == REG_SZ, "type %ld is not REG_SZ\n", type); } +static void test_reg_open_key() +{ + DWORD ret = 0; + HKEY hkResult = NULL; + HKEY hkPreserve = NULL; + + /* successful open */ + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + hkPreserve = hkResult; + + /* open same key twice */ + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(hkResult != hkPreserve && hkResult != NULL, + "expected hkResult != hkPreserve and hkResult != NULL\n"); + RegCloseKey(hkResult); + + /* open nonexistent key + * check that hkResult is set to NULL + */ + hkResult = hkPreserve; + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult); + ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret); + ok(hkResult == NULL, "expected hkResult == NULL\n"); + + /* open the same nonexistent key again to make sure the key wasn't created */ + hkResult = hkPreserve; + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult); + ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret); + ok(hkResult == NULL, "expected hkResult == NULL\n"); + + /* send in NULL lpSubKey + * check that hkResult receives the value of hKey + */ + hkResult = hkPreserve; + ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n"); + + /* send empty-string in lpSubKey */ + hkResult = hkPreserve; + ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n"); + + /* send in NULL lpSubKey and NULL hKey + * hkResult is set to NULL + */ + hkResult = hkPreserve; + ret = RegOpenKeyA(NULL, NULL, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(hkResult == NULL, "expected hkResult == NULL\n"); + + /* only send NULL hKey + * the value of hkResult remains unchanged + */ + hkResult = hkPreserve; + ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult); + ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret); + ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n"); + RegCloseKey(hkResult); + + /* send in NULL hkResult */ + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL); + ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret); +} + +static void test_reg_close_key() +{ + DWORD ret = 0; + HKEY hkHandle; + + /* successfully close key + * hkHandle remains changed after call to RegCloseKey + */ + ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle); + ret = RegCloseKey(hkHandle); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + + /* try to close the key twice */ + ret = RegCloseKey(hkHandle); + ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret); + + /* try to close a NULL handle */ + ret = RegCloseKey(NULL); + ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret); +} + START_TEST(registry) { setup_main_key(); create_test_entries(); test_enum_value(); test_query_value_ex(); + test_reg_open_key(); + test_reg_close_key(); /* cleanup */ delete_key( hkey_main ); diff -urN wine-20050211/dlls/advapi32/tests/security.c wine-20050310/dlls/advapi32/tests/security.c --- wine-20050211/dlls/advapi32/tests/security.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050310/dlls/advapi32/tests/security.c 2005-03-05 11:47:13.000000000 +0100 @@ -27,11 +27,15 @@ #include "aclapi.h" #include "winnt.h" +typedef BOOL (WINAPI *fnBuildTrusteeWithSidA)( TRUSTEE *trustee, PSID psid ); +typedef BOOL (WINAPI *fnBuildTrusteeWithNameA)( TRUSTEE *trustee, LPSTR str ); typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str ); typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid ); static HMODULE hmod; +fnBuildTrusteeWithSidA pBuildTrusteeWithSidA; +fnBuildTrusteeWithNameA pBuildTrusteeWithNameA; fnConvertSidToStringSidA pConvertSidToStringSidA; fnConvertStringSidToSidA pConvertStringSidToSidA; @@ -143,6 +147,13 @@ SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} }; + pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA) + GetProcAddress( hmod, "BuildTrusteeWithSidA" ); + pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA) + GetProcAddress( hmod, "BuildTrusteeWithNameA" ); + if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA) + return; + if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) ) { trace( "failed to init SID\n" ); @@ -150,7 +161,7 @@ } memset( &trustee, 0xff, sizeof trustee ); - BuildTrusteeWithSidA( &trustee, psid ); + pBuildTrusteeWithSidA( &trustee, psid ); ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, @@ -162,7 +173,7 @@ /* test BuildTrusteeWithNameA */ memset( &trustee, 0xff, sizeof trustee ); - BuildTrusteeWithNameA( &trustee, str ); + pBuildTrusteeWithNameA( &trustee, str ); ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n"); ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, @@ -213,7 +224,7 @@ LUID luid1, luid2; BOOL ret; - pAllocateLocallyUniqueId = GetProcAddress(hmod, "AllocateLocallyUniqueId"); + pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId"); if (!pAllocateLocallyUniqueId) return; ret = pAllocateLocallyUniqueId(&luid1); @@ -245,7 +256,7 @@ BOOL ret; /* check whether it's available first */ - pLookupPrivilegeNameA = GetProcAddress(hmod, "LookupPrivilegeNameA"); + pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA"); if (!pLookupPrivilegeNameA) return; luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE; ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName); @@ -269,14 +280,14 @@ cchName == strlen("SeCreateTokenPrivilege"), "LookupPrivilegeNameA returned an incorrect output length for\n" "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName, - strlen("SeCreateTokenPrivilege")); + (int)strlen("SeCreateTokenPrivilege")); /* check known values */ for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++) { luid.LowPart = i; cchName = sizeof(buf); ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName); - ok( ret, + ok( ret && GetLastError() != ERROR_NO_SUCH_PRIVILEGE, "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i, GetLastError()); } /* check a bogus LUID */ @@ -298,7 +309,7 @@ struct NameToLUID { const char *name; - LONG lowPart; + DWORD lowPart; }; static void test_lookupPrivilegeValue(void) @@ -340,7 +351,7 @@ BOOL ret; /* check whether it's available first */ - pLookupPrivilegeValueA = GetProcAddress(hmod, "LookupPrivilegeValueA"); + pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA"); if (!pLookupPrivilegeValueA) return; ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid); if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) diff -urN wine-20050211/dlls/advpack/tests/Makefile.in wine-20050310/dlls/advpack/tests/Makefile.in --- wine-20050211/dlls/advpack/tests/Makefile.in 2005-01-20 21:03:13.000000000 +0100 +++ wine-20050310/dlls/advpack/tests/Makefile.in 2005-02-14 12:02:46.000000000 +0100 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = advpack.dll -IMPORTS = advpack user32 kernel32 +IMPORTS = user32 kernel32 CTESTS = \ advpack.c diff -urN wine-20050211/dlls/advpack/tests/advpack.c wine-20050310/dlls/advpack/tests/advpack.c --- wine-20050211/dlls/advpack/tests/advpack.c 2005-01-20 21:03:13.000000000 +0100 +++ wine-20050310/dlls/advpack/tests/advpack.c 2005-02-14 12:02:46.000000000 +0100 @@ -18,12 +18,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define NONAMELESSSTRUCT -#define NONAMELESSUNION #include +#include #include "wine/test.h" -#include "advpub.h" + + +static HRESULT (WINAPI *pGetVersionFromFile)(LPSTR,LPDWORD,LPDWORD,BOOL); + static void version_test() { @@ -31,7 +33,7 @@ DWORD major, minor; major = minor = 0; - hr = GetVersionFromFile("kernel32.dll", &major, &minor, FALSE); + hr = pGetVersionFromFile("kernel32.dll", &major, &minor, FALSE); ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " "0x%08lx\n", hr); @@ -39,7 +41,7 @@ major, minor); major = minor = 0; - hr = GetVersionFromFile("kernel32.dll", &major, &minor, TRUE); + hr = pGetVersionFromFile("kernel32.dll", &major, &minor, TRUE); ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " "0x%08lx\n", hr); @@ -49,5 +51,14 @@ START_TEST(advpack) { + HMODULE hdll; + + hdll = LoadLibraryA("advpack.dll"); + if (!hdll) + return; + pGetVersionFromFile = (void*)GetProcAddress(hdll, "GetVersionFromFile"); + if (!pGetVersionFromFile) + return; + version_test(); } diff -urN wine-20050211/dlls/atl/atl.spec wine-20050310/dlls/atl/atl.spec --- wine-20050211/dlls/atl/atl.spec 2005-01-19 18:00:32.000000000 +0100 +++ wine-20050310/dlls/atl/atl.spec 2005-03-07 12:02:31.000000000 +0100 @@ -1,5 +1,5 @@ 1 stub DllCanUnloadNow -2 stub DllGetClassObject +2 stdcall -private DllGetClassObject(ptr ptr ptr) ATL_DllGetClassObject 3 stdcall -private DllRegisterServer() ATL_DllRegisterServer 4 stdcall -private DllUnregisterServer() ATL_DllUnregisterServer 10 stdcall AtlAdvise(ptr ptr ptr ptr) diff -urN wine-20050211/dlls/atl/regsvr.c wine-20050310/dlls/atl/regsvr.c --- wine-20050211/dlls/atl/regsvr.c 2004-08-30 21:30:17.000000000 +0200 +++ wine-20050310/dlls/atl/regsvr.c 2005-03-07 12:02:31.000000000 +0100 @@ -554,3 +554,16 @@ hr = unregister_interfaces(interface_list); return hr; } + +/*********************************************************************** + * DllGetClassObject (ATL.@) + */ +HRESULT WINAPI ATL_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + if (IsEqualCLSID (rclsid, &CLSID_ATLRegistrar)) { + FIXME("No COM Class for ATLRegistrar\n"); + return CLASS_E_CLASSNOTAVAILABLE; + } + FIXME("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + return CLASS_E_CLASSNOTAVAILABLE; +} diff -urN wine-20050211/dlls/avifil32/avifile_Es.rc wine-20050310/dlls/avifil32/avifile_Es.rc --- wine-20050211/dlls/avifil32/avifile_Es.rc 2004-08-24 20:33:04.000000000 +0200 +++ wine-20050310/dlls/avifil32/avifile_Es.rc 2005-02-16 22:11:01.000000000 +0100 @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL IDD_SAVEOPTIONS DIALOG FIXED IMPURE 43, 37, 196, 82 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU diff -urN wine-20050211/dlls/comctl32/comctl32.spec wine-20050310/dlls/comctl32/comctl32.spec --- wine-20050211/dlls/comctl32/comctl32.spec 2004-10-20 00:59:59.000000000 +0200 +++ wine-20050310/dlls/comctl32/comctl32.spec 2005-02-23 16:41:14.000000000 +0100 @@ -101,10 +101,10 @@ 402 stdcall -noname FindMRUStringW(long wstr ptr) 403 stdcall -noname EnumMRUListW(long long ptr long) 404 stdcall -noname CreateMRUListLazyW(ptr long long long) -410 stdcall SetWindowSubclass(long ptr long long) -411 stdcall GetWindowSubclass(long ptr long ptr) -412 stdcall RemoveWindowSubclass(long ptr long) -413 stdcall DefSubclassProc(long long long long) +410 stdcall -noname SetWindowSubclass(long ptr long long) +411 stdcall -noname GetWindowSubclass(long ptr long ptr) +412 stdcall -noname RemoveWindowSubclass(long ptr long) +413 stdcall -noname DefSubclassProc(long long long long) 414 stdcall -noname MirrorIcon(ptr ptr) 415 stdcall -noname DrawTextWrap(long wstr long ptr long) user32.DrawTextW 416 stdcall -noname DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW diff -urN wine-20050211/dlls/comctl32/comctl_Es.rc wine-20050310/dlls/comctl32/comctl_Es.rc --- wine-20050211/dlls/comctl32/comctl_Es.rc 2004-09-20 21:13:36.000000000 +0200 +++ wine-20050310/dlls/comctl32/comctl_Es.rc 2005-02-16 22:11:01.000000000 +0100 @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE diff -urN wine-20050211/dlls/comctl32/draglist.c wine-20050310/dlls/comctl32/draglist.c --- wine-20050211/dlls/comctl32/draglist.c 2004-09-14 03:06:11.000000000 +0200 +++ wine-20050310/dlls/comctl32/draglist.c 2005-03-03 14:51:47.000000000 +0100 @@ -42,10 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(commctrl); -/* for compiler compatibility we only accept literal ASCII strings */ -#undef TEXT -#define TEXT(string) string - #define DRAGLIST_SUBCLASSID 0 #define DRAGLIST_SCROLLPERIOD 200 #define DRAGLIST_TIMERID 666 @@ -95,7 +91,7 @@ } /* cleans up after dragging */ -static inline void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data) +static void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data) { KillTimer(hwnd, DRAGLIST_TIMERID); ReleaseCapture(); @@ -207,12 +203,12 @@ */ BOOL WINAPI MakeDragList (HWND hwndLB) { - DRAGLISTDATA * data = Alloc(sizeof(DRAGLISTDATA)); + DRAGLISTDATA *data = Alloc(sizeof(DRAGLISTDATA)); TRACE("(%p)\n", hwndLB); if (!uDragListMessage) - uDragListMessage = RegisterWindowMessageA(DRAGLISTMSGSTRING); + uDragListMessage = RegisterWindowMessageW(DRAGLISTMSGSTRINGW); return SetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR)data); } @@ -301,14 +297,14 @@ ScreenToClient (hwndLB, &pt); GetClientRect (hwndLB, &rcClient); - nIndex = (INT)SendMessageA (hwndLB, LB_GETTOPINDEX, 0, 0); + nIndex = (INT)SendMessageW (hwndLB, LB_GETTOPINDEX, 0, 0); if (PtInRect (&rcClient, pt)) { /* point is inside -- get the item index */ while (TRUE) { - if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR) + if (SendMessageW (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR) return -1; if (PtInRect (&rcClient, pt)) @@ -338,7 +334,7 @@ dwLastScrollTime = dwScrollTime; - SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0); + SendMessageW (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0); } return -1; diff -urN wine-20050211/dlls/comctl32/header.c wine-20050310/dlls/comctl32/header.c --- wine-20050211/dlls/comctl32/header.c 2005-01-10 15:25:30.000000000 +0100 +++ wine-20050310/dlls/comctl32/header.c 2005-02-23 13:41:43.000000000 +0100 @@ -324,9 +324,19 @@ } else tx = 0; - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left + tx + 2*infoPtr->iMargin, - r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, infoPtr->himl->cx, r.bottom-r.top, - CLR_DEFAULT, CLR_DEFAULT, 0); + + if (tx < (r.right-r.left - infoPtr->himl->cx - GetSystemMetrics(SM_CXEDGE))) + ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left + tx + 2*infoPtr->iMargin, + r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, infoPtr->himl->cx, r.bottom-r.top, + CLR_DEFAULT, CLR_DEFAULT, 0); + else { + INT x = max(r.right - infoPtr->iMargin - infoPtr->himl->cx, r.left); + INT cx = min(infoPtr->himl->cx, r.right-r.left - GetSystemMetrics(SM_CXEDGE)); + ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, x , + r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, cx, r.bottom-r.top, + CLR_DEFAULT, CLR_DEFAULT, 0); + r.right -= infoPtr->himl->cx - infoPtr->iMargin; + } } if (((phdi->fmt & HDF_STRING) @@ -1203,10 +1213,8 @@ { lpItem->iOrder = phdi->iOrder; } - else - lpItem->iOrder = nItem; - HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem, phdi->mask); + HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem, phdi->mask); HEADER_SetItemBounds (hwnd); @@ -1270,10 +1278,8 @@ { lpItem->iOrder = phdi->iOrder; } - else - lpItem->iOrder = nItem; - HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDW, nItem, phdi->mask); + HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDW, nItem, phdi->mask); HEADER_SetItemBounds (hwnd); diff -urN wine-20050211/dlls/comctl32/imagelist.c wine-20050310/dlls/comctl32/imagelist.c --- wine-20050211/dlls/comctl32/imagelist.c 2005-01-10 15:29:20.000000000 +0100 +++ wine-20050310/dlls/comctl32/imagelist.c 2005-02-24 13:46:57.000000000 +0100 @@ -1577,84 +1577,28 @@ * * Creates an image list from a bitmap, icon or cursor. * - * PARAMS - * hi [I] instance handle - * lpbmp [I] name or id of the image - * cx [I] width of each image - * cGrow [I] number of images to expand - * clrMask [I] mask color - * uType [I] type of image to load - * uFlags [I] loading flags - * - * RETURNS - * Success: handle to the loaded image list - * Failure: NULL - * * SEE - * LoadImage () + * ImageList_LoadImageW () */ HIMAGELIST WINAPI ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow, COLORREF clrMask, UINT uType, UINT uFlags) { - HIMAGELIST himl = NULL; - HANDLE handle; - INT nImageCount; - - handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags); - if (!handle) { - ERR("Error loading image!\n"); - return NULL; - } - - if (uType == IMAGE_BITMAP) { - BITMAP bmp; - GetObjectA (handle, sizeof(BITMAP), &bmp); - - /* To match windows behavior, if cx is set to zero and - the flag DI_DEFAULTSIZE is specified, cx becomes the - system metric value for icons. If the flag is not specified - the function sets the size to the height of the bitmap */ - if (cx == 0) - { - if (uFlags & DI_DEFAULTSIZE) - cx = GetSystemMetrics (SM_CXICON); - else - cx = bmp.bmHeight; - } - - nImageCount = bmp.bmWidth / cx; - - himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR, - nImageCount, cGrow); - if (!himl) { - DeleteObject (handle); - return NULL; - } - ImageList_AddMasked (himl, (HBITMAP)handle, clrMask); - } - else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) { - ICONINFO ii; - BITMAP bmp; - - GetIconInfo (handle, &ii); - GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp); - himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, - ILC_MASK | ILC_COLOR, 1, cGrow); - if (!himl) { - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - DeleteObject (handle); - return NULL; - } - ImageList_Add (himl, ii.hbmColor, ii.hbmMask); - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - } - - DeleteObject (handle); + HIMAGELIST himl; + LPWSTR lpbmpW; + DWORD len; + + if (!HIWORD(lpbmp)) + return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask, + uType, uFlags); + + len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0); + lpbmpW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len); + himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags); + HeapFree(GetProcessHeap(), 0, lpbmpW); return himl; } @@ -1683,7 +1627,7 @@ HIMAGELIST WINAPI ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow, - COLORREF clrMask, UINT uType, UINT uFlags) + COLORREF clrMask, UINT uType, UINT uFlags) { HIMAGELIST himl = NULL; HANDLE handle; @@ -1726,7 +1670,7 @@ BITMAP bmp; GetIconInfo (handle, &ii); - GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); + GetObjectW (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp); himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, ILC_MASK | ILC_COLOR, 1, cGrow); if (!himl) { diff -urN wine-20050211/dlls/comctl32/listview.c wine-20050310/dlls/comctl32/listview.c --- wine-20050211/dlls/comctl32/listview.c 2005-01-26 22:09:05.000000000 +0100 +++ wine-20050310/dlls/comctl32/listview.c 2005-02-21 21:38:31.000000000 +0100 @@ -6274,7 +6274,7 @@ if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush); infoPtr->clrBk = clrBk; if (clrBk == CLR_NONE) - infoPtr->hBkBrush = (HBRUSH)GetClassLongW(infoPtr->hwndSelf, GCL_HBRBACKGROUND); + infoPtr->hBkBrush = (HBRUSH)GetClassLongPtrW(infoPtr->hwndSelf, GCLP_HBRBACKGROUND); else infoPtr->hBkBrush = CreateSolidBrush(clrBk); LISTVIEW_InvalidateList(infoPtr); @@ -8249,6 +8249,7 @@ lpColumnInfo->rcHeader.right += dx; LISTVIEW_ScrollColumns(infoPtr, lpnmh->iItem + 1, dx); + LISTVIEW_UpdateItemSize(infoPtr); if (uView == LVS_REPORT && is_redrawing(infoPtr)) { /* this trick works for left aligned columns only */ diff -urN wine-20050211/dlls/comctl32/rebar.c wine-20050310/dlls/comctl32/rebar.c --- wine-20050211/dlls/comctl32/rebar.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050310/dlls/comctl32/rebar.c 2005-03-02 14:53:52.000000000 +0100 @@ -134,7 +134,7 @@ SIZE offChild; /* x,y offset if child is not FIXEDSIZE */ UINT uMinHeight; - INT iRow; /* row this band assigned to */ + INT iRow; /* zero-based index of the row this band assigned to */ UINT fStatus; /* status flags, reset only by _Validate */ UINT fDraw; /* drawing flags, reset only by _Layout */ UINT uCDret; /* last return from NM_CUSTOMDRAW */ @@ -360,8 +360,14 @@ REBAR_DumpBandInfo( LPREBARBANDINFOA pB) { if( !TRACE_ON(rebar) ) return; - TRACE("band info: ID=%u, size=%u, child=%p, clrF=0x%06lx, clrB=0x%06lx\n", - pB->wID, pB->cbSize, pB->hwndChild, pB->clrFore, pB->clrBack); + TRACE("band info: "); + if (pB->fMask & RBBIM_ID); + TRACE("ID=%u, ", pB->wID); + TRACE("size=%u, child=%p", pB->cbSize, pB->hwndChild); + if (pB->fMask & RBBIM_COLORS) + TRACE(", clrF=0x%06lx, clrB=0x%06lx", pB->clrFore, pB->clrBack); + TRACE("\n"); + TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask)); if (pB->fMask & RBBIM_STYLE) TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle)); @@ -403,8 +409,14 @@ (iP->NtfUnicode)?"TRUE":"FALSE", (iP->DoRedraw)?"TRUE":"FALSE"); for (i = 0; i < iP->uNumBands; i++) { pB = &iP->bands[i]; - TRACE("band # %u: ID=%u, child=%p, row=%u, clrF=0x%06lx, clrB=0x%06lx\n", - i, pB->wID, pB->hwndChild, pB->iRow, pB->clrFore, pB->clrBack); + TRACE("band # %u:", i); + if (pB->fMask & RBBIM_ID); + TRACE(" ID=%u", pB->wID); + if (pB->fMask & RBBIM_CHILD) + TRACE(" child=%p", pB->hwndChild); + if (pB->fMask & RBBIM_COLORS) + TRACE(" clrF=0x%06lx clrB=0x%06lx", pB->clrFore, pB->clrBack); + TRACE("\n"); TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask)); if (pB->fMask & RBBIM_STYLE) TRACE("band # %u: style=0x%08x (%s)\n", @@ -1419,7 +1431,7 @@ clientcx, clientcy, adjcx, adjcy); x = initx; y = inity; - row = 1; + row = 0; cx = 0; mcy = 0; rowstart = 0; @@ -1560,7 +1572,7 @@ } if (infoPtr->uNumBands) - infoPtr->uNumRows = row; + infoPtr->uNumRows = row + 1; /* ******* End Phase 1 - all bands on row at minimum size ******* */ @@ -1583,7 +1595,7 @@ /* now adjust all rectangles by using the height found above */ xy = 0; - row = 1; + row = 0; for (i=0; iuNumBands; i++) { lpBand = &infoPtr->bands[i]; if (HIDDENBAND(lpBand)) continue; @@ -1759,6 +1771,7 @@ if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) ) continue; + /* FIXME: this next line is wrong, but fixing it to be inverted causes IE's sidebars to be the wrong size */ if (lpBand->fMask & RBBS_VARIABLEHEIGHT) continue; if (((INT)lpBand->cyMaxChild < 1) || ((INT)lpBand->cyIntegral < 1)) { @@ -1943,7 +1956,7 @@ infoPtr->fStatus |= BAND_NEEDS_LAYOUT; /* Header is where the image, text and gripper exist */ - /* in the band and preceed the child window. */ + /* in the band and precede the child window. */ /* count number of non-FIXEDSIZE and non-Hidden bands */ nonfixed = 0; diff -urN wine-20050211/dlls/comctl32/status.c wine-20050310/dlls/comctl32/status.c --- wine-20050211/dlls/comctl32/status.c 2005-02-01 19:53:59.000000000 +0100 +++ wine-20050310/dlls/comctl32/status.c 2005-03-02 11:08:29.000000000 +0100 @@ -79,6 +79,9 @@ BOOL NtfUnicode; /* notify format */ STATUSWINDOWPART part0; /* simple window */ STATUSWINDOWPART* parts; + INT horizontalBorder; + INT verticalBorder; + INT horizontalGap; } STATUS_INFO; /* @@ -159,28 +162,24 @@ DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST); - if (part->style & SBT_OWNERDRAW) - { - DRAWITEMSTRUCT dis; + if (part->style & SBT_OWNERDRAW) { + DRAWITEMSTRUCT dis; - dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - dis.itemID = itemID; - dis.hwndItem = infoPtr->Self; - dis.hDC = hdc; - dis.rcItem = r; - dis.itemData = (INT)part->text; - SendMessageW (infoPtr->Notify, WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis); - } - else - { - if (part->hIcon) - { - INT cy = r.bottom - r.top; - - r.left += 2; - DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL); - r.left += cy; - } + dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); + dis.itemID = itemID; + dis.hwndItem = infoPtr->Self; + dis.hDC = hdc; + dis.rcItem = r; + dis.itemData = (INT)part->text; + SendMessageW (infoPtr->Notify, WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis); + } else { + if (part->hIcon) { + INT cy = r.bottom - r.top; + + r.left += 2; + DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL); + r.left += cy; + } DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); } } @@ -213,12 +212,11 @@ if (infoPtr->clrBk != CLR_DEFAULT) DeleteObject (hbrBk); - if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) - { - RECT rect; + if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) { + RECT rect; - GetClientRect (infoPtr->Self, &rect); - STATUSBAR_DrawSizeGrip (hdc, &rect); + GetClientRect (infoPtr->Self, &rect); + STATUSBAR_DrawSizeGrip (hdc, &rect); } } @@ -240,19 +238,19 @@ GetClientRect (infoPtr->Self, &rect); if (infoPtr->clrBk != CLR_DEFAULT) - hbrBk = CreateSolidBrush (infoPtr->clrBk); + hbrBk = CreateSolidBrush (infoPtr->clrBk); else - hbrBk = GetSysColorBrush (COLOR_3DFACE); + hbrBk = GetSysColorBrush (COLOR_3DFACE); FillRect(hdc, &rect, hbrBk); hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont); if (infoPtr->simple) { - STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0); + STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0); } else { - for (i = 0; i < infoPtr->numParts; i++) { - STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i); - } + for (i = 0; i < infoPtr->numParts; i++) { + STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i); + } } SelectObject (hdc, hOldFont); @@ -278,7 +276,8 @@ GetClientRect (infoPtr->Self, &rect); TRACE("client wnd size is %ld,%ld - %ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom); - rect.top += VERT_BORDER; + rect.left += infoPtr->horizontalBorder; + rect.top += infoPtr->verticalBorder; /* set bounds for simple rectangle */ infoPtr->part0.bound = rect; @@ -292,7 +291,7 @@ if (i == 0) r->left = 0; else - r->left = infoPtr->parts[i-1].bound.right + HORZ_GAP; + r->left = infoPtr->parts[i-1].bound.right + infoPtr->horizontalGap; if (part->x == -1) r->right = rect.right; else @@ -331,12 +330,25 @@ static BOOL -STATUSBAR_GetBorders (INT out[]) +STATUSBAR_GetBorders (STATUS_INFO *infoPtr, INT out[]) +{ + TRACE("\n"); + out[0] = infoPtr->horizontalBorder; + out[1] = infoPtr->verticalBorder; + out[2] = infoPtr->horizontalGap; + + return TRUE; +} + + +static BOOL +STATUSBAR_SetBorders (STATUS_INFO *infoPtr, INT in[]) { TRACE("\n"); - out[0] = HORZ_BORDER; /* horizontal border width */ - out[1] = VERT_BORDER; /* vertical border width */ - out[2] = HORZ_GAP; /* width of border between rectangles */ + infoPtr->horizontalBorder = in[0]; + infoPtr->verticalBorder = in[1]; + infoPtr->horizontalGap = in[2]; + InvalidateRect(infoPtr->Self, NULL, FALSE); return TRUE; } @@ -560,13 +572,13 @@ RECT parent_rect; GetClientRect (infoPtr->Notify, &parent_rect); - infoPtr->height = height + VERT_BORDER; + infoPtr->height = height + infoPtr->verticalBorder; width = parent_rect.right - parent_rect.left; x = parent_rect.left; y = parent_rect.bottom - infoPtr->height; MoveWindow (infoPtr->Self, parent_rect.left, - parent_rect.bottom - infoPtr->height, - width, infoPtr->height, TRUE); + parent_rect.bottom - infoPtr->height, + width, infoPtr->height, TRUE); STATUSBAR_SetPartBounds (infoPtr); } @@ -728,8 +740,7 @@ ti.uId = id; ti.hinst = 0; ti.lpszText = text; - SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA, - 0, (LPARAM)&ti); + SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA, 0, (LPARAM)&ti); } return 0; @@ -747,8 +758,7 @@ ti.uId = id; ti.hinst = 0; ti.lpszText = text; - SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, - 0, (LPARAM)&ti); + SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti); } return 0; @@ -838,6 +848,9 @@ infoPtr->simple = FALSE; infoPtr->clrBk = CLR_DEFAULT; infoPtr->hFont = 0; + infoPtr->horizontalBorder = HORZ_BORDER; + infoPtr->verticalBorder = VERT_BORDER; + infoPtr->horizontalGap = HORZ_GAP; i = SendMessageW(infoPtr->Notify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY); infoPtr->NtfUnicode = (i == NFR_UNICODE); @@ -929,7 +942,7 @@ if (!(dwStyle & CCS_NORESIZE)) { /* don't resize wnd if it doesn't want it ! */ GetClientRect (infoPtr->Notify, &rect); width = rect.right - rect.left; - infoPtr->height = textHeight + 4 + VERT_BORDER; + infoPtr->height = textHeight + 4 + infoPtr->verticalBorder; SetWindowPos(hwnd, 0, lpCreate->x, lpCreate->y - 1, width, infoPtr->height, SWP_NOZORDER); STATUSBAR_SetPartBounds (infoPtr); @@ -1069,8 +1082,7 @@ /* Need to resize width to match parent */ TRACE("flags %04x\n", flags); - if (flags != SIZE_RESTORED && flags != SIZE_MAXIMIZED) - { + if (flags != SIZE_RESTORED && flags != SIZE_MAXIMIZED) { WARN("flags MUST be SIZE_RESTORED or SIZE_MAXIMIZED\n"); return FALSE; } @@ -1129,7 +1141,7 @@ switch (msg) { case SB_GETBORDERS: - return STATUSBAR_GetBorders ((INT *)lParam); + return STATUSBAR_GetBorders (infoPtr, (INT *)lParam); case SB_GETICON: return (LRESULT)STATUSBAR_GetIcon (infoPtr, nPart); @@ -1162,6 +1174,9 @@ case SB_ISSIMPLE: return infoPtr->simple; + case SB_SETBORDERS: + return STATUSBAR_SetBorders (infoPtr, (INT *)lParam); + case SB_SETBKCOLOR: return STATUSBAR_SetBkColor (infoPtr, (COLORREF)lParam); diff -urN wine-20050211/dlls/comctl32/string.c wine-20050310/dlls/comctl32/string.c --- wine-20050211/dlls/comctl32/string.c 2004-09-22 21:10:27.000000000 +0200 +++ wine-20050310/dlls/comctl32/string.c 2005-02-25 15:07:58.000000000 +0100 @@ -421,7 +421,7 @@ /************************************************************************** * StrRChrA [COMCTL32.351] * - * Find the last occurence of a character in string. + * Find the last occurrence of a character in string. * * PARAMS * lpszStr [I] String to search in @@ -572,7 +572,7 @@ /************************************************************************* * StrRStrIA [COMCTL32.372] * - * Find the last occurence of a substring within a string. + * Find the last occurrence of a substring within a string. * * PARAMS * lpszStr [I] String to search in @@ -580,7 +580,7 @@ * lpszSearch [I] String to look for * * RETURNS - * The last occurence lpszSearch within lpszStr, or NULL if not found. + * The last occurrence lpszSearch within lpszStr, or NULL if not found. */ LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch) { @@ -709,7 +709,7 @@ /************************************************************************** * StrRChrIA [COMCTL32.368] * - * Find the last occurence of a character in string, ignoring case. + * Find the last occurrence of a character in string, ignoring case. * * PARAMS * lpszStr [I] String to search in diff -urN wine-20050211/dlls/comctl32/syslink.c wine-20050310/dlls/comctl32/syslink.c --- wine-20050211/dlls/comctl32/syslink.c 2004-12-23 19:24:50.000000000 +0100 +++ wine-20050310/dlls/comctl32/syslink.c 2005-03-02 14:53:52.000000000 +0100 @@ -513,7 +513,7 @@ /*********************************************************************** * SYSLINK_GetLinkItemByIndex - * Retreives a document link by it's index + * Retrieves a document link by its index */ static PDOC_ITEM SYSLINK_GetLinkItemByIndex (SYSLINK_INFO *infoPtr, int iLink) { @@ -532,7 +532,7 @@ /*********************************************************************** * SYSLINK_GetFocusLink - * Retreives the link that has the LIS_FOCUSED bit + * Retrieves the link that has the LIS_FOCUSED bit */ static PDOC_ITEM SYSLINK_GetFocusLink (SYSLINK_INFO *infoPtr, int *LinkId) { diff -urN wine-20050211/dlls/comctl32/tab.c wine-20050310/dlls/comctl32/tab.c --- wine-20050211/dlls/comctl32/tab.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050310/dlls/comctl32/tab.c 2005-02-25 17:19:07.000000000 +0100 @@ -59,7 +59,7 @@ * leftmost item (the leftmost item, 0, would have a * "left" member of 0 in this rectangle) * - * additionally the top member hold the row number + * additionally the top member holds the row number * and bottom is unused and should be 0 */ BYTE extra[1]; /* Space for caller supplied info, variable size */ } TAB_ITEM; @@ -69,6 +69,7 @@ typedef struct { + HWND hwnd; /* Tab control window */ HWND hwndNotify; /* notification window (parent) */ UINT uNumItem; /* number of tab items */ UINT uNumRows; /* number of tab rows */ @@ -126,20 +127,17 @@ /****************************************************************************** * Prototypes */ -static void TAB_Refresh (HWND hwnd, HDC hdc); -static void TAB_InvalidateTabArea(HWND hwnd, TAB_INFO* infoPtr); -static void TAB_EnsureSelectionVisible(HWND hwnd, TAB_INFO* infoPtr); -static void TAB_DrawItem(HWND hwnd, HDC hdc, INT iItem); -static void TAB_DrawItemInterior(HWND hwnd, HDC hdc, INT iItem, RECT* drawRect); +static void TAB_InvalidateTabArea(TAB_INFO *); +static void TAB_EnsureSelectionVisible(TAB_INFO *); +static void TAB_DrawItemInterior(TAB_INFO *, HDC, INT, RECT*); static BOOL -TAB_SendSimpleNotify (HWND hwnd, UINT code) +TAB_SendSimpleNotify (const TAB_INFO *infoPtr, UINT code) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); NMHDR nmhdr; - nmhdr.hwndFrom = hwnd; - nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); + nmhdr.hwndFrom = infoPtr->hwnd; + nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwnd, GWLP_ID); nmhdr.code = code; return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, @@ -203,11 +201,8 @@ /* RETURNS * the index of the selected tab, or -1 if no tab is selected. */ -static LRESULT -TAB_GetCurSel (HWND hwnd) +static inline LRESULT TAB_GetCurSel (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - return infoPtr->iSelected; } @@ -217,10 +212,9 @@ * we have not to return negative value * TODO * test for windows */ -static LRESULT -TAB_GetCurFocus (HWND hwnd) +static inline LRESULT +TAB_GetCurFocus (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); if (infoPtr->uFocus<0) { FIXME("we have not to return negative value"); @@ -229,79 +223,66 @@ return infoPtr->uFocus; } -static LRESULT -TAB_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_GetToolTips (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - if (infoPtr == NULL) return 0; return (LRESULT)infoPtr->hwndToolTip; } -static LRESULT -TAB_SetCurSel (HWND hwnd,WPARAM wParam) +static inline LRESULT TAB_SetCurSel (TAB_INFO *infoPtr, INT iItem) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT)wParam; - INT prevItem; + INT prevItem = -1; - prevItem = -1; - if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) { - prevItem=infoPtr->iSelected; + if (iItem >= 0 && iItem < infoPtr->uNumItem) { + prevItem=infoPtr->iSelected; infoPtr->iSelected=iItem; - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_EnsureSelectionVisible(infoPtr); + TAB_InvalidateTabArea(infoPtr); } return prevItem; } -static LRESULT -TAB_SetCurFocus (HWND hwnd,WPARAM wParam) +static LRESULT TAB_SetCurFocus (TAB_INFO *infoPtr, INT iItem) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem=(INT) wParam; - - if ((iItem < 0) || (iItem >= infoPtr->uNumItem)) return 0; + if (iItem < 0 || iItem >= infoPtr->uNumItem) return 0; - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) { + if (GetWindowLongA(infoPtr->hwnd, GWL_STYLE) & TCS_BUTTONS) { FIXME("Should set input focus\n"); } else { int oldFocus = infoPtr->uFocus; if (infoPtr->iSelected != iItem || oldFocus == -1 ) { infoPtr->uFocus = iItem; if (oldFocus != -1) { - if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) { + if (!TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGING)) { infoPtr->iSelected = iItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); + TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE); } else infoPtr->iSelected = iItem; - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_EnsureSelectionVisible(infoPtr); + TAB_InvalidateTabArea(infoPtr); } } } return 0; } -static LRESULT -TAB_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_SetToolTips (TAB_INFO *infoPtr, HWND hwndToolTip) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr == NULL) return 0; - infoPtr->hwndToolTip = (HWND)wParam; + if (infoPtr) + infoPtr->hwndToolTip = hwndToolTip; return 0; } -static LRESULT -TAB_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_SetPadding (TAB_INFO *infoPtr, LPARAM lParam) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr == NULL) return 0; - infoPtr->uHItemPadding_s=LOWORD(lParam); - infoPtr->uVItemPadding_s=HIWORD(lParam); + if (infoPtr) + { + infoPtr->uHItemPadding_s=LOWORD(lParam); + infoPtr->uVItemPadding_s=HIWORD(lParam); + } return 0; } @@ -315,14 +296,13 @@ * if it is completely outside the client area. */ static BOOL TAB_InternalGetItemRect( - HWND hwnd, - TAB_INFO* infoPtr, + const TAB_INFO* infoPtr, INT itemIndex, RECT* itemRect, RECT* selectedRect) { RECT tmpItemRect,clientRect; - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); /* Perform a sanity check and a trivial visibility check. */ if ( (infoPtr->uNumItem <= 0) || @@ -341,7 +321,7 @@ *itemRect = TAB_GetItem(infoPtr,itemIndex)->rect; /* calculate the times bottom and top based on the row */ - GetClientRect(hwnd, &clientRect); + GetClientRect(infoPtr->hwnd, &clientRect); if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { @@ -440,10 +420,10 @@ return TRUE; } -static BOOL TAB_GetItemRect(HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline BOOL +TAB_GetItemRect(TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { - return TAB_InternalGetItemRect(hwnd, TAB_GetInfoPtr(hwnd), (INT)wParam, - (LPRECT)lParam, (LPRECT)NULL); + return TAB_InternalGetItemRect(infoPtr, (INT)wParam, (LPRECT)lParam, (LPRECT)NULL); } /****************************************************************************** @@ -451,11 +431,8 @@ * * This method is called to handle keyboard input */ -static LRESULT TAB_KeyUp( - HWND hwnd, - WPARAM keyCode) +static LRESULT TAB_KeyUp(TAB_INFO* infoPtr, WPARAM keyCode) { - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); int newItem = -1; switch (keyCode) @@ -471,18 +448,18 @@ /* * If we changed to a valid item, change the selection */ - if ((newItem >= 0) && - (newItem < infoPtr->uNumItem) && - (infoPtr->uFocus != newItem)) + if (newItem >= 0 && + newItem < infoPtr->uNumItem && + infoPtr->uFocus != newItem) { - if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) + if (!TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGING)) { infoPtr->iSelected = newItem; infoPtr->uFocus = newItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); + TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE); - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_EnsureSelectionVisible(infoPtr); + TAB_InvalidateTabArea(infoPtr); } } @@ -495,21 +472,15 @@ * This method is called whenever the focus goes in or out of this control * it is used to update the visual state of the control. */ -static LRESULT TAB_FocusChanging( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) +static VOID TAB_FocusChanging(const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); RECT selectedRect; BOOL isVisible; /* * Get the rectangle for the item. */ - isVisible = TAB_InternalGetItemRect(hwnd, - infoPtr, + isVisible = TAB_InternalGetItemRect(infoPtr, infoPtr->uFocus, NULL, &selectedRect); @@ -523,17 +494,11 @@ TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n", selectedRect.left,selectedRect.top, selectedRect.right,selectedRect.bottom); - InvalidateRect(hwnd, &selectedRect, TRUE); + InvalidateRect(infoPtr->hwnd, &selectedRect, TRUE); } - - /* - * Don't otherwise disturb normal behavior. - */ - return DefWindowProcW (hwnd, uMsg, wParam, lParam); } static INT TAB_InternalHitTest ( - HWND hwnd, TAB_INFO* infoPtr, POINT pt, UINT* flags) @@ -544,7 +509,7 @@ for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) { - TAB_InternalGetItemRect(hwnd, infoPtr, iCount, &rect, NULL); + TAB_InternalGetItemRect(infoPtr, iCount, &rect, NULL); if (PtInRect(&rect, pt)) { @@ -557,13 +522,10 @@ return -1; } -static LRESULT -TAB_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_HitTest (TAB_INFO *infoPtr, LPTCHITTESTINFO lptest) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LPTCHITTESTINFO lptest = (LPTCHITTESTINFO) lParam; - - return TAB_InternalHitTest (hwnd, infoPtr, lptest->pt, &lptest->flags); + return TAB_InternalHitTest (infoPtr, lptest->pt, &lptest->flags); } /****************************************************************************** @@ -578,77 +540,75 @@ * FIXME: WM_NCHITTEST handling correct ? Fix it if you know that Windows * doesn't do it that way. Maybe depends on tab control styles ? */ -static LRESULT -TAB_NCHitTest (HWND hwnd, LPARAM lParam) +static inline LRESULT +TAB_NCHitTest (TAB_INFO *infoPtr, LPARAM lParam) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); POINT pt; UINT dummyflag; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); - ScreenToClient(hwnd, &pt); + ScreenToClient(infoPtr->hwnd, &pt); - if (TAB_InternalHitTest(hwnd, infoPtr, pt, &dummyflag) == -1) + if (TAB_InternalHitTest(infoPtr, pt, &dummyflag) == -1) return HTTRANSPARENT; else return HTCLIENT; } static LRESULT -TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) +TAB_LButtonDown (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); POINT pt; INT newItem, dummy; if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, + TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam); - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) { - SetFocus (hwnd); + if (GetWindowLongA(infoPtr->hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) { + SetFocus (infoPtr->hwnd); } if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, + TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam); pt.x = (INT)LOWORD(lParam); pt.y = (INT)HIWORD(lParam); - newItem = TAB_InternalHitTest (hwnd, infoPtr, pt, &dummy); + newItem = TAB_InternalHitTest (infoPtr, pt, &dummy); TRACE("On Tab, item %d\n", newItem); - if ((newItem != -1) && (infoPtr->iSelected != newItem)) + if (newItem != -1 && infoPtr->iSelected != newItem) { - if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) + if (!TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGING)) { infoPtr->iSelected = newItem; infoPtr->uFocus = newItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); + TAB_SendSimpleNotify(infoPtr, TCN_SELCHANGE); - TAB_EnsureSelectionVisible(hwnd, infoPtr); + TAB_EnsureSelectionVisible(infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_InvalidateTabArea(infoPtr); } } return 0; } -static LRESULT -TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_LButtonUp (const TAB_INFO *infoPtr) { - TAB_SendSimpleNotify(hwnd, NM_CLICK); + TAB_SendSimpleNotify(infoPtr, NM_CLICK); return 0; } -static LRESULT -TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_RButtonDown (const TAB_INFO *infoPtr) { - TAB_SendSimpleNotify(hwnd, NM_RCLICK); + TAB_SendSimpleNotify(infoPtr, NM_RCLICK); return 0; } @@ -661,20 +621,20 @@ * only calls TAB_DrawItemInterior for the single specified item. */ static void -TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem) +TAB_DrawLoneItemInterior(TAB_INFO* infoPtr, int iItem) { - HDC hdc = GetDC(hwnd); + HDC hdc = GetDC(infoPtr->hwnd); RECT r, rC; /* Clip UpDown control to not draw over it */ if (infoPtr->needsScrolling) { - GetWindowRect(hwnd, &rC); + GetWindowRect(infoPtr->hwnd, &rC); GetWindowRect(infoPtr->hwndUpDown, &r); ExcludeClipRect(hdc, r.left - rC.left, r.top - rC.top, r.right - rC.left, r.bottom - rC.top); } - TAB_DrawItemInterior(hwnd, hdc, iItem, NULL); - ReleaseDC(hwnd, hdc); + TAB_DrawItemInterior(infoPtr, hdc, iItem, NULL); + ReleaseDC(infoPtr->hwnd, hdc); } /****************************************************************************** @@ -716,7 +676,7 @@ /* Redraw iHotTracked to look normal */ INT iRedraw = infoPtr->iHotTracked; infoPtr->iHotTracked = -1; - TAB_DrawLoneItemInterior(hwnd, infoPtr, iRedraw); + TAB_DrawLoneItemInterior(infoPtr, iRedraw); /* Kill this timer */ KillTimer(hwnd, TAB_HOTTRACK_TIMER); @@ -743,14 +703,12 @@ static void TAB_RecalcHotTrack ( - HWND hwnd, + TAB_INFO* infoPtr, const LPARAM* pos, int* out_redrawLeave, int* out_redrawEnter ) { - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - int item = -1; @@ -759,7 +717,7 @@ if (out_redrawEnter != NULL) *out_redrawEnter = -1; - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_HOTTRACK) + if (GetWindowLongA(infoPtr->hwnd, GWL_STYLE) & TCS_HOTTRACK) { POINT pt; UINT flags; @@ -767,7 +725,7 @@ if (pos == NULL) { GetCursorPos(&pt); - ScreenToClient(hwnd, &pt); + ScreenToClient(infoPtr->hwnd, &pt); } else { @@ -775,7 +733,7 @@ pt.y = HIWORD(*pos); } - item = TAB_InternalHitTest(hwnd, infoPtr, pt, &flags); + item = TAB_InternalHitTest(infoPtr, pt, &flags); } if (item != infoPtr->iHotTracked) @@ -789,7 +747,7 @@ if (item < 0) { /* Kill timer which forces recheck of mouse pos */ - KillTimer(hwnd, TAB_HOTTRACK_TIMER); + KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); } } else @@ -797,7 +755,7 @@ /* Start timer so we recheck mouse pos */ UINT timerID = SetTimer ( - hwnd, + infoPtr->hwnd, TAB_HOTTRACK_TIMER, TAB_HOTTRACK_TIMER_INTERVAL, TAB_HotTrackTimerProc @@ -824,25 +782,23 @@ * Handles the mouse-move event. Updates tooltips. Updates hot-tracking. */ static LRESULT -TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) +TAB_MouseMove (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { int redrawLeave; int redrawEnter; - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, + TAB_RelayEvent (infoPtr->hwndToolTip, infoPtr->hwnd, WM_LBUTTONDOWN, wParam, lParam); /* Determine which tab to highlight. Redraw tabs which change highlight ** status. */ - TAB_RecalcHotTrack(hwnd, &lParam, &redrawLeave, &redrawEnter); + TAB_RecalcHotTrack(infoPtr, &lParam, &redrawLeave, &redrawEnter); if (redrawLeave != -1) - TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawLeave); + TAB_DrawLoneItemInterior(infoPtr, redrawLeave); if (redrawEnter != -1) - TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawEnter); + TAB_DrawLoneItemInterior(infoPtr, redrawEnter); return 0; } @@ -854,15 +810,14 @@ * the window rectangle given the requested display rectangle. */ static LRESULT TAB_AdjustRect( - HWND hwnd, + TAB_INFO *infoPtr, WPARAM fLarger, LPRECT prc) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); + DWORD lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); LONG *iRightBottom, *iLeftTop; - TRACE ("hwnd=%p fLarger=%d (%ld,%ld)-(%ld,%ld)\n", hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom); + TRACE ("hwnd=%p fLarger=%d (%ld,%ld)-(%ld,%ld)\n", infoPtr->hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom); if(lStyle & TCS_VERTICAL) { @@ -916,13 +871,11 @@ * perform the scrolling operation on the tab control. */ static LRESULT TAB_OnHScroll( - HWND hwnd, + TAB_INFO *infoPtr, int nScrollCode, int nPos, HWND hwndScroll) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible) { if(nPos < infoPtr->leftmostVisible) @@ -930,8 +883,8 @@ else infoPtr->leftmostVisible++; - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL); + TAB_InvalidateTabArea(infoPtr); SendMessageW(infoPtr->hwndUpDown, UDM_SETPOS, 0, MAKELONG(infoPtr->leftmostVisible, 0)); } @@ -1061,10 +1014,9 @@ * it checks if all the tabs fit in the client area of the window. If they * don't, a scrolling control is added. */ -static void TAB_SetItemBounds (HWND hwnd) +static void TAB_SetItemBounds (TAB_INFO *infoPtr) { - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); TEXTMETRICA fontMetrics; UINT curItem; INT curItemLeftPos; @@ -1082,7 +1034,7 @@ * We need to get text information so we need a DC and we need to select * a font. */ - hdc = GetDC(hwnd); + hdc = GetDC(infoPtr->hwnd); hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); hOldFont = SelectObject (hdc, hFont); @@ -1091,7 +1043,7 @@ * We will base the rectangle calculations on the client rectangle * of the control. */ - GetClientRect(hwnd, &clientRect); + GetClientRect(infoPtr->hwnd, &clientRect); /* if TCS_VERTICAL then swap the height and width so this code places the tabs along the top of the rectangle and we can just rotate them after @@ -1242,7 +1194,7 @@ infoPtr->needsScrolling = FALSE; infoPtr->leftmostVisible = 0; } - TAB_SetupScrolling(hwnd, infoPtr, &clientRect); + TAB_SetupScrolling(infoPtr->hwnd, infoPtr, &clientRect); /* Set the number of rows */ infoPtr->uNumRows = curItemRowCount; @@ -1404,26 +1356,25 @@ } } - TAB_EnsureSelectionVisible(hwnd,infoPtr); - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); + TAB_EnsureSelectionVisible(infoPtr); + TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL); /* Cleanup */ SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); + ReleaseDC (infoPtr->hwnd, hdc); } static void TAB_EraseTabInterior ( - HWND hwnd, + TAB_INFO* infoPtr, HDC hdc, INT iItem, RECT* drawRect ) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); HBRUSH hbr = CreateSolidBrush (comctl32_color.clrBtnFace); BOOL deleteBrush = TRUE; RECT rTemp = *drawRect; @@ -1484,14 +1435,13 @@ static void TAB_DrawItemInterior ( - HWND hwnd, + TAB_INFO* infoPtr, HDC hdc, INT iItem, RECT* drawRect ) { - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); RECT localRect; @@ -1509,7 +1459,7 @@ /* * Get the rectangle for the item. */ - isVisible = TAB_InternalGetItemRect(hwnd, infoPtr, iItem, &itemRect, &selectedRect); + isVisible = TAB_InternalGetItemRect(infoPtr, iItem, &itemRect, &selectedRect); if (!isVisible) return; @@ -1600,11 +1550,11 @@ drawRect->left, drawRect->top, drawRect->right, drawRect->bottom); /* Clear interior */ - TAB_EraseTabInterior (hwnd, hdc, iItem, drawRect); + TAB_EraseTabInterior (infoPtr, hdc, iItem, drawRect); /* Draw the focus rectangle */ if (!(lStyle & TCS_FOCUSNEVER) && - (GetFocus() == hwnd) && + (GetFocus() == infoPtr->hwnd) && (iItem == infoPtr->uFocus) ) { RECT rFocus = *drawRect; @@ -1638,7 +1588,7 @@ /* * if owner draw, tell the owner to draw */ - if ((lStyle & TCS_OWNERDRAWFIXED) && GetParent(hwnd)) + if ((lStyle & TCS_OWNERDRAWFIXED) && GetParent(infoPtr->hwnd)) { DRAWITEMSTRUCT dis; UINT id; @@ -1654,7 +1604,7 @@ /* * get the control id */ - id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID ); + id = (UINT)GetWindowLongPtrW( infoPtr->hwnd, GWLP_ID ); /* * put together the DRAWITEMSTRUCT @@ -1668,7 +1618,7 @@ dis.itemState |= ODS_SELECTED; if (infoPtr->uFocus == iItem) dis.itemState |= ODS_FOCUS; - dis.hwndItem = hwnd; /* */ + dis.hwndItem = infoPtr->hwnd; dis.hDC = hdc; CopyRect(&dis.rcItem,drawRect); dis.itemData = (ULONG_PTR)TAB_GetItem(infoPtr, iItem)->extra; @@ -1891,12 +1841,11 @@ * This method is used to draw a single tab into the tab control. */ static void TAB_DrawItem( - HWND hwnd, + TAB_INFO *infoPtr, HDC hdc, INT iItem) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); RECT itemRect; RECT selectedRect; BOOL isVisible; @@ -1908,8 +1857,7 @@ /* * Get the rectangle for the item. */ - isVisible = TAB_InternalGetItemRect(hwnd, - infoPtr, + isVisible = TAB_InternalGetItemRect(infoPtr, iItem, &itemRect, &selectedRect); @@ -1921,7 +1869,7 @@ /* Clip UpDown control to not draw over it */ if (infoPtr->needsScrolling) { - GetWindowRect(hwnd, &rC); + GetWindowRect(infoPtr->hwnd, &rC); GetWindowRect(infoPtr->hwndUpDown, &rUD); ExcludeClipRect(hdc, rUD.left - rC.left, rUD.top - rC.top, rUD.right - rC.left, rUD.bottom - rC.top); } @@ -1965,7 +1913,7 @@ * state. */ if (iItem == infoPtr->iSelected) { RECT rect; - GetClientRect (hwnd, &rect); + GetClientRect (infoPtr->hwnd, &rect); clRight = rect.right; clBottom = rect.bottom; r = selectedRect; @@ -2188,7 +2136,7 @@ TAB_DumpItemInternal(infoPtr, iItem); /* This modifies r to be the text rectangle. */ - TAB_DrawItemInterior(hwnd, hdc, iItem, &r); + TAB_DrawItemInterior(infoPtr, hdc, iItem, &r); } } @@ -2198,13 +2146,12 @@ * This method is used to draw the raised border around the tab control * "content" area. */ -static void TAB_DrawBorder (HWND hwnd, HDC hdc) +static void TAB_DrawBorder (TAB_INFO *infoPtr, HDC hdc) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); RECT rect; - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); + DWORD lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); - GetClientRect (hwnd, &rect); + GetClientRect (infoPtr->hwnd, &rect); /* * Adjust for the style @@ -2233,9 +2180,8 @@ * * This method repaints the tab control.. */ -static void TAB_Refresh (HWND hwnd, HDC hdc) +static void TAB_Refresh (TAB_INFO *infoPtr, HDC hdc) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); HFONT hOldFont; INT i; @@ -2244,10 +2190,10 @@ hOldFont = SelectObject (hdc, infoPtr->hFont); - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) + if (GetWindowLongA(infoPtr->hwnd, GWL_STYLE) & TCS_BUTTONS) { for (i = 0; i < infoPtr->uNumItem; i++) - TAB_DrawItem (hwnd, hdc, i); + TAB_DrawItem (infoPtr, hdc, i); } else { @@ -2255,39 +2201,33 @@ for (i = 0; i < infoPtr->uNumItem; i++) { if (i != infoPtr->iSelected) - TAB_DrawItem (hwnd, hdc, i); + TAB_DrawItem (infoPtr, hdc, i); } /* Now, draw the border, draw it before the selected item * since the selected item overwrites part of the border. */ - TAB_DrawBorder (hwnd, hdc); + TAB_DrawBorder (infoPtr, hdc); /* Then, draw the selected item */ - TAB_DrawItem (hwnd, hdc, infoPtr->iSelected); + TAB_DrawItem (infoPtr, hdc, infoPtr->iSelected); /* If we haven't set the current focus yet, set it now. * Only happens when we first paint the tab controls */ if (infoPtr->uFocus == -1) - TAB_SetCurFocus(hwnd, infoPtr->iSelected); + TAB_SetCurFocus(infoPtr, infoPtr->iSelected); } SelectObject (hdc, hOldFont); } -static DWORD -TAB_GetRowCount (HWND hwnd ) +static inline DWORD TAB_GetRowCount (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - return infoPtr->uNumRows; } -static LRESULT -TAB_SetRedraw (HWND hwnd, WPARAM wParam) +static inline LRESULT TAB_SetRedraw (TAB_INFO *infoPtr, BOOL doRedraw) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - infoPtr->DoRedraw=(BOOL) wParam; + infoPtr->DoRedraw = doRedraw; return 0; } @@ -2298,11 +2238,10 @@ * visible by scrolling until it is. */ static void TAB_EnsureSelectionVisible( - HWND hwnd, TAB_INFO* infoPtr) { INT iSelected = infoPtr->iSelected; - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); INT iOrigLeftmostVisible = infoPtr->leftmostVisible; /* set the items row to the bottommost row or topmost row depending on @@ -2356,7 +2295,7 @@ } } } - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); + TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL); } } @@ -2379,7 +2318,7 @@ UINT i; /* Calculate the part of the client area that is visible */ - GetClientRect(hwnd, &r); + GetClientRect(infoPtr->hwnd, &r); width = r.right; GetClientRect(infoPtr->hwndUpDown, &r); @@ -2405,7 +2344,7 @@ } if (infoPtr->leftmostVisible != iOrigLeftmostVisible) - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); + TAB_RecalcHotTrack(infoPtr, NULL, NULL, NULL); SendMessageW(infoPtr->hwndUpDown, UDM_SETPOS, 0, MAKELONG(infoPtr->leftmostVisible, 0)); @@ -2418,24 +2357,22 @@ * tabs. It is called when the state of the control changes and needs * to be redisplayed */ -static void TAB_InvalidateTabArea( - HWND hwnd, - TAB_INFO* infoPtr) +static void TAB_InvalidateTabArea(TAB_INFO* infoPtr) { RECT clientRect, rInvalidate, rAdjClient; - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); + DWORD lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); INT lastRow = infoPtr->uNumRows - 1; RECT rect; if (lastRow < 0) return; - GetClientRect(hwnd, &clientRect); + GetClientRect(infoPtr->hwnd, &clientRect); rInvalidate = clientRect; rAdjClient = clientRect; - TAB_AdjustRect(hwnd, 0, &rAdjClient); + TAB_AdjustRect(infoPtr, 0, &rAdjClient); - TAB_InternalGetItemRect(hwnd, infoPtr, infoPtr->uNumItem-1 , &rect, NULL); + TAB_InternalGetItemRect(infoPtr, infoPtr->uNumItem-1 , &rect, NULL); if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { rInvalidate.left = rAdjClient.right; @@ -2475,44 +2412,42 @@ rInvalidate.left, rInvalidate.top, rInvalidate.right, rInvalidate.bottom); - InvalidateRect(hwnd, &rInvalidate, TRUE); + InvalidateRect(infoPtr->hwnd, &rInvalidate, TRUE); } -static LRESULT -TAB_Paint (HWND hwnd, WPARAM wParam) +static inline LRESULT TAB_Paint (TAB_INFO *infoPtr, HDC hdcPaint) { HDC hdc; PAINTSTRUCT ps; - if (wParam == 0) + if (hdcPaint) + hdc = hdcPaint; + else { - hdc = BeginPaint (hwnd, &ps); + hdc = BeginPaint (infoPtr->hwnd, &ps); TRACE("erase %d, rect=(%ld,%ld)-(%ld,%ld)\n", ps.fErase, ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom); - } else { - hdc = (HDC)wParam; } - - TAB_Refresh (hwnd, hdc); - if(!wParam) - EndPaint (hwnd, &ps); + TAB_Refresh (infoPtr, hdc); + + if (!hdcPaint) + EndPaint (infoPtr->hwnd, &ps); return 0; } static LRESULT -TAB_InsertItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) +TAB_InsertItemAW (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam, BOOL bUnicode) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); TAB_ITEM *item; TCITEMA *pti; INT iItem; RECT rect; - GetClientRect (hwnd, &rect); - TRACE("Rect: %p T %li, L %li, B %li, R %li\n", hwnd, + GetClientRect (infoPtr->hwnd, &rect); + TRACE("Rect: %p T %li, L %li, B %li, R %li\n", infoPtr->hwnd, rect.top, rect.left, rect.bottom, rect.right); pti = (TCITEMA *)lParam; @@ -2582,23 +2517,22 @@ else memset(item->extra, 0, infoPtr->cbInfo); - TAB_SetItemBounds(hwnd); + TAB_SetItemBounds(infoPtr); if (infoPtr->uNumItem > 1) - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_InvalidateTabArea(infoPtr); else - InvalidateRect(hwnd, NULL, TRUE); + InvalidateRect(infoPtr->hwnd, NULL, TRUE); TRACE("[%p]: added item %d %s\n", - hwnd, iItem, debugstr_w(item->pszText)); + infoPtr->hwnd, iItem, debugstr_w(item->pszText)); return iItem; } static LRESULT -TAB_SetItemSize (HWND hwnd, WPARAM wParam, LPARAM lParam) +TAB_SetItemSize (TAB_INFO *infoPtr, LPARAM lParam) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG lStyle = GetWindowLongA(infoPtr->hwnd, GWL_STYLE); LONG lResult = 0; BOOL bNeedPaint = FALSE; @@ -2624,60 +2558,56 @@ if (bNeedPaint) { - TAB_SetItemBounds(hwnd); - RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + TAB_SetItemBounds(infoPtr); + RedrawWindow(infoPtr->hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); } - + return lResult; } -static LRESULT -TAB_SetMinTabWidth (HWND hwnd, LPARAM lParam) +static inline LRESULT TAB_SetMinTabWidth (TAB_INFO *infoPtr, INT cx) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT cx = (INT)lParam; - INT oldcx; + INT oldcx = 0; + + TRACE("(%p,%d)\n", infoPtr, cx); if (infoPtr) { oldcx = infoPtr->tabMinWidth; infoPtr->tabMinWidth = (cx==-1)?DEFAULT_TAB_WIDTH:cx; - } else - return 0; + } return oldcx; } -static LRESULT -TAB_HighlightItem (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT +TAB_HighlightItem (TAB_INFO *infoPtr, INT iItem, BOOL fHighlight) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT)wParam; - BOOL fHighlight = (BOOL)LOWORD(lParam); - - if ((infoPtr) && (iItem>=0) && (iItemuNumItem)) { - if (fHighlight) - TAB_GetItem(infoPtr, iItem)->dwState |= TCIS_HIGHLIGHTED; - else - TAB_GetItem(infoPtr, iItem)->dwState &= ~TCIS_HIGHLIGHTED; - } else + LPDWORD lpState; + + TRACE("(%p,%d,%s)\n", infoPtr, iItem, fHighlight ? "true" : "false"); + + if (!infoPtr || iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE; + + lpState = &TAB_GetItem(infoPtr, iItem)->dwState; + + if (fHighlight) + *lpState |= TCIS_HIGHLIGHTED; + else + *lpState &= ~TCIS_HIGHLIGHTED; return TRUE; } static LRESULT -TAB_SetItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) +TAB_SetItemAW (TAB_INFO *infoPtr, INT iItem, LPTCITEMA tabItem, BOOL bUnicode) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TCITEMA *tabItem; TAB_ITEM *wineItem; - INT iItem; - iItem = (INT)wParam; - tabItem = (LPTCITEMA)lParam; + TRACE("(%p,%d,%p,%s)\n", infoPtr, iItem, tabItem, bUnicode ? "true" : "false"); - TRACE("%d %p\n", iItem, tabItem); - if ((iItem<0) || (iItem>=infoPtr->uNumItem)) return FALSE; + if (iItem < 0 || iItem >= infoPtr->uNumItem) + return FALSE; if (bUnicode) TAB_DumpItemExternalW((TCITEMW *)tabItem, iItem); @@ -2712,33 +2642,26 @@ } /* Update and repaint tabs */ - TAB_SetItemBounds(hwnd); - TAB_InvalidateTabArea(hwnd,infoPtr); + TAB_SetItemBounds(infoPtr); + TAB_InvalidateTabArea(infoPtr); return TRUE; } -static LRESULT -TAB_GetItemCount (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_GetItemCount (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - return infoPtr->uNumItem; } static LRESULT -TAB_GetItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) +TAB_GetItemAW (TAB_INFO *infoPtr, INT iItem, LPTCITEMA tabItem, BOOL bUnicode) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TCITEMA *tabItem; - TAB_ITEM *wineItem; - INT iItem; + TAB_ITEM *wineItem; - iItem = (INT)wParam; - tabItem = (LPTCITEMA)lParam; - TRACE("\n"); - if ((iItem<0) || (iItem>=infoPtr->uNumItem)) + TRACE("(%p,%d,%p,%s)\n", infoPtr, iItem, tabItem, bUnicode ? "true" : "false"); + + if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE; wineItem = TAB_GetItem(infoPtr, iItem); @@ -2772,19 +2695,18 @@ } -static LRESULT -TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam) +static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT) wParam; BOOL bResult = FALSE; + TRACE("(%p, %d)\n", infoPtr, iItem); + if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) { TAB_ITEM *item = TAB_GetItem(infoPtr, iItem); LPBYTE oldItems = (LPBYTE)infoPtr->items; - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_InvalidateTabArea(infoPtr); if ((item->mask & TCIF_TEXT) && item->pszText) Free(item->pszText); @@ -2796,7 +2718,7 @@ infoPtr->items = NULL; if (infoPtr->iHotTracked >= 0) { - KillTimer(hwnd, TAB_HOTTRACK_TIMER); + KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); infoPtr->iHotTracked = -1; } } @@ -2831,7 +2753,7 @@ infoPtr->iSelected = -1; /* Reposition and repaint tabs */ - TAB_SetItemBounds(hwnd); + TAB_SetItemBounds(infoPtr); bResult = TRUE; } @@ -2839,86 +2761,64 @@ return bResult; } -static LRESULT -TAB_DeleteAllItems (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - + TRACE("(%p)\n", infoPtr); while (infoPtr->uNumItem) - TAB_DeleteItem (hwnd, 0, 0); + TAB_DeleteItem (infoPtr, 0); return TRUE; } -static LRESULT -TAB_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_GetFont (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("\n"); + TRACE("(%p) returning %p\n", infoPtr, infoPtr->hFont); return (LRESULT)infoPtr->hFont; } -static LRESULT -TAB_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) - +static inline LRESULT TAB_SetFont (TAB_INFO *infoPtr, HFONT hNewFont) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("%x %lx\n",wParam, lParam); + TRACE("(%p,%p)\n", infoPtr, hNewFont); - infoPtr->hFont = (HFONT)wParam; + infoPtr->hFont = hNewFont; - TAB_SetItemBounds(hwnd); + TAB_SetItemBounds(infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); + TAB_InvalidateTabArea(infoPtr); return 0; } -static LRESULT -TAB_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_GetImageList (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TRACE("\n"); return (LRESULT)infoPtr->himl; } -static LRESULT -TAB_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) +static inline LRESULT TAB_SetImageList (TAB_INFO *infoPtr, HIMAGELIST himlNew) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - HIMAGELIST himlPrev; - + HIMAGELIST himlPrev = infoPtr->himl; TRACE("\n"); - himlPrev = infoPtr->himl; - infoPtr->himl= (HIMAGELIST)lParam; + infoPtr->himl = himlNew; return (LRESULT)himlPrev; } -static LRESULT -TAB_GetUnicodeFormat (HWND hwnd) +static inline LRESULT TAB_GetUnicodeFormat (const TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd); return infoPtr->bUnicode; } -static LRESULT -TAB_SetUnicodeFormat (HWND hwnd, WPARAM wParam) +static inline LRESULT TAB_SetUnicodeFormat (TAB_INFO *infoPtr, BOOL bUnicode) { - TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd); BOOL bTemp = infoPtr->bUnicode; - infoPtr->bUnicode = (BOOL)wParam; + infoPtr->bUnicode = bUnicode; return bTemp; } -static LRESULT -TAB_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) - +static inline LRESULT TAB_Size (TAB_INFO *infoPtr) { /* I'm not really sure what the following code was meant to do. This is what it is doing: @@ -2945,17 +2845,16 @@ } */ /* Recompute the size/position of the tabs. */ - TAB_SetItemBounds (hwnd); + TAB_SetItemBounds (infoPtr); /* Force a repaint of the control. */ - InvalidateRect(hwnd, NULL, TRUE); + InvalidateRect(infoPtr->hwnd, NULL, TRUE); return 0; } -static LRESULT -TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) +static LRESULT TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) { TAB_INFO *infoPtr; TEXTMETRICA fontMetrics; @@ -2967,6 +2866,7 @@ SetWindowLongA(hwnd, 0, (DWORD)infoPtr); + infoPtr->hwnd = hwnd; infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; infoPtr->uNumItem = 0; infoPtr->uNumRows = 0; @@ -3050,9 +2950,8 @@ } static LRESULT -TAB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) +TAB_Destroy (TAB_INFO *infoPtr) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); UINT iItem; if (!infoPtr) @@ -3073,19 +2972,16 @@ DestroyWindow(infoPtr->hwndUpDown); if (infoPtr->iHotTracked >= 0) - KillTimer(hwnd, TAB_HOTTRACK_TIMER); + KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); Free (infoPtr); - SetWindowLongA(hwnd, 0, 0); + SetWindowLongA(infoPtr->hwnd, 0, 0); return 0; } -static LRESULT -TAB_SetItemExtra (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT cbInfo = wParam; - +static inline LRESULT +TAB_SetItemExtra (TAB_INFO *infoPtr, INT cbInfo) +{ if (!infoPtr || cbInfo <= 0) return FALSE; @@ -3105,92 +3001,92 @@ TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); TRACE("hwnd=%p msg=%x wParam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam); - if (!TAB_GetInfoPtr(hwnd) && (uMsg != WM_CREATE)) + if (!infoPtr && (uMsg != WM_CREATE)) return DefWindowProcW (hwnd, uMsg, wParam, lParam); switch (uMsg) { case TCM_GETIMAGELIST: - return TAB_GetImageList (hwnd, wParam, lParam); + return TAB_GetImageList (infoPtr); case TCM_SETIMAGELIST: - return TAB_SetImageList (hwnd, wParam, lParam); + return TAB_SetImageList (infoPtr, (HIMAGELIST)lParam); case TCM_GETITEMCOUNT: - return TAB_GetItemCount (hwnd, wParam, lParam); + return TAB_GetItemCount (infoPtr); case TCM_GETITEMA: case TCM_GETITEMW: - return TAB_GetItemAW (hwnd, wParam, lParam, uMsg == TCM_GETITEMW); + return TAB_GetItemAW (infoPtr, (INT)wParam, (LPTCITEMA)lParam, uMsg == TCM_GETITEMW); case TCM_SETITEMA: case TCM_SETITEMW: - return TAB_SetItemAW (hwnd, wParam, lParam, uMsg == TCM_SETITEMW); + return TAB_SetItemAW (infoPtr, (INT)wParam, (LPTCITEMA)lParam, uMsg == TCM_SETITEMW); case TCM_DELETEITEM: - return TAB_DeleteItem (hwnd, wParam, lParam); + return TAB_DeleteItem (infoPtr, (INT)wParam); case TCM_DELETEALLITEMS: - return TAB_DeleteAllItems (hwnd, wParam, lParam); + return TAB_DeleteAllItems (infoPtr); case TCM_GETITEMRECT: - return TAB_GetItemRect (hwnd, wParam, lParam); + return TAB_GetItemRect (infoPtr, wParam, lParam); case TCM_GETCURSEL: - return TAB_GetCurSel (hwnd); + return TAB_GetCurSel (infoPtr); case TCM_HITTEST: - return TAB_HitTest (hwnd, wParam, lParam); + return TAB_HitTest (infoPtr, (LPTCHITTESTINFO)lParam); case TCM_SETCURSEL: - return TAB_SetCurSel (hwnd, wParam); + return TAB_SetCurSel (infoPtr, (INT)wParam); case TCM_INSERTITEMA: case TCM_INSERTITEMW: - return TAB_InsertItemAW (hwnd, wParam, lParam, uMsg == TCM_INSERTITEMW); + return TAB_InsertItemAW (infoPtr, wParam, lParam, uMsg == TCM_INSERTITEMW); case TCM_SETITEMEXTRA: - return TAB_SetItemExtra (hwnd, wParam, lParam); + return TAB_SetItemExtra (infoPtr, (int)wParam); case TCM_ADJUSTRECT: - return TAB_AdjustRect (hwnd, (BOOL)wParam, (LPRECT)lParam); + return TAB_AdjustRect (infoPtr, (BOOL)wParam, (LPRECT)lParam); case TCM_SETITEMSIZE: - return TAB_SetItemSize (hwnd, wParam, lParam); + return TAB_SetItemSize (infoPtr, lParam); case TCM_REMOVEIMAGE: FIXME("Unimplemented msg TCM_REMOVEIMAGE\n"); return 0; case TCM_SETPADDING: - return TAB_SetPadding (hwnd, wParam, lParam); + return TAB_SetPadding (infoPtr, lParam); case TCM_GETROWCOUNT: - return TAB_GetRowCount(hwnd); + return TAB_GetRowCount(infoPtr); case TCM_GETUNICODEFORMAT: - return TAB_GetUnicodeFormat (hwnd); + return TAB_GetUnicodeFormat (infoPtr); case TCM_SETUNICODEFORMAT: - return TAB_SetUnicodeFormat (hwnd, wParam); + return TAB_SetUnicodeFormat (infoPtr, (BOOL)wParam); case TCM_HIGHLIGHTITEM: - return TAB_HighlightItem (hwnd, wParam, lParam); + return TAB_HighlightItem (infoPtr, (INT)wParam, (BOOL)LOWORD(lParam)); case TCM_GETTOOLTIPS: - return TAB_GetToolTips (hwnd, wParam, lParam); + return TAB_GetToolTips (infoPtr); case TCM_SETTOOLTIPS: - return TAB_SetToolTips (hwnd, wParam, lParam); + return TAB_SetToolTips (infoPtr, (HWND)wParam); case TCM_GETCURFOCUS: - return TAB_GetCurFocus (hwnd); + return TAB_GetCurFocus (infoPtr); case TCM_SETCURFOCUS: - return TAB_SetCurFocus (hwnd, wParam); + return TAB_SetCurFocus (infoPtr, (INT)wParam); case TCM_SETMINTABWIDTH: - return TAB_SetMinTabWidth(hwnd, lParam); + return TAB_SetMinTabWidth(infoPtr, (INT)lParam); case TCM_DESELECTALL: FIXME("Unimplemented msg TCM_DESELECTALL\n"); @@ -3205,49 +3101,49 @@ return 0; case WM_GETFONT: - return TAB_GetFont (hwnd, wParam, lParam); + return TAB_GetFont (infoPtr); case WM_SETFONT: - return TAB_SetFont (hwnd, wParam, lParam); + return TAB_SetFont (infoPtr, (HFONT)wParam); case WM_CREATE: return TAB_Create (hwnd, wParam, lParam); case WM_NCDESTROY: - return TAB_Destroy (hwnd, wParam, lParam); + return TAB_Destroy (infoPtr); case WM_GETDLGCODE: return DLGC_WANTARROWS | DLGC_WANTCHARS; case WM_LBUTTONDOWN: - return TAB_LButtonDown (hwnd, wParam, lParam); + return TAB_LButtonDown (infoPtr, wParam, lParam); case WM_LBUTTONUP: - return TAB_LButtonUp (hwnd, wParam, lParam); + return TAB_LButtonUp (infoPtr); case WM_NOTIFY: return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam); case WM_RBUTTONDOWN: - return TAB_RButtonDown (hwnd, wParam, lParam); + return TAB_RButtonDown (infoPtr); case WM_MOUSEMOVE: - return TAB_MouseMove (hwnd, wParam, lParam); + return TAB_MouseMove (infoPtr, wParam, lParam); case WM_PAINT: - return TAB_Paint (hwnd, wParam); + return TAB_Paint (infoPtr, (HDC)wParam); case WM_SIZE: - return TAB_Size (hwnd, wParam, lParam); + return TAB_Size (infoPtr); case WM_SETREDRAW: - return TAB_SetRedraw (hwnd, wParam); + return TAB_SetRedraw (infoPtr, (BOOL)wParam); case WM_HSCROLL: - return TAB_OnHScroll(hwnd, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam); + return TAB_OnHScroll(infoPtr, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam); case WM_STYLECHANGED: - TAB_SetItemBounds (hwnd); + TAB_SetItemBounds (infoPtr); InvalidateRect(hwnd, NULL, TRUE); return 0; @@ -3257,19 +3153,21 @@ case WM_KILLFOCUS: case WM_SETFOCUS: - return TAB_FocusChanging(hwnd, uMsg, wParam, lParam); + TAB_FocusChanging(infoPtr); + break; /* Don't disturb normal focus behavior */ case WM_KEYUP: - return TAB_KeyUp(hwnd, wParam); + return TAB_KeyUp(infoPtr, wParam); case WM_NCHITTEST: - return TAB_NCHitTest(hwnd, lParam); + return TAB_NCHitTest(infoPtr, lParam); default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) + if (uMsg >= WM_USER && uMsg < WM_APP) WARN("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - return DefWindowProcW(hwnd, uMsg, wParam, lParam); + break; } + return DefWindowProcW(hwnd, uMsg, wParam, lParam); } diff -urN wine-20050211/dlls/comctl32/treeview.c wine-20050310/dlls/comctl32/treeview.c --- wine-20050211/dlls/comctl32/treeview.c 2005-01-14 16:13:24.000000000 +0100 +++ wine-20050310/dlls/comctl32/treeview.c 2005-02-22 20:31:01.000000000 +0100 @@ -2386,7 +2386,9 @@ /* The custom draw handler can query the text rectangle, * so get ready. */ - TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc); + /* should already be known, set to 0 when changed */ + if (!wineItem->textWidth) + TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc); cditem = 0; @@ -3084,6 +3086,9 @@ { UINT action = TVE_COLLAPSE | (bRemoveChildren ? TVE_COLLAPSERESET : 0); BOOL bSetSelection, bSetFirstVisible; + RECT scrollRect; + LONG scrollDist = 0; + TREEVIEW_ITEM *nextItem = NULL, *tmpItem; TRACE("TVE_COLLAPSE %p %s\n", wineItem, TREEVIEW_ItemName(wineItem)); @@ -3107,6 +3112,20 @@ bSetFirstVisible = (infoPtr->firstVisible != NULL && TREEVIEW_IsChildOf(wineItem, infoPtr->firstVisible)); + tmpItem = wineItem; + while (tmpItem) + { + if (tmpItem->nextSibling) + { + nextItem = tmpItem->nextSibling; + break; + } + tmpItem = tmpItem->parent; + } + + if (nextItem) + scrollDist = nextItem->rect.top; + if (bRemoveChildren) { INT old_cChildren = wineItem->cChildren; @@ -3131,8 +3150,8 @@ TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); - TREEVIEW_SetFirstVisible(infoPtr, bSetFirstVisible ? wineItem - : infoPtr->firstVisible, TRUE); + if (nextItem) + scrollDist = -(scrollDist - nextItem->rect.top); if (bSetSelection) { @@ -3141,12 +3160,29 @@ infoPtr->selectedItem->state &= ~TVIS_SELECTED; wineItem->state |= TVIS_SELECTED; infoPtr->selectedItem = wineItem; - - TREEVIEW_EnsureVisible(infoPtr, wineItem, FALSE); } TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); + + scrollRect.left = 0; + scrollRect.right = infoPtr->clientWidth; + scrollRect.bottom = infoPtr->clientHeight; + + if (nextItem) + { + scrollRect.top = nextItem->rect.top; + + ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL, + NULL, NULL, SW_ERASE | SW_INVALIDATE); + TREEVIEW_Invalidate(infoPtr, wineItem); + } else { + scrollRect.top = wineItem->rect.top; + InvalidateRect(infoPtr->hwnd, &scrollRect, TRUE); + } + + TREEVIEW_SetFirstVisible(infoPtr, + bSetFirstVisible ? wineItem : infoPtr->firstVisible, + TRUE); return TRUE; } @@ -3155,11 +3191,30 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, BOOL bExpandPartial, BOOL bUser) { + LONG scrollDist; + LONG orgNextTop = 0; + RECT scrollRect; + TREEVIEW_ITEM *nextItem, *tmpItem; + TRACE("\n"); if (wineItem->state & TVIS_EXPANDED) return TRUE; + tmpItem = wineItem; nextItem = NULL; + while (tmpItem) + { + if (tmpItem->nextSibling) + { + nextItem = tmpItem->nextSibling; + break; + } + tmpItem = tmpItem->parent; + } + + if (nextItem) + orgNextTop = nextItem->rect.top; + TRACE("TVE_EXPAND %p %s\n", wineItem, TREEVIEW_ItemName(wineItem)); if (bUser || ((wineItem->cChildren != 0) && @@ -3194,6 +3249,22 @@ TREEVIEW_UpdateSubTree(infoPtr, wineItem); TREEVIEW_UpdateScrollBars(infoPtr); + scrollRect.left = 0; + scrollRect.bottom = infoPtr->treeHeight; + scrollRect.right = infoPtr->clientWidth; + if (nextItem) + { + scrollDist = nextItem->rect.top - orgNextTop; + scrollRect.top = orgNextTop; + + ScrollWindowEx (infoPtr->hwnd, 0, scrollDist, &scrollRect, NULL, + NULL, NULL, SW_ERASE | SW_INVALIDATE); + TREEVIEW_Invalidate (infoPtr, wineItem); + } else { + scrollRect.top = wineItem->rect.top; + InvalidateRect(infoPtr->hwnd, &scrollRect, FALSE); + } + /* Scroll up so that as many children as possible are visible. * This fails when expanding causes an HScroll bar to appear, but we * don't know that yet, so the last item is obscured. */ @@ -3226,8 +3297,6 @@ } } - TREEVIEW_Invalidate(infoPtr, NULL); - return TRUE; } @@ -4735,7 +4804,7 @@ infoPtr->uIndent = MINIMUM_INDENT; infoPtr->selectedItem = 0; infoPtr->focusedItem = 0; - /* hotItem? */ + infoPtr->hotItem = 0; infoPtr->firstVisible = 0; infoPtr->maxVisibleOrder = 0; infoPtr->dropItem = 0; @@ -5435,7 +5504,10 @@ return TREEVIEW_MouseLeave(infoPtr); case WM_MOUSEMOVE: - return TREEVIEW_MouseMove(infoPtr, wParam, lParam); + if (infoPtr->dwStyle & TVS_TRACKSELECT) + return TREEVIEW_MouseMove(infoPtr, wParam, lParam); + else + return 0; case WM_NOTIFY: return TREEVIEW_Notify(infoPtr, wParam, lParam); diff -urN wine-20050211/dlls/commdlg/cdlg32.c wine-20050310/dlls/commdlg/cdlg32.c --- wine-20050211/dlls/commdlg/cdlg32.c 2005-01-28 15:02:52.000000000 +0100 +++ wine-20050310/dlls/commdlg/cdlg32.c 2005-02-25 15:07:58.000000000 +0100 @@ -131,8 +131,8 @@ * COMDLG32_AllocMem (internal) * Get memory for internal datastructure plus stringspace etc. * RETURNS - * Pointer to a heap block: Succes - * NULL: Failure + * Success: Pointer to a heap block + * Failure: null */ LPVOID COMDLG32_AllocMem( int size /* [in] Block size to allocate */ diff -urN wine-20050211/dlls/commdlg/cdlg_En.rc wine-20050310/dlls/commdlg/cdlg_En.rc --- wine-20050211/dlls/commdlg/cdlg_En.rc 2005-01-24 12:26:23.000000000 +0100 +++ wine-20050310/dlls/commdlg/cdlg_En.rc 2005-02-14 12:12:30.000000000 +0100 @@ -470,33 +470,6 @@ IDS_OPEN_FILE "Open File" } -/* Translators do not need to translate this text, unless the language uses a - * different character set or if the distribution of characters looks wrong. - * It is rendered illegibly small and is used to make a mock-up of a document. - */ -STRINGTABLE DISCARDABLE -{ - IDS_FAKEDOCTEXT - "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \ - Nulla a tortor. Etiam aliquet libero venenatis nunc. \n \ - \n \ - Sed augue ante, fermentum sit amet, imperdiet et, gravida eu, enim. \ - Donec nibh quam, sodales in, commodo vel, facilisis id, neque. \n \ - \n \ - Nunc eleifend bibendum nibh. Phasellus in lorem. Ut vel odio quis \ - libero adipiscing consequat. Donec consectetuer laoreet mauris. \n \ - \n \ - Maecenas tempor, ligula sed congue nonummy, arcu dolor ornare erat, \ - egestas iaculis magna purus sed turpis. \n \ - \n \ - Morbi ultricies est non ipsum. Cum sociis natoque penatibus et magnis \ - dis parturient montes, nascetur ridiculus mus. \n \ - \n \ - Duis sit amet nibh quis purus sollicitudin blandit. Curabitur justo. \ - Phasellus varius, erat eu luctus pharetra, odio elit fringilla leo, \ - non vulputate turpis elit id neque. Vestibulum sit amet tellus sed \ - tortor fermentum consectetuer." -} /****************************************************************/ /* English neutral resources diff -urN wine-20050211/dlls/commdlg/cdlg_Es.rc wine-20050310/dlls/commdlg/cdlg_Es.rc --- wine-20050211/dlls/commdlg/cdlg_Es.rc 2005-01-24 12:31:23.000000000 +0100 +++ wine-20050310/dlls/commdlg/cdlg_Es.rc 2005-02-16 22:11:00.000000000 +0100 @@ -21,7 +21,7 @@ * WARNING: DO NOT CHANGE THE SIZE OF THE STANDARD DIALOG TEMPLATES. */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL OPEN_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU diff -urN wine-20050211/dlls/commdlg/cdlg_Pt.rc wine-20050310/dlls/commdlg/cdlg_Pt.rc --- wine-20050211/dlls/commdlg/cdlg_Pt.rc 2005-01-04 21:35:24.000000000 +0100 +++ wine-20050310/dlls/commdlg/cdlg_Pt.rc 2005-02-14 12:12:30.000000000 +0100 @@ -458,3 +458,13 @@ IDS_COLOR_AQUA "Azul-piscina" IDS_COLOR_WHITE "Branco" } + +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Selecione o tamanho da fonte entre %d e %d pontos." + IDS_SAVE_BUTTON "&Salvar" + IDS_SAVE_IN "Salvar &em:" + IDS_SAVE "Salvar" + IDS_SAVE_AS "Salvar como" + IDS_OPEN_FILE "Abrir Arquivo" +} diff -urN wine-20050211/dlls/commdlg/cdlg_xx.rc wine-20050310/dlls/commdlg/cdlg_xx.rc --- wine-20050211/dlls/commdlg/cdlg_xx.rc 2003-12-30 23:08:17.000000000 +0100 +++ wine-20050310/dlls/commdlg/cdlg_xx.rc 2005-02-14 12:12:30.000000000 +0100 @@ -32,6 +32,35 @@ #include "wine/wine_common_ver.rc" +/* Translators do not need to translate this text, unless the language uses a + * different character set or if the distribution of characters looks wrong. + * It is rendered illegibly small and is used to make a mock-up of a document. + */ +STRINGTABLE DISCARDABLE +{ + IDS_FAKEDOCTEXT + "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \ + Nulla a tortor. Etiam aliquet libero venenatis nunc. \n \ + \n \ + Sed augue ante, fermentum sit amet, imperdiet et, gravida eu, enim. \ + Donec nibh quam, sodales in, commodo vel, facilisis id, neque. \n \ + \n \ + Nunc eleifend bibendum nibh. Phasellus in lorem. Ut vel odio quis \ + libero adipiscing consequat. Donec consectetuer laoreet mauris. \n \ + \n \ + Maecenas tempor, ligula sed congue nonummy, arcu dolor ornare erat, \ + egestas iaculis magna purus sed turpis. \n \ + \n \ + Morbi ultricies est non ipsum. Cum sociis natoque penatibus et magnis \ + dis parturient montes, nascetur ridiculus mus. \n \ + \n \ + Duis sit amet nibh quis purus sollicitudin blandit. Curabitur justo. \ + Phasellus varius, erat eu luctus pharetra, odio elit fringilla leo, \ + non vulputate turpis elit id neque. Vestibulum sit amet tellus sed \ + tortor fermentum consectetuer." +} + + /* BINRES pd32_collate.ico */ PD32_COLLATE ICON DISCARDABLE LOADONCALL pd32_collate.ico /* { diff -urN wine-20050211/dlls/commdlg/colordlg.c wine-20050310/dlls/commdlg/colordlg.c --- wine-20050211/dlls/commdlg/colordlg.c 2005-01-10 14:22:35.000000000 +0100 +++ wine-20050310/dlls/commdlg/colordlg.c 2005-02-15 22:51:07.000000000 +0100 @@ -461,7 +461,7 @@ int oben; RECT rect; HWND hwnd = GetDlgItem(hDlg, 0x2be); - LCCPRIV lpp = (LCCPRIV)GetWindowLongA( hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW( hDlg, DWLP_USER); if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6))) /* if full size */ { @@ -480,7 +480,7 @@ points[2].y = points[0].y - w; points[2].x = points[1].x = points[0].x + w; - FillRect(hDC, &lpp->old3angle, (HBRUSH)GetClassLongA( hwnd, GCL_HBRBACKGROUND)); + FillRect(hDC, &lpp->old3angle, (HBRUSH)GetClassLongPtrW( hwnd, GCLP_HBRBACKGROUND)); lpp->old3angle.left = points[0].x; lpp->old3angle.right = points[1].x + 1; lpp->old3angle.top = points[2].y - 1; @@ -499,7 +499,7 @@ HDC hDC; int w = GetDialogBaseUnits(); HWND hwnd = GetDlgItem(hDlg, 0x2c6); - LCCPRIV lpp = (LCCPRIV)GetWindowLongA( hDlg, DWL_USER ); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW( hDlg, DWLP_USER ); RECT rect; POINT point, p; HPEN hPen; @@ -544,11 +544,11 @@ { int sdif, hdif, xdif, ydif, r, g, b, hue, sat; HWND hwnd = GetDlgItem(hDlg, 0x2c6); - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); HBRUSH hbrush; HDC hdc ; RECT rect, client; - HCURSOR hcursor = SetCursor( LoadCursorA(0, (LPSTR)IDC_WAIT) ); + HCURSOR hcursor = SetCursor( LoadCursorW(0, (LPCWSTR)IDC_WAIT) ); GetClientRect(hwnd, &client); hdc = GetDC(hwnd); @@ -587,7 +587,7 @@ static void CC_PaintColorGraph( HWND hDlg ) { HWND hwnd = GetDlgItem( hDlg, 0x2c6 ); - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); HDC hDC; RECT rect; if (IsWindowVisible(hwnd)) /* if full size */ @@ -647,7 +647,7 @@ void CC_EditSetRGB( HWND hDlg, COLORREF cr ) { char buffer[10]; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); int r = GetRValue(cr); int g = GetGValue(cr); int b = GetBValue(cr); @@ -670,7 +670,7 @@ void CC_EditSetHSL( HWND hDlg, int h, int s, int l ) { char buffer[10]; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); lpp->updating = TRUE; if (IsWindowVisible( GetDlgItem(hDlg, 0x2c6) )) /* if full size */ { @@ -692,7 +692,7 @@ void CC_SwitchToFullSize( HWND hDlg, COLORREF result, LPRECT lprect ) { int i; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); EnableWindow( GetDlgItem(hDlg, 0x2cf), FALSE); CC_PrepareColorGraph(hDlg); @@ -728,7 +728,7 @@ HDC hdc; HBRUSH hBrush; int dx, dy, i, j, k; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); GetClientRect(hwnd, &rect); dx = rect.right / cols; @@ -737,7 +737,7 @@ hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); - FillRect(hdc, &rect, (HBRUSH)GetClassLongA(hwnd, GCL_HBRBACKGROUND)); + FillRect(hdc, &rect, (HBRUSH)GetClassLongPtrW(hwnd, GCLP_HBRBACKGROUND)); for ( j = 0; j < rows; j++ ) { for ( i = 0; i < cols; i++ ) @@ -770,7 +770,7 @@ HDC hdc; HBRUSH hBrush; int dx, dy, i, j, k; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); GetClientRect(hwnd, &rect); @@ -781,7 +781,7 @@ hdc = GetDC(hwnd); if (hdc) { - FillRect(hdc, &rect, (HBRUSH)GetClassLongA(hwnd, GCL_HBRBACKGROUND) ); + FillRect(hdc, &rect, (HBRUSH)GetClassLongPtrW(hwnd, GCLP_HBRBACKGROUND) ); for (j = 0; j < rows; j++) { for (i = 0; i < cols; i++) @@ -842,7 +842,7 @@ return FALSE; } - SetWindowLongA(hDlg, DWL_USER, (LONG)lpp); + SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)lpp); if (!(lpp->lpcc->Flags & CC_SHOWHELP)) ShowWindow( GetDlgItem(hDlg,0x40e), SW_HIDE); @@ -936,7 +936,7 @@ UINT cokmsg; HDC hdc; COLORREF *cr; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); TRACE("CC_WMCommand wParam=%x lParam=%lx\n", wParam, lParam); switch (wParam) { @@ -1058,7 +1058,7 @@ LRESULT CC_WMPaint( HWND hDlg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); BeginPaint(hDlg, &ps); /* we have to paint dialog children except text and buttons */ @@ -1079,7 +1079,7 @@ */ LRESULT CC_WMLButtonUp( HWND hDlg, WPARAM wParam, LPARAM lParam ) { - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); if (lpp->capturedGraph) { lpp->capturedGraph = 0; @@ -1095,7 +1095,7 @@ */ LRESULT CC_WMMouseMove( HWND hDlg, LPARAM lParam ) { - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); int r, g, b; if (lpp->capturedGraph) @@ -1133,7 +1133,7 @@ */ LRESULT CC_WMLButtonDown( HWND hDlg, WPARAM wParam, LPARAM lParam ) { - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); int r, g, b, i; i = 0; @@ -1192,7 +1192,7 @@ { int res; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); if (message != WM_INITDIALOG) { if (!lpp) @@ -1217,7 +1217,7 @@ DeleteDC(lpp->hdcMem); DeleteObject(lpp->hbmMem); HeapFree(GetProcessHeap(), 0, lpp); - SetWindowLongA(hDlg, DWL_USER, 0L); /* we don't need it anymore */ + SetWindowLongPtrW(hDlg, DWLP_USER, 0); /* we don't need it anymore */ break; case WM_COMMAND: if (CC_WMCommand( hDlg, wParam, lParam, HIWORD(wParam), (HWND) lParam)) diff -urN wine-20050211/dlls/commdlg/colordlg16.c wine-20050310/dlls/commdlg/colordlg16.c --- wine-20050211/dlls/commdlg/colordlg16.c 2004-09-22 21:36:47.000000000 +0200 +++ wine-20050310/dlls/commdlg/colordlg16.c 2005-02-15 22:51:07.000000000 +0100 @@ -102,7 +102,7 @@ ch32->lpfnHook = (LPCCHOOKPROC) ch16->lpfnHook; /* only used as flag */ ch32->Flags = ch16->Flags; - SetWindowLongA(hDlg, DWL_USER, (LONG)lpp); + SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)lpp); if (!(lpp->lpcc->Flags & CC_SHOWHELP)) ShowWindow( GetDlgItem(hDlg,0x40e), SW_HIDE); @@ -196,7 +196,7 @@ UINT cokmsg; HDC hdc; COLORREF *cr; - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); TRACE("CC_WMCommand wParam=%x lParam=%lx\n", wParam, lParam); switch (wParam) { @@ -334,7 +334,7 @@ BOOL16 res; HWND hDlg = HWND_32(hDlg16); - LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); + LCCPRIV lpp = (LCCPRIV)GetWindowLongPtrW(hDlg, DWLP_USER); if (message != WM_INITDIALOG) { if (!lpp) @@ -360,7 +360,7 @@ DeleteObject(lpp->hbmMem); HeapFree(GetProcessHeap(), 0, lpp->lpcc); HeapFree(GetProcessHeap(), 0, lpp); - SetWindowLongA(hDlg, DWL_USER, 0L); /* we don't need it anymore */ + SetWindowLongPtrW(hDlg, DWLP_USER, 0); /* we don't need it anymore */ break; case WM_COMMAND: if (CC_WMCommand16(hDlg, wParam, lParam, diff -urN wine-20050211/dlls/commdlg/filedlg.c wine-20050310/dlls/commdlg/filedlg.c --- wine-20050211/dlls/commdlg/filedlg.c 2005-02-10 18:10:01.000000000 +0100 +++ wine-20050310/dlls/commdlg/filedlg.c 2005-02-15 22:51:07.000000000 +0100 @@ -1528,7 +1528,7 @@ TRACE("\n"); - SetWindowLongA(hwnd,DWL_MSGRESULT,(LONG)fodInfos->Shell.FOIShellBrowser); + SetWindowLongPtrW(hwnd,DWLP_MSGRESULT,(LONG_PTR)fodInfos->Shell.FOIShellBrowser); return TRUE; } @@ -1551,7 +1551,7 @@ TRACE("---\n"); /* First send CDN_FILEOK as MSDN doc says */ SendCustomDlgNotificationMessage(hwnd,CDN_FILEOK); - if (GetWindowLongW(fodInfos->DlgInfos.hwndCustomDlg, DWL_MSGRESULT)) + if (GetWindowLongPtrW(fodInfos->DlgInfos.hwndCustomDlg, DWLP_MSGRESULT)) { TRACE("canceled\n"); return FALSE; @@ -1560,7 +1560,7 @@ /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */ SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, fodInfos->HookMsg.fileokstring, 0, (LPARAM)fodInfos->ofnInfos); - if (GetWindowLongW(fodInfos->DlgInfos.hwndCustomDlg, DWL_MSGRESULT)) + if (GetWindowLongPtrW(fodInfos->DlgInfos.hwndCustomDlg, DWLP_MSGRESULT)) { TRACE("canceled\n"); return FALSE; diff -urN wine-20050211/dlls/commdlg/finddlg.c wine-20050310/dlls/commdlg/finddlg.c --- wine-20050211/dlls/commdlg/finddlg.c 2004-09-22 21:36:47.000000000 +0200 +++ wine-20050310/dlls/commdlg/finddlg.c 2005-02-15 22:51:07.000000000 +0100 @@ -230,7 +230,7 @@ static LRESULT FINDDLG_WMInitDialog(HWND hWnd, LPARAM lParam, LPDWORD lpFlags, LPSTR lpstrFindWhat, BOOL fUnicode) { - SetWindowLongA(hWnd, DWL_USER, lParam); + SetWindowLongPtrW(hWnd, DWLP_USER, lParam); *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM); /* * FIXME : If the initial FindWhat string is empty, we should disable the @@ -295,14 +295,14 @@ else *lpFlags &= ~FR_MATCHCASE; *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM); *lpFlags |= FR_FINDNEXT; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); return TRUE; case IDCANCEL: *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL); *lpFlags |= FR_DIALOGTERM; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); DestroyWindow(hWnd); return TRUE; case pshHelp: @@ -328,7 +328,7 @@ return FINDDLG_WMInitDialog(hWnd, lParam, &(lpfr->Flags), MapSL(lpfr->lpstrFindWhat), FALSE); case WM_COMMAND: - lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER)); + lpfr=MapSL(GetWindowLongPtrW(hWnd, DWLP_USER)); return FINDDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner), &lpfr->Flags, MapSL(lpfr->lpstrFindWhat), lpfr->wFindWhatLen, FALSE); @@ -344,7 +344,7 @@ LPDWORD lpFlags, LPSTR lpstrFindWhat, LPSTR lpstrReplaceWith, BOOL fUnicode) { - SetWindowLongA(hWnd, DWL_USER, lParam); + SetWindowLongPtrW(hWnd, DWLP_USER, lParam); *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM); /* * FIXME : If the initial FindWhat string is empty, we should disable the FinNext / @@ -410,14 +410,14 @@ else *lpFlags &= ~FR_MATCHCASE; *lpFlags &= ~(FR_REPLACE | FR_REPLACEALL | FR_DIALOGTERM); *lpFlags |= FR_FINDNEXT; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); return TRUE; case IDCANCEL: *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL); *lpFlags |= FR_DIALOGTERM; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); DestroyWindow(hWnd); return TRUE; case psh1: @@ -438,8 +438,8 @@ else *lpFlags &= ~FR_MATCHCASE; *lpFlags &= ~(FR_FINDNEXT | FR_REPLACEALL | FR_DIALOGTERM); *lpFlags |= FR_REPLACE; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); return TRUE; case psh2: if (fUnicode) @@ -459,8 +459,8 @@ else *lpFlags &= ~FR_MATCHCASE; *lpFlags &= ~(FR_FINDNEXT | FR_REPLACE | FR_DIALOGTERM); *lpFlags |= FR_REPLACEALL; - SendMessageA(hwndOwner, uFindReplaceMessage, 0, - GetWindowLongA(hWnd, DWL_USER) ); + SendMessageW( hwndOwner, uFindReplaceMessage, 0, + GetWindowLongPtrW(hWnd, DWLP_USER) ); return TRUE; case pshHelp: /* FIXME : should lpfr structure be passed as an argument ??? */ @@ -486,7 +486,7 @@ MapSL(lpfr->lpstrFindWhat), MapSL(lpfr->lpstrReplaceWith), FALSE); case WM_COMMAND: - lpfr=MapSL(GetWindowLongA(hWnd, DWL_USER)); + lpfr=MapSL(GetWindowLongPtrW(hWnd, DWLP_USER)); return REPLACEDLG_WMCommand(hWnd, wParam, HWND_32(lpfr->hwndOwner), &lpfr->Flags, MapSL(lpfr->lpstrFindWhat), lpfr->wFindWhatLen, MapSL(lpfr->lpstrReplaceWith), diff -urN wine-20050211/dlls/commdlg/fontdlg.c wine-20050310/dlls/commdlg/fontdlg.c --- wine-20050211/dlls/commdlg/fontdlg.c 2005-01-06 20:43:43.000000000 +0100 +++ wine-20050310/dlls/commdlg/fontdlg.c 2005-02-25 15:00:38.000000000 +0100 @@ -590,7 +590,7 @@ HCURSOR hcursor=SetCursor(LoadCursorW(0,(LPWSTR)IDC_WAIT)); static const WCHAR strColorName[] = {'[','c','o','l','o','r',' ','n','a','m','e',']',0}; - SetPropW(hDlg, strWineFontData, (HANDLE)lParam); + SetPropW(hDlg, strWineFontData, (HANDLE)lpcf); lpxx=lpcf->lpLogFont; TRACE("WM_INITDIALOG lParam=%08lX\n", lParam); @@ -697,7 +697,7 @@ SendMessageW(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE), (LPARAM)GetDlgItem(hDlg,cmb1)); } - if (lpcf->Flags & CF_USESTYLE && lpcf->lpszStyle) + if ((lpcf->Flags & CF_USESTYLE) && lpcf->lpszStyle) { j=SendDlgItemMessageW(hDlg,cmb2,CB_FINDSTRING,-1,(LONG)lpcf->lpszStyle); if (j!=CB_ERR) @@ -1041,7 +1041,7 @@ WideCharToMultiByte(CP_ACP, 0, lpcfw->lpLogFont->lfFaceName, LF_FACESIZE, lpcfa->lpLogFont->lfFaceName, LF_FACESIZE, 0, 0); - if(lpcfw->lpszStyle) { + if((lpcfw->Flags & CF_USESTYLE) && lpcfw->lpszStyle) { len = WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, NULL, -1, 0, 0); WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, lpcfa->lpszStyle, len, 0, 0); HeapFree(GetProcessHeap(), 0, lpcfw->lpszStyle); @@ -1135,13 +1135,13 @@ MultiByteToWideChar(CP_ACP, 0, lpcfa->lpLogFont->lfFaceName, LF_FACESIZE, lpcfw->lpLogFont->lfFaceName, LF_FACESIZE); - if(lpcfa->lpszStyle) { + if((lpcfa->Flags & CF_USESTYLE) && lpcfa->lpszStyle) { len = MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, NULL, 0); lpcfw->lpszStyle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, lpcfw->lpszStyle, len); } - if(lpcfa->lpTemplateName) { + if((lpcfa->Flags & CF_ENABLETEMPLATE) && lpcfa->lpTemplateName) { len = MultiByteToWideChar(CP_ACP, 0, lpcfa->lpTemplateName, -1, NULL, 0); lpcfw->lpTemplateName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, lpcfa->lpTemplateName, diff -urN wine-20050211/dlls/commdlg/fontdlg16.c wine-20050310/dlls/commdlg/fontdlg16.c --- wine-20050211/dlls/commdlg/fontdlg16.c 2004-12-23 19:24:50.000000000 +0100 +++ wine-20050310/dlls/commdlg/fontdlg16.c 2005-02-15 22:51:07.000000000 +0100 @@ -122,7 +122,7 @@ { HWND hwnd=HWND_32(LOWORD(lParam)); HWND hDlg=GetParent(hwnd); - LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); + LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongPtrW(hDlg, DWLP_USER); LOGFONT16 *lplf = MapSL( logfont ); TEXTMETRIC16 *lpmtrx16 = MapSL(metrics); ENUMLOGFONTEXW elf32w; @@ -142,7 +142,7 @@ HWND hcmb2=HWND_32(LOWORD(lParam)); HWND hcmb3=HWND_32(HIWORD(lParam)); HWND hDlg=GetParent(hcmb3); - LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); + LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongPtrW(hDlg, DWLP_USER); LOGFONT16 *lplf = MapSL(logfont); TEXTMETRIC16 *lpmtrx16 = MapSL(metrics); ENUMLOGFONTEXW elf32w; @@ -300,7 +300,7 @@ BOOL16 res=0; if (message!=WM_INITDIALOG) { - lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); + lpcf=(LPCHOOSEFONT16)GetWindowLongPtrW(hDlg, DWLP_USER); if (!lpcf && message != WM_MEASUREITEM) return FALSE; if (CFn_HookCallChk(lpcf)) diff -urN wine-20050211/dlls/cryptdll/Makefile.in wine-20050310/dlls/cryptdll/Makefile.in --- wine-20050211/dlls/cryptdll/Makefile.in 2005-01-24 20:07:16.000000000 +0100 +++ wine-20050310/dlls/cryptdll/Makefile.in 2005-02-22 20:34:15.000000000 +0100 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = cryptdll.dll -IMPORTS = kernel32 +IMPORTS = advapi32 kernel32 C_SRCS = \ cryptdll.c diff -urN wine-20050211/dlls/cryptdll/cryptdll.spec wine-20050310/dlls/cryptdll/cryptdll.spec --- wine-20050211/dlls/cryptdll/cryptdll.spec 2005-01-24 20:07:16.000000000 +0100 +++ wine-20050310/dlls/cryptdll/cryptdll.spec 2005-02-22 20:34:15.000000000 +0100 @@ -9,6 +9,6 @@ @ stub CDRegisterCSystem @ stub CDRegisterCheckSum @ stub CDRegisterRng -@ stub MD5Final -@ stub MD5Init -@ stub MD5Update +@ stdcall MD5Final(ptr) advapi32.MD5Final +@ stdcall MD5Init(ptr) advapi32.MD5Init +@ stdcall MD5Update(ptr ptr long) advapi32.MD5Update diff -urN wine-20050211/dlls/d3d8/d3d8_private.h wine-20050310/dlls/d3d8/d3d8_private.h --- wine-20050211/dlls/d3d8/d3d8_private.h 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050310/dlls/d3d8/d3d8_private.h 2005-03-02 13:23:22.000000000 +0100 @@ -378,10 +378,10 @@ BOOL last_was_rhw; /* true iff last draw_primitive was in xyzrhw mode */ GLenum tracking_parm; /* Which source is tracking current colour */ LONG tracking_color; /* used iff GL_COLOR_MATERIAL was enabled */ - #define DISABLED_TRACKING 0 /* Disabled */ - #define IS_TRACKING 1 /* tracking_parm is tracking diffuse color */ - #define NEEDS_TRACKING 2 /* Tracking needs to be enabled when needed */ - #define NEEDS_DISABLE 3 /* Tracking needs to be disabled when needed*/ +#define DISABLED_TRACKING 0 /* Disabled */ +#define IS_TRACKING 1 /* tracking_parm is tracking diffuse color */ +#define NEEDS_TRACKING 2 /* Tracking needs to be enabled when needed */ +#define NEEDS_DISABLE 3 /* Tracking needs to be disabled when needed*/ /* OpenGL related */ GLXContext glCtx; diff -urN wine-20050211/dlls/d3d8/directx.c wine-20050310/dlls/d3d8/directx.c --- wine-20050211/dlls/d3d8/directx.c 2005-01-31 17:34:07.000000000 +0100 +++ wine-20050310/dlls/d3d8/directx.c 2005-02-24 11:05:06.000000000 +0100 @@ -264,8 +264,10 @@ case VENDOR_ATI: major = minor = 0; gl_string_cursor = strchr(gl_string, '-'); - if (gl_string_cursor++) { + if (gl_string_cursor) { int error = 0; + gl_string_cursor++; + /* Check if version number is of the form x.y.z */ if (*gl_string_cursor > '9' && *gl_string_cursor < '0') error = 1; diff -urN wine-20050211/dlls/d3d9/d3d9_main.c wine-20050310/dlls/d3d9/d3d9_main.c --- wine-20050211/dlls/d3d9/d3d9_main.c 2004-11-23 14:52:46.000000000 +0100 +++ wine-20050310/dlls/d3d9/d3d9_main.c 2005-03-02 14:44:59.000000000 +0100 @@ -21,6 +21,7 @@ */ #include "config.h" +#include "initguid.h" #include "d3d9_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); diff -urN wine-20050211/dlls/d3d9/d3d9_private.h wine-20050310/dlls/d3d9/d3d9_private.h --- wine-20050211/dlls/d3d9/d3d9_private.h 2005-01-28 15:03:32.000000000 +0100 +++ wine-20050310/dlls/d3d9/d3d9_private.h 2005-03-03 14:57:15.000000000 +0100 @@ -2,7 +2,8 @@ * Direct3D 9 private include file * * Copyright 2002-2003 Jason Edmeades - * Raphael Junqueira + * Copyright 2002-2003 Raphael Junqueira + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -83,7 +84,7 @@ #define MAX_LEVELS 256 /* Other useful values */ -#define HIGHEST_RENDER_STATE 174 +#define HIGHEST_RENDER_STATE D3DRS_BLENDOPALPHA #define HIGHEST_TEXTURE_STATE 29 #define HIGHEST_TRANSFORMSTATE 512 #define D3DSBT_RECORDED 0xfffffffe @@ -108,7 +109,6 @@ typedef struct IDirect3DVertexShader9Impl IDirect3DVertexShader9Impl; typedef struct IDirect3DPixelShader9Impl IDirect3DPixelShader9Impl; typedef struct IDirect3DVertexDeclaration9Impl IDirect3DVertexDeclaration9Impl; -typedef struct IDirect3DQuery9Impl IDirect3DQuery9Impl; #define D3DCOLOR_R(dw) (((float) (((dw) >> 16) & 0xFF)) / 255.0f) @@ -1108,37 +1108,24 @@ /***************************************************************************** * IDirect3DPixelShader implementation structure */ -struct IDirect3DQuery9Impl { +typedef struct IDirect3DQuery9Impl { /* IUnknown fields */ IDirect3DQuery9Vtbl *lpVtbl; - DWORD ref; + DWORD ref; - /* IDirect3DQuery9 fields */ - IDirect3DDevice9Impl* Device; -}; + /* IDirect3DQuery9 fields */ + IWineD3DQuery *wineD3DQuery; +} IDirect3DQuery9Impl; -/* IUnknown: */ -extern HRESULT WINAPI IDirect3DQuery9Impl_QueryInterface(LPDIRECT3DQUERY9 iface, REFIID riid, LPVOID* ppobj); -extern ULONG WINAPI IDirect3DQuery9Impl_AddRef(LPDIRECT3DQUERY9 iface); -extern ULONG WINAPI IDirect3DQuery9Impl_Release(LPDIRECT3DQUERY9 iface); - -/* IDirect3DQuery9: */ -extern HRESULT WINAPI IDirect3DQuery9Impl_GetDevice(LPDIRECT3DQUERY9 iface, IDirect3DDevice9** ppDevice); -extern D3DQUERYTYPE WINAPI IDirect3DQuery9Impl_GetType(LPDIRECT3DQUERY9 iface); -extern DWORD WINAPI IDirect3DQuery9Impl_GetDataSize(LPDIRECT3DQUERY9 iface); -extern HRESULT WINAPI IDirect3DQuery9Impl_Issue(LPDIRECT3DQUERY9 iface, DWORD dwIssueFlags); -extern HRESULT WINAPI IDirect3DQuery9Impl_GetData(LPDIRECT3DQUERY9 iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags); /* Callbacks */ -extern HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *pDevice, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IWineD3DSurface **ppSurface, - HANDLE * pSharedHandle); +extern HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, UINT Width, UINT Height, + D3DFORMAT Format, DWORD Usage, D3DPOOL Pool, UINT Level, + IWineD3DSurface** ppSurface, HANDLE* pSharedHandle); + extern HRESULT WINAPI D3D9CB_CreateVolume(IUnknown *pDevice, UINT Width, UINT Height, UINT Depth, D3DFORMAT Format, D3DPOOL Pool, DWORD Usage, IWineD3DVolume **ppVolume, HANDLE * pSharedHandle); + #endif /* __WINE_D3D9_PRIVATE_H */ diff -urN wine-20050211/dlls/d3d9/device.c wine-20050310/dlls/d3d9/device.c --- wine-20050211/dlls/d3d9/device.c 2005-02-10 21:25:20.000000000 +0100 +++ wine-20050310/dlls/d3d9/device.c 2005-03-02 13:16:11.000000000 +0100 @@ -2,7 +2,8 @@ * IDirect3DDevice9 implementation * * Copyright 2002-2005 Jason Edmeades - * Raphael Junqueira + * Copyright 2002-2005 Raphael Junqueira + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,8 +23,7 @@ #include "config.h" #include "d3d9_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); -WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); +WINE_DEFAULT_DEBUG_CHANNEL(d3d9); /* IDirect3D IUnknown parts follow: */ @@ -67,23 +67,23 @@ /* IDirect3DDevice Interface follow: */ HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : stub\n", This); /* No way of notifying yet! */ - return D3D_OK; + + TRACE("(%p) : Relay\n", This); + return IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice); } UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub, emulating 32Mb for now\n", This); - /* - * pretend we have 32MB of any type of memory queried. - */ - return (1024*1024*32); + + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_GetAvailableTextureMem(This->WineD3DDevice); } -HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedRessources(LPDIRECT3DDEVICE9 iface) { +HRESULT WINAPI IDirect3DDevice9Impl_EvictManagedResources(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + + TRACE("(%p) : relay\n", This); + return IWineD3DDevice_EvictManagedResources(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice9Impl_GetDirect3D(LPDIRECT3DDEVICE9 iface, IDirect3D9** ppD3D9) { @@ -102,6 +102,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n", This); return IWineD3DDevice_GetDisplayMode(This->WineD3DDevice, iSwapChain, pMode); } @@ -114,106 +115,118 @@ HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVICE9 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot); - -/* TODO: - IDirect3DSurface9Impl* pSur = (IDirect3DSurface9Impl*) pCursorBitmap; - if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) { - ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap); - return D3DERR_INVALIDCALL; - } - if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) { - ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap); - return D3DERR_INVALIDCALL; - } -*/ - - This->xHotSpot = XHotSpot; - This->yHotSpot = YHotSpot; - return D3D_OK; + IDirect3DSurface9Impl *pSurface = (IDirect3DSurface9Impl*)pCursorBitmap; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_SetCursorProperties(This->WineD3DDevice,XHotSpot,YHotSpot,(IWineD3DSurface*)pSurface->wineD3DSurface); } void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9 iface, int XScreenSpace, int YScreenSpace, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace); - This->xScreenSpace = XScreenSpace; - This->yScreenSpace = YScreenSpace; - return; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_SetCursorPosition(This->WineD3DDevice, XScreenSpace, YScreenSpace, Flags); } BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9 iface, BOOL bShow) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : visible(%d)\n", This, bShow); - This->bCursorVisible = bShow; - return D3D_OK; + TRACE("(%p) Relay\n", This); + + return IWineD3DDevice_ShowCursor(This->WineD3DDevice, bShow); } HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + WINED3DPRESENT_PARAMETERS localParameters; + TRACE("(%p) Relay pPresentationParameters(%p)\n", This, pPresentationParameters); + + localParameters.BackBufferWidth = &pPresentationParameters->BackBufferWidth; + localParameters.BackBufferHeight = &pPresentationParameters->BackBufferHeight; + localParameters.BackBufferFormat = &pPresentationParameters->BackBufferFormat; + localParameters.BackBufferCount = &pPresentationParameters->BackBufferCount; + localParameters.MultiSampleType = &pPresentationParameters->MultiSampleType; + localParameters.MultiSampleQuality = &pPresentationParameters->MultiSampleQuality; + localParameters.SwapEffect = &pPresentationParameters->SwapEffect; + localParameters.hDeviceWindow = &pPresentationParameters->hDeviceWindow; + localParameters.Windowed = &pPresentationParameters->Windowed; + localParameters.EnableAutoDepthStencil = &pPresentationParameters->EnableAutoDepthStencil; + localParameters.AutoDepthStencilFormat = &pPresentationParameters->AutoDepthStencilFormat; + localParameters.Flags = &pPresentationParameters->Flags; + localParameters.FullScreen_RefreshRateInHz = &pPresentationParameters->FullScreen_RefreshRateInHz; + localParameters.PresentationInterval = &pPresentationParameters->PresentationInterval; + return IWineD3DDevice_Reset(This->WineD3DDevice, &localParameters); } -HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) { +HRESULT WINAPI IDirect3DDevice9Impl_Present(LPDIRECT3DDEVICE9 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* + pDirtyRegion) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n", This); return IWineD3DDevice_Present(This->WineD3DDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); } -HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { +HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 ** ppBackBuffer) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - IWineD3DSurface *retSurface = NULL; HRESULT rc = D3D_OK; + TRACE("(%p) Relay\n", This); + rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, iSwapChain, BackBuffer, Type, (IWineD3DSurface **)&retSurface); - if (rc == D3D_OK && NULL != ppBackBuffer) { + if (rc == D3D_OK && NULL != retSurface && NULL != ppBackBuffer) { IWineD3DSurface_GetParent(retSurface, (IUnknown **)ppBackBuffer); IWineD3DSurface_Release(retSurface); } return rc; } - HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + + return IWineD3DDevice_GetRasterStatus(This->WineD3DDevice, iSwapChain, pRasterStatus); } HRESULT WINAPI IDirect3DDevice9Impl_SetDialogBoxMode(LPDIRECT3DDEVICE9 iface, BOOL bEnableDialogs) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + + return IWineD3DDevice_SetDialogBoxMode(This->WineD3DDevice, bEnableDialogs); } void WINAPI IDirect3DDevice9Impl_SetGammaRamp(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) { - HDC hDC; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - - FIXME("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); - SetDeviceGammaRamp(hDC, (LPVOID) pRamp); - ReleaseDC(This->win_handle, hDC); - return; + TRACE("(%p) Relay\n", This); + + return IWineD3DDevice_SetGammaRamp(This->WineD3DDevice, iSwapChain, Flags, pRamp); } -void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { - HDC hDC; +void WINAPI IDirect3DDevice9Impl_GetGammaRamp(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - - FIXME("(%p) : pRamp@%p\n", This, pRamp); - hDC = GetDC(This->win_handle); - GetDeviceGammaRamp(hDC, pRamp); - ReleaseDC(This->win_handle, hDC); - return; + TRACE("(%p) Relay\n", This); + + return IWineD3DDevice_GetGammaRamp(This->WineD3DDevice, iSwapChain, pRamp); } -HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, - D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, - DWORD MultisampleQuality, BOOL Lockable, - IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) { + +HRESULT WINAPI IDirect3DDevice9Impl_CreateSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface9 **ppSurface,D3DRESOURCETYPE Type, UINT Usage,D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,HANDLE* pSharedHandle ) { + HRESULT hrc; IDirect3DSurface9Impl *object; - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hrc = D3D_OK; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n", This); + if(MultisampleQuality < 0) { + FIXME("MultisampleQuality out of range %ld, substituting 0 \n", MultisampleQuality); + /*FIXME: Find out what windows does with a MultisampleQuality < 0 */ + MultisampleQuality=0; + } + + if(MultisampleQuality > 0){ + FIXME("MultisampleQuality set to %ld, bstituting 0 \n" , MultisampleQuality); + /* + MultisampleQuality + [in] Quality level. The valid range is between zero and one less than the level returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality values of paired render targets, depth stencil surfaces, and the MultiSample type must all match. + */ + + MultisampleQuality=0; + } + /*FIXME: Check MAX bounds of MultisampleQuality*/ /* Allocate the storage for the device */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface9Impl)); @@ -225,95 +238,112 @@ object->lpVtbl = &Direct3DSurface9_Vtbl; object->ref = 1; - hrc = IWineD3DDevice_CreateRenderTarget(This->WineD3DDevice, Width, Height, Format, MultiSample, MultisampleQuality, - Lockable, &object->wineD3DSurface, pSharedHandle, (IUnknown *)object); + + TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p\n", This, Width, Height, Format, *ppSurface); + + hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, Format, Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage, Pool,MultiSample,MultisampleQuality,pSharedHandle,(IUnknown *)object); + if (hrc != D3D_OK) { - /* free up object */ + /* free up object */ FIXME("(%p) call to IWineD3DDevice_CreateRenderTarget failed\n", This); HeapFree(GetProcessHeap(), 0, object); *ppSurface = NULL; } else { *ppSurface = (LPDIRECT3DSURFACE9) object; - } + } return hrc; } -HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + + +HRESULT WINAPI IDirect3DDevice9Impl_CreateRenderTarget(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, + D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Lockable, + IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { + TRACE("Relay\n"); + /* Is this correct? */ + return IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,Lockable,FALSE/*Discard*/, 0/*Level*/, ppSurface,D3DRTYPE_SURFACE,D3DUSAGE_RENDERTARGET,D3DPOOL_DEFAULT,MultiSample,MultisampleQuality,pSharedHandle); + + } +HRESULT WINAPI IDirect3DDevice9Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, + D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, + DWORD MultisampleQuality, BOOL Discard, + IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { + TRACE("Relay\n"); + return IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,TRUE/* Lockable */,Discard, 0/* Level */ + ,ppSurface,D3DRTYPE_SURFACE,D3DUSAGE_DEPTHSTENCIL, + D3DPOOL_DEFAULT,MultiSample,MultisampleQuality,pSharedHandle); +} + + HRESULT WINAPI IDirect3DDevice9Impl_UpdateSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_UpdateSurface(This->WineD3DDevice, ((IDirect3DSurface9Impl *)pSourceSurface)->wineD3DSurface, pSourceRect, ((IDirect3DSurface9Impl *)pDestinationSurface)->wineD3DSurface, pDestPoint); } HRESULT WINAPI IDirect3DDevice9Impl_UpdateTexture(LPDIRECT3DDEVICE9 iface, IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_UpdateTexture(This->WineD3DDevice, ((IDirect3DBaseTexture9Impl *)pSourceTexture)->wineD3DBaseTexture, ((IDirect3DBaseTexture9Impl *)pDestinationTexture)->wineD3DBaseTexture); } +/* This isn't in MSDN! HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBuffer(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; FIXME("(%p) : stub\n", This); return D3D_OK; } +*/ HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTargetData(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DSurface9Impl *renderTarget = (IDirect3DSurface9Impl *)pRenderTarget; + IDirect3DSurface9Impl *destSurface = (IDirect3DSurface9Impl *)pDestSurface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetRenderTargetData(This->WineD3DDevice, renderTarget->wineD3DSurface, destSurface->wineD3DSurface); } HRESULT WINAPI IDirect3DDevice9Impl_GetFrontBufferData(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, IDirect3DSurface9* pDestSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DSurface9Impl *destSurface = (IDirect3DSurface9Impl *)pDestSurface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetFrontBufferData(This->WineD3DDevice, iSwapChain, destSurface->wineD3DSurface); } -HRESULT WINAPI IDirect3DDevice9Impl_StretchRects(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; +HRESULT WINAPI IDirect3DDevice9Impl_StretchRect(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_StretchRect(This->WineD3DDevice, ((IDirect3DSurface9Impl *)pSourceSurface)->wineD3DSurface, pSourceRect, ((IDirect3DSurface9Impl *)pDestSurface)->wineD3DSurface, pDestRect, Filter); } HRESULT WINAPI IDirect3DDevice9Impl_ColorFill(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pSurface, CONST RECT* pRect, D3DCOLOR color) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; -} - -HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) { - IDirect3DSurface9Impl *object; - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - HRESULT hrc = D3D_OK; - - /* Allocate the storage for the device */ - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface9Impl)); - if (NULL == object) { - FIXME("Allocation of memory failed\n"); - *ppSurface = NULL; - return D3DERR_OUTOFVIDEOMEMORY; - } - - object->lpVtbl = &Direct3DSurface9_Vtbl; - object->ref = 1; - hrc = IWineD3DDevice_CreateOffscreenPlainSurface(This->WineD3DDevice, Width, Height, Format, Pool, - &(object->wineD3DSurface), pSharedHandle, (IUnknown *)object); - if (hrc != D3D_OK) { - /* free up object */ - FIXME("(%p) call to IWineD3DDevice_CreateOffscreenPlainSurface failed\n", This); - HeapFree(GetProcessHeap(), 0, object); - *ppSurface = NULL; - } else { - *ppSurface = (LPDIRECT3DSURFACE9) object; - } - return hrc; + IDirect3DSurface9Impl *surface = (IDirect3DSurface9Impl *)pSurface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_ColorFill(This->WineD3DDevice, surface->wineD3DSurface, (CONST D3DRECT*)pRect, color); +} + +HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE* pSharedHandle) { + TRACE("Relay\n"); + if(Pool == D3DPOOL_MANAGED ){ + FIXME("Attempting to create a managed offscreen plain surface\n"); + return D3DERR_INVALIDCALL; + } + /*MSDN: D3DPOOL_SCRATCH will return a surface that has identical characteristics to a surface created by the Microsoft DirectX 8.x method CreateImageSurface. + + 'Off-screen plain surfaces are always lockable, regardless of their pool types.' + but then... + D3DPOOL_DEFAULT is the appropriate pool for use with the IDirect3DDevice9::StretchRect and IDirect3DDevice9::ColorFill. + Why, their always lockable? + should I change the usage to dynamic? + */ + return IDirect3DDevice9Impl_CreateSurface(iface,Width,Height,Format,TRUE/*Loackable*/,FALSE/*Discard*/,0/*Level*/ , ppSurface,D3DRTYPE_SURFACE, 0/*Usage (undefined/none)*/,Pool,D3DMULTISAMPLE_NONE,0/*MultisampleQuality*/,pSharedHandle); } +/* TODO: move to wineD3D */ HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr = S_OK; @@ -333,6 +363,7 @@ return hr; } +/* TODO: move to wineD3D */ HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer); @@ -341,6 +372,7 @@ return D3D_OK; } +/* TODO: move to wineD3D */ HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr = S_OK; @@ -355,6 +387,7 @@ return D3D_OK; } +/* TODO: move to wineD3D */ HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9** ppZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; TRACE("(%p)->returning (%p) default is stencilbuffer=(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer); @@ -365,227 +398,260 @@ HRESULT WINAPI IDirect3DDevice9Impl_BeginScene(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_BeginScene(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice9Impl_EndScene(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_EndScene(This->WineD3DDevice); + } HRESULT WINAPI IDirect3DDevice9Impl_Clear(LPDIRECT3DDEVICE9 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_Clear(This->WineD3DDevice, Count, pRects, Flags, Color, Z, Stencil); } HRESULT WINAPI IDirect3DDevice9Impl_SetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* lpMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetTransform(This->WineD3DDevice, State, lpMatrix); } HRESULT WINAPI IDirect3DDevice9Impl_GetTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetTransform(This->WineD3DDevice, State, pMatrix); } HRESULT WINAPI IDirect3DDevice9Impl_MultiplyTransform(LPDIRECT3DDEVICE9 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_MultiplyTransform(This->WineD3DDevice, State, pMatrix); } HRESULT WINAPI IDirect3DDevice9Impl_SetViewport(LPDIRECT3DDEVICE9 iface, CONST D3DVIEWPORT9* pViewport) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetViewport(This->WineD3DDevice, (WINED3DVIEWPORT *)pViewport); } HRESULT WINAPI IDirect3DDevice9Impl_GetViewport(LPDIRECT3DDEVICE9 iface, D3DVIEWPORT9* pViewport) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetViewport(This->WineD3DDevice, (WINED3DVIEWPORT *)pViewport); } HRESULT WINAPI IDirect3DDevice9Impl_SetMaterial(LPDIRECT3DDEVICE9 iface, CONST D3DMATERIAL9* pMaterial) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetMaterial(This->WineD3DDevice, (WINED3DMATERIAL *)pMaterial); } HRESULT WINAPI IDirect3DDevice9Impl_GetMaterial(LPDIRECT3DDEVICE9 iface, D3DMATERIAL9* pMaterial) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetMaterial(This->WineD3DDevice, (WINED3DMATERIAL *)pMaterial); } HRESULT WINAPI IDirect3DDevice9Impl_SetLight(LPDIRECT3DDEVICE9 iface, DWORD Index, CONST D3DLIGHT9* pLight) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetLight(This->WineD3DDevice, Index, (WINED3DLIGHT *)pLight); } HRESULT WINAPI IDirect3DDevice9Impl_GetLight(LPDIRECT3DDEVICE9 iface, DWORD Index, D3DLIGHT9* pLight) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetLight(This->WineD3DDevice, Index, (WINED3DLIGHT *)pLight); } HRESULT WINAPI IDirect3DDevice9Impl_LightEnable(LPDIRECT3DDEVICE9 iface, DWORD Index, BOOL Enable) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetLightEnable(This->WineD3DDevice, Index, Enable); } HRESULT WINAPI IDirect3DDevice9Impl_GetLightEnable(LPDIRECT3DDEVICE9 iface, DWORD Index, BOOL* pEnable) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetLightEnable(This->WineD3DDevice, Index, pEnable); } HRESULT WINAPI IDirect3DDevice9Impl_SetClipPlane(LPDIRECT3DDEVICE9 iface, DWORD Index, CONST float* pPlane) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetClipPlane(This->WineD3DDevice, Index, pPlane); } HRESULT WINAPI IDirect3DDevice9Impl_GetClipPlane(LPDIRECT3DDEVICE9 iface, DWORD Index, float* pPlane) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetClipPlane(This->WineD3DDevice, Index, pPlane); } HRESULT WINAPI IDirect3DDevice9Impl_SetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetRenderState(This->WineD3DDevice, State, Value); } HRESULT WINAPI IDirect3DDevice9Impl_GetRenderState(LPDIRECT3DDEVICE9 iface, D3DRENDERSTATETYPE State, DWORD* pValue) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetRenderState(This->WineD3DDevice, State, pValue); } HRESULT WINAPI IDirect3DDevice9Impl_SetClipStatus(LPDIRECT3DDEVICE9 iface, CONST D3DCLIPSTATUS9* pClipStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetClipStatus(This->WineD3DDevice, (WINED3DCLIPSTATUS *)pClipStatus); } HRESULT WINAPI IDirect3DDevice9Impl_GetClipStatus(LPDIRECT3DDEVICE9 iface, D3DCLIPSTATUS9* pClipStatus) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetClipStatus(This->WineD3DDevice, (WINED3DCLIPSTATUS *)pClipStatus); } -HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9** ppTexture) { +HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9 **ppTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DBaseTexture *retTexture = NULL; HRESULT rc = D3D_OK; + TRACE("(%p) Relay\n" , This); + + if(ppTexture == NULL){ + return D3DERR_INVALIDCALL; + } + rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, (IWineD3DBaseTexture **)&retTexture); - if (rc == D3D_OK && NULL != ppTexture) { + if (rc == D3D_OK && NULL != retTexture) { IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); IWineD3DBaseTexture_Release(retTexture); + }else{ + FIXME("Call to get texture (%ld) failed (%p) \n", Stage, retTexture); + *ppTexture = NULL; } return rc; } HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9* pTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay %ld %p\n" , This, Stage, pTexture); return IWineD3DDevice_SetTexture(This->WineD3DDevice, Stage, pTexture==NULL ? NULL:((IDirect3DBaseTexture9Impl *)pTexture)->wineD3DBaseTexture); } HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, Type, pValue); } HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, Type, Value); } HRESULT WINAPI IDirect3DDevice9Impl_GetSamplerState(LPDIRECT3DDEVICE9 iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Sampler, Type, pValue); } HRESULT WINAPI IDirect3DDevice9Impl_SetSamplerState(LPDIRECT3DDEVICE9 iface, DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Sampler, Type, Value); } HRESULT WINAPI IDirect3DDevice9Impl_ValidateDevice(LPDIRECT3DDEVICE9 iface, DWORD* pNumPasses) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_ValidateDevice(This->WineD3DDevice, pNumPasses); } HRESULT WINAPI IDirect3DDevice9Impl_SetPaletteEntries(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber, pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags); - memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY)); - return D3D_OK; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); } HRESULT WINAPI IDirect3DDevice9Impl_GetPaletteEntries(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY)); - FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber, pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetPaletteEntries(This->WineD3DDevice, PaletteNumber, pEntries); } HRESULT WINAPI IDirect3DDevice9Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE9 iface, UINT PaletteNumber) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); } HRESULT WINAPI IDirect3DDevice9Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE9 iface, UINT* PaletteNumber) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - *PaletteNumber = This->currentPalette; - FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetCurrentTexturePalette(This->WineD3DDevice, PaletteNumber); } HRESULT WINAPI IDirect3DDevice9Impl_SetScissorRect(LPDIRECT3DDEVICE9 iface, CONST RECT* pRect) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetScissorRect(This->WineD3DDevice, pRect); } HRESULT WINAPI IDirect3DDevice9Impl_GetScissorRect(LPDIRECT3DDEVICE9 iface, RECT* pRect) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetScissorRect(This->WineD3DDevice, pRect); } HRESULT WINAPI IDirect3DDevice9Impl_SetSoftwareVertexProcessing(LPDIRECT3DDEVICE9 iface, BOOL bSoftware) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetSoftwareVertexProcessing(This->WineD3DDevice, bSoftware); } BOOL WINAPI IDirect3DDevice9Impl_GetSoftwareVertexProcessing(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetSoftwareVertexProcessing(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice9Impl_SetNPatchMode(LPDIRECT3DDEVICE9 iface, float nSegments) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_SetNPatchMode(This->WineD3DDevice, nSegments); } float WINAPI IDirect3DDevice9Impl_GetNPatchMode(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0.0f; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetNPatchMode(This->WineD3DDevice); } HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitive(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_DrawPrimitive(This->WineD3DDevice, PrimitiveType, StartVertex, PrimitiveCount); } HRESULT WINAPI IDirect3DDevice9Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_DrawIndexedPrimitive(This->WineD3DDevice, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); } HRESULT WINAPI IDirect3DDevice9Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE9 iface, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_DrawPrimitiveUP(This->WineD3DDevice, PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); } @@ -593,98 +659,122 @@ UINT NumVertexIndices, UINT PrimitiveCount, CONST void* pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_DrawIndexedPrimitiveUP(This->WineD3DDevice, PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); } HRESULT WINAPI IDirect3DDevice9Impl_ProcessVertices(LPDIRECT3DDEVICE9 iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_ProcessVertices(This->WineD3DDevice,SrcStartIndex, DestIndex, VertexCount, ((IDirect3DVertexBuffer9Impl *)pDestBuffer)->wineD3DVertexBuffer, ((IDirect3DVertexBuffer9Impl *)pVertexDecl)->wineD3DVertexBuffer, Flags); } HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(LPDIRECT3DDEVICE9 iface, DWORD FVF) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetFVF(This->WineD3DDevice, FVF); } HRESULT WINAPI IDirect3DDevice9Impl_GetFVF(LPDIRECT3DDEVICE9 iface, DWORD* pFVF) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_GetFVF(This->WineD3DDevice, pFVF); } HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); return IWineD3DDevice_SetStreamSource(This->WineD3DDevice, StreamNumber, pStreamData==NULL ? NULL:((IDirect3DVertexBuffer9Impl *)pStreamData)->wineD3DVertexBuffer, OffsetInBytes, Stride); } -HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9** pStream, UINT* OffsetInBytes, UINT* pStride) { +HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSource(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, IDirect3DVertexBuffer9 **pStream, UINT* OffsetInBytes, UINT* pStride) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DVertexBuffer *retStream = NULL; HRESULT rc = D3D_OK; + TRACE("(%p) Relay\n" , This); + + if(pStream == NULL){ + return D3DERR_INVALIDCALL; + } + rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, (IWineD3DVertexBuffer **)&retStream, OffsetInBytes, pStride); - if (rc == D3D_OK && NULL != pStream) { + if (rc == D3D_OK && NULL != retStream) { IWineD3DVertexBuffer_GetParent(retStream, (IUnknown **)pStream); IWineD3DVertexBuffer_Release(retStream); + }else{ + FIXME("Call to GetStreamSource failed %p %p\n", OffsetInBytes, pStride); + *pStream = NULL; } return rc; } HRESULT WINAPI IDirect3DDevice9Impl_SetStreamSourceFreq(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, UINT Divider) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n" , This); + IWineD3DDevice_SetStreamSourceFreq(This->WineD3DDevice, StreamNumber, Divider); return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_GetStreamSourceFreq(LPDIRECT3DDEVICE9 iface, UINT StreamNumber, UINT* Divider) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + TRACE("(%p) Relay\n" , This); + return IWineD3DDevice_GetStreamSourceFreq(This->WineD3DDevice, StreamNumber, Divider); return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_SetIndices(LPDIRECT3DDEVICE9 iface, IDirect3DIndexBuffer9* pIndexData) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + TRACE("(%p) Relay\n", This); return IWineD3DDevice_SetIndices(This->WineD3DDevice, pIndexData==NULL ? NULL:((IDirect3DIndexBuffer9Impl *)pIndexData)->wineD3DIndexBuffer, 0); } -HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9 iface, IDirect3DIndexBuffer9** ppIndexData) { +HRESULT WINAPI IDirect3DDevice9Impl_GetIndices(LPDIRECT3DDEVICE9 iface, IDirect3DIndexBuffer9 **ppIndexData) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IWineD3DIndexBuffer *retIndexData = NULL; HRESULT rc = D3D_OK; UINT tmp; + TRACE("(%p) Relay\n", This); + + if(ppIndexData == NULL){ + return D3DERR_INVALIDCALL; + } + rc = IWineD3DDevice_GetIndices(This->WineD3DDevice, &retIndexData, &tmp); - if (rc == D3D_OK && NULL != ppIndexData) { + if (rc == D3D_OK && NULL != retIndexData) { IWineD3DVertexBuffer_GetParent(retIndexData, (IUnknown **)ppIndexData); IWineD3DVertexBuffer_Release(retIndexData); + }else{ + if(rc != D3D_OK) FIXME("Call to GetIndices failed\n"); + *ppIndexData = NULL; } return rc; } -HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) { +HRESULT WINAPI IDirect3DDevice9Impl_DrawRectPatch(LPDIRECT3DDEVICE9 iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_DrawRectPatch(This->WineD3DDevice, Handle, pNumSegs, pRectPatchInfo); } - -HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) { +/*http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp*/ +HRESULT WINAPI IDirect3DDevice9Impl_DrawTriPatch(LPDIRECT3DDEVICE9 iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_DrawTriPatch(This->WineD3DDevice, Handle, pNumSegs, pTriPatchInfo); } HRESULT WINAPI IDirect3DDevice9Impl_DeletePatch(LPDIRECT3DDEVICE9 iface, UINT Handle) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DDevice_DeletePatch(This->WineD3DDevice, Handle); } - IDirect3DDevice9Vtbl Direct3DDevice9_Vtbl = { IDirect3DDevice9Impl_QueryInterface, @@ -692,7 +782,7 @@ IDirect3DDevice9Impl_Release, IDirect3DDevice9Impl_TestCooperativeLevel, IDirect3DDevice9Impl_GetAvailableTextureMem, - IDirect3DDevice9Impl_EvictManagedRessources, + IDirect3DDevice9Impl_EvictManagedResources, IDirect3DDevice9Impl_GetDirect3D, IDirect3DDevice9Impl_GetDeviceCaps, IDirect3DDevice9Impl_GetDisplayMode, @@ -721,7 +811,7 @@ IDirect3DDevice9Impl_UpdateTexture, IDirect3DDevice9Impl_GetRenderTargetData, IDirect3DDevice9Impl_GetFrontBufferData, - IDirect3DDevice9Impl_StretchRects, + IDirect3DDevice9Impl_StretchRect, IDirect3DDevice9Impl_ColorFill, IDirect3DDevice9Impl_CreateOffscreenPlainSurface, IDirect3DDevice9Impl_SetRenderTarget, @@ -807,3 +897,27 @@ IDirect3DDevice9Impl_DeletePatch, IDirect3DDevice9Impl_CreateQuery }; + + +/* Internal function called back during the CreateDevice to create a render target */ +HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, UINT Width, UINT Height, + D3DFORMAT Format, DWORD Usage, D3DPOOL Pool, UINT Level, + IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) { + + HRESULT res = D3D_OK; + IDirect3DSurface9Impl *d3dSurface = NULL; + BOOL Lockable = TRUE; + + if((Pool == D3DPOOL_DEFAULT && Usage != D3DUSAGE_DYNAMIC)) + Lockable = FALSE; + + TRACE("relay\n"); + res = IDirect3DDevice9Impl_CreateSurface((IDirect3DDevice9 *)device, Width, Height, Format, Lockable, FALSE/*Discard*/, Level, (IDirect3DSurface9 **)&d3dSurface, D3DRTYPE_SURFACE, Usage, Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */, pSharedHandle); + + if (res == D3D_OK) { + *ppSurface = d3dSurface->wineD3DSurface; + }else{ + FIXME("(%p) IDirect3DDevice9_CreateSurface failed\n", device); + } + return res; +} diff -urN wine-20050211/dlls/d3d9/query.c wine-20050310/dlls/d3d9/query.c --- wine-20050211/dlls/d3d9/query.c 2005-01-28 15:03:32.000000000 +0100 +++ wine-20050310/dlls/d3d9/query.c 2005-03-03 14:57:15.000000000 +0100 @@ -2,7 +2,8 @@ * IDirect3DQuery9 implementation * * Copyright 2002-2003 Raphael Junqueira - * Jason Edmeades + * Copyright 2002-2003 Jason Edmeades + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,15 +23,16 @@ #include "config.h" #include "d3d9_private.h" -WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DEFAULT_DEBUG_CHANNEL(d3d9); /* IDirect3DQuery9 IUnknown parts follow: */ HRESULT WINAPI IDirect3DQuery9Impl_QueryInterface(LPDIRECT3DQUERY9 iface, REFIID riid, LPVOID* ppobj) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; + TRACE("(%p) Relay\n", This); if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirect3DQuery9)) { - IDirect3DQuery9Impl_AddRef(iface); + IUnknown_AddRef(iface); *ppobj = This; return D3D_OK; } @@ -44,7 +46,6 @@ ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) : AddRef from %ld\n", This, ref - 1); - return ref; } @@ -63,34 +64,43 @@ /* IDirect3DQuery9 Interface follow: */ HRESULT WINAPI IDirect3DQuery9Impl_GetDevice(LPDIRECT3DQUERY9 iface, IDirect3DDevice9** ppDevice) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - TRACE("(%p) : returning %p\n", This, This->Device); - *ppDevice = (LPDIRECT3DDEVICE9) This->Device; - IDirect3DDevice9Impl_AddRef(*ppDevice); - return D3D_OK; + IWineD3DDevice* pDevice; + HRESULT hr; + + TRACE("(%p) Relay\n", This); + + hr = IWineD3DQuery_GetDevice(This->wineD3DQuery, &pDevice); + if(hr != D3D_OK){ + *ppDevice = NULL; + }else{ + hr = IWineD3DDevice_GetParent(pDevice, (IUnknown **)ppDevice); + IWineD3DDevice_Release(pDevice); + } + return hr; } D3DQUERYTYPE WINAPI IDirect3DQuery9Impl_GetType(LPDIRECT3DQUERY9 iface) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0; + TRACE("(%p) Relay\n", This); + return IWineD3DQuery_GetType(This->wineD3DQuery); } DWORD WINAPI IDirect3DQuery9Impl_GetDataSize(LPDIRECT3DQUERY9 iface) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0; + TRACE("(%p) Relay\n", This); + return IWineD3DQuery_GetDataSize(This->wineD3DQuery); } HRESULT WINAPI IDirect3DQuery9Impl_Issue(LPDIRECT3DQUERY9 iface, DWORD dwIssueFlags) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DQuery_Issue(This->wineD3DQuery, dwIssueFlags); } HRESULT WINAPI IDirect3DQuery9Impl_GetData(LPDIRECT3DQUERY9 iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + TRACE("(%p) Relay\n", This); + return IWineD3DQuery_GetData(This->wineD3DQuery, pData, dwSize, dwGetDataFlags); } @@ -109,12 +119,11 @@ /* IDirect3DDevice9 IDirect3DQuery9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9 iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) { -#if 0 IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; -#endif IDirect3DQuery9Impl *object = NULL; HRESULT hr = D3D_OK; - + + TRACE("(%p) Relay\n", This); if (NULL == ppQuery) { return D3DERR_INVALIDCALL; } @@ -128,8 +137,7 @@ object->lpVtbl = &Direct3DQuery9_Vtbl; object->ref = 1; -#if 0 - hr = IWineD3DDevice_CreateQuery(This->WineD3DDevice, 9, pVertexElements, &(object->wineD3DQuery)); + hr = IWineD3DDevice_CreateQuery(This->WineD3DDevice, Type, &(object->wineD3DQuery), (IUnknown*)object); if (FAILED(hr)) { /* free up object */ @@ -139,6 +147,6 @@ } else { *ppQuery = (LPDIRECT3DQUERY9) object; } -#endif + TRACE("(%p) : returning %p \n", This, *ppQuery); return hr; } diff -urN wine-20050211/dlls/d3d9/surface.c wine-20050310/dlls/d3d9/surface.c --- wine-20050211/dlls/d3d9/surface.c 2005-01-24 13:44:01.000000000 +0100 +++ wine-20050310/dlls/d3d9/surface.c 2005-03-02 14:44:59.000000000 +0100 @@ -109,26 +109,46 @@ IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; HRESULT res; - /* The container returned from IWineD3DSurface_GetContainer is either a IWineD3DDevice or - opne of the subclasses of resource */ + /* The container returned from IWineD3DSurface_GetContainer is either a IWineD3DDevice, + one of the subclasses of IWineD3DBaseTexture or a IWineD3DSwapChain */ IUnknown *IWineContainer = NULL; - res = IWineD3DSurface_GetContainer(This->wineD3DSurface, riid, (void **)&IWineContainer); - if (res == D3D_OK) { - IWineD3DDevice *myDevice = NULL; - IWineD3DResource_GetDevice((IWineD3DSurface *)This->wineD3DSurface, &myDevice); - - if (IWineContainer == (IUnknown *)myDevice) { - IWineD3DDevice_GetParent((IWineD3DDevice *)IWineContainer, (IUnknown **)ppContainer); - IWineD3DDevice_Release((IWineD3DDevice *)IWineContainer); - } else { - IWineD3DResource_GetParent((IWineD3DResource *)IWineContainer, (IUnknown **)ppContainer); - IWineD3DResource_Release((IWineD3DResource *)IWineContainer); + TRACE("(%p) Relay\n", This); + + /* Get the IUnknown container. */ + res = IWineD3DSurface_GetContainer(This->wineD3DSurface, &IID_IUnknown, (void **)&IWineContainer); + if (res == D3D_OK && IWineContainer != NULL) { + + /* Now find out what kind of container it is (so that we can get its parent)*/ + IUnknown *IUnknownParent = NULL; + IUnknown *myContainer = NULL; + if(D3D_OK == IUnknown_QueryInterface(IWineContainer, &IID_IWineD3DDevice, (void **)&myContainer)){ + IWineD3DDevice_GetParent((IWineD3DDevice *)IWineContainer, &IUnknownParent); + IUnknown_Release(myContainer); + } else + if(D3D_OK == IUnknown_QueryInterface(IWineContainer, &IID_IWineD3DBaseTexture, (void **)&myContainer)){ + IWineD3DBaseTexture_GetParent((IWineD3DBaseTexture *)IWineContainer, &IUnknownParent); + IUnknown_Release(myContainer); + } else + if(D3D_OK == IUnknown_QueryInterface(IWineContainer, &IID_IWineD3DSwapChain, (void **)&myContainer)){ + IWineD3DBaseTexture_GetParent((IWineD3DBaseTexture *)IWineContainer, &IUnknownParent); + IUnknown_Release(myContainer); + }else{ + FIXME("Container is of unknown interface\n"); } + /* Tidy up.. */ + IUnknown_Release((IWineD3DDevice *)IWineContainer); - IWineD3DDevice_Release(myDevice); + /* Now, query the interface of the parent for the riid */ + if(IUnknownParent != NULL){ + res = IUnknown_QueryInterface(IUnknownParent, riid, ppContainer); + /* Tidy up.. */ + IUnknown_Release(IUnknownParent); + } + } + TRACE("(%p) : returning %p\n", This, *ppContainer); return res; } @@ -192,25 +212,3 @@ IDirect3DSurface9Impl_GetDC, IDirect3DSurface9Impl_ReleaseDC }; - -/* Internal function called back during the CreateTexture and CreateCubeTextures to create the surface(s) */ -HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *pDevice, - UINT Width, - UINT Height, - D3DFORMAT Format, - D3DPOOL Pool, - IWineD3DSurface **ppSurface, - HANDLE * pSharedHandle) { - - HRESULT res = D3D_OK; - IDirect3DSurface9Impl *d3dSurface = NULL; - - res = IDirect3DDevice9_CreateOffscreenPlainSurface((IDirect3DDevice9 *)pDevice, Width, Height, - Format, Pool, (IDirect3DSurface9 **)&d3dSurface, pSharedHandle); - if (res == D3D_OK) { - *ppSurface = d3dSurface->wineD3DSurface; - } else { - *ppSurface = NULL; - } - return res; -} diff -urN wine-20050211/dlls/d3d9/vertexdeclaration.c wine-20050310/dlls/d3d9/vertexdeclaration.c --- wine-20050211/dlls/d3d9/vertexdeclaration.c 2005-01-28 15:03:32.000000000 +0100 +++ wine-20050310/dlls/d3d9/vertexdeclaration.c 2005-03-02 13:16:11.000000000 +0100 @@ -89,6 +89,7 @@ /* IDirect3DDevice9 IDirect3DVertexDeclaration9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) { + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; IDirect3DVertexDeclaration9Impl *object = NULL; HRESULT hr = D3D_OK; @@ -106,7 +107,7 @@ object->lpVtbl = &Direct3DVertexDeclaration9_Vtbl; object->ref = 1; - hr = IWineD3DDevice_CreateVertexDeclaration(This->WineD3DDevice, 9, pVertexElements, &(object->wineD3DVertexDeclaration)); + hr = IWineD3DDevice_CreateVertexDeclaration(This->WineD3DDevice, pVertexElements, &object->wineD3DVertexDeclaration, (IUnknown *)object); if (FAILED(hr)) { /* free up object */ diff -urN wine-20050211/dlls/dbghelp/dbghelp.c wine-20050310/dlls/dbghelp/dbghelp.c --- wine-20050211/dlls/dbghelp/dbghelp.c 2004-11-19 19:02:47.000000000 +0100 +++ wine-20050310/dlls/dbghelp/dbghelp.c 2005-03-07 13:24:02.000000000 +0100 @@ -37,6 +37,11 @@ * but those values are not directly usable from a debugger (that's why, I * assume, that we have also to define constants for enum values, as * Codeview does BTW. + * + SymGetType(TI_GET_LENGTH) takes a ULONG64 (yurk, ugly) + * - SymGetLine{Next|Prev} don't work as expected (they don't seem to work across + * functions, and even across function blocks...). Basically, for *Next* to work + * it requires an address after the prolog of the func (the base address of the + * func doesn't work) * - most options (dbghelp_options) are not used (loading lines...) * - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when * we're supposed to use RE, it doesn't make use of our hash tables. Therefore, @@ -45,7 +50,7 @@ * - msc: * + we should add parameters' types to the function's signature * while processing a function's parameters - * + get rid of MSC reading FIXME:s (lots of types are not defined) + * + add support for function-less labels (as MSC seems to define them) * + C++ management * - stabs: * + when, in a same module, the same definition is used in several compilation @@ -132,25 +137,17 @@ * SymInitialize helper: loads in dbghelp all known (and loaded modules) * this assumes that hProcess is a handle on a valid process */ -static BOOL process_invade(HANDLE hProcess) +static BOOL WINAPI process_invade_cb(char* name, DWORD base, DWORD size, void* user) { - HMODULE hMods[256]; - char img[256]; - DWORD i, sz; - MODULEINFO mi; - - if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &sz)) - return FALSE; /* FIXME should grow hMods */ - - for (i = 0; i < sz / sizeof(HMODULE); i++) - { - if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) || - !GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) || - !SymLoadModule(hProcess, 0, img, NULL, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage)) - return FALSE; - } + char tmp[MAX_PATH]; + HANDLE hProcess = (HANDLE)user; - return sz != 0; + if (!GetModuleFileNameExA(hProcess, (HMODULE)base, + tmp, sizeof(tmp))) + lstrcpynA(tmp, name, sizeof(tmp)); + + SymLoadModule(hProcess, 0, tmp, name, base, size); + return TRUE; } /****************************************************************** @@ -235,9 +232,10 @@ SymCleanup(hProcess); return FALSE; } - process_invade(hProcess); + EnumerateLoadedModules(hProcess, process_invade_cb, (void*)hProcess); elf_synchronize_module_list(pcs); } + return TRUE; } diff -urN wine-20050211/dlls/dbghelp/dbghelp.spec wine-20050310/dlls/dbghelp/dbghelp.spec --- wine-20050211/dlls/dbghelp/dbghelp.spec 2004-10-21 21:57:56.000000000 +0200 +++ wine-20050310/dlls/dbghelp/dbghelp.spec 2005-03-07 12:03:21.000000000 +0100 @@ -20,8 +20,8 @@ @ stdcall ImagehlpApiVersionEx(ptr) @ stdcall MakeSureDirectoryPathExists(str) @ stdcall MapDebugInformation(long str str long) -@ stub MiniDumpReadDumpStream -@ stub MiniDumpWriteDump +@ stdcall MiniDumpReadDumpStream(ptr long ptr ptr ptr) +@ stdcall MiniDumpWriteDump(ptr long ptr long long long long) @ stdcall SearchTreeForFile(str str str) @ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr) @ stub StackWalk64 diff -urN wine-20050211/dlls/dbghelp/dbghelp_private.h wine-20050310/dlls/dbghelp/dbghelp_private.h --- wine-20050211/dlls/dbghelp/dbghelp_private.h 2004-11-19 19:02:47.000000000 +0100 +++ wine-20050310/dlls/dbghelp/dbghelp_private.h 2005-03-01 11:39:49.000000000 +0100 @@ -293,9 +293,12 @@ extern HANDLE hMsvcrt; /* elf_module.c */ -extern BOOL elf_load_debug_info(struct module* module); +typedef BOOL (*elf_enum_modules_cb)(const char*, unsigned long addr, void* user); +extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*); +struct elf_file_map; +extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap); extern struct module* - elf_load_module(struct process* pcs, const char* name); + elf_load_module(struct process* pcs, const char* name, unsigned long); extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs); extern BOOL elf_synchronize_module_list(struct process* pcs); diff -urN wine-20050211/dlls/dbghelp/elf_module.c wine-20050310/dlls/dbghelp/elf_module.c --- wine-20050211/dlls/dbghelp/elf_module.c 2005-01-31 17:24:57.000000000 +0100 +++ wine-20050310/dlls/dbghelp/elf_module.c 2005-03-07 12:03:21.000000000 +0100 @@ -89,6 +89,25 @@ struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */ }; +#define NO_MAP ((const void*)0xffffffff) +/* structure holding information while handling an ELF image + * allows one by one section mapping for memory savings + */ +struct elf_file_map +{ + Elf32_Ehdr elfhdr; + size_t elf_size; + size_t elf_start; + struct + { + Elf32_Shdr shdr; + const char* mapped; + }* sect; + int fd; + unsigned with_crc; + unsigned long crc; +}; + struct symtab_elt { struct hash_table_elt ht_elt; @@ -106,14 +125,127 @@ }; /****************************************************************** + * elf_map_section + * + * Maps a single section into memory from a ELF file + */ +static const char* elf_map_section(struct elf_file_map* fmap, int sidx) +{ + unsigned pgsz = getpagesize(); + unsigned ofst, size; + + if (sidx >= fmap->elfhdr.e_shnum || + fmap->sect[sidx].shdr.sh_type == SHT_NOBITS) + return NO_MAP; + /* align required information on page size (we assume pagesize is a power of 2) */ + ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1); + size = (fmap->sect[sidx].shdr.sh_offset + fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1); + fmap->sect[sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fmap->fd, ofst); + if (fmap->sect[sidx].mapped == NO_MAP) return NO_MAP; + return fmap->sect[sidx].mapped + (fmap->sect[sidx].shdr.sh_offset & (pgsz - 1)); +} + +/****************************************************************** + * elf_unmap_section + * + * Unmaps a single section from memory + */ +static void elf_unmap_section(struct elf_file_map* fmap, int sidx) +{ + if (sidx < fmap->elfhdr.e_shnum && fmap->sect[sidx].mapped != NO_MAP) + { + munmap((char*)fmap->sect[sidx].mapped, fmap->sect[sidx].shdr.sh_size); + fmap->sect[sidx].mapped = NO_MAP; + } +} + +/****************************************************************** + * elf_map_file + * + * Maps a ELF file into memory (and checks it's a real ELF file) + */ +static BOOL elf_map_file(const char* filename, struct elf_file_map* fmap) +{ + static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; + struct stat statbuf; + int i; + Elf32_Phdr phdr; + unsigned tmp, page_mask = getpagesize() - 1; + + + fmap->fd = -1; + fmap->with_crc = 0; + + /* check that the file exists, and that the module hasn't been loaded yet */ + if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) return FALSE; + + /* Now open the file, so that we can mmap() it. */ + if ((fmap->fd = open(filename, O_RDONLY)) == -1) return FALSE; + + if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr)) + return FALSE; + /* and check for an ELF header */ + if (memcmp(fmap->elfhdr.e_ident, + elf_signature, sizeof(elf_signature))) return FALSE; + + fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->elfhdr.e_shnum * sizeof(fmap->sect[0])); + if (!fmap->sect) return FALSE; + + lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET); + for (i = 0; i < fmap->elfhdr.e_shnum; i++) + { + read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr)); + fmap->sect[i].mapped = NO_MAP; + } + + /* grab size of module once loaded in memory */ + lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET); + fmap->elf_size = 0; + fmap->elf_start = ~0L; + for (i = 0; i < fmap->elfhdr.e_phnum; i++) + { + if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) && + phdr.p_type == PT_LOAD) + { + tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask; + if (fmap->elf_size < tmp) fmap->elf_size = tmp; + if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr; + } + } + /* if non relocatable ELF, then remove fixed address from computation + * otherwise, all addresses are zero based and start has no effect + */ + fmap->elf_size -= fmap->elf_start; + return TRUE; +} + +/****************************************************************** + * elf_unmap_file + * + * Unmaps a ELF file from memory (previously mapped with elf_map_file) + */ +static void elf_unmap_file(struct elf_file_map* fmap) +{ + if (fmap->fd != -1) + { + int i; + for (i = 0; i < fmap->elfhdr.e_shnum; i++) + { + elf_unmap_section(fmap, i); + } + HeapFree(GetProcessHeap(), 0, fmap->sect); + close(fmap->fd); + } +} + +/****************************************************************** * elf_hash_symtab * * creating an internal hash table to ease use ELF symtab information lookup */ static void elf_hash_symtab(const struct module* module, struct pool* pool, - struct hash_table* ht_symtab, const char* map_addr, - const Elf32_Shdr* symtab, const Elf32_Shdr* strtab, - unsigned num_areas, struct thunk_area* thunks) + struct hash_table* ht_symtab, struct elf_file_map* fmap, + int symtab_idx, struct thunk_area* thunks) { int i, j, nsym; const char* strp; @@ -123,11 +255,13 @@ const Elf32_Sym* symp; struct symtab_elt* ste; - symp = (const Elf32_Sym*)(map_addr + symtab->sh_offset); - nsym = symtab->sh_size / sizeof(*symp); - strp = (const char*)(map_addr + strtab->sh_offset); + symp = (const Elf32_Sym*)elf_map_section(fmap, symtab_idx); + strp = elf_map_section(fmap, fmap->sect[symtab_idx].shdr.sh_link); + if (symp == NO_MAP || strp == NO_MAP) return; + + nsym = fmap->sect[symtab_idx].shdr.sh_size / sizeof(*symp); - for (j = 0; j < num_areas; j++) + for (j = 0; thunks[j].symname; j++) thunks[j].rva_start = thunks[j].rva_end = 0; for (i = 0; i < nsym; i++, symp++) @@ -135,7 +269,10 @@ /* Ignore certain types of entries which really aren't of that much * interest. */ - if (ELF32_ST_TYPE(symp->st_info) == STT_SECTION || symp->st_shndx == SHN_UNDEF) + if ((ELF32_ST_TYPE(symp->st_info) != STT_FILE && + ELF32_ST_TYPE(symp->st_info) != STT_OBJECT && + ELF32_ST_TYPE(symp->st_info) != STT_FUNC) || + symp->st_shndx == SHN_UNDEF) { continue; } @@ -147,7 +284,7 @@ filename = symname; continue; } - for (j = 0; j < num_areas; j++) + for (j = 0; thunks[j].symname; j++) { if (!strcmp(symname, thunks[j].symname)) { @@ -156,7 +293,7 @@ break; } } - if (j < num_areas) continue; + if (thunks[j].symname) continue; /* FIXME: we don't need to handle them (GCC internals) * Moreover, they screw up our symbol lookup :-/ @@ -165,7 +302,8 @@ continue; ste = pool_alloc(pool, sizeof(*ste)); - /* GCC seems to emit, in some cases, a .+ suffix. + ste->ht_elt.name = symname; + /* GCC emits, in some cases, a .+ suffix. * This is used for static variable inside functions, so * that we can have several such variables with same name in * the same compilation unit @@ -173,10 +311,9 @@ * of it in stabs parsing) */ ptr = symname + strlen(symname) - 1; - ste->ht_elt.name = symname; if (isdigit(*ptr)) { - while (*ptr >= '0' && *ptr <= '9' && ptr >= symname) ptr--; + while (isdigit(*ptr) && ptr >= symname) ptr--; if (ptr > symname && *ptr == '.') { char* n = pool_alloc(pool, ptr - symname + 1); @@ -190,6 +327,10 @@ ste->used = 0; hash_table_add(ht_symtab, &ste->ht_elt); } + /* as we added in the ht_symtab pointers to the symbols themselves, + * we cannot unmap yet the sections, it will be done when we're over + * with this ELF file + */ } /****************************************************************** @@ -253,7 +394,7 @@ } if (!result && !(result = weak_result)) { - FIXME("Couldn't find symbol %s.%s in symtab\n", + FIXME("Couldn't find symbol %s!%s in symtab\n", module->module.ModuleName, name); return NULL; } @@ -289,10 +430,20 @@ ((struct symt_function*)sym)->container); if (symp) { + if (((struct symt_function*)sym)->address != module->elf_info->elf_addr && + ((struct symt_function*)sym)->address != module->elf_info->elf_addr + symp->st_value) + FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", + sym, module->module.ModuleName, sym->hash_elt.name, + ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); + if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size) + FIXME("Changing size for %p/%s!%s from %08lx to %08x\n", + sym, module->module.ModuleName, sym->hash_elt.name, + ((struct symt_function*)sym)->size, symp->st_size); + ((struct symt_function*)sym)->address = module->elf_info->elf_addr + symp->st_value; ((struct symt_function*)sym)->size = symp->st_size; - } else FIXME("Couldn't find %s\n", sym->hash_elt.name); + } else FIXME("Couldn't find %s!%s\n", module->module.ModuleName, sym->hash_elt.name); break; case SymTagData: switch (((struct symt_data*)sym)->kind) @@ -305,11 +456,16 @@ ((struct symt_data*)sym)->container); if (symp) { + if (((struct symt_data*)sym)->u.address != module->elf_info->elf_addr && + ((struct symt_data*)sym)->u.address != module->elf_info->elf_addr + symp->st_value) + FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", + sym, module->module.ModuleName, sym->hash_elt.name, + ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); ((struct symt_data*)sym)->u.address = module->elf_info->elf_addr + symp->st_value; ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal; - } + } else FIXME("Couldn't find %s!%s\n", module->module.ModuleName, sym->hash_elt.name); break; default:; } @@ -381,16 +537,20 @@ * used yet (ie we have no debug information on them) * That's the case, for example, of the .spec.c files */ - if (ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC) + switch (ELF32_ST_TYPE(ste->symp->st_info)) { + case STT_FUNC: symt_new_function(module, compiland, ste->ht_elt.name, addr, ste->symp->st_size, NULL); - } - else - { + break; + case STT_OBJECT: symt_new_global_variable(module, compiland, ste->ht_elt.name, ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL, addr, ste->symp->st_size, NULL); + break; + default: + FIXME("Shouldn't happen\n"); + break; } /* FIXME: this is a hack !!! * we are adding new symbols, but as we're parsing a symbol table @@ -410,7 +570,6 @@ symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_LENGTH, &xsize); symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_DATAKIND, &kind); -#if 0 /* If none of symbols has a correct size, we consider they are both markers * Hence, we can silence this warning * Also, we check that we don't have two symbols, one local, the other @@ -423,7 +582,6 @@ ste->ht_elt.name, addr, ste->symp->st_size, module->addr_sorttab[idx]->hash_elt.name, wine_dbgstr_longlong(xaddr), xsize); -#endif } } } @@ -529,7 +687,7 @@ /* using byte-swap instructions. */ -static DWORD calc_crc32(const unsigned char *buf, size_t len) +static DWORD calc_crc32(struct elf_file_map* fmap) { #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) static const DWORD crc_32_tab[] = @@ -578,37 +736,38 @@ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; - size_t i; - DWORD crc = ~0; - for(i = 0; i < len; i++) - crc = UPDC32(buf[i], crc); + int i, r; + unsigned char buffer[256]; + DWORD crc = ~0; + + lseek(fmap->fd, 0, SEEK_SET); + while ((r = read(fmap->fd, buffer, sizeof(buffer))) > 0) + { + for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc); + } return ~crc; #undef UPDC32 } - /****************************************************************** - * elf_load_debug_info_from_file + * elf_load_debug_info_from_map * - * Loads the symbolic information from ELF module stored in 'file' + * Loads the symbolic information from ELF module which mapping is described + * in fmap * the module has been loaded at 'load_offset' address, so symbols' address - * relocation is performed. crc optionally points to the CRC of the debug file - * to load. + * relocation is performed. + * CRC is checked if fmap->with_crc is TRUE * returns * 0 if the file doesn't contain symbolic info (or this info cannot be * read or parsed) * 1 on success */ -static BOOL elf_load_debug_info_from_file( - struct module* module, const char* file, struct pool* pool, - struct hash_table* ht_symtab, const DWORD *crc) +static BOOL elf_load_debug_info_from_map(struct module* module, + struct elf_file_map* fmap, + struct pool* pool, + struct hash_table* ht_symtab) { BOOL ret = FALSE; - char* addr = (char*)0xffffffff; - int fd = -1; - struct stat statbuf; - const Elf32_Ehdr* ehptr; - const Elf32_Shdr* spnt; const char* shstrtab; int i; int symtab_sect, dynsym_sect, stab_sect, stabstr_sect, debug_sect, debuglink_sect; @@ -622,35 +781,15 @@ {"__wine_spec_thunk_data_16", -16, 0, 0}, /* 16 => 32 thunks */ {"__wine_spec_thunk_text_32", -32, 0, 0}, /* 32 => 16 thunks */ {"__wine_spec_thunk_data_32", -32, 0, 0}, /* 32 => 16 thunks */ + {NULL, 0, 0, 0} }; - if (module->type != DMT_ELF || !module->elf_info) - { - ERR("Bad elf module '%s'\n", module->module.LoadedImageName); - return FALSE; - } - - TRACE("%s\n", file); - /* check that the file exists, and that the module hasn't been loaded yet */ - if (stat(file, &statbuf) == -1) goto leave; - if (S_ISDIR(statbuf.st_mode)) goto leave; - - /* - * Now open the file, so that we can mmap() it. - */ - if ((fd = open(file, O_RDONLY)) == -1) goto leave; - - /* - * Now mmap() the file. - */ - addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == (char*)0xffffffff) goto leave; - - if (crc && (*crc != calc_crc32(addr, statbuf.st_size))) + if (fmap->with_crc && (fmap->crc != calc_crc32(fmap))) { - ERR("Bad CRC for file %s\n", file); + ERR("Bad CRC for module %s (got %08lx while expecting %08lx)\n", + module->module.ImageName, calc_crc32(fmap), fmap->crc); /* we don't tolerate mis-matched files */ - goto leave; + return FALSE; } /* @@ -658,29 +797,30 @@ * this thing. We need the main executable header, and the section * table. */ - ehptr = (Elf32_Ehdr*)addr; - spnt = (Elf32_Shdr*)(addr + ehptr->e_shoff); - shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset); + shstrtab = elf_map_section(fmap, fmap->elfhdr.e_shstrndx); + if (shstrtab == NO_MAP) return FALSE; symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = debuglink_sect = -1; - for (i = 0; i < ehptr->e_shnum; i++) + for (i = 0; i < fmap->elfhdr.e_shnum; i++) { - if (strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0) + if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".stab") == 0) stab_sect = i; - if (strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0) + if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".stabstr") == 0) stabstr_sect = i; - if (strcmp(shstrtab + spnt[i].sh_name, ".debug_info") == 0) + if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".debug_info") == 0) debug_sect = i; - if (strcmp(shstrtab + spnt[i].sh_name, ".gnu_debuglink") == 0) + if (strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".gnu_debuglink") == 0) debuglink_sect = i; - if ((strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0) && - (spnt[i].sh_type == SHT_SYMTAB)) + if ((strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".symtab") == 0) && + (fmap->sect[i].shdr.sh_type == SHT_SYMTAB)) symtab_sect = i; - if ((strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0) && - (spnt[i].sh_type == SHT_DYNSYM)) + if ((strcmp(shstrtab + fmap->sect[i].shdr.sh_name, ".dynsym") == 0) && + (fmap->sect[i].shdr.sh_type == SHT_DYNSYM)) dynsym_sect = i; } + elf_unmap_section(fmap, fmap->elfhdr.e_shstrndx); + shstrtab = NULL; if (symtab_sect == -1) { @@ -688,31 +828,38 @@ * section instead. It'll contain less (relevant) information, * but it'll be better than nothing */ - if (dynsym_sect == -1) goto leave; + if (dynsym_sect == -1) return FALSE; symtab_sect = dynsym_sect; } module->module.SymType = SymExport; /* create a hash table for the symtab */ - elf_hash_symtab(module, pool, ht_symtab, addr, - spnt + symtab_sect, spnt + spnt[symtab_sect].sh_link, - sizeof(thunks) / sizeof(thunks[0]), thunks); + elf_hash_symtab(module, pool, ht_symtab, fmap, symtab_sect, thunks); if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { if (stab_sect != -1 && stabstr_sect != -1) { - /* OK, now just parse all of the stabs. */ - ret = stabs_parse(module, module->elf_info->elf_addr, - addr + spnt[stab_sect].sh_offset, - spnt[stab_sect].sh_size, - addr + spnt[stabstr_sect].sh_offset, - spnt[stabstr_sect].sh_size); + const char* stab; + const char* stabstr; + + stab = elf_map_section(fmap, stab_sect); + stabstr = elf_map_section(fmap, stabstr_sect); + if (stab != NO_MAP && stabstr != NO_MAP) + { + /* OK, now just parse all of the stabs. */ + ret = stabs_parse(module, module->elf_info->elf_addr, + stab, fmap->sect[stab_sect].shdr.sh_size, + stabstr, fmap->sect[stabstr_sect].shdr.sh_size); + } + elf_unmap_section(fmap, stab_sect); + elf_unmap_section(fmap, stabstr_sect); + if (!ret) { - WARN("Couldn't read correctly read stabs\n"); - goto leave; + WARN("Couldn't correctly read stabs\n"); + return FALSE; } /* and fill in the missing information for stabs */ elf_finish_stabs_info(module, ht_symtab); @@ -724,14 +871,25 @@ } else if (debuglink_sect != -1) { - DWORD crc; - const char * file = (const char *)(addr + spnt[debuglink_sect].sh_offset); - /* crc is stored after the null terminated file string rounded - * up to the next 4 byte boundary */ - crc = *(const DWORD *)(file + ((DWORD_PTR)(strlen(file) + 4) & ~3)); - ret = elf_load_debug_info_from_file(module, file, pool, ht_symtab, &crc); - if (!ret) - WARN("Couldn't load linked debug file %s\n", file); + const char* dbg_link; + struct elf_file_map fmap_link; + + dbg_link = elf_map_section(fmap, debuglink_sect); + /* The content of a debug link section is: + * 1/ a NULL terminated string, containing the file name for the debug info + * 2/ padding on 4 byte boundary + * 3/ CRC of the linked ELF file + */ + if (dbg_link != NO_MAP && elf_map_file(dbg_link, &fmap_link)) + { + fmap_link.crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3)); + fmap_link.with_crc = 1; + ret = elf_load_debug_info_from_map(module, &fmap_link, pool, ht_symtab); + if (!ret) + WARN("Couldn't load debug information from %s\n", dbg_link); + } + else WARN("Couldn't load linked debug file for %s\n", module->module.ModuleName); + elf_unmap_file(&fmap_link); } } if (strstr(module->module.ModuleName, "") || @@ -745,10 +903,6 @@ /* add all the public symbols from symtab */ if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE; -leave: - if (addr != (char*)0xffffffff) munmap(addr, statbuf.st_size); - if (fd != -1) close(fd); - return ret; } @@ -757,20 +911,32 @@ * * Loads ELF debugging information from the module image file. */ -BOOL elf_load_debug_info(struct module* module) +BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) { - BOOL ret; - struct pool pool; - struct hash_table ht_symtab; + BOOL ret = TRUE; + struct pool pool; + struct hash_table ht_symtab; + struct elf_file_map my_fmap; + + if (module->type != DMT_ELF || !module->elf_info) + { + ERR("Bad elf module '%s'\n", module->module.LoadedImageName); + return FALSE; + } pool_init(&pool, 65536); hash_table_init(&pool, &ht_symtab, 256); - ret = elf_load_debug_info_from_file(module, - module->module.LoadedImageName, &pool, &ht_symtab, NULL); + if (!fmap) + { + fmap = &my_fmap; + ret = elf_map_file(module->module.LoadedImageName, fmap); + } + if (ret) + ret = elf_load_debug_info_from_map(module, fmap, &pool, &ht_symtab); pool_destroy(&pool); - + if (fmap == &my_fmap) elf_unmap_file(fmap); return ret; } @@ -811,63 +977,22 @@ static BOOL elf_load_file(struct process* pcs, const char* filename, unsigned long load_offset, struct elf_info* elf_info) { - static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; BOOL ret = FALSE; - const char* addr = (char*)0xffffffff; - int fd = -1; - struct stat statbuf; - const Elf32_Ehdr* ehptr; - const Elf32_Shdr* spnt; - const Elf32_Phdr* ppnt; - const char* shstrtab; + struct elf_file_map fmap; int i; - DWORD size, start; - unsigned tmp, page_mask = getpagesize() - 1; TRACE("Processing elf file '%s' at %08lx\n", filename, load_offset); - /* check that the file exists, and that the module hasn't been loaded yet */ - if (stat(filename, &statbuf) == -1) goto leave; - - /* Now open the file, so that we can mmap() it. */ - if ((fd = open(filename, O_RDONLY)) == -1) goto leave; - - /* Now mmap() the file. */ - addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (addr == (char*)-1) goto leave; + if (!elf_map_file(filename, &fmap)) goto leave; /* Next, we need to find a few of the internal ELF headers within * this thing. We need the main executable header, and the section * table. */ - ehptr = (const Elf32_Ehdr*)addr; - if (memcmp(ehptr->e_ident, elf_signature, sizeof(elf_signature))) goto leave; - - spnt = (const Elf32_Shdr*)(addr + ehptr->e_shoff); - shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset); - - /* grab size of module once loaded in memory */ - ppnt = (const Elf32_Phdr*)(addr + ehptr->e_phoff); - size = 0; start = ~0L; - - for (i = 0; i < ehptr->e_phnum; i++) - { - if (ppnt[i].p_type == PT_LOAD) - { - tmp = (ppnt[i].p_vaddr + ppnt[i].p_memsz + page_mask) & ~page_mask; - if (size < tmp) size = tmp; - if (ppnt[i].p_vaddr < start) start = ppnt[i].p_vaddr; - } - } - - /* if non relocatable ELF, then remove fixed address from computation - * otherwise, all addresses are zero based and start has no effect - */ - size -= start; - if (!start && !load_offset) + if (!fmap.elf_start && !load_offset) ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n", filename); - if (start && load_offset) + if (fmap.elf_start && load_offset) { WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. " "Assuming load address is corrupt\n", filename, load_offset); @@ -876,13 +1001,15 @@ if (elf_info->flags & ELF_INFO_DEBUG_HEADER) { - for (i = 0; i < ehptr->e_shnum; i++) + const char* shstrtab = elf_map_section(&fmap, fmap.elfhdr.e_shstrndx); + if (shstrtab == NO_MAP) goto leave; + for (i = 0; i < fmap.elfhdr.e_shnum; i++) { - if (strcmp(shstrtab + spnt[i].sh_name, ".dynamic") == 0 && - spnt[i].sh_type == SHT_DYNAMIC) + if (strcmp(shstrtab + fmap.sect[i].shdr.sh_name, ".dynamic") == 0 && + fmap.sect[i].shdr.sh_type == SHT_DYNAMIC) { Elf32_Dyn dyn; - char* ptr = (char*)spnt[i].sh_addr; + char* ptr = (char*)fmap.sect[i].shdr.sh_addr; unsigned long len; do @@ -896,6 +1023,7 @@ elf_info->dbg_hdr_addr = dyn.d_un.d_ptr; } } + elf_unmap_section(&fmap, fmap.elfhdr.e_shstrndx); } if (elf_info->flags & ELF_INFO_MODULE) @@ -904,8 +1032,8 @@ HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info)); if (!elf_module_info) goto leave; elf_info->module = module_new(pcs, filename, DMT_ELF, - (load_offset) ? load_offset : start, - size, 0, 0); + (load_offset) ? load_offset : fmap.elf_start, + fmap.elf_size, 0, 0); if (!elf_info->module) { HeapFree(GetProcessHeap(), 0, elf_module_info); @@ -919,15 +1047,14 @@ elf_info->module->module.SymType = SymDeferred; ret = TRUE; } - else ret = elf_load_debug_info(elf_info->module); + else ret = elf_load_debug_info(elf_info->module, &fmap); elf_info->module->elf_info->elf_mark = 1; elf_info->module->elf_info->elf_loader = 0; } else ret = TRUE; leave: - if (addr != (char*)0xffffffff) munmap((void*)addr, statbuf.st_size); - if (fd != -1) close(fd); + elf_unmap_file(&fmap); return ret; } @@ -1005,33 +1132,23 @@ } /****************************************************************** - * elf_synchronize_module_list + * elf_enum_modules_internal * - * this functions rescans the debuggee module's list and synchronizes it with - * the one from 'pcs', ie: - * - if a module is in debuggee and not in pcs, it's loaded into pcs - * - if a module is in pcs and not in debuggee, it's unloaded from pcs + * Enumerate ELF modules from a running process */ -BOOL elf_synchronize_module_list(struct process* pcs) +static BOOL elf_enum_modules_internal(const struct process* pcs, + elf_enum_modules_cb cb, void* user) { struct r_debug dbg_hdr; void* lm_addr; struct link_map lm; char bufstr[256]; - struct elf_info elf_info; - struct module* module; if (!pcs->dbg_hdr_addr || !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr), NULL)) return FALSE; - for (module = pcs->lmodules; module; module = module->next) - { - if (module->type == DMT_ELF) module->elf_info->elf_mark = 0; - } - - elf_info.flags = ELF_INFO_MODULE; /* Now walk the linked list. In all known ELF implementations, * the dynamic loader maintains this linked list for us. In some * cases the first entry doesn't appear with a name, in other cases it @@ -1047,13 +1164,52 @@ ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL)) { bufstr[sizeof(bufstr) - 1] = '\0'; - elf_search_and_load_file(pcs, bufstr, (unsigned long)lm.l_addr, - &elf_info); + if (!cb(bufstr, lm.l_addr, user)) break; } } + return TRUE; +} + +struct elf_sync +{ + struct process* pcs; + struct elf_info elf_info; +}; + +static BOOL elf_enum_sync_cb(const char* name, unsigned long addr, void* user) +{ + struct elf_sync* es = user; + + elf_search_and_load_file(es->pcs, name, addr, &es->elf_info); + return TRUE; +} + +/****************************************************************** + * elf_synchronize_module_list + * + * this functions rescans the debuggee module's list and synchronizes it with + * the one from 'pcs', ie: + * - if a module is in debuggee and not in pcs, it's loaded into pcs + * - if a module is in pcs and not in debuggee, it's unloaded from pcs + */ +BOOL elf_synchronize_module_list(struct process* pcs) +{ + struct module* module; + struct elf_sync es; for (module = pcs->lmodules; module; module = module->next) { + if (module->type == DMT_ELF) module->elf_info->elf_mark = 0; + } + + es.pcs = pcs; + es.elf_info.flags = ELF_INFO_MODULE; + if (!elf_enum_modules_internal(pcs, elf_enum_sync_cb, &es)) + return FALSE; + + module = pcs->lmodules; + while (module) + { if (module->type == DMT_ELF && !module->elf_info->elf_mark && !module->elf_info->elf_loader) { @@ -1061,97 +1217,143 @@ /* restart all over */ module = pcs->lmodules; } + else module = module->next; } return TRUE; } /****************************************************************** - * elf_read_wine_loader_dbg_info + * elf_search_loader * - * Try to find a decent wine executable which could have loaded the debuggee + * Lookup in a running ELF process the loader, and sets its ELF link + * address (for accessing the list of loaded .so libs) in pcs. + * If flags is ELF_INFO_MODULE, the module for the loader is also + * added as a module into pcs. */ -BOOL elf_read_wine_loader_dbg_info(struct process* pcs) +static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info) { - const char* ptr; - struct elf_info elf_info; BOOL ret; + const char* ptr; - elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE; /* All binaries are loaded with WINELOADER (if run from tree) or by the * main executable (either wine-kthread or wine-pthread) - * Note: the heuristic use to know whether we need to load wine-pthread or - * wine-kthread is not 100% safe + * FIXME: the heuristic used to know whether we need to load wine-pthread + * or wine-kthread is not 100% safe */ if ((ptr = getenv("WINELOADER"))) - ret = elf_search_and_load_file(pcs, ptr, 0, &elf_info); + ret = elf_search_and_load_file(pcs, ptr, 0, elf_info); else { - ret = elf_search_and_load_file(pcs, "wine-kthread", 0, &elf_info) || - elf_search_and_load_file(pcs, "wine-pthread", 0, &elf_info); + ret = elf_search_and_load_file(pcs, "wine-kthread", 0, elf_info) || + elf_search_and_load_file(pcs, "wine-pthread", 0, elf_info); } - if (!ret) return FALSE; + return ret; +} + +/****************************************************************** + * elf_read_wine_loader_dbg_info + * + * Try to find a decent wine executable which could have loaded the debuggee + */ +BOOL elf_read_wine_loader_dbg_info(struct process* pcs) +{ + struct elf_info elf_info; + + elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE; + if (!elf_search_loader(pcs, &elf_info)) return FALSE; elf_info.module->elf_info->elf_loader = 1; strcpy(elf_info.module->module.ModuleName, ""); return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0; } /****************************************************************** + * elf_enum_modules + * + * Enumerates the ELF loaded modules from a running target (hProc) + * This function doesn't require that someone has called SymInitialize + * on this very process. + */ +BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user) +{ + struct process pcs; + struct elf_info elf_info; + + memset(&pcs, 0, sizeof(pcs)); + pcs.handle = hProc; + elf_info.flags = ELF_INFO_DEBUG_HEADER; + if (!elf_search_loader(&pcs, &elf_info)) return FALSE; + pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr; + return elf_enum_modules_internal(&pcs, cb, user); +} + +struct elf_load +{ + struct process* pcs; + struct elf_info elf_info; + const char* name; + BOOL ret; +}; + +/****************************************************************** + * elf_load_cb + * + * Callback for elf_load_module, used to walk the list of loaded + * modules. + */ +static BOOL elf_load_cb(const char* name, unsigned long addr, void* user) +{ + struct elf_load* el = user; + const char* p; + + /* memcmp is needed for matches when bufstr contains also version information + * el->name: libc.so, name: libc.so.6.0 + */ + p = strrchr(name, '/'); + if (!p++) p = name; + if (!memcmp(p, el->name, strlen(el->name))) + { + elf_search_and_load_file(el->pcs, name, addr, &el->elf_info); + return FALSE; + } + return TRUE; +} + +/****************************************************************** * elf_load_module * * loads an ELF module and stores it in process' module list * Also, find module real name and load address from * the real loaded modules list in pcs address space */ -struct module* elf_load_module(struct process* pcs, const char* name) +struct module* elf_load_module(struct process* pcs, const char* name, DWORD addr) { - struct elf_info elf_info; - BOOL ret = FALSE; - const char* p; - const char* xname; - struct r_debug dbg_hdr; - void* lm_addr; - struct link_map lm; - char bufstr[256]; + struct elf_load el; TRACE("(%p %s)\n", pcs, name); - elf_info.flags = ELF_INFO_MODULE; + el.elf_info.flags = ELF_INFO_MODULE; + el.ret = FALSE; - /* do only the lookup from the filename, not the path (as we lookup module name - * in the process' loaded module list) - */ - xname = strrchr(name, '/'); - if (!xname++) xname = name; - - if (!ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, &dbg_hdr, sizeof(dbg_hdr), NULL)) - return NULL; - - for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next) + if (pcs->dbg_hdr_addr) /* we're debugging a life target */ { - if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL)) - return NULL; + el.pcs = pcs; + /* do only the lookup from the filename, not the path (as we lookup module name + * in the process' loaded module list) + */ + el.name = strrchr(name, '/'); + if (!el.name++) el.name = name; + el.ret = FALSE; - if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */ - lm.l_name != NULL && - ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL)) - { - bufstr[sizeof(bufstr) - 1] = '\0'; - /* memcmp is needed for matches when bufstr contains also version information - * name: libc.so, bufstr: libc.so.6.0 - */ - p = strrchr(bufstr, '/'); - if (!p++) p = bufstr; - if (!memcmp(p, xname, strlen(xname))) - { - ret = elf_search_and_load_file(pcs, bufstr, - (unsigned long)lm.l_addr, &elf_info); - break; - } - } + if (!elf_enum_modules_internal(pcs, elf_load_cb, &el)) + return NULL; + } + else if (addr) + { + el.ret = elf_search_and_load_file(pcs, name, addr, &el.elf_info); } - if (!lm_addr || !ret) return NULL; - assert(elf_info.module); - return elf_info.module; + if (!el.ret) return NULL; + assert(el.elf_info.module); + return el.elf_info.module; } #else /* !__ELF__ */ @@ -1166,7 +1368,7 @@ return FALSE; } -struct module* elf_load_module(struct process* pcs, const char* name) +struct module* elf_load_module(struct process* pcs, const char* name, DWORD addr) { return NULL; } diff -urN wine-20050211/dlls/dbghelp/minidump.c wine-20050310/dlls/dbghelp/minidump.c --- wine-20050211/dlls/dbghelp/minidump.c 2004-04-06 00:21:27.000000000 +0200 +++ wine-20050310/dlls/dbghelp/minidump.c 2005-03-07 12:03:21.000000000 +0100 @@ -24,74 +24,415 @@ #define NONAMELESSSTRUCT #include "dbghelp_private.h" +#include "ntstatus.h" +#include "winnls.h" +#include "winreg.h" +#include "winternl.h" +#include "psapi.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); -#if 0 -/* hard to see how we can generate this very easily (how to grab latest exception - * in a process ?) +struct dump_memory +{ + ULONG base; + ULONG size; + ULONG rva; +}; + +struct dump_module +{ + unsigned is_elf; + ULONG base; + ULONG size; + char name[MAX_PATH]; +}; + +struct dump_context +{ + /* process & thread information */ + HANDLE hProcess; + DWORD pid; + void* pcs_buffer; + SYSTEM_PROCESS_INFORMATION* spi; + /* module information */ + struct dump_module* module; + unsigned num_module; + /* exception information */ + /* output information */ + MINIDUMP_TYPE type; + HANDLE hFile; + RVA rva; + struct dump_memory* mem; + unsigned num_mem; + /* callback information */ + MINIDUMP_CALLBACK_INFORMATION* cb; +}; + +/****************************************************************** + * fetch_process_info + * + * reads system wide process information, and make spi point to the record + * for process of id 'pid' + */ +static BOOL fetch_process_info(struct dump_context* dc) +{ + ULONG buf_size = 0x1000; + NTSTATUS nts; + + dc->pcs_buffer = NULL; + if (!(dc->pcs_buffer = HeapAlloc(GetProcessHeap(), 0, buf_size))) return FALSE; + for (;;) + { + nts = NtQuerySystemInformation(SystemProcessInformation, + dc->pcs_buffer, buf_size, NULL); + if (nts != STATUS_INFO_LENGTH_MISMATCH) break; + dc->pcs_buffer = HeapReAlloc(GetProcessHeap(), 0, dc->pcs_buffer, + buf_size *= 2); + if (!dc->pcs_buffer) return FALSE; + } + + if (nts == STATUS_SUCCESS) + { + dc->spi = dc->pcs_buffer; + for (;;) + { + if (dc->spi->dwProcessID == dc->pid) return TRUE; + if (!dc->spi->dwOffset) break; + dc->spi = (SYSTEM_PROCESS_INFORMATION*) + ((char*)dc->spi + dc->spi->dwOffset); + } + } + HeapFree(GetProcessHeap(), 0, dc->pcs_buffer); + dc->pcs_buffer = NULL; + dc->spi = NULL; + return FALSE; +} + +/****************************************************************** + * fetch_thread_info + * + * fetches some information about thread of id 'tid' + */ +static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx, + MINIDUMP_THREAD* mdThd, CONTEXT* ctx) +{ + NT_TIB tib; + DWORD tid = dc->spi->ti[thd_idx].dwThreadID; + HANDLE hThread; + THREAD_BASIC_INFORMATION tbi; + + memset(ctx, 0, sizeof(*ctx)); + + mdThd->ThreadId = dc->spi->ti[thd_idx].dwThreadID; + mdThd->SuspendCount = 0; + mdThd->Teb = 0; + mdThd->Stack.StartOfMemoryRange = 0; + mdThd->Stack.Memory.DataSize = 0; + mdThd->Stack.Memory.Rva = 0; + mdThd->ThreadContext.DataSize = 0; + mdThd->ThreadContext.Rva = 0; + mdThd->PriorityClass = dc->spi->ti[thd_idx].dwBasePriority; /* FIXME */ + mdThd->Priority = dc->spi->ti[thd_idx].dwCurrentPriority; + + if ((hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid)) == NULL) + { + FIXME("Couldn't open thread %lu (%lu)\n", + dc->spi->ti[thd_idx].dwThreadID, GetLastError()); + return FALSE; + } + + if (NtQueryInformationThread(hThread, ThreadBasicInformation, + &tbi, sizeof(tbi), NULL) == STATUS_SUCCESS) + { + mdThd->Teb = (ULONG_PTR)tbi.TebBaseAddress; + if (tbi.ExitStatus == STILL_ACTIVE && tid != GetCurrentThreadId() && + (mdThd->SuspendCount = SuspendThread(hThread)) != (DWORD)-1) + { + mdThd->SuspendCount--; + ctx->ContextFlags = CONTEXT_FULL; + if (!GetThreadContext(hThread, ctx)) + memset(ctx, 0, sizeof(*ctx)); + + if (ReadProcessMemory(dc->hProcess, tbi.TebBaseAddress, + &tib, sizeof(tib), NULL)) + { +#ifdef __i386__ + /* limiting the stack dumping to the size actually used */ + if (ctx->Esp) + mdThd->Stack.StartOfMemoryRange = (ctx->Esp - 4); + else + mdThd->Stack.StartOfMemoryRange = (ULONG_PTR)tib.StackLimit; + mdThd->Stack.Memory.DataSize = (ULONG_PTR)tib.StackBase - + mdThd->Stack.StartOfMemoryRange; +#else +#error unsupported CPU +#endif + } + ResumeThread(hThread); + } + } + CloseHandle(hThread); + return TRUE; +} + +/****************************************************************** + * add_module + * + * Add a module to a dump context */ -static void DumpException(struct process* pcs, HANDLE hFile, RVA* rva) +static BOOL add_module(struct dump_context* dc, const char* name, + DWORD base, DWORD size, BOOL is_elf) +{ + if (!dc->module) + dc->module = HeapAlloc(GetProcessHeap(), 0, ++dc->num_module * sizeof(*dc->module)); + else + dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module, ++dc->num_module * sizeof(*dc->module)); + if (!dc->module) return FALSE; + if (is_elf || + !GetModuleFileNameExA(dc->hProcess, (HMODULE)base, + dc->module[dc->num_module - 1].name, + sizeof(dc->module[dc->num_module - 1].name))) + lstrcpynA(dc->module[dc->num_module - 1].name, name, + sizeof(dc->module[dc->num_module - 1].name)); + dc->module[dc->num_module - 1].base = base; + dc->module[dc->num_module - 1].size = size; + dc->module[dc->num_module - 1].is_elf = is_elf; + + return TRUE; +} + +/****************************************************************** + * fetch_pe_module_info_cb + * + * Callback for accumulating in dump_context a PE modules set + */ +static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size, + void* user) +{ + return add_module((struct dump_context*)user, name, base, size, FALSE); +} + +/****************************************************************** + * fetch_elf_module_info_cb + * + * Callback for accumulating in dump_context a ELF modules set + */ +static BOOL fetch_elf_module_info_cb(const char* name, unsigned long base, + void* user) +{ + return add_module((struct dump_context*)user, name, + base, 0 /* FIXME */, TRUE); +} + +static void fetch_module_info(struct dump_context* dc) +{ + WINE_FIXME("--> %p\n", dc->hProcess); + EnumerateLoadedModules(dc->hProcess, fetch_pe_module_info_cb, dc); + /* Since we include ELF modules in a separate stream from the regular PE ones, + * we can always include those ELF modules (they don't eat lots of space) + * And it's always a good idea to have a trace of the loaded ELF modules for + * a given application in a post mortem debugging condition. + */ + elf_enum_modules(dc->hProcess, fetch_elf_module_info_cb, dc); +} + +/****************************************************************** + * add_memory_block + * + * Add a memory block to be dumped in a minidump + * If rva is non 0, it's the rva in the minidump where has to be stored + * also the rva of the memory block when written (this allows to reference + * a memory block from outside the list of memory blocks). + */ +static void add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva) +{ + if (dc->mem) + dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem, + ++dc->num_mem * sizeof(*dc->mem)); + else + dc->mem = HeapAlloc(GetProcessHeap(), 0, ++dc->num_mem * sizeof(*dc->mem)); + if (dc->mem) + { + dc->mem[dc->num_mem - 1].base = base; + dc->mem[dc->num_mem - 1].size = size; + dc->mem[dc->num_mem - 1].rva = rva; + } + else dc->num_mem = 0; +} + +/****************************************************************** + * writeat + * + * Writes a chunk of data at a given position in the minidump + */ +static void writeat(struct dump_context* dc, RVA rva, void* data, unsigned size) +{ + DWORD written; + + SetFilePointer(dc->hFile, rva, NULL, FILE_BEGIN); + WriteFile(dc->hFile, data, size, &written, NULL); +} + +/****************************************************************** + * append + * + * writes a new chunk of data to the minidump, increasing the current + * rva in dc + */ +static void append(struct dump_context* dc, void* data, unsigned size) +{ + writeat(dc, dc->rva, data, size); + dc->rva += size; +} + +/****************************************************************** + * dump_exception_info + * + * Write in File the exception information from pcs + */ +static void dump_exception_info(struct dump_context* dc, + const MINIDUMP_EXCEPTION_INFORMATION* except) { MINIDUMP_EXCEPTION_STREAM mdExcpt; + EXCEPTION_RECORD rec, *prec; + CONTEXT ctx, *pctx; + int i; - mdExcpt.ThreadId = DEBUG_CurrThread->tid; + mdExcpt.ThreadId = except->ThreadId; mdExcpt.__alignment = 0; - mdExcpt.ExceptionRecord. + if (except->ClientPointers) + { + EXCEPTION_POINTERS ep; + + ReadProcessMemory(dc->hProcess, + except->ExceptionPointers, &ep, sizeof(ep), NULL); + ReadProcessMemory(dc->hProcess, + ep.ExceptionRecord, &rec, sizeof(rec), NULL); + ReadProcessMemory(dc->hProcess, + ep.ContextRecord, &ctx, sizeof(ctx), NULL); + prec = &rec; + pctx = &ctx; + + } + else + { + prec = except->ExceptionPointers->ExceptionRecord; + pctx = except->ExceptionPointers->ContextRecord; + } + mdExcpt.ExceptionRecord.ExceptionCode = prec->ExceptionCode; + mdExcpt.ExceptionRecord.ExceptionFlags = prec->ExceptionFlags; + mdExcpt.ExceptionRecord.ExceptionRecord = (DWORD_PTR)prec->ExceptionRecord; + mdExcpt.ExceptionRecord.ExceptionAddress = (DWORD_PTR)prec->ExceptionAddress; + mdExcpt.ExceptionRecord.NumberParameters = prec->NumberParameters; + mdExcpt.ExceptionRecord.__unusedAlignment = 0; + for (i = 0; i < mdExcpt.ExceptionRecord.NumberParameters; i++) + mdExcpt.ExceptionRecord.ExceptionInformation[i] = (DWORD_PTR)prec->ExceptionInformation[i]; + mdExcpt.ThreadContext.DataSize = sizeof(*pctx); + mdExcpt.ThreadContext.Rva = dc->rva + sizeof(mdExcpt); - ULONG ExceptionCode; - ULONG ExceptionFlags; - ULONGLONG ExceptionRecord; - ULONGLONG ExceptionAddress; - ULONG NumberParameters; - ULONG __unusedAlignment; - ULONGLONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; + append(dc, &mdExcpt, sizeof(mdExcpt)); + append(dc, pctx, sizeof(*pctx)); } -#endif /****************************************************************** * dump_modules * * Write in File the modules from pcs */ -static void dump_modules(struct process* pcs, HANDLE hFile, RVA* rva) +static void dump_modules(struct dump_context* dc, BOOL dump_elf) { MINIDUMP_MODULE mdModule; MINIDUMP_MODULE_LIST mdModuleList; - DWORD written; - struct module* module = NULL; + char tmp[1024]; + MINIDUMP_STRING* ms = (MINIDUMP_STRING*)tmp; + ULONG i, nmod; + RVA rva_base; + DWORD flags_out; + + for (i = nmod = 0; i < dc->num_module; i++) + { + if ((dc->module[i].is_elf && dump_elf) || (!dc->module[i].is_elf && !dump_elf)) + nmod++; + } mdModuleList.NumberOfModules = 0; - for (module = pcs->lmodules; module; module = module->next) - mdModuleList.NumberOfModules++; - WriteFile(hFile, &mdModuleList.NumberOfModules, - sizeof(mdModuleList.NumberOfModules), &written, NULL); - *rva += sizeof(mdModuleList.NumberOfModules) + - sizeof(mdModule) * mdModuleList.NumberOfModules; - for (module = pcs->lmodules; module; module = module->next) - { - mdModule.BaseOfImage = (DWORD)module->module.BaseOfImage; - mdModule.SizeOfImage = module->module.ImageSize; - mdModule.CheckSum = module->module.CheckSum; - mdModule.TimeDateStamp = module->module.TimeDateStamp; - mdModule.ModuleNameRva = *rva; - *rva += strlen(module->module.ModuleName) + 1; - memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */ - mdModule.CvRecord.DataSize = 0; /* FIXME */ - mdModule.CvRecord.Rva = 0; /* FIXME */ - mdModule.MiscRecord.DataSize = 0; /* FIXME */ - mdModule.MiscRecord.Rva = 0; /* FIXME */ - mdModule.Reserved0 = 0; - mdModule.Reserved1 = 0; - WriteFile(hFile, &mdModule, sizeof(mdModule), &written, NULL); - } - for (module = pcs->lmodules; module; module = module->next) - { - WriteFile(hFile, module->module.ModuleName, - strlen(module->module.ModuleName) + 1, &written, NULL); - FIXME("CV and misc records not written\n"); + /* reserve space for mdModuleList + * FIXME: since we don't support 0 length arrays, we cannot use the + * size of mdModuleList + * FIXME: if we don't ask for all modules in cb, we'll get a hole in the file + */ + rva_base = dc->rva; + dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod; + for (i = 0; i < dc->num_module; i++) + { + if ((dc->module[i].is_elf && !dump_elf) || (!dc->module[i].is_elf && dump_elf)) + continue; + + flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord; + if (dc->type & MiniDumpWithDataSegs) + flags_out |= ModuleWriteDataSeg; + if (dc->type & MiniDumpWithProcessThreadData) + flags_out |= ModuleWriteTlsData; + if (dc->type & MiniDumpWithCodeSegs) + flags_out |= ModuleWriteCodeSegs; + ms->Length = MultiByteToWideChar(CP_ACP, 0, + dc->module[i].name, -1, + NULL, 0) * sizeof(WCHAR); + if (sizeof(ULONG) + ms->Length > sizeof(tmp)) + FIXME("Buffer overflow!!!\n"); + MultiByteToWideChar(CP_ACP, 0, dc->module[i].name, -1, + ms->Buffer, ms->Length); + + if (dc->cb) + { + MINIDUMP_CALLBACK_INPUT cbin; + MINIDUMP_CALLBACK_OUTPUT cbout; + + cbin.ProcessId = dc->pid; + cbin.ProcessHandle = dc->hProcess; + cbin.CallbackType = ModuleCallback; + + cbin.u.Module.FullPath = ms->Buffer; + cbin.u.Module.BaseOfImage = dc->module[i].base; + cbin.u.Module.SizeOfImage = dc->module[i].size; + cbin.u.Module.CheckSum = 0; /* FIXME */ + cbin.u.Module.TimeDateStamp = 0; /* FIXME */ + memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo)); + cbin.u.Module.CvRecord = NULL; + cbin.u.Module.SizeOfCvRecord = 0; + cbin.u.Module.MiscRecord = NULL; + cbin.u.Module.SizeOfMiscRecord = 0; + + cbout.u.ModuleWriteFlags = flags_out; + if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout)) + continue; + flags_out &= cbout.u.ModuleWriteFlags; + } + if (flags_out & ModuleWriteModule) + { + mdModule.BaseOfImage = dc->module[i].base; + mdModule.SizeOfImage = dc->module[i].size; + mdModule.CheckSum = 0; /* FIXME */ + mdModule.TimeDateStamp = 0; /* FIXME */ + mdModule.ModuleNameRva = dc->rva; + ms->Length -= sizeof(WCHAR); + append(dc, ms, sizeof(ULONG) + ms->Length); + memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */ + mdModule.CvRecord.DataSize = 0; /* FIXME */ + mdModule.CvRecord.Rva = 0; /* FIXME */ + mdModule.MiscRecord.DataSize = 0; /* FIXME */ + mdModule.MiscRecord.Rva = 0; /* FIXME */ + mdModule.Reserved0 = 0; /* FIXME */ + mdModule.Reserved1 = 0; /* FIXME */ + writeat(dc, + rva_base + sizeof(mdModuleList.NumberOfModules) + + mdModuleList.NumberOfModules++ * sizeof(mdModule), + &mdModule, sizeof(mdModule)); + } } + writeat(dc, rva_base, &mdModuleList.NumberOfModules, + sizeof(mdModuleList.NumberOfModules)); } /****************************************************************** @@ -99,34 +440,39 @@ * * Dumps into File the information about the system */ -static void dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva) +static void dump_system_info(struct dump_context* dc) { MINIDUMP_SYSTEM_INFO mdSysInfo; SYSTEM_INFO sysInfo; - OSVERSIONINFOA osInfo; + OSVERSIONINFOW osInfo; DWORD written; + ULONG slen; GetSystemInfo(&sysInfo); - GetVersionExA(&osInfo); + osInfo.dwOSVersionInfoSize = sizeof(osInfo); + GetVersionExW(&osInfo); mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture; mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel; mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision; - mdSysInfo.Reserved0 = 0; - + mdSysInfo.u.s.NumberOfProcessors = sysInfo.dwNumberOfProcessors; + mdSysInfo.u.s.ProductType = VER_NT_WORKSTATION; /* FIXME */ mdSysInfo.MajorVersion = osInfo.dwMajorVersion; mdSysInfo.MinorVersion = osInfo.dwMinorVersion; mdSysInfo.BuildNumber = osInfo.dwBuildNumber; mdSysInfo.PlatformId = osInfo.dwPlatformId; - mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo); - mdSysInfo.Reserved1 = 0; + mdSysInfo.CSDVersionRva = dc->rva + sizeof(mdSysInfo); + mdSysInfo.u1.Reserved1 = 0; + + memset(&mdSysInfo.Cpu, 0, sizeof(mdSysInfo.Cpu)); - WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL); - *rva += sizeof(mdSysInfo); - WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1, - &written, NULL); - *rva += strlen(osInfo.szCSDVersion) + 1; + append(dc, &mdSysInfo, sizeof(mdSysInfo)); + + slen = lstrlenW(osInfo.szCSDVersion) * sizeof(WCHAR); + WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL); + WriteFile(dc->hFile, osInfo.szCSDVersion, slen, &written, NULL); + dc->rva += sizeof(ULONG) + slen; } /****************************************************************** @@ -134,36 +480,140 @@ * * Dumps into File the information about running threads */ -static void dump_threads(struct process* pcs, HANDLE hFile, RVA* rva) +static void dump_threads(struct dump_context* dc) { -#if 0 MINIDUMP_THREAD mdThd; MINIDUMP_THREAD_LIST mdThdList; - DWORD written; - DBG_THREAD* thd; + unsigned i; + RVA rva_base; + DWORD flags_out; + CONTEXT ctx; + + mdThdList.NumberOfThreads = 0; + + rva_base = dc->rva; + dc->rva += sizeof(mdThdList.NumberOfThreads) + + dc->spi->dwThreadCount * sizeof(mdThd); - mdThdList.NumberOfThreads = pcs->num_threads; - WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads), - &written, NULL); - *rva += sizeof(mdThdList.NumberOfThreads) + - mdThdList.NumberOfThreads * sizeof(mdThd); - for (thd = pcs->threads; thd; thd = thd->next) - { - mdThd.ThreadId = thd->tid; - mdThd.SuspendCount = 0; /* FIXME */ - mdThd.PriorityClass = 0; /* FIXME */ - mdThd.Priority = 0; /* FIXME */ - mdThd.Teb = 0; /* FIXME */ - mdThd.Stack.StartOfMemoryRange = 0; /* FIXME */ - mdThd.Stack.Memory.DataSize = 0; /* FIXME */ - mdThd.Stack.Memory.Rva = 0; /* FIXME */ - mdThd.ThreadContext.DataSize = 0;/* FIXME */ - mdThd.ThreadContext.Rva = 0; /* FIXME */ + for (i = 0; i < dc->spi->dwThreadCount; i++) + { + fetch_thread_info(dc, i, &mdThd, &ctx); - WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL); - FIXME("Stack & thread context not written\n"); + flags_out = ThreadWriteThread | ThreadWriteStack | ThreadWriteContext | + ThreadWriteInstructionWindow; + if (dc->type & MiniDumpWithProcessThreadData) + flags_out |= ThreadWriteThreadData; + if (dc->type & MiniDumpWithThreadInfo) + flags_out |= ThreadWriteThreadInfo; + + if (dc->cb) + { + MINIDUMP_CALLBACK_INPUT cbin; + MINIDUMP_CALLBACK_OUTPUT cbout; + + cbin.ProcessId = dc->pid; + cbin.ProcessHandle = dc->hProcess; + cbin.CallbackType = ThreadCallback; + cbin.u.Thread.ThreadId = dc->spi->ti[i].dwThreadID; + cbin.u.Thread.ThreadHandle = 0; /* FIXME */ + memcpy(&cbin.u.Thread.Context, &ctx, sizeof(CONTEXT)); + cbin.u.Thread.SizeOfContext = sizeof(CONTEXT); + cbin.u.Thread.StackBase = mdThd.Stack.StartOfMemoryRange; + cbin.u.Thread.StackEnd = mdThd.Stack.StartOfMemoryRange + + mdThd.Stack.Memory.DataSize; + + cbout.u.ThreadWriteFlags = flags_out; + if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout)) + continue; + flags_out &= cbout.u.ThreadWriteFlags; + } + if (flags_out & ThreadWriteThread) + { + if (ctx.ContextFlags && (flags_out & ThreadWriteContext)) + { + mdThd.ThreadContext.Rva = dc->rva; + mdThd.ThreadContext.DataSize = sizeof(CONTEXT); + append(dc, &ctx, sizeof(CONTEXT)); + } + if (mdThd.Stack.Memory.DataSize && (flags_out & ThreadWriteStack)) + { + add_memory_block(dc, mdThd.Stack.StartOfMemoryRange, + mdThd.Stack.Memory.DataSize, + rva_base + sizeof(mdThdList.NumberOfThreads) + + mdThdList.NumberOfThreads * sizeof(mdThd) + + FIELD_OFFSET(MINIDUMP_THREAD, Stack.Memory.Rva)); + } + writeat(dc, + rva_base + sizeof(mdThdList.NumberOfThreads) + + mdThdList.NumberOfThreads * sizeof(mdThd), + &mdThd, sizeof(mdThd)); + mdThdList.NumberOfThreads++; + } + if (ctx.ContextFlags && (flags_out & ThreadWriteInstructionWindow)) + { + /* FIXME: - Native dbghelp also dumps 0x80 bytes around EIP + * - also crop values across module boundaries, + * - and don't make it i386 dependent + */ + /* add_memory_block(dc, ctx.Eip - 0x80, ctx.Eip + 0x80, 0); */ + } } -#endif + writeat(dc, rva_base, + &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads)); +} + +/****************************************************************** + * dump_memory_info + * + * dumps information about the memory of the process (stack of the threads) + */ +static void dump_memory_info(struct dump_context* dc) +{ + MINIDUMP_MEMORY_LIST mdMemList; + MINIDUMP_MEMORY_DESCRIPTOR mdMem; + DWORD written; + unsigned i, pos, len; + RVA rva_base; + char tmp[1024]; + + mdMemList.NumberOfMemoryRanges = dc->num_mem; + append(dc, &mdMemList.NumberOfMemoryRanges, + sizeof(mdMemList.NumberOfMemoryRanges)); + rva_base = dc->rva; + dc->rva += mdMemList.NumberOfMemoryRanges * sizeof(mdMem); + + for (i = 0; i < dc->num_mem; i++) + { + mdMem.StartOfMemoryRange = dc->mem[i].base; + mdMem.Memory.Rva = dc->rva; + mdMem.Memory.DataSize = dc->mem[i].size; + SetFilePointer(dc->hFile, dc->rva, NULL, FILE_BEGIN); + for (pos = 0; pos < dc->mem[i].size; pos += sizeof(tmp)) + { + len = min(dc->mem[i].size - pos, sizeof(tmp)); + if (ReadProcessMemory(dc->hProcess, + (void*)(ULONG)(dc->mem[i].base + pos), + tmp, len, NULL)) + WriteFile(dc->hFile, tmp, len, &written, NULL); + } + dc->rva += mdMem.Memory.DataSize; + writeat(dc, rva_base + i * sizeof(mdMem), &mdMem, sizeof(mdMem)); + if (dc->mem[i].rva) + { + writeat(dc, dc->mem[i].rva, &mdMem.Memory.Rva, sizeof(mdMem.Memory.Rva)); + } + } +} + +static void dump_misc_info(struct dump_context* dc) +{ + MINIDUMP_MISC_INFO mmi; + + mmi.SizeOfInfo = sizeof(mmi); + mmi.Flags1 = MINIDUMP_MISC1_PROCESS_ID; + mmi.ProcessId = dc->pid; + /* FIXME: create/user/kernel time */ + append(dc, &mmi, sizeof(mmi)); } /****************************************************************** @@ -171,28 +621,34 @@ * * */ -BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, +BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam) { - struct process* pcs; MINIDUMP_HEADER mdHead; MINIDUMP_DIRECTORY mdDir; - DWORD currRva, written; - DWORD i, nStream, addStream; - RVA rva; + DWORD i, nStreams, idx_stream; + struct dump_context dc; - pcs = process_find_by_handle(hProcess); - if (!pcs) return FALSE; /* FIXME: should try to load it ??? */ + dc.hProcess = hProcess; + dc.hFile = hFile; + dc.pid = pid; + dc.module = NULL; + dc.num_module = 0; + dc.cb = CallbackParam; + dc.type = DumpType; + dc.mem = NULL; + dc.num_mem = 0; + dc.rva = 0; - /* 1) init */ + if (!fetch_process_info(&dc)) return FALSE; + fetch_module_info(&dc); - nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0; - addStream = 0; - if (DumpType & MiniDumpNormal) - addStream += 3; /* sure ? thread stack back trace */ + /* 1) init */ + nStreams = 6 + (ExceptionParam ? 1 : 0) + + (UserStreamParam ? UserStreamParam->UserStreamCount : 0); if (DumpType & MiniDumpWithDataSegs) FIXME("NIY MiniDumpWithDataSegs\n"); @@ -206,61 +662,123 @@ FIXME("NIY MiniDumpScanMemory\n"); /* 2) write header */ - rva = sizeof(mdHead); mdHead.Signature = MINIDUMP_SIGNATURE; mdHead.Version = MINIDUMP_VERSION; - mdHead.NumberOfStreams = nStream + addStream; - mdHead.StreamDirectoryRva = rva; + mdHead.NumberOfStreams = nStreams; + mdHead.StreamDirectoryRva = sizeof(mdHead); mdHead.u.TimeDateStamp = time(NULL); mdHead.Flags = DumpType; - WriteFile(hFile, &mdHead, sizeof(mdHead), &written, NULL); - + append(&dc, &mdHead, sizeof(mdHead)); + /* 3) write stream directories */ - rva += (nStream + addStream) * sizeof(mdDir); + dc.rva += nStreams * sizeof(mdDir); + idx_stream = 0; + /* 3.1) write data stream directories */ - currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - SetFilePointer(hFile, rva, NULL, FILE_BEGIN); - mdDir.StreamType = ModuleListStream; - mdDir.Location.Rva = rva; - dump_modules(pcs, hFile, &rva); - mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva; - SetFilePointer(hFile, currRva, NULL, FILE_BEGIN); - WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL); - currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - SetFilePointer(hFile, rva, NULL, FILE_BEGIN); mdDir.StreamType = ThreadListStream; - mdDir.Location.Rva = rva; - dump_threads(pcs, hFile, &rva); - mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva; - SetFilePointer(hFile, currRva, NULL, FILE_BEGIN); - WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL); + mdDir.Location.Rva = dc.rva; + dump_threads(&dc); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + + mdDir.StreamType = ModuleListStream; + mdDir.Location.Rva = dc.rva; + dump_modules(&dc, FALSE); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + + mdDir.StreamType = 0xfff0; /* FIXME: this is part of MS reserved streams */ + mdDir.Location.Rva = dc.rva; + dump_modules(&dc, TRUE); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + + mdDir.StreamType = MemoryListStream; + mdDir.Location.Rva = dc.rva; + dump_memory_info(&dc); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); - currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - SetFilePointer(hFile, rva, NULL, FILE_BEGIN); mdDir.StreamType = SystemInfoStream; - mdDir.Location.Rva = rva; - dump_system_info(pcs, hFile, &rva); - mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva; - SetFilePointer(hFile, currRva, NULL, FILE_BEGIN); - WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL); - - /* 3.2) write user define stream */ - for (i = 0; i < nStream; i++) - { - mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type; - mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize; - mdDir.Location.Rva = rva; - WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL); - currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - SetFilePointer(hFile, rva, NULL, FILE_BEGIN); - WriteFile(hFile, - UserStreamParam->UserStreamArray[i].Buffer, - UserStreamParam->UserStreamArray[i].BufferSize, - &written, NULL); - rva += UserStreamParam->UserStreamArray[i].BufferSize; - SetFilePointer(hFile, currRva, NULL, FILE_BEGIN); + mdDir.Location.Rva = dc.rva; + dump_system_info(&dc); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + + mdDir.StreamType = MiscInfoStream; + mdDir.Location.Rva = dc.rva; + dump_misc_info(&dc); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + + /* 3.2) write exception information (if any) */ + if (ExceptionParam) + { + mdDir.StreamType = ExceptionStream; + mdDir.Location.Rva = dc.rva; + dump_exception_info(&dc, ExceptionParam); + mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + } + + /* 3.3) write user defined streams (if any) */ + if (UserStreamParam) + { + for (i = 0; i < UserStreamParam->UserStreamCount; i++) + { + mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type; + mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize; + mdDir.Location.Rva = dc.rva; + writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + append(&dc, UserStreamParam->UserStreamArray[i].Buffer, + UserStreamParam->UserStreamArray[i].BufferSize); + } } + HeapFree(GetProcessHeap(), 0, dc.pcs_buffer); + HeapFree(GetProcessHeap(), 0, dc.mem); + HeapFree(GetProcessHeap(), 0, dc.module); + return TRUE; } + +/****************************************************************** + * MiniDumpReadDumpStream (DEBUGHLP.@) + * + * + */ +BOOL WINAPI MiniDumpReadDumpStream(void* base, ULONG str_idx, + PMINIDUMP_DIRECTORY* pdir, + void** stream, ULONG* size) +{ + MINIDUMP_HEADER* mdHead = (MINIDUMP_HEADER*)base; + + if (mdHead->Signature == MINIDUMP_SIGNATURE) + { + MINIDUMP_DIRECTORY* dir; + int i; + + dir = (MINIDUMP_DIRECTORY*)((char*)base + mdHead->StreamDirectoryRva); + for (i = 0; i < mdHead->NumberOfStreams; i++, dir++) + { + if (dir->StreamType == str_idx) + { + *pdir = dir; + *stream = (char*)base + dir->Location.Rva; + *size = dir->Location.DataSize; + return TRUE; + } + } + } + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; +} diff -urN wine-20050211/dlls/dbghelp/module.c wine-20050310/dlls/dbghelp/module.c --- wine-20050211/dlls/dbghelp/module.c 2004-11-08 21:26:22.000000000 +0100 +++ wine-20050310/dlls/dbghelp/module.c 2005-03-01 11:39:49.000000000 +0100 @@ -48,6 +48,10 @@ if (len > 4 && (!strcasecmp(&out[len - 4], ".dll") || !strcasecmp(&out[len - 4], ".exe"))) out[len - 4] = '\0'; + else if (((len > 12 && out[len - 13] == '/') || len == 12) && + (!strcasecmp(out + len - 12, "wine-pthread") || + !strcasecmp(out + len - 12, "wine-kthread"))) + strcpy(out, ""); else { if (len > 7 && @@ -134,14 +138,17 @@ } else { + char modname[MAX_PATH]; + for (module = pcs->lmodules; module; module = module->next) { if (type == module->type && !strcasecmp(name, module->module.LoadedImageName)) return module; } + module_fill_module(name, modname, sizeof(modname)); for (module = pcs->lmodules; module; module = module->next) { - if (type == module->type && !strcasecmp(name, module->module.ModuleName)) + if (type == module->type && !strcasecmp(modname, module->module.ModuleName)) return module; } } @@ -214,9 +221,9 @@ switch (module->type) { - case DMT_ELF: ret = elf_load_debug_info(module); break; - case DMT_PE: ret = pe_load_debug_info(pcs, module); break; - default: ret = FALSE; break; + case DMT_ELF: ret = elf_load_debug_info(module, NULL); break; + case DMT_PE: ret = pe_load_debug_info(pcs, module); break; + default: ret = FALSE; break; } if (!ret) module->module.SymType = SymNone; assert(module->module.SymType != SymDeferred); @@ -277,6 +284,33 @@ return FALSE; } +static BOOL elf_is_shared_by_name(const char* name) +{ + const char* ptr; + int len = strlen(name); + + /* check for terminating .so or .so.[digit]+ */ + while (len) + { + for (ptr = name + len - 1; ptr >= name; ptr--) if (*ptr == '.') break; + if (ptr < name) break; + if (ptr == name + len - 2 && isdigit(ptr[1])) + { + len -= 2; + continue; + } + if (ptr == name + len - 3 && ptr[1] == 's' && ptr[2] == 'o') + return TRUE; + break; + } + /* wine-[kp]thread is valid too */ + if (((len > 12 && name[len - 13] == '/') || len == 12) && + (!strcasecmp(name + len - 12, "wine-pthread") || + !strcasecmp(name + len - 12, "wine-kthread"))) + return TRUE; + return FALSE; +} + /*********************************************************************** * SymLoadModule (DBGHELP.@) */ @@ -310,11 +344,11 @@ TRACE("Assuming %s as native DLL\n", ImageName); if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll))) { - unsigned len = strlen(ImageName); - - if (!strcmp(ImageName + len - 3, ".so") && - (module = elf_load_module(pcs, ImageName))) goto done; - FIXME("should have successfully loaded some debug information for image %s\n", ImageName); + if (elf_is_shared_by_name(ImageName) && + (module = elf_load_module(pcs, ImageName, BaseOfDll))) + goto done; + FIXME("Should have successfully loaded debug information for image %s\n", + ImageName); if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll))) goto done; WARN("Couldn't locate %s\n", ImageName); @@ -418,7 +452,7 @@ DWORD i, sz; MODULEINFO mi; - hMods = HeapAlloc(GetProcessHeap(), 0, sz); + hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0])); if (!hMods) return FALSE; if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz)) diff -urN wine-20050211/dlls/dbghelp/pe_module.c wine-20050310/dlls/dbghelp/pe_module.c --- wine-20050211/dlls/dbghelp/pe_module.c 2004-12-06 12:41:32.000000000 +0100 +++ wine-20050310/dlls/dbghelp/pe_module.c 2005-03-01 11:39:49.000000000 +0100 @@ -404,21 +404,25 @@ } } if (ptr && (module = module_find_by_name(pcs, ptr, DMT_PE))) return module; - if (base && pcs->dbg_hdr_addr) + if (base) { - IMAGE_DOS_HEADER dos; - IMAGE_NT_HEADERS nth; - - if (ReadProcessMemory(pcs->handle, (char*)base, &dos, sizeof(dos), NULL) && - dos.e_magic == IMAGE_DOS_SIGNATURE && - ReadProcessMemory(pcs->handle, (char*)(base + dos.e_lfanew), - &nth, sizeof(nth), NULL) && - nth.Signature == IMAGE_NT_SIGNATURE) + if (pcs->dbg_hdr_addr) { - if (!size) size = nth.OptionalHeader.SizeOfImage; - module = module_new(pcs, name, DMT_PE, base, size, - nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum); - } + IMAGE_DOS_HEADER dos; + IMAGE_NT_HEADERS nth; + + if (ReadProcessMemory(pcs->handle, (char*)base, &dos, sizeof(dos), NULL) && + dos.e_magic == IMAGE_DOS_SIGNATURE && + ReadProcessMemory(pcs->handle, (char*)(base + dos.e_lfanew), + &nth, sizeof(nth), NULL) && + nth.Signature == IMAGE_NT_SIGNATURE) + { + if (!size) size = nth.OptionalHeader.SizeOfImage; + module = module_new(pcs, name, DMT_PE, base, size, + nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum); + } + } else if (size) + module = module_new(pcs, name, DMT_PE, base, size, 0 /* FIXME */, 0 /* FIXME */); } return module; } diff -urN wine-20050211/dlls/dbghelp/stabs.c wine-20050310/dlls/dbghelp/stabs.c --- wine-20050211/dlls/dbghelp/stabs.c 2005-01-31 12:29:09.000000000 +0100 +++ wine-20050310/dlls/dbghelp/stabs.c 2005-03-01 11:39:49.000000000 +0100 @@ -100,6 +100,7 @@ static void stab_strcpy(char* dest, int sz, const char* source) { + char* ptr = dest; /* * A strcpy routine that stops when we hit the ':' character. * Faster than copying the whole thing, and then nuking the @@ -108,28 +109,27 @@ */ while (*source != '\0') { - if (source[0] != ':' && sz-- > 0) *dest++ = *source++; + if (source[0] != ':' && sz-- > 0) *ptr++ = *source++; else if (source[1] == ':' && (sz -= 2) > 0) { - *dest++ = *source++; - *dest++ = *source++; + *ptr++ = *source++; + *ptr++ = *source++; } else break; } - *dest-- = '\0'; - /* GCC seems to emit, in some cases, a .+ suffix. + *ptr-- = '\0'; + /* GCC emits, in some cases, a .+ suffix. * This is used for static variable inside functions, so * that we can have several such variables with same name in * the same compilation unit * We simply ignore that suffix when present (we also get rid * of it in ELF symtab parsing) */ - if (isdigit(*dest)) + if (ptr >= dest && isdigit(*ptr)) { - while (isdigit(*dest)) dest--; - if (*dest == '.') *dest = '\0'; + while (ptr > dest && isdigit(*ptr)) ptr--; + if (*ptr == '.') *ptr = '\0'; } - assert(sz > 0); } @@ -1098,7 +1098,7 @@ * function (assuming that current function ends where next function starts) */ static void stabs_finalize_function(struct module* module, struct symt_function* func, - unsigned long end) + unsigned long size) { IMAGEHLP_LINE il; @@ -1113,7 +1113,7 @@ symt_add_function_point(module, func, SymTagFuncDebugStart, il.Address - func->address, NULL); } - if (end) func->size = end - func->address; + if (size) func->size = size; } BOOL stabs_parse(struct module* module, unsigned long load_offset, @@ -1389,10 +1389,6 @@ } break; case N_FUN: - /* First, clean up the previous function we were working on. */ - stabs_finalize_function(module, curr_func, - stab_ptr->n_value ? load_offset + stab_ptr->n_value : 0); - /* * For now, just declare the various functions. Later * on, we will add the line number information and the @@ -1409,6 +1405,17 @@ if (*symname) { struct symt_function_signature* func_type; + + if (curr_func) + { + /* First, clean up the previous function we were working on. + * Assume size of the func is the delta between current offset + * and offset of last function + */ + stabs_finalize_function(module, curr_func, + stab_ptr->n_value ? + (load_offset + stab_ptr->n_value - curr_func->address) : 0); + } func_type = symt_new_function_signature(module, stabs_parse_type(ptr)); curr_func = symt_new_function(module, compiland, symname, @@ -1417,7 +1424,10 @@ } else { - /* some GCC seem to use a N_FUN "" to mark the end of a function */ + /* some versions of GCC to use a N_FUN "" to mark the end of a function + * and n_value contains the size of the func + */ + stabs_finalize_function(module, curr_func, stab_ptr->n_value); curr_func = NULL; } break; @@ -1430,8 +1440,7 @@ { /* Nuke old path. */ srcpath[0] = '\0'; - stabs_finalize_function(module, curr_func, - stab_ptr->n_value ? load_offset + stab_ptr->n_value : 0); + stabs_finalize_function(module, curr_func, 0); curr_func = NULL; source_idx = -1; incl_stk = -1; @@ -1467,9 +1476,12 @@ strs += strtabinc; strtabinc = stab_ptr->n_value; /* I'm not sure this is needed, so trace it before we obsolete it */ - if (curr_func) FIXME("UNDF: curr_func %s\n", curr_func->hash_elt.name); - stabs_finalize_function(module, curr_func, 0); /* FIXME */ - curr_func = NULL; + if (curr_func) + { + FIXME("UNDF: curr_func %s\n", curr_func->hash_elt.name); + stabs_finalize_function(module, curr_func, 0); /* FIXME */ + curr_func = NULL; + } break; case N_OPT: /* Ignore this. We don't care what it points to. */ diff -urN wine-20050211/dlls/ddraw/d3d_private.h wine-20050310/dlls/ddraw/d3d_private.h --- wine-20050211/dlls/ddraw/d3d_private.h 2004-08-06 19:30:44.000000000 +0200 +++ wine-20050310/dlls/ddraw/d3d_private.h 2005-02-14 12:09:47.000000000 +0100 @@ -197,6 +197,9 @@ ICOM_VFIELD_MULTI(IDirect3DDevice); DWORD ref; + /* Version of the Direct3D object from which the device has been created */ + DWORD version; + /* IDirect3DDevice fields */ IDirectDrawImpl *d3d; IDirectDrawSurfaceImpl *surface; diff -urN wine-20050211/dlls/ddraw/d3ddevice/main.c wine-20050310/dlls/ddraw/d3ddevice/main.c --- wine-20050211/dlls/ddraw/d3ddevice/main.c 2005-01-09 18:35:44.000000000 +0100 +++ wine-20050310/dlls/ddraw/d3ddevice/main.c 2005-02-14 12:09:47.000000000 +0100 @@ -207,6 +207,9 @@ *obp = NULL; + /* Note: We cannot get an interface whose version is higher than the + * Direct3D object that created the device */ + if ( IsEqualGUID( &IID_IUnknown, riid ) ) { IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7)); *obp = iface; @@ -219,19 +222,19 @@ TRACE(" Creating IDirect3DDevice interface %p\n", *obp); return S_OK; } - if ( IsEqualGUID( &IID_IDirect3DDevice2, riid ) ) { + if ( IsEqualGUID( &IID_IDirect3DDevice2, riid ) && (This->version >= 2)) { IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7)); *obp = ICOM_INTERFACE(This, IDirect3DDevice2); TRACE(" Creating IDirect3DDevice2 interface %p\n", *obp); return S_OK; } - if ( IsEqualGUID( &IID_IDirect3DDevice3, riid ) ) { + if ( IsEqualGUID( &IID_IDirect3DDevice3, riid ) && (This->version >= 3)) { IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7)); *obp = ICOM_INTERFACE(This, IDirect3DDevice3); TRACE(" Creating IDirect3DDevice3 interface %p\n", *obp); return S_OK; } - if ( IsEqualGUID( &IID_IDirect3DDevice7, riid ) ) { + if ( IsEqualGUID( &IID_IDirect3DDevice7, riid ) && (This->version >= 7)) { IDirect3DDevice7_AddRef(ICOM_INTERFACE(This, IDirect3DDevice7)); *obp = ICOM_INTERFACE(This, IDirect3DDevice7); TRACE(" Creating IDirect3DDevice7 interface %p\n", *obp); diff -urN wine-20050211/dlls/ddraw/d3ddevice/mesa.c wine-20050310/dlls/ddraw/d3ddevice/mesa.c --- wine-20050211/dlls/ddraw/d3ddevice/mesa.c 2005-01-10 14:29:25.000000000 +0100 +++ wine-20050310/dlls/ddraw/d3ddevice/mesa.c 2005-02-14 12:09:46.000000000 +0100 @@ -474,7 +474,7 @@ static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1, LPD3DENUMPIXELFORMATSCALLBACK cb_2, - LPVOID context) + LPVOID context, int version) { DDSURFACEDESC sdesc; LPDDPIXELFORMAT pformat; @@ -617,7 +617,8 @@ if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK; if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK; - if (GL_extensions.s3tc_compressed_texture) { + /* DXT textures only exist for devices created from IDirect3D3 and above */ + if ((version >= 3) && GL_extensions.s3tc_compressed_texture) { TRACE("Enumerating DXT1\n"); pformat->dwFlags = DDPF_FOURCC; pformat->dwFourCC = MAKE_FOURCC('D','X','T','1'); @@ -682,7 +683,7 @@ { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface); TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg); - return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg); + return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg, This->version); } HRESULT WINAPI @@ -692,7 +693,7 @@ { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg); - return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg); + return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg, This->version); } HRESULT WINAPI @@ -2312,7 +2313,7 @@ /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */ if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) || - (glThis->version == 1)) && + (glThis->parent.version == 1)) && (enable_colorkey)) { TRACE(" colorkey activated.\n"); @@ -3877,7 +3878,7 @@ } HRESULT -d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface) +d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, int version) { IDirect3DDeviceImpl *object; IDirect3DDeviceGLImpl *gl_object; @@ -3903,6 +3904,7 @@ object->set_matrices = d3ddevice_set_matrices; object->matrices_updated = d3ddevice_matrices_updated; object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer; + object->version = version; TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d); @@ -3910,13 +3912,6 @@ TRACE(" device critical section : %p\n", &(object->crit)); - /* This is just a hack for some badly done games :-/ */ - if (from_surface) { - gl_object->version = 1; - TRACE(" using D3D1 special hacks.\n"); - } else - gl_object->version = 7; - device_context = GetDC(surface->ddraw_owner->window); gl_object->display = get_display(device_context); gl_object->drawable = get_drawable(device_context); @@ -4067,8 +4062,7 @@ /* And finally warn D3D that this device is now present */ object->d3d->d3d_added_device(object->d3d, object); - /* FIXME: Should handle other versions than just 7 */ - InitDefaultStateBlock(&object->state_block, 7); + InitDefaultStateBlock(&object->state_block, object->version); /* Apply default render state and texture stage state values */ apply_render_state(object, &object->state_block); apply_texture_state(object); diff -urN wine-20050211/dlls/ddraw/ddraw/user.c wine-20050310/dlls/ddraw/ddraw/user.c --- wine-20050211/dlls/ddraw/ddraw/user.c 2004-09-08 03:50:37.000000000 +0200 +++ wine-20050310/dlls/ddraw/ddraw/user.c 2005-03-07 12:01:10.000000000 +0100 @@ -143,7 +143,7 @@ #define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \ | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP \ | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY \ - | DDCAPS_COLORKEYHWASSIST) + | DDCAPS_COLORKEYHWASSIST | DDCAPS_OVERLAY | DDCAPS_OVERLAYSTRETCH) #define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT) #define FX_CAPS (DDFXCAPS_BLTALPHA | DDFXCAPS_BLTMIRRORLEFTRIGHT \ | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTROTATION90 \ @@ -362,7 +362,7 @@ #define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \ | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP \ | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY \ - | DDCAPS_COLORKEYHWASSIST) + | DDCAPS_COLORKEYHWASSIST | DDCAPS_OVERLAY | DDCAPS_OVERLAYSTRETCH) #define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT) diff -urN wine-20050211/dlls/ddraw/ddraw_private.h wine-20050310/dlls/ddraw/ddraw_private.h --- wine-20050211/dlls/ddraw/ddraw_private.h 2004-12-27 18:12:55.000000000 +0100 +++ wine-20050310/dlls/ddraw/ddraw_private.h 2005-03-07 13:23:34.000000000 +0100 @@ -277,6 +277,7 @@ RECT lastlockrect; DWORD lastlocktype; BOOL dc_in_use; + BOOL locked; HRESULT (*duplicate_surface)(IDirectDrawSurfaceImpl* src, LPDIRECTDRAWSURFACE7* dst); diff -urN wine-20050211/dlls/ddraw/direct3d/mesa.c wine-20050310/dlls/ddraw/direct3d/mesa.c --- wine-20050211/dlls/ddraw/direct3d/mesa.c 2004-12-20 18:08:41.000000000 +0100 +++ wine-20050310/dlls/ddraw/direct3d/mesa.c 2005-02-14 12:09:46.000000000 +0100 @@ -62,7 +62,22 @@ } HRESULT WINAPI -GL_IDirect3DImpl_3_2T_EnumDevices(LPDIRECT3D3 iface, +GL_IDirect3DImpl_2_EnumDevices(LPDIRECT3D2 iface, + LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback, + LPVOID lpUserArg) +{ + ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface); + TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpEnumDevicesCallback, lpUserArg); + + /* Call functions defined in d3ddevices.c */ + if (d3ddevice_enumerate(lpEnumDevicesCallback, lpUserArg, 2) != D3DENUMRET_OK) + return D3D_OK; + + return D3D_OK; +} + +HRESULT WINAPI +GL_IDirect3DImpl_3_EnumDevices(LPDIRECT3D3 iface, LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback, LPVOID lpUserArg) { @@ -146,7 +161,7 @@ IDirect3DDeviceImpl *lpd3ddev; HRESULT ret_value; - ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS, FALSE); + ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS, version); if (FAILED(ret_value)) return ret_value; if ((iid == NULL) || @@ -331,7 +346,7 @@ XCAST(QueryInterface) Thunk_IDirect3DImpl_3_QueryInterface, XCAST(AddRef) Thunk_IDirect3DImpl_3_AddRef, XCAST(Release) Thunk_IDirect3DImpl_3_Release, - XCAST(EnumDevices) GL_IDirect3DImpl_3_2T_EnumDevices, + XCAST(EnumDevices) GL_IDirect3DImpl_3_EnumDevices, XCAST(CreateLight) GL_IDirect3DImpl_3_2T_1T_CreateLight, XCAST(CreateMaterial) GL_IDirect3DImpl_3_2T_1T_CreateMaterial, XCAST(CreateViewport) GL_IDirect3DImpl_3_2T_1T_CreateViewport, @@ -358,7 +373,7 @@ XCAST(QueryInterface) Thunk_IDirect3DImpl_2_QueryInterface, XCAST(AddRef) Thunk_IDirect3DImpl_2_AddRef, XCAST(Release) Thunk_IDirect3DImpl_2_Release, - XCAST(EnumDevices) Thunk_IDirect3DImpl_2_EnumDevices, + XCAST(EnumDevices) GL_IDirect3DImpl_2_EnumDevices, XCAST(CreateLight) Thunk_IDirect3DImpl_2_CreateLight, XCAST(CreateMaterial) Thunk_IDirect3DImpl_2_CreateMaterial, XCAST(CreateViewport) Thunk_IDirect3DImpl_2_CreateViewport, diff -urN wine-20050211/dlls/ddraw/dsurface/dib.c wine-20050310/dlls/ddraw/dsurface/dib.c --- wine-20050211/dlls/ddraw/dsurface/dib.c 2005-01-03 15:41:08.000000000 +0100 +++ wine-20050310/dlls/ddraw/dsurface/dib.c 2005-03-10 12:13:11.000000000 +0100 @@ -514,6 +514,11 @@ } } + if ((This->locked) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked))) { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return DDERR_SURFACEBUSY; + } + /* First, check if the possible override function handles this case */ if (This->aux_blt != NULL) { if (This->aux_blt(This, rdst, src, rsrc, dwFlags, lpbltfx) == DD_OK) return DD_OK; @@ -985,6 +990,11 @@ TRACE(" srcrect: NULL\n"); } + if ((This->locked) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked))) { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return DDERR_SURFACEBUSY; + } + /* First, check if the possible override function handles this case */ if (This->aux_bltfast != NULL) { if (This->aux_bltfast(This, dstx, dsty, src, rsrc, trans) == DD_OK) return DD_OK; diff -urN wine-20050211/dlls/ddraw/dsurface/main.c wine-20050310/dlls/ddraw/dsurface/main.c --- wine-20050211/dlls/ddraw/dsurface/main.c 2005-01-09 18:35:44.000000000 +0100 +++ wine-20050310/dlls/ddraw/dsurface/main.c 2005-03-07 13:23:34.000000000 +0100 @@ -195,7 +195,7 @@ IDirect3DDeviceImpl *d3ddevimpl; HRESULT ret_value; - ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE); + ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, 1); if (FAILED(ret_value)) return ret_value; *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice); @@ -1094,6 +1094,12 @@ } } + /* If the surface is already locked, return busy */ + if (This->locked) { + WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); + return DDERR_SURFACEBUSY; + } + /* First, copy the Surface description */ DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc)); @@ -1142,6 +1148,8 @@ This->lock_update(This, NULL, flags); } + This->locked = TRUE; + TRACE("locked surface returning description : \n"); if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD); @@ -1417,6 +1425,12 @@ TRACE("(%p)->Unlock(%p)\n",This,pRect); + if (!This->locked) { + WARN("Surface not locked - returing DDERR_NOTLOCKED\n"); + return DDERR_NOTLOCKED; + } + + This->locked = FALSE; This->unlock_update(This, pRect); if (This->aux_unlock) This->aux_unlock(This->aux_ctx, This->aux_data, pRect); diff -urN wine-20050211/dlls/ddraw/mesa.c wine-20050310/dlls/ddraw/mesa.c --- wine-20050211/dlls/ddraw/mesa.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050310/dlls/ddraw/mesa.c 2005-02-14 12:09:47.000000000 +0100 @@ -361,7 +361,7 @@ glThis->blending = dwRenderState; /* Hack for some old games ... */ - if (glThis->version == 1) { + if (glThis->parent.version == 1) { lpStateBlock->render_state[D3DRENDERSTATE_COLORKEYENABLE - 1] = dwRenderState; } break; diff -urN wine-20050211/dlls/ddraw/mesa_private.h wine-20050310/dlls/ddraw/mesa_private.h --- wine-20050211/dlls/ddraw/mesa_private.h 2004-07-30 20:54:32.000000000 +0200 +++ wine-20050310/dlls/ddraw/mesa_private.h 2005-02-14 12:09:47.000000000 +0100 @@ -117,9 +117,6 @@ /* The last type of vertex drawn */ GL_TRANSFORM_STATE transform_state; - /* Maybe a hack, but it works */ - DWORD version; - /* Used to handle fogging faster... */ BYTE fog_table[3 * 0x10000]; /* 3 is for R, G and B 0x10000 is 0xFF for the vertex color and @@ -192,7 +189,7 @@ extern HRESULT d3dmaterial_create(IDirect3DMaterialImpl **obj, IDirectDrawImpl *d3d); extern HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d); extern HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags); -extern HRESULT d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface); +extern HRESULT d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, int version); /* Used for Direct3D to request the device to enumerate itself */ extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version) ; diff -urN wine-20050211/dlls/dinput/joystick_linuxinput.c wine-20050310/dlls/dinput/joystick_linuxinput.c --- wine-20050211/dlls/dinput/joystick_linuxinput.c 2004-12-23 19:33:44.000000000 +0100 +++ wine-20050310/dlls/dinput/joystick_linuxinput.c 2005-02-15 16:03:03.000000000 +0100 @@ -978,7 +978,7 @@ { JoystickImpl *This = (JoystickImpl *)iface; - TRACE("(this=%p,%s,%p): stub!\n", + TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph); if (TRACE_ON(dinput)) diff -urN wine-20050211/dlls/dinput/keyboard.c wine-20050310/dlls/dinput/keyboard.c --- wine-20050211/dlls/dinput/keyboard.c 2004-12-23 19:33:44.000000000 +0100 +++ wine-20050310/dlls/dinput/keyboard.c 2005-03-08 18:00:38.000000000 +0100 @@ -356,6 +356,37 @@ return DI_OK; } +static HRESULT WINAPI SysKeyboardAImpl_GetProperty( + LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPDIPROPHEADER ph +) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); + TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n", + ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow); + if (!HIWORD(rguid)) { + switch ((DWORD)rguid) { + case (DWORD) DIPROP_BUFFERSIZE: { + LPDIPROPDWORD pd = (LPDIPROPDWORD)ph; + + TRACE("(buffersize=%ld)\n",pd->dwData); + + if (This->acquired) + return DIERR_INVALIDPARAM; + + pd->dwData = This->buffersize; + + break; + } + default: + WARN("Unknown type %ld\n",(DWORD)rguid); + break; + } + } + return DI_OK; +} + static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr ) @@ -366,7 +397,7 @@ if (len != 256) return DIERR_INVALIDPARAM; - MsgWaitForMultipleObjectsEx(0, NULL, 0, 0, 0); + MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); if (TRACE_ON(dinput)) { int i; @@ -401,7 +432,7 @@ if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) return DIERR_INVALIDPARAM; - MsgWaitForMultipleObjectsEx(0, NULL, 0, 0, 0); + MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); EnterCriticalSection(&(This->crit)); @@ -712,7 +743,7 @@ SysKeyboardAImpl_Release, SysKeyboardAImpl_GetCapabilities, SysKeyboardAImpl_EnumObjects, - IDirectInputDevice2AImpl_GetProperty, + SysKeyboardAImpl_GetProperty, SysKeyboardAImpl_SetProperty, SysKeyboardAImpl_Acquire, SysKeyboardAImpl_Unacquire, @@ -754,7 +785,7 @@ XCAST(Release)SysKeyboardAImpl_Release, XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities, SysKeyboardWImpl_EnumObjects, - XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty, + XCAST(GetProperty)SysKeyboardAImpl_GetProperty, XCAST(SetProperty)SysKeyboardAImpl_SetProperty, XCAST(Acquire)SysKeyboardAImpl_Acquire, XCAST(Unacquire)SysKeyboardAImpl_Unacquire, diff -urN wine-20050211/dlls/dinput/mouse.c wine-20050310/dlls/dinput/mouse.c --- wine-20050211/dlls/dinput/mouse.c 2005-01-25 21:05:12.000000000 +0100 +++ wine-20050310/dlls/dinput/mouse.c 2005-02-15 16:03:03.000000000 +0100 @@ -845,7 +845,7 @@ { SysMouseImpl *This = (SysMouseImpl *)iface; - TRACE("(this=%p,%s,%p): stub!\n", + TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph); if (TRACE_ON(dinput)) diff -urN wine-20050211/dlls/dplayx/dplobby.c wine-20050310/dlls/dplayx/dplobby.c --- wine-20050211/dlls/dplayx/dplobby.c 2005-01-26 22:09:05.000000000 +0100 +++ wine-20050310/dlls/dplayx/dplobby.c 2005-03-09 12:48:05.000000000 +0100 @@ -1156,22 +1156,16 @@ LPHANDLE lphRead ) { /* These are the handles for the created process */ - HANDLE hAppStart, hAppDeath, hAppRead, hTemp; + HANDLE hAppStart = 0, hAppDeath = 0, hAppRead = 0; SECURITY_ATTRIBUTES s_attrib; s_attrib.nLength = sizeof( s_attrib ); s_attrib.lpSecurityDescriptor = NULL; s_attrib.bInheritHandle = TRUE; - /* FIXME: Is there a handle leak here? */ - hTemp = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); - *lphStart = ConvertToGlobalHandle( hTemp ); - - hTemp = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); - *lphDeath = ConvertToGlobalHandle( hTemp ); - - hTemp = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); - *lphRead = ConvertToGlobalHandle( hTemp ); + *lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); + *lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); + *lphRead = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart, hDestProcess, &hAppStart, @@ -1184,6 +1178,9 @@ 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ) { + if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; } + if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; } + if (*lphRead) { CloseHandle(*lphRead); *lphRead = 0; } /* FIXME: Handle leak... */ ERR( "Unable to dup handles\n" ); return FALSE; @@ -1192,6 +1189,7 @@ if( !DPLAYX_SetLobbyHandles( dwDestProcessId, hAppStart, hAppDeath, hAppRead ) ) { + /* FIXME: Handle leak... */ return FALSE; } diff -urN wine-20050211/dlls/dsound/buffer.c wine-20050310/dlls/dsound/buffer.c --- wine-20050211/dlls/dsound/buffer.c 2005-02-11 12:49:05.000000000 +0100 +++ wine-20050310/dlls/dsound/buffer.c 2005-02-16 17:09:03.000000000 +0100 @@ -1060,9 +1060,14 @@ CopyMemory(dsb->pwfx, wfex, cp_size); - dsb->buflen = dsbd->dwBufferBytes; - dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec; + if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign) + dsb->buflen = dsbd->dwBufferBytes + + (dsbd->lpwfxFormat->nBlockAlign - + (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)); + else + dsb->buflen = dsbd->dwBufferBytes; + dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec; dsb->notify = NULL; dsb->notifies = NULL; dsb->nrofnotifies = 0; diff -urN wine-20050211/dlls/dsound/dsound.c wine-20050310/dlls/dsound/dsound.c --- wine-20050211/dlls/dsound/dsound.c 2005-02-11 12:49:05.000000000 +0100 +++ wine-20050310/dlls/dsound/dsound.c 2005-02-25 17:50:57.000000000 +0100 @@ -614,8 +614,8 @@ TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level)); if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) { - FIXME("level=%s not fully supported\n", - level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); + WARN("level=%s not fully supported\n", + level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); } This->priolevel = level; return DS_OK; diff -urN wine-20050211/dlls/dsound/mixer.c wine-20050310/dlls/dsound/mixer.c --- wine-20050211/dlls/dsound/mixer.c 2005-02-10 18:10:54.000000000 +0100 +++ wine-20050310/dlls/dsound/mixer.c 2005-02-25 20:16:57.000000000 +0100 @@ -91,12 +91,10 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) { - DWORD sw; TRACE("(%p)\n",dsb); - sw = dsb->pwfx->nChannels * (dsb->pwfx->wBitsPerSample / 8); /* calculate the 10ms write lead */ - dsb->writelead = (dsb->freq / 100) * sw; + dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign; } void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) @@ -374,7 +372,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen) { - INT i, len, ilen, field, nBlockAlign, todo; + INT i, len, ilen, field, todo; BYTE *buf, *ibuf; TRACE("(%p,%ld,%ld)\n",dsb,writepos,fraglen); @@ -387,8 +385,12 @@ dsb->nAvgBytesPerSec); len = min(len, temp); } - nBlockAlign = dsb->dsound->pwfx->nBlockAlign; - len = len / nBlockAlign * nBlockAlign; /* data alignment */ + + if (len % dsb->dsound->pwfx->nBlockAlign) { + INT nBlockAlign = dsb->dsound->pwfx->nBlockAlign; + len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ + ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign); + } if (len == 0) { /* This should only happen if we aren't looping and temp < nBlockAlign */ @@ -495,14 +497,17 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len) { - INT ilen, field, nBlockAlign; + INT ilen, field; UINT i, todo; BYTE *buf, *ibuf; TRACE("(%p,%ld,%ld)\n",dsb,writepos,len); - nBlockAlign = dsb->dsound->pwfx->nBlockAlign; - len = len / nBlockAlign * nBlockAlign; /* data alignment */ + if (len % dsb->dsound->pwfx->nBlockAlign) { + INT nBlockAlign = dsb->dsound->pwfx->nBlockAlign; + len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ + ERR("length not a multiple of block size, len = %ld, block size = %d\n", len, nBlockAlign); + } if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL) return; diff -urN wine-20050211/dlls/dsound/primary.c wine-20050310/dlls/dsound/primary.c --- wine-20050211/dlls/dsound/primary.c 2005-02-11 12:49:05.000000000 +0100 +++ wine-20050310/dlls/dsound/primary.c 2005-02-16 17:26:13.000000000 +0100 @@ -38,22 +38,22 @@ void DSOUND_RecalcPrimary(IDirectSoundImpl *This) { - DWORD sw; + DWORD nBlockAlign; TRACE("(%p)\n",This); - sw = This->pwfx->nChannels * (This->pwfx->wBitsPerSample / 8); + nBlockAlign = This->pwfx->nBlockAlign; if (This->hwbuf) { DWORD fraglen; /* let fragment size approximate the timer delay */ - fraglen = (This->pwfx->nSamplesPerSec * DS_TIME_DEL / 1000) * sw; + fraglen = (This->pwfx->nSamplesPerSec * DS_TIME_DEL / 1000) * nBlockAlign; /* reduce fragment size until an integer number of them fits in the buffer */ /* (FIXME: this may or may not be a good idea) */ - while (This->buflen % fraglen) fraglen -= sw; + while (This->buflen % fraglen) fraglen -= nBlockAlign; This->fraglen = fraglen; TRACE("fraglen=%ld\n", This->fraglen); } /* calculate the 10ms write lead */ - This->writelead = (This->pwfx->nSamplesPerSec / 100) * sw; + This->writelead = (This->pwfx->nSamplesPerSec / 100) * nBlockAlign; } static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This) @@ -72,7 +72,7 @@ else if (This->state == STATE_STOPPING) This->state = STATE_STOPPED; /* use fragments of 10ms (1/100s) each (which should get us within * the documented write cursor lead of 10-15ms) */ - buflen = ((This->pwfx->nAvgBytesPerSec / 100) & ~3) * DS_HEL_FRAGS; + buflen = ((This->pwfx->nSamplesPerSec / 100) * This->pwfx->nBlockAlign) * DS_HEL_FRAGS; TRACE("desired buflen=%ld, old buffer=%p\n", buflen, This->buffer); /* reallocate emulated primary buffer */ diff -urN wine-20050211/dlls/dsound/tests/Makefile.in wine-20050310/dlls/dsound/tests/Makefile.in --- wine-20050211/dlls/dsound/tests/Makefile.in 2004-07-30 20:42:51.000000000 +0200 +++ wine-20050310/dlls/dsound/tests/Makefile.in 2005-03-05 11:49:08.000000000 +0100 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = dsound.dll -IMPORTS = dsound ole32 user32 kernel32 +IMPORTS = dsound ole32 version user32 kernel32 EXTRALIBS = -ldxguid -luuid -ldxerr8 CTESTS = \ diff -urN wine-20050211/dlls/dsound/tests/capture.c wine-20050310/dlls/dsound/tests/capture.c --- wine-20050211/dlls/dsound/tests/capture.c 2005-01-10 13:25:57.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/capture.c 2005-03-05 11:49:08.000000000 +0100 @@ -314,11 +314,15 @@ } rc=pDirectSoundCaptureCreate(lpGuid,&dsco,NULL); - ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate() failed: " - "%s\n",DXGetErrorString8(rc)); + ok((rc==DS_OK)||(rc==DSERR_NODRIVER)||(rc==E_FAIL)||(rc==DSERR_ALLOCATED), + "DirectSoundCaptureCreate() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) { if (rc==DSERR_NODRIVER) trace(" No Driver\n"); + else if (rc==E_FAIL) + trace(" No Device\n"); + else if (rc==DSERR_ALLOCATED) + trace(" Already In Use\n"); goto EXIT; } @@ -430,9 +434,10 @@ if (winetest_interactive) trace(" Testing the capture buffer at %s\n", format_string(&wfx)); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); - ok(((rc==DS_OK)&&(dscbo!=NULL))||(rc==DSERR_BADFORMAT)||(rc==DSERR_ALLOCATED), + ok(((rc==DS_OK)&&(dscbo!=NULL))||(rc==DSERR_BADFORMAT)|| + (rc==DSERR_ALLOCATED)||(rc==E_INVALIDARG), "IDirectSoundCapture_CreateCaptureBuffer() failed to create a " - "capture buffer: %s\n",DXGetErrorString8(rc)); + "%s capture buffer: %s\n",format_string(&wfx),DXGetErrorString8(rc)); if (rc==DS_OK) { test_capture_buffer(dsco, dscbo, winetest_interactive); ref=IDirectSoundCaptureBuffer_Release(dscbo); @@ -444,8 +449,29 @@ "capture buffer: format listed as supported but using it failed\n"); if (!(dsccaps.dwFormats & formats[f][3])) trace(" Format not supported: %s\n", format_string(&wfx)); - } else if (rc==DSERR_ALLOCATED) + } else if (rc==DSERR_ALLOCATED) { trace(" Already In Use\n"); + } else if (rc==E_INVALIDARG) { /* try the old version struct */ + DSCBUFFERDESC1 bufdesc1; + ZeroMemory(&bufdesc1, sizeof(bufdesc1)); + bufdesc1.dwSize=sizeof(bufdesc1); + bufdesc1.dwFlags=0; + bufdesc1.dwBufferBytes=wfx.nAvgBytesPerSec; + bufdesc1.dwReserved=0; + bufdesc1.lpwfxFormat=&wfx; + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco, + (DSCBUFFERDESC*)&bufdesc1,&dscbo,NULL); + ok(rc==DS_OK, + "IDirectSoundCapture_CreateCaptureBuffer() failed to create a " + "%s capture buffer: %s\n",format_string(&wfx), + DXGetErrorString8(rc)); + if (rc==DS_OK) { + test_capture_buffer(dsco, dscbo, winetest_interactive); + ref=IDirectSoundCaptureBuffer_Release(dscbo); + ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d " + "references, should have 0\n",ref); + } + } } /* try a non PCM format */ @@ -515,6 +541,9 @@ trace("dsound.dll not found\n"); return; } + + trace("DLL Version: %s\n", get_file_version("dsound.dll")); + pDirectSoundCaptureCreate=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate"); pDirectSoundCaptureEnumerateA=(void*)GetProcAddress(hDsound,"DirectSoundCaptureEnumerateA"); if (!pDirectSoundCaptureCreate || !pDirectSoundCaptureEnumerateA) diff -urN wine-20050211/dlls/dsound/tests/ds3d.c wine-20050310/dlls/dsound/tests/ds3d.c --- wine-20050211/dlls/dsound/tests/ds3d.c 2005-02-10 21:26:20.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/ds3d.c 2005-03-05 11:49:08.000000000 +0100 @@ -280,7 +280,8 @@ BOOL is_primary, BOOL set_volume, LONG volume, BOOL set_pan, LONG pan, BOOL play, double duration, BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener, - BOOL move_listener, BOOL move_sound) + BOOL move_listener, BOOL move_sound, + BOOL set_frequency, DWORD frequency) { HRESULT rc; DSBCAPS dsbcaps; @@ -288,6 +289,15 @@ DWORD size,status,freq; int ref; + if (set_frequency) { + rc=IDirectSoundBuffer_SetFrequency(dsbo,frequency); + ok(rc==DS_OK||rc==DSERR_CONTROLUNAVAIL, + "IDirectSoundBuffer_SetFrequency() failed to set frequency " + "%s\n",DXGetErrorString8(rc)); + if (rc!=DS_OK) + return; + } + /* DSOUND: Error: Invalid caps pointer */ rc=IDirectSoundBuffer_GetCaps(dsbo,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have " @@ -336,8 +346,9 @@ (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)), "IDirectSoundBuffer_GetFrequency() failed: %s\n",DXGetErrorString8(rc)); if (rc==DS_OK) { - ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency " - "%ld does not match the format %ld\n",freq,wfx.nSamplesPerSec); + DWORD f = set_frequency?frequency:wfx.nSamplesPerSec; + ok(freq==f,"The frequency returned by GetFrequency " + "%ld does not match the format %ld\n",freq,f); } /* DSOUND: Error: Invalid status pointer */ @@ -404,8 +415,14 @@ DWORD start_time,now; if (winetest_interactive) { - trace(" Playing %g second 440Hz tone at %ldx%dx%d\n", duration, - wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels); + if (set_frequency) + trace(" Playing %g second 440Hz tone at %ldx%dx%d with a " + "frequency of %ld (%ldHz)\n", duration, + wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels, + frequency, (440 * frequency) / wfx.nSamplesPerSec); + else + trace(" Playing %g second 440Hz tone at %ldx%dx%d\n", duration, + wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels); } if (is_primary) { @@ -522,7 +539,10 @@ } } - state.wave=wave_generate_la(&wfx,duration,&state.wave_len); + if (set_frequency) + state.wave=wave_generate_la(&wfx,(duration*frequency)/wfx.nSamplesPerSec,&state.wave_len); + else + state.wave=wave_generate_la(&wfx,duration,&state.wave_len); state.dsbo=dsbo; state.wfx=&wfx; @@ -713,7 +733,8 @@ else bufdesc.dwFlags|= (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN); - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; if (winetest_interactive) { trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d " @@ -839,7 +860,7 @@ duration=(move_listener || move_sound?4.0:1.0); test_buffer(dso,secondary,0,FALSE,0,FALSE,0, winetest_interactive,duration,has_3dbuffer, - listener,move_listener,move_sound); + listener,move_listener,move_sound,FALSE,0); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, " "should have 0\n",has_duplicate?"duplicated":"secondary", @@ -881,7 +902,7 @@ /* Create the DirectSound object */ rc=DirectSoundCreate(lpGuid,&dso,NULL); - ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) return rc; @@ -936,7 +957,8 @@ "to create a primary buffer: %s\n",DXGetErrorString8(rc)); if (rc==DS_OK && primary!=NULL) { test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && - !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0); + !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0, + FALSE,0); if (winetest_interactive) { LONG volume,pan; @@ -945,7 +967,7 @@ test_buffer(dso,primary,1,TRUE,volume,TRUE,0, winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER), - 1.0,0,NULL,0,0); + 1.0,0,NULL,0,0,FALSE,0); volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40); } @@ -953,7 +975,7 @@ for (i = 0; i < 7; i++) { test_buffer(dso,primary,1,TRUE,0,TRUE,pan, winetest_interactive && - !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0); + !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0,FALSE,0); pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6); } } @@ -1029,7 +1051,8 @@ "failed to create a 3D primary buffer: %s\n",DXGetErrorString8(rc)); if (rc==DS_OK && primary!=NULL) { test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && - !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0); + !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0, + FALSE,0); ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); @@ -1128,7 +1151,7 @@ test_buffer(dso,primary,1,FALSE,0,FALSE,0, winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0, - listener,0,0); + listener,0,0,FALSE,0); } /* Testing the reference counting */ @@ -1165,6 +1188,9 @@ } else if (rc == DSERR_ALLOCATED) { trace(" Already In Use\n"); return 1; + } else if (rc == E_FAIL) { + trace(" No Device\n"); + return 1; } trace(" Testing the primary buffer\n"); @@ -1206,6 +1232,8 @@ { CoInitialize(NULL); + trace("DLL Version: %s\n", get_file_version("dsound.dll")); + ds3d_tests(); CoUninitialize(); diff -urN wine-20050211/dlls/dsound/tests/ds3d8.c wine-20050310/dlls/dsound/tests/ds3d8.c --- wine-20050211/dlls/dsound/tests/ds3d8.c 2005-02-10 22:21:13.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/ds3d8.c 2005-03-05 11:49:08.000000000 +0100 @@ -615,7 +615,8 @@ else bufdesc.dwFlags|= (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN); - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; if (has_3d) { /* a stereo 3D buffer should fail */ @@ -795,7 +796,7 @@ /* Create the DirectSound object */ rc=pDirectSoundCreate8(lpGuid,&dso,NULL); - ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) return rc; @@ -1080,6 +1081,9 @@ } else if (rc == DSERR_ALLOCATED) { trace(" Already In Use\n"); return 1; + } else if (rc == E_FAIL) { + trace(" No Device\n"); + return 1; } trace(" Testing the primary buffer\n"); @@ -1129,6 +1133,8 @@ return; } + trace("DLL Version: %s\n", get_file_version("dsound.dll")); + pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8"); if (!pDirectSoundCreate8) { trace("ds3d8 test skipped\n"); diff -urN wine-20050211/dlls/dsound/tests/dsound.c wine-20050310/dlls/dsound/tests/dsound.c --- wine-20050211/dlls/dsound/tests/dsound.c 2005-02-10 21:26:20.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/dsound.c 2005-03-05 12:15:27.000000000 +0100 @@ -89,11 +89,14 @@ DXGetErrorString8(rc)); rc=IDirectSound_Initialize(dso,lpGuid); - ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc)); if (rc==DSERR_NODRIVER) { trace(" No Driver\n"); return; + } else if (rc==E_FAIL) { + trace(" No Device\n"); + return; } else if (rc==DSERR_ALLOCATED) { trace(" Already Allocated\n"); return; @@ -210,14 +213,14 @@ /* try with no device specified */ rc=DirectSoundCreate(NULL,&dso,NULL); - ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc)); if (rc==S_OK && dso) IDirectSound_test(dso, TRUE, NULL); /* try with default playback device specified */ rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL); - ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n", DXGetErrorString8(rc)); if (rc==DS_OK && dso) @@ -225,7 +228,7 @@ /* try with default voice playback device specified */ rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL); - ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n", DXGetErrorString8(rc)); if (rc==DS_OK && dso) @@ -250,7 +253,7 @@ /* Create the DirectSound object */ rc=DirectSoundCreate(lpGuid,&dso,NULL); - ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) return rc; @@ -305,7 +308,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL, @@ -454,7 +458,7 @@ trace("Listen for stutter, changes in pitch, volume, etc.\n"); } test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && - !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0); + !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0); ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " @@ -573,7 +577,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx2; if (winetest_interactive) { trace(" Testing a primary buffer at %ldx%dx%d with a " @@ -588,7 +593,7 @@ if (rc==DS_OK && secondary!=NULL) { test_buffer(dso,secondary,0,FALSE,0,FALSE,0, - winetest_interactive,1.0,0,NULL,0,0); + winetest_interactive,1.0,0,NULL,0,0,FALSE,0); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " @@ -672,7 +677,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() " "should have returned DSERR_INVALIDPARAM, returned: %s\n", @@ -684,7 +690,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; if (winetest_interactive) { trace(" Testing a secondary buffer at %ldx%dx%d " @@ -699,7 +706,7 @@ if (rc==DS_OK && secondary!=NULL) { test_buffer(dso,secondary,0,FALSE,0,FALSE,0, - winetest_interactive,1.0,0,NULL,0,0); + winetest_interactive,1.0,0,NULL,0,0,FALSE,0); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " @@ -727,6 +734,167 @@ return rc; } +static HRESULT test_block_align(LPGUID lpGuid) +{ + HRESULT rc; + LPDIRECTSOUND dso=NULL; + LPDIRECTSOUNDBUFFER secondary=NULL; + DSBUFFERDESC bufdesc; + DSBCAPS dsbcaps; + WAVEFORMATEX wfx; + int ref; + + /* Create the DirectSound object */ + rc=DirectSoundCreate(lpGuid,&dso,NULL); + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); + if (rc!=DS_OK) + return rc; + + init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; + bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1; + bufdesc.lpwfxFormat=&wfx; + rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); + ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() " + "should have returned DS_OK, returned: %s\n", + DXGetErrorString8(rc)); + + if (rc==DS_OK && secondary!=NULL) { + ZeroMemory(&dsbcaps, sizeof(dsbcaps)); + dsbcaps.dwSize = sizeof(dsbcaps); + rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps); + ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, " + "returned: %s\n", DXGetErrorString8(rc)); + if (rc==DS_OK) + ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign), + "Buffer size not a multiple of nBlockAlign: requested %ld, " + "got %ld, should be %ld\n", bufdesc.dwBufferBytes, + dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign); + ref=IDirectSoundBuffer_Release(secondary); + ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, " + "should have 0\n",ref); + } + + ref=IDirectSound_Release(dso); + ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); + if (ref!=0) + return DSERR_GENERIC; + + return rc; +} + +static struct fmt { + int bits; + int channels; +} fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } }; + +static HRESULT test_frequency(LPGUID lpGuid) +{ + HRESULT rc; + LPDIRECTSOUND dso=NULL; + LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; + DSBUFFERDESC bufdesc; + DSCAPS dscaps; + WAVEFORMATEX wfx, wfx1; + DWORD f, r; + int ref; + int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 96000 }; + + /* Create the DirectSound object */ + rc=DirectSoundCreate(lpGuid,&dso,NULL); + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); + if (rc!=DS_OK) + return rc; + + /* Get the device capabilities */ + ZeroMemory(&dscaps, sizeof(dscaps)); + dscaps.dwSize=sizeof(dscaps); + rc=IDirectSound_GetCaps(dso,&dscaps); + ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc)); + if (rc!=DS_OK) + goto EXIT; + + /* We must call SetCooperativeLevel before creating primary buffer */ + /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ + rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); + ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n", + DXGetErrorString8(rc)); + if (rc!=DS_OK) + goto EXIT; + + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; + rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); + ok(rc==DS_OK && primary!=NULL, + "IDirectSound_CreateSoundBuffer() failed to create a primary buffer " + "%s\n",DXGetErrorString8(rc)); + + if (rc==DS_OK && primary!=NULL) { + rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL); + ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n", + DXGetErrorString8(rc)); + if (rc!=DS_OK) + goto EXIT1; + + for (f=0;f +#include #include "wine/test.h" #include "dsound.h" @@ -38,6 +39,11 @@ static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL; +int align(int length, int align) +{ + return (length / align) * align; +} + static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized, LPCGUID lpGuid) { @@ -315,7 +321,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL, @@ -594,7 +601,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx2; if (winetest_interactive) { trace(" Testing a primary buffer at %ldx%dx%d with a " @@ -693,7 +701,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() " "should have returned DSERR_INVALIDPARAM, returned: %s\n", @@ -705,7 +714,8 @@ ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; - bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; + bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, + wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; if (winetest_interactive) { trace(" Testing a secondary buffer at %ldx%dx%d " @@ -758,6 +768,8 @@ trace(" No Driver\n"); else if (rc == DSERR_ALLOCATED) trace(" Already In Use\n"); + else if (rc == E_FAIL) + trace(" No Device\n"); else { test_primary8(lpGuid); test_primary_secondary8(lpGuid); @@ -774,6 +786,39 @@ ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc)); } +const char * get_file_version(const char * file_name) +{ + static char version[32]; + DWORD size; + DWORD handle; + + size = GetFileVersionInfoSizeA("dsound.dll", &handle); + if (size) { + char * data = HeapAlloc(GetProcessHeap(), 0, size); + if (data) { + if (GetFileVersionInfoA("dsound.dll", handle, size, data)) { + VS_FIXEDFILEINFO *pFixedVersionInfo; + UINT len; + if (VerQueryValueA(data, "\\", (LPLPVOID)&pFixedVersionInfo, &len)) { + sprintf(version, "%ld.%ld.%ld.%ld", + pFixedVersionInfo->dwFileVersionMS >> 16, + pFixedVersionInfo->dwFileVersionMS & 0xffff, + pFixedVersionInfo->dwFileVersionLS >> 16, + pFixedVersionInfo->dwFileVersionLS & 0xffff); + } else + sprintf(version, "not available"); + } else + sprintf(version, "failed"); + + HeapFree(GetProcessHeap(), 0, data); + } else + sprintf(version, "failed"); + } else + sprintf(version, "not available"); + + return version; +} + START_TEST(dsound8) { HMODULE hDsound; @@ -786,6 +831,8 @@ return; } + trace("DLL Version: %s\n", get_file_version("dsound.dll")); + pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8"); if (!pDirectSoundCreate8) { trace("dsound8 test skipped\n"); diff -urN wine-20050211/dlls/dsound/tests/dsound_test.h wine-20050310/dlls/dsound/tests/dsound_test.h --- wine-20050211/dlls/dsound/tests/dsound_test.h 2004-12-13 22:19:02.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/dsound_test.h 2005-03-05 11:49:08.000000000 +0100 @@ -50,14 +50,15 @@ #define TIME_SLICE 31 #define BUFFER_LEN 400 - extern char* wave_generate_la(WAVEFORMATEX*,double,DWORD*); extern HWND get_hwnd(void); extern void init_format(WAVEFORMATEX*,int,int,int,int); extern void test_buffer(LPDIRECTSOUND,LPDIRECTSOUNDBUFFER, BOOL,BOOL,LONG,BOOL,LONG,BOOL,double,BOOL, - LPDIRECTSOUND3DLISTENER,BOOL,BOOL); + LPDIRECTSOUND3DLISTENER,BOOL,BOOL,BOOL,DWORD); extern void test_buffer8(LPDIRECTSOUND8,LPDIRECTSOUNDBUFFER, BOOL,BOOL,LONG,BOOL,LONG,BOOL,double,BOOL, LPDIRECTSOUND3DLISTENER,BOOL,BOOL); extern const char * getDSBCAPS(DWORD xmask); +extern int align(int length, int align); +extern const char * get_file_version(const char * file_name); diff -urN wine-20050211/dlls/dsound/tests/propset.c wine-20050310/dlls/dsound/tests/propset.c --- wine-20050211/dlls/dsound/tests/propset.c 2005-01-10 13:25:56.000000000 +0100 +++ wine-20050310/dlls/dsound/tests/propset.c 2005-03-05 11:49:08.000000000 +0100 @@ -51,6 +51,16 @@ typedef HRESULT (CALLBACK * MYPROC)(REFCLSID, REFIID, LPVOID *); +static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*, + LPUNKNOWN)=NULL; +static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID, + LPDIRECTSOUNDCAPTURE*,LPUNKNOWN)=NULL; +static HRESULT (WINAPI *pDirectSoundCaptureCreate8)(LPCGUID, + LPDIRECTSOUNDCAPTURE8*,LPUNKNOWN)=NULL; +static HRESULT (WINAPI *pDirectSoundFullDuplexCreate)(LPCGUID,LPCGUID, + LPCDSCBUFFERDESC,LPCDSBUFFERDESC,HWND,DWORD,LPDIRECTSOUNDFULLDUPLEX*, + LPDIRECTSOUNDCAPTUREBUFFER8*,LPDIRECTSOUNDBUFFER8*,LPUNKNOWN)=NULL; + BOOL CALLBACK callback(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA data, LPVOID context) { @@ -117,59 +127,67 @@ "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); /* and the direct sound 8 version */ - rc = (fProc)(&CLSID_DirectSound8, &IID_IClassFactory, (void **)(&pcf)); - ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound8, IID_IClassFactory) " - "failed: %s\n",DXGetErrorString8(rc)); - if (pcf==0) - goto error; - - /* direct sound 8 doesn't have an IKsPropertySet */ - rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, - (void **)(&pps)); - ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " - "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + if (pDirectSoundCreate8) { + rc = (fProc)(&CLSID_DirectSound8, &IID_IClassFactory, (void **)(&pcf)); + ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound8, IID_IClassFactory) " + "failed: %s\n",DXGetErrorString8(rc)); + if (pcf==0) + goto error; + + /* direct sound 8 doesn't have an IKsPropertySet */ + rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, + (void **)(&pps)); + ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " + "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + } /* try direct sound capture next */ - rc = (fProc)(&CLSID_DirectSoundCapture, &IID_IClassFactory, - (void **)(&pcf)); - ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) " - "failed: %s\n",DXGetErrorString8(rc)); - if (pcf==0) - goto error; - - /* direct sound capture doesn't have an IKsPropertySet */ - rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, - (void **)(&pps)); - ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " - "returned E_NOINTERFACE,returned: %s\n",DXGetErrorString8(rc)); + if (pDirectSoundCaptureCreate) { + rc = (fProc)(&CLSID_DirectSoundCapture, &IID_IClassFactory, + (void **)(&pcf)); + ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) " + "failed: %s\n",DXGetErrorString8(rc)); + if (pcf==0) + goto error; + + /* direct sound capture doesn't have an IKsPropertySet */ + rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, + (void **)(&pps)); + ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " + "returned E_NOINTERFACE,returned: %s\n",DXGetErrorString8(rc)); + } /* and the direct sound capture 8 version */ - rc = (fProc)(&CLSID_DirectSoundCapture8, &IID_IClassFactory, - (void **)(&pcf)); - ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture8, " - "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc)); - if (pcf==0) - goto error; - - /* direct sound capture 8 doesn't have an IKsPropertySet */ - rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, - (void **)(&pps)); - ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " - "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + if (pDirectSoundCaptureCreate8) { + rc = (fProc)(&CLSID_DirectSoundCapture8, &IID_IClassFactory, + (void **)(&pcf)); + ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture8, " + "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc)); + if (pcf==0) + goto error; + + /* direct sound capture 8 doesn't have an IKsPropertySet */ + rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, + (void **)(&pps)); + ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " + "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + } /* try direct sound full duplex next */ - rc = (fProc)(&CLSID_DirectSoundFullDuplex, &IID_IClassFactory, - (void **)(&pcf)); - ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundFullDuplex, " - "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc)); - if (pcf==0) - goto error; - - /* direct sound full duplex doesn't have an IKsPropertySet */ - rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, - (void **)(&pps)); - ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " - "returned NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + if (pDirectSoundFullDuplexCreate) { + rc = (fProc)(&CLSID_DirectSoundFullDuplex, &IID_IClassFactory, + (void **)(&pcf)); + ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundFullDuplex, " + "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc)); + if (pcf==0) + goto error; + + /* direct sound full duplex doesn't have an IKsPropertySet */ + rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet, + (void **)(&pps)); + ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have " + "returned NOINTERFACE, returned: %s\n",DXGetErrorString8(rc)); + } /* try direct sound private last */ rc = (fProc)(&CLSID_DirectSoundPrivate, &IID_IClassFactory, @@ -190,11 +208,14 @@ rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice, DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION, &support); - ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, " + ok(rc==DS_OK||rc==E_INVALIDARG, "QuerySupport(DSPROPSETID_DirectSoundDevice, " "DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION) failed: %s\n", DXGetErrorString8(rc)); - if (rc!=DS_OK) + if (rc!=DS_OK) { + if (rc==E_INVALIDARG) + trace(" Not Supported\n"); goto error; + } ok(support & KSPROPERTY_SUPPORT_GET, "Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION: " @@ -263,13 +284,15 @@ trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule); rc=DirectSoundCreate(lpGuid,&dso,NULL); - ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) { if (rc==DSERR_NODRIVER) trace(" No Driver\n"); else if (rc == DSERR_ALLOCATED) trace(" Already In Use\n"); + else if (rc == E_FAIL) + trace(" No Device\n"); goto EXIT; } @@ -403,8 +426,23 @@ START_TEST(propset) { + HMODULE hDsound; + CoInitialize(NULL); + hDsound = LoadLibraryA("dsound.dll"); + if (!hDsound) { + trace("dsound.dll not found\n"); + return; + } + + trace("DLL Version: %s\n", get_file_version("dsound.dll")); + + pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8"); + pDirectSoundCaptureCreate=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate"); + pDirectSoundCaptureCreate8=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate8"); + pDirectSoundFullDuplexCreate=(void*)GetProcAddress(hDsound,"DirectSoundFullDuplexCreate"); + propset_private_tests(); propset_buffer_tests(); diff -urN wine-20050211/dlls/gdi/Makefile.in wine-20050310/dlls/gdi/Makefile.in --- wine-20050211/dlls/gdi/Makefile.in 2004-08-12 01:59:07.000000000 +0200 +++ wine-20050310/dlls/gdi/Makefile.in 2005-03-08 17:55:26.000000000 +0100 @@ -71,7 +71,7 @@ # Special rules for 16-bit resource and spec files gdi.exe.spec.c: gdi.exe.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/gdi.exe.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --export $(SRCDIR)/gdi.exe.spec version16.res: version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc diff -urN wine-20050211/dlls/gdi/dib.c wine-20050310/dlls/gdi/dib.c --- wine-20050211/dlls/gdi/dib.c 2004-11-02 06:23:49.000000000 +0100 +++ wine-20050310/dlls/gdi/dib.c 2005-02-22 20:34:33.000000000 +0100 @@ -133,6 +133,7 @@ else /* assume BITMAPINFOHEADER */ { colors = info->bmiHeader.biClrUsed; + if (colors > 256) colors = 256; if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount; return sizeof(BITMAPINFOHEADER) + colors * @@ -313,12 +314,15 @@ BITMAPOBJ *bitmap; INT result = 0; - if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0; - if (!(dc = DC_GetDCUpdate( hdc ))) { if (coloruse == DIB_RGB_COLORS) FIXME( "shouldn't require a DC for DIB_RGB_COLORS\n" ); - GDI_ReleaseObj( hbitmap ); + return 0; + } + + if (!(bitmap = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) + { + GDI_ReleaseObj( hdc ); return 0; } @@ -331,8 +335,8 @@ result = lines; done: - GDI_ReleaseObj( hdc ); GDI_ReleaseObj( hbitmap ); + GDI_ReleaseObj( hdc ); return result; } diff -urN wine-20050211/dlls/gdi/font.c wine-20050310/dlls/gdi/font.c --- wine-20050211/dlls/gdi/font.c 2005-01-05 14:24:52.000000000 +0100 +++ wine-20050310/dlls/gdi/font.c 2005-02-22 20:37:18.000000000 +0100 @@ -1924,19 +1924,6 @@ /*********************************************************************** - * GetGlyphOutline (GDI.309) - */ -DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat, - LPGLYPHMETRICS16 lpgm, DWORD cbBuffer, - LPVOID lpBuffer, const MAT2 *lpmat2 ) -{ - FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n", - hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 ); - return ~0UL; /* failure */ -} - - -/*********************************************************************** * GetGlyphOutlineA (GDI32.@) */ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat, @@ -1948,7 +1935,17 @@ UINT c; if(!(fuFormat & GGO_GLYPH_INDEX)) { - p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL); + int len; + char mbchs[2]; + if(uChar > 0xff) { /* but, 2 bytes character only */ + len = 2; + mbchs[0] = (uChar & 0xff00) >> 8; + mbchs[1] = (uChar & 0xff); + } else { + len = 1; + mbchs[0] = (uChar & 0xff); + } + p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL); c = p[0]; } else c = uChar; diff -urN wine-20050211/dlls/gdi/freetype.c wine-20050310/dlls/gdi/freetype.c --- wine-20050211/dlls/gdi/freetype.c 2005-01-24 20:00:10.000000000 +0100 +++ wine-20050310/dlls/gdi/freetype.c 2005-02-25 14:59:22.000000000 +0100 @@ -2385,10 +2385,6 @@ if(format == GGO_METRICS) return 1; /* FIXME */ - if (buf && !buflen){ - return GDI_ERROR; - } - if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) { TRACE("loaded a bitmap\n"); return GDI_ERROR; @@ -2467,14 +2463,16 @@ pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + memset(ft_bitmap.buffer, 0, buflen); + pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); if(format == GGO_GRAY2_BITMAP) - mult = 5; + mult = 4; else if(format == GGO_GRAY4_BITMAP) - mult = 17; + mult = 16; else if(format == GGO_GRAY8_BITMAP) - mult = 65; + mult = 64; else if(format == WINE_GGO_GRAY16_BITMAP) break; else { @@ -2486,7 +2484,7 @@ for(row = 0; row < height; row++) { ptr = start; for(col = 0; col < width; col++, ptr++) { - *ptr = (*(unsigned int*)ptr * mult + 128) / 256; + *ptr = (((int)*ptr) * mult + 128) / 256; } start += pitch; } @@ -2903,7 +2901,9 @@ TM.tmStruckOut = font->strikeout; /* Yes TPMF_FIXED_PITCH is correct; braindead api */ - if(!FT_IS_FIXED_WIDTH(ft_face)) + if(!FT_IS_FIXED_WIDTH(ft_face) && + (pOS2->version == 0xFFFFU || + pOS2->panose[PAN_PROPORTION_INDEX] != PAN_PROP_MONOSPACED)) TM.tmPitchAndFamily = TMPF_FIXED_PITCH; else TM.tmPitchAndFamily = 0; diff -urN wine-20050211/dlls/gdi/gdi16.c wine-20050310/dlls/gdi/gdi16.c --- wine-20050211/dlls/gdi/gdi16.c 2004-12-23 19:41:06.000000000 +0100 +++ wine-20050310/dlls/gdi/gdi16.c 2005-02-21 21:43:59.000000000 +0100 @@ -1719,6 +1719,27 @@ /*********************************************************************** + * GetGlyphOutline (GDI.309) + */ +DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat, + LPGLYPHMETRICS16 lpgm, DWORD cbBuffer, + LPVOID lpBuffer, const MAT2 *lpmat2 ) +{ + DWORD ret; + GLYPHMETRICS gm32; + + ret = GetGlyphOutlineA( HDC_32(hdc), uChar, fuFormat, &gm32, cbBuffer, lpBuffer, lpmat2); + lpgm->gmBlackBoxX = gm32.gmBlackBoxX; + lpgm->gmBlackBoxY = gm32.gmBlackBoxY; + lpgm->gmptGlyphOrigin.x = gm32.gmptGlyphOrigin.x; + lpgm->gmptGlyphOrigin.y = gm32.gmptGlyphOrigin.y; + lpgm->gmCellIncX = gm32.gmCellIncX; + lpgm->gmCellIncY = gm32.gmCellIncY; + return ret; +} + + +/*********************************************************************** * CreateScalableFontResource (GDI.310) */ BOOL16 WINAPI CreateScalableFontResource16( UINT16 fHidden, LPCSTR lpszResourceFile, diff -urN wine-20050211/dlls/gdi/gdiobj.c wine-20050310/dlls/gdi/gdiobj.c --- wine-20050211/dlls/gdi/gdiobj.c 2005-01-05 18:12:07.000000000 +0100 +++ wine-20050310/dlls/gdi/gdiobj.c 2005-03-10 12:20:51.000000000 +0100 @@ -743,6 +743,8 @@ case MEMORY_DC_MAGIC: case BITMAP_MAGIC: case PALETTE_MAGIC: + case FONT_MAGIC: + case REGION_MAGIC: if (!(obj = alloc_large_heap( size, handle ))) goto error; break; } diff -urN wine-20050211/dlls/gdi/region.c wine-20050310/dlls/gdi/region.c --- wine-20050211/dlls/gdi/region.c 2004-12-14 12:38:50.000000000 +0100 +++ wine-20050310/dlls/gdi/region.c 2005-03-02 14:53:51.000000000 +0100 @@ -444,6 +444,7 @@ /* Note the parameter order is different from the X11 equivalents */ static void REGION_CopyRegion(WINEREGION *d, WINEREGION *s); +static void REGION_OffsetRegion(WINEREGION *d, WINEREGION *s, INT x, INT y); static void REGION_IntersectRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static void REGION_UnionRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static void REGION_SubtractRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); @@ -558,6 +559,35 @@ /*********************************************************************** + * REGION_OffsetRegion + * Offset a WINEREGION by x,y + */ +static void REGION_OffsetRegion( WINEREGION *rgn, WINEREGION *srcrgn, + INT x, INT y ) +{ + if( rgn != srcrgn) + REGION_CopyRegion( rgn, srcrgn); + if(x || y) { + int nbox = rgn->numRects; + RECT *pbox = rgn->rects; + + if(nbox) { + while(nbox--) { + pbox->left += x; + pbox->right += x; + pbox->top += y; + pbox->bottom += y; + pbox++; + } + rgn->extents.left += x; + rgn->extents.right += x; + rgn->extents.top += y; + rgn->extents.bottom += y; + } + } +} + +/*********************************************************************** * OffsetRgn (GDI32.@) * * Moves a region by the specified X- and Y-axis offsets. @@ -585,24 +615,8 @@ if (!obj) return ERROR; - if(x || y) { - int nbox = obj->rgn->numRects; - RECT *pbox = obj->rgn->rects; + REGION_OffsetRegion( obj->rgn, obj->rgn, x, y); - if(nbox) { - while(nbox--) { - pbox->left += x; - pbox->right += x; - pbox->top += y; - pbox->bottom += y; - pbox++; - } - obj->rgn->extents.left += x; - obj->rgn->extents.right += x; - obj->rgn->extents.top += y; - obj->rgn->extents.bottom += y; - } - } ret = get_region_type( obj ); GDI_ReleaseObj( hrgn ); return ret; @@ -1191,7 +1205,9 @@ * REGION_CreateFrameRgn * * Create a region that is a frame around another region. - * Expand all rectangles by +/- x and y, then subtract original region. + * Compute the intersection of the region moved in all 4 directions + * ( +x, -x, +y, -y) and subtract from the original. + * The result looks slightly better than in Windows :) */ BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y ) { @@ -1201,22 +1217,19 @@ if (!srcObj) return FALSE; if (srcObj->rgn->numRects != 0) { - RGNOBJ* destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC ); - RECT *pRect, *pEndRect; - RECT tempRect; - - EMPTY_REGION( destObj->rgn ); - - pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects; - for(pRect = srcObj->rgn->rects; pRect < pEndRect; pRect++) - { - tempRect.left = pRect->left - x; - tempRect.top = pRect->top - y; - tempRect.right = pRect->right + x; - tempRect.bottom = pRect->bottom + y; - REGION_UnionRectWithRegion( &tempRect, destObj->rgn ); - } - REGION_SubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn ); + RGNOBJ* destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC ); + WINEREGION *tmprgn = REGION_AllocWineRegion( srcObj->rgn->numRects); + + REGION_OffsetRegion( destObj->rgn, srcObj->rgn, -x, 0); + REGION_OffsetRegion( tmprgn, srcObj->rgn, x, 0); + REGION_IntersectRegion( destObj->rgn, destObj->rgn, tmprgn); + REGION_OffsetRegion( tmprgn, srcObj->rgn, 0, -y); + REGION_IntersectRegion( destObj->rgn, destObj->rgn, tmprgn); + REGION_OffsetRegion( tmprgn, srcObj->rgn, 0, y); + REGION_IntersectRegion( destObj->rgn, destObj->rgn, tmprgn); + REGION_SubtractRegion( destObj->rgn, srcObj->rgn, destObj->rgn); + + REGION_DestroyWineRegion(tmprgn); GDI_ReleaseObj ( hDest ); bRet = TRUE; } @@ -2157,7 +2170,7 @@ else if (r2->left <= left) { /* - * Subtrahend preceeds minuend: nuke left edge of minuend. + * Subtrahend precedes minuend: nuke left edge of minuend. */ left = r2->right; if (left >= r1->right) diff -urN wine-20050211/dlls/gdi/tests/brush.c wine-20050310/dlls/gdi/tests/brush.c --- wine-20050211/dlls/gdi/tests/brush.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050310/dlls/gdi/tests/brush.c 2005-02-14 12:03:36.000000000 +0100 @@ -29,7 +29,7 @@ typedef struct _STOCK_BRUSH { COLORREF color; int stockobj; - char *name; + const char *name; } STOCK_BRUSH; static void test_solidbrush() diff -urN wine-20050211/dlls/gdi/tests/metafile.c wine-20050310/dlls/gdi/tests/metafile.c --- wine-20050211/dlls/gdi/tests/metafile.c 2005-01-14 16:12:59.000000000 +0100 +++ wine-20050310/dlls/gdi/tests/metafile.c 2005-02-14 22:04:45.000000000 +0100 @@ -259,8 +259,7 @@ static void dump_mf_bits (const HMETAFILE mf, const char *desc) { char buf[MF_BUFSIZE]; - UINT mfsize; - int i; + UINT mfsize, i; mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf); ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc); @@ -286,12 +285,12 @@ * otherwise returns the number of non-matching bytes. */ -static int compare_mf_bits (const HMETAFILE mf, const char *bits, int bsize, +static int compare_mf_bits (const HMETAFILE mf, const char *bits, UINT bsize, const char *desc) { char buf[MF_BUFSIZE]; - UINT mfsize; - int i, diff; + UINT mfsize, i; + int diff; mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf); ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc); diff -urN wine-20050211/dlls/itss/itss.c wine-20050310/dlls/itss/itss.c --- wine-20050211/dlls/itss/itss.c 2005-01-14 18:21:00.000000000 +0100 +++ wine-20050310/dlls/itss/itss.c 2005-02-22 20:30:24.000000000 +0100 @@ -146,10 +146,15 @@ return hres; } -static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) +static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); + TRACE("(%p)->(%d)\n", iface, dolock); + + if(dolock) + InterlockedIncrement(&dll_count); + else + InterlockedDecrement(&dll_count); + return S_OK; } diff -urN wine-20050211/dlls/kernel/Makefile.in wine-20050310/dlls/kernel/Makefile.in --- wine-20050211/dlls/kernel/Makefile.in 2005-02-03 17:58:21.000000000 +0100 +++ wine-20050310/dlls/kernel/Makefile.in 2005-03-08 17:55:26.000000000 +0100 @@ -106,7 +106,7 @@ # Special rules for 16-bit resource and spec files krnl386.exe.spec.c: krnl386.exe.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/krnl386.exe.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --export $(SRCDIR)/krnl386.exe.spec version16.res: version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc diff -urN wine-20050211/dlls/kernel/comm.c wine-20050310/dlls/kernel/comm.c --- wine-20050211/dlls/kernel/comm.c 2005-01-14 20:54:39.000000000 +0100 +++ wine-20050310/dlls/kernel/comm.c 2005-02-25 15:07:58.000000000 +0100 @@ -692,7 +692,7 @@ * Only TIOCSBRK and TIOCCBRK are supported. */ BOOL WINAPI SetCommBreak( - HANDLE handle) /* [in] The communictions device to suspend. */ + HANDLE handle) /* [in] The communications device to suspend. */ { #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */ int fd,result; @@ -1395,7 +1395,7 @@ case ONESTOPBIT: port.c_cflag &= ~CSTOPB; break; - case ONE5STOPBITS: /* wil be selected if bytesize is 5 */ + case ONE5STOPBITS: /* will be selected if bytesize is 5 */ case TWOSTOPBITS: port.c_cflag |= CSTOPB; break; diff -urN wine-20050211/dlls/kernel/console.c wine-20050310/dlls/kernel/console.c --- wine-20050211/dlls/kernel/console.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/console.c 2005-03-09 12:44:33.000000000 +0100 @@ -386,7 +386,7 @@ { memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X], new_size.X * sizeof(CHAR_INFO) ); - char_info_AtoW( ciw, new_size.X ); + char_info_AtoW( &ciw[ y * new_size.X ], new_size.X ); } new_coord.X = new_coord.Y = 0; ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region ); diff -urN wine-20050211/dlls/kernel/cpu.c wine-20050310/dlls/kernel/cpu.c --- wine-20050211/dlls/kernel/cpu.c 2005-01-28 12:29:03.000000000 +0100 +++ wine-20050310/dlls/kernel/cpu.c 2005-02-23 21:29:17.000000000 +0100 @@ -192,8 +192,7 @@ */ BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) { - LARGE_INTEGER frequency; - NtQueryPerformanceCounter( counter, &frequency ); + NtQueryPerformanceCounter( counter, NULL ); return TRUE; } diff -urN wine-20050211/dlls/kernel/editline.c wine-20050310/dlls/kernel/editline.c --- wine-20050211/dlls/kernel/editline.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/editline.c 2005-02-25 15:07:58.000000000 +0100 @@ -192,7 +192,7 @@ /* completely erase all the others (full lines) */ for (i = cbeg.Y + 1; i < cend.Y; i++) CONSOLE_FillLineUniform(ctx->hConOut, 0, i, ctx->csbi.dwSize.X, &ci); - /* erase from begining of line until last pos on last line */ + /* erase from beginning of line until last pos on last line */ CONSOLE_FillLineUniform(ctx->hConOut, 0, cend.Y, cend.X, &ci); } ctx->len -= str_len; diff -urN wine-20050211/dlls/kernel/except.c wine-20050310/dlls/kernel/except.c --- wine-20050211/dlls/kernel/except.c 2004-12-14 21:03:23.000000000 +0100 +++ wine-20050310/dlls/kernel/except.c 2005-02-24 14:15:36.000000000 +0100 @@ -66,7 +66,7 @@ /******************************************************************* * RaiseException (KERNEL32.@) */ -void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const LPDWORD args ) +void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const ULONG_PTR *args ) { EXCEPTION_RECORD record; diff -urN wine-20050211/dlls/kernel/kernel32.spec wine-20050310/dlls/kernel/kernel32.spec --- wine-20050211/dlls/kernel/kernel32.spec 2005-01-31 17:23:31.000000000 +0100 +++ wine-20050310/dlls/kernel/kernel32.spec 2005-02-21 22:02:12.000000000 +0100 @@ -661,9 +661,9 @@ @ stdcall PrepareTape(ptr long long) @ stub PrivMoveFileIdentityW @ stdcall Process32First (ptr ptr) -@ stub Process32FirstW +@ stdcall Process32FirstW (ptr ptr) @ stdcall Process32Next (ptr ptr) -@ stub Process32NextW +@ stdcall Process32NextW (ptr ptr) @ stdcall PulseEvent(long) @ stdcall PurgeComm(long long) @ stdcall -register -i386 QT_Thunk() @@ -675,7 +675,7 @@ @ stdcall QueryPerformanceCounter(ptr) @ stdcall QueryPerformanceFrequency(ptr) @ stdcall QueueUserAPC(ptr long long) -@ stub QueueUserWorkItem +@ stdcall QueueUserWorkItem(ptr ptr long) @ stdcall RaiseException(long long long ptr) @ stdcall ReadConsoleA(long ptr long ptr ptr) @ stdcall ReadConsoleInputA(long ptr long ptr) diff -urN wine-20050211/dlls/kernel/local16.c wine-20050310/dlls/kernel/local16.c --- wine-20050211/dlls/kernel/local16.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/local16.c 2005-03-02 13:23:22.000000000 +0100 @@ -95,9 +95,9 @@ */ #ifdef ALLOW_UNALIGNED_ACCESS - #define MOVEABLE_PREFIX sizeof(HLOCAL16) +# define MOVEABLE_PREFIX sizeof(HLOCAL16) #else - #define MOVEABLE_PREFIX sizeof(int) +# define MOVEABLE_PREFIX sizeof(int) #endif diff -urN wine-20050211/dlls/kernel/ne_module.c wine-20050310/dlls/kernel/ne_module.c --- wine-20050211/dlls/kernel/ne_module.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/ne_module.c 2005-03-07 20:24:44.000000000 +0100 @@ -1827,7 +1827,7 @@ HeapFree( GetProcessHeap(), 0, cmdline ); if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name ); - if (ret == 21) /* 32-bit module */ + if (ret == 21 || ret == 11) /* 32-bit module or unknown executable*/ { DWORD count; ReleaseThunkLock( &count ); diff -urN wine-20050211/dlls/kernel/path.c wine-20050310/dlls/kernel/path.c --- wine-20050211/dlls/kernel/path.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/path.c 2005-03-01 11:42:22.000000000 +0100 @@ -852,6 +852,7 @@ { HANDLE h1, h2; BY_HANDLE_FILE_INFORMATION info; + FILETIME filetime; DWORD count; BOOL ret = FALSE; char buffer[2048]; @@ -900,6 +901,10 @@ } ret = TRUE; done: + /* Maintain the timestamp of source file to destination file */ + GetFileTime(h1, NULL, NULL, &filetime); + SetFileTime(h2, NULL, NULL, &filetime); + CloseHandle( h1 ); CloseHandle( h2 ); return ret; diff -urN wine-20050211/dlls/kernel/process.c wine-20050310/dlls/kernel/process.c --- wine-20050211/dlls/kernel/process.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/process.c 2005-03-07 20:24:44.000000000 +0100 @@ -82,6 +82,7 @@ static const WCHAR comW[] = {'.','c','o','m',0}; static const WCHAR batW[] = {'.','b','a','t',0}; +static const WCHAR pifW[] = {'.','p','i','f',0}; static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0}; extern void SHELL_LoadRegistry(void); @@ -608,7 +609,7 @@ if (*a==' ' || *a=='\t') { has_space=1; } else if (*a=='"') { - /* doubling of '\' preceeding a '"', + /* doubling of '\' preceding a '"', * plus escaping of said '"' */ len+=2*bcount+1; @@ -667,7 +668,7 @@ if (*a=='"') { int i; - /* Double all the '\\' preceeding this '"', plus one */ + /* Double all the '\\' preceding this '"', plus one */ for (i=0;i<=bcount;i++) *p++='\\'; *p++='"'; @@ -1271,14 +1272,14 @@ } else if (*s=='"') { /* '"' */ if ((bcount & 1)==0) { - /* Preceeded by an even number of '\', this is half that + /* Preceded by an even number of '\', this is half that * number of '\', plus a '"' which we discard. */ d-=bcount/2; s++; in_quotes=!in_quotes; } else { - /* Preceeded by an odd number of '\', this is half that + /* Preceded by an odd number of '\', this is half that * number of '\' followed by a '"' */ d=d-bcount/2-1; @@ -1952,7 +1953,7 @@ /* check for .com or .bat extension */ if ((p = strrchrW( name, '.' ))) { - if (!strcmpiW( p, comW )) + if (!strcmpiW( p, comW ) || !strcmpiW( p, pifW )) { TRACE( "starting %s as DOS binary\n", debugstr_w(name) ); retv = create_vdm_process( name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr, diff -urN wine-20050211/dlls/kernel/profile.c wine-20050310/dlls/kernel/profile.c --- wine-20050211/dlls/kernel/profile.c 2005-02-10 22:22:31.000000000 +0100 +++ wine-20050310/dlls/kernel/profile.c 2005-03-04 11:46:55.000000000 +0100 @@ -863,6 +863,7 @@ if (len <= 2) break; if (!*key->name) continue; /* Skip empty lines */ if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */ + if (!return_values && !key->value) continue; /* Skip lines w.o. '=' */ PROFILE_CopyEntry( buffer, key->name, len - 1, 0 ); len -= strlenW(buffer) + 1; buffer += strlenW(buffer) + 1; diff -urN wine-20050211/dlls/kernel/string.c wine-20050310/dlls/kernel/string.c --- wine-20050211/dlls/kernel/string.c 2003-11-27 01:59:36.000000000 +0100 +++ wine-20050310/dlls/kernel/string.c 2005-02-22 16:50:14.000000000 +0100 @@ -27,6 +27,7 @@ #include #include +#define WINE_NO_INLINE_STRING #include "windef.h" #include "winbase.h" #include "excpt.h" diff -urN wine-20050211/dlls/kernel/sync.c wine-20050310/dlls/kernel/sync.c --- wine-20050211/dlls/kernel/sync.c 2005-02-08 13:08:04.000000000 +0100 +++ wine-20050310/dlls/kernel/sync.c 2005-03-04 13:38:37.000000000 +0100 @@ -29,6 +29,9 @@ #ifdef HAVE_SYS_IOCTL_H #include #endif +#ifdef HAVE_POLL_H +#include +#endif #ifdef HAVE_SYS_POLL_H #include #endif diff -urN wine-20050211/dlls/kernel/tests/environ.c wine-20050310/dlls/kernel/tests/environ.c --- wine-20050211/dlls/kernel/tests/environ.c 2004-01-23 21:50:35.000000000 +0100 +++ wine-20050310/dlls/kernel/tests/environ.c 2005-03-10 18:15:39.000000000 +0100 @@ -211,8 +211,21 @@ ret, GetLastError()); } +static void test_ExpandEnvironmentStringsA() +{ + char buf[256], buf1[256]; + DWORD ret_size, ret_size1; + + ret_size1 = GetWindowsDirectoryA(buf1,256); + ok ((ret_size1 >0) && (ret_size1<256), "GetWindowsDirectory Failed\n"); + ret_size = ExpandEnvironmentStringsA("%SystemRoot%",buf,256); + ok(!strcmp(buf, buf1), "ExpandEnvironmentStrings failed %s vs %s\n", buf, buf1); +} + + START_TEST(environ) { test_GetSetEnvironmentVariableA(); test_GetSetEnvironmentVariableW(); + test_ExpandEnvironmentStringsA(); } diff -urN wine-20050211/dlls/kernel/tests/file.c wine-20050310/dlls/kernel/tests/file.c --- wine-20050211/dlls/kernel/tests/file.c 2005-02-10 20:19:36.000000000 +0100 +++ wine-20050310/dlls/kernel/tests/file.c 2005-03-02 14:53:51.000000000 +0100 @@ -540,6 +540,7 @@ char source[MAX_PATH], dest[MAX_PATH]; static const char prefix[] = "pfx"; HANDLE hfile; + FILETIME ft1, ft2; char buf[10]; DWORD ret; BOOL retok; @@ -558,6 +559,10 @@ ok( retok && ret == sizeof(prefix), "WriteFile error %ld\n", GetLastError()); ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n"); + /* get the file time and change it to prove the difference */ + ok(GetFileTime(hfile, NULL, NULL, &ft1), "GetFileTime error %ld\n", GetLastError()); + ft1.dwLowDateTime -= 600000000; /* 60 second */ + ok(SetFileTime(hfile, NULL, NULL, &ft1), "SetFileTime error %ld\n", GetLastError()); CloseHandle(hfile); ret = GetTempFileNameA(temp_path, prefix, 0, dest); @@ -577,6 +582,11 @@ ret = GetFileSize(hfile, NULL); ok(ret == sizeof(prefix), "destination file has wrong size %ld\n", ret); + /* make sure that destination has the same filetime */ + ok(ret = GetFileTime(hfile, NULL, NULL, &ft1), "GetFileTime error %ld\n", GetLastError()); + ok(ret = GetFileTime(hfile, NULL, NULL, &ft2), "GetFileTime error %ld\n", GetLastError()); + ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n"); + SetLastError(0xdeadbeef); ret = CopyFileA(source, dest, FALSE); ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, @@ -1076,17 +1086,23 @@ static const DWORD sharing_modes[4] = { 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE }; int a1, s1, a2, s2; int ret; + HANDLE h, h2; /* make sure the file exists */ - HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + if (h == INVALID_HANDLE_VALUE) + { + ok(0, "couldn't create file \"%s\" (err=%ld)\n", filename, GetLastError()); + return; + } CloseHandle( h ); for (a1 = 0; a1 < 4; a1++) { for (s1 = 0; s1 < 4; s1++) { - HANDLE h = CreateFileA( filename, access_modes[a1], sharing_modes[s1], - NULL, OPEN_EXISTING, 0, 0 ); + h = CreateFileA( filename, access_modes[a1], sharing_modes[s1], + NULL, OPEN_EXISTING, 0, 0 ); if (h == INVALID_HANDLE_VALUE) { ok(0,"couldn't create file \"%s\" (err=%ld)\n",filename,GetLastError()); @@ -1096,8 +1112,9 @@ { for (s2 = 0; s2 < 4; s2++) { - HANDLE h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2], - NULL, OPEN_EXISTING, 0, 0 ); + SetLastError(0xdeadbeef); + h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2], + NULL, OPEN_EXISTING, 0, 0 ); if (is_sharing_compatible( access_modes[a1], sharing_modes[s1], access_modes[a2], sharing_modes[s2] )) { @@ -1129,6 +1146,22 @@ CloseHandle( h ); } } + + SetLastError(0xdeadbeef); + h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 ); + ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %ld\n", GetLastError() ); + + SetLastError(0xdeadbeef); + h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); + ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n"); + ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %ld\n", GetLastError() ); + + h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); + ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %ld\n", GetLastError() ); + + CloseHandle(h); + CloseHandle(h2); + DeleteFileA( filename ); } diff -urN wine-20050211/dlls/kernel/tests/locale.c wine-20050310/dlls/kernel/tests/locale.c --- wine-20050211/dlls/kernel/tests/locale.c 2004-12-09 15:07:59.000000000 +0100 +++ wine-20050310/dlls/kernel/tests/locale.c 2005-03-02 11:11:22.000000000 +0100 @@ -353,7 +353,9 @@ STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */ ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer)); - EXPECT_VALID; EXPECT_LENA; EXPECT_EQA; + EXPECT_VALID; EXPECT_LENA; + if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0) + ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer); STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */ ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer)); diff -urN wine-20050211/dlls/kernel/tests/profile.c wine-20050310/dlls/kernel/tests/profile.c --- wine-20050211/dlls/kernel/tests/profile.c 2004-06-18 01:00:54.000000000 +0200 +++ wine-20050310/dlls/kernel/tests/profile.c 2005-03-04 11:46:55.000000000 +0100 @@ -28,6 +28,7 @@ #define KEY "ProfileInt" #define SECTION "Test" #define TESTFILE ".\\testwine.ini" +#define TESTFILE2 ".\\testwine2.ini" struct _profileInt { LPCSTR section; @@ -88,7 +89,52 @@ DeleteFileA( TESTFILE); } +void test_profile_string() +{ + HANDLE h; + int ret; + DWORD count; + char buf[100]; + char *p; + /* test that lines without an '=' will not be enumerated */ + /* in the case below, name2 is a key while name3 is not. */ + char content[]="[s]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n"; + DeleteFileA( TESTFILE2); + h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2); + if( h == INVALID_HANDLE_VALUE) return; + WriteFile( h, content, sizeof(content), &count, NULL); + CloseHandle( h); + /* enumerate the keys */ + ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf), + TESTFILE2); + for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1) + p[-1] = ','; + /* and test */ + ok( !strcmp( buf, "name1,name2,name4"), "wrong keys returned: %s\n", + buf); + + ret=GetPrivateProfileSectionA("s", buf, sizeof(buf), TESTFILE2); + for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1) + p[-1] = ','; + /* and test */ + ok( !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned: %s\n", + buf); + + /* add a new key to test that the file is quite usable */ + WritePrivateProfileStringA( "s", "name5", "val5", TESTFILE2); + ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf), + TESTFILE2); + for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1) + p[-1] = ','; + ok( !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned: %s\n", + buf); + DeleteFileA( TESTFILE2); +} + START_TEST(profile) { test_profile_int(); + test_profile_string(); } diff -urN wine-20050211/dlls/kernel/tests/thread.c wine-20050310/dlls/kernel/tests/thread.c --- wine-20050211/dlls/kernel/tests/thread.c 2004-12-27 18:26:38.000000000 +0100 +++ wine-20050310/dlls/kernel/tests/thread.c 2005-03-02 13:23:22.000000000 +0100 @@ -43,13 +43,13 @@ Anyhow, the check is currently commented out */ #if CHECK_STACK - #ifdef __try - #define __TRY __try - #define __EXCEPT __except - #define __ENDTRY - #else - #include "wine/exception.h" - #endif +# ifdef __try +# define __TRY __try +# define __EXCEPT __except +# define __ENDTRY +# else +# include "wine/exception.h" +# endif #endif typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL); diff -urN wine-20050211/dlls/kernel/thread.c wine-20050310/dlls/kernel/thread.c --- wine-20050211/dlls/kernel/thread.c 2004-12-01 16:37:26.000000000 +0100 +++ wine-20050310/dlls/kernel/thread.c 2005-02-21 22:02:12.000000000 +0100 @@ -549,6 +549,14 @@ return !status; } +/*********************************************************************** + * QueueUserWorkItem (KERNEL32.@) + */ +BOOL WINAPI QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags ) +{ + FIXME("(%p,%p,0x%08lx): stub\n", Function, Context, Flags); + return FALSE; +} /********************************************************************** * GetThreadTimes [KERNEL32.@] Obtains timing information. diff -urN wine-20050211/dlls/kernel/thunk.c wine-20050310/dlls/kernel/thunk.c --- wine-20050211/dlls/kernel/thunk.c 2004-10-22 21:55:14.000000000 +0200 +++ wine-20050310/dlls/kernel/thunk.c 2005-02-25 15:07:58.000000000 +0100 @@ -1216,7 +1216,7 @@ * If fn is given as NULL then the function expects hf16 to be valid. */ BOOL16 WINAPI IsPeFormat16( - LPSTR fn, /* [in] Filename to the executeable */ + LPSTR fn, /* [in] Filename to the executable */ HFILE16 hf16) /* [in] An open file handle */ { BOOL ret = FALSE; diff -urN wine-20050211/dlls/kernel/time.c wine-20050310/dlls/kernel/time.c --- wine-20050211/dlls/kernel/time.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/time.c 2005-02-25 15:07:58.000000000 +0100 @@ -239,7 +239,7 @@ *pTZinfo, /* [in] The time zone data. */ FILETIME *lpFileTime, /* [in] The system or local time. */ BOOL islocal, /* [in] it is local time */ - LONG *pBias /* [out] The calulated bias in minutes */ + LONG *pBias /* [out] The calculated bias in minutes */ ) { LONG bias = pTZinfo->Bias; @@ -299,9 +299,9 @@ * Only the special case of disabled time adjustments is supported. */ BOOL WINAPI GetSystemTimeAdjustment( - PDWORD lpTimeAdjustment, /* [out] The clock adjustment per interupt in 100's of nanoseconds. */ - PDWORD lpTimeIncrement, /* [out] The time between clock interupts in 100's of nanoseconds. */ - PBOOL lpTimeAdjustmentDisabled) /* [out] The clock synchonisation has been disabled. */ + PDWORD lpTimeAdjustment, /* [out] The clock adjustment per interrupt in 100's of nanoseconds. */ + PDWORD lpTimeIncrement, /* [out] The time between clock interrupts in 100's of nanoseconds. */ + PBOOL lpTimeAdjustmentDisabled) /* [out] The clock synchronisation has been disabled. */ { *lpTimeAdjustment = 0; *lpTimeIncrement = 0; @@ -536,7 +536,7 @@ HANDLE hprocess, /* [in] The process to be queried (obtained from PROCESS_QUERY_INFORMATION). */ LPFILETIME lpCreationTime, /* [out] The creation time of the process. */ LPFILETIME lpExitTime, /* [out] The exit time of the process if exited. */ - LPFILETIME lpKernelTime, /* [out] The time spent in kernal routines in 100's of nanoseconds. */ + LPFILETIME lpKernelTime, /* [out] The time spent in kernel routines in 100's of nanoseconds. */ LPFILETIME lpUserTime) /* [out] The time spent in user routines in 100's of nanoseconds. */ { struct tms tms; diff -urN wine-20050211/dlls/kernel/toolhelp.c wine-20050310/dlls/kernel/toolhelp.c --- wine-20050211/dlls/kernel/toolhelp.c 2004-05-24 21:06:32.000000000 +0200 +++ wine-20050310/dlls/kernel/toolhelp.c 2005-02-21 21:57:34.000000000 +0100 @@ -295,19 +295,33 @@ /*********************************************************************** * TOOLHELP_Process32Next * - * Implementation of Process32First/Next + * Implementation of Process32First/Next. Note that the ANSI / Unicode + * version check is a bit of a hack as it relies on the fact that only + * the last field is actually different. */ -static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL first ) +static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32W lppe, BOOL first, BOOL unicode ) { BOOL ret; - WCHAR exe[MAX_PATH]; + WCHAR exe[MAX_PATH-1]; DWORD len; - if (lppe->dwSize < sizeof(PROCESSENTRY32)) + if (unicode) { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize); - return FALSE; + if (lppe->dwSize < sizeof(PROCESSENTRY32W)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32W), lppe->dwSize); + return FALSE; + } + } + else + { + if (lppe->dwSize < sizeof(PROCESSENTRY32)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ERR("Result buffer too small (req: %d, was: %ld)\n", sizeof(PROCESSENTRY32), lppe->dwSize); + return FALSE; + } } SERVER_START_REQ( next_process ) { @@ -324,9 +338,20 @@ lppe->th32ParentProcessID = reply->ppid; lppe->pcPriClassBase = reply->priority; lppe->dwFlags = -1; /* FIXME */ - len = WideCharToMultiByte( CP_ACP, 0, exe, wine_server_reply_size(reply) / sizeof(WCHAR), - lppe->szExeFile, sizeof(lppe->szExeFile), NULL, NULL ); - lppe->szExeFile[len] = 0; + if (unicode) + { + len = wine_server_reply_size(reply) / sizeof(WCHAR); + memcpy(lppe->szExeFile, reply, wine_server_reply_size(reply)); + lppe->szExeFile[len] = 0; + } + else + { + LPPROCESSENTRY32 lppe_a = (LPPROCESSENTRY32) lppe; + + len = WideCharToMultiByte( CP_ACP, 0, exe, wine_server_reply_size(reply) / sizeof(WCHAR), + lppe_a->szExeFile, sizeof(lppe_a->szExeFile)-1, NULL, NULL ); + lppe_a->szExeFile[len] = 0; + } } } SERVER_END_REQ; @@ -341,7 +366,7 @@ */ BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) { - return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE ); + return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, TRUE, FALSE /* ANSI */ ); } /*********************************************************************** @@ -351,7 +376,27 @@ */ BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) { - return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE ); + return TOOLHELP_Process32Next( hSnapshot, (LPPROCESSENTRY32W) lppe, FALSE, FALSE /* ANSI */ ); +} + +/*********************************************************************** + * Process32FirstW (KERNEL32.@) + * + * Return info about the first process in a toolhelp32 snapshot + */ +BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) +{ + return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE, TRUE /* Unicode */ ); +} + +/*********************************************************************** + * Process32NextW (KERNEL32.@) + * + * Return info about the "next" process in a toolhelp32 snapshot + */ +BOOL WINAPI Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) +{ + return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE, TRUE /* Unicode */ ); } diff -urN wine-20050211/dlls/kernel/volume.c wine-20050310/dlls/kernel/volume.c --- wine-20050211/dlls/kernel/volume.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050310/dlls/kernel/volume.c 2005-02-26 18:46:34.000000000 +0100 @@ -959,7 +959,7 @@ else { TRACE( "cannot open device %s: err %ld\n", debugstr_w(device), GetLastError() ); - if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE; + if (GetLastError() == ERROR_ACCESS_DENIED) return FALSE; } /* we couldn't open the device, fallback to default strategy */ @@ -1307,10 +1307,10 @@ DWORD WINAPI QueryDosDeviceA( LPCSTR devname, LPSTR target, DWORD bufsize ) { DWORD ret = 0, retW; - WCHAR *devnameW; + WCHAR *devnameW = NULL; LPWSTR targetW; - if (!(devnameW = FILE_name_AtoW( devname, FALSE ))) return 0; + if (devname && !(devnameW = FILE_name_AtoW( devname, FALSE ))) return 0; targetW = HeapAlloc( GetProcessHeap(),0, bufsize * sizeof(WCHAR) ); if (!targetW) diff -urN wine-20050211/dlls/mapi32/prop.c wine-20050310/dlls/mapi32/prop.c --- wine-20050211/dlls/mapi32/prop.c 2005-01-10 14:29:25.000000000 +0100 +++ wine-20050310/dlls/mapi32/prop.c 2005-02-22 15:51:03.000000000 +0100 @@ -795,7 +795,8 @@ { LPSPropValue lpDest = (LPSPropValue)lpDst; char *lpDataDest = (char *)(lpDest + cValues); - ULONG ulLen, i, iter; + ULONG ulLen, i; + int iter; TRACE("(%d,%p,%p,%p)\n", cValues, lpProps, lpDst, lpCount); @@ -930,7 +931,8 @@ static const BOOL bBadPtr = TRUE; /* Windows bug - Assumes source is bad */ LPSPropValue lpDest = (LPSPropValue)lpProps; ULONG ulCount = cValues * sizeof(SPropValue); - ULONG ulLen, i, iter; + ULONG ulLen, i; + int iter; TRACE("(%d,%p,%p,%p,%p)\n", cValues, lpProps, lpOld, lpNew, lpCount); @@ -1520,7 +1522,7 @@ { IPropDataImpl *This = (IPropDataImpl*)iface; - TRACE("(%p)->(count=%ld)\n", This, This->lRef); + TRACE("(%p)->(count before=%lu)\n", This, This->lRef); return InterlockedIncrement(&This->lRef); } @@ -1534,10 +1536,12 @@ static inline ULONG WINAPI IMAPIProp_fnRelease(LPMAPIPROP iface) { IPropDataImpl *This = (IPropDataImpl*)iface; + LONG lRef; - TRACE("(%p)->()\n", This); + TRACE("(%p)->(count before=%lu)\n", This, This->lRef); - if (!InterlockedDecrement(&This->lRef)) + lRef = InterlockedDecrement(&This->lRef); + if (!lRef) { TRACE("Destroying IPropData (%p)\n",This); @@ -1552,9 +1556,8 @@ } RtlDeleteCriticalSection(&This->cs); This->lpFree(This); - return 0U; } - return (ULONG)This->lRef; + return (ULONG)lRef; } /************************************************************************** diff -urN wine-20050211/dlls/mlang/tests/mlang.c wine-20050310/dlls/mlang/tests/mlang.c --- wine-20050211/dlls/mlang/tests/mlang.c 2004-09-02 22:09:37.000000000 +0200 +++ wine-20050310/dlls/mlang/tests/mlang.c 2005-02-14 22:04:45.000000000 +0100 @@ -51,7 +51,7 @@ WCHAR stringW[] = {'J','u','s','t',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0}; char bufA[256]; WCHAR bufW[256]; - UINT lenA, lenW, expected_len; + int lenA, lenW, expected_len; HRESULT ret; HMODULE hMlang; FARPROC pConvertINetMultiByteToUnicode; @@ -105,7 +105,7 @@ ret = IMultiLanguage2_ConvertStringToUnicode(iML2, NULL, CP_UNICODE, stringA, &lenA, bufW, &lenW); ok(ret == S_OK, "IMultiLanguage2_ConvertStringToUnicode failed: %08lx\n", ret); ok(lenA == lstrlenA(stringA), "expected lenA %u, got %u\n", lstrlenA(stringA), lenA); - ok(lenW == lstrlenW(stringW)/sizeof(WCHAR), "expected lenW %u, got %u\n", lstrlenW(stringW)/sizeof(WCHAR), lenW); + ok(lenW == lstrlenW(stringW)/(int)sizeof(WCHAR), "expected lenW %u, got %u\n", lstrlenW(stringW)/sizeof(WCHAR), lenW); ok(bufW[lenW] != 0, "buf should not be 0 terminated\n"); bufW[lenW] = 0; /* -1 doesn't include 0 terminator */ ok(!lstrcmpA((LPCSTR)bufW, stringA), "bufW/stringA mismatch\n"); @@ -176,7 +176,7 @@ TRACE_2("Call IMultiLanguage2_ConvertStringFromUnicode\n"); ret = IMultiLanguage2_ConvertStringFromUnicode(iML2, NULL, CP_UNICODE, stringW, &lenW, bufA, &lenA); ok(ret == S_OK, "IMultiLanguage2_ConvertStringFromUnicode failed: %08lx\n", ret); - ok(lenA == lstrlenA(stringA) * sizeof(WCHAR), "expected lenA %u, got %u\n", lstrlenA(stringA) * sizeof(WCHAR), lenA); + ok(lenA == lstrlenA(stringA) * (int)sizeof(WCHAR), "expected lenA %u, got %u\n", lstrlenA(stringA) * sizeof(WCHAR), lenA); ok(lenW == lstrlenW(stringW), "expected lenW %u, got %u\n", lstrlenW(stringW), lenW); ok(bufA[lenA] != 0 && bufA[lenA+1] != 0, "buf should not be 0 terminated\n"); bufA[lenA] = 0; /* -1 doesn't include 0 terminator */ diff -urN wine-20050211/dlls/mpr/mpr_De.rc wine-20050310/dlls/mpr/mpr_De.rc --- wine-20050211/dlls/mpr/mpr_De.rc 2005-01-17 14:43:16.000000000 +0100 +++ wine-20050310/dlls/mpr/mpr_De.rc 2005-02-21 19:38:36.000000000 +0100 @@ -28,7 +28,7 @@ IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Netzwerkkennung eingeben" -FONT 8, "Helv" +FONT 8, "MS Shell Dlg" { LTEXT "Bitte geben Sie Benutzernamen und Kennwort ein:", IDC_EXPLAIN, 40, 6, 150, 15 LTEXT "Proxy", -1, 40, 26, 50, 10 diff -urN wine-20050211/dlls/mpr/mpr_En.rc wine-20050310/dlls/mpr/mpr_En.rc --- wine-20050211/dlls/mpr/mpr_En.rc 2005-01-10 15:27:29.000000000 +0100 +++ wine-20050310/dlls/mpr/mpr_En.rc 2005-02-21 19:38:36.000000000 +0100 @@ -28,7 +28,7 @@ IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Enter Network Password" -FONT 8, "Helv" +FONT 8, "MS Shell Dlg" { LTEXT "Please enter your username and password:", IDC_EXPLAIN, 40, 6, 150, 15 LTEXT "Proxy", -1, 40, 26, 50, 10 diff -urN wine-20050211/dlls/mpr/mpr_Es.rc wine-20050310/dlls/mpr/mpr_Es.rc --- wine-20050211/dlls/mpr/mpr_Es.rc 2004-07-04 02:07:57.000000000 +0200 +++ wine-20050310/dlls/mpr/mpr_Es.rc 2005-02-16 22:11:00.000000000 +0100 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff -urN wine-20050211/dlls/mpr/mpr_Fr.rc wine-20050310/dlls/mpr/mpr_Fr.rc --- wine-20050211/dlls/mpr/mpr_Fr.rc 2005-01-17 16:34:50.000000000 +0100 +++ wine-20050310/dlls/mpr/mpr_Fr.rc 2005-02-21 19:38:36.000000000 +0100 @@ -29,7 +29,7 @@ IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Entrez le mot de passe réseau" -FONT 8, "Helv" +FONT 8, "MS Shell Dlg" { LTEXT "Veuillez saisir votre nom d'utilisateur et votre mot de passe:", IDC_EXPLAIN, 40, 6, 150, 15 LTEXT "Proxy", -1, 40, 26, 50, 10 diff -urN wine-20050211/dlls/mpr/mpr_Pt.rc wine-20050310/dlls/mpr/mpr_Pt.rc --- wine-20050211/dlls/mpr/mpr_Pt.rc 2004-07-19 22:09:00.000000000 +0200 +++ wine-20050310/dlls/mpr/mpr_Pt.rc 2005-02-21 19:38:36.000000000 +0100 @@ -24,3 +24,23 @@ { IDS_ENTIRENETWORK "Toda a rede" } + +IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Entre a senha da rede" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Por favor, entre como o nome de usuário e a senha:", IDC_EXPLAIN, 40, 6, 150, 15 + LTEXT "Proxy", -1, 40, 26, 50, 10 +/* LTEXT "Realm", -1, 40, 46, 50, 10 */ + LTEXT "Usuário", -1, 40, 66, 50, 10 + LTEXT "Senha", -1, 40, 86, 50, 10 + LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 + LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 + EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD + CHECKBOX "&Salvar esta senha (Inseguro)", IDC_SAVEPASSWORD, + 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON + PUSHBUTTON "Cancelar", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} diff -urN wine-20050211/dlls/msacm/msacm_Es.rc wine-20050310/dlls/msacm/msacm_Es.rc --- wine-20050211/dlls/msacm/msacm_Es.rc 2004-04-06 05:24:20.000000000 +0200 +++ wine-20050310/dlls/msacm/msacm_Es.rc 2005-02-16 22:11:00.000000000 +0100 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL DLG_ACMFORMATCHOOSE_ID DIALOG DISCARDABLE 10, 20, 225, 100 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU diff -urN wine-20050211/dlls/mscms/Makefile.in wine-20050310/dlls/mscms/Makefile.in --- wine-20050211/dlls/mscms/Makefile.in 2004-12-20 18:04:11.000000000 +0100 +++ wine-20050310/dlls/mscms/Makefile.in 2005-02-21 19:38:15.000000000 +0100 @@ -10,7 +10,8 @@ icc.c \ mscms_main.c \ profile.c \ - stub.c + stub.c \ + transform.c RC_SRCS = version.rc diff -urN wine-20050211/dlls/mscms/handle.c wine-20050310/dlls/mscms/handle.c --- wine-20050211/dlls/mscms/handle.c 2004-11-30 22:06:14.000000000 +0100 +++ wine-20050310/dlls/mscms/handle.c 2005-02-21 19:38:15.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,19 +44,28 @@ /* A simple structure to tie together a pointer to an icc profile, an lcms * color profile handle and a Windows file handle. Windows color profile * handles are built from indexes into an array of these structures. If - * the profile is memory based the file handle field is NULL. + * the profile is memory based the file handle field is NULL. The 'access' + * field records the access parameter supplied to an OpenColorProfile() + * call, i.e. PROFILE_READ or PROFILE_READWRITE. */ -struct handlemap +struct profile { HANDLE file; + DWORD access; icProfile *iccprofile; cmsHPROFILE cmsprofile; }; +struct transform +{ + cmsHTRANSFORM cmstransform; +}; + #define CMSMAXHANDLES 0x80 -static struct handlemap handlemaptable[CMSMAXHANDLES]; +static struct profile profiletable[CMSMAXHANDLES]; +static struct transform transformtable[CMSMAXHANDLES]; HPROFILE MSCMS_handle2hprofile( HANDLE file ) { @@ -69,7 +78,7 @@ for (i = 0; i <= CMSMAXHANDLES; i++) { - if (handlemaptable[i].file == file) + if (profiletable[i].file == file) { profile = (HPROFILE)(i + 1); goto out; } @@ -77,7 +86,6 @@ out: LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; } @@ -89,13 +97,26 @@ EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - file = handlemaptable[i].file; + file = profiletable[i].file; LeaveCriticalSection( &MSCMS_handle_cs ); - return file; } +DWORD MSCMS_hprofile2access( HPROFILE profile ) +{ + DWORD access; + unsigned int i; + + EnterCriticalSection( &MSCMS_handle_cs ); + + i = (unsigned int)profile - 1; + access = profiletable[i].access; + + LeaveCriticalSection( &MSCMS_handle_cs ); + return access; +} + HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ) { HPROFILE profile = NULL; @@ -107,7 +128,7 @@ for (i = 0; i <= CMSMAXHANDLES; i++) { - if (handlemaptable[i].cmsprofile == cmsprofile) + if (profiletable[i].cmsprofile == cmsprofile) { profile = (HPROFILE)(i + 1); goto out; } @@ -115,23 +136,21 @@ out: LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; } cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ) { - cmsHPROFILE cmshprofile; + cmsHPROFILE cmsprofile; unsigned int i; EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - cmshprofile = handlemaptable[i].cmsprofile; + cmsprofile = profiletable[i].cmsprofile; LeaveCriticalSection( &MSCMS_handle_cs ); - - return cmshprofile; + return cmsprofile; } HPROFILE MSCMS_iccprofile2hprofile( icProfile *iccprofile ) @@ -145,7 +164,7 @@ for (i = 0; i <= CMSMAXHANDLES; i++) { - if (handlemaptable[i].iccprofile == iccprofile) + if (profiletable[i].iccprofile == iccprofile) { profile = (HPROFILE)(i + 1); goto out; } @@ -153,7 +172,6 @@ out: LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; } @@ -165,14 +183,14 @@ EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - iccprofile = handlemaptable[i].iccprofile; + iccprofile = profiletable[i].iccprofile; LeaveCriticalSection( &MSCMS_handle_cs ); - return iccprofile; } -HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, cmsHPROFILE cmsprofile ) +HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, + cmsHPROFILE cmsprofile, DWORD access ) { HPROFILE profile = NULL; unsigned int i; @@ -183,11 +201,12 @@ for (i = 0; i <= CMSMAXHANDLES; i++) { - if (handlemaptable[i].iccprofile == 0) + if (profiletable[i].iccprofile == 0) { - handlemaptable[i].file = file; - handlemaptable[i].iccprofile = iccprofile; - handlemaptable[i].cmsprofile = cmsprofile; + profiletable[i].file = file; + profiletable[i].access = access; + profiletable[i].iccprofile = iccprofile; + profiletable[i].cmsprofile = cmsprofile; profile = (HPROFILE)(i + 1); goto out; } @@ -195,7 +214,6 @@ out: LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; } @@ -208,7 +226,59 @@ EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - memset( &handlemaptable[i], 0, sizeof(struct handlemap) ); + memset( &profiletable[i], 0, sizeof(struct profile) ); + + LeaveCriticalSection( &MSCMS_handle_cs ); + } +} + +cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform ) +{ + cmsHTRANSFORM cmstransform; + unsigned int i; + + EnterCriticalSection( &MSCMS_handle_cs ); + + i = (unsigned int)transform - 1; + cmstransform = transformtable[i].cmstransform; + + LeaveCriticalSection( &MSCMS_handle_cs ); + return cmstransform; +} + +HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform ) +{ + HTRANSFORM transform = NULL; + unsigned int i; + + if (!cmstransform) return NULL; + + EnterCriticalSection( &MSCMS_handle_cs ); + + for (i = 0; i <= CMSMAXHANDLES; i++) + { + if (transformtable[i].cmstransform == 0) + { + transformtable[i].cmstransform = cmstransform; + transform = (HTRANSFORM)(i + 1); goto out; + } + } + +out: + LeaveCriticalSection( &MSCMS_handle_cs ); + return transform; +} + +void MSCMS_destroy_htransform_handle( HTRANSFORM transform ) +{ + unsigned int i; + + if (transform) + { + EnterCriticalSection( &MSCMS_handle_cs ); + + i = (unsigned int)transform - 1; + memset( &transformtable[i], 0, sizeof(struct transform) ); LeaveCriticalSection( &MSCMS_handle_cs ); } diff -urN wine-20050211/dlls/mscms/icc.c wine-20050310/dlls/mscms/icc.c --- wine-20050211/dlls/mscms/icc.c 2004-12-13 14:23:18.000000000 +0100 +++ wine-20050310/dlls/mscms/icc.c 2005-02-14 21:53:59.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -101,4 +101,12 @@ memcpy( (char *)iccprofile + tag->offset + offset, buffer, tag->size - offset ); } +DWORD MSCMS_get_profile_size( icProfile *iccprofile ) +{ + DWORD size = ((icHeader *)iccprofile)->size; + + MSCMS_adjust_endianess32( (ULONG *)&size ); + return size; +} + #endif /* HAVE_LCMS_H */ diff -urN wine-20050211/dlls/mscms/lcms_api.h wine-20050310/dlls/mscms/lcms_api.h --- wine-20050211/dlls/mscms/lcms_api.h 2004-11-21 16:48:18.000000000 +0100 +++ wine-20050310/dlls/mscms/lcms_api.h 2005-03-08 20:00:14.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,14 +27,20 @@ #ifdef HAVE_LCMS_H LCMS_API_FUNCTION(cmsCloseProfile) -LCMS_API_FUNCTION(cmsIsTag) -LCMS_API_FUNCTION(cmsOpenProfileFromFile) +LCMS_API_FUNCTION(cmsCreate_sRGBProfile) +LCMS_API_FUNCTION(cmsCreateMultiprofileTransform) +LCMS_API_FUNCTION(cmsCreateTransform) +LCMS_API_FUNCTION(cmsDeleteTransform) +LCMS_API_FUNCTION(cmsDoTransform) LCMS_API_FUNCTION(cmsOpenProfileFromMem) #ifndef LCMS_API_NO_REDEFINE #define cmsCloseProfile pcmsCloseProfile -#define cmsIsTag pcmsIsTag -#define cmsOpenProfileFromFile pcmsOpenProfileFromFile +#define cmsCreate_sRGBProfile pcmsCreate_sRGBProfile +#define cmsCreateMultiprofileTransform pcmsCreateMultiprofileTransform +#define cmsCreateTransform pcmsCreateTransform +#define cmsDeleteTransform pcmsDeleteTransform +#define cmsDoTransform pcmsDoTransform #define cmsOpenProfileFromMem pcmsOpenProfileFromMem #endif /* LCMS_API_NO_REDEFINE */ diff -urN wine-20050211/dlls/mscms/mscms.spec wine-20050310/dlls/mscms/mscms.spec --- wine-20050211/dlls/mscms/mscms.spec 2004-12-20 18:04:11.000000000 +0100 +++ wine-20050310/dlls/mscms/mscms.spec 2005-03-09 19:42:52.000000000 +0100 @@ -16,7 +16,7 @@ @ stdcall DisassociateColorProfileFromDeviceW(ptr ptr ptr) @ stdcall EnumColorProfilesA(ptr ptr ptr ptr ptr) @ stdcall EnumColorProfilesW(ptr ptr ptr ptr ptr) -@ stub GenerateCopyFilePaths +@ stdcall GenerateCopyFilePaths(wstr wstr ptr long ptr ptr ptr ptr long) @ stdcall GetCMMInfo(ptr long) @ stdcall GetColorDirectoryA(ptr ptr long) @ stdcall GetColorDirectoryW(ptr ptr long) @@ -52,7 +52,7 @@ @ stdcall SetColorProfileHeader(ptr ptr) @ stdcall SetStandardColorSpaceProfileA(ptr long ptr) @ stdcall SetStandardColorSpaceProfileW(ptr long ptr) -@ stub SpoolerCopyFileEvent +@ stdcall SpoolerCopyFileEvent(wstr wstr long) @ stdcall TranslateBitmapBits(ptr ptr long long long long ptr long long ptr long) @ stdcall TranslateColors(ptr ptr long long ptr long) @ stdcall UninstallColorProfileA(ptr ptr long) diff -urN wine-20050211/dlls/mscms/mscms_main.c wine-20050310/dlls/mscms/mscms_main.c --- wine-20050211/dlls/mscms/mscms_main.c 2004-11-21 16:48:18.000000000 +0100 +++ wine-20050310/dlls/mscms/mscms_main.c 2005-03-09 19:42:52.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -68,13 +68,16 @@ } } - #define LOAD_FUNCPTR(f) \ +#define LOAD_FUNCPTR(f) \ if ((p##f = wine_dlsym( lcmshandle, #f, NULL, 0 )) == NULL) \ goto sym_not_found; LOAD_FUNCPTR(cmsCloseProfile); - LOAD_FUNCPTR(cmsIsTag); - LOAD_FUNCPTR(cmsOpenProfileFromFile); + LOAD_FUNCPTR(cmsCreate_sRGBProfile); + LOAD_FUNCPTR(cmsCreateMultiprofileTransform); + LOAD_FUNCPTR(cmsCreateTransform); + LOAD_FUNCPTR(cmsDeleteTransform); + LOAD_FUNCPTR(cmsDoTransform); LOAD_FUNCPTR(cmsOpenProfileFromMem); #undef LOAD_FUNCPTR @@ -122,12 +125,12 @@ switch (reason) { case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hinst ); return MSCMS_init_lcms(); case DLL_PROCESS_DETACH: MSCMS_deinit_lcms(); break; } - return TRUE; } diff -urN wine-20050211/dlls/mscms/mscms_priv.h wine-20050310/dlls/mscms/mscms_priv.h --- wine-20050211/dlls/mscms/mscms_priv.h 2004-12-13 14:23:18.000000000 +0100 +++ wine-20050310/dlls/mscms/mscms_priv.h 2005-02-21 19:38:15.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -68,6 +68,7 @@ #define DWORD DWORD #define LPDWORD LPDWORD +extern DWORD MSCMS_hprofile2access( HPROFILE ); extern HPROFILE MSCMS_handle2hprofile( HANDLE file ); extern HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ); extern HPROFILE MSCMS_iccprofile2hprofile( icProfile *iccprofile ); @@ -75,14 +76,20 @@ extern cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ); extern icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile ); -extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, cmsHPROFILE cmsprofile ); +extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, + cmsHPROFILE cmsprofile, DWORD access ); extern void MSCMS_destroy_hprofile_handle( HPROFILE profile ); +extern cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform ); +extern HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform ); +extern void MSCMS_destroy_htransform_handle( HTRANSFORM transform ); + extern DWORD MSCMS_get_tag_count( icProfile *iccprofile ); extern void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag ); extern void MSCMS_get_tag_data( icProfile *iccprofile, icTag *tag, DWORD offset, void *buffer ); extern void MSCMS_set_tag_data( icProfile *iccprofile, icTag *tag, DWORD offset, void *buffer ); extern void MSCMS_get_profile_header( icProfile *iccprofile, PROFILEHEADER *header ); extern void MSCMS_set_profile_header( icProfile *iccprofile, PROFILEHEADER *header ); +extern DWORD MSCMS_get_profile_size( icProfile *iccprofile ); #endif /* HAVE_LCMS_H */ diff -urN wine-20050211/dlls/mscms/profile.c wine-20050310/dlls/mscms/profile.c --- wine-20050211/dlls/mscms/profile.c 2004-12-20 18:04:11.000000000 +0100 +++ wine-20050310/dlls/mscms/profile.c 2005-03-09 19:42:52.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -340,6 +340,11 @@ return ret; } +/****************************************************************************** + * GetStandardColorSpaceProfileA [MSCMS.@] + * + * See GetStandardColorSpaceProfileW. + */ BOOL WINAPI GetStandardColorSpaceProfileA( PCSTR machine, DWORD id, PSTR profile, PDWORD size ) { INT len; @@ -378,6 +383,22 @@ return ret; } +/****************************************************************************** + * GetStandardColorSpaceProfileW [MSCMS.@] + * + * Retrieve the profile filename for a given standard color space id. + * + * PARAMS + * machine [I] Name of the machine for which to get the standard color space. + * Must be NULL, which indicates the local machine. + * id [I] Id of a standard color space. + * profile [O] Buffer to recieve the profile filename. + * size [I/O] Size of the filename buffer in bytes. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ BOOL WINAPI GetStandardColorSpaceProfileW( PCWSTR machine, DWORD id, PWSTR profile, PDWORD size ) { DWORD len; @@ -491,15 +512,29 @@ { BOOL ret = FALSE; #ifdef HAVE_LCMS_H - cmsHPROFILE cmsprofile = MSCMS_hprofile2cmsprofile( profile ); + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + DWORD i, count; + icTag tag; TRACE( "( %p, 0x%08lx, %p )\n", profile, type, present ); - if (!cmsprofile || !present) return FALSE; - ret = cmsIsTag( cmsprofile, type ); + if (!iccprofile || !present) return FALSE; + + count = MSCMS_get_tag_count( iccprofile ); + + for (i = 0; i < count; i++) + { + MSCMS_get_tag_by_index( iccprofile, i, &tag ); + + if (tag.sig == type) + { + *present = ret = TRUE; + break; + } + } #endif /* HAVE_LCMS_H */ - return *present = ret; + return ret; } /****************************************************************************** @@ -554,12 +589,14 @@ BOOL ret = FALSE; #ifdef HAVE_LCMS_H icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); - DWORD i, count; + DWORD i, count, access = MSCMS_hprofile2access( profile ); icTag tag; TRACE( "( %p, 0x%08lx, %ld, %p, %p )\n", profile, type, offset, size, buffer ); if (!iccprofile || !size || !buffer) return FALSE; + if (!(access & PROFILE_READWRITE)) return FALSE; + count = MSCMS_get_tag_count( iccprofile ); for (i = 0; i < count; i++) @@ -579,15 +616,30 @@ return ret; } +/****************************************************************************** + * SetColorProfileHeader [MSCMS.@] + * + * Set header data for a given profile. + * + * PARAMS + * profile [I] Handle to a color profile. + * header [I] Buffer holding the header data. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ BOOL WINAPI SetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) { BOOL ret = FALSE; #ifdef HAVE_LCMS_H icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + DWORD access = MSCMS_hprofile2access( profile ); TRACE( "( %p, %p )\n", profile, header ); if (!iccprofile || !header) return FALSE; + if (!(access & PROFILE_READWRITE)) return FALSE; MSCMS_set_profile_header( iccprofile, header ); return TRUE; @@ -596,20 +648,6 @@ return ret; } -BOOL WINAPI SetStandardColorSpaceProfileA( PCSTR machine, DWORD id, PSTR profile ) -{ - FIXME( "( 0x%08lx, %p ) stub\n", id, profile ); - - return TRUE; -} - -BOOL WINAPI SetStandardColorSpaceProfileW( PCWSTR machine, DWORD id, PWSTR profile ) -{ - FIXME( "( 0x%08lx, %p ) stub\n", id, profile ); - - return TRUE; -} - /****************************************************************************** * UninstallColorProfileA [MSCMS.@] * @@ -794,7 +832,7 @@ } if (cmsprofile) - return MSCMS_create_hprofile_handle( handle, iccprofile, cmsprofile ); + return MSCMS_create_hprofile_handle( handle, iccprofile, cmsprofile, access ); #endif /* HAVE_LCMS_H */ return NULL; @@ -815,15 +853,26 @@ BOOL WINAPI CloseColorProfile( HPROFILE profile ) { BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + HANDLE file = MSCMS_hprofile2handle( profile ); + DWORD access = MSCMS_hprofile2access( profile ); TRACE( "( %p )\n", profile ); -#ifdef HAVE_LCMS_H - ret = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) ); + if (file && (access & PROFILE_READWRITE)) + { + DWORD written, size = MSCMS_get_profile_size( iccprofile ); + + if (SetFilePointer( file, 0, NULL, FILE_BEGIN ) || + !WriteFile( file, iccprofile, size, &written, NULL ) || written != size) + ERR( "Unable to write color profile\n" ); + } + ret = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) ); HeapFree( GetProcessHeap(), 0, MSCMS_hprofile2iccprofile( profile ) ); - CloseHandle( MSCMS_hprofile2handle( profile ) ); + CloseHandle( MSCMS_hprofile2handle( profile ) ); MSCMS_destroy_hprofile_handle( profile ); #endif /* HAVE_LCMS_H */ diff -urN wine-20050211/dlls/mscms/stub.c wine-20050310/dlls/mscms/stub.c --- wine-20050211/dlls/mscms/stub.c 2004-12-20 18:04:11.000000000 +0100 +++ wine-20050310/dlls/mscms/stub.c 2005-03-09 19:42:52.000000000 +0100 @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -77,22 +77,6 @@ return FALSE; } -HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, HPROFILE target, - DWORD flags ) -{ - FIXME( "( %p, %p, %p, 0x%08lx ) stub\n", space, dest, target, flags ); - - return NULL; -} - -HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HPROFILE target, - DWORD flags ) -{ - FIXME( "( %p, %p, %p, 0x%08lx ) stub\n", space, dest, target, flags ); - - return NULL; -} - BOOL WINAPI CreateDeviceLinkProfile( PHPROFILE profiles, DWORD nprofiles, PDWORD intents, DWORD nintents, DWORD flags, PBYTE *data, DWORD index ) { @@ -102,15 +86,6 @@ return FALSE; } -HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles, PDWORD intents, - DWORD nintents, DWORD flags, DWORD index ) -{ - FIXME( "( %p, 0x%08lx, %p, 0x%08lx, 0x%08lx, 0x%08lx ) stub\n", - profiles, nprofiles, intents, nintents, flags, index ); - - return NULL; -} - BOOL WINAPI CreateProfileFromLogColorSpaceA( LPLOGCOLORSPACEA space, PBYTE *buffer ) { FIXME( "( %p, %p ) stub\n", space, buffer ); @@ -125,13 +100,6 @@ return FALSE; } -BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) -{ - FIXME( "( %p ) stub\n", transform ); - - return TRUE; -} - BOOL WINAPI DisassociateColorProfileFromDeviceA( PCSTR machine, PCSTR profile, PCSTR device ) { FIXME( "( %p, %p, %p ) stub\n", machine, profile, device ); @@ -162,6 +130,16 @@ return FALSE; } +DWORD WINAPI GenerateCopyFilePaths( LPCWSTR printer, LPCWSTR directory, LPBYTE clientinfo, + DWORD level, LPWSTR sourcedir, LPDWORD sourcedirsize, + LPWSTR targetdir, LPDWORD targetdirsize, DWORD flags ) +{ + FIXME( "( %s, %s, %p, 0x%08lx, %p, %p, %p, %p, 0x%08lx ) stub\n", + debugstr_w(printer), debugstr_w(directory), clientinfo, level, sourcedir, + sourcedirsize, targetdir, targetdirsize, flags ); + return ERROR_SUCCESS; +} + DWORD WINAPI GetCMMInfo( HTRANSFORM transform, DWORD info ) { FIXME( "( %p, 0x%08lx ) stub\n", transform, info ); @@ -234,16 +212,22 @@ return FALSE; } -BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT input, - DWORD width, DWORD height, DWORD inputstride, PVOID destbits, - BMFORMAT output, DWORD outputstride, PBMCALLBACKFN callback, - ULONG data ) -{ - FIXME( "( %p, %p, 0x%08x, 0x%08lx, 0x%08lx, 0x%08lx, %p, 0x%08x, 0x%08lx, %p, 0x%08lx ) stub\n", - transform, srcbits, input, width, height, inputstride, destbits, output, outputstride, - callback, data ); +BOOL WINAPI SetStandardColorSpaceProfileA( PCSTR machine, DWORD id, PSTR profile ) +{ + FIXME( "( 0x%08lx, %p ) stub\n", id, profile ); + return TRUE; +} + +BOOL WINAPI SetStandardColorSpaceProfileW( PCWSTR machine, DWORD id, PWSTR profile ) +{ + FIXME( "( 0x%08lx, %p ) stub\n", id, profile ); + return TRUE; +} - return FALSE; +BOOL WINAPI SpoolerCopyFileEvent( LPWSTR printer, LPWSTR key, DWORD event ) +{ + FIXME( "( %s, %s, 0x%08lx ) stub\n", debugstr_w(printer), debugstr_w(key), event ); + return TRUE; } BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR inputcolors, DWORD number, diff -urN wine-20050211/dlls/mscms/tests/profile.c wine-20050310/dlls/mscms/tests/profile.c --- wine-20050211/dlls/mscms/tests/profile.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050310/dlls/mscms/tests/profile.c 2005-02-14 21:53:59.000000000 +0100 @@ -1,7 +1,7 @@ /* * Tests for color profile functions * - * Copyright 2004 Hans Leidekker + * Copyright 2004, 2005 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -743,22 +743,19 @@ profile.pProfileData = testprofile; profile.cbDataSize = strlen(testprofile); + /* Parameter checks */ + handle = OpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING ); ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); - todo_wine - { ret = SetColorProfileElement( handle, tag, 0, &size, data ); ok( !ret, "SetColorProfileElement() succeeded (%ld)\n", GetLastError() ); - } CloseColorProfile( handle ); handle = OpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING ); ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); - /* Parameter checks */ - ret = SetColorProfileElement( NULL, 0, 0, NULL, NULL ); ok( !ret, "SetColorProfileElement() succeeded (%ld)\n", GetLastError() ); @@ -827,11 +824,8 @@ handle = OpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING ); ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); - todo_wine - { ret = SetColorProfileHeader( handle, &header ); ok( !ret, "SetColorProfileHeader() succeeded (%ld)\n", GetLastError() ); - } CloseColorProfile( handle ); diff -urN wine-20050211/dlls/mscms/transform.c wine-20050310/dlls/mscms/transform.c --- wine-20050211/dlls/mscms/transform.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/mscms/transform.c 2005-03-08 20:00:14.000000000 +0100 @@ -0,0 +1,161 @@ +/* + * MSCMS - Color Management System for Wine + * + * Copyright 2005 Hans Leidekker + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/debug.h" + +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "wingdi.h" +#include "winuser.h" +#include "icm.h" + +#define LCMS_API_FUNCTION(f) extern typeof(f) * p##f; +#include "lcms_api.h" +#undef LCMS_API_FUNCTION + +WINE_DEFAULT_DEBUG_CHANNEL(mscms); + +HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, + HPROFILE target, DWORD flags ) +{ + LOGCOLORSPACEW spaceW; + DWORD len; + + TRACE( "( %p, %p, %p, 0x%08lx )\n", space, dest, target, flags ); + + if (!space || !dest) return FALSE; + + memcpy( &spaceW, space, FIELD_OFFSET(LOGCOLORSPACEA, lcsFilename) ); + spaceW.lcsSize = sizeof(LOGCOLORSPACEW); + + len = MultiByteToWideChar( CP_ACP, 0, space->lcsFilename, -1, NULL, 0 ); + MultiByteToWideChar( CP_ACP, 0, space->lcsFilename, -1, spaceW.lcsFilename, len ); + + return CreateColorTransformW( &spaceW, dest, target, flags ); +} + +HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, + HPROFILE target, DWORD flags ) +{ + HTRANSFORM ret = NULL; +#ifdef HAVE_LCMS_H + cmsHTRANSFORM cmstransform; + cmsHPROFILE cmsprofiles[3]; + int intent; + + TRACE( "( %p, %p, %p, 0x%08lx )\n", space, dest, target, flags ); + + if (!space || !dest) return FALSE; + + intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent; + + cmsprofiles[0] = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */ + cmsprofiles[1] = MSCMS_hprofile2cmsprofile( dest ); + + if (target) + { + cmsprofiles[2] = MSCMS_hprofile2cmsprofile( target ); + cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, 3, TYPE_BGR_8, + TYPE_BGR_8, intent, 0 ); + } + else + { + cmstransform = cmsCreateTransform( cmsprofiles[0], TYPE_BGR_8, cmsprofiles[1], + TYPE_BGR_8, intent, 0 ); + } + ret = MSCMS_create_htransform_handle( cmstransform ); + +#endif /* HAVE_LCMS_H */ + return ret; +} + +HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles, + PDWORD intents, DWORD nintents, DWORD flags, DWORD cmm ) +{ + HTRANSFORM ret = NULL; +#ifdef HAVE_LCMS_H + cmsHPROFILE *cmsprofiles; + cmsHTRANSFORM cmstransform; + DWORD i; + + TRACE( "( %p, 0x%08lx, %p, 0x%08lx, 0x%08lx, 0x%08lx ) stub\n", + profiles, nprofiles, intents, nintents, flags, cmm ); + + if (!profiles || !intents) return NULL; + + cmsprofiles = HeapAlloc( GetProcessHeap(), 0, nprofiles * sizeof(cmsHPROFILE) ); + + if (cmsprofiles) + { + for (i = 0; i < nprofiles; i++) + cmsprofiles[i] = MSCMS_hprofile2cmsprofile( profiles[i] ); + } + + cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, TYPE_BGR_8, + TYPE_BGR_8, *intents, 0 ); + HeapFree( GetProcessHeap(), 0, cmsprofiles ); + ret = MSCMS_create_htransform_handle( cmstransform ); + +#endif /* HAVE_LCMS_H */ + return ret; +} + +BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + cmsHTRANSFORM cmstransform; + + TRACE( "( %p )\n", transform ); + + cmstransform = MSCMS_htransform2cmstransform( transform ); + cmsDeleteTransform( cmstransform ); + + MSCMS_destroy_htransform_handle( transform ); + ret = TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; +} + +BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT input, + DWORD width, DWORD height, DWORD inputstride, PVOID destbits, BMFORMAT output, + DWORD outputstride, PBMCALLBACKFN callback, ULONG data ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + cmsHTRANSFORM cmstransform; + + TRACE( "( %p, %p, 0x%08x, 0x%08lx, 0x%08lx, 0x%08lx, %p, 0x%08x, 0x%08lx, %p, 0x%08lx )\n", + transform, srcbits, input, width, height, inputstride, destbits, output, + outputstride, callback, data ); + + cmstransform = MSCMS_htransform2cmstransform( transform ); + + cmsDoTransform( cmstransform, srcbits, destbits, width * height ); + ret = TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; +} diff -urN wine-20050211/dlls/msdmo/dmort.c wine-20050310/dlls/msdmo/dmort.c --- wine-20050211/dlls/msdmo/dmort.c 2004-10-07 05:06:50.000000000 +0200 +++ wine-20050310/dlls/msdmo/dmort.c 2005-02-24 13:48:00.000000000 +0100 @@ -32,152 +32,173 @@ WINE_DEFAULT_DEBUG_CHANNEL(msdmo); /*********************************************************************** - * MoCreateMediaType (MSDMO.@) + * MoCreateMediaType (MSDMO.@) + * + * Allocate a new media type structure */ HRESULT WINAPI MoCreateMediaType(DMO_MEDIA_TYPE** ppmedia, DWORD cbFormat) { - HRESULT hr; + HRESULT r; - TRACE("(%p,%lu)\n", ppmedia, cbFormat); + TRACE("%p %lu\n", ppmedia, cbFormat); - if (ppmedia == NULL) - return E_POINTER; + if (!ppmedia) + return E_POINTER; - *ppmedia = CoTaskMemAlloc(sizeof(DMO_MEDIA_TYPE)); - if (*ppmedia == NULL) - return E_OUTOFMEMORY; + *ppmedia = CoTaskMemAlloc(sizeof(DMO_MEDIA_TYPE)); + if (!*ppmedia) + return E_OUTOFMEMORY; - hr = MoInitMediaType(*ppmedia, cbFormat); - if (FAILED(hr)) { - CoTaskMemFree(*ppmedia); - *ppmedia = NULL; - } + r = MoInitMediaType(*ppmedia, cbFormat); + if (FAILED(r)) + { + CoTaskMemFree(*ppmedia); + *ppmedia = NULL; + } - return hr; + return r; } /*********************************************************************** - * MoInitMediaType (MSDMO.@) + * MoInitMediaType (MSDMO.@) + * + * Initialize media type structure */ HRESULT WINAPI MoInitMediaType(DMO_MEDIA_TYPE* pmedia, DWORD cbFormat) { - TRACE("(%p,%lu)\n", pmedia,cbFormat); + TRACE("%p %lu\n", pmedia, cbFormat); - if (pmedia == NULL) - return E_POINTER; + if (!pmedia) + return E_POINTER; - memset(pmedia, 0, sizeof(DMO_MEDIA_TYPE)); + memset(pmedia, 0, sizeof(DMO_MEDIA_TYPE)); - if (cbFormat > 0) { - pmedia->pbFormat = CoTaskMemAlloc(cbFormat); - if (pmedia->pbFormat == NULL) - return E_OUTOFMEMORY; + if (cbFormat > 0) + { + pmedia->pbFormat = CoTaskMemAlloc(cbFormat); + if (!pmedia->pbFormat) + return E_OUTOFMEMORY; - pmedia->cbFormat = cbFormat; - } + pmedia->cbFormat = cbFormat; + } - return S_OK; + return S_OK; } /*********************************************************************** - * MoDeleteMediaType (MSDMO.@) + * MoDeleteMediaType (MSDMO.@) + * + * Delete a media type structure */ HRESULT WINAPI MoDeleteMediaType(DMO_MEDIA_TYPE* pmedia) { - TRACE("(%p)\n", pmedia); + TRACE("%p\n", pmedia); - if (pmedia == NULL) - return E_POINTER; + if (!pmedia) + return E_POINTER; - MoFreeMediaType(pmedia); - CoTaskMemFree(pmedia); + MoFreeMediaType(pmedia); + CoTaskMemFree(pmedia); - return S_OK; + return S_OK; } /*********************************************************************** - * MoFreeMediaType (MSDMO.@) + * MoFreeMediaType (MSDMO.@) + * + * Free allocated members of a media type structure */ HRESULT WINAPI MoFreeMediaType(DMO_MEDIA_TYPE* pmedia) { - TRACE("(%p)\n", pmedia); + TRACE("%p\n", pmedia); - if (pmedia == NULL) - return E_POINTER; + if (!pmedia) + return E_POINTER; - if (pmedia->pUnk != NULL) { - IUnknown_Release(pmedia->pUnk); - pmedia->pUnk = NULL; - } + if (pmedia->pUnk) + { + IUnknown_Release(pmedia->pUnk); + pmedia->pUnk = NULL; + } - if (pmedia->pbFormat != NULL) { - CoTaskMemFree(pmedia->pbFormat); - pmedia->pbFormat = NULL; - } + if (pmedia->pbFormat) + { + CoTaskMemFree(pmedia->pbFormat); + pmedia->pbFormat = NULL; + } - return S_OK; + return S_OK; } /*********************************************************************** - * MoDuplicateMediaType (MSDMO.@) + * MoDuplicateMediaType (MSDMO.@) + * + * Duplicates a media type structure */ HRESULT WINAPI MoDuplicateMediaType(DMO_MEDIA_TYPE** ppdst, - const DMO_MEDIA_TYPE* psrc) + const DMO_MEDIA_TYPE* psrc) { - HRESULT hr; + HRESULT r; - TRACE("(%p,%p)\n", ppdst, psrc); + TRACE("%p %p\n", ppdst, psrc); - if (ppdst == NULL || psrc == NULL) - return E_POINTER; + if (!ppdst || !psrc) + return E_POINTER; - *ppdst = CoTaskMemAlloc(sizeof(DMO_MEDIA_TYPE)); - if (*ppdst == NULL) - return E_OUTOFMEMORY; + *ppdst = CoTaskMemAlloc(sizeof(DMO_MEDIA_TYPE)); + if (!*ppdst) + return E_OUTOFMEMORY; - hr = MoCopyMediaType(*ppdst, psrc); - if (FAILED(hr)) { - MoFreeMediaType(*ppdst); - *ppdst = NULL; - } + r = MoCopyMediaType(*ppdst, psrc); + if (FAILED(r)) + { + MoFreeMediaType(*ppdst); + *ppdst = NULL; + } - return hr; + return r; } /*********************************************************************** - * MoCopyMediaType (MSDMO.@) + * MoCopyMediaType (MSDMO.@) + * + * Copy a new media type structure */ HRESULT WINAPI MoCopyMediaType(DMO_MEDIA_TYPE* pdst, - const DMO_MEDIA_TYPE* psrc) + const DMO_MEDIA_TYPE* psrc) { - TRACE("(%p,%p)\n", pdst, psrc); + TRACE("%p %p\n", pdst, psrc); - if (pdst == NULL || psrc == NULL) - return E_POINTER; + if (!pdst || !psrc) + return E_POINTER; - memcpy(&pdst->majortype, &psrc->majortype, sizeof(psrc->majortype)); - memcpy(&pdst->subtype, &psrc->subtype, sizeof(psrc->subtype)); - memcpy(&pdst->formattype, &psrc->formattype, sizeof(psrc->formattype)); - - pdst->bFixedSizeSamples = psrc->bFixedSizeSamples; - pdst->bTemporalCompression = psrc->bTemporalCompression; - pdst->lSampleSize = psrc->lSampleSize; - pdst->cbFormat = psrc->cbFormat; - - if (psrc->pbFormat != NULL && psrc->cbFormat > 0) { - pdst->pbFormat = CoTaskMemAlloc(psrc->cbFormat); - if (pdst->pbFormat == NULL) - return E_OUTOFMEMORY; - - memcpy(pdst->pbFormat, psrc->pbFormat, psrc->cbFormat); - } else - pdst->pbFormat = NULL; - - if (psrc->pUnk != NULL) { - pdst->pUnk = psrc->pUnk; - IUnknown_AddRef(pdst->pUnk); - } else - pdst->pUnk = NULL; + memcpy(&pdst->majortype, &psrc->majortype, sizeof(psrc->majortype)); + memcpy(&pdst->subtype, &psrc->subtype, sizeof(psrc->subtype)); + memcpy(&pdst->formattype, &psrc->formattype, sizeof(psrc->formattype)); + + pdst->bFixedSizeSamples = psrc->bFixedSizeSamples; + pdst->bTemporalCompression = psrc->bTemporalCompression; + pdst->lSampleSize = psrc->lSampleSize; + pdst->cbFormat = psrc->cbFormat; + + if (psrc->pbFormat && psrc->cbFormat > 0) + { + pdst->pbFormat = CoTaskMemAlloc(psrc->cbFormat); + if (!pdst->pbFormat) + return E_OUTOFMEMORY; + + memcpy(pdst->pbFormat, psrc->pbFormat, psrc->cbFormat); + } + else + pdst->pbFormat = NULL; + + if (psrc->pUnk) + { + pdst->pUnk = psrc->pUnk; + IUnknown_AddRef(pdst->pUnk); + } + else + pdst->pUnk = NULL; - return S_OK; + return S_OK; } diff -urN wine-20050211/dlls/msi/Makefile.in wine-20050310/dlls/msi/Makefile.in --- wine-20050211/dlls/msi/Makefile.in 2005-02-08 13:12:29.000000000 +0100 +++ wine-20050310/dlls/msi/Makefile.in 2005-02-14 12:07:13.000000000 +0100 @@ -11,6 +11,7 @@ appsearch.c \ create.c \ custom.c \ + delete.c \ dialog.c \ distinct.c \ format.c \ diff -urN wine-20050211/dlls/msi/action.c wine-20050310/dlls/msi/action.c --- wine-20050211/dlls/msi/action.c 2005-02-10 18:09:44.000000000 +0100 +++ wine-20050310/dlls/msi/action.c 2005-03-10 12:15:40.000000000 +0100 @@ -39,6 +39,7 @@ #include "fdi.h" #include "msi.h" #include "msiquery.h" +#include "msidefs.h" #include "msvcrt/fcntl.h" #include "objbase.h" #include "objidl.h" @@ -96,6 +97,8 @@ static UINT ACTION_InstallFinalize(MSIPACKAGE *package); static UINT ACTION_ForceReboot(MSIPACKAGE *package); static UINT ACTION_ResolveSource(MSIPACKAGE *package); +static UINT ACTION_ExecuteAction(MSIPACKAGE *package); +static UINT ACTION_RegisterFonts(MSIPACKAGE *package); /* @@ -106,168 +109,188 @@ static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0}; static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0}; static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0}; -static const WCHAR c_collen[] = {'C',':','\\',0}; - +static const WCHAR c_colon[] = {'C',':','\\',0}; +static const WCHAR szProductCode[]= + {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR cszbs[]={'\\',0}; - const static WCHAR szCreateFolders[] = -{'C','r','e','a','t','e','F','o','l','d','e','r','s',0}; + {'C','r','e','a','t','e','F','o','l','d','e','r','s',0}; const static WCHAR szCostFinalize[] = -{'C','o','s','t','F','i','n','a','l','i','z','e',0}; + {'C','o','s','t','F','i','n','a','l','i','z','e',0}; const static WCHAR szInstallFiles[] = -{'I','n','s','t','a','l','l','F','i','l','e','s',0}; + {'I','n','s','t','a','l','l','F','i','l','e','s',0}; const static WCHAR szDuplicateFiles[] = -{'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0}; + {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0}; const static WCHAR szWriteRegistryValues[] = -{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0}; + {'W','r','i','t','e','R','e','g','i','s','t','r','y', + 'V','a','l','u','e','s',0}; const static WCHAR szCostInitialize[] = -{'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0}; + {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0}; const static WCHAR szFileCost[] = -{'F','i','l','e','C','o','s','t',0}; + {'F','i','l','e','C','o','s','t',0}; const static WCHAR szInstallInitialize[] = -{'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0}; + {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0}; const static WCHAR szInstallValidate[] = -{'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0}; + {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0}; const static WCHAR szLaunchConditions[] = -{'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0}; + {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0}; const static WCHAR szProcessComponents[] = -{'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0}; + {'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0}; const static WCHAR szRegisterTypeLibraries[] = -{'R','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r', -'i','e','s',0}; + {'R','e','g','i','s','t','e','r','T','y','p','e', + 'L','i','b','r','a','r','i','e','s',0}; const static WCHAR szRegisterClassInfo[] = -{'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0}; + {'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0}; const static WCHAR szRegisterProgIdInfo[] = -{'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0}; + {'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0}; const static WCHAR szCreateShortcuts[] = -{'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0}; + {'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0}; const static WCHAR szPublishProduct[] = -{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0}; + {'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0}; const static WCHAR szWriteIniValues[] = -{'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0}; + {'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0}; const static WCHAR szSelfRegModules[] = -{'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0}; + {'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0}; const static WCHAR szPublishFeatures[] = -{'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0}; + {'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0}; const static WCHAR szRegisterProduct[] = -{'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0}; + {'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0}; const static WCHAR szInstallExecute[] = -{'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0}; + {'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0}; const static WCHAR szInstallExecuteAgain[] = -{'I','n','s','t','a','l','l','E','x','e','c','u','t','e','A','g','a','i','n',0}; + {'I','n','s','t','a','l','l','E','x','e','c','u','t','e', + 'A','g','a','i','n',0}; const static WCHAR szInstallFinalize[] = -{'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0}; + {'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0}; const static WCHAR szForceReboot[] = -{'F','o','r','c','e','R','e','b','o','o','t',0}; + {'F','o','r','c','e','R','e','b','o','o','t',0}; const static WCHAR szResolveSource[] = -{'R','e','s','o','l','v','e','S','o','u','r','c','e',0}; + {'R','e','s','o','l','v','e','S','o','u','r','c','e',0}; const static WCHAR szAppSearch[] = -{'A','p','p','S','e','a','r','c','h',0}; + {'A','p','p','S','e','a','r','c','h',0}; const static WCHAR szAllocateRegistrySpace[] = -{'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y','S','p','a','c','e',0}; + {'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y', + 'S','p','a','c','e',0}; const static WCHAR szBindImage[] = -{'B','i','n','d','I','m','a','g','e',0}; + {'B','i','n','d','I','m','a','g','e',0}; const static WCHAR szCCPSearch[] = -{'C','C','P','S','e','a','r','c','h',0}; + {'C','C','P','S','e','a','r','c','h',0}; const static WCHAR szDeleteServices[] = -{'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0}; + {'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0}; const static WCHAR szDisableRollback[] = -{'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0}; + {'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0}; const static WCHAR szExecuteAction[] = -{'E','x','e','c','u','t','e','A','c','t','i','o','n',0}; + {'E','x','e','c','u','t','e','A','c','t','i','o','n',0}; const static WCHAR szFindRelatedProducts[] = -{'F','i','n','d','R','e','l','a','t','e','d','P','r','o','d','u','c','t','s',0}; + {'F','i','n','d','R','e','l','a','t','e','d', + 'P','r','o','d','u','c','t','s',0}; const static WCHAR szInstallAdminPackage[] = -{'I','n','s','t','a','l','l','A','d','m','i','n','P','a','c','k','a','g','e',0}; + {'I','n','s','t','a','l','l','A','d','m','i','n', + 'P','a','c','k','a','g','e',0}; const static WCHAR szInstallSFPCatalogFile[] = -{'I','n','s','t','a','l','l','S','F','P','C','a','t','a','l','o','g','F','i','l','e',0}; + {'I','n','s','t','a','l','l','S','F','P','C','a','t','a','l','o','g', + 'F','i','l','e',0}; const static WCHAR szIsolateComponents[] = -{'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0}; + {'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0}; const static WCHAR szMigrateFeatureStates[] = -{'M','i','g','r','a','t','e','F','e','a','t','u','r','e','S','t','a','t','e','s',0}; + {'M','i','g','r','a','t','e','F','e','a','t','u','r','e', + 'S','t','a','t','e','s',0}; const static WCHAR szMoveFiles[] = -{'M','o','v','e','F','i','l','e','s',0}; + {'M','o','v','e','F','i','l','e','s',0}; const static WCHAR szMsiPublishAssemblies[] = -{'M','s','i','P','u','b','l','i','s','h','A','s','s','e','m','b','l','i','e','s',0}; + {'M','s','i','P','u','b','l','i','s','h', + 'A','s','s','e','m','b','l','i','e','s',0}; const static WCHAR szMsiUnpublishAssemblies[] = -{'M','s','i','U','n','p','u','b','l','i','s','h','A','s','s','e','m','b','l','i','e','s',0}; + {'M','s','i','U','n','p','u','b','l','i','s','h', + 'A','s','s','e','m','b','l','i','e','s',0}; const static WCHAR szInstallODBC[] = -{'I','n','s','t','a','l','l','O','D','B','C',0}; + {'I','n','s','t','a','l','l','O','D','B','C',0}; const static WCHAR szInstallServices[] = -{'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0}; + {'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0}; const static WCHAR szPatchFiles[] = -{'P','a','t','c','h','F','i','l','e','s',0}; + {'P','a','t','c','h','F','i','l','e','s',0}; const static WCHAR szPublishComponents[] = -{'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0}; + {'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0}; const static WCHAR szRegisterComPlus[] = -{'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0}; + {'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0}; const static WCHAR szRegisterExtensionInfo[] = -{'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n','I','n','f','o',0}; + {'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n', + 'I','n','f','o',0}; const static WCHAR szRegisterFonts[] = -{'R','e','g','i','s','t','e','r','F','o','n','t','s',0}; + {'R','e','g','i','s','t','e','r','F','o','n','t','s',0}; const static WCHAR szRegisterMIMEInfo[] = -{'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0}; + {'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0}; const static WCHAR szRegisterUser[] = -{'R','e','g','i','s','t','e','r','U','s','e','r',0}; + {'R','e','g','i','s','t','e','r','U','s','e','r',0}; const static WCHAR szRemoveDuplicateFiles[] = -{'R','e','m','o','v','e','D','u','p','l','i','c','a','t','e','F','i','l','e','s',0}; + {'R','e','m','o','v','e','D','u','p','l','i','c','a','t','e', + 'F','i','l','e','s',0}; const static WCHAR szRemoveEnvironmentStrings[] = -{'R','e','m','o','v','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0}; + {'R','e','m','o','v','e','E','n','v','i','r','o','n','m','e','n','t', + 'S','t','r','i','n','g','s',0}; const static WCHAR szRemoveExistingProducts[] = -{'R','e','m','o','v','e','E','x','i','s','t','i','n','g','P','r','o','d','u','c','t','s',0}; + {'R','e','m','o','v','e','E','x','i','s','t','i','n','g', + 'P','r','o','d','u','c','t','s',0}; const static WCHAR szRemoveFiles[] = -{'R','e','m','o','v','e','F','i','l','e','s',0}; + {'R','e','m','o','v','e','F','i','l','e','s',0}; const static WCHAR szRemoveFolders[] = -{'R','e','m','o','v','e','F','o','l','d','e','r','s',0}; + {'R','e','m','o','v','e','F','o','l','d','e','r','s',0}; const static WCHAR szRemoveIniValues[] = -{'R','e','m','o','v','e','I','n','i','V','a','l','u','e','s',0}; + {'R','e','m','o','v','e','I','n','i','V','a','l','u','e','s',0}; const static WCHAR szRemoveODBC[] = -{'R','e','m','o','v','e','O','D','B','C',0}; + {'R','e','m','o','v','e','O','D','B','C',0}; const static WCHAR szRemoveRegistryValues[] = -{'R','e','m','o','v','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0}; + {'R','e','m','o','v','e','R','e','g','i','s','t','r','y', + 'V','a','l','u','e','s',0}; const static WCHAR szRemoveShortcuts[] = -{'R','e','m','o','v','e','S','h','o','r','t','c','u','t','s',0}; + {'R','e','m','o','v','e','S','h','o','r','t','c','u','t','s',0}; const static WCHAR szRMCCPSearch[] = -{'R','M','C','C','P','S','e','a','r','c','h',0}; + {'R','M','C','C','P','S','e','a','r','c','h',0}; const static WCHAR szScheduleReboot[] = -{'S','c','h','e','d','u','l','e','R','e','b','o','o','t',0}; + {'S','c','h','e','d','u','l','e','R','e','b','o','o','t',0}; const static WCHAR szSelfUnregModules[] = -{'S','e','l','f','U','n','r','e','g','M','o','d','u','l','e','s',0}; + {'S','e','l','f','U','n','r','e','g','M','o','d','u','l','e','s',0}; const static WCHAR szSetODBCFolders[] = -{'S','e','t','O','D','B','C','F','o','l','d','e','r','s',0}; + {'S','e','t','O','D','B','C','F','o','l','d','e','r','s',0}; const static WCHAR szStartServices[] = -{'S','t','a','r','t','S','e','r','v','i','c','e','s',0}; + {'S','t','a','r','t','S','e','r','v','i','c','e','s',0}; const static WCHAR szStopServices[] = -{'S','t','o','p','S','e','r','v','i','c','e','s',0}; + {'S','t','o','p','S','e','r','v','i','c','e','s',0}; const static WCHAR szUnpublishComponents[] = -{'U','n','p','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0}; + {'U','n','p','u','b','l','i','s','h', + 'C','o','m','p','o','n','e','n','t','s',0}; const static WCHAR szUnpublishFeatures[] = -{'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0}; + {'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0}; const static WCHAR szUnregisterClassInfo[] = -{'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0}; + {'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s', + 'I','n','f','o',0}; const static WCHAR szUnregisterComPlus[] = -{'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0}; + {'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0}; const static WCHAR szUnregisterExtensionInfo[] = -{'U','n','r','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n','I','n','f','o',0}; + {'U','n','r','e','g','i','s','t','e','r', + 'E','x','t','e','n','s','i','o','n','I','n','f','o',0}; const static WCHAR szUnregisterFonts[] = -{'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0}; + {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0}; const static WCHAR szUnregisterMIMEInfo[] = -{'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0}; + {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0}; const static WCHAR szUnregisterProgIdInfo[] = -{'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0}; + {'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d', + 'I','n','f','o',0}; const static WCHAR szUnregisterTypeLibraries[] = -{'U','n','r','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r','i','e','s',0}; + {'U','n','r','e','g','i','s','t','e','r','T','y','p','e', + 'L','i','b','r','a','r','i','e','s',0}; const static WCHAR szValidateProductID[] = -{'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; + {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0}; const static WCHAR szWriteEnvironmentStrings[] = -{'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0}; + {'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t', + 'S','t','r','i','n','g','s',0}; struct _actions { LPCWSTR action; STANDARDACTIONHANDLER handler; }; -struct _actions StandardActions[] = { +static struct _actions StandardActions[] = { { szAllocateRegistrySpace, NULL}, { szAppSearch, ACTION_AppSearch }, { szBindImage, NULL}, @@ -278,8 +301,8 @@ { szCreateShortcuts, ACTION_CreateShortcuts }, { szDeleteServices, NULL}, { szDisableRollback, NULL}, - { szDuplicateFiles, ACTION_DuplicateFiles}, - { szExecuteAction, NULL}, + { szDuplicateFiles, ACTION_DuplicateFiles }, + { szExecuteAction, ACTION_ExecuteAction }, { szFileCost, ACTION_FileCost }, { szFindRelatedProducts, NULL}, { szForceReboot, ACTION_ForceReboot }, @@ -307,7 +330,7 @@ { szRegisterClassInfo, ACTION_RegisterClassInfo }, { szRegisterComPlus, NULL}, { szRegisterExtensionInfo, ACTION_RegisterExtensionInfo }, - { szRegisterFonts, NULL}, + { szRegisterFonts, ACTION_RegisterFonts }, { szRegisterMIMEInfo, ACTION_RegisterMIMEInfo }, { szRegisterProduct, ACTION_RegisterProduct }, { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo }, @@ -565,7 +588,9 @@ if (package->folders && package->loaded_folders > 0) HeapFree(GetProcessHeap(),0,package->folders); - /* no dynamic buffers in components */ + for (i = 0; i < package->loaded_components; i++) + HeapFree(GetProcessHeap(),0,package->components[i].FullKeypath); + if (package->components && package->loaded_components > 0) HeapFree(GetProcessHeap(),0,package->components); @@ -611,9 +636,9 @@ static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record) { static const WCHAR Query_t[] = -{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o', -'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=', -' ','\'','%','s','\'',0}; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'A','c','t','i','o', 'n','T','e','x','t',' ','W','H','E','R','E',' ', + 'A','c','t','i','o','n',' ','=', ' ','\'','%','s','\'',0}; WCHAR message[1024]; UINT rc; MSIQUERY * view; @@ -674,13 +699,14 @@ static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action) { static const WCHAR template_s[]= -{'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ','%','s','.',0}; + {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ', '%','s', + '.',0}; static const WCHAR format[] = -{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; + {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; static const WCHAR Query_t[] = -{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o', -'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=', -' ','\'','%','s','\'',0}; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'A','c','t','i','o', 'n','T','e','x','t',' ','W','H','E','R','E', ' ', + 'A','c','t','i','o','n',' ','=', ' ','\'','%','s','\'',0}; WCHAR message[1024]; WCHAR timet[0x100]; UINT rc; @@ -728,13 +754,14 @@ { MSIRECORD * row; static const WCHAR template_s[]= -{'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ','%','s', -'.',0}; + {'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ', + '%','s', '.',0}; static const WCHAR template_e[]= -{'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ','%','s', -'.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ','%','i','.',0}; + {'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ', + '%','s', '.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ', + '%','i','.',0}; static const WCHAR format[] = -{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; + {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; WCHAR message[1024]; WCHAR timet[0x100]; @@ -802,6 +829,30 @@ return dir; } +static BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, INT index, + INSTALLSTATE check ) +{ + if (package->components[index].Installed == check) + return FALSE; + + if (package->components[index].ActionRequest == check) + return TRUE; + else + return FALSE; +} + +static BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE* package, INT index, + INSTALLSTATE check ) +{ + if (package->features[index].Installed == check) + return FALSE; + + if (package->features[index].ActionRequest == check) + return TRUE; + else + return FALSE; +} + /**************************************************** * TOP level entry points @@ -818,6 +869,7 @@ static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0}; MSI_SetPropertyW(package, szAction, szInstall); + package->ExecuteSequenceRun = FALSE; if (szPackagePath) { @@ -949,13 +1001,11 @@ WCHAR buffer[0x100]; DWORD sz = 0x100; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ', - 'I','n','s','t','a','l','l','E','x','e','c','u','t','e', - 'S','e','q','u','e','n','c','e',' ', - 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', - '=',' ','%','i',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'I','n','s','t','a','l','l','E','x','e','c','u','t','e', + 'S','e','q','u','e','n','c','e',' ', 'W','H','E','R','E',' ', + 'S','e','q','u','e','n','c','e',' ', '=',' ','%','i',0}; rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq); @@ -1024,24 +1074,31 @@ { MSIQUERY * view; UINT rc; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ', - 'I','n','s','t','a','l','l','E','x','e','c','u','t','e', - 'S','e','q','u','e','n','c','e',' ', - 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', - '>',' ','%','i',' ','o','r','d','e','r',' ', - 'b','y',' ','S','e','q','u','e','n','c','e',0 }; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'I','n','s','t','a','l','l','E','x','e','c','u','t','e', + 'S','e','q','u','e','n','c','e',' ', 'W','H','E','R','E',' ', + 'S','e','q','u','e','n','c','e',' ', '>',' ','%','i',' ', + 'O','R','D','E','R',' ', 'B','Y',' ', + 'S','e','q','u','e','n','c','e',0 }; MSIRECORD * row = 0; - static const WCHAR IVQuery[] = { - 's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ', - 'f','r','o','m',' ','I','n','s','t','a','l','l', - 'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e',' ', - 'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ', - '`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`', - 0}; + static const WCHAR IVQuery[] = + {'S','E','L','E','C','T',' ','S','e','q','u','e','n','c','e',' ', + 'F','R','O','M',' ','I','n','s','t','a','l','l', + 'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e',' ', + 'W','H','E','R','E',' ','A','c','t','i','o','n',' ','=',' ','`', + 'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`', 0}; INT seq = 0; + + if (package->ExecuteSequenceRun) + { + TRACE("Execute Sequence already Run\n"); + return ERROR_SUCCESS; + } + + package->ExecuteSequenceRun = TRUE; + /* get the sequence number */ if (UIran) { @@ -1152,12 +1209,12 @@ { MSIQUERY * view; UINT rc; - static const WCHAR ExecSeqQuery [] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ','I','n','s','t','a','l','l', - 'U','I','S','e','q','u','e','n','c','e',' ', - 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', '>',' ','0',' ', - 'o','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e',0}; + static const WCHAR ExecSeqQuery [] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e', + ' ','W','H','E','R','E',' ', 'S','e','q','u','e','n','c','e',' ', + '>',' ','0',' ','O','R','D','E','R',' ','B','Y',' ', + 'S','e','q','u','e','n','c','e',0}; rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); @@ -1421,9 +1478,10 @@ */ static UINT ACTION_CreateFolders(MSIPACKAGE *package) { - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','D','i','r','e','c','t','o','r','y','_',' ', - 'f','r','o','m',' ','C','r','e','a','t','e','F','o','l','d','e','r',0 }; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','D','i','r','e','c','t','o','r','y','_', + ' ','F','R','O','M',' ', + 'C','r','e','a','t','e','F','o','l','d','e','r',0 }; UINT rc; MSIQUERY *view; MSIFOLDER *folder; @@ -1534,7 +1592,7 @@ sz = 96; MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz); - package->components[index].Installed = INSTALLSTATE_ABSENT; + package->components[index].Installed = INSTALLSTATE_UNKNOWN; package->components[index].Action = INSTALLSTATE_UNKNOWN; package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN; @@ -1547,13 +1605,15 @@ { int index = package->loaded_features; DWORD sz; - static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p', - 'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e', - 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e', - 'a','t','u','r','e','_','=','\'','%','s','\'',0}; - static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R', - 'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C', - 'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0}; + static const WCHAR Query1[] = + {'S','E','L','E','C','T',' ','C','o','m','p','o','n','e','n','t','_', + ' ','F','R','O','M',' ','F','e','a','t','u','r','e', + 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ', + 'F','e', 'a','t','u','r','e','_','=','\'','%','s','\'',0}; + static const WCHAR Query2[] = + {'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', + 'C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ', + 'C','o','m','p','o','n','e','n','t','=','\'','%','s','\'',0}; MSIQUERY * view; MSIQUERY * view2; MSIRECORD * row2; @@ -1599,7 +1659,7 @@ package->features[index].Attributes= MSI_RecordGetInteger(row,8); - package->features[index].Installed = INSTALLSTATE_ABSENT; + package->features[index].Installed = INSTALLSTATE_UNKNOWN; package->features[index].Action = INSTALLSTATE_UNKNOWN; package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN; @@ -1695,15 +1755,15 @@ MSIQUERY * view; MSIRECORD * row; UINT rc; - static const WCHAR Query_all[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','F','e','a','t','u','r','e',0}; - static const WCHAR szCosting[] = { - 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 }; + static const WCHAR Query_all[] = + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'F','e','a','t','u','r','e',0}; + static const WCHAR szCosting[] = + {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 }; static const WCHAR szZero[] = { '0', 0 }; MSI_SetPropertyW(package, szCosting, szZero); - MSI_SetPropertyW(package, cszRootDrive , c_collen); + MSI_SetPropertyW(package, cszRootDrive , c_colon); rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view); if (rc != ERROR_SUCCESS) @@ -1786,10 +1846,10 @@ MSIQUERY * view; MSIRECORD * row; UINT rc; - static const WCHAR Query[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','F','i','l','e',' ', - 'O','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e', 0}; + static const WCHAR Query[] = + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'F','i','l','e',' ', 'O','R','D','E','R',' ','B','Y',' ', + 'S','e','q','u','e','n','c','e', 0}; if (!package) return ERROR_INVALID_HANDLE; @@ -1824,15 +1884,15 @@ } static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) - { static const WCHAR Query[] = - {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c', - 't','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t', - 'o','r','y','`',' ','=',' ','`','%','s','`',0}; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'D','i','r','e','c', 't','o','r','y',' ','W','H','E','R','E',' ','`', + 'D','i','r','e','c','t', 'o','r','y','`',' ','=',' ','`','%','s','`', + 0}; UINT rc; MSIQUERY * view; - LPWSTR targetdir, parent, srcdir; + LPWSTR ptargetdir, targetdir, parent, srcdir; MSIRECORD * row = 0; INT index = -1; DWORD i; @@ -1883,7 +1943,7 @@ return -1; } - targetdir = load_dynamic_stringW(row,3); + ptargetdir = targetdir = load_dynamic_stringW(row,3); /* split src and target dir */ if (strchrW(targetdir,':')) @@ -1927,7 +1987,7 @@ package->folders[index].SourceDefault = dupstrW(srcdir); else if (targetdir) package->folders[index].SourceDefault = dupstrW(targetdir); - HeapFree(GetProcessHeap(), 0, targetdir); + HeapFree(GetProcessHeap(), 0, ptargetdir); parent = load_dynamic_stringW(row,2); if (parent) @@ -2069,6 +2129,46 @@ return path; } +/* scan for and update current install states */ +void ACTION_UpdateInstallStates(MSIPACKAGE *package) +{ + int i; + LPWSTR productcode; + + productcode = load_dynamic_property(package,szProductCode,NULL); + + for (i = 0; i < package->loaded_components; i++) + { + INSTALLSTATE res; + res = MsiGetComponentPathW(productcode, + package->components[i].ComponentId , NULL, NULL); + if (res < 0) + res = INSTALLSTATE_ABSENT; + package->components[i].Installed = res; + } + + for (i = 0; i < package->loaded_features; i++) + { + INSTALLSTATE res = -10; + int j; + for (j = 0; j < package->features[i].ComponentCount; j++) + { + MSICOMPONENT* component = &package->components[package->features[i]. + Components[j]]; + if (res == -10) + res = component->Installed; + else + { + if (res == component->Installed) + continue; + + if (res != component->Installed) + res = INSTALLSTATE_INCOMPLETE; + } + } + } +} + /* update compoennt state based on a feature change */ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) { @@ -2120,49 +2220,24 @@ } } -static UINT SetFeatureStates(MSIPACKAGE *package) +static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property, + INSTALLSTATE state) { - LPWSTR level; - INT install_level; - DWORD i; - INT j; - LPWSTR override = NULL; static const WCHAR all[]={'A','L','L',0}; - static const WCHAR szlevel[] = { - 'I','N','S','T','A','L','L','L','E','V','E','L',0}; - static const WCHAR szAddLocal[] = { - 'A','D','D','L','O','C','A','L',0}; - - /* I do not know if this is where it should happen.. but */ - - TRACE("Checking Install Level\n"); - - level = load_dynamic_property(package,szlevel,NULL); - if (level) - { - install_level = atoiW(level); - HeapFree(GetProcessHeap(), 0, level); - } - else - install_level = 1; + LPWSTR override = NULL; + INT i; + BOOL rc = FALSE; - /* ok hereis the rub - * ADDLOCAL and its friend OVERRIDE INSTALLLEVLE - * I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is - * itnored for all the features. seems strange, epsecially since it is not - * documented anywhere, but it is how it works. - */ - - override = load_dynamic_property(package,szAddLocal,NULL); - + override = load_dynamic_property(package, property, NULL); if (override) { + rc = TRUE; for(i = 0; i < package->loaded_features; i++) { if (strcmpiW(override,all)==0) { - package->features[i].ActionRequest= INSTALLSTATE_LOCAL; - package->features[i].Action = INSTALLSTATE_LOCAL; + package->features[i].ActionRequest= state; + package->features[i].Action = state; } else { @@ -2176,8 +2251,8 @@ || (!ptr2 && strcmpW(ptr,package->features[i].Feature)==0)) { - package->features[i].ActionRequest= INSTALLSTATE_LOCAL; - package->features[i].Action = INSTALLSTATE_LOCAL; + package->features[i].ActionRequest= state; + package->features[i].Action = state; break; } if (ptr2) @@ -2192,16 +2267,72 @@ } HeapFree(GetProcessHeap(),0,override); } + + return rc; +} + +static UINT SetFeatureStates(MSIPACKAGE *package) +{ + LPWSTR level; + INT install_level; + DWORD i; + INT j; + static const WCHAR szlevel[] = + {'I','N','S','T','A','L','L','L','E','V','E','L',0}; + static const WCHAR szAddLocal[] = + {'A','D','D','L','O','C','A','L',0}; + static const WCHAR szRemove[] = + {'R','E','M','O','V','E',0}; + BOOL override = FALSE; + + /* I do not know if this is where it should happen.. but */ + + TRACE("Checking Install Level\n"); + + level = load_dynamic_property(package,szlevel,NULL); + if (level) + { + install_level = atoiW(level); + HeapFree(GetProcessHeap(), 0, level); + } else + install_level = 1; + + /* ok hereis the _real_ rub + * all these activation/deactivation things happen in order and things + * later on the list override things earlier on the list. + * 1) INSTALLLEVEL processing + * 2) ADDLOCAL + * 3) REMOVE + * 4) ADDSOURCE + * 5) ADDDEFAULT + * 6) REINSTALL + * 7) COMPADDLOCAL + * 8) COMPADDSOURCE + * 9) FILEADDLOCAL + * 10) FILEADDSOURCE + * 11) FILEADDDEFAULT + * I have confirmed that if ADDLOCAL is stated then the INSTALLLEVEL is + * ignored for all the features. seems strange, especially since it is not + * documented anywhere, but it is how it works. + * + * I am still ignoring a lot of these. But that is ok for now, ADDLOCAL and + * REMOVE are the big ones, since we don't handle administrative installs + * yet anyway. + */ + override |= process_state_property(package,szAddLocal,INSTALLSTATE_LOCAL); + override |= process_state_property(package,szRemove,INSTALLSTATE_ABSENT); + + if (!override) { for(i = 0; i < package->loaded_features; i++) { - BOOL feature_state= ((package->features[i].Level > 0) && + BOOL feature_state = ((package->features[i].Level > 0) && (package->features[i].Level <= install_level)); if (feature_state) { - package->features[i].ActionRequest= INSTALLSTATE_LOCAL; + package->features[i].ActionRequest = INSTALLSTATE_LOCAL; package->features[i].Action = INSTALLSTATE_LOCAL; } } @@ -2225,15 +2356,24 @@ if (!component->Enabled) { - component->Action = INSTALLSTATE_ABSENT; - component->ActionRequest = INSTALLSTATE_ABSENT; + component->Action = INSTALLSTATE_UNKNOWN; + component->ActionRequest = INSTALLSTATE_UNKNOWN; } else { if (feature->Action == INSTALLSTATE_LOCAL) + { component->Action = INSTALLSTATE_LOCAL; - if (feature->ActionRequest == INSTALLSTATE_LOCAL) component->ActionRequest = INSTALLSTATE_LOCAL; + } + else if (feature->ActionRequest == INSTALLSTATE_ABSENT) + { + if (component->Action == INSTALLSTATE_UNKNOWN) + { + component->Action = INSTALLSTATE_ABSENT; + component->ActionRequest = INSTALLSTATE_ABSENT; + } + } } } } @@ -2259,16 +2399,16 @@ */ static UINT ACTION_CostFinalize(MSIPACKAGE *package) { - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ', - 'D','i','r','e','c','t','o','r','y',0}; - static const WCHAR ConditionQuery[] = { - 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ', - 'C','o','n','d','i','t','i','o','n',0}; - static const WCHAR szCosting[] = { - 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 }; - static const WCHAR szlevel[] = { - 'I','N','S','T','A','L','L','L','E','V','E','L',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'D','i','r','e','c','t','o','r','y',0}; + static const WCHAR ConditionQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'C','o','n','d','i','t','i','o','n',0}; + static const WCHAR szCosting[] = + {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 }; + static const WCHAR szlevel[] = + {'I','N','S','T','A','L','L','L','E','V','E','L',0}; static const WCHAR szOne[] = { '1', 0 }; UINT rc; MSIQUERY * view; @@ -2365,9 +2505,9 @@ UINT sz; LPVOID version; static const WCHAR name[] = - {'\\',0}; + {'\\',0}; static const WCHAR name_fmt[] = - {'%','u','.','%','u','.','%','u','.','%','u',0}; + {'%','u','.','%','u','.','%','u','.','%','u',0}; WCHAR filever[0x100]; VS_FIXEDFILEINFO *lpVer; @@ -2481,8 +2621,9 @@ else HeapFree(GetProcessHeap(),0,level); - return SetFeatureStates(package); + ACTION_UpdateInstallStates(package); + return SetFeatureStates(package); } /* @@ -2569,7 +2710,8 @@ dwCreateDisposition = CREATE_NEW; else if (oflag & _O_CREAT) dwCreateDisposition = CREATE_ALWAYS; - return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, dwCreateDisposition, 0, NULL); + return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, + dwCreateDisposition, 0, NULL); } static UINT cabinet_read(INT_PTR hf, void *pv, UINT cb) @@ -2735,11 +2877,12 @@ MSIQUERY * view; MSIRECORD * row = 0; static WCHAR source[MAX_PATH]; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ','M','e','d','i','a',' ', - 'w','h','e','r','e',' ','L','a','s','t','S','e','q','u','e','n','c','e',' ','>','=',' ','%','i',' ', - 'o','r','d','e','r',' ','b','y',' ','L','a','s','t','S','e','q','u','e','n','c','e',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'M','e','d','i','a',' ','W','H','E','R','E',' ', + 'L','a','s','t','S','e','q','u','e','n','c','e',' ','>','=',' ','%', + 'i',' ','O','R','D','E','R',' ','B','Y',' ', + 'L','a','s','t','S','e','q','u','e','n','c','e',0}; WCHAR Query[1024]; WCHAR cab[0x100]; DWORD sz=0x100; @@ -2867,8 +3010,9 @@ if (file->Temporary) continue; - if (package->components[file->ComponentIndex].ActionRequest != - INSTALLSTATE_LOCAL) + + if (!ACTION_VerifyComponentForAction(package, file->ComponentIndex, + INSTALLSTATE_LOCAL)) { ui_progress(package,2,file->FileSize,0,0); TRACE("File %s is not scheduled for install\n", @@ -2944,7 +3088,7 @@ } else if (rc == ERROR_FILE_NOT_FOUND) { - ERR("Source File Not Found! Continueing\n"); + ERR("Source File Not Found! Continuing\n"); rc = 0; } else @@ -2991,9 +3135,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ', - 'D','u','p','l','i','c','a','t','e','F','i','l','e',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'D','u','p','l','i','c','a','t','e','F','i','l','e',0}; if (!package) return ERROR_INVALID_HANDLE; @@ -3038,8 +3182,9 @@ } component_index = get_loaded_component(package,component); - if (package->components[component_index].ActionRequest != - INSTALLSTATE_LOCAL) + + if (!ACTION_VerifyComponentForAction(package, component_index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping copy due to disabled component\n"); @@ -3052,7 +3197,6 @@ } package->components[component_index].Action = INSTALLSTATE_LOCAL; - package->components[component_index].Installed = INSTALLSTATE_LOCAL; sz=0x100; rc = MSI_RecordGetStringW(row,3,file_key,&sz); @@ -3109,7 +3253,6 @@ } dest = build_directory_name(2, dest_path, dest_name); - HeapFree(GetProcessHeap(), 0, dest_path); TRACE("Duplicating file %s to %s\n",debugstr_w(file_source), debugstr_w(dest)); @@ -3120,11 +3263,12 @@ rc = ERROR_SUCCESS; if (rc != ERROR_SUCCESS) - ERR("Failed to copy file\n"); + ERR("Failed to copy file %s -> %s, last error %ld\n", debugstr_w(file_source), debugstr_w(dest_path), GetLastError()); FIXME("We should track these duplicate files as well\n"); msiobj_release(&row->hdr); + HeapFree(GetProcessHeap(),0,dest_path); HeapFree(GetProcessHeap(),0,dest); HeapFree(GetProcessHeap(),0,file_source); } @@ -3177,13 +3321,28 @@ else { LPWSTR deformated; + LPWSTR p; + DWORD d = 0; deformat_string(package, &value[1], &deformated); *type=REG_DWORD; *size = sizeof(DWORD); data = HeapAlloc(GetProcessHeap(),0,*size); - *(LPDWORD)data = atoiW(deformated); - TRACE("DWORD %i\n",*data); + p = deformated; + if (*p == '-') + p++; + while (*p) + { + if ( (*p < '0') || (*p > '9') ) + break; + d *= 10; + d += (*p - '0'); + p++; + } + if (deformated[0] == '-') + d = -d; + *(LPDWORD)data = d; + TRACE("DWORD %li\n",*(LPDWORD)data); HeapFree(GetProcessHeap(),0,deformated); } @@ -3220,9 +3379,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ','R','e','g','i','s','t','r','y',0 }; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'R','e','g','i','s','t','r','y',0 }; if (!package) return ERROR_INVALID_HANDLE; @@ -3245,14 +3404,16 @@ while (1) { static const WCHAR szHCR[] = -{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T','\\',0}; + {'H','K','E','Y','_','C','L','A','S','S','E','S','_', + 'R','O','O','T','\\',0}; static const WCHAR szHCU[] = -{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',0}; + {'H','K','E','Y','_','C','U','R','R','E','N','T','_', + 'U','S','E','R','\\',0}; static const WCHAR szHLM[] = -{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E', -'\\',0}; + {'H','K','E','Y','_','L','O','C','A','L','_', + 'M','A','C','H','I','N','E','\\',0}; static const WCHAR szHU[] = -{'H','K','E','Y','_','U','S','E','R','S','\\',0}; + {'H','K','E','Y','_','U','S','E','R','S','\\',0}; LPSTR value_data = NULL; HKEY root_key, hkey; @@ -3280,8 +3441,8 @@ component = load_dynamic_stringW(row, 6); component_index = get_loaded_component(package,component); - if (package->components[component_index].ActionRequest != - INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, component_index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping write due to disabled component\n"); msiobj_release(&row->hdr); @@ -3293,20 +3454,27 @@ } package->components[component_index].Action = INSTALLSTATE_LOCAL; - package->components[component_index].Installed = INSTALLSTATE_LOCAL; - /* null values have special meanings during uninstalls and such */ - - if(MSI_RecordIsNull(row,5)) + name = load_dynamic_stringW(row, 4); + if( MSI_RecordIsNull(row,5) && name ) { - msiobj_release(&row->hdr); - goto next; + /* null values can have special meanings */ + if (name[0]=='-' && name[1] == 0) + { + msiobj_release(&row->hdr); + goto next; + } + else if ((name[0]=='+' && name[1] == 0) || + (name[0] == '*' && name[1] == 0)) + { + HeapFree(GetProcessHeap(),0,name); + name = NULL; + } } root = MSI_RecordGetInteger(row,2); key = load_dynamic_stringW(row, 3); - name = load_dynamic_stringW(row, 4); /* get the root key */ switch (root) @@ -3351,29 +3519,33 @@ HeapFree(GetProcessHeap(),0,deformated); value = load_dynamic_stringW(row,5); - value_data = parse_value(package, value, &type, &size); + if (value) + value_data = parse_value(package, value, &type, &size); + else + { + value_data = NULL; + size = 0; + type = REG_SZ; + } deformat_string(package, name, &deformated); - if (value_data) - { - TRACE("Setting value %s\n",debugstr_w(deformated)); - RegSetValueExW(hkey, deformated, 0, type, value_data, size); + TRACE("Setting value %s\n",debugstr_w(deformated)); + RegSetValueExW(hkey, deformated, 0, type, value_data, size); - uirow = MSI_CreateRecord(3); - MSI_RecordSetStringW(uirow,2,deformated); - MSI_RecordSetStringW(uirow,1,uikey); + uirow = MSI_CreateRecord(3); + MSI_RecordSetStringW(uirow,2,deformated); + MSI_RecordSetStringW(uirow,1,uikey); - if (type == REG_SZ) - MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data); - else - MSI_RecordSetStringW(uirow,3,value); + if (type == REG_SZ) + MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data); + else + MSI_RecordSetStringW(uirow,3,value); - ui_actiondata(package,szWriteRegistryValues,uirow); - msiobj_release( &uirow->hdr ); + ui_actiondata(package,szWriteRegistryValues,uirow); + msiobj_release( &uirow->hdr ); - HeapFree(GetProcessHeap(),0,value_data); - } + HeapFree(GetProcessHeap(),0,value_data); HeapFree(GetProcessHeap(),0,value); HeapFree(GetProcessHeap(),0,deformated); @@ -3400,9 +3572,9 @@ { DWORD progress = 0; DWORD total = 0; - static const WCHAR q1[]={ - 'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','R','e','g','i','s','t','r','y',0}; + static const WCHAR q1[]= + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'R','e','g','i','s','t','r','y',0}; UINT rc; MSIQUERY * view; MSIRECORD * row = 0; @@ -3450,11 +3622,11 @@ UINT rc; MSIQUERY * view = NULL; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','L','a','u','n','c','h','C','o','n','d','i','t','i','o','n',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n',0}; static const WCHAR title[]= - {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0}; + {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0}; TRACE("Checking launch conditions\n"); @@ -3513,19 +3685,19 @@ LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL); return p; } - if (cmp->Attributes & 0x4) + if (cmp->Attributes & msidbComponentAttributesRegistryKeyPath) { MSIQUERY * view; MSIRECORD * row = 0; UINT rc,root,len; LPWSTR key,deformated,buffer,name,deformated_name; - static const WCHAR ExecSeqQuery[] = { - 's','e','l','e','c','t',' ','*',' ', - 'f','r','o','m',' ','R','e','g','i','s','t','r','y',' ', -'w','h','e','r','e',' ','R','e','g','i','s','t','r','y',' ','=',' ' -,'`','%','s','`',0 }; - static const WCHAR fmt[]={'%','0','2','i',':','%','s',0}; - static const WCHAR fmt2[]={'%','0','2','i',':','%','s','\\','%','s',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'R','e','g','i','s','t','r','y',' ','W','H','E','R','E',' ', + 'R','e','g','i','s','t','r','y',' ','=',' ' ,'`','%','s','`',0 }; + static const WCHAR fmt[]={'%','0','2','i',':','\\','%','s','\\',0}; + static const WCHAR fmt2[]= + {'%','0','2','i',':','\\','%','s','\\','%','s',0}; rc = MSI_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath); @@ -3554,7 +3726,7 @@ deformat_string(package, key , &deformated); deformat_string(package, name, &deformated_name); - len = strlenW(deformated) + 5; + len = strlenW(deformated) + 6; if (deformated_name) len+=strlenW(deformated_name); @@ -3575,7 +3747,7 @@ return buffer; } - else if (cmp->Attributes & 0x20) + else if (cmp->Attributes & msidbComponentAttributesODBCDataSource) { FIXME("UNIMPLEMENTED keypath as ODBC Source\n"); return NULL; @@ -3594,6 +3766,127 @@ return NULL; } +static HKEY openSharedDLLsKey() +{ + HKEY hkey=0; + static const WCHAR path[] = + {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'S','h','a','r','e','d','D','L','L','s',0}; + + RegCreateKeyW(HKEY_LOCAL_MACHINE,path,&hkey); + return hkey; +} + +static UINT ACTION_GetSharedDLLsCount(LPCWSTR dll) +{ + HKEY hkey; + DWORD count=0; + DWORD type; + DWORD sz = sizeof(count); + DWORD rc; + + hkey = openSharedDLLsKey(); + rc = RegQueryValueExW(hkey, dll, NULL, &type, (LPBYTE)&count, &sz); + if (rc != ERROR_SUCCESS) + count = 0; + RegCloseKey(hkey); + return count; +} + +static UINT ACTION_WriteSharedDLLsCount(LPCWSTR path, UINT count) +{ + HKEY hkey; + + hkey = openSharedDLLsKey(); + if (count > 0) + RegSetValueExW(hkey,path,0,REG_DWORD, + (LPBYTE)&count,sizeof(count)); + else + RegDeleteValueW(hkey,path); + RegCloseKey(hkey); + return count; +} + +/* + * Return TRUE if the count should be written out and FALSE if not + */ +static void ACTION_RefCountComponent( MSIPACKAGE* package, UINT index) +{ + INT count = 0; + BOOL write = FALSE; + INT j; + + /* only refcount DLLs */ + if (package->components[index].KeyPath[0]==0 || + package->components[index].Attributes & + msidbComponentAttributesRegistryKeyPath || + package->components[index].Attributes & + msidbComponentAttributesODBCDataSource) + write = FALSE; + else + { + count = ACTION_GetSharedDLLsCount(package->components[index]. + FullKeypath); + write = (count > 0); + + if (package->components[index].Attributes & + msidbComponentAttributesSharedDllRefCount) + write = TRUE; + } + + /* increment counts */ + for (j = 0; j < package->loaded_features; j++) + { + int i; + + if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_LOCAL)) + continue; + + for (i = 0; i < package->features[j].ComponentCount; i++) + { + if (package->features[j].Components[i] == index) + count++; + } + } + /* decrement counts */ + for (j = 0; j < package->loaded_features; j++) + { + int i; + if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_ABSENT)) + continue; + + for (i = 0; i < package->features[j].ComponentCount; i++) + { + if (package->features[j].Components[i] == index) + count--; + } + } + + /* ref count all the files in the component */ + if (write) + for (j = 0; j < package->loaded_files; j++) + { + if (package->files[j].Temporary) + continue; + if (package->files[j].ComponentIndex == index) + ACTION_WriteSharedDLLsCount(package->files[j].TargetPath,count); + } + + /* add a count for permenent */ + if (package->components[index].Attributes & + msidbComponentAttributesPermanent) + count ++; + + package->components[index].RefCount = count; + + if (write) + ACTION_WriteSharedDLLsCount(package->components[index].FullKeypath, + package->components[index].RefCount); +} + /* * Ok further analysis makes me think that this work is * actually done in the PublishComponents and PublishFeatures @@ -3609,8 +3902,6 @@ UINT rc; DWORD i; HKEY hkey=0,hkey2=0; - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; if (!package) return ERROR_INVALID_HANDLE; @@ -3640,21 +3931,71 @@ continue; keypath = resolve_keypath(package,i); - if (keypath) + package->components[i].FullKeypath = keypath; + + /* do the refcounting */ + ACTION_RefCountComponent( package, i); + + TRACE("Component %s, Keypath=%s, RefCount=%i\n", + debugstr_w(package->components[i].Component), + debugstr_w(package->components[i].FullKeypath), + package->components[i].RefCount); + /* + * Write the keypath out if the component is to be registered + * and delete the key if the component is to be deregistered + */ + if (ACTION_VerifyComponentForAction(package, i, + INSTALLSTATE_LOCAL)) { - RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath, - (strlenW(keypath)+1)*sizeof(WCHAR)); + if (keypath) + { + RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath, + (strlenW(keypath)+1)*sizeof(WCHAR)); + + if (package->components[i].Attributes & + msidbComponentAttributesPermanent) + { + static const WCHAR szPermKey[] = + { '0','0','0','0','0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0', '0','0','0','0','0', + '0','0','0','0','0','0','0','0',0}; + + RegSetValueExW(hkey2,szPermKey,0,REG_SZ, + (LPVOID)keypath, + (strlenW(keypath)+1)*sizeof(WCHAR)); + } + + RegCloseKey(hkey2); + + /* UI stuff */ + uirow = MSI_CreateRecord(3); + MSI_RecordSetStringW(uirow,1,productcode); + MSI_RecordSetStringW(uirow,2,package->components[i]. + ComponentId); + MSI_RecordSetStringW(uirow,3,keypath); + ui_actiondata(package,szProcessComponents,uirow); + msiobj_release( &uirow->hdr ); + } + } + else if (ACTION_VerifyComponentForAction(package, i, + INSTALLSTATE_ABSENT)) + { + DWORD res; + RegDeleteValueW(hkey2,squished_pc); + + /* if the key is empty delete it */ + res = RegEnumKeyExW(hkey2,0,NULL,0,0,NULL,0,NULL); RegCloseKey(hkey2); + if (res == ERROR_NO_MORE_ITEMS) + RegDeleteKeyW(hkey,squished_cc); /* UI stuff */ - uirow = MSI_CreateRecord(3); + uirow = MSI_CreateRecord(2); MSI_RecordSetStringW(uirow,1,productcode); MSI_RecordSetStringW(uirow,2,package->components[i]. - ComponentId); - MSI_RecordSetStringW(uirow,3,keypath); + ComponentId); ui_actiondata(package,szProcessComponents,uirow); msiobj_release( &uirow->hdr ); - HeapFree(GetProcessHeap(),0,keypath); } } } @@ -3675,9 +4016,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR Query[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','T','y','p','e','L','i','b',0}; + static const WCHAR Query[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'T','y','p','e','L','i','b',0}; ITypeLib *ptLib; HRESULT res; @@ -3719,7 +4060,8 @@ continue; } - if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping typelib reg due to disabled component\n"); msiobj_release(&row->hdr); @@ -3731,7 +4073,6 @@ } package->components[index].Action = INSTALLSTATE_LOCAL; - package->components[index].Installed = INSTALLSTATE_LOCAL; index = get_loaded_file(package,package->components[index].KeyPath); @@ -3790,8 +4131,9 @@ MSIQUERY * view; MSIRECORD * row = 0; static const WCHAR ExecSeqQuery[] = - {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I' - ,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0}; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'A','p','p','I' ,'d',' ','w','h','e','r','e',' ', + 'A','p','p','I','d','=','`','%','s','`',0}; HKEY hkey2,hkey3; LPWSTR buffer=0; @@ -3828,7 +4170,8 @@ LPWSTR deformated=0; UINT size; static const WCHAR szRemoteServerName[] = - {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0}; + {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e', + 0}; buffer = load_dynamic_stringW(row,2); size = deformat_string(package,buffer,&deformated); RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated, @@ -3851,7 +4194,8 @@ if (!MSI_RecordIsNull(row,4)) { static const WCHAR szService[] = - {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0}; + {'S','e','r','v','i','c','e', + 'P','a','r','a','m','e','t','e','r','s',0}; UINT size; buffer = load_dynamic_stringW(row,4); size = (strlenW(buffer)+1) * sizeof(WCHAR); @@ -3873,7 +4217,8 @@ if (!MSI_RecordIsNull(row,6)) { static const WCHAR szActivate[] = - {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0}; + {'A','c','t','i','v','a','t','e','A','s', + 'S','t','o','r','a','g','e',0}; static const WCHAR szY[] = {'Y',0}; if (MSI_RecordGetInteger(row,6)) @@ -3884,7 +4229,8 @@ { static const WCHAR szRunAs[] = {'R','u','n','A','s',0}; static const WCHAR szUser[] = - {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0}; + {'I','n','t','e','r','a','c','t','i','v','e',' ', + 'U','s','e','r',0}; if (MSI_RecordGetInteger(row,7)) RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34); @@ -3914,9 +4260,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','C','l','a','s','s',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'C','l','a','s','s',0}; static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 }; static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 }; static const WCHAR szAppID[] = { 'A','p','p','I','D',0 }; @@ -3973,7 +4319,8 @@ continue; } - if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping class reg due to disabled component\n"); msiobj_release(&row->hdr); @@ -3985,7 +4332,6 @@ } package->components[index].Action = INSTALLSTATE_LOCAL; - package->components[index].Installed = INSTALLSTATE_LOCAL; sz=0x100; MSI_RecordGetStringW(row,1,clsid,&sz); @@ -4063,7 +4409,7 @@ if (!MSI_RecordIsNull(row,8)) { static const WCHAR szDefaultIcon[] = - {'D','e','f','a','u','l','t','I','c','o','n',0}; + {'D','e','f','a','u','l','t','I','c','o','n',0}; LPWSTR FileName = load_dynamic_stringW(row,8); LPWSTR FilePath; @@ -4090,16 +4436,17 @@ if (!MSI_RecordIsNull(row,10)) { - static const WCHAR szInproc32[] = { - 'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0}; - static const WCHAR szInproc[] = { - 'I','n','p','r','o','c','H','a','n','d','l','e','r',0}; + static const WCHAR szInproc32[] = + {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2', + 0}; + static const WCHAR szInproc[] = + {'I','n','p','r','o','c','H','a','n','d','l','e','r',0}; INT i = MSI_RecordGetInteger(row,10); if (i != MSI_NULL_INTEGER && i > 0 && i < 4) { static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0}; - static const WCHAR ole32[] = { - 'o','l','e','3','2','.','d','l','l',0}; + static const WCHAR ole32[] = + {'o','l','e','3','2','.','d','l','l',0}; switch(i) { case 1: @@ -4159,8 +4506,8 @@ LPWSTR clsid) { static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 }; - static const WCHAR szDefaultIcon[] = { - 'D','e','f','a','u','l','t','I','c','o','n',0}; + static const WCHAR szDefaultIcon[] = + {'D','e','f','a','u','l','t','I','c','o','n',0}; HKEY hkey,hkey2; WCHAR buffer[0x100]; DWORD sz; @@ -4229,9 +4576,9 @@ MSIQUERY * view; MSIRECORD * row = 0; static const WCHAR Query_t[] = - {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g' - ,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`' - ,'%','s','`',0}; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'P','r','o','g' ,'I','d',' ','W','H','E','R','E',' ', + 'P','r','o','g','I','d',' ','=',' ','`' ,'%','s','`',0}; if (!package) return ERROR_INVALID_HANDLE; @@ -4276,8 +4623,8 @@ DWORD sz, disp; HKEY hkey,hkey2; static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 }; - static const WCHAR szDefaultIcon[] = { - 'D','e','f','a','u','l','t','I','c','o','n',0}; + static const WCHAR szDefaultIcon[] = + {'D','e','f','a','u','l','t','I','c','o','n',0}; /* check if already registered */ sz = 0x100; @@ -4342,9 +4689,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR Query[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'F','R','O','M',' ','P','r','o','g','I','d',0}; + static const WCHAR Query[] = + {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', + 'P','r','o','g','I','d',0}; if (!package) return ERROR_INVALID_HANDLE; @@ -4392,8 +4739,6 @@ static const WCHAR szInstaller[] = {'I','n','s','t','a','l','l','e','r','\\',0}; - static const WCHAR szProductCode[] = - {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szFolder[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; @@ -4420,9 +4765,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR Query[] = { - 'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ', - 'S','h','o','r','t','c','u','t',0}; + static const WCHAR Query[] = + {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ', + 'S','h','o','r','t','c','u','t',0}; IShellLinkW *sl; IPersistFile *pf; HRESULT res; @@ -4475,7 +4820,8 @@ continue; } - if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping shortcut creation due to disabled component\n"); msiobj_release(&row->hdr); @@ -4487,7 +4833,6 @@ } package->components[index].Action = INSTALLSTATE_LOCAL; - package->components[index].Installed = INSTALLSTATE_LOCAL; ui_actiondata(package,szCreateShortcuts,row); @@ -4535,11 +4880,11 @@ } else { - FIXME("UNHANDLED shortcut format, advertised shortcut\n"); - IPersistFile_Release( pf ); - IShellLinkW_Release( sl ); - msiobj_release(&row->hdr); - continue; + LPWSTR keypath; + FIXME("poorly handled shortcut format, advertised shortcut\n"); + keypath = dupstrW(package->components[index].FullKeypath); + IShellLinkW_SetPath(sl,keypath); + HeapFree(GetProcessHeap(),0,keypath); } if (!MSI_RecordIsNull(row,6)) @@ -4622,20 +4967,18 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR Query[]={ - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','I','c','o','n',0}; + static const WCHAR Query[]= + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'I','c','o','n',0}; DWORD sz; /* for registry stuff */ LPWSTR productcode; HKEY hkey=0; HKEY hukey=0; - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; - static const WCHAR szProductName[] = { - 'P','r','o','d','u','c','t','N','a','m','e',0}; - static const WCHAR szPackageCode[] = { - 'P','a','c','k','a','g','e','C','o','d','e',0}; + static const WCHAR szProductName[] = + {'P','r','o','d','u','c','t','N','a','m','e',0}; + static const WCHAR szPackageCode[] = + {'P','a','c','k','a','g','e','C','o','d','e',0}; LPWSTR buffer; DWORD size; MSIHANDLE hDb, hSumInfo; @@ -4738,13 +5081,14 @@ HeapFree(GetProcessHeap(),0,buffer); FIXME("Need to write more keys to the user registry\n"); - hDb= msiobj_findhandle( &package->db->hdr ); + hDb= alloc_msihandle( &package->db->hdr ); rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo); + MsiCloseHandle(hDb); if (rc == ERROR_SUCCESS) { WCHAR guidbuffer[0x200]; size = 0x200; - rc = MsiSummaryInfoGetPropertyW(hSumInfo, 8, NULL, NULL, NULL, + rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL, guidbuffer, &size); if (rc == ERROR_SUCCESS) { @@ -4753,10 +5097,9 @@ LPWSTR ptr = strchrW(guidbuffer,';'); if (ptr) *ptr = 0; squash_guid(guidbuffer,squashed); - size = strlenW(guidbuffer)*sizeof(WCHAR); - RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)guidbuffer, + size = strlenW(squashed)*sizeof(WCHAR); + RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)squashed, size); - } else { @@ -4785,8 +5128,9 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*', - ' ','f','r','o','m',' ','I','n','i','F','i','l','e',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'I','n','i','F','i','l','e',0}; static const WCHAR szWindowsFolder[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; @@ -4824,8 +5168,8 @@ component_index = get_loaded_component(package,component); HeapFree(GetProcessHeap(),0,component); - if (package->components[component_index].ActionRequest != - INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, component_index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping ini file due to disabled component\n"); msiobj_release(&row->hdr); @@ -4837,7 +5181,6 @@ } package->components[component_index].Action = INSTALLSTATE_LOCAL; - package->components[component_index].Installed = INSTALLSTATE_LOCAL; identifier = load_dynamic_stringW(row,1); filename = load_dynamic_stringW(row,2); @@ -4927,11 +5270,12 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',' ', -'f','r','o','m',' ','S','e','l','f','R','e','g',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'S','e','l','f','R','e','g',0}; - static const WCHAR ExeStr[] = { -'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','s',' ',0}; + static const WCHAR ExeStr[] = + {'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','s',' ',0}; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL brc; @@ -4988,7 +5332,7 @@ TRACE("Registering %s\n",debugstr_w(filename)); brc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); + c_colon, &si, &info); if (brc) msi_dialog_check_messages(package->dialog, info.hProcess); @@ -5008,8 +5352,6 @@ DWORD i; HKEY hkey=0; HKEY hukey=0; - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; if (!package) return ERROR_INVALID_HANDLE; @@ -5034,6 +5376,9 @@ int j; INT size; + if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL)) + continue; + size = package->features[i].ComponentCount*21; size +=1; if (package->features[i].Feature_Parent[0]) @@ -5081,8 +5426,6 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) { - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; HKEY hkey=0; LPWSTR buffer; LPWSTR productcode; @@ -5094,14 +5437,14 @@ static const WCHAR szPropKeys[][80] = { {'A','R','P','A','U','T','H','O','R','I','Z','E','D','C','D','F','P','R','E','F','I','X',0}, -{'A','R','P','C','O','N','T','A','C','T'}, +{'A','R','P','C','O','N','T','A','C','T',0}, {'A','R','P','C','O','M','M','E','N','T','S',0}, {'P','r','o','d','u','c','t','N','a','m','e',0}, {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}, {'A','R','P','H','E','L','P','L','I','N','K',0}, {'A','R','P','H','E','L','P','T','E','L','E','P','H','O','N','E',0}, {'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0}, -{'S','O','U','R','C','E','D','I','R',0}, +{'S','o','u','r','c','e','D','i','r',0}, {'M','a','n','u','f','a','c','t','u','r','e','r',0}, {'A','R','P','R','E','A','D','M','E',0}, {'A','R','P','S','I','Z','E',0}, @@ -5129,16 +5472,16 @@ {0}, }; - static const WCHAR path[] = { - 'C',':','\\','W','i','n','d','o','w','s','\\', - 'I','n','s','t','a','l','l','e','r','\\'}; + static const WCHAR installerPathFmt[] = { + '%','s','\\', + 'I','n','s','t','a','l','l','e','r','\\',0}; static const WCHAR fmt[] = { - 'C',':','\\','W','i','n','d','o','w','s','\\', + '%','s','\\', 'I','n','s','t','a','l','l','e','r','\\', '%','x','.','m','s','i',0}; static const WCHAR szLocalPackage[]= {'L','o','c','a','l','P','a','c','k','a','g','e',0}; - WCHAR packagefile[MAX_PATH]; + WCHAR windir[MAX_PATH], path[MAX_PATH], packagefile[MAX_PATH]; INT num,start; if (!package) @@ -5175,7 +5518,9 @@ if (!num) num = 1; start = num; - sprintfW(packagefile,fmt,num); + GetWindowsDirectoryW(windir, sizeof(windir) / sizeof(windir[0])); + snprintfW(packagefile,sizeof(packagefile)/sizeof(packagefile[0]),fmt, + windir,num); do { HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL, @@ -5192,6 +5537,7 @@ sprintfW(packagefile,fmt,num); } while (num != start); + snprintfW(path,sizeof(path)/sizeof(path[0]),installerPathFmt,windir); create_full_pathW(path); TRACE("Copying to local package %s\n",debugstr_w(packagefile)); CopyFileW(package->PackagePath,packagefile,FALSE); @@ -5262,31 +5608,29 @@ 'M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'R','u','n','O','n','c','e'}; + 'R','u','n','O','n','c','e',0}; static const WCHAR InstallRunOnce[] = { 'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'I','n','s','t','a','l','l','e','r','\\', - 'R','u','n','O','n','c','e','E','n','t','r','i','e','s'}; + 'R','u','n','O','n','c','e','E','n','t','r','i','e','s',0}; static const WCHAR msiexec_fmt[] = { - 'C',':','\\','W','i','n','d','o','w','s','\\','S','y','s','t','e','m', + '%','s', '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ', '\"','%','s','\"',0}; static const WCHAR install_fmt[] = { '/','I',' ','\"','%','s','\"',' ', 'A','F','T','E','R','R','E','B','O','O','T','=','1',' ', 'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0}; - WCHAR buffer[256]; + WCHAR buffer[256], sysdir[MAX_PATH]; HKEY hkey,hukey; LPWSTR productcode; WCHAR squished_pc[100]; INT rc; DWORD size; - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szLUS[] = { 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0}; static const WCHAR szSourceList[] = { @@ -5303,8 +5647,10 @@ squash_guid(productcode,squished_pc); + GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0])); RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey); - sprintfW(buffer,msiexec_fmt,squished_pc); + snprintfW(buffer,sizeof(buffer)/sizeof(buffer[0]),msiexec_fmt,sysdir, + squished_pc); size = strlenW(buffer)*sizeof(WCHAR); RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); @@ -5314,6 +5660,8 @@ RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey); sprintfW(buffer,install_fmt,productcode,squished_pc); + + size = strlenW(buffer)*sizeof(WCHAR); RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); RegCloseKey(hkey); @@ -5358,11 +5706,11 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','E','x','t','e','n','s','i','o','n',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'E','x','t','e','n','s','i','o','n',0}; static const WCHAR szContentType[] = -{ 'C','o','n','t','e','n','t',' ','T','y','p','e',0 }; + {'C','o','n','t','e','n','t',' ','T','y','p','e',0 }; HKEY hkey; if (!package) @@ -5409,7 +5757,8 @@ continue; } - if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) + if (!ACTION_VerifyComponentForAction(package, index, + INSTALLSTATE_LOCAL)) { TRACE("Skipping extension reg due to disabled component\n"); msiobj_release(&row->hdr); @@ -5421,7 +5770,6 @@ } package->components[index].Action = INSTALLSTATE_LOCAL; - package->components[index].Installed = INSTALLSTATE_LOCAL; exten = load_dynamic_stringW(row,1); extension[0] = '.'; @@ -5442,7 +5790,7 @@ if (!MSI_RecordIsNull(row,3)) { static const WCHAR szSN[] = - {'\\','S','h','e','l','l','N','e','w',0}; + {'\\','S','h','e','l','l','N','e','w',0}; HKEY hkey2; LPWSTR newkey; LPWSTR progid= load_dynamic_stringW(row,3); @@ -5481,11 +5829,11 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = { - 'S','E','L','E','C','T',' ','*',' ', - 'f','r','o','m',' ','M','I','M','E',0}; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'M','I','M','E',0}; static const WCHAR szExten[] = -{ 'E','x','t','e','n','s','i','o','n',0 }; + {'E','x','t','e','n','s','i','o','n',0 }; HKEY hkey; if (!package) @@ -5512,10 +5860,8 @@ LPWSTR exten; LPWSTR mime; static const WCHAR fmt[] = -{'M','I','M','E','\\', -'D','a','t','a','b','a','s','e','\\', -'C','o','n','t','e','n','t',' ','T','y','p','e','\\', -'%','s',0}; + {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\', + 'C','o','n','t','e','n','t',' ','T','y','p','e','\\', '%','s',0}; LPWSTR key; rc = MSI_ViewFetch(view,&row); @@ -5562,8 +5908,6 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package) { - static const WCHAR szProductCode[]= - {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szProductID[]= {'P','r','o','d','u','c','t','I','D',0}; HKEY hkey=0; @@ -5575,18 +5919,18 @@ static const WCHAR szPropKeys[][80] = { -{'P','r','o','d','u','c','t','I','D',0}, -{'U','S','E','R','N','A','M','E',0}, -{'C','O','M','P','A','N','Y','N','A','M','E',0}, -{0}, + {'P','r','o','d','u','c','t','I','D',0}, + {'U','S','E','R','N','A','M','E',0}, + {'C','O','M','P','A','N','Y','N','A','M','E',0}, + {0}, }; static const WCHAR szRegKeys[][80] = { -{'P','r','o','d','u','c','t','I','D',0}, -{'R','e','g','O','w','n','e','r',0}, -{'R','e','g','C','o','m','p','a','n','y',0}, -{0}, + {'P','r','o','d','u','c','t','I','D',0}, + {'R','e','g','O','w','n','e','r',0}, + {'R','e','g','C','o','m','p','a','n','y',0}, + {0}, }; if (!package) @@ -5624,6 +5968,245 @@ return ERROR_SUCCESS; } + +static UINT ACTION_ExecuteAction(MSIPACKAGE *package) +{ + UINT rc; + rc = ACTION_ProcessExecSequence(package,TRUE); + return rc; +} + + +/* + * Code based off of code located here + * http://www.codeproject.com/gdi/fontnamefromfile.asp + * + * Using string index 4 (full font name) instead of 1 (family name) + */ +static LPWSTR load_ttfname_from(LPCWSTR filename) +{ + HANDLE handle; + LPWSTR ret = NULL; + int i; + + typedef struct _tagTT_OFFSET_TABLE{ + USHORT uMajorVersion; + USHORT uMinorVersion; + USHORT uNumOfTables; + USHORT uSearchRange; + USHORT uEntrySelector; + USHORT uRangeShift; + }TT_OFFSET_TABLE; + + typedef struct _tagTT_TABLE_DIRECTORY{ + char szTag[4]; /* table name */ + ULONG uCheckSum; /* Check sum */ + ULONG uOffset; /* Offset from beginning of file */ + ULONG uLength; /* length of the table in bytes */ + }TT_TABLE_DIRECTORY; + + typedef struct _tagTT_NAME_TABLE_HEADER{ + USHORT uFSelector; /* format selector. Always 0 */ + USHORT uNRCount; /* Name Records count */ + USHORT uStorageOffset; /* Offset for strings storage, + * from start of the table */ + }TT_NAME_TABLE_HEADER; + + typedef struct _tagTT_NAME_RECORD{ + USHORT uPlatformID; + USHORT uEncodingID; + USHORT uLanguageID; + USHORT uNameID; + USHORT uStringLength; + USHORT uStringOffset; /* from start of storage area */ + }TT_NAME_RECORD; + +#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x)) +#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x))) + + handle = CreateFileW(filename ,GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, 0 ); + if (handle != INVALID_HANDLE_VALUE) + { + TT_TABLE_DIRECTORY tblDir; + BOOL bFound = FALSE; + TT_OFFSET_TABLE ttOffsetTable; + + ReadFile(handle,&ttOffsetTable, sizeof(TT_OFFSET_TABLE),NULL,NULL); + ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables); + ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion); + ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion); + + if (ttOffsetTable.uMajorVersion != 1 || + ttOffsetTable.uMinorVersion != 0) + return NULL; + + for (i=0; i< ttOffsetTable.uNumOfTables; i++) + { + ReadFile(handle,&tblDir, sizeof(TT_TABLE_DIRECTORY),NULL,NULL); + if (strncmp(tblDir.szTag,"name",4)==0) + { + bFound = TRUE; + tblDir.uLength = SWAPLONG(tblDir.uLength); + tblDir.uOffset = SWAPLONG(tblDir.uOffset); + break; + } + } + + if (bFound) + { + TT_NAME_TABLE_HEADER ttNTHeader; + TT_NAME_RECORD ttRecord; + + SetFilePointer(handle, tblDir.uOffset, NULL, FILE_BEGIN); + ReadFile(handle,&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER), + NULL,NULL); + + ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount); + ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset); + bFound = FALSE; + for(i=0; i 0) + { + strcat(buf,tt); + ret = strdupAtoW(buf); + HeapFree(GetProcessHeap(),0,buf); + break; + } + + HeapFree(GetProcessHeap(),0,buf); + SetFilePointer(handle,nPos, NULL, FILE_BEGIN); + } + } + } + CloseHandle(handle); + } + + TRACE("Returning fontname %s\n",debugstr_w(ret)); + return ret; +} + +static UINT ACTION_RegisterFonts(MSIPACKAGE *package) +{ + UINT rc; + MSIQUERY * view; + MSIRECORD * row = 0; + static const WCHAR ExecSeqQuery[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + 'F','o','n','t',0}; + static const WCHAR regfont1[] = + {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','N','T','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'F','o','n','t','s',0}; + static const WCHAR regfont2[] = + {'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'F','o','n','t','s',0}; + HKEY hkey1; + HKEY hkey2; + + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); + if (rc != ERROR_SUCCESS) + return rc; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } + + RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont1,&hkey1); + RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2); + + while (1) + { + LPWSTR name; + LPWSTR file; + UINT index; + DWORD size; + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + file = load_dynamic_stringW(row,1); + index = get_loaded_file(package,file); + if (index < 0) + { + ERR("Unable to load file\n"); + HeapFree(GetProcessHeap(),0,file); + continue; + } + + /* check to make sure that component is installed */ + if (!ACTION_VerifyComponentForAction(package, + package->files[index].ComponentIndex, INSTALLSTATE_LOCAL)) + { + TRACE("Skipping: Component not scheduled for install\n"); + HeapFree(GetProcessHeap(),0,file); + + msiobj_release(&row->hdr); + + continue; + } + + if (MSI_RecordIsNull(row,2)) + name = load_ttfname_from(package->files[index].TargetPath); + else + name = load_dynamic_stringW(row,2); + + if (name) + { + size = strlenW(package->files[index].FileName) * sizeof(WCHAR); + RegSetValueExW(hkey1,name,0,REG_SZ, + (LPBYTE)package->files[index].FileName,size); + RegSetValueExW(hkey2,name,0,REG_SZ, + (LPBYTE)package->files[index].FileName,size); + } + + HeapFree(GetProcessHeap(),0,file); + HeapFree(GetProcessHeap(),0,name); + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); + + RegCloseKey(hkey1); + RegCloseKey(hkey2); + + return rc; +} + /* Msi functions that seem appropriate here */ UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) { @@ -5658,7 +6241,7 @@ package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if( package ) { - ret = ACTION_PerformAction(package,szAction); + ret = ACTION_PerformUIAction(package,szAction); msiobj_release( &package->hdr ); } return ret; @@ -5963,6 +6546,7 @@ { MSIPACKAGE* package; INT index; + UINT rc = ERROR_SUCCESS; TRACE(" %s to %i\n",debugstr_w(szFeature), iState); @@ -5972,12 +6556,17 @@ index = get_loaded_feature(package,szFeature); if (index < 0) - return ERROR_UNKNOWN_FEATURE; + { + rc = ERROR_UNKNOWN_FEATURE; + goto end; + } package->features[index].ActionRequest= iState; ACTION_UpdateComponentStates(package,szFeature); - return ERROR_SUCCESS; +end: + msiobj_release( &package->hdr ); + return rc; } UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature, diff -urN wine-20050211/dlls/msi/action.h wine-20050310/dlls/msi/action.h --- wine-20050211/dlls/msi/action.h 2005-02-01 19:46:26.000000000 +0100 +++ wine-20050310/dlls/msi/action.h 2005-02-24 13:47:43.000000000 +0100 @@ -53,6 +53,9 @@ BOOL Enabled; INT Cost; + INT RefCount; + + LPWSTR FullKeypath; } MSICOMPONENT; typedef struct tagMSIFOLDER diff -urN wine-20050211/dlls/msi/appsearch.c wine-20050310/dlls/msi/appsearch.c --- wine-20050211/dlls/msi/appsearch.c 2005-02-08 13:08:49.000000000 +0100 +++ wine-20050310/dlls/msi/appsearch.c 2005-03-10 18:24:20.000000000 +0100 @@ -629,7 +629,7 @@ WCHAR first = toupperW(path[0]); BOOL ret; - if (first >= 'A' && first <= 'A' && path[1] == ':') + if (first >= 'A' && first <= 'Z' && path[1] == ':') ret = TRUE; else if (path[0] == '\\' && path[1] == '\\') ret = TRUE; @@ -644,6 +644,7 @@ UINT rc; BOOL found; + TRACE("%p, %p, %s, %d\n", package, sig, debugstr_w(expanded), depth); if (ACTION_IsFullPath(expanded)) { if (sig->File) @@ -681,6 +682,7 @@ } } } + TRACE("returning %d\n", rc); return rc; } diff -urN wine-20050211/dlls/msi/delete.c wine-20050310/dlls/msi/delete.c --- wine-20050211/dlls/msi/delete.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/msi/delete.c 2005-02-14 12:07:13.000000000 +0100 @@ -0,0 +1,218 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2002-2005 Mike McCormack 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "wine/debug.h" +#include "msi.h" +#include "msiquery.h" +#include "objbase.h" +#include "objidl.h" +#include "msipriv.h" +#include "winnls.h" + +#include "query.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + + +/* + * Code to delete rows from a table. + * + * We delete rows by blanking them out rather than trying to remove the row. + * This appears to be what the native MSI does (or tries to do). For the query: + * + * delete from Property + * + * some non-zero entries are left in the table by native MSI. I'm not sure if + * that's a bug in the way I'm running the query, or a just a bug. + */ + +typedef struct tagMSIDELETEVIEW +{ + MSIVIEW view; + MSIDATABASE *db; + MSIVIEW *table; +} MSIDELETEVIEW; + +static UINT DELETE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %d %d %p\n", dv, row, col, val ); + + return ERROR_FUNCTION_FAILED; +} + +static UINT DELETE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %d %d %p\n", dv, row, col, stm ); + + return ERROR_FUNCTION_FAILED; +} + +static UINT DELETE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %d %d %04x\n", dv, row, col, val ); + + return ERROR_FUNCTION_FAILED; +} + +static UINT DELETE_insert_row( struct tagMSIVIEW *view, UINT *num ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %p\n", dv, num ); + + return ERROR_FUNCTION_FAILED; +} + +static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + UINT r, i, j, rows = 0, cols = 0; + + TRACE("%p %p\n", dv, record); + + if( !dv->table ) + return ERROR_FUNCTION_FAILED; + + r = dv->table->ops->execute( dv->table, record ); + if( r != ERROR_SUCCESS ) + return r; + + r = dv->table->ops->get_dimensions( dv->table, &rows, &cols ); + if( r != ERROR_SUCCESS ) + return r; + + TRACE("blanking %d rows\n", rows); + + /* blank out all the rows that match */ + for( i=0; itable->ops->set_int( dv->table, i, j, 0 ); + + return ERROR_SUCCESS; +} + +static UINT DELETE_close( struct tagMSIVIEW *view ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p\n", dv ); + + if( !dv->table ) + return ERROR_FUNCTION_FAILED; + + return dv->table->ops->close( dv->table ); +} + +static UINT DELETE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %p %p\n", dv, rows, cols ); + + if( !dv->table ) + return ERROR_FUNCTION_FAILED; + + *rows = 0; + + return dv->table->ops->get_dimensions( dv->table, NULL, cols ); +} + +static UINT DELETE_get_column_info( struct tagMSIVIEW *view, + UINT n, LPWSTR *name, UINT *type ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %d %p %p\n", dv, n, name, type ); + + if( !dv->table ) + return ERROR_FUNCTION_FAILED; + + return dv->table->ops->get_column_info( dv->table, n, name, type ); +} + +static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p %d %p\n", dv, eModifyMode, rec ); + + return ERROR_FUNCTION_FAILED; +} + +static UINT DELETE_delete( struct tagMSIVIEW *view ) +{ + MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; + + TRACE("%p\n", dv ); + + if( dv->table ) + dv->table->ops->delete( dv->table ); + + HeapFree( GetProcessHeap(), 0, dv ); + + return ERROR_SUCCESS; +} + + +MSIVIEWOPS delete_ops = +{ + DELETE_fetch_int, + DELETE_fetch_stream, + DELETE_set_int, + DELETE_insert_row, + DELETE_execute, + DELETE_close, + DELETE_get_dimensions, + DELETE_get_column_info, + DELETE_modify, + DELETE_delete +}; + +UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) +{ + MSIDELETEVIEW *dv = NULL; + + TRACE("%p\n", dv ); + + dv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *dv ); + if( !dv ) + return ERROR_FUNCTION_FAILED; + + /* fill the structure */ + dv->view.ops = &delete_ops; + dv->db = db; + dv->table = table; + + *view = &dv->view; + + return ERROR_SUCCESS; +} diff -urN wine-20050211/dlls/msi/dialog.c wine-20050310/dlls/msi/dialog.c --- wine-20050211/dlls/msi/dialog.c 2005-02-09 14:24:31.000000000 +0100 +++ wine-20050310/dlls/msi/dialog.c 2005-03-04 13:32:08.000000000 +0100 @@ -41,6 +41,9 @@ 'M','s','i','D','i','a','l','o','g','C','l','o','s','e','C','l','a','s','s',0 }; const static WCHAR szStatic[] = { 'S','t','a','t','i','c',0 }; +const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 }; + +const static WCHAR szButtonData[] = { 'M','S','I','D','A','T','A',0 }; struct msi_control_tag; typedef struct msi_control_tag msi_control; @@ -83,10 +86,19 @@ msi_dialog_control_func func; }; +typedef struct +{ + msi_dialog* dialog; + msi_control *parent; + DWORD attributes; +} radio_button_group_descr; + static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM ); static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * ); static UINT msi_dialog_button_handler( msi_dialog *, msi_control *, WPARAM ); static UINT msi_dialog_edit_handler( msi_dialog *, msi_control *, WPARAM ); +static UINT msi_dialog_radiogroup_handler( msi_dialog *, msi_control *, WPARAM param ); +static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); INT msi_dialog_scale_unit( msi_dialog *dialog, INT val ) @@ -275,7 +287,6 @@ static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec ) { - const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 }; msi_control *control; TRACE("%p %p\n", dialog, rec); @@ -288,7 +299,6 @@ static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec ) { - const static WCHAR szButton[] = { 'B','U','T','T','O','N', 0 }; msi_control *control; LPCWSTR prop; @@ -319,7 +329,7 @@ TRACE("%p %p\n", dialog, rec); - msi_dialog_add_control( dialog, rec, szEdit, + msi_dialog_add_control( dialog, rec, szEdit, WS_BORDER | ES_MULTILINE | WS_VSCROLL | ES_READONLY | ES_AUTOVSCROLL ); return ERROR_SUCCESS; @@ -350,7 +360,7 @@ LPCWSTR prop; LPWSTR val; - control = msi_dialog_add_control( dialog, rec, szEdit, 0 ); + control = msi_dialog_add_control( dialog, rec, szEdit, WS_BORDER ); control->handler = msi_dialog_edit_handler; prop = MSI_RecordGetString( rec, 9 ); if( prop ) @@ -361,8 +371,125 @@ return ERROR_SUCCESS; } +static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + FIXME("not implemented properly\n"); + return msi_dialog_edit_control( dialog, rec ); +} + +static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param ) +{ + radio_button_group_descr *group = (radio_button_group_descr *)param; + msi_dialog *dialog = group->dialog; + msi_control *control; + LPCWSTR prop; + DWORD x, y, width, height, style; + DWORD attributes = group->attributes; + LPCWSTR text, name; + LPWSTR font = NULL, title = NULL; + + style = WS_CHILD | BS_AUTORADIOBUTTON | BS_MULTILINE; + name = MSI_RecordGetString( rec, 3 ); + control = HeapAlloc( GetProcessHeap(), 0, + sizeof *control + strlenW(name)*sizeof(WCHAR) ); + strcpyW( control->name, name ); + control->next = dialog->control_list; + dialog->control_list = control; + + x = MSI_RecordGetInteger( rec, 4 ); + y = MSI_RecordGetInteger( rec, 5 ); + width = MSI_RecordGetInteger( rec, 6 ); + height = MSI_RecordGetInteger( rec, 7 ); + text = MSI_RecordGetString( rec, 8 ); + + x = msi_dialog_scale_unit( dialog, x ); + y = msi_dialog_scale_unit( dialog, y ); + width = msi_dialog_scale_unit( dialog, width ); + height = msi_dialog_scale_unit( dialog, height ); + + if( attributes & 1 ) + style |= WS_VISIBLE; + if( ~attributes & 2 ) + style |= WS_DISABLED; + + if( text ) + { + font = msi_dialog_get_style( &text ); + deformat_string( dialog->package, text, &title ); + } + + control->hwnd = CreateWindowW( szButton, title, style, x, y, width, height, + group->parent->hwnd, NULL, NULL, NULL ); + + TRACE("Dialog %s control %s hwnd %p\n", debugstr_w(dialog->name), debugstr_w(text), control->hwnd); + + msi_dialog_set_font( dialog, control->hwnd, + font ? font : dialog->default_font ); + + HeapFree( GetProcessHeap(), 0, font ); + HeapFree( GetProcessHeap(), 0, title ); + + control->handler = msi_dialog_radiogroup_handler; + + prop = MSI_RecordGetString( rec, 1 ); + if( prop ) + control->property = dupstrW( prop ); + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_radiogroup_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ', + 'F','R','O','M',' ','R','a','d','i','o','B','u','t','t','o','n',' ', + 'W','H','E','R','E',' ', + '`','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; + UINT r; + LPCWSTR prop; + msi_control *control; + MSIQUERY *view = NULL; + radio_button_group_descr group; + MSIPACKAGE *package = dialog->package; + + prop = MSI_RecordGetString( rec, 9 ); + + TRACE("%p %p %s\n", dialog, rec, debugstr_w( prop )); + + /* Create parent group box to hold radio buttons */ + control = msi_dialog_add_control( dialog, rec, szButton, BS_OWNERDRAW ); + + if (control->hwnd) + { + WNDPROC oldproc = (WNDPROC) SetWindowLongPtrW(control->hwnd, GWLP_WNDPROC, + (LONG_PTR)MSIRadioGroup_WndProc); + SetPropW(control->hwnd, szButtonData, oldproc); + } + + if( prop ) + control->property = dupstrW( prop ); + + /* query the Radio Button table for all control in this group */ + r = MSI_OpenQuery( package->db, &view, query, prop ); + if( r != ERROR_SUCCESS ) + { + ERR("query failed for dialog %s radio group %s\n", + debugstr_w(dialog->name), debugstr_w(prop)); + return ERROR_INVALID_PARAMETER; + } + + group.dialog = dialog; + group.parent = control; + group.attributes = MSI_RecordGetInteger( rec, 8 ); + + r = MSI_IterateRecords( view, 0, msi_dialog_create_radiobutton, &group ); + msiobj_release( &view->hdr ); + + return r; +} + static const WCHAR szText[] = { 'T','e','x','t',0 }; -static const WCHAR szButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 }; +static const WCHAR szPushButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 }; static const WCHAR szLine[] = { 'L','i','n','e',0 }; static const WCHAR szBitmap[] = { 'B','i','t','m','a','p',0 }; static const WCHAR szCheckBox[] = { 'C','h','e','c','k','B','o','x',0 }; @@ -371,11 +498,14 @@ static const WCHAR szComboBox[] = { 'C','o','m','b','o','B','o','x',0 }; static const WCHAR szEdit[] = { 'E','d','i','t',0 }; static const WCHAR szMaskedEdit[] = { 'M','a','s','k','e','d','E','d','i','t',0 }; +static const WCHAR szPathEdit[] = { 'P','a','t','h','E','d','i','t',0 }; +static const WCHAR szRadioButtonGroup[] = { + 'R','a','d','i','o','B','u','t','t','o','n','G','r','o','u','p',0 }; struct control_handler msi_dialog_handler[] = { { szText, msi_dialog_text_control }, - { szButton, msi_dialog_button_control }, + { szPushButton, msi_dialog_button_control }, { szLine, msi_dialog_line_control }, { szBitmap, msi_dialog_bitmap_control }, { szCheckBox, msi_dialog_checkbox_control }, @@ -383,6 +513,8 @@ { szComboBox, msi_dialog_combo_control }, { szEdit, msi_dialog_edit_control }, { szMaskedEdit, msi_dialog_edit_control }, + { szPathEdit, msi_dialog_pathedit_control }, + { szRadioButtonGroup, msi_dialog_radiogroup_control }, }; #define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0]) @@ -791,6 +923,20 @@ return ERROR_SUCCESS; } +static UINT msi_dialog_radiogroup_handler( msi_dialog *dialog, + msi_control *control, WPARAM param ) +{ + if( HIWORD(param) != BN_CLICKED ) + return ERROR_SUCCESS; + + TRACE("clicked radio button %s, set %s\n", debugstr_w(control->name), + debugstr_w(control->property)); + + MSI_SetPropertyW( dialog->package, control->property, control->name ); + + return msi_dialog_button_handler( dialog, control, param ); +} + static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd ) { msi_control *control; @@ -816,6 +962,7 @@ { msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + TRACE(" 0x%04x\n", msg); switch (msg) { case WM_CREATE: @@ -971,3 +1118,15 @@ { UnregisterClassW( szMsiDialogClass, NULL ); } + +static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC oldproc = (WNDPROC) GetPropW(hWnd, szButtonData); + + TRACE("hWnd %p msg %04x wParam 0x%08x lParam 0x%08lx\n", hWnd, msg, wParam, lParam); + + if (msg == WM_COMMAND) /* Forward notifications to dialog */ + SendMessageW(GetParent(hWnd), msg, wParam, lParam); + + return CallWindowProcW(oldproc, hWnd, msg, wParam, lParam); +} diff -urN wine-20050211/dlls/msi/format.c wine-20050310/dlls/msi/format.c --- wine-20050211/dlls/msi/format.c 2005-02-09 23:22:25.000000000 +0100 +++ wine-20050310/dlls/msi/format.c 2005-03-10 12:15:40.000000000 +0100 @@ -231,13 +231,13 @@ *nested = FALSE; for (i = 1; (*mark - source) + i < len_remaining && count > 0; i++) { - if ((*mark)[i] == '[') + if ((*mark)[i] == '[' && (*mark)[i-1] != '\\') { count ++; total_count ++; *nested = TRUE; } - else if ((*mark)[i] == ']') + else if ((*mark)[i] == ']' && (*mark)[i-1] != '\\') { count --; } @@ -538,11 +538,8 @@ package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); - if( record ) - { - r = MSI_FormatRecordW( package, record, szResult, sz ); - msiobj_release( &record->hdr ); - } + r = MSI_FormatRecordW( package, record, szResult, sz ); + msiobj_release( &record->hdr ); if (package) msiobj_release( &package->hdr ); return r; @@ -572,11 +569,8 @@ package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); - if( record ) - { - r = MSI_FormatRecordA( package, record, szResult, sz ); - msiobj_release( &record->hdr ); - } + r = MSI_FormatRecordA( package, record, szResult, sz ); + msiobj_release( &record->hdr ); if (package) msiobj_release( &package->hdr ); return r; diff -urN wine-20050211/dlls/msi/msi.c wine-20050310/dlls/msi/msi.c --- wine-20050211/dlls/msi/msi.c 2005-02-10 19:57:42.000000000 +0100 +++ wine-20050310/dlls/msi/msi.c 2005-03-10 12:15:40.000000000 +0100 @@ -484,6 +484,11 @@ goto end; package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); + if (!package) + { + rc = ERROR_INVALID_HANDLE; + goto end; + } sz = strlenW(szInstalled); @@ -862,7 +867,7 @@ * id [I] id of the string to be loaded * lpBuffer [O] buffer for the string to be written to * nBufferMax [I] maximum size of the buffer in characters - * lang [I] the prefered language for the string + * lang [I] the preferred language for the string * * RETURNS * @@ -970,219 +975,6 @@ return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid) -{ - DWORD r; - WCHAR szwGuid[GUID_SIZE]; - - TRACE("%ld %p\n",index,lpguid); - - if (NULL == lpguid) { - return ERROR_INVALID_PARAMETER; - } - r = MsiEnumProductsW(index, szwGuid); - if( r == ERROR_SUCCESS ) - WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL); - - return r; -} - -UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) -{ - HKEY hkeyFeatures = 0; - DWORD r; - WCHAR szKeyName[33]; - - TRACE("%ld %p\n",index,lpguid); - - if (NULL == lpguid) - return ERROR_INVALID_PARAMETER; - - r = MSIREG_OpenFeatures(&hkeyFeatures); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE); - - unsquash_guid(szKeyName, lpguid); - -end: - - if( hkeyFeatures ) - RegCloseKey(hkeyFeatures); - - return r; -} - -UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, - LPSTR szFeature, LPSTR szParent) -{ - DWORD r; - WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE]; - LPWSTR szwProduct = NULL; - - TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent); - - if( szProduct ) - { - UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); - szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwProduct ) - MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); - else - return ERROR_FUNCTION_FAILED; - } - - r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent); - if( r == ERROR_SUCCESS ) - { - WideCharToMultiByte(CP_ACP, 0, szwFeature, -1, - szFeature, GUID_SIZE, NULL, NULL); - WideCharToMultiByte(CP_ACP, 0, szwParent, -1, - szParent, GUID_SIZE, NULL, NULL); - } - - HeapFree( GetProcessHeap(), 0, szwProduct); - - return r; -} - -UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, - LPWSTR szFeature, LPWSTR szParent) -{ - HKEY hkeyProduct = 0; - DWORD r, sz; - - TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent); - - r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE); - if( r != ERROR_SUCCESS ) - goto end; - - sz = GUID_SIZE; - r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL); - -end: - if( hkeyProduct ) - RegCloseKey(hkeyProduct); - - return r; -} - -UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid) -{ - DWORD r; - WCHAR szwGuid[GUID_SIZE]; - - TRACE("%ld %p\n",index,lpguid); - - r = MsiEnumComponentsW(index, szwGuid); - if( r == ERROR_SUCCESS ) - WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL); - - return r; -} - -UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid) -{ - HKEY hkeyComponents = 0; - DWORD r; - WCHAR szKeyName[33]; - - TRACE("%ld %p\n",index,lpguid); - - r = MSIREG_OpenComponents(&hkeyComponents); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE); - - unsquash_guid(szKeyName, lpguid); - -end: - - if( hkeyComponents ) - RegCloseKey(hkeyComponents); - - return r; -} - -UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct) -{ - DWORD r; - WCHAR szwProduct[GUID_SIZE]; - LPWSTR szwComponent = NULL; - - TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct); - - if( szComponent ) - { - UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); - szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwComponent ) - MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); - else - return ERROR_FUNCTION_FAILED; - } - - r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct); - if( r == ERROR_SUCCESS ) - { - WideCharToMultiByte(CP_ACP, 0, szwProduct, -1, - szProduct, GUID_SIZE, NULL, NULL); - } - - HeapFree( GetProcessHeap(), 0, szwComponent); - - return r; -} - -UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct) -{ - HKEY hkeyComp = 0; - DWORD r, sz; - WCHAR szValName[GUID_SIZE]; - - TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct); - - r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE); - if( r != ERROR_SUCCESS ) - goto end; - - sz = GUID_SIZE; - r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL); - if( r != ERROR_SUCCESS ) - goto end; - - unsquash_guid(szValName, szProduct); - -end: - if( hkeyComp ) - RegCloseKey(hkeyComp); - - return r; -} - -UINT WINAPI MsiEnumComponentQualifiersA( LPSTR szComponent, DWORD iIndex, - LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, - LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf) -{ - FIXME("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, - lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, - pcchApplicationDataBuf); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, - LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, - LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf ) -{ - FIXME("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, - lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, - pcchApplicationDataBuf); - return ERROR_CALL_NOT_IMPLEMENTED; -} - UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, DWORD* pcchPathBuf ) @@ -1340,41 +1132,72 @@ WCHAR squished_pc[GUID_SIZE]; UINT rc; INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN; - HKEY hkey=0; + HKEY hkey = 0; + LPWSTR path = NULL; + DWORD sz, type; TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szComponent), lpPathBuf, pcchBuf); + if( lpPathBuf && !pcchBuf ) + return INSTALLSTATE_INVALIDARG; + squash_guid(szProduct,squished_pc); - rc = MSIREG_OpenProductsKey(szProduct,&hkey,FALSE); - if (rc != ERROR_SUCCESS) + rc = MSIREG_OpenProductsKey( szProduct, &hkey, FALSE); + if( rc != ERROR_SUCCESS ) goto end; RegCloseKey(hkey); - rc = MSIREG_OpenComponentsKey(szComponent,&hkey,FALSE); - if (rc != ERROR_SUCCESS) + rc = MSIREG_OpenComponentsKey( szComponent, &hkey, FALSE); + if( rc != ERROR_SUCCESS ) + goto end; + + sz = 0; + type = 0; + rc = RegQueryValueExW( hkey, squished_pc, NULL, &type, NULL, &sz ); + if( rc != ERROR_SUCCESS ) + goto end; + if( type != REG_SZ ) goto end; - *pcchBuf *= sizeof(WCHAR); - rc = RegQueryValueExW(hkey,squished_pc,NULL,NULL,(LPVOID)lpPathBuf, - pcchBuf); - *pcchBuf /= sizeof(WCHAR); + sz += sizeof(WCHAR); + path = HeapAlloc( GetProcessHeap(), 0, sz ); + if( !path ) + goto end; - if (rc!= ERROR_SUCCESS) + rc = RegQueryValueExW( hkey, squished_pc, NULL, NULL, (LPVOID) path, &sz ); + if( rc != ERROR_SUCCESS ) goto end; TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent), - debugstr_w(szProduct), debugstr_w(lpPathBuf)); + debugstr_w(szProduct), debugstr_w(path)); - FIXME("Only working for installed files, not registry keys\n"); - if (GetFileAttributesW(lpPathBuf) != INVALID_FILE_ATTRIBUTES) - rrc = INSTALLSTATE_LOCAL; + if (path[0]=='0') + { + FIXME("Registry entry.. check entry\n"); + rrc = INSTALLSTATE_LOCAL; + } else - rrc = INSTALLSTATE_ABSENT; + { + /* PROBABLY a file */ + if ( GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES ) + rrc = INSTALLSTATE_LOCAL; + else + rrc = INSTALLSTATE_ABSENT; + } + + if( pcchBuf ) + { + sz = sz / sizeof(WCHAR); + if( *pcchBuf >= sz ) + strcpyW( lpPathBuf, path ); + *pcchBuf = sz; + } end: + HeapFree(GetProcessHeap(), 0, path ); RegCloseKey(hkey); return rrc; } @@ -1418,7 +1241,10 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) { FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); - return INSTALLSTATE_UNKNOWN; + /* + * Iterates all the features components and the features parents components + */ + return INSTALLSTATE_LOCAL; } UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, @@ -1652,22 +1478,6 @@ return S_FALSE; } -UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, - DWORD iProductIndex, LPWSTR lpProductBuf) -{ - FIXME("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved, - iProductIndex, lpProductBuf); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved, - DWORD iProductIndex, LPSTR lpProductBuf) -{ - FIXME("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved, - iProductIndex, lpProductBuf); - return ERROR_CALL_NOT_IMPLEMENTED; -} - UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature, DWORD* pdwUseCount, WORD* pwDateUsed) { @@ -1684,11 +1494,42 @@ return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, +INSTALLSTATE WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwInstallMode, DWORD dwReserved) { FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature), dwInstallMode, dwReserved); + + /* + * Polls all the components of the feature to find install state and then + * writes: + * Software\\Microsoft\\Windows\\CurrentVersion\\ + * Installer\\Products\\\\ + * "Usage"=dword:........ + */ + + return INSTALLSTATE_LOCAL; +} + +INSTALLSTATE WINAPI MsiUseFeatureExA(LPCSTR szProduct, LPCSTR szFeature, + DWORD dwInstallMode, DWORD dwReserved) +{ + FIXME("%s %s %li %li\n", debugstr_a(szProduct), debugstr_a(szFeature), + dwInstallMode, dwReserved); + + return INSTALLSTATE_LOCAL; +} + +INSTALLSTATE WINAPI MsiUseFeatureW(LPCWSTR szProduct, LPCWSTR szFeature) +{ + FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); + + return INSTALLSTATE_LOCAL; +} + +INSTALLSTATE WINAPI MsiUseFeatureA(LPCSTR szProduct, LPCSTR szFeature) +{ + FIXME("%s %s\n", debugstr_a(szProduct), debugstr_a(szFeature)); return INSTALLSTATE_LOCAL; } @@ -1746,17 +1587,33 @@ } UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget, - LPSTR szProductCode, LPSTR szFeatureId, - LPSTR szComponentCode) + LPSTR szProductCode, LPSTR szFeatureId, + LPSTR szComponentCode ) { FIXME("\n"); return ERROR_CALL_NOT_IMPLEMENTED; } UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, - LPWSTR szProductCode, LPWSTR szFeatureId, - LPWSTR szComponentCode) + LPWSTR szProductCode, LPWSTR szFeatureId, + LPWSTR szComponentCode ) { FIXME("\n"); return ERROR_CALL_NOT_IMPLEMENTED; } + +UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, + DWORD dwReinstallMode ) +{ + FIXME("%s %s %li\n", debugstr_w(szProduct), debugstr_w(szFeature), + dwReinstallMode); + return ERROR_SUCCESS; +} + +UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature, + DWORD dwReinstallMode ) +{ + FIXME("%s %s %li\n", debugstr_a(szProduct), debugstr_a(szFeature), + dwReinstallMode); + return ERROR_SUCCESS; +} diff -urN wine-20050211/dlls/msi/msi.rc wine-20050310/dlls/msi/msi.rc --- wine-20050211/dlls/msi/msi.rc 2005-02-08 13:12:29.000000000 +0100 +++ wine-20050310/dlls/msi/msi.rc 2005-02-23 13:41:09.000000000 +0100 @@ -27,4 +27,8 @@ #include "version.rc" +#include "msi_De.rc" #include "msi_En.rc" +#include "msi_Es.rc" +#include "msi_Fr.rc" +#include "msi_Pt.rc" diff -urN wine-20050211/dlls/msi/msi.spec wine-20050310/dlls/msi/msi.spec --- wine-20050211/dlls/msi/msi.spec 2005-02-10 18:10:14.000000000 +0100 +++ wine-20050310/dlls/msi/msi.spec 2005-02-16 17:24:38.000000000 +0100 @@ -123,10 +123,10 @@ 123 stdcall MsiRecordSetStreamW(long long wstr) 124 stdcall MsiRecordSetStringA(long long str) 125 stdcall MsiRecordSetStringW(long long wstr) -126 stub MsiReinstallFeatureA +126 stdcall MsiReinstallFeatureA(str str long) 127 stub MsiReinstallFeatureFromDescriptorA 128 stub MsiReinstallFeatureFromDescriptorW -129 stub MsiReinstallFeatureW +129 stdcall MsiReinstallFeatureW(wstr wstr long) 130 stdcall MsiReinstallProductA(str long) 131 stdcall MsiReinstallProductW(wstr long) 132 stub MsiSequenceA @@ -151,8 +151,8 @@ 151 stdcall MsiSummaryInfoPersist(long) 152 stdcall MsiSummaryInfoSetPropertyA(long long long long ptr str) 153 stdcall MsiSummaryInfoSetPropertyW(long long long long ptr wstr) -154 stub MsiUseFeatureA -155 stub MsiUseFeatureW +154 stdcall MsiUseFeatureA(str str) +155 stdcall MsiUseFeatureW(wstr wstr) 156 stdcall MsiVerifyPackageA(str) 157 stdcall MsiVerifyPackageW(wstr) 158 stdcall MsiViewClose(long) @@ -189,7 +189,7 @@ 189 stdcall MsiConfigureProductExA(str long long str) 190 stdcall MsiConfigureProductExW(wstr long long wstr) 191 stub MsiInvalidateFeatureCache -192 stub MsiUseFeatureExA +192 stdcall MsiUseFeatureExA(str str long long) 193 stdcall MsiUseFeatureExW(wstr wstr long long) 194 stdcall MsiGetFileVersionA(str str ptr str ptr) 195 stdcall MsiGetFileVersionW(wstr wstr ptr wstr ptr) diff -urN wine-20050211/dlls/msi/msi_De.rc wine-20050310/dlls/msi/msi_De.rc --- wine-20050211/dlls/msi/msi_De.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/msi/msi_De.rc 2005-02-15 21:46:19.000000000 +0100 @@ -0,0 +1,33 @@ +/* + * German resources for MSI + * + * Copyright 2005 Henning Gerhardt + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "Der Pfad %s wurde nicht gefunden." + 9 "Bitte Disk %s einlegen." + 10 "schlechte Parameter" + 11 "Geben Sie das Verzeichnis ein, dass %s enthält." + 12 "Die Installationsquelle für das Feature fehlt." + 13 "Das Netzwerklaufwerk für das Feature fehlt." + 14 "Feature von:" + 15 "Wählen Sie das Verzeichnis aus, dass %s enthält." +} diff -urN wine-20050211/dlls/msi/msi_Es.rc wine-20050310/dlls/msi/msi_Es.rc --- wine-20050211/dlls/msi/msi_Es.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/msi/msi_Es.rc 2005-02-23 13:41:09.000000000 +0100 @@ -0,0 +1,33 @@ +/* + * Spanish resources for MSI + * + * Copyright 2005 José Manuel Ferrer Ortiz + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "ruta %s no encontrada" + 9 "inserte el disco %s" + 10 "parámetros incorrectos" + 11 "introduzca qué carpeta contiene %s" + 12 "instalar fuente para característica ausente" + 13 "unidad de red para característica ausente" + 14 "característica de:" + 15 "elija qué carpeta contiene %s" +} diff -urN wine-20050211/dlls/msi/msi_Fr.rc wine-20050310/dlls/msi/msi_Fr.rc --- wine-20050211/dlls/msi/msi_Fr.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/msi/msi_Fr.rc 2005-02-16 22:10:02.000000000 +0100 @@ -0,0 +1,33 @@ +/* + * French resources for MSI + * + * Copyright 2005 Jonathan Ernst + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "Le chemin %s est introuvable" + 9 "insérez le disque %s" + 10 "mauvais paramètres" + 11 "saisissez le nom du dossier contenant %s" + 12 "source d'installation pour la fonctionnalité manquante" + 13 "lecteur réseau pour la fonctionnalité manquant" + 14 "fonctionnalité depuis:" + 15 "sélectionnez le dossier contenant %s" +} diff -urN wine-20050211/dlls/msi/msi_Pt.rc wine-20050310/dlls/msi/msi_Pt.rc --- wine-20050211/dlls/msi/msi_Pt.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/msi/msi_Pt.rc 2005-02-14 12:12:30.000000000 +0100 @@ -0,0 +1,33 @@ +/* + * Portuguese resources for MSI + * + * Copyright 2005 Marcelo Duarte + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "caminho %s não encontrado" + 9 "insira disco %s" + 10 "parâmetros inválidos" + 11 "entre qual pasta contém %s" + 12 "instalar fonte para característica faltando" + 13 "drive de rede para característica faltando" + 14 "característica de:" + 15 "escolha qual pasta contém %s" +} diff -urN wine-20050211/dlls/msi/msipriv.h wine-20050310/dlls/msi/msipriv.h --- wine-20050211/dlls/msi/msipriv.h 2005-02-08 14:44:25.000000000 +0100 +++ wine-20050310/dlls/msi/msipriv.h 2005-03-10 18:24:05.000000000 +0100 @@ -214,6 +214,8 @@ UINT CurrentInstallState; msi_dialog *dialog; LPWSTR next_dialog; + + BOOL ExecuteSequenceRun; } MSIPACKAGE; typedef struct tagMSIPREVIEW @@ -362,6 +364,7 @@ extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create); /* msi dialog interface */ typedef VOID (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* ); diff -urN wine-20050211/dlls/msi/msiquery.c wine-20050310/dlls/msi/msiquery.c --- wine-20050211/dlls/msi/msiquery.c 2005-02-08 14:44:25.000000000 +0100 +++ wine-20050310/dlls/msi/msiquery.c 2005-03-10 12:15:40.000000000 +0100 @@ -1,7 +1,7 @@ /* * Implementation of the Microsoft Installer (msi.dll) * - * Copyright 2002-2004 Mike McCormack for CodeWeavers + * Copyright 2002-2005 Mike McCormack for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -212,6 +212,9 @@ if( count ) *count = n; + if( r == ERROR_NO_MORE_ITEMS ) + r = ERROR_SUCCESS; + return r; } @@ -420,8 +423,7 @@ msiobj_unlock( &rec->hdr ); out: - if( query ) - msiobj_release( &query->hdr ); + msiobj_release( &query->hdr ); if( rec ) msiobj_release( &rec->hdr ); @@ -460,7 +462,10 @@ rec = MSI_CreateRecord( count ); if( !rec ) - return ERROR_FUNCTION_FAILED; + { + r = ERROR_FUNCTION_FAILED; + goto out; + } for( i=0; ihdr ); out: - if( query ) - msiobj_release( &query->hdr ); + msiobj_release( &query->hdr ); if( rec ) msiobj_release( &rec->hdr ); @@ -514,8 +518,7 @@ r = view->ops->modify( view, eModifyMode, rec ); out: - if( query ) - msiobj_release( &query->hdr ); + msiobj_release( &query->hdr ); if( rec ) msiobj_release( &rec->hdr ); @@ -574,18 +577,116 @@ return r; } -UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, - LPCSTR table, MSIHANDLE* rec) +struct msi_primary_key_record_info { - FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec); - return ERROR_CALL_NOT_IMPLEMENTED; + DWORD n; + MSIRECORD *rec; +}; + +static UINT msi_primary_key_iterator( MSIRECORD *rec, LPVOID param ) +{ + struct msi_primary_key_record_info *info = param; + LPCWSTR name; + DWORD type; + + type = MSI_RecordGetInteger( rec, 4 ); + if( type & MSITYPE_KEY ) + { + info->n++; + if( info->rec ) + { + name = MSI_RecordGetString( rec, 3 ); + MSI_RecordSetStringW( info->rec, info->n, name ); + } + } + + return ERROR_SUCCESS; } -UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb, - LPCWSTR table, MSIHANDLE* rec) +UINT MSI_DatabaseGetPrimaryKeys( MSIDATABASE *db, + LPCWSTR table, MSIRECORD **prec ) { - FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec); - return ERROR_CALL_NOT_IMPLEMENTED; + static const WCHAR sql[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ','`','_','C','o','l','u','m','n','s','`',' ', + 'w','h','e','r','e',' ', + '`','T','a','b','l','e','`',' ','=',' ','\'','%','s','\'',0 }; + struct msi_primary_key_record_info info; + MSIQUERY *query = NULL; + MSIVIEW *view; + UINT r; + + r = MSI_OpenQuery( db, &query, sql, table ); + if( r != ERROR_SUCCESS ) + return r; + + view = query->view; + + /* count the number of primary key records */ + info.n = 0; + info.rec = 0; + r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info ); + if( r == ERROR_SUCCESS ) + { + TRACE("Found %ld primary keys\n", info.n ); + + /* allocate a record and fill in the names of the tables */ + info.rec = MSI_CreateRecord( info.n ); + info.n = 0; + r = MSI_IterateRecords( query, 0, msi_primary_key_iterator, &info ); + if( r == ERROR_SUCCESS ) + *prec = info.rec; + else + msiobj_release( &info.rec->hdr ); + } + msiobj_release( &query->hdr ); + + return r; +} + +UINT WINAPI MsiDatabaseGetPrimaryKeysW( MSIHANDLE hdb, + LPCWSTR table, MSIHANDLE* phRec ) +{ + MSIRECORD *rec = NULL; + MSIDATABASE *db; + UINT r; + + TRACE("%ld %s %p\n", hdb, debugstr_w(table), phRec); + + db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE ); + if( !db ) + return ERROR_INVALID_HANDLE; + + r = MSI_DatabaseGetPrimaryKeys( db, table, &rec ); + if( r == ERROR_SUCCESS ) + { + *phRec = alloc_msihandle( &rec->hdr ); + msiobj_release( &rec->hdr ); + } + msiobj_release( &db->hdr ); + + return r; +} + +UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, + LPCSTR table, MSIHANDLE* phRec) +{ + LPWSTR szwTable = NULL; + DWORD len; + UINT r; + + TRACE("%ld %s %p\n", hdb, debugstr_a(table), phRec); + + if( table ) + { + len = MultiByteToWideChar( CP_ACP, 0, table, -1, NULL, 0 ); + szwTable = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, table, -1, szwTable, len ); + } + r = MsiDatabaseGetPrimaryKeysW( hdb, szwTable, phRec ); + HeapFree( GetProcessHeap(), 0, szwTable ); + + return r; } UINT WINAPI MsiDatabaseIsTablePersistentA( diff -urN wine-20050211/dlls/msi/package.c wine-20050310/dlls/msi/package.c --- wine-20050211/dlls/msi/package.c 2005-02-02 10:55:51.000000000 +0100 +++ wine-20050310/dlls/msi/package.c 2005-03-10 12:15:40.000000000 +0100 @@ -60,7 +60,7 @@ msiobj_release( &package->db->hdr ); } -static const UINT clone_properties(MSIDATABASE *db) +static UINT clone_properties(MSIDATABASE *db) { MSIQUERY * view = NULL; UINT rc; @@ -617,7 +617,7 @@ package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); if( !package ) - goto out; + return ERROR_INVALID_HANDLE; record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); if( !record ) @@ -626,8 +626,7 @@ ret = MSI_ProcessMessage( package, eMessageType, record ); out: - if( package ) - msiobj_release( &package->hdr ); + msiobj_release( &package->hdr ); if( record ) msiobj_release( &record->hdr ); diff -urN wine-20050211/dlls/msi/preview.c wine-20050310/dlls/msi/preview.c --- wine-20050211/dlls/msi/preview.c 2005-02-02 10:55:51.000000000 +0100 +++ wine-20050310/dlls/msi/preview.c 2005-03-10 12:15:40.000000000 +0100 @@ -77,6 +77,7 @@ msiobj_release( &preview->hdr ); r = ERROR_SUCCESS; } + msiobj_release( &db->hdr ); return r; } diff -urN wine-20050211/dlls/msi/query.h wine-20050310/dlls/msi/query.h --- wine-20050211/dlls/msi/query.h 2004-12-22 16:22:12.000000000 +0100 +++ wine-20050310/dlls/msi/query.h 2005-02-14 12:07:13.000000000 +0100 @@ -131,6 +131,8 @@ UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **, LPWSTR table, column_assignment *list, struct expr *expr ); +UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ); + void delete_expr( struct expr *e ); void delete_string_list( string_list *sl ); void delete_value_list( value_list *vl ); diff -urN wine-20050211/dlls/msi/record.c wine-20050310/dlls/msi/record.c --- wine-20050211/dlls/msi/record.c 2005-01-31 12:30:59.000000000 +0100 +++ wine-20050310/dlls/msi/record.c 2005-03-10 12:15:40.000000000 +0100 @@ -210,6 +210,7 @@ rec->fields[i].u.iVal = 0; } msiobj_unlock( &rec->hdr ); + msiobj_release( &rec->hdr ); return ERROR_SUCCESS; } diff -urN wine-20050211/dlls/msi/registry.c wine-20050310/dlls/msi/registry.c --- wine-20050211/dlls/msi/registry.c 2005-01-26 20:41:13.000000000 +0100 +++ wine-20050310/dlls/msi/registry.c 2005-03-10 18:24:05.000000000 +0100 @@ -117,6 +117,23 @@ 'P','r','o','d','u','c','t','s','\\', '%','s',0}; +static const WCHAR szInstaller_UpgradeCodes[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'I','n','s','t','a','l','l','e','r','\\', +'U','p','g','r','a','d','e','C','o','d','e','s',0}; + +static const WCHAR szInstaller_UpgradeCodes_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'I','n','s','t','a','l','l','e','r','\\', +'U','p','g','r','a','d','e','C','o','d','e','s','\\', +'%','s',0}; + BOOL unsquash_guid(LPCWSTR in, LPWSTR out) { DWORD i,n=0; @@ -389,6 +406,26 @@ return rc; } +UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szUpgradeCode)); + squash_guid(szUpgradeCode,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key); + + return rc; +} + /************************************************************************* * MsiDecomposeDescriptorW [MSI.@] * @@ -484,3 +521,281 @@ return r; } + +UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid) +{ + DWORD r; + WCHAR szwGuid[GUID_SIZE]; + + TRACE("%ld %p\n",index,lpguid); + + if (NULL == lpguid) + return ERROR_INVALID_PARAMETER; + r = MsiEnumProductsW(index, szwGuid); + if( r == ERROR_SUCCESS ) + WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL); + + return r; +} + +UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) +{ + HKEY hkeyFeatures = 0; + DWORD r; + WCHAR szKeyName[33]; + + TRACE("%ld %p\n",index,lpguid); + + if (NULL == lpguid) + return ERROR_INVALID_PARAMETER; + + r = MSIREG_OpenFeatures(&hkeyFeatures); + if( r != ERROR_SUCCESS ) + goto end; + + r = RegEnumKeyW(hkeyFeatures, index, szKeyName, GUID_SIZE); + + unsquash_guid(szKeyName, lpguid); + +end: + + if( hkeyFeatures ) + RegCloseKey(hkeyFeatures); + + return r; +} + +UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, + LPSTR szFeature, LPSTR szParent) +{ + DWORD r; + WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE]; + LPWSTR szwProduct = NULL; + + TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent); + + if( szProduct ) + { + UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); + szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); + if( szwProduct ) + MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); + else + return ERROR_FUNCTION_FAILED; + } + + r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent); + if( r == ERROR_SUCCESS ) + { + WideCharToMultiByte(CP_ACP, 0, szwFeature, -1, + szFeature, GUID_SIZE, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, szwParent, -1, + szParent, GUID_SIZE, NULL, NULL); + } + + HeapFree( GetProcessHeap(), 0, szwProduct); + + return r; +} + +UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, + LPWSTR szFeature, LPWSTR szParent) +{ + HKEY hkeyProduct = 0; + DWORD r, sz; + + TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent); + + r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE); + if( r != ERROR_SUCCESS ) + goto end; + + sz = GUID_SIZE; + r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL); + +end: + if( hkeyProduct ) + RegCloseKey(hkeyProduct); + + return r; +} + +UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid) +{ + DWORD r; + WCHAR szwGuid[GUID_SIZE]; + + TRACE("%ld %p\n",index,lpguid); + + r = MsiEnumComponentsW(index, szwGuid); + if( r == ERROR_SUCCESS ) + WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL); + + return r; +} + +UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid) +{ + HKEY hkeyComponents = 0; + DWORD r; + WCHAR szKeyName[33]; + + TRACE("%ld %p\n",index,lpguid); + + r = MSIREG_OpenComponents(&hkeyComponents); + if( r != ERROR_SUCCESS ) + goto end; + + r = RegEnumKeyW(hkeyComponents, index, szKeyName, GUID_SIZE); + + unsquash_guid(szKeyName, lpguid); + +end: + + if( hkeyComponents ) + RegCloseKey(hkeyComponents); + + return r; +} + +UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct) +{ + DWORD r; + WCHAR szwProduct[GUID_SIZE]; + LPWSTR szwComponent = NULL; + + TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct); + + if( szComponent ) + { + UINT len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); + szwComponent = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); + if( szwComponent ) + MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); + else + return ERROR_FUNCTION_FAILED; + } + + r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct); + if( r == ERROR_SUCCESS ) + { + WideCharToMultiByte(CP_ACP, 0, szwProduct, -1, + szProduct, GUID_SIZE, NULL, NULL); + } + + HeapFree( GetProcessHeap(), 0, szwComponent); + + return r; +} + +UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct) +{ + HKEY hkeyComp = 0; + DWORD r, sz; + WCHAR szValName[GUID_SIZE]; + + TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct); + + r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE); + if( r != ERROR_SUCCESS ) + goto end; + + sz = GUID_SIZE; + r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL); + if( r != ERROR_SUCCESS ) + goto end; + + unsquash_guid(szValName, szProduct); + +end: + if( hkeyComp ) + RegCloseKey(hkeyComp); + + return r; +} + +UINT WINAPI MsiEnumComponentQualifiersA( LPSTR szComponent, DWORD iIndex, + LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, + LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf) +{ + FIXME("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, + lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, + pcchApplicationDataBuf); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, + LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, + LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf ) +{ + FIXME("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, + lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, + pcchApplicationDataBuf); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, + DWORD iProductIndex, LPWSTR lpProductBuf) +{ + UINT rc; + HKEY hkey; + WCHAR szKeyName[33]; + + TRACE("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved, + iProductIndex, lpProductBuf); + + if (NULL == szUpgradeCode) + return ERROR_INVALID_PARAMETER; + if (NULL == lpProductBuf) + return ERROR_INVALID_PARAMETER; + rc = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_NO_MORE_ITEMS; + goto end; + } + + rc = RegEnumKeyW(hkey, iProductIndex, szKeyName, + sizeof(szKeyName) / sizeof(szKeyName[0])); + + unsquash_guid(szKeyName, lpProductBuf); + RegCloseKey(hkey); + +end: + return rc; +} + +UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved, + DWORD iProductIndex, LPSTR lpProductBuf) +{ + UINT rc; + int len; + LPWSTR szUpgradeCodeW = NULL; + + TRACE("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved, + iProductIndex, lpProductBuf); + if (!szUpgradeCode) + return ERROR_INVALID_PARAMETER; + len = MultiByteToWideChar(CP_ACP, 0, szUpgradeCode, -1, NULL, 0); + szUpgradeCodeW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, + len * sizeof(WCHAR)); + if (szUpgradeCodeW) + { + WCHAR productW[39]; + + MultiByteToWideChar(CP_ACP, 0, szUpgradeCode, -1, szUpgradeCodeW, len); + rc = MsiEnumRelatedProductsW(szUpgradeCodeW, dwReserved, + iProductIndex, productW); + if (rc == ERROR_SUCCESS) + { + LPWSTR ptr; + + for (ptr = productW; *ptr; ) + *lpProductBuf++ = *ptr++; + } + HeapFree(GetProcessHeap(), 0, szUpgradeCodeW); + } + else + rc = ERROR_OUTOFMEMORY; + return rc; +} diff -urN wine-20050211/dlls/msi/sql.y wine-20050310/dlls/msi/sql.y --- wine-20050211/dlls/msi/sql.y 2005-01-20 21:39:15.000000000 +0100 +++ wine-20050310/dlls/msi/sql.y 2005-02-14 12:07:13.000000000 +0100 @@ -129,7 +129,8 @@ %type column table string_or_id %type selcollist -%type from unorderedsel oneselect onequery onecreate oneinsert oneupdate +%type from unorderedsel oneselect onequery onecreate oneinsert +%type oneupdate onedelete %type expr val column_val const_val %type column_type data_type data_type_l data_count %type column_def table_def @@ -159,6 +160,11 @@ SQL_input* sql = (SQL_input*) info; *sql->view = $1; } + | onedelete + { + SQL_input* sql = (SQL_input*) info; + *sql->view = $1; + } ; oneinsert: @@ -214,6 +220,17 @@ } ; +onedelete: + TK_DELETE from + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *delete = NULL; + + DELETE_CreateView( sql->db, &delete, $2 ); + $$ = delete; + } + ; + table_def: column_def TK_PRIMARY TK_KEY selcollist { diff -urN wine-20050211/dlls/msi/suminfo.c wine-20050310/dlls/msi/suminfo.c --- wine-20050211/dlls/msi/suminfo.c 2005-02-01 15:21:03.000000000 +0100 +++ wine-20050310/dlls/msi/suminfo.c 2005-03-10 12:15:40.000000000 +0100 @@ -108,11 +108,9 @@ if( FAILED( r ) ) { ERR("IStorage -> IPropertySetStorage failed\n"); - if (db) - msiobj_release(&db->hdr); - return ERROR_FUNCTION_FAILED; + ret = ERROR_FUNCTION_FAILED; + goto end; } - ERR("storage = %p propertysetstorage = %p\n", db->storage, psstg); grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE; r = IPropertySetStorage_Open( psstg, &FMTID_SummaryInformation, grfMode, &ps ); @@ -135,7 +133,7 @@ suminfo->propstg = ps; handle = alloc_msihandle( &suminfo->hdr ); if( handle ) - *phSummaryInfo = handle; + *phSummaryInfo = handle; else ret = ERROR_FUNCTION_FAILED; msiobj_release( &suminfo->hdr ); @@ -145,7 +143,7 @@ IPropertyStorage_Release(ps); if( psstg ) IPropertySetStorage_Release(psstg); - if (db) + if( db ) msiobj_release(&db->hdr); return ret; @@ -161,6 +159,7 @@ if( !suminfo ) return ERROR_INVALID_HANDLE; + msiobj_release( &suminfo->hdr ); return ERROR_CALL_NOT_IMPLEMENTED; } @@ -172,6 +171,7 @@ HRESULT r; PROPSPEC spec; PROPVARIANT var; + UINT rc = ERROR_SUCCESS; TRACE("%ld %d %p %p %p %p %p\n", hSummaryInfo, uiProperty, puiDataType, piValue, @@ -186,7 +186,10 @@ r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); if( FAILED(r) ) - return ERROR_FUNCTION_FAILED; + { + rc = ERROR_FUNCTION_FAILED; + goto end; + } if( puiDataType ) *puiDataType = var.vt; @@ -215,7 +218,9 @@ break; } - return ERROR_SUCCESS; +end: + msiobj_release( &suminfo->hdr ); + return rc; } UINT WINAPI MsiSummaryInfoGetPropertyW( @@ -226,6 +231,7 @@ HRESULT r; PROPSPEC spec; PROPVARIANT var; + UINT rc = ERROR_SUCCESS; TRACE("%ld %d %p %p %p %p %p\n", hSummaryInfo, uiProperty, puiDataType, piValue, @@ -240,7 +246,10 @@ r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); if( FAILED(r) ) - return ERROR_FUNCTION_FAILED; + { + rc = ERROR_FUNCTION_FAILED; + goto end; + } if( puiDataType ) *puiDataType = var.vt; @@ -270,24 +279,31 @@ break; } - return ERROR_SUCCESS; +end: + msiobj_release( &suminfo->hdr ); + return rc; } UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, UINT uiDataType, INT iValue, - FILETIME* pftValue, LPSTR szValue) + FILETIME* pftValue, LPSTR szValue ) { + FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, + uiDataType, iValue, pftValue, debugstr_a(szValue) ); return ERROR_CALL_NOT_IMPLEMENTED; } UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE hSummaryInfo, UINT uiProperty, UINT uiDataType, INT iValue, - FILETIME* pftValue, LPWSTR szValue) + FILETIME* pftValue, LPWSTR szValue ) { + FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, + uiDataType, iValue, pftValue, debugstr_w(szValue) ); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE hSummaryInfo) +UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE hSummaryInfo ) { + FIXME("%ld\n", hSummaryInfo ); return ERROR_CALL_NOT_IMPLEMENTED; } diff -urN wine-20050211/dlls/msi/table.c wine-20050310/dlls/msi/table.c --- wine-20050211/dlls/msi/table.c 2005-02-10 20:19:36.000000000 +0100 +++ wine-20050310/dlls/msi/table.c 2005-02-16 17:06:05.000000000 +0100 @@ -1220,7 +1220,10 @@ TRACE("%p %p\n", tv, record); if( tv->table ) - return ERROR_FUNCTION_FAILED; + { + release_table( tv->db, tv->table ); + tv->table = NULL; + } r = get_table( tv->db, tv->name, &tv->table ); if( r != ERROR_SUCCESS ) diff -urN wine-20050211/dlls/msi/tests/db.c wine-20050310/dlls/msi/tests/db.c --- wine-20050211/dlls/msi/tests/db.c 2005-01-27 11:43:27.000000000 +0100 +++ wine-20050310/dlls/msi/tests/db.c 2005-02-26 18:41:36.000000000 +0100 @@ -41,6 +41,9 @@ res = MsiCloseHandle( hdb ); ok( res == ERROR_SUCCESS , "Failed to close database" ); + + res = DeleteFile( szName ); + ok( res == TRUE, "Falled to delete database\n" ); } void test_msiinsert(void) diff -urN wine-20050211/dlls/msi/where.c wine-20050310/dlls/msi/where.c --- wine-20050211/dlls/msi/where.c 2005-02-08 14:44:25.000000000 +0100 +++ wine-20050310/dlls/msi/where.c 2005-02-16 17:06:05.000000000 +0100 @@ -247,6 +247,7 @@ if( !wv->reorder ) return ERROR_FUNCTION_FAILED; + wv->row_count = 0; for( i=0; i resize) { resize = (written == -1 ? resize * 2 : written + 1); diff -urN wine-20050211/dlls/msvcrt/mbcs.c wine-20050310/dlls/msvcrt/mbcs.c --- wine-20050211/dlls/msvcrt/mbcs.c 2004-07-24 01:02:10.000000000 +0200 +++ wine-20050310/dlls/msvcrt/mbcs.c 2005-02-25 15:07:57.000000000 +0100 @@ -796,7 +796,7 @@ */ int _ismbstrail(const unsigned char* start, const unsigned char* str) { - /* Must not be a lead, and must be preceeded by one */ + /* Must not be a lead, and must be preceded by one */ return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]); } diff -urN wine-20050211/dlls/msvcrt/msvcrt.h wine-20050310/dlls/msvcrt/msvcrt.h --- wine-20050211/dlls/msvcrt/msvcrt.h 2005-01-04 21:38:14.000000000 +0100 +++ wine-20050310/dlls/msvcrt/msvcrt.h 2005-03-07 12:00:46.000000000 +0100 @@ -576,6 +576,7 @@ MSVCRT_time_t MSVCRT_time(MSVCRT_time_t*); void * MSVCRT___p__daylight(void); MSVCRT_FILE* MSVCRT__fdopen(int, const char *); +int MSVCRT_vsnprintf(char *str, unsigned int len, const char *format, va_list valist); #ifndef __WINE_MSVCRT_TEST int _write(int,const void*,unsigned int); diff -urN wine-20050211/dlls/msvcrt/msvcrt.spec wine-20050310/dlls/msvcrt/msvcrt.spec --- wine-20050211/dlls/msvcrt/msvcrt.spec 2004-12-10 16:28:25.000000000 +0100 +++ wine-20050310/dlls/msvcrt/msvcrt.spec 2005-02-14 21:53:42.000000000 +0100 @@ -484,8 +484,8 @@ @ cdecl _unloaddll(long) @ cdecl _unlock(long) @ cdecl _utime(str ptr) -@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf -@ cdecl _vsnwprintf(ptr long wstr long) +@ cdecl _vsnprintf(ptr long ptr ptr) MSVCRT_vsnprintf +@ cdecl _vsnwprintf(ptr long wstr long) MSVCRT_vsnwprintf @ cdecl _waccess(wstr long) @ stub _wasctime #(ptr) MSVCRT__wasctime @ cdecl _wchdir(wstr) @@ -693,7 +693,7 @@ @ cdecl signal(long long) MSVCRT_signal @ cdecl sin(double) @ cdecl sinh(double) -@ varargs sprintf(ptr str) +@ varargs sprintf(ptr str) MSVCRT_sprintf @ cdecl sqrt(double) @ cdecl srand(long) @ varargs sscanf(str str) MSVCRT_sscanf diff -urN wine-20050211/dlls/msvcrt/scanf.h wine-20050310/dlls/msvcrt/scanf.h --- wine-20050211/dlls/msvcrt/scanf.h 2005-01-28 12:27:26.000000000 +0100 +++ wine-20050310/dlls/msvcrt/scanf.h 2005-03-10 12:44:19.000000000 +0100 @@ -427,6 +427,19 @@ int*n = va_arg(ap, int*); *n = consumed - (nch!=_EOF_); } + /* This is an odd one: according to the standard, + * "Execution of a %n directive does not increment the + * assignment count returned at the completion of + * execution" even if it wasn't suppressed with the + * '*' flag. The Corrigendum to the standard seems + * to contradict this (comment out the assignment to + * suppress below if you want to implement these + * alternate semantics) but the windows program I'm + * looking at expects the behavior I've coded here + * (which happens to be what glibc does as well). + */ + suppress = 1; + st = 1; } break; case '[': { diff -urN wine-20050211/dlls/msvcrt/tests/file.c wine-20050310/dlls/msvcrt/tests/file.c --- wine-20050211/dlls/msvcrt/tests/file.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050310/dlls/msvcrt/tests/file.c 2005-02-14 22:04:45.000000000 +0100 @@ -71,7 +71,7 @@ ok(feof(file) !=0,"feof doesn't signal EOF\n"); rewind(file); ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected\n"); - ok(lstrlenA(buffer) == strlen(outbuffer) -1,"fgets didn't read right size\n"); + ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size\n"); ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n"); ok(strlen(buffer) == 1,"fgets dropped chars\n"); ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars\n"); @@ -83,7 +83,7 @@ ok(feof(file) !=0,"feof doesn't signal EOF\n"); rewind(file); ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n"); - ok(lstrlenW(wbuffer) == (strlen(outbuffer) -1),"fgetws didn't read right size\n"); + ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n"); ok(fgetws(wbuffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected\n"); ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n"); fclose (file); diff -urN wine-20050211/dlls/msvcrt/tests/printf.c wine-20050310/dlls/msvcrt/tests/printf.c --- wine-20050211/dlls/msvcrt/tests/printf.c 2004-11-28 16:01:50.000000000 +0100 +++ wine-20050310/dlls/msvcrt/tests/printf.c 2005-03-05 11:46:46.000000000 +0100 @@ -3,6 +3,7 @@ * * Copyright 2002 Uwe Bonnes * Copyright 2004 Aneurin Price + * Copyright 2005 Mike McCormack * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,54 +27,248 @@ static void test_sprintf( void ) { char buffer[100]; - const char *I64d = "%I64d"; - const char *O4c = "%04c"; - const char *O4s = "%04s"; - const char *hash012p = "%#012p"; + const char *format; double pnumber=789456123; -/** WCHAR widestring[]={'w','i','d','e','s','t','r','i','n','g',0};**/ - sprintf(buffer,"%+#23.15e",pnumber); - todo_wine - { - ok(strstr(buffer,"e+008") != 0,"Sprintf different \"%s\"\n",buffer); - } - sprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff); - todo_wine - { - ok(strlen(buffer) == 11,"Problem with long long \"%s\"\n",buffer); - } - sprintf(buffer,"%lld",((ULONGLONG)0xffffffff)*0xffffffff); - todo_wine - { - ok(strlen(buffer) == 1,"Problem with \"ll\" interpretation \"%s\"\n",buffer); - } -/** This one actually crashes WINE at the moment, when using builtin msvcrt.dll. - sprintf(buffer,"%S",widestring); - todo_wine - { - ok(strlen(buffer) == 10,"Problem with \"%%S\" interpretation \"%s\"\n",buffer); - } - **/ - sprintf(buffer,O4c,'1'); - todo_wine - { - ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer); - } - sprintf(buffer,"%p",(void *)57); - todo_wine - { - ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); - } - sprintf(buffer,hash012p,(void *)57); - todo_wine - { - ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); - } - sprintf(buffer,O4s,"foo");/**Warning again**/ - todo_wine - { - ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer); - } + int x, r; + WCHAR wide[] = { 'w','i','d','e',0}; + + format = "%+#23.15e"; + r = sprintf(buffer,format,pnumber); + todo_wine { + ok(!strcmp(buffer,"+7.894561230000000e+008"),"exponent format incorrect\n"); + } + ok( r==23, "return count wrong\n"); + + todo_wine { + format = "%I64d"; + r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff); + ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n"); + ok( r==11, "return count wrong\n"); + } + + format = "%lld"; + r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff); + ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation\n"); + ok( r==1, "return count wrong\n"); + + format = "%S"; + r = sprintf(buffer,format,wide); + ok(!strcmp(buffer,"wide"),"Problem with wide string format\n"); + ok( r==4, "return count wrong\n"); + + format = "%04c"; + r = sprintf(buffer,format,'1'); + ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer); + ok( r==4, "return count wrong\n"); + + format = "%p"; + r = sprintf(buffer,format,(void *)57); + ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); + ok( r==8, "return count wrong\n"); + + format = "%#012p"; + r = sprintf(buffer,format,(void *)57); + ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly\n"); + ok( r==12, "return count wrong\n"); + + format = "%Fp"; + r = sprintf(buffer,format,(void *)57); + ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer); + ok( r==8, "return count wrong\n"); + + format = "%04s"; + r = sprintf(buffer,format,"foo"); + ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer); + ok( r==4, "return count wrong\n"); + + format = "%.1s"; + r = sprintf(buffer,format,"foo"); + ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer); + ok( r==1, "return count wrong\n"); + + format = "%.*s"; + r = sprintf(buffer,format,1,"foo"); + ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer); + ok( r==1, "return count wrong\n"); + + format = "%#-012p"; + r = sprintf(buffer,format,(void *)57); + ok(!strcmp(buffer,"0X00000039 "),"Pointer formatted incorrectly\n"); + ok( r==12, "return count wrong\n"); + + format = "hello"; + r = sprintf(buffer, format); + ok(!strcmp(buffer,"hello"), "failed\n"); + ok( r==5, "return count wrong\n"); + + format = "%ws"; + r = sprintf(buffer, format, wide); + ok(!strcmp(buffer,"wide"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%-10ws"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer,"wide "), "failed\n"); + ok( r==10, "return count wrong\n"); + + format = "%10ws"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer," wide"), "failed\n"); + ok( r==10, "return count wrong\n"); + + format = "%#+ -03whlls"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer,"wide"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%w0s"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer,"0s"), "failed\n"); + ok( r==2, "return count wrong\n"); + + format = "%w-s"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer,"-s"), "failed\n"); + ok( r==2, "return count wrong\n"); + + format = "%ls"; + r = sprintf(buffer, format, wide ); + ok(!strcmp(buffer,"wide"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%Ls"; + r = sprintf(buffer, format, "not wide" ); + ok(!strcmp(buffer,"not wide"), "failed\n"); + ok( r==8, "return count wrong\n"); + + format = "%b"; + r = sprintf(buffer, format); + ok(!strcmp(buffer,"b"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "%3c"; + r = sprintf(buffer, format,'a'); + ok(!strcmp(buffer," a"), "failed\n"); + ok( r==3, "return count wrong\n"); + + format = "%3d"; + r = sprintf(buffer, format,1234); + ok(!strcmp(buffer,"1234"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%3h"; + r = sprintf(buffer, format); + ok(!strcmp(buffer,""), "failed\n"); + ok( r==0, "return count wrong\n"); + + format = "%j%k%m%q%r%t%v%y%z"; + r = sprintf(buffer, format); + ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n"); + ok( r==9, "return count wrong\n"); + + format = "asdf%n"; + x = 0; + r = sprintf(buffer, format, &x ); + ok(x == 4, "should write to x\n"); + ok(!strcmp(buffer,"asdf"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%-1d"; + r = sprintf(buffer, format,2); + ok(!strcmp(buffer,"2"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "%2.4f"; + r = sprintf(buffer, format,8.6); + ok(!strcmp(buffer,"8.6000"), "failed\n"); + ok( r==6, "return count wrong\n"); + + todo_wine { + format = "%2.4e"; + r = sprintf(buffer, format,8.6); + ok(!strcmp(buffer,"8.6000e+000"), "failed\n"); + ok( r==11, "return count wrong\n"); + } + + format = "%2.4g"; + r = sprintf(buffer, format,8.6); + ok(!strcmp(buffer,"8.6"), "failed\n"); + ok( r==3, "return count wrong\n"); + + format = "%-i"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,"-1"), "failed\n"); + ok( r==2, "return count wrong\n"); + + format = "%-i"; + r = sprintf(buffer, format,1); + ok(!strcmp(buffer,"1"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "%+i"; + r = sprintf(buffer, format,1); + ok(!strcmp(buffer,"+1"), "failed\n"); + ok( r==2, "return count wrong\n"); + + format = "%o"; + r = sprintf(buffer, format,10); + ok(!strcmp(buffer,"12"), "failed\n"); + ok( r==2, "return count wrong\n"); + + format = "%p"; + r = sprintf(buffer, format,0); + ok(!strcmp(buffer,"00000000"), "failed\n"); + ok( r==8, "return count wrong\n"); + + format = "%s"; + r = sprintf(buffer, format,0); + ok(!strcmp(buffer,"(null)"), "failed\n"); + ok( r==6, "return count wrong\n"); + + format = "%s"; + r = sprintf(buffer, format,"%%%%"); + ok(!strcmp(buffer,"%%%%"), "failed\n"); + ok( r==4, "return count wrong\n"); + + format = "%u"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,"4294967295"), "failed\n"); + ok( r==10, "return count wrong\n"); + + format = "%w"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,""), "failed\n"); + ok( r==0, "return count wrong\n"); + + format = "%h"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,""), "failed\n"); + ok( r==0, "return count wrong\n"); + + format = "%z"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,"z"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "%j"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,"j"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "%F"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,""), "failed\n"); + ok( r==0, "return count wrong\n"); + + format = "%H"; + r = sprintf(buffer, format,-1); + ok(!strcmp(buffer,"H"), "failed\n"); + ok( r==1, "return count wrong\n"); + + format = "x%cx"; + r = sprintf(buffer, format, 0x100+'X'); + ok(!strcmp(buffer,"xXx"), "failed\n"); + ok( r==3, "return count wrong\n"); } static void test_swprintf( void ) diff -urN wine-20050211/dlls/msvcrt/tests/scanf.c wine-20050310/dlls/msvcrt/tests/scanf.c --- wine-20050211/dlls/msvcrt/tests/scanf.c 2005-01-28 12:27:26.000000000 +0100 +++ wine-20050310/dlls/msvcrt/tests/scanf.c 2005-03-10 12:44:19.000000000 +0100 @@ -117,6 +117,14 @@ ok(hour == 18, "Field 1 incorrect: %d\n", hour); ok(min == 59, "Field 2 incorrect: %d\n", min); ok(c == 0x55, "Field 3 incorrect: 0x%02x\n", c); + + /* Check %n (also whitespace in format strings and %s) */ + buffer[0]=0; buffer1[0]=0; + ret = sscanf("abc def", "%s %n%s", buffer, &number_so_far, buffer1); + ok(strcmp(buffer, "abc")==0, "First %%s read incorrectly: %s\n", buffer); + ok(strcmp(buffer1,"def")==0, "Second %%s read incorrectly: %s\n", buffer1); + ok(number_so_far==6, "%%n yielded wrong result: %d\n", number_so_far); + ok(ret == 2, "%%n shouldn't count as a conversion: %d\n", ret); } START_TEST(scanf) diff -urN wine-20050211/dlls/msvcrt/wcs.c wine-20050310/dlls/msvcrt/wcs.c --- wine-20050211/dlls/msvcrt/wcs.c 2004-06-25 03:19:15.000000000 +0200 +++ wine-20050310/dlls/msvcrt/wcs.c 2005-03-05 11:46:46.000000000 +0100 @@ -21,6 +21,7 @@ #include #include #include +#include #include "msvcrt.h" #include "winnls.h" #include "wine/unicode.h" @@ -178,184 +179,501 @@ return ret; } -static int MSVCRT_vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist) + +typedef struct pf_output_t { - unsigned int written = 0; - const WCHAR *iter = format; - char bufa[256], fmtbufa[64], *fmta; + int used; + int len; + BOOL unicode; + union { + LPWSTR W; + LPSTR A; + } buf; +} pf_output; + +typedef struct pf_flags_t +{ + char Sign, LeftAlign, Alternate, PadZero; + char FieldLength, Precision; + char IntegerLength, IntegerDouble; + char WideString; + char Format; +} pf_flags; + +/* + * writes a string of characters to the output + * returns -1 if the string doesn't fit in the output buffer + * return the length of the string if all characters were written + */ +static inline int pf_output_stringW( pf_output *out, LPCWSTR str, int len ) +{ + int space = out->len - out->used; + + if( len < 0 ) + len = strlenW( str ); + if( out->unicode ) + { + LPWSTR p = out->buf.W + out->used; - while (*iter) + if( space >= len ) + { + memcpy( p, str, len*sizeof(WCHAR) ); + out->used += len; + return len; + } + if( space > 0 ) + memcpy( p, str, space*sizeof(WCHAR) ); + out->used += len; + } + else { - while (*iter && *iter != '%') + int n = WideCharToMultiByte( CP_ACP, 0, str, len, NULL, 0, NULL, NULL ); + LPSTR p = out->buf.A + out->used; + + if( space >= n ) { - if (written++ >= len) - return -1; - *str++ = *iter++; + WideCharToMultiByte( CP_ACP, 0, str, len, p, n, NULL, NULL ); + out->used += n; + return len; } - if (*iter == '%') + if( space > 0 ) + WideCharToMultiByte( CP_ACP, 0, str, len, p, space, NULL, NULL ); + out->used += n; + } + return -1; +} + +static inline int pf_output_stringA( pf_output *out, LPCSTR str, int len ) +{ + int space = out->len - out->used; + + if( len < 0 ) + len = strlen( str ); + if( !out->unicode ) + { + LPSTR p = out->buf.A + out->used; + + if( space >= len ) { - if (iter[1] == '%') - { - if (written++ >= len) - return -1; - *str++ = '%'; /* "%%"->'%' */ - iter += 2; - continue; - } + memcpy( p, str, len ); + out->used += len; + return len; + } + if( space > 0 ) + memcpy( p, str, space ); + out->used += len; + } + else + { + int n = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ); + LPWSTR p = out->buf.W + out->used; - fmta = fmtbufa; - *fmta++ = *iter++; - while (*iter == '0' || - *iter == '+' || - *iter == '-' || - *iter == ' ' || - *iter == '*' || - *iter == '#') - { - if (*iter == '*') - { - char *buffiter = bufa; - int fieldlen = va_arg(valist, int); - sprintf(buffiter, "%d", fieldlen); - while (*buffiter) - *fmta++ = *buffiter++; - } - else - *fmta++ = *iter; - iter++; - } + if( space >= n ) + { + MultiByteToWideChar( CP_ACP, 0, str, len, p, n ); + out->used += n; + return len; + } + if( space > 0 ) + MultiByteToWideChar( CP_ACP, 0, str, len, p, space ); + out->used += n; + } + return -1; +} - while (isdigit(*iter)) - *fmta++ = *iter++; +static inline int pf_fill( pf_output *out, int len, pf_flags *flags, char left ) +{ + int i, r = 0; - if (*iter == '.') - { - *fmta++ = *iter++; - if (*iter == '*') - { - char *buffiter = bufa; - int fieldlen = va_arg(valist, int); - sprintf(buffiter, "%d", fieldlen); - while (*buffiter) - *fmta++ = *buffiter++; - } - else - while (isdigit(*iter)) - *fmta++ = *iter++; - } - if (*iter == 'h' || *iter == 'l') - *fmta++ = *iter++; + if( ( !left && flags->LeftAlign ) || + ( left && !flags->LeftAlign ) || + ( left && flags->PadZero ) ) + { + for( i=0; (i<(flags->FieldLength-len)) && (r>=0); i++ ) + { + if( flags->PadZero ) + r = pf_output_stringA( out, "0", 1 ); + else + r = pf_output_stringA( out, " ", 1 ); + } + } - switch (*iter) - { - case 'S': - { - static const char *none = "(null)"; - const char *astr = va_arg(valist, const char *); - const char *striter = astr ? astr : none; - int r, n; - while (*striter) - { - if (written >= len) - return -1; - n = 1; - if( IsDBCSLeadByte( *striter ) ) - n++; - r = MultiByteToWideChar( CP_ACP, 0, - striter, n, str, len - written ); - striter += n; - str += r; - written += r; - } - iter++; + return r; +} + +static inline int pf_output_format_W( pf_output *out, LPCWSTR str, + int len, pf_flags *flags ) +{ + int r = 0; + + if( len < 0 ) + len = strlenW( str ); + + if (flags->Precision && flags->Precision < len) + len = flags->Precision; + + r = pf_fill( out, len, flags, 1 ); + + if( r>=0 ) + r = pf_output_stringW( out, str, len ); + + if( r>=0 ) + r = pf_fill( out, len, flags, 0 ); + + return r; +} + +static inline int pf_output_format_A( pf_output *out, LPCSTR str, + int len, pf_flags *flags ) +{ + int r = 0; + + if( len < 0 ) + len = strlen( str ); + + if (flags->Precision && flags->Precision < len) + len = flags->Precision; + + r = pf_fill( out, len, flags, 1 ); + + if( r>=0 ) + r = pf_output_stringA( out, str, len ); + + if( r>=0 ) + r = pf_fill( out, len, flags, 0 ); + + return r; +} + +static inline BOOL pf_is_double_format( char fmt ) +{ + char float_fmts[] = "aefg"; + if (!fmt) + return FALSE; + fmt = tolower( fmt ); + return strchr( float_fmts, fmt ) ? TRUE : FALSE; +} + +static inline BOOL pf_is_valid_format( char fmt ) +{ + char float_fmts[] = "acdefginoux"; + if (!fmt) + return FALSE; + fmt = tolower( fmt ); + return strchr( float_fmts, fmt ) ? TRUE : FALSE; +} + +static void pf_rebuild_format_string( char *p, pf_flags *flags ) +{ + *p++ = '%'; + if( flags->Sign ) + *p++ = flags->Sign; + if( flags->LeftAlign ) + *p++ = flags->LeftAlign; + if( flags->Alternate ) + *p++ = flags->Alternate; + if( flags->PadZero ) + *p++ = flags->PadZero; + if( flags->FieldLength ) + { + sprintf(p, "%d", flags->FieldLength); + p += strlen(p); + } + if( flags->Precision ) + { + sprintf(p, ".%d", flags->Precision); + p += strlen(p); + } + *p++ = flags->Format; + *p++ = 0; +} + +/********************************************************************* + * pf_vsnprintf (INTERNAL) + * + * implements both A and W vsnprintf functions + */ +static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist ) +{ + int r; + LPCWSTR q, p = format; + pf_flags flags; + + while (*p) + { + q = strchrW( p, '%' ); + + /* there's no % characters left, output the rest of the string */ + if( !q ) + { + r = pf_output_stringW(out, p, -1); + if( r<0 ) + return r; + p += r; + continue; + } + + /* there's characters before the %, output them */ + if( q != p ) + { + r = pf_output_stringW(out, p, q - p); + if( r<0 ) + return r; + p = q; + } + + /* we must be at a % now, skip over it */ + assert( *p == '%' ); + p++; + + /* output a single % character */ + if( *p == '%' ) + { + r = pf_output_stringW(out, p, 1); + if( r<0 ) + return r; + continue; + } + + /* parse the flags */ + memset( &flags, 0, sizeof flags ); + while (*p) + { + if( *p == '+' || *p == ' ' ) + flags.Sign = '+'; + else if( *p == '-' ) + flags.LeftAlign = *p; + else if( *p == '0' ) + flags.PadZero = *p; + else if( *p == '#' ) + flags.Alternate = *p; + else break; - } + p++; + } + + /* deal with the field width specifier */ + flags.FieldLength = 0; + if( *p == '*' ) + flags.FieldLength = va_arg( valist, int ); + else while( isdigit(*p) ) + { + flags.FieldLength *= 10; + flags.FieldLength += *p++ - '0'; + } - case 's': + /* deal with precision */ + if( *p == '.' ) + { + p++; + if( *p == '*' ) { - static const WCHAR none[] = { '(','n','u','l','l',')',0 }; - const WCHAR *wstr = va_arg(valist, const WCHAR *); - const WCHAR *striter = wstr ? wstr : none; - while (*striter) - { - if (written++ >= len) - return -1; - *str++ = *striter++; - } - iter++; - break; + flags.Precision = va_arg( valist, int ); + p++; } + else while( isdigit(*p) ) + { + flags.Precision *= 10; + flags.Precision += *p++ - '0'; + } + } - case 'c': - if (written++ >= len) - return -1; - *str++ = (WCHAR)va_arg(valist, int); - iter++; - break; - - default: + /* deal with integer width modifier */ + while( *p ) + { + if( *p == 'h' || *p == 'l' || *p == 'L' ) { - /* For non wc types, use system sprintf and append to wide char output */ - /* FIXME: for unrecognised types, should ignore % when printing */ - char *bufaiter = bufa; - if (*iter == 'p') - sprintf(bufaiter, "%08lX", va_arg(valist, long)); + if( flags.IntegerLength == *p ) /* FIXME: this is wrong */ + flags.IntegerDouble++; else - { - *fmta++ = *iter; - *fmta = '\0'; - if (*iter == 'a' || *iter == 'A' || - *iter == 'e' || *iter == 'E' || - *iter == 'f' || *iter == 'F' || - *iter == 'g' || *iter == 'G') - sprintf(bufaiter, fmtbufa, va_arg(valist, double)); - else - { - /* FIXME: On 32 bit systems this doesn't handle int 64's. - * on 64 bit systems this doesn't work for 32 bit types - */ - sprintf(bufaiter, fmtbufa, va_arg(valist, void *)); - } - } - while (*bufaiter) - { - if (written++ >= len) - return -1; - *str++ = *bufaiter++; - } - iter++; - break; - } + flags.IntegerLength = *p; + p++; } + else if( *p == 'w' ) + flags.WideString = *p++; + else if( *p == 'F' ) + p++; /* ignore */ + else + break; + } + + flags.Format = *p; + r = 0; + + /* output a unicode string */ + if( ( flags.Format == 's' && (flags.WideString || flags.IntegerLength == 'l' )) || + ( !out->unicode && flags.Format == 'S' ) || + ( out->unicode && flags.Format == 's' ) ) + { + LPCWSTR str = va_arg( valist, const WCHAR * ); + + if( str ) + r = pf_output_format_W( out, str, -1, &flags ); + else + r = pf_output_format_A( out, "(null)", -1, &flags ); + } + + /* output a ASCII string */ + else if( ( flags.Format == 's' && flags.IntegerLength == 'h' ) || + ( out->unicode && flags.Format == 'S' ) || + ( !out->unicode && flags.Format == 's' ) ) + { + LPCSTR str = va_arg( valist, const CHAR * ); + + if( str ) + r = pf_output_format_A( out, str, -1, &flags ); + else + r = pf_output_format_A( out, "(null)", -1, &flags ); + } + + /* output a single wide character */ + else if( ( flags.Format == 'c' && flags.IntegerLength == 'w' ) || + ( out->unicode && flags.Format == 'c' ) || + ( !out->unicode && flags.Format == 'C' ) ) + { + WCHAR ch = va_arg( valist, int ); + + r = pf_output_format_W( out, &ch, 1, &flags ); + } + + /* output a single ascii character */ + else if( ( flags.Format == 'c' && flags.IntegerLength == 'h' ) || + ( out->unicode && flags.Format == 'C' ) || + ( !out->unicode && flags.Format == 'c' ) ) + { + CHAR ch = va_arg( valist, int ); + + r = pf_output_format_A( out, &ch, 1, &flags ); + } + + /* output a pointer */ + else if( flags.Format == 'p' ) + { + char pointer[10]; + + flags.PadZero = 0; + if( flags.Alternate ) + sprintf(pointer, "0X%08lX", va_arg(valist, long)); + else + sprintf(pointer, "%08lX", va_arg(valist, long)); + r = pf_output_format_A( out, pointer, -1, &flags ); + } + + /* deal with %n */ + else if( flags.Format == 'n' ) + { + int *x = va_arg(valist, int *); + *x = out->used; } + + /* deal with integers and floats using libc's printf */ + else if( pf_is_valid_format( flags.Format ) ) + { + char fmt[20], number[40], *x = number; + + if( flags.FieldLength >= sizeof number ) + x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 ); + + pf_rebuild_format_string( fmt, &flags ); + + if( pf_is_double_format( flags.Format ) ) + sprintf( number, fmt, va_arg(valist, double) ); + else + sprintf( number, fmt, va_arg(valist, int) ); + + r = pf_output_stringA( out, number, -1 ); + if( x != number ) + HeapFree( GetProcessHeap(), 0, number ); + } + else + continue; + + if( r<0 ) + return r; + p++; } - if (written >= len) - return -1; - *str++ = 0; - return (int)written; + + /* check we reached the end, and null terminate the string */ + assert( *p == 0 ); + r = pf_output_stringW( out, p, 1 ); + if( r<0 ) + return r; + + return out->used - 1; } /********************************************************************* - * swprintf (MSVCRT.@) + * _vsnprintf (MSVCRT.@) */ -int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... ) +int MSVCRT_vsnprintf( char *str, unsigned int len, + const char *format, va_list valist ) +{ + DWORD sz; + LPWSTR formatW = NULL; + pf_output out; + int r; + + out.unicode = FALSE; + out.buf.A = str; + out.used = 0; + out.len = len; + + if( format ) + { + sz = MultiByteToWideChar( CP_ACP, 0, format, -1, NULL, 0 ); + formatW = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, format, -1, formatW, sz ); + } + + r = pf_vsnprintf( &out, formatW, valist ); + + HeapFree( GetProcessHeap(), 0, formatW ); + + return r; +} + +/********************************************************************* + * _vsnwsprintf (MSVCRT.@) + */ +int MSVCRT_vsnwprintf( MSVCRT_wchar_t *str, unsigned int len, + const WCHAR *format, va_list valist ) +{ + pf_output out; + + out.unicode = TRUE; + out.buf.W = str; + out.used = 0; + out.len = len; + + return pf_vsnprintf( &out, format, valist ); +} + +/********************************************************************* + * sprintf (MSVCRT.@) + */ +int MSVCRT_sprintf( char *str, const char *format, ... ) { va_list ap; int r; va_start( ap, format ); - r = MSVCRT_vsnprintfW( str, INT_MAX, format, ap ); + r = MSVCRT_vsnprintf( str, INT_MAX, format, ap ); va_end( ap ); return r; } /********************************************************************* - * _vsnwprintf (MSVCRT.@) + * swprintf (MSVCRT.@) */ -int _vsnwprintf(MSVCRT_wchar_t *str, unsigned int len, - const MSVCRT_wchar_t *format, va_list valist) +int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... ) { - return MSVCRT_vsnprintfW(str, len, format, valist); + va_list ap; + int r; + + va_start( ap, format ); + r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap ); + va_end( ap ); + return r; } /********************************************************************* @@ -363,7 +681,7 @@ */ int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args ) { - return MSVCRT_vsnprintfW( str, INT_MAX, format, args ); + return MSVCRT_vsnwprintf( str, INT_MAX, format, args ); } /********************************************************************* diff -urN wine-20050211/dlls/msvideo/msvideo_main.c wine-20050310/dlls/msvideo/msvideo_main.c --- wine-20050211/dlls/msvideo/msvideo_main.c 2005-01-17 16:33:43.000000000 +0100 +++ wine-20050310/dlls/msvideo/msvideo_main.c 2005-02-17 12:51:01.000000000 +0100 @@ -116,14 +116,15 @@ lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey); if (lRet == ERROR_SUCCESS) { - RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0); - for (i = 0; i < cnt; i++) + DWORD numkeys; + RegQueryInfoKeyA( hKey, 0, 0, 0, &numkeys, 0, 0, 0, 0, 0, 0, 0); + for (i = 0; i < numkeys; i++) { bufLen = sizeof(buf) / sizeof(buf[0]); lRet = RegEnumKeyExA(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite); if (lRet != ERROR_SUCCESS) continue; if (strncasecmp(buf, fccTypeStr, 5) || buf[9] != '=') continue; - if ((result = handler(buf, i, param))) break; + if ((result = handler(buf, cnt++, param))) break; } RegCloseKey( hKey ); } @@ -132,10 +133,10 @@ /* if that didn't work, go through the values in system.ini */ if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini")) { - for (s = buf; *s; cnt++, s += strlen(s) + 1) + for (s = buf; *s; s += strlen(s) + 1) { if (strncasecmp(s, fccTypeStr, 5) || s[9] != '=') continue; - if ((result = handler(s, cnt, param))) break; + if ((result = handler(s, cnt++, param))) break; } } diff -urN wine-20050211/dlls/ntdll/cdrom.c wine-20050310/dlls/ntdll/cdrom.c --- wine-20050211/dlls/ntdll/cdrom.c 2005-01-07 16:33:58.000000000 +0100 +++ wine-20050310/dlls/ntdll/cdrom.c 2005-03-02 13:23:22.000000000 +0100 @@ -92,10 +92,10 @@ lack the following constants. */ #ifndef CD_SECS - #define CD_SECS 60 /* seconds per minute */ +# define CD_SECS 60 /* seconds per minute */ #endif #ifndef CD_FRAMES - #define CD_FRAMES 75 /* frames per second */ +# define CD_FRAMES 75 /* frames per second */ #endif /* definitions taken from libdvdcss */ diff -urN wine-20050211/dlls/ntdll/critsection.c wine-20050310/dlls/ntdll/critsection.c --- wine-20050211/dlls/ntdll/critsection.c 2004-09-06 22:26:23.000000000 +0200 +++ wine-20050310/dlls/ntdll/critsection.c 2005-02-24 14:15:36.000000000 +0100 @@ -264,7 +264,7 @@ rec.ExceptionRecord = NULL; rec.ExceptionAddress = RtlRaiseException; /* sic */ rec.NumberParameters = 1; - rec.ExceptionInformation[0] = (DWORD)crit; + rec.ExceptionInformation[0] = (ULONG_PTR)crit; RtlRaiseException( &rec ); } } diff -urN wine-20050211/dlls/ntdll/exception.c wine-20050310/dlls/ntdll/exception.c --- wine-20050211/dlls/ntdll/exception.c 2004-12-14 21:03:23.000000000 +0100 +++ wine-20050310/dlls/ntdll/exception.c 2005-02-24 14:15:36.000000000 +0100 @@ -266,7 +266,7 @@ /* Check frame address */ if (((void*)frame < NtCurrentTeb()->Tib.StackLimit) || ((void*)(frame+1) > NtCurrentTeb()->Tib.StackBase) || - (int)frame & 3) + (ULONG_PTR)frame & 3) { rec->ExceptionFlags |= EH_STACK_INVALID; break; diff -urN wine-20050211/dlls/ntdll/file.c wine-20050310/dlls/ntdll/file.c --- wine-20050211/dlls/ntdll/file.c 2005-01-14 20:54:39.000000000 +0100 +++ wine-20050310/dlls/ntdll/file.c 2005-03-02 13:23:22.000000000 +0100 @@ -1441,9 +1441,9 @@ break; } #elif defined (__APPLE__) - #include - #include /* for kCFBooleanTrue, kCFBooleanFalse */ - #include +# include +# include /* for kCFBooleanTrue, kCFBooleanFalse */ +# include struct statfs stfs; info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM; diff -urN wine-20050211/dlls/ntdll/handletable.c wine-20050310/dlls/ntdll/handletable.c --- wine-20050211/dlls/ntdll/handletable.c 2004-12-07 15:47:13.000000000 +0100 +++ wine-20050310/dlls/ntdll/handletable.c 2005-02-22 20:33:50.000000000 +0100 @@ -82,7 +82,7 @@ /* native version only releases committed memory, but we also release reserved */ return NtFreeVirtualMemory( - GetCurrentProcess(), + NtCurrentProcess(), &HandleTable->FirstHandle, &Size, MEM_RELEASE); @@ -111,7 +111,7 @@ /* reserve memory for the handles, but don't commit it yet because we * probably won't use most of it and it will use up physical memory */ status = NtAllocateVirtualMemory( - GetCurrentProcess(), + NtCurrentProcess(), &FirstHandleAddr, 0, &MaxSize, @@ -134,7 +134,7 @@ return STATUS_NO_MEMORY; /* the handle table is completely full */ status = NtAllocateVirtualMemory( - GetCurrentProcess(), + NtCurrentProcess(), &NextAvailAddr, 0, &CommitSize, diff -urN wine-20050211/dlls/ntdll/heap.c wine-20050310/dlls/ntdll/heap.c --- wine-20050211/dlls/ntdll/heap.c 2005-01-24 12:27:27.000000000 +0100 +++ wine-20050310/dlls/ntdll/heap.c 2005-03-03 14:50:21.000000000 +0100 @@ -246,6 +246,47 @@ } +void HEAP_DumpEntry( LPPROCESS_HEAP_ENTRY entry ) +{ + WORD rem_flags; + TRACE( "Dumping entry %p\n", entry ); + TRACE( "lpData\t\t: %p\n", entry->lpData ); + TRACE( "cbData\t\t: %08lx\n", entry->cbData); + TRACE( "cbOverhead\t: %08x\n", entry->cbOverhead); + TRACE( "iRegionIndex\t: %08x\n", entry->iRegionIndex); + TRACE( "WFlags\t\t: "); + if (entry->wFlags & PROCESS_HEAP_REGION) + TRACE( "PROCESS_HEAP_REGION "); + if (entry->wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) + TRACE( "PROCESS_HEAP_UNCOMMITTED_RANGE "); + if (entry->wFlags & PROCESS_HEAP_ENTRY_BUSY) + TRACE( "PROCESS_HEAP_ENTRY_BUSY "); + if (entry->wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) + TRACE( "PROCESS_HEAP_ENTRY_MOVEABLE "); + if (entry->wFlags & PROCESS_HEAP_ENTRY_DDESHARE) + TRACE( "PROCESS_HEAP_ENTRY_DDESHARE "); + rem_flags = entry->wFlags & + ~(PROCESS_HEAP_REGION | PROCESS_HEAP_UNCOMMITTED_RANGE | + PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_MOVEABLE| + PROCESS_HEAP_ENTRY_DDESHARE); + if (rem_flags) + TRACE( "Unknown %08x", rem_flags); + TRACE( "\n"); + if ((entry->wFlags & PROCESS_HEAP_ENTRY_BUSY ) + && (entry->wFlags & PROCESS_HEAP_ENTRY_MOVEABLE)) + { + /* Treat as block */ + TRACE( "BLOCK->hMem\t\t:%p\n", entry->u.Block.hMem); + } + if (entry->wFlags & PROCESS_HEAP_REGION) + { + TRACE( "Region.dwCommittedSize\t:%08lx\n",entry->u.Region.dwCommittedSize); + TRACE( "Region.dwUnCommittedSize\t:%08lx\n",entry->u.Region.dwUnCommittedSize); + TRACE( "Region.lpFirstBlock\t:%p\n",entry->u.Region.lpFirstBlock); + TRACE( "Region.lpLastBlock\t:%p\n",entry->u.Region.lpLastBlock); + } +} + /*********************************************************************** * HEAP_GetPtr * RETURNS @@ -338,7 +379,7 @@ if (size <= subheap->commitSize) return TRUE; size -= subheap->commitSize; ptr = (char *)subheap + subheap->commitSize; - if (NtAllocateVirtualMemory( GetCurrentProcess(), &ptr, 0, + if (NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) { WARN("Could not commit %08lx bytes at %p for heap %p\n", @@ -367,7 +408,7 @@ decommit_size = subheap->commitSize - size; addr = (char *)subheap + size; - if (NtFreeVirtualMemory( GetCurrentProcess(), &addr, &decommit_size, MEM_DECOMMIT )) + if (NtFreeVirtualMemory( NtCurrentProcess(), &addr, &decommit_size, MEM_DECOMMIT )) { WARN("Could not decommit %08lx bytes at %08lx for heap %p\n", decommit_size, (DWORD)((char *)subheap + size), subheap->heap ); @@ -477,7 +518,7 @@ if (pPrev) pPrev->next = subheap->next; /* Free the memory */ subheap->magic = 0; - NtFreeVirtualMemory( GetCurrentProcess(), (void **)&subheap, &size, MEM_RELEASE ); + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&subheap, &size, MEM_RELEASE ); return; } @@ -524,7 +565,7 @@ if (flags & HEAP_SHARED) commitSize = totalSize; /* always commit everything in a shared heap */ - if (NtAllocateVirtualMemory( GetCurrentProcess(), &address, 0, + if (NtAllocateVirtualMemory( NtCurrentProcess(), &address, 0, &commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) { WARN("Could not commit %08lx bytes for sub-heap %p\n", commitSize, address ); @@ -579,7 +620,7 @@ HANDLE sem = heap->critSection.LockSemaphore; if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 ); - NtDuplicateObject( GetCurrentProcess(), sem, GetCurrentProcess(), &sem, 0, 0, + NtDuplicateObject( NtCurrentProcess(), sem, NtCurrentProcess(), &sem, 0, 0, DUP_HANDLE_MAKE_GLOBAL | DUP_HANDLE_SAME_ACCESS | DUP_HANDLE_CLOSE_SOURCE ); heap->critSection.LockSemaphore = sem; } @@ -613,7 +654,7 @@ if (!address) { /* allocate the memory block */ - if (NtAllocateVirtualMemory( GetCurrentProcess(), &address, 0, &totalSize, + if (NtAllocateVirtualMemory( NtCurrentProcess(), &address, 0, &totalSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE )) { WARN("Could not allocate %08lx bytes\n", totalSize ); @@ -627,7 +668,7 @@ address, flags, commitSize, totalSize )) { ULONG size = 0; - if (!base) NtFreeVirtualMemory( GetCurrentProcess(), &address, &size, MEM_RELEASE ); + if (!base) NtFreeVirtualMemory( NtCurrentProcess(), &address, &size, MEM_RELEASE ); return NULL; } @@ -1066,7 +1107,7 @@ SUBHEAP *next = subheap->next; ULONG size = 0; void *addr = subheap; - NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); + NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); subheap = next; } return 0; @@ -1452,7 +1493,7 @@ /*********************************************************************** * RtlValidateHeap (NTDLL.@) * - * Determine if a block is a valid alloction from a heap. + * Determine if a block is a valid allocation from a heap. * * PARAMS * heap [I] Heap that block was allocated from @@ -1487,8 +1528,6 @@ char *ptr; int region_index = 0; - FIXME( "not fully compatible\n" ); - if (!heapPtr || !entry) return STATUS_INVALID_PARAMETER; if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); @@ -1577,6 +1616,7 @@ currentheap + currentheap->size; } ret = STATUS_SUCCESS; + if (TRACE_ON(heap)) HEAP_DumpEntry(entry); HW_end: if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); diff -urN wine-20050211/dlls/ntdll/large_int.c wine-20050310/dlls/ntdll/large_int.c --- wine-20050211/dlls/ntdll/large_int.c 2003-10-01 05:20:21.000000000 +0200 +++ wine-20050310/dlls/ntdll/large_int.c 2005-02-25 15:07:57.000000000 +0100 @@ -389,8 +389,8 @@ * NOTES * Instead of base 0 it uses 10 as base. * Writes at most length characters to the string str. - * Str is '\0' terminated when length allowes it. - * When str fits exactly in length characters the '\0' is ommitted. + * Str is '\0' terminated when length allows it. + * When str fits exactly in length characters the '\0' is omitted. * If value_ptr is NULL it crashes, as the native function does. * * DIFFERENCES diff -urN wine-20050211/dlls/ntdll/loader.c wine-20050310/dlls/ntdll/loader.c --- wine-20050211/dlls/ntdll/loader.c 2005-01-24 13:49:53.000000000 +0100 +++ wine-20050310/dlls/ntdll/loader.c 2005-02-24 14:15:36.000000000 +0100 @@ -178,8 +178,8 @@ rec.ExceptionAddress = *((void **)&dll - 1); #endif rec.NumberParameters = 2; - rec.ExceptionInformation[0] = (DWORD)dll; - rec.ExceptionInformation[1] = (DWORD)name; + rec.ExceptionInformation[0] = (ULONG_PTR)dll; + rec.ExceptionInformation[1] = (ULONG_PTR)name; for (;;) RtlRaiseException( &rec ); } @@ -215,7 +215,7 @@ if (!stubs) { ULONG size = MAX_SIZE; - if (NtAllocateVirtualMemory( GetCurrentProcess(), (void **)&stubs, 0, &size, + if (NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&stubs, 0, &size, MEM_COMMIT, PAGE_EXECUTE_WRITECOPY ) != STATUS_SUCCESS) return (void *)0xdeadbeef; } @@ -491,7 +491,7 @@ while (import_list[protect_size].u1.Ordinal) protect_size++; protect_base = thunk_list; protect_size *= sizeof(*thunk_list); - NtProtectVirtualMemory( GetCurrentProcess(), &protect_base, + NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, PAGE_WRITECOPY, &protect_old ); imp_mod = wmImp->ldr.BaseAddress; @@ -561,7 +561,7 @@ done: /* restore old protection of the import address table */ - NtProtectVirtualMemory( GetCurrentProcess(), &protect_base, &protect_size, protect_old, NULL ); + NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL ); return wmImp; } @@ -1229,7 +1229,7 @@ } wm->ldr.Flags |= LDR_WINE_INTERNAL; addr = module; - NtAllocateVirtualMemory( GetCurrentProcess(), &addr, 0, &nt->OptionalHeader.SizeOfImage, + NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &nt->OptionalHeader.SizeOfImage, MEM_SYSTEM | MEM_IMAGE, PAGE_EXECUTE_WRITECOPY ); /* fixup imports */ @@ -1299,7 +1299,7 @@ if (status != STATUS_SUCCESS) return status; module = NULL; - status = NtMapViewOfSection( mapping, GetCurrentProcess(), + status = NtMapViewOfSection( mapping, NtCurrentProcess(), &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY ); NtClose( mapping ); if (status != STATUS_SUCCESS) return status; @@ -1802,7 +1802,7 @@ } SERVER_END_REQ; - NtUnmapViewOfSection( GetCurrentProcess(), mod->BaseAddress ); + NtUnmapViewOfSection( NtCurrentProcess(), mod->BaseAddress ); if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle ); if (cached_modref == wm) cached_modref = NULL; RtlFreeUnicodeString( &mod->FullDllName ); diff -urN wine-20050211/dlls/ntdll/nt.c wine-20050310/dlls/ntdll/nt.c --- wine-20050211/dlls/ntdll/nt.c 2005-02-11 12:52:07.000000000 +0100 +++ wine-20050310/dlls/ntdll/nt.c 2005-02-23 21:29:17.000000000 +0100 @@ -37,6 +37,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); +/* FIXME: fixed at 2005/2/22 */ +static LONGLONG boottime = (LONGLONG)1275356510 * 100000000; + /* Structures used by NtConnectPort */ typedef struct LpcSectionInfo @@ -512,17 +515,27 @@ /****************************************************************************** * NtQueryPerformanceCounter [NTDLL.@] * - * Note: Windows uses a timer clocked at a multiple of 1193182 Hz. - * + * Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a + * good number of applications that crash when the returned frequency is either + * lower or higher then what Windows gives. Also too high counter values are + * reported to give problems. */ NTSTATUS WINAPI NtQueryPerformanceCounter( OUT PLARGE_INTEGER Counter, OUT PLARGE_INTEGER Frequency) { LARGE_INTEGER time; + + if (!Counter) return STATUS_ACCESS_VIOLATION; NtQuerySystemTime( &time ); - Counter->QuadPart = time.QuadPart; - Frequency->QuadPart = 10000000; + time.QuadPart -= boottime; + /* convert a counter that increments at a rate of 10 MHz + * to one of 1193182 Hz, with some care for arithmetic + * overflow ( will not overflow until 3396 or so ) and + * good accuracy ( 21/176 = 0.119318182) */ + Counter->QuadPart = (time.QuadPart * 21) / 176; + if (Frequency) + Frequency->QuadPart = 1193182; return 0; } @@ -622,7 +635,7 @@ SYSTEM_TIMEOFDAY_INFORMATION* sti = (SYSTEM_TIMEOFDAY_INFORMATION*)SystemInformation; if (Length >= sizeof(*sti)) { - sti->liKeBootTime.QuadPart = 0; /* FIXME */ + sti->liKeBootTime.QuadPart = boottime; sti->liKeSystemTime.QuadPart = 0; /* FIXME */ sti->liExpTimeZoneBias.QuadPart = 0; /* FIXME */ sti->uCurrentTimeZoneId = 0; /* FIXME */ diff -urN wine-20050211/dlls/ntdll/ntdll.spec wine-20050310/dlls/ntdll/ntdll.spec --- wine-20050211/dlls/ntdll/ntdll.spec 2005-01-26 21:41:36.000000000 +0100 +++ wine-20050310/dlls/ntdll/ntdll.spec 2005-02-14 22:07:33.000000000 +0100 @@ -313,7 +313,7 @@ @ stdcall RtlAssert(ptr ptr long long) @ stub RtlCaptureStackBackTrace @ stdcall RtlCharToInteger(ptr long ptr) -@ stub RtlCheckRegistryKey +@ stdcall RtlCheckRegistryKey(long ptr) @ stdcall RtlClearAllBits(ptr) @ stdcall RtlClearBits(ptr long long) @ stdcall RtlCompactHeap(long long) @@ -369,7 +369,7 @@ @ stub RtlDeleteNoSplay @ stub RtlDeleteOwnersRanges @ stub RtlDeleteRange -@ stub RtlDeleteRegistryValue +@ stdcall RtlDeleteRegistryValue(long ptr ptr) @ stdcall RtlDeleteResource(ptr) @ stdcall RtlDeleteSecurityObject(long) @ stdcall RtlDestroyEnvironment(ptr) @@ -540,7 +540,7 @@ @ stdcall RtlQueryProcessDebugInformation(long long ptr) @ stub RtlQueryProcessHeapInformation @ stub RtlQueryProcessLockInformation -@ stub RtlQueryRegistryValues +@ stdcall RtlQueryRegistryValues(long ptr ptr ptr ptr) @ stub RtlQuerySecurityObject @ stub RtlQueryTagHeap @ stdcall RtlQueryTimeZoneInformation(ptr) diff -urN wine-20050211/dlls/ntdll/reg.c wine-20050310/dlls/ntdll/reg.c --- wine-20050211/dlls/ntdll/reg.c 2004-12-17 20:41:55.000000000 +0100 +++ wine-20050310/dlls/ntdll/reg.c 2005-03-02 14:53:51.000000000 +0100 @@ -3,6 +3,7 @@ * * Copyright (C) 1999 Juergen Schmied * Copyright (C) 2000 Alexandre Julliard + * Copyright 2005 Ivan Leo Puoti, Laurent Pinchart * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,13 +38,13 @@ #include "winreg.h" #include "ntdll_misc.h" #include "wine/debug.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(reg); /* maximum length of a key/value name in bytes (without terminating null) */ #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR)) - /****************************************************************************** * NtCreateKey [NTDLL.@] * ZwCreateKey [NTDLL.@] @@ -759,3 +760,476 @@ RtlFreeUnicodeString(&ObjectName); return ret; } + + +static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo, + PRTL_QUERY_REGISTRY_TABLE pQuery, PVOID pContext, PVOID pEnvironment) +{ + PUNICODE_STRING str; + UNICODE_STRING src, dst; + LONG *bin; + ULONG offset; + PWSTR wstr; + DWORD res; + NTSTATUS status = STATUS_SUCCESS; + ULONG len; + LPWSTR String; + INT count = 0; + + if (pInfo == NULL) + { + if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT) + { + FIXME("(pInfo == NULL, pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT), stub!\n"); + return status; + } + else + { + status = pQuery->QueryRoutine(pQuery->Name, pQuery->DefaultType, pQuery->DefaultData, + pQuery->DefaultLength, pContext, pQuery->EntryContext); + } + return status; + } + len = pInfo->DataLength; + + if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT) + { + str = (PUNICODE_STRING)pQuery->EntryContext; + + switch(pInfo->Type) + { + case REG_EXPAND_SZ: + if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)); + res = 0; + dst.MaximumLength = 0; + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + dst.Length = 0; + dst.MaximumLength = res; + dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR)); + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer, + dst.Length, pContext, pQuery->EntryContext); + RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer); + } + + case REG_SZ: + case REG_LINK: + if (str->Buffer == NULL) + RtlCreateUnicodeString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)); + else + RtlAppendUnicodeToString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)); + break; + + case REG_MULTI_SZ: + if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + return STATUS_INVALID_PARAMETER; + + if (str->Buffer == NULL) + { + str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len); + str->MaximumLength = len; + } + len = min(len, str->MaximumLength); + memcpy(str->Buffer, ((CHAR*)pInfo) + pInfo->DataOffset, len); + str->Length = len; + break; + + default: + bin = (LONG*)pQuery->EntryContext; + if (pInfo->DataLength <= sizeof(ULONG)) + memcpy(bin, ((CHAR*)pInfo) + pInfo->DataOffset, + pInfo->DataLength); + else + { + if (bin[0] <= sizeof(ULONG)) + { + memcpy(&bin[1], ((CHAR*)pInfo) + pInfo->DataOffset, + min(-bin[0], pInfo->DataLength)); + } + else + { + len = min(bin[0], pInfo->DataLength); + bin[1] = len; + bin[2] = pInfo->Type; + memcpy(&bin[3], ((CHAR*)pInfo) + pInfo->DataOffset, len); + } + } + break; + } + } + else + { + if((pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND) || + (pInfo->Type != REG_EXPAND_SZ && pInfo->Type != REG_MULTI_SZ)) + { + status = pQuery->QueryRoutine(pInfo->Name, pInfo->Type, + ((CHAR*)pInfo) + pInfo->DataOffset, pInfo->DataLength, + pContext, pQuery->EntryContext); + } + else if (pInfo->Type == REG_EXPAND_SZ) + { + RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)); + res = 0; + dst.MaximumLength = 0; + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + dst.Length = 0; + dst.MaximumLength = res; + dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR)); + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer, + dst.Length, pContext, pQuery->EntryContext); + RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer); + } + else /* REG_MULTI_SZ */ + { + if(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND) + { + for (offset = 0; offset <= pInfo->DataLength; offset += len + sizeof(WCHAR)) + { + wstr = (WCHAR*)(((CHAR*)pInfo) + offset); + len = strlenW(wstr) * sizeof(WCHAR); + status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, wstr, len, + pContext, pQuery->EntryContext); + if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) + return status; + } + } + else + { + while(count<=pInfo->DataLength) + { + String = (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)+count; + count+=strlenW(String)+1; + RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)); + res = 0; + dst.MaximumLength = 0; + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + dst.Length = 0; + dst.MaximumLength = res; + dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR)); + RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res); + status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer, + dst.Length, pContext, pQuery->EntryContext); + RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer); + if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) + return status; + } + } + } + } + return status; +} + + +static NTSTATUS RTL_GetKeyHandle(ULONG RelativeTo, PCWSTR Path, PHKEY handle) +{ + UNICODE_STRING KeyString; + OBJECT_ATTRIBUTES regkey; + PCWSTR base; + INT len; + NTSTATUS status; + + static const WCHAR empty[] = {0}; + static const WCHAR control[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e', + '\\','S','y','s','t','e','m','\\','C','u','r','r','e','n','t',' ','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\',0}; + + static const WCHAR devicemap[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\', + 'H','a','r','d','w','a','r','e','\\','D','e','v','i','c','e','M','a','p','\\',0}; + + static const WCHAR services[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\', + 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'S','e','r','v','i','c','e','s','\\',0}; + + static const WCHAR user[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\', + 'C','u','r','r','e','n','t','U','s','e','r','\\',0}; + + static const WCHAR windows_nt[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\', + 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',0}; + + switch (RelativeTo & 0xff) + { + case RTL_REGISTRY_ABSOLUTE: + base = empty; + break; + + case RTL_REGISTRY_CONTROL: + base = control; + break; + + case RTL_REGISTRY_DEVICEMAP: + base = devicemap; + break; + + case RTL_REGISTRY_SERVICES: + base = services; + break; + + case RTL_REGISTRY_USER: + base = user; + break; + + case RTL_REGISTRY_WINDOWS_NT: + base = windows_nt; + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + len = (strlenW(base) + strlenW(Path) + 1) * sizeof(WCHAR); + KeyString.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len); + if (KeyString.Buffer == NULL) + return STATUS_NO_MEMORY; + + strcpyW(KeyString.Buffer, base); + strcatW(KeyString.Buffer, Path); + KeyString.Length = len - sizeof(WCHAR); + KeyString.MaximumLength = len; + InitializeObjectAttributes(®key, &KeyString, 0, NULL, NULL); + status = NtOpenKey(handle, KEY_ALL_ACCESS, ®key); + RtlFreeHeap(GetProcessHeap(), 0, KeyString.Buffer); + return status; +} + +/************************************************************************* + * RtlQueryRegistryValues [NTDLL.@] + * + * Query multiple registry values with a signle call. + * + * PARAMS + * RelativeTo [I] Registry path that Path refers to + * Path [I] Path to key + * QueryTable [I] Table of key values to query + * Context [I] Paremeter to pass to the application defined QueryRoutine function + * Environment [I] Optional parameter to use when performing expantion + * + * RETURNS + * STATUS_SUCCESS or an appropriate NTSTATUS error code. + */ +NTSTATUS WINAPI RtlQueryRegistryValues(IN ULONG RelativeTo, IN PCWSTR Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context, + IN PVOID Environment OPTIONAL) +{ + UNICODE_STRING Value; + HKEY handle, topkey; + PKEY_VALUE_FULL_INFORMATION pInfo = NULL; + ULONG len, buflen = 0; + NTSTATUS status=STATUS_SUCCESS, ret = STATUS_SUCCESS; + INT i; + + TRACE("(%ld, %s, %p, %p, %p)\n", RelativeTo, debugstr_w(Path), QueryTable, Context, Environment); + + /* get a valid handle */ + if (RelativeTo & RTL_REGISTRY_HANDLE) + topkey = handle = (HANDLE)Path; + else + { + status = RTL_GetKeyHandle(RelativeTo, Path, &topkey); + handle = topkey; + } + if(status != STATUS_SUCCESS) + return status; + + /* Process query table entries */ + for (; QueryTable->QueryRoutine != NULL || QueryTable->Name != NULL; ++QueryTable) + { + if (QueryTable->Flags & + (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) + { + /* topkey must be kept open just in case we will reuse it later */ + if (handle != topkey) + NtClose(handle); + + if (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY) + { + handle = 0; + status = RTL_GetKeyHandle((ULONG)QueryTable->Name, Path, &handle); + if(status != STATUS_SUCCESS) + { + ret = status; + goto out; + } + } + else + handle = topkey; + } + + if (QueryTable->Flags & RTL_QUERY_REGISTRY_NOVALUE) + { + QueryTable->QueryRoutine(QueryTable->Name, REG_NONE, NULL, 0, + Context, QueryTable->EntryContext); + continue; + } + + if (!handle) + { + if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED) + { + ret = STATUS_OBJECT_NAME_NOT_FOUND; + goto out; + } + continue; + } + + if (QueryTable->Name == NULL) + { + if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT) + { + ret = STATUS_INVALID_PARAMETER; + goto out; + } + + /* Report all subkeys */ + for (i = 0;; ++i) + { + status = NtEnumerateValueKey(handle, i, + KeyValueFullInformation, pInfo, buflen, &len); + if (status == STATUS_NO_MORE_ENTRIES) + break; + if (status == STATUS_BUFFER_OVERFLOW || + status == STATUS_BUFFER_TOO_SMALL) + { + buflen = len; + RtlFreeHeap(GetProcessHeap(), 0, pInfo); + pInfo = (KEY_VALUE_FULL_INFORMATION*)RtlAllocateHeap( + GetProcessHeap(), 0, buflen); + NtEnumerateValueKey(handle, i, KeyValueFullInformation, + pInfo, buflen, &len); + } + + status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment); + if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) + { + ret = status; + goto out; + } + if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE) + { + RtlInitUnicodeString(&Value, pInfo->Name); + NtDeleteValueKey(handle, &Value); + } + } + + if (i == 0 && (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)) + { + ret = STATUS_OBJECT_NAME_NOT_FOUND; + goto out; + } + } + else + { + RtlInitUnicodeString(&Value, QueryTable->Name); + status = NtQueryValueKey(handle, &Value, KeyValueFullInformation, + pInfo, buflen, &len); + if (status == STATUS_BUFFER_OVERFLOW || + status == STATUS_BUFFER_TOO_SMALL) + { + buflen = len; + RtlFreeHeap(GetProcessHeap(), 0, pInfo); + pInfo = (KEY_VALUE_FULL_INFORMATION*)RtlAllocateHeap( + GetProcessHeap(), 0, buflen); + status = NtQueryValueKey(handle, &Value, + KeyValueFullInformation, pInfo, buflen, &len); + } + if (status != STATUS_SUCCESS) + { + if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED) + { + ret = STATUS_OBJECT_NAME_NOT_FOUND; + goto out; + } + status = RTL_ReportRegistryValue(NULL, QueryTable, Context, Environment); + if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) + { + ret = status; + goto out; + } + } + else + { + status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment); + if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) + { + ret = status; + goto out; + } + if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE) + NtDeleteValueKey(handle, &Value); + } + } + } + +out: + RtlFreeHeap(GetProcessHeap(), 0, pInfo); + if (handle != topkey) + NtClose(handle); + NtClose(topkey); + return ret; +} + +/************************************************************************* + * RtlCheckRegistryKey [NTDLL.@] + * + * Query multiple registry values with a signle call. + * + * PARAMS + * RelativeTo [I] Registry path that Path refers to + * Path [I] Path to key + * + * RETURNS + * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code. + */ +NTSTATUS WINAPI RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path) +{ + HKEY handle; + NTSTATUS status; + + TRACE("(%ld, %s)\n", RelativeTo, debugstr_w(Path)); + + if((!RelativeTo) && Path == NULL) + return STATUS_OBJECT_PATH_SYNTAX_BAD; + if(RelativeTo & RTL_REGISTRY_HANDLE) + return STATUS_SUCCESS; + + status = RTL_GetKeyHandle(RelativeTo, Path, &handle); + if (handle) NtClose(handle); + if (status == STATUS_INVALID_HANDLE) status = STATUS_OBJECT_NAME_NOT_FOUND; + return status; +} + +/************************************************************************* + * RtlDeleteRegistryValue [NTDLL.@] + * + * Query multiple registry values with a signle call. + * + * PARAMS + * RelativeTo [I] Registry path that Path refers to + * Path [I] Path to key + * ValueName [I] Name of the value to delete + * + * RETURNS + * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code. + */ +NTSTATUS WINAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName) +{ + NTSTATUS status; + HKEY handle; + UNICODE_STRING Value; + + TRACE("(%ld, %s, %s)\n", RelativeTo, debugstr_w(Path), debugstr_w(ValueName)); + + RtlInitUnicodeString(&Value, ValueName); + if(RelativeTo == RTL_REGISTRY_HANDLE) + { + return NtDeleteValueKey((HKEY)Path, &Value); + } + status = RTL_GetKeyHandle(RelativeTo, Path, &handle); + if (status) return status; + status = NtDeleteValueKey(handle, &Value); + NtClose(handle); + return status; +} diff -urN wine-20050211/dlls/ntdll/relay.c wine-20050310/dlls/ntdll/relay.c --- wine-20050211/dlls/ntdll/relay.c 2004-10-11 22:59:06.000000000 +0200 +++ wine-20050310/dlls/ntdll/relay.c 2005-02-22 20:33:50.000000000 +0100 @@ -820,7 +820,7 @@ /* another dll, loaded at the same address */ addr = (*dll)->funs; size = (*dll)->nrofordinals * sizeof(SNOOP_FUN); - NtFreeVirtualMemory(GetCurrentProcess(), &addr, &size, MEM_RELEASE); + NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); break; } dll = &((*dll)->next); @@ -842,7 +842,7 @@ size = exports->NumberOfFunctions * sizeof(SNOOP_FUN); addr = NULL; - NtAllocateVirtualMemory(GetCurrentProcess(), &addr, 0, &size, + NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!addr) { RtlFreeHeap(GetProcessHeap(),0,*dll); @@ -1009,7 +1009,7 @@ SIZE_T size = 4096; VOID* addr = NULL; - NtAllocateVirtualMemory(GetCurrentProcess(), &addr, 0, &size, + NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!addr) return; diff -urN wine-20050211/dlls/ntdll/rtlbitmap.c wine-20050310/dlls/ntdll/rtlbitmap.c --- wine-20050211/dlls/ntdll/rtlbitmap.c 2004-12-17 20:41:55.000000000 +0100 +++ wine-20050310/dlls/ntdll/rtlbitmap.c 2005-02-25 15:07:57.000000000 +0100 @@ -742,7 +742,7 @@ lpOut++; } - /* Count remaining contigious bits, if any */ + /* Count remaining contiguous bits, if any */ if (*lpOut & 1) { ULONG ulOffset = 0; @@ -833,7 +833,7 @@ lpOut++; } - /* Count remaining contigious bits, if any */ + /* Count remaining contiguous bits, if any */ if (!(*lpOut & 1)) { ULONG ulOffset = 0; diff -urN wine-20050211/dlls/ntdll/rtlstr.c wine-20050310/dlls/ntdll/rtlstr.c --- wine-20050211/dlls/ntdll/rtlstr.c 2004-04-19 05:05:07.000000000 +0200 +++ wine-20050310/dlls/ntdll/rtlstr.c 2005-02-25 15:07:57.000000000 +0100 @@ -1071,8 +1071,14 @@ { NTSTATUS ret; UNICODE_STRING upcase; + WCHAR tmp[32]; - if (!(ret = RtlUpcaseUnicodeString( &upcase, uni, TRUE ))) + upcase.Buffer = tmp; + upcase.MaximumLength = sizeof(tmp); + ret = RtlUpcaseUnicodeString( &upcase, uni, FALSE ); + if (ret == STATUS_BUFFER_OVERFLOW) ret = RtlUpcaseUnicodeString( &upcase, uni, TRUE ); + + if (!ret) { DWORD len = RtlUnicodeStringToOemSize( &upcase ) - 1; oem->Length = len; @@ -1093,7 +1099,7 @@ } RtlUnicodeToOemN( oem->Buffer, oem->Length, NULL, upcase.Buffer, upcase.Length ); done: - RtlFreeUnicodeString( &upcase ); + if (upcase.Buffer != tmp) RtlFreeUnicodeString( &upcase ); } return ret; } @@ -1347,8 +1353,8 @@ * * NOTES * if src is NULL dest is unchanged. - * dest is '\0' terminated when the MaximumLength allowes it. - * When dest fits exactly in MaximumLength characters the '\0' is ommitted. + * dest is '\0' terminated when the MaximumLength allows it. + * When dest fits exactly in MaximumLength characters the '\0' is omitted. * * DIFFERENCES * Does not write in the src->Buffer beyond MaximumLength when @@ -1386,8 +1392,8 @@ * * NOTES * if src->length is zero dest is unchanged. - * dest is '\0' terminated when the MaximumLength allowes it. - * When dest fits exactly in MaximumLength characters the '\0' is ommitted. + * dest is '\0' terminated when the MaximumLength allows it. + * When dest fits exactly in MaximumLength characters the '\0' is omitted. * * DIFFERENCES * Does not write in the src->Buffer beyond MaximumLength when @@ -1686,8 +1692,8 @@ * NOTES * Instead of base 0 it uses 10 as base. * Writes at most length characters to the string str. - * Str is '\0' terminated when length allowes it. - * When str fits exactly in length characters the '\0' is ommitted. + * Str is '\0' terminated when length allows it. + * When str fits exactly in length characters the '\0' is omitted. */ NTSTATUS WINAPI RtlIntegerToChar( ULONG value, /* [I] Value to be converted */ diff -urN wine-20050211/dlls/ntdll/sec.c wine-20050310/dlls/ntdll/sec.c --- wine-20050211/dlls/ntdll/sec.c 2005-01-20 11:37:36.000000000 +0100 +++ wine-20050310/dlls/ntdll/sec.c 2005-02-25 15:07:57.000000000 +0100 @@ -190,7 +190,7 @@ * Determine the amount of memory a SID is using * * PARAMS - * pSid [I] SID to ge the size of. + * pSid [I] SID to get the size of. * * RETURNS * The size, in bytes, of pSid. @@ -213,7 +213,7 @@ * nSubAuthorityCount [I] Number of Sub Authorities * * RETURNS - * Success: TRUE. pSid is initialised withe the details given. + * Success: TRUE. pSid is initialised with the details given. * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES. */ BOOL WINAPI RtlInitializeSid( diff -urN wine-20050211/dlls/ntdll/signal_i386.c wine-20050310/dlls/ntdll/signal_i386.c --- wine-20050211/dlls/ntdll/signal_i386.c 2004-12-02 19:19:25.000000000 +0100 +++ wine-20050310/dlls/ntdll/signal_i386.c 2005-02-24 14:15:36.000000000 +0100 @@ -1022,7 +1022,7 @@ #ifdef FAULT_ADDRESS rec->NumberParameters = 2; rec->ExceptionInformation[0] = (get_error_code(HANDLER_CONTEXT) & 2) != 0; - rec->ExceptionInformation[1] = (DWORD)FAULT_ADDRESS; + rec->ExceptionInformation[1] = (ULONG_PTR)FAULT_ADDRESS; #endif break; case T_ALIGNFLT: /* Alignment check exception */ diff -urN wine-20050211/dlls/ntdll/signal_powerpc.c wine-20050310/dlls/ntdll/signal_powerpc.c --- wine-20050211/dlls/ntdll/signal_powerpc.c 2003-12-08 22:58:55.000000000 +0100 +++ wine-20050310/dlls/ntdll/signal_powerpc.c 2005-02-24 14:15:36.000000000 +0100 @@ -317,7 +317,7 @@ case SEGV_ACCERR: rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)addr; + rec.ExceptionInformation[1] = (ULONG_PTR)addr; if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; @@ -339,7 +339,7 @@ /* FIXME: correct for all cases ? */ rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME ? */ - rec.ExceptionInformation[1] = (DWORD)addr; + rec.ExceptionInformation[1] = (ULONG_PTR)addr; if (!(page_fault_code=VIRTUAL_HandleFault(addr))) return; rec.ExceptionCode = page_fault_code; diff -urN wine-20050211/dlls/ntdll/signal_sparc.c wine-20050310/dlls/ntdll/signal_sparc.c --- wine-20050211/dlls/ntdll/signal_sparc.c 2004-11-21 16:38:26.000000000 +0100 +++ wine-20050310/dlls/ntdll/signal_sparc.c 2005-02-24 14:15:36.000000000 +0100 @@ -171,7 +171,7 @@ rec.ExceptionAddress = (LPVOID)context.pc; rec.NumberParameters = 2; rec.ExceptionInformation[0] = 0; /* FIXME: read/write access ? */ - rec.ExceptionInformation[1] = (DWORD)info->si_addr; + rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr; EXC_RtlRaiseException( &rec, &context ); restore_context( &context, ucontext ); diff -urN wine-20050211/dlls/ntdll/sync.c wine-20050310/dlls/ntdll/sync.c --- wine-20050211/dlls/ntdll/sync.c 2005-01-14 20:54:39.000000000 +0100 +++ wine-20050310/dlls/ntdll/sync.c 2005-03-04 13:38:37.000000000 +0100 @@ -29,6 +29,9 @@ #ifdef HAVE_SYS_TIME_H # include #endif +#ifdef HAVE_POLL_H +#include +#endif #ifdef HAVE_SYS_POLL_H # include #endif diff -urN wine-20050211/dlls/ntdll/tests/.cvsignore wine-20050310/dlls/ntdll/tests/.cvsignore --- wine-20050211/dlls/ntdll/tests/.cvsignore 2004-10-22 21:54:17.000000000 +0200 +++ wine-20050310/dlls/ntdll/tests/.cvsignore 2005-02-14 22:08:56.000000000 +0100 @@ -4,6 +4,7 @@ generated.ok large_int.ok path.ok +reg.ok rtl.ok rtlbitmap.ok rtlstr.ok diff -urN wine-20050211/dlls/ntdll/tests/Makefile.in wine-20050310/dlls/ntdll/tests/Makefile.in --- wine-20050211/dlls/ntdll/tests/Makefile.in 2004-10-22 21:54:17.000000000 +0200 +++ wine-20050310/dlls/ntdll/tests/Makefile.in 2005-02-14 22:08:56.000000000 +0100 @@ -11,6 +11,7 @@ generated.c \ large_int.c \ path.c \ + reg.c \ rtl.c \ rtlbitmap.c \ rtlstr.c \ diff -urN wine-20050211/dlls/ntdll/tests/generated.c wine-20050310/dlls/ntdll/tests/generated.c --- wine-20050211/dlls/ntdll/tests/generated.c 2004-09-06 23:26:57.000000000 +0200 +++ wine-20050310/dlls/ntdll/tests/generated.c 2005-02-24 14:15:36.000000000 +0100 @@ -374,10 +374,10 @@ TEST_TYPE(EXCEPTION_RECORD, 80, 4); TEST_FIELD(EXCEPTION_RECORD, DWORD, ExceptionCode, 0, 4, 4); TEST_FIELD(EXCEPTION_RECORD, DWORD, ExceptionFlags, 4, 4, 4); - TEST_FIELD(EXCEPTION_RECORD, struct __EXCEPTION_RECORD *, ExceptionRecord, 8, 4, 4); - TEST_FIELD(EXCEPTION_RECORD, LPVOID, ExceptionAddress, 12, 4, 4); + TEST_FIELD(EXCEPTION_RECORD, struct _EXCEPTION_RECORD *, ExceptionRecord, 8, 4, 4); + TEST_FIELD(EXCEPTION_RECORD, PVOID, ExceptionAddress, 12, 4, 4); TEST_FIELD(EXCEPTION_RECORD, DWORD, NumberParameters, 16, 4, 4); - TEST_FIELD(EXCEPTION_RECORD, DWORD[EXCEPTION_MAXIMUM_PARAMETERS], ExceptionInformation, 20, 60, 4); + TEST_FIELD(EXCEPTION_RECORD, ULONG_PTR[EXCEPTION_MAXIMUM_PARAMETERS], ExceptionInformation, 20, 60, 4); } static void test_pack_EXECUTION_STATE(void) diff -urN wine-20050211/dlls/ntdll/tests/path.c wine-20050310/dlls/ntdll/tests/path.c --- wine-20050211/dlls/ntdll/tests/path.c 2004-08-14 02:42:12.000000000 +0200 +++ wine-20050310/dlls/ntdll/tests/path.c 2005-02-14 22:04:45.000000000 +0100 @@ -35,7 +35,7 @@ struct test { const char *path; - int ret; + UINT ret; }; static const struct test tests[] = @@ -255,7 +255,7 @@ ULONG ret; WCHAR *file_part; DWORD reslen; - int len; + UINT len; for (test = tests; test->path; test++) { diff -urN wine-20050211/dlls/ntdll/tests/reg.c wine-20050310/dlls/ntdll/tests/reg.c --- wine-20050211/dlls/ntdll/tests/reg.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/ntdll/tests/reg.c 2005-02-15 21:47:25.000000000 +0100 @@ -0,0 +1,368 @@ +/* Unit test suite for Rtl* Registry API functions + * + * Copyright 2003 Thomas Mertes + * Copyright 2005 Brad DeMorrow + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through + * helper function RTL_GetKeyHandle().--Brad DeMorrow + * + */ + +#include "ntdll_test.h" +#include "winternl.h" +#include "wine/library.h" +#include "stdio.h" +#include "winnt.h" +#include "winnls.h" +#include "stdlib.h" +#include "wine/unicode.h" + +#ifndef __WINE_WINTERNL_H + +/* RtlQueryRegistryValues structs and defines */ +#define RTL_REGISTRY_ABSOLUTE 0 +#define RTL_REGISTRY_SERVICES 1 +#define RTL_REGISTRY_CONTROL 2 +#define RTL_REGISTRY_WINDOWS_NT 3 +#define RTL_REGISTRY_DEVICEMAP 4 +#define RTL_REGISTRY_USER 5 + +#define RTL_REGISTRY_HANDLE 0x40000000 +#define RTL_REGISTRY_OPTIONAL 0x80000000 + +#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 +#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 +#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 +#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 +#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 +#define RTL_QUERY_REGISTRY_DIRECT 0x00000020 +#define RTL_QUERY_REGISTRY_DELETE 0x00000040 + +typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext); + +typedef struct _RTL_QUERY_REGISTRY_TABLE { + PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; + +#endif + +static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR); +static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING); +static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING); +static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID); +static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR); +static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY); +static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES); +static NTSTATUS (WINAPI * pNtClose)(IN HANDLE); +static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING); +static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY); +static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, + ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, + PULONG dispos ); +static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG, + ULONG, const PVOID, ULONG ); +static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING); +static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR); +static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG); +static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR); +static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL); +static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID); +static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG); +static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG); + +static HMODULE hntdll = 0; +static int CurrentTest = 0; +static UNICODE_STRING winetestpath; + +static void InitFunctionPtrs(void) +{ + hntdll = LoadLibraryA("ntdll.dll"); + ok(hntdll != 0, "LoadLibrary failed\n"); + if (hntdll) + { + pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz"); + pRtlCreateUnicodeString = (void*)GetProcAddress(hntdll, "RtlCreateUnicodeString"); + pRtlFreeUnicodeString = (void*)GetProcAddress(hntdll, "RtlFreeUnicodeString"); + pNtDeleteValueKey = (void*)GetProcAddress(hntdll, "NtDeleteValueKey"); + pRtlQueryRegistryValues = (void*)GetProcAddress(hntdll, "RtlQueryRegistryValues"); + pRtlCheckRegistryKey = (void*)GetProcAddress(hntdll, "RtlCheckRegistryKey"); + pRtlOpenCurrentUser = (void*)GetProcAddress(hntdll, "RtlOpenCurrentUser"); + pNtClose = (void*)GetProcAddress(hntdll, "NtClose"); + pNtDeleteValueKey = (void*)GetProcAddress(hntdll, "NtDeleteValueKey"); + pNtCreateKey = (void*)GetProcAddress(hntdll, "NtCreateKey"); + pNtDeleteKey = (void*)GetProcAddress(hntdll, "NtDeleteKey"); + pNtSetValueKey = (void*)GetProcAddress(hntdll, "NtSetValueKey"); + pNtOpenKey = (void*)GetProcAddress(hntdll, "NtOpenKey"); + pRtlFormatCurrentUserKeyPath = (void*)GetProcAddress(hntdll, "RtlFormatCurrentUserKeyPath"); + pRtlReAllocateHeap = (void*)GetProcAddress(hntdll, "RtlReAllocateHeap"); + pRtlAppendUnicodeToString = (void*)GetProcAddress(hntdll, "RtlAppendUnicodeToString"); + pRtlUnicodeStringToAnsiString = (void*)GetProcAddress(hntdll, "RtlUnicodeStringToAnsiString"); + pRtlFreeHeap = (void*)GetProcAddress(hntdll, "RtlFreeHeap"); + pRtlAllocateHeap = (void*)GetProcAddress(hntdll, "RtlAllocateHeap"); + pRtlZeroMemory = (void*)GetProcAddress(hntdll, "RtlZeroMemory"); + } + + +} + +static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, + IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext) +{ + NTSTATUS ret = STATUS_SUCCESS; + int ValueNameLength = 0; + LPSTR ValName = 0; + trace("**Test %d**\n", CurrentTest); + + if(ValueName) + { + ValueNameLength = strlenW(ValueName); + + ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength); + + WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0); + + trace("ValueName: %s\n", ValName); + } + else + trace("ValueName: (null)\n"); + + switch(ValueType) + { + case REG_NONE: + trace("ValueType: REG_NONE\n"); + trace("ValueData: %d\n", (int)ValueData); + break; + + case REG_BINARY: + trace("ValueType: REG_BINARY\n"); + trace("ValueData: %d\n", (int)ValueData); + break; + + case REG_SZ: + trace("ValueType: REG_SZ\n"); + trace("ValueData: %s\n", (char*)ValueData); + break; + + case REG_MULTI_SZ: + trace("ValueType: REG_MULTI_SZ\n"); + trace("ValueData: %s\n", (char*)ValueData); + break; + + case REG_EXPAND_SZ: + trace("ValueType: REG_EXPAND_SZ\n"); + trace("ValueData: %s\n", (char*)ValueData); + break; + + case REG_DWORD: + trace("ValueType: REG_DWORD\n"); + trace("ValueData: %d\n", (int)ValueData); + break; + }; + trace("ValueLength: %d\n", (int)ValueLength); + + if(CurrentTest == 0) + ok(1, "\n"); /*checks that QueryRoutine is called*/ + if(CurrentTest > 7) + ok(!1, "Invalid Test Specified!\n"); + + CurrentTest++; + + if(ValName) + pRtlFreeHeap(GetProcessHeap(), 0, ValName); + + return ret; +} + +static void test_RtlQueryRegistryValues(void) +{ + + /* + ****************************** + * QueryTable Flags * + ****************************** + *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path + *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path + *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present + *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back + *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables! + *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored) + *RTL_QUERY_REGISTRY_DELETE * Delete value key after query + ****************************** + + + **Test layout(numbered according to CurrentTest value)** + 0)NOVALUE Just make sure call-back works + 1)Null Name See if QueryRoutine is called for every value in current key + 2)SUBKEY See if we can use SUBKEY to change the current path on the fly + 3)REQUIRED Test for value that's not there + 4)NOEXPAND See if it will return multiple strings(no expand should split strings up) + 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine + 6)DefaultType Test return values when key isn't present + 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set) + 8)DefaultLength Test Default Length with DefaultType = REG_SZ + 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ + 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ + 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be) + 12)Delete Try to delete value key + + */ + NTSTATUS status; + ULONG RelativeTo; + + PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL; + RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/ + + QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26); + + pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26); + + QueryTable[0].QueryRoutine = QueryRoutine; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE; + QueryTable[0].Name = NULL; + QueryTable[0].EntryContext = NULL; + QueryTable[0].DefaultType = REG_BINARY; + QueryTable[0].DefaultData = NULL; + QueryTable[0].DefaultLength = 100; + + QueryTable[1].QueryRoutine = QueryRoutine; + QueryTable[1].Flags = 0; + QueryTable[1].Name = NULL; + QueryTable[1].EntryContext = 0; + QueryTable[1].DefaultType = REG_NONE; + QueryTable[1].DefaultData = NULL; + QueryTable[1].DefaultLength = 0; + + QueryTable[2].QueryRoutine = NULL; + QueryTable[2].Flags = 0; + QueryTable[2].Name = NULL; + QueryTable[2].EntryContext = 0; + QueryTable[2].DefaultType = REG_NONE; + QueryTable[2].DefaultData = NULL; + QueryTable[2].DefaultLength = 0; + + status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0); + ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status); + + pRtlFreeHeap(GetProcessHeap(), 0, QueryTable); +} + +static void test_NtCreateKey(void) +{ + /*Create WineTest*/ + OBJECT_ATTRIBUTES attr; + UNICODE_STRING ValName; + HKEY key; + ACCESS_MASK am = GENERIC_ALL; + NTSTATUS status; + + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); + status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0); + ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status); + + pRtlFreeUnicodeString(&ValName); + pNtClose(&key); +} + +static void test_NtSetValueKey(void) +{ + HANDLE key; + NTSTATUS status; + OBJECT_ATTRIBUTES attr; + ACCESS_MASK am = KEY_WRITE; + UNICODE_STRING ValName; + DWORD data = 711; + + pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest"); + + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); + status = pNtOpenKey(&key, am, &attr); + ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status); + + status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data)); + ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status); + + pRtlFreeUnicodeString(&ValName); + pNtClose(&key); +} + +static void test_RtlOpenCurrentUser(void) +{ + NTSTATUS status; + HKEY handle; + status=pRtlOpenCurrentUser(KEY_READ, &handle); + ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status); + pNtClose(&handle); +} + +static void test_RtlCheckRegistryKey(void) +{ + NTSTATUS status; + + status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer); + ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status); + + status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE & RTL_REGISTRY_OPTIONAL), winetestpath.Buffer); + ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE & RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status); +} + +static void test_NtDeleteKey() +{ + NTSTATUS status; + HANDLE hkey; + OBJECT_ATTRIBUTES attr; + ACCESS_MASK am = KEY_ALL_ACCESS; + + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); + status = pNtOpenKey(&hkey, am, &attr); + + status = pNtDeleteKey(hkey); + ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status); +} + +START_TEST(reg) +{ + static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0}; + InitFunctionPtrs(); + pRtlFormatCurrentUserKeyPath(&winetestpath); + winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer, + winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR)); + winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR); + + pRtlAppendUnicodeToString(&winetestpath, winetest); + + test_NtCreateKey(); + test_NtSetValueKey(); + test_RtlCheckRegistryKey(); + test_RtlOpenCurrentUser(); + test_RtlQueryRegistryValues(); + test_NtDeleteKey(); + + pRtlFreeUnicodeString(&winetestpath); + + FreeLibrary(hntdll); +} diff -urN wine-20050211/dlls/ntdll/thread.c wine-20050310/dlls/ntdll/thread.c --- wine-20050211/dlls/ntdll/thread.c 2004-10-11 22:59:06.000000000 +0200 +++ wine-20050310/dlls/ntdll/thread.c 2005-02-22 20:33:50.000000000 +0100 @@ -85,7 +85,7 @@ ULONG size = 0; void *addr = teb; - NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); + NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); wine_ldt_free_fs( teb->teb_sel ); munmap( teb, SIGNAL_STACK_SIZE + sizeof(TEB) ); } @@ -143,7 +143,7 @@ /* create a memory view for the TEB */ addr = teb; - NtAllocateVirtualMemory( GetCurrentProcess(), &addr, 0, &size, + NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); /* create the process heap */ @@ -181,7 +181,7 @@ /* allocate a memory view for the stack */ size = info->stack_size; teb->DeallocationStack = info->stack_base; - NtAllocateVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, 0, + NtAllocateVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, 0, &size, MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); /* limit is lower than base since the stack grows down */ teb->Tib.StackBase = (char *)info->stack_base + info->stack_size; @@ -189,7 +189,7 @@ /* setup the guard page */ size = 1; - NtProtectVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, + NtProtectVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, PAGE_EXECUTE_READWRITE | PAGE_GUARD, NULL ); RtlFreeHeap( GetProcessHeap(), 0, info ); @@ -266,7 +266,7 @@ teb->htask16 = NtCurrentTeb()->htask16; info->pthread_info.teb_base = teb; - NtAllocateVirtualMemory( GetCurrentProcess(), &info->pthread_info.teb_base, 0, &size, + NtAllocateVirtualMemory( NtCurrentProcess(), &info->pthread_info.teb_base, 0, &size, MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); info->pthread_info.teb_size = size; info->pthread_info.teb_sel = teb->teb_sel; diff -urN wine-20050211/dlls/ntdll/time.c wine-20050310/dlls/ntdll/time.c --- wine-20050211/dlls/ntdll/time.c 2005-02-08 13:13:36.000000000 +0100 +++ wine-20050310/dlls/ntdll/time.c 2005-02-22 15:49:59.000000000 +0100 @@ -145,11 +145,11 @@ {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d', 'a','r','d',' ','T','i','m','e','\0'}, 150, 1}, {"BRT", - {'E','.',' ','S','o','u','t','h',' ','A','m','e','r','i','c','a',' ','S', - 't','a','n','d','a','r','d',' ','T','i','m','e','\0'}, 180, 0}, + {'B','r','a','z','i','l','i','a','n',' ','S','t','a','n','d','a','r','d', + ' ','T','i','m','e','\0'}, 180, 0}, {"BRST", - {'E','.',' ','B','r','a','z','i','l','i','a','n',' ','S','t','a','n','d', - 'a','r','d',' ','T','i','m','e','\0'}, 180, 0}, + {'B','r','a','z','i','l','i','a','n',' ','S','u','m','m','e','r', + ' ','T','i','m','e','\0'}, 120, 1}, {"ART", {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r', 'd',' ','T','i','m','e','\0'}, 180, 0}, @@ -309,6 +309,9 @@ {"NZST", {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a', 'r','d',' ','T','i','m','e','\0'}, -720, 0}, + {"NZDT", + {'N','e','w',' ','Z','e','a','l','a','n','d',' ','D','a','y','l','i','g', + 'h','t',' ','T','i','m','e','\0'}, -780, 1}, {"FJT", {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e', '\0'}, -720, 0}, @@ -815,8 +818,9 @@ ) return TZ_INFO[i].psTZWindows; } - FIXME("Can't match system time zone name \"%s\" to an entry in TZ_INFO\n",psTZName); - FIXME(" Please add appropriate entry to TZ_INFO and submit as patch to wine-patches\n"); + FIXME("Can't match system time zone name \"%s\", bias=%d and dst=%d " + "to an entry in TZ_INFO. Please add appropriate entry to " + "TZ_INFO and submit as patch to wine-patches\n",psTZName,bias,dst); return NULL; } diff -urN wine-20050211/dlls/ntdll/virtual.c wine-20050310/dlls/ntdll/virtual.c --- wine-20050211/dlls/ntdll/virtual.c 2005-01-24 12:25:41.000000000 +0100 +++ wine-20050310/dlls/ntdll/virtual.c 2005-02-22 20:33:50.000000000 +0100 @@ -1044,8 +1044,8 @@ done: if (!removable) /* don't keep handle open on removable media */ - NtDuplicateObject( GetCurrentProcess(), hmapping, - GetCurrentProcess(), &view->mapping, + NtDuplicateObject( NtCurrentProcess(), hmapping, + NtCurrentProcess(), &view->mapping, 0, 0, DUPLICATE_SAME_ACCESS ); RtlLeaveCriticalSection( &csVirtual ); @@ -1069,7 +1069,7 @@ { BOOL ret = FALSE; - if (handle == GetCurrentProcess()) return TRUE; + if (handle == NtCurrentProcess()) return TRUE; SERVER_START_REQ( get_process_info ) { req->handle = handle; @@ -1777,8 +1777,8 @@ if (res == STATUS_SUCCESS) { if (!removable) /* don't keep handle open on removable media */ - NtDuplicateObject( GetCurrentProcess(), handle, - GetCurrentProcess(), &view->mapping, + NtDuplicateObject( NtCurrentProcess(), handle, + NtCurrentProcess(), &view->mapping, 0, 0, DUPLICATE_SAME_ACCESS ); *addr_ptr = view->base; diff -urN wine-20050211/dlls/ole32/Makefile.in wine-20050310/dlls/ole32/Makefile.in --- wine-20050211/dlls/ole32/Makefile.in 2004-12-27 20:21:47.000000000 +0100 +++ wine-20050310/dlls/ole32/Makefile.in 2005-02-21 21:58:09.000000000 +0100 @@ -34,6 +34,7 @@ regsvr.c \ rpc.c \ stg_bigblockfile.c \ + stg_prop.c \ stg_stream.c \ storage32.c \ stubmanager.c diff -urN wine-20050211/dlls/ole32/clipboard.c wine-20050310/dlls/ole32/clipboard.c --- wine-20050211/dlls/ole32/clipboard.c 2004-12-23 21:20:49.000000000 +0100 +++ wine-20050310/dlls/ole32/clipboard.c 2005-03-02 14:53:51.000000000 +0100 @@ -82,7 +82,7 @@ /* For CoGetMalloc (MEMCTX_TASK is currently ignored) */ #ifndef MEMCTX_TASK - #define MEMCTX_TASK -1 +# define MEMCTX_TASK -1 #endif WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -799,7 +799,7 @@ * (Recall that in OleSetClipboard, we used SetClipboardData to * make all HGLOBAL formats supported by the source IDataObject * available using delayed rendering) - * On receiving this mesage we must actually render the data in the + * On receiving this message we must actually render the data in the * specified format and place it on the clipboard by calling the * SetClipboardData function. */ diff -urN wine-20050211/dlls/ole32/compobj.c wine-20050310/dlls/ole32/compobj.c --- wine-20050211/dlls/ole32/compobj.c 2005-02-08 17:51:22.000000000 +0100 +++ wine-20050310/dlls/ole32/compobj.c 2005-03-10 18:25:02.000000000 +0100 @@ -30,12 +30,11 @@ * * - Implement the service control manager (in rpcss) to keep track * of registered class objects: ISCM::ServerRegisterClsid et al - * - Implement the OXID resolver so we don't need magic pipe names for + * - Implement the OXID resolver so we don't need magic endpoint names for * clients and servers to meet up - * - Flip our marshalling on top of the RPC runtime transport API, - * so we no longer use named pipes to communicate - * - Implement RPC thread affinity (should fix InstallShield painting - * problems) + * + * - Pump the message loop during RPC calls. + * - Call IMessageFilter functions. * * - Make all ole interface marshaling use NDR to be wire compatible with * native DCOM @@ -163,7 +162,7 @@ }; static CRITICAL_SECTION csOpenDllList = { &dll_cs_debug, -1, 0, 0, 0, 0 }; -static const char aptWinClass[] = "WINE_OLE32_APT_CLASS"; +static const WCHAR wszAptWinClass[] = {'W','I','N','E','_','O','L','E','3','2','_','A','P','T','_','C','L','A','S','S',0}; static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static void COMPOBJ_DLLList_Add(HANDLE hLibrary); @@ -171,7 +170,7 @@ void COMPOBJ_InitProcess( void ) { - WNDCLASSA wclass; + WNDCLASSW wclass; /* Dispatching to the correct thread in an apartment is done through * window messages rather than RPC transports. When an interface is @@ -183,15 +182,15 @@ * was unmarshalled. */ memset(&wclass, 0, sizeof(wclass)); - wclass.lpfnWndProc = &COM_AptWndProc; + wclass.lpfnWndProc = COM_AptWndProc; wclass.hInstance = OLE32_hInstance; - wclass.lpszClassName = aptWinClass; - RegisterClassA(&wclass); + wclass.lpszClassName = wszAptWinClass; + RegisterClassW(&wclass); } void COMPOBJ_UninitProcess( void ) { - UnregisterClassA(aptWinClass, OLE32_hInstance); + UnregisterClassW(wszAptWinClass, OLE32_hInstance); } void COM_TlsDestroy() @@ -239,7 +238,7 @@ { /* FIXME: should be randomly generated by in an RPC call to rpcss */ apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId(); - apt->win = CreateWindowA(aptWinClass, NULL, 0, + apt->win = CreateWindowW(wszAptWinClass, NULL, 0, 0, 0, 0, 0, 0, 0, OLE32_hInstance, NULL); } @@ -249,8 +248,6 @@ apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe; } - apt->shutdown_event = CreateEventW(NULL, TRUE, FALSE, NULL); - TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid)); /* the locking here is not currently needed for the MTA case, but it @@ -354,8 +351,6 @@ if (apt->filter) IUnknown_Release(apt->filter); DeleteCriticalSection(&apt->cs); - SetEvent(apt->shutdown_event); - CloseHandle(apt->shutdown_event); CloseHandle(apt->thread); HeapFree(GetProcessHeap(), 0, apt); } @@ -425,10 +420,15 @@ return apt->win; } -/* Currently inter-thread marshalling is not fully implemented, so this does nothing */ static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return DefWindowProcA(hWnd, msg, wParam, lParam); + switch (msg) + { + case DM_EXECUTERPC: + return RPC_ExecuteCall((RPCOLEMESSAGE *)wParam, (IRpcStubBuffer *)lParam); + default: + return DefWindowProcW(hWnd, msg, wParam, lParam); + } } /***************************************************************************** @@ -473,7 +473,7 @@ static void COMPOBJ_DllList_FreeUnused(int Timeout) { OpenDll *curr, *next, *prev = NULL; - typedef HRESULT(*DllCanUnloadNowFunc)(void); + typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void); DllCanUnloadNowFunc DllCanUnloadNow; TRACE("\n"); @@ -1629,7 +1629,7 @@ /* Next try out of process */ if (CLSCTX_LOCAL_SERVER & dwClsContext) { - return create_marshalled_proxy(rclsid,iid,ppv); + return RPC_GetLocalClassObject(rclsid,iid,ppv); } /* Finally try remote: this requires networked DCOM (a lot of work) */ diff -urN wine-20050211/dlls/ole32/compobj_private.h wine-20050310/dlls/ole32/compobj_private.h --- wine-20050211/dlls/ole32/compobj_private.h 2005-02-08 17:51:22.000000000 +0100 +++ wine-20050310/dlls/ole32/compobj_private.h 2005-03-07 18:14:11.000000000 +0100 @@ -53,10 +53,12 @@ typedef enum ifstub_state { - IFSTUB_STATE_NORMAL_MARSHALED, - IFSTUB_STATE_NORMAL_UNMARSHALED, - IFSTUB_STATE_TABLE_MARSHALED -} IFSTUB_STATE; + STUBSTATE_NORMAL_MARSHALED, + STUBSTATE_NORMAL_UNMARSHALED, + STUBSTATE_TABLE_WEAK_MARSHALED, + STUBSTATE_TABLE_WEAK_UNMARSHALED, + STUBSTATE_TABLE_STRONG, +} STUB_STATE; /* an interface stub */ struct ifstub @@ -66,7 +68,6 @@ IID iid; /* RO */ IPID ipid; /* RO */ IUnknown *iface; /* RO */ - IFSTUB_STATE state; /* CS stub_manager->lock */ }; @@ -78,11 +79,12 @@ CRITICAL_SECTION lock; APARTMENT *apt; /* owning apt (RO) */ - ULONG extrefs; /* number of 'external' references (LOCK) */ + ULONG extrefs; /* number of 'external' references (CS lock) */ ULONG refs; /* internal reference count (CS apt->cs) */ OID oid; /* apartment-scoped unique identifier (RO) */ IUnknown *object; /* the object we are managing the stub for (RO) */ ULONG next_ipid; /* currently unused (LOCK) */ + STUB_STATE state; /* state machine (CS lock) */ }; /* imported interface proxy */ @@ -95,6 +97,7 @@ IPID ipid; /* imported interface ID (RO) */ LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */ DWORD refs; /* imported (public) references (CS parent->cs) */ + IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */ }; /* imported object / proxy manager */ @@ -103,7 +106,6 @@ const IMultiQIVtbl *lpVtbl; struct apartment *parent; /* owning apartment (RO) */ struct list entry; /* entry in apartment (CS parent->cs) */ - LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */ OXID oxid; /* object exported ID (RO) */ OID oid; /* object ID (RO) */ struct list interfaces; /* imported interfaces (CS cs) */ @@ -130,11 +132,10 @@ struct list proxies; /* imported objects (CS cs) */ struct list stubmgrs; /* stub managers for exported objects (CS cs) */ BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */ + LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */ - /* FIXME: These should all be removed long term as they leak information that should be encapsulated */ + /* FIXME: OID's should be given out by RPCSS */ OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ - DWORD listenertid; /* id of apartment_listener_thread */ - HANDLE shutdown_event; /* event used to tell the client_dispatch_thread to shut down */ }; /* this is what is stored in TEB->ReservedForOle */ @@ -146,59 +147,49 @@ DWORD inits; /* number of times CoInitializeEx called */ }; + +/* Global Interface Table Functions */ + extern void* StdGlobalInterfaceTable_Construct(void); extern void StdGlobalInterfaceTable_Destroy(void* self); extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv); +extern void* StdGlobalInterfaceTableInstance; /* FIXME: these shouldn't be needed, except for 16-bit functions */ extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr); HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id); -extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv); - -extern void* StdGlobalInterfaceTableInstance; - -/* Standard Marshalling definitions */ -typedef struct _wine_marshal_id { - OXID oxid; /* id of apartment */ - OID oid; /* id of stub manager */ - IPID ipid; /* id of interface pointer */ -} wine_marshal_id; - -inline static BOOL -MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) { - return - (mid1->oxid == mid2->oxid) && - (mid1->oid == mid2->oid) && - IsEqualGUID(&(mid1->ipid),&(mid2->ipid)) - ; -} - HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt); HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv); +/* Stub Manager */ + ULONG stub_manager_int_addref(struct stub_manager *This); ULONG stub_manager_int_release(struct stub_manager *This); -struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object); +struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object, MSHLFLAGS mshlflags); ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs); ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs); -struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal); +struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid); struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid); struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object); void apartment_disconnect_object(APARTMENT *apt, void *object); -BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid); -BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid); +BOOL stub_manager_notify_unmarshal(struct stub_manager *m); +BOOL stub_manager_is_table_marshaled(struct stub_manager *m); +void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs); HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags); HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret); -IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid); +IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt); HRESULT start_apartment_remote_unknown(void); -IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid); - -void start_apartment_listener_thread(void); +/* RPC Backend */ -extern HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf); -void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); +void RPC_StartRemoting(struct apartment *apt); +HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf); +HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub); +HRESULT RPC_RegisterInterface(REFIID riid); +void RPC_UnregisterInterface(REFIID riid); +void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); +HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv); /* This function initialize the Running Object Table */ HRESULT WINAPI RunningObjectTableImpl_Initialize(void); @@ -209,12 +200,17 @@ /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); -/* compobj.c */ + +/* Apartment Functions */ + APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref); APARTMENT *COM_ApartmentFromTID(DWORD tid); DWORD COM_ApartmentAddRef(struct apartment *apt); DWORD COM_ApartmentRelease(struct apartment *apt); +/* messages used by the apartment window (not compatible with native) */ +#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = (RPCOLEMESSAGE *), LPARAM = (IRpcStubBuffer *) */ + /* * Per-thread values are stored in the TEB on offset 0xF80, * see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm diff -urN wine-20050211/dlls/ole32/errorinfo.c wine-20050310/dlls/ole32/errorinfo.c --- wine-20050211/dlls/ole32/errorinfo.c 2005-01-09 18:29:21.000000000 +0100 +++ wine-20050310/dlls/ole32/errorinfo.c 2005-02-14 12:07:55.000000000 +0100 @@ -386,11 +386,10 @@ LPOLESTR szHelpFile) { _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); - TRACE("(%p)\n",This); + TRACE("(%p,%s)\n",This,debugstr_w(szHelpFile)); if (This->bstrHelpFile != NULL) ERRORINFO_SysFreeString(This->bstrHelpFile); This->bstrHelpFile = ERRORINFO_SysAllocString(szHelpFile); - return S_OK; } @@ -399,9 +398,8 @@ DWORD dwHelpContext) { _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); - TRACE("(%p)\n",This); + TRACE("(%p,%ld)\n",This,dwHelpContext); This->m_dwHelpContext = dwHelpContext; - return S_OK; } diff -urN wine-20050211/dlls/ole32/filemoniker.c wine-20050310/dlls/ole32/filemoniker.c --- wine-20050211/dlls/ole32/filemoniker.c 2004-12-23 21:20:49.000000000 +0100 +++ wine-20050310/dlls/ole32/filemoniker.c 2005-02-18 21:13:23.000000000 +0100 @@ -157,7 +157,7 @@ { FileMonikerImpl *This = (FileMonikerImpl *)iface; - TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); /* Perform a sanity check on the parameters.*/ if ( (This==0) || (ppvObject==0) ) @@ -223,7 +223,7 @@ HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID)/* Pointer to CLSID of object */ { - TRACE("(%p,%p),stub!\n",iface,pClassID); + TRACE("(%p,%p)\n",iface,pClassID); if (pClassID==NULL) return E_POINTER; @@ -473,7 +473,7 @@ static const WCHAR bkSlash[]={'\\',0}; BYTE addBkSlash; - TRACE("(%p,%p)\n",This,lpszPathName); + TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName)); /* Initialize the virtual fgunction table. */ This->lpvtbl1 = &VT_FileMonikerImpl; @@ -566,7 +566,7 @@ *ppvResult=0; - TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); + TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); if(pmkToLeft==NULL){ @@ -673,7 +673,7 @@ IStorage *pstg=0; HRESULT res; - TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject); + TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); if (pmkToLeft==NULL){ @@ -708,7 +708,7 @@ } else { - FIXME("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject); + FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); return E_NOTIMPL; } @@ -1243,6 +1243,8 @@ strcpyW(*ppszDisplayName,This->filePathName); + TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); + return S_OK; } @@ -1283,7 +1285,7 @@ ICOM_THIS_From_IROTData(IMoniker, iface); - TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); return FileMonikerImpl_QueryInterface(This, riid, ppvObject); } @@ -1329,29 +1331,28 @@ ******************************************************************************/ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk) { - FileMonikerImpl* newFileMoniker = 0; - HRESULT hr = E_FAIL; - IID riid=IID_IMoniker; + FileMonikerImpl* newFileMoniker; + HRESULT hr; - TRACE("(%p,%p)\n",lpszPathName,ppmk); + TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk); - if (ppmk==NULL) + if (!ppmk) return E_POINTER; - if(lpszPathName==NULL) + if(!lpszPathName) return MK_E_SYNTAX; - *ppmk=0; + *ppmk=NULL; newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl)); - if (newFileMoniker == 0) + if (!newFileMoniker) return E_OUTOFMEMORY; hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName); if (SUCCEEDED(hr)) - hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk); + hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&IID_IMoniker,(void**)ppmk); else HeapFree(GetProcessHeap(),0,newFileMoniker); diff -urN wine-20050211/dlls/ole32/git.c wine-20050310/dlls/ole32/git.c --- wine-20050211/dlls/ole32/git.c 2004-10-07 05:06:49.000000000 +0200 +++ wine-20050310/dlls/ole32/git.c 2005-02-15 16:47:44.000000000 +0100 @@ -223,6 +223,7 @@ IStream* stream = NULL; HRESULT hres; StdGITEntry* entry; + static const LARGE_INTEGER zero; TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie); @@ -230,8 +231,18 @@ /* marshal the interface */ TRACE("About to marshal the interface\n"); - hres = CoMarshalInterThreadInterfaceInStream(riid, pUnk, &stream); + + hres = CreateStreamOnHGlobal(0, TRUE, &stream); if (hres) return hres; + hres = CoMarshalInterface(stream, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); + if (hres) + { + IStream_Release(stream); + return hres; + } + + IStream_Seek(stream, zero, SEEK_SET, NULL); + entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry)); if (entry == NULL) return E_OUTOFMEMORY; @@ -261,6 +272,7 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) { StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; StdGITEntry* entry; + HRESULT hr; TRACE("iface=%p, dwCookie=0x%x\n", iface, (UINT)dwCookie); @@ -271,6 +283,12 @@ } /* Free the stream */ + hr = CoReleaseMarshalData(entry->stream); + if (hr != S_OK) + { + WARN("Failed to release marshal data, hr = 0x%08lx\n", hr); + return hr; + } IStream_Release(entry->stream); /* chop entry out of the list, and free the memory */ diff -urN wine-20050211/dlls/ole32/itemmoniker.c wine-20050310/dlls/ole32/itemmoniker.c --- wine-20050211/dlls/ole32/itemmoniker.c 2004-12-23 21:20:49.000000000 +0100 +++ wine-20050310/dlls/ole32/itemmoniker.c 2005-02-18 21:13:23.000000000 +0100 @@ -156,7 +156,7 @@ { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; - TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); /* Perform a sanity check on the parameters.*/ if ( (This==0) || (ppvObject==0) ) @@ -221,7 +221,7 @@ ******************************************************************************/ HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) { - TRACE("(%p,%p),stub!\n",iface,pClassID); + TRACE("(%p,%p)\n",iface,pClassID); if (pClassID==NULL) return E_POINTER; @@ -257,6 +257,8 @@ CHAR *itemNameA,*itemDelimiterA; ULONG bread; + TRACE("\n"); + /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */ /* read item delimiter string length + 1 */ @@ -335,6 +337,8 @@ WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL); WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL); + TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE"); + res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL); res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL); res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL); @@ -381,7 +385,7 @@ static const OLECHAR emptystr[1]; LPCOLESTR delim; - TRACE("(%p,%p)\n",This,lpszItem); + TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem)); /* Initialize the virtual fgunction table. */ This->lpvtbl1 = &VT_ItemMonikerImpl; @@ -437,7 +441,7 @@ IID refid=IID_IOleItemContainer; IOleItemContainer *poic=0; - TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); + TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); if(ppvResult ==NULL) return E_POINTER; @@ -473,7 +477,7 @@ HRESULT res; IOleItemContainer *poic=0; - TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); + TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); *ppvResult=0; @@ -781,6 +785,9 @@ HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) { DWORD mkSys; + + TRACE("(%p,%p)\n", pmkOther, ppmkPrefix); + IMoniker_IsSystemMoniker(pmkOther,&mkSys); /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */ /* to this moniker and returns MK_S_US */ @@ -841,6 +848,8 @@ lstrcpyW(*ppszDisplayName,This->itemDelimiter); lstrcatW(*ppszDisplayName,This->itemName); + TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); + return S_OK; } @@ -860,6 +869,8 @@ HRESULT res; ItemMonikerImpl *This = (ItemMonikerImpl *)iface; + TRACE("%s\n", debugstr_w(pszDisplayName)); + /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */ if (pmkToLeft==NULL) @@ -955,15 +966,14 @@ ******************************************************************************/ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk) { - ItemMonikerImpl* newItemMoniker = 0; - HRESULT hr = S_OK; - IID riid=IID_IMoniker; + ItemMonikerImpl* newItemMoniker; + HRESULT hr; - TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk); + TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk); newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); - if (newItemMoniker == 0) + if (!newItemMoniker) return STG_E_INSUFFICIENTMEMORY; hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem); @@ -974,5 +984,5 @@ return hr; } - return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk); + return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk); } diff -urN wine-20050211/dlls/ole32/marshal.c wine-20050310/dlls/ole32/marshal.c --- wine-20050211/dlls/ole32/marshal.c 2005-02-08 15:26:19.000000000 +0100 +++ wine-20050310/dlls/ole32/marshal.c 2005-03-07 18:14:11.000000000 +0100 @@ -117,13 +117,15 @@ stdobjref->oxid = apt->oxid; + /* FIXME: what happens if we register an interface twice with different + * marshaling flags? */ if ((manager = get_stub_manager_from_object(apt, obj))) TRACE("registering new ifstub on pre-existing manager\n"); else { TRACE("constructing new stub manager\n"); - manager = new_stub_manager(apt, obj); + manager = new_stub_manager(apt, obj, mshlflags); if (!manager) return E_OUTOFMEMORY; } @@ -131,7 +133,7 @@ tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK)); - ifstub = stub_manager_new_ifstub(manager, stub, obj, riid, tablemarshal); + ifstub = stub_manager_new_ifstub(manager, stub, obj, riid); if (!ifstub) { IRpcStubBuffer_Release(stub); @@ -153,6 +155,9 @@ stub_manager_ext_addref(manager, 1); } + /* FIXME: check return value */ + RPC_RegisterInterface(riid); + stdobjref->ipid = ifstub->ipid; stub_manager_int_release(manager); @@ -372,12 +377,17 @@ return hr; } +/* should be called inside This->parent->cs critical section */ static void ifproxy_disconnect(struct ifproxy * This) { ifproxy_release_public_refs(This); if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy); + + IRpcChannelBuffer_Release(This->chan); + This->chan = NULL; } +/* should be called in This->parent->cs critical section if it is an entry in parent's list */ static void ifproxy_destroy(struct ifproxy * This) { TRACE("%p\n", This); @@ -388,6 +398,12 @@ list_remove(&This->entry); + if (This->chan) + { + IRpcChannelBuffer_Release(This->chan); + This->chan = NULL; + } + /* note: we don't call Release for This->proxy because its lifetime is * controlled by the return value from ClientIdentity_Release, which this * function is always called from */ @@ -397,7 +413,7 @@ static HRESULT proxy_manager_construct( APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid, - IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager) + struct proxy_manager ** proxy_manager) { struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); if (!This) return E_OUTOFMEMORY; @@ -423,9 +439,6 @@ * should store the STDOBJREF flags in the proxy manager. */ This->sorflags = sorflags; - assert(channel); - This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */ - /* we create the IRemUnknown proxy on demand */ This->remunk = NULL; @@ -473,8 +486,8 @@ } static HRESULT proxy_manager_create_ifproxy( - struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs, - struct ifproxy ** iif_out) + struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs, + IRpcChannelBuffer * channel, struct ifproxy ** iif_out) { HRESULT hr; IPSFactoryBuffer * psfb; @@ -484,11 +497,14 @@ list_init(&ifproxy->entry); ifproxy->parent = This; - ifproxy->ipid = ipid; + ifproxy->ipid = *ipid; ifproxy->iid = *riid; ifproxy->refs = cPublicRefs; ifproxy->proxy = NULL; + assert(channel); + ifproxy->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */ + /* the IUnknown interface is special because it does not have a * proxy associated with the ifproxy as we handle IUnknown ourselves */ if (IsEqualIID(riid, &IID_IUnknown)) @@ -517,7 +533,7 @@ debugstr_guid(riid), hr); if (hr == S_OK) - hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan); + hr = IRpcProxyBuffer_Connect(ifproxy->proxy, ifproxy->chan); } /* get at least one external reference to the object to keep it alive */ @@ -532,7 +548,7 @@ *iif_out = ifproxy; TRACE("ifproxy %p created for IPID %s, interface %s with %lu public refs\n", - ifproxy, debugstr_guid(&ipid), debugstr_guid(riid), cPublicRefs); + ifproxy, debugstr_guid(ipid), debugstr_guid(riid), cPublicRefs); } else ifproxy_destroy(ifproxy); @@ -579,11 +595,6 @@ /* apartment is being destroyed so don't keep a pointer around to it */ This->parent = NULL; - /* FIXME: will this still be necessary if/when we use a real RPC - * channel? */ - IRpcChannelBuffer_Release(This->chan); - This->chan = NULL; - LeaveCriticalSection(&This->cs); } @@ -671,7 +682,6 @@ } if (This->remunk) IRemUnknown_Release(This->remunk); - if (This->chan) IRpcChannelBuffer_Release(This->chan); DeleteCriticalSection(&This->cs); @@ -792,8 +802,8 @@ return CO_E_NOTINITIALIZED; } - start_apartment_listener_thread(); /* just to be sure we have one running. */ - start_apartment_remote_unknown(); + /* make sure this apartment can be reached from other threads / processes */ + RPC_StartRemoting(apt); hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk); if (hres != S_OK) @@ -839,18 +849,9 @@ * object */ if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager)) { - IRpcChannelBuffer *chanbuf; - wine_marshal_id mid; - - mid.oxid = stdobjref->oxid; - mid.oid = stdobjref->oid; - mid.ipid = stdobjref->ipid; - - hr = PIPE_GetNewPipeBuf(&mid,&chanbuf); - if (hr == S_OK) - hr = proxy_manager_construct(apt, stdobjref->flags, - stdobjref->oxid, stdobjref->oid, - chanbuf, &proxy_manager); + hr = proxy_manager_construct(apt, stdobjref->flags, + stdobjref->oxid, stdobjref->oid, + &proxy_manager); } else TRACE("proxy manager already created, using\n"); @@ -860,9 +861,14 @@ struct ifproxy * ifproxy; hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy); if (hr == E_NOINTERFACE) - hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref->ipid, - riid, stdobjref->cPublicRefs, - &ifproxy); + { + IRpcChannelBuffer *chanbuf; + hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf); + if (hr == S_OK) + hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid, + riid, stdobjref->cPublicRefs, + chanbuf, &ifproxy); + } if (hr == S_OK) { @@ -911,7 +917,7 @@ hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv); /* unref the ifstub. FIXME: only do this on success? */ - if (!stub_manager_is_table_marshaled(stubmgr, &stdobjref.ipid)) + if (!stub_manager_is_table_marshaled(stubmgr)) stub_manager_ext_release(stubmgr, 1); stub_manager_int_release(stubmgr); @@ -927,7 +933,7 @@ { if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid))) { - if (!stub_manager_notify_unmarshal(stubmgr, &stdobjref.ipid)) + if (!stub_manager_notify_unmarshal(stubmgr)) hres = CO_E_OBJNOTCONNECTED; stub_manager_int_release(stubmgr); @@ -982,9 +988,7 @@ return RPC_E_INVALID_OBJREF; } - /* FIXME: don't release if table-weak and already unmarshaled an object */ - /* FIXME: this should also depend on stdobjref.cPublicRefs */ - stub_manager_ext_release(stubmgr, 1); + stub_manager_release_marshal_data(stubmgr, stdobjref.cPublicRefs); stub_manager_int_release(stubmgr); COM_ApartmentRelease(apt); @@ -1418,11 +1422,19 @@ if (hr == S_OK) { - hr = IUnknown_QueryInterface(object, &iid, ppv); - if (hr) - ERR("Couldn't query for interface %s, hr = 0x%08lx\n", - debugstr_guid(riid), hr); - IUnknown_Release(object); + if (!IsEqualIID(riid, &iid)) + { + TRACE("requested interface != marshalled interface, additional QI needed\n"); + hr = IUnknown_QueryInterface(object, &iid, ppv); + if (hr) + ERR("Couldn't query for interface %s, hr = 0x%08lx\n", + debugstr_guid(riid), hr); + IUnknown_Release(object); + } + else + { + *ppv = object; + } } IMarshal_Release(pMarshal); diff -urN wine-20050211/dlls/ole32/ole2.c wine-20050310/dlls/ole32/ole2.c --- wine-20050211/dlls/ole32/ole2.c 2005-01-14 18:05:36.000000000 +0100 +++ wine-20050310/dlls/ole32/ole2.c 2005-02-25 15:07:57.000000000 +0100 @@ -1036,7 +1036,7 @@ * All menu messages from these groups should be routed to the server. * * RETURNS: TRUE if the popup menu is part of a server owned group - * FASE if the popup menu is part of a container owned group + * FALSE if the popup menu is part of a container owned group */ BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor ) { diff -urN wine-20050211/dlls/ole32/ole32.spec wine-20050310/dlls/ole32/ole32.spec --- wine-20050211/dlls/ole32/ole32.spec 2005-02-08 17:51:22.000000000 +0100 +++ wine-20050310/dlls/ole32/ole32.spec 2005-03-07 11:59:09.000000000 +0100 @@ -233,6 +233,7 @@ @ stub SNB_UserUnmarshal @ stdcall StgCreateDocfile(wstr long long ptr) @ stdcall StgCreateDocfileOnILockBytes(ptr long long ptr) +@ stdcall StgCreatePropSetStg(ptr long ptr) @ stdcall StgCreateStorageEx(wstr long long long ptr ptr ptr ptr) @ stub StgGetIFillLockBytesOnFile @ stub StgGetIFillLockBytesOnILockBytes diff -urN wine-20050211/dlls/ole32/oleproxy.c wine-20050310/dlls/ole32/oleproxy.c --- wine-20050211/dlls/ole32/oleproxy.c 2005-01-26 22:07:05.000000000 +0100 +++ wine-20050310/dlls/ole32/oleproxy.c 2005-02-15 22:48:09.000000000 +0100 @@ -190,10 +190,8 @@ msg->cbBuffer = ststg.cbSize.u.LowPart; - if (msg->Buffer) - msg->Buffer = HeapReAlloc(GetProcessHeap(),0,msg->Buffer,ststg.cbSize.u.LowPart); - else - msg->Buffer = HeapAlloc(GetProcessHeap(),0,ststg.cbSize.u.LowPart); + I_RpcGetBuffer((RPC_MESSAGE *)msg); + if (hres) return hres; seekto.u.LowPart = 0;seekto.u.HighPart = 0; hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); @@ -546,10 +544,10 @@ /* out */ pMsg->cbBuffer = cIids * sizeof(REMQIRESULT); - if (pMsg->Buffer) - pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer); - else - pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer); + + I_RpcGetBuffer((RPC_MESSAGE *)pMsg); + if (hr) return hr; + buf = pMsg->Buffer; /* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */ memcpy(buf, pQIResults, cIids * sizeof(REMQIRESULT)); @@ -573,12 +571,13 @@ /* out */ pMsg->cbBuffer = cIids * sizeof(HRESULT); - if (pMsg->Buffer) - pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer); - else - pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer); - buf = pMsg->Buffer; - memcpy(buf, pResults, cIids * sizeof(HRESULT)); + + I_RpcGetBuffer((RPC_MESSAGE *)pMsg); + if (!hr) + { + buf = pMsg->Buffer; + memcpy(buf, pResults, cIids * sizeof(HRESULT)); + } CoTaskMemFree(pResults); diff -urN wine-20050211/dlls/ole32/rpc.c wine-20050310/dlls/ole32/rpc.c --- wine-20050211/dlls/ole32/rpc.c 2005-02-08 14:42:15.000000000 +0100 +++ wine-20050310/dlls/ole32/rpc.c 2005-03-04 13:30:47.000000000 +0100 @@ -1,6 +1,7 @@ /* * (Local) RPC Stuff * + * Copyright 2001 Ove Kåven, TransGaming Technologies * Copyright 2002 Marcus Meissner * Copyright 2005 Mike Hearn, Rob Shearman for CodeWeavers * @@ -49,425 +50,530 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); -#define PIPEPREF "\\\\.\\pipe\\" -#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr" +static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg); + +/* we only use one function to dispatch calls for all methods - we use the + * RPC_IF_OLE flag to tell the RPC runtime that this is the case */ +static RPC_DISPATCH_FUNCTION rpc_dispatch_table[1] = { dispatch_rpc }; /* (RO) */ +static RPC_DISPATCH_TABLE rpc_dispatch = { 1, rpc_dispatch_table }; /* (RO) */ + +static struct list registered_interfaces = LIST_INIT(registered_interfaces); /* (CS csRegIf) */ +static CRITICAL_SECTION csRegIf; +static CRITICAL_SECTION_DEBUG csRegIf_debug = +{ + 0, 0, &csRegIf, + { &csRegIf_debug.ProcessLocksList, &csRegIf_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": dcom registered server interfaces") } +}; +static CRITICAL_SECTION csRegIf = { &csRegIf_debug, -1, 0, 0, 0, 0 }; -#define REQTYPE_REQUEST 0 -#define REQTYPE_RESPONSE 1 +static WCHAR wszPipeTransport[] = {'n','c','a','c','n','_','n','p',0}; -struct request_header + +struct registered_if { - DWORD reqid; - IPID ipid; - DWORD iMethod; - DWORD cbBuffer; + struct list entry; + DWORD refs; /* ref count */ + RPC_SERVER_INTERFACE If; /* interface registered with the RPC runtime */ }; -struct response_header +/* get the pipe endpoint specified of the specified apartment */ +static inline void get_rpc_endpoint(LPWSTR endpoint, const OXID *oxid) { - DWORD reqid; - DWORD cbBuffer; - DWORD retval; -}; + /* FIXME: should get endpoint from rpcss */ + static const WCHAR wszEndpointFormat[] = {'\\','p','i','p','e','\\','O','L','E','_','%','0','8','l','x','%','0','8','l','x',0}; + wsprintfW(endpoint, wszEndpointFormat, (DWORD)(*oxid >> 32),(DWORD)*oxid); +} +typedef struct +{ + const IRpcChannelBufferVtbl *lpVtbl; + DWORD refs; +} RpcChannelBuffer; -#define REQSTATE_START 0 -#define REQSTATE_REQ_QUEUED 1 -#define REQSTATE_REQ_WAITING_FOR_REPLY 2 -#define REQSTATE_REQ_GOT 3 -#define REQSTATE_INVOKING 4 -#define REQSTATE_RESP_QUEUED 5 -#define REQSTATE_RESP_GOT 6 -#define REQSTATE_DONE 6 - -struct rpc -{ - int state; - HANDLE hPipe; /* temp copy of handle */ - struct request_header reqh; - struct response_header resph; - LPBYTE Buffer; -}; +typedef struct +{ + RpcChannelBuffer super; /* superclass */ -/* fixme: this should have a lock */ -static struct rpc **reqs = NULL; -static int nrofreqs = 0; - -/* This pipe is _thread_ based, each thread which talks to a remote - * apartment (oxid) has its own pipe. The same structure is used both - * for outgoing and incoming RPCs. - */ -struct pipe + RPC_BINDING_HANDLE bind; /* handle to the remote server */ +} ClientRpcChannelBuffer; + +static HRESULT WINAPI RpcChannelBuffer_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv) { - wine_marshal_id mid; /* target mid */ - DWORD tid; /* thread which owns this pipe */ - HANDLE hPipe; + *ppv = NULL; + if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) + { + *ppv = (LPVOID)iface; + IUnknown_AddRef(iface); + return S_OK; + } + return E_NOINTERFACE; +} - int pending; - HANDLE hThread; - CRITICAL_SECTION crit; +static ULONG WINAPI RpcChannelBuffer_AddRef(LPRPCCHANNELBUFFER iface) +{ + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; + return InterlockedIncrement(&This->refs); +} - APARTMENT *apt; /* apartment of the marshalling thread for the stub dispatch case */ -}; +static ULONG WINAPI ServerRpcChannelBuffer_Release(LPRPCCHANNELBUFFER iface) +{ + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; + ULONG ref; -typedef struct _PipeBuf { - IRpcChannelBufferVtbl *lpVtbl; - DWORD ref; + ref = InterlockedDecrement(&This->refs); + if (ref) + return ref; - wine_marshal_id mid; - HANDLE pipe; -} PipeBuf; + HeapFree(GetProcessHeap(), 0, This); + return 0; +} +static ULONG WINAPI ClientRpcChannelBuffer_Release(LPRPCCHANNELBUFFER iface) +{ + ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface; + ULONG ref; + ref = InterlockedDecrement(&This->super.refs); + if (ref) + return ref; -/* some helper functions */ + RpcBindingFree(&This->bind); + HeapFree(GetProcessHeap(), 0, This); + return 0; +} -static HRESULT WINAPI read_pipe(HANDLE hf, LPVOID ptr, DWORD size) +static HRESULT WINAPI ServerRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) { - DWORD res; - - if (!ReadFile(hf,ptr,size,&res,NULL)) - { - ERR("Failed to read from %p, le is %ld\n",hf,GetLastError()); - return E_FAIL; - } - - if (res != size) - { - if (!res) - { - WARN("%p disconnected\n", hf); - return RPC_E_DISCONNECTED; - } - ERR("Read only %ld of %ld bytes from %p.\n",res,size,hf); - return E_FAIL; - } - return S_OK; -} + RpcChannelBuffer *This = (RpcChannelBuffer *)iface; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; -static HRESULT WINAPI -write_pipe(HANDLE hf, LPVOID ptr, DWORD size) { - DWORD res; - if (!WriteFile(hf,ptr,size,&res,NULL)) { - FIXME("Failed to write to %p, le is %ld\n",hf,GetLastError()); - return E_FAIL; - } - if (res!=size) { - FIXME("Wrote only %ld of %ld bytes to %p.\n",res,size,hf); - return E_FAIL; - } - return S_OK; + TRACE("(%p)->(%p,%p)\n", This, olemsg, riid); + + status = I_RpcGetBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } -static HANDLE dupe_handle(HANDLE h) +static HRESULT WINAPI ClientRpcChannelBuffer_GetBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg, REFIID riid) { - HANDLE h2; - - if (!DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), - &h2, 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - ERR("could not duplicate handle: %ld\n", GetLastError()); - return INVALID_HANDLE_VALUE; - } + ClientRpcChannelBuffer *This = (ClientRpcChannelBuffer *)iface; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_CLIENT_INTERFACE *cif; + RPC_STATUS status; + + TRACE("(%p)->(%p,%p)\n", This, olemsg, riid); + + cif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_CLIENT_INTERFACE)); + if (!cif) + return E_OUTOFMEMORY; + + cif->Length = sizeof(RPC_CLIENT_INTERFACE); + /* RPC interface ID = COM interface ID */ + cif->InterfaceId.SyntaxGUID = *riid; + /* COM objects always have a version of 0.0 */ + cif->InterfaceId.SyntaxVersion.MajorVersion = 0; + cif->InterfaceId.SyntaxVersion.MinorVersion = 0; + msg->RpcInterfaceInformation = cif; + msg->Handle = This->bind; - return h2; + status = I_RpcGetBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } +struct rpc_sendreceive_params +{ + RPC_MESSAGE *msg; + RPC_STATUS status; +}; +/* this thread runs an outgoing RPC */ +static DWORD WINAPI rpc_sendreceive_thread(LPVOID param) +{ + struct rpc_sendreceive_params *data = (struct rpc_sendreceive_params *) param; + + TRACE("starting up\n"); + /* FIXME: trap and rethrow RPC exceptions in app thread */ + data->status = I_RpcSendReceive(data->msg); -static DWORD WINAPI client_dispatch_thread(LPVOID); + TRACE("completed with status 0x%lx\n", data->status); + + return 0; +} -/* FIXME: this all needs to be made thread safe */ -static HRESULT RPC_GetRequest(struct rpc **req) +static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus) { - static int reqid = 0; - int i; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + HRESULT hr = S_OK; + HANDLE thread; + struct rpc_sendreceive_params *params; + DWORD tid, res; + RPC_STATUS status; + + TRACE("(%p)\n", msg); + + params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params)); + if (!params) return E_OUTOFMEMORY; + + params->msg = msg; + + /* we use a separate thread here because we need to be able to + * pump the message loop in the application thread: if we do not, + * any windows created by this thread will hang and RPCs that try + * and re-enter this STA from an incoming server thread will + * deadlock. InstallShield is an example of that. + */ + + thread = CreateThread(NULL, 0, rpc_sendreceive_thread, params, 0, &tid); + if (!thread) + { + ERR("Could not create RpcSendReceive thread, error %lx\n", GetLastError()); + return E_UNEXPECTED; + } - /* try to reuse */ - for (i = 0; i < nrofreqs; i++) + while (TRUE) { - if (reqs[i]->state == REQSTATE_DONE) + TRACE("waiting for rpc completion or window message\n"); + res = MsgWaitForMultipleObjectsEx(1, &thread, INFINITE, QS_ALLINPUT, 0); + + if (res == WAIT_OBJECT_0 + 1) /* messages available */ { - TRACE("reusing reqs[%d]\n", i); - - reqs[i]->reqh.reqid = reqid++; - reqs[i]->resph.reqid = reqs[i]->reqh.reqid; - reqs[i]->hPipe = INVALID_HANDLE_VALUE; - reqs[i]->state = REQSTATE_START; - *req = reqs[i]; - return S_OK; + MSG message; + while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE)) + { + /* FIXME: filter the messages here */ + if (message.message == DM_EXECUTERPC) + TRACE("received DM_EXECUTRPC dispatch request, re-entering ...\n"); + else + TRACE("received message whilst waiting for RPC: 0x%x\n", message.message); + TranslateMessage(&message); + DispatchMessageW(&message); + } + } + else if (res == WAIT_OBJECT_0) + { + break; /* RPC is completed */ + } + else + { + ERR("Unexpected wait termination: %ld, %ld\n", res, GetLastError()); + hr = E_UNEXPECTED; + break; } } + + CloseHandle(thread); + + status = params->status; + HeapFree(GetProcessHeap(), 0, params); + params = NULL; + if (hr) return hr; - TRACE("creating new struct rpc (request)\n"); - - if (reqs) - reqs = (struct rpc**)HeapReAlloc( - GetProcessHeap(), - HEAP_ZERO_MEMORY, - reqs, - sizeof(struct rpc*)*(nrofreqs+1) - ); + if (pstatus) *pstatus = status; + + TRACE("RPC call status: 0x%lx\n", status); + if (status == RPC_S_OK) + hr = S_OK; + else if (status == RPC_S_CALL_FAILED) + hr = *(HRESULT *)msg->Buffer; else - reqs = (struct rpc**)HeapAlloc( - GetProcessHeap(), - HEAP_ZERO_MEMORY, - sizeof(struct rpc*) - ); - - if (!reqs) return E_OUTOFMEMORY; - - reqs[nrofreqs] = (struct rpc*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(struct rpc)); - reqs[nrofreqs]->reqh.reqid = reqid++; - reqs[nrofreqs]->resph.reqid = reqs[nrofreqs]->reqh.reqid; - reqs[nrofreqs]->hPipe = INVALID_HANDLE_VALUE; - reqs[nrofreqs]->state = REQSTATE_START; - *req = reqs[nrofreqs]; - - nrofreqs++; - - return S_OK; -} + hr = HRESULT_FROM_WIN32(status); -static HRESULT WINAPI -PipeBuf_QueryInterface( - LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv -) { - *ppv = NULL; - if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) { - *ppv = (LPVOID)iface; - IUnknown_AddRef(iface); - return S_OK; - } - return E_NOINTERFACE; -} + TRACE("-- 0x%08lx\n", hr); -static ULONG WINAPI -PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) { - PipeBuf *This = (PipeBuf *)iface; - return InterlockedIncrement(&This->ref); + return hr; } -static ULONG WINAPI -PipeBuf_Release(LPRPCCHANNELBUFFER iface) { - PipeBuf *This = (PipeBuf *)iface; - ULONG ref; +static HRESULT WINAPI ServerRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) +{ + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; - ref = InterlockedDecrement(&This->ref); - if (ref) - return ref; + TRACE("(%p)\n", msg); - CloseHandle(This->pipe); - HeapFree(GetProcessHeap(),0,This); - return 0; + status = I_RpcFreeBuffer(msg); + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } -static HRESULT WINAPI -PipeBuf_GetBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid) +static HRESULT WINAPI ClientRpcChannelBuffer_FreeBuffer(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE* olemsg) { - TRACE("(%p,%s)\n",msg,debugstr_guid(riid)); - /* probably reuses IID in real. */ - if (msg->cbBuffer && (msg->Buffer == NULL)) - msg->Buffer = HeapAlloc(GetProcessHeap(),0,msg->cbBuffer); - return S_OK; + RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg; + RPC_STATUS status; + + TRACE("(%p)\n", msg); + + status = I_RpcFreeBuffer(msg); + + HeapFree(GetProcessHeap(), 0, msg->RpcInterfaceInformation); + msg->RpcInterfaceInformation = NULL; + + TRACE("-- %ld\n", status); + + return HRESULT_FROM_WIN32(status); } -static HRESULT -COM_InvokeAndRpcSend(struct rpc *req) { - IRpcStubBuffer *stub; - RPCOLEMESSAGE msg; - HRESULT hres; - DWORD reqtype; +static HRESULT WINAPI RpcChannelBuffer_GetDestCtx(LPRPCCHANNELBUFFER iface, DWORD* pdwDestContext, void** ppvDestContext) +{ + FIXME("(%p,%p), stub!\n", pdwDestContext, ppvDestContext); + return E_FAIL; +} - if (!(stub = ipid_to_stubbuffer(&(req->reqh.ipid)))) - /* ipid_to_stubbuffer will already have logged the error */ - return RPC_E_DISCONNECTED; - - IUnknown_AddRef(stub); - msg.Buffer = req->Buffer; - msg.iMethod = req->reqh.iMethod; - msg.cbBuffer = req->reqh.cbBuffer; - msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; - req->state = REQSTATE_INVOKING; - req->resph.retval = IRpcStubBuffer_Invoke(stub,&msg,NULL); - IUnknown_Release(stub); - req->Buffer = msg.Buffer; - req->resph.cbBuffer = msg.cbBuffer; - reqtype = REQTYPE_RESPONSE; - hres = write_pipe(req->hPipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - hres = write_pipe(req->hPipe,&(req->resph),sizeof(req->resph)); - if (hres) return hres; - hres = write_pipe(req->hPipe,req->Buffer,req->resph.cbBuffer); - if (hres) return hres; - req->state = REQSTATE_DONE; +static HRESULT WINAPI RpcChannelBuffer_IsConnected(LPRPCCHANNELBUFFER iface) +{ + TRACE("()\n"); + /* native does nothing too */ return S_OK; } -static HRESULT process_incoming_rpc(HANDLE pipe); +static const IRpcChannelBufferVtbl ClientRpcChannelBufferVtbl = +{ + RpcChannelBuffer_QueryInterface, + RpcChannelBuffer_AddRef, + ClientRpcChannelBuffer_Release, + ClientRpcChannelBuffer_GetBuffer, + RpcChannelBuffer_SendReceive, + ClientRpcChannelBuffer_FreeBuffer, + RpcChannelBuffer_GetDestCtx, + RpcChannelBuffer_IsConnected +}; -static HRESULT RPC_QueueRequestAndWait(struct rpc *req, HANDLE pipe) +static const IRpcChannelBufferVtbl ServerRpcChannelBufferVtbl = { - int i; - struct rpc *xreq; - HRESULT hres; - DWORD reqtype; - - req->hPipe = pipe; - req->state = REQSTATE_REQ_WAITING_FOR_REPLY; - reqtype = REQTYPE_REQUEST; - hres = write_pipe(req->hPipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - hres = write_pipe(req->hPipe,&(req->reqh),sizeof(req->reqh)); - if (hres) return hres; - hres = write_pipe(req->hPipe,req->Buffer,req->reqh.cbBuffer); - if (hres) return hres; + RpcChannelBuffer_QueryInterface, + RpcChannelBuffer_AddRef, + ServerRpcChannelBuffer_Release, + ServerRpcChannelBuffer_GetBuffer, + RpcChannelBuffer_SendReceive, + ServerRpcChannelBuffer_FreeBuffer, + RpcChannelBuffer_GetDestCtx, + RpcChannelBuffer_IsConnected +}; + +/* returns a channel buffer for proxies */ +HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **chan) +{ + ClientRpcChannelBuffer *This; + WCHAR endpoint[200]; + RPC_BINDING_HANDLE bind; + RPC_STATUS status; + LPWSTR string_binding; + + /* connect to the apartment listener thread */ + get_rpc_endpoint(endpoint, oxid); + + TRACE("proxy pipe: connecting to endpoint: %s\n", debugstr_w(endpoint)); + + status = RpcStringBindingComposeW( + NULL, + wszPipeTransport, + NULL, + endpoint, + NULL, + &string_binding); + + if (status == RPC_S_OK) + { + status = RpcBindingFromStringBindingW(string_binding, &bind); + + if (status == RPC_S_OK) + { + IPID ipid2 = *ipid; /* why can't RpcBindingSetObject take a const? */ + status = RpcBindingSetObject(bind, &ipid2); + if (status != RPC_S_OK) + RpcBindingFree(&bind); + } - /* This loop is about allowing re-entrancy. While waiting for the - * response to one RPC we may receive a request starting another. */ - while (!hres) { - hres = process_incoming_rpc(pipe); - if (hres) break; - - for (i=0;istate==REQSTATE_REQ_GOT) && (xreq->hPipe==req->hPipe)) { - hres = COM_InvokeAndRpcSend(xreq); - if (hres) break; - } - } - if (req->state == REQSTATE_RESP_GOT) - return S_OK; + RpcStringFreeW(&string_binding); } - if (FAILED(hres)) - WARN("-- 0x%08lx\n", hres); - return hres; -} -static HRESULT WINAPI -PipeBuf_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *msg, ULONG *status) -{ - PipeBuf *This = (PipeBuf *)iface; - struct rpc *req; - HRESULT hres; - - if (This->mid.oxid == COM_CurrentApt()->oxid) { - ERR("Need to call directly!\n"); - return E_FAIL; + if (status != RPC_S_OK) + { + ERR("Couldn't get binding for endpoint %s, status = %ld\n", debugstr_w(endpoint), status); + return HRESULT_FROM_WIN32(status); } - hres = RPC_GetRequest(&req); - if (hres) return hres; - req->reqh.iMethod = msg->iMethod; - req->reqh.cbBuffer = msg->cbBuffer; - req->reqh.ipid = This->mid.ipid; - req->Buffer = msg->Buffer; - TRACE(" -> rpc ->\n"); - hres = RPC_QueueRequestAndWait(req, This->pipe); - TRACE(" <- response <-\n"); - if (hres) + This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) { - req->state = REQSTATE_DONE; - return hres; + RpcBindingFree(&bind); + return E_OUTOFMEMORY; } - - msg->cbBuffer = req->resph.cbBuffer; - msg->Buffer = req->Buffer; - *status = req->resph.retval; - req->state = REQSTATE_DONE; - + + This->super.lpVtbl = &ClientRpcChannelBufferVtbl; + This->super.refs = 1; + This->bind = bind; + + *chan = (IRpcChannelBuffer*)This; + return S_OK; } - -static HRESULT WINAPI -PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) +HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan) { - TRACE("(%p)\n",msg); - HeapFree(GetProcessHeap(), 0, msg->Buffer); + RpcChannelBuffer *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->lpVtbl = &ServerRpcChannelBufferVtbl; + This->refs = 1; + + *chan = (IRpcChannelBuffer*)This; + return S_OK; } -static HRESULT WINAPI -PipeBuf_GetDestCtx(LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext) + +HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub) { - FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext); - return E_FAIL; + /* FIXME: pass server channel buffer, but don't create it every time */ + return IRpcStubBuffer_Invoke(stub, msg, NULL); } -static HRESULT WINAPI -PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) +static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg) { - FIXME("(), stub!\n"); - return S_OK; -} + IRpcStubBuffer *stub; + APARTMENT *apt; + IPID ipid; -static IRpcChannelBufferVtbl pipebufvt = { - PipeBuf_QueryInterface, - PipeBuf_AddRef, - PipeBuf_Release, - PipeBuf_GetBuffer, - PipeBuf_SendReceive, - PipeBuf_FreeBuffer, - PipeBuf_GetDestCtx, - PipeBuf_IsConnected -}; + RpcBindingInqObject(msg->Handle, &ipid); -/* returns a pipebuf for proxies */ -HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) -{ - wine_marshal_id ourid; - HANDLE handle; - PipeBuf *pbuf; - char pipefn[200]; + stub = ipid_to_apt_and_stubbuffer(&ipid, &apt); + if (!apt || !stub) + { + if (apt) COM_ApartmentRelease(apt); + /* ipid_to_apt_and_stubbuffer will already have logged the error */ + return RpcRaiseException(RPC_E_DISCONNECTED); + } - /* connect to the apartment listener thread */ - sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid); + /* Note: this is the important difference between STAs and MTAs - we + * always execute RPCs to STAs in the thread that originally created the + * apartment (i.e. the one that pumps messages to the window) */ + if (apt->model & COINIT_APARTMENTTHREADED) + SendMessageW(apt->win, DM_EXECUTERPC, (WPARAM)msg, (LPARAM)stub); + else + RPC_ExecuteCall((RPCOLEMESSAGE *)msg, stub); - TRACE("proxy pipe: connecting to apartment listener thread: %s\n", pipefn); + COM_ApartmentRelease(apt); + IRpcStubBuffer_Release(stub); +} - while (TRUE) +/* stub registration */ +HRESULT RPC_RegisterInterface(REFIID riid) +{ + struct registered_if *rif; + BOOL found = FALSE; + HRESULT hr = S_OK; + + TRACE("(%s)\n", debugstr_guid(riid)); + + EnterCriticalSection(&csRegIf); + LIST_FOR_EACH_ENTRY(rif, ®istered_interfaces, struct registered_if, entry) { - BOOL ret = WaitNamedPipeA(pipefn, NMPWAIT_USE_DEFAULT_WAIT); - if (!ret) + if (IsEqualGUID(&rif->If.InterfaceId.SyntaxGUID, riid)) { - ERR("Could not open named pipe %s, error %ld\n", pipefn, GetLastError()); - return RPC_E_SERVER_DIED; + rif->refs++; + found = TRUE; + break; } + } + if (!found) + { + TRACE("Creating new interface\n"); - handle = CreateFileA(pipefn, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, 0, 0); - - if (handle == INVALID_HANDLE_VALUE) + rif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rif)); + if (rif) { - if (GetLastError() == ERROR_PIPE_BUSY) continue; - - ERR("Could not open named pipe %s, error %ld\n", pipefn, GetLastError()); - return RPC_E_SERVER_DIED; + RPC_STATUS status; + + rif->refs = 1; + rif->If.Length = sizeof(RPC_SERVER_INTERFACE); + /* RPC interface ID = COM interface ID */ + rif->If.InterfaceId.SyntaxGUID = *riid; + rif->If.DispatchTable = &rpc_dispatch; + /* all other fields are 0, including the version asCOM objects + * always have a version of 0.0 */ + status = RpcServerRegisterIfEx( + (RPC_IF_HANDLE)&rif->If, + NULL, NULL, + RPC_IF_OLE | RPC_IF_AUTOLISTEN, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, + NULL); + if (status == RPC_S_OK) + list_add_tail(®istered_interfaces, &rif->entry); + else + { + ERR("RpcServerRegisterIfEx failed with error %ld\n", status); + HeapFree(GetProcessHeap(), 0, rif); + hr = HRESULT_FROM_WIN32(status); + } } + else + hr = E_OUTOFMEMORY; + } + LeaveCriticalSection(&csRegIf); + return hr; +} - break; +/* stub unregistration */ +void RPC_UnregisterInterface(REFIID riid) +{ + struct registered_if *rif; + EnterCriticalSection(&csRegIf); + LIST_FOR_EACH_ENTRY(rif, ®istered_interfaces, struct registered_if, entry) + { + if (IsEqualGUID(&rif->If.InterfaceId.SyntaxGUID, riid)) + { + if (!--rif->refs) + { +#if 0 /* this is a stub in builtin and spams the console with FIXME's */ + IID iid = *riid; /* RpcServerUnregisterIf doesn't take const IID */ + RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, &iid, 0); + list_remove(&rif->entry); + HeapFree(GetProcessHeap(), 0, rif); +#endif + } + break; + } } + LeaveCriticalSection(&csRegIf); +} + +/* make the apartment reachable by other threads and processes and create the + * IRemUnknown object */ +void RPC_StartRemoting(struct apartment *apt) +{ + if (!InterlockedExchange(&apt->remoting_started, TRUE)) + { + WCHAR endpoint[200]; + RPC_STATUS status; + + get_rpc_endpoint(endpoint, &apt->oxid); - memset(&ourid,0,sizeof(ourid)); - ourid.oxid = COM_CurrentApt()->oxid; - - TRACE("constructing new pipebuf for proxy\n"); - - pbuf = (PipeBuf*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PipeBuf)); - pbuf->lpVtbl = &pipebufvt; - pbuf->ref = 1; - memcpy(&(pbuf->mid),mid,sizeof(*mid)); - pbuf->pipe = dupe_handle(handle); - - *pipebuf = (IRpcChannelBuffer*)pbuf; - - return S_OK; + status = RpcServerUseProtseqEpW( + wszPipeTransport, + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + endpoint, + NULL); + if (status != RPC_S_OK) + ERR("Couldn't register endpoint %s\n", debugstr_w(endpoint)); + + /* FIXME: move remote unknown exporting into this function */ + } + start_apartment_remote_unknown(); } -static HRESULT -create_server(REFCLSID rclsid) + +static HRESULT create_server(REFCLSID rclsid) { static const WCHAR embedding[] = { ' ', '-','E','m','b','e','d','d','i','n','g',0 }; HKEY key; @@ -512,8 +618,10 @@ if (!CreateProcessW(exe, command, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo)) { WARN("failed to run local server %s\n", debugstr_w(exe)); - return E_FAIL; + return HRESULT_FROM_WIN32(GetLastError()); } + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); return S_OK; } @@ -521,8 +629,7 @@ /* * start_local_service() - start a service given its name and parameters */ -static DWORD -start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) +static DWORD start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) { SC_HANDLE handle, hsvc; DWORD r = ERROR_FUNCTION_FAILED; @@ -559,8 +666,7 @@ * * Note: Local Services are not supported under Windows 9x */ -static HRESULT -create_local_service(REFCLSID rclsid) +static HRESULT create_local_service(REFCLSID rclsid) { HRESULT hres = REGDB_E_READREGDB; WCHAR buf[40], keyname[50]; @@ -625,8 +731,10 @@ return hres; } -/* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */ -HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +#define PIPEPREF "\\\\.\\pipe\\" + +/* FIXME: should call to rpcss instead */ +HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { HRESULT hres; HANDLE hPipe; @@ -637,8 +745,8 @@ LARGE_INTEGER seekto; ULARGE_INTEGER newpos; int tries = 0; - - static const int MAXTRIES = 10000; + + static const int MAXTRIES = 30; /* 30 seconds */ TRACE("rclsid=%s, iid=%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); @@ -691,302 +799,13 @@ } -/* this reads an RPC from the given pipe and places it in the global reqs array */ -static HRESULT process_incoming_rpc(HANDLE pipe) -{ - DWORD reqtype; - HRESULT hres = S_OK; - - hres = read_pipe(pipe,&reqtype,sizeof(reqtype)); - if (hres) return hres; - - /* only received by servers */ - if (reqtype == REQTYPE_REQUEST) - { - struct rpc *xreq; - - RPC_GetRequest(&xreq); - - xreq->hPipe = pipe; - hres = read_pipe(pipe,&(xreq->reqh),sizeof(xreq->reqh)); - if (hres) - { - xreq->state = REQSTATE_DONE; - return hres; - } - - xreq->resph.reqid = xreq->reqh.reqid; - xreq->Buffer = HeapAlloc(GetProcessHeap(),0, xreq->reqh.cbBuffer); - hres = read_pipe(pipe,xreq->Buffer,xreq->reqh.cbBuffer); - if (hres) goto end; - - TRACE("received RPC for IPID %s\n", debugstr_guid(&xreq->reqh.ipid)); - - xreq->state = REQSTATE_REQ_GOT; - goto end; - } - else if (reqtype == REQTYPE_RESPONSE) - { - struct response_header resph; - int i; - - hres = read_pipe(pipe,&resph,sizeof(resph)); - if (hres) goto end; - - TRACE("read RPC response\n"); - - for (i = nrofreqs; i--;) - { - struct rpc *xreq = reqs[i]; - - if (xreq->state != REQSTATE_REQ_WAITING_FOR_REPLY) - continue; - - if (xreq->reqh.reqid == resph.reqid) - { - memcpy(&(xreq->resph),&resph,sizeof(resph)); - - if (xreq->Buffer) - xreq->Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->Buffer,xreq->resph.cbBuffer); - else - xreq->Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->resph.cbBuffer); - - hres = read_pipe(pipe,xreq->Buffer,xreq->resph.cbBuffer); - if (hres) goto end; - - TRACE("received response for reqid 0x%lx\n", xreq->reqh.reqid); - - xreq->state = REQSTATE_RESP_GOT; - goto end; - } - } - - ERR("protocol error: did not find request for id %lx\n",resph.reqid); - hres = E_FAIL; - goto end; - } - - ERR("protocol error: unknown reqtype %ld\n",reqtype); - hres = E_FAIL; -end: - return hres; -} - -struct stub_dispatch_params -{ - struct apartment *apt; - HANDLE pipe; -}; - -/* This thread listens on the given pipe for requests to any stub manager */ -static DWORD WINAPI client_dispatch_thread(LPVOID param) -{ - HANDLE pipe = ((struct stub_dispatch_params *)param)->pipe; - struct apartment *apt = ((struct stub_dispatch_params *)param)->apt; - HRESULT hres = S_OK; - HANDLE shutdown_event = dupe_handle(apt->shutdown_event); - - HeapFree(GetProcessHeap(), 0, param); - - /* join marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */ - COM_CurrentInfo()->apt = apt; - - while (TRUE) - { - int i; - - TRACE("waiting for RPC on OXID: %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - - /* read a new request into the global array, block if no requests have been sent */ - hres = process_incoming_rpc(pipe); - if (hres) break; - - /* do you expect me to talk? */ - if (WaitForSingleObject(shutdown_event, 0) == WAIT_OBJECT_0) - { - /* no mr bond, i expect you to die! bwahaha */ - CloseHandle(shutdown_event); - break; - } - - TRACE("received RPC on OXID: %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - - /* now scan the array looking for the RPC just loaded */ - for (i=nrofreqs;i--;) - { - struct rpc *req = reqs[i]; - - if ((req->state == REQSTATE_REQ_GOT) && (req->hPipe == pipe)) - { - hres = COM_InvokeAndRpcSend(req); - if (!hres) break; - } - } - } - - TRACE("exiting with hres %lx\n",hres); - - /* leave marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */ - COM_CurrentInfo()->apt = NULL; - - DisconnectNamedPipe(pipe); - CloseHandle(pipe); - return 0; -} - -struct apartment_listener_params -{ - APARTMENT *apt; - HANDLE event; -}; - -/* This thread listens on a named pipe for each apartment that exports - * objects. It deals with incoming connection requests. Each time a - * client connects a separate thread is spawned for that particular - * connection. - * - * This architecture is different in native DCOM. - */ -static DWORD WINAPI apartment_listener_thread(LPVOID p) -{ - char pipefn[200]; - HANDLE listenPipe, thread_handle; - OVERLAPPED overlapped; - HANDLE wait[2]; - - struct apartment_listener_params * params = (struct apartment_listener_params *)p; - struct apartment *apt = params->apt; - HANDLE event = params->event; - HANDLE apt_shutdown_event = dupe_handle(apt->shutdown_event); - OXID this_oxid = apt->oxid; /* copy here so we can print it when we shut down */ - - HeapFree(GetProcessHeap(), 0, params); - - overlapped.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - - /* we must join the marshalling threads apartment. we already have a ref here */ - COM_CurrentInfo()->apt = apt; - - sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - TRACE("Apartment listener thread starting on (%s)\n",pipefn); - - while (TRUE) - { - struct stub_dispatch_params *params; - DWORD res; - - listenPipe = CreateNamedPipeA( - pipefn, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE|PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - 4096, - 4096, - 500 /* 0.5 seconds */, - NULL - ); - - /* tell function that started this thread that we have attempted to created the - * named pipe. */ - if (event) { - SetEvent(event); - event = NULL; - } - - if (listenPipe == INVALID_HANDLE_VALUE) { - FIXME("pipe creation failed for %s, error %ld\n",pipefn,GetLastError()); - break; /* permanent failure, so quit stubmgr thread */ - } - - TRACE("waiting for a client ...\n"); - - /* an already connected pipe is not an error */ - if (!ConnectNamedPipe(listenPipe, &overlapped)) - { - DWORD le = GetLastError(); - - if ((le != ERROR_IO_PENDING) && (le != ERROR_PIPE_CONNECTED)) - { - ERR("Failure during ConnectNamedPipe %ld!\n",GetLastError()); - CloseHandle(listenPipe); - continue; - } - } - - /* wait for action */ - wait[0] = apt_shutdown_event; - wait[1] = overlapped.hEvent; - res = WaitForMultipleObjectsEx(2, wait, FALSE, INFINITE, FALSE); - if (res == WAIT_OBJECT_0) break; - - ResetEvent(overlapped.hEvent); - - /* start the stub dispatch thread for this connection */ - TRACE("starting stub dispatch thread for OXID %08lx%08lx\n", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); - params = HeapAlloc(GetProcessHeap(), 0, sizeof(struct stub_dispatch_params)); - if (!params) - { - ERR("out of memory, dropping this client\n"); - CloseHandle(listenPipe); - continue; - } - params->apt = apt; - params->pipe = listenPipe; - thread_handle = CreateThread(NULL, 0, &client_dispatch_thread, params, 0, NULL); - CloseHandle(thread_handle); - } - - TRACE("shutting down: %s\n", wine_dbgstr_longlong(this_oxid)); - - /* we must leave the marshalling threads apartment. we don't have a ref here */ - COM_CurrentInfo()->apt = NULL; - - DisconnectNamedPipe(listenPipe); - CloseHandle(listenPipe); - CloseHandle(overlapped.hEvent); - CloseHandle(apt_shutdown_event); - return 0; -} - -void start_apartment_listener_thread() -{ - APARTMENT *apt = COM_CurrentApt(); - - assert( apt ); - - TRACE("apt->listenertid=%ld\n", apt->listenertid); - - /* apt->listenertid is a hack which needs to die at some point, as - * it leaks information into the apartment structure. in fact, - * this thread isn't quite correct anyway as native RPC doesn't - * use a thread per apartment at all, instead the dispatch thread - * either enters the apartment to perform the RPC (for MTAs, RTAs) - * or does a context switch into it for STAs. - */ - - if (!apt->listenertid) - { - HANDLE thread; - HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); - struct apartment_listener_params * params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params)); - - params->apt = apt; - params->event = event; - thread = CreateThread(NULL, 0, apartment_listener_thread, params, 0, &apt->listenertid); - CloseHandle(thread); - /* wait for pipe to be created before returning, otherwise we - * might try to use it and fail */ - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } -} - struct local_server_params { CLSID clsid; IStream *stream; }; +/* FIXME: should call to rpcss instead */ static DWORD WINAPI local_server_thread(LPVOID param) { struct local_server_params * lsp = (struct local_server_params *)param; diff -urN wine-20050211/dlls/ole32/stg_bigblockfile.c wine-20050310/dlls/ole32/stg_bigblockfile.c --- wine-20050211/dlls/ole32/stg_bigblockfile.c 2004-12-22 19:38:32.000000000 +0100 +++ wine-20050310/dlls/ole32/stg_bigblockfile.c 2005-03-07 13:24:42.000000000 +0100 @@ -866,8 +866,11 @@ */ static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) { - if (openFlags & (STGM_WRITE | STGM_READWRITE)) - return PAGE_READWRITE; - else - return PAGE_READONLY; + switch(STGM_ACCESS_MODE(openFlags)) + { + case STGM_WRITE: + case STGM_READWRITE: + return PAGE_READWRITE; + } + return PAGE_READONLY; } diff -urN wine-20050211/dlls/ole32/stg_prop.c wine-20050310/dlls/ole32/stg_prop.c --- wine-20050211/dlls/ole32/stg_prop.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/ole32/stg_prop.c 2005-03-01 11:41:25.000000000 +0100 @@ -0,0 +1,479 @@ +/* + * Compound Storage (32 bit version) + * Storage implementation + * + * This file contains the compound file implementation + * of the storage interface. + * + * Copyright 1999 Francis Beaudet + * Copyright 1999 Sylvain St-Germain + * Copyright 1999 Thuy Nguyen + * Copyright 2005 Mike McCormack + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winuser.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +#include "storage32.h" + +WINE_DEFAULT_DEBUG_CHANNEL(storage); + +#define _IPropertySetStorage_Offset ((int)(&(((StorageImpl*)0)->base.pssVtbl))) +#define _ICOM_THIS_From_IPropertySetStorage(class, name) \ + class* This = (class*)(((char*)name)-_IPropertySetStorage_Offset) + +static IPropertyStorageVtbl IPropertyStorage_Vtbl; + +/*********************************************************************** + * Implementation of IPropertyStorage + */ +typedef struct tagPropertyStorage_impl +{ + IPropertyStorageVtbl *vtbl; + DWORD ref; + IStream *stm; +} PropertyStorage_impl; + +/************************************************************************ + * IPropertyStorage_fnQueryInterface (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnQueryInterface( + IPropertyStorage *iface, + REFIID riid, + void** ppvObject) +{ + PropertyStorage_impl *This = (PropertyStorage_impl *)iface; + + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + *ppvObject = 0; + + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IPropertyStorage, riid)) + { + IPropertyStorage_AddRef(iface); + *ppvObject = (IPropertyStorage*)iface; + return S_OK; + } + + return E_NOINTERFACE; +} + +/************************************************************************ + * IPropertyStorage_fnAddRef (IPropertyStorage) + */ +static ULONG WINAPI IPropertyStorage_fnAddRef( + IPropertyStorage *iface) +{ + PropertyStorage_impl *This = (PropertyStorage_impl *)iface; + return InterlockedIncrement(&This->ref); +} + +/************************************************************************ + * IPropertyStorage_fnRelease (IPropertyStorage) + */ +static ULONG WINAPI IPropertyStorage_fnRelease( + IPropertyStorage *iface) +{ + PropertyStorage_impl *This = (PropertyStorage_impl *)iface; + ULONG ref; + + ref = InterlockedDecrement(&This->ref); + if (ref == 0) + { + TRACE("Destroying %p\n", This); + IStream_Release(This->stm); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +/************************************************************************ + * IPropertyStorage_fnReadMultiple (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnReadMultiple( + IPropertyStorage* iface, + ULONG cpspec, + const PROPSPEC rgpspec[], + PROPVARIANT rgpropvar[]) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnWriteMultiple (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnWriteMultiple( + IPropertyStorage* iface, + ULONG cpspec, + const PROPSPEC rgpspec[], + const PROPVARIANT rgpropvar[], + PROPID propidNameFirst) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnDeleteMultiple (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnDeleteMultiple( + IPropertyStorage* iface, + ULONG cpspec, + const PROPSPEC rgpspec[]) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnReadPropertyNames (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnReadPropertyNames( + IPropertyStorage* iface, + ULONG cpropid, + const PROPID rgpropid[], + LPOLESTR rglpwstrName[]) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnWritePropertyNames (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames( + IPropertyStorage* iface, + ULONG cpropid, + const PROPID rgpropid[], + const LPOLESTR rglpwstrName[]) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnDeletePropertyNames (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnDeletePropertyNames( + IPropertyStorage* iface, + ULONG cpropid, + const PROPID rgpropid[]) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnCommit (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnCommit( + IPropertyStorage* iface, + DWORD grfCommitFlags) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnRevert (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnRevert( + IPropertyStorage* iface) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnEnum (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnEnum( + IPropertyStorage* iface, + IEnumSTATPROPSTG** ppenum) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnSetTimes (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnSetTimes( + IPropertyStorage* iface, + const FILETIME* pctime, + const FILETIME* patime, + const FILETIME* pmtime) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnSetClass (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnSetClass( + IPropertyStorage* iface, + REFCLSID clsid) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/************************************************************************ + * IPropertyStorage_fnStat (IPropertyStorage) + */ +static HRESULT WINAPI IPropertyStorage_fnStat( + IPropertyStorage* iface, + STATPROPSETSTG* statpsstg) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +/*********************************************************************** + * PropertyStorage_Contruct + */ +static HRESULT PropertyStorage_Contruct(IStream *stm, IPropertyStorage** pps) +{ + PropertyStorage_impl *ps; + + ps = HeapAlloc(GetProcessHeap(), 0, sizeof *ps); + if (!ps) + return E_OUTOFMEMORY; + + ps->vtbl = &IPropertyStorage_Vtbl; + ps->ref = 1; + ps->stm = stm; + + *pps = (IPropertyStorage*)ps; + + TRACE("PropertyStorage %p constructed\n", ps); + + return S_OK; +} + + +/*********************************************************************** + * Implementation of IPropertySetStorage + */ + +static LPCWSTR format_id_to_name(REFFMTID rfmtid) +{ + static const WCHAR szSummaryInfo[] = { 5,'S','u','m','m','a','r','y', + 'I','n','f','o','r','m','a','t','i','o','n',0 }; + + if (IsEqualGUID(&FMTID_SummaryInformation, rfmtid)) + return szSummaryInfo; + ERR("Unknown format id %s\n", debugstr_guid(rfmtid)); + return NULL; +} + +/************************************************************************ + * IPropertySetStorage_fnQueryInterface (IUnknown) + * + * This method forwards to the common QueryInterface implementation + */ +static HRESULT WINAPI IPropertySetStorage_fnQueryInterface( + IPropertySetStorage *ppstg, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + return StorageBaseImpl_QueryInterface( (IStorage*)This, riid, ppvObject ); +} + +/************************************************************************ + * IPropertySetStorage_fnAddRef (IUnknown) + * + * This method forwards to the common AddRef implementation + */ +static ULONG WINAPI IPropertySetStorage_fnAddRef( + IPropertySetStorage *ppstg) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + return StorageBaseImpl_AddRef( (IStorage*)This ); +} + +/************************************************************************ + * IPropertySetStorage_fnRelease (IUnknown) + * + * This method forwards to the common Release implementation + */ +static ULONG WINAPI IPropertySetStorage_fnRelease( + IPropertySetStorage *ppstg) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + return StorageBaseImpl_Release( (IStorage*)This ); +} + +/************************************************************************ + * IPropertySetStorage_fnCreate (IPropertySetStorage) + */ +static HRESULT WINAPI IPropertySetStorage_fnCreate( + IPropertySetStorage *ppstg, + REFFMTID rfmtid, + const CLSID* pclsid, + DWORD grfFlags, + DWORD grfMode, + IPropertyStorage** ppprstg) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + LPCWSTR name = NULL; + IStream *stm = NULL; + HRESULT r; + + TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg); + + /* be picky */ + if (grfMode != (STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE)) + return STG_E_INVALIDFLAG; + + if (!rfmtid) + return E_INVALIDARG; + + name = format_id_to_name(rfmtid); + if (!name) + return STG_E_FILENOTFOUND; + + r = IStorage_CreateStream( (IStorage*)This, name, grfMode, 0, 0, &stm ); + if (FAILED(r)) + return r; + + return PropertyStorage_Contruct(stm, ppprstg); +} + +/************************************************************************ + * IPropertySetStorage_fnOpen (IPropertySetStorage) + */ +static HRESULT WINAPI IPropertySetStorage_fnOpen( + IPropertySetStorage *ppstg, + REFFMTID rfmtid, + DWORD grfMode, + IPropertyStorage** ppprstg) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + IStream *stm = NULL; + LPCWSTR name = NULL; + HRESULT r; + + TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg); + + /* be picky */ + if (grfMode != (STGM_READWRITE|STGM_SHARE_EXCLUSIVE) && + grfMode != (STGM_READ|STGM_SHARE_EXCLUSIVE)) + return STG_E_INVALIDFLAG; + + if (!rfmtid) + return E_INVALIDARG; + + name = format_id_to_name(rfmtid); + if (!name) + return STG_E_FILENOTFOUND; + + r = IStorage_OpenStream((IStorage*) This, name, 0, grfMode, 0, &stm ); + if (FAILED(r)) + return r; + + return PropertyStorage_Contruct(stm, ppprstg); +} + +/************************************************************************ + * IPropertySetStorage_fnDelete (IPropertySetStorage) + */ +static HRESULT WINAPI IPropertySetStorage_fnDelete( + IPropertySetStorage *ppstg, + REFFMTID rfmtid) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + IStorage *stg = NULL; + LPCWSTR name = NULL; + + TRACE("%p %s\n", This, debugstr_guid(rfmtid)); + + if (!rfmtid) + return E_INVALIDARG; + + name = format_id_to_name(rfmtid); + if (!name) + return STG_E_FILENOTFOUND; + + stg = (IStorage*) This; + return IStorage_DestroyElement(stg, name); +} + +/************************************************************************ + * IPropertySetStorage_fnEnum (IPropertySetStorage) + */ +static HRESULT WINAPI IPropertySetStorage_fnEnum( + IPropertySetStorage *ppstg, + IEnumSTATPROPSETSTG** ppenum) +{ + _ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg); + FIXME("%p\n", This); + return E_NOTIMPL; +} + + +/*********************************************************************** + * vtables + */ +IPropertySetStorageVtbl IPropertySetStorage_Vtbl = +{ + IPropertySetStorage_fnQueryInterface, + IPropertySetStorage_fnAddRef, + IPropertySetStorage_fnRelease, + IPropertySetStorage_fnCreate, + IPropertySetStorage_fnOpen, + IPropertySetStorage_fnDelete, + IPropertySetStorage_fnEnum +}; + +static IPropertyStorageVtbl IPropertyStorage_Vtbl = +{ + IPropertyStorage_fnQueryInterface, + IPropertyStorage_fnAddRef, + IPropertyStorage_fnRelease, + IPropertyStorage_fnReadMultiple, + IPropertyStorage_fnWriteMultiple, + IPropertyStorage_fnDeleteMultiple, + IPropertyStorage_fnReadPropertyNames, + IPropertyStorage_fnWritePropertyNames, + IPropertyStorage_fnDeletePropertyNames, + IPropertyStorage_fnCommit, + IPropertyStorage_fnRevert, + IPropertyStorage_fnEnum, + IPropertyStorage_fnSetTimes, + IPropertyStorage_fnSetClass, + IPropertyStorage_fnStat, +}; diff -urN wine-20050211/dlls/ole32/stg_stream.c wine-20050310/dlls/ole32/stg_stream.c --- wine-20050211/dlls/ole32/stg_stream.c 2005-01-11 11:44:28.000000000 +0100 +++ wine-20050310/dlls/ole32/stg_stream.c 2005-03-07 13:24:42.000000000 +0100 @@ -443,7 +443,12 @@ /* * Do we have permission to write to this stream? */ - if (!(This->grfMode & (STGM_WRITE | STGM_READWRITE))) { + switch(STGM_ACCESS_MODE(This->grfMode)) + { + case STGM_WRITE: + case STGM_READWRITE: + break; + default: return STG_E_ACCESSDENIED; } diff -urN wine-20050211/dlls/ole32/storage32.c wine-20050310/dlls/ole32/storage32.c --- wine-20050211/dlls/ole32/storage32.c 2005-01-11 16:08:08.000000000 +0100 +++ wine-20050310/dlls/ole32/storage32.c 2005-03-09 12:44:59.000000000 +0100 @@ -8,6 +8,7 @@ * Copyright 1999 Francis Beaudet * Copyright 1999 Sylvain St-Germain * Copyright 1999 Thuy Nguyen + * Copyright 2005 Mike McCormack * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,8 +52,6 @@ #define FILE_BEGIN 0 -#define STGM_SHARE_MODE(stgm) ((stgm)&0xf0) - /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ #define OLESTREAM_ID 0x501 #define OLESTREAM_MAX_STR_LEN 255 @@ -222,7 +221,7 @@ IEnumSTATSTGImpl_Clone }; - +extern IPropertySetStorageVtbl IPropertySetStorage_Vtbl; @@ -266,6 +265,10 @@ { *ppvObject = (IStorage*)This; } + else if (memcmp(&IID_IPropertySetStorage, riid, sizeof(IID_IPropertySetStorage)) == 0) + { + *ppvObject = (IStorage*)&This->pssVtbl; + } /* * Check that we obtained an interface. @@ -294,7 +297,11 @@ IStorage* iface) { StorageBaseImpl *This = (StorageBaseImpl *)iface; - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) AddRef to %ld\n", This, ref); + + return ref; } /************************************************************************ @@ -314,6 +321,8 @@ */ ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) ReleaseRef to %ld\n", This, ref); + /* * If the reference count goes down to 0, perform suicide. */ @@ -381,7 +390,7 @@ /* * As documented. */ - if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || + if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE || (grfMode & STGM_DELETEONRELEASE) || (grfMode & STGM_TRANSACTED) ) { @@ -500,7 +509,7 @@ /* * As documented. */ - if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || + if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE || (grfMode & STGM_DELETEONRELEASE) || (grfMode & STGM_PRIORITY) ) { @@ -882,7 +891,7 @@ if ( FAILED( validateSTGM(grfMode) )) return STG_E_INVALIDFLAG; - if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ) + if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE) return STG_E_INVALIDFLAG; /* @@ -914,7 +923,7 @@ /* * An element with this name already exists */ - if (grfMode & STGM_CREATE) + if (STGM_CREATE_MODE(grfMode) == STGM_CREATE) { IStorage_DestroyElement(iface, pwcsName); } @@ -1089,8 +1098,8 @@ /* * Create a property enumeration and search the properties */ - propertyEnumeration = IEnumSTATSTGImpl_Construct( This->ancestorStorage, - This->rootPropertySetIndex); + propertyEnumeration = IEnumSTATSTGImpl_Construct( This->base.ancestorStorage, + This->base.rootPropertySetIndex); foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration, pwcsName, @@ -1102,7 +1111,7 @@ /* * An element with this name already exists */ - if (grfMode & STGM_CREATE) + if (STGM_CREATE_MODE(grfMode) == STGM_CREATE) IStorage_DestroyElement(iface, pwcsName); else return STG_E_FILEALREADYEXISTS; @@ -1141,13 +1150,13 @@ /* * Obtain a free property in the property chain */ - newPropertyIndex = getFreeProperty(This->ancestorStorage); + newPropertyIndex = getFreeProperty(This->base.ancestorStorage); /* * Save the new property into the new property spot */ StorageImpl_WriteProperty( - This->ancestorStorage, + This->base.ancestorStorage, newPropertyIndex, &newProperty); @@ -1200,7 +1209,7 @@ /* * Start by reading the root property */ - readSuccessful = StorageImpl_ReadProperty(storage->ancestorStorage, + readSuccessful = StorageImpl_ReadProperty(storage->base.ancestorStorage, currentPropertyIndex, ¤tProperty); if (readSuccessful) @@ -1239,7 +1248,7 @@ * obtain the new count of property blocks */ blockCount = BlockChainStream_GetCount( - storage->ancestorStorage->rootBlockChain)+1; + storage->base.ancestorStorage->rootBlockChain)+1; /* * initialize the size used by the property stream @@ -1250,7 +1259,7 @@ /* * add a property block to the property chain */ - BlockChainStream_SetSize(storage->ancestorStorage->rootBlockChain, newSize); + BlockChainStream_SetSize(storage->base.ancestorStorage->rootBlockChain, newSize); /* * memset the empty property in order to initialize the unused newly @@ -1269,7 +1278,7 @@ propertyIndex++) { StorageImpl_WriteProperty( - storage->ancestorStorage, + storage->base.ancestorStorage, propertyIndex, &emptyProperty); } @@ -1322,8 +1331,8 @@ /* * Read the root property */ - StorageImpl_ReadProperty(storage->ancestorStorage, - storage->rootPropertySetIndex, + StorageImpl_ReadProperty(storage->base.ancestorStorage, + storage->base.rootPropertySetIndex, ¤tProperty); if (currentProperty.dirProperty != PROPERTY_NULL) @@ -1343,7 +1352,7 @@ /* * Read */ - StorageImpl_ReadProperty(storage->ancestorStorage, + StorageImpl_ReadProperty(storage->base.ancestorStorage, currentProperty.dirProperty, ¤tProperty); @@ -1359,7 +1368,7 @@ { if (previous != PROPERTY_NULL) { - StorageImpl_ReadProperty(storage->ancestorStorage, + StorageImpl_ReadProperty(storage->base.ancestorStorage, previous, ¤tProperty); current = previous; @@ -1367,7 +1376,7 @@ else { currentProperty.previousProperty = newPropertyIndex; - StorageImpl_WriteProperty(storage->ancestorStorage, + StorageImpl_WriteProperty(storage->base.ancestorStorage, current, ¤tProperty); found = 1; @@ -1377,7 +1386,7 @@ { if (next != PROPERTY_NULL) { - StorageImpl_ReadProperty(storage->ancestorStorage, + StorageImpl_ReadProperty(storage->base.ancestorStorage, next, ¤tProperty); current = next; @@ -1385,7 +1394,7 @@ else { currentProperty.nextProperty = newPropertyIndex; - StorageImpl_WriteProperty(storage->ancestorStorage, + StorageImpl_WriteProperty(storage->base.ancestorStorage, current, ¤tProperty); found = 1; @@ -1410,8 +1419,8 @@ * The root storage is empty, link the new property to it's dir property */ currentProperty.dirProperty = newPropertyIndex; - StorageImpl_WriteProperty(storage->ancestorStorage, - storage->rootPropertySetIndex, + StorageImpl_WriteProperty(storage->base.ancestorStorage, + storage->base.rootPropertySetIndex, ¤tProperty); } } @@ -1657,8 +1666,8 @@ * Create a property enumeration to search the property with the given name */ propertyEnumeration = IEnumSTATSTGImpl_Construct( - This->ancestorStorage, - This->rootPropertySetIndex); + This->base.ancestorStorage, + This->base.rootPropertySetIndex); foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty( propertyEnumeration, @@ -1682,8 +1691,8 @@ * First, read This's StgProperty.. */ res = StorageImpl_ReadProperty( - This->ancestorStorage, - This->rootPropertySetIndex, + This->base.ancestorStorage, + This->base.rootPropertySetIndex, &parentProperty); assert(res); @@ -1698,7 +1707,7 @@ * Set data as it would have been done in the else part... */ typeOfRelation = PROPERTY_RELATION_DIR; - parentPropertyId = This->rootPropertySetIndex; + parentPropertyId = This->base.rootPropertySetIndex; } else { @@ -1709,8 +1718,8 @@ IEnumSTATSTGImpl* propertyEnumeration2; propertyEnumeration2 = IEnumSTATSTGImpl_Construct( - This->ancestorStorage, - This->rootPropertySetIndex); + This->base.ancestorStorage, + This->base.rootPropertySetIndex); typeOfRelation = IEnumSTATSTGImpl_FindParentProperty( propertyEnumeration2, @@ -1847,7 +1856,7 @@ */ propertyToDelete.sizeOfNameString = 0; - StorageImpl_WriteProperty(parentStorage->ancestorStorage, + StorageImpl_WriteProperty(parentStorage->base.ancestorStorage, indexOfPropertyToDelete, &propertyToDelete); @@ -1914,7 +1923,7 @@ * but since we are here to zap it, I don't do it... */ StorageImpl_WriteProperty( - parentStorage->ancestorStorage, + parentStorage->base.ancestorStorage, indexOfPropertyToDelete, &propertyToDelete); @@ -1942,7 +1951,7 @@ * Read the storage property */ res = StorageImpl_ReadProperty( - storage->ancestorStorage, + storage->base.ancestorStorage, storePropertyIndex, &storeProperty); @@ -1998,7 +2007,7 @@ } hr = StorageImpl_WriteProperty( - storage->ancestorStorage, + storage->base.ancestorStorage, storePropertyIndex, &storeProperty); @@ -2140,7 +2149,7 @@ * Write back the parent property */ res = StorageImpl_WriteProperty( - This->ancestorStorage, + This->base.ancestorStorage, parentPropertyId, &parentProperty); if(! res) @@ -2213,14 +2222,15 @@ /* * Initialize the virtual function table. */ - This->lpVtbl = &Storage32Impl_Vtbl; - This->v_destructor = &StorageImpl_Destroy; + This->base.lpVtbl = &Storage32Impl_Vtbl; + This->base.pssVtbl = &IPropertySetStorage_Vtbl; + This->base.v_destructor = &StorageImpl_Destroy; /* * This is the top-level storage so initialize the ancestor pointer * to this. */ - This->ancestorStorage = This; + This->base.ancestorStorage = This; /* * Initialize the physical support of the storage. @@ -2372,13 +2382,13 @@ if ( (currentProperty.sizeOfNameString != 0 ) && (currentProperty.propertyType == PROPTYPE_ROOT) ) { - This->rootPropertySetIndex = currentPropertyIndex; + This->base.rootPropertySetIndex = currentPropertyIndex; } } currentPropertyIndex++; - } while (readSuccessful && (This->rootPropertySetIndex == PROPERTY_NULL) ); + } while (readSuccessful && (This->base.rootPropertySetIndex == PROPERTY_NULL) ); if (!readSuccessful) { @@ -2390,15 +2400,15 @@ * Create the block chain abstraction for the small block root chain. */ if(!(This->smallBlockRootChain = - BlockChainStream_Construct(This, NULL, This->rootPropertySetIndex))) + BlockChainStream_Construct(This, NULL, This->base.rootPropertySetIndex))) return STG_E_READFAULT; return hr; } -void StorageImpl_Destroy( - StorageImpl* This) +void StorageImpl_Destroy(StorageBaseImpl* iface) { + StorageImpl *This = (StorageImpl*) iface; TRACE("(%p)\n", This); HeapFree(GetProcessHeap(), 0, This->pwcsName); @@ -3138,7 +3148,7 @@ if (readSuccessful) { /* replace the name of root entry (often "Root Entry") by the file name */ - WCHAR *propName = (index == This->rootPropertySetIndex) ? + WCHAR *propName = (index == This->base.rootPropertySetIndex) ? This->filename : (WCHAR *)currentProperty+OFFSET_PS_NAME; memset(buffer->name, 0, sizeof(buffer->name)); @@ -3484,19 +3494,19 @@ /* * Initialize the virtual function table. */ - newStorage->lpVtbl = &Storage32InternalImpl_Vtbl; - newStorage->v_destructor = &StorageInternalImpl_Destroy; + newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl; + newStorage->base.v_destructor = &StorageInternalImpl_Destroy; /* * Keep the ancestor storage pointer and nail a reference to it. */ - newStorage->ancestorStorage = ancestorStorage; - StorageBaseImpl_AddRef((IStorage*)(newStorage->ancestorStorage)); + newStorage->base.ancestorStorage = ancestorStorage; + StorageBaseImpl_AddRef((IStorage*)(newStorage->base.ancestorStorage)); /* * Keep the index of the root property set for this storage, */ - newStorage->rootPropertySetIndex = rootPropertyIndex; + newStorage->base.rootPropertySetIndex = rootPropertyIndex; return newStorage; } @@ -3504,10 +3514,11 @@ return 0; } -void StorageInternalImpl_Destroy( - StorageInternalImpl* This) +void StorageInternalImpl_Destroy( StorageBaseImpl *iface) { - StorageBaseImpl_Release((IStorage*)This->ancestorStorage); + StorageInternalImpl* This = (StorageInternalImpl*) iface; + + StorageBaseImpl_Release((IStorage*)This->base.ancestorStorage); HeapFree(GetProcessHeap(), 0, This); } @@ -4938,7 +4949,7 @@ StorageImpl_ReadProperty( This->parentStorage, - This->parentStorage->rootPropertySetIndex, + This->parentStorage->base.rootPropertySetIndex, &rootProp); rootProp.startingBlock = sbStartIndex; @@ -4947,7 +4958,7 @@ StorageImpl_WriteProperty( This->parentStorage, - This->parentStorage->rootPropertySetIndex, + This->parentStorage->base.rootPropertySetIndex, &rootProp); } } @@ -4966,7 +4977,7 @@ StorageImpl_ReadProperty( This->parentStorage, - This->parentStorage->rootPropertySetIndex, + This->parentStorage->base.rootPropertySetIndex, &rootProp); if (rootProp.size.u.LowPart < @@ -4980,7 +4991,7 @@ StorageImpl_WriteProperty( This->parentStorage, - This->parentStorage->rootPropertySetIndex, + This->parentStorage->base.rootPropertySetIndex, &rootProp); } } @@ -5415,7 +5426,7 @@ { StorageImpl* newStorage = 0; HANDLE hFile = INVALID_HANDLE_VALUE; - HRESULT hr = S_OK; + HRESULT hr = STG_E_INVALIDFLAG; DWORD shareMode; DWORD accessMode; DWORD creationMode; @@ -5438,16 +5449,33 @@ * Validate the STGM flags */ if ( FAILED( validateSTGM(grfMode) )) - return STG_E_INVALIDFLAG; + goto end; /* StgCreateDocFile always opens for write */ - if (!(grfMode & (STGM_WRITE|STGM_READWRITE))) - return STG_E_INVALIDFLAG; + switch(STGM_ACCESS_MODE(grfMode)) + { + case STGM_WRITE: + case STGM_READWRITE: + break; + default: + goto end; + } + + /* can't share write */ + switch(STGM_SHARE_MODE(grfMode)) + { + case STGM_SHARE_EXCLUSIVE: + case STGM_SHARE_DENY_WRITE: + break; + default: + goto end; + } + + /* shared reading requires transacted mode */ + if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE && + !(grfMode&STGM_TRANSACTED) ) + goto end; - /* always opens non-shared */ - if (!(grfMode & STGM_SHARE_EXCLUSIVE)) - return STG_E_INVALIDFLAG; - /* * Generate a unique name. */ @@ -5456,10 +5484,8 @@ WCHAR tempPath[MAX_PATH]; static const WCHAR prefix[] = { 'S', 'T', 'O', 0 }; - if (!(grfMode & STGM_SHARE_EXCLUSIVE)) - return STG_E_INVALIDFLAG; - if (!(grfMode & (STGM_WRITE|STGM_READWRITE))) - return STG_E_INVALIDFLAG; + if (STGM_SHARE_MODE(grfMode) == STGM_SHARE_EXCLUSIVE) + goto end; memset(tempPath, 0, sizeof(tempPath)); memset(tempFileName, 0, sizeof(tempFileName)); @@ -5470,7 +5496,10 @@ if (GetTempFileNameW(tempPath, prefix, 0, tempFileName) != 0) pwcsName = tempFileName; else - return STG_E_INSUFFICIENTMEMORY; + { + hr = STG_E_INSUFFICIENTMEMORY; + goto end; + } creationMode = TRUNCATE_EXISTING; } @@ -5501,16 +5530,18 @@ hFile = CreateFileW(pwcsName, accessMode, shareMode, - NULL, + NULL, creationMode, fileAttributes, - 0); + 0); if (hFile == INVALID_HANDLE_VALUE) { if(GetLastError() == ERROR_FILE_EXISTS) - return STG_E_FILEALREADYEXISTS; - return E_FAIL; + hr = STG_E_FILEALREADYEXISTS; + else + hr = E_FAIL; + goto end; } /* @@ -5519,7 +5550,10 @@ newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); if (newStorage == 0) - return STG_E_INSUFFICIENTMEMORY; + { + hr = STG_E_INSUFFICIENTMEMORY; + goto end; + } hr = StorageImpl_Construct( newStorage, @@ -5533,7 +5567,7 @@ if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, newStorage); - return hr; + goto end; } /* @@ -5543,6 +5577,8 @@ (IStorage*)newStorage, (REFIID)&IID_IStorage, (void**)ppstgOpen); +end: + TRACE("<-- %p r = %08lx\n", *ppstgOpen, hr); return hr; } @@ -5558,6 +5594,23 @@ } /****************************************************************************** + * StgCreatePropSetStg [OLE32.@] + */ +HRESULT WINAPI StgCreatePropSetStg(IStorage *pstg, DWORD reserved, + IPropertySetStorage **ppPropSetStg) +{ + HRESULT hr; + + TRACE("(%p, 0x%lx, %p): stub\n", pstg, reserved, ppPropSetStg); + if (reserved) + hr = STG_E_INVALIDPARAMETER; + else + hr = StorageBaseImpl_QueryInterface(pstg, &IID_IPropertySetStorage, + (void**)ppPropSetStg); + return hr; +} + +/****************************************************************************** * StgOpenStorage [OLE32.@] */ HRESULT WINAPI StgOpenStorage( @@ -5850,11 +5903,23 @@ * * */ -HRESULT WINAPI StgSetTimes(OLECHAR const *str, FILETIME const *a, - FILETIME const *b, FILETIME const *c ) +HRESULT WINAPI StgSetTimes(OLECHAR const *str, FILETIME const *pctime, + FILETIME const *patime, FILETIME const *pmtime) { - FIXME("(%s, %p, %p, %p),stub!\n", debugstr_w(str), a, b, c); - return S_OK; + IStorage *stg = NULL; + HRESULT r; + + TRACE("%s %p %p %p\n", debugstr_w(str), pctime, patime, pmtime); + + r = StgOpenStorage(str, NULL, STGM_READWRITE | STGM_SHARE_DENY_WRITE, + 0, 0, &stg); + if( SUCCEEDED(r) ) + { + r = IStorage_SetElementTimes(stg, NULL, pctime, patime, pmtime); + IStorage_Release(stg); + } + + return r; } /****************************************************************************** @@ -5985,6 +6050,9 @@ /**************************************************************************** * This method validate a STGM parameter that can contain the values below * + * The stgm modes in 0x0000ffff are not bit masks, but distinct 4 bit values. + * The stgm values contained in 0xffff0000 are bitmasks. + * * STGM_DIRECT 0x00000000 * STGM_TRANSACTED 0x00010000 * STGM_SIMPLE 0x08000000 @@ -6010,79 +6078,74 @@ */ static HRESULT validateSTGM(DWORD stgm) { - BOOL bSTGM_TRANSACTED = ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED); - BOOL bSTGM_SIMPLE = ((stgm & STGM_SIMPLE) == STGM_SIMPLE); - BOOL bSTGM_DIRECT = ! (bSTGM_TRANSACTED || bSTGM_SIMPLE); - - BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE); - BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE); - BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE); - - BOOL bSTGM_SHARE_DENY_NONE = - ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE); + DWORD access = STGM_ACCESS_MODE(stgm); + DWORD share = STGM_SHARE_MODE(stgm); + DWORD create = STGM_CREATE_MODE(stgm); - BOOL bSTGM_SHARE_DENY_READ = - ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ); - - BOOL bSTGM_SHARE_DENY_WRITE = - ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE); + if (stgm&~STGM_KNOWN_FLAGS) + { + ERR("unknown flags %08lx\n", stgm); + return E_FAIL; + } - BOOL bSTGM_SHARE_EXCLUSIVE = - ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE); + switch (access) + { + case STGM_READ: + case STGM_WRITE: + case STGM_READWRITE: + break; + default: + return E_FAIL; + } - BOOL bSTGM_CREATE = ((stgm & STGM_CREATE) == STGM_CREATE); - BOOL bSTGM_CONVERT = ((stgm & STGM_CONVERT) == STGM_CONVERT); + switch (share) + { + case STGM_SHARE_DENY_NONE: + case STGM_SHARE_DENY_READ: + case STGM_SHARE_DENY_WRITE: + case STGM_SHARE_EXCLUSIVE: + break; + default: + return E_FAIL; + } - BOOL bSTGM_NOSCRATCH = ((stgm & STGM_NOSCRATCH) == STGM_NOSCRATCH); - BOOL bSTGM_NOSNAPSHOT = ((stgm & STGM_NOSNAPSHOT) == STGM_NOSNAPSHOT); + switch (create) + { + case STGM_CREATE: + case STGM_FAILIFTHERE: + break; + default: + return E_FAIL; + } /* * STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE */ - if ( ! bSTGM_DIRECT ) - if( bSTGM_TRANSACTED && bSTGM_SIMPLE ) - return E_FAIL; - - /* - * STGM_WRITE | STGM_READWRITE | STGM_READ - */ - if ( ! bSTGM_READ ) - if( bSTGM_WRITE && bSTGM_READWRITE ) - return E_FAIL; - - /* - * STGM_SHARE_DENY_NONE | others - * (I assume here that DENY_READ implies DENY_WRITE) - */ - if ( bSTGM_SHARE_DENY_NONE ) - if ( bSTGM_SHARE_DENY_READ || - bSTGM_SHARE_DENY_WRITE || - bSTGM_SHARE_EXCLUSIVE) + if ( (stgm & STGM_TRANSACTED) && (stgm & STGM_SIMPLE) ) return E_FAIL; /* * STGM_CREATE | STGM_CONVERT * if both are false, STGM_FAILIFTHERE is set to TRUE */ - if ( bSTGM_CREATE && bSTGM_CONVERT ) + if ( create == STGM_CREATE && (stgm & STGM_CONVERT) ) return E_FAIL; /* * STGM_NOSCRATCH requires STGM_TRANSACTED */ - if ( bSTGM_NOSCRATCH && ! bSTGM_TRANSACTED ) + if ( (stgm & STGM_NOSCRATCH) && (stgm & STGM_TRANSACTED) ) return E_FAIL; /* * STGM_NOSNAPSHOT requires STGM_TRANSACTED and * not STGM_SHARE_EXCLUSIVE or STGM_SHARE_DENY_WRITE` */ - if (bSTGM_NOSNAPSHOT) - { - if ( ! ( bSTGM_TRANSACTED && - !(bSTGM_SHARE_EXCLUSIVE || bSTGM_SHARE_DENY_WRITE)) ) + if ( (stgm & STGM_NOSNAPSHOT) && + (!(stgm & STGM_TRANSACTED) || + share == STGM_SHARE_EXCLUSIVE || + share == STGM_SHARE_DENY_WRITE) ) return E_FAIL; - } return S_OK; } @@ -6095,29 +6158,20 @@ */ static DWORD GetShareModeFromSTGM(DWORD stgm) { - DWORD dwShareMode = 0; - BOOL bSTGM_SHARE_DENY_NONE = - ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE); - - BOOL bSTGM_SHARE_DENY_READ = - ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ); - - BOOL bSTGM_SHARE_DENY_WRITE = - ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE); - - BOOL bSTGM_SHARE_EXCLUSIVE = - ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE); - - if ((bSTGM_SHARE_EXCLUSIVE) || (bSTGM_SHARE_DENY_READ)) - dwShareMode = 0; - - if (bSTGM_SHARE_DENY_NONE) - dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - if (bSTGM_SHARE_DENY_WRITE) - dwShareMode = FILE_SHARE_READ; - - return dwShareMode; + switch (STGM_SHARE_MODE(stgm)) + { + case STGM_SHARE_DENY_NONE: + return FILE_SHARE_READ | FILE_SHARE_WRITE; + case STGM_SHARE_DENY_READ: + return FILE_SHARE_WRITE; + case STGM_SHARE_DENY_WRITE: + return FILE_SHARE_READ; + case STGM_SHARE_EXCLUSIVE: + return 0; + } + ERR("Invalid share mode!\n"); + assert(0); + return 0; } /**************************************************************************** @@ -6128,21 +6182,17 @@ */ static DWORD GetAccessModeFromSTGM(DWORD stgm) { - DWORD dwDesiredAccess = GENERIC_READ; - BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE); - BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE); - BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE); - - if (bSTGM_READ) - dwDesiredAccess = GENERIC_READ; - - if (bSTGM_WRITE) - dwDesiredAccess |= GENERIC_WRITE; - - if (bSTGM_READWRITE) - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - - return dwDesiredAccess; + switch (STGM_ACCESS_MODE(stgm)) + { + case STGM_READ: + return GENERIC_READ; + case STGM_WRITE: + case STGM_READWRITE: + return GENERIC_READ | GENERIC_WRITE; + } + ERR("Invalid access mode!\n"); + assert(0); + return 0; } /**************************************************************************** @@ -6153,16 +6203,19 @@ */ static DWORD GetCreationModeFromSTGM(DWORD stgm) { - if ( stgm & STGM_CREATE) + switch(STGM_CREATE_MODE(stgm)) + { + case STGM_CREATE: return CREATE_ALWAYS; - if (stgm & STGM_CONVERT) { + case STGM_CONVERT: FIXME("STGM_CONVERT not implemented!\n"); return CREATE_NEW; + case STGM_FAILIFTHERE: + return CREATE_NEW; } - /* All other cases */ - if (stgm & ~ (STGM_CREATE|STGM_CONVERT)) - FIXME("unhandled storage mode : 0x%08lx\n",stgm & ~ (STGM_CREATE|STGM_CONVERT)); - return CREATE_NEW; + ERR("Invalid create mode!\n"); + assert(0); + return 0; } @@ -6831,7 +6884,7 @@ STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm ); if( FAILED ( r ) ) { - ERR("Failed to open stream\n"); + WARN("Failed to open stream r = %08lx\n", r); return r; } diff -urN wine-20050211/dlls/ole32/storage32.h wine-20050310/dlls/ole32/storage32.h --- wine-20050211/dlls/ole32/storage32.h 2004-08-12 21:52:50.000000000 +0200 +++ wine-20050310/dlls/ole32/storage32.h 2005-03-07 13:24:42.000000000 +0100 @@ -100,6 +100,14 @@ #define LIMIT_TO_USE_SMALL_BLOCK 0x1000 #define NUM_BLOCKS_PER_DEPOT_BLOCK 128 +#define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f) +#define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0) +#define STGM_CREATE_MODE(stgm) ((stgm)&0x0f000) + +#define STGM_KNOWN_FLAGS (0xf0ff | \ + STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY | STGM_NOSCRATCH | \ + STGM_NOSNAPSHOT | STGM_DIRECT_SWMR | STGM_DELETEONRELEASE | STGM_SIMPLE) + /* * These are signatures to detect the type of Document file. */ @@ -207,6 +215,8 @@ IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct * since we want to cast this in a Storage32 pointer */ + IPropertySetStorageVtbl *pssVtbl; /* interface for adding a properties stream */ + /* * Reference count of this object */ @@ -298,17 +308,7 @@ */ struct StorageImpl { - IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct - * since we want to cast this in a Storage32 pointer */ - - /* - * Declare the member of the Storage32BaseImpl class to allow - * casting as a Storage32BaseImpl - */ - ULONG ref; - struct StorageImpl* ancestorStorage; - ULONG rootPropertySetIndex; - void (*v_destructor)(struct StorageImpl*); + struct StorageBaseImpl base; /* * The following data members are specific to the Storage32Impl @@ -405,7 +405,7 @@ DWORD grfStatFlag); /* [in] */ void StorageImpl_Destroy( - StorageImpl* This); + StorageBaseImpl* This); HRESULT StorageImpl_Construct( StorageImpl* This, @@ -498,17 +498,7 @@ */ struct StorageInternalImpl { - IStorageVtbl *lpVtbl; /* Needs to be the first item in the struct - * since we want to cast this in a Storage32 pointer */ - - /* - * Declare the member of the Storage32BaseImpl class to allow - * casting as a Storage32BaseImpl - */ - ULONG ref; - struct StorageImpl* ancestorStorage; - ULONG rootPropertySetIndex; - void (*v_destructor)(struct StorageInternalImpl*); + struct StorageBaseImpl base; /* * There is no specific data for this class. @@ -523,7 +513,7 @@ ULONG rootTropertyIndex); void StorageInternalImpl_Destroy( - StorageInternalImpl* This); + StorageBaseImpl* This); HRESULT WINAPI StorageInternalImpl_Commit( IStorage* iface, diff -urN wine-20050211/dlls/ole32/stubmanager.c wine-20050310/dlls/ole32/stubmanager.c --- wine-20050211/dlls/ole32/stubmanager.c 2005-02-08 17:51:22.000000000 +0100 +++ wine-20050310/dlls/ole32/stubmanager.c 2005-02-18 21:03:23.000000000 +0100 @@ -29,6 +29,7 @@ #include #include +#include #include "windef.h" #include "winbase.h" @@ -48,7 +49,7 @@ /* creates a new stub manager and adds it into the apartment. caller must * release stub manager when it is no longer required. the apartment and * external refs together take one implicit ref */ -struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) +struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object, MSHLFLAGS mshlflags) { struct stub_manager *sm; @@ -74,6 +75,13 @@ * the marshalled ifptr. */ sm->extrefs = 0; + + if (mshlflags & MSHLFLAGS_TABLESTRONG) + sm->state = STUBSTATE_TABLE_STRONG; + else if (mshlflags & MSHLFLAGS_TABLEWEAK) + sm->state = STUBSTATE_TABLE_WEAK_UNMARSHALED; + else + sm->state = STUBSTATE_NORMAL_MARSHALED; EnterCriticalSection(&apt->cs); sm->oid = apt->oidc++; @@ -228,8 +236,16 @@ /* add some external references (ie from a client that unmarshaled an ifptr) */ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs) { - ULONG rc = InterlockedExchangeAdd(&m->extrefs, refs) + refs; + ULONG rc; + + EnterCriticalSection(&m->lock); + + /* make sure we don't overflow extrefs */ + refs = min(refs, (ULONG_MAX-1 - m->extrefs)); + rc = (m->extrefs += refs); + LeaveCriticalSection(&m->lock); + TRACE("added %lu refs to %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc); return rc; @@ -238,7 +254,15 @@ /* remove some external references */ ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs) { - ULONG rc = InterlockedExchangeAdd(&m->extrefs, -refs) - refs; + ULONG rc; + + EnterCriticalSection(&m->lock); + + /* make sure we don't underflow extrefs */ + refs = min(refs, m->extrefs); + rc = (m->extrefs -= refs); + + LeaveCriticalSection(&m->lock); TRACE("removed %lu refs from %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc); @@ -321,24 +345,27 @@ return S_OK; } -IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid) +/* gets the apartment and IRpcStubBuffer from an object. the caller must + * release the references to both objects */ +IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt) { IRpcStubBuffer *ret = NULL; - APARTMENT *apt; struct stub_manager *stubmgr; struct ifstub *ifstub; HRESULT hr; - hr = ipid_to_stub_manager(ipid, &apt, &stubmgr); + *stub_apt = NULL; + + hr = ipid_to_stub_manager(ipid, stub_apt, &stubmgr); if (hr != S_OK) return NULL; ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid); if (ifstub) ret = ifstub->stubbuffer; - stub_manager_int_release(stubmgr); + if (ret) IRpcStubBuffer_AddRef(ret); - COM_ApartmentRelease(apt); + stub_manager_int_release(stubmgr); return ret; } @@ -367,12 +394,12 @@ } /* registers a new interface stub COM object with the stub manager and returns registration record */ -struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal) +struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid) { struct ifstub *stub; - TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s, tablemarshal=%s\n", - wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid), tablemarshal ? "TRUE" : "FALSE"); + TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s\n", + wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid)); stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub)); if (!stub) return NULL; @@ -383,11 +410,6 @@ /* no need to ref this, same object as sb */ stub->iface = iptr; - if (tablemarshal) - stub->state = IFSTUB_STATE_TABLE_MARSHALED; - else - stub->state = IFSTUB_STATE_NORMAL_MARSHALED; - stub->iid = *iid; /* FIXME: hack for IRemUnknown because we don't notify SCM of our IPID @@ -415,8 +437,10 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub) { TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid)); - + list_remove(&ifstub->entry); + + RPC_UnregisterInterface(&ifstub->iid); IUnknown_Release(ifstub->stubbuffer); IUnknown_Release(ifstub->iface); @@ -425,33 +449,30 @@ } /* returns TRUE if it is possible to unmarshal, FALSE otherwise. */ -BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) +BOOL stub_manager_notify_unmarshal(struct stub_manager *m) { - struct ifstub *ifstub; BOOL ret; - ifstub = stub_manager_ipid_to_ifstub(m, ipid); - if (!ifstub) - { - WARN("Can't find ifstub for OID %s, IPID %s\n", - wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid)); - return FALSE; - } - EnterCriticalSection(&m->lock); - switch (ifstub->state) + switch (m->state) { - case IFSTUB_STATE_TABLE_MARSHALED: + case STUBSTATE_TABLE_STRONG: + case STUBSTATE_TABLE_WEAK_MARSHALED: + /* no transition */ + ret = TRUE; + break; + case STUBSTATE_TABLE_WEAK_UNMARSHALED: + m->state = STUBSTATE_TABLE_WEAK_MARSHALED; ret = TRUE; break; - case IFSTUB_STATE_NORMAL_MARSHALED: - ifstub->state = IFSTUB_STATE_NORMAL_UNMARSHALED; + case STUBSTATE_NORMAL_MARSHALED: + m->state = STUBSTATE_NORMAL_UNMARSHALED; ret = TRUE; break; default: - WARN("object OID %s, IPID %s already unmarshaled\n", - wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid)); + WARN("object OID %s already unmarshaled\n", + wine_dbgstr_longlong(m->oid)); ret = FALSE; break; } @@ -461,22 +482,39 @@ return ret; } -/* is an ifstub table marshaled? */ -BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) +void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs) { - struct ifstub *ifstub; - BOOL ret; + EnterCriticalSection(&m->lock); - ifstub = stub_manager_ipid_to_ifstub(m, ipid); - if (!ifstub) + switch (m->state) { - WARN("Can't find ifstub for OID %s, IPID %s\n", - wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid)); - return FALSE; + case STUBSTATE_NORMAL_MARSHALED: + case STUBSTATE_NORMAL_UNMARSHALED: /* FIXME: check this */ + /* nothing to change */ + break; + case STUBSTATE_TABLE_WEAK_UNMARSHALED: + case STUBSTATE_TABLE_STRONG: + refs = 1; + break; + case STUBSTATE_TABLE_WEAK_MARSHALED: + refs = 0; /* like native */ + break; } + stub_manager_ext_release(m, refs); + + LeaveCriticalSection(&m->lock); +} + +/* is an ifstub table marshaled? */ +BOOL stub_manager_is_table_marshaled(struct stub_manager *m) +{ + BOOL ret; + EnterCriticalSection(&m->lock); - ret = (ifstub->state == IFSTUB_STATE_TABLE_MARSHALED); + ret = ((m->state == STUBSTATE_TABLE_STRONG) || + (m->state == STUBSTATE_TABLE_WEAK_MARSHALED) || + (m->state == STUBSTATE_TABLE_WEAK_UNMARSHALED)); LeaveCriticalSection(&m->lock); return ret; @@ -688,7 +726,7 @@ { STDOBJREF stdobjref; /* dummy - not used */ /* register it with the stub manager */ - hr = register_ifstub(COM_CurrentApt(), &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL); + hr = register_ifstub(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL); /* release our reference to the object as the stub manager will manage the life cycle for us */ IRemUnknown_Release(pRemUnknown); if (hr == S_OK) diff -urN wine-20050211/dlls/ole32/tests/marshal.c wine-20050310/dlls/ole32/tests/marshal.c --- wine-20050211/dlls/ole32/tests/marshal.c 2005-02-08 17:51:22.000000000 +0100 +++ wine-20050310/dlls/ole32/tests/marshal.c 2005-03-04 13:30:47.000000000 +0100 @@ -497,7 +497,7 @@ HANDLE thread; CoUninitialize(); - CoInitializeEx(NULL, COINIT_MULTITHREADED); + pCoInitializeEx(NULL, COINIT_MULTITHREADED); cLocks = 0; @@ -506,7 +506,7 @@ tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); - + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); ok_ole_success(hr, CoUnmarshalInterface); @@ -524,7 +524,7 @@ end_host_object(tid, thread); - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); } struct ncu_params @@ -540,7 +540,7 @@ struct ncu_params *ncu_params = (struct ncu_params *)p; HRESULT hr; - CoInitializeEx(NULL, COINIT_MULTITHREADED); + pCoInitializeEx(NULL, COINIT_MULTITHREADED); hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); ok_ole_success(hr, CoMarshalInterface); @@ -669,14 +669,14 @@ IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); release_host_object(tid); - todo_wine { ok_more_than_one_lock(); } + ok_more_than_one_lock(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); - todo_wine { ok_ole_success(hr, CoUnmarshalInterface); } + ok_ole_success(hr, CoUnmarshalInterface); IStream_Release(pStream); - todo_wine { ok_more_than_one_lock(); } + ok_more_than_one_lock(); IUnknown_Release(pProxy1); if (pProxy2) @@ -712,20 +712,19 @@ IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); release_host_object(tid); - todo_wine - { - ok_no_locks(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); + todo_wine + { ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n", hr); + } IStream_Release(pStream); ok_no_locks(); - } end_host_object(tid, thread); } @@ -912,7 +911,7 @@ HRESULT hr; IUnknown * proxy = NULL; - CoInitializeEx(NULL, COINIT_MULTITHREADED); + pCoInitializeEx(NULL, COINIT_MULTITHREADED); hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); if (proxy) IUnknown_Release(proxy); @@ -1204,6 +1203,97 @@ ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs); } +static HWND hwnd_app; + +static HRESULT WINAPI TestRE_IClassFactory_CreateInstance( + LPCLASSFACTORY iface, + LPUNKNOWN pUnkOuter, + REFIID riid, + LPVOID *ppvObj) +{ + DWORD res; + BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res); + ok(ret, "Timed out sending a message to originating window during RPC call\n"); + return S_FALSE; +} + +static IClassFactoryVtbl TestREClassFactory_Vtbl = +{ + Test_IClassFactory_QueryInterface, + Test_IClassFactory_AddRef, + Test_IClassFactory_Release, + TestRE_IClassFactory_CreateInstance, + Test_IClassFactory_LockServer +}; + +IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl }; + +static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) + { + case WM_USER: + { + HRESULT hr; + IStream *pStream = NULL; + IClassFactory *proxy = NULL; + IUnknown *object; + DWORD tid; + HANDLE thread; + + cLocks = 0; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + ok_ole_success(hr, CreateStreamOnHGlobal); + tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); + + ok_more_than_one_lock(); + + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); + ok_ole_success(hr, CoReleaseMarshalData); + IStream_Release(pStream); + + ok_more_than_one_lock(); + + hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); + + IClassFactory_Release(proxy); + + ok_no_locks(); + + end_host_object(tid, thread); + + PostMessage(hwnd, WM_QUIT, 0, 0); + + return 0; + } + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +static void test_message_reentrancy() +{ + WNDCLASS wndclass; + MSG msg; + + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.lpfnWndProc = window_proc; + wndclass.lpszClassName = "WineCOMTest"; + RegisterClass(&wndclass); + + hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); + ok(hwnd_app != NULL, "Window creation failed\n"); + + PostMessage(hwnd_app, WM_USER, 0, 0); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */ #if 0 @@ -1223,6 +1313,97 @@ SetEvent(heventShutdown); } +static HWND hwnd_app; + +static HRESULT WINAPI TestRE_IClassFactory_CreateInstance( + LPCLASSFACTORY iface, + LPUNKNOWN pUnkOuter, + REFIID riid, + LPVOID *ppvObj) +{ + DWORD res; + BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 500, &res); + todo_wine { ok(ret, "Timed out sending a message to originating window during RPC call\n"); } + return S_FALSE; +} + +static IClassFactoryVtbl TestREClassFactory_Vtbl = +{ + Test_IClassFactory_QueryInterface, + Test_IClassFactory_AddRef, + Test_IClassFactory_Release, + TestRE_IClassFactory_CreateInstance, + Test_IClassFactory_LockServer +}; + +IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl }; + +static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) + { + case WM_USER: + { + HRESULT hr; + IStream *pStream = NULL; + IClassFactory *proxy = NULL; + IUnknown *object; + DWORD tid; + HANDLE thread; + + cLocks = 0; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + ok_ole_success(hr, CreateStreamOnHGlobal); + tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); + + ok_more_than_one_lock(); + + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); + ok_ole_success(hr, CoReleaseMarshalData); + IStream_Release(pStream); + + ok_more_than_one_lock(); + + hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); + + IClassFactory_Release(proxy); + + ok_no_locks(); + + end_host_object(tid, thread); + + PostMessage(hwnd, WM_QUIT, 0, 0); + + return 0; + } + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +static void test_message_reentrancy() +{ + WNDCLASS wndclass; + MSG msg; + + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.lpfnWndProc = window_proc; + wndclass.lpszClassName = "WineCOMTest"; + RegisterClass(&wndclass); + + hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); + ok(hwnd_app != NULL, "Window creation failed\n"); + + PostMessage(hwnd_app, WM_USER, 0, 0); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface( LPCLASSFACTORY iface, @@ -1395,7 +1576,7 @@ test_proxy_interfaces(); test_stubbuffer(&IID_IClassFactory); /* FIXME: test GIT */ - /* FIXME: test COM re-entrancy */ + test_message_reentrancy(); /* test_out_of_process_com(); */ CoUninitialize(); diff -urN wine-20050211/dlls/ole32/tests/storage32.c wine-20050310/dlls/ole32/tests/storage32.c --- wine-20050211/dlls/ole32/tests/storage32.c 2005-01-11 16:08:08.000000000 +0100 +++ wine-20050310/dlls/ole32/tests/storage32.c 2005-03-09 12:44:59.000000000 +0100 @@ -90,16 +90,32 @@ ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg); ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); - r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | - STGM_READWRITE, 0, NULL); + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL); ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n"); - r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | - STGM_READWRITE, 1, &stg); + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg); ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg); ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg); ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + + /* StgCreateDocfile seems to be very particular about the flags it accepts */ + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); ok(stg == NULL, "stg was set\n"); /* check what happens if the file already exists */ @@ -107,8 +123,7 @@ ok(r==S_OK, "StgCreateDocfile failed\n"); r = IStorage_Release(stg); ok(r == 0, "storage not released\n"); - r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE | - STGM_TRANSACTED, 0, &stg); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); r = StgCreateDocfile( filename, STGM_READ, 0, &stg); ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); @@ -130,24 +145,68 @@ ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n"); ok(DeleteFileW(filename), "failed to delete file\n"); - r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE | - STGM_TRANSACTED, 0, &stg); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); ok(r==S_OK, "StgCreateDocfile failed\n"); r = IStorage_Release(stg); ok(r == 0, "storage not released\n"); - r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE | - STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg); + r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg); ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg); ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); - r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | - STGM_READWRITE |STGM_TRANSACTED, 0, &stg); + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg); + ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg); ok(r==S_OK, "StgCreateDocfile failed\n"); r = IStorage_Release(stg); ok(r == 0, "storage not released\n"); ok(DeleteFileW(filename), "failed to delete file\n"); + + /* test the way excel uses StgCreateDocFile */ + r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg); + ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); + if(r == S_OK) + { + r = IStorage_Release(stg); + ok(r == 0, "storage not released\n"); + ok(DeleteFileW(filename), "failed to delete file\n"); + } + + /* looks like we need STGM_TRANSACTED or STGM_CREATE */ + r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg); + ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); + if(r == S_OK) + { + r = IStorage_Release(stg); + ok(r == 0, "storage not released\n"); + ok(DeleteFileW(filename), "failed to delete file\n"); + } + + r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg); + ok(r==S_OK, "StgCreateDocfile the excel way failed\n"); + if(r == S_OK) + { + r = IStorage_Release(stg); + ok(r == 0, "storage not released\n"); + ok(DeleteFileW(filename), "failed to delete file\n"); + } + + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); + ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n"); + if(r == S_OK) + { + r = IStorage_Release(stg); + ok(r == 0, "storage not released\n"); + ok(DeleteFileW(filename), "failed to delete file\n"); + } + + /* test the way msi uses StgCreateDocfile */ + r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg); + ok(r==S_OK, "StgCreateDocFile failed\n"); + r = IStorage_Release(stg); + ok(r == 0, "storage not released\n"); + ok(DeleteFileW(filename), "failed to delete file\n"); } void test_storage_stream(void) @@ -309,10 +368,125 @@ ok(r, "file didn't exist\n"); } +void test_storage_suminfo(void) +{ + static const WCHAR szDot[] = { '.',0 }; + static const WCHAR szPrefix[] = { 's','t','g',0 }; + WCHAR filename[MAX_PATH]; + IStorage *stg = NULL; + IPropertySetStorage *propset = NULL; + IPropertyStorage *ps = NULL; + HRESULT r; + + if(!GetTempFileNameW(szDot, szPrefix, 0, filename)) + return; + + DeleteFileW(filename); + + /* create the file */ + r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | + STGM_READWRITE |STGM_TRANSACTED, 0, &stg); + ok(r==S_OK, "StgCreateDocfile failed\n"); + + r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset ); + ok(r == S_OK, "query interface failed\n"); + + /* delete it */ + r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation ); + ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n"); + + r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, + STGM_READ | STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == STG_E_FILENOTFOUND, "opened property set storage\n"); + + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_READ | STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); + + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_READ, &ps ); + ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); + + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps ); + ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); + + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); + + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == STG_E_INVALIDFLAG, "created property set storage\n"); + + /* now try really creating a a property set */ + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == S_OK, "failed to create property set storage\n"); + + if( ps ) + IPropertyStorage_Release(ps); + + /* now try creating the same thing again */ + r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, + STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps ); + ok(r == S_OK, "failed to create property set storage\n"); + if( ps ) + IPropertyStorage_Release(ps); + + /* should be able to open it */ + r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, + STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); + ok(r == S_OK, "open failed\n"); + if(r == S_OK) + IPropertyStorage_Release(ps); + + /* delete it */ + r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation ); + ok(r == S_OK, "failed to delete property set storage\n"); + + /* try opening with an invalid FMTID */ + r = IPropertySetStorage_Open( propset, NULL, + STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); + ok(r == E_INVALIDARG, "open succeeded\n"); + if(r == S_OK) + IPropertyStorage_Release(ps); + + /* try a bad guid */ + r = IPropertySetStorage_Open( propset, &IID_IStorage, + STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); + ok(r == STG_E_FILENOTFOUND, "open succeeded\n"); + if(r == S_OK) + IPropertyStorage_Release(ps); + + + /* try some invalid flags */ + r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, + STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); + ok(r == STG_E_INVALIDFLAG, "open succeeded\n"); + if(r == S_OK) + IPropertyStorage_Release(ps); + + /* after deleting it, it should be gone */ + r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, + STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps); + ok(r == STG_E_FILENOTFOUND, "open failed\n"); + if(r == S_OK) + IPropertyStorage_Release(ps); + + r = IPropertySetStorage_Release( propset ); + ok(r == 1, "ref count wrong\n"); + + r = IStorage_Release(stg); + ok(r == 0, "ref count wrong\n"); + + DeleteFileW(filename); +} + START_TEST(storage32) { test_hglobal_storage_stat(); test_create_storage_modes(); test_storage_stream(); test_open_storage(); + test_storage_suminfo(); } diff -urN wine-20050211/dlls/oleaut32/Makefile.in wine-20050310/dlls/oleaut32/Makefile.in --- wine-20050211/dlls/oleaut32/Makefile.in 2004-10-27 02:47:53.000000000 +0200 +++ wine-20050310/dlls/oleaut32/Makefile.in 2005-03-07 20:22:49.000000000 +0100 @@ -5,7 +5,7 @@ VPATH = @srcdir@ MODULE = oleaut32.dll IMPORTS = ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll -DELAYIMPORTS = comctl32 +DELAYIMPORTS = comctl32 urlmon EXTRALIBS = $(LIBUNICODE) -luuid C_SRCS = \ @@ -16,6 +16,7 @@ oleaut.c \ olefont.c \ olepicture.c \ + recinfo.c \ regsvr.c \ safearray.c \ stubs.c \ diff -urN wine-20050211/dlls/oleaut32/oleaut.c wine-20050310/dlls/oleaut32/oleaut.c --- wine-20050211/dlls/oleaut32/oleaut.c 2005-02-08 13:56:50.000000000 +0100 +++ wine-20050310/dlls/oleaut32/oleaut.c 2005-03-07 20:22:48.000000000 +0100 @@ -572,28 +572,6 @@ } /****************************************************************************** - * GetRecordInfoFromGuids [OLEAUT32.322] - * - * RETURNS - * Success: S_OK - * Failure: E_INVALIDARG, if any argument is invalid. - * - * BUGS - * Unimplemented - */ -HRESULT WINAPI GetRecordInfoFromGuids( - REFGUID rGuidTypeLib, - ULONG uVerMajor, - ULONG uVerMinor, - LCID lcid, - REFGUID rGuidTypeInfo, - IRecordInfo** ppRecInfo) -{ - FIXME("(%p,%ld,%ld,%ld,%p,%p),stub!\n",rGuidTypeLib, uVerMajor, uVerMinor, lcid, rGuidTypeInfo, ppRecInfo); - return E_NOTIMPL; -} - -/****************************************************************************** * OleTranslateColor [OLEAUT32.421] * * Convert an OLE_COLOR to a COLORREF. diff -urN wine-20050211/dlls/oleaut32/oleaut32.rc wine-20050310/dlls/oleaut32/oleaut32.rc --- wine-20050211/dlls/oleaut32/oleaut32.rc 2004-12-15 11:44:00.000000000 +0100 +++ wine-20050310/dlls/oleaut32/oleaut32.rc 2005-02-14 12:12:30.000000000 +0100 @@ -42,7 +42,7 @@ /* * FIXME: - * Finnish, Greek, Hebrew, Japanese, Korean, Portuguese, + * Finnish, Greek, Hebrew, Japanese, Korean, * Turkish, Slovenian (at least) are localised in XP Home. * I expect Chinese etc are localised in Asian Editions also. */ diff -urN wine-20050211/dlls/oleaut32/oleaut32.spec wine-20050310/dlls/oleaut32/oleaut32.spec --- wine-20050211/dlls/oleaut32/oleaut32.spec 2004-05-27 03:55:54.000000000 +0200 +++ wine-20050310/dlls/oleaut32/oleaut32.spec 2005-03-07 20:22:48.000000000 +0100 @@ -315,7 +315,7 @@ 320 stdcall -private DllRegisterServer() OLEAUT32_DllRegisterServer 321 stdcall -private DllUnregisterServer() OLEAUT32_DllUnregisterServer 322 stdcall GetRecordInfoFromGuids(ptr long long long ptr ptr) -323 stub GetRecordInfoFromTypeInfo # stdcall (ptr ptr) +323 stdcall GetRecordInfoFromTypeInfo(ptr ptr) 325 stub SetVarConversionLocaleSetting 326 stub GetVarConversionLocaleSetting 327 stdcall SetOaNoCache() @@ -396,7 +396,7 @@ 421 stdcall OleTranslateColor(long long long) 422 stub OleLoadPictureFile 423 stub OleSavePictureFile -424 stub OleLoadPicturePath +424 stdcall OleLoadPicturePath(wstr ptr long long ptr ptr) 425 stdcall VarUI4FromI8(long long ptr) 426 stdcall VarUI4FromUI8(long long ptr) 427 stdcall VarI8FromUI8(long long ptr) diff -urN wine-20050211/dlls/oleaut32/oleaut32_Es.rc wine-20050310/dlls/oleaut32/oleaut32_Es.rc --- wine-20050211/dlls/oleaut32/oleaut32_Es.rc 2003-10-15 22:50:24.000000000 +0200 +++ wine-20050310/dlls/oleaut32/oleaut32_Es.rc 2005-02-16 22:11:00.000000000 +0100 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL STRINGTABLE DISCARDABLE { diff -urN wine-20050211/dlls/oleaut32/olefont.c wine-20050310/dlls/oleaut32/olefont.c --- wine-20050211/dlls/oleaut32/olefont.c 2005-01-31 12:34:10.000000000 +0100 +++ wine-20050310/dlls/oleaut32/olefont.c 2005-02-18 13:51:23.000000000 +0100 @@ -1068,8 +1068,16 @@ IFont* iface, TEXTMETRICOLE* ptm) { - FIXME("(%p, %p), stub!\n",iface,ptm); - return E_NOTIMPL; + HDC hdcRef; + HFONT hOldFont, hNewFont; + + hdcRef = GetDC(0); + OLEFontImpl_get_hFont(iface, &hNewFont); + hOldFont = SelectObject(hdcRef, hNewFont); + GetTextMetricsW(hdcRef, ptm); + SelectObject(hdcRef, hOldFont); + ReleaseDC(0, hdcRef); + return S_OK; } /************************************************************************ diff -urN wine-20050211/dlls/oleaut32/olepicture.c wine-20050310/dlls/oleaut32/olepicture.c --- wine-20050211/dlls/oleaut32/olepicture.c 2005-01-14 17:12:10.000000000 +0100 +++ wine-20050310/dlls/oleaut32/olepicture.c 2005-03-04 13:30:26.000000000 +0100 @@ -71,7 +71,9 @@ #include "olectl.h" #include "oleauto.h" #include "connpt.h" +#include "urlmon.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "wine/wingdi16.h" #include "cursoricon.h" @@ -106,7 +108,7 @@ IPersistStreamVtbl *lpvtbl3; IConnectionPointContainerVtbl *lpvtbl4; - /* Object referenece count */ + /* Object reference count */ DWORD ref; /* We own the object and must destroy it ourselves */ @@ -705,7 +707,7 @@ TRACE("(%p)->(%p).\n", This, pdwAttr); *pdwAttr = 0; switch (This->desc.picType) { - case PICTYPE_BITMAP: break; /* not 'truely' scalable, see MSDN. */ + case PICTYPE_BITMAP: break; /* not 'truly' scalable, see MSDN. */ case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break; case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break; default:FIXME("Unknown pictype %d\n",This->desc.picType);break; @@ -1514,9 +1516,15 @@ GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); /* Calculate the total length required for the BMP data */ - if (pInfoBitmap->bmiHeader.biClrUsed != 0) iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; - else if (pInfoBitmap->bmiHeader.biBitCount <= 8) iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; - else iNumPaletteEntries = 0; + if (pInfoBitmap->bmiHeader.biClrUsed != 0) { + iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; + if (iNumPaletteEntries > 256) iNumPaletteEntries = 256; + } else { + if (pInfoBitmap->bmiHeader.biBitCount <= 8) + iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; + else + iNumPaletteEntries = 0; + } *pLength = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + @@ -1624,6 +1632,7 @@ || (pInfoBitmap->bmiHeader.biBitCount == 24) || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; + if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { iNumEntriesPalette = 3; @@ -1820,7 +1829,7 @@ VariantInit(pVarResult); V_VT(pVarResult) = VT_BOOL; - V_UNION(pVarResult,boolVal) = FALSE; + V_BOOL(pVarResult) = FALSE; return S_OK; } @@ -1984,6 +1993,113 @@ return hr; } +/*********************************************************************** + * OleLoadPicturePath (OLEAUT32.424) + */ +HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller, + DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid, + LPVOID *ppvRet ) +{ + static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 }; + IPicture *ipicture; + HANDLE hFile; + DWORD dwFileSize; + HGLOBAL hGlobal = NULL; + DWORD dwBytesRead = 0; + IStream *stream; + BOOL bRead; + IPersistStream *pStream; + HRESULT hRes; + + TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n", + debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved, + debugstr_guid(riid), ppvRet); + + if (!ppvRet) return E_POINTER; + + if (strncmpW(szURLorPath, file, 7) == 0) { + szURLorPath += 7; + + hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, + 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return E_UNEXPECTED; + + dwFileSize = GetFileSize(hFile, NULL); + if (dwFileSize != INVALID_FILE_SIZE ) + { + hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize); + if ( hGlobal) + { + bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL); + if (!bRead) + { + GlobalFree(hGlobal); + hGlobal = 0; + } + } + } + CloseHandle(hFile); + + if (!hGlobal) + return E_UNEXPECTED; + + hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream); + if (FAILED(hRes)) + { + GlobalFree(hGlobal); + return hRes; + } + } else { + IMoniker *pmnk; + IBindCtx *pbc; + + hRes = CreateBindCtx(0, &pbc); + if (SUCCEEDED(hRes)) + { + hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk); + if (SUCCEEDED(hRes)) + { + hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream); + IMoniker_Release(pmnk); + } + IBindCtx_Release(pbc); + } + if (FAILED(hRes)) + return hRes; + } + + hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, + &IID_IPicture, (LPVOID*)&ipicture); + if (hRes != S_OK) { + IStream_Release(stream); + return hRes; + } + + hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream); + if (hRes) { + IStream_Release(stream); + IPicture_Release(ipicture); + return hRes; + } + + hRes = IPersistStream_Load(pStream, stream); + IPersistStream_Release(pStream); + IStream_Release(stream); + + if (hRes) { + IPicture_Release(ipicture); + return hRes; + } + + hRes = IPicture_QueryInterface(ipicture,riid,ppvRet); + if (hRes) + FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid)); + + IPicture_Release(ipicture); + return hRes; +} + /******************************************************************************* * StdPic ClassFactory */ @@ -2017,12 +2133,8 @@ static HRESULT WINAPI SPCF_CreateInstance( LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj ) { - PICTDESC pd; - - FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface,pOuter,debugstr_guid(riid),ppobj); - pd.cbSizeofstruct = sizeof(pd); - pd.picType = PICTYPE_NONE; - return OleCreatePictureIndirect(&pd,riid,TRUE,ppobj); + /* Creates an uninitialized picture */ + return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj); } diff -urN wine-20050211/dlls/oleaut32/recinfo.c wine-20050310/dlls/oleaut32/recinfo.c --- wine-20050211/dlls/oleaut32/recinfo.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050310/dlls/oleaut32/recinfo.c 2005-03-09 12:43:55.000000000 +0100 @@ -0,0 +1,621 @@ +/* + * Copyright 2005 Jacek Caban + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" +#include "oaidl.h" +#include "oleauto.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +typedef struct { + enum VARENUM vt; + VARKIND varkind; + ULONG offset; + BSTR name; +} fieldstr; + +typedef struct { + IRecordInfoVtbl *lpVtbl; + ULONG ref; + + GUID guid; + UINT lib_index; + WORD n_vars; + ULONG size; + BSTR name; + fieldstr *fields; + ITypeInfo *pTypeInfo; +} IRecordInfoImpl; + +static HRESULT copy_to_variant(void *src, VARIANT *pvar, enum VARENUM vt) +{ + TRACE("%p %p %d\n", src, pvar, vt); + +#define CASE_COPY(x) \ + case VT_ ## x: \ + V_ ## x(pvar) = *(typeof(V_ ## x(pvar))*)src; \ + break + + switch(vt) { + CASE_COPY(I2); + CASE_COPY(I4); + CASE_COPY(R4); + CASE_COPY(R8); + CASE_COPY(CY); + CASE_COPY(DATE); + CASE_COPY(BSTR); + CASE_COPY(ERROR); + CASE_COPY(BOOL); + CASE_COPY(DECIMAL); + CASE_COPY(I1); + CASE_COPY(UI1); + CASE_COPY(UI2); + CASE_COPY(UI4); + CASE_COPY(I8); + CASE_COPY(UI8); + CASE_COPY(INT); + CASE_COPY(UINT); + CASE_COPY(INT_PTR); + CASE_COPY(UINT_PTR); + default: + FIXME("Not supported type: %d\n", vt); + return E_NOTIMPL; + }; +#undef CASE_COPY + + V_VT(pvar) = vt; + return S_OK; +} + +static HRESULT copy_from_variant(VARIANT *src, void *dest, enum VARENUM vt) +{ + VARIANT var; + HRESULT hres; + + TRACE("(%p(%d) %p %d)\n", src, V_VT(src), dest, vt); + + hres = VariantChangeType(&var, src, 0, vt); + if(FAILED(hres)) + return hres; + +#define CASE_COPY(x) \ + case VT_ ## x: \ + *(typeof(V_ ## x(&var))*)dest = V_ ## x(&var); \ + break + + switch(vt) { + CASE_COPY(I2); + CASE_COPY(I4); + CASE_COPY(R4); + CASE_COPY(R8); + CASE_COPY(CY); + CASE_COPY(DATE); + CASE_COPY(BSTR); + CASE_COPY(ERROR); + CASE_COPY(BOOL); + CASE_COPY(DECIMAL); + CASE_COPY(I1); + CASE_COPY(UI1); + CASE_COPY(UI2); + CASE_COPY(UI4); + CASE_COPY(I8); + CASE_COPY(UI8); + CASE_COPY(INT); + CASE_COPY(UINT); + CASE_COPY(INT_PTR); + CASE_COPY(UINT_PTR); + default: + FIXME("Not supported type: %d\n", V_VT(&var)); + return E_NOTIMPL; + }; +#undef CASE_COPY + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_QueryInterface(IRecordInfo *iface, REFIID riid, + void **ppvObject) +{ + TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject); + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRecordInfo, riid)) { + *ppvObject = iface; + IRecordInfo_AddRef(iface); + return S_OK; + } + + FIXME("Not supported interface: %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI IRecordInfoImpl_AddRef(IRecordInfo *iface) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) -> %ld\n", This, ref); + return ref; +} + +static ULONG WINAPI IRecordInfoImpl_Release(IRecordInfo *iface) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) -> %ld\n", This, ref); + + if(!ref) { + int i; + for(i=0; in_vars; i++) + SysFreeString(This->fields[i].name); + HeapFree(GetProcessHeap(), 0, This->name); + HeapFree(GetProcessHeap(), 0, This->fields); + ITypeInfo_Release(This->pTypeInfo); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI IRecordInfoImpl_RecordInit(IRecordInfo *iface, PVOID pvNew) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + TRACE("(%p)->(%p)\n", This, pvNew); + + if(!pvNew) + return E_INVALIDARG; + + memset(pvNew, 0, This->size); + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + int i; + PVOID var; + + TRACE("(%p)->(%p)\n", This, pvExisting); + + if(!pvExisting) + return E_INVALIDARG; + + for(i=0; in_vars; i++) { + if(This->fields[i].varkind != VAR_PERINSTANCE) { + ERR("varkind != VAR_PERINSTANCE\n"); + continue; + } + var = ((PBYTE)pvExisting)+This->fields[i].offset; + switch(This->fields[i].vt) { + case VT_BSTR: + /* NOTE: Windows implementatino reads DWORD (len) before string, + * but it seems to do nothing with this */ + *(BSTR*)var = NULL; + break; + case VT_I2: + case VT_I4: + case VT_R8: + case VT_CY: + case VT_DATE: + case VT_ERROR: + case VT_BOOL: + case VT_DECIMAL: + case VT_I1: + case VT_UI1: + case VT_UI2: + case VT_UI4: + case VT_I8: + case VT_UI8: + case VT_INT: + case VT_UINT: + break; + case VT_INT_PTR: + case VT_UINT_PTR: + *(void**)var = NULL; + break; + default: + FIXME("Not supported vt = %d\n", This->fields[i].vt); + break; + } + } + + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, PVOID pvExisting, + PVOID pvNew) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p %p)\n", This, pvExisting, pvNew); + + if(!pvExisting || !pvNew) + return E_INVALIDARG; + + memcpy(pvExisting, pvNew, This->size); + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_GetGuid(IRecordInfo *iface, GUID *pguid) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p)\n", This, pguid); + + if(!pguid) + return E_INVALIDARG; + + memcpy(pguid, &This->guid, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_GetName(IRecordInfo *iface, BSTR *pbstrName) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p)\n", This, pbstrName); + + if(!pbstrName) + return E_INVALIDARG; + + *pbstrName = SysAllocString(This->name); + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG *pcbSize) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p)\n", This, pcbSize); + + if(!pcbSize) + return E_INVALIDARG; + + *pcbSize = This->size; + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p)\n", This, ppTypeInfo); + + if(!ppTypeInfo) + return E_INVALIDARG; + + ITypeInfo_AddRef(This->pTypeInfo); + *ppTypeInfo = This->pTypeInfo; + + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_GetField(IRecordInfo *iface, PVOID pvData, + LPCOLESTR szFieldName, VARIANT *pvarField) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + int i; + + TRACE("(%p)->(%p %s %p)\n", This, pvData, debugstr_w(szFieldName), pvarField); + + if(!pvData || !szFieldName || !pvarField) + return E_INVALIDARG; + + for(i=0; in_vars; i++) + if(!strcmpW(This->fields[i].name, szFieldName)) + break; + if(i == This->n_vars) + return TYPE_E_FIELDNOTFOUND; + + VariantClear(pvarField); + return copy_to_variant(((PBYTE)pvData)+This->fields[i].offset, pvarField, + This->fields[i].vt); +} + +static HRESULT WINAPI IRecordInfoImpl_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, + LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + int i; + + TRACE("(%p)->(%p %s %p %p)\n", This, pvData, debugstr_w(szFieldName), pvarField, ppvDataCArray); + + if(!pvData || !szFieldName || !pvarField) + return E_INVALIDARG; + + for(i=0; in_vars; i++) + if(!strcmpW(This->fields[i].name, szFieldName)) + break; + if(i == This->n_vars) + return TYPE_E_FIELDNOTFOUND; + + VariantClear(pvarField); + V_VT(pvarField) = VT_BYREF|This->fields[i].vt; + V_BYREF(pvarField) = ((PBYTE)pvData)+This->fields[i].offset; + *ppvDataCArray = NULL; + return S_OK; +} + +static HRESULT WINAPI IRecordInfoImpl_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData, + LPCOLESTR szFieldName, VARIANT *pvarField) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + int i; + + TRACE("(%p)->(%08lx %p %s %p)\n", This, wFlags, pvData, debugstr_w(szFieldName), + pvarField); + + if(!pvData || !szFieldName || !pvarField + || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT)) + return E_INVALIDARG; + + if(wFlags == INVOKE_PROPERTYPUTREF) { + FIXME("wFlag == INVOKE_PROPERTYPUTREF not supported\n"); + return E_NOTIMPL; + } + + for(i=0; in_vars; i++) + if(!strcmpW(This->fields[i].name, szFieldName)) + break; + if(i == This->n_vars) + return TYPE_E_FIELDNOTFOUND; + + return copy_from_variant(pvarField, ((PBYTE)pvData)+This->fields[i].offset, + This->fields[i].vt); +} + +static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, + PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + int i; + + FIXME("(%p)->(%08lx %p %s %p) stub\n", This, wFlags, pvData, debugstr_w(szFieldName), pvarField); + + if(!pvData || !szFieldName || !pvarField + || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT)) + return E_INVALIDARG; + + for(i=0; in_vars; i++) + if(!strcmpW(This->fields[i].name, szFieldName)) + break; + if(i == This->n_vars) + return TYPE_E_FIELDNOTFOUND; + + return E_NOTIMPL; +} + +static HRESULT WINAPI IRecordInfoImpl_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, + BSTR *rgBstrNames) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + ULONG n = This->n_vars; + int i; + + TRACE("(%p)->(%p %p)\n", This, pcNames, rgBstrNames); + + if(!pcNames) + return E_INVALIDARG; + + if(*pcNames < n) + n = *pcNames; + + if(rgBstrNames) { + for(i=0; ifields[i].name); + } + + *pcNames = n; + return S_OK; +} + +static BOOL WINAPI IRecordInfoImpl_IsMatchingType(IRecordInfo *iface, IRecordInfo *pRecordInfo) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + FIXME("(%p)->(%p) stub\n", This, pRecordInfo); + + return FALSE; +} + +static PVOID WINAPI IRecordInfoImpl_RecordCreate(IRecordInfo *iface) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)\n", This); + + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->size); +} + +static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, + PVOID *ppvDest) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p %p)\n", This, pvSource, ppvDest); + + if(!pvSource || !ppvDest) + return E_INVALIDARG; + + *ppvDest = IRecordInfo_RecordCreate(iface); + return IRecordInfo_RecordCopy(iface, pvSource, *ppvDest); +} + +static HRESULT WINAPI IRecordInfoImpl_RecordDestroy(IRecordInfo *iface, PVOID pvRecord) +{ + IRecordInfoImpl *This = (IRecordInfoImpl*)iface; + + TRACE("(%p)->(%p)\n", This, pvRecord); + + if(!HeapFree(GetProcessHeap(), 0, pvRecord)) + return E_INVALIDARG; + + return S_OK; +} + +static IRecordInfoVtbl IRecordInfoImplVtbl = { + IRecordInfoImpl_QueryInterface, + IRecordInfoImpl_AddRef, + IRecordInfoImpl_Release, + IRecordInfoImpl_RecordInit, + IRecordInfoImpl_RecordClear, + IRecordInfoImpl_RecordCopy, + IRecordInfoImpl_GetGuid, + IRecordInfoImpl_GetName, + IRecordInfoImpl_GetSize, + IRecordInfoImpl_GetTypeInfo, + IRecordInfoImpl_GetField, + IRecordInfoImpl_GetFieldNoCopy, + IRecordInfoImpl_PutField, + IRecordInfoImpl_PutFieldNoCopy, + IRecordInfoImpl_GetFieldNames, + IRecordInfoImpl_IsMatchingType, + IRecordInfoImpl_RecordCreate, + IRecordInfoImpl_RecordCreateCopy, + IRecordInfoImpl_RecordDestroy +}; + +/****************************************************************************** + * GetRecordInfoFromGuids [OLEAUT32.322] + * + * RETURNS + * Success: S_OK + * Failure: E_INVALIDARG, if any argument is invalid. + */ +HRESULT WINAPI GetRecordInfoFromGuids(REFGUID rGuidTypeLib, ULONG uVerMajor, + ULONG uVerMinor, LCID lcid, REFGUID rGuidTypeInfo, IRecordInfo** ppRecInfo) +{ + ITypeInfo *pTypeInfo; + ITypeLib *pTypeLib; + HRESULT hres; + + TRACE("(%p,%ld,%ld,%ld,%p,%p)\n", rGuidTypeLib, uVerMajor, uVerMinor, + lcid, rGuidTypeInfo, ppRecInfo); + + hres = LoadRegTypeLib(rGuidTypeLib, uVerMajor, uVerMinor, lcid, &pTypeLib); + if(FAILED(hres)) { + WARN("LoadRegTypeLib failed!\n"); + return hres; + } + + hres = ITypeLib_GetTypeInfoOfGuid(pTypeLib, rGuidTypeInfo, &pTypeInfo); + ITypeLib_Release(pTypeLib); + if(FAILED(hres)) { + WARN("GetTypeInfoOfGuid failed!\n"); + return hres; + } + + hres = GetRecordInfoFromTypeInfo(pTypeInfo, ppRecInfo); + ITypeInfo_Release(pTypeInfo); + return hres; +} + +/****************************************************************************** + * GetRecordInfoFromTypeInfo [OLEAUT32.332] + */ +HRESULT WINAPI GetRecordInfoFromTypeInfo(ITypeInfo* pTI, IRecordInfo** ppRecInfo) { + HRESULT hres; + TYPEATTR *typeattr; + IRecordInfoImpl *ret; + ITypeInfo *pTypeInfo; + int i; + GUID guid; + + TRACE("(%p %p)\n", pTI, ppRecInfo); + + if(!pTI || !ppRecInfo) + return E_INVALIDARG; + + hres = ITypeInfo_GetTypeAttr(pTI, &typeattr); + if(FAILED(hres) || !typeattr) { + WARN("GetTypeAttr failed: %08lx\n", hres); + return hres; + } + + if(typeattr->typekind == TKIND_ALIAS) { + hres = ITypeInfo_GetRefTypeInfo(pTI, typeattr->tdescAlias.u.hreftype, &pTypeInfo); + memcpy(&guid, &typeattr->guid, sizeof(GUID)); + ITypeInfo_ReleaseTypeAttr(pTI, typeattr); + if(FAILED(hres)) { + WARN("GetRefTypeInfo failed: %08lx\n", hres); + return hres; + } + ITypeInfo_GetTypeAttr(pTypeInfo, &typeattr); + }else { + pTypeInfo = pTI; + ITypeInfo_AddRef(pTypeInfo); + memcpy(&guid, &typeattr->guid, sizeof(GUID)); + } + + if(typeattr->typekind != TKIND_RECORD) { + WARN("typekind != TKIND_RECORD\n"); + ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr); + ITypeInfo_Release(pTypeInfo); + return E_INVALIDARG; + } + + ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); + ret->lpVtbl = &IRecordInfoImplVtbl; + ret->ref = 1; + ret->pTypeInfo = pTypeInfo; + ret->n_vars = typeattr->cVars; + ret->size = typeattr->cbSizeInstance; + ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr); + + memcpy(&ret->guid, &guid, sizeof(GUID)); + + /* NOTE: Windows implementation calls ITypeInfo::GetCantainingTypeLib and + * ITypeLib::GetLibAttr, but we currently don't need this. + */ + + hres = ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &ret->name, NULL, NULL, NULL); + if(FAILED(hres)) { + WARN("ITypeInfo::GetDocumentation failed\n"); + ret->name = NULL; + } + + ret->fields = HeapAlloc(GetProcessHeap(), 0, ret->n_vars*sizeof(VARDESC)); + for(i = 0; in_vars; i++) { + VARDESC *vardesc; + hres = ITypeInfo_GetVarDesc(pTypeInfo, i, &vardesc); + if(FAILED(hres)) { + WARN("GetVarDesc failed\n"); + continue; + } + ret->fields[i].vt = vardesc->elemdescVar.tdesc.vt; + ret->fields[i].varkind = vardesc->varkind; + ret->fields[i].offset = vardesc->u.oInst; + hres = ITypeInfo_GetDocumentation(pTypeInfo, vardesc->memid, &ret->fields[i].name, + NULL, NULL, NULL); + if(FAILED(hres)) + WARN("GetDocumentation failed: %08lx\n", hres); + ITypeInfo_ReleaseVarDesc(pTypeInfo, vardesc); + } + + *ppRecInfo = (IRecordInfo*)ret; + + return S_OK; +} diff -urN wine-20050211/dlls/oleaut32/tests/vartype.c wine-20050310/dlls/oleaut32/tests/vartype.c --- wine-20050211/dlls/oleaut32/tests/vartype.c 2004-12-17 20:13:24.000000000 +0100 +++ wine-20050310/dlls/oleaut32/tests/vartype.c 2005-02-25 15:07:57.000000000 +0100 @@ -4498,7 +4498,7 @@ CONVERT_STR(VarBoolFromStr,"faux",0); EXPECT_MISMATCH; /* But accepted if this flag is given */ CONVERT_STR(VarBoolFromStr,"faux",VARIANT_LOCALBOOL); EXPECT(VARIANT_FALSE); - /* Regardless of case - from this we assume locale text comparasons ignore case */ + /* Regardless of case - from this we assume locale text comparisons ignore case */ CONVERT_STR(VarBoolFromStr,"Faux",VARIANT_LOCALBOOL); EXPECT(VARIANT_FALSE); /* Changing the locale prevents the localised text from being compared - diff -urN wine-20050211/dlls/oleaut32/typelib.c wine-20050310/dlls/oleaut32/typelib.c --- wine-20050211/dlls/oleaut32/typelib.c 2005-01-31 12:34:10.000000000 +0100 +++ wine-20050310/dlls/oleaut32/typelib.c 2005-03-02 14:53:51.000000000 +0100 @@ -315,6 +315,9 @@ TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); + /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */ + memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR)); + *pptLib = NULL; if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath, NULL)) { @@ -331,9 +334,6 @@ return TYPE_E_CANTLOADLIBRARY; if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY) return TYPE_E_CANTLOADLIBRARY; - } else { - TRACE("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile)); - return TYPE_E_CANTLOADLIBRARY; } } @@ -848,9 +848,10 @@ libary. Only used while read MSFT typelibs */ - /* typelibs are cached, keyed by path, so store the linked list info within them */ + /* typelibs are cached, keyed by path and index, so store the linked list info within them */ struct tagITypeLibImpl *next, *prev; WCHAR *path; + INT index; } ITypeLibImpl; static struct ITypeLib2Vtbl tlbvt; @@ -865,7 +866,7 @@ /*======================= ITypeInfo implementation =======================*/ -/* data for refernced types */ +/* data for referenced types */ typedef struct tagTLBRefType { INT index; /* Type index for internal ref or for external ref @@ -1497,7 +1498,7 @@ if(offset <0) { /* data are packed in here */ V_VT(pVar) = (offset & 0x7c000000 )>> 26; - V_UNION(pVar, iVal) = offset & 0x3ffffff; + V_I2(pVar) = offset & 0x3ffffff; return; } MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx, @@ -1537,7 +1538,7 @@ } else { ptr=TLB_Alloc(size);/* allocate temp buffer */ MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */ - V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size); + V_BSTR(pVar)=SysAllocStringLen(NULL,size); /* FIXME: do we need a AtoW conversion here? */ V_UNION(pVar, bstrVal[size])=L'\0'; while(size--) V_UNION(pVar, bstrVal[size])=ptr[size]; @@ -1570,7 +1571,7 @@ } if(size>0) /* (big|small) endian correct? */ - MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK ); + MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK ); return; } /* @@ -1924,7 +1925,7 @@ recoffset += reclength; } } -/* fill in data for a hreftype (offset). When the refernced type is contained +/* fill in data for a hreftype (offset). When the referenced type is contained * in the typelib, it's just an (file) offset in the type info base dir. * If comes from import, it's an offset+1 in the ImpInfo table * */ @@ -2169,7 +2170,7 @@ EnterCriticalSection(&cache_section); for (entry = tlb_cache_first; entry != NULL; entry = entry->next) { - if (!strcmpiW(entry->path, pszFileName)) + if (!strcmpiW(entry->path, pszFileName) && entry->index == index) { TRACE("cache hit\n"); *ppTypeLib = (ITypeLib2*)entry; @@ -2209,8 +2210,13 @@ } CloseHandle(hFile); } + else + { + TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName)); + } - if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE ) + /* if the file is a DLL or not found, try loading it with LoadLibrary */ + if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0)) { /* find the typelibrary resource*/ HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES| @@ -2258,6 +2264,7 @@ impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR)); lstrcpyW(impl->path, pszFileName); /* We should really canonicalise the path here. */ + impl->index = index; /* FIXME: check if it has added already in the meantime */ EnterCriticalSection(&cache_section); @@ -3074,7 +3081,7 @@ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra); } -/* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more +/* Because SLTG_OtherTypeInfo is such a painful struct, we make a more managable copy of it into this */ typedef struct { WORD small_no; @@ -4109,8 +4116,8 @@ TRACE("(%p)->(%lu)\n",This, ref); if (ref) { - /* We don't release ITypeLib when ref=0 becouse - it means that funtion is called by ITypeLi2_Release */ + /* We don't release ITypeLib when ref=0 because + it means that function is called by ITypeLib2_Release */ ITypeLib2_Release((ITypeLib2*)This->pTypeLib); } else { FIXME("destroy child objects\n"); @@ -4518,12 +4525,12 @@ } if (V_VT(arg) == vt) { - memcpy(argpos, &V_UNION(arg,lVal), arglen); + memcpy(argpos, &V_I4(arg), arglen); return S_OK; } if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) { - memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*)); + memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*)); return S_OK; } @@ -4533,13 +4540,13 @@ } /* Deref BYREF vars if there is need */ if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) { - memcpy(argpos,(void*)V_UNION(arg,lVal), arglen); + memcpy(argpos,(void*)V_I4(arg), arglen); return S_OK; } if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) { /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */ - memcpy(argpos,&V_UNION(arg,lVal), arglen); + memcpy(argpos,&V_I4(arg), arglen); return S_OK; } if ((vt == VT_PTR) && tdesc) @@ -4555,7 +4562,7 @@ FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, " "while coercing from vt 0x%x. Copying 4 byte.\n", tdesc->u.hreftype,V_VT(arg)); - memcpy(argpos, &V_UNION(arg,lVal), 4); + memcpy(argpos, &V_I4(arg), 4); return S_OK; } hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr); @@ -4569,11 +4576,11 @@ case TKIND_ENUM: switch ( V_VT( arg ) ) { case VT_I2: - *argpos = V_UNION(arg,iVal); + *argpos = V_I2(arg); hres = S_OK; break; case VT_I4: - memcpy(argpos, &V_UNION(arg,lVal), 4); + memcpy(argpos, &V_I4(arg), 4); hres = S_OK; break; default: @@ -4592,15 +4599,15 @@ if (V_VT(arg) == VT_DISPATCH) { IDispatch *disp; if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) { - memcpy(argpos, &V_UNION(arg,pdispVal), 4); + memcpy(argpos, &V_DISPATCH(arg), 4); hres = S_OK; break; } - hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal), + hres=IUnknown_QueryInterface(V_DISPATCH(arg), &IID_IDispatch,(LPVOID*)&disp); if (SUCCEEDED(hres)) { memcpy(argpos,&disp,4); - IUnknown_Release(V_UNION(arg,pdispVal)); + IUnknown_Release(V_DISPATCH(arg)); hres = S_OK; break; } @@ -4610,7 +4617,7 @@ break; } if (V_VT(arg) == VT_UNKNOWN) { - memcpy(argpos, &V_UNION(arg,punkVal), 4); + memcpy(argpos, &V_UNKNOWN(arg), 4); hres = S_OK; break; } @@ -4621,7 +4628,7 @@ case TKIND_DISPATCH: if (V_VT(arg) == VT_DISPATCH) { - memcpy(argpos, &V_UNION(arg,pdispVal), 4); + memcpy(argpos, &V_DISPATCH(arg), 4); hres = S_OK; } else { @@ -4646,7 +4653,7 @@ oldvt = V_VT(arg); VariantInit(&va); if (VariantChangeType(&va,arg,0,vt)==S_OK) { - memcpy(argpos,&V_UNION(&va,lVal), arglen); + memcpy(argpos,&V_I4(&va), arglen); FIXME("Should not use VariantChangeType here." " (conversion from 0x%x -> 0x%x) %08lx\n", V_VT(arg), vt, *argpos @@ -4768,7 +4775,7 @@ if(i < func_desc->cParams - func_desc->cParamsOpt) ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n"); if(V_VT(arg) == VT_EMPTY - || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) { + || ((V_ISBYREF(arg)) && !V_BYREF(arg))) { /* FIXME: Documentation says that we do this when parameter is left unspecified. How to determine it? */ @@ -4834,7 +4841,7 @@ continue; VariantInit(pVarResult); - memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD)); + memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD)); if (tdesc->vt == VT_PTR) tdesc = tdesc->u.lptdesc; diff -urN wine-20050211/dlls/oleaut32/typelib2.c wine-20050310/dlls/oleaut32/typelib2.c --- wine-20050211/dlls/oleaut32/typelib2.c 2005-01-10 13:31:06.000000000 +0100 +++ wine-20050310/dlls/oleaut32/typelib2.c 2005-02-25 15:07:57.000000000 +0100 @@ -140,7 +140,7 @@ int guid; LCID lcid; int version; - char filename[0]; /* preceeded by two bytes of encoded (length << 2) + flags in the low two bits. */ + char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */ } MSFT_ImpFile; typedef struct tagICreateTypeLib2Impl @@ -2055,7 +2055,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData( ICreateTypeInfo2* iface, /* [I] The typeinfo in which to set the custom data. */ UINT indexFunc, /* [I] The index of the function on which the parameter resides. */ - UINT indexParam, /* [I] The index of the paramter on which to set the custom data. */ + UINT indexParam, /* [I] The index of the parameter on which to set the custom data. */ REFGUID guid, /* [I] The GUID used as a key to retrieve the custom data. */ VARIANT* pVarVal) /* [I] The custom data. */ { diff -urN wine-20050211/dlls/oleaut32/usrmarshal.c wine-20050310/dlls/oleaut32/usrmarshal.c --- wine-20050211/dlls/oleaut32/usrmarshal.c 2004-10-07 05:06:49.000000000 +0200 +++ wine-20050310/dlls/oleaut32/usrmarshal.c 2005-02-22 15:54:01.000000000 +0100 @@ -190,7 +190,7 @@ ULONG size; HRESULT hr; - if (V_VT(pvar) & VT_ARRAY) { + if (V_ISARRAY(pvar)) { FIXME("wire-size safearray\n"); return 0; } @@ -527,7 +527,7 @@ /* count by-ref args */ for (cVarRef=0,u=0; ucArgs; u++) { VARIANTARG* arg = &pDispParams->rgvarg[u]; - if (V_VT(arg) & VT_BYREF) { + if (V_ISBYREF(arg)) { cVarRef++; } } @@ -537,7 +537,7 @@ /* make list of by-ref args */ for (cVarRef=0,u=0; ucArgs; u++) { VARIANTARG* arg = &pDispParams->rgvarg[u]; - if (V_VT(arg) & VT_BYREF) { + if (V_ISBYREF(arg)) { rgVarRefIdx[cVarRef] = u; VariantInit(&rgVarRef[cVarRef]); cVarRef++; diff -urN wine-20050211/dlls/oleaut32/varformat.c wine-20050310/dlls/oleaut32/varformat.c --- wine-20050211/dlls/oleaut32/varformat.c 2005-01-09 17:52:51.000000000 +0100 +++ wine-20050310/dlls/oleaut32/varformat.c 2005-03-02 14:53:51.000000000 +0100 @@ -94,7 +94,7 @@ * characters. Literal characters are copied unmodified to the formatted * output at the position they occupy in the format string. Any character * that is not recognised as a token is treated as a literal. A literal can - * also be specified by preceeding it with a backslash character + * also be specified by preceding it with a backslash character * (e.g. "\L\i\t\e\r\a\l") or enclosing it in double quotes. * * A user-defined format can have up to 4 sections, depending on the type of @@ -885,7 +885,7 @@ TRACE("h\n"); } fmt_state &= ~FMT_STATE_OPEN_COPY; - /* Note that now we have seen an hours token, the next occurence of + /* Note that now we have seen an hours token, the next occurrence of * 'mm' indicates minutes, not months. */ fmt_state |= FMT_STATE_SEEN_HOURS; diff -urN wine-20050211/dlls/oleaut32/variant.c wine-20050310/dlls/oleaut32/variant.c --- wine-20050211/dlls/oleaut32/variant.c 2005-01-25 19:57:43.000000000 +0100 +++ wine-20050310/dlls/oleaut32/variant.c 2005-02-22 15:54:01.000000000 +0100 @@ -984,7 +984,7 @@ { VARIANTARG vTmp, vSrcDeref; - if(V_VT(pvargSrc)&VT_BYREF && !V_BYREF(pvargSrc)) + if(V_ISBYREF(pvargSrc) && !V_BYREF(pvargSrc)) res = DISP_E_TYPEMISMATCH; else { @@ -2531,7 +2531,7 @@ } xmask = (1<<(V_VT(left)&VT_TYPEMASK))|(1<<(V_VT(right)&VT_TYPEMASK)); - if (xmask & (1< V_R8(&rv)) return VARCMP_GT; return E_FAIL; /* can't get here */ } - if (xmask & (1< V_UNION(right,date)) { + } else if (V_DATE(left) > V_DATE(right)) { return VARCMP_GT; } } @@ -2665,29 +2665,29 @@ lOk = TRUE; switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_UNION(left,cVal); resT=VT_I4; break; - case VT_I2 : lVal = V_UNION(left,iVal); resT=VT_I2; break; - case VT_I4 : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_INT : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_UI1 : lVal = V_UNION(left,bVal); resT=VT_I4; break; - case VT_UI2 : lVal = V_UNION(left,uiVal); resT=VT_I4; break; - case VT_UI4 : lVal = V_UNION(left,ulVal); resT=VT_I4; break; - case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break; - case VT_BOOL : rVal = V_UNION(left,boolVal); resT=VT_I4; break; + case VT_I1 : lVal = V_I1(left); resT=VT_I4; break; + case VT_I2 : lVal = V_I2(left); resT=VT_I2; break; + case VT_I4 : + case VT_INT : lVal = V_I4(left); resT=VT_I4; break; + case VT_UI1 : lVal = V_UI1(left); resT=VT_I4; break; + case VT_UI2 : lVal = V_UI2(left); resT=VT_I4; break; + case VT_UI4 : + case VT_UINT : lVal = V_UI4(left); resT=VT_I4; break; + case VT_BOOL : rVal = V_BOOL(left); resT=VT_I4; break; default: lOk = FALSE; } rOk = TRUE; switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_UNION(right,cVal); resT=VT_I4; break; - case VT_I2 : rVal = V_UNION(right,iVal); resT=max(VT_I2, resT); break; - case VT_I4 : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_INT : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_UI1 : rVal = V_UNION(right,bVal); resT=VT_I4; break; - case VT_UI2 : rVal = V_UNION(right,uiVal); resT=VT_I4; break; - case VT_UI4 : rVal = V_UNION(right,ulVal); resT=VT_I4; break; - case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break; - case VT_BOOL : rVal = V_UNION(right,boolVal); resT=VT_I4; break; + case VT_I1 : rVal = V_I1(right); resT=VT_I4; break; + case VT_I2 : rVal = V_I2(right); resT=max(VT_I2, resT); break; + case VT_I4 : + case VT_INT : rVal = V_I4(right); resT=VT_I4; break; + case VT_UI1 : rVal = V_UI1(right); resT=VT_I4; break; + case VT_UI2 : rVal = V_UI2(right); resT=VT_I4; break; + case VT_UI4 : + case VT_UINT : rVal = V_UI4(right); resT=VT_I4; break; + case VT_BOOL : rVal = V_BOOL(right); resT=VT_I4; break; default: rOk = FALSE; } @@ -2695,11 +2695,11 @@ res = (lVal & rVal); V_VT(result) = resT; switch (resT) { - case VT_I2 : V_UNION(result,iVal) = res; break; - case VT_I4 : V_UNION(result,lVal) = res; break; + case VT_I2 : V_I2(result) = res; break; + case VT_I4 : V_I4(result) = res; break; default: FIXME("Unexpected result variant type %x\n", resT); - V_UNION(result,lVal) = res; + V_I4(result) = res; } rc = S_OK; @@ -2747,32 +2747,32 @@ lOk = TRUE; switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_UNION(left,cVal); break; - case VT_I2 : lVal = V_UNION(left,iVal); break; - case VT_I4 : lVal = V_UNION(left,lVal); break; - case VT_INT : lVal = V_UNION(left,lVal); break; - case VT_UI1 : lVal = V_UNION(left,bVal); break; - case VT_UI2 : lVal = V_UNION(left,uiVal); break; - case VT_UI4 : lVal = V_UNION(left,ulVal); break; - case VT_UINT : lVal = V_UNION(left,ulVal); break; - case VT_R4 : lVal = V_UNION(left,fltVal); break; - case VT_R8 : lVal = V_UNION(left,dblVal); break; + case VT_I1 : lVal = V_I1(left); break; + case VT_I2 : lVal = V_I2(left); break; + case VT_I4 : + case VT_INT : lVal = V_I4(left); break; + case VT_UI1 : lVal = V_UI1(left); break; + case VT_UI2 : lVal = V_UI2(left); break; + case VT_UI4 : + case VT_UINT : lVal = V_UI4(left); break; + case VT_R4 : lVal = V_R4(left); break; + case VT_R8 : lVal = V_R8(left); break; case VT_NULL : lVal = 0.0; break; default: lOk = FALSE; } rOk = TRUE; switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_UNION(right,cVal); break; - case VT_I2 : rVal = V_UNION(right,iVal); break; - case VT_I4 : rVal = V_UNION(right,lVal); break; - case VT_INT : rVal = V_UNION(right,lVal); break; - case VT_UI1 : rVal = V_UNION(right,bVal); break; - case VT_UI2 : rVal = V_UNION(right,uiVal); break; - case VT_UI4 : rVal = V_UNION(right,ulVal); break; - case VT_UINT : rVal = V_UNION(right,ulVal); break; - case VT_R4 : rVal = V_UNION(right,fltVal);break; - case VT_R8 : rVal = V_UNION(right,dblVal);break; + case VT_I1 : rVal = V_I1(right); break; + case VT_I2 : rVal = V_I2(right); break; + case VT_I4 : + case VT_INT : rVal = V_I4(right); break; + case VT_UI1 : rVal = V_UI1(right); break; + case VT_UI2 : rVal = V_UI2(right); break; + case VT_UI4 : + case VT_UINT : rVal = V_UI4(right); break; + case VT_R4 : rVal = V_R4(right);break; + case VT_R8 : rVal = V_R8(right);break; case VT_NULL : rVal = 0.0; break; default: rOk = FALSE; } @@ -2780,7 +2780,7 @@ if (lOk && rOk) { res = (lVal + rVal); V_VT(result) = VT_R8; - V_UNION(result,dblVal) = res; + V_R8(result) = res; rc = S_OK; } else { FIXME("Unhandled type pair %d / %d in double addition.\n", @@ -2801,30 +2801,30 @@ lOk = TRUE; switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_UNION(left,cVal); break; - case VT_I2 : lVal = V_UNION(left,iVal); break; - case VT_I4 : lVal = V_UNION(left,lVal); break; - case VT_INT : lVal = V_UNION(left,lVal); break; - case VT_UI1 : lVal = V_UNION(left,bVal); break; - case VT_UI2 : lVal = V_UNION(left,uiVal); break; - case VT_UI4 : lVal = V_UNION(left,ulVal); break; - case VT_UINT : lVal = V_UNION(left,ulVal); break; - case VT_R4 : lVal = V_UNION(left,fltVal); break; + case VT_I1 : lVal = V_I1(left); break; + case VT_I2 : lVal = V_I2(left); break; + case VT_I4 : + case VT_INT : lVal = V_I4(left); break; + case VT_UI1 : lVal = V_UI1(left); break; + case VT_UI2 : lVal = V_UI2(left); break; + case VT_UI4 : + case VT_UINT : lVal = V_UI4(left); break; + case VT_R4 : lVal = V_R4(left); break; case VT_NULL : lVal = 0.0; break; default: lOk = FALSE; } rOk = TRUE; switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_UNION(right,cVal); break; - case VT_I2 : rVal = V_UNION(right,iVal); break; - case VT_I4 : rVal = V_UNION(right,lVal); break; - case VT_INT : rVal = V_UNION(right,lVal); break; - case VT_UI1 : rVal = V_UNION(right,bVal); break; - case VT_UI2 : rVal = V_UNION(right,uiVal); break; - case VT_UI4 : rVal = V_UNION(right,ulVal); break; - case VT_UINT : rVal = V_UNION(right,ulVal); break; - case VT_R4 : rVal = V_UNION(right,fltVal);break; + case VT_I1 : rVal = V_I1(right); break; + case VT_I2 : rVal = V_I2(right); break; + case VT_I4 : + case VT_INT : rVal = V_I4(right); break; + case VT_UI1 : rVal = V_UI1(right); break; + case VT_UI2 : rVal = V_UI2(right); break; + case VT_UI4 : + case VT_UINT : rVal = V_UI4(right); break; + case VT_R4 : rVal = V_R4(right);break; case VT_NULL : rVal = 0.0; break; default: rOk = FALSE; } @@ -2832,7 +2832,7 @@ if (lOk && rOk) { res = (lVal + rVal); V_VT(result) = VT_R4; - V_UNION(result,fltVal) = res; + V_R4(result) = res; rc = S_OK; } else { FIXME("Unhandled type pair %d / %d in float addition.\n", @@ -2861,28 +2861,28 @@ lOk = TRUE; switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_UNION(left,cVal); resT=VT_I4; break; - case VT_I2 : lVal = V_UNION(left,iVal); resT=VT_I2; break; - case VT_I4 : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_INT : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_UI1 : lVal = V_UNION(left,bVal); resT=VT_I4; break; - case VT_UI2 : lVal = V_UNION(left,uiVal); resT=VT_I4; break; - case VT_UI4 : lVal = V_UNION(left,ulVal); resT=VT_I4; break; - case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break; + case VT_I1 : lVal = V_I1(left); resT=VT_I4; break; + case VT_I2 : lVal = V_I2(left); resT=VT_I2; break; + case VT_I4 : + case VT_INT : lVal = V_I4(left); resT=VT_I4; break; + case VT_UI1 : lVal = V_UI1(left); resT=VT_I4; break; + case VT_UI2 : lVal = V_UI2(left); resT=VT_I4; break; + case VT_UI4 : + case VT_UINT : lVal = V_UI4(left); resT=VT_I4; break; case VT_NULL : lVal = 0; resT = VT_I4; break; default: lOk = FALSE; } rOk = TRUE; switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_UNION(right,cVal); resT=VT_I4; break; - case VT_I2 : rVal = V_UNION(right,iVal); resT=max(VT_I2, resT); break; - case VT_I4 : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_INT : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_UI1 : rVal = V_UNION(right,bVal); resT=VT_I4; break; - case VT_UI2 : rVal = V_UNION(right,uiVal); resT=VT_I4; break; - case VT_UI4 : rVal = V_UNION(right,ulVal); resT=VT_I4; break; - case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break; + case VT_I1 : rVal = V_I1(right); resT=VT_I4; break; + case VT_I2 : rVal = V_I2(right); resT=max(VT_I2, resT); break; + case VT_I4 : + case VT_INT : rVal = V_I4(right); resT=VT_I4; break; + case VT_UI1 : rVal = V_UI1(right); resT=VT_I4; break; + case VT_UI2 : rVal = V_UI2(right); resT=VT_I4; break; + case VT_UI4 : + case VT_UINT : rVal = V_UI4(right); resT=VT_I4; break; case VT_NULL : rVal = 0; resT=VT_I4; break; default: rOk = FALSE; } @@ -2891,11 +2891,11 @@ res = (lVal + rVal); V_VT(result) = resT; switch (resT) { - case VT_I2 : V_UNION(result,iVal) = res; break; - case VT_I4 : V_UNION(result,lVal) = res; break; + case VT_I2 : V_I2(result) = res; break; + case VT_I4 : V_I4(result) = res; break; default: FIXME("Unexpected result variant type %x\n", resT); - V_UNION(result,lVal) = res; + V_I4(result) = res; } rc = S_OK; @@ -2927,11 +2927,11 @@ lvt = V_VT(left)&VT_TYPEMASK; rvt = V_VT(right)&VT_TYPEMASK; found = FALSE;resvt=VT_VOID; - if (((1<hdc = hdc; + object->display = display; + object->width = iWidth; + object->height = iHeight; + object->pixelFormat = iPixelFormat; + + nAttribs = ConvertAttribWGLtoGLX(piAttribList, attribs); + PUSH1(attribs, None); + + cfgs = glXChooseFBConfig(display, DefaultScreen(display), attribs, &nCfgs); + if (nCfgs < iPixelFormat) return NULL; /* unespected error */ + + --nAttribs; /** append more to attribs now we have fbConfig */ + PUSH2(attribs, GLX_PBUFFER_WIDTH, iWidth); + PUSH2(attribs, GLX_PBUFFER_HEIGHT, iHeight); + PUSH1(attribs, None); + + object->drawable = glXCreatePbuffer(display, cfgs[iPixelFormat], attribs); + TRACE("drawable as %p\n", (void*) object->drawable); + + TRACE("->(%p)\n", object); + return (HPBUFFERARB) object; +} + +HDC WINAPI wglGetPbufferDCARB(HPBUFFERARB hPbuffer) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + HDC hDC; + hDC = CreateCompatibleDC(object->hdc); + set_drawable(hDC, object->drawable); /* works ?? */ + TRACE("(%p)\n", hPbuffer); + return hDC; +} + +int WINAPI wglReleasePbufferDCARB(HPBUFFERARB hPbuffer, HDC hdc) +{ + TRACE("(%p, %p)\n", hPbuffer, hdc); + DeleteDC(hdc); + return 0; +} + +GLboolean WINAPI wglDestroyPbufferARB(HPBUFFERARB hPbuffer) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + TRACE("(%p)\n", hPbuffer); + + glXDestroyPbuffer(object->display, object->drawable); + HeapFree(GetProcessHeap(), 0, object); + + return GL_TRUE; +} + +GLboolean WINAPI wglQueryPbufferARB(HPBUFFERARB hPbuffer, int iAttribute, int *piValue) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + TRACE("(%p, %d, %p)\n", hPbuffer, iAttribute, piValue); + + /*glXQueryDrawable(object->display, object->drawable);*/ + + switch (iAttribute) { + case WGL_PBUFFER_WIDTH_ARB: + glXQueryDrawable(object->display, object->drawable, GLX_WIDTH, piValue); + break; + case WGL_PBUFFER_HEIGHT_ARB: + glXQueryDrawable(object->display, object->drawable, GLX_HEIGHT, piValue); + break; + + default: + break; + } + + return GL_TRUE; +} + +GLboolean WINAPI wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + TRACE("(%p, %d)\n", hPbuffer, iBuffer); + return p_glXBindTexImageARB(object->display, object->drawable, iBuffer); +} + +GLboolean WINAPI wglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + TRACE("(%p, %d)\n", hPbuffer, iBuffer); + return p_glXReleaseTexImageARB(object->display, object->drawable, iBuffer); +} + +GLboolean WINAPI wglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList) +{ + Wine_GLPBuffer* object = (Wine_GLPBuffer*) hPbuffer; + WARN("(%p, %p): alpha-testing, report any problem\n", hPbuffer, piAttribList); + return p_glXDrawableAttribARB(object->display, object->drawable, piAttribList); +} + static const struct { const char *name; - BOOL (*query_function)(const char *gl_version, const char *gl_extensions, const char *glx_extensions, + BOOL (*query_function)(glXGetProcAddressARB_t proc, const char *gl_version, const char *gl_extensions, + const char *glx_version, const char *glx_extensions, const char *server_glx_extensions, const char *client_glx_extensions); } extension_list[] = { - { "WGL_ARB_pbuffer", query_function_pbuffers } + { "WGL_ARB_multisample", query_function_multisample }, + { "WGL_ARB_pbuffer", query_function_pbuffer }, + { "WGL_ARB_pixel_format" , query_function_pixel_format }, + { "WGL_ARB_render_texture", query_function_render_texture } }; /* Used to initialize the WGL extension string at DLL loading */ -void wgl_ext_initialize_extensions(Display *display, int screen) +void wgl_ext_initialize_extensions(Display *display, int screen, glXGetProcAddressARB_t proc) { int size = strlen(WGL_extensions_base); const char *glx_extensions = glXQueryExtensionsString(display, screen); @@ -103,6 +446,7 @@ const char *client_glx_extensions = glXGetClientString(display, GLX_EXTENSIONS); const char *gl_extensions = (const char *) glGetString(GL_EXTENSIONS); const char *gl_version = (const char *) glGetString(GL_VERSION); + const char *glx_version = glXGetClientString(display, GLX_VERSION); int i; TRACE("GL version : %s.\n", debugstr_a(gl_version)); @@ -112,7 +456,8 @@ TRACE("Client GLX exts : %s.\n", debugstr_a(client_glx_extensions)); for (i = 0; i < (sizeof(extension_list) / sizeof(extension_list[0])); i++) { - if (extension_list[i].query_function(gl_version, gl_extensions, glx_extensions, + if (extension_list[i].query_function(proc, gl_version, gl_extensions, + glx_version, glx_extensions, server_glx_extensions, client_glx_extensions)) { size += strlen(extension_list[i].name) + 1; } @@ -125,7 +470,8 @@ } else { strcpy(WGL_extensions, WGL_extensions_base); for (i = 0; i < (sizeof(extension_list) / sizeof(extension_list[0])); i++) { - if (extension_list[i].query_function(gl_version, gl_extensions, glx_extensions, + if (extension_list[i].query_function(proc, gl_version, gl_extensions, + glx_version, glx_extensions, server_glx_extensions, client_glx_extensions)) { strcat(WGL_extensions, " "); strcat(WGL_extensions, extension_list[i].name); @@ -143,11 +489,26 @@ } } -/* Putting this at the end to prevent having to write the prototypes :-) */ +/* + * Putting this at the end to prevent having to write the prototypes :-) + * + * @WARNING: this list must be ordered by name + */ WGL_extension wgl_extension_registry[] = { + { "wglBindTexImageARB", (void *) wglBindTexImageARB, NULL, NULL}, + { "wglChoosePixelFormatARB", (void *) wglChoosePixelFormatARB, NULL, NULL}, + { "wglCreatePbufferARB", (void *) wglCreatePbufferARB, NULL, NULL}, + { "wglDestroyPbufferARB", (void *) wglDestroyPbufferARB, NULL, NULL}, { "wglGetExtensionsStringARB", (void *) wglGetExtensionsStringARB, NULL, NULL}, { "wglGetExtensionsStringEXT", (void *) wglGetExtensionsStringEXT, NULL, NULL}, - { "wglGetSwapIntervalEXT", (void *) wglSwapIntervalEXT, NULL, NULL}, + { "wglGetPbufferDCARB", (void *) wglGetPbufferDCARB, NULL, NULL}, + { "wglGetPixelFormatAttribfvARB", (void *) wglGetPixelFormatAttribfvARB, NULL, NULL}, + { "wglGetPixelFormatAttribivARB", (void *) wglGetPixelFormatAttribivARB, NULL, NULL}, + { "wglGetSwapIntervalEXT", (void *) wglGetSwapIntervalEXT, NULL, NULL}, + { "wglQueryPbufferARB", (void *) wglQueryPbufferARB, NULL, NULL}, + { "wglReleasePbufferDCARB", (void *) wglReleasePbufferDCARB, NULL, NULL}, + { "wglReleaseTexImageARB", (void *) wglReleaseTexImageARB, NULL, NULL}, + { "wglSetPbufferAttribARB", (void *) wglSetPbufferAttribARB, NULL, NULL}, { "wglSwapIntervalEXT", (void *) wglSwapIntervalEXT, NULL, NULL} }; int wgl_extension_registry_size = sizeof(wgl_extension_registry) / sizeof(wgl_extension_registry[0]); diff -urN wine-20050211/dlls/opengl32/wgl_ext.h wine-20050310/dlls/opengl32/wgl_ext.h --- wine-20050211/dlls/opengl32/wgl_ext.h 2004-02-07 02:29:33.000000000 +0100 +++ wine-20050310/dlls/opengl32/wgl_ext.h 2005-03-10 12:13:33.000000000 +0100 @@ -22,8 +22,10 @@ #include "opengl_ext.h" +typedef void* (*glXGetProcAddressARB_t)(const GLubyte *); + /* Used to initialize the WGL extension string at DLL loading */ -void wgl_ext_initialize_extensions(Display *display, int screen); +void wgl_ext_initialize_extensions(Display *display, int screen, glXGetProcAddressARB_t proc); void wgl_ext_finalize_extensions(void); typedef struct { diff -urN wine-20050211/dlls/quartz/acmwrapper.c wine-20050310/dlls/quartz/acmwrapper.c --- wine-20050211/dlls/quartz/acmwrapper.c 2005-02-10 20:19:35.000000000 +0100 +++ wine-20050310/dlls/quartz/acmwrapper.c 2005-02-22 15:50:16.000000000 +0100 @@ -59,7 +59,7 @@ BOOL reinit_codec; /* FIXME: Should use sync points instead */ } ACMWrapperImpl; -static DWORD ACMWrapper_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) +static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) { ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; AM_MEDIA_TYPE amt; @@ -187,7 +187,7 @@ This->pWfOut = (WAVEFORMATEX*)outpmt->pbFormat; This->pWfOut->wFormatTag = WAVE_FORMAT_PCM; This->pWfOut->wBitsPerSample = 16; - This->pWfOut->nBlockAlign = 1; + This->pWfOut->nBlockAlign = 4; This->pWfOut->cbSize = 0; This->pWfOut->nAvgBytesPerSec = This->pWfOut->nChannels * This->pWfOut->nSamplesPerSec * (This->pWfOut->wBitsPerSample/8); @@ -202,6 +202,9 @@ } TRACE("input buffer size %ld\n", This->max_size); + + /* Update buffer size of media samples in output */ + ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = OUTPUT_BUFFER_SIZE; TRACE("Connection accepted\n"); return S_OK; @@ -230,6 +233,14 @@ return S_OK; } +TransformFuncsTable ACMWrapper_FuncsTable = { + NULL, + ACMWrapper_ProcessSampleData, + NULL, + ACMWrapper_ConnectInput, + ACMWrapper_Cleanup +}; + HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) { HRESULT hr; @@ -248,7 +259,7 @@ This->has = 0; This->reinit_codec = TRUE; - hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, ACMWrapper_SendSampleData, ACMWrapper_ConnectInput, ACMWrapper_Cleanup); + hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable); if (FAILED(hr)) return hr; diff -urN wine-20050211/dlls/quartz/avidec.c wine-20050310/dlls/quartz/avidec.c --- wine-20050211/dlls/quartz/avidec.c 2005-02-01 15:22:00.000000000 +0100 +++ wine-20050310/dlls/quartz/avidec.c 2005-02-21 21:37:45.000000000 +0100 @@ -46,6 +46,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); +static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter); + typedef struct AVIDecImpl { TransformFilterImpl tf; @@ -54,7 +56,23 @@ BITMAPINFOHEADER* pBihOut; } AVIDecImpl; -static DWORD AVIDec_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) +static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) +{ + AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + DWORD result; + + TRACE("(%p)->()\n", This); + + result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut); + if (result != ICERR_OK) + { + ERR("Cannot start processing (%ld)\n", result); + return E_FAIL; + } + return S_OK; +} + +static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) { AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; VIDEOINFOHEADER* format; @@ -115,25 +133,45 @@ return hr; } +static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) +{ + AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + DWORD result; + + TRACE("(%p)->()\n", This); + + result = ICDecompressEnd(This->hvid); + if (result != ICERR_OK) + { + ERR("Cannot stop processing (%ld)\n", result); + return E_FAIL; + } + return S_OK; +} + static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt) { AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + HRESULT hr = S_FALSE; TRACE("(%p)->(%p)\n", This, pmt); + AVIDec_Cleanup(pTransformFilter); + if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) && (!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */ (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))) { - HIC drv; VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat; - drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS); - if (drv) + This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS); + if (This->hvid) { AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent; const CLSID* outsubtype; DWORD bih_size; + DWORD output_depth = format->bmiHeader.biBitCount; + DWORD result; switch(format->bmiHeader.biBitCount) { @@ -142,41 +180,46 @@ case 16: outsubtype = &MEDIASUBTYPE_RGB565; break; case 8: outsubtype = &MEDIASUBTYPE_RGB8; break; default: - FIXME("Depth %d not supported\n", format->bmiHeader.biBitCount); - ICClose(drv); - return S_FALSE; + TRACE("Non standard input depth %d, forced ouptut depth to 32\n", format->bmiHeader.biBitCount); + outsubtype = &MEDIASUBTYPE_RGB32; + output_depth = 32; + break; } - CopyMediaType(outpmt, pmt); - outpmt->subtype = *outsubtype; - This->hvid = drv; /* Copy bitmap header from media type to 1 for input and 1 for output */ - if (This->pBihIn) { - CoTaskMemFree(This->pBihIn); - CoTaskMemFree(This->pBihOut); - } bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4; This->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size); if (!This->pBihIn) { - ICClose(drv); - return E_OUTOFMEMORY; + hr = E_OUTOFMEMORY; + goto failed; } This->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size); if (!This->pBihOut) { - CoTaskMemFree(This->pBihIn); - This->pBihIn = NULL; - ICClose(drv); - return E_OUTOFMEMORY; + hr = E_OUTOFMEMORY; + goto failed; } memcpy(This->pBihIn, &format->bmiHeader, bih_size); memcpy(This->pBihOut, &format->bmiHeader, bih_size); /* Update output format as non compressed bitmap */ This->pBihOut->biCompression = 0; + This->pBihOut->biBitCount = output_depth; This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8; + result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut); + if (result != ICERR_OK) + { + TRACE("Unable to found a suitable output format (%ld)\n", result); + goto failed; + } + + /* Update output media type */ + CopyMediaType(outpmt, pmt); + outpmt->subtype = *outsubtype; + memcpy(&(((VIDEOINFOHEADER*)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); + /* Update buffer size of media samples in output */ ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage; @@ -186,8 +229,11 @@ TRACE("Unable to find a suitable VFW decompressor\n"); } +failed: + AVIDec_Cleanup(pTransformFilter); + TRACE("Connection refused\n"); - return S_FALSE; + return hr; } static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter) @@ -198,18 +244,26 @@ if (This->hvid) ICClose(This->hvid); - - if (This->pBihIn) { + if (This->pBihIn) CoTaskMemFree(This->pBihIn); + if (This->pBihOut) CoTaskMemFree(This->pBihOut); - } This->hvid = NULL; This->pBihIn = NULL; + This->pBihOut = NULL; return S_OK; } +TransformFuncsTable AVIDec_FuncsTable = { + AVIDec_ProcessBegin, + AVIDec_ProcessSampleData, + AVIDec_ProcessEnd, + AVIDec_ConnectInput, + AVIDec_Cleanup +}; + HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) { HRESULT hr; @@ -227,8 +281,9 @@ This->hvid = NULL; This->pBihIn = NULL; + This->pBihOut = NULL; - hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, AVIDec_SendSampleData, AVIDec_ConnectInput, AVIDec_Cleanup); + hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, &AVIDec_FuncsTable); if (FAILED(hr)) return hr; diff -urN wine-20050211/dlls/quartz/avisplit.c wine-20050310/dlls/quartz/avisplit.c --- wine-20050211/dlls/quartz/avisplit.c 2005-02-08 14:43:59.000000000 +0100 +++ wine-20050310/dlls/quartz/avisplit.c 2005-03-02 11:12:12.000000000 +0100 @@ -55,11 +55,14 @@ AVIMAINHEADER AviHeader; } AVISplitterImpl; -static HRESULT AVISplitter_NextChunk(LONGLONG * pllCurrentChunkOffset, RIFFCHUNK * pCurrentChunk, const REFERENCE_TIME * tStart, const REFERENCE_TIME * tStop, const BYTE * pbSrcStream) +static HRESULT AVISplitter_NextChunk(LONGLONG * pllCurrentChunkOffset, RIFFCHUNK * pCurrentChunk, const REFERENCE_TIME * tStart, const REFERENCE_TIME * tStop, const BYTE * pbSrcStream, int inner) { - *pllCurrentChunkOffset += MEDIATIME_FROM_BYTES(sizeof(RIFFCHUNK) + RIFFROUND(pCurrentChunk->cb)); - - if (*pllCurrentChunkOffset > *tStop) + if (inner) + *pllCurrentChunkOffset += MEDIATIME_FROM_BYTES(sizeof(RIFFLIST)); + else + *pllCurrentChunkOffset += MEDIATIME_FROM_BYTES(sizeof(RIFFCHUNK) + RIFFROUND(pCurrentChunk->cb)); + + if (*pllCurrentChunkOffset >= *tStop) return S_FALSE; /* no more data - we couldn't even get the next chunk header! */ else if (*pllCurrentChunkOffset + MEDIATIME_FROM_BYTES(sizeof(RIFFCHUNK)) >= *tStop) { @@ -88,7 +91,7 @@ cbSrcStream = IMediaSample_GetActualDataLength(pSample); /* trace removed for performance reasons */ -/* TRACE("(%p)\n", pSample); */ + /* TRACE("(%p)\n", pSample); */ assert(BYTES_FROM_MEDIATIME(tStop - tStart) == cbSrcStream); @@ -104,7 +107,8 @@ if (offset >= (DWORD)cbSrcStream) { FIXME("large offset\n"); - return S_OK; + hr = S_OK; + goto skip; } memcpy(&This->CurrentChunk, pbSrcStream + offset, sizeof(RIFFCHUNK)); @@ -132,7 +136,7 @@ case ckidJUNK: case aviFCC('i','d','x','1'): /* Index is not handled */ /* silently ignore */ - if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream)) + if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, FALSE)) bMoreData = FALSE; continue; case ckidLIST: @@ -141,12 +145,16 @@ { /* FIXME: We only advanced to the first chunk inside the list without keeping track that we are in it. * This is not clean and the parser should be improved for that but it is enough for most AVI files. */ - This->CurrentChunkOffset = MEDIATIME_FROM_BYTES(BYTES_FROM_MEDIATIME(This->CurrentChunkOffset) + sizeof(RIFFLIST)); + if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, TRUE)) + { + bMoreData = FALSE; + continue; + } This->CurrentChunk = *(RIFFCHUNK*) (pbSrcStream + BYTES_FROM_MEDIATIME(This->CurrentChunkOffset-tStart)); offset_src = (long)BYTES_FROM_MEDIATIME(This->CurrentChunkOffset - tStart) + sizeof(RIFFCHUNK); break; } - else if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream)) + else if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, FALSE)) bMoreData = FALSE; continue; default: @@ -168,7 +176,7 @@ break; default: FIXME("Skipping unknown chunk type: %s at file offset 0x%lx\n", debugstr_an((LPSTR)&This->CurrentChunk.fcc, 4), (DWORD)BYTES_FROM_MEDIATIME(This->CurrentChunkOffset)); - if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream)) + if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, FALSE)) bMoreData = FALSE; continue; } @@ -180,7 +188,8 @@ if (streamId > This->Parser.cStreams) { ERR("Corrupted AVI file (contains stream id %d, but supposed to only have %ld streams)\n", streamId, This->Parser.cStreams); - return E_FAIL; + hr = E_FAIL; + break; } pOutputPin = (Parser_OutputPin *)This->Parser.ppPins[streamId + 1]; @@ -200,7 +209,7 @@ { TRACE("Skipping sending sample for stream %02d due to error (%lx)\n", streamId, hr); This->pCurrentSample = NULL; - if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream)) + if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, FALSE)) bMoreData = FALSE; continue; } @@ -263,7 +272,7 @@ This->pCurrentSample = NULL; - if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream)) + if (S_FALSE == AVISplitter_NextChunk(&This->CurrentChunkOffset, &This->CurrentChunk, &tStart, &tStop, pbSrcStream, FALSE)) bMoreData = FALSE; } else @@ -276,6 +285,38 @@ bMoreData = FALSE; } } + +skip: + if (tStop >= This->EndOfFile) + { + int i; + + TRACE("End of file reached\n"); + + for (i = 0; i < This->Parser.cStreams; i++) + { + IPin* ppin; + HRESULT hr; + + TRACE("Send End Of Stream to output pin %d\n", i); + + hr = IPin_ConnectedTo(This->Parser.ppPins[i+1], &ppin); + if (SUCCEEDED(hr)) + { + hr = IPin_EndOfStream(ppin); + IPin_Release(ppin); + } + if (FAILED(hr)) + { + ERR("%lx\n", hr); + break; + } + } + + /* Force the pullpin thread to stop */ + hr = S_FALSE; + } + return hr; } diff -urN wine-20050211/dlls/quartz/dsoundrender.c wine-20050310/dlls/quartz/dsoundrender.c --- wine-20050211/dlls/quartz/dsoundrender.c 2005-01-06 20:36:47.000000000 +0100 +++ wine-20050310/dlls/quartz/dsoundrender.c 2005-03-02 11:12:12.000000000 +0100 @@ -58,7 +58,6 @@ REFERENCE_TIME rtStreamStart; IReferenceClock * pClock; FILTER_INFO filterInfo; - IMediaEventSink * pEventSink; InputPin * pInputPin; IPin ** ppPins; @@ -550,7 +549,6 @@ static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) { - HRESULT hr; DSoundRenderImpl *This = (DSoundRenderImpl *)iface; TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); @@ -562,12 +560,10 @@ else *This->filterInfo.achName = '\0'; This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - - hr = IFilterGraph_QueryInterface(pGraph, &IID_IMediaEventSink, (LPVOID*)&This->pEventSink); } LeaveCriticalSection(&This->csFilter); - return hr; + return S_OK; } static HRESULT WINAPI DSoundRender_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) @@ -598,12 +594,21 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) { - /* FIXME: critical section */ InputPin* This = (InputPin*)iface; - + IMediaEventSink* pEventSink; + HRESULT hr; + TRACE("(%p/%p)->()\n", This, iface); - - return IMediaEventSink_Notify(((DSoundRenderImpl*)This->pin.pinInfo.pFilter)->pEventSink, EC_COMPLETE, S_OK, 0); + + hr = IFilterGraph_QueryInterface(((DSoundRenderImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); + if (SUCCEEDED(hr)) + { + /* FIXME: We should wait that all audio data has been played */ + hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); + IMediaEventSink_Release(pEventSink); + } + + return hr; } static const IPinVtbl DSoundRender_InputPin_Vtbl = diff -urN wine-20050211/dlls/quartz/filtergraph.c wine-20050310/dlls/quartz/filtergraph.c --- wine-20050211/dlls/quartz/filtergraph.c 2005-01-09 19:24:41.000000000 +0100 +++ wine-20050310/dlls/quartz/filtergraph.c 2005-03-02 11:12:12.000000000 +0100 @@ -2995,30 +2995,35 @@ if ((EventCode == EC_COMPLETE) && This->HandleEcComplete) { - if (++This->EcCompleteCount == This->nRenderers) - { - evt.lEventCode = EC_COMPLETE; - evt.lParam1 = S_OK; - evt.lParam2 = 0; - EventsQueue_PutEvent(&This->evqueue, &evt); - if (!This->notif.disabled && This->notif.hWnd) - PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); - This->CompletionStatus = EC_COMPLETE; - SetEvent(This->hEventCompletion); - } + TRACE("Process EC_COMPLETE notification\n"); + if (++This->EcCompleteCount == This->nRenderers) + { + evt.lEventCode = EC_COMPLETE; + evt.lParam1 = S_OK; + evt.lParam2 = 0; + TRACE("Send EC_COMPLETE to app\n"); + EventsQueue_PutEvent(&This->evqueue, &evt); + if (!This->notif.disabled && This->notif.hWnd) + { + TRACE("Send Window message\n"); + PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); + } + This->CompletionStatus = EC_COMPLETE; + SetEvent(This->hEventCompletion); + } } else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint) { - /* FIXME: Not handled yet */ + /* FIXME: Not handled yet */ } else { - evt.lEventCode = EventCode; - evt.lParam1 = EventParam1; - evt.lParam2 = EventParam2; - EventsQueue_PutEvent(&This->evqueue, &evt); - if (!This->notif.disabled && This->notif.hWnd) - PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); + evt.lEventCode = EventCode; + evt.lParam1 = EventParam1; + evt.lParam2 = EventParam2; + EventsQueue_PutEvent(&This->evqueue, &evt); + if (!This->notif.disabled && This->notif.hWnd) + PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); } LeaveCriticalSection(&This->evqueue.msg_crst); @@ -3059,11 +3064,11 @@ fimpl->nFilters = 0; fimpl->filterCapacity = 0; fimpl->nameIndex = 1; - fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE,0); + fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0); fimpl->HandleEcComplete = TRUE; fimpl->HandleEcRepaint = TRUE; fimpl->notif.hWnd = 0; - fimpl->notif.disabled = TRUE; + fimpl->notif.disabled = FALSE; fimpl->nRenderers = 0; fimpl->EcCompleteCount = 0; fimpl->state = State_Stopped; diff -urN wine-20050211/dlls/quartz/main.c wine-20050310/dlls/quartz/main.c --- wine-20050211/dlls/quartz/main.c 2005-02-10 18:13:18.000000000 +0100 +++ wine-20050310/dlls/quartz/main.c 2005-03-02 13:23:22.000000000 +0100 @@ -205,15 +205,16 @@ } +#define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } , #name }, + static struct { const GUID riid; const char *name; } InterfaceDesc[] = { - #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } , #name }, - #include "uuids.h" - { { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }, NULL } +#include "uuids.h" + { { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }, NULL } }; /*********************************************************************** diff -urN wine-20050211/dlls/quartz/pin.c wine-20050310/dlls/quartz/pin.c --- wine-20050211/dlls/quartz/pin.c 2005-01-06 20:36:47.000000000 +0100 +++ wine-20050310/dlls/quartz/pin.c 2005-03-02 11:12:12.000000000 +0100 @@ -1158,7 +1158,7 @@ TRACE("Start\n"); - while (rtCurrent < This->rtStop) + while (rtCurrent < This->rtStop && hr == S_OK) { /* FIXME: to improve performance by quite a bit this should be changed * so that one sample is processed while one sample is fetched. However, diff -urN wine-20050211/dlls/quartz/tests/filtergraph.c wine-20050310/dlls/quartz/tests/filtergraph.c --- wine-20050211/dlls/quartz/tests/filtergraph.c 2004-12-16 15:25:15.000000000 +0100 +++ wine-20050310/dlls/quartz/tests/filtergraph.c 2005-03-02 11:12:12.000000000 +0100 @@ -51,6 +51,8 @@ { HRESULT hr; IMediaControl* pmc; + IMediaEvent* pme; + HANDLE hEvent; hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaControl, (LPVOID*)&pmc); ok(hr==S_OK, "Cannot get IMediaControl interface returned: %lx\n", hr); @@ -58,13 +60,23 @@ hr = IMediaControl_Run(pmc); ok(hr==S_FALSE, "Cannot run the graph returned: %lx\n", hr); + hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaEvent, (LPVOID*)&pme); + ok(hr==S_OK, "Cannot get IMediaEvent interface returned: %lx\n", hr); + + hr = IMediaEvent_GetEventHandle(pme, (OAEVENT*)&hEvent); + ok(hr==S_OK, "Cannot get event handle returned: %lx\n", hr); + + /* WaitForSingleObject(hEvent, INFINITE); */ Sleep(20000); + hr = IMediaControl_Release(pme); + ok(hr==2, "Releasing mediaevent returned: %lx\n", hr); + hr = IMediaControl_Stop(pmc); ok(hr==S_OK, "Cannot stop the graph returned: %lx\n", hr); hr = IMediaControl_Release(pmc); - ok(hr==1, "Releasing mediacontrol returned: %lx\n", hr); + ok(hr==1, "Releasing mediacontrol returned: %lx\n", hr); } static void releasefiltergraph() diff -urN wine-20050211/dlls/quartz/transform.c wine-20050310/dlls/quartz/transform.c --- wine-20050211/dlls/quartz/transform.c 2005-01-31 17:24:00.000000000 +0100 +++ wine-20050310/dlls/quartz/transform.c 2005-03-02 11:12:12.000000000 +0100 @@ -92,7 +92,7 @@ } #endif - This->pfnProcessSample(This, pbSrcStream, cbSrcStream); + This->pFuncsTable->pfnProcessSampleData(This, pbSrcStream, cbSrcStream); return S_OK; } @@ -103,7 +103,7 @@ TRACE("%p\n", iface); dump_AM_MEDIA_TYPE(pmt); - return This->pfnConnectInput(This, pmt); + return This->pFuncsTable->pfnConnectInput(This, pmt); } @@ -173,7 +173,7 @@ return E_FAIL; } -HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, PFN_PROCESS_SAMPLE pps, PFN_CONNECT_INPUT pci, PFN_CLEANUP pcu) +HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, TransformFuncsTable* pFuncsTable) { HRESULT hr; PIN_INFO piInput; @@ -181,9 +181,7 @@ /* pTransformFilter is already allocated */ pTransformFilter->clsid = *pClsid; - pTransformFilter->pfnProcessSample = pps; - pTransformFilter->pfnConnectInput = pci; - pTransformFilter->pfnCleanup = pcu; + pTransformFilter->pFuncsTable = pFuncsTable; pTransformFilter->lpVtbl = &TransformFilter_Vtbl; @@ -285,7 +283,7 @@ HeapFree(GetProcessHeap(), 0, This->ppPins); This->lpVtbl = NULL; - This->pfnCleanup(This); + This->pFuncsTable->pfnCleanup(This); TRACE("Destroying transform filter\n"); CoTaskMemFree(This); @@ -320,6 +318,8 @@ EnterCriticalSection(&This->csFilter); { This->state = State_Stopped; + if (This->pFuncsTable->pfnProcessEnd) + This->pFuncsTable->pfnProcessEnd(This); } LeaveCriticalSection(&This->csFilter); @@ -353,6 +353,8 @@ This->rtStreamStart = tStart; This->state = State_Running; OutputPin_CommitAllocator((OutputPin *)This->ppPins[1]); + if (This->pFuncsTable->pfnProcessBegin) + This->pFuncsTable->pfnProcessBegin(This); } LeaveCriticalSection(&This->csFilter); @@ -493,6 +495,32 @@ TransformFilter_QueryVendorInfo }; +HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface) +{ + InputPin* This = (InputPin*) iface; + TransformFilterImpl* pTransform; + IPin* ppin; + HRESULT hr; + + TRACE("(%p)->()\n", iface); + + /* Since we process samples synchronously, just forward notification downstream */ + pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; + if (!pTransform) + hr = E_FAIL; + else + hr = IPin_ConnectedTo(pTransform->ppPins[1], &ppin); + if (SUCCEEDED(hr)) + { + hr = IPin_EndOfStream(ppin); + IPin_Release(ppin); + } + + if (FAILED(hr)) + ERR("%lx\n", hr); + return hr; +} + static const IPinVtbl TransformFilter_InputPin_Vtbl = { InputPin_QueryInterface, @@ -509,7 +537,7 @@ IPinImpl_QueryAccept, IPinImpl_EnumMediaTypes, IPinImpl_QueryInternalConnections, - InputPin_EndOfStream, + TransformFilter_InputPin_EndOfStream, InputPin_BeginFlush, InputPin_EndFlush, InputPin_NewSegment @@ -540,7 +568,7 @@ if (hr == S_OK) { - pTransformFilter->pfnCleanup(pTransformFilter); + pTransformFilter->pFuncsTable->pfnCleanup(pTransformFilter); } return hr; diff -