diff -urN wine-20050111/ANNOUNCE wine-20050211/ANNOUNCE --- wine-20050111/ANNOUNCE 2005-01-11 20:08:58.000000000 +0100 +++ wine-20050211/ANNOUNCE 2005-02-11 14:34:17.000000000 +0100 @@ -1,14 +1,12 @@ -This is release 20050111 of Wine, a free implementation of Windows on +This is release 20050211 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-20050111: (see ChangeLog for details) - - Many OLE bug fixes and improvements. - - A lot more work on the MSI dll. - - Update regions now handled in the Wine server. - - Beginnings of typelib generation in the IDL compiler. - - Many janitorial cleanups. +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. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -17,8 +15,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-20050111.tar.gz - http://prdownloads.sourceforge.net/wine/Wine-20050111.tar.gz + http://www.ibiblio.org/pub/Linux/ALPHA/wine/development/Wine-20050211.tar.gz + http://prdownloads.sourceforge.net/wine/Wine-20050211.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-20050111/ChangeLog wine-20050211/ChangeLog --- wine-20050111/ChangeLog 2005-01-11 20:08:58.000000000 +0100 +++ wine-20050211/ChangeLog 2005-02-11 14:34:17.000000000 +0100 @@ -1,4 +1,2250 @@ ---------------------------------------------------------------- +2005-02-11 Alexandre Julliard + + * documentation/Makefile.in, documentation/compiling.sgml, + documentation/getting.sgml, documentation/installing.sgml, + documentation/introduction.sgml, documentation/wine-user.sgml: + Scott Ritchie + User Guide Chapter 2 rewrite. + + * dlls/advapi32/security.c, dlls/ntdll/nt.c, + include/wine/server_protocol.h, include/winnt.h, include/winternl.h, + server/object.h, server/process.c, server/protocol.def, + server/request.h, server/token.c, server/trace.c: + Robert Shearman + - Implement AdjustTokenPrivileges, DuplicateTokenEx and + GetTokenInformation (for the TokenPrivileges case). + - Return STATUS_NO_TOKEN for OpenThreadToken when there is no token + set for the thread. + + * dlls/dsound/buffer.c, dlls/dsound/capture.c, dlls/dsound/dsound.c, + dlls/dsound/dsound_main.c, dlls/dsound/primary.c, + dlls/dsound/propset.c, dlls/dsound/sound3d.c: + Robert Reif + Removed printing of thread id for AddRef and Release because + WINEDEBUG=+tid gives the same result. + General consistency cleanup. + +2005-02-10 Alexandre Julliard + + * dlls/kernel/profile.c: + Fixed profile cache flushing when no filename is specified (reported + by Mike Hearn). + + * dlls/dsound/tests/ds3d8.c: Francois Gouget + Don't link with DirectSoundCreate8 as this prevents running with older + versions of DirectX. + + * dlls/ntdll/version.c: Mike Hearn + Alter the version heuristics a bit. + + * programs/winedbg/gdbproxy.c: + Oliver Stieber + Added vCont support. + + * dlls/opengl32/opengl_ext.c: Tom Wickline + Sync to latest OpenGL specifications. + + * programs/msiexec/msiexec.c: Mike McCormack + Set full UI mode by default. + + * dlls/dsound/tests/ds3d.c, dlls/dsound/tests/ds3d8.c, + dlls/dsound/tests/dsound.c, dlls/dsound/tests/dsound8.c: + Robert Reif + Print info about primary buffer format. + + * dlls/d3d9/device.c: Paul Vriens + Check that ppZStencilSurface is not null. + + * aclocal.m4, dlls/advapi32/tests/crypt.c, + dlls/comctl32/tests/imagelist.c, dlls/dplayx/name_server.c, + dlls/kernel/tests/directory.c, dlls/kernel/tests/file.c, + dlls/kernel/tests/mailslot.c, dlls/kernel/tests/path.c, + dlls/lzexpand/tests/lzexpand_main.c, dlls/mapi32/tests/prop.c, + dlls/msi/table.c, dlls/msrle32/msrle32.c, dlls/msvcrt/environ.c, + dlls/msvcrt/tests/environ.c, dlls/quartz/acmwrapper.c, + dlls/rsaenh/rsaenh.c, dlls/shell32/pidl.c, dlls/shell32/shellpath.c, + dlls/shell32/tests/shellpath.c, dlls/shell32/tests/shlfileop.c, + dlls/shlwapi/tests/clist.c, dlls/wined3d/directx.c, + dlls/winedos/ppdev.c, documentation/configuring.sgml, + programs/wcmd/En.rc, programs/wcmd/Ru.rc, programs/wcmd/Si.rc, + tools/winebuild/spec32.c: + Francois Gouget + Assorted spelling fixes. + + * configure, configure.ac: Alex Woods + Handle host_cpu of x86_64 like other x86s. + + * programs/msiexec/Makefile.in, programs/msiexec/msiexec.c: + Mike McCormack + Read args from the registry when passed the /@ flag. + + * dlls/msi/msi.c, include/msi.h: Mike McCormack + Update headers, add MsiGetUserInfoA stub implementation. + + * dlls/serialui/Pt.rc, dlls/setupapi/Pt.rc, programs/clock/Pt.rc, + programs/cmdlgtst/Pt.rc, programs/notepad/Pt.rc, + programs/progman/Pt.rc, programs/regedit/Pt.rc, programs/start/Pt.rc, + programs/view/Pt.rc, programs/wcmd/Pt.rc, programs/winecfg/Pt.rc, + programs/winefile/Pt.rc, programs/winemine/Pt.rc, + programs/winhelp/Pt.rc: + Américo José Melo + Francois Gouget + Translate the Wine resources to Portuguese. + + * dlls/quartz/Makefile.in, dlls/quartz/main.c, + dlls/quartz/quartz_private.h, dlls/quartz/regsvr.c, + dlls/quartz/waveparser.c, include/uuids.h: + Christian Costa + Added WAVE parser. + + * programs/msiexec/msiexec.c: Mike McCormack + Convert to Unicode. + + * dlls/dsound/mixer.c: Robert Reif + Signed/unsigned fix and code cleanup. + + * dlls/shlwapi/tests/path.c: Paul Vriens + Use aliases for calls to ordinals. + + * dlls/msi/msi.c, dlls/msi/msi.spec: + Aric Stewart + Added stubs for MsiGetShortcutTargetA/W. + + * dlls/commdlg/filedlg.c, dlls/commdlg/filedlg16.c: + Dmitry Timoshkov + Do not forget to allocate internal OPENFILENAMEW structure for 16-bit + GetOpenFileName, initialize it by zeros for 16/A cases. + + * dlls/msi/action.c: Aric Stewart + Add the RegisterUser action. + + * dlls/dsound/buffer.c: Robert Reif + Always allocate an empty buffer. + +2005-02-09 Alexandre Julliard + + * dlls/winmm/Makefile.in, dlls/winmm/driver.c, dlls/winmm/mci.c, + dlls/winmm/mcianim/mcianim.c, dlls/winmm/mciavi/info.c, + dlls/winmm/mciavi/mciavi.c, dlls/winmm/mciavi/mciavi_res.rc, + dlls/winmm/mciavi/private_mciavi.h, dlls/winmm/mciavi/wnd.c, + dlls/winmm/mcicda/Makefile.in, dlls/winmm/mcicda/mcicda.c, + dlls/winmm/mciseq/mcimidi.c, dlls/winmm/message16.c, + dlls/winmm/mmio.c, dlls/winmm/mmsystem.c, dlls/winmm/mmsystem.spec, + dlls/winmm/winemm.h, dlls/winmm/winmm.c, dlls/winmm/winmm.spec, + dlls/winmm/winmm_res.rc, dlls/winmm/mciwave/mciwave.c, + include/mmsystem.h: + Eric Pouech + - rewrite MCI interfaces as Unicode interface (as it should be) + - made some winmm APIs rely on the Unicode version for the core + implementation (instead of Ansi flavor) + + * dlls/rsaenh/rsaenh.c, dlls/rsaenh/tests/rsaenh.c: + Michael Jung + Implemented CPGetProvParam's PP_ENUMCONTAINERS parameter type. + Added corresponding test. + Removed some tabs that slipped in with the last patch. + + * dlls/msi/action.c, dlls/msi/format.c: + Ulrich Czekalla + Handle 0 length buffers in MSI_FormatRecordW. + Remove unused buffer in deformat_string. + + * dlls/dbghelp/msc.c: Mike Hearn + Change an ERR to a WARN. + + * tools/winebuild/import.c: Marcus Meissner + Put generated import table code into .text segment. + + * programs/msiexec/msiexec.c: Mike McCormack + - Quote the parameter strings passed to MsiInstallProduct. + - Return the error code that the Msi* function returned when we quit. + + * dlls/msi/custom.c: Aric Stewart + Do not track the temp files for custom actions based on the name from + the table because then we get conflicts and files not tracked or + cleaned up. + + * dlls/dsound/buffer.c, dlls/dsound/primary.c: + Robert Reif + Fill new software buffers with silence. + + * dlls/x11drv/window.c, dlls/x11drv/winpos.c: + Make the win data pointer only available in the thread that owns the + window. + + * tools/config.guess, tools/config.sub: Upgrade to the latest version. + + * programs/msiexec/msiexec.c: Mike McCormack + - Fix msiexec's command line parsing. + - Don't allocate memory for fixed size structure. + - Remove a few non-tab indents, since the rest of the file uses tabbed + indent. + + * dlls/msi/action.c: Aric Stewart + Implement RegisterExtensionInfo and RegisterMIMEInfo. + + * dlls/msi/custom.c: Mike McCormack + Handle a number as a parameter for custom action 19. + + * dlls/ntdll/directory.c: + Consider any character above 0x7f to be invalid in a DOS short name. + + * dlls/itss/moniker.c: Tom Fogal + Simple aggregation fix. + + * dlls/msi/cond.y: Aric Stewart + Do not limit properties to 256 characters when evaluating them. + + * dlls/x11drv/keyboard.c: Dmitry Timoshkov + Add support for Turkish (tr) X11 keyboard layout. + + * dlls/shell32/cpanelfolder.c: Ge van Geldorp + - Fix quoting of .cpl filename. + - Use "cplopen" verb to execute .cpl files. + + * dlls/msi/action.c, dlls/msi/custom.c, dlls/msi/dialog.c: + Mike McCormack + - add support for Edit boxes in MSI dialogs + - run the message loop when waiting for threads or processes + + * dlls/msi/msi.c: Mike McCormack + Fix a memory leak in MsiConfigureProductExW. + +2005-02-08 Alexandre Julliard + + * include/wine/wined3d_gl.h: + Jason Edmeades + Avoid compile warnings. + + * tools/widl/write_msft.c: Huw Davies + Add support for modules. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/ole32.spec, dlls/ole32/regsvr.c, dlls/ole32/stubmanager.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Implement CoDisconnectObject. + - Change CoLockObjectExternal so that it does the correct action now + and eliminate a fair few lines of now redundant code. + - Rename OLE32_Dll{Register,Unregister}Server to + Dll{Register,Unregister}Server. + + * tools/widl/write_msft.c: Huw Davies + Check if we've already added the ptr to iface typedesc before adding a + new one. + + * dlls/user/tests/msg.c, windows/scroll.c: + Rein Klazes + ScrollWindowEx when called with the SW_ERASE flag does not send a + WM_ERASEBKGND message, it just sets the erase flag. With some tests + that show this behavior. + + * dlls/msi/custom.c: Aric Stewart + Make a temp file for each dll saved for custom actions. This prevents + name collisions from causing custom actions to fail. + + * dlls/msi/action.c: Aric Stewart + Add logic to be able to resolve the SourceDir based on + CurrentPath. Also add logic to get the source locations of a file if + it is not in a cabinet. + + * dlls/ole32/marshal.c: Robert Shearman + Move object-to-stub-manager mapping rule to register_ifstub. + + * dlls/msi/create.c, dlls/msi/distinct.c, dlls/msi/insert.c, + dlls/msi/msipriv.h, dlls/msi/msiquery.c, dlls/msi/order.c, + dlls/msi/select.c, dlls/msi/table.c, dlls/msi/update.c, + dlls/msi/where.c: + Mike McCormack + Fix MsiModifyView and MsiViewGetColumnInfo to use MSIRECORD* not + MSIHANDLE. + + * dlls/quartz/Makefile.in, dlls/quartz/avisplit.c, + dlls/quartz/parser.c, dlls/quartz/parser.h: + Christian Costa + Added parser template and made AVISplitter use it. + + * dlls/version/tests/info.c: + Stefan Leichter + Fixed GetFileVersionInfoSizeA tests on Win95. + + * tools/widl/write_msft.c: Vincent Béron + Support some more attributes for interface properties. + + * dlls/wininet/internet.c, dlls/wininet/urlcache.c, + dlls/wininet/wininet.spec: + Hans Leidekker + Stub implementations for DeleteUrlCacheContainer{A,W}, + CreateCacheContainer{A,W}, FindFirstUrlCacheContainer{A,W}, + FindNextUrlCacheContainer{A,W}. + Handle the case where the supplied buffer size is too small in + InternetQueryOption. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/ole32_main.c, dlls/ole32/rpc.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Split up apartment creation so that the long code paths that don't + need locking no longer have locking. + - Add special cases for the threads that join apartments but can't + increase the refcount of the apartment. + - Free TLS storage on thread destruction (including releasing the + apartment the thread is in, if any, and so making another test + pass). + + * dlls/oleaut32/oleaut.c: Paul Vriens + Add WinXP to OaBuildVersion. + + * tools/widl/write_msft.c: Vincent Béron + Support ATTR_READONLY for interface properties. + + * include/msidefs.h: Mike McCormack + Add the msidbCustomAction and msidbFeatureAttributes enumerations. + + * dlls/msi/dialog.c, dlls/msi/msipriv.h: + Mike McCormack + - fix the dialog font + - allow waiting on a handle while running the message loop + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c: + Mike Hearn + Robert Shearman + - Rework RPC dispatch layer to be simpler and not get confused by + server/client duality. + - Make threads shut down at the right time and not access freed memory + after apartment destruction. + - Rename stub_dispatch_thread to client_dispatch_thread. + - Add some more tracing + - Check return value of WaitNamedPipe. + - Change named pipe timeouts to 0.5s, which should be enough for even + the slowest machines. + + * server/named_pipe.c: Robert Shearman + Support WaitNamedPipe timeouts. + + * dlls/msi/cond.y: Juan Lang + Identifiers evaluate to true if they are non-empty, regardless of + value. + + * dlls/ntdll/time.c: Robert Shearman + Replace 10000000 with TICKSPERSEC to make it more obvious what the + code is doing. + + * Make.rules.in: Vincent Béron + Make tlb generation from idl files dependent on widl. + + * documentation/faq.sgml: Scott Ritchie + Remove two ancient FAQ entries that did more harm than good. + Replace a reference to wine.conf with ~/.wine/config. + + * dlls/oleaut32/oleaut.c: Mike Hearn + Return OLE automation build value as win2k by default. + + * dlls/msi/.cvsignore, dlls/msi/Makefile.in, dlls/msi/msi.c, + dlls/msi/msi.rc, dlls/msi/msi_En.rc: + Mike McCormack + Implement and document MsiLoadString. + + * dlls/msi/action.c: Mike Hearn + Correctly ensure properties set from resolved directory paths are + backslash terminated. + + * dlls/dinput/device.c: Carlos Lozano + Fix regression in Fallout game. + + * dlls/d3d8/device.c, dlls/wined3d/device.c: + Carlos Lozano + Check that pstream is not null. + + * dlls/wininet/wininet.spec: Steven Edwards + Correct spec entry for FindFirstUrlCacheEntryEx. + + * tools/widl/typelib.c, tools/widl/typelib_struct.h, + tools/widl/write_msft.c: + Huw Davies + Add VARIANT_BOOL. + Fix CURRENCY alignment. + A function with a [retval] param has a bit set in the FKCCIC bitfield. + Two functions with the same name share the same id. + The param names of propput and propputref functions don't go into the + typelib. + + * dlls/user/tests/sysparams.c: Paul Vriens + Extra tracing for SPI_GETICONTITLEWRAP. + + * dlls/msi/appsearch.c: Juan Lang + If a full path isn't specified, search across all fixed drives. + + * programs/winecfg/En.rc, programs/winecfg/driveui.c: + Kris Marsh + Fixed window height to show all data properly. + Cleaned up drives->advanced information visuals. + + * dlls/kernel/sync.c: Robert Shearman + Convert last error from NTSTATUS to a DOS error code in WaitNamedPipe + and ConnectNamedPipe. + + * server/window.c: Robert Shearman + Don't overwrite last byte of the window structure as we might not have + allocated the memory for it if extrabytes was 0. + +2005-02-03 Alexandre Julliard + + * dlls/commdlg/filedlg.c, dlls/commdlg/filedlg16.c, + dlls/commdlg/filedlg31.c, dlls/commdlg/filedlg31.h: + Dmitry Timoshkov + Make GetOpenFileNameW with an old style open file dialog work with the + original OPENFILENAMEW structure, making sure that all changes are + passed back to the caller. + + * dlls/shlwapi/tests/shreg.c: Paul Vriens + More verbosity of errors. + + * dlls/urlmon/sec_mgr.c, dlls/urlmon/umon.c, dlls/urlmon/urlmon_main.c, + dlls/urlmon/urlmon_main.h: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/kernel/Makefile.in, dlls/kernel/atom.c, dlls/kernel/atom16.c: + Eric Pouech + Moved 16 bit atom support to dlls/kernel/atom16.c. + + * dlls/ttydrv/wnd.c, dlls/user/hook.c, dlls/user/message.c, + dlls/user/tests/msg.c, dlls/x11drv/window.c, + include/wine/server_protocol.h, server/hook.c, server/protocol.def, + server/queue.c, server/thread.c, server/trace.c, server/user.h, + windows/nonclient.c: + Dmitry Timoshkov + Add support for winevent hooks. + + * dlls/ttydrv/wnd.c, dlls/x11drv/window.c, dlls/x11drv/winpos.c, + dlls/x11drv/x11drv.h, include/wine/server_protocol.h, + server/protocol.def, server/trace.c, server/window.c: + Properly compute the client area valid rects and pass them to the + server in set_window_pos to avoid invalidating areas that remain + valid. + + * dlls/setupapi/devinst.c, dlls/setupapi/setupapi_private.h, + dlls/setupapi/setupcab.c: + Eric Kohl + - Implement SetupDiBuildClassInfoListExA, + SetupDiClassGuidsFromNameExA, SetupDiCreateDeviceInfoListExA and + SetupDiOpenClassRegKeyExA using MultiByteToUnicode. + - Retrieve OS version upon process attach. + + * tools/widl/parser.l, tools/widl/parser.y, tools/widl/typelib.c, + tools/widl/widltypes.h, tools/widl/write_msft.c: + Huw Davies + Coclass support. + + * dlls/shlwapi/path.c, dlls/shlwapi/shlwapi.spec, + dlls/shlwapi/tests/path.c: + Hans Leidekker + Implement and test PathIsValidChar{A,W}. + + * server/named_pipe.c: + Fixed refcount handling (waiting clients must not increase the + refcount of the pipe). + Converted linked lists to use the standard functions. + Small cleanups. + + * server/main.c, server/request.c: + Make sure leaked objects are printed even if a file descriptor is + still open. + + * server/fd.c: Fixed potential crash in fd_dump function. + + * dlls/kernel/sync.c: Async callback function must be stdcall. + + * dlls/msi/dialog.c, dlls/msi/msiquery.c: + Mike McCormack + - implement checkboxes in dialogs + - use TextStyle enumeration instead of numbers + - fix MSI_IterateRecords to return the correct count + + * dlls/msi/appsearch.c: Juan Lang + Simplify AppSearch error checking. + + * programs/winecfg/En.rc: Paul van Schayck + Clean up about dialog. Remove groupbox, position logo correctly. + +2005-02-02 Alexandre Julliard + + * dlls/ole32/marshal.c: Robert Shearman + - Pass the original IID to IMarshal_UnmarshalInterface and query for + the requested interface. + - Unmarshaling IID_NULL means use the IID the interface was originally + marshaled with. + + * dlls/user/listbox.c, dlls/user/tests/listbox.c: + Lauri Tulmin + Add test for LB_SELITEMRANGE and make it pass. + + * include/mmsystem.h: Lauri Tulmin + Added some more defines. + + * tools/widl/parser.y, tools/widl/typelib.c, tools/widl/typelib.h, + tools/widl/widltypes.h, tools/widl/write_msft.c: + Huw Davies + Add support for typedefs. + + * dlls/setupapi/misc.c, dlls/setupapi/setupapi.spec, + include/setupapi.h: + Eric Kohl + - Implement DoesUserHavePrivilege, EnablePrivilege, IsUserAdmin, + MultiByteToUnicode and UnicodeToMultiByte. + - Sort prototypes in setupapi.h and a few function in spec. + + * dlls/wininet/http.c: David McCullough + HTTP_HttpSendRequestW was getting invoked with a null verb, default to + the GET method. + + * dlls/msi/dialog.c, dlls/msi/msipriv.h, dlls/msi/msiquery.c, + dlls/msi/package.c, dlls/msi/preview.c: + Mike McCormack + Add more dialog controls, do something when they're clicked on. + + * include/msidefs.h: Mike McCormack + Add the msidbTextStyleStyleBits enumeration. + + * dlls/user/tests/win.c, include/win.h, windows/mdi.c, windows/win.c: + Dmitry Timoshkov + Use the idFirstChild specified in the MDIClient's CLIENTCREATESTRUCT + when creating MDI children. Add a test case for the desired + behaviour. + + * dlls/dmscript/dmscript_main.c, dlls/dmscript/dmscript_private.h, + dlls/dmscript/script.c, dlls/dmscript/scripttrack.c: + James Hawkins + Properly implement DllCanUnload ref counting. + + * dlls/dmime/audiopath.c, dlls/dmime/dmime_main.c, + dlls/dmime/dmime_private.h, dlls/dmime/graph.c, + dlls/dmime/lyricstrack.c, dlls/dmime/markertrack.c, + dlls/dmime/paramcontroltrack.c, dlls/dmime/patterntrack.c, + dlls/dmime/performance.c, dlls/dmime/segment.c, + dlls/dmime/segmentstate.c, dlls/dmime/segtriggertrack.c, + dlls/dmime/seqtrack.c, dlls/dmime/sysextrack.c, + dlls/dmime/tempotrack.c, dlls/dmime/timesigtrack.c, + dlls/dmime/tool.c, dlls/dmime/wavetrack.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/msi/format.c: Aric Stewart + Cleanup processing a bit more. + Allow for nested keys to work properly. + + * dlls/msi/appsearch.c: Aric Stewart + Fix a copy and paste error, check for a null value and discard + unneeded errors. + + * dlls/msi/cond.y: Mike McCormack + MsiEvaluateCondition returns an error when passed NULL as a + condition. + + * dlls/msi/action.c: Aric Stewart + Finish up the framework by stubbing out all the remaining Standard + actions. + A fix to deformat_string so it only returns a null return if you + provided a null buffer. + +2005-02-01 Alexandre Julliard + + * dlls/user/user32.spec, include/win.h, windows/win.c: + Removed the no longer used WIN_SetExStyle function. + + * dlls/comctl32/status.c, dlls/user/focus.c, dlls/user/menu.c, + dlls/x11drv/window.c, dlls/x11drv/winpos.c, dlls/x11drv/x11drv.h, + include/winuser.h, windows/winpos.c: + Store the "managed" flag as a window property instead of the + Wine-specific WS_EX_MANAGED style bit. + + * dlls/wininet/ftp.c, dlls/wininet/http.c, dlls/wininet/internet.c, + dlls/wininet/urlcache.c, dlls/wininet/wininet.spec, + include/wininet.h: + Hans Leidekker + - Stub implementations for FtpGetFileSize, FtpCommand{A,W}, + HttpSendRequestExW, InternetGetLastResponseInfoW, + InternetConfirmZoneCrossing{A,W}, InternetDial{A,W}, + InternetGoOnline{A,W}, InternetHangUp, CreateMD5SSOHash, + InternetClearAllPerSiteCookieDecisions, + InternetEnumPerSiteCookieDecision{A,W}, InternetGetCookieEx{A,W}, + InternetGetPerSiteCookieDecision{A,W}, + InternetSetPerSiteCookieDecision{A,W}, InternetSetCookieEx{A,W}, + ResumeSuspendedDownload, RetrieveUrlCacheEntryFileW, + UnlockUrlCacheEntryFileW, {Create,Delete}UrlCacheEntryW, + CommitUrlCacheEntryW, RetrieveUrlCacheEntryStreamW, + FindCloseUrlCache, FindFirstUrlCacheEntryEx{A,W}, + FindFirstUrlCacheGroup, FindNextUrlCacheEntry{,Ex}{A,W}, + FindNextUrlCacheGroup, SetUrlCacheEntryGroup{A,W}, + {Get,Set}UrlCacheGroupAttribute{A,W}, SetUrlCacheConfigInfo{A,W}. + - Spec file stubs for new undocumented functions + ForceNexusLookup{,ExW}, Ftp{Get,Put}FileEx, HttpCheckDavCompliance, + InternetAlgIdToString{A,W}, InternetFortezzaCommand, + InternetGetCertByURLA, InternetQueryFortezzaStatus, + InternetSecurityProtocolToString{A,W}, InternetSetDialState{A,W}, + InternetShowSecurityInfoByURL{A,W}, IsUrlCacheEntryExpired{A,W}, + Privacy{Get,Set}ZonePreferenceW, RegisterUrlCacheNotification, + UrlZonesDetach. + - Use memcpy instead of strncpy in InternetGetLastResponseInfoA. + - Add and improve some traces. + - Fix my own coding style in InternetTimeToSystemTimeW. + - Fix a couple of signedness warnings. + + * tools/widl/parser.l, tools/widl/parser.y, + tools/widl/typelib_struct.h, tools/widl/widltypes.h, + tools/widl/write_msft.c: + Huw Davies + Add support for dispinterfaces (slightly hacked because we force the + import of stdole2.tlb). + Add propputref attribute. + + * dlls/user/dde/client.c, dlls/user/dde/dde_private.h, + dlls/user/dde/misc.c, dlls/user/dde/server.c: + Dmitry Timoshkov + Handle CBR_BLOCK in EXECUTE and ADVISE DDE transactions. + + * dlls/dsound/dsound.c: Robert Reif + Fix primary buffer memory leak. + + * dlls/user/sysparams.c: Justin Chevrier + - SPI_GETWORKAREA: Read work area information from system metrics + initially only and not from a WINE specific registry entry. + - SPI_SETWORKAREA: Don't save work area information to registry. + + * dlls/msi/action.c, dlls/msi/action.h, dlls/msi/custom.c: + Aric Stewart + Continued work to simplify the ProcessAction call, also split it into + a ProcessAction and ProcessUIAction for future dialog box work. + Also fix a bug in deformat_string where i was not freeing the created + record. + + * Make.rules.in: Don't clean all tlb files, only the ones we generated. + + * dlls/dxdiagn/container.c, dlls/dxdiagn/dxdiag_main.c, + dlls/dxdiagn/dxdiag_private.h, dlls/dxdiagn/provider.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/msi/Makefile.in, dlls/msi/action.c, dlls/msi/action.h, + dlls/msi/appsearch.c: + Juan Lang + Partially implement AppSearch action. + + * dlls/quartz/Makefile.in, dlls/quartz/acmwrapper.c, + dlls/quartz/avidec.c, dlls/quartz/main.c, + dlls/quartz/quartz_private.h, dlls/quartz/regsvr.c: + Christian Costa + Added ACM Wrapper filter. + Cleaned up AVIDec. + + * dlls/dswave/dswave.c, dlls/dswave/dswave_main.c, + dlls/dswave/dswave_private.h: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * documentation/fonts.sgml: Tom Wickline + Fix a broken link. + + * dlls/msi/msi.spec, dlls/msi/suminfo.c, include/msi.h: + Aric Stewart + Added some more suminfo stubs. + + * dlls/ole32/compobj.c, dlls/ole32/marshal.c, dlls/ole32/ole32_main.h, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Add code for destroying the thread-local storage data, but don't use + it yet. + - Don't release apartment on changing modes because we didn't add a + reference anywhere. + - Quieten the RPC_E_DISCONNECTED error message as it is an expected + return code. + - Treat IID_NULL the same as IID_IUnknown. + - Make tests compile on Win95 again. + - Fix copy+paste error where the test failure should be from the + CoUnmarshalInterface function. + +2005-01-31 Alexandre Julliard + + * dlls/msi/format.c: Aric Stewart + A reworking of format.c to remove the recursion, clean things up and + stabilize behavior to match windows. + + * dlls/dmband/band.c, dlls/dmband/bandtrack.c, + dlls/dmband/dmband_main.c, dlls/dmband/dmband_private.h, + dlls/dmsynth/dmsynth_main.c, dlls/dmsynth/dmsynth_private.h, + dlls/dmsynth/synth.c, dlls/dmsynth/synthsink.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/user/user32.spec, include/win.h, windows/win.c: + WIN_ListParents no longer needs to be exported, make it static. + + * dlls/d3d8/directx.c, dlls/wined3d/directx.c, dlls/x11drv/mouse.c, + dlls/x11drv/window.c, dlls/x11drv/winpos.c, dlls/x11drv/x11drv.h: + Only create an X window for top-level windows, not for child windows. + Get rid of the X client window too, it's no longer needed. + + * dlls/dbghelp/elf_module.c: Silence a noisy FIXME. + + * tools/widl/write_msft.c: Huw Davies + Dynamically allocate the type data storage. + Split the function and variable type data into two - this will be + needed for dispinterfaces. + + * dlls/quartz/Makefile.in, dlls/quartz/avidec.c, dlls/quartz/regsvr.c, + dlls/quartz/transform.c, dlls/quartz/transform.h: + Christian Costa + Added transform filter template and made AVIDec use it. + Fixed memory leak in register_filters function. + + * dlls/kernel/change.c, dlls/kernel/kernel32.spec: + Hans Leidekker + Stub implementation for ReadDirectoryChangesW. + + * dlls/msi/action.c: Aric Stewart + Eliminate the giant if.. else if block from ACTION_ProcessAction in + favor of a table of handlers. + Return code of the install should not depend on the return code of the + final action. + Update component installed states as they are installed so that + conditions based on component states are at least a little more + correct. + Add icon and argument when regestering clsids. + Add a stub for ResolveSource because we do that work just not in + ResolveSource like we should. + When quering a Component state return the correct state. + + * programs/winedbg/info.c: Mike Hearn + Show window owner thread in winedbg. + + * dlls/dbghelp/symbol.c, include/dbghelp.h, programs/winedbg/break.c, + programs/winedbg/dbg.y, programs/winedbg/debug.l, + programs/winedbg/memory.c, programs/winedbg/source.c, + programs/winedbg/stack.c, programs/winedbg/symbol.c, + programs/winedbg/types.c: + Eric Pouech + Cleanup of dbghelp.h (and a couple of definition fixes). The + displacements (in most of the functions) are not optional. + + * dlls/oleaut32/olefont.c, dlls/oleaut32/typelib.c: + Vincent Béron + Remove message telling users to copy native stdole32.tlb over as we + now provide it. + Better trace in LoadTypeLib. + Change debug messages type to reflect we provide stdole32.tlb. + + * include/Makefile.in, include/msidefs.h: + Mike McCormack + Add the msidefs.h header. + + * documentation/faq.sgml, documentation/introduction.sgml: + Tom Wickline + Remove outdated information from the introduction page and the FAQ. + + * include/dxdiag.h: Troy Rollo + Correct errors in the macros for two DxDiag method calls. + + * dlls/opengl32/wgl_ext.c: Troy Rollo + Add stubs for wglSwapIntervalEXT & wglGetSwapIntervalEXT. + + * dlls/oleaut32/safearray.c, dlls/oleaut32/tests/safearray.c: + Rein Klazes + SafeArrayDestroy() returns success when called with a NULL + pointer. Added to the test cases. + + * dlls/msi/record.c, dlls/msi/tests/record.c: + Aric Stewart + Setting a record to an empty string is the same as making it null. + + * windows/dce.c: Dimitrie O. Paun + Replace a DPRINTF with TRACE. + + * tools/widl/write_msft.c: Vincent Béron + Check that there are some methods to iterate through before iterating + through them. + + * dlls/shlwapi/tests/shreg.c: Paul Vriens + - new test + - changed test to reflect windows results + + * dlls/ole32/tests/marshal.c: Robert Shearman + Remove test that fails on Win98 and is not useful. + + * dlls/dbghelp/stabs.c: Eric Pouech + Various fixes for C++ class parsing (nesting, templates) (from test + cases provided by Michael Lin). + + * dlls/rsaenh/rsaenh.c, dlls/rsaenh/tests/rsaenh.c: + Michael Jung + Moved PKCS1 #2 un-/padding from Import-/ExportKey to helper + functions. + Support RSA en-/decryption via CPEncrypt and CPDecrypt. + Added test case for RSA en-/decryption. + +2005-01-28 Alexandre Julliard + + * dlls/x11drv/desktop.c, dlls/x11drv/event.c, dlls/x11drv/window.c, + dlls/x11drv/winpos.c, dlls/x11drv/x11drv.h, include/win.h: + Use an X context to associated the x11drv private window data to a + window handle instead of accessing the WND structure directly. + + * dlls/user/painting.c: + Fixed bug that caused the whole window to be repainted by RedrawWindow + when the passed region was empty. + + * dlls/dsound/capture.c, dlls/dsound/dsound_main.c, + dlls/dsound/propset.c, 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, + dlls/winmm/wineoss/audio.c, include/dsdriver.h: + Robert Reif + Fix structure member name to match windows headers and fix up all + uses. + Nameless struct fix for dsound/propset.c to compile on both windows + and wine. + + * dlls/ole32/compobj.c: Robert Shearman + Release the client security objects when no longer needed (reported by + Mike McCormack). + + * dlls/comctl32/toolbar.c: + Thomas Weidenmueller + When a toolbar doesn't have the TBSTYLE_FLAT style redrawing the + buttons when moving the mouse is not necessary. + + * Make.rules.in, configure, configure.ac, dlls/Makefile.in, + dlls/stdole32.tlb/.cvsignore, dlls/stdole32.tlb/Makefile.in, + dlls/stdole32.tlb/rsrc.rc, dlls/stdole32.tlb/std_ole_v1.idl, + dlls/stdole32.tlb/stdole32.tlb.spec: + Huw Davies + Added stdole32.tlb. + + * dlls/d3d9/d3d9_private.h, dlls/d3d9/device.c, dlls/d3d9/directx.c, + dlls/d3d9/query.c, dlls/d3d9/texture.c, + dlls/d3d9/vertexdeclaration.c: + Raphael Junqueira + - add vertex Declaration support (using wined3d) + - minimal impl for SetRenderTarget and CreateQuery (needed to get + some samples working) + - remove no longer needed #undef GL_VERSION_1_4 + + * dlls/commdlg/cdlg32.c, dlls/kernel/tests/comm.c, + dlls/kernel/tests/console.c, dlls/lzexpand/tests/lzexpand_main.c, + loader/preloader.c: + Rémi Assailly + char -> const char fixes. + + * tools/wrc/parser.y: + Avoid assertion failure when loading an empty data file. + + * tools/widl/typelib.c: Huw Davies + Structs with ptrs are also VT_USERDEFINED. + + * dlls/msi/Makefile.in, dlls/msi/dialog.c, dlls/msi/msi.c, + dlls/msi/msipriv.h, dlls/msi/package.c, dlls/msi/preview.c: + Mike McCormack + Implement MsiPreviewDialog. + + * dlls/ole32/compobj.c, dlls/ole32/marshal.c, dlls/ole32/rpc.c, + dlls/ole32/tests/marshal.c, dlls/ole32/tests/moniker.c: + Robert Shearman + - More tests. + - Change return code of CoGetPSClsid to match test result. + - Do a slight hack to make IRemUnknown proxies be added after the + proxy that uses them to stop them being used after they are + destroyed. + - Fix multiple local server connections. + + * dlls/ntdll/nt.c, include/winternl.h: Rein Klazes + In NtQuerySystemInformation, handle request for information class 1, + now named SystemCpuInformation. Return some dummy data for now. + + * configure, configure.ac, dlls/Makefile.in, dlls/sensapi/.cvsignore, + dlls/sensapi/Makefile.in, dlls/sensapi/sensapi.c, + dlls/sensapi/sensapi.spec, include/Makefile.in, include/sensapi.h: + Steven Edwards + Add a stub dll for the System Event Notification Service. + + * tools/winegcc/Makefile.in, tools/winegcc/winegcc.man: + Dimitrie O. Paun + Added a new man page for winegcc. + + * dlls/wined3d/vertexdeclaration.c: + Raphael Junqueira + - convert D3D8 VertexDecl to D3D9 format (D3DVERTEXELEMENT9 vector) + while parsing + - display result on traces + + * dlls/wineps/truetype.c: Huw Davies + Add a few missing RegCloseKey calls. + + * dlls/user/lstr.c: Tony Lambregts + Fix bug in CharPrevExA(). + + * dlls/rsaenh/tests/rsaenh.c: Michael Jung + Added a test case for hashing with schannel mac keys. + + * dlls/kernel/cpu.c: Oliver Stieber + Fill in the information in VendorIdentifier and make a better effort + at filling in Identifier in the registry key. + + * include/msiquery.h: Juan Lang + Remove duplicate definition. + + * dlls/ole32/compobj.c, dlls/ole32/ole32.spec: + Robert Shearman + - Implement CoSetProxyBlanket, CoQueryProxyBlanket and CoCopyProxy. + - Update todo list. + + * dlls/msvcrt/scanf.h, dlls/msvcrt/tests/scanf.c: + Francois Gouget + Fix handling of EOF for the '%c' and '%C' cases in scanf(). + Add conformance tests to verify the behavior of '%c'. + Improve some of the test's error messages. + + * dlls/x11drv/keyboard.c: Oliver Stieber + Send a scancode through for the 5 key when numlock isn't on. + +2005-01-27 Alexandre Julliard + + * dlls/advapi32/tests/registry.c: + Don't make the test key volatile, that can break other tests. + + * dlls/user/hook.c, dlls/user/tests/msg.c, server/hook.c, + server/trace.c: + Dmitry Timoshkov + Add more tests for old style hooks and winevent hooks, make them pass + under Wine. + + * dlls/msi/action.c, dlls/msi/action.h, dlls/msi/msipriv.h: + Aric Stewart + Enable the updating of Feature and thus the resulting component + states. + Run the end of install actions for suspend and user exit states as + well. + Start putting in place a currently running state for future ui use. + + * dlls/msi/package.c: Mike McCormack + - implement MsiOpenPackageEx, and forward MsiOpenPackage there + - make a MSI_CreatePackage function and use it in MSI_OpenPackage + - move MsiOpenPackageA down with the rest of the API functions + + * dlls/ntdll/time.c: Troy Rollo + Add TZ_INFO entry to match (incorrect) Australian Eastern Daylight + Time information given by some systems. + + * dlls/oleaut32/tmarshal.c: Mike Hearn + - Change some FIXMEs to ERRs to reflect the fact that nothing needs + fixing. + - Fix some memory leaks on error paths in _marshal_interface. + + * dlls/user/tests/sysparams.c: Paul Vriens + Check for availability of SPI_GETICONTITLEWRAP. + + * windows/win.c, windows/winpos.c: + Avoid a few more uses of WIN_FindWndPtr. + + * include/.cvsignore, include/Makefile.in, include/sensevts.idl: + Mike McCormack + Added idl file for the System Event Notifcation Services API + (SENSAPI). + + * dlls/shdocvw/classinfo.c, dlls/shdocvw/events.c, + dlls/shdocvw/factory.c, dlls/shdocvw/misc.c, + dlls/shdocvw/oleobject.c, dlls/shdocvw/persist.c, + dlls/shdocvw/shdocvw.h, dlls/shdocvw/shdocvw_main.c, + dlls/shdocvw/webbrowser.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. Make sure the mozilla + control is ready to unload as well. + + * dlls/msi/tests/db.c: Mike McCormack + Test different types of dodgy queries. + + * dlls/msi/custom.c: Aric Stewart + Implement custom action type 19, Halt install and display error + message. + + * dlls/msi/package.c: Aric Stewart + MsiGetProperty does not return any error on missing properties. + + * dlls/ddraw/ddraw/main.c: Raphael Junqueira + Set default video memory to 64Mb (was 16Mb) as many d3d9 demos use + d3d7 code to get available video memory size (ex ConfigSystem.exe on + d3d9 sdk). + + * dlls/dxdiagn/Makefile.in, dlls/dxdiagn/container.c, + dlls/dxdiagn/dxdiag_private.h, dlls/dxdiagn/provider.c: + Raphael Junqueira + - some fixes on sub containers support + - add support for properties (VARIANT) + - hard coded simple init for root container (getting simple dx9 + version checks working) + + * dlls/kernel/lcformat.c: Vincent Béron + Change UTF-8 name back to ISO-8859-1. + + * dlls/wined3d/device.c, dlls/wined3d/directx.c, + dlls/wined3d/vertexdeclaration.c, include/wine/wined3d_interface.h: + Raphael Junqueira + - fix typo in wined3d_interface.h + - add needed defines in wined3d_interface.h + - add IWineD3DVertexDeclarationImpl_ParseToken9 for debug traces + - fix ParseDeclaration9 + - limit flood of traces (single shot traces) + + * dlls/ole32/marshal.c, dlls/ole32/tests/marshal.c: + Robert Shearman + Give IUnknown its own ifstub to fix ref-counting and ipid storage + issues. + +2005-01-26 Alexandre Julliard + + * dlls/comctl32/listview.c, dlls/comctl32/toolbar.c, + dlls/dplayx/dplayx_global.c, dlls/dplayx/dplobby.c, + dlls/msi/action.c, dlls/msi/custom.c, dlls/msi/format.c, + dlls/msi/table.c, dlls/rsaenh/mpi.c, dlls/shell32/shellord.c, + dlls/wininet/cookie.c, dlls/wininet/http.c, documentation/ole.sgml, + programs/winedbg/db_disasm.c, tools/winapi/make_parser.pm: + Francois Gouget + Assorted spelling fixes. + + * dlls/ole32/compobj_private.h, dlls/ole32/marshal.c, + dlls/ole32/oleproxy.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Make proxy manager use IMultiQI instead of IInternalUnknown as tests + show that IInternalUnknown isn't exposed. + - Implement IMultiQI on top of IRemUnknown calls. + - Silence some fixmes that occur during tests and don't give us any + useful information. + - Fix typo in class factory proxy that caused us to use the wrong + offset into the CFProxy structure, causing us to not call the + outer_unknown properly. + + * dlls/wined3d/directx.c, dlls/wined3d/drawprim.c, + include/wine/wined3d_gl.h: + Raphael Junqueira + - a very basic blending support on fast drawing path (to have better + performances on last games) + - some defines for VBO support + + * dlls/wined3d/device.c, dlls/wined3d/vertexdeclaration.c, + dlls/wined3d/wined3d_private.h, include/wine/wined3d_interface.h: + Raphael Junqueira + - VertexDeclaration device APIs + - D3D9 declarations parsing + - a little better APIs (trying to avoid compile problems) + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/oleproxy.c, dlls/ole32/rpc.c, + dlls/ole32/stubmanager.c: + Robert Shearman + - Use InterlockedIncrement for the ipid counter instead of a critical + section (suggested by Mike Hearn). + - Remove a line added by a bad merge. + - Implement RemUnkStub_Disconnect. + - Remove all of the RPC disconnect code. + + * dlls/ole32/marshal.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Implement IRemUnknown. + - Use IRemUnknown for life-cycle management instead of the current + hacks. + + * include/winternl.h, dlls/kernel/cpu.c, dlls/ntdll/nt.c, + dlls/ntdll/ntdll.spec: + Rein Klazes + Get rid of the rdtsc cpu instruction method for calculation of the + performance counter. Put the calculation (based on gettimeofday) in + NtQueryPerformanceCounter() and use that in the kernel functions. + + * dlls/dmscript/script.c: Francois Gouget + Remove unneeded NULL cast. + + * tools/widl/typelib_struct.h, tools/widl/write_msft.c: + Huw Davies + When adding an interface, midl adds the inherited interface first + unless the inherited interface doesn't itself inherit. + Fix the id, sizevft and datatype2 fields for interfaces that inherit. + Prevent a crash if the typelib is empty. + Clarify a few more entries on typelib_struct.h + + * dlls/msi/record.c, dlls/msi/tests/record.c: + Mike McCormack + Fix MsiRecordSetString for NULL strings and update test case. + + * dlls/x11drv/xrender.c: Glenn Wurster + Disable antialiasing of fonts while working in a palette. + + * dlls/setupapi/Nl.rc, programs/notepad/Nl.rc, programs/progman/Nl.rc, + programs/regedit/Nl.rc, programs/start/Nl.rc, + programs/winefile/Nl.rc, programs/winhelp/Nl.rc: + Hans Leidekker + Don't use utf8 in rc files. + + * dlls/oleaut32/tmarshal.c: Mike Hearn + Fix a typo, propagate errors better from inside the typelib + marshaller. + + * dlls/gdi/metafile.c: Huw Davies + GetMetaFile checks both the version and the header size when it tries + to load a metafile. Powerpoint XP depends on this. + + * dlls/dmusic/buffer.c, dlls/dmusic/clock.c, dlls/dmusic/collection.c, + dlls/dmusic/dmusic.c, dlls/dmusic/dmusic_main.c, + dlls/dmusic/dmusic_private.h, dlls/dmusic/download.c, + dlls/dmusic/downloadedinstrument.c, dlls/dmusic/instrument.c, + dlls/dmusic/port.c, dlls/dmusic/portdownload.c, dlls/dmusic/thru.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/msi/msi.c, dlls/msi/msi.spec, dlls/msi/msipriv.h, + dlls/msi/registry.c: + Aric Stewart + Added a few more stub implementations. + + * tools/widl/parser.l, tools/widl/parser.y, tools/widl/proxy.c, + tools/widl/typelib.c, tools/widl/widl.c, tools/widl/widl.h, + tools/widl/widl.man: + Huw Davies + Fix typelib only option. + Make -t and -h options inclusive. + +2005-01-25 Alexandre Julliard + + * dlls/msi/Makefile.in, dlls/msi/action.c, dlls/msi/action.h, + dlls/msi/custom.c, dlls/msi/format.c, dlls/msi/msipriv.h, + dlls/msi/package.c, dlls/msi/record.c: + Aric Stewart + - action.c is getting too big, so split out all the handling of + CustomActions into custom.c. Cleaned up a lot of the handling of + custom actions including scripting actions and processing return + codes. + - Mike McCormack pointed out that MsiFormatRecord is basically the + same as internal function deformat_string. So broke deformat_string + out and updated it to function as MsiFormatRecord and implemented + MsiFormatRecord. + - A number of random fixes to action.c including properly calculating + the length for the LocalPackage name, not forcing a reboot when + really we should just return ERROR_INSTALL_SUSPEND and handling + REG_MULTI_SZ now that we can deformat the properly. + + * programs/winhelp/hlp2sgml.c, programs/winhelp/hlpfile.c, + programs/winhelp/macro.lex.l, programs/winhelp/winhelp.c: + Ken Belleau + - Used wine_dbgstr_a to prevent an overflow. + - Improved support to call macros with a variable number of + parameters. + - Put a check to prevent an out of bounds access. + + * dlls/dinput/joystick_linux.c, dlls/dinput/mouse.c: + Robert Reif + Copy data structures one at a time using supplied size. + + * tools/widl/parser.y, tools/widl/typelib.c, tools/widl/typelib.h, + tools/widl/widltypes.h, tools/widl/write_msft.c: + Huw Davies + Add enum support. + Another attempt at getting the alignment bits correct. + + * dlls/odbc32/odbc32.spec, dlls/odbc32/proxyodbc.c, + dlls/odbc32/proxyodbc.h: + Alex Villacís Lasso + Implemented Unicode proxy for ODBC. + + * dlls/ole32/regsvr.c, dlls/oleaut32/regsvr.c: + Robert Shearman + - Move OLE automation interface registration to oleaut32. + - Add IRemUnknown to list of interfaces to register. + + * dlls/ole32/oleproxy.c: Robert Shearman + Proxies/stubs for IRemUnknown methods, based on code written by Ove + Kåven. + + * tools/widl/write_msft.c: Huw Davies + Add encoding for VT_R8. + Bug fix: Initialise child_size. + + * dlls/setupapi/misc.c, dlls/setupapi/setupapi.spec: + Eric Kohl + Implement DuplicateString and QueryRegistryValue. + + * dlls/oleaut32/variant.c: + Alex Villacís Lasso + Initialize temporary variants before calling VariantChangeTypeEx. + + * dlls/wininet/http.c: Maxime Bellengé + Replace '\' with '/' in the URL in HTTP_HttpSendRequestW. + + * programs/winepath/winepath.c: + Dmitry Timoshkov + Convert programs/winepath to unicode, print the output string using + Unix locale. + + * dlls/msi/msi.spec, dlls/msi/registry.c, dlls/msi/tests/db.c: + Mike McCormack + Implement, test and document MsiDecomposeDescriptor. + + * tools/widl/parser.y: Huw Davies + unsigned char support. + + * dlls/user/tests/msg.c: Added a couple of SetWindowPos tests. + + * dlls/user/tests/msg.c, dlls/x11drv/winpos.c: + Rein Klazes + Make ShowWindow(...,SW_SHOWNA) also work on already visible windows + with some conformance tests. + + * dlls/msi/action.c: Aric Stewart + Use the new registry functions in registry.c. + Do not force a reboot, just return ERROR_INSTALL_SUSPEND and write + some keys to the registry. + + * dlls/msi/Makefile.in, dlls/msi/msi.c, dlls/msi/msipriv.h, + dlls/msi/registry.c: + Aric Stewart + Move the guid squishing functions out of msi.c and make a new + registry.c file. Also clean up all the various registry keys we need + to open and create to this module and modify the functions for msi.c + to call these functions. + + * dlls/user/scroll.c: Robert Shearman + Add a summary line for several scrollbar functions. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/rpc.c, dlls/ole32/stubmanager.c: + Robert Shearman + - Generate machine-local IPIDs. + - Make pipes be uniquely identified only by their IPID. + + * tools/widl/write_msft.c: Huw Davies + Add interface inheritance. + + * dlls/devenum/createdevenum.c: + Christian Costa + Fixed pin direction when registering audio input device. + + * dlls/shlwapi/tests/string.c: Hans Leidekker + StrIsIntlEqual and IntlStrEqWorker may be absent. + +2005-01-24 Alexandre Julliard + + * configure, configure.ac, dlls/Makefile.in, dlls/wtsapi32/.cvsignore, + dlls/wtsapi32/Makefile.in, dlls/wtsapi32/wtsapi32.c, + dlls/wtsapi32/wtsapi32.spec, include/Makefile.in, include/wtsapi32.h: + Ulrich Czekalla + Added WTSAPI32.DLL. + + * dlls/advapi32/service.c: Mike McCormack + Convert services to use pipes for RPC instead of shared memory. + + * dlls/dmstyle/auditiontrack.c, dlls/dmstyle/chordtrack.c, + dlls/dmstyle/commandtrack.c, dlls/dmstyle/dmstyle_main.c, + dlls/dmstyle/dmstyle_private.h, dlls/dmstyle/motiftrack.c, + dlls/dmstyle/mutetrack.c, dlls/dmstyle/style.c, + dlls/dmstyle/styletrack.c: + James Hawkins + Properly implement DllCanUnloadNow ref counting. + + * dlls/x11drv/xrender.c: Glenn Wurster + Disable antialiasing if the font dictates it. + + * dlls/x11drv/xrender.c: Glenn Wurster + Split caching of antialiased and non-antialiased glyphs. + + * configure, configure.ac, dlls/Makefile.in, dlls/cryptdll/.cvsignore, + dlls/cryptdll/Makefile.in, dlls/cryptdll/cryptdll.c, + dlls/cryptdll/cryptdll.spec: + Ulrich Czekalla + Add stub version of cryptdll.dll. + + * dlls/gdi/freetype.c: Troy Rollo + Don't refuse to process VDMX ratio entries with bCharSet == 0. These + entries are at least as useful as those with bCharSet == 1. Add + comment containing URL of documentation for VDMX records. + + * dlls/comctl32/toolbar.c: Tinus + Properly allow removing toolbar bitmaps by changing it into 0. + + * dlls/x11drv/keyboard.c: Dmitry Timoshkov + Put Brazilian ABNT2 keyboard layouts in line with appropriate virtual + keyboard maps. + + * dlls/x11drv/wintab.c: Robert North <7ownq0k402@sneakemail.com> + Bring wintab in line with Jeremy's X11 event timing patches again. + + * dlls/x11drv/wintab.c: Robert North <7ownq0k402@sneakemail.com> + Add the rule that inverted cursor has -ve altitude, matching behaviour + on Windows wacom tablets. + + * dlls/x11drv/wintab.c: Robert North <7ownq0k402@sneakemail.com> + Packets from eraser cursors are marked as inverted, matching behavior + on Windows Wacom tablets. + + * dlls/wintab32/context.c: Robert North <7ownq0k402@sneakemail.com> + WTEnable, when called to disable tablet context, clears context queue, + as per wintab spec. + + * dlls/dsound/primary.c: Robert Reif + Don't allow other threads to access the primary buffer while the + format is being changed. + + * dlls/x11drv/wintab.c: Robert North <7ownq0k402@sneakemail.com> + - In wintab's default system context, change context options to match + Wacom tablet in windows. + - Change device orientation unit definition to angular. + - Use Macros where appropriate to define cursor and device defaults. + + * dlls/wintab32/context.c: Robert North <7ownq0k402@sneakemail.com> + - Correct overflow 1 message too early. + - Overflow now going onto message queue. + - Overflow state correctly or-ed with other packet status. + + * dlls/setupapi/Makefile.in, dlls/setupapi/misc.c, + dlls/setupapi/setupapi.spec: + Eric Kohl + Implement MyFree, MyMalloc and MyRealloc. + + * tools/widl/write_msft.c: Huw Davies + Add referenced types that aren't already in the typelib. + + * dlls/dsound/buffer.c, dlls/dsound/capture.c, dlls/dsound/dsound.c, + dlls/dsound/dsound_main.c, dlls/dsound/mixer.c, + dlls/dsound/primary.c, dlls/dsound/propset.c, dlls/dsound/regsvr.c, + dlls/dsound/sound3d.c: + Robert Reif + Remove unused includes. + + * dlls/msi/msi.c, dlls/msi/msipriv.h, dlls/msi/package.c: + Avoid unnecessary run-time initializations. + + * dlls/rsaenh/rsaenh.c, dlls/rsaenh/tests/rsaenh.c: + Michael Jung + Support for TLS1 pseudo random function. + Some helper functions for DATA_BLOB's. + Computing TLS1 master secret from the pre-master secret. + Deriving the master hash from the master secret. + Deriving TLS1 MAC and encryption keys from the master hash. + Tests for most of the above. + + * dlls/ntdll/loader.c, dlls/ntdll/ntdll.spec, include/winternl.h: + Ivan Leo Puoti + Added NtLoadDriver and NtUnloadDriver stubs. + + * dlls/d3d9/basetexture.c, dlls/d3d9/cubetexture.c, dlls/d3d9/device.c, + dlls/d3d9/directx.c, dlls/d3d9/indexbuffer.c, + dlls/d3d9/pixelshader.c, dlls/d3d9/query.c, dlls/d3d9/resource.c, + dlls/d3d9/stateblock.c, dlls/d3d9/surface.c, dlls/d3d9/swapchain.c, + dlls/d3d9/texture.c, dlls/d3d9/vertexbuffer.c, + dlls/d3d9/vertexdeclaration.c, dlls/d3d9/vertexshader.c, + dlls/d3d9/volume.c, dlls/d3d9/volumetexture.c, + dlls/d3d8/basetexture.c, dlls/d3d8/cubetexture.c, dlls/d3d8/device.c, + dlls/d3d8/directx.c, dlls/d3d8/indexbuffer.c, dlls/d3d8/resource.c, + dlls/d3d8/surface.c, dlls/d3d8/swapchain.c, dlls/d3d8/texture.c, + dlls/d3d8/vertexbuffer.c, dlls/d3d8/volume.c, + dlls/d3d8/volumetexture.c: + Paul Vriens + - use Interlocked* functions in AddRef and Release. + - store the result of the Interlocked functions and use only this. + + * documentation/faq.sgml: + Tony Lambregts + Add missing /'s to urls http://www.cygwin.com and + http://www.mingw.org. + + * dlls/user/sysparams.c: Bernd Fuhrmann + Added fixme macros in SystemParametersInfoW for several action numbers + that are yet unimplemented. + + * tools/widl/write_msft.c: Huw Davies + Fix handling of void. + + * dlls/dsound/buffer.c, dlls/dsound/capture.c, dlls/dsound/dsound.c, + dlls/dsound/dsound_main.c, dlls/dsound/mixer.c, + dlls/dsound/primary.c, dlls/dsound/propset.c: + Robert Reif + Use Windows memory functions. + + * dlls/wintab32/context.c, dlls/wintab32/wintab32.c, + dlls/x11drv/wintab.c: + Robert North <7ownq0k402@sneakemail.com> + - Don't post messages on Wine message queue, if tablet context flags + posting are disabled. + - When posting messages on Wine message queue, use message base stored + in tablet context, not the default message base. + - Ensure that X11 Proximity events put messages onto Wintab message + queue. + + * dlls/d3drm/version.rc, include/Makefile.in, include/d3drm.h: + Peter Berg Larsen + Added a simple d3drm.h header. + Corrected a copy/paste typo from d3dim. + + * dlls/dmstyle/auditiontrack.c, dlls/dmstyle/chordtrack.c, + dlls/dmstyle/commandtrack.c, dlls/dmstyle/dmstyle_main.c, + dlls/dmstyle/motiftrack.c, dlls/dmstyle/mutetrack.c, + dlls/dmstyle/style.c, dlls/dmstyle/styletrack.c, + dlls/dmscript/dmscript_main.c, dlls/dmscript/script.c, + dlls/dmscript/scripttrack.c: + Paul Vriens + - use Interlocked* functions in AddRef and Release. + - store the result of the Interlocked functions and use only this. + + * dlls/commdlg/cdlg_Es.rc: José Manuel Ferrer Ortiz + Updated Spanish resources. + + * dlls/rsaenh/implglue.c: Michael Jung + Removed another check for valid'ness of algid. It's redundant. + + * dlls/d3d8/shader.c, dlls/dinput/dinput_main.c, + dlls/dinput/joystick_linux.c, dlls/oleaut32/tests/vartest.c: + Rémi Assailly + char -> const char fixes. + + * include/wincrypt.h: Michael Jung + Added CRYPT_SERVER define. + + * tools/widl/write_msft.c: Huw Davies + Add support for hidden and restricted function attributes. + Add support for odl interface attribute. + + * dlls/ntdll/heap.c: Dmitry Timoshkov + Make HeapFree(NULL) case faster by retrieving heap pointer after the + memory block pointer test. + + * dlls/dsound/dsound.c, dlls/dsound/dsound_private.h, + dlls/dsound/mixer.c: + Robert Reif + Fixed memory leak in mixer code. + + * dlls/commdlg/cdlg.h, dlls/commdlg/cdlg_En.rc, + dlls/commdlg/printdlg.c: + Robert Shearman + - Draw a representation of a document in the page setup dialog. + - Change some FIXME's to TRACE's because everything we need is + implemented and they fire for ones that we don't need to implement. + + * dlls/ntdll/virtual.c: Gerald Pfeifer + Fix format string in NtQueryVirtualMemory(). + + * dlls/msi/package.c: Aric Stewart + The new Insert fixes now properly require ?,? instead of just ? for + the Insert call. This fix modifies the MSI_SetProperty query to be + correct. + + * dlls/msi/suminfo.c: Aric Stewart + An implementation of MsiSummaryInfoGetPropertyW based off of + MsiSummaryInfoGetPropertyA. + + * dlls/ole32/compobj_private.h, dlls/ole32/marshal.c: + Robert Shearman + - Add a new flag SORFP_NOLIFETIMEMGMT to tell the proxy manager not to + call any IRemUnknown functions. + - Move the low-level unmarshaling code into a new function, + unmarshal_object, so that it can be easily reused for unmarshaling + IRemUnknown. + + * dlls/x11drv/wintab.c: Robert North <7ownq0k402@sneakemail.com> + Generate Wintab packets for XInput button up/down events. + + * dlls/msi/msi.c: Mike McCormack + Indentation and style cleanup. + +2005-01-21 Alexandre Julliard + + * dlls/user/tests/msg.c, dlls/x11drv/winpos.c: + Tweak SetWindowPos flags handling to make a few more of the messaging + tests pass. + + * tools/widl/write_msft.c: Huw Davies + Bit 0x0200 always appears to be set in the typeinfo's + typekind/alignment member. + + * windows/winpos.c: + Max tracking size in WM_GETMINMAXINFO should take into account the + window frame. + + * tools/widl/write_msft.c: Huw Davies + [local] functions should not be written to the typelib. + + * dlls/msi/action.c, dlls/msi/msipriv.h, dlls/msi/msiquery.c: + Mike McCormack + Move OpenQuery into msiquery.c and make it non-static. + + * dlls/comctl32/status.c: Gunnar Dalsnes + Ge van Geldorp + STATUSBAR_SetTextT: + - ntext wasn't freed on return if text was unicode + - part->text was always freed, but if the previous style was + SBT_OWNERDRAW, part->text would contain 32bit data + - free old text if new style is SBT_OWNERDRAW but old style wasn't + + * dlls/shlwapi/tests/shreg.c: Paul Vriens + - More verbose output of errors. + - Bail out if first test fails (produce one error only). + + * dlls/ttydrv/wnd.c, dlls/user/scroll.c, dlls/user/user32.spec, + dlls/x11drv/window.c, dlls/x11drv/winpos.c, include/win.h, + windows/defwnd.c, windows/win.c: + Make WIN_SetStyle more thread-safe by specifying the bits to change + instead of the new value. + + * tools/widl/proxy.c: Rémi Assailly + Small char -> const char fix. + + * dlls/d3dx8/d3dxbuffer.c, dlls/dmband/band.c, dlls/dmband/bandtrack.c, + dlls/dmband/dmband_main.c: + Paul Vriens + - Use Interlocked* functions in AddRef and Release. + - Store the result of the Interlocked functions and use only this. + + * dlls/msi/Makefile.in, dlls/msi/msi.spec, dlls/msi/msipriv.h, + dlls/msi/preview.c: + Mike McCormack + Added stub implementations for MsiPreviewDialog and + MsiPreviewBillboard. + + * dlls/msi/msiquery.c: Mike McCormack + Lock record in MsiViewExecute, move stubs to end. + + * dlls/shell32/shlview.c: Mike McCormack + Implement GetAdvise and SetAdvise. + + * include/ntsecapi.h: Juan Lang + Added some definitions. + + * dlls/ole32/rpc.c: Mike Hearn + Various formatting/style changes. + + * programs/winetest/Makefile.in: + Stefan Leichter + Include new tests. + + * dlls/quartz/regsvr.c: Mike Hearn + Fix heap corruption in quartz server registration, add some + whitespace, break out of loop if out of memory. + +2005-01-20 Alexandre Julliard + + * dlls/user/sysparams.c, dlls/user/tests/sysparams.c: + Justin Chevrier + - Implemented SPI_SETICONMETRICS. + - Fixed SPI_GETICONTITLELOGFONT to only return values retrieved from + win.ini on first call and return a cached version in subsequent + calls. + - Created unit test for SPI_{GET,SET}ICONMETRICS. + + * dlls/msi/insert.c, dlls/msi/sql.y, dlls/msi/tests/db.c: + Mike McCormack + Fix and test inserting records. + + * dlls/x11drv/event.c, dlls/x11drv/window.c, dlls/x11drv/x11drv.h, + dlls/x11drv/xfont.c: + Rémi Assailly + Added missing declarations. + + * dlls/msi/handle.c, dlls/msi/msi.c, dlls/msi/msipriv.h, + dlls/msi/msiquery.c: + Mike McCormack + Fix refcounting, use Interlocked functions. + + * tools/widl/parser.y: Huw Davies + Don't set ATTR_IN or ATTR_OUT by default - this essentially reverts + rev. 1.21. The proxy code must explicitly add these if they're + needed. + + * tools/widl/write_msft.c: Huw Davies + Better guid hash. + + * dlls/user/menu.c, dlls/user/scroll.c, dlls/x11drv/event.c, + dlls/x11drv/window.c, dlls/x11drv/winpos.c, windows/dialog.c, + windows/mdi.c, windows/nonclient.c, windows/win.c, windows/winpos.c: + Replace a number of calls to WIN_FindWndPtr by WIN_GetPtr. + + * configure, configure.ac, dlls/advpack/Makefile.in, + dlls/advpack/advpack.c, dlls/advpack/advpack.spec, + dlls/advpack/tests/.cvsignore, dlls/advpack/tests/Makefile.in, + dlls/advpack/tests/advpack.c, include/advpub.h: + Robert Reif + Added stubs for NeedRebootInit and NeedReboot. + Added implementations for GetVersionFromFile and + GetVersionFromFileEx. + Added test for GetVersionFromFile. + + * dlls/ntdll/virtual.c, dlls/psapi/psapi.spec, dlls/psapi/psapi_main.c, + include/psapi.h, include/winternl.h: + Hans Leidekker + Stub implementations for EnumPageFiles{A,W}, GetProcessImageFileName{A,W}. + Implement GetPerformanceInfo, GetProcessMemoryInfo on top of + NtQueryInformationProcess and GetWsChanges, QueryWorkingSet{,Ex} on + top of NtQueryVirtualMemory. + + * dlls/user/misc.c, dlls/user/user32.spec: + Tanabe Hiroshi + Added stubs for SendIMEMessageEx[A,W]. + + * dlls/msi/table.c: Mike McCormack + Fix a bug caused by freeing memory too soon in the table code. + + * tools/widl/write_msft.c: Huw Davies + MIDL adds two sets of custom data to the library: one is a timestamp + and the second is MIDL's version number. + + * dlls/commdlg/cdlg_Ru.rc: Dmitry Timoshkov + Correct coordinates of a couple of controls. + + * include/msiquery.h: Mike McCormack + Declare the preview functions. + + * dlls/d3dxof/d3dxof.c, dlls/d3dxof/d3dxof_private.h: + Paul Vriens + - Use Interlocked* functions in AddRef and Release. + - Store the result of the Interlocked functions and use only this. + + * dlls/ntdll/time.c: Tony Lambregts + Added time zone information for SAMT (Samara Standard Time). + + * dlls/ntdll/sec.c: Ulrich Czekalla + ACL fixes and cleanups. + + * dlls/cfgmgr32/cfgmgr32.spec, dlls/cfgmgr32/main.c: + + Added some stub implementations. + + * dlls/msi/action.c, dlls/msi/cond.y, dlls/msi/distinct.c, + dlls/msi/msi.c, dlls/msi/order.c, dlls/msi/package.c, + dlls/msi/string.c, dlls/msi/suminfo.c, dlls/msi/table.c, + dlls/msi/where.c: + Michael Stefaniuc + Do not check for non NULL pointer before HeapFree'ing it. It's + redundant. + + * dlls/ole32/compobj.c, dlls/ole32/marshal.c: + Robert Shearman + - Consolidate more stub creation details into register_ifstub. + - Replace the current wine_marshal_id structure with STDOBJREF for the + on-the-wire format. + + * dlls/netapi32/netapi32.spec, dlls/netapi32/wksta.c, + include/Makefile.in, include/lm.h, include/lmjoin.h: + Ulrich Czekalla + Added stub implementation of NetGetJoinInformation. + +2005-01-19 Alexandre Julliard + + * dlls/kernel/locale.c, dlls/kernel/nls/ukr.nls, dlls/mlang/mlang.c, + dlls/x11drv/keyboard.c, dlls/x11drv/xfont.c, + libs/unicode/Makefile.in, libs/unicode/c_21866.c, + libs/unicode/cpmap.pl, libs/unicode/cptable.c: + Oleh R. Nykyforchyn + Ukrainian codepage 21866 added and respective files corrected. Two + keyboard layouts (for Ukrainian and Russian) added. + + * include/wine/wined3d_interface.h: + Michael Stefaniuc + Hack to fix the compile. + + * windows/win.c: Ulrich Czekalla + Handle case when only height is set to CW_USEDEFAULT. + + * documentation/winedev-coding.sgml: + Bill Medland + Trivial language corrections to the Wine Developer's Guide coding + section. + + * dlls/user/edit.c: Lauri Tulmin + Reposition caret after window resize. + + * dlls/wined3d/Makefile.in, dlls/wined3d/vertexdeclaration.c, + dlls/wined3d/wined3d_private.h, include/wine/wined3d_interface.h: + Raphael Junqueira + Begin support of VertexDeclaration on wined3d using d3d8 code base + (handling d3d8 and d3d9 specs). + + * windows/cursoricon.c: Vitaly Lipatov + Add FIXME for file with broken counters. + + * dlls/user/edit.c: Lauri Tulmin + Don't recalculate line indexes if number of lines doesn't change. + + * tools/widl/typelib_struct.h, tools/widl/write_msft.c: + Huw Davies + Add propget and propput function attributes. + Clarify the meaning of the FKCCIC bit field. + + * dlls/msi/action.c, dlls/msi/msipriv.h: + Aric Stewart + Quite a few fixes: + - Allow for the queing of custom actions to trigger on the + InstallExecute or InstallExecuteAgain actions. + - allow for the queing of custom actions to trigger on + InstallFinalize. + - Properly set the CustomActionData property for said queued actions. + - Implement RegisterProduct. + - Beginning implementation of ForceReboot. + - Don't kill install if an item to be duplicated does not exist. + - Write out SourceList and LastUsedSource for resuming installs. + - Use regsvr32 to register self reg dlls. + + * dlls/shdocvw/misc.c, dlls/shdocvw/shdocvw.spec: + Mike McCormack + Stub definition for OpenUrl. + + * include/win.h, windows/win.c: + Removed no longer used WIN_InternalShowOwnedPopups function. + + * dlls/ttydrv/wnd.c: + Store the window id as a property instead of accessing the WND + structure directly. + Fetch the update region from the server and remove a lot of obsolete + code. + + * dlls/kernel/cpu.c: Rein Klazes + Return a fixed frequency of 1193182 Hz for the Performance Counter. + + * dlls/kernel/sync.c: Mike McCormack + Implement TransactNamedPipe for the non-overlapped case. + + * dlls/atl/atl.spec, dlls/atl/atl_main.c: + Mike McCormack + Stub implementation for some functions. + + * dlls/ole32/marshal.c, dlls/ole32/oleproxy.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + - Initialize ppv pointer in ClientIdentity_QueryInterface to NULL as + apps depend on this. + - Don't release IRpcProxyBuffer on ifproxy destruction - the caller + will do this for us. + - Make find_proxy_manager add a reference to the proxy manager and + make proxy_manager_construct return an object with a valid + ref-count. + - Remove stray not operator to fix a memory leak / crash in + proxy_manager_destroy. + - More debug messages, especially on errors. + - Fix ref-count leak in the Class Factory proxy. + - Add a test case for IClassFactory_CreateInstance. + + * programs/winecfg/driveui.c: Paul van Schayck + Reset the type dropdown when selecting another drive. + + * dlls/version/tests/info.c: + Stefan Leichter + Fixed GetFileVersionInfoSizeA tests on WinME. + + * dlls/rsaenh/rsaenh.c: Michael Jung + Avoid code duplication by moving handle lookup into get_algid_info. + + * dlls/wined3d/basetexture.c, dlls/wined3d/indexbuffer.c, + dlls/wined3d/resource.c, dlls/wined3d/surface.c, + dlls/wined3d/vertexbuffer.c: + Joris Huizer + Get rid of some TRACE(..., This->resource.ref). + + * tools/widl/write_msft.c: Huw Davies + Pad small strings out to eight bytes. + Fix 'has default values' flag. + + * dlls/msi/msi.c, dlls/msi/msi.spec: + Aric Stewart + Do a very basic first implementation of MsiConfigureProductExW for + msiexec /@ when run as a reboot. + Also add a number of new stubs for the office xp and 2k3 install and + startup process. + + * include/msi.h: Mike McCormack + Added definition for the USERINFOSTATE enumeration. + + * dlls/setupapi/devinst.c, dlls/setupapi/setupapi.spec: + Mike McCormack + Aric Stewart + Mike McCormack + Added some stub implementations. + +2005-01-18 Alexandre Julliard + + * dlls/user/msg16.c, include/winpos.h, windows/defwnd.c, + windows/winpos.c: + Moved DefWindowProc16 to msg16.c and cleaned up a few related things. + + * dlls/wininet/internet.c, dlls/wininet/tests/http.c, + dlls/wininet/wininet.spec, include/wininet.h: + Hans Leidekker + Implement and test InternetTime{From,To}SystemTime{A,W}. + Correct spelling in InternetCheckConnectionA. + + * dlls/d3d9/cubetexture.c, dlls/d3d9/device.c, dlls/d3d9/directx.c, + dlls/d3d9/indexbuffer.c, dlls/d3d9/surface.c, dlls/d3d9/texture.c, + dlls/d3d9/vertexbuffer.c, dlls/d3d9/volume.c, + dlls/d3d9/volumetexture.c, dlls/wined3d/device.c, + dlls/wined3d/directx.c, dlls/wined3d/surface.c, + dlls/wined3d/wined3d_private.h, include/d3d9types.h, + include/wine/wined3d_interface.h: + Jason Edmeades + - Handle failures to allocate storage more gracefully. + - Only prototype the interfaces which are subclassed (I overdid it + last time!). + - Implement Get/Set Texture and GetBackBuffer, plus device's + GetDisplayMode / GetDeviceCaps. + - Make some of the d3d9 skeleton code issue fixme's to highlight code + which hasn't been migrated yet. + - Correct the d3d9 headers for D3DSURFACE_DESC which caused stack + corruption in demos. + + * include/winsvc.h: Mike McCormack + Add definitions for session change notifications. + + * dlls/mpr/netspi.h, dlls/mpr/nps.c, include/Makefile.in, + include/netspi.h: + Juan Lang + Make netspi.h private, as some of its declarations conflict with + npapi.h. Spotted by Paul Vriens. + + * dlls/setupapi/queue.c: Aric Stewart + Copy the implementation from SetupDefaultQueueCallbackA and make it + W. + + * tools/widl/write_msft.c: Huw Davies + Add a missing break to fix typeinfo version regression. + + * dlls/shlwapi/path.c, dlls/shlwapi/reg.c, dlls/shlwapi/shlwapi.spec: + Hans Leidekker + Stub implementations for PathUnExpandEnvStringsSHRegEnumUSValue{A,W}, + SHRegCreateUSKey{A,W}, SHRegDeleteEmptyUSKey{A,W}, + SHRegDeleteUSValue{A,W}, SHRegEnumUSValue{A,W}. + +2005-01-17 Alexandre Julliard + + * dlls/user/controls.h, dlls/user/menu.c, dlls/user/user32.spec, + dlls/x11drv/winpos.c, include/nonclient.h, windows/defwnd.c, + windows/mdi.c, windows/nonclient.c, windows/winpos.c: + Get rid of nonclient.h and of the corresponding exported functions in + user32.spec. + + * dlls/oleaut32/tests/vartest.c, dlls/oleaut32/variant.c: + Alex Villacís Lasso + When parsing an hex/oct integer value, copy value verbatim in VARIANT, + rather than a negated value. Add test case for this behavior. + + * dlls/shell32/shell32_De.rc: + Henning Gerhardt + A small spelling fix and a small update (thank to Andreas Mohr). + + * dlls/ole32/marshal.c: Robert Shearman + Initialize clsid member to the marshaler clsid to fix custom + marshaling. + + * dlls/user/edit.c: Lauri Tulmin + Make long lines behave nicely. + + * dlls/x11drv/clipboard.c, dlls/x11drv/event.c, dlls/x11drv/mouse.c, + dlls/x11drv/scroll.c, dlls/x11drv/window.c, dlls/x11drv/winpos.c, + dlls/x11drv/x11drv.h, dlls/x11drv/x11drv_main.c, windows/defwnd.c: + Avoid most references to the internals of the WND structure by passing + around an x11drv_win_data pointer instead. + + * dlls/user/edit.c, dlls/user/user32.spec, dlls/x11drv/winpos.c: + Removed a couple of unnecessary calls to WIN_SuspendWndsLock. + + * dlls/shlwapi/tests/shreg.c: Paul Vriens + Use a registry key for copying, that's known on every system. + + * dlls/commdlg/cdlg_Fr.rc, dlls/mpr/mpr.rc, dlls/mpr/mpr_Fr.rc, + dlls/oledlg/oledlg_Fr.rc, dlls/oledlg/rsrc.rc, + dlls/wininet/wininet_Fr.rc: + Jonathan Ernst + Updated French resources. + + * dlls/msvideo/drawdib.c, dlls/msvideo/msvfw32.spec, + dlls/msvideo/msvideo_main.c, include/vfw.h: + Hans Leidekker + Stub implementations for DrawDibChangePalette, DrawDibGetBuffer, + DrawDibTime, ICSeqCompressFrame{,End,Start}. + Forward GetOpenFileNamePreview to GetOpenFileNamePreviewA. + + * dlls/shlwapi/reg.c, dlls/shlwapi/tests/shreg.c: + Paul Vriens + Change the order of Src and Dst in CopyKey calls/functions. + + * windows/winpos.c: Small optimization in WINPOS_GetWinOffset. + + * dlls/user/user_main.c, dlls/user/user_private.h, + dlls/x11drv/winpos.c, dlls/x11drv/x11drv.spec: + Removed unused ForceWindowRaise function. + + * dlls/d3d9/basetexture.c, dlls/d3d9/cubetexture.c, + dlls/d3d9/d3d9_private.h, dlls/d3d9/device.c, dlls/d3d9/resource.c, + dlls/d3d9/surface.c, dlls/d3d9/texture.c, dlls/d3d9/volume.c, + dlls/d3d9/volumetexture.c, dlls/wined3d/Makefile.in, + dlls/wined3d/basetexture.c, dlls/wined3d/cubetexture.c, + dlls/wined3d/device.c, dlls/wined3d/drawprim.c, + dlls/wined3d/indexbuffer.c, dlls/wined3d/surface.c, + dlls/wined3d/texture.c, dlls/wined3d/utils.c, + dlls/wined3d/vertexbuffer.c, dlls/wined3d/volume.c, + dlls/wined3d/volumetexture.c, dlls/wined3d/wined3d_private.h, + include/wine/wined3d_interface.h: + Jason Edmeades + - Add texture support for all the texture types for d3d9->wined3d. + - Add prototypes for the COM interfaces. + - Fix some incorrect types from the last patch. + + * dlls/winmm/winmm_De.rc: Klemens Friedl + Henning Gerhardt + Spelling fixes. + + * dlls/commdlg/cdlg_De.rc, dlls/mpr/mpr_De.rc, + dlls/shell32/shell32_De.rc, dlls/wininet/wininet_De.rc, + programs/wineconsole/wineconsole_De.rc: + Henning Gerhardt + Update German resources. + + * include/wincrypt.h: Michael Jung + Added definitions of TLS1PRF algorithm identifiers. + + * dlls/shlwapi/tests/clist.c: Paul Vriens + Use Interlocked* functions in AddRef and Release. + + * programs/winecfg/libraries.c: Gerald Pfeifer + Use switch statements instead of if-cascades. Avoid warnings. + + * dlls/rsaenh/rsaenh.c: Michael Jung + Moved HMAC initialization and finalization code to + init_/finalize_hash. + Removed the redundant pKeyContainer function parameter from + init_hash. + + * tools/widl/write_msft.c: Huw Davies + Add VT_VARIANT support. + Fix for the case when there is no helpstringdll. + Fix for parameter arrays. + + * dlls/msi/action.c: Aric Stewart + Implementations for SelfRegModules and PublishFeatures. + Set default ACTION property for Install. + Deformat more than JUST properties properly. Allows for Files and + Component paths in deformat. + Properly deformat a LaunchCondition failure dialog box. + Resolve and save registry Keypaths. + Write the Features published keys more correctly. Still some + problems. + + * dlls/msi/msi.c: Aric Stewart + First pass implement ion of MsiQueryProductState[A/W] as well as a few + fixes for MsiGetComponentPath. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h, + dlls/ole32/marshal.c, dlls/ole32/stubmanager.c, + dlls/ole32/tests/marshal.c: + Robert Shearman + Implement table marshaling. + + * programs/winetest/Makefile.in: + Stefan Leichter + Include new tests. + + * dlls/comctl32/trackbar.c: Paul Vriens + Remove the checking/setting of the defaults in TRACKBAR_Create. + + * dlls/comctl32/pager.c: Paul Vriens + Remove needless check for horizontal or vertical pager. + +2005-01-14 Alexandre Julliard + + * dlls/kernel/comm.c, dlls/kernel/file.c, dlls/ntdll/file.c, + dlls/ntdll/sync.c, dlls/winsock/socket.c, include/async.h, + include/thread.h, include/wine/server_protocol.h, server/Makefile.in, + server/async.c, server/async.h, server/fd.c, server/file.c, + server/file.h, server/named_pipe.c, server/process.c, + server/protocol.def, server/request.c, server/request.h, + server/serial.c, server/signal.c, server/sock.c, server/thread.c, + server/trace.c: + Eric Pouech + - got rid of include/async.h + - fixed some overlapped issues in socket handling + - moved kernel32.CancelIo implementation to ntdll + + * programs/winecfg/appdefaults.c, programs/winecfg/audio.c, + programs/winecfg/libraries.c, programs/winecfg/winecfg.c, + programs/winecfg/x11drvdlg.c: + Crestez Leonard + Fix add application (memory error). + Fix apply button lighting up in audio tab. + Fix video tab(crash when checking desktop, apply button not lighting + up. + Deal with invalid Desktop registry value in video tab. + Fix apply button in libraries tab. + Cleaned up and documented all the conversions in the libraries tab. + + * dlls/itss/itss.c, dlls/itss/itss.spec: + Robert Shearman + Remove MODULENAME prefix from + Dll{GetClassObject,RegisterServer,CanUnloadNow} functions. + + * tools/widl/write_msft.c: Huw Davies + Add support for BSTR default values. + + * dlls/ole32/compobj_private.h: Robert Shearman + - Remove obsolete structs, rearrange things to group the structs + together and to group similar functions. + - Document thread-safety of members of structs. + + * dlls/ole32/marshal.c, dlls/ole32/tests/marshal.c: + Robert Shearman + Make proxy shutdown test succeed by releasing the channel on + disconnect. + + * dlls/x11drv/event.c, dlls/x11drv/keyboard.c, dlls/x11drv/mouse.c, + dlls/x11drv/window.c, dlls/x11drv/wintab.c, dlls/x11drv/x11drv.h, + dlls/x11drv/x11drv_main.c: + Jeremy White + Fix X11 event timing so that we correctly correlate X11 timing and + Wine timing and dynamically adjust it as we go. + + * dlls/msi/msi.c: Aric Stewart + Actually start on an implemention for MsiGetComponentPathW that should + handle all keypaths that are files. + + * dlls/ole32/compobj.c, dlls/ole32/ifs.c, dlls/ole32/ole2.c, + dlls/ole32/ole2stubs.c: + Robert Shearman + - Add documentation for most Co* functions. + - Move several functions into different files to group them with + similar functions. + + * dlls/dmsynth/dmsynth_main.c, dlls/dmsynth/synth.c, + dlls/dmsynth/synthsink.c, dlls/dpnet/address.c, dlls/dpnet/client.c: + James Hawkins + - Use Interlocked* instead of ++/-- in AddRef/Release. + - Use only stored result of Interlocked* in AddRef/Release. + - Expand TRACEs to display the ref count. + + * dlls/shell32/shlfileop.c: Joris Huizer + - add file_operation_delete + - add file_operation_checkFlags + - use these in SHFileOperationW replacing inline code + + * dlls/advapi32/service.c, include/winsvc.h: + Mike McCormack + Fix, add and rearrange winsvc.h declarations. + + * dlls/msi/action.c: Marcus Meissner + Initialize rc in create_component_directory(). + + * tools/widl/typelib.c, tools/widl/write_msft.c: + Huw Davies + Add support for interface ptrs including the special cases for + IUnknown and IDispatch. + + * dlls/commdlg/filedlg.c: Ulrich Czekalla + GetFileName31W should call unicode version of FD31_AllocPrivate. + + * dlls/user/tests/sysparams.c: Justin Chevrier + Created unit test for SPI_{GET,SET}MINIMIZEDMETRICS. + + * dlls/user/sysparams.c: Justin Chevrier + - Implemented SPI_GETMINIMIZEDMETRICS calculated from values returned + by GetSystemMetrics. + - Implemented SPI_SETMINIMIZEDMETRICS. Determined that the values set + here are valid for the current session only and will not persist + across reboots. + + * dlls/ole32/compobj_private.h, dlls/ole32/marshal.c, dlls/ole32/rpc.c, + dlls/ole32/stubmanager.c, dlls/ole32/tests/marshal.c: + Robert Shearman + - The apartment reference should be held while the stub manager + reference is held. + - Fix same apartment-unmarshal detection. + + * dlls/comctl32/listview.c: Dimitrie O. Paun + Use the LVCFMT_{LEFT,RIGHT,CENTER} enumeration flags properly. + + * dlls/winedos/int21.c: Rein Klazes + In int21_ioctl - get device data-, set the "is console" bits if the + device handle is a tty or a proper console io handle. + + * dlls/advapi32/service.c: Mike McCormack + Move all service stubs together, make them consistent. + + * dlls/dmusic/buffer.c, dlls/dmusic/clock.c, dlls/dmusic/collection.c, + dlls/dmusic/dmusic.c, dlls/dmusic/dmusic_main.c, + dlls/dmusic/download.c, dlls/dmusic/downloadedinstrument.c, + dlls/dmusic/instrument.c, dlls/dmusic/port.c, + dlls/dmusic/portdownload.c, dlls/dmusic/thru.c, dlls/dswave/dswave.c, + dlls/dswave/dswave_main.c, dlls/dxdiagn/container.c, + dlls/dxdiagn/provider.c, dlls/msdmo/dmoreg.c, dlls/oleaut32/connpt.c, + dlls/oleaut32/dispatch.c, dlls/oleaut32/olepicture.c, + dlls/oleaut32/tmarshal.c, dlls/shdocvw/classinfo.c, + dlls/shdocvw/events.c, dlls/shdocvw/factory.c, dlls/shdocvw/misc.c, + dlls/shdocvw/oleobject.c, dlls/shdocvw/persist.c, + dlls/shdocvw/webbrowser.c, dlls/shell32/autocomplete.c, + dlls/shell32/cpanelfolder.c, dlls/shell32/dataobject.c, + dlls/shell32/dragdrophelper.c, dlls/shell32/enumidlist.c, + dlls/shell32/folders.c, dlls/shell32/memorystream.c, + dlls/shell32/shelllink.c, dlls/shell32/shellole.c, + dlls/shell32/shfldr_desktop.c, dlls/shell32/shfldr_fs.c, + dlls/shell32/shfldr_mycomp.c, dlls/shell32/shlfsbind.c, + dlls/shell32/shlview.c, dlls/shell32/shv_bg_cmenu.c, + dlls/shell32/shv_item_cmenu.c: + James Hawkins + - Use Interlocked* instead of ++/-- in AddRef/Release. + - Use only stored result of Interlocked* in AddRef/Release. + - Expand TRACEs to display the ref count. + + * dlls/msi/action.c: Aric Stewart + First implementation of the WriteIniValues action. + + * dlls/ole32/rpc.c: Robert Shearman + - Don't use the pipe caching code because it doesn't work correctly at + the moment. + - Always write disconnect reply packet, even in failure cases. + + * include/winuser.h, windows/spy.c: + Dmitry Timoshkov + Add WM_GETOBJECT definition, remove WM_OTHERWINDOWCREATED define. + + * documentation/patches.sgml: Dimitrie O. Paun + Suggest testing patches in a gentler way. + Encourage people to submit tests with their patches as well. + + * dlls/shell32/shell32_De.rc: Klemens Friedl + Update German language file. + + * dlls/advapi32/service.c: Mike McCormack + Cleanup service handles. + + * dlls/comctl32/treeview.c: Jon Griffiths + Increase the required rectangle size before drawing big +/-. + + * dlls/gdi/mfdrv/objects.c, dlls/gdi/tests/metafile.c: + Walt Ogburn + Fix BS_PATTERN brushes in mfdrv. Un-comment the corresponding test. + + * dlls/dsound/dsound_main.c: James Hawkins + Return CLASS_E_NOAGGREGATION if pUnkOuter is non-null. + + * dlls/msi/action.c: Aric Stewart + Custom actions can have null in their target parameters, handle that + without crashing. Also enable deformating of lines greater than 256 + characters. + + * dlls/ole32/compobj.c: Robert Shearman + Destroy stubs on apartment shutdown. + + * dlls/rpcrt4/rpcrt4_main.c, include/rpcdce.h: + Ge van Geldorp + Fix prototypes according to PSDK. + + * dlls/ole32/rpc.c: Mike Hearn + Force context switch on chanbuf disconnect to avoid a race in the test + suite. + + * include/wine/list.h: Robert Shearman + Add a LIST_FOR_EACH_ENTRY list helper. + + * dlls/avifil32/acmstream.c, dlls/avifil32/avifile.c, + dlls/avifil32/editstream.c, dlls/avifil32/getframe.c, + dlls/avifil32/icmstream.c, dlls/avifil32/tmpfile.c, + dlls/avifil32/wavfile.c: + Paul Vriens + - use Interlocked* functions in AddRef and Release. + - store the result of the Interlocked functions and use only this. + +2005-01-12 Alexandre Julliard + + * dlls/ole32/compobj.c: Christian Costa + CoInitialize(Ex) should return S_FALSE when COM is already initialized + for the current thread. + + * dlls/gdi/gdi32.spec, windows/dce.c: + Use the exported functions SaveDC/RestoreDC instead of SetDCState16. + + * dlls/winmm/winealsa/audio.c, dlls/winmm/wineaudioio/audio.c, + dlls/winmm/wineoss/dscapture.c, dlls/winmm/wineoss/dsrender.c: + James Hawkins + - Use Interlocked* instead of ++/-- in AddRef/Release. + - Use only stored result of Interlocked* in AddRef/Release. + - Expand TRACEs to display the ref count. + + * dlls/urlmon/sec_mgr.c, dlls/urlmon/umon.c: + James Hawkins + - Use only stored result of Interlocked* in AddRef/Release. + - Expand TRACEs to display the ref count. + + * dlls/wined3d/device.c, dlls/wined3d/directx.c, + dlls/wined3d/stateblock.c: + James Hawkins + Use only stored result of Interlocked* in AddRef/Release. + + * dlls/ole32/compobj.c, dlls/ole32/compobj_private.h: + Robert Shearman + - Document CoSetState & CoGetState. + - Rewrite them to only retrieve TLS info once. + - Remove trailing whitespace in COM_CurrentInfo. + + * dlls/ole32/marshal.c: Robert Shearman + Remove wine_marshal_data: it is unneeded and there is no equivalent in + STDOBJREF. + + * dlls/shlwapi/assoc.c, dlls/shlwapi/istream.c, + dlls/shlwapi/regstream.c: + James Hawkins + - use only stored result of Interlocked* in AddRef/Release + - expand TRACEs to display the ref count + + * dlls/avifil32/acmstream.c, dlls/avifil32/icmstream.c: + Paul Vriens + - Fix logic in Stream_fnRelease, refcount should be decremented before + the test for 0. + - Use Interlocked* functions in Stream_fnRelease . + - Store the result of the Interlocked functions and this in the + TRACE. + + * tools/widl/typelib.c, tools/widl/typelib.h, tools/widl/write_msft.c: + Huw Davies + Better type encoding. (Interface ptrs still not there yet). + + * dlls/ole32/tests/marshal.c: Robert Shearman + - Force creation of thread queue to stop PostThreadMessage from + failing. + - Remove incorrect comment. + + * dlls/user/sysparams.c: Justin Chevrier + - Revert previous change of border metric to reference the + registry. Testing on Win98/WinXP showed that regardless of the + "BorderWidth" value CM_C{X,Y}BORDER always returns 1. + - Point SPI_SETBORDER to "BorderWidth" under "HKCU\Control + Panel\Desktop\WindowMetrics" instead of "HKCU\Control Panel\Desktop" + to make it match Windows. + + * include/wine/list.h: Robert Shearman + Add LIST_FOR_EACH_SAFE - a list iteration macro that is safe against + removal. + + * dlls/ole32/rpc.c: Robert Shearman + The way apartments are used has changed, so fix up the hacks in the + RPC code that haven't yet been updated. + + * dlls/ole32/compobj.c: Robert Shearman + - Make MTA dynamically allocated so that proxies and other resources + are freed at the proper time. + - Changed/removed some incorrect comments regarding apartments. + + * dlls/dmcompos/chordmap.c, dlls/dmcompos/chordmaptrack.c, + dlls/dmcompos/composer.c, dlls/dmcompos/signposttrack.c: + Paul Vriens + - use Interlocked* functions in AddRef and Release. + - store the result of the Interlocked functions and use only this. + +2005-01-11 Alexandre Julliard + + * ANNOUNCE, ChangeLog, VERSION, configure: Release 20050111. + +---------------------------------------------------------------- 2005-01-11 Alexandre Julliard * dlls/dmime/audiopath.c, dlls/dmime/dmime_main.c, dlls/dmime/graph.c, diff -urN wine-20050111/Make.rules.in wine-20050211/Make.rules.in --- wine-20050111/Make.rules.in 2004-10-07 05:12:44.000000000 +0200 +++ wine-20050211/Make.rules.in 2005-02-08 13:13:10.000000000 +0100 @@ -113,7 +113,7 @@ # Implicit rules -.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.c .spec.def .idl .h .ok .sfd .ttf +.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.c .spec.def .idl .tlb .h .ok .sfd .ttf .c.o: $(CC) -c $(ALLCFLAGS) -o $@ $< @@ -139,6 +139,9 @@ .idl.h: $(WIDL) $(IDLFLAGS) -h -H $@ $< +.idl.tlb: + $(WIDL) $(IDLFLAGS) -t -T $@ $< + .c.ln: $(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 ) @@ -162,7 +165,7 @@ $(RC_BINARIES): $(BIN2RES) $(RC_BINSRC) $(BIN2RES) -f -o $@ $(SRCDIR)/$(RC_BINSRC) -$(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res): $(WRC) $(RC_BINARIES) +$(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res): $(WRC) $(RC_BINARIES) $(RC_TLB) # Rule for main module debug channels @@ -219,7 +222,7 @@ testclean:: $(SUBDIRS:%=%/__testclean__) clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__) - $(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(IDL_SRCS:.idl=.h) $(PROGRAMS) $(RC_BINARIES) + $(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(IDL_SRCS:.idl=.h) $(PROGRAMS) $(RC_BINARIES) $(RC_TLB) .PHONY: clean testclean $(SUBDIRS:%=%/__clean__) $(SUBDIRS:%=%/__testclean__) $(EXTRASUBDIRS:%=%/__clean__) @@ -268,6 +271,8 @@ $(IDL_SRCS:.idl=.h): $(WIDL) +$(RC_TLB:.idl=.tlb): $(WIDL) + $(SUBDIRS): dummy @cd $@ && $(MAKE) diff -urN wine-20050111/VERSION wine-20050211/VERSION --- wine-20050111/VERSION 2005-01-11 20:08:58.000000000 +0100 +++ wine-20050211/VERSION 2005-02-11 14:34:18.000000000 +0100 @@ -1 +1 @@ -Wine version 20050111 +Wine version 20050211 diff -urN wine-20050111/aclocal.m4 wine-20050211/aclocal.m4 --- wine-20050111/aclocal.m4 2004-09-22 21:17:55.000000000 +0200 +++ wine-20050211/aclocal.m4 2005-02-10 20:19:36.000000000 +0100 @@ -111,7 +111,7 @@ fi rm -f conf$$ conf$$.file]) -dnl **** Create non-existent directories from config.status **** +dnl **** Create nonexistent directories from config.status **** dnl dnl Usage: WINE_CONFIG_EXTRA_DIR(dirname) dnl diff -urN wine-20050111/configure wine-20050211/configure --- wine-20050111/configure 2005-01-11 20:08:58.000000000 +0100 +++ wine-20050211/configure 2005-02-11 14:34:18.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 20050111. +# Generated by GNU Autoconf 2.59 for Wine 20050211. # # Report bugs to . # @@ -269,8 +269,8 @@ # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='20050111' -PACKAGE_STRING='Wine 20050111' +PACKAGE_VERSION='20050211' +PACKAGE_STRING='Wine 20050211' 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 20050111 to adapt to many kinds of systems. +\`configure' configures Wine 20050211 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 20050111:";; + short | recursive ) echo "Configuration of Wine 20050211:";; esac cat <<\_ACEOF @@ -984,7 +984,7 @@ test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -Wine configure 20050111 +Wine configure 20050211 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 20050111, which was +It was created by Wine $as_me 20050211, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1487,6 +1487,7 @@ test -n "$CC" || CC="gcc -m32" test -n "$LD" || LD="ld -m elf_i386" test -n "$AS" || AS="as --32" + host_cpu="i386" fi ;; esac @@ -19985,7 +19986,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/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/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/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/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/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/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 @@ -20350,7 +20351,7 @@ } >&5 cat >&5 <<_CSEOF -This file was extended by Wine $as_me 20050111, which was +This file was extended by Wine $as_me 20050211, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -20413,7 +20414,7 @@ cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 20050111 +Wine config.status 20050211 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" @@ -20526,6 +20527,7 @@ "dlls/advapi32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/advapi32/Makefile" ;; "dlls/advapi32/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/advapi32/tests/Makefile" ;; "dlls/advpack/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/advpack/Makefile" ;; + "dlls/advpack/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/advpack/tests/Makefile" ;; "dlls/amstream/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/amstream/Makefile" ;; "dlls/atl/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/atl/Makefile" ;; "dlls/avicap32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/avicap32/Makefile" ;; @@ -20540,6 +20542,7 @@ "dlls/commdlg/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/commdlg/Makefile" ;; "dlls/crtdll/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/crtdll/Makefile" ;; "dlls/crypt32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/crypt32/Makefile" ;; + "dlls/cryptdll/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/cryptdll/Makefile" ;; "dlls/ctl3d/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/ctl3d/Makefile" ;; "dlls/d3d8/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3d8/Makefile" ;; "dlls/d3d9/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3d9/Makefile" ;; @@ -20653,6 +20656,7 @@ "dlls/rsaenh/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/rsaenh/Makefile" ;; "dlls/rsaenh/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/rsaenh/tests/Makefile" ;; "dlls/secur32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/secur32/Makefile" ;; + "dlls/sensapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/sensapi/Makefile" ;; "dlls/serialui/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/serialui/Makefile" ;; "dlls/setupapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/setupapi/Makefile" ;; "dlls/shdocvw/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/shdocvw/Makefile" ;; @@ -20662,6 +20666,7 @@ "dlls/shlwapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/shlwapi/Makefile" ;; "dlls/shlwapi/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/shlwapi/tests/Makefile" ;; "dlls/snmpapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/snmpapi/Makefile" ;; + "dlls/stdole32.tlb/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/stdole32.tlb/Makefile" ;; "dlls/sti/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/sti/Makefile" ;; "dlls/strmiids/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/strmiids/Makefile" ;; "dlls/tapi32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/tapi32/Makefile" ;; @@ -20716,6 +20721,7 @@ "dlls/wintrust/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/wintrust/Makefile" ;; "dlls/wow32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/wow32/Makefile" ;; "dlls/wsock32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/wsock32/Makefile" ;; + "dlls/wtsapi32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/wtsapi32/Makefile" ;; "dlls/x11drv/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/x11drv/Makefile" ;; "documentation/Makefile" ) CONFIG_FILES="$CONFIG_FILES documentation/Makefile" ;; "fonts/Makefile" ) CONFIG_FILES="$CONFIG_FILES fonts/Makefile" ;; diff -urN wine-20050111/configure.ac wine-20050211/configure.ac --- wine-20050111/configure.ac 2005-01-10 14:26:33.000000000 +0100 +++ wine-20050211/configure.ac 2005-02-10 20:09:08.000000000 +0100 @@ -49,6 +49,7 @@ test -n "$CC" || CC="gcc -m32" test -n "$LD" || LD="ld -m elf_i386" test -n "$AS" || AS="as --32" + host_cpu="i386" fi ;; esac @@ -1511,6 +1512,7 @@ dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/advpack/Makefile +dlls/advpack/tests/Makefile dlls/amstream/Makefile dlls/atl/Makefile dlls/avicap32/Makefile @@ -1525,6 +1527,7 @@ dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile +dlls/cryptdll/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile @@ -1638,6 +1641,7 @@ dlls/rsaenh/Makefile dlls/rsaenh/tests/Makefile dlls/secur32/Makefile +dlls/sensapi/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile @@ -1647,6 +1651,7 @@ dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile +dlls/stdole32.tlb/Makefile dlls/sti/Makefile dlls/strmiids/Makefile dlls/tapi32/Makefile @@ -1701,6 +1706,7 @@ dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile +dlls/wtsapi32/Makefile dlls/x11drv/Makefile documentation/Makefile fonts/Makefile diff -urN wine-20050111/dlls/Makefile.in wine-20050211/dlls/Makefile.in --- wine-20050111/dlls/Makefile.in 2004-11-04 22:15:33.000000000 +0100 +++ wine-20050211/dlls/Makefile.in 2005-01-28 15:13:08.000000000 +0100 @@ -31,6 +31,7 @@ commdlg \ crtdll \ crypt32 \ + cryptdll \ ctl3d \ d3dim \ d3drm \ @@ -112,6 +113,7 @@ rsabase \ rsaenh \ secur32 \ + sensapi \ serialui \ setupapi \ shdocvw \ @@ -119,6 +121,7 @@ shfolder \ shlwapi \ snmpapi \ + stdole32.tlb \ sti \ tapi32 \ ttydrv \ @@ -162,7 +165,8 @@ wintab32 \ wintrust \ wow32 \ - wsock32 + wsock32 \ + wtsapi32 SUBDIRS = \ $(BASEDIRS) \ @@ -258,6 +262,7 @@ comdlg32.dll.so \ crtdll.dll.so \ crypt32.dll.so \ + cryptdll.dll.so \ ctl3d32.dll.so \ d3dim.dll.so \ d3drm.dll.so \ @@ -351,6 +356,7 @@ rsabase.dll.so \ rsaenh.dll.so \ secur32.dll.so \ + sensapi.dll.so \ serialui.dll.so \ setupapi.dll.so \ shdocvw.dll.so \ @@ -358,6 +364,7 @@ shfolder.dll.so \ shlwapi.dll.so \ snmpapi.dll.so \ + stdole32.tlb.so \ sti.dll.so \ tapi32.dll.so \ ttydrv.dll.so \ @@ -394,7 +401,8 @@ wnaspi32.dll.so \ wow32.dll.so \ ws2_32.dll.so \ - wsock32.dll.so + wsock32.dll.so \ + wtsapi32.dll.so # Main target @@ -460,6 +468,9 @@ crypt32.dll.so: crypt32/crypt32.dll.so $(RM) $@ && $(LN_S) crypt32/crypt32.dll.so $@ +cryptdll.dll.so: cryptdll/cryptdll.dll.so + $(RM) $@ && $(LN_S) cryptdll/cryptdll.dll.so $@ + ctl3d32.dll.so: ctl3d/ctl3d32.dll.so $(RM) $@ && $(LN_S) ctl3d/ctl3d32.dll.so $@ @@ -785,6 +796,9 @@ secur32.dll.so: secur32/secur32.dll.so $(RM) $@ && $(LN_S) secur32/secur32.dll.so $@ +sensapi.dll.so: sensapi/sensapi.dll.so + $(RM) $@ && $(LN_S) sensapi/sensapi.dll.so $@ + serialui.dll.so: serialui/serialui.dll.so $(RM) $@ && $(LN_S) serialui/serialui.dll.so $@ @@ -812,6 +826,9 @@ snmpapi.dll.so: snmpapi/snmpapi.dll.so $(RM) $@ && $(LN_S) snmpapi/snmpapi.dll.so $@ +stdole32.tlb.so: stdole32.tlb/stdole32.tlb.so + $(RM) $@ && $(LN_S) stdole32.tlb/stdole32.tlb.so $@ + sti.dll.so: sti/sti.dll.so $(RM) $@ && $(LN_S) sti/sti.dll.so $@ @@ -960,6 +977,9 @@ wsock32.dll.so: wsock32/wsock32.dll.so $(RM) $@ && $(LN_S) wsock32/wsock32.dll.so $@ +wtsapi32.dll.so: wtsapi32/wtsapi32.dll.so + $(RM) $@ && $(LN_S) wtsapi32/wtsapi32.dll.so $@ + x11drv.dll.so: x11drv/x11drv.dll.so $(RM) $@ && $(LN_S) x11drv/x11drv.dll.so $@ @@ -997,6 +1017,7 @@ libcomdlg32.$(IMPLIBEXT) \ libcrtdll.$(IMPLIBEXT) \ libcrypt32.$(IMPLIBEXT) \ + libcryptdll.$(IMPLIBEXT) \ libctl3d32.$(IMPLIBEXT) \ libd3d8.$(IMPLIBEXT) \ libd3d9.$(IMPLIBEXT) \ @@ -1076,6 +1097,7 @@ librsabase.$(IMPLIBEXT) \ librsaenh.$(IMPLIBEXT) \ libsecur32.$(IMPLIBEXT) \ + libsensapi.$(IMPLIBEXT) \ libserialui.$(IMPLIBEXT) \ libsetupapi.$(IMPLIBEXT) \ libshdocvw.$(IMPLIBEXT) \ @@ -1108,6 +1130,7 @@ libwow32.$(IMPLIBEXT) \ libws2_32.$(IMPLIBEXT) \ libwsock32.$(IMPLIBEXT) \ + libwtsapi32.$(IMPLIBEXT) \ libx11drv.$(IMPLIBEXT) \ libdxerr8.a \ libdxerr9.a \ @@ -1192,6 +1215,11 @@ libcrypt32.a: crypt32/crypt32.spec.def $(DLLTOOL) -k -l $@ -d crypt32/crypt32.spec.def +libcryptdll.def: cryptdll/cryptdll.spec.def + $(RM) $@ && $(LN_S) cryptdll/cryptdll.spec.def $@ +libcryptdll.a: cryptdll/cryptdll.spec.def + $(DLLTOOL) -k -l $@ -d cryptdll/cryptdll.spec.def + libctl3d32.def: ctl3d/ctl3d32.spec.def $(RM) $@ && $(LN_S) ctl3d/ctl3d32.spec.def $@ libctl3d32.a: ctl3d/ctl3d32.spec.def @@ -1587,6 +1615,11 @@ libsecur32.a: secur32/secur32.spec.def $(DLLTOOL) -k -l $@ -d secur32/secur32.spec.def +libsensapi.def: sensapi/sensapi.spec.def + $(RM) $@ && $(LN_S) sensapi/sensapi.spec.def $@ +libsensapi.a: sensapi/sensapi.spec.def + $(DLLTOOL) -k -l $@ -d sensapi/sensapi.spec.def + libserialui.def: serialui/serialui.spec.def $(RM) $@ && $(LN_S) serialui/serialui.spec.def $@ libserialui.a: serialui/serialui.spec.def @@ -1747,6 +1780,11 @@ libwsock32.a: wsock32/wsock32.spec.def $(DLLTOOL) -k -l $@ -d wsock32/wsock32.spec.def +libwtsapi32.def: wtsapi32/wtsapi32.spec.def + $(RM) $@ && $(LN_S) wtsapi32/wtsapi32.spec.def $@ +libwtsapi32.a: wtsapi32/wtsapi32.spec.def + $(DLLTOOL) -k -l $@ -d wtsapi32/wtsapi32.spec.def + libx11drv.def: x11drv/x11drv.spec.def $(RM) $@ && $(LN_S) x11drv/x11drv.spec.def $@ libx11drv.a: x11drv/x11drv.spec.def @@ -1767,6 +1805,7 @@ commdlg/comdlg32.spec.def: $(WINEBUILD) crtdll/crtdll.spec.def: $(WINEBUILD) crypt32/crypt32.spec.def: $(WINEBUILD) +cryptdll/cryptdll.spec.def: $(WINEBUILD) ctl3d/ctl3d32.spec.def: $(WINEBUILD) d3d8/d3d8.spec.def: $(WINEBUILD) d3d9/d3d9.spec.def: $(WINEBUILD) @@ -1846,6 +1885,7 @@ rsabase/rsabase.spec.def: $(WINEBUILD) rsaenh/rsaenh.spec.def: $(WINEBUILD) secur32/secur32.spec.def: $(WINEBUILD) +sensapi/sensapi.spec.def: $(WINEBUILD) serialui/serialui.spec.def: $(WINEBUILD) setupapi/setupapi.spec.def: $(WINEBUILD) shdocvw/shdocvw.spec.def: $(WINEBUILD) @@ -1878,6 +1918,7 @@ wow32/wow32.spec.def: $(WINEBUILD) winsock/ws2_32.spec.def: $(WINEBUILD) wsock32/wsock32.spec.def: $(WINEBUILD) +wtsapi32/wtsapi32.spec.def: $(WINEBUILD) x11drv/x11drv.spec.def: $(WINEBUILD) $(BUILDSUBDIRS): $(IMPORT_LIBS) @@ -1900,6 +1941,7 @@ commdlg/comdlg32.dll.so: commdlg crtdll/crtdll.dll.so: crtdll crypt32/crypt32.dll.so: crypt32 +cryptdll/cryptdll.dll.so: cryptdll ctl3d/ctl3d32.dll.so: ctl3d d3d8/d3d8.dll.so: d3d8 d3d9/d3d9.dll.so: d3d9 @@ -1995,6 +2037,7 @@ rsabase/rsabase.dll.so: rsabase rsaenh/rsaenh.dll.so: rsaenh secur32/secur32.dll.so: secur32 +sensapi/sensapi.dll.so: sensapi serialui/serialui.dll.so: serialui setupapi/setupapi.dll.so: setupapi shdocvw/shdocvw.dll.so: shdocvw @@ -2002,6 +2045,7 @@ shfolder/shfolder.dll.so: shfolder shlwapi/shlwapi.dll.so: shlwapi snmpapi/snmpapi.dll.so: snmpapi +stdole32.tlb/stdole32.tlb.so: stdole32.tlb sti/sti.dll.so: sti tapi32/tapi32.dll.so: tapi32 ttydrv/ttydrv.dll.so: ttydrv @@ -2040,6 +2084,7 @@ wow32/wow32.dll.so: wow32 winsock/ws2_32.dll.so: winsock wsock32/wsock32.dll.so: wsock32 +wtsapi32/wtsapi32.dll.so: wtsapi32 x11drv/x11drv.dll.so: x11drv dxerr8/libdxerr8.a: dxerr8 dxerr9/libdxerr9.a: dxerr9 diff -urN wine-20050111/dlls/advapi32/security.c wine-20050211/dlls/advapi32/security.c --- wine-20050111/dlls/advapi32/security.c 2005-01-03 18:12:51.000000000 +0100 +++ wine-20050211/dlls/advapi32/security.c 2005-02-11 12:52:07.000000000 +0100 @@ -238,9 +238,18 @@ LPVOID NewState, DWORD BufferLength, LPVOID PreviousState, LPDWORD ReturnLength ) { - return set_ntstatus( NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges, + NTSTATUS status; + + TRACE("\n"); + + status = NtAdjustPrivilegesToken(TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, - ReturnLength)); + ReturnLength); + SetLastError( RtlNtStatusToDosError( status )); + if ((status == STATUS_SUCCESS) || (status == STATUS_NOT_ALL_ASSIGNED)) + return TRUE; + else + return FALSE; } /****************************************************************************** @@ -2996,10 +3005,24 @@ TOKEN_TYPE TokenType, PHANDLE DuplicateTokenHandle ) { - FIXME("%p 0x%08lx 0x%08x 0x%08x %p - stub\n", ExistingTokenHandle, dwDesiredAccess, + OBJECT_ATTRIBUTES ObjectAttributes; + + TRACE("%p 0x%08lx 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess, ImpersonationLevel, TokenType, DuplicateTokenHandle); - return FALSE; + InitializeObjectAttributes( + &ObjectAttributes, + NULL, + (lpTokenAttributes && lpTokenAttributes->bInheritHandle) ? OBJ_INHERIT : 0, + NULL, + lpTokenAttributes ? lpTokenAttributes->lpSecurityDescriptor : NULL ); + + return set_ntstatus( NtDuplicateToken( ExistingTokenHandle, + dwDesiredAccess, + &ObjectAttributes, + ImpersonationLevel, + TokenType, + DuplicateTokenHandle ) ); } BOOL WINAPI DuplicateToken( diff -urN wine-20050111/dlls/advapi32/service.c wine-20050211/dlls/advapi32/service.c --- wine-20050111/dlls/advapi32/service.c 2005-01-03 18:12:51.000000000 +0100 +++ wine-20050211/dlls/advapi32/service.c 2005-01-24 20:33:43.000000000 +0100 @@ -2,6 +2,7 @@ * Win32 advapi functions * * Copyright 1995 Sven Verdoolaege + * 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 @@ -21,6 +22,7 @@ #include #include #include +#include #include "windef.h" #include "winbase.h" @@ -38,31 +40,44 @@ 'S','e','r','v','i','c','e','s','\\',0 }; static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M', 'L','O','C','K',0}; -static const WCHAR szServiceShmemNameFmtW[] = {'A','D','V','A','P','I','_', - 'S','E','B','_','%','s',0}; -static const WCHAR szServiceDispEventNameFmtW[] = {'A','D','V','A','P','I','_', - 'D','I','S','P','_','%','s',0}; -static const WCHAR szServiceMutexNameFmtW[] = {'A','D','V','A','P','I','_', - 'M','U','X','_','%','s',0}; -static const WCHAR szServiceAckEventNameFmtW[] = {'A','D','V','A','P','I','_', - 'A','C','K','_','%','s',0}; -static const WCHAR szWaitServiceStartW[] = {'A','D','V','A','P','I','_','W', - 'a','i','t','S','e','r','v','i', - 'c','e','S','t','a','r','t',0}; - -struct SEB /* service environment block */ -{ /* resides in service's shared memory object */ - DWORD control_code; /* service control code */ - DWORD dispatcher_error; /* set by dispatcher if it fails to invoke control handler */ + +typedef struct service_start_info_t +{ + DWORD cmd; + DWORD size; + WCHAR str[1]; +} service_start_info; + +#define WINESERV_STARTINFO 1 +#define WINESERV_GETSTATUS 2 +#define WINESERV_SENDCONTROL 3 + +typedef struct service_data_t +{ + struct service_data_t *next; + LPHANDLER_FUNCTION handler; SERVICE_STATUS status; - DWORD argc; - /* variable part of SEB contains service arguments */ + HANDLE thread; + BOOL unicode; + union { + LPSERVICE_MAIN_FUNCTIONA a; + LPSERVICE_MAIN_FUNCTIONW w; + } proc; + LPWSTR args; + WCHAR name[1]; +} service_data; + +static CRITICAL_SECTION service_cs; +static CRITICAL_SECTION_DEBUG service_cs_debug = +{ + 0, 0, &service_cs, + { &service_cs_debug.ProcessLocksList, + &service_cs_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": service_cs") } }; +static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 }; -static HANDLE dispatcher_event; /* this is used by service thread to wakeup - * service control dispatcher when thread terminates */ - -static struct service_thread_data *service; /* FIXME: this should be a list */ +service_data *service_list; /****************************************************************************** * SC_HANDLEs @@ -73,104 +88,90 @@ typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE; struct sc_handle; +typedef VOID (*sc_handle_destructor)(struct sc_handle *); -struct sc_manager /* SCM handle */ +struct sc_handle { - HKEY hkey_scm_db; /* handle to services database in the registry */ - LONG ref_count; /* handle must remain alive until any related service */ - /* handle exists because DeleteService requires it */ + SC_HANDLE_TYPE htype; + DWORD ref_count; + sc_handle_destructor destroy; }; -struct sc_service /* service handle */ +struct sc_manager /* service control manager handle */ { - HKEY hkey; /* handle to service entry in the registry (under hkey_scm_db) */ - struct sc_handle *sc_manager; /* pointer to SCM handle */ - WCHAR name[ MAX_SERVICE_NAME ]; + struct sc_handle hdr; + HKEY hkey; /* handle to services database in the registry */ }; -struct sc_handle +struct sc_service /* service handle */ { - SC_HANDLE_TYPE htype; - union - { - struct sc_manager manager; - struct sc_service service; - } u; + struct sc_handle hdr; + HKEY hkey; /* handle to service entry in the registry (under hkey) */ + struct sc_manager *scm; /* pointer to SCM handle */ + WCHAR name[1]; }; -static struct sc_handle* alloc_sc_handle( SC_HANDLE_TYPE htype ) +static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size, + sc_handle_destructor destroy) { - struct sc_handle *retval; + struct sc_handle *hdr; - retval = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct sc_handle) ); - if( retval != NULL ) + hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); + if (hdr) { - retval->htype = htype; + hdr->htype = htype; + hdr->ref_count = 1; + hdr->destroy = destroy; } - TRACE("SC_HANDLE type=%d -> %p\n",htype,retval); - return retval; + TRACE("sc_handle type=%d -> %p\n", htype, hdr); + return hdr; } -static void free_sc_handle( struct sc_handle* handle ) +static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype) { - if( NULL == handle ) - return; - - switch( handle->htype ) - { - case SC_HTYPE_MANAGER: - { - if( InterlockedDecrement( &handle->u.manager.ref_count ) ) - /* there are references to this handle */ - return; + struct sc_handle *hdr = (struct sc_handle *) handle; - if( handle->u.manager.hkey_scm_db ) - RegCloseKey( handle->u.manager.hkey_scm_db ); - break; - } - - case SC_HTYPE_SERVICE: - { - struct sc_handle *h = handle->u.service.sc_manager; + if (!hdr) + return NULL; + if (hdr->htype != htype) + return NULL; + return hdr; +} - if( h ) - { - /* release SCM handle */ - if( 0 == InterlockedDecrement( &h->u.manager.ref_count ) ) - { - /* it's time to destroy SCM handle */ - if( h->u.manager.hkey_scm_db ) - RegCloseKey( h->u.manager.hkey_scm_db ); - - TRACE("SC_HANDLE (SCM) %p type=%d\n",h,h->htype); - - HeapFree( GetProcessHeap(), 0, h ); - } - } - if( handle->u.service.hkey ) - RegCloseKey( handle->u.service.hkey ); - break; - } - } +static void sc_handle_free(struct sc_handle* hdr) +{ + if (!hdr) + return; + if (--hdr->ref_count) + return; + hdr->destroy(hdr); + HeapFree(GetProcessHeap(), 0, hdr); +} - TRACE("SC_HANDLE %p type=%d\n",handle,handle->htype); +static void sc_handle_destroy_manager(struct sc_handle *handle) +{ + struct sc_manager *mgr = (struct sc_manager*) handle; - HeapFree( GetProcessHeap(), 0, handle ); + TRACE("destroying SC Manager %p\n", mgr); + if (mgr->hkey) + RegCloseKey(mgr->hkey); } -static void init_service_handle( struct sc_handle* handle, - struct sc_handle* sc_manager, - HKEY hKey, LPCWSTR lpServiceName ) +static void sc_handle_destroy_service(struct sc_handle *handle) { - /* init sc_service structure */ - handle->u.service.hkey = hKey; - lstrcpynW( handle->u.service.name, lpServiceName, MAX_SERVICE_NAME ); - - /* add reference to SCM handle */ - InterlockedIncrement( &sc_manager->u.manager.ref_count ); - handle->u.service.sc_manager = sc_manager; + struct sc_service *svc = (struct sc_service*) handle; + + TRACE("destroying service %p\n", svc); + if (svc->hkey) + RegCloseKey(svc->hkey); + svc->hkey = NULL; + sc_handle_free(&svc->scm->hdr); + svc->scm = NULL; } +/****************************************************************************** + * String management functions + */ static inline LPWSTR SERV_dup( LPCSTR str ) { UINT len; @@ -184,7 +185,7 @@ return wstr; } -static inline LPWSTR SERV_dupmulti( LPCSTR str ) +static inline LPWSTR SERV_dupmulti(LPCSTR str) { UINT len = 0, n = 0; LPWSTR wstr; @@ -208,415 +209,543 @@ HeapFree( GetProcessHeap(), 0, wstr ); } + /****************************************************************************** - * EnumServicesStatusA [ADVAPI32.@] + * Service IPC functions */ -BOOL WINAPI -EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType, - DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, - DWORD cbBufSize, LPDWORD pcbBytesNeeded, - LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) -{ FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, - dwServiceType, dwServiceState, lpServices, cbBufSize, - pcbBytesNeeded, lpServicesReturned, lpResumeHandle); - SetLastError (ERROR_ACCESS_DENIED); - return FALSE; +static LPWSTR service_get_pipe_name(LPWSTR service) +{ + static const WCHAR prefix[] = { '\\','\\','.','\\','p','i','p','e','\\', + '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0}; + LPWSTR name; + DWORD len; + + len = sizeof prefix + strlenW(service)*sizeof(WCHAR); + name = HeapAlloc(GetProcessHeap(), 0, len); + strcpyW(name, prefix); + strcatW(name, service); + return name; +} + +static HANDLE service_open_pipe(LPWSTR service) +{ + LPWSTR szPipe = service_get_pipe_name( service ); + HANDLE handle = INVALID_HANDLE_VALUE; + + do { + handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, 0, NULL); + if (handle != INVALID_HANDLE_VALUE) + break; + if (GetLastError() != ERROR_PIPE_BUSY) + break; + } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER)); + SERV_free(szPipe); + + return handle; } /****************************************************************************** - * EnumServicesStatusW [ADVAPI32.@] + * service_get_event_handle */ -BOOL WINAPI -EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType, - DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, - DWORD cbBufSize, LPDWORD pcbBytesNeeded, - LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) -{ FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, - dwServiceType, dwServiceState, lpServices, cbBufSize, - pcbBytesNeeded, lpServicesReturned, lpResumeHandle); - SetLastError (ERROR_ACCESS_DENIED); - return FALSE; +static HANDLE service_get_event_handle(LPWSTR service) +{ + static const WCHAR prefix[] = { + '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0}; + LPWSTR name; + DWORD len; + HANDLE handle; + + len = sizeof prefix + strlenW(service)*sizeof(WCHAR); + name = HeapAlloc(GetProcessHeap(), 0, len); + strcpyW(name, prefix); + strcatW(name, service); + handle = CreateEventW(NULL, TRUE, FALSE, name); + SERV_free(name); + return handle; } /****************************************************************************** - * read_scm_lock_data - * - * helper function for service control dispatcher + * service_thread * - * SCM database is locked by StartService; - * open global SCM lock object and read service name + * Call into the main service routine provided by StartServiceCtrlDispatcher. */ -static BOOL read_scm_lock_data( LPWSTR buffer ) +static DWORD WINAPI service_thread(LPVOID arg) { - HANDLE hLock; - LPWSTR argptr; + service_data *info = arg; + LPWSTR str = info->args; + DWORD argc = 0, len = 0; + + TRACE("%p\n", arg); - hLock = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, szSCMLock ); - if( NULL == hLock ) + while (str[len]) { - SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ); - return FALSE; + len += strlenW(&str[len]) + 1; + argc++; } - argptr = MapViewOfFile( hLock, FILE_MAP_ALL_ACCESS, - 0, 0, MAX_SERVICE_NAME * sizeof(WCHAR) ); - if( NULL == argptr ) + + if (info->unicode) { - CloseHandle( hLock ); - return FALSE; + LPWSTR *argv, p; + + argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR)); + for (argc=0, p=str; *p; p += strlenW(p) + 1) + argv[argc++] = p; + argv[argc] = NULL; + + info->proc.w(argc, argv); + HeapFree(GetProcessHeap(), 0, argv); } - strcpyW( buffer, argptr ); - UnmapViewOfFile( argptr ); - CloseHandle( hLock ); - return TRUE; + else + { + LPSTR strA, *argv, p; + DWORD lenA; + + lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL); + strA = HeapAlloc(GetProcessHeap(), 0, lenA); + WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL); + + argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR)); + for (argc=0, p=strA; *p; p += strlen(p) + 1) + argv[argc++] = p; + argv[argc] = NULL; + + info->proc.a(argc, argv); + HeapFree(GetProcessHeap(), 0, argv); + HeapFree(GetProcessHeap(), 0, strA); + } + return 0; } /****************************************************************************** - * open_seb_shmem - * - * helper function for service control dispatcher + * service_handle_start */ -static struct SEB* open_seb_shmem( LPWSTR service_name, HANDLE* hServiceShmem ) +static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count) { - WCHAR object_name[ MAX_PATH ]; - HANDLE hmem; - struct SEB *ret; + DWORD read = 0, result = 0; + LPWSTR args; + BOOL r; - snprintfW( object_name, MAX_PATH, szServiceShmemNameFmtW, service_name ); - hmem = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, object_name ); - if( NULL == hmem ) - return NULL; + TRACE("%p %p %ld\n", pipe, service, count); - ret = MapViewOfFile( hmem, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); - if( NULL == ret ) - CloseHandle( hmem ); - else - *hServiceShmem = hmem; - return ret; + args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR)); + r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL); + if (!r || count!=read/sizeof(WCHAR) || args[count-1]) + { + ERR("pipe read failed r = %d count = %ld/%ld args[n-1]=%s\n", + r, count, read/sizeof(WCHAR), debugstr_wn(args, count)); + goto end; + } + + if (service->thread) + { + ERR("service is not stopped\n"); + goto end; + } + + if (service->args) + SERV_free(service->args); + service->args = args; + args = NULL; + service->thread = CreateThread( NULL, 0, service_thread, + service, 0, NULL ); + +end: + HeapFree(GetProcessHeap(), 0, args); + WriteFile( pipe, &result, sizeof result, &read, NULL ); + + return TRUE; } /****************************************************************************** - * build_arg_vectors - * - * helper function for start_new_service - * - * Allocate and initialize array of LPWSTRs to arguments in variable part - * of service environment block. - * First entry in the array is reserved for service name and not initialized. + * service_send_start_message */ -static LPWSTR* build_arg_vectors( struct SEB* seb ) +static BOOL service_send_start_message(HANDLE pipe, LPCWSTR *argv, DWORD argc) { - LPWSTR *ret; - LPWSTR argptr; - DWORD i; + DWORD i, len, count, result; + service_start_info *ssi; + LPWSTR p; + BOOL r; - ret = HeapAlloc( GetProcessHeap(), 0, (1 + seb->argc) * sizeof(LPWSTR) ); - if( NULL == ret ) - return NULL; + TRACE("%p %p %ld\n", pipe, argv, argc); - argptr = (LPWSTR) &seb[1]; - for( i = 0; i < seb->argc; i++ ) + /* calculate how much space do we need to send the startup info */ + len = 1; + for (i=0; icmd = WINESERV_STARTINFO; + ssi->size = len; + + /* copy service args into a single buffer*/ + p = &ssi->str[0]; + for (i=0; istatus, + sizeof service->status, &count, NULL); +} -static DWORD WINAPI service_thread( LPVOID arg ) +/****************************************************************************** + * service_get_status + */ +static BOOL service_get_status(HANDLE pipe, LPSERVICE_STATUS status) { - struct service_thread_data *data = arg; - - data->service_main( data->argc, data->argv ); - SetEvent( dispatcher_event ); - return 0; + DWORD cmd[2], count = 0; + BOOL r; + + cmd[0] = WINESERV_GETSTATUS; + cmd[1] = 0; + r = WriteFile( pipe, cmd, sizeof cmd, &count, NULL ); + if (!r || count != sizeof cmd) + { + ERR("service protocol error - failed to write pipe!\n"); + return r; + } + r = ReadFile( pipe, status, sizeof *status, &count, NULL ); + if (!r || count != sizeof *status) + ERR("service protocol error - failed to read pipe " + "r = %d count = %ld/%d!\n", r, count, sizeof *status); + return r; } /****************************************************************************** - * dispose_service_thread_data - * - * helper function for service control dispatcher + * service_send_control */ -static void dispose_service_thread_data( struct service_thread_data* thread_data ) +static BOOL service_send_control(HANDLE pipe, DWORD dwControl, DWORD *result) { - if( thread_data->mutex ) CloseHandle( thread_data->mutex ); - if( thread_data->ack_event ) CloseHandle( thread_data->ack_event ); - HeapFree( GetProcessHeap(), 0, thread_data->argv ); - if( thread_data->seb ) UnmapViewOfFile( thread_data->seb ); - if( thread_data->hServiceShmem ) CloseHandle( thread_data->hServiceShmem ); - HeapFree( GetProcessHeap(), 0, thread_data ); + DWORD cmd[2], count = 0; + BOOL r; + + cmd[0] = WINESERV_SENDCONTROL; + cmd[1] = dwControl; + r = WriteFile(pipe, cmd, sizeof cmd, &count, NULL); + if (!r || count != sizeof cmd) + { + ERR("service protocol error - failed to write pipe!\n"); + return r; + } + r = ReadFile(pipe, result, sizeof *result, &count, NULL); + if (!r || count != sizeof *result) + ERR("service protocol error - failed to read pipe " + "r = %d count = %ld/%d!\n", r, count, sizeof *result); + return r; } /****************************************************************************** - * start_new_service - * - * helper function for service control dispatcher + * service_accepts_control */ -static struct service_thread_data* -start_new_service( LPSERVICE_MAIN_FUNCTIONW service_main, BOOL ascii ) +static BOOL service_accepts_control(service_data *service, DWORD dwControl) { - struct service_thread_data *thread_data; - unsigned int i; - WCHAR object_name[ MAX_PATH ]; - - thread_data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct service_thread_data) ); - if( NULL == thread_data ) - return NULL; + DWORD a = service->status.dwControlsAccepted; - if( ! read_scm_lock_data( thread_data->service_name ) ) + switch (dwControl) { - /* FIXME: Instead of exiting we allow - service to be executed as ordinary program. - This behaviour was specially introduced in the patch - submitted against revision 1.45 and so preserved here. - */ - FIXME("should fail with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT\n"); - service_main( 0, NULL ); - HeapFree( GetProcessHeap(), 0, thread_data ); - return NULL; + case SERVICE_CONTROL_INTERROGATE: + return TRUE; + case SERVICE_CONTROL_STOP: + if (a&SERVICE_ACCEPT_STOP) + return TRUE; + break; + case SERVICE_CONTROL_SHUTDOWN: + if (a&SERVICE_ACCEPT_SHUTDOWN) + return TRUE; + break; + case SERVICE_CONTROL_PAUSE: + case SERVICE_CONTROL_CONTINUE: + if (a&SERVICE_ACCEPT_PAUSE_CONTINUE) + return TRUE; + break; + case SERVICE_CONTROL_PARAMCHANGE: + if (a&SERVICE_ACCEPT_PARAMCHANGE) + return TRUE; + break; + case SERVICE_CONTROL_NETBINDADD: + case SERVICE_CONTROL_NETBINDREMOVE: + case SERVICE_CONTROL_NETBINDENABLE: + case SERVICE_CONTROL_NETBINDDISABLE: + if (a&SERVICE_ACCEPT_NETBINDCHANGE) + return TRUE; } - - thread_data->seb = open_seb_shmem( thread_data->service_name, &thread_data->hServiceShmem ); - if( NULL == thread_data->seb ) - goto error; - - thread_data->argv = build_arg_vectors( thread_data->seb ); - if( NULL == thread_data->argv ) - goto error; - - thread_data->argv[0] = thread_data->service_name; - thread_data->argc = thread_data->seb->argc + 1; - - if( ascii ) + if (1) /* (!service->handlerex) */ + return FALSE; + switch (dwControl) { - /* Convert the Unicode arg vectors back to ASCII; - * but we'll need unicode service name (argv[0]) for object names */ - WideCharToMultiByte( CP_ACP, 0, thread_data->argv[0], -1, - thread_data->service_nameA, MAX_SERVICE_NAME, NULL, NULL ); - thread_data->argv[0] = (LPWSTR) thread_data->service_nameA; - - for(i=1; iargc; i++) - { - LPWSTR src = thread_data->argv[i]; - int len = WideCharToMultiByte( CP_ACP, 0, src, -1, NULL, 0, NULL, NULL ); - LPSTR dest = HeapAlloc( GetProcessHeap(), 0, len ); - if( NULL == dest ) - goto error; - WideCharToMultiByte( CP_ACP, 0, src, -1, dest, len, NULL, NULL ); - /* copy converted string back */ - memcpy( src, dest, len ); - HeapFree( GetProcessHeap(), 0, dest ); - } + case SERVICE_CONTROL_HARDWAREPROFILECHANGE: + if (a&SERVICE_ACCEPT_HARDWAREPROFILECHANGE) + return TRUE; + break; + case SERVICE_CONTROL_POWEREVENT: + if (a&SERVICE_ACCEPT_POWEREVENT) + return TRUE; + break; + case SERVICE_CONTROL_SESSIONCHANGE: + if (a&SERVICE_ACCEPT_SESSIONCHANGE) + return TRUE; + break; } + return FALSE; +} - /* init status according to docs for StartService */ - thread_data->seb->status.dwCurrentState = SERVICE_START_PENDING; - thread_data->seb->status.dwControlsAccepted = 0; - thread_data->seb->status.dwCheckPoint = 0; - thread_data->seb->status.dwWaitHint = 2000; - - /* create service mutex; mutex is initially owned */ - snprintfW( object_name, MAX_PATH, szServiceMutexNameFmtW, thread_data->service_name ); - thread_data->mutex = CreateMutexW( NULL, TRUE, object_name ); - if( NULL == thread_data->mutex ) - goto error; +/****************************************************************************** + * service_handle_control + */ +static BOOL service_handle_control(HANDLE pipe, service_data *service, + DWORD dwControl) +{ + DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL; - if( ERROR_ALREADY_EXISTS == GetLastError() ) + TRACE("received control %ld\n", dwControl); + + if (service_accepts_control(service, dwControl) && service->handler) { - SetLastError( ERROR_SERVICE_ALREADY_RUNNING ); - goto error; + service->handler(dwControl); + ret = ERROR_SUCCESS; } + return WriteFile(pipe, &ret, sizeof ret, &count, NULL); +} - /* create service event */ - snprintfW( object_name, MAX_PATH, szServiceAckEventNameFmtW, thread_data->service_name ); - thread_data->ack_event = CreateEventW( NULL, FALSE, FALSE, object_name ); - if( NULL == thread_data->ack_event ) - goto error; +/****************************************************************************** + * service_reap_thread + */ +static DWORD service_reap_thread(service_data *service) +{ + DWORD exitcode = 0; - if( ERROR_ALREADY_EXISTS == GetLastError() ) + if (!service->thread) + return 0; + GetExitCodeThread(service->thread, &exitcode); + if (exitcode!=STILL_ACTIVE) { - SetLastError( ERROR_SERVICE_ALREADY_RUNNING ); - goto error; + CloseHandle(service->thread); + service->thread = 0; } - - /* create service thread in suspended state - * to avoid race while caller handles return value */ - thread_data->service_main = service_main; - thread_data->thread_handle = CreateThread( NULL, 0, service_thread, - thread_data, CREATE_SUSPENDED, NULL ); - if( thread_data->thread_handle ) - return thread_data; - -error: - dispose_service_thread_data( thread_data ); - return FALSE; + return exitcode; } /****************************************************************************** - * service_ctrl_dispatcher + * service_control_dispatcher */ -static BOOL service_ctrl_dispatcher( LPSERVICE_TABLE_ENTRYW servent, BOOL ascii ) +static DWORD WINAPI service_control_dispatcher(LPVOID arg) { - WCHAR object_name[ MAX_PATH ]; - HANDLE wait; + service_data *service = arg; + LPWSTR name; + HANDLE pipe, event; - /* FIXME: if shared service, find entry by service name */ + TRACE("%p %s\n", service, debugstr_w(service->name)); - /* FIXME: move this into dispatcher loop */ - service = start_new_service( servent->lpServiceProc, ascii ); - if( NULL == service ) - return FALSE; - - ResumeThread( service->thread_handle ); + /* create a pipe to talk to the rest of the world with */ + name = service_get_pipe_name(service->name); + pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX, + PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL ); + SERV_free(name); - /* create dispatcher event object */ - /* FIXME: object_name should be based on executable image path because - * this object is common for all services in the process */ - /* But what if own and shared services have the same executable? */ - snprintfW( object_name, MAX_PATH, szServiceDispEventNameFmtW, service->service_name ); - dispatcher_event = CreateEventW( NULL, FALSE, FALSE, object_name ); - if( NULL == dispatcher_event ) - { - dispose_service_thread_data( service ); - return FALSE; - } + /* let the process who started us know we've tried to create a pipe */ + event = service_get_event_handle(service->name); + SetEvent(event); + CloseHandle(event); - if( ERROR_ALREADY_EXISTS == GetLastError() ) + if (pipe==INVALID_HANDLE_VALUE) { - SetLastError( ERROR_SERVICE_ALREADY_RUNNING ); - CloseHandle( dispatcher_event ); - return FALSE; - } - - /* ready to accept control requests */ - ReleaseMutex( service->mutex ); - - /* signal for StartService */ - wait = OpenSemaphoreW( SEMAPHORE_MODIFY_STATE, FALSE, szWaitServiceStartW ); - if( wait ) - { - ReleaseSemaphore( wait, 1, NULL ); - CloseHandle( wait ); + ERR("failed to create pipe, error = %ld\n", GetLastError()); + return 0; } /* dispatcher loop */ - for(;;) + while (1) { - DWORD ret; + BOOL r; + DWORD count, req[2] = {0,0}; - WaitForSingleObject( dispatcher_event, INFINITE ); + r = ConnectNamedPipe(pipe, NULL); + if (!r && GetLastError() != ERROR_PIPE_CONNECTED) + { + ERR("pipe connect failed\n"); + break; + } - /* at first, look for terminated service thread - * FIXME: threads, if shared service */ - if( !GetExitCodeThread( service->thread_handle, &ret ) ) - ERR("Couldn't get thread exit code\n"); - else if( ret != STILL_ACTIVE ) + r = ReadFile( pipe, &req, sizeof req, &count, NULL ); + if (!r || count!=sizeof req) { - CloseHandle( service->thread_handle ); - dispose_service_thread_data( service ); + ERR("pipe read failed\n"); break; } - /* look for control requests */ - if( service->seb->control_code ) + service_reap_thread(service); + + /* handle the request */ + switch (req[0]) { - if( NULL == service->ctrl_handler ) - service->seb->dispatcher_error = ERROR_SERVICE_CANNOT_ACCEPT_CTRL; - else - { - service->ctrl_handler( service->seb->control_code ); - service->seb->dispatcher_error = 0; - } - service->seb->control_code = 0; - SetEvent( service->ack_event ); + case WINESERV_STARTINFO: + service_handle_start(pipe, service, req[1]); + break; + case WINESERV_GETSTATUS: + service_handle_get_status(pipe, service); + break; + case WINESERV_SENDCONTROL: + service_handle_control(pipe, service, req[1]); + break; + default: + ERR("received invalid command %ld length %ld\n", req[0], req[1]); } - /* FIXME: if shared service, check SCM lock object; - * if exists, a new service should be started */ + FlushFileBuffers(pipe); + DisconnectNamedPipe(pipe); } - CloseHandle( dispatcher_event ); - return TRUE; + CloseHandle(pipe); + return 1; } /****************************************************************************** - * StartServiceCtrlDispatcherA [ADVAPI32.@] + * service_run_threads */ -BOOL WINAPI -StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) +static BOOL service_run_threads(void) { - int count, i; - LPSERVICE_TABLE_ENTRYW ServiceTableW; - BOOL ret; + service_data *service; + DWORD count = 0, n = 0; + HANDLE *handles; - TRACE("(%p)\n", servent); + EnterCriticalSection( &service_cs ); - /* convert service table to unicode */ - for( count = 0; servent[ count ].lpServiceName; ) + /* count how many services there are */ + for (service = service_list; service; service = service->next) count++; - ServiceTableW = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(SERVICE_TABLE_ENTRYW) ); - if( NULL == ServiceTableW ) - return FALSE; - for( i = 0; i < count; i++ ) + TRACE("starting %ld pipe listener threads\n", count); + + handles = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE)*count); + + for (n=0, service = service_list; service; service = service->next, n++) + handles[n] = CreateThread( NULL, 0, service_control_dispatcher, + service, 0, NULL ); + assert(n==count); + + LeaveCriticalSection( &service_cs ); + + /* wait for all the threads to pack up and exit */ + WaitForMultipleObjectsEx(count, handles, TRUE, INFINITE, FALSE); + + HeapFree(GetProcessHeap(), 0, handles); + + return TRUE; +} + +/****************************************************************************** + * StartServiceCtrlDispatcherA [ADVAPI32.@] + * + * Connects a process containing one or more services to the service control + * manager. + * + * PARAMS + * servent [I] A list of the service names and service procedures + */ +BOOL WINAPI StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent ) +{ + service_data *info; + DWORD sz, len; + BOOL ret = TRUE; + + TRACE("%p\n", servent); + + EnterCriticalSection( &service_cs ); + while (servent->lpServiceName) { - ServiceTableW[ i ].lpServiceName = SERV_dup( servent[ i ].lpServiceName ); - ServiceTableW[ i ].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW) servent[ i ].lpServiceProc; + LPSTR name = servent->lpServiceName; + + len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0); + sz = len*sizeof(WCHAR) + sizeof *info; + info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz ); + MultiByteToWideChar(CP_ACP, 0, name, -1, info->name, len); + info->proc.a = servent->lpServiceProc; + info->unicode = FALSE; + + /* insert into the list */ + info->next = service_list; + service_list = info; + + servent++; } - ServiceTableW[ count ].lpServiceName = NULL; - ServiceTableW[ count ].lpServiceProc = NULL; + LeaveCriticalSection( &service_cs ); - /* start dispatcher */ - ret = service_ctrl_dispatcher( ServiceTableW, TRUE ); + service_run_threads(); - /* free service table */ - for( i = 0; i < count; i++ ) - SERV_free( ServiceTableW[ i ].lpServiceName ); - HeapFree( GetProcessHeap(), 0, ServiceTableW ); return ret; } /****************************************************************************** * StartServiceCtrlDispatcherW [ADVAPI32.@] * + * Connects a process containing one or more services to the service control + * manager. + * * PARAMS - * servent [] + * servent [I] A list of the service names and service procedures */ -BOOL WINAPI -StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent ) +BOOL WINAPI StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent ) { - TRACE("(%p)\n", servent); - return service_ctrl_dispatcher( servent, FALSE ); + service_data *info; + DWORD sz, len; + BOOL ret = TRUE; + + TRACE("%p\n", servent); + + EnterCriticalSection( &service_cs ); + while (servent->lpServiceName) + { + LPWSTR name = servent->lpServiceName; + + len = strlenW(name); + sz = len*sizeof(WCHAR) + sizeof *info; + info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz ); + strcpyW(info->name, name); + info->proc.w = servent->lpServiceProc; + info->unicode = TRUE; + + /* insert into the list */ + info->next = service_list; + service_list = info; + + servent++; + } + LeaveCriticalSection( &service_cs ); + + service_run_threads(); + + return ret; } /****************************************************************************** * LockServiceDatabase [ADVAPI32.@] */ -LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager) +SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager) { HANDLE ret; TRACE("%p\n",hSCManager); - ret = CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, - 0, MAX_SERVICE_NAME * sizeof(WCHAR), szSCMLock ); + ret = CreateSemaphoreW( NULL, 1, 1, szSCMLock ); if( ret && GetLastError() == ERROR_ALREADY_EXISTS ) { CloseHandle( ret ); @@ -632,19 +761,18 @@ /****************************************************************************** * UnlockServiceDatabase [ADVAPI32.@] */ -BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock) +BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock) { TRACE("%p\n",ScLock); - return CloseHandle( (HANDLE) ScLock ); + return CloseHandle( ScLock ); } /****************************************************************************** * RegisterServiceCtrlHandlerA [ADVAPI32.@] */ SERVICE_STATUS_HANDLE WINAPI -RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, - LPHANDLER_FUNCTION lpfHandler ) +RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler ) { LPWSTR lpServiceNameW; SERVICE_STATUS_HANDLE ret; @@ -662,14 +790,20 @@ * lpServiceName [] * lpfHandler [] */ -SERVICE_STATUS_HANDLE WINAPI -RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName, +SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler ) { - /* FIXME: find service thread data by service name */ + service_data *service; - service->ctrl_handler = lpfHandler; - return 0xcacacafe; + EnterCriticalSection( &service_cs ); + for(service = service_list; service; service = service->next) + if(!strcmpW(lpServiceName, service->name)) + break; + if (service) + service->handler = lpfHandler; + LeaveCriticalSection( &service_cs ); + + return (SERVICE_STATUS_HANDLE)service; } /****************************************************************************** @@ -682,28 +816,32 @@ BOOL WINAPI SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus ) { - DWORD r; + service_data *service; + BOOL r = TRUE; - TRACE("\tType:%lx\n",lpStatus->dwServiceType); - TRACE("\tState:%lx\n",lpStatus->dwCurrentState); - TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted); - TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode); - TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode); - TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint); - TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint); - - /* FIXME: find service thread data by status handle */ - - /* acquire mutex; note that mutex may already be owned - * when service handles control request - */ - r = WaitForSingleObject( service->mutex, 0 ); - memcpy( &service->seb->status, lpStatus, sizeof(SERVICE_STATUS) ); - if( WAIT_OBJECT_0 == r || WAIT_ABANDONED == r ) - ReleaseMutex( service->mutex ); - return TRUE; + TRACE("%lx %lx %lx %lx %lx %lx %lx %lx\n", hService, + lpStatus->dwServiceType, lpStatus->dwCurrentState, + lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode, + lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint, + lpStatus->dwWaitHint); + + EnterCriticalSection( &service_cs ); + for (service = service_list; service; service = service->next) + if(service == (service_data*)hService) + break; + if (service) + { + memcpy( &service->status, lpStatus, sizeof(SERVICE_STATUS) ); + TRACE("Set service status to %ld\n",service->status.dwCurrentState); + } + else + r = FALSE; + LeaveCriticalSection( &service_cs ); + + return r; } + /****************************************************************************** * OpenSCManagerA [ADVAPI32.@] * @@ -740,7 +878,7 @@ SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess ) { - struct sc_handle *retval; + struct sc_manager *manager; HKEY hReg; LONG r; @@ -765,27 +903,27 @@ } } - retval = alloc_sc_handle( SC_HTYPE_MANAGER ); - if( NULL == retval ) return NULL; - - retval->u.manager.ref_count = 1; + manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager), + sc_handle_destroy_manager ); + if (!manager) + return NULL; r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg); if (r!=ERROR_SUCCESS) goto error; r = RegOpenKeyExW(hReg, szServiceManagerKey, - 0, KEY_ALL_ACCESS, &retval->u.manager.hkey_scm_db); + 0, KEY_ALL_ACCESS, &manager->hkey); RegCloseKey( hReg ); if (r!=ERROR_SUCCESS) goto error; - TRACE("returning %p\n", retval); + TRACE("returning %p\n", manager); - return (SC_HANDLE) retval; + return (SC_HANDLE) &manager->hdr; error: - free_sc_handle( retval ); + sc_handle_free( &manager->hdr ); return NULL; } @@ -810,84 +948,54 @@ BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus ) { - struct sc_handle *hsvc = hService; - WCHAR object_name[ MAX_PATH ]; - HANDLE mutex = NULL, shmem = NULL; - HANDLE disp_event = NULL, ack_event = NULL; - struct SEB *seb = NULL; - DWORD r; - BOOL ret = FALSE, mutex_owned = FALSE; - - /* open and hold mutex */ - snprintfW( object_name, MAX_PATH, szServiceMutexNameFmtW, hsvc->u.service.name ); - mutex = OpenMutexW( MUTEX_ALL_ACCESS, FALSE, object_name ); - if( NULL == mutex ) + struct sc_service *hsvc; + BOOL ret = FALSE; + HANDLE handle; + + TRACE("%p %ld %p\n", hService, dwControl, lpServiceStatus); + + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) { - SetLastError( ERROR_SERVICE_NOT_ACTIVE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } - r = WaitForSingleObject( mutex, 30000 ); - if( WAIT_FAILED == r ) - goto done; - - if( WAIT_TIMEOUT == r ) + ret = QueryServiceStatus(hService, lpServiceStatus); + if (ret) { - SetLastError( ERROR_SERVICE_REQUEST_TIMEOUT ); - goto done; + ERR("failed to query service status\n"); + SetLastError(ERROR_SERVICE_NOT_ACTIVE); + return FALSE; } - mutex_owned = TRUE; - - /* open event objects */ - snprintfW( object_name, MAX_PATH, szServiceDispEventNameFmtW, hsvc->u.service.name ); - disp_event = OpenEventW( EVENT_ALL_ACCESS, FALSE, object_name ); - if( NULL == disp_event ) - goto done; - - snprintfW( object_name, MAX_PATH, szServiceAckEventNameFmtW, hsvc->u.service.name ); - ack_event = OpenEventW( EVENT_ALL_ACCESS, FALSE, object_name ); - if( NULL == ack_event ) - goto done; - - /* get service environment block */ - seb = open_seb_shmem( hsvc->u.service.name, &shmem ); - if( NULL == seb ) - goto done; - - /* send request */ - /* FIXME: check dwControl against controls accepted */ - seb->control_code = dwControl; - SetEvent( disp_event ); - - /* wait for acknowledgement */ - r = WaitForSingleObject( ack_event, 30000 ); - if( WAIT_FAILED == r ) - goto done; - if( WAIT_TIMEOUT == r ) + switch (lpServiceStatus->dwCurrentState) { - SetLastError( ERROR_SERVICE_REQUEST_TIMEOUT ); - goto done; + case SERVICE_STOPPED: + SetLastError(ERROR_SERVICE_NOT_ACTIVE); + return FALSE; + case SERVICE_START_PENDING: + if (dwControl==SERVICE_CONTROL_STOP) + break; + /* fall thru */ + case SERVICE_STOP_PENDING: + SetLastError(ERROR_SERVICE_CANNOT_ACCEPT_CTRL); + return FALSE; } - if( seb->dispatcher_error ) + handle = service_open_pipe(hsvc->name); + if (handle!=INVALID_HANDLE_VALUE) { - SetLastError( seb->dispatcher_error ); - goto done; + DWORD result = ERROR_SUCCESS; + ret = service_send_control(handle, dwControl, &result); + CloseHandle(handle); + if (result!=ERROR_SUCCESS) + { + SetLastError(result); + ret = FALSE; + } } - /* get status */ - if( lpServiceStatus ) - memcpy( lpServiceStatus, &seb->status, sizeof(SERVICE_STATUS) ); - ret = TRUE; - -done: - if( seb ) UnmapViewOfFile( seb ); - if( shmem ) CloseHandle( shmem ); - if( ack_event ) CloseHandle( ack_event ); - if( disp_event ) CloseHandle( disp_event ); - if( mutex_owned ) ReleaseMutex( mutex ); - if( mutex ) CloseHandle( mutex ); return ret; } @@ -906,9 +1014,9 @@ BOOL WINAPI CloseServiceHandle( SC_HANDLE hSCObject ) { - TRACE("(%p)\n", hSCObject); + TRACE("%p\n", hSCObject); - free_sc_handle( (struct sc_handle*) hSCObject ); + sc_handle_free( (struct sc_handle*) hSCObject ); return TRUE; } @@ -934,7 +1042,7 @@ LPWSTR lpServiceNameW; SC_HANDLE ret; - TRACE("%p %s %ld\n",hSCManager, debugstr_a(lpServiceName), dwDesiredAccess); + TRACE("%p %s %ld\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess); lpServiceNameW = SERV_dup(lpServiceName); ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess); @@ -951,12 +1059,13 @@ SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess) { - struct sc_handle *hscm = hSCManager; - struct sc_handle *retval; + struct sc_manager *hscm; + struct sc_service *hsvc; HKEY hKey; long r; + DWORD len; - TRACE("%p %s %ld\n",hSCManager, debugstr_w(lpServiceName), dwDesiredAccess); + TRACE("%p %s %ld\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess); if (!lpServiceName) { @@ -964,24 +1073,36 @@ return NULL; } - retval = alloc_sc_handle( SC_HTYPE_SERVICE ); - if( NULL == retval ) - return NULL; + hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER ); + if (!hscm) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } - r = RegOpenKeyExW( hscm->u.manager.hkey_scm_db, - lpServiceName, 0, KEY_ALL_ACCESS, &hKey ); + r = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hKey ); if (r!=ERROR_SUCCESS) { - free_sc_handle( retval ); SetLastError( ERROR_SERVICE_DOES_NOT_EXIST ); return NULL; } - init_service_handle( retval, hscm, hKey, lpServiceName ); + len = strlenW(lpServiceName)+1; + hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, + sizeof (struct sc_service) + len*sizeof(WCHAR), + sc_handle_destroy_service ); + if (!hsvc) + return NULL; + strcpyW( hsvc->name, lpServiceName ); + hsvc->hkey = hKey; - TRACE("returning %p\n",retval); + /* add reference to SCM handle */ + hscm->hdr.ref_count++; + hsvc->scm = hscm; + + TRACE("returning %p\n",hsvc); - return (SC_HANDLE) retval; + return (SC_HANDLE) &hsvc->hdr; } /****************************************************************************** @@ -996,11 +1117,11 @@ LPCWSTR lpDependencies, LPCWSTR lpServiceStartName, LPCWSTR lpPassword ) { - struct sc_handle *hscm = hSCManager; - struct sc_handle *retval; + struct sc_manager *hscm; + struct sc_service *hsvc = NULL; HKEY hKey; LONG r; - DWORD dp; + DWORD dp, len; static const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 }; static const WCHAR szType[] = {'T','y','p','e',0}; static const WCHAR szStart[] = {'S','t','a','r','t',0}; @@ -1012,17 +1133,18 @@ FIXME("%p %s %s\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); - retval = alloc_sc_handle( SC_HTYPE_SERVICE ); - if( NULL == retval ) + hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER ); + if (!hscm) + { + SetLastError( ERROR_INVALID_HANDLE ); return NULL; + } - r = RegCreateKeyExW(hscm->u.manager.hkey_scm_db, lpServiceName, 0, NULL, + r = RegCreateKeyExW(hscm->hkey, lpServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp); if (r!=ERROR_SUCCESS) goto error; - init_service_handle( retval, hscm, hKey, lpServiceName ); - if (dp != REG_CREATED_NEW_KEY) { SetLastError(ERROR_SERVICE_EXISTS); @@ -1091,10 +1213,22 @@ FIXME("Don't know how to add a ServiceStartName for a service.\n"); } - return (SC_HANDLE) retval; + len = strlenW(lpServiceName)+1; + hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, + sizeof (struct sc_service) + len*sizeof(WCHAR), + sc_handle_destroy_service ); + if (!hsvc) + return NULL; + strcpyW( hsvc->name, lpServiceName ); + hsvc->hkey = hKey; + hsvc->scm = hscm; + hscm->hdr.ref_count++; + + return (SC_HANDLE) &hsvc->hdr; error: - free_sc_handle( retval ); + if (hsvc) + sc_handle_free( &hsvc->hdr ); return NULL; } @@ -1157,13 +1291,21 @@ */ BOOL WINAPI DeleteService( SC_HANDLE hService ) { - struct sc_handle *hsvc = hService; - HKEY hKey = hsvc->u.service.hkey; + struct sc_service *hsvc; + HKEY hKey; WCHAR valname[MAX_PATH+1]; INT index = 0; LONG rc; DWORD size; + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + hKey = hsvc->hkey; + size = MAX_PATH+1; /* Clean out the values */ rc = RegEnumValueW(hKey, index, valname,&size,0,0,0,0); @@ -1176,11 +1318,10 @@ } RegCloseKey(hKey); - hsvc->u.service.hkey = NULL; + hsvc->hkey = NULL; /* delete the key */ - RegDeleteKeyW(hsvc->u.service.sc_manager->u.manager.hkey_scm_db, - hsvc->u.service.name); + RegDeleteKeyW(hsvc->scm->hkey, hsvc->name); return TRUE; } @@ -1209,178 +1350,160 @@ * Success: TRUE. * Failure: FALSE */ -BOOL WINAPI -StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, - LPCSTR *lpServiceArgVectors ) +BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, + LPCSTR *lpServiceArgVectors ) { LPWSTR *lpwstr=NULL; unsigned int i; + BOOL r; TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors); - if(dwNumServiceArgs) + if (dwNumServiceArgs) lpwstr = HeapAlloc( GetProcessHeap(), 0, dwNumServiceArgs*sizeof(LPWSTR) ); for(i=0; iu.service.hkey, _ImagePathW, NULL, &type, (LPVOID)str, &size); - if (r!=ERROR_SUCCESS) + /* read the executable path from memory */ + size = 0; + ret = RegQueryValueExW(hsvc->hkey, _ImagePathW, NULL, &type, NULL, &size); + if (ret!=ERROR_SUCCESS) return FALSE; - ExpandEnvironmentStringsW(str,path,sizeof(path)); - - TRACE("Starting service %s\n", debugstr_w(path) ); - - hLock = LockServiceDatabase( hsvc->u.service.sc_manager ); - if( NULL == hLock ) + str = HeapAlloc(GetProcessHeap(),0,size); + ret = RegQueryValueExW(hsvc->hkey, _ImagePathW, NULL, &type, (LPBYTE)str, &size); + if (ret==ERROR_SUCCESS) + { + size = ExpandEnvironmentStringsW(str,NULL,0); + path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR)); + ExpandEnvironmentStringsW(str,path,size); + } + HeapFree(GetProcessHeap(),0,str); + if (!path) return FALSE; - /* - * FIXME: start dependent services - */ + /* wait for the process to start and set an event or terminate */ + handles[0] = service_get_event_handle( hsvc->name ); + ZeroMemory(&si, sizeof(STARTUPINFOW)); + si.cb = sizeof(STARTUPINFOW); + r = CreateProcessW(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + if (r) + { + handles[1] = pi.hProcess; + ret = WaitForMultipleObjectsEx(2, handles, FALSE, 30000, FALSE); + if(ret != WAIT_OBJECT_0) + { + SetLastError(ERROR_IO_PENDING); + r = FALSE; + } - /* pass argv[0] (service name) to the service via global SCM lock object */ - shmem_lock = MapViewOfFile( hLock, FILE_MAP_ALL_ACCESS, - 0, 0, MAX_SERVICE_NAME * sizeof(WCHAR) ); - if( NULL == shmem_lock ) - { - ERR("Couldn't map shared memory\n"); - goto done; + CloseHandle( pi.hThread ); + CloseHandle( pi.hProcess ); } - strcpyW( shmem_lock, hsvc->u.service.name ); - - /* create service environment block */ - size = sizeof(struct SEB); - for( i = 0; i < dwNumServiceArgs; i++ ) - size += sizeof(WCHAR) * (1 + strlenW( lpServiceArgVectors[ i ] )); + CloseHandle( handles[0] ); + HeapFree(GetProcessHeap(),0,path); + return r; +} - snprintfW( str, MAX_PATH, szServiceShmemNameFmtW, hsvc->u.service.name ); - hServiceShmem = CreateFileMappingW( INVALID_HANDLE_VALUE, - NULL, PAGE_READWRITE, 0, size, str ); - if( NULL == hServiceShmem ) - { - ERR("Couldn't create shared memory object\n"); - goto done; - } - if( GetLastError() == ERROR_ALREADY_EXISTS ) - { - SetLastError( ERROR_SERVICE_ALREADY_RUNNING ); - goto done; - } - seb = MapViewOfFile( hServiceShmem, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); - if( NULL == seb ) - { - ERR("Couldn't map shared memory\n"); - goto done; - } +static BOOL service_wait_for_startup(SC_HANDLE hService) +{ + DWORD i; + SERVICE_STATUS status; + BOOL r = FALSE; - /* copy service args to SEB */ - seb->argc = dwNumServiceArgs; - argptr = (LPWSTR) &seb[1]; - for( i = 0; i < dwNumServiceArgs; i++ ) - { - strcpyW( argptr, lpServiceArgVectors[ i ] ); - argptr += 1 + strlenW( argptr ); - } + TRACE("%p\n", hService); - wait = CreateSemaphoreW(NULL,0,1,szWaitServiceStartW); - if (!wait) + for (i=0; i<30; i++) { - ERR("Couldn't create wait semaphore\n"); - goto done; + status.dwCurrentState = 0; + r = QueryServiceStatus(hService, &status); + if (!r) + break; + if (status.dwCurrentState == SERVICE_RUNNING) + { + TRACE("Service started successfully\n"); + break; + } + r = FALSE; + Sleep(1000); } + return r; +} - ZeroMemory(&startupinfo,sizeof(STARTUPINFOW)); - startupinfo.cb = sizeof(STARTUPINFOW); +/****************************************************************************** + * StartServiceW [ADVAPI32.@] + * + * See StartServiceA. + */ +BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, + LPCWSTR *lpServiceArgVectors) +{ + struct sc_service *hsvc; + BOOL r = FALSE; + SC_LOCK hLock; + HANDLE handle = INVALID_HANDLE_VALUE; - r = CreateProcessW(NULL, - path, - NULL, /* process security attribs */ - NULL, /* thread security attribs */ - FALSE, /* inherit handles */ - 0, /* creation flags */ - NULL, /* environment */ - NULL, /* current directory */ - &startupinfo, /* startup info */ - &procinfo); /* process info */ + TRACE("%p %ld %p\n", hService, dwNumServiceArgs, lpServiceArgVectors); - if(r == FALSE) + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) { - ERR("Couldn't start process\n"); - goto done; + SetLastError(ERROR_INVALID_HANDLE); + return r; } - CloseHandle( procinfo.hThread ); - /* docs for StartServiceCtrlDispatcher say this should be 30 sec */ - r = WaitForSingleObject(wait,30000); - if( WAIT_FAILED == r ) + hLock = LockServiceDatabase(hsvc->scm); + if (!hLock) + return r; + + handle = service_open_pipe(hsvc->name); + if (handle==INVALID_HANDLE_VALUE) { - CloseHandle( procinfo.hProcess ); - goto done; + /* start the service process */ + if (service_start_process(hsvc)) + handle = service_open_pipe(hsvc->name); } - if( WAIT_TIMEOUT == r ) + + if (handle != INVALID_HANDLE_VALUE) { - TerminateProcess( procinfo.hProcess, 1 ); - CloseHandle( procinfo.hProcess ); - SetLastError( ERROR_SERVICE_REQUEST_TIMEOUT ); - goto done; + service_send_start_message(handle, lpServiceArgVectors, dwNumServiceArgs); + CloseHandle(handle); + r = TRUE; } - /* allright */ - CloseHandle( procinfo.hProcess ); - ret = TRUE; - -done: - if( wait ) CloseHandle( wait ); - if( seb != NULL ) UnmapViewOfFile( seb ); - if( hServiceShmem != NULL ) CloseHandle( hServiceShmem ); - if( shmem_lock != NULL ) UnmapViewOfFile( shmem_lock ); UnlockServiceDatabase( hLock ); - return ret; + + TRACE("returning %d\n", r); + + service_wait_for_startup(hService); + + return r; } /****************************************************************************** @@ -1391,65 +1514,44 @@ * lpservicestatus [] * */ -BOOL WINAPI -QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus ) +BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, + LPSERVICE_STATUS lpservicestatus) { - struct sc_handle *hsvc = hService; + struct sc_service *hsvc; + DWORD size, type, val; + HANDLE pipe; LONG r; - DWORD type, val, size; - WCHAR object_name[ MAX_PATH ]; - HANDLE mutex, shmem = NULL; - struct SEB *seb = NULL; - BOOL ret = FALSE, mutex_owned = FALSE; - - /* try to open service mutex */ - snprintfW( object_name, MAX_PATH, szServiceMutexNameFmtW, hsvc->u.service.name ); - mutex = OpenMutexW( MUTEX_ALL_ACCESS, FALSE, object_name ); - if( NULL == mutex ) - goto stopped; - - /* hold mutex */ - r = WaitForSingleObject( mutex, 30000 ); - if( WAIT_FAILED == r ) - goto done; - - if( WAIT_TIMEOUT == r ) - { - SetLastError( ERROR_SERVICE_REQUEST_TIMEOUT ); - goto done; - } - mutex_owned = TRUE; - - /* get service environment block */ - seb = open_seb_shmem( hsvc->u.service.name, &shmem ); - if( NULL == seb ) - goto done; - - /* get status */ - memcpy( lpservicestatus, &seb->status, sizeof(SERVICE_STATUS) ); - ret = TRUE; - -done: - if( seb ) UnmapViewOfFile( seb ); - if( shmem ) CloseHandle( shmem ); - if( mutex_owned ) ReleaseMutex( mutex ); - CloseHandle( mutex ); - return ret; - -stopped: - /* service stopped */ - /* read the service type from the registry */ - size = sizeof(val); - r = RegQueryValueExA(hsvc->u.service.hkey, "Type", NULL, &type, (LPBYTE)&val, &size); - if(type!=REG_DWORD) + + TRACE("%p %p\n", hService, lpservicestatus); + + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) { - ERR("invalid Type\n"); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } + + pipe = service_open_pipe(hsvc->name); + if (pipe != INVALID_HANDLE_VALUE) + { + r = service_get_status(pipe, lpservicestatus); + CloseHandle(pipe); + if (r) + return TRUE; + } + + TRACE("Failed to read service status\n"); + + /* read the service type from the registry */ + size = sizeof(val); + r = RegQueryValueExA(hsvc->hkey, "Type", NULL, &type, (LPBYTE)&val, &size); + if(r!=ERROR_SUCCESS || type!=REG_DWORD) + val = 0; + lpservicestatus->dwServiceType = val; - lpservicestatus->dwCurrentState = 1; /* stopped */ + lpservicestatus->dwCurrentState = SERVICE_STOPPED; /* stopped */ lpservicestatus->dwControlsAccepted = 0; - lpservicestatus->dwWin32ExitCode = NO_ERROR; + lpservicestatus->dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED; lpservicestatus->dwServiceSpecificExitCode = 0; lpservicestatus->dwCheckPoint = 0; lpservicestatus->dwWaitHint = 0; @@ -1497,7 +1599,8 @@ static const CHAR szImagePath[] = "ImagePath"; static const CHAR szGroup[] = "Group"; static const CHAR szDependencies[] = "Dependencies"; - HKEY hKey = ((struct sc_handle*) hService)->u.service.hkey; + struct sc_service *hsvc; + HKEY hKey; CHAR str_buffer[ MAX_PATH ]; LONG r; DWORD type, val, sz, total, n; @@ -1506,6 +1609,14 @@ TRACE("%p %p %ld %p\n", hService, lpServiceConfig, cbBufSize, pcbBytesNeeded); + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + hKey = hsvc->hkey; + /* calculate the size required first */ total = sizeof (QUERY_SERVICE_CONFIGA); @@ -1636,15 +1747,24 @@ static const WCHAR szGroup[] = {'G','r','o','u','p',0}; static const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0}; - HKEY hKey = ((struct sc_handle*) hService)->u.service.hkey; WCHAR str_buffer[ MAX_PATH ]; LONG r; DWORD type, val, sz, total, n; LPBYTE p; + HKEY hKey; + struct sc_service *hsvc; TRACE("%p %p %ld %p\n", hService, lpServiceConfig, cbBufSize, pcbBytesNeeded); + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + hKey = hsvc->hkey; + /* calculate the size required first */ total = sizeof (QUERY_SERVICE_CONFIGW); @@ -1758,36 +1878,78 @@ return TRUE; } +/****************************************************************************** + * EnumServicesStatusA [ADVAPI32.@] + */ +BOOL WINAPI +EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType, + DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, + DWORD cbBufSize, LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) +{ + FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, + dwServiceType, dwServiceState, lpServices, cbBufSize, + pcbBytesNeeded, lpServicesReturned, lpResumeHandle); + SetLastError (ERROR_ACCESS_DENIED); + return FALSE; +} + +/****************************************************************************** + * EnumServicesStatusW [ADVAPI32.@] + */ +BOOL WINAPI +EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType, + DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, LPDWORD lpResumeHandle ) +{ + FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager, + dwServiceType, dwServiceState, lpServices, cbBufSize, + pcbBytesNeeded, lpServicesReturned, lpResumeHandle); + SetLastError (ERROR_ACCESS_DENIED); + return FALSE; +} + +/****************************************************************************** + * GetServiceKeyNameA [ADVAPI32.@] + */ BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPDWORD lpcchBuffer ) { FIXME("%p %s %p %p\n", hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer); - return FALSE; } +/****************************************************************************** + * GetServiceKeyNameW [ADVAPI32.@] + */ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName, LPWSTR lpServiceName, LPDWORD lpcchBuffer ) { FIXME("%p %s %p %p\n", hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer); - return FALSE; } +/****************************************************************************** + * QueryServiceLockStatusA [ADVAPI32.@] + */ BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager, LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, DWORD cbBufSize, LPDWORD pcbBytesNeeded) { - FIXME("%p %p 0x%08lx %p - stub\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded); + FIXME("%p %p %08lx %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded); return FALSE; } +/****************************************************************************** + * QueryServiceLockStatusW [ADVAPI32.@] + */ BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager, LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, DWORD cbBufSize, LPDWORD pcbBytesNeeded) { - FIXME("%p %p 0x%08lx %p - stub\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded); + FIXME("%p %p %08lx %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded); return FALSE; } @@ -1803,7 +1965,6 @@ return FALSE; } - /****************************************************************************** * GetServiceDisplayNameW [ADVAPI32.@] */ @@ -1815,7 +1976,6 @@ return FALSE; } - /****************************************************************************** * ChangeServiceConfigW [ADVAPI32.@] */ @@ -1921,7 +2081,16 @@ BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo) { - HKEY hKey = ((struct sc_handle*) hService)->u.service.hkey; + HKEY hKey; + struct sc_service *hsvc; + + hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE); + if (!hsvc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + hKey = hsvc->hkey; if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) { @@ -1952,10 +2121,10 @@ DWORD cbBufSize, LPDWORD pcbBytesNeeded) { PACL pACL = NULL; + FIXME("%p %ld %p %lu %p\n", hService, dwSecurityInformation, lpSecurityDescriptor, cbBufSize, pcbBytesNeeded); - InitializeSecurityDescriptor(lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); pACL = HeapAlloc( GetProcessHeap(), 0, sizeof(ACL) ); @@ -1975,13 +2144,15 @@ return TRUE; } +/****************************************************************************** + * SetServiceBits [ADVAPI32.@] + */ BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, BOOL bSetBitsOn, BOOL bUpdateImmediately) { - FIXME("0x%08lx 0x%08lx %x %x - stub\n", hServiceStatus, dwServiceBits, + FIXME("%08lx %08lx %x %x\n", hServiceStatus, dwServiceBits, bSetBitsOn, bUpdateImmediately); - return TRUE; } diff -urN wine-20050111/dlls/advapi32/tests/crypt.c wine-20050211/dlls/advapi32/tests/crypt.c --- wine-20050111/dlls/advapi32/tests/crypt.c 2005-01-04 21:31:53.000000000 +0100 +++ wine-20050211/dlls/advapi32/tests/crypt.c 2005-02-10 20:19:36.000000000 +0100 @@ -29,7 +29,7 @@ #include "wine/test.h" static const char szRsaBaseProv[] = MS_DEF_PROV_A; -static const char szNonExistentProv[] = "Wine Non Existent Cryptographic Provider v11.2"; +static const char szNonExistentProv[] = "Wine Nonexistent Cryptographic Provider v11.2"; static const char szKeySet[] = "wine_test_keyset"; static const char szBadKeySet[] = "wine_test_bad_keyset"; #define NON_DEF_PROV_TYPE 999 diff -urN wine-20050111/dlls/advapi32/tests/registry.c wine-20050211/dlls/advapi32/tests/registry.c --- wine-20050111/dlls/advapi32/tests/registry.c 2004-11-30 22:39:01.000000000 +0100 +++ wine-20050211/dlls/advapi32/tests/registry.c 2005-01-27 12:15:00.000000000 +0100 @@ -56,8 +56,7 @@ { if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main ); - assert (!RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Wine\\Test", 0, NULL, - REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_main, NULL )); + assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )); } static void create_test_entries(void) diff -urN wine-20050111/dlls/advpack/Makefile.in wine-20050211/dlls/advpack/Makefile.in --- wine-20050111/dlls/advpack/Makefile.in 2004-09-27 22:39:40.000000000 +0200 +++ wine-20050211/dlls/advpack/Makefile.in 2005-01-20 21:03:13.000000000 +0100 @@ -3,13 +3,15 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = advpack.dll -IMPORTS = setupapi user32 kernel32 ntdll +IMPORTS = setupapi version user32 kernel32 ntdll EXTRALIBS = $(LIBUNICODE) C_SRCS = \ advpack.c \ reg.c +SUBDIRS = tests + @MAKE_DLL_RULES@ ### Dependencies: diff -urN wine-20050111/dlls/advpack/advpack.c wine-20050211/dlls/advpack/advpack.c --- wine-20050111/dlls/advpack/advpack.c 2004-12-15 11:52:57.000000000 +0100 +++ wine-20050211/dlls/advpack/advpack.c 2005-01-20 21:03:13.000000000 +0100 @@ -24,6 +24,8 @@ #include "winbase.h" #include "winuser.h" #include "winreg.h" +#include "winver.h" +#include "winnls.h" #include "setupapi.h" #include "advpub.h" #include "wine/debug.h" @@ -96,3 +98,77 @@ return ret; } + +/*********************************************************************** + * NeedRebootInit (ADVPACK.@) + */ +DWORD WINAPI NeedRebootInit(VOID) +{ + FIXME("() stub!\n"); + return 0; +} + +/*********************************************************************** + * NeedReboot (ADVPACK.@) + */ +BOOL WINAPI NeedReboot(DWORD dwRebootCheck) +{ + FIXME("(0x%08lx) stub!\n", dwRebootCheck); + return FALSE; +} + +/*********************************************************************** + * GetVersionFromFile (ADVPACK.@) + */ +HRESULT WINAPI GetVersionFromFile( LPSTR Filename, LPDWORD MajorVer, + LPDWORD MinorVer, BOOL Version ) +{ + TRACE("(%s, %p, %p, %d)\n", Filename, MajorVer, MinorVer, Version); + return GetVersionFromFileEx(Filename, MajorVer, MinorVer, Version); +} + +/*********************************************************************** + * GetVersionFromFileEx (ADVPACK.@) + */ +HRESULT WINAPI GetVersionFromFileEx( LPSTR lpszFilename, LPDWORD pdwMSVer, + LPDWORD pdwLSVer, BOOL bVersion ) +{ + DWORD hdl, retval; + LPVOID pVersionInfo; + BOOL boolret; + VS_FIXEDFILEINFO *pFixedVersionInfo; + UINT uiLength; + TRACE("(%s, %p, %p, %d)\n", lpszFilename, pdwMSVer, pdwLSVer, bVersion); + + if (bVersion) + { + retval = GetFileVersionInfoSizeA(lpszFilename, &hdl); + if (retval == 0 || hdl != 0) + return E_FAIL; + + pVersionInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, retval); + if (pVersionInfo == NULL) + return E_FAIL; + GetFileVersionInfoA( lpszFilename, 0, retval, pVersionInfo); + + boolret = VerQueryValueA(pVersionInfo, "\\", + (LPVOID) &pFixedVersionInfo, &uiLength); + + HeapFree(GetProcessHeap(), 0, pVersionInfo); + + if (boolret) + { + *pdwMSVer = pFixedVersionInfo->dwFileVersionMS; + *pdwLSVer = pFixedVersionInfo->dwFileVersionLS; + } + else + return E_FAIL; + } + else + { + *pdwMSVer = GetUserDefaultUILanguage(); + *pdwLSVer = GetACP(); + } + + return S_OK; +} diff -urN wine-20050111/dlls/advpack/advpack.spec wine-20050211/dlls/advpack/advpack.spec --- wine-20050111/dlls/advpack/advpack.spec 2004-12-15 11:52:57.000000000 +0100 +++ wine-20050211/dlls/advpack/advpack.spec 2005-01-20 21:03:13.000000000 +0100 @@ -10,13 +10,13 @@ @ stub FileSaveMarkNotExist @ stub FileSaveRestore @ stub FileSaveRestoreOnINF -@ stub GetVersionFromFile -@ stub GetVersionFromFileEx +@ stdcall GetVersionFromFile(str ptr ptr long) +@ stdcall GetVersionFromFileEx(str ptr ptr long) @ stub IsNTAdmin @ stdcall LaunchINFSection(ptr ptr str long) @ stdcall LaunchINFSectionEx(ptr ptr str long) -@ stub NeedReboot -@ stub NeedRebootInit +@ stdcall NeedReboot(long) +@ stdcall NeedRebootInit() @ stub OpenINFEngine @ stub RebootCheckOnInstall @ stdcall RegInstall(ptr str ptr) diff -urN wine-20050111/dlls/advpack/tests/.cvsignore wine-20050211/dlls/advpack/tests/.cvsignore --- wine-20050111/dlls/advpack/tests/.cvsignore 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/advpack/tests/.cvsignore 2005-01-20 21:03:13.000000000 +0100 @@ -0,0 +1,3 @@ +Makefile +advpack.ok +testlist.c diff -urN wine-20050111/dlls/advpack/tests/Makefile.in wine-20050211/dlls/advpack/tests/Makefile.in --- wine-20050111/dlls/advpack/tests/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/advpack/tests/Makefile.in 2005-01-20 21:03:13.000000000 +0100 @@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +TESTDLL = advpack.dll +IMPORTS = advpack user32 kernel32 + +CTESTS = \ + advpack.c + +@MAKE_TEST_RULES@ + +### Dependencies: diff -urN wine-20050111/dlls/advpack/tests/advpack.c wine-20050211/dlls/advpack/tests/advpack.c --- wine-20050111/dlls/advpack/tests/advpack.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/advpack/tests/advpack.c 2005-01-20 21:03:13.000000000 +0100 @@ -0,0 +1,53 @@ +/* + * Unit tests for advpack.dll + * + * Copyright (C) 2005 Robert Reif + * + * 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 + */ + +#define NONAMELESSSTRUCT +#define NONAMELESSUNION +#include + +#include "wine/test.h" +#include "advpub.h" + +static void version_test() +{ + HRESULT hr; + DWORD major, minor; + + major = minor = 0; + hr = GetVersionFromFile("kernel32.dll", &major, &minor, FALSE); + ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " + "0x%08lx\n", hr); + + trace("kernel32.dll Language ID: 0x%08lx, Codepage ID: 0x%08lx\n", + major, minor); + + major = minor = 0; + hr = GetVersionFromFile("kernel32.dll", &major, &minor, TRUE); + ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " + "0x%08lx\n", hr); + + trace("kernel32.dll version: %d.%d.%d.%d\n", HIWORD(major), LOWORD(major), + HIWORD(minor), LOWORD(minor)); +} + +START_TEST(advpack) +{ + version_test(); +} diff -urN wine-20050111/dlls/atl/atl.spec wine-20050211/dlls/atl/atl.spec --- wine-20050111/dlls/atl/atl.spec 2004-12-27 18:08:08.000000000 +0100 +++ wine-20050211/dlls/atl/atl.spec 2005-01-19 18:00:32.000000000 +0100 @@ -2,19 +2,19 @@ 2 stub DllGetClassObject 3 stdcall -private DllRegisterServer() ATL_DllRegisterServer 4 stdcall -private DllUnregisterServer() ATL_DllUnregisterServer -10 stub AtlAdvise -11 stub AtlUnadvise -12 stub AtlFreeMarshalStream -13 stub AtlMarshalPtrInProc -14 stub AtlUnmarshalPtr -15 stub AtlModuleGetClassObject +10 stdcall AtlAdvise(ptr ptr ptr ptr) +11 stdcall AtlUnadvise(ptr ptr long) +12 stdcall AtlFreeMarshalStream(ptr) +13 stdcall AtlMarshalPtrInProc(ptr ptr ptr) +14 stdcall AtlUnmarshalPtr(ptr ptr ptr) +15 stdcall AtlModuleGetClassObject(ptr ptr ptr ptr) 16 stdcall AtlModuleInit(ptr long long) 17 stdcall AtlModuleRegisterClassObjects(ptr long long) 18 stdcall AtlModuleRegisterServer(ptr long ptr) -19 stub AtlModuleRegisterTypeLib -20 stub AtlModuleRevokeClassObjects +19 stdcall AtlModuleRegisterTypeLib(ptr wstr) +20 stdcall AtlModuleRevokeClassObjects(ptr) 21 stdcall AtlModuleTerm(ptr) -22 stub AtlModuleUnregisterServer +22 stdcall AtlModuleUnregisterServer(ptr ptr) 23 stdcall AtlModuleUpdateRegistryFromResourceD(ptr wstr long ptr ptr) 24 stub AtlWaitWithMessageLoop 25 stub AtlSetErrorInfo diff -urN wine-20050111/dlls/atl/atl_main.c wine-20050211/dlls/atl/atl_main.c --- wine-20050111/dlls/atl/atl_main.c 2004-12-27 18:08:08.000000000 +0100 +++ wine-20050211/dlls/atl/atl_main.c 2005-01-19 18:00:32.000000000 +0100 @@ -189,3 +189,85 @@ FIXME("%p %d %s\n", pM, bRegTypeLib, debugstr_guid(clsid)); return S_OK; } + +/*********************************************************************** + * AtlAdvise [ATL.@] + */ +HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, LPDWORD pdw) +{ + FIXME("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw); + return E_FAIL; +} + +/*********************************************************************** + * AtlUnadvise [ATL.@] + */ +HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw) +{ + FIXME("%p %p %ld\n", pUnkCP, iid, dw); + return S_OK; +} + +/*********************************************************************** + * AtlFreeMarshalStream [ATL.@] + */ +HRESULT WINAPI AtlFreeMarshalStream(IStream *stm) +{ + FIXME("%p\n", stm); + return S_OK; +} + +/*********************************************************************** + * AtlMarshalPtrInProc [ATL.@] + */ +HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm) +{ + FIXME("%p %p %p\n", pUnk, iid, pstm); + return E_FAIL; +} + +/*********************************************************************** + * AtlUnmarshalPtr [ATL.@] + */ +HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk) +{ + FIXME("%p %p %p\n", stm, iid, ppUnk); + return E_FAIL; +} + +/*********************************************************************** + * AtlModuleGetClassObject [ATL.@] + */ +HRESULT WINAPI AtlModuleGetClassObject(_ATL_MODULEW *pm, REFCLSID rclsid, + REFIID riid, LPVOID *ppv) +{ + FIXME("%p %p %p %p\n", pm, rclsid, riid, ppv); + return E_FAIL; +} + +/*********************************************************************** + * AtlModuleGetClassObject [ATL.@] + */ +HRESULT WINAPI AtlModuleRegisterTypeLib(_ATL_MODULEW *pm, LPCOLESTR lpszIndex) +{ + FIXME("%p %s\n", pm, debugstr_w(lpszIndex)); + return E_FAIL; +} + +/*********************************************************************** + * AtlModuleRevokeClassObjects [ATL.@] + */ +HRESULT WINAPI AtlModuleRevokeClassObjects(_ATL_MODULEW *pm) +{ + FIXME("%p\n", pm); + return E_FAIL; +} + +/*********************************************************************** + * AtlModuleUnregisterServer [ATL.@] + */ +HRESULT WINAPI AtlModuleUnregisterServer(_ATL_MODULEW *pm, const CLSID *clsid) +{ + FIXME("%p %s\n", pm, debugstr_guid(clsid)); + return E_FAIL; +} diff -urN wine-20050111/dlls/avifil32/acmstream.c wine-20050211/dlls/avifil32/acmstream.c --- wine-20050111/dlls/avifil32/acmstream.c 2004-10-05 20:10:21.000000000 +0200 +++ wine-20050211/dlls/avifil32/acmstream.c 2005-01-14 16:10:52.000000000 +0100 @@ -147,23 +147,25 @@ static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); + TRACE("(%p) -> %ld\n", iface, ref); /* also add reference to the nested stream */ if (This->pStream != NULL) IAVIStream_AddRef(This->pStream); - return ++(This->ref); + return ref; } static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref - 1); + TRACE("(%p) -> %ld\n", iface, ref); - if (This->ref == 0) { + if (ref == 0) { /* destruct */ if (This->has != NULL) { if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) @@ -202,7 +204,7 @@ if (This->pStream != NULL) IAVIStream_Release(This->pStream); - return --This->ref; + return ref; } /* lParam1: PAVISTREAM diff -urN wine-20050111/dlls/avifil32/avifile.c wine-20050211/dlls/avifil32/avifile.c --- wine-20050111/dlls/avifil32/avifile.c 2004-12-09 15:08:00.000000000 +0100 +++ wine-20050211/dlls/avifil32/avifile.c 2005-01-14 16:10:52.000000000 +0100 @@ -282,21 +282,22 @@ static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface) { IAVIFileImpl *This = (IAVIFileImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); - return InterlockedIncrement(&This->ref); + TRACE("(%p) -> %ld\n", iface, ref); + + return ref; } static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface) { IAVIFileImpl *This = (IAVIFileImpl *)iface; UINT i; - ULONG ret; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref - 1); + TRACE("(%p) -> %ld\n", iface, ref); - ret = InterlockedDecrement(&This->ref); - if (!ret) { + if (!ref) { if (This->fDirty) { /* need to write headers to file */ AVIFILE_SaveFile(This); @@ -337,7 +338,7 @@ LocalFree((HLOCAL)This); } - return ret; + return ref; } static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, LPAVIFILEINFOW afi, @@ -737,27 +738,28 @@ static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream *iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); + TRACE("(%p) -> %ld\n", iface, ref); /* also add ref to parent, so that it doesn't kill us */ if (This->paf != NULL) IAVIFile_AddRef((PAVIFILE)This->paf); - return InterlockedIncrement(&This->ref); + return ref; } static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; - ULONG ret = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, ret); + TRACE("(%p) -> %ld\n", iface, ref); if (This->paf != NULL) IAVIFile_Release((PAVIFILE)This->paf); - return ret; + return ref; } static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream *iface, LPARAM lParam1, diff -urN wine-20050111/dlls/avifil32/editstream.c wine-20050211/dlls/avifil32/editstream.c --- wine-20050111/dlls/avifil32/editstream.c 2004-10-05 06:16:21.000000000 +0200 +++ wine-20050211/dlls/avifil32/editstream.c 2005-01-14 16:10:52.000000000 +0100 @@ -381,20 +381,23 @@ static ULONG WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface) { IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); - return ++(This->ref); + TRACE("(%p) -> %ld\n", iface, ref); + + return ref; } static ULONG WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface) { IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface; DWORD i; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref - 1); + TRACE("(%p) -> %ld\n", iface, ref); - if (!--(This->ref)) { - /* releaase memory */ + if (!ref) { + /* release memory */ if (This->pg != NULL) AVIStreamGetFrameClose(This->pg); if (This->pStreams != NULL) { @@ -408,7 +411,7 @@ LocalFree((HLOCAL)This); return 0; } - return This->ref; + return ref; } static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart, diff -urN wine-20050111/dlls/avifil32/getframe.c wine-20050211/dlls/avifil32/getframe.c --- wine-20050111/dlls/avifil32/getframe.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/avifil32/getframe.c 2005-01-14 16:10:52.000000000 +0100 @@ -155,19 +155,21 @@ static ULONG WINAPI IGetFrame_fnAddRef(IGetFrame *iface) { IGetFrameImpl *This = (IGetFrameImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p)\n", iface); - return ++(This->ref); + return ref; } static ULONG WINAPI IGetFrame_fnRelease(IGetFrame *iface) { IGetFrameImpl *This = (IGetFrameImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)\n", iface); - if (!--(This->ref)) { + if (!ref) { AVIFILE_CloseCompressor(This); if (This->pStream != NULL) { IAVIStream_Release(This->pStream); @@ -178,7 +180,7 @@ return 0; } - return This->ref; + return ref; } static LPVOID WINAPI IGetFrame_fnGetFrame(IGetFrame *iface, LONG lPos) diff -urN wine-20050111/dlls/avifil32/icmstream.c wine-20050211/dlls/avifil32/icmstream.c --- wine-20050111/dlls/avifil32/icmstream.c 2004-11-29 19:00:11.000000000 +0100 +++ wine-20050211/dlls/avifil32/icmstream.c 2005-01-14 16:10:52.000000000 +0100 @@ -163,23 +163,25 @@ static ULONG WINAPI ICMStream_fnAddRef(IAVIStream *iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); + TRACE("(%p) -> %ld\n", iface, ref); /* also add reference to the nested stream */ if (This->pStream != NULL) IAVIStream_AddRef(This->pStream); - return ++(This->ref); + return ref; } static ULONG WINAPI ICMStream_fnRelease(IAVIStream* iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref - 1); + TRACE("(%p) -> %ld\n", iface, ref); - if (This->ref == 0) { + if (ref == 0) { /* destruct */ if (This->pg != NULL) { AVIStreamGetFrameClose(This->pg); @@ -224,7 +226,7 @@ if (This->pStream != NULL) IAVIStream_Release(This->pStream); - return --This->ref; + return ref; } /* lParam1: PAVISTREAM diff -urN wine-20050111/dlls/avifil32/tmpfile.c wine-20050211/dlls/avifil32/tmpfile.c --- wine-20050111/dlls/avifil32/tmpfile.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/avifil32/tmpfile.c 2005-01-14 16:10:52.000000000 +0100 @@ -152,18 +152,21 @@ static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface) { ITmpFileImpl *This = (ITmpFileImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref + 1); - return ++(This->ref); + TRACE("(%p) -> %ld\n", iface, ref); + + return ref; } static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface) { ITmpFileImpl *This = (ITmpFileImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) -> %ld\n", iface, This->ref - 1); + TRACE("(%p) -> %ld\n", iface, ref); - if (!--(This->ref)) { + if (!ref) { unsigned int i; for (i = 0; i < This->fInfo.dwStreams; i++) { @@ -178,7 +181,7 @@ return 0; } - return This->ref; + return ref; } static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface, diff -urN wine-20050111/dlls/avifil32/wavfile.c wine-20050211/dlls/avifil32/wavfile.c --- wine-20050111/dlls/avifil32/wavfile.c 2004-12-20 20:27:07.000000000 +0100 +++ wine-20050211/dlls/avifil32/wavfile.c 2005-01-14 16:10:52.000000000 +0100 @@ -272,16 +272,17 @@ TRACE("(%p)\n",iface); - return ++(This->ref); + return InterlockedIncrement(&This->ref); } static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface) { IAVIFileImpl *This = (IAVIFileImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)\n",iface); - if (!--(This->ref)) { + if (!ref) { if (This->fDirty) { /* need to write headers to file */ AVIFILE_SaveFile(This); @@ -309,7 +310,7 @@ LocalFree((HLOCAL)This); return 0; } - return This->ref; + return ref; } static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, LPAVIFILEINFOW afi, diff -urN wine-20050111/dlls/cfgmgr32/cfgmgr32.spec wine-20050211/dlls/cfgmgr32/cfgmgr32.spec --- wine-20050111/dlls/cfgmgr32/cfgmgr32.spec 2004-05-03 22:05:11.000000000 +0200 +++ wine-20050211/dlls/cfgmgr32/cfgmgr32.spec 2005-01-20 11:37:08.000000000 +0100 @@ -60,7 +60,7 @@ @ stub CM_Get_DevNode_Registry_Property_ExW @ stub CM_Get_DevNode_Status @ stub CM_Get_DevNode_Status_Ex -@ stub CM_Get_Device_IDA +@ stdcall CM_Get_Device_IDA(ptr ptr long long) @ stub CM_Get_Device_IDW @ stub CM_Get_Device_ID_ExA @ stub CM_Get_Device_ID_ExW @@ -72,7 +72,7 @@ @ stub CM_Get_Device_ID_List_SizeW @ stub CM_Get_Device_ID_List_Size_ExA @ stub CM_Get_Device_ID_List_Size_ExW -@ stub CM_Get_Device_ID_Size +@ stdcall CM_Get_Device_ID_Size(ptr ptr long) @ stub CM_Get_Device_ID_Size_Ex @ stub CM_Get_Device_Interface_AliasA @ stub CM_Get_Device_Interface_AliasW diff -urN wine-20050111/dlls/cfgmgr32/main.c wine-20050211/dlls/cfgmgr32/main.c --- wine-20050111/dlls/cfgmgr32/main.c 2003-10-31 04:38:07.000000000 +0100 +++ wine-20050211/dlls/cfgmgr32/main.c 2005-01-20 11:37:08.000000000 +0100 @@ -1,6 +1,7 @@ /* * cfgmgr32 implementation * + * Copyright 2004 Aric Stewart for CodeWeavers * Copyright 2003 Mike McCormack for CodeWeavers * * This library is free software; you can redistribute it and/or @@ -22,15 +23,12 @@ #include "windef.h" #include "winbase.h" #include "winnt.h" +#include "cfgmgr32.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(cfgmgr32); -typedef DWORD CONFIGRET; - -#define CR_SUCCESS 0 - CONFIGRET WINAPI CM_Get_Device_ID_ListA( PCSTR pszFilter, PCHAR Buffer, ULONG BufferLen, ULONG ulFlags ) { @@ -38,3 +36,19 @@ memset(Buffer,0,2); return CR_SUCCESS; } + +CONFIGRET WINAPI CM_Get_Device_ID_Size( ULONG* pulLen, LPVOID dnDevInst, + ULONG ulFlags) +{ + FIXME("%p %p %lu\n",pulLen, dnDevInst, ulFlags); + *pulLen = 1; + return CR_SUCCESS; +} + +CONFIGRET WINAPI CM_Get_Device_IDA( LPVOID dnDevInst, LPSTR Buffer, + ULONG BufferLen, ULONG ulFlags) +{ + FIXME("%p, %p, %lu %lu\n",dnDevInst, Buffer, BufferLen, ulFlags); + Buffer[0] = 0; + return CR_SUCCESS; +} diff -urN wine-20050111/dlls/comctl32/listview.c wine-20050211/dlls/comctl32/listview.c --- wine-20050111/dlls/comctl32/listview.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050211/dlls/comctl32/listview.c 2005-01-26 22:09:05.000000000 +0100 @@ -253,7 +253,7 @@ BOOL bRedraw; /* Turns on/off repaints & invalidations */ BOOL bAutoarrange; /* Autoarrange flag when NOT in LVS_AUTOARRANGE */ BOOL bFocus; - BOOL bDoChangeNotify; /* send change notification messages? */ + BOOL bDoChangeNotify; /* send change notification messages? */ INT nFocusedItem; RECT rcFocus; DWORD dwStyle; /* the cached window GWL_STYLE */ @@ -4143,7 +4143,7 @@ for (i = infoPtr->nItemCount - 1; i >= 0; i--) { - /* send LVN_DELETEITEM notification, if not supressed */ + /* send LVN_DELETEITEM notification, if not suppressed */ if (!bSuppress) notify_deleteitem(infoPtr, i); if (!(infoPtr->dwStyle & LVS_OWNERDATA)) { @@ -6294,11 +6294,11 @@ lphdi->mask |= HDI_FORMAT; /* set text alignment (leftmost column must be left-aligned) */ - if (nColumn == 0 || lpColumn->fmt & LVCFMT_LEFT) + if (nColumn == 0 || (lpColumn->fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT) lphdi->fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_RIGHT) + else if ((lpColumn->fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT) lphdi->fmt |= HDF_RIGHT; - else if (lpColumn->fmt & LVCFMT_CENTER) + else if ((lpColumn->fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_CENTER) lphdi->fmt |= HDF_CENTER; if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) diff -urN wine-20050111/dlls/comctl32/pager.c wine-20050211/dlls/comctl32/pager.c --- wine-20050111/dlls/comctl32/pager.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050211/dlls/comctl32/pager.c 2005-01-17 14:38:28.000000000 +0100 @@ -836,16 +836,6 @@ if (dwStyle & PGS_DRAGNDROP) FIXME("[%p] Drag and Drop style is not implemented yet.\n", hwnd); - /* - * If neither horizontal nor vertical style specified, default to vertical. - * This is probably not necessary, since the style may be set later on as - * the control is initialized, but just in case it isn't, set it here. - */ - if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT)) - { - dwStyle |= PGS_VERT; - SetWindowLongA(hwnd, GWL_STYLE, dwStyle); - } return 0; } diff -urN wine-20050111/dlls/comctl32/status.c wine-20050211/dlls/comctl32/status.c --- wine-20050111/dlls/comctl32/status.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050211/dlls/comctl32/status.c 2005-02-01 19:53:59.000000000 +0100 @@ -650,6 +650,7 @@ { STATUSWINDOWPART *part=NULL; BOOL changed = FALSE; + INT oldStyle; if (style & SBT_OWNERDRAW) { TRACE("part %d, text %p\n",nPart,text); @@ -671,11 +672,15 @@ if (part->style != style) changed = TRUE; + oldStyle = part->style; part->style = style; if (style & SBT_OWNERDRAW) { - if (part->text == text) - return TRUE; - part->text = (LPWSTR)text; + if (!(oldStyle & SBT_OWNERDRAW)) { + if (part->text) + Free (part->text); + } else if (part->text == text) + return TRUE; + part->text = (LPWSTR)text; } else { LPWSTR ntext; @@ -694,7 +699,7 @@ /* check if text is unchanged -> no need to redraw */ if (text) { if (!changed && part->text && !lstrcmpW(ntext, part->text)) { - if (!isW) Free(ntext); + Free(ntext); return TRUE; } } else { @@ -702,7 +707,7 @@ return TRUE; } - if (part->text) + if (part->text && !(oldStyle & SBT_OWNERDRAW)) Free (part->text); part->text = ntext; } @@ -885,9 +890,9 @@ dwStyle = GetWindowLongW (hwnd, GWL_STYLE); /* statusbars on managed windows should not have SIZEGRIP style */ - if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent) - if (GetWindowLongW (lpCreate->hwndParent, GWL_EXSTYLE) & WS_EX_MANAGED) - SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP); + if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent && + GetPropA( lpCreate->hwndParent, "__wine_x11_managed" )) + SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP); if ((hdc = GetDC (hwnd))) { TEXTMETRICW tm; diff -urN wine-20050111/dlls/comctl32/tests/imagelist.c wine-20050211/dlls/comctl32/tests/imagelist.c --- wine-20050111/dlls/comctl32/tests/imagelist.c 2004-12-13 22:19:02.000000000 +0100 +++ wine-20050211/dlls/comctl32/tests/imagelist.c 2005-02-10 20:19:36.000000000 +0100 @@ -307,9 +307,9 @@ ok(hicon3 != 0, "no hicon3\n"); /* remove when nothing exists */ - ok(!ImageList_Remove(himl,0),"removed non-existent icon\n"); + ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n"); /* removing everything from an empty imagelist should succeed */ - ok(ImageList_RemoveAll(himl),"removed non-existent icon\n"); + ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n"); /* add three */ ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n"); @@ -317,7 +317,7 @@ ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n"); /* remove an index out of range */ - ok(!ImageList_Remove(himl,4711),"removed non-existent icon\n"); + ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n"); /* remove three */ ok(ImageList_Remove(himl,0),"can't remove 0\n"); @@ -325,7 +325,7 @@ ok(ImageList_Remove(himl,0),"can't remove 0\n"); /* remove one extra */ - ok(!ImageList_Remove(himl,0),"removed non-existent icon\n"); + ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n"); /* destroy it */ ok(ImageList_Destroy(himl),"destroy imagelist failed\n"); diff -urN wine-20050111/dlls/comctl32/toolbar.c wine-20050211/dlls/comctl32/toolbar.c --- wine-20050111/dlls/comctl32/toolbar.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050211/dlls/comctl32/toolbar.c 2005-01-28 18:19:29.000000000 +0100 @@ -64,7 +64,7 @@ * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe, * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe, * setparnt.exe, setrows.exe, toolwnd.exe. - * - Microsofts controlspy examples. + * - Microsoft's controlspy examples. * - Charles Petzold's 'Programming Windows': gadgets.exe */ @@ -4269,7 +4269,7 @@ LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam; HBITMAP hBitmap; int i = 0, nOldButtons = 0, pos = 0; - int nOldBitmaps, nNewBitmaps; + int nOldBitmaps, nNewBitmaps = 0; HIMAGELIST himlDef = 0; TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n", @@ -4322,6 +4322,7 @@ for (i = pos + nOldBitmaps - 1; i >= pos; i--) ImageList_Remove(himlDef, i); + if (hBitmap) { BITMAP bmp; HBITMAP hOldBitmapBitmap, hOldBitmapLoad, hbmLoad; @@ -6079,24 +6080,26 @@ TRACKMOUSEEVENT trackinfo; INT nHit; TBUTTON_INFO *btnPtr; + + if (infoPtr->dwStyle & TBSTYLE_FLAT) { + /* fill in the TRACKMOUSEEVENT struct */ + trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); + trackinfo.dwFlags = TME_QUERY; + trackinfo.hwndTrack = hwnd; + trackinfo.dwHoverTime = HOVER_DEFAULT; - /* fill in the TRACKMOUSEEVENT struct */ - trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); - trackinfo.dwFlags = TME_QUERY; - trackinfo.hwndTrack = hwnd; - trackinfo.dwHoverTime = HOVER_DEFAULT; - - /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ - _TrackMouseEvent(&trackinfo); - - /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ - if(!(trackinfo.dwFlags & TME_LEAVE)) { - trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ - - /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ - /* and can properly deactivate the hot toolbar button */ + /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ _TrackMouseEvent(&trackinfo); - } + + /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ + if(!(trackinfo.dwFlags & TME_LEAVE)) { + trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ + + /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ + /* and can properly deactivate the hot toolbar button */ + _TrackMouseEvent(&trackinfo); + } + } if (infoPtr->hwndToolTip) TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd, @@ -6107,7 +6110,7 @@ nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - if (!infoPtr->bAnchor || (nHit >= 0)) + if ((infoPtr->dwStyle & TBSTYLE_FLAT) && (!infoPtr->bAnchor || (nHit >= 0))) TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE); if (infoPtr->nOldHit != nHit) diff -urN wine-20050111/dlls/comctl32/trackbar.c wine-20050211/dlls/comctl32/trackbar.c --- wine-20050111/dlls/comctl32/trackbar.c 2005-01-09 17:42:54.000000000 +0100 +++ wine-20050211/dlls/comctl32/trackbar.c 2005-01-17 14:38:44.000000000 +0100 @@ -1336,7 +1336,7 @@ TRACKBAR_Create (HWND hwnd, LPCREATESTRUCTW lpcs) { TRACKBAR_INFO *infoPtr; - DWORD oldStyle, newStyle; + DWORD dwStyle; infoPtr = (TRACKBAR_INFO *)Alloc (sizeof(TRACKBAR_INFO)); if (!infoPtr) return -1; @@ -1359,19 +1359,10 @@ TRACKBAR_InitializeThumb (infoPtr); - oldStyle = newStyle = GetWindowLongW (hwnd, GWL_STYLE); - if (oldStyle & TBS_VERT) { - if (! (oldStyle & (TBS_LEFT | TBS_RIGHT | TBS_BOTH)) ) - newStyle |= TBS_RIGHT; - } else { - if (! (oldStyle & (TBS_TOP | TBS_BOTTOM | TBS_BOTH)) ) - newStyle |= TBS_BOTTOM; - } - if (newStyle != oldStyle) - SetWindowLongW (hwnd, GWL_STYLE, newStyle); + dwStyle = GetWindowLongW (hwnd, GWL_STYLE); /* Create tooltip control */ - if (newStyle & TBS_TOOLTIPS) { + if (dwStyle & TBS_TOOLTIPS) { infoPtr->hwndToolTip = CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, 0, diff -urN wine-20050111/dlls/comctl32/treeview.c wine-20050211/dlls/comctl32/treeview.c --- wine-20050111/dlls/comctl32/treeview.c 2005-01-11 11:39:33.000000000 +0100 +++ wine-20050211/dlls/comctl32/treeview.c 2005-01-14 16:13:24.000000000 +0100 @@ -2345,7 +2345,7 @@ SelectObject(hdc, hOldPen); DeleteObject(hNewPen); - if (height < 16 || width < 16) + if (height < 18 || width < 18) { MoveToEx(hdc, centerx - plussize + 1, centery, NULL); LineTo(hdc, centerx + plussize, centery); diff -urN wine-20050111/dlls/commdlg/cdlg.h wine-20050211/dlls/commdlg/cdlg.h --- wine-20050111/dlls/commdlg/cdlg.h 2005-01-09 17:31:36.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg.h 2005-01-24 12:26:23.000000000 +0100 @@ -152,6 +152,8 @@ #define IDS_SAVE_AS 1204 #define IDS_OPEN_FILE 1205 +#define IDS_FAKEDOCTEXT 1300 + #include "windef.h" #include "winbase.h" #include "wingdi.h" diff -urN wine-20050111/dlls/commdlg/cdlg32.c wine-20050211/dlls/commdlg/cdlg32.c --- wine-20050111/dlls/commdlg/cdlg32.c 2003-10-16 21:31:11.000000000 +0200 +++ wine-20050211/dlls/commdlg/cdlg32.c 2005-01-28 15:02:52.000000000 +0100 @@ -63,7 +63,7 @@ * FALSE if sibling could not be loaded or instantiated twice, TRUE * otherwise. */ -static char * GPA_string = "Failed to get entry point %s for hinst = 0x%08x\n"; +static const char * GPA_string = "Failed to get entry point %s for hinst = 0x%08x\n"; #define GPA(dest, hinst, name) \ if(!(dest = (void*)GetProcAddress(hinst,name)))\ { \ diff -urN wine-20050111/dlls/commdlg/cdlg_De.rc wine-20050211/dlls/commdlg/cdlg_De.rc --- wine-20050111/dlls/commdlg/cdlg_De.rc 2005-01-04 21:35:24.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg_De.rc 2005-01-17 14:43:16.000000000 +0100 @@ -148,7 +148,7 @@ CHOOSE_FONT DIALOG DISCARDABLE 13, 54, 264, 147 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Font" +CAPTION "Schriftart" FONT 8, "MS Shell Dlg" { LTEXT "Schrift&art:",1088 ,6,3,40,9 @@ -315,7 +315,7 @@ PRINT32_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 32, 32, 288, 178 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CONTEXTHELP | DS_3DLOOK -CAPTION "Print Setup" +CAPTION "Druckereinrichtung" FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "OK",IDOK,180,156,48,14,WS_GROUP @@ -441,15 +441,25 @@ IDS_COLOR_GREEN "Grün" IDS_COLOR_OLIVE "Olivgrün" IDS_COLOR_NAVY "Dunkelblau" - IDS_COLOR_PURPLE "Violett" - IDS_COLOR_TEAL "Teal" + IDS_COLOR_PURPLE "Lila" + IDS_COLOR_TEAL "Blaugrün" IDS_COLOR_GRAY "Grau" IDS_COLOR_SILVER "Silber" IDS_COLOR_RED "Rot" IDS_COLOR_LIME "Hellgrün" IDS_COLOR_YELLOW "Gelb" IDS_COLOR_BLUE "Blau" - IDS_COLOR_FUCHSIA "Lila" - IDS_COLOR_AQUA "Aqua" + IDS_COLOR_FUCHSIA "Pink" + IDS_COLOR_AQUA "Aquamarin" IDS_COLOR_WHITE "Weiß" } + +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Wählen Sie eine Schriftgröße zwischen %d und %d Punkten aus." + IDS_SAVE_BUTTON "&Speichern" + IDS_SAVE_IN "Speichern &unter:" + IDS_SAVE "Speichern" + IDS_SAVE_AS "Speichern als" + IDS_OPEN_FILE "Öffne Datei" +} diff -urN wine-20050111/dlls/commdlg/cdlg_En.rc wine-20050211/dlls/commdlg/cdlg_En.rc --- wine-20050111/dlls/commdlg/cdlg_En.rc 2005-01-09 17:31:36.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg_En.rc 2005-01-24 12:26:23.000000000 +0100 @@ -470,6 +470,34 @@ 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-20050111/dlls/commdlg/cdlg_Es.rc wine-20050211/dlls/commdlg/cdlg_Es.rc --- wine-20050111/dlls/commdlg/cdlg_Es.rc 2005-01-09 17:33:26.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg_Es.rc 2005-01-24 12:31:23.000000000 +0100 @@ -47,7 +47,7 @@ SAVE_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "&Guardar como..." +CAPTION "Guardar como..." FONT 8, "MS Shell Dlg" { LTEXT "Nombre de &archivo:", 1090, 6, 6, 76, 9 @@ -85,7 +85,7 @@ LTEXT "&Hasta:", 1091, 120, 80, 30, 9 LTEXT "Calidad de impre&sión:", 1092, 6, 100, 76, 9 COMBOBOX cmb1, 80, 100, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP - CHECKBOX "Impri&mir en un archivo", chx1, 20, 100, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + CHECKBOX "Impri&mir en archivo", chx1, 20, 100, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP CHECKBOX "Condensado", chx2, 160, 100, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP } @@ -96,7 +96,7 @@ FONT 8, "MS Shell Dlg" { GROUPBOX "Impresora:", grp1, 6, 10, 180, 65, BS_GROUPBOX - RADIOBUTTON "Pre&determinada del sistema", rad1, 16, 20, 80, 12 + RADIOBUTTON "Impresora por &defecto", rad1, 16, 20, 80, 12 LTEXT "[ninguna]", 1088, 35, 35, 120, 9 RADIOBUTTON "Impresora &específica:", rad2, 16, 50, 80, 12 COMBOBOX cmb1, 35, 65, 149, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP @@ -187,7 +187,7 @@ CAPTION "Buscar" FONT 8, "MS Shell Dlg" { - LTEXT "Buscar:", -1, 4, 8, 42, 8 + LTEXT "Buscar:", -1, 4, 8, 42, 8 EDITTEXT edt1, 47, 7, 128, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP CHECKBOX "&Sólo palabra entera", chx1, 4, 26, 100, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP CHECKBOX "&Mayúsculas/minúsculas", chx2, 4, 42, 64, 12, BS_AUTOCHECKBOX | WS_TABSTOP @@ -202,7 +202,7 @@ REPLACEDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 230, 94 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "R&eemplazar" +CAPTION "Reemplazar" FONT 8, "MS Shell Dlg" { LTEXT "Buscar:", -1, 4, 9, 48, 8 @@ -230,7 +230,7 @@ PUSHBUTTON "&Ayuda", pshHelp, 50, 161, 48,14, WS_GROUP GROUPBOX "Impresora", grp4, 8, 4, 272,84, WS_GROUP - CONTROL "Imprimir a a&rchivo", chx1, "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,212,70,64,12 + CONTROL "Imprimir en a&rchivo", chx1, "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,212,70,64,12 PUSHBUTTON "&Propiedades", psh2, 212, 17, 60,14, WS_GROUP LTEXT "&Nombre:", stc6, 16, 20, 36,8 COMBOBOX cmb4, 52, 18, 152,152,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP @@ -296,7 +296,7 @@ PAGESETUPDLGORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 32, 32, 240, 240 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Página de configuración" +CAPTION "Configuración de página" FONT 8, "MS Shell Dlg" BEGIN CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 @@ -392,8 +392,8 @@ página.\n\ Por favor, introduzca un valor entre %d y %d." PD32_FROM_NOT_ABOVE_TO "La entrada 'desde' no puede exceder \ a la entrada 'hasta'." - PD32_MARGINS_OVERLAP "Los márgenes overlap o fall outside \ -los boundaries del papel.\nPor favor, reintroduzca los márgenes." + PD32_MARGINS_OVERLAP "Los márgenes se superponen o quedan \ +fuera de los límites del papel.\nPor favor, reintroduzca los márgenes." PD32_NR_OF_COPIES_EMPTY "El número del valor 'Número de \ copias' no puede estar vacío." PD32_TOO_LARGE_COPIES "Este número tan grande de copias no \ @@ -421,11 +421,11 @@ PD32_PRINTER_STATUS_PAPER_OUT "Sin papel; " PD32_PRINTER_STATUS_MANUAL_FEED "Ponga papel a mano; " PD32_PRINTER_STATUS_PAPER_PROBLEM "Problema con el papel; " - PD32_PRINTER_STATUS_OFFLINE "Impresora apagada; " + PD32_PRINTER_STATUS_OFFLINE "Impresora desconectada; " PD32_PRINTER_STATUS_IO_ACTIVE "E/S activa; " PD32_PRINTER_STATUS_BUSY "Ocupada; " PD32_PRINTER_STATUS_PRINTING "Imprimiendo; " - PD32_PRINTER_STATUS_OUTPUT_BIN_FULL "La bandeja de salida está llena; " + PD32_PRINTER_STATUS_OUTPUT_BIN_FULL "Bandeja de salida llena; " PD32_PRINTER_STATUS_NOT_AVAILABLE "No disponible; " PD32_PRINTER_STATUS_WAITING "Esperando; " PD32_PRINTER_STATUS_PROCESSING "Procesando; " @@ -434,10 +434,9 @@ PD32_PRINTER_STATUS_TONER_LOW "Tóner bajo; " PD32_PRINTER_STATUS_NO_TONER "Sin tóner; " PD32_PRINTER_STATUS_PAGE_PUNT "Page punt; " - PD32_PRINTER_STATUS_USER_INTERVENTION "Interrumpido por el usuario; " + PD32_PRINTER_STATUS_USER_INTERVENTION "Interrumpida por el usuario; " PD32_PRINTER_STATUS_OUT_OF_MEMORY "Sin memoria; " - PD32_PRINTER_STATUS_DOOR_OPEN "La puerta de la impresora está \ -abierta; " + PD32_PRINTER_STATUS_DOOR_OPEN "Puerta de la impresora abierta; " PD32_PRINTER_STATUS_SERVER_UNKNOWN "Servidor de impresión desconocido; " PD32_PRINTER_STATUS_POWER_SAVE "Modo de ahorro de energía; " } @@ -445,9 +444,9 @@ STRINGTABLE DISCARDABLE /* Color names */ { IDS_COLOR_BLACK "Negro" - IDS_COLOR_MAROON "Marrón" + IDS_COLOR_MAROON "Granate" IDS_COLOR_GREEN "Verde" - IDS_COLOR_OLIVE "Oliva" + IDS_COLOR_OLIVE "Verde oliva" IDS_COLOR_NAVY "Azul marino" IDS_COLOR_PURPLE "Morado" IDS_COLOR_TEAL "Turquesa" @@ -464,5 +463,10 @@ STRINGTABLE DISCARDABLE { - IDS_FONT_SIZE "Elija un tamaño de fuente entre %d and %d puntos." + IDS_FONT_SIZE "Elija un tamaño de fuente entre %d y %d puntos." + IDS_SAVE_BUTTON "&Guardar" + IDS_SAVE_IN "Guardar &en:" + IDS_SAVE "Guardar" + IDS_SAVE_AS "Guardar como" + IDS_OPEN_FILE "Abrir archivo" } diff -urN wine-20050111/dlls/commdlg/cdlg_Fr.rc wine-20050211/dlls/commdlg/cdlg_Fr.rc --- wine-20050111/dlls/commdlg/cdlg_Fr.rc 2005-01-04 21:35:24.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg_Fr.rc 2005-01-17 16:34:50.000000000 +0100 @@ -3,6 +3,7 @@ * French language support * * Copyright 1995 Alexandre Julliard + * 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 @@ -462,3 +463,13 @@ IDS_COLOR_AQUA "Aqua" IDS_COLOR_WHITE "Blanc" } + +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Sélectionnez une taille de police entre %d et %d points." + IDS_SAVE_BUTTON "&Sauver" + IDS_SAVE_IN "Sauver &dans:" + IDS_SAVE "Enregistrer" + IDS_SAVE_AS "Enregistrer sous" + IDS_OPEN_FILE "Ouvrir Fichier" +} diff -urN wine-20050111/dlls/commdlg/cdlg_Ru.rc wine-20050211/dlls/commdlg/cdlg_Ru.rc --- wine-20050111/dlls/commdlg/cdlg_Ru.rc 2004-12-22 15:59:50.000000000 +0100 +++ wine-20050211/dlls/commdlg/cdlg_Ru.rc 2005-01-20 20:56:37.000000000 +0100 @@ -235,9 +235,9 @@ LTEXT "&Èìÿ:", stc6, 16, 20, 36,8 COMBOBOX cmb4, 52, 18, 152,152,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP LTEXT "Ñòàòóñ:", stc8, 16, 36, 36,10, SS_NOPREFIX - LTEXT "Ýìóëèðîâàí", stc12, 60, 36, 224,10, SS_NOPREFIX | SS_LEFTNOWORDWRAP + LTEXT "Ýìóëèðîâàí", stc12, 52, 36, 224,10, SS_NOPREFIX | SS_LEFTNOWORDWRAP LTEXT "Òèï:", stc7, 16, 48, 36,10, SS_NOPREFIX - LTEXT "Ýìóëèðîâàí", stc11, 60, 48, 224,10, SS_NOPREFIX | SS_LEFTNOWORDWRAP + LTEXT "Ýìóëèðîâàí", stc11, 52, 48, 224,10, SS_NOPREFIX | SS_LEFTNOWORDWRAP LTEXT "Ìåñòî:", stc10, 16, 60, 36,10, SS_NOPREFIX LTEXT "Ýìóëèðîâàíî", stc14, 60, 60, 224,10, SS_NOPREFIX | SS_LEFTNOWORDWRAP LTEXT "Ïðèìå÷àíèå:", stc9, 16, 72, 36,10, SS_NOPREFIX diff -urN wine-20050111/dlls/commdlg/filedlg.c wine-20050211/dlls/commdlg/filedlg.c --- wine-20050111/dlls/commdlg/filedlg.c 2005-01-10 14:22:35.000000000 +0100 +++ wine-20050211/dlls/commdlg/filedlg.c 2005-02-10 18:10:01.000000000 +0100 @@ -3377,7 +3377,7 @@ */ static BOOL FD32_GetTemplate(PFD31_DATA lfs) { - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632; HANDLE hDlgTmpl; @@ -3445,9 +3445,9 @@ if (NULL == lfs->private1632) return FALSE; if (IsUnicode) { - lfs->ofnW = *((LPOPENFILENAMEW) lParam); - if (lfs->ofnW.Flags & OFN_ENABLEHOOK) - if (lfs->ofnW.lpfnHook) + lfs->ofnW = (LPOPENFILENAMEW) lParam; + if (lfs->ofnW->Flags & OFN_ENABLEHOOK) + if (lfs->ofnW->lpfnHook) lfs->hook = TRUE; } else @@ -3456,7 +3456,8 @@ if (priv->ofnA->Flags & OFN_ENABLEHOOK) if (priv->ofnA->lpfnHook) lfs->hook = TRUE; - FD31_MapOfnStructA(priv->ofnA, &lfs->ofnW, lfs->open); + lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW)); + FD31_MapOfnStructA(priv->ofnA, lfs->ofnW, lfs->open); } if (! FD32_GetTemplate(lfs)) return FALSE; @@ -3472,18 +3473,25 @@ BOOL CALLBACK FD32_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam, LPARAM lParam) { + BOOL ret; PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632; if (priv->ofnA) { - return (BOOL) CallWindowProcA( - (WNDPROC)priv->ofnA->lpfnHook, lfs->hwnd, - wMsg, wParam, lParam); + TRACE("Call hookA %p (%p, %04x, %08x, %08lx)\n", + priv->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); + ret = priv->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); + TRACE("ret hookA %p (%p, %04x, %08x, %08lx)\n", + priv->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); + return ret; } - return (BOOL) CallWindowProcW( - (WNDPROC)lfs->ofnW.lpfnHook, lfs->hwnd, - wMsg, wParam, lParam); + TRACE("Call hookW %p (%p, %04x, %08x, %08lx)\n", + lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); + ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); + TRACE("Ret hookW %p (%p, %04x, %08x, %08lx)\n", + lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); + return ret; } /*********************************************************************** @@ -3493,7 +3501,7 @@ static void CALLBACK FD32_UpdateResult(PFD31_DATA lfs) { PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; if (priv->ofnA) { @@ -3513,7 +3521,7 @@ static void CALLBACK FD32_UpdateFileTitle(PFD31_DATA lfs) { PFD32_PRIVATE priv = (PFD32_PRIVATE) lfs->private1632; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; if (priv->ofnA) { @@ -3544,7 +3552,10 @@ /* if ofnW has been allocated, have to free everything in it */ if (NULL != priv && NULL != priv->ofnA) - FD31_FreeOfnW(&lfs->ofnW); + { + FD31_FreeOfnW(lfs->ofnW); + HeapFree(GetProcessHeap(), 0, lfs->ofnW); + } } static void FD32_SetupCallbacks(PFD31_CALLBACKS callbacks) @@ -3667,7 +3678,7 @@ if (!lpofn || !FD31_Init()) return FALSE; FD32_SetupCallbacks(&callbacks); - lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, &callbacks, (DWORD) FALSE); + lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, &callbacks, (DWORD) TRUE); if (lfs) { hInst = (HINSTANCE)GetWindowLongPtrW( lpofn->hwndOwner, GWLP_HINSTANCE ); @@ -3676,7 +3687,8 @@ FD31_DestroyPrivate(lfs); } - TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile)); + TRACE("file %s, file offset %d, ext offset %d\n", + debugstr_w(lpofn->lpstrFile), lpofn->nFileOffset, lpofn->nFileExtension); return bRet; } @@ -3697,6 +3709,10 @@ { BOOL win16look = FALSE; + /* OFN_FILEMUSTEXIST implies OFN_PATHMUSTEXIST */ + if (ofn->Flags & OFN_FILEMUSTEXIST) + ofn->Flags |= OFN_PATHMUSTEXIST; + if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE)) win16look = (ofn->Flags & OFN_EXPLORER) ? FALSE : TRUE; diff -urN wine-20050111/dlls/commdlg/filedlg16.c wine-20050211/dlls/commdlg/filedlg16.c --- wine-20050111/dlls/commdlg/filedlg16.c 2004-10-08 23:02:22.000000000 +0200 +++ wine-20050211/dlls/commdlg/filedlg16.c 2005-02-10 18:10:01.000000000 +0100 @@ -170,7 +170,8 @@ if (priv->ofn16->lpfnHook) lfs->hook = TRUE; - FD16_MapOfnStruct16(priv->ofn16, &lfs->ofnW, lfs->open); + lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW)); + FD16_MapOfnStruct16(priv->ofn16, lfs->ofnW, lfs->open); if (! FD16_GetTemplate(lfs)) return FALSE; @@ -204,7 +205,7 @@ static void CALLBACK FD16_UpdateResult(PFD31_DATA lfs) { PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; if (priv->ofn16) { /* we have to convert to short (8.3) path */ @@ -240,7 +241,7 @@ static void CALLBACK FD16_UpdateFileTitle(PFD31_DATA lfs) { PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; if (priv->ofn16) { @@ -279,7 +280,8 @@ GlobalUnlock16(priv->hGlobal16); GlobalFree16(priv->hGlobal16); } - FD31_FreeOfnW(&lfs->ofnW); + FD31_FreeOfnW(lfs->ofnW); + HeapFree(GetProcessHeap(), 0, lfs->ofnW); } } diff -urN wine-20050111/dlls/commdlg/filedlg31.c wine-20050211/dlls/commdlg/filedlg31.c --- wine-20050111/dlls/commdlg/filedlg31.c 2005-01-09 17:31:36.000000000 +0100 +++ wine-20050211/dlls/commdlg/filedlg31.c 2005-02-03 20:39:26.000000000 +0100 @@ -38,6 +38,7 @@ #include "cderr.h" #include "winreg.h" #include "winternl.h" +#include "shlwapi.h" WINE_DEFAULT_DEBUG_CHANNEL(commdlg); @@ -305,9 +306,9 @@ void FD31_UpdateResult(PFD31_DATA lfs, WCHAR *tmpstr) { int lenstr2; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; WCHAR tmpstr2[BUFFILE]; - WCHAR *bs; + WCHAR *p; TRACE("%s\n", debugstr_w(tmpstr)); if(ofnW->Flags & OFN_NOVALIDATE) @@ -320,17 +321,18 @@ lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2); if (ofnW->lpstrFile) lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile); - if((bs = strrchrW(tmpstr2, '\\')) != NULL) - ofnW->nFileOffset = bs - tmpstr2 +1; - else - ofnW->nFileOffset = 0; - ofnW->nFileExtension = 0; - while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0') - ofnW->nFileExtension++; - if (tmpstr2[ofnW->nFileExtension] == '\0') - ofnW->nFileExtension = 0; - else - ofnW->nFileExtension++; + + /* set filename offset */ + p = PathFindFileNameW(ofnW->lpstrFile); + ofnW->nFileOffset = (p - ofnW->lpstrFile); + + /* set extension offset */ + p = PathFindExtensionW(ofnW->lpstrFile); + ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0; + + TRACE("file %s, file offset %d, ext offset %d\n", + debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension); + /* update the real client structures if any */ lfs->callbacks->UpdateResult(lfs); } @@ -342,7 +344,7 @@ void FD31_UpdateFileTitle(PFD31_DATA lfs) { LONG lRet; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; if (ofnW->lpstrFileTitle != NULL) { lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0); @@ -447,14 +449,14 @@ else { strcpyW(tmpstr2, path); - if(!(lfs->ofnW.Flags & OFN_NOVALIDATE)) + if(!(lfs->ofnW->Flags & OFN_NOVALIDATE)) *path = 0; } TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2)); SetDlgItemTextW( hWnd, edt1, tmpstr2 ); FD31_ScanDir(hWnd, path); - return (lfs->ofnW.Flags & OFN_NOVALIDATE) ? TRUE : FALSE; + return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE; } /* no wildcards, we might have a directory or a filename */ @@ -501,7 +503,7 @@ LONG lRet; HWND hWnd = lfs->hwnd; OPENFILENAMEW ofnsav; - LPOPENFILENAMEW ofnW = &lfs->ofnW; + LPOPENFILENAMEW ofnW = lfs->ofnW; WCHAR filename[BUFFILE]; ofnsav = *ofnW; /* for later restoring */ @@ -610,9 +612,7 @@ FD31_StripEditControl(hWnd); if (notification == LBN_DBLCLK) { - if (FD31_Validate( lfs, NULL, control, 0, FALSE )) - EndDialog(hWnd, TRUE); - return TRUE; + return SendMessageW(hWnd, WM_COMMAND, IDOK, 0); } else if (notification == LBN_SELCHANGE) return FD31_FileListSelect( lfs ); @@ -700,7 +700,7 @@ * FD31_MapOfnStructA [internal] * map a 32 bits Ansi structure to an Unicode one */ -void FD31_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open) +void FD31_MapOfnStructA(const LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open) { UNICODE_STRING usBuffer; @@ -828,7 +828,7 @@ if (!lfs) return FALSE; SetPropA(hWnd, FD31_OFN_PROP, (HANDLE)lfs); lfs->hwnd = hWnd; - ofn = &lfs->ofnW; + ofn = lfs->ofnW; TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir)); diff -urN wine-20050111/dlls/commdlg/filedlg31.h wine-20050211/dlls/commdlg/filedlg31.h --- wine-20050111/dlls/commdlg/filedlg31.h 2004-07-14 02:39:10.000000000 +0200 +++ wine-20050211/dlls/commdlg/filedlg31.h 2005-02-03 20:39:26.000000000 +0100 @@ -44,7 +44,8 @@ LPARAM lParam; /* save original lparam */ LPCVOID template; /* template for 32 bits resource */ BOOL open; /* TRUE if open dialog, FALSE if save dialog */ - OPENFILENAMEW ofnW; /* copy of original structure or work struct */ + LPOPENFILENAMEW ofnW; /* pointer either to the original structure or + a W copy for A/16 API */ LPVOID private1632; /* 16/32 bit caller private data */ PFD31_CALLBACKS callbacks; /* callbacks to handle 16/32 bit differences */ } FD31_DATA; diff -urN wine-20050111/dlls/commdlg/printdlg.c wine-20050211/dlls/commdlg/printdlg.c --- wine-20050111/dlls/commdlg/printdlg.c 2004-12-23 19:24:50.000000000 +0100 +++ wine-20050211/dlls/commdlg/printdlg.c 2005-01-24 12:26:23.000000000 +0100 @@ -71,6 +71,11 @@ {-1, NULL} }; +/* address of wndproc for subclassed Static control */ +static WNDPROC lpfnStaticWndProc; +/* the text of the fake document to render for the Page Setup dialog */ +static WCHAR wszFakeDocumentText[1024]; + /*********************************************************************** * PRINTDLG_OpenDefaultPrinter * @@ -2551,6 +2556,8 @@ PRINTDLG_PS_WMCommandA( HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda ) { + TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n", + LOWORD(lParam),wParam,lParam); switch (LOWORD(wParam)) { case IDOK: if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda)) @@ -2570,9 +2577,6 @@ return TRUE; } } - FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n", - LOWORD(lParam),wParam,lParam - ); return FALSE; } @@ -2580,6 +2584,8 @@ PRINTDLG_PS_WMCommandW( HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda ) { + TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n", + LOWORD(lParam),wParam,lParam); switch (LOWORD(wParam)) { case IDOK: if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda)) @@ -2599,13 +2605,114 @@ return TRUE; } } - FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n", - LOWORD(lParam),wParam,lParam - ); return FALSE; } +static LRESULT CALLBACK +PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_PAINT) + { + PAINTSTRUCT ps; + RECT rcClient; + HPEN hpen, holdpen; + HDC hdc; + HFONT hfont, holdfont; + LOGFONTW lf; + HBRUSH hbrush, holdbrush; + INT oldbkmode; + + hdc = BeginPaint(hWnd, &ps); + + GetClientRect(hWnd, &rcClient); + + /* fill background */ + hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT); + FillRect(hdc, &rcClient, hbrush); + holdbrush = SelectObject(hdc, hbrush); + + hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW)); + holdpen = SelectObject(hdc, hpen); + + /* paint left edge */ + MoveToEx(hdc, rcClient.left, rcClient.top, NULL); + LineTo(hdc, rcClient.left, rcClient.bottom-1); + + /* paint top edge */ + MoveToEx(hdc, rcClient.left, rcClient.top, NULL); + LineTo(hdc, rcClient.right, rcClient.top); + + hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW)); + DeleteObject(SelectObject(hdc, hpen)); + + /* paint right edge */ + MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL); + LineTo(hdc, rcClient.right-1, rcClient.bottom); + + /* paint bottom edge */ + MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL); + LineTo(hdc, rcClient.right, rcClient.bottom-1); + + hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW)); + DeleteObject(SelectObject(hdc, hpen)); + + /* draw dashed rectangle showing margins */ + + /* FIXME: use real margin values */ + rcClient.left += 5; + rcClient.top += 5; + rcClient.right -= 5; + rcClient.bottom -= 5; + + /* if the space is too small then we make sure to not draw anything */ + rcClient.left = min(rcClient.left,rcClient.right); + rcClient.top = min(rcClient.top,rcClient.bottom); + + Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + + DeleteObject(SelectObject(hdc, holdpen)); + + /* draw the fake document */ + + /* give text a bit of a space from the frame */ + rcClient.left += 2; + rcClient.top += 2; + rcClient.right -= 2; + rcClient.bottom -= 2; + + /* if the space is too small then we make sure to not draw anything */ + rcClient.left = min(rcClient.left,rcClient.right); + rcClient.top = min(rcClient.top,rcClient.bottom); + + /* select a nice scalable font, because we want the text really small */ + SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); + lf.lfHeight = 6; /* value chosen based on visual effect */ + hfont = CreateFontIndirectW(&lf); + holdfont = SelectObject(hdc, hfont); + + /* if text not loaded, then do so now */ + if (wszFakeDocumentText[0] == '\0') + LoadStringW(COMDLG32_hInstance, + IDS_FAKEDOCTEXT, + wszFakeDocumentText, + sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0])); + + oldbkmode = SetBkMode(hdc, TRANSPARENT); + DrawTextW(hdc, wszFakeDocumentText, -1, &rcClient, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK); + SetBkMode(hdc, oldbkmode); + + DeleteObject(SelectObject(hdc, holdfont)); + + SelectObject(hdc, holdbrush); + + EndPaint(hWnd, &ps); + return 0; + } + else + return CallWindowProcW(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam); +} + static INT_PTR CALLBACK PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -2613,6 +2720,10 @@ INT_PTR res = FALSE; if (uMsg==WM_INITDIALOG) { + lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW( + GetDlgItem(hDlg, rct1), + GWLP_WNDPROC, + (ULONG_PTR)PagePaintProc); res = TRUE; pda = (PageSetupDataA*)lParam; SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",pda); diff -urN wine-20050111/dlls/cryptdll/.cvsignore wine-20050211/dlls/cryptdll/.cvsignore --- wine-20050111/dlls/cryptdll/.cvsignore 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/cryptdll/.cvsignore 2005-01-24 20:07:16.000000000 +0100 @@ -0,0 +1,3 @@ +Makefile +cryptdll.dll.dbg.c +cryptdll.spec.def diff -urN wine-20050111/dlls/cryptdll/Makefile.in wine-20050211/dlls/cryptdll/Makefile.in --- wine-20050111/dlls/cryptdll/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/cryptdll/Makefile.in 2005-01-24 20:07:16.000000000 +0100 @@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = cryptdll.dll +IMPORTS = kernel32 + +C_SRCS = \ + cryptdll.c + +@MAKE_DLL_RULES@ + +### Dependencies: diff -urN wine-20050111/dlls/cryptdll/cryptdll.c wine-20050211/dlls/cryptdll/cryptdll.c --- wine-20050111/dlls/cryptdll/cryptdll.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/cryptdll/cryptdll.c 2005-01-24 20:07:16.000000000 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright 2005 Ulrich Czekalla (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 "config.h" +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(cryptdll); + +HMODULE CRYPTDLL_hModule = 0; + +BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved); + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + { + DisableThreadLibraryCalls(hinstDLL); + CRYPTDLL_hModule = hinstDLL; + break; + } + case DLL_PROCESS_DETACH: + { + break; + } + } + + return TRUE; +} diff -urN wine-20050111/dlls/cryptdll/cryptdll.spec wine-20050211/dlls/cryptdll/cryptdll.spec --- wine-20050111/dlls/cryptdll/cryptdll.spec 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/cryptdll/cryptdll.spec 2005-01-24 20:07:16.000000000 +0100 @@ -0,0 +1,14 @@ +@ stub CDBuildIntegrityVect +@ stub CDBuildVect +@ stub CDFindCommonCSystem +@ stub CDFindCommonCSystemWithKey +@ stub CDGenerateRandomBits +@ stub CDLocateCSystem +@ stub CDLocateCheckSum +@ stub CDLocateRng +@ stub CDRegisterCSystem +@ stub CDRegisterCheckSum +@ stub CDRegisterRng +@ stub MD5Final +@ stub MD5Init +@ stub MD5Update diff -urN wine-20050111/dlls/d3d8/basetexture.c wine-20050211/dlls/d3d8/basetexture.c --- wine-20050111/dlls/d3d8/basetexture.c 2004-09-08 03:50:38.000000000 +0200 +++ wine-20050211/dlls/d3d8/basetexture.c 2005-01-24 13:43:26.000000000 +0100 @@ -51,14 +51,19 @@ ULONG WINAPI IDirect3DBaseTexture8Impl_AddRef(LPDIRECT3DBASETEXTURE8 iface) { IDirect3DBaseTexture8Impl *This = (IDirect3DBaseTexture8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DBaseTexture8Impl_Release(LPDIRECT3DBASETEXTURE8 iface) { IDirect3DBaseTexture8Impl *This = (IDirect3DBaseTexture8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) HeapFree(GetProcessHeap(), 0, This); return ref; diff -urN wine-20050111/dlls/d3d8/cubetexture.c wine-20050211/dlls/d3d8/cubetexture.c --- wine-20050111/dlls/d3d8/cubetexture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/d3d8/cubetexture.c 2005-01-24 13:43:26.000000000 +0100 @@ -52,16 +52,19 @@ ULONG WINAPI IDirect3DCubeTexture8Impl_AddRef(LPDIRECT3DCUBETEXTURE8 iface) { IDirect3DCubeTexture8Impl *This = (IDirect3DCubeTexture8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 iface) { IDirect3DCubeTexture8Impl *This = (IDirect3DCubeTexture8Impl *)iface; - ULONG ref = --This->ref; + ULONG ref = InterlockedDecrement(&This->ref); unsigned int i, j; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); if (ref == 0) { for (i = 0; i < This->levels; i++) { for (j = 0; j < 6; j++) { diff -urN wine-20050111/dlls/d3d8/device.c wine-20050211/dlls/d3d8/device.c --- wine-20050111/dlls/d3d8/device.c 2004-12-23 19:33:45.000000000 +0100 +++ wine-20050211/dlls/d3d8/device.c 2005-02-08 13:10:57.000000000 +0100 @@ -297,14 +297,19 @@ ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) { IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) { IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IDirect3DDevice8Impl_CleanRender(iface); IDirect3D8_Release((LPDIRECT3D8) This->direct3d8); @@ -4339,7 +4344,7 @@ TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]); *pStream = This->StateBlock->stream_source[StreamNumber]; *pStride = This->StateBlock->stream_stride[StreamNumber]; - IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream); + if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream); return D3D_OK; } diff -urN wine-20050111/dlls/d3d8/directx.c wine-20050211/dlls/d3d8/directx.c --- wine-20050111/dlls/d3d8/directx.c 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d8/directx.c 2005-01-31 17:34:07.000000000 +0100 @@ -90,14 +90,19 @@ ULONG WINAPI IDirect3D8Impl_AddRef(LPDIRECT3D8 iface) { IDirect3D8Impl *This = (IDirect3D8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) { IDirect3D8Impl *This = (IDirect3D8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3D_Release(This->WineD3D); HeapFree(GetProcessHeap(), 0, This); @@ -633,7 +638,7 @@ whichHWND = hFocusWindow; } object->win_handle = whichHWND; - object->win = (Window)GetPropA( whichHWND, "__wine_x11_client_window" ); + object->win = (Window)GetPropA( whichHWND, "__wine_x11_whole_window" ); hDc = GetDC(whichHWND); object->display = get_display(hDc); diff -urN wine-20050111/dlls/d3d8/indexbuffer.c wine-20050211/dlls/d3d8/indexbuffer.c --- wine-20050111/dlls/d3d8/indexbuffer.c 2004-09-08 03:50:38.000000000 +0200 +++ wine-20050211/dlls/d3d8/indexbuffer.c 2005-01-24 13:43:25.000000000 +0100 @@ -51,14 +51,19 @@ ULONG WINAPI IDirect3DIndexBuffer8Impl_AddRef(LPDIRECT3DINDEXBUFFER8 iface) { IDirect3DIndexBuffer8Impl *This = (IDirect3DIndexBuffer8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DIndexBuffer8Impl_Release(LPDIRECT3DINDEXBUFFER8 iface) { IDirect3DIndexBuffer8Impl *This = (IDirect3DIndexBuffer8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->allocatedMemory); HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/d3d8/resource.c wine-20050211/dlls/d3d8/resource.c --- wine-20050111/dlls/d3d8/resource.c 2004-09-08 03:50:38.000000000 +0200 +++ wine-20050211/dlls/d3d8/resource.c 2005-01-24 13:43:25.000000000 +0100 @@ -50,14 +50,19 @@ ULONG WINAPI IDirect3DResource8Impl_AddRef(LPDIRECT3DRESOURCE8 iface) { IDirect3DResource8Impl *This = (IDirect3DResource8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DResource8Impl_Release(LPDIRECT3DRESOURCE8 iface) { IDirect3DResource8Impl *This = (IDirect3DResource8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) HeapFree(GetProcessHeap(), 0, This); return ref; diff -urN wine-20050111/dlls/d3d8/shader.c wine-20050211/dlls/d3d8/shader.c --- wine-20050111/dlls/d3d8/shader.c 2004-12-06 17:11:38.000000000 +0100 +++ wine-20050211/dlls/d3d8/shader.c 2005-01-24 12:29:44.000000000 +0100 @@ -1627,7 +1627,7 @@ strcat(pgm, "\n"); } -char* shift_tab[] = { +static const char* shift_tab[] = { "dummy", /* 0 (none) */ "coefmul.x", /* 1 (x2) */ "coefmul.y", /* 2 (x4) */ diff -urN wine-20050111/dlls/d3d8/surface.c wine-20050211/dlls/d3d8/surface.c --- wine-20050111/dlls/d3d8/surface.c 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d8/surface.c 2005-01-24 13:43:25.000000000 +0100 @@ -57,14 +57,19 @@ ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) { IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) { IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->allocatedMemory); HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/d3d8/swapchain.c wine-20050211/dlls/d3d8/swapchain.c --- wine-20050111/dlls/d3d8/swapchain.c 2004-09-08 03:50:38.000000000 +0200 +++ wine-20050211/dlls/d3d8/swapchain.c 2005-01-24 13:43:25.000000000 +0100 @@ -50,14 +50,19 @@ ULONG WINAPI IDirect3DSwapChain8Impl_AddRef(LPDIRECT3DSWAPCHAIN8 iface) { IDirect3DSwapChain8Impl *This = (IDirect3DSwapChain8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DSwapChain8Impl_Release(LPDIRECT3DSWAPCHAIN8 iface) { IDirect3DSwapChain8Impl *This = (IDirect3DSwapChain8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } diff -urN wine-20050111/dlls/d3d8/texture.c wine-20050211/dlls/d3d8/texture.c --- wine-20050111/dlls/d3d8/texture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/d3d8/texture.c 2005-01-24 13:43:25.000000000 +0100 @@ -52,16 +52,20 @@ ULONG WINAPI IDirect3DTexture8Impl_AddRef(LPDIRECT3DTEXTURE8 iface) { IDirect3DTexture8Impl *This = (IDirect3DTexture8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) { IDirect3DTexture8Impl *This = (IDirect3DTexture8Impl *)iface; - ULONG ref = --This->ref; + ULONG ref = InterlockedDecrement(&This->ref); unsigned int i; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { for (i = 0; i < This->levels; i++) { if (This->surfaces[i] != NULL) { diff -urN wine-20050111/dlls/d3d8/vertexbuffer.c wine-20050211/dlls/d3d8/vertexbuffer.c --- wine-20050111/dlls/d3d8/vertexbuffer.c 2004-12-23 19:33:45.000000000 +0100 +++ wine-20050211/dlls/d3d8/vertexbuffer.c 2005-01-24 13:43:25.000000000 +0100 @@ -51,14 +51,19 @@ ULONG WINAPI IDirect3DVertexBuffer8Impl_AddRef(LPDIRECT3DVERTEXBUFFER8 iface) { IDirect3DVertexBuffer8Impl *This = (IDirect3DVertexBuffer8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVertexBuffer8Impl_Release(LPDIRECT3DVERTEXBUFFER8 iface) { IDirect3DVertexBuffer8Impl *This = (IDirect3DVertexBuffer8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->allocatedMemory); HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/d3d8/volume.c wine-20050211/dlls/d3d8/volume.c --- wine-20050111/dlls/d3d8/volume.c 2004-10-07 05:06:51.000000000 +0200 +++ wine-20050211/dlls/d3d8/volume.c 2005-01-24 13:43:25.000000000 +0100 @@ -54,14 +54,19 @@ ULONG WINAPI IDirect3DVolume8Impl_AddRef(LPDIRECT3DVOLUME8 iface) { IDirect3DVolume8Impl *This = (IDirect3DVolume8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVolume8Impl_Release(LPDIRECT3DVOLUME8 iface) { IDirect3DVolume8Impl *This = (IDirect3DVolume8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->allocatedMemory); HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/d3d8/volumetexture.c wine-20050211/dlls/d3d8/volumetexture.c --- wine-20050111/dlls/d3d8/volumetexture.c 2004-09-08 03:50:38.000000000 +0200 +++ wine-20050211/dlls/d3d8/volumetexture.c 2005-01-24 13:43:25.000000000 +0100 @@ -53,16 +53,20 @@ ULONG WINAPI IDirect3DVolumeTexture8Impl_AddRef(LPDIRECT3DVOLUMETEXTURE8 iface) { IDirect3DVolumeTexture8Impl *This = (IDirect3DVolumeTexture8Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVolumeTexture8Impl_Release(LPDIRECT3DVOLUMETEXTURE8 iface) { IDirect3DVolumeTexture8Impl *This = (IDirect3DVolumeTexture8Impl *)iface; - ULONG ref = --This->ref; + ULONG ref = InterlockedDecrement(&This->ref); UINT i; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { for (i = 0; i < This->levels; i++) { if (This->volumes[i] != NULL) { diff -urN wine-20050111/dlls/d3d9/basetexture.c wine-20050211/dlls/d3d9/basetexture.c --- wine-20050111/dlls/d3d9/basetexture.c 2004-12-07 15:29:12.000000000 +0100 +++ wine-20050211/dlls/d3d9/basetexture.c 2005-01-24 13:44:01.000000000 +0100 @@ -42,14 +42,19 @@ ULONG WINAPI IDirect3DBaseTexture9Impl_AddRef(LPDIRECT3DBASETEXTURE9 iface) { IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DBaseTexture9Impl_Release(LPDIRECT3DBASETEXTURE9 iface) { IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3DBaseTexture_Release(This->wineD3DBaseTexture); HeapFree(GetProcessHeap(), 0, This); @@ -102,41 +107,34 @@ /* IDirect3DBaseTexture9 Interface follow: */ DWORD WINAPI IDirect3DBaseTexture9Impl_SetLOD(LPDIRECT3DBASETEXTURE9 iface, DWORD LODNew) { IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0; + return IWineD3DBaseTexture_SetLOD(This->wineD3DBaseTexture, LODNew); } DWORD WINAPI IDirect3DBaseTexture9Impl_GetLOD(LPDIRECT3DBASETEXTURE9 iface) { IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0; + return IWineD3DBaseTexture_GetLOD(This->wineD3DBaseTexture); } DWORD WINAPI IDirect3DBaseTexture9Impl_GetLevelCount(LPDIRECT3DBASETEXTURE9 iface) { IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return 0; + return IWineD3DBaseTexture_GetLevelCount(This->wineD3DBaseTexture); } HRESULT WINAPI IDirect3DBaseTexture9Impl_SetAutoGenFilterType(LPDIRECT3DBASETEXTURE9 iface, D3DTEXTUREFILTERTYPE FilterType) { - IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; + return IWineD3DBaseTexture_SetAutoGenFilterType(This->wineD3DBaseTexture, FilterType); } D3DTEXTUREFILTERTYPE WINAPI IDirect3DBaseTexture9Impl_GetAutoGenFilterType(LPDIRECT3DBASETEXTURE9 iface) { - IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3DTEXF_NONE; + IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; + return IWineD3DBaseTexture_GetAutoGenFilterType(This->wineD3DBaseTexture); } void WINAPI IDirect3DBaseTexture9Impl_GenerateMipSubLevels(LPDIRECT3DBASETEXTURE9 iface) { - IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + IDirect3DBaseTexture9Impl *This = (IDirect3DBaseTexture9Impl *)iface; + return IWineD3DBaseTexture_GenerateMipSubLevels(This->wineD3DBaseTexture); } - IDirect3DBaseTexture9Vtbl Direct3DBaseTexture9_Vtbl = { IDirect3DBaseTexture9Impl_QueryInterface, diff -urN wine-20050111/dlls/d3d9/cubetexture.c wine-20050211/dlls/d3d9/cubetexture.c --- wine-20050111/dlls/d3d9/cubetexture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/d3d9/cubetexture.c 2005-01-24 13:44:01.000000000 +0100 @@ -1,7 +1,7 @@ /* * IDirect3DCubeTexture9 implementation * - * Copyright 2002-2003 Jason Edmeades + * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * * This library is free software; you can redistribute it and/or @@ -43,25 +43,21 @@ ULONG WINAPI IDirect3DCubeTexture9Impl_AddRef(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - ULONG ref = --This->ref; - unsigned int i, j; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); if (ref == 0) { - for (i = 0; i < This->levels; i++) { - for (j = 0; j < 6; j++) { - if (This->surfaces[j][i] != NULL) { - TRACE("(%p) : Releasing surface %p\n", This, This->surfaces[j][i]); - IDirect3DSurface9Impl_Release((LPDIRECT3DSURFACE9) This->surfaces[j][i]); - } - } - } + IWineD3DCubeTexture_Release(This->wineD3DCubeTexture); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -75,47 +71,43 @@ HRESULT WINAPI IDirect3DCubeTexture9Impl_SetPrivateData(LPDIRECT3DCUBETEXTURE9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DCubeTexture_SetPrivateData(This->wineD3DCubeTexture,refguid,pData,SizeOfData,Flags); } HRESULT WINAPI IDirect3DCubeTexture9Impl_GetPrivateData(LPDIRECT3DCUBETEXTURE9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DCubeTexture_GetPrivateData(This->wineD3DCubeTexture,refguid,pData,pSizeOfData); } HRESULT WINAPI IDirect3DCubeTexture9Impl_FreePrivateData(LPDIRECT3DCUBETEXTURE9 iface, REFGUID refguid) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DCubeTexture_FreePrivateData(This->wineD3DCubeTexture,refguid); } DWORD WINAPI IDirect3DCubeTexture9Impl_SetPriority(LPDIRECT3DCUBETEXTURE9 iface, DWORD PriorityNew) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DResource9Impl_SetPriority((LPDIRECT3DRESOURCE9) This, PriorityNew); + return IWineD3DCubeTexture_SetPriority(This->wineD3DCubeTexture, PriorityNew); } DWORD WINAPI IDirect3DCubeTexture9Impl_GetPriority(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DResource9Impl_GetPriority((LPDIRECT3DRESOURCE9) This); + return IWineD3DCubeTexture_GetPriority(This->wineD3DCubeTexture); } void WINAPI IDirect3DCubeTexture9Impl_PreLoad(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + return IWineD3DCubeTexture_PreLoad(This->wineD3DCubeTexture); } D3DRESOURCETYPE WINAPI IDirect3DCubeTexture9Impl_GetType(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DResource9Impl_GetType((LPDIRECT3DRESOURCE9) This); + return IWineD3DCubeTexture_GetType(This->wineD3DCubeTexture); } /* IDirect3DCubeTexture9 IDirect3DBaseTexture9 Interface follow: */ DWORD WINAPI IDirect3DCubeTexture9Impl_SetLOD(LPDIRECT3DCUBETEXTURE9 iface, DWORD LODNew) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetLOD((LPDIRECT3DBASETEXTURE9) This, LODNew); + return IWineD3DCubeTexture_SetLOD(This->wineD3DCubeTexture, LODNew); } DWORD WINAPI IDirect3DCubeTexture9Impl_GetLOD(LPDIRECT3DCUBETEXTURE9 iface) { @@ -125,86 +117,71 @@ DWORD WINAPI IDirect3DCubeTexture9Impl_GetLevelCount(LPDIRECT3DCUBETEXTURE9 iface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetLevelCount((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DCubeTexture_GetLevelCount(This->wineD3DCubeTexture); } HRESULT WINAPI IDirect3DCubeTexture9Impl_SetAutoGenFilterType(LPDIRECT3DCUBETEXTURE9 iface, D3DTEXTUREFILTERTYPE FilterType) { - IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This, FilterType); + IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; + return IWineD3DCubeTexture_SetAutoGenFilterType(This->wineD3DCubeTexture, FilterType); } D3DTEXTUREFILTERTYPE WINAPI IDirect3DCubeTexture9Impl_GetAutoGenFilterType(LPDIRECT3DCUBETEXTURE9 iface) { - IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This); + IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; + return IWineD3DCubeTexture_GetAutoGenFilterType(This->wineD3DCubeTexture); } void WINAPI IDirect3DCubeTexture9Impl_GenerateMipSubLevels(LPDIRECT3DCUBETEXTURE9 iface) { - IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; + return IWineD3DCubeTexture_GenerateMipSubLevels(This->wineD3DCubeTexture); } /* IDirect3DCubeTexture9 Interface follow: */ HRESULT WINAPI IDirect3DCubeTexture9Impl_GetLevelDesc(LPDIRECT3DCUBETEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - if (Level < This->levels) { - TRACE("(%p) level (%d)\n", This, Level); - return IDirect3DSurface9Impl_GetDesc((LPDIRECT3DSURFACE9) This->surfaces[0][Level], pDesc); - } - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - return D3D_OK; + WINED3DSURFACE_DESC wined3ddesc; + UINT tmpInt = -1; + + /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ + wined3ddesc.Format = &pDesc->Format; + wined3ddesc.Type = &pDesc->Type; + wined3ddesc.Usage = &pDesc->Usage; + wined3ddesc.Pool = &pDesc->Pool; + wined3ddesc.Size = &tmpInt; + wined3ddesc.MultiSampleType = &pDesc->MultiSampleType; + wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; + wined3ddesc.Width = &pDesc->Width; + wined3ddesc.Height = &pDesc->Height; + + return IWineD3DCubeTexture_GetLevelDesc(This->wineD3DCubeTexture, Level, &wined3ddesc); } HRESULT WINAPI IDirect3DCubeTexture9Impl_GetCubeMapSurface(LPDIRECT3DCUBETEXTURE9 iface, D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - if (Level < This->levels) { - *ppCubeMapSurface = (LPDIRECT3DSURFACE9) This->surfaces[FaceType][Level]; - IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppCubeMapSurface); - TRACE("(%p) -> faceType(%d) level(%d) returning surface@%p \n", This, FaceType, Level, This->surfaces[FaceType][Level]); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; + HRESULT hrc = D3D_OK; + + IWineD3DSurface *mySurface = NULL; + hrc = IWineD3DCubeTexture_GetCubeMapSurface(This->wineD3DCubeTexture, FaceType, Level, &mySurface); + if (hrc == D3D_OK && NULL != ppCubeMapSurface) { + IWineD3DCubeTexture_GetParent(mySurface, (IUnknown **)ppCubeMapSurface); + IWineD3DCubeTexture_Release(mySurface); } - return D3D_OK; + return hrc; } HRESULT WINAPI IDirect3DCubeTexture9Impl_LockRect(LPDIRECT3DCUBETEXTURE9 iface, D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { - HRESULT hr; IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - if (Level < This->levels) { - /** - * Not dirtified while Surfaces don't notify dirtification - * This->Dirty = TRUE; - */ - hr = IDirect3DSurface9Impl_LockRect((LPDIRECT3DSURFACE9) This->surfaces[FaceType][Level], pLockedRect, pRect, Flags); - TRACE("(%p) -> faceType(%d) level(%d) returning memory@%p success(%lu)\n", This, FaceType, Level, pLockedRect->pBits, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DCubeTexture_LockRect(This->wineD3DCubeTexture, FaceType, Level, pLockedRect, pRect, Flags); } HRESULT WINAPI IDirect3DCubeTexture9Impl_UnlockRect(LPDIRECT3DCUBETEXTURE9 iface, D3DCUBEMAP_FACES FaceType, UINT Level) { - HRESULT hr; IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - if (Level < This->levels) { - hr = IDirect3DSurface9Impl_UnlockRect((LPDIRECT3DSURFACE9) This->surfaces[FaceType][Level]); - TRACE("(%p) -> faceType(%d) level(%d) success(%lu)\n", This, FaceType, Level, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DCubeTexture_UnlockRect(This->wineD3DCubeTexture, FaceType, Level); } HRESULT WINAPI IDirect3DCubeTexture9Impl_AddDirtyRect(LPDIRECT3DCUBETEXTURE9 iface, D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) { IDirect3DCubeTexture9Impl *This = (IDirect3DCubeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - This->Dirty = TRUE; - return D3D_OK; + return IWineD3DCubeTexture_AddDirtyRect(This->wineD3DCubeTexture, FaceType, pDirtyRect); } @@ -237,11 +214,35 @@ /* IDirect3DDevice9 IDirect3DCubeTexture9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateCubeTexture(LPDIRECT3DDEVICE9 iface, - UINT EdgeLength, UINT Levels, DWORD Usage, + UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, - IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) { + IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) { + IDirect3DCubeTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hr = D3D_OK; + + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture9Impl)); + if (NULL == object) { + FIXME("(%p) allocation of CubeTexture failed\n", This); + *ppCubeTexture = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DCubeTexture9_Vtbl; + object->ref = 1; + hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage, + Format, Pool, &(object->wineD3DCubeTexture), pSharedHandle, (IUnknown *)object, + D3D9CB_CreateSurface); + + if (hr != D3D_OK) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateCubeTexture failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppCubeTexture = NULL; + } else { + *ppCubeTexture = (LPDIRECT3DCUBETEXTURE9) object; + } + return hr; } diff -urN wine-20050111/dlls/d3d9/d3d9_private.h wine-20050211/dlls/d3d9/d3d9_private.h --- wine-20050111/dlls/d3d9/d3d9_private.h 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d9/d3d9_private.h 2005-01-28 15:03:32.000000000 +0100 @@ -447,20 +447,7 @@ DWORD ref; /* IDirect3DVolume9 fields */ - IDirect3DDevice9Impl *Device; - D3DRESOURCETYPE ResourceType; - - IUnknown *Container; - D3DVOLUME_DESC myDesc; - BYTE *allocatedMemory; - UINT textureName; - UINT bytesPerPixel; - - BOOL lockable; - BOOL locked; - D3DBOX lockedBox; - D3DBOX dirtyBox; - BOOL Dirty; + IWineD3DVolume *wineD3DVolume; }; /* IUnknown: */ @@ -756,17 +743,7 @@ DWORD ref; /* IDirect3DResource9 fields */ - D3DRESOURCETYPE ResourceType; - - /* IDirect3DBaseTexture9 fields */ - BOOL Dirty; - D3DFORMAT format; - UINT levels; - - /* IDirect3DCubeTexture9 fields */ - UINT edgeLength; - DWORD usage; - IDirect3DSurface9Impl *surfaces[6][MAX_LEVELS]; + IWineD3DCubeTexture *wineD3DCubeTexture; }; /* IUnknown: */ @@ -819,18 +796,8 @@ DWORD ref; /* IDirect3DResource9 fields */ - D3DRESOURCETYPE ResourceType; + IWineD3DTexture *wineD3DTexture; - /* IDirect3DBaseTexture9 fields */ - BOOL Dirty; - D3DFORMAT format; - UINT levels; - - /* IDirect3DTexture9 fields */ - UINT width; - UINT height; - DWORD usage; - IDirect3DSurface9Impl *surfaces[MAX_LEVELS]; }; /* IUnknown: */ @@ -883,19 +850,7 @@ DWORD ref; /* IDirect3DResource9 fields */ - D3DRESOURCETYPE ResourceType; - - /* IDirect3DBaseTexture9 fields */ - BOOL Dirty; - D3DFORMAT format; - UINT levels; - - /* IDirect3DVolumeTexture9 fields */ - UINT width; - UINT height; - UINT depth; - DWORD usage; - IDirect3DVolume9Impl *volumes[MAX_LEVELS]; + IWineD3DVolumeTexture *wineD3DVolumeTexture; }; /* IUnknown: */ @@ -1045,15 +1000,7 @@ DWORD ref; /* IDirect3DVertexDeclaration9 fields */ - IDirect3DDevice9Impl* Device; - - /** precomputed fvf if simple declaration */ - DWORD fvf[MAX_STREAMS]; - DWORD allFVF; - - /** dx8 compatible Declaration fields */ - DWORD* pDeclaration8; - DWORD declaration8Length; + IWineD3DVertexDeclaration *wineD3DVertexDeclaration; }; /* IUnknown: */ @@ -1182,5 +1129,16 @@ 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_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-20050111/dlls/d3d9/device.c wine-20050211/dlls/d3d9/device.c --- wine-20050111/dlls/d3d9/device.c 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d9/device.c 2005-02-10 21:25:20.000000000 +0100 @@ -1,7 +1,7 @@ /* * IDirect3DDevice9 implementation * - * Copyright 2002-2003 Jason Edmeades + * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * * This library is free software; you can redistribute it and/or @@ -22,9 +22,6 @@ #include "config.h" #include "d3d9_private.h" -/** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */ -#undef GL_VERSION_1_4 - WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); @@ -46,14 +43,19 @@ ULONG WINAPI IDirect3DDevice9Impl_AddRef(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IDirect3D9_Release((LPDIRECT3D9) This->direct3d); IWineD3DDevice_Release(This->WineD3DDevice); @@ -71,7 +73,7 @@ UINT WINAPI IDirect3DDevice9Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : stub, emulating 32Mb for now\n", This); + FIXME("(%p) : stub, emulating 32Mb for now\n", This); /* * pretend we have 32MB of any type of memory queried. */ @@ -95,27 +97,24 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetDeviceCaps(LPDIRECT3DDEVICE9 iface, D3DCAPS9* pCaps) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub, calling idirect3d for now\n", This); - IDirect3D9Impl_GetDeviceCaps((LPDIRECT3D9) This->direct3d, This->adapterNo, This->devType, pCaps); - return D3D_OK; + return IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pCaps); } HRESULT WINAPI IDirect3DDevice9Impl_GetDisplayMode(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DDevice_GetDisplayMode(This->WineD3DDevice, iSwapChain, pMode); } HRESULT WINAPI IDirect3DDevice9Impl_GetCreationParameters(LPDIRECT3DDEVICE9 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) copying to %p\n", This, pParameters); + FIXME("(%p) copying to %p\n", This, pParameters); memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS)); return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_SetCursorProperties(LPDIRECT3DDEVICE9 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot); + FIXME("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot); /* TODO: IDirect3DSurface9Impl* pSur = (IDirect3DSurface9Impl*) pCursorBitmap; @@ -136,7 +135,7 @@ void WINAPI IDirect3DDevice9Impl_SetCursorPosition(LPDIRECT3DDEVICE9 iface, int XScreenSpace, int YScreenSpace, DWORD Flags) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace); + FIXME("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace); This->xScreenSpace = XScreenSpace; This->yScreenSpace = YScreenSpace; return; @@ -144,7 +143,7 @@ BOOL WINAPI IDirect3DDevice9Impl_ShowCursor(LPDIRECT3DDEVICE9 iface, BOOL bShow) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : visible(%d)\n", This, bShow); + FIXME("(%p) : visible(%d)\n", This, bShow); This->bCursorVisible = bShow; return D3D_OK; } @@ -162,15 +161,16 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetBackBuffer(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - *ppBackBuffer = (LPDIRECT3DSURFACE9) This->backBuffer; - TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer); - if (BackBuffer > This->PresentParms.BackBufferCount - 1) { - FIXME("Only one backBuffer currently supported\n"); - return D3DERR_INVALIDCALL; + + IWineD3DSurface *retSurface = NULL; + HRESULT rc = D3D_OK; + + rc = IWineD3DDevice_GetBackBuffer(This->WineD3DDevice, iSwapChain, BackBuffer, Type, (IWineD3DSurface **)&retSurface); + if (rc == D3D_OK && NULL != ppBackBuffer) { + IWineD3DSurface_GetParent(retSurface, (IUnknown **)ppBackBuffer); + IWineD3DSurface_Release(retSurface); } - /* Note inc ref on returned surface */ - IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppBackBuffer); - return D3D_OK; + return rc; } HRESULT WINAPI IDirect3DDevice9Impl_GetRasterStatus(LPDIRECT3DDEVICE9 iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { @@ -213,16 +213,29 @@ 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; - IWineD3DDevice_CreateRenderTarget(This->WineD3DDevice, Width, Height, Format, MultiSample, MultisampleQuality, - Lockable, &object->wineD3DSurface, pSharedHandle, (IUnknown *)This); - *ppSurface = (LPDIRECT3DSURFACE9) object; - - return D3D_OK; + hrc = IWineD3DDevice_CreateRenderTarget(This->WineD3DDevice, Width, Height, Format, MultiSample, MultisampleQuality, + Lockable, &object->wineD3DSurface, pSharedHandle, (IUnknown *)object); + if (hrc != D3D_OK) { + /* 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) { @@ -274,32 +287,79 @@ } HRESULT WINAPI IDirect3DDevice9Impl_CreateOffscreenPlainSurface(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) { + IDirect3DSurface9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + 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; } HRESULT WINAPI IDirect3DDevice9Impl_SetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hr = S_OK; + + /* If pRenderTarget == NULL, it seems to default to back buffer */ + if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface9*) This->backBuffer; + + /* If we are trying to set what we already have, don't bother */ + if ((IDirect3DSurface9Impl*) pRenderTarget == This->renderTarget) { + TRACE("Trying to do a NOP SetRenderTarget operation\n"); + } else { + /* Otherwise, set the render target up */ + TRACE("(%p) : newRender@%p (default is backbuffer=(%p))\n", This, pRenderTarget, This->backBuffer); + hr = E_FAIL; /* not supported yet */ + } + + return hr; } HRESULT WINAPI IDirect3DDevice9Impl_GetRenderTarget(LPDIRECT3DDEVICE9 iface, DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer); + *ppRenderTarget = (LPDIRECT3DSURFACE9) This->renderTarget; + IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppRenderTarget); return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_SetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9* pZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + HRESULT hr = S_OK; + /* If we are trying to set what we already have, don't bother */ + if ((IDirect3DSurface9Impl*) pZStencilSurface == This->stencilBufferTarget) { + TRACE("Trying to do a NOP SetDepthStencilSurface operation\n"); + } else { + /* Otherwise, set the target up */ + TRACE("(%p) : newDepthStencil@%p (default is stencilbuffer=(%p))\n", This, pZStencilSurface, This->depthStencilBuffer); + hr = E_FAIL; /* not supported yet */ + } return D3D_OK; } HRESULT WINAPI IDirect3DDevice9Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE9 iface, IDirect3DSurface9** ppZStencilSurface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); + TRACE("(%p)->returning (%p) default is stencilbuffer=(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer); + *ppZStencilSurface = (LPDIRECT3DSURFACE9) This->stencilBufferTarget; + if (NULL != *ppZStencilSurface) IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) *ppZStencilSurface); return D3D_OK; } @@ -405,16 +465,21 @@ HRESULT WINAPI IDirect3DDevice9Impl_GetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9** ppTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage); - *ppTexture = (LPDIRECT3DBASETEXTURE9) This->UpdateStateBlock->textures[Stage]; - IDirect3DBaseTexture9Impl_AddRef(*ppTexture); - return D3D_OK; + IWineD3DBaseTexture *retTexture = NULL; + HRESULT rc = D3D_OK; + + rc = IWineD3DDevice_GetTexture(This->WineD3DDevice, Stage, (IWineD3DBaseTexture **)&retTexture); + if (rc == D3D_OK && NULL != ppTexture) { + IWineD3DBaseTexture_GetParent(retTexture, (IUnknown **)ppTexture); + IWineD3DBaseTexture_Release(retTexture); + } + return rc; } HRESULT WINAPI IDirect3DDevice9Impl_SetTexture(LPDIRECT3DDEVICE9 iface, DWORD Stage, IDirect3DBaseTexture9* pTexture) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DDevice_SetTexture(This->WineD3DDevice, Stage, + pTexture==NULL ? NULL:((IDirect3DBaseTexture9Impl *)pTexture)->wineD3DBaseTexture); } HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { @@ -561,7 +626,7 @@ HRESULT rc = D3D_OK; rc = IWineD3DDevice_GetStreamSource(This->WineD3DDevice, StreamNumber, (IWineD3DVertexBuffer **)&retStream, OffsetInBytes, pStride); - if (rc == D3D_OK && NULL != *pStream) { + if (rc == D3D_OK && NULL != pStream) { IWineD3DVertexBuffer_GetParent(retStream, (IUnknown **)pStream); IWineD3DVertexBuffer_Release(retStream); } @@ -594,7 +659,7 @@ UINT tmp; rc = IWineD3DDevice_GetIndices(This->WineD3DDevice, &retIndexData, &tmp); - if (rc == D3D_OK && NULL != *ppIndexData) { + if (rc == D3D_OK && NULL != ppIndexData) { IWineD3DVertexBuffer_GetParent(retIndexData, (IUnknown **)ppIndexData); IWineD3DVertexBuffer_Release(retIndexData); } diff -urN wine-20050111/dlls/d3d9/directx.c wine-20050211/dlls/d3d9/directx.c --- wine-20050111/dlls/d3d9/directx.c 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d9/directx.c 2005-01-28 15:03:32.000000000 +0100 @@ -41,14 +41,19 @@ ULONG WINAPI IDirect3D9Impl_AddRef(LPDIRECT3D9 iface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3D9Impl_Release(LPDIRECT3D9 iface) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3D_Release(This->WineD3D); HeapFree(GetProcessHeap(), 0, This); @@ -144,7 +149,7 @@ HRESULT WINAPI IDirect3D9Impl_GetDeviceCaps(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) { IDirect3D9Impl *This = (IDirect3D9Impl *)iface; - return IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, (void *)pCaps); + return IWineD3D_GetDeviceCaps(This->WineD3D, Adapter, DeviceType, (WINED3DCAPS *)pCaps); } HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9 iface, UINT Adapter) { @@ -159,12 +164,21 @@ IWineD3DSurface** ppSurface, HANDLE* pSharedHandle) { HRESULT res = D3D_OK; IDirect3DSurface9Impl *d3dSurface = NULL; + IDirect3DDevice9Impl* pDeviceImpl = (IDirect3DDevice9Impl*) device; res = IDirect3DDevice9_CreateRenderTarget((IDirect3DDevice9 *)device, Width, Height, Format, MultiSample, MultisampleQuality, Lockable, (IDirect3DSurface9 **)&d3dSurface, pSharedHandle); - if (res == D3D_OK) { + + if (SUCCEEDED(res)) { *ppSurface = d3dSurface->wineD3DSurface; + if (NULL == pDeviceImpl->backBuffer) { + pDeviceImpl->backBuffer = d3dSurface; + pDeviceImpl->renderTarget = d3dSurface; + IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) pDeviceImpl->renderTarget); + } + } else { + *ppSurface = NULL; } return res; } @@ -179,14 +193,18 @@ /* Check the validity range of the adapter parameter */ if (Adapter >= IDirect3D9Impl_GetAdapterCount(iface)) { + *ppReturnedDeviceInterface = NULL; return D3DERR_INVALIDCALL; } /* Allocate the storage for the device object */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice9Impl)); if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppReturnedDeviceInterface = NULL; return D3DERR_OUTOFVIDEOMEMORY; } + object->lpVtbl = &Direct3DDevice9_Vtbl; object->ref = 1; object->direct3d = This; @@ -208,10 +226,7 @@ localParameters.Flags = &pPresentationParameters->Flags; localParameters.FullScreen_RefreshRateInHz = &pPresentationParameters->FullScreen_RefreshRateInHz; localParameters.PresentationInterval = &pPresentationParameters->PresentationInterval; - IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D9CB_CreateRenderTarget); - - FIXME("(%p) : incomplete stub\n", This); - return D3D_OK; + return IWineD3D_CreateDevice(This->WineD3D, Adapter, DeviceType, hFocusWindow, BehaviourFlags, &localParameters, &object->WineD3DDevice, (IUnknown *)object, D3D9CB_CreateRenderTarget); } IDirect3D9Vtbl Direct3D9_Vtbl = diff -urN wine-20050111/dlls/d3d9/indexbuffer.c wine-20050211/dlls/d3d9/indexbuffer.c --- wine-20050111/dlls/d3d9/indexbuffer.c 2004-11-24 19:13:41.000000000 +0100 +++ wine-20050211/dlls/d3d9/indexbuffer.c 2005-01-24 13:44:01.000000000 +0100 @@ -42,14 +42,19 @@ ULONG WINAPI IDirect3DIndexBuffer9Impl_AddRef(LPDIRECT3DINDEXBUFFER9 iface) { IDirect3DIndexBuffer9Impl *This = (IDirect3DIndexBuffer9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DIndexBuffer9Impl_Release(LPDIRECT3DINDEXBUFFER9 iface) { IDirect3DIndexBuffer9Impl *This = (IDirect3DIndexBuffer9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3DIndexBuffer_Release(This->wineD3DIndexBuffer); HeapFree(GetProcessHeap(), 0, This); @@ -142,13 +147,26 @@ IDirect3DIndexBuffer9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + HRESULT hrc = D3D_OK; /* Allocate the storage for the device */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppIndexBuffer = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + object->lpVtbl = &Direct3DIndexBuffer9_Vtbl; object->ref = 1; - IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage, Format, Pool, &(object->wineD3DIndexBuffer), pSharedHandle, (IUnknown *)object); - - *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER9) object; - return D3D_OK; + hrc = IWineD3DDevice_CreateIndexBuffer(This->WineD3DDevice, Length, Usage, Format, Pool, &(object->wineD3DIndexBuffer), pSharedHandle, (IUnknown *)object); + if (hrc != D3D_OK) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateIndexBuffer failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppIndexBuffer = NULL; + } else { + *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER9) object; + } + return hrc; } diff -urN wine-20050111/dlls/d3d9/pixelshader.c wine-20050211/dlls/d3d9/pixelshader.c --- wine-20050111/dlls/d3d9/pixelshader.c 2004-11-30 22:39:00.000000000 +0100 +++ wine-20050211/dlls/d3d9/pixelshader.c 2005-01-24 13:44:01.000000000 +0100 @@ -41,15 +41,19 @@ ULONG WINAPI IDirect3DPixelShader9Impl_AddRef(LPDIRECT3DPIXELSHADER9 iface) { IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DPixelShader9Impl_Release(LPDIRECT3DPIXELSHADER9 iface) { IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface; - ULONG ref = --This->ref; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } diff -urN wine-20050111/dlls/d3d9/query.c wine-20050211/dlls/d3d9/query.c --- wine-20050111/dlls/d3d9/query.c 2004-10-14 02:32:04.000000000 +0200 +++ wine-20050211/dlls/d3d9/query.c 2005-01-28 15:03:32.000000000 +0100 @@ -41,14 +41,19 @@ ULONG WINAPI IDirect3DQuery9Impl_AddRef(LPDIRECT3DQUERY9 iface) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DQuery9Impl_Release(LPDIRECT3DQUERY9 iface) { IDirect3DQuery9Impl *This = (IDirect3DQuery9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } @@ -104,7 +109,36 @@ /* IDirect3DDevice9 IDirect3DQuery9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateQuery(LPDIRECT3DDEVICE9 iface, D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; +#if 0 + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; +#endif + IDirect3DQuery9Impl *object = NULL; + HRESULT hr = D3D_OK; + + if (NULL == ppQuery) { + return D3DERR_INVALIDCALL; + } + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DQuery9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppQuery = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DQuery9_Vtbl; + object->ref = 1; +#if 0 + hr = IWineD3DDevice_CreateQuery(This->WineD3DDevice, 9, pVertexElements, &(object->wineD3DQuery)); + + if (FAILED(hr)) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateQuery failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppQuery = NULL; + } else { + *ppQuery = (LPDIRECT3DQUERY9) object; + } +#endif + return hr; } diff -urN wine-20050111/dlls/d3d9/resource.c wine-20050211/dlls/d3d9/resource.c --- wine-20050111/dlls/d3d9/resource.c 2004-12-07 15:29:12.000000000 +0100 +++ wine-20050211/dlls/d3d9/resource.c 2005-01-24 13:44:01.000000000 +0100 @@ -41,14 +41,19 @@ ULONG WINAPI IDirect3DResource9Impl_AddRef(LPDIRECT3DRESOURCE9 iface) { IDirect3DResource9Impl *This = (IDirect3DResource9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DResource9Impl_Release(LPDIRECT3DRESOURCE9 iface) { IDirect3DResource9Impl *This = (IDirect3DResource9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3DResource_Release(This->wineD3DResource); HeapFree(GetProcessHeap(), 0, This); @@ -62,6 +67,7 @@ IWineD3DDevice *myDevice = NULL; IWineD3DResource_GetDevice(This->wineD3DResource, &myDevice); IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); + IWineD3DDevice_Release(myDevice); return D3D_OK; } diff -urN wine-20050111/dlls/d3d9/stateblock.c wine-20050211/dlls/d3d9/stateblock.c --- wine-20050111/dlls/d3d9/stateblock.c 2004-10-14 02:32:04.000000000 +0200 +++ wine-20050211/dlls/d3d9/stateblock.c 2005-01-24 13:44:01.000000000 +0100 @@ -41,14 +41,19 @@ ULONG WINAPI IDirect3DStateBlock9Impl_AddRef(LPDIRECT3DSTATEBLOCK9 iface) { IDirect3DStateBlock9Impl *This = (IDirect3DStateBlock9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DStateBlock9Impl_Release(LPDIRECT3DSTATEBLOCK9 iface) { IDirect3DStateBlock9Impl *This = (IDirect3DStateBlock9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } diff -urN wine-20050111/dlls/d3d9/surface.c wine-20050211/dlls/d3d9/surface.c --- wine-20050111/dlls/d3d9/surface.c 2005-01-09 18:37:02.000000000 +0100 +++ wine-20050211/dlls/d3d9/surface.c 2005-01-24 13:44:01.000000000 +0100 @@ -42,16 +42,21 @@ ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { - IWineD3DBaseTexture_Release(This->wineD3DSurface); + IWineD3DSurface_Release(This->wineD3DSurface); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -130,12 +135,14 @@ HRESULT WINAPI IDirect3DSurface9Impl_GetDesc(LPDIRECT3DSURFACE9 iface, D3DSURFACE_DESC* pDesc) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; WINED3DSURFACE_DESC wined3ddesc; + UINT tmpInt = -1; /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ wined3ddesc.Format = &pDesc->Format; wined3ddesc.Type = &pDesc->Type; wined3ddesc.Usage = &pDesc->Usage; wined3ddesc.Pool = &pDesc->Pool; + wined3ddesc.Size = &tmpInt; wined3ddesc.MultiSampleType = &pDesc->MultiSampleType; wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; wined3ddesc.Width = &pDesc->Width; @@ -185,3 +192,25 @@ 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-20050111/dlls/d3d9/swapchain.c wine-20050211/dlls/d3d9/swapchain.c --- wine-20050111/dlls/d3d9/swapchain.c 2004-10-14 02:32:04.000000000 +0200 +++ wine-20050211/dlls/d3d9/swapchain.c 2005-01-24 13:44:01.000000000 +0100 @@ -42,14 +42,19 @@ ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface) { IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } diff -urN wine-20050111/dlls/d3d9/texture.c wine-20050211/dlls/d3d9/texture.c --- wine-20050111/dlls/d3d9/texture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/d3d9/texture.c 2005-01-28 15:03:32.000000000 +0100 @@ -1,7 +1,7 @@ /* * IDirect3DTexture9 implementation * - * Copyright 2002-2003 Jason Edmeades + * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * * This library is free software; you can redistribute it and/or @@ -43,23 +43,21 @@ ULONG WINAPI IDirect3DTexture9Impl_AddRef(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - ULONG ref = --This->ref; - unsigned int i; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); if (ref == 0) { - for (i = 0; i < This->levels; i++) { - if (NULL != This->surfaces[i]) { - TRACE("(%p) : Releasing surface %p\n", This, This->surfaces[i]); - IDirect3DSurface9Impl_Release((LPDIRECT3DSURFACE9) This->surfaces[i]); - } - } + IWineD3DTexture_Release(This->wineD3DTexture); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -73,130 +71,117 @@ HRESULT WINAPI IDirect3DTexture9Impl_SetPrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DTexture_SetPrivateData(This->wineD3DTexture,refguid,pData,SizeOfData,Flags); } HRESULT WINAPI IDirect3DTexture9Impl_GetPrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DTexture_GetPrivateData(This->wineD3DTexture,refguid,pData,pSizeOfData); } HRESULT WINAPI IDirect3DTexture9Impl_FreePrivateData(LPDIRECT3DTEXTURE9 iface, REFGUID refguid) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DTexture_FreePrivateData(This->wineD3DTexture,refguid); } DWORD WINAPI IDirect3DTexture9Impl_SetPriority(LPDIRECT3DTEXTURE9 iface, DWORD PriorityNew) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DResource9Impl_SetPriority((LPDIRECT3DRESOURCE9) This, PriorityNew); + return IWineD3DTexture_SetPriority(This->wineD3DTexture, PriorityNew); } DWORD WINAPI IDirect3DTexture9Impl_GetPriority(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DResource9Impl_GetPriority((LPDIRECT3DRESOURCE9) This); + return IWineD3DTexture_GetPriority(This->wineD3DTexture); } void WINAPI IDirect3DTexture9Impl_PreLoad(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + return IWineD3DTexture_PreLoad(This->wineD3DTexture); } D3DRESOURCETYPE WINAPI IDirect3DTexture9Impl_GetType(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DResource9Impl_GetType((LPDIRECT3DRESOURCE9) This); + return IWineD3DTexture_GetType(This->wineD3DTexture); } /* IDirect3DTexture9 IDirect3DBaseTexture9 Interface follow: */ DWORD WINAPI IDirect3DTexture9Impl_SetLOD(LPDIRECT3DTEXTURE9 iface, DWORD LODNew) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetLOD((LPDIRECT3DBASETEXTURE9) This, LODNew); + return IWineD3DTexture_SetLOD(This->wineD3DTexture, LODNew); } DWORD WINAPI IDirect3DTexture9Impl_GetLOD(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetLOD((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DTexture_GetLOD(This->wineD3DTexture); } DWORD WINAPI IDirect3DTexture9Impl_GetLevelCount(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetLevelCount((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DTexture_GetLevelCount(This->wineD3DTexture); } HRESULT WINAPI IDirect3DTexture9Impl_SetAutoGenFilterType(LPDIRECT3DTEXTURE9 iface, D3DTEXTUREFILTERTYPE FilterType) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This, FilterType); + return IWineD3DTexture_SetAutoGenFilterType(This->wineD3DTexture, FilterType); } D3DTEXTUREFILTERTYPE WINAPI IDirect3DTexture9Impl_GetAutoGenFilterType(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DTexture_GetAutoGenFilterType(This->wineD3DTexture); } void WINAPI IDirect3DTexture9Impl_GenerateMipSubLevels(LPDIRECT3DTEXTURE9 iface) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + return IWineD3DTexture_GenerateMipSubLevels(This->wineD3DTexture); } /* IDirect3DTexture9 Interface follow: */ HRESULT WINAPI IDirect3DTexture9Impl_GetLevelDesc(LPDIRECT3DTEXTURE9 iface, UINT Level, D3DSURFACE_DESC* pDesc) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - if (Level < This->levels) { - TRACE("(%p) Level (%d)\n", This, Level); - return IDirect3DSurface9Impl_GetDesc((LPDIRECT3DSURFACE9) This->surfaces[Level], pDesc); - } - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; + WINED3DSURFACE_DESC wined3ddesc; + UINT tmpInt = -1; + + /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ + wined3ddesc.Format = &pDesc->Format; + wined3ddesc.Type = &pDesc->Type; + wined3ddesc.Usage = &pDesc->Usage; + wined3ddesc.Pool = &pDesc->Pool; + wined3ddesc.Size = &tmpInt; + wined3ddesc.MultiSampleType = &pDesc->MultiSampleType; + wined3ddesc.MultiSampleQuality = &pDesc->MultiSampleQuality; + wined3ddesc.Width = &pDesc->Width; + wined3ddesc.Height = &pDesc->Height; + + return IWineD3DTexture_GetLevelDesc(This->wineD3DTexture, Level, &wined3ddesc); } HRESULT WINAPI IDirect3DTexture9Impl_GetSurfaceLevel(LPDIRECT3DTEXTURE9 iface, UINT Level, IDirect3DSurface9** ppSurfaceLevel) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - *ppSurfaceLevel = (LPDIRECT3DSURFACE9) This->surfaces[Level]; - IDirect3DSurface9Impl_AddRef((LPDIRECT3DSURFACE9) This->surfaces[Level]); - TRACE("(%p) : returning %p for level %d\n", This, *ppSurfaceLevel, Level); - return D3D_OK; + HRESULT hrc = D3D_OK; + + IWineD3DSurface *mySurface = NULL; + hrc = IWineD3DTexture_GetSurfaceLevel(This->wineD3DTexture, Level, &mySurface); + if (hrc == D3D_OK && NULL != ppSurfaceLevel) { + IWineD3DSurface_GetParent(mySurface, (IUnknown **)ppSurfaceLevel); + IWineD3DSurface_Release(mySurface); + } + return hrc; } HRESULT WINAPI IDirect3DTexture9Impl_LockRect(LPDIRECT3DTEXTURE9 iface, UINT Level,D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) { - HRESULT hr; IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - if (Level < This->levels) { - /** - * Not dirtified while Surfaces don't notify dirtification - * This->impl.parent.Dirty = TRUE; - */ - hr = IDirect3DSurface9Impl_LockRect((LPDIRECT3DSURFACE9) This->surfaces[Level], pLockedRect, pRect, Flags); - TRACE("(%p) Level (%d) success(%lu)\n", This, Level, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DTexture_LockRect(This->wineD3DTexture, Level, pLockedRect, pRect, Flags); } HRESULT WINAPI IDirect3DTexture9Impl_UnlockRect(LPDIRECT3DTEXTURE9 iface, UINT Level) { - HRESULT hr; IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - if (Level < This->levels) { - hr = IDirect3DSurface9Impl_UnlockRect((LPDIRECT3DSURFACE9) This->surfaces[Level]); - TRACE("(%p) Level (%d) success(%lu)\n", This, Level, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DTexture_UnlockRect(This->wineD3DTexture, Level); } HRESULT WINAPI IDirect3DTexture9Impl_AddDirtyRect(LPDIRECT3DTEXTURE9 iface, CONST RECT* pDirtyRect) { IDirect3DTexture9Impl *This = (IDirect3DTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - This->Dirty = TRUE; - return D3D_OK; + return IWineD3DTexture_AddDirtyRect(This->wineD3DTexture, pDirtyRect); } @@ -230,7 +215,30 @@ /* IDirect3DDevice9 IDirect3DTexture9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateTexture(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) { + IDirect3DTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hrc = D3D_OK; + + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppTexture = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DTexture9_Vtbl; + object->ref = 1; + hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage, + Format, Pool, &(object->wineD3DTexture), pSharedHandle, (IUnknown *)object, D3D9CB_CreateSurface); + + if (FAILED(hrc)) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateTexture failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppTexture = NULL; + } else { + *ppTexture = (LPDIRECT3DTEXTURE9) object; + } + return hrc; } diff -urN wine-20050111/dlls/d3d9/vertexbuffer.c wine-20050211/dlls/d3d9/vertexbuffer.c --- wine-20050111/dlls/d3d9/vertexbuffer.c 2004-11-24 19:13:41.000000000 +0100 +++ wine-20050211/dlls/d3d9/vertexbuffer.c 2005-01-24 13:44:01.000000000 +0100 @@ -42,14 +42,19 @@ ULONG WINAPI IDirect3DVertexBuffer9Impl_AddRef(LPDIRECT3DVERTEXBUFFER9 iface) { IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVertexBuffer9Impl_Release(LPDIRECT3DVERTEXBUFFER9 iface) { IDirect3DVertexBuffer9Impl *This = (IDirect3DVertexBuffer9Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { IWineD3DVertexBuffer_Release(This->wineD3DVertexBuffer); HeapFree(GetProcessHeap(), 0, This); @@ -141,13 +146,27 @@ IDirect3DVertexBuffer9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; + HRESULT hrc = D3D_OK; /* Allocate the storage for the device */ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppVertexBuffer = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + object->lpVtbl = &Direct3DVertexBuffer9_Vtbl; object->ref = 1; - IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage, FVF, Pool, &(object->wineD3DVertexBuffer), pSharedHandle, (IUnknown *)object); - *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER9) object; - - return D3D_OK; + hrc = IWineD3DDevice_CreateVertexBuffer(This->WineD3DDevice, Size, Usage, FVF, Pool, &(object->wineD3DVertexBuffer), pSharedHandle, (IUnknown *)object); + + if (hrc != D3D_OK) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateVertexBuffer failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppVertexBuffer = NULL; + } else { + *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER9) object; + } + return hrc; } diff -urN wine-20050111/dlls/d3d9/vertexdeclaration.c wine-20050211/dlls/d3d9/vertexdeclaration.c --- wine-20050111/dlls/d3d9/vertexdeclaration.c 2004-10-14 02:32:04.000000000 +0200 +++ wine-20050211/dlls/d3d9/vertexdeclaration.c 2005-01-28 15:03:32.000000000 +0100 @@ -41,15 +41,21 @@ ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLARATION9 iface) { IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) { IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { + IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -58,16 +64,16 @@ /* IDirect3DVertexDeclaration9 Interface follow: */ HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDevice(LPDIRECT3DVERTEXDECLARATION9 iface, IDirect3DDevice9** ppDevice) { IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; - TRACE("(%p) : returning %p\n", This, This->Device); - *ppDevice = (LPDIRECT3DDEVICE9) This->Device; - IDirect3DDevice9Impl_AddRef(*ppDevice); + IWineD3DDevice *myDevice = NULL; + IWineD3DVertexDeclaration_GetDevice(This->wineD3DVertexDeclaration, &myDevice); + IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); + IWineD3DDevice_Release(myDevice); return D3D_OK; } HRESULT WINAPI IDirect3DVertexDeclaration9Impl_GetDeclaration(LPDIRECT3DVERTEXDECLARATION9 iface, D3DVERTEXELEMENT9* pDecl, UINT* pNumElements) { IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVertexDeclaration_GetDeclaration(This->wineD3DVertexDeclaration, 9, pDecl, (DWORD*) pNumElements); } @@ -84,18 +90,63 @@ /* IDirect3DDevice9 IDirect3DVertexDeclaration9 Methods follow: */ HRESULT WINAPI IDirect3DDevice9Impl_CreateVertexDeclaration(LPDIRECT3DDEVICE9 iface, CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DVertexDeclaration9Impl *object = NULL; + HRESULT hr = D3D_OK; + + if (NULL == ppDecl) { + return D3DERR_INVALIDCALL; + } + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexDeclaration9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppDecl = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DVertexDeclaration9_Vtbl; + object->ref = 1; + hr = IWineD3DDevice_CreateVertexDeclaration(This->WineD3DDevice, 9, pVertexElements, &(object->wineD3DVertexDeclaration)); + + if (FAILED(hr)) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateVertexDeclaration failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppDecl = NULL; + } else { + *ppDecl = (LPDIRECT3DVERTEXDECLARATION9) object; + } + return hr; } HRESULT WINAPI IDirect3DDevice9Impl_SetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9* pDecl) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DVertexDeclaration9Impl *pDeclImpl = (IDirect3DVertexDeclaration9Impl *)pDecl; + HRESULT hr = S_OK; + + This->UpdateStateBlock->vertexDecl = NULL; + if (NULL != pDecl) { + hr = IWineD3DDevice_SetVertexDeclaration(This->WineD3DDevice, pDeclImpl->wineD3DVertexDeclaration); + if (SUCCEEDED(hr)) { + This->UpdateStateBlock->vertexDecl = (IDirect3DVertexDeclaration9Impl*) pDecl; + } + } + return hr; } HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(LPDIRECT3DDEVICE9 iface, IDirect3DVertexDeclaration9** ppDecl) { - IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + IDirect3DDevice9Impl* This = (IDirect3DDevice9Impl*) iface; + IWineD3DVertexDeclaration* pTest = NULL; + HRESULT hr = S_OK; + IDirect3DVertexDeclaration9Impl* pCur = This->StateBlock->vertexDecl; + + if (NULL == ppDecl) { + return D3DERR_INVALIDCALL; + } + *ppDecl = NULL; + hr = IWineD3DDevice_GetVertexDeclaration(This->WineD3DDevice, &pTest); + if (SUCCEEDED(hr) && (NULL == pCur || pCur->wineD3DVertexDeclaration == pTest)) { + *ppDecl = (IDirect3DVertexDeclaration9*) pCur; + } + return hr; } diff -urN wine-20050111/dlls/d3d9/vertexshader.c wine-20050211/dlls/d3d9/vertexshader.c --- wine-20050111/dlls/d3d9/vertexshader.c 2004-12-06 21:43:56.000000000 +0100 +++ wine-20050211/dlls/d3d9/vertexshader.c 2005-01-24 13:44:01.000000000 +0100 @@ -41,15 +41,19 @@ ULONG WINAPI IDirect3DVertexShader9Impl_AddRef(LPDIRECT3DVERTEXSHADER9 iface) { IDirect3DVertexShader9Impl *This = (IDirect3DVertexShader9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVertexShader9Impl_Release(LPDIRECT3DVERTEXSHADER9 iface) { IDirect3DVertexShader9Impl *This = (IDirect3DVertexShader9Impl *)iface; - ULONG ref = --This->ref; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } diff -urN wine-20050111/dlls/d3d9/volume.c wine-20050211/dlls/d3d9/volume.c --- wine-20050111/dlls/d3d9/volume.c 2004-10-14 02:32:04.000000000 +0200 +++ wine-20050211/dlls/d3d9/volume.c 2005-01-24 13:44:01.000000000 +0100 @@ -1,7 +1,7 @@ /* * IDirect3DVolume9 implementation * - * Copyright 2002-2003 Jason Edmeades + * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * * This library is free software; you can redistribute it and/or @@ -41,16 +41,21 @@ ULONG WINAPI IDirect3DVolume9Impl_AddRef(LPDIRECT3DVOLUME9 iface) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVolume9Impl_Release(LPDIRECT3DVOLUME9 iface) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { - HeapFree(GetProcessHeap(), 0, This->allocatedMemory); + IWineD3DVolume_Release(This->wineD3DVolume); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -59,62 +64,73 @@ /* IDirect3DVolume9 Interface follow: */ HRESULT WINAPI IDirect3DVolume9Impl_GetDevice(LPDIRECT3DVOLUME9 iface, IDirect3DDevice9** ppDevice) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - TRACE("(%p) : returning %p\n", This, This->Device); - *ppDevice = (LPDIRECT3DDEVICE9) This->Device; - - /* Note Calling this method will increase the internal reference count - on the IDirect3DDevice9 interface. */ - IDirect3DDevice9Impl_AddRef(*ppDevice); + IWineD3DDevice *myDevice = NULL; + IWineD3DVolume_GetDevice(This->wineD3DVolume, &myDevice); + IWineD3DDevice_GetParent(myDevice, (IUnknown **)ppDevice); + IWineD3DDevice_Release(myDevice); return D3D_OK; } HRESULT WINAPI IDirect3DVolume9Impl_SetPrivateData(LPDIRECT3DVOLUME9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolume_SetPrivateData(This->wineD3DVolume, refguid, pData, SizeOfData, Flags); } HRESULT WINAPI IDirect3DVolume9Impl_GetPrivateData(LPDIRECT3DVOLUME9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolume_GetPrivateData(This->wineD3DVolume, refguid, pData, pSizeOfData); } HRESULT WINAPI IDirect3DVolume9Impl_FreePrivateData(LPDIRECT3DVOLUME9 iface, REFGUID refguid) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolume_FreePrivateData(This->wineD3DVolume, refguid); } HRESULT WINAPI IDirect3DVolume9Impl_GetContainer(LPDIRECT3DVOLUME9 iface, REFIID riid, void** ppContainer) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - TRACE("(%p) : returning %p\n", This, This->Container); - *ppContainer = This->Container; - IUnknown_AddRef(This->Container); - return D3D_OK; + HRESULT res; + + IUnknown *IWineContainer = NULL; + res = IWineD3DVolume_GetContainer(This->wineD3DVolume, riid, (void **)&IWineContainer); + + /* If this works, the only valid container is a child of resource (volumetexture) */ + if (res == D3D_OK && NULL != ppContainer) { + IWineD3DResource_GetParent((IWineD3DResource *)IWineContainer, (IUnknown **)ppContainer); + IWineD3DResource_Release((IWineD3DResource *)IWineContainer); + } + + return res; } HRESULT WINAPI IDirect3DVolume9Impl_GetDesc(LPDIRECT3DVOLUME9 iface, D3DVOLUME_DESC* pDesc) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - TRACE("(%p) : copying into %p\n", This, pDesc); - memcpy(pDesc, &This->myDesc, sizeof(D3DVOLUME_DESC)); - return D3D_OK; + WINED3DVOLUME_DESC wined3ddesc; + UINT tmpInt = -1; + + /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ + wined3ddesc.Format = &pDesc->Format; + wined3ddesc.Type = &pDesc->Type; + wined3ddesc.Usage = &pDesc->Usage; + wined3ddesc.Pool = &pDesc->Pool; + wined3ddesc.Size = &tmpInt; + wined3ddesc.Width = &pDesc->Width; + wined3ddesc.Height = &pDesc->Height; + wined3ddesc.Depth = &pDesc->Depth; + + return IWineD3DVolume_GetDesc(This->wineD3DVolume, &wined3ddesc); } HRESULT WINAPI IDirect3DVolume9Impl_LockBox(LPDIRECT3DVOLUME9 iface, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolume_LockBox(This->wineD3DVolume, pLockedVolume, pBox, Flags); } HRESULT WINAPI IDirect3DVolume9Impl_UnlockBox(LPDIRECT3DVOLUME9 iface) { IDirect3DVolume9Impl *This = (IDirect3DVolume9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolume_UnlockBox(This->wineD3DVolume); } - IDirect3DVolume9Vtbl Direct3DVolume9_Vtbl = { IDirect3DVolume9Impl_QueryInterface, @@ -129,3 +145,35 @@ IDirect3DVolume9Impl_LockBox, IDirect3DVolume9Impl_UnlockBox }; + +/* Internal function called back during the CreateVolumeTexture */ +HRESULT WINAPI D3D9CB_CreateVolume(IUnknown *pDevice, UINT Width, UINT Height, UINT Depth, + D3DFORMAT Format, D3DPOOL Pool, DWORD Usage, + IWineD3DVolume **ppVolume, + HANDLE * pSharedHandle) { + IDirect3DVolume9Impl *object; + IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)pDevice; + HRESULT hrc = D3D_OK; + + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume9Impl)); + if (NULL == object) { + FIXME("Allocation of memory failed\n"); + *ppVolume = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DVolume9_Vtbl; + object->ref = 1; + hrc = IWineD3DDevice_CreateVolume(This->WineD3DDevice, Width, Height, Depth, Usage, Format, + Pool, ppVolume, pSharedHandle, (IUnknown *)object); + if (hrc != D3D_OK) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateVolume failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppVolume = NULL; + } else { + *ppVolume = (IWineD3DVolume *)object; + } + return hrc; +} diff -urN wine-20050111/dlls/d3d9/volumetexture.c wine-20050211/dlls/d3d9/volumetexture.c --- wine-20050111/dlls/d3d9/volumetexture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/d3d9/volumetexture.c 2005-01-24 13:44:01.000000000 +0100 @@ -1,7 +1,7 @@ /* * IDirect3DVolumeTexture9 implementation * - * Copyright 2002-2003 Jason Edmeades + * Copyright 2002-2005 Jason Edmeades * Raphael Junqueira * * This library is free software; you can redistribute it and/or @@ -43,23 +43,21 @@ ULONG WINAPI IDirect3DVolumeTexture9Impl_AddRef(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI IDirect3DVolumeTexture9Impl_Release(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - ULONG ref = --This->ref; - UINT i; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); if (ref == 0) { - for (i = 0; i < This->levels; i++) { - if (This->volumes[i] != NULL) { - TRACE("(%p) : Releasing volume %p\n", This, This->volumes[i]); - IDirect3DVolume9Impl_Release((LPDIRECT3DVOLUME9) This->volumes[i]); - } - } + IWineD3DVolumeTexture_Release(This->wineD3DVolumeTexture); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -73,134 +71,115 @@ HRESULT WINAPI IDirect3DVolumeTexture9Impl_SetPrivateData(LPDIRECT3DVOLUMETEXTURE9 iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolumeTexture_SetPrivateData(This->wineD3DVolumeTexture,refguid,pData,SizeOfData,Flags); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetPrivateData(LPDIRECT3DVOLUMETEXTURE9 iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolumeTexture_GetPrivateData(This->wineD3DVolumeTexture,refguid,pData,pSizeOfData); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_FreePrivateData(LPDIRECT3DVOLUMETEXTURE9 iface, REFGUID refguid) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + return IWineD3DVolumeTexture_FreePrivateData(This->wineD3DVolumeTexture,refguid); } DWORD WINAPI IDirect3DVolumeTexture9Impl_SetPriority(LPDIRECT3DVOLUMETEXTURE9 iface, DWORD PriorityNew) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DResource9Impl_SetPriority((LPDIRECT3DRESOURCE9) This, PriorityNew); + return IWineD3DVolumeTexture_SetPriority(This->wineD3DVolumeTexture, PriorityNew); } DWORD WINAPI IDirect3DVolumeTexture9Impl_GetPriority(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DResource9Impl_GetPriority((LPDIRECT3DRESOURCE9) This); + return IWineD3DVolumeTexture_GetPriority(This->wineD3DVolumeTexture); } void WINAPI IDirect3DVolumeTexture9Impl_PreLoad(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + return IWineD3DVolumeTexture_PreLoad(This->wineD3DVolumeTexture); } D3DRESOURCETYPE WINAPI IDirect3DVolumeTexture9Impl_GetType(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DResource9Impl_GetType((LPDIRECT3DRESOURCE9) This); + return IWineD3DVolumeTexture_GetType(This->wineD3DVolumeTexture); } /* IDirect3DVolumeTexture9 IDirect3DBaseTexture9 Interface follow: */ DWORD WINAPI IDirect3DVolumeTexture9Impl_SetLOD(LPDIRECT3DVOLUMETEXTURE9 iface, DWORD LODNew) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetLOD((LPDIRECT3DBASETEXTURE9) This, LODNew); + return IWineD3DVolumeTexture_SetLOD(This->wineD3DVolumeTexture, LODNew); } DWORD WINAPI IDirect3DVolumeTexture9Impl_GetLOD(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetLOD((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DVolumeTexture_GetLOD(This->wineD3DVolumeTexture); } DWORD WINAPI IDirect3DVolumeTexture9Impl_GetLevelCount(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetLevelCount((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DVolumeTexture_GetLevelCount(This->wineD3DVolumeTexture); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_SetAutoGenFilterType(LPDIRECT3DVOLUMETEXTURE9 iface, D3DTEXTUREFILTERTYPE FilterType) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_SetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This, FilterType); + return IWineD3DVolumeTexture_SetAutoGenFilterType(This->wineD3DVolumeTexture, FilterType); } D3DTEXTUREFILTERTYPE WINAPI IDirect3DVolumeTexture9Impl_GetAutoGenFilterType(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - return IDirect3DBaseTexture9Impl_GetAutoGenFilterType((LPDIRECT3DBASETEXTURE9) This); + return IWineD3DVolumeTexture_GetAutoGenFilterType(This->wineD3DVolumeTexture); } void WINAPI IDirect3DVolumeTexture9Impl_GenerateMipSubLevels(LPDIRECT3DVOLUMETEXTURE9 iface) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - return ; + return IWineD3DVolumeTexture_GenerateMipSubLevels(This->wineD3DVolumeTexture); } /* IDirect3DVolumeTexture9 Interface follow: */ HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetLevelDesc(LPDIRECT3DVOLUMETEXTURE9 iface, UINT Level, D3DVOLUME_DESC* pDesc) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - if (Level < This->levels) { - TRACE("(%p) Level (%d)\n", This, Level); - return IDirect3DVolume9Impl_GetDesc((LPDIRECT3DVOLUME9) This->volumes[Level], pDesc); - } - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; + WINED3DVOLUME_DESC wined3ddesc; + UINT tmpInt = -1; + + /* As d3d8 and d3d9 structures differ, pass in ptrs to where data needs to go */ + wined3ddesc.Format = &pDesc->Format; + wined3ddesc.Type = &pDesc->Type; + wined3ddesc.Usage = &pDesc->Usage; + wined3ddesc.Pool = &pDesc->Pool; + wined3ddesc.Size = &tmpInt; + wined3ddesc.Width = &pDesc->Width; + wined3ddesc.Height = &pDesc->Height; + wined3ddesc.Depth = &pDesc->Depth; + + return IWineD3DVolumeTexture_GetLevelDesc(This->wineD3DVolumeTexture, Level, &wined3ddesc); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_GetVolumeLevel(LPDIRECT3DVOLUMETEXTURE9 iface, UINT Level, IDirect3DVolume9** ppVolumeLevel) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - if (Level < This->levels) { - *ppVolumeLevel = (LPDIRECT3DVOLUME9) This->volumes[Level]; - IDirect3DVolume9Impl_AddRef((LPDIRECT3DVOLUME9) *ppVolumeLevel); - TRACE("(%p) -> level(%d) returning volume@%p\n", This, Level, *ppVolumeLevel); - } else { - FIXME("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; + HRESULT hrc = D3D_OK; + + IWineD3DVolume *myVolume = NULL; + hrc = IWineD3DVolumeTexture_GetVolumeLevel(This->wineD3DVolumeTexture, Level, &myVolume); + if (hrc == D3D_OK && NULL != ppVolumeLevel) { + IWineD3DVolumeTexture_GetParent(myVolume, (IUnknown **)ppVolumeLevel); + IWineD3DVolumeTexture_Release(myVolume); } - return D3D_OK; - + return hrc; } + HRESULT WINAPI IDirect3DVolumeTexture9Impl_LockBox(LPDIRECT3DVOLUMETEXTURE9 iface, UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) { - HRESULT hr; IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - if (Level < This->levels) { - /** - * Not dirtified while Surfaces don't notify dirtification - * This->Dirty = TRUE; - */ - hr = IDirect3DVolume9Impl_LockBox((LPDIRECT3DVOLUME9) This->volumes[Level], pLockedVolume, pBox, Flags); - TRACE("(%p) Level (%d) success(%lu)\n", This, Level, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DVolumeTexture_LockBox(This->wineD3DVolumeTexture, Level, pLockedVolume, pBox, Flags); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_UnlockBox(LPDIRECT3DVOLUMETEXTURE9 iface, UINT Level) { - HRESULT hr; IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - if (Level < This->levels) { - hr = IDirect3DVolume9Impl_UnlockBox((LPDIRECT3DVOLUME9) This->volumes[Level]); - TRACE("(%p) -> level(%d) success(%lu)\n", This, Level, hr); - } else { - FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->levels); - return D3DERR_INVALIDCALL; - } - return hr; + return IWineD3DVolumeTexture_UnlockBox(This->wineD3DVolumeTexture, Level); } HRESULT WINAPI IDirect3DVolumeTexture9Impl_AddDirtyBox(LPDIRECT3DVOLUMETEXTURE9 iface, CONST D3DBOX* pDirtyBox) { IDirect3DVolumeTexture9Impl *This = (IDirect3DVolumeTexture9Impl *)iface; - FIXME("(%p) : stub\n", This); - This->Dirty = TRUE; - return D3D_OK; + return IWineD3DVolumeTexture_AddDirtyBox(This->wineD3DVolumeTexture, pDirtyBox); } @@ -235,9 +214,34 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateVolumeTexture(LPDIRECT3DDEVICE9 iface, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, - IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) { + IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) { + IDirect3DVolumeTexture9Impl *object; IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; - FIXME("(%p) : stub\n", This); - return D3D_OK; + HRESULT hrc = D3D_OK; + + /* Allocate the storage for the device */ + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture9Impl)); + if (NULL == object) { + FIXME("(%p) allocation of memory failed\n", This); + *ppVolumeTexture = NULL; + return D3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &Direct3DVolumeTexture9_Vtbl; + object->ref = 1; + hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels, Usage, + Format, Pool, &(object->wineD3DVolumeTexture), pSharedHandle, + (IUnknown *)object, D3D9CB_CreateVolume); + + + if (hrc != D3D_OK) { + /* free up object */ + FIXME("(%p) call to IWineD3DDevice_CreateVolumeTexture failed\n", This); + HeapFree(GetProcessHeap(), 0, object); + *ppVolumeTexture = NULL; + } else { + *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE9) object; + } + return hrc; } diff -urN wine-20050111/dlls/d3drm/version.rc wine-20050211/dlls/d3drm/version.rc --- wine-20050111/dlls/d3drm/version.rc 2004-11-23 14:59:36.000000000 +0100 +++ wine-20050211/dlls/d3drm/version.rc 2005-01-24 12:33:47.000000000 +0100 @@ -17,7 +17,7 @@ */ #define WINE_FILEDESCRIPTION_STR "Wine Direct3D Retained Mode Utility Functions" -#define WINE_FILENAME_STR "d3dim.dll" +#define WINE_FILENAME_STR "d3drm.dll" #define WINE_FILEVERSION 5,0,2134,14 #define WINE_FILEVERSION_STR "5.0.2134.14" #define WINE_PRODUCTVERSION 5,0,2134,14 diff -urN wine-20050111/dlls/d3dx8/d3dxbuffer.c wine-20050211/dlls/d3dx8/d3dxbuffer.c --- wine-20050111/dlls/d3dx8/d3dxbuffer.c 2004-12-23 19:33:45.000000000 +0100 +++ wine-20050211/dlls/d3dx8/d3dxbuffer.c 2005-01-21 11:18:16.000000000 +0100 @@ -51,14 +51,19 @@ ULONG WINAPI ID3DXBufferImpl_AddRef(LPD3DXBUFFER iface) { ID3DXBufferImpl *This = (ID3DXBufferImpl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + return ref; } ULONG WINAPI ID3DXBufferImpl_Release(LPD3DXBUFFER iface) { ID3DXBufferImpl *This = (ID3DXBufferImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->buffer); HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/d3dxof/d3dxof.c wine-20050211/dlls/d3dxof/d3dxof.c --- wine-20050111/dlls/d3dxof/d3dxof.c 2004-10-07 05:06:51.000000000 +0200 +++ wine-20050211/dlls/d3dxof/d3dxof.c 2005-01-20 11:53:56.000000000 +0100 @@ -80,23 +80,24 @@ static ULONG WINAPI IDirectXFileImpl_AddRef(IDirectXFile* iface) { IDirectXFileImpl *This = (IDirectXFileImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileImpl_Release(IDirectXFile* iface) { IDirectXFileImpl *This = (IDirectXFileImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFile methods ***/ @@ -190,23 +191,24 @@ static ULONG WINAPI IDirectXFileBinaryImpl_AddRef(IDirectXFileBinary* iface) { IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileBinaryImpl_Release(IDirectXFileBinary* iface) { IDirectXFileBinaryImpl *This = (IDirectXFileBinaryImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFileObject methods ***/ @@ -308,23 +310,24 @@ static ULONG WINAPI IDirectXFileDataImpl_AddRef(IDirectXFileData* iface) { IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileDataImpl_Release(IDirectXFileData* iface) { IDirectXFileDataImpl *This = (IDirectXFileDataImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFileObject methods ***/ @@ -456,23 +459,24 @@ static ULONG WINAPI IDirectXFileDataReferenceImpl_AddRef(IDirectXFileDataReference* iface) { IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileDataReferenceImpl_Release(IDirectXFileDataReference* iface) { IDirectXFileDataReferenceImpl *This = (IDirectXFileDataReferenceImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFileObject methods ***/ @@ -552,23 +556,24 @@ static ULONG WINAPI IDirectXFileEnumObjectImpl_AddRef(IDirectXFileEnumObject* iface) { IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileEnumObjectImpl_Release(IDirectXFileEnumObject* iface) { IDirectXFileEnumObjectImpl *This = (IDirectXFileEnumObjectImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFileEnumObject methods ***/ @@ -655,23 +660,24 @@ static ULONG WINAPI IDirectXFileObjectImpl_AddRef(IDirectXFileObject* iface) { IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileObjectImpl_Release(IDirectXFileObject* iface) { IDirectXFileObjectImpl *This = (IDirectXFileObjectImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } /*** IDirectXFileObject methods ***/ @@ -740,23 +746,24 @@ static ULONG WINAPI IDirectXFileSaveObjectImpl_AddRef(IDirectXFileSaveObject* iface) { IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): AddRef from %ld\n", iface, This, ref - 1); - This->ref++; - return S_OK; + return ref; } static ULONG WINAPI IDirectXFileSaveObjectImpl_Release(IDirectXFileSaveObject* iface) { IDirectXFileSaveObjectImpl *This = (IDirectXFileSaveObjectImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p/%p)\n", iface, This); + TRACE("(%p/%p): ReleaseRef to %ld\n", iface, This, ref); - if (!--This->ref) + if (!ref) HeapFree(GetProcessHeap(), 0, This); - return S_OK; + return ref; } static HRESULT WINAPI IDirectXFileSaveObjectImpl_SaveTemplates(IDirectXFileSaveObject* iface, DWORD cTemplates, const GUID** ppguidTemplates) diff -urN wine-20050111/dlls/d3dxof/d3dxof_private.h wine-20050211/dlls/d3dxof/d3dxof_private.h --- wine-20050111/dlls/d3dxof/d3dxof_private.h 2004-06-04 21:36:56.000000000 +0200 +++ wine-20050211/dlls/d3dxof/d3dxof_private.h 2005-01-20 11:53:56.000000000 +0100 @@ -35,37 +35,37 @@ typedef struct { IDirectXFile lpVtbl; - int ref; + ULONG ref; } IDirectXFileImpl; typedef struct { IDirectXFileBinary lpVtbl; - int ref; + ULONG ref; } IDirectXFileBinaryImpl; typedef struct { IDirectXFileData lpVtbl; - int ref; + ULONG ref; } IDirectXFileDataImpl; typedef struct { IDirectXFileDataReference lpVtbl; - int ref; + ULONG ref; } IDirectXFileDataReferenceImpl; typedef struct { IDirectXFileObject lpVtbl; - int ref; + ULONG ref; } IDirectXFileObjectImpl; typedef struct { IDirectXFileEnumObject lpVtbl; - int ref; + ULONG ref; } IDirectXFileEnumObjectImpl; typedef struct { IDirectXFileSaveObject lpVtbl; - int ref; + ULONG ref; } IDirectXFileSaveObjectImpl; HRESULT IDirectXFileImpl_Create(IUnknown *pUnkOuter, LPVOID *ppObj); diff -urN wine-20050111/dlls/dbghelp/elf_module.c wine-20050211/dlls/dbghelp/elf_module.c --- wine-20050111/dlls/dbghelp/elf_module.c 2004-11-22 19:30:10.000000000 +0100 +++ wine-20050211/dlls/dbghelp/elf_module.c 2005-01-31 17:24:57.000000000 +0100 @@ -410,6 +410,7 @@ 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 @@ -422,6 +423,7 @@ ste->ht_elt.name, addr, ste->symp->st_size, module->addr_sorttab[idx]->hash_elt.name, wine_dbgstr_longlong(xaddr), xsize); +#endif } } } diff -urN wine-20050111/dlls/dbghelp/msc.c wine-20050211/dlls/dbghelp/msc.c --- wine-20050111/dlls/dbghelp/msc.c 2004-12-23 19:33:44.000000000 +0100 +++ wine-20050211/dlls/dbghelp/msc.c 2005-02-09 23:21:58.000000000 +0100 @@ -1993,7 +1993,7 @@ ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) || ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL)) { - ERR("-Unable to peruse .PDB file %s\n", pdb_lookup->filename); + WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename); goto leave; } pdb_init(pdb_lookup, image); diff -urN wine-20050111/dlls/dbghelp/stabs.c wine-20050211/dlls/dbghelp/stabs.c --- wine-20050111/dlls/dbghelp/stabs.c 2004-12-23 19:33:44.000000000 +0100 +++ wine-20050211/dlls/dbghelp/stabs.c 2005-01-31 12:29:09.000000000 +0100 @@ -104,9 +104,18 @@ * A strcpy routine that stops when we hit the ':' character. * Faster than copying the whole thing, and then nuking the * ':'. + * Takes also care of (valid) a::b constructs */ - while (*source != '\0' && *source != ':' && sz-- > 0) - *dest++ = *source++; + while (*source != '\0') + { + if (source[0] != ':' && sz-- > 0) *dest++ = *source++; + else if (source[1] == ':' && (sz -= 2) > 0) + { + *dest++ = *source++; + *dest++ = *source++; + } + else break; + } *dest-- = '\0'; /* GCC seems to emit, in some cases, a .+ suffix. * This is used for static variable inside functions, so @@ -358,16 +367,29 @@ static int stabs_pts_read_id(struct ParseTypedefData* ptd) { const char* first = ptd->ptr; - unsigned int len; + unsigned int template = 0; + char ch; - PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL); - len = ptd->ptr - first; - PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx); - memcpy(ptd->buf + ptd->idx, first, len); - ptd->buf[ptd->idx + len] = '\0'; - ptd->idx += len + 1; - ptd->ptr++; /* ':' */ - return 0; + while ((ch = *ptd->ptr++) != '\0') + { + switch (ch) + { + case ':': + if (template == 0) + { + unsigned int len = ptd->ptr - first - 1; + PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx); + memcpy(ptd->buf + ptd->idx, first, len); + ptd->buf[ptd->idx + len] = '\0'; + ptd->idx += len + 1; + return 0; + } + break; + case '<': template++; break; + case '>': PTS_ABORTIF(ptd, template == 0); template--; break; + } + } + return -1; } static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v) @@ -604,7 +626,7 @@ DWORD size; symt_get_info(adt, TI_GET_SYMNAME, &name); - strcmp(tmp, "__inherited_class_"); + strcpy(tmp, "__inherited_class_"); WideCharToMultiByte(CP_ACP, 0, name, -1, tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), NULL, NULL); @@ -845,16 +867,28 @@ } else { + unsigned l1, l2; if (udt->symt.tag != SymTagUDT) { ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n", udt, symt_get_name(&udt->symt), udt->symt.tag); return -1; } - if (strcmp(udt->hash_elt.name, typename)) + /* FIXME: we currently don't correctly construct nested C++ + * classes names. Therefore, we could be here with either: + * - typename and udt->hash_elt.name being the same string + * (non embedded case) + * - typename being foo::bar while udt->hash_elt.name being + * just bar + * So, we twist the comparison to test both occurrences. When + * we have proper C++ types in this file, this twist has to be + * removed + */ + l1 = strlen(udt->hash_elt.name); + l2 = strlen(typename); + if (l1 > l2 || strcmp(udt->hash_elt.name, typename + l2 - l1)) ERR("Forward declaration name mismatch %s <> %s\n", udt->hash_elt.name, typename); - /* should check typename is the same too */ new_dt = &udt->symt; } PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1); @@ -971,7 +1005,7 @@ /* check for already existing definition */ - TRACE("%s\n", debugstr_a(ptr)); + TRACE("%s => %s\n", typename, debugstr_a(ptr)); ptd.module = module; ptd.idx = 0; #ifdef PTS_DEBUG diff -urN wine-20050111/dlls/dbghelp/symbol.c wine-20050211/dlls/dbghelp/symbol.c --- wine-20050111/dlls/dbghelp/symbol.c 2004-11-22 19:30:10.000000000 +0100 +++ wine-20050211/dlls/dbghelp/symbol.c 2005-01-31 12:35:00.000000000 +0100 @@ -888,7 +888,7 @@ sym = module->addr_sorttab[idx]; symt_fill_sym_info(module, &sym->symt, Symbol); - if (Displacement) *Displacement = Address - Symbol->Address; + *Displacement = Address - Symbol->Address; return TRUE; } @@ -1081,7 +1081,7 @@ if (!symt_fill_func_line_info(module, (struct symt_function*)module->addr_sorttab[idx], dwAddr, Line)) return FALSE; - if (pdwDisplacement) *pdwDisplacement = dwAddr - Line->Address; + *pdwDisplacement = dwAddr - Line->Address; return TRUE; } diff -urN wine-20050111/dlls/ddraw/ddraw/main.c wine-20050211/dlls/ddraw/ddraw/main.c --- wine-20050111/dlls/ddraw/ddraw/main.c 2005-01-09 18:35:44.000000000 +0100 +++ wine-20050211/dlls/ddraw/ddraw/main.c 2005-01-27 11:42:24.000000000 +0100 @@ -118,7 +118,7 @@ /* This is for the moment here... */ This->free_memory = free_memory; This->allocate_memory = allocate_memory; - This->total_vidmem = 16 * 1024 * 1024; + This->total_vidmem = 64 * 1024 * 1024; This->available_vidmem = This->total_vidmem; return DD_OK; diff -urN wine-20050111/dlls/devenum/createdevenum.c wine-20050211/dlls/devenum/createdevenum.c --- wine-20050111/dlls/devenum/createdevenum.c 2004-12-13 22:19:02.000000000 +0100 +++ wine-20050211/dlls/devenum/createdevenum.c 2005-01-25 11:56:39.000000000 +0100 @@ -230,7 +230,6 @@ rf2.dwMerit = MERIT_PREFERRED; rf2.u.s1.cPins2 = 1; rf2.u.s1.rgPins2 = &rfp2; - rfp2.dwFlags = REG_PINFLAG_B_RENDERER; rfp2.cInstances = 1; rfp2.nMediums = 0; rfp2.lpMedium = NULL; @@ -261,6 +260,7 @@ if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; + rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW)) @@ -324,6 +324,7 @@ if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; + rfp2.dwFlags = REG_PINFLAG_B_OUTPUT; for (i = 0; i < numDevs; i++) { if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW)) @@ -368,6 +369,7 @@ if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; + rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW)) diff -urN wine-20050111/dlls/dinput/device.c wine-20050211/dlls/dinput/device.c --- wine-20050111/dlls/dinput/device.c 2004-09-17 20:10:41.000000000 +0200 +++ wine-20050211/dlls/dinput/device.c 2005-02-08 13:11:12.000000000 +0100 @@ -316,7 +316,7 @@ * instance id. */ ((asked_format->rgodf[j].dwType & 0x00FFFF00) == DIDFT_ANYINSTANCE) || - (DIDFT_GETINSTANCE(wine_format->rgodf[i].dwType) == DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType)))) { + (wine_format->rgodf[i].dwType & asked_format->rgodf[j].dwType))) { done[j] = 1; diff -urN wine-20050111/dlls/dinput/dinput_main.c wine-20050211/dlls/dinput/dinput_main.c --- wine-20050111/dlls/dinput/dinput_main.c 2004-12-07 15:19:29.000000000 +0100 +++ wine-20050211/dlls/dinput/dinput_main.c 2005-01-24 12:29:44.000000000 +0100 @@ -195,7 +195,7 @@ return 0; } -static char *_dump_DIDEVTYPE_value(DWORD dwDevType) { +static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) { switch (dwDevType) { case 0: return "All devices"; case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE"; diff -urN wine-20050111/dlls/dinput/joystick_linux.c wine-20050211/dlls/dinput/joystick_linux.c --- wine-20050111/dlls/dinput/joystick_linux.c 2004-12-23 19:33:44.000000000 +0100 +++ wine-20050211/dlls/dinput/joystick_linux.c 2005-01-25 21:05:12.000000000 +0100 @@ -304,7 +304,7 @@ int tokens = 0; int axis = 0; int pov = 0; - char *delim = ","; + const char *delim = ","; char * ptr; TRACE("\"%s\" = \"%s\"\n", device->name, buffer); @@ -1060,18 +1060,14 @@ *entries = 0; nqtail = This->queue_tail; while (len) { - DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head) - nqtail; - if (span > len) - span = len; - /* Copy the buffered data into the application queue */ - memcpy(dod + *entries, This->data_queue + nqtail, span * dodsize); + memcpy((char *)dod + *entries * dodsize, This->data_queue + nqtail, dodsize); /* Advance position */ - nqtail += span; + nqtail++; if (nqtail >= This->queue_len) nqtail -= This->queue_len; - *entries += span; - len -= span; + (*entries)++; + len--; } } diff -urN wine-20050111/dlls/dinput/mouse.c wine-20050211/dlls/dinput/mouse.c --- wine-20050111/dlls/dinput/mouse.c 2005-01-04 21:39:55.000000000 +0100 +++ wine-20050211/dlls/dinput/mouse.c 2005-01-25 21:05:12.000000000 +0100 @@ -766,17 +766,14 @@ *entries = 0; nqtail = This->queue_tail; while (len) { - DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head) - nqtail; - if (span > len) - span = len; - /* Copy the buffered data into the application queue */ - memcpy(dod + *entries, This->data_queue + nqtail, span * dodsize); + memcpy((char *)dod + *entries * dodsize, This->data_queue + nqtail, dodsize); /* Advance position */ - nqtail += span; - if (nqtail >= This->queue_len) nqtail -= This->queue_len; - *entries += span; - len -= span; + nqtail++; + if (nqtail >= This->queue_len) + nqtail -= This->queue_len; + (*entries)++; + len--; } } if (!(flags & DIGDD_PEEK)) diff -urN wine-20050111/dlls/dmband/band.c wine-20050211/dlls/dmband/band.c --- wine-20050111/dlls/dmband/band.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dmband/band.c 2005-01-31 21:40:44.000000000 +0100 @@ -56,17 +56,27 @@ ULONG WINAPI IDirectMusicBandImpl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicBandImpl, UnknownVtbl, iface); - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + DMBAND_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicBandImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicBandImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMBAND_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmband/bandtrack.c wine-20050211/dlls/dmband/bandtrack.c --- wine-20050111/dlls/dmband/bandtrack.c 2004-12-22 16:13:21.000000000 +0100 +++ wine-20050211/dlls/dmband/bandtrack.c 2005-01-31 21:40:44.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicBandTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface); - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + + DMBAND_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicBandTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMBAND_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmband/dmband_main.c wine-20050211/dlls/dmband/dmband_main.c --- wine-20050111/dlls/dmband/dmband_main.c 2004-09-06 22:34:30.000000000 +0200 +++ wine-20050211/dlls/dmband/dmband_main.c 2005-01-31 21:40:44.000000000 +0100 @@ -21,10 +21,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmband); +LONG DMBAND_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** @@ -32,31 +32,39 @@ */ static HRESULT WINAPI BandCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n",This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI BandCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMBAND_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI BandCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMBAND_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI BandCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicBandImpl (riid, ppobj, pOuter); } static HRESULT WINAPI BandCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMBAND_LockModule(); + else + DMBAND_UnlockModule(); + return S_OK; } @@ -68,7 +76,7 @@ BandCF_LockServer }; -static IClassFactoryImpl Band_CF = {&BandCF_Vtbl, 1 }; +static IClassFactoryImpl Band_CF = {&BandCF_Vtbl}; /****************************************************************** @@ -76,32 +84,39 @@ */ static HRESULT WINAPI BandTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI BandTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMBAND_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI BandTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMBAND_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI BandTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicBandTrack (riid, ppobj, pOuter); } static HRESULT WINAPI BandTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMBAND_LockModule(); + else + DMBAND_UnlockModule(); + return S_OK; } @@ -113,7 +128,7 @@ BandTrackCF_LockServer }; -static IClassFactoryImpl BandTrack_CF = {&BandTrackCF_Vtbl, 1 }; +static IClassFactoryImpl BandTrack_CF = {&BandTrackCF_Vtbl}; /****************************************************************** * DllMain @@ -138,8 +153,7 @@ * */ HRESULT WINAPI DMBAND_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMBAND_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmband/dmband_private.h wine-20050211/dlls/dmband/dmband_private.h --- wine-20050111/dlls/dmband/dmband_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dmband/dmband_private.h 2005-01-31 21:40:44.000000000 +0100 @@ -192,6 +192,12 @@ extern HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty); extern HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize); +/********************************************************************** + * Dll lifetime tracking declaration for dmband.dll + */ +extern LONG DMBAND_refCount; +static inline void DMBAND_LockModule() { InterlockedIncrement( &DMBAND_refCount ); } +static inline void DMBAND_UnlockModule() { InterlockedDecrement( &DMBAND_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dmcompos/chordmap.c wine-20050211/dlls/dmcompos/chordmap.c --- wine-20050111/dlls/dmcompos/chordmap.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dmcompos/chordmap.c 2005-01-12 20:26:42.000000000 +0100 @@ -54,17 +54,20 @@ ULONG WINAPI IDirectMusicChordMapImpl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordMapImpl, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); DMCOMPOS_LockModule(); - return ++(This->ref); + return ref; } ULONG WINAPI IDirectMusicChordMapImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordMapImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/dmcompos/chordmaptrack.c wine-20050211/dlls/dmcompos/chordmaptrack.c --- wine-20050111/dlls/dmcompos/chordmaptrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmcompos/chordmaptrack.c 2005-01-12 20:26:42.000000000 +0100 @@ -51,17 +51,20 @@ ULONG WINAPI IDirectMusicChordMapTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordMapTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); DMCOMPOS_LockModule(); - return ++(This->ref); + return ref; } ULONG WINAPI IDirectMusicChordMapTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordMapTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/dmcompos/composer.c wine-20050211/dlls/dmcompos/composer.c --- wine-20050111/dlls/dmcompos/composer.c 2004-12-09 14:46:47.000000000 +0100 +++ wine-20050211/dlls/dmcompos/composer.c 2005-01-12 20:26:42.000000000 +0100 @@ -38,17 +38,20 @@ ULONG WINAPI IDirectMusicComposerImpl_AddRef (LPDIRECTMUSICCOMPOSER iface) { IDirectMusicComposerImpl *This = (IDirectMusicComposerImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); DMCOMPOS_LockModule(); - return ++(This->ref); + return ref; } ULONG WINAPI IDirectMusicComposerImpl_Release (LPDIRECTMUSICCOMPOSER iface) { IDirectMusicComposerImpl *This = (IDirectMusicComposerImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/dmcompos/signposttrack.c wine-20050211/dlls/dmcompos/signposttrack.c --- wine-20050111/dlls/dmcompos/signposttrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmcompos/signposttrack.c 2005-01-12 20:26:42.000000000 +0100 @@ -51,17 +51,20 @@ ULONG WINAPI IDirectMusicSignPostTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicSignPostTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); DMCOMPOS_LockModule(); - return ++(This->ref); + return ref; } ULONG WINAPI IDirectMusicSignPostTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicSignPostTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); diff -urN wine-20050111/dlls/dmime/audiopath.c wine-20050211/dlls/dmime/audiopath.c --- wine-20050111/dlls/dmime/audiopath.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/audiopath.c 2005-02-02 10:31:07.000000000 +0100 @@ -58,6 +58,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -65,12 +67,16 @@ ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { if (This->pDSBuffer) { IDirectSoundBuffer8_Release(This->pDSBuffer); } HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/dmime_main.c wine-20050211/dlls/dmime/dmime_main.c --- wine-20050111/dlls/dmime/dmime_main.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/dmime_main.c 2005-02-02 10:31:07.000000000 +0100 @@ -23,41 +23,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmime); WINE_DECLARE_DEBUG_CHANNEL(dmfile); +LONG DMIME_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusicPerformance ClassFactory */ static HRESULT WINAPI PerformanceCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI PerformanceCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI PerformanceCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI PerformanceCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicPerformanceImpl (riid, ppobj, pOuter); } static HRESULT WINAPI PerformanceCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -69,37 +77,45 @@ PerformanceCF_LockServer }; -static IClassFactoryImpl Performance_CF = {&PerformanceCF_Vtbl, 1 }; +static IClassFactoryImpl Performance_CF = {&PerformanceCF_Vtbl}; /****************************************************************** * DirectMusicSegment ClassFactory */ static HRESULT WINAPI SegmentCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SegmentCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SegmentCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SegmentCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicSegmentImpl (riid, ppobj, pOuter); } static HRESULT WINAPI SegmentCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -111,37 +127,45 @@ SegmentCF_LockServer }; -static IClassFactoryImpl Segment_CF = {&SegmentCF_Vtbl, 1 }; +static IClassFactoryImpl Segment_CF = {&SegmentCF_Vtbl}; /****************************************************************** * DirectMusicSegmentState ClassFactory */ static HRESULT WINAPI SegmentStateCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SegmentStateCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based objects */ } static ULONG WINAPI SegmentStateCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SegmentStateCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicSegmentStateImpl (riid, ppobj, pOuter); } static HRESULT WINAPI SegmentStateCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -153,37 +177,45 @@ SegmentStateCF_LockServer }; -static IClassFactoryImpl SegmentState_CF = {&SegmentStateCF_Vtbl, 1 }; +static IClassFactoryImpl SegmentState_CF = {&SegmentStateCF_Vtbl}; /****************************************************************** * DirectMusicGraph ClassFactory */ static HRESULT WINAPI GraphCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI GraphCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI GraphCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI GraphCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicGraphImpl (riid, ppobj, pOuter); } static HRESULT WINAPI GraphCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -195,37 +227,45 @@ GraphCF_LockServer }; -static IClassFactoryImpl Graph_CF = {&GraphCF_Vtbl, 1 }; +static IClassFactoryImpl Graph_CF = {&GraphCF_Vtbl}; /****************************************************************** * DirectMusicTempoTrack ClassFactory */ static HRESULT WINAPI TempoTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI TempoTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI TempoTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI TempoTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicTempoTrack (riid, ppobj, pOuter); } static HRESULT WINAPI TempoTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -237,37 +277,45 @@ TempoTrackCF_LockServer }; -static IClassFactoryImpl TempoTrack_CF = {&TempoTrackCF_Vtbl, 1 }; +static IClassFactoryImpl TempoTrack_CF = {&TempoTrackCF_Vtbl}; /****************************************************************** * DirectMusicSeqTrack ClassFactory */ static HRESULT WINAPI SeqTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SeqTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SeqTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SeqTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicSeqTrack (riid, ppobj, pOuter); } static HRESULT WINAPI SeqTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -279,37 +327,44 @@ SeqTrackCF_LockServer }; -static IClassFactoryImpl SeqTrack_CF = {&SeqTrackCF_Vtbl, 1 }; +static IClassFactoryImpl SeqTrack_CF = {&SeqTrackCF_Vtbl}; /****************************************************************** * DirectMusicSysExTrack ClassFactory */ static HRESULT WINAPI SysExTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SysExTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SysExTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SysExTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicSysExTrack (riid, ppobj, pOuter); } static HRESULT WINAPI SysExTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -321,37 +376,45 @@ SysExTrackCF_LockServer }; -static IClassFactoryImpl SysExTrack_CF = {&SysExTrackCF_Vtbl, 1 }; +static IClassFactoryImpl SysExTrack_CF = {&SysExTrackCF_Vtbl}; /****************************************************************** * DirectMusicTimeSigTrack ClassFactory */ static HRESULT WINAPI TimeSigTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI TimeSigTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI TimeSigTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI TimeSigTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicTimeSigTrack (riid, ppobj, pOuter); } static HRESULT WINAPI TimeSigTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -363,37 +426,45 @@ TimeSigTrackCF_LockServer }; -static IClassFactoryImpl TimeSigTrack_CF = {&TimeSigTrackCF_Vtbl, 1 }; +static IClassFactoryImpl TimeSigTrack_CF = {&TimeSigTrackCF_Vtbl}; /****************************************************************** * DirectMusicParamControlTrack ClassFactory */ static HRESULT WINAPI ParamControlTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ParamControlTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ParamControlTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ParamControlTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicParamControlTrack (riid, ppobj, pOuter); } static HRESULT WINAPI ParamControlTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -405,37 +476,45 @@ ParamControlTrackCF_LockServer }; -static IClassFactoryImpl ParamControlTrack_CF = {&ParamControlTrackCF_Vtbl, 1 }; +static IClassFactoryImpl ParamControlTrack_CF = {&ParamControlTrackCF_Vtbl}; /****************************************************************** * DirectMusicMarkerTrack ClassFactory */ static HRESULT WINAPI MarkerTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI MarkerTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI MarkerTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI MarkerTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicMarkerTrack (riid, ppobj, pOuter); } static HRESULT WINAPI MarkerTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -447,37 +526,45 @@ MarkerTrackCF_LockServer }; -static IClassFactoryImpl MarkerTrack_CF = {&MarkerTrackCF_Vtbl, 1 }; +static IClassFactoryImpl MarkerTrack_CF = {&MarkerTrackCF_Vtbl}; /****************************************************************** * DirectMusicLyricsTrack ClassFactory */ static HRESULT WINAPI LyricsTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI LyricsTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI LyricsTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI LyricsTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicLyricsTrack (riid, ppobj, pOuter); } static HRESULT WINAPI LyricsTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -489,38 +576,46 @@ LyricsTrackCF_LockServer }; -static IClassFactoryImpl LyricsTrack_CF = {&LyricsTrackCF_Vtbl, 1 }; +static IClassFactoryImpl LyricsTrack_CF = {&LyricsTrackCF_Vtbl}; /****************************************************************** * DirectMusicSegTriggerTrack ClassFactory */ static HRESULT WINAPI SegTriggerTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SegTriggerTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SegTriggerTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SegTriggerTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicSegTriggerTrack (riid, ppobj, pOuter); } static HRESULT WINAPI SegTriggerTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -532,37 +627,45 @@ SegTriggerTrackCF_LockServer }; -static IClassFactoryImpl SegTriggerTrack_CF = {&SegTriggerTrackCF_Vtbl, 1 }; +static IClassFactoryImpl SegTriggerTrack_CF = {&SegTriggerTrackCF_Vtbl}; /****************************************************************** * DirectMusicAudioPath ClassFactory */ static HRESULT WINAPI AudioPathCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI AudioPathCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI AudioPathCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI AudioPathCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicAudioPathImpl (riid, ppobj, pOuter); } static HRESULT WINAPI AudioPathCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -574,37 +677,45 @@ AudioPathCF_LockServer }; -static IClassFactoryImpl AudioPath_CF = {&AudioPathCF_Vtbl, 1 }; +static IClassFactoryImpl AudioPath_CF = {&AudioPathCF_Vtbl}; /****************************************************************** * DirectMusicWaveTrack ClassFactory */ static HRESULT WINAPI WaveTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI WaveTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DMIME_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI WaveTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DMIME_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI WaveTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicWaveTrack (riid, ppobj, pOuter); } static HRESULT WINAPI WaveTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMIME_LockModule(); + else + DMIME_UnlockModule(); + return S_OK; } @@ -616,7 +727,7 @@ WaveTrackCF_LockServer }; -static IClassFactoryImpl WaveTrack_CF = {&WaveTrackCF_Vtbl, 1 }; +static IClassFactoryImpl WaveTrack_CF = {&WaveTrackCF_Vtbl}; /****************************************************************** * DllMain @@ -642,8 +753,7 @@ * */ HRESULT WINAPI DMIME_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMIME_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmime/dmime_private.h wine-20050211/dlls/dmime/dmime_private.h --- wine-20050111/dlls/dmime/dmime_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dmime/dmime_private.h 2005-02-02 10:31:07.000000000 +0100 @@ -949,6 +949,12 @@ extern HRESULT WINAPI IDirectMusicWaveTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty); extern HRESULT WINAPI IDirectMusicWaveTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize); +/********************************************************************** + * Dll lifetime tracking declaration for dmime.dll + */ +extern LONG DMIME_refCount; +static inline void DMIME_LockModule() { InterlockedIncrement( &DMIME_refCount ); } +static inline void DMIME_UnlockModule() { InterlockedDecrement( &DMIME_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dmime/graph.c wine-20050211/dlls/dmime/graph.c --- wine-20050111/dlls/dmime/graph.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/graph.c 2005-02-02 10:31:07.000000000 +0100 @@ -58,6 +58,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -65,9 +67,13 @@ ICOM_THIS_MULTI(IDirectMusicGraphImpl, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/lyricstrack.c wine-20050211/dlls/dmime/lyricstrack.c --- wine-20050111/dlls/dmime/lyricstrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/lyricstrack.c 2005-02-02 10:31:07.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicLyricsTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/markertrack.c wine-20050211/dlls/dmime/markertrack.c --- wine-20050111/dlls/dmime/markertrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/markertrack.c 2005-02-02 10:31:07.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicMarkerTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/paramcontroltrack.c wine-20050211/dlls/dmime/paramcontroltrack.c --- wine-20050111/dlls/dmime/paramcontroltrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/paramcontroltrack.c 2005-02-02 10:31:07.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicParamControlTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/patterntrack.c wine-20050211/dlls/dmime/patterntrack.c --- wine-20050111/dlls/dmime/patterntrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/patterntrack.c 2005-02-02 10:31:07.000000000 +0100 @@ -43,6 +43,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -50,9 +52,13 @@ IDirectMusicPatternTrackImpl *This = (IDirectMusicPatternTrackImpl *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/performance.c wine-20050211/dlls/dmime/performance.c --- wine-20050111/dlls/dmime/performance.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/performance.c 2005-02-02 10:31:07.000000000 +0100 @@ -186,6 +186,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -193,10 +195,14 @@ IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { DeleteCriticalSection(&This->safe); HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/segment.c wine-20050211/dlls/dmime/segment.c --- wine-20050111/dlls/dmime/segment.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/segment.c 2005-02-02 10:31:07.000000000 +0100 @@ -61,6 +61,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -68,9 +70,13 @@ ICOM_THIS_MULTI(IDirectMusicSegment8Impl, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/segmentstate.c wine-20050211/dlls/dmime/segmentstate.c --- wine-20050111/dlls/dmime/segmentstate.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/segmentstate.c 2005-02-02 10:31:07.000000000 +0100 @@ -43,6 +43,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -50,9 +52,13 @@ IDirectMusicSegmentState8Impl *This = (IDirectMusicSegmentState8Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/segtriggertrack.c wine-20050211/dlls/dmime/segtriggertrack.c --- wine-20050111/dlls/dmime/segtriggertrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/segtriggertrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -56,6 +56,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -63,9 +65,13 @@ ICOM_THIS_MULTI(IDirectMusicSegTriggerTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/seqtrack.c wine-20050211/dlls/dmime/seqtrack.c --- wine-20050111/dlls/dmime/seqtrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/seqtrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicSeqTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/sysextrack.c wine-20050211/dlls/dmime/sysextrack.c --- wine-20050111/dlls/dmime/sysextrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/sysextrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicSysExTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/tempotrack.c wine-20050211/dlls/dmime/tempotrack.c --- wine-20050111/dlls/dmime/tempotrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/tempotrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -56,6 +56,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -63,9 +65,13 @@ ICOM_THIS_MULTI(IDirectMusicTempoTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/timesigtrack.c wine-20050211/dlls/dmime/timesigtrack.c --- wine-20050111/dlls/dmime/timesigtrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/timesigtrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p): AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicTimeSigTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/tool.c wine-20050211/dlls/dmime/tool.c --- wine-20050111/dlls/dmime/tool.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/tool.c 2005-02-02 10:31:06.000000000 +0100 @@ -42,6 +42,8 @@ TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -49,9 +51,13 @@ IDirectMusicTool8Impl *This = (IDirectMusicTool8Impl *)iface; ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmime/wavetrack.c wine-20050211/dlls/dmime/wavetrack.c --- wine-20050111/dlls/dmime/wavetrack.c 2005-01-11 17:02:21.000000000 +0100 +++ wine-20050211/dlls/dmime/wavetrack.c 2005-02-02 10:31:06.000000000 +0100 @@ -55,6 +55,8 @@ TRACE("(%p) : AddRef from %ld\n", This, ref - 1); + DMIME_LockModule(); + return ref; } @@ -62,9 +64,13 @@ ICOM_THIS_MULTI(IDirectMusicWaveTrack, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) : ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMIME_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmscript/dmscript_main.c wine-20050211/dlls/dmscript/dmscript_main.c --- wine-20050111/dlls/dmscript/dmscript_main.c 2004-09-06 22:34:30.000000000 +0200 +++ wine-20050211/dlls/dmscript/dmscript_main.c 2005-02-02 10:31:28.000000000 +0100 @@ -21,43 +21,51 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmscript); +LONG DMSCRIPT_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusicScriptAutoImplSegment ClassFactory */ static HRESULT WINAPI ScriptAutoImplSegmentCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplSegmentCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptAutoImplSegmentCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplSegmentCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplSegmentCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -69,37 +77,44 @@ ScriptAutoImplSegmentCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplSegment_CF = {&ScriptAutoImplSegmentCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplSegment_CF = {&ScriptAutoImplSegmentCF_Vtbl}; /****************************************************************** * DirectMusicScriptTrack ClassFactory */ static HRESULT WINAPI ScriptTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicScriptTrack (riid, ppobj, pOuter); } static HRESULT WINAPI ScriptTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -111,39 +126,47 @@ ScriptTrackCF_LockServer }; -static IClassFactoryImpl ScriptTrack_CF = {&ScriptTrackCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptTrack_CF = {&ScriptTrackCF_Vtbl}; /****************************************************************** * DirectMusicAudioVBScript ClassFactory */ static HRESULT WINAPI AudioVBScriptCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI AudioVBScriptCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI AudioVBScriptCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI AudioVBScriptCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI AudioVBScriptCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -155,37 +178,45 @@ AudioVBScriptCF_LockServer }; -static IClassFactoryImpl AudioVBScript_CF = {&AudioVBScriptCF_Vtbl, 1 }; +static IClassFactoryImpl AudioVBScript_CF = {&AudioVBScriptCF_Vtbl}; /****************************************************************** * DirectMusicScript ClassFactory */ static HRESULT WINAPI ScriptCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicScriptImpl (riid, ppobj, pOuter); } static HRESULT WINAPI ScriptCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -197,39 +228,47 @@ ScriptCF_LockServer }; -static IClassFactoryImpl Script_CF = {&ScriptCF_Vtbl, 1 }; +static IClassFactoryImpl Script_CF = {&ScriptCF_Vtbl}; /****************************************************************** * DirectMusicScriptAutoImplPerformance ClassFactory */ static HRESULT WINAPI ScriptAutoImplPerformanceCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplPerformanceCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptAutoImplPerformanceCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplPerformanceCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplPerformanceCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -241,39 +280,47 @@ ScriptAutoImplPerformanceCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplPerformance_CF = {&ScriptAutoImplPerformanceCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplPerformance_CF = {&ScriptAutoImplPerformanceCF_Vtbl}; /****************************************************************** * DirectMusicScriptSourceCodeLoader ClassFactory */ static HRESULT WINAPI ScriptSourceCodeLoaderCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptSourceCodeLoaderCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptSourceCodeLoaderCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptSourceCodeLoaderCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptSourceCodeLoaderCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -285,39 +332,47 @@ ScriptSourceCodeLoaderCF_LockServer }; -static IClassFactoryImpl ScriptSourceCodeLoader_CF = {&ScriptSourceCodeLoaderCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptSourceCodeLoader_CF = {&ScriptSourceCodeLoaderCF_Vtbl}; /****************************************************************** * DirectMusicScriptAutoImplSegmentState ClassFactory */ static HRESULT WINAPI ScriptAutoImplSegmentStateCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplSegmentStateCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptAutoImplSegmentStateCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplSegmentStateCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplSegmentStateCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -329,39 +384,47 @@ ScriptAutoImplSegmentStateCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplSegmentState_CF = {&ScriptAutoImplSegmentStateCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplSegmentState_CF = {&ScriptAutoImplSegmentStateCF_Vtbl}; /****************************************************************** * DirectMusicScriptAutoImplAudioPathConfig ClassFactory */ static HRESULT WINAPI ScriptAutoImplAudioPathConfigCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplAudioPathConfigCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptAutoImplAudioPathConfigCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplAudioPathConfigCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplAudioPathConfigCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -373,39 +436,47 @@ ScriptAutoImplAudioPathConfigCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplAudioPathConfig_CF = {&ScriptAutoImplAudioPathConfigCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplAudioPathConfig_CF = {&ScriptAutoImplAudioPathConfigCF_Vtbl}; /****************************************************************** * DirectMusicScriptAutoImplAudioPath ClassFactory */ static HRESULT WINAPI ScriptAutoImplAudioPathCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplAudioPathCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ScriptAutoImplAudioPathCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplAudioPathCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplAudioPathCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -417,39 +488,47 @@ ScriptAutoImplAudioPathCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplAudioPath_CF = {&ScriptAutoImplAudioPathCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplAudioPath_CF = {&ScriptAutoImplAudioPathCF_Vtbl}; /****************************************************************** * DirectMusicScriptAutoImplSong ClassFactory */ static HRESULT WINAPI ScriptAutoImplSongCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ScriptAutoImplSongCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSCRIPT_LockModule(); + + return 2; /* non-heap based */ } static ULONG WINAPI ScriptAutoImplSongCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSCRIPT_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ScriptAutoImplSongCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); - /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static HRESULT WINAPI ScriptAutoImplSongCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSCRIPT_LockModule(); + else + DMSCRIPT_UnlockModule(); + return S_OK; } @@ -461,7 +540,7 @@ ScriptAutoImplSongCF_LockServer }; -static IClassFactoryImpl ScriptAutoImplSong_CF = {&ScriptAutoImplSongCF_Vtbl, 1 }; +static IClassFactoryImpl ScriptAutoImplSong_CF = {&ScriptAutoImplSongCF_Vtbl}; /****************************************************************** * DllMain @@ -486,8 +565,7 @@ * */ HRESULT WINAPI DMSCRIPT_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMSCRIPT_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmscript/dmscript_private.h wine-20050211/dlls/dmscript/dmscript_private.h --- wine-20050111/dlls/dmscript/dmscript_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dmscript/dmscript_private.h 2005-02-02 10:31:28.000000000 +0100 @@ -170,6 +170,12 @@ extern HRESULT WINAPI IDirectMusicScriptTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty); extern HRESULT WINAPI IDirectMusicScriptTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize); +/********************************************************************** + * Dll lifetime tracking declaration for dmscript.dll + */ +extern LONG DMSCRIPT_refCount; +static inline void DMSCRIPT_LockModule() { InterlockedIncrement( &DMSCRIPT_refCount ); } +static inline void DMSCRIPT_UnlockModule() { InterlockedDecrement( &DMSCRIPT_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dmscript/script.c wine-20050211/dlls/dmscript/script.c --- wine-20050111/dlls/dmscript/script.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dmscript/script.c 2005-02-02 10:31:28.000000000 +0100 @@ -63,14 +63,21 @@ ULONG WINAPI IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicScriptImpl, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSCRIPT_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicScriptImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicScriptImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This->pHeader); HeapFree(GetProcessHeap(), 0, This->pVersion); @@ -78,6 +85,9 @@ HeapFree(GetProcessHeap(), 0, This->pwzSource); HeapFree(GetProcessHeap(), 0, This); } + + DMSCRIPT_UnlockModule(); + return ref; } @@ -679,7 +689,7 @@ obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicScriptImpl)); if (NULL == obj) { - *ppobj = (LPVOID) NULL; + *ppobj = NULL; return E_OUTOFMEMORY; } obj->UnknownVtbl = &DirectMusicScript_Unknown_Vtbl; diff -urN wine-20050111/dlls/dmscript/scripttrack.c wine-20050211/dlls/dmscript/scripttrack.c --- wine-20050111/dlls/dmscript/scripttrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmscript/scripttrack.c 2005-02-02 10:31:28.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicScriptTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicScriptTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSCRIPT_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicScriptTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicScriptTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSCRIPT_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/auditiontrack.c wine-20050211/dlls/dmstyle/auditiontrack.c --- wine-20050111/dlls/dmstyle/auditiontrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmstyle/auditiontrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicAuditionTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicAuditionTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicAuditionTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicAuditionTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/chordtrack.c wine-20050211/dlls/dmstyle/chordtrack.c --- wine-20050111/dlls/dmstyle/chordtrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmstyle/chordtrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -52,17 +52,27 @@ ULONG WINAPI IDirectMusicChordTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicChordTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicChordTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/commandtrack.c wine-20050211/dlls/dmstyle/commandtrack.c --- wine-20050111/dlls/dmstyle/commandtrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmstyle/commandtrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicCommandTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicCommandTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicCommandTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicCommandTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/dmstyle_main.c wine-20050211/dlls/dmstyle/dmstyle_main.c --- wine-20050111/dlls/dmstyle/dmstyle_main.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/dmstyle/dmstyle_main.c 2005-01-24 20:33:23.000000000 +0100 @@ -21,43 +21,52 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmstyle); +LONG DMSTYLE_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusicSection ClassFactory */ static HRESULT WINAPI SectionCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SectionCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SectionCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SectionCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + /* nothing here yet */ - WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); + WARN("(%s, %p): not found\n", debugstr_dmguid(riid), ppobj); + return E_NOINTERFACE; } static HRESULT WINAPI SectionCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -69,37 +78,45 @@ SectionCF_LockServer }; -static IClassFactoryImpl Section_CF = {&SectionCF_Vtbl, 1 }; +static IClassFactoryImpl Section_CF = {&SectionCF_Vtbl}; /****************************************************************** * DirectMusicStyle ClassFactory */ static HRESULT WINAPI StyleCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI StyleCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI StyleCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI StyleCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicStyleImpl (riid, ppobj, pOuter); } static HRESULT WINAPI StyleCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -111,37 +128,45 @@ StyleCF_LockServer }; -static IClassFactoryImpl Style_CF = {&StyleCF_Vtbl, 1 }; +static IClassFactoryImpl Style_CF = {&StyleCF_Vtbl}; /****************************************************************** * DirectMusicChordTrack ClassFactory */ static HRESULT WINAPI ChordTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI ChordTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI ChordTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI ChordTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicChordTrack (riid, ppobj, pOuter); } static HRESULT WINAPI ChordTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -153,37 +178,45 @@ ChordTrackCF_LockServer }; -static IClassFactoryImpl ChordTrack_CF = {&ChordTrackCF_Vtbl, 1 }; +static IClassFactoryImpl ChordTrack_CF = {&ChordTrackCF_Vtbl}; /****************************************************************** * DirectMusicCommandTrack ClassFactory */ static HRESULT WINAPI CommandTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI CommandTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI CommandTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI CommandTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicCommandTrack (riid, ppobj, pOuter); } static HRESULT WINAPI CommandTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -195,37 +228,45 @@ CommandTrackCF_LockServer }; -static IClassFactoryImpl CommandTrack_CF = {&CommandTrackCF_Vtbl, 1 }; +static IClassFactoryImpl CommandTrack_CF = {&CommandTrackCF_Vtbl}; /****************************************************************** * DirectMusicStyleTrack ClassFactory */ static HRESULT WINAPI StyleTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI StyleTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI StyleTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI StyleTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicStyleTrack (riid, ppobj, pOuter); } static HRESULT WINAPI StyleTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -237,37 +278,45 @@ StyleTrackCF_LockServer }; -static IClassFactoryImpl StyleTrack_CF = {&StyleTrackCF_Vtbl, 1 }; +static IClassFactoryImpl StyleTrack_CF = {&StyleTrackCF_Vtbl}; /****************************************************************** * DirectMusicMotifTrack ClassFactory */ static HRESULT WINAPI MotifTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI MotifTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI MotifTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI MotifTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicMotifTrack (riid, ppobj, pOuter); } static HRESULT WINAPI MotifTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -279,37 +328,45 @@ MotifTrackCF_LockServer }; -static IClassFactoryImpl MotifTrack_CF = {&MotifTrackCF_Vtbl, 1 }; +static IClassFactoryImpl MotifTrack_CF = {&MotifTrackCF_Vtbl}; /****************************************************************** * DirectMusicAuditionTrack ClassFactory */ static HRESULT WINAPI AuditionTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI AuditionTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI AuditionTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI AuditionTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicAuditionTrack (riid, ppobj, pOuter); } static HRESULT WINAPI AuditionTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -321,37 +378,45 @@ AuditionTrackCF_LockServer }; -static IClassFactoryImpl AuditionTrack_CF = {&AuditionTrackCF_Vtbl, 1 }; +static IClassFactoryImpl AuditionTrack_CF = {&AuditionTrackCF_Vtbl}; /****************************************************************** * DirectMusicMuteTrack ClassFactory */ static HRESULT WINAPI MuteTrackCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI MuteTrackCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSTYLE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI MuteTrackCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSTYLE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI MuteTrackCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicMuteTrack (riid, ppobj, pOuter); } static HRESULT WINAPI MuteTrackCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSTYLE_LockModule(); + else + DMSTYLE_UnlockModule(); + return S_OK; } @@ -363,7 +428,7 @@ MuteTrackCF_LockServer }; -static IClassFactoryImpl MuteTrack_CF = {&MuteTrackCF_Vtbl, 1 }; +static IClassFactoryImpl MuteTrack_CF = {&MuteTrackCF_Vtbl}; /****************************************************************** * DllMain @@ -388,8 +453,7 @@ * */ HRESULT WINAPI DMSTYLE_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMSTYLE_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmstyle/dmstyle_private.h wine-20050211/dlls/dmstyle/dmstyle_private.h --- wine-20050111/dlls/dmstyle/dmstyle_private.h 2005-01-05 14:22:57.000000000 +0100 +++ wine-20050211/dlls/dmstyle/dmstyle_private.h 2005-01-24 20:33:23.000000000 +0100 @@ -539,6 +539,12 @@ extern HRESULT WINAPI IDirectMusicStyleTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty); extern HRESULT WINAPI IDirectMusicStyleTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize); +/********************************************************************** + * Dll lifetime tracking declaration for dmstyle.dll + */ +extern LONG DMSTYLE_refCount; +static inline void DMSTYLE_LockModule() { InterlockedIncrement( &DMSTYLE_refCount ); } +static inline void DMSTYLE_UnlockModule() { InterlockedDecrement( &DMSTYLE_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dmstyle/motiftrack.c wine-20050211/dlls/dmstyle/motiftrack.c --- wine-20050111/dlls/dmstyle/motiftrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmstyle/motiftrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicMotifTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicMotifTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicMotifTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicMotifTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/mutetrack.c wine-20050211/dlls/dmstyle/mutetrack.c --- wine-20050111/dlls/dmstyle/mutetrack.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmstyle/mutetrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicMuteTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicMuteTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicMuteTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicMuteTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/style.c wine-20050211/dlls/dmstyle/style.c --- wine-20050111/dlls/dmstyle/style.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dmstyle/style.c 2005-01-24 20:33:23.000000000 +0100 @@ -59,17 +59,27 @@ ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmstyle/styletrack.c wine-20050211/dlls/dmstyle/styletrack.c --- wine-20050111/dlls/dmstyle/styletrack.c 2005-01-05 14:22:57.000000000 +0100 +++ wine-20050211/dlls/dmstyle/styletrack.c 2005-01-24 20:33:23.000000000 +0100 @@ -51,17 +51,27 @@ ULONG WINAPI IDirectMusicStyleTrack_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicStyleTrack, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %ld\n", This, ref - 1); + + DMSTYLE_LockModule(); + + return ref; } ULONG WINAPI IDirectMusicStyleTrack_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicStyleTrack, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %ld\n", This, ref); + if (ref == 0) { HeapFree(GetProcessHeap(), 0, This); } + + DMSTYLE_UnlockModule(); + return ref; } diff -urN wine-20050111/dlls/dmsynth/dmsynth_main.c wine-20050211/dlls/dmsynth/dmsynth_main.c --- wine-20050111/dlls/dmsynth/dmsynth_main.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/dmsynth/dmsynth_main.c 2005-01-31 21:40:26.000000000 +0100 @@ -23,41 +23,48 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmsynth); +LONG DMSYNTH_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusicSynth ClassFactory */ static HRESULT WINAPI SynthCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SynthCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSYNTH_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SynthCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSYNTH_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SynthCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicSynthImpl (riid, ppobj, pOuter); } static HRESULT WINAPI SynthCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSYNTH_LockModule(); + else + DMSYNTH_UnlockModule(); + return S_OK; } @@ -69,37 +76,44 @@ SynthCF_LockServer }; -static IClassFactoryImpl Synth_CF = {&SynthCF_Vtbl, 1 }; +static IClassFactoryImpl Synth_CF = {&SynthCF_Vtbl}; /****************************************************************** * DirectMusicSynthSink ClassFactory */ static HRESULT WINAPI SynthSinkCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI SynthSinkCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMSYNTH_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI SynthSinkCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMSYNTH_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI SynthSinkCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicSynthSinkImpl (riid, ppobj, pOuter); } static HRESULT WINAPI SynthSinkCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMSYNTH_LockModule(); + else + DMSYNTH_UnlockModule(); + return S_OK; } @@ -111,7 +125,7 @@ SynthSinkCF_LockServer }; -static IClassFactoryImpl SynthSink_CF = {&SynthSinkCF_Vtbl, 1 }; +static IClassFactoryImpl SynthSink_CF = {&SynthSinkCF_Vtbl}; /****************************************************************** * DllMain @@ -136,8 +150,7 @@ * */ HRESULT WINAPI DMSYNTH_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMSYNTH_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmsynth/dmsynth_private.h wine-20050211/dlls/dmsynth/dmsynth_private.h --- wine-20050111/dlls/dmsynth/dmsynth_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dmsynth/dmsynth_private.h 2005-01-31 21:40:26.000000000 +0100 @@ -127,6 +127,12 @@ extern HRESULT WINAPI IDirectMusicSynthSinkImpl_SetDirectSound (LPDIRECTMUSICSYNTHSINK iface, LPDIRECTSOUND pDirectSound, LPDIRECTSOUNDBUFFER pDirectSoundBuffer); extern HRESULT WINAPI IDirectMusicSynthSinkImpl_GetDesiredBufferSize (LPDIRECTMUSICSYNTHSINK iface, LPDWORD pdwBufferSizeInSamples); +/********************************************************************** + * Dll lifetime tracking declaration for dmsynth.dll + */ +extern LONG DMSYNTH_refCount; +static inline void DMSYNTH_LockModule() { InterlockedIncrement( &DMSYNTH_refCount ); } +static inline void DMSYNTH_UnlockModule() { InterlockedDecrement( &DMSYNTH_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dmsynth/synth.c wine-20050211/dlls/dmsynth/synth.c --- wine-20050111/dlls/dmsynth/synth.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/dmsynth/synth.c 2005-01-31 21:40:26.000000000 +0100 @@ -39,18 +39,28 @@ ULONG WINAPI IDirectMusicSynth8Impl_AddRef (LPDIRECTMUSICSYNTH8 iface) { IDirectMusicSynth8Impl *This = (IDirectMusicSynth8Impl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMSYNTH_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicSynth8Impl_Release (LPDIRECTMUSICSYNTH8 iface) { IDirectMusicSynth8Impl *This = (IDirectMusicSynth8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMSYNTH_UnlockModule(); + + return refCount; } /* IDirectMusicSynth8Impl IDirectMusicSynth part: */ diff -urN wine-20050111/dlls/dmsynth/synthsink.c wine-20050211/dlls/dmsynth/synthsink.c --- wine-20050111/dlls/dmsynth/synthsink.c 2004-09-06 23:34:26.000000000 +0200 +++ wine-20050211/dlls/dmsynth/synthsink.c 2005-01-31 21:40:26.000000000 +0100 @@ -38,18 +38,28 @@ ULONG WINAPI IDirectMusicSynthSinkImpl_AddRef (LPDIRECTMUSICSYNTHSINK iface) { IDirectMusicSynthSinkImpl *This = (IDirectMusicSynthSinkImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMSYNTH_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicSynthSinkImpl_Release (LPDIRECTMUSICSYNTHSINK iface) { IDirectMusicSynthSinkImpl *This = (IDirectMusicSynthSinkImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMSYNTH_UnlockModule(); + + return refCount; } /* IDirectMusicSynthSinkImpl IDirectMusicSynthSink part: */ diff -urN wine-20050111/dlls/dmusic/buffer.c wine-20050211/dlls/dmusic/buffer.c --- wine-20050111/dlls/dmusic/buffer.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmusic/buffer.c 2005-01-26 20:41:43.000000000 +0100 @@ -37,18 +37,28 @@ ULONG WINAPI IDirectMusicBufferImpl_AddRef (LPDIRECTMUSICBUFFER iface) { IDirectMusicBufferImpl *This = (IDirectMusicBufferImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicBufferImpl_Release (LPDIRECTMUSICBUFFER iface) { IDirectMusicBufferImpl *This = (IDirectMusicBufferImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicBufferImpl IDirectMusicBuffer part: */ diff -urN wine-20050111/dlls/dmusic/clock.c wine-20050211/dlls/dmusic/clock.c --- wine-20050111/dlls/dmusic/clock.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/clock.c 2005-01-26 20:41:43.000000000 +0100 @@ -38,18 +38,28 @@ ULONG WINAPI IReferenceClockImpl_AddRef (IReferenceClock *iface) { IReferenceClockImpl *This = (IReferenceClockImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IReferenceClockImpl_Release (IReferenceClock *iface) { IReferenceClockImpl *This = (IReferenceClockImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IReferenceClockImpl IReferenceClock part: */ diff -urN wine-20050111/dlls/dmusic/collection.c wine-20050211/dlls/dmusic/collection.c --- wine-20050111/dlls/dmusic/collection.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dmusic/collection.c 2005-01-26 20:41:43.000000000 +0100 @@ -54,18 +54,28 @@ ULONG WINAPI IDirectMusicCollectionImpl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicCollectionImpl, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicCollectionImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicCollectionImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } IUnknownVtbl DirectMusicCollection_Unknown_Vtbl = { diff -urN wine-20050111/dlls/dmusic/dmusic.c wine-20050211/dlls/dmusic/dmusic.c --- wine-20050111/dlls/dmusic/dmusic.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/dmusic.c 2005-01-26 20:41:43.000000000 +0100 @@ -40,18 +40,28 @@ ULONG WINAPI IDirectMusic8Impl_AddRef (LPDIRECTMUSIC8 iface) { IDirectMusic8Impl *This = (IDirectMusic8Impl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusic8Impl_Release (LPDIRECTMUSIC8 iface) { IDirectMusic8Impl *This = (IDirectMusic8Impl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusic8Impl IDirectMusic part: */ diff -urN wine-20050111/dlls/dmusic/dmusic_main.c wine-20050211/dlls/dmusic/dmusic_main.c --- wine-20050111/dlls/dmusic/dmusic_main.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/dmusic_main.c 2005-01-26 20:41:43.000000000 +0100 @@ -23,41 +23,48 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmusic); +LONG DMUSIC_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusic ClassFactory */ static HRESULT WINAPI DirectMusicCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n",This,debugstr_dmguid(riid),ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI DirectMusicCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMUSIC_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI DirectMusicCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMUSIC_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI DirectMusicCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicImpl (riid, (LPVOID*) ppobj, pOuter); } static HRESULT WINAPI DirectMusicCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMUSIC_LockModule(); + else + DMUSIC_UnlockModule(); + return S_OK; } @@ -69,37 +76,44 @@ DirectMusicCF_LockServer }; -static IClassFactoryImpl DirectMusic_CF = {&DirectMusicCF_Vtbl, 1 }; +static IClassFactoryImpl DirectMusic_CF = {&DirectMusicCF_Vtbl}; /****************************************************************** * DirectMusicCollection ClassFactory */ static HRESULT WINAPI CollectionCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n",This,debugstr_dmguid(riid),ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI CollectionCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DMUSIC_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI CollectionCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DMUSIC_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI CollectionCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); return DMUSIC_CreateDirectMusicCollectionImpl (riid, ppobj, pOuter); } static HRESULT WINAPI CollectionCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DMUSIC_LockModule(); + else + DMUSIC_UnlockModule(); + return S_OK; } @@ -111,7 +125,7 @@ CollectionCF_LockServer }; -static IClassFactoryImpl Collection_CF = {&CollectionCF_Vtbl, 1 }; +static IClassFactoryImpl Collection_CF = {&CollectionCF_Vtbl}; /****************************************************************** * DllMain @@ -136,8 +150,7 @@ * */ HRESULT WINAPI DMUSIC_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DMUSIC_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dmusic/dmusic_private.h wine-20050211/dlls/dmusic/dmusic_private.h --- wine-20050111/dlls/dmusic/dmusic_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dmusic/dmusic_private.h 2005-01-26 20:41:43.000000000 +0100 @@ -402,6 +402,12 @@ /* custom :) */ extern HRESULT WINAPI IDirectMusicInstrumentImpl_Custom_Load (LPDIRECTMUSICINSTRUMENT iface, LPSTREAM pStm); +/********************************************************************** + * Dll lifetime tracking declaration for dmusic.dll + */ +extern LONG DMUSIC_refCount; +static inline void DMUSIC_LockModule() { InterlockedIncrement( &DMUSIC_refCount ); } +static inline void DMUSIC_UnlockModule() { InterlockedDecrement( &DMUSIC_refCount ); } /***************************************************************************** * Helper Functions diff -urN wine-20050111/dlls/dmusic/download.c wine-20050211/dlls/dmusic/download.c --- wine-20050111/dlls/dmusic/download.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmusic/download.c 2005-01-26 20:41:43.000000000 +0100 @@ -38,18 +38,28 @@ ULONG WINAPI IDirectMusicDownloadImpl_AddRef (LPDIRECTMUSICDOWNLOAD iface) { IDirectMusicDownloadImpl *This = (IDirectMusicDownloadImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicDownloadImpl_Release (LPDIRECTMUSICDOWNLOAD iface) { IDirectMusicDownloadImpl *This = (IDirectMusicDownloadImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicDownloadImpl IDirectMusicDownload part: */ diff -urN wine-20050111/dlls/dmusic/downloadedinstrument.c wine-20050211/dlls/dmusic/downloadedinstrument.c --- wine-20050111/dlls/dmusic/downloadedinstrument.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmusic/downloadedinstrument.c 2005-01-26 20:41:43.000000000 +0100 @@ -38,18 +38,28 @@ ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef (LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface) { IDirectMusicDownloadedInstrumentImpl *This = (IDirectMusicDownloadedInstrumentImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release (LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface) { IDirectMusicDownloadedInstrumentImpl *This = (IDirectMusicDownloadedInstrumentImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicDownloadedInstrumentImpl IDirectMusicDownloadedInstrument part: */ diff -urN wine-20050111/dlls/dmusic/instrument.c wine-20050211/dlls/dmusic/instrument.c --- wine-20050111/dlls/dmusic/instrument.c 2004-12-22 16:13:20.000000000 +0100 +++ wine-20050211/dlls/dmusic/instrument.c 2005-01-26 20:41:43.000000000 +0100 @@ -54,18 +54,28 @@ ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_AddRef (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface); - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } IUnknownVtbl DirectMusicInstrument_Unknown_Vtbl = { diff -urN wine-20050111/dlls/dmusic/port.c wine-20050211/dlls/dmusic/port.c --- wine-20050111/dlls/dmusic/port.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/port.c 2005-01-26 20:41:43.000000000 +0100 @@ -37,18 +37,28 @@ ULONG WINAPI IDirectMusicPortImpl_AddRef (LPDIRECTMUSICPORT iface) { IDirectMusicPortImpl *This = (IDirectMusicPortImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicPortImpl_Release (LPDIRECTMUSICPORT iface) { IDirectMusicPortImpl *This = (IDirectMusicPortImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicPortImpl IDirectMusicPort part: */ diff -urN wine-20050111/dlls/dmusic/portdownload.c wine-20050211/dlls/dmusic/portdownload.c --- wine-20050111/dlls/dmusic/portdownload.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/portdownload.c 2005-01-26 20:41:43.000000000 +0100 @@ -37,18 +37,28 @@ ULONG WINAPI IDirectMusicPortDownloadImpl_AddRef (LPDIRECTMUSICPORTDOWNLOAD iface) { IDirectMusicPortDownloadImpl *This = (IDirectMusicPortDownloadImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicPortDownloadImpl_Release (LPDIRECTMUSICPORTDOWNLOAD iface) { IDirectMusicPortDownloadImpl *This = (IDirectMusicPortDownloadImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicPortDownload Interface follow: */ diff -urN wine-20050111/dlls/dmusic/thru.c wine-20050211/dlls/dmusic/thru.c --- wine-20050111/dlls/dmusic/thru.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dmusic/thru.c 2005-01-26 20:41:43.000000000 +0100 @@ -38,18 +38,28 @@ ULONG WINAPI IDirectMusicThruImpl_AddRef (LPDIRECTMUSICTHRU iface) { IDirectMusicThruImpl *This = (IDirectMusicThruImpl *)iface; - TRACE("(%p): AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DMUSIC_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicThruImpl_Release (LPDIRECTMUSICTHRU iface) { IDirectMusicThruImpl *This = (IDirectMusicThruImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DMUSIC_UnlockModule(); + + return refCount; } /* IDirectMusicThru Interface follow: */ diff -urN wine-20050111/dlls/dplayx/dplayx_global.c wine-20050211/dlls/dplayx/dplayx_global.c --- wine-20050111/dlls/dplayx/dplayx_global.c 2003-09-29 22:12:05.000000000 +0200 +++ wine-20050211/dlls/dplayx/dplayx_global.c 2005-01-26 22:09:05.000000000 +0100 @@ -1207,8 +1207,8 @@ /* NOTE: This is potentially not thread safe. You are not guaranteed to end up with the correct string printed in the case where the HRESULT is not - known. You'll just get the last hr passed in printed. This can change - over time if this method is used alot :) */ + known. You will just get the last hr passed in. This can change + over time if this method is used a lot :) */ LPCSTR DPLAYX_HresultToString(HRESULT hr) { static char szTempStr[12]; diff -urN wine-20050111/dlls/dplayx/dplobby.c wine-20050211/dlls/dplayx/dplobby.c --- wine-20050111/dlls/dplayx/dplobby.c 2005-01-07 16:40:09.000000000 +0100 +++ wine-20050211/dlls/dplayx/dplobby.c 2005-01-26 22:09:05.000000000 +0100 @@ -70,9 +70,9 @@ /***************************************************************************** * IDirectPlayLobby {1,2,3} implementation structure * - * The philosophy behind this extra pointer derefernce is that I wanted to + * The philosophy behind this extra pointer dereference is that I wanted to * have the same structure for all types of objects without having to do - * alot of casting. I also only wanted to implement an interface in the + * a lot of casting. I also only wanted to implement an interface in the * object it was "released" with IUnknown interface being implemented in the 1 version. * Of course, with these new interfaces comes the data required to keep the state required * by these interfaces. So, basically, the pointers contain the data associated with diff -urN wine-20050111/dlls/dplayx/name_server.c wine-20050211/dlls/dplayx/name_server.c --- wine-20050111/dlls/dplayx/name_server.c 2003-09-29 22:12:05.000000000 +0200 +++ wine-20050211/dlls/dplayx/name_server.c 2005-02-10 20:19:36.000000000 +0100 @@ -267,7 +267,7 @@ if( lpCache == NULL ) { - ERR( ": invalidate non existent cache\n" ); + ERR( ": invalidate nonexistent cache\n" ); return; } diff -urN wine-20050111/dlls/dpnet/address.c wine-20050211/dlls/dpnet/address.c --- wine-20050111/dlls/dpnet/address.c 2004-11-30 22:38:59.000000000 +0100 +++ wine-20050211/dlls/dpnet/address.c 2005-01-14 17:52:04.000000000 +0100 @@ -54,18 +54,23 @@ ULONG WINAPI IDirectPlay8AddressImpl_AddRef(PDIRECTPLAY8ADDRESS iface) { IDirectPlay8AddressImpl *This = (IDirectPlay8AddressImpl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + return refCount; } ULONG WINAPI IDirectPlay8AddressImpl_Release(PDIRECTPLAY8ADDRESS iface) { IDirectPlay8AddressImpl *This = (IDirectPlay8AddressImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + return refCount; } /* IDirectPlay8Address Interface follow: */ diff -urN wine-20050111/dlls/dpnet/client.c wine-20050211/dlls/dpnet/client.c --- wine-20050111/dlls/dpnet/client.c 2004-09-06 22:34:30.000000000 +0200 +++ wine-20050211/dlls/dpnet/client.c 2005-01-14 17:52:04.000000000 +0100 @@ -54,18 +54,23 @@ ULONG WINAPI IDirectPlay8ClientImpl_AddRef(PDIRECTPLAY8CLIENT iface) { IDirectPlay8ClientImpl *This = (IDirectPlay8ClientImpl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + return refCount; } ULONG WINAPI IDirectPlay8ClientImpl_Release(PDIRECTPLAY8CLIENT iface) { IDirectPlay8ClientImpl *This = (IDirectPlay8ClientImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + return refCount; } /* IDirectPlay8Client Interface follow: */ diff -urN wine-20050111/dlls/dsound/buffer.c wine-20050211/dlls/dsound/buffer.c --- wine-20050111/dlls/dsound/buffer.c 2004-12-23 19:41:06.000000000 +0100 +++ wine-20050211/dlls/dsound/buffer.c 2005-02-11 12:49:05.000000000 +0100 @@ -19,31 +19,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include #define NONAMELESSSTRUCT #define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winreg.h" #include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -70,25 +54,25 @@ static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { - IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); -} - -static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { - IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; - ULONG ref; - - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - - ref = InterlockedDecrement(&(This->ref)); - if (ref == 0) { - IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb); - This->dsb->notify = NULL; - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); - } - return ref; + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; +} + +static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) +{ + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + + if (!ref) { + IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb); + This->dsb->notify = NULL; + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; } static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions( @@ -129,7 +113,7 @@ WARN("out of memory\n"); return DSERR_OUTOFMEMORY; } - memcpy(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); + CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); This->dsb->nrofnotifies = howmuch; } else { HeapFree(GetProcessHeap(), 0, This->dsb->notifies); @@ -366,22 +350,19 @@ static ULONG WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - ULONG ref; - - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - - ref = InterlockedDecrement(&(This->ref)); - if (ref) - return ref; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { DSOUND_RemoveBuffer(This->dsound, This); This->lock.DebugInfo->Spare[1] = 0; @@ -406,10 +387,11 @@ HeapFree(GetProcessHeap(), 0, This->notifies); HeapFree(GetProcessHeap(), 0, This->pwfx); - HeapFree(GetProcessHeap(),0,This); + HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n",This); - return 0; + TRACE("(%p) released\n", This); + } + return ref; } DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, @@ -568,7 +550,7 @@ if (lpwf) { /* NULL is valid */ if (wfsize >= size) { - memcpy(lpwf,This->pwfx,size); + CopyMemory(lpwf,This->pwfx,size); if (wfwritten) *wfwritten = size; } else { @@ -1059,7 +1041,7 @@ dsb->iks = NULL; /* size depends on version */ - memcpy(&dsb->dsbd, dsbd, dsbd->dwSize); + CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize); /* variable sized struct so calculate size based on format */ if (wfex->wFormatTag == WAVE_FORMAT_PCM) { @@ -1076,7 +1058,7 @@ return DSERR_OUTOFMEMORY; } - memcpy(dsb->pwfx, wfex, cp_size); + CopyMemory(dsb->pwfx, wfex, cp_size); dsb->buflen = dsbd->dwBufferBytes; dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec; @@ -1100,17 +1082,18 @@ /* FIXME: check whether any hardware buffers are left */ /* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */ - /* Allocate system memory if applicable */ - if ((ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) { - dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer))); - if (dsb->buffer == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->pwfx); - HeapFree(GetProcessHeap(),0,dsb); - *pdsb = NULL; - return DSERR_OUTOFMEMORY; - } + /* Allocate an empty buffer */ + dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer))); + if (dsb->buffer == NULL) { + WARN("out of memory\n"); + HeapFree(GetProcessHeap(),0,dsb->pwfx); + HeapFree(GetProcessHeap(),0,dsb); + *pdsb = NULL; + return DSERR_OUTOFMEMORY; + } + /* Allocate system memory for buffer if applicable */ + if ((ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) { dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); if (dsb->buffer->memory == NULL) { WARN("out of memory\n"); @@ -1121,6 +1104,7 @@ return DSERR_OUTOFMEMORY; } dsb->buffer->ref = 1; + FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0); } /* Allocate the hardware buffer */ @@ -1133,15 +1117,6 @@ TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n"); use_hw = 0; if (ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { - dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer))); - if (dsb->buffer == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->pwfx); - HeapFree(GetProcessHeap(),0,dsb); - *pdsb = NULL; - return DSERR_OUTOFMEMORY; - } - dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); if (dsb->buffer->memory == NULL) { WARN("out of memory\n"); @@ -1152,6 +1127,7 @@ return DSERR_OUTOFMEMORY; } dsb->buffer->ref = 1; + FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0); } err = DS_OK; } @@ -1268,25 +1244,25 @@ static ULONG WINAPI SecondaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI SecondaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - ULONG ref; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - ref = InterlockedDecrement(&(This->ref)); - if (!ref) { - This->dsb->dsb = NULL; - IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); - } - return ref; + if (!ref) { + This->dsb->dsb = NULL; + IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; } static HRESULT WINAPI SecondaryBufferImpl_GetCaps( diff -urN wine-20050111/dlls/dsound/capture.c wine-20050211/dlls/dsound/capture.c --- wine-20050111/dlls/dsound/capture.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dsound/capture.c 2005-02-11 12:49:05.000000000 +0100 @@ -24,23 +24,12 @@ * Implement FX support. */ -#include "config.h" -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "mmddk.h" #include "winreg.h" @@ -201,8 +190,8 @@ err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", - "Primary Sound Capture Driver",desc.szDrvName,lpContext); - if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE) + "Primary Sound Capture Driver",desc.szDrvname,lpContext); + if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvname, lpContext) == FALSE) return DS_OK; } } @@ -214,8 +203,8 @@ err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", - debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvName,lpContext); - if (lpDSEnumCallback(&capture_guids[wid], desc.szDesc, desc.szDrvName, lpContext) == FALSE) + debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext); + if (lpDSEnumCallback(&capture_guids[wid], desc.szDesc, desc.szDrvname, lpContext) == FALSE) return DS_OK; } } @@ -263,10 +252,10 @@ err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", - "Primary Sound Capture Driver",desc.szDrvName,lpContext); + "Primary Sound Capture Driver",desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE) return DS_OK; @@ -280,10 +269,10 @@ err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", - debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvName,lpContext); + debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); if (lpDSEnumCallback((LPGUID)&capture_guids[wid], wDesc, wName, lpContext) == FALSE) return DS_OK; @@ -374,19 +363,19 @@ IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface ) { IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface ) { - ULONG uRef; IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - uRef = InterlockedDecrement(&(This->ref)); - if ( uRef == 0 ) { + if (!ref) { TRACE("deleting object\n"); if (This->capture_buffer) IDirectSoundCaptureBufferImpl_Release( @@ -402,10 +391,9 @@ DeleteCriticalSection( &(This->lock) ); HeapFree( GetProcessHeap(), 0, This ); dsound_capture = NULL; - TRACE("(%p) released\n",This); + TRACE("(%p) released\n", This); } - - return uRef; + return ref; } static HRESULT WINAPI @@ -581,8 +569,8 @@ if (err == DS_OK) { This->drvcaps.dwFlags = 0; - strncpy(This->drvdesc.szDrvName, wic.szPname, - sizeof(This->drvdesc.szDrvName)); + strncpy(This->drvdesc.szDrvname, wic.szPname, + sizeof(This->drvdesc.szDrvname)); This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER; This->drvcaps.dwFormats = wic.dwFormats; @@ -657,11 +645,11 @@ if (wfex->wFormatTag == WAVE_FORMAT_PCM) { ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)); - memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)); + CopyMemory(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)); ipDSC->pwfx->cbSize = 0; } else { ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize); - memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize); + CopyMemory(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize); } } else { WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n"); @@ -692,7 +680,7 @@ This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, lpcDSCBufferDesc->dwSize); if (This->pdscbd) - memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); + CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); else { WARN("no memory\n"); This->dsound->capture_buffer = 0; @@ -799,25 +787,24 @@ static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; - ULONG ref; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - - ref = InterlockedDecrement(&(This->ref)); - if (ref == 0) { + if (!ref) { if (This->dscb->hwnotify) IDsDriverNotify_Release(This->dscb->hwnotify); This->dscb->notify=NULL; IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb); HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + TRACE("(%p) released\n", This); } return ref; } @@ -862,7 +849,7 @@ WARN("out of memory\n"); return DSERR_OUTOFMEMORY; } - memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); + CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); This->dscb->nrofnotifies = howmuch; } else { HeapFree(GetProcessHeap(), 0, This->dscb->notifies); @@ -963,19 +950,19 @@ IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { - ULONG uRef; IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - uRef = InterlockedDecrement(&(This->ref)); - if ( uRef == 0 ) { + if (!ref) { TRACE("deleting object\n"); if (This->dsound->state == STATE_CAPTURING) This->dsound->state = STATE_STOPPING; @@ -1004,10 +991,9 @@ HeapFree(GetProcessHeap(), 0, This->notifies); HeapFree( GetProcessHeap(), 0, This ); - TRACE("(%p) released\n",This); + TRACE("(%p) released\n", This); } - - return uRef; + return ref; } static HRESULT WINAPI @@ -1132,7 +1118,7 @@ dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize; if (lpwfxFormat) { /* NULL is valid (just want size) */ - memcpy(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated); + CopyMemory(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated); if (lpdwSizeWritten) *lpdwSizeWritten = dwSizeAllocated; } else { @@ -1376,8 +1362,8 @@ } } - memset(ipDSC->buffer, - (ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0, ipDSC->buflen); + FillMemory(ipDSC->buffer, ipDSC->buflen, + (ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0); } else { TRACE("no notifiers specified\n"); /* no notifiers specified so just create a single default header */ @@ -1589,17 +1575,19 @@ DSCCF_AddRef(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI DSCCF_Release(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); /* static class, won't be freed */ - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedDecrement(&(This->ref)); + return ref; } static HRESULT WINAPI @@ -1740,26 +1728,25 @@ IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface ) { IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface ) { - ULONG uRef; IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); - uRef = InterlockedDecrement(&(This->ref)); - if ( uRef == 0 ) { + if (!ref) { This->lock.DebugInfo->Spare[1] = 0; DeleteCriticalSection( &(This->lock) ); HeapFree( GetProcessHeap(), 0, This ); - TRACE("(%p) released\n",This); + TRACE("(%p) released\n", This); } - - return uRef; + return ref; } static HRESULT WINAPI diff -urN wine-20050111/dlls/dsound/dsound.c wine-20050211/dlls/dsound/dsound.c --- wine-20050111/dlls/dsound/dsound.c 2004-12-07 15:23:46.000000000 +0100 +++ wine-20050211/dlls/dsound/dsound.c 2005-02-11 12:49:05.000000000 +0100 @@ -20,38 +20,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" -#include "wine/port.h" - #include #include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include #define NONAMELESSSTRUCT #define NONAMELESSUNION #include "windef.h" #include "winbase.h" #include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winternl.h" #include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" #include "dsound_private.h" -#include "dsconf.h" WINE_DEFAULT_DEBUG_CHANNEL(dsound); @@ -247,21 +230,19 @@ LPDIRECTSOUND8 iface) { IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSoundImpl_Release( LPDIRECTSOUND8 iface) { IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - ULONG ref; - TRACE("(%p) ref was %ld, thread is %04lx\n", - This, This->ref, GetCurrentThreadId()); + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - ref = InterlockedDecrement(&(This->ref)); - if (ref == 0) { + if (!ref) { HRESULT hres; INT i; @@ -301,14 +282,15 @@ if (This->driver) IDsDriver_Release(This->driver); + HeapFree(GetProcessHeap(),0,This->tmp_buffer); + HeapFree(GetProcessHeap(),0,This->buffer); RtlDeleteResource(&This->buffer_list_lock); This->mixlock.DebugInfo->Spare[1] = 0; DeleteCriticalSection(&This->mixlock); HeapFree(GetProcessHeap(),0,This); dsound = NULL; - TRACE("(%p) released\n",This); + TRACE("(%p) released\n", This); } - return ref; } @@ -538,7 +520,7 @@ return DSERR_OUTOFMEMORY; } - memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl)); + CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl)); if (pdsb->hwbuf) { TRACE("duplicating hardware buffer\n"); @@ -596,7 +578,7 @@ return DSERR_OUTOFMEMORY; } - memcpy(dsb->pwfx, pdsb->pwfx, size); + CopyMemory(dsb->pwfx, pdsb->pwfx, size); InitializeCriticalSection(&(dsb->lock)); dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock"; @@ -809,6 +791,8 @@ pDS->primary = NULL; pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16); pDS->initialized = FALSE; + pDS->tmp_buffer = NULL; + pDS->tmp_buffer_len = 0; /* 3D listener initial parameters */ pDS->listener = NULL; @@ -984,23 +968,23 @@ LPUNKNOWN iface) { IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound_IUnknown_Release( LPUNKNOWN iface) { IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - ULONG ulReturn; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - if (ulReturn == 0) { + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static IUnknownVtbl DirectSound_Unknown_Vtbl = @@ -1062,23 +1046,23 @@ LPDIRECTSOUND iface) { IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound_IDirectSound_Release( LPDIRECTSOUND iface) { IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - ULONG ulReturn; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&This->ref); - if (ulReturn == 0) { + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer( @@ -1223,23 +1207,23 @@ LPUNKNOWN iface) { IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound8_IUnknown_Release( LPUNKNOWN iface) { IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - ULONG ulReturn; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - if (ulReturn == 0) { + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static IUnknownVtbl DirectSound8_Unknown_Vtbl = @@ -1301,23 +1285,23 @@ LPDIRECTSOUND iface) { IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound8_IDirectSound_Release( LPDIRECTSOUND iface) { IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - ULONG ulReturn; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - if (ulReturn == 0) { + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer( @@ -1462,23 +1446,23 @@ LPDIRECTSOUND8 iface) { IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound8_IDirectSound8_Release( LPDIRECTSOUND8 iface) { IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - ULONG ulReturn; - TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - if (ulReturn == 0) { + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + if (!ref) { IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer( diff -urN wine-20050111/dlls/dsound/dsound_main.c wine-20050211/dlls/dsound/dsound_main.c --- wine-20050111/dlls/dsound/dsound_main.c 2004-10-07 05:06:50.000000000 +0200 +++ wine-20050211/dlls/dsound/dsound_main.c 2005-02-11 12:49:05.000000000 +0100 @@ -36,37 +36,18 @@ * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN */ -#include "config.h" -#include "wine/port.h" - -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include #define COBJMACROS #define NONAMELESSSTRUCT #define NONAMELESSUNION - #include "windef.h" #include "winbase.h" +#include "winnls.h" #include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winternl.h" #include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -287,19 +268,19 @@ if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) || IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) { - memcpy(pGuidDest, &renderer_guids[ds_default_playback], sizeof(GUID)); + CopyMemory(pGuidDest, &renderer_guids[ds_default_playback], sizeof(GUID)); TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; } if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) || IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) { - memcpy(pGuidDest, &capture_guids[ds_default_capture], sizeof(GUID)); + CopyMemory(pGuidDest, &capture_guids[ds_default_capture], sizeof(GUID)); TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; } - memcpy(pGuidDest, pGuidSrc, sizeof(GUID)); + CopyMemory(pGuidDest, pGuidSrc, sizeof(GUID)); TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; @@ -344,8 +325,8 @@ err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", - "Primary Sound Driver",desc.szDrvName,lpContext); - if (lpDSEnumCallback(NULL, "Primary Sound Driver", desc.szDrvName, lpContext) == FALSE) + "Primary Sound Driver",desc.szDrvname,lpContext); + if (lpDSEnumCallback(NULL, "Primary Sound Driver", desc.szDrvname, lpContext) == FALSE) return DS_OK; } } @@ -357,8 +338,8 @@ err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", - debugstr_guid(&renderer_guids[wod]),desc.szDesc,desc.szDrvName,lpContext); - if (lpDSEnumCallback(&renderer_guids[wod], desc.szDesc, desc.szDrvName, lpContext) == FALSE) + debugstr_guid(&renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext); + if (lpDSEnumCallback(&renderer_guids[wod], desc.szDesc, desc.szDrvname, lpContext) == FALSE) return DS_OK; } } @@ -405,10 +386,10 @@ err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", - "Primary Sound Driver",desc.szDrvName,lpContext); + "Primary Sound Driver",desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE) return DS_OK; @@ -422,10 +403,10 @@ err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", - debugstr_guid(&renderer_guids[wod]),desc.szDesc,desc.szDrvName,lpContext); + debugstr_guid(&renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); if (lpDSEnumCallback(&renderer_guids[wod], wDesc, wName, lpContext) == FALSE) return DS_OK; @@ -446,18 +427,21 @@ return E_NOINTERFACE; } -static ULONG WINAPI -DSCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); +static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } -static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedDecrement(&(This->ref)); +static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + /* static class, won't be freed */ + return ref; } static HRESULT WINAPI DSCF_CreateInstance( @@ -466,6 +450,9 @@ IClassFactoryImpl *This = (IClassFactoryImpl *)iface; TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + if (pOuter) + return CLASS_E_NOAGGREGATION; + if (ppobj == NULL) { WARN("invalid parameter\n"); return DSERR_INVALIDPARAM; @@ -511,19 +498,21 @@ return E_NOINTERFACE; } -static ULONG WINAPI -DSPCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); +static ULONG WINAPI DSPCF_AddRef(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } -static ULONG WINAPI -DSPCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedDecrement(&(This->ref)); +static ULONG WINAPI DSPCF_Release(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + /* static class, won't be freed */ + return ref; } static HRESULT WINAPI diff -urN wine-20050111/dlls/dsound/dsound_private.h wine-20050211/dlls/dsound/dsound_private.h --- wine-20050111/dlls/dsound/dsound_private.h 2004-09-07 21:32:21.000000000 +0200 +++ wine-20050211/dlls/dsound/dsound_private.h 2005-01-24 12:27:05.000000000 +0100 @@ -95,6 +95,8 @@ DSBUFFERDESC dsbd; DWORD speaker_config; BOOL initialized; + LPBYTE tmp_buffer; + DWORD tmp_buffer_len; /* DirectSound3DListener fields */ IDirectSound3DListenerImpl* listener; diff -urN wine-20050111/dlls/dsound/mixer.c wine-20050211/dlls/dsound/mixer.c --- wine-20050111/dlls/dsound/mixer.c 2004-09-08 03:37:25.000000000 +0200 +++ wine-20050211/dlls/dsound/mixer.c 2005-02-10 18:10:54.000000000 +0100 @@ -19,29 +19,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" #include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include #include /* Insomnia - pow() function */ +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winreg.h" #include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -237,13 +225,13 @@ if ((dsb->freq == dsb->dsound->pwfx->nSamplesPerSec) && (dsb->pwfx->wBitsPerSample == dsb->dsound->pwfx->wBitsPerSample) && (dsb->pwfx->nChannels == dsb->dsound->pwfx->nChannels)) { - DWORD bytesleft = dsb->buflen - dsb->buf_mixpos; + INT bytesleft = dsb->buflen - dsb->buf_mixpos; TRACE("(%p) Best case\n", dsb); if (len <= bytesleft ) - memcpy(obp, ibp, len); + CopyMemory(obp, ibp, len); else { /* wrap */ - memcpy(obp, ibp, bytesleft ); - memcpy(obp + bytesleft, dsb->buffer->memory, len - bytesleft); + CopyMemory(obp, ibp, bytesleft); + CopyMemory(obp + bytesleft, dsb->buffer->memory, len - bytesleft); } return len; } @@ -368,36 +356,36 @@ } } -static void *tmp_buffer; -static size_t tmp_buffer_len = 0; - -static void *DSOUND_tmpbuffer(size_t len) +static LPBYTE DSOUND_tmpbuffer(IDirectSoundImpl *dsound, DWORD len) { - if (len>tmp_buffer_len) { - void *new_buffer = realloc(tmp_buffer, len); - if (new_buffer) { - tmp_buffer = new_buffer; - tmp_buffer_len = len; + TRACE("(%p,%ld)\n",dsound,len); + + if (len > dsound->tmp_buffer_len) { + if (dsound->tmp_buffer) + dsound->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsound->tmp_buffer, len); + else + dsound->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len); + + dsound->tmp_buffer_len = len; } - return new_buffer; - } - return tmp_buffer; + + return dsound->tmp_buffer; } static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen) { - INT i, len, ilen, temp, field, nBlockAlign, todo; + INT i, len, ilen, field, nBlockAlign, todo; BYTE *buf, *ibuf; TRACE("(%p,%ld,%ld)\n",dsb,writepos,fraglen); len = fraglen; if (!(dsb->playflags & DSBPLAY_LOOPING)) { - temp = MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buflen, + INT temp = MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buflen, dsb->nAvgBytesPerSec) - - MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buf_mixpos, + MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buf_mixpos, dsb->nAvgBytesPerSec); - len = (len > temp) ? temp : len; + len = min(len, temp); } nBlockAlign = dsb->dsound->pwfx->nBlockAlign; len = len / nBlockAlign * nBlockAlign; /* data alignment */ @@ -407,9 +395,7 @@ return 0; } - /* Been seeing segfaults in malloc() for some reason... */ - TRACE("allocating buffer (size = %d)\n", len); - if ((buf = ibuf = (BYTE *) DSOUND_tmpbuffer(len)) == NULL) + if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL) return 0; TRACE("MixInBuffer (%p) len = %d, dest = %ld\n", dsb, len, writepos); @@ -518,8 +504,7 @@ nBlockAlign = dsb->dsound->pwfx->nBlockAlign; len = len / nBlockAlign * nBlockAlign; /* data alignment */ - TRACE("allocating buffer (size = %ld)\n", len); - if ((buf = ibuf = (BYTE *) DSOUND_tmpbuffer(len)) == NULL) + if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL) return; TRACE("PhaseCancel (%p) len = %ld, dest = %ld\n", dsb, len, writepos); @@ -906,10 +891,10 @@ /* wipe out premixed data */ if (dsound->mixpos < writepos) { - memset(dsound->buffer + writepos, nfiller, dsound->buflen - writepos); - memset(dsound->buffer, nfiller, dsound->mixpos); + FillMemory(dsound->buffer + writepos, dsound->buflen - writepos, nfiller); + FillMemory(dsound->buffer, dsound->mixpos, nfiller); } else { - memset(dsound->buffer + writepos, nfiller, dsound->mixpos - writepos); + FillMemory(dsound->buffer + writepos, dsound->mixpos - writepos, nfiller); } /* reset primary mix position */ @@ -995,10 +980,10 @@ assert(dsound->playpos < dsound->buflen); /* wipe out just-played sound data */ if (playpos < dsound->playpos) { - memset(dsound->buffer + dsound->playpos, nfiller, dsound->buflen - dsound->playpos); - memset(dsound->buffer, nfiller, playpos); + FillMemory(dsound->buffer + dsound->playpos, dsound->buflen - dsound->playpos, nfiller); + FillMemory(dsound->buffer, playpos, nfiller); } else { - memset(dsound->buffer + dsound->playpos, nfiller, playpos - dsound->playpos); + FillMemory(dsound->buffer + dsound->playpos, playpos - dsound->playpos, nfiller); } dsound->playpos = playpos; @@ -1070,7 +1055,7 @@ inq = 0; maxq = dsound->buflen; if (maxq > frag) maxq = frag; - memset(dsound->buffer, nfiller, dsound->buflen); + FillMemory(dsound->buffer, dsound->buflen, nfiller); paused = TRUE; } diff -urN wine-20050111/dlls/dsound/primary.c wine-20050211/dlls/dsound/primary.c --- wine-20050111/dlls/dsound/primary.c 2004-12-23 19:41:06.000000000 +0100 +++ wine-20050211/dlls/dsound/primary.c 2005-02-11 12:49:05.000000000 +0100 @@ -19,29 +19,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include /* Insomnia - pow() function */ +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winreg.h" #include "winternl.h" #include "mmddk.h" -#include "wine/windef16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -127,7 +114,7 @@ This->pwqueue = 0; This->playpos = 0; This->mixpos = 0; - memset(This->buffer, (This->pwfx->wBitsPerSample == 16) ? 0 : 128, This->buflen); + FillMemory(This->buffer, This->buflen, (This->pwfx->wBitsPerSample == 8) ? 128 : 0); TRACE("fraglen=%ld\n", This->fraglen); DSOUND_WaveQueue(This, (DWORD)-1); } @@ -360,6 +347,7 @@ /* **** */ RtlAcquireResourceExclusive(&(dsound->buffer_list_lock), TRUE); + EnterCriticalSection(&(dsound->mixlock)); if (wfex->wFormatTag == WAVE_FORMAT_PCM) { alloc_size = sizeof(WAVEFORMATEX); @@ -371,7 +359,7 @@ nSamplesPerSec = dsound->pwfx->nSamplesPerSec; - memcpy(dsound->pwfx, wfex, cp_size); + CopyMemory(dsound->pwfx, wfex, cp_size); if (dsound->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) { DWORD flags = CALLBACK_FUNCTION; @@ -387,14 +375,12 @@ if (err == DS_OK) { err = DSOUND_PrimaryOpen(dsound); if (err != DS_OK) { - WARN("DSOUND_PrimaryOpen failed\n"); - RtlReleaseResource(&(dsound->buffer_list_lock)); - return err; + WARN("DSOUND_PrimaryOpen failed\n"); + goto done; } } else { WARN("waveOutOpen failed\n"); - RtlReleaseResource(&(dsound->buffer_list_lock)); - return err; + goto done; } } else if (dsound->hwbuf) { err = IDsDriverBuffer_SetFormat(dsound->hwbuf, dsound->pwfx); @@ -407,15 +393,13 @@ (LPVOID)&(dsound->hwbuf)); if (err != DS_OK) { WARN("IDsDriver_CreateSoundBuffer failed\n"); - RtlReleaseResource(&(dsound->buffer_list_lock)); - return err; + goto done; } if (dsound->state == STATE_PLAYING) dsound->state = STATE_STARTING; else if (dsound->state == STATE_STOPPING) dsound->state = STATE_STOPPED; } else { WARN("IDsDriverBuffer_SetFormat failed\n"); - RtlReleaseResource(&(dsound->buffer_list_lock)); - return err; + goto done; } /* FIXME: should we set err back to DS_OK in all cases ? */ } @@ -435,6 +419,8 @@ } } +done: + LeaveCriticalSection(&(dsound->mixlock)); RtlReleaseResource(&(dsound->buffer_list_lock)); /* **** */ @@ -576,26 +562,26 @@ return DS_OK; } -static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { - PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); +static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) +{ + PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } -static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { - PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - DWORD ref; - - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - ref = InterlockedDecrement(&(This->ref)); - - if (ref == 0) { - This->dsound->primary = NULL; - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); - } +static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) +{ + PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; + DWORD ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - return ref; + if (!ref) { + This->dsound->primary = NULL; + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; } static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition( @@ -656,7 +642,7 @@ if (lpwf) { /* NULL is valid */ if (wfsize >= size) { - memcpy(lpwf,This->dsound->pwfx,size); + CopyMemory(lpwf,This->dsound->pwfx,size); if (wfwritten) *wfwritten = size; } else { @@ -1089,7 +1075,7 @@ dsb->dsound = ds; dsb->lpVtbl = &dspbvt; - memcpy(&ds->dsbd, dsbd, sizeof(*dsbd)); + CopyMemory(&ds->dsbd, dsbd, sizeof(*dsbd)); TRACE("Created primary buffer at %p\n", dsb); TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," diff -urN wine-20050111/dlls/dsound/propset.c wine-20050211/dlls/dsound/propset.c --- wine-20050111/dlls/dsound/propset.c 2005-01-09 17:42:53.000000000 +0100 +++ wine-20050211/dlls/dsound/propset.c 2005-02-11 12:49:05.000000000 +0100 @@ -19,32 +19,16 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "config.h" -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include /* Insomnia - pow() function */ -#define NONAMELESSUNION -#define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winreg.h" #include "winternl.h" #include "winnls.h" +#include "vfwmsgs.h" #include "mmddk.h" -#include "wine/windef16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -52,6 +36,12 @@ #include "initguid.h" #include "dsconf.h" +#ifdef NONAMELESSSTRUCT +# define S(x) (x).s +#else +# define S(x) (x) +#endif + WINE_DEFAULT_DEBUG_CHANNEL(dsound); @@ -74,24 +64,24 @@ static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface) { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface) { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; - ULONG ulReturn; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - TRACE("(%p) ref was %ld\n", This, This->ref); - ulReturn = InterlockedDecrement(&(This->ref)); - if (!ulReturn) { + if (!ref) { This->dsb->iks = 0; IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static HRESULT WINAPI IKsBufferPropertySetImpl_Get( @@ -116,10 +106,10 @@ DSPROPERTY prop; HRESULT hres; - prop.s.Set = *guidPropSet; - prop.s.Id = dwPropID; - prop.s.Flags = 0; /* unused */ - prop.s.InstanceId = (ULONG)This->dsb->dsound; + S(prop).Set = *guidPropSet; + S(prop).Id = dwPropID; + S(prop).Flags = 0; /* unused */ + S(prop).InstanceId = (ULONG)This->dsb->dsound; hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned); @@ -152,10 +142,10 @@ DSPROPERTY prop; HRESULT hres; - prop.s.Set = *guidPropSet; - prop.s.Id = dwPropID; - prop.s.Flags = 0; /* unused */ - prop.s.InstanceId = (ULONG)This->dsb->dsound; + S(prop).Set = *guidPropSet; + S(prop).Id = dwPropID; + S(prop).Flags = 0; /* unused */ + S(prop).InstanceId = (ULONG)This->dsb->dsound; hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData); IDsDriverPropertySet_Release(ps); @@ -258,22 +248,22 @@ static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; - ULONG ulReturn; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); - TRACE("(%p) ref was %ld\n", This, This->ref); - ulReturn = InterlockedDecrement(&(This->ref)); - if (ulReturn == 0) { - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); + if (!ref) { + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - return ulReturn; + return ref; } static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA( @@ -395,9 +385,9 @@ if (err == DS_OK) { PIDSDRIVER drv = NULL; strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1); - strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1); + strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; @@ -424,9 +414,9 @@ if (err == DS_OK) { PIDSCDRIVER drv; strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1); - strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1); + strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; @@ -454,9 +444,9 @@ if (err == DS_OK) { PIDSDRIVER drv = NULL; strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1); - strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1); + strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; @@ -485,9 +475,9 @@ if (err == DS_OK) { PIDSDRIVER drv = NULL; strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1); - strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1); + strncpy(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA) - 1); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; @@ -561,11 +551,11 @@ PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1); - CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1); + CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1); CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1); strcpy(szDescription, desc.szDesc); - strcpy(szModule, desc.szDrvName); + strcpy(szModule, desc.szDrvname); strcpy(szInterface, "Interface"); ppd->Description = szDescription; @@ -597,11 +587,11 @@ PIDSCDRIVER drv; /* FIXME: this is a memory leak */ CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1); - CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1); + CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1); CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1); strcpy(szDescription, desc.szDesc); - strcpy(szModule, desc.szDrvName); + strcpy(szModule, desc.szDrvname); strcpy(szInterface, "Interface"); ppd->Description = szDescription; @@ -634,11 +624,11 @@ PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1); - CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1); + CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvname) + 1); CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1); strcpy(szDescription, desc.szDesc); - strcpy(szModule, desc.szDrvName); + strcpy(szModule, desc.szDrvname); strcpy(szInterface, "Interface"); ppd->Description = szDescription; @@ -720,7 +710,7 @@ WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 ); ppd->Description = wDescription; @@ -756,7 +746,7 @@ WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 ); ppd->Description = wDescription; @@ -793,7 +783,7 @@ WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 ); ppd->Description = wDescription; @@ -859,12 +849,12 @@ err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { DWORD size; - memset(&data, 0, sizeof(data)); + ZeroMemory(&data, sizeof(data)); data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; data.WaveDeviceId = wod; data.DeviceId = renderer_guids[wod]; data.Description = desc.szDesc; - data.Module = desc.szDrvName; + data.Module = desc.szDrvname; err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); if (err == DS_OK) { WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); @@ -889,12 +879,12 @@ err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0)); if (err == DS_OK) { DWORD size; - memset(&data, 0, sizeof(data)); + ZeroMemory(&data, sizeof(data)); data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; data.WaveDeviceId = wid; data.DeviceId = capture_guids[wid]; data.Description = desc.szDesc; - data.Module = desc.szDrvName; + data.Module = desc.szDrvname; err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); if (err == DS_OK) { WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); @@ -959,13 +949,13 @@ WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); if (err == DS_OK) { - memset(&data, 0, sizeof(data)); + ZeroMemory(&data, sizeof(data)); data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; data.WaveDeviceId = wod; data.DeviceId = renderer_guids[wod]; MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); data.Description = wDescription; data.Module = wModule; @@ -993,13 +983,13 @@ WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); if (err == DS_OK) { - memset(&data, 0, sizeof(data)); + ZeroMemory(&data, sizeof(data)); data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; data.WaveDeviceId = wid; data.DeviceId = capture_guids[wid]; MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); data.Description = wDescription; data.Module = wModule; diff -urN wine-20050111/dlls/dsound/regsvr.c wine-20050211/dlls/dsound/regsvr.c --- wine-20050111/dlls/dsound/regsvr.c 2003-09-06 01:08:38.000000000 +0200 +++ wine-20050211/dlls/dsound/regsvr.c 2005-01-24 14:31:27.000000000 +0100 @@ -19,14 +19,13 @@ */ #include -#include +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" #include "winuser.h" #include "winreg.h" -#include "winerror.h" #include "mmsystem.h" #include "dsound.h" diff -urN wine-20050111/dlls/dsound/sound3d.c wine-20050211/dlls/dsound/sound3d.c --- wine-20050111/dlls/dsound/sound3d.c 2004-12-09 15:07:59.000000000 +0100 +++ wine-20050211/dlls/dsound/sound3d.c 2005-02-11 12:49:05.000000000 +0100 @@ -37,31 +37,17 @@ * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN */ -#include "config.h" -#include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include #include /* Insomnia - pow() function */ #define NONAMELESSUNION #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" #include "mmsystem.h" #include "winreg.h" #include "winternl.h" #include "mmddk.h" -#include "wine/windef16.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -378,26 +364,25 @@ static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface) { - IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface) { - IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - ULONG ulReturn; - - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - if (!ulReturn) { - This->dsb->ds3db = NULL; - IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); - } - - return ulReturn; + IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + + if (!ref) { + This->dsb->ds3db = NULL; + IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; } /* IDirectSound3DBuffer methods */ @@ -815,27 +800,24 @@ static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface) { - IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - return InterlockedIncrement(&(This->ref)); + IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref - 1); + return ref; } static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface) { - IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - ULONG ulReturn; - - TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); - ulReturn = InterlockedDecrement(&(This->ref)); - - /* Free all resources */ - if( ulReturn == 0 ) { - This->dsound->listener = 0; - HeapFree(GetProcessHeap(),0,This); - TRACE("(%p) released\n",This); - } - - return ulReturn; + IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %ld\n", This, ref + 1); + + if (!ref) { + This->dsound->listener = 0; + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; } /* IDirectSound3DListener methods */ diff -urN wine-20050111/dlls/dsound/tests/ds3d.c wine-20050211/dlls/dsound/tests/ds3d.c --- wine-20050111/dlls/dsound/tests/ds3d.c 2005-01-10 13:25:56.000000000 +0100 +++ wine-20050211/dlls/dsound/tests/ds3d.c 2005-02-10 21:26:20.000000000 +0100 @@ -628,7 +628,7 @@ LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; LPDIRECTSOUND3DLISTENER listener=NULL; DSBUFFERDESC bufdesc; - WAVEFORMATEX wfx; + WAVEFORMATEX wfx, wfx1; int ref; /* Create the DirectSound object */ @@ -659,6 +659,12 @@ 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; + if (has_listener) { rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSound3DListener, @@ -710,7 +716,8 @@ bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; bufdesc.lpwfxFormat=&wfx; if (winetest_interactive) { - trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n", + trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d " + "with a primary buffer at %ldx%dx%d\n", has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"", listener!=NULL||move_sound?"with ":"", @@ -718,7 +725,8 @@ listener!=NULL?"listener ":"", listener&&move_sound?"and moving sound ":move_sound? "moving sound ":"", - wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, + wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels); } rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL,"IDirectSound_CreateSoundBuffer() " @@ -839,6 +847,7 @@ } } } +EXIT1: if (has_listener) { ref=IDirectSound3DListener_Release(listener); ok(ref==0,"IDirectSound3dListener_Release() listener has %d " diff -urN wine-20050111/dlls/dsound/tests/ds3d8.c wine-20050211/dlls/dsound/tests/ds3d8.c --- wine-20050111/dlls/dsound/tests/ds3d8.c 2005-01-10 13:25:56.000000000 +0100 +++ wine-20050211/dlls/dsound/tests/ds3d8.c 2005-02-10 22:21:13.000000000 +0100 @@ -530,7 +530,7 @@ LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; LPDIRECTSOUND3DLISTENER listener=NULL; DSBUFFERDESC bufdesc; - WAVEFORMATEX wfx; + WAVEFORMATEX wfx, wfx1; int ref; /* Create the DirectSound object */ @@ -561,6 +561,12 @@ 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; + if (has_listener) { rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSound3DListener, @@ -624,7 +630,8 @@ } if (winetest_interactive) { - trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n", + trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d " + "with a primary buffer at %ldx%dx%d\n", has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"", listener!=NULL||move_sound?"with ":"", @@ -632,7 +639,8 @@ listener!=NULL?"listener ":"", listener&&move_sound?"and moving sound ":move_sound? "moving sound ":"", - wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, + wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels); } rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() " @@ -753,6 +761,7 @@ } } } +EXIT1: if (has_listener) { ref=IDirectSound3DListener_Release(listener); ok(ref==0,"IDirectSound3dListener_Release() listener has %d " @@ -785,7 +794,7 @@ int ref; /* Create the DirectSound object */ - rc=DirectSoundCreate8(lpGuid,&dso,NULL); + rc=pDirectSoundCreate8(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) diff -urN wine-20050111/dlls/dsound/tests/dsound.c wine-20050211/dlls/dsound/tests/dsound.c --- wine-20050111/dlls/dsound/tests/dsound.c 2005-01-10 13:25:56.000000000 +0100 +++ wine-20050211/dlls/dsound/tests/dsound.c 2005-02-10 21:26:20.000000000 +0100 @@ -623,7 +623,7 @@ LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; - WAVEFORMATEX wfx; + WAVEFORMATEX wfx, wfx1; DWORD f; int ref; @@ -659,6 +659,12 @@ "%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;fref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DSWAVE_LockModule(); + + return refCount; } ULONG WINAPI IDirectMusicWaveImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicWaveImpl, UnknownVtbl, iface); - ULONG ref = --This->ref; - TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DSWAVE_UnlockModule(); + + return refCount; } IUnknownVtbl DirectMusicWave_Unknown_Vtbl = { diff -urN wine-20050111/dlls/dswave/dswave_main.c wine-20050211/dlls/dswave/dswave_main.c --- wine-20050111/dlls/dswave/dswave_main.c 2004-09-06 22:34:29.000000000 +0200 +++ wine-20050211/dlls/dswave/dswave_main.c 2005-02-01 15:21:37.000000000 +0100 @@ -23,41 +23,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(dswave); +LONG DSWAVE_refCount = 0; + typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; } IClassFactoryImpl; /****************************************************************** * DirectMusicWave ClassFactory */ static HRESULT WINAPI WaveCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n", This, debugstr_dmguid(riid), ppobj); + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; + return E_NOINTERFACE; } static ULONG WINAPI WaveCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + DSWAVE_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI WaveCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return --(This->ref); + DSWAVE_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI WaveCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE ("(%p, %p, %s, %p)\n", This, pOuter, debugstr_dmguid(riid), ppobj); + TRACE ("(%p, %s, %p)\n", pOuter, debugstr_dmguid(riid), ppobj); + return DMUSIC_CreateDirectMusicWaveImpl (riid, ppobj, pOuter); } static HRESULT WINAPI WaveCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DSWAVE_LockModule(); + else + DSWAVE_UnlockModule(); + return S_OK; } @@ -69,7 +77,7 @@ WaveCF_LockServer }; -static IClassFactoryImpl Wave_CF = {&WaveCF_Vtbl, 1 }; +static IClassFactoryImpl Wave_CF = {&WaveCF_Vtbl}; /****************************************************************** * DllMain @@ -94,8 +102,7 @@ * */ HRESULT WINAPI DSWAVE_DllCanUnloadNow(void) { - FIXME("(void): stub\n"); - return S_FALSE; + return DSWAVE_refCount != 0 ? S_FALSE : S_OK; } diff -urN wine-20050111/dlls/dswave/dswave_private.h wine-20050211/dlls/dswave/dswave_private.h --- wine-20050111/dlls/dswave/dswave_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dswave/dswave_private.h 2005-02-01 15:21:37.000000000 +0100 @@ -130,6 +130,12 @@ extern HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty); extern HRESULT WINAPI IDirectMusicWaveImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize); +/********************************************************************** + * Dll lifetime tracking declaration for dswave.dll + */ +extern LONG DSWAVE_refCount; +static inline void DSWAVE_LockModule() { InterlockedIncrement( &DSWAVE_refCount ); } +static inline void DSWAVE_UnlockModule() { InterlockedDecrement( &DSWAVE_refCount ); } /***************************************************************************** * Misc. diff -urN wine-20050111/dlls/dxdiagn/Makefile.in wine-20050211/dlls/dxdiagn/Makefile.in --- wine-20050111/dlls/dxdiagn/Makefile.in 2004-04-19 04:57:09.000000000 +0200 +++ wine-20050211/dlls/dxdiagn/Makefile.in 2005-01-27 11:42:00.000000000 +0100 @@ -3,7 +3,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = dxdiagn.dll -IMPORTS = ole32 user32 advapi32 kernel32 +IMPORTS = ole32 oleaut32 user32 advapi32 kernel32 EXTRALIBS = -ldxguid -luuid C_SRCS = \ diff -urN wine-20050111/dlls/dxdiagn/container.c wine-20050211/dlls/dxdiagn/container.c --- wine-20050111/dlls/dxdiagn/container.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dxdiagn/container.c 2005-02-01 15:23:07.000000000 +0100 @@ -44,18 +44,28 @@ ULONG WINAPI IDxDiagContainerImpl_AddRef(PDXDIAGCONTAINER iface) { IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DXDIAGN_LockModule(); + + return refCount; } ULONG WINAPI IDxDiagContainerImpl_Release(PDXDIAGCONTAINER iface) { IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DXDIAGN_UnlockModule(); + + return refCount; } /* IDxDiagContainer Interface follow: */ @@ -70,9 +80,9 @@ } HRESULT WINAPI IDxDiagContainerImpl_EnumChildContainerNames(PDXDIAGCONTAINER iface, DWORD dwIndex, LPWSTR pwszContainer, DWORD cchContainer) { + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; IDxDiagContainerImpl_SubContainer* p = NULL; DWORD i = 0; - IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; TRACE("(%p, %lu, %s, %lu)\n", iface, dwIndex, debugstr_w(pwszContainer), cchContainer); @@ -99,8 +109,8 @@ } HRESULT WINAPI IDxDiagContainerImpl_GetChildContainer(PDXDIAGCONTAINER iface, LPCWSTR pwszContainer, IDxDiagContainer** ppInstance) { - IDxDiagContainerImpl_SubContainer* p = NULL; IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + IDxDiagContainerImpl_SubContainer* p = NULL; FIXME("(%p, %s, %p)\n", iface, debugstr_w(pwszContainer), ppInstance); @@ -111,7 +121,8 @@ p = This->subContainers; while (NULL != p) { if (0 == lstrcmpW(p->contName, pwszContainer)) { - IDxDiagContainerImpl_QueryInterface((PDXDIAGCONTAINER)p, &IID_IDxDiagContainer, (void**) ppInstance); + IDxDiagContainerImpl_QueryInterface((PDXDIAGCONTAINER)p->pCont, &IID_IDxDiagContainer, (void**) ppInstance); + /*TRACE"(%p) returns %p\n", iface, *ppInstance);*/ return S_OK; } p = p->next; @@ -121,20 +132,128 @@ } HRESULT WINAPI IDxDiagContainerImpl_GetNumberOfProps(PDXDIAGCONTAINER iface, DWORD* pdwCount) { - /* IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; */ - FIXME("(%p, %p): stub\n", iface, pdwCount); + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + TRACE("(%p)\n", iface); + if (NULL == pdwCount) { + return E_INVALIDARG; + } + *pdwCount = This->nProperties; return S_OK; } HRESULT WINAPI IDxDiagContainerImpl_EnumPropNames(PDXDIAGCONTAINER iface, DWORD dwIndex, LPWSTR pwszPropName, DWORD cchPropName) { - /* IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; */ - FIXME("(%p, %lu, %s, %lu): stub\n", iface, dwIndex, debugstr_w(pwszPropName), cchPropName); - return S_OK; + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + IDxDiagContainerImpl_Property* p = NULL; + DWORD i = 0; + + FIXME("(%p, %lu, %s, %lu)\n", iface, dwIndex, debugstr_w(pwszPropName), cchPropName); + + if (NULL == pwszPropName) { + return E_INVALIDARG; + } + if (256 > cchPropName) { + return DXDIAG_E_INSUFFICIENT_BUFFER; + } + + p = This->properties; + while (NULL != p) { + if (dwIndex == i) { + if (cchPropName <= lstrlenW(p->vName)) { + return DXDIAG_E_INSUFFICIENT_BUFFER; + } + lstrcpynW(pwszPropName, p->vName, cchPropName); + return S_OK; + } + p = p->next; + ++i; + } + return E_INVALIDARG; } HRESULT WINAPI IDxDiagContainerImpl_GetProp(PDXDIAGCONTAINER iface, LPCWSTR pwszPropName, VARIANT* pvarProp) { - /* IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; */ - FIXME("(%p, %s, %p): stub\n", iface, debugstr_w(pwszPropName), pvarProp); + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + IDxDiagContainerImpl_Property* p = NULL; + FIXME("(%p, %s, %p)\n", iface, debugstr_w(pwszPropName), pvarProp); + + if (NULL == pvarProp || NULL == pwszPropName) { + return E_INVALIDARG; + } + + p = This->properties; + while (NULL != p) { + if (0 == lstrcmpW(p->vName, pwszPropName)) { + VariantCopy(pvarProp, &p->v); + return S_OK; + } + p = p->next; + } + return S_OK; +} + +HRESULT WINAPI IDxDiagContainerImpl_AddProp(PDXDIAGCONTAINER iface, LPCWSTR pwszPropName, VARIANT* pVarProp) { + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + IDxDiagContainerImpl_Property* p = NULL; + IDxDiagContainerImpl_Property* pNew = NULL; + + FIXME("(%p, %s, %p)\n", iface, debugstr_w(pwszPropName), pVarProp); + + if (NULL == pVarProp || NULL == pwszPropName) { + return E_INVALIDARG; + } + + pNew = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDxDiagContainerImpl_Property)); + if (NULL == pNew) { + return E_OUTOFMEMORY; + } + VariantInit(&pNew->v); + VariantCopy(&pNew->v, pVarProp); + pNew->vName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lstrlenW(pwszPropName) * sizeof(WCHAR)); + lstrcpyW(pNew->vName, pwszPropName); + pNew->next = NULL; + + p = This->properties; + if (NULL == p) { + This->properties = pNew; + } else { + while (NULL != p->next) { + p = p->next; + } + p->next = pNew; + } + ++This->nProperties; + return S_OK; +} + +HRESULT WINAPI IDxDiagContainerImpl_AddChildContainer(PDXDIAGCONTAINER iface, LPCWSTR pszContName, PDXDIAGCONTAINER pSubCont) { + IDxDiagContainerImpl *This = (IDxDiagContainerImpl *)iface; + IDxDiagContainerImpl_SubContainer* p = NULL; + IDxDiagContainerImpl_SubContainer* pNew = NULL; + + FIXME("(%p, %s, %p)\n", iface, debugstr_w(pszContName), pSubCont); + + if (NULL == pSubCont || NULL == pszContName) { + return E_INVALIDARG; + } + + pNew = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDxDiagContainerImpl_SubContainer)); + if (NULL == pNew) { + return E_OUTOFMEMORY; + } + pNew->pCont = pSubCont; + pNew->contName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lstrlenW(pszContName) * sizeof(WCHAR)); + lstrcpyW(pNew->contName, pszContName); + pNew->next = NULL; + + p = This->subContainers; + if (NULL == p) { + This->subContainers = pNew; + } else { + while (NULL != p->next) { + p = p->next; + } + p->next = pNew; + } + ++This->nSubContainers; return S_OK; } diff -urN wine-20050111/dlls/dxdiagn/dxdiag_main.c wine-20050211/dlls/dxdiagn/dxdiag_main.c --- wine-20050111/dlls/dxdiagn/dxdiag_main.c 2004-09-28 21:19:27.000000000 +0200 +++ wine-20050211/dlls/dxdiagn/dxdiag_main.c 2005-02-01 15:23:07.000000000 +0100 @@ -25,6 +25,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dxdiag); +LONG DXDIAGN_refCount = 0; + /* At process attach */ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) { @@ -39,41 +41,46 @@ * DXDiag ClassFactory */ typedef struct { - /* IUnknown fields */ IClassFactoryVtbl *lpVtbl; - DWORD ref; REFCLSID rclsid; HRESULT (*pfnCreateInstanceFactory)(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj); } IClassFactoryImpl; static HRESULT WINAPI DXDiagCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); + + if (ppobj == NULL) return E_POINTER; - FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); return E_NOINTERFACE; } static ULONG WINAPI DXDiagCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); + DXDIAGN_LockModule(); + + return 2; /* non-heap based object */ } static ULONG WINAPI DXDiagCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); + DXDIAGN_UnlockModule(); + + return 1; /* non-heap based object */ } static HRESULT WINAPI DXDiagCF_CreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + return This->pfnCreateInstanceFactory(iface, pOuter, riid, ppobj); } static HRESULT WINAPI DXDiagCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); + TRACE("(%d)\n", dolock); + + if (dolock) + DXDIAGN_LockModule(); + else + DXDIAGN_UnlockModule(); + return S_OK; } @@ -86,8 +93,8 @@ }; static IClassFactoryImpl DXDiag_CFS[] = { - { &DXDiagCF_Vtbl, 1, &CLSID_DxDiagProvider, DXDiag_CreateDXDiagProvider }, - { NULL, 0, NULL, NULL } + { &DXDiagCF_Vtbl, &CLSID_DxDiagProvider, DXDiag_CreateDXDiagProvider }, + { NULL, NULL, NULL } }; /*********************************************************************** @@ -95,7 +102,7 @@ */ HRESULT WINAPI DllCanUnloadNow(void) { - return S_FALSE; + return DXDIAGN_refCount != 0 ? S_FALSE : S_OK; } /*********************************************************************** diff -urN wine-20050111/dlls/dxdiagn/dxdiag_private.h wine-20050211/dlls/dxdiagn/dxdiag_private.h --- wine-20050111/dlls/dxdiagn/dxdiag_private.h 2004-08-22 23:38:47.000000000 +0200 +++ wine-20050211/dlls/dxdiagn/dxdiag_private.h 2005-02-01 15:23:07.000000000 +0100 @@ -77,6 +77,13 @@ struct IDxDiagContainerImpl_SubContainer* next; } IDxDiagContainerImpl_SubContainer; +typedef struct IDxDiagContainerImpl_Property { + LPWSTR vName; + VARIANT v; + struct IDxDiagContainerImpl_Property* next; +} IDxDiagContainerImpl_Property; + + /***************************************************************************** * Predeclare the interface implementation structures */ @@ -90,7 +97,9 @@ IDxDiagContainerVtbl *lpVtbl; DWORD ref; /* IDxDiagContainer fields */ + IDxDiagContainerImpl_Property* properties; IDxDiagContainerImpl_SubContainer* subContainers; + DWORD nProperties; DWORD nSubContainers; }; @@ -107,6 +116,10 @@ extern HRESULT WINAPI IDxDiagContainerImpl_EnumPropNames(PDXDIAGCONTAINER iface, DWORD dwIndex, LPWSTR pwszPropName, DWORD cchPropName); extern HRESULT WINAPI IDxDiagContainerImpl_GetProp(PDXDIAGCONTAINER iface, LPCWSTR pwszPropName, VARIANT* pvarProp); +/** Internal */ +extern HRESULT WINAPI IDxDiagContainerImpl_AddProp(PDXDIAGCONTAINER iface, LPCWSTR pwszPropName, VARIANT* pVarProp); +extern HRESULT WINAPI IDxDiagContainerImpl_AddChildContainer(PDXDIAGCONTAINER iface, LPCWSTR pszContName, PDXDIAGCONTAINER pSubCont); + /** * factories */ @@ -114,7 +127,13 @@ /** internal factory */ extern HRESULT DXDiag_CreateDXDiagContainer(REFIID riid, LPVOID *ppobj); +extern HRESULT DXDiag_InitRootDXDiagContainer(IDxDiagContainer* pRootCont); - +/********************************************************************** + * Dll lifetime tracking declaration for dxdiagn.dll + */ +extern LONG DXDIAGN_refCount; +static inline void DXDIAGN_LockModule() { InterlockedIncrement( &DXDIAGN_refCount ); } +static inline void DXDIAGN_UnlockModule() { InterlockedDecrement( &DXDIAGN_refCount ); } #endif diff -urN wine-20050111/dlls/dxdiagn/provider.c wine-20050211/dlls/dxdiagn/provider.c --- wine-20050111/dlls/dxdiagn/provider.c 2004-09-06 23:34:25.000000000 +0200 +++ wine-20050211/dlls/dxdiagn/provider.c 2005-02-01 15:23:07.000000000 +0100 @@ -43,18 +43,28 @@ ULONG WINAPI IDxDiagProviderImpl_AddRef(PDXDIAGPROVIDER iface) { IDxDiagProviderImpl *This = (IDxDiagProviderImpl *)iface; - TRACE("(%p) : AddRef from %ld\n", This, This->ref); - return ++(This->ref); + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount - 1); + + DXDIAGN_LockModule(); + + return refCount; } ULONG WINAPI IDxDiagProviderImpl_Release(PDXDIAGPROVIDER iface) { IDxDiagProviderImpl *This = (IDxDiagProviderImpl *)iface; - ULONG ref = --This->ref; - TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref); - if (ref == 0) { + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(ref before=%lu)\n", This, refCount + 1); + + if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } - return ref; + + DXDIAGN_UnlockModule(); + + return refCount; } /* IDxDiagProvider Interface follow: */ @@ -90,6 +100,7 @@ if (FAILED(hr)) { return hr; } + hr = DXDiag_InitRootDXDiagContainer((PDXDIAGCONTAINER)This->pRootContainer); } return IDxDiagContainerImpl_QueryInterface((PDXDIAGCONTAINER)This->pRootContainer, &IID_IDxDiagContainer, (void**) ppInstance); } @@ -117,3 +128,31 @@ provider->ref = 0; /* will be inited with QueryInterface */ return IDxDiagProviderImpl_QueryInterface ((PDXDIAGPROVIDER)provider, riid, ppobj); } + +HRESULT DXDiag_InitRootDXDiagContainer(IDxDiagContainer* pRootCont) { + static const WCHAR DxDiag_SystemInfo[] = {'D','x','D','i','a','g','_','S','y','s','t','e','m','I','n','f','o',0}; + static const WCHAR dwDirectXVersionMajor[] = {'d','w','D','i','r','e','c','t','X','V','e','r','s','i','o','n','M','a','j','o','r',0}; + static const WCHAR dwDirectXVersionMinor[] = {'d','w','D','i','r','e','c','t','X','V','e','r','s','i','o','n','M','i','n','o','r',0}; + static const WCHAR szDirectXVersionLetter[] = {'s','z','D','i','r','e','c','t','X','V','e','r','s','i','o','n','L','e','t','t','e','r',0}; + static const WCHAR szDirectXVersionLetter_v[] = {'c',0}; + + IDxDiagContainer* pSubCont = NULL; + VARIANT v; + HRESULT hr = S_OK; + + TRACE("(%p)\n", pRootCont); + + hr = DXDiag_CreateDXDiagContainer(&IID_IDxDiagContainer, (void**) &pSubCont); + if (FAILED(hr)) { + return hr; + } + V_VT(&v) = VT_UI4; V_UI4(&v) = 9; + hr = IDxDiagContainerImpl_AddProp(pSubCont, dwDirectXVersionMajor, &v); + V_VT(&v) = VT_UI4; V_UI4(&v) = 0; + hr = IDxDiagContainerImpl_AddProp(pSubCont, dwDirectXVersionMinor, &v); + V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szDirectXVersionLetter_v); + hr = IDxDiagContainerImpl_AddProp(pSubCont, szDirectXVersionLetter, &v); + + hr = IDxDiagContainerImpl_AddChildContainer(pRootCont, DxDiag_SystemInfo, pSubCont); + return hr; +} diff -urN wine-20050111/dlls/gdi/freetype.c wine-20050211/dlls/gdi/freetype.c --- wine-20050111/dlls/gdi/freetype.c 2005-01-05 18:12:07.000000000 +0100 +++ wine-20050211/dlls/gdi/freetype.c 2005-01-24 20:00:10.000000000 +0100 @@ -1425,6 +1425,10 @@ LONG ppem = 0; int i; + /* For documentation on VDMX records, see + * http://www.microsoft.com/OpenType/OTSpec/vdmx.htm + */ + result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6); if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */ @@ -1447,9 +1451,6 @@ TRACE("Ratios[%d] %d %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio); - if(ratio.bCharSet != 1) - continue; - if((ratio.xRatio == 0 && ratio.yStartRatio == 0 && ratio.yEndRatio == 0) || diff -urN wine-20050111/dlls/gdi/gdi32.spec wine-20050211/dlls/gdi/gdi32.spec --- wine-20050111/dlls/gdi/gdi32.spec 2005-01-03 15:33:07.000000000 +0100 +++ wine-20050211/dlls/gdi/gdi32.spec 2005-01-12 20:57:08.000000000 +0100 @@ -425,11 +425,9 @@ @ stdcall DeleteMetaFile16(long) @ stdcall DrvGetPrinterData16(str str ptr ptr long ptr) @ stdcall DrvSetPrinterData16(str str long ptr long) -@ stdcall GetDCState16(long) @ stdcall OpenJob16(str str long) @ stdcall SelectVisRgn16(long long) @ stdcall SetDCHook(long ptr long) -@ stdcall SetDCState16(long long) @ stdcall SetHookFlags16(long long) @ stdcall WriteSpool16(long ptr long) diff -urN wine-20050111/dlls/gdi/metafile.c wine-20050211/dlls/gdi/metafile.c --- wine-20050111/dlls/gdi/metafile.c 2004-12-23 19:41:06.000000000 +0100 +++ wine-20050211/dlls/gdi/metafile.c 2005-01-26 20:41:58.000000000 +0100 @@ -245,6 +245,10 @@ HeapFree( GetProcessHeap(), 0, mh ); return NULL; } + if(mh->mtVersion != MFVERSION || mh->mtHeaderSize != size / 2) { + HeapFree( GetProcessHeap(), 0, mh ); + return NULL; + } size = mh->mtSize * 2; mh = HeapReAlloc( GetProcessHeap(), 0, mh, size ); if(!mh) return NULL; diff -urN wine-20050111/dlls/gdi/mfdrv/objects.c wine-20050211/dlls/gdi/mfdrv/objects.c --- wine-20050111/dlls/gdi/mfdrv/objects.c 2004-11-22 19:19:59.000000000 +0100 +++ wine-20050211/dlls/gdi/mfdrv/objects.c 2005-01-14 16:12:59.000000000 +0100 @@ -126,6 +126,68 @@ return 0; } +/*********************************************************************** + * Internal helper for MFDRV_CreateBrushIndirect(): + * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits. + */ +static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width) +{ + int bytes16 = 2 * ((width + 15) / 16); + int bytes32 = 4 * ((width + 31) / 32); + LPBYTE lpSrc, lpDst; + int i; + + if (!height) + return; + + height = abs(height) - 1; + lpSrc = lpRows + height * bytes16; + lpDst = lpRows + height * bytes32; + + /* Note that we work backwards so we can re-pad in place */ + while (height >= 0) + { + for (i = bytes32; i > bytes16; i--) + lpDst[i - 1] = 0; /* Zero the padding bytes */ + for (; i > 0; i--) + lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */ + lpSrc -= bytes16; + lpDst -= bytes32; + height--; + } +} + +/*********************************************************************** + * Internal helper for MFDRV_CreateBrushIndirect(): + * Reverse order of bitmap rows in going from BMP to DIB. + */ +static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width) +{ + int bytes = 4 * ((width + 31) / 32); + LPBYTE lpSrc, lpDst; + BYTE temp; + int i; + + if (!height) + return; + + lpSrc = lpRows; + lpDst = lpRows + (height-1) * bytes; + height = height/2; + + while (height > 0) + { + for (i = 0; i < bytes; i++) + { + temp = lpDst[i]; + lpDst[i] = lpSrc[i]; + lpSrc[i] = temp; + } + lpSrc += bytes; + lpDst -= bytes; + height--; + } +} /****************************************************************** * MFDRV_CreateBrushIndirect @@ -162,9 +224,9 @@ case BS_PATTERN: { BITMAP bm; - BYTE *bits; BITMAPINFO *info; DWORD bmSize; + COLORREF cref; GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm); if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) { @@ -190,12 +252,30 @@ info->bmiHeader.biHeight = bm.bmHeight; info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = 1; - bits = ((BYTE *)info) + sizeof(BITMAPINFO) + sizeof(RGBQUAD); + info->bmiHeader.biSizeImage = bmSize; - GetDIBits(physDev->hdc, (HANDLE)logbrush.lbHatch, 0, bm.bmHeight, - bits, info, DIB_RGB_COLORS); - *(DWORD *)info->bmiColors = 0; - *(DWORD *)(info->bmiColors + 1) = 0xffffff; + GetBitmapBits((HANDLE)logbrush.lbHatch, + bm.bmHeight * BITMAP_GetWidthBytes (bm.bmWidth, bm.bmBitsPixel), + (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD)); + + /* Change the padding to be DIB compatible if needed */ + if(bm.bmWidth & 31) + MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), + bm.bmWidth, bm.bmHeight); + /* BMP and DIB have opposite row order conventions */ + MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), + bm.bmWidth, bm.bmHeight); + + cref = GetTextColor(physDev->hdc); + info->bmiColors[0].rgbRed = GetRValue(cref); + info->bmiColors[0].rgbGreen = GetGValue(cref); + info->bmiColors[0].rgbBlue = GetBValue(cref); + info->bmiColors[0].rgbReserved = 0; + cref = GetBkColor(physDev->hdc); + info->bmiColors[1].rgbRed = GetRValue(cref); + info->bmiColors[1].rgbGreen = GetGValue(cref); + info->bmiColors[1].rgbBlue = GetBValue(cref); + info->bmiColors[1].rgbReserved = 0; break; } diff -urN wine-20050111/dlls/gdi/tests/metafile.c wine-20050211/dlls/gdi/tests/metafile.c --- wine-20050111/dlls/gdi/tests/metafile.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050211/dlls/gdi/tests/metafile.c 2005-01-14 16:12:59.000000000 +0100 @@ -442,8 +442,5 @@ /* For win-format metafiles (mfdrv) */ test_mf_Blank(); test_mf_Graphics(); - - /* Crashes under wine: */ - /* test_mf_PatternBrush(); */ - + test_mf_PatternBrush(); } diff -urN wine-20050111/dlls/itss/itss.c wine-20050211/dlls/itss/itss.c --- wine-20050111/dlls/itss/itss.c 2005-01-03 15:39:51.000000000 +0100 +++ wine-20050211/dlls/itss/itss.c 2005-01-14 18:21:00.000000000 +0100 @@ -163,7 +163,7 @@ }; -HRESULT WINAPI ITSS_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { DWORD i; IClassFactoryImpl *factory; @@ -407,13 +407,13 @@ /*****************************************************************************/ -HRESULT WINAPI ITSS_DllRegisterServer(void) +HRESULT WINAPI DllRegisterServer(void) { FIXME("\n"); return S_OK; } -HRESULT WINAPI ITSS_DllCanUnloadNow(void) +HRESULT WINAPI DllCanUnloadNow(void) { TRACE("dll_count = %lu\n", dll_count); return dll_count ? S_FALSE : S_OK; diff -urN wine-20050111/dlls/itss/itss.spec wine-20050211/dlls/itss/itss.spec --- wine-20050111/dlls/itss/itss.spec 2004-08-24 23:00:15.000000000 +0200 +++ wine-20050211/dlls/itss/itss.spec 2005-01-14 18:21:00.000000000 +0100 @@ -1,5 +1,5 @@ -@ stdcall -private DllCanUnloadNow() ITSS_DllCanUnloadNow -@ stdcall -private DllGetClassObject(ptr ptr ptr) ITSS_DllGetClassObject +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) @ stub DllInstall -@ stdcall -private DllRegisterServer() ITSS_DllRegisterServer +@ stdcall -private DllRegisterServer() @ stub DllUnregisterServer diff -urN wine-20050111/dlls/itss/moniker.c wine-20050211/dlls/itss/moniker.c --- wine-20050111/dlls/itss/moniker.c 2005-01-03 15:39:51.000000000 +0100 +++ wine-20050211/dlls/itss/moniker.c 2005-02-09 14:26:46.000000000 +0100 @@ -471,6 +471,9 @@ { ITS_IParseDisplayNameImpl *its; + if( pUnkOuter ) + return CLASS_E_NOAGGREGATION; + its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) ); its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl; its->ref = 1; diff -urN wine-20050111/dlls/kernel/Makefile.in wine-20050211/dlls/kernel/Makefile.in --- wine-20050111/dlls/kernel/Makefile.in 2004-08-19 03:20:45.000000000 +0200 +++ wine-20050211/dlls/kernel/Makefile.in 2005-02-03 17:58:21.000000000 +0100 @@ -75,6 +75,7 @@ wowthunk.c C_SRCS16 = \ + atom16.c \ error16.c \ registry16.c diff -urN wine-20050111/dlls/kernel/atom.c wine-20050211/dlls/kernel/atom.c --- wine-20050111/dlls/kernel/atom.c 2004-08-11 01:43:21.000000000 +0200 +++ wine-20050211/dlls/kernel/atom.c 2005-02-03 17:58:21.000000000 +0100 @@ -40,79 +40,13 @@ #include "wine/server.h" #include "wine/unicode.h" -#include "wine/winbase16.h" #include "kernel_private.h" -#include "stackframe.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(atom); -#define DEFAULT_ATOMTABLE_SIZE 37 -#define MAX_ATOM_LEN 255 - -#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2) -#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2))) - -typedef struct -{ - HANDLE16 next; - WORD refCount; - BYTE length; - BYTE str[1]; -} ATOMENTRY; - -typedef struct -{ - WORD size; - HANDLE16 entries[1]; -} ATOMTABLE; - - -/*********************************************************************** - * ATOM_GetTable - * - * Return a pointer to the atom table of a given segment, creating - * it if necessary. - * - * RETURNS - * Pointer to table: Success - * NULL: Failure - */ -static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ ) -{ - INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); - if (ptr->atomtable) - { - ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable); - if (table->size) return table; - } - if (!create) return NULL; - if (!InitAtomTable16( 0 )) return NULL; - /* Reload ptr in case it moved in linear memory */ - ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); - return (ATOMTABLE *)((char *)ptr + ptr->atomtable); -} - - -/*********************************************************************** - * ATOM_Hash - * RETURNS - * The hash value for the input string - */ -static WORD ATOM_Hash( - WORD entries, /* [in] Total number of entries */ - LPCSTR str, /* [in] Pointer to string to hash */ - WORD len /* [in] Length of string */ -) { - WORD i, hash = 0; - - TRACE("%x, %s, %x\n", entries, str, len); - - for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i; - return hash % entries; -} - +#define MAX_ATOM_LEN 255 /*********************************************************************** * ATOM_IsIntAtomA @@ -169,222 +103,6 @@ /*********************************************************************** - * ATOM_MakePtr - * - * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()). - */ -static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ ) -{ - return MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); -} - - -/*********************************************************************** - * InitAtomTable (KERNEL.68) - */ -WORD WINAPI InitAtomTable16( WORD entries ) -{ - int i; - HANDLE16 handle; - ATOMTABLE *table; - - /* Allocate the table */ - - if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */ - handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) ); - if (!handle) return 0; - table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); - table->size = entries; - for (i = 0; i < entries; i++) table->entries[i] = 0; - - /* Store a pointer to the table in the instance data */ - - ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle; - return handle; -} - -/*********************************************************************** - * GetAtomHandle (KERNEL.73) - */ -HANDLE16 WINAPI GetAtomHandle16( ATOM atom ) -{ - if (atom < MAXINTATOM) return 0; - return ATOMTOHANDLE( atom ); -} - - -/*********************************************************************** - * AddAtom (KERNEL.70) - * - * Windows DWORD aligns the atom entry size. - * The remaining unused string space created by the alignment - * gets padded with '\0's in a certain way to ensure - * that at least one trailing '\0' remains. - * - * RETURNS - * Atom: Success - * 0: Failure - */ -ATOM WINAPI AddAtom16( LPCSTR str ) -{ - char buffer[MAX_ATOM_LEN+1]; - WORD hash; - HANDLE16 entry; - ATOMENTRY * entryPtr; - ATOMTABLE * table; - int len, ae_len; - WORD iatom; - - if (ATOM_IsIntAtomA( str, &iatom )) return iatom; - - TRACE("%s\n",debugstr_a(buffer)); - - /* Make a copy of the string to be sure it doesn't move in linear memory. */ - lstrcpynA( buffer, str, sizeof(buffer) ); - - len = strlen( buffer ); - if (!(table = ATOM_GetTable( TRUE ))) return 0; - - hash = ATOM_Hash( table->size, buffer, len ); - entry = table->entries[hash]; - while (entry) - { - entryPtr = ATOM_MakePtr( entry ); - if ((entryPtr->length == len) && - (!strncasecmp( entryPtr->str, buffer, len ))) - { - entryPtr->refCount++; - TRACE("-- existing 0x%x\n", entry); - return HANDLETOATOM( entry ); - } - entry = entryPtr->next; - } - - ae_len = (sizeof(ATOMENTRY)+len+3) & ~3; - entry = LocalAlloc16( LMEM_FIXED, ae_len ); - if (!entry) return 0; - /* Reload the table ptr in case it moved in linear memory */ - table = ATOM_GetTable( FALSE ); - entryPtr = ATOM_MakePtr( entry ); - entryPtr->next = table->entries[hash]; - entryPtr->refCount = 1; - entryPtr->length = len; - /* Some applications _need_ the '\0' padding provided by this strncpy */ - strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 ); - entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0'; - table->entries[hash] = entry; - TRACE("-- new 0x%x\n", entry); - return HANDLETOATOM( entry ); -} - - -/*********************************************************************** - * DeleteAtom (KERNEL.71) - */ -ATOM WINAPI DeleteAtom16( ATOM atom ) -{ - ATOMENTRY * entryPtr; - ATOMTABLE * table; - HANDLE16 entry, *prevEntry; - WORD hash; - - if (atom < MAXINTATOM) return 0; /* Integer atom */ - - TRACE("0x%x\n",atom); - - if (!(table = ATOM_GetTable( FALSE ))) return 0; - entry = ATOMTOHANDLE( atom ); - entryPtr = ATOM_MakePtr( entry ); - - /* Find previous atom */ - hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length ); - prevEntry = &table->entries[hash]; - while (*prevEntry && *prevEntry != entry) - { - ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry ); - prevEntry = &prevEntryPtr->next; - } - if (!*prevEntry) return atom; - - /* Delete atom */ - if (--entryPtr->refCount == 0) - { - *prevEntry = entryPtr->next; - LocalFree16( entry ); - } - return 0; -} - - -/*********************************************************************** - * FindAtom (KERNEL.69) - */ -ATOM WINAPI FindAtom16( LPCSTR str ) -{ - ATOMTABLE * table; - WORD hash,iatom; - HANDLE16 entry; - int len; - - TRACE("%s\n",debugstr_a(str)); - - if (ATOM_IsIntAtomA( str, &iatom )) return iatom; - if ((len = strlen( str )) > 255) len = 255; - if (!(table = ATOM_GetTable( FALSE ))) return 0; - hash = ATOM_Hash( table->size, str, len ); - entry = table->entries[hash]; - while (entry) - { - ATOMENTRY * entryPtr = ATOM_MakePtr( entry ); - if ((entryPtr->length == len) && - (!strncasecmp( entryPtr->str, str, len ))) - { - TRACE("-- found %x\n", entry); - return HANDLETOATOM( entry ); - } - entry = entryPtr->next; - } - TRACE("-- not found\n"); - return 0; -} - - -/*********************************************************************** - * GetAtomName (KERNEL.72) - */ -UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count ) -{ - ATOMTABLE * table; - ATOMENTRY * entryPtr; - HANDLE16 entry; - char * strPtr; - INT len; - char text[8]; - - TRACE("%x\n",atom); - - if (!count) return 0; - if (atom < MAXINTATOM) - { - sprintf( text, "#%d", atom ); - len = strlen(text); - strPtr = text; - } - else - { - if (!(table = ATOM_GetTable( FALSE ))) return 0; - entry = ATOMTOHANDLE( atom ); - entryPtr = ATOM_MakePtr( entry ); - len = entryPtr->length; - strPtr = entryPtr->str; - } - if (len >= count) len = count-1; - memcpy( buffer, strPtr, len ); - buffer[len] = '\0'; - return len; -} - -/*********************************************************************** * InitAtomTable (KERNEL32.@) * * Initialise the global atom table. diff -urN wine-20050111/dlls/kernel/atom16.c wine-20050211/dlls/kernel/atom16.c --- wine-20050111/dlls/kernel/atom16.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/kernel/atom16.c 2005-02-03 17:58:21.000000000 +0100 @@ -0,0 +1,357 @@ +/* + * Atom table functions - 16 bit variant + * + * Copyright 1993, 1994, 1995 Alexandre Julliard + * + * 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 + */ + +/* + * Warning: The code assumes that LocalAlloc() returns a block aligned + * on a 4-bytes boundary (because of the shifting done in + * HANDLETOATOM). If this is not the case, the allocation code will + * have to be changed. + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "wine/server.h" +#include "wine/unicode.h" +#include "wine/winbase16.h" +#include "kernel_private.h" +#include "stackframe.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(atom); + +#define DEFAULT_ATOMTABLE_SIZE 37 +#define MAX_ATOM_LEN 255 + +#define ATOMTOHANDLE(atom) ((HANDLE16)(atom) << 2) +#define HANDLETOATOM(handle) ((ATOM)(0xc000 | ((handle) >> 2))) + +typedef struct +{ + HANDLE16 next; + WORD refCount; + BYTE length; + BYTE str[1]; +} ATOMENTRY; + +typedef struct +{ + WORD size; + HANDLE16 entries[1]; +} ATOMTABLE; + + +/*********************************************************************** + * ATOM_GetTable + * + * Return a pointer to the atom table of a given segment, creating + * it if necessary. + * + * RETURNS + * Pointer to table: Success + * NULL: Failure + */ +static ATOMTABLE *ATOM_GetTable( BOOL create /* [in] Create */ ) +{ + INSTANCEDATA *ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); + if (ptr->atomtable) + { + ATOMTABLE *table = (ATOMTABLE *)((char *)ptr + ptr->atomtable); + if (table->size) return table; + } + if (!create) return NULL; + if (!InitAtomTable16( 0 )) return NULL; + /* Reload ptr in case it moved in linear memory */ + ptr = MapSL( MAKESEGPTR( CURRENT_DS, 0 ) ); + return (ATOMTABLE *)((char *)ptr + ptr->atomtable); +} + + +/*********************************************************************** + * ATOM_Hash + * RETURNS + * The hash value for the input string + */ +static WORD ATOM_Hash( + WORD entries, /* [in] Total number of entries */ + LPCSTR str, /* [in] Pointer to string to hash */ + WORD len /* [in] Length of string */ +) { + WORD i, hash = 0; + + TRACE("%x, %s, %x\n", entries, str, len); + + for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i; + return hash % entries; +} + + +/*********************************************************************** + * ATOM_IsIntAtomA + */ +static BOOL ATOM_IsIntAtomA(LPCSTR atomstr,WORD *atomid) +{ + UINT atom = 0; + if (!HIWORD(atomstr)) atom = LOWORD(atomstr); + else + { + if (*atomstr++ != '#') return FALSE; + while (*atomstr >= '0' && *atomstr <= '9') + { + atom = atom * 10 + *atomstr - '0'; + atomstr++; + } + if (*atomstr) return FALSE; + } + if (atom >= MAXINTATOM) + { + SetLastError( ERROR_INVALID_PARAMETER ); + atom = 0; + } + *atomid = atom; + return TRUE; +} + + +/*********************************************************************** + * ATOM_MakePtr + * + * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()). + */ +static inline ATOMENTRY *ATOM_MakePtr( HANDLE16 handle /* [in] Handle */ ) +{ + return MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); +} + + +/*********************************************************************** + * InitAtomTable (KERNEL.68) + */ +WORD WINAPI InitAtomTable16( WORD entries ) +{ + int i; + HANDLE16 handle; + ATOMTABLE *table; + + /* Allocate the table */ + + if (!entries) entries = DEFAULT_ATOMTABLE_SIZE; /* sanity check */ + handle = LocalAlloc16( LMEM_FIXED, sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE16) ); + if (!handle) return 0; + table = MapSL( MAKESEGPTR( CURRENT_DS, handle ) ); + table->size = entries; + for (i = 0; i < entries; i++) table->entries[i] = 0; + + /* Store a pointer to the table in the instance data */ + + ((INSTANCEDATA *)MapSL( MAKESEGPTR( CURRENT_DS, 0 )))->atomtable = handle; + return handle; +} + +/*********************************************************************** + * GetAtomHandle (KERNEL.73) + */ +HANDLE16 WINAPI GetAtomHandle16( ATOM atom ) +{ + if (atom < MAXINTATOM) return 0; + return ATOMTOHANDLE( atom ); +} + + +/*********************************************************************** + * AddAtom (KERNEL.70) + * + * Windows DWORD aligns the atom entry size. + * The remaining unused string space created by the alignment + * gets padded with '\0's in a certain way to ensure + * that at least one trailing '\0' remains. + * + * RETURNS + * Atom: Success + * 0: Failure + */ +ATOM WINAPI AddAtom16( LPCSTR str ) +{ + char buffer[MAX_ATOM_LEN+1]; + WORD hash; + HANDLE16 entry; + ATOMENTRY * entryPtr; + ATOMTABLE * table; + int len, ae_len; + WORD iatom; + + if (ATOM_IsIntAtomA( str, &iatom )) return iatom; + + TRACE("%s\n",debugstr_a(buffer)); + + /* Make a copy of the string to be sure it doesn't move in linear memory. */ + lstrcpynA( buffer, str, sizeof(buffer) ); + + len = strlen( buffer ); + if (!(table = ATOM_GetTable( TRUE ))) return 0; + + hash = ATOM_Hash( table->size, buffer, len ); + entry = table->entries[hash]; + while (entry) + { + entryPtr = ATOM_MakePtr( entry ); + if ((entryPtr->length == len) && + (!strncasecmp( entryPtr->str, buffer, len ))) + { + entryPtr->refCount++; + TRACE("-- existing 0x%x\n", entry); + return HANDLETOATOM( entry ); + } + entry = entryPtr->next; + } + + ae_len = (sizeof(ATOMENTRY)+len+3) & ~3; + entry = LocalAlloc16( LMEM_FIXED, ae_len ); + if (!entry) return 0; + /* Reload the table ptr in case it moved in linear memory */ + table = ATOM_GetTable( FALSE ); + entryPtr = ATOM_MakePtr( entry ); + entryPtr->next = table->entries[hash]; + entryPtr->refCount = 1; + entryPtr->length = len; + /* Some applications _need_ the '\0' padding provided by this strncpy */ + strncpy( entryPtr->str, buffer, ae_len - sizeof(ATOMENTRY) + 1 ); + entryPtr->str[ae_len - sizeof(ATOMENTRY)] = '\0'; + table->entries[hash] = entry; + TRACE("-- new 0x%x\n", entry); + return HANDLETOATOM( entry ); +} + + +/*********************************************************************** + * DeleteAtom (KERNEL.71) + */ +ATOM WINAPI DeleteAtom16( ATOM atom ) +{ + ATOMENTRY * entryPtr; + ATOMTABLE * table; + HANDLE16 entry, *prevEntry; + WORD hash; + + if (atom < MAXINTATOM) return 0; /* Integer atom */ + + TRACE("0x%x\n",atom); + + if (!(table = ATOM_GetTable( FALSE ))) return 0; + entry = ATOMTOHANDLE( atom ); + entryPtr = ATOM_MakePtr( entry ); + + /* Find previous atom */ + hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length ); + prevEntry = &table->entries[hash]; + while (*prevEntry && *prevEntry != entry) + { + ATOMENTRY * prevEntryPtr = ATOM_MakePtr( *prevEntry ); + prevEntry = &prevEntryPtr->next; + } + if (!*prevEntry) return atom; + + /* Delete atom */ + if (--entryPtr->refCount == 0) + { + *prevEntry = entryPtr->next; + LocalFree16( entry ); + } + return 0; +} + + +/*********************************************************************** + * FindAtom (KERNEL.69) + */ +ATOM WINAPI FindAtom16( LPCSTR str ) +{ + ATOMTABLE * table; + WORD hash,iatom; + HANDLE16 entry; + int len; + + TRACE("%s\n",debugstr_a(str)); + + if (ATOM_IsIntAtomA( str, &iatom )) return iatom; + if ((len = strlen( str )) > 255) len = 255; + if (!(table = ATOM_GetTable( FALSE ))) return 0; + hash = ATOM_Hash( table->size, str, len ); + entry = table->entries[hash]; + while (entry) + { + ATOMENTRY * entryPtr = ATOM_MakePtr( entry ); + if ((entryPtr->length == len) && + (!strncasecmp( entryPtr->str, str, len ))) + { + TRACE("-- found %x\n", entry); + return HANDLETOATOM( entry ); + } + entry = entryPtr->next; + } + TRACE("-- not found\n"); + return 0; +} + + +/*********************************************************************** + * GetAtomName (KERNEL.72) + */ +UINT16 WINAPI GetAtomName16( ATOM atom, LPSTR buffer, INT16 count ) +{ + ATOMENTRY * entryPtr; + HANDLE16 entry; + char * strPtr; + INT len; + char text[8]; + + TRACE("%x\n",atom); + + if (!count) return 0; + if (atom < MAXINTATOM) + { + sprintf( text, "#%d", atom ); + len = strlen(text); + strPtr = text; + } + else + { + if (!ATOM_GetTable( FALSE )) return 0; + entry = ATOMTOHANDLE( atom ); + entryPtr = ATOM_MakePtr( entry ); + len = entryPtr->length; + strPtr = entryPtr->str; + } + if (len >= count) len = count-1; + memcpy( buffer, strPtr, len ); + buffer[len] = '\0'; + return len; +} diff -urN wine-20050111/dlls/kernel/change.c wine-20050211/dlls/kernel/change.c --- wine-20050111/dlls/kernel/change.c 2004-05-13 22:21:25.000000000 +0200 +++ wine-20050211/dlls/kernel/change.c 2005-01-31 17:23:31.000000000 +0100 @@ -130,3 +130,14 @@ FIXME("(0x%8x): stub\n", (int) x); return (FARPROC16)TRUE; } + +BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree, + DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped, + LPOVERLAPPED_COMPLETION_ROUTINE completion ) +{ + FIXME( "%p %p 0x%08lx %d 0x%08lx %p %p %p\n", handle, buffer, len, subtree, filter, + returned, overlapped, completion ); + + SetLastError( ERROR_INVALID_FUNCTION ); + return FALSE; +} diff -urN wine-20050111/dlls/kernel/comm.c wine-20050211/dlls/kernel/comm.c --- wine-20050111/dlls/kernel/comm.c 2005-01-07 16:40:09.000000000 +0100 +++ wine-20050211/dlls/kernel/comm.c 2005-01-14 20:54:39.000000000 +0100 @@ -93,8 +93,8 @@ #include "winerror.h" #include "wine/server.h" -#include "async.h" #include "wine/unicode.h" +#include "thread.h" #include "wine/debug.h" @@ -125,32 +125,15 @@ * Asynchronous I/O for asynchronous wait requests * */ -static DWORD commio_get_async_count (const async_private *ovp); -static void commio_async_cleanup (async_private *ovp); - -static async_ops commio_async_ops = -{ - commio_get_async_count, /* get_count */ - NULL, /* call_completion */ - commio_async_cleanup /* cleanup */ -}; - typedef struct async_commio { - struct async_private async; - char *buffer; + HANDLE handle; + PIO_APC_ROUTINE apc_internal; + int type; + char* buffer; + int fd; } async_commio; -static DWORD commio_get_async_count (const struct async_private *ovp) -{ - return 0; -} - -static void commio_async_cleanup (async_private *ovp) -{ - HeapFree(GetProcessHeap(), 0, ovp ); -} - /***********************************************************************/ #if !defined(TIOCINQ) && defined(FIONREAD) @@ -1928,17 +1911,27 @@ * This function is called while the client is waiting on the * server, so we can't make any server calls here. */ -static void COMM_WaitCommEventService(async_private *ovp) +static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status) { async_commio *commio = (async_commio*) ovp; - IO_STATUS_BLOCK* iosb = commio->async.iosb; - TRACE("iosb %p\n",iosb); + TRACE("iosb %p\n", iosb); - /* FIXME: detect other events */ - *commio->buffer = EV_RXCHAR; - - iosb->u.Status = STATUS_SUCCESS; + switch (status) + { + case STATUS_ALERTED: /* got some new stuff */ + /* FIXME: detect other events */ + *commio->buffer = EV_RXCHAR; + iosb->u.Status = STATUS_SUCCESS; + break; + default: + iosb->u.Status = status; + break; + } + wine_server_release_fd( commio->handle, commio->fd ); + if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE ) + NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL ); + HeapFree(GetProcessHeap(), 0, commio ); } @@ -1952,44 +1945,52 @@ LPDWORD lpdwEvents, /* [out] event(s) that were detected */ LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */ { - int fd; - async_commio *ovp; + int fd; + async_commio* commio; + NTSTATUS status; - if(!lpOverlapped) + if (!lpOverlapped) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - if(NtResetEvent(lpOverlapped->hEvent,NULL)) + if (NtResetEvent(lpOverlapped->hEvent,NULL)) return FALSE; fd = get_comm_fd( hFile, GENERIC_WRITE ); - if(fd<0) - return FALSE; + if (fd < 0) return FALSE; - ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio)); - if(!ovp) + commio = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio)); + if (!commio) { release_comm_fd( hFile, fd ); return FALSE; } - ovp->async.ops = &commio_async_ops; - ovp->async.handle = hFile; - ovp->async.fd = fd; /* FIXME */ - ovp->async.type = ASYNC_TYPE_WAIT; - ovp->async.func = COMM_WaitCommEventService; - ovp->async.event = lpOverlapped->hEvent; - ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped; - ovp->buffer = (char *)lpdwEvents; + commio->handle = hFile; + commio->type = ASYNC_TYPE_WAIT; + commio->apc_internal = COMM_WaitCommEventService; + commio->buffer = (char *)lpdwEvents; + commio->fd = fd; /* FIXME */ lpOverlapped->InternalHigh = 0; lpOverlapped->Offset = 0; lpOverlapped->OffsetHigh = 0; - if ( !register_new_async (&ovp->async) ) - SetLastError( ERROR_IO_PENDING ); + SERVER_START_REQ( register_async ) + { + req->handle = hFile; + req->io_apc = COMM_WaitCommEventService; + req->io_user = commio; + req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped; + req->count = 0; + status = wine_server_call( req ); + } + SERVER_END_REQ; + + if ( status ) SetLastError( RtlNtStatusToDosError(status) ); + else NtCurrentTeb()->num_async_io++; return FALSE; } diff -urN wine-20050111/dlls/kernel/cpu.c wine-20050211/dlls/kernel/cpu.c --- wine-20050111/dlls/kernel/cpu.c 2004-12-27 18:16:39.000000000 +0100 +++ wine-20050211/dlls/kernel/cpu.c 2005-01-28 12:29:03.000000000 +0100 @@ -111,6 +111,9 @@ static const WCHAR IdentifierW[] = {'I','d','e','n','t','i','f','i','e','r',0}; static const WCHAR SysidW[] = {'A','T',' ','c','o','m','p','a','t','i','b','l','e',0}; static const WCHAR mhzKeyW[] = {'~','M','H','z',0}; + static const WCHAR VendorIdentifierW[] = {'V','e','n','d','o','r','I','d','e','n','t','i','f','i','e','r',0}; + static const WCHAR VenidIntelW[] = {'G','e','n','u','i','n','e','I','n','t','e','l',0}; + /* static const WCHAR VenidAMDW[] = {'A','u','t','h','e','n','t','i','c','A','M','D',0}; */ unsigned int i; HKEY hkey, system_key, cpu_key; @@ -146,13 +149,21 @@ RtlCreateUnicodeStringFromAsciiz( &nameW, num ); if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) { - WCHAR idW[20]; + WCHAR idW[40]; DWORD cpuMHz = cpuHz / 1000000; - sprintf( id, "CPU %ld", info->dwProcessorType ); + /*TODO: report 64bit processors properly*/ + RtlInitUnicodeString( &valueW, IdentifierW ); + sprintf( id, "x86 Family %d Model %d Stepping %d", + info->wProcessorLevel /*model and family are messed up*/, info->wProcessorLevel, info->wProcessorRevision); + RtlMultiByteToUnicodeN( idW, sizeof(idW), NULL, id, strlen(id)+1 ); NtSetValueKey( hkey, &valueW, 0, REG_SZ, idW, (strlenW(idW)+1)*sizeof(WCHAR) ); + /*TODO; report amd's properly*/ + RtlInitUnicodeString( &valueW, VendorIdentifierW ); + NtSetValueKey( hkey, &valueW, 0, REG_SZ, VenidIntelW, (strlenW(VenidIntelW)+1) * sizeof(WCHAR) ); + RtlInitUnicodeString( &valueW, mhzKeyW ); NtSetValueKey( hkey, &valueW, 0, REG_DWORD, &cpuMHz, sizeof(DWORD) ); NtClose( hkey ); @@ -181,21 +192,8 @@ */ BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) { - LARGE_INTEGER time; - -#if defined(__i386__) && defined(__GNUC__) - if (IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE )) { - /* i586 optimized version */ - __asm__ __volatile__ ( "rdtsc" - : "=a" (counter->u.LowPart), "=d" (counter->u.HighPart) ); - counter->QuadPart = counter->QuadPart / 1000; /* see below */ - return TRUE; - } -#endif - - /* fall back to generic routine (ie, for i386, i486) */ - NtQuerySystemTime( &time ); - counter->QuadPart = time.QuadPart; + LARGE_INTEGER frequency; + NtQueryPerformanceCounter( counter, &frequency ); return TRUE; } @@ -217,17 +215,8 @@ */ BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) { -#if defined(__i386__) && defined(__GNUC__) - if (IsProcessorFeaturePresent( PF_RDTSC_INSTRUCTION_AVAILABLE )) { - /* The way Windows calculates this value is unclear, however simply using the CPU frequency - gives a value out by approximately a thousand. That can cause some applications to crash, - so we divide here to make our number more similar to the one Windows gives */ - frequency->QuadPart = cpuHz / 1000; - return TRUE; - } -#endif - frequency->u.LowPart = 10000000; - frequency->u.HighPart = 0; + LARGE_INTEGER counter; + NtQueryPerformanceCounter( &counter, frequency ); return TRUE; } diff -urN wine-20050111/dlls/kernel/file.c wine-20050211/dlls/kernel/file.c --- wine-20050111/dlls/kernel/file.c 2005-01-11 16:09:01.000000000 +0100 +++ wine-20050211/dlls/kernel/file.c 2005-01-14 20:54:39.000000000 +0100 @@ -43,7 +43,8 @@ #include "excpt.h" #include "wine/unicode.h" #include "wine/debug.h" -#include "async.h" +#include "thread.h" +#include "wine/server.h" WINE_DEFAULT_DEBUG_CHANNEL(file); @@ -512,7 +513,7 @@ else { /* busy loop */ - while ( (volatile DWORD)lpOverlapped->Internal == STATUS_PENDING ) + while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING ) Sleep( 10 ); } } @@ -532,7 +533,7 @@ } if ( r == WAIT_FAILED ) { - ERR("wait operation failed\n"); + WARN("wait operation failed\n"); return FALSE; } if (lpTransferred) *lpTransferred = lpOverlapped->InternalHigh; @@ -556,17 +557,14 @@ */ BOOL WINAPI CancelIo(HANDLE handle) { - async_private *ovp,*t; + IO_STATUS_BLOCK io_status; - TRACE("handle = %p\n",handle); - - for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t) + NtCancelIoFile(handle, &io_status); + if (io_status.u.Status) { - t = ovp->next; - if ( ovp->handle == handle ) - cancel_async ( ovp ); + SetLastError( RtlNtStatusToDosError( io_status.u.Status ) ); + return FALSE; } - SleepEx(1,TRUE); return TRUE; } diff -urN wine-20050111/dlls/kernel/kernel32.spec wine-20050211/dlls/kernel/kernel32.spec --- wine-20050111/dlls/kernel/kernel32.spec 2005-01-03 15:32:16.000000000 +0100 +++ wine-20050211/dlls/kernel/kernel32.spec 2005-01-31 17:23:31.000000000 +0100 @@ -1027,7 +1027,7 @@ @ stdcall OpenWaitableTimerW(long long wstr) @ stub ReadConsoleInputExA @ stub ReadConsoleInputExW -@ stub ReadDirectoryChangesW +@ stdcall ReadDirectoryChangesW(long ptr long long long ptr ptr ptr) @ stub ReadFileScatter @ stub SetConsoleIcon @ stdcall SetConsoleInputExeNameA(ptr) diff -urN wine-20050111/dlls/kernel/lcformat.c wine-20050211/dlls/kernel/lcformat.c --- wine-20050111/dlls/kernel/lcformat.c 2005-01-07 18:08:55.000000000 +0100 +++ wine-20050211/dlls/kernel/lcformat.c 2005-01-27 11:41:40.000000000 +0100 @@ -3,7 +3,7 @@ * * Copyright 1995 Martin von Loewis * Copyright 1998 David Lee Lambert - * Copyright 2000 Julio César Gázquez + * Copyright 2000 Julio César Gázquez * Copyright 2003 Jon Griffiths * * This library is free software; you can redistribute it and/or diff -urN wine-20050111/dlls/kernel/locale.c wine-20050211/dlls/kernel/locale.c --- wine-20050111/dlls/kernel/locale.c 2004-12-23 19:48:47.000000000 +0100 +++ wine-20050211/dlls/kernel/locale.c 2005-01-19 21:59:32.000000000 +0100 @@ -121,7 +121,7 @@ { "ISO88598", 28598 }, { "ISO88599", 28599 }, { "KOI8R", 20866 }, - { "KOI8U", 20866 }, + { "KOI8U", 21866 }, { "UTF8", CP_UTF8 } }; diff -urN wine-20050111/dlls/kernel/nls/ukr.nls wine-20050211/dlls/kernel/nls/ukr.nls --- wine-20050111/dlls/kernel/nls/ukr.nls 2003-09-08 21:38:47.000000000 +0200 +++ wine-20050211/dlls/kernel/nls/ukr.nls 2005-01-19 21:59:32.000000000 +0100 @@ -36,7 +36,7 @@ LOCALE_IDEFAULTEBCDICCODEPAGE "500" LOCALE_IDEFAULTLANGUAGE "0422" LOCALE_IDEFAULTMACCODEPAGE "10017" - LOCALE_IDEFAULTUNIXCODEPAGE "20866" + LOCALE_IDEFAULTUNIXCODEPAGE "21866" LOCALE_IDIGITS "2" LOCALE_IDIGITSUBSTITUTION "1" LOCALE_IFIRSTDAYOFWEEK "0" diff -urN wine-20050111/dlls/kernel/profile.c wine-20050211/dlls/kernel/profile.c --- wine-20050111/dlls/kernel/profile.c 2005-01-11 11:43:24.000000000 +0100 +++ wine-20050211/dlls/kernel/profile.c 2005-02-10 22:22:31.000000000 +0100 @@ -1421,22 +1421,22 @@ RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) + if (!section && !entry && !string) /* documented "file flush" case */ { - if (!section && !entry && !string) /* documented "file flush" case */ + if (!filename || PROFILE_Open( filename )) { + if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ + } + } + else if (PROFILE_Open( filename )) + { + if (!section) { + FIXME("(NULL?,%s,%s,%s)?\n", + debugstr_w(entry), debugstr_w(string), debugstr_w(filename)); + } else { + ret = PROFILE_SetString( section, entry, string, FALSE); PROFILE_FlushFile(); - PROFILE_ReleaseFile(); /* always return FALSE in this case */ } - else { - if (!section) { - FIXME("(NULL?,%s,%s,%s)?\n", - debugstr_w(entry), debugstr_w(string), debugstr_w(filename)); - } else { - ret = PROFILE_SetString( section, entry, string, FALSE); - PROFILE_FlushFile(); - } - } } RtlLeaveCriticalSection( &PROFILE_CritSect ); @@ -1481,10 +1481,15 @@ RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) { - if (!section && !string) - PROFILE_ReleaseFile(); /* always return FALSE in this case */ - else if (!string) {/* delete the named section*/ + if (!section && !string) + { + if (!filename || PROFILE_Open( filename )) + { + if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ + } + } + else if (PROFILE_Open( filename )) { + if (!string) {/* delete the named section*/ ret = PROFILE_SetString(section,NULL,NULL, FALSE); PROFILE_FlushFile(); } else { diff -urN wine-20050111/dlls/kernel/sync.c wine-20050211/dlls/kernel/sync.c --- wine-20050111/dlls/kernel/sync.c 2005-01-07 16:40:09.000000000 +0100 +++ wine-20050211/dlls/kernel/sync.c 2005-02-08 13:08:04.000000000 +0100 @@ -1174,7 +1174,7 @@ /*********************************************************************** * SYNC_CompletePipeOverlapped (Internal) */ -static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result) +static void CALLBACK SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result) { TRACE("for %p result %08lx\n",overlapped,result); if(!overlapped) @@ -1250,7 +1250,7 @@ { if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE)) { - SetLastError(ov.Internal); + SetLastError(RtlNtStatusToDosError(ov.Internal)); ret = (ov.Internal==STATUS_SUCCESS); } } @@ -1310,7 +1310,7 @@ { if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE)) { - SetLastError(ov.Internal); + SetLastError(RtlNtStatusToDosError(ov.Internal)); ret = (ov.Internal==STATUS_SUCCESS); } } @@ -1342,17 +1342,32 @@ /*********************************************************************** * TransactNamedPipe (KERNEL32.@) + * + * BUGS + * should be done as a single operation in the wineserver or kernel */ BOOL WINAPI TransactNamedPipe( - HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput, + HANDLE handle, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput, DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped) { - FIXME("%p %p %ld %p %ld %p %p\n", - hPipe, lpInput, dwInputSize, lpOutput, + BOOL r; + DWORD count; + + TRACE("%p %p %ld %p %ld %p %p\n", + handle, lpInput, dwInputSize, lpOutput, dwOutputSize, lpBytesRead, lpOverlapped); - if(lpBytesRead) - *lpBytesRead=0; - return FALSE; + + if (lpOverlapped) + { + FIXME("Doesn't support overlapped operation as yet\n"); + return FALSE; + } + + r = WriteFile(handle, lpOutput, dwOutputSize, &count, NULL); + if (r) + r = ReadFile(handle, lpInput, dwInputSize, lpBytesRead, NULL); + + return r; } /*********************************************************************** diff -urN wine-20050111/dlls/kernel/tests/comm.c wine-20050211/dlls/kernel/tests/comm.c --- wine-20050111/dlls/kernel/tests/comm.c 2004-08-10 01:42:19.000000000 +0200 +++ wine-20050211/dlls/kernel/tests/comm.c 2005-01-28 15:02:52.000000000 +0100 @@ -409,7 +409,7 @@ pdcb->wReserved1 & 0xffff ); } */ -static void check_result(char *function, TEST *ptest, int initial_value, BOOL result) +static void check_result(const char *function, TEST *ptest, int initial_value, BOOL result) { DWORD LastError = GetLastError(); DWORD CorrectError = (ptest->result ? 0xdeadbeef : ERROR_INVALID_PARAMETER); @@ -421,7 +421,7 @@ #define check_dcb_member(a,b) ok(pdcb1->a == pdcb2->a, "%s(\"%s\"), 0x%02x: "#a" is "b", should be "b"\n", function, ptest->string, initial_value, pdcb1->a, pdcb2->a) #define check_dcb_member2(a,c,b) if(pdcb2->a == c) { check_dcb_member(a,b); } else { ok(pdcb1->a == pdcb2->a || pdcb1->a == c, "%s(\"%s\"), 0x%02x: "#a" is "b", should be "b" or "b"\n", function, ptest->string, initial_value, pdcb1->a, pdcb2->a, c); } -static void check_dcb(char *function, TEST *ptest, int initial_value, DCB *pdcb1, DCB *pdcb2) +static void check_dcb(const char *function, TEST *ptest, int initial_value, DCB *pdcb1, DCB *pdcb2) { /* DCBlength is a special case since Win 9x sets it but NT does not. We will accept either as correct. */ @@ -493,7 +493,7 @@ #define check_timeouts_member(a) ok(ptimeouts1->a == ptimeouts2->a, "%s(\"%s\"), 0x%02x: "#a" is %lu, should be %lu\n", function, ptest->string, initial_value, ptimeouts1->a, ptimeouts2->a); -static void check_timeouts(char *function, TEST *ptest, int initial_value, COMMTIMEOUTS *ptimeouts1, COMMTIMEOUTS *ptimeouts2) +static void check_timeouts(const char *function, TEST *ptest, int initial_value, COMMTIMEOUTS *ptimeouts1, COMMTIMEOUTS *ptimeouts2) { check_timeouts_member(ReadIntervalTimeout); check_timeouts_member(ReadTotalTimeoutMultiplier); diff -urN wine-20050111/dlls/kernel/tests/console.c wine-20050211/dlls/kernel/tests/console.c --- wine-20050111/dlls/kernel/tests/console.c 2004-10-09 01:35:47.000000000 +0200 +++ wine-20050211/dlls/kernel/tests/console.c 2005-01-28 15:02:52.000000000 +0100 @@ -137,8 +137,8 @@ { COORD c; DWORD len, mode; - char* mytest; - int mylen; + const char* mytest = "123"; + const int mylen = strlen(mytest); int ret; int p; @@ -149,10 +149,6 @@ c.X = sbSize.X - 3; c.Y = 0; ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n"); - mytest = "123"; - - mylen = strlen(mytest); - ret = WriteConsole(hCon, mytest, mylen, &len, NULL); ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %ld\n", ret, len); c.Y = 0; diff -urN wine-20050111/dlls/kernel/tests/directory.c wine-20050211/dlls/kernel/tests/directory.c --- wine-20050111/dlls/kernel/tests/directory.c 2004-12-20 20:27:07.000000000 +0100 +++ wine-20050211/dlls/kernel/tests/directory.c 2005-02-10 20:19:36.000000000 +0100 @@ -213,7 +213,7 @@ lstrcatA(tmpdir, "Please Remove Me/Please Remove Me"); ret = CreateDirectoryA(tmpdir, NULL); ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, - "CreateDirectoryA with multiple non-existent directories in path should fail\n"); + "CreateDirectoryA with multiple nonexistent directories in path should fail\n"); ret = RemoveDirectoryA(tmpdir); } @@ -285,7 +285,7 @@ lstrcatW(tmpdir, tmp_dir_name); ret = CreateDirectoryW(tmpdir, NULL); ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, - "CreateDirectoryW with multiple non-existent directories in path should fail\n"); + "CreateDirectoryW with multiple nonexistent directories in path should fail\n"); ret = RemoveDirectoryW(tmpdir); } diff -urN wine-20050111/dlls/kernel/tests/file.c wine-20050211/dlls/kernel/tests/file.c --- wine-20050111/dlls/kernel/tests/file.c 2004-12-27 18:26:38.000000000 +0100 +++ wine-20050211/dlls/kernel/tests/file.c 2005-02-10 20:19:36.000000000 +0100 @@ -690,7 +690,7 @@ ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND, "CreateFileW(\"\") returned ret=%p error=%ld\n",hFile,GetLastError()); - /* test the result of opening a non-existent driver name */ + /* test the result of opening a nonexistent driver name */ hFile = CreateFileW(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND, diff -urN wine-20050111/dlls/kernel/tests/mailslot.c wine-20050211/dlls/kernel/tests/mailslot.c --- wine-20050111/dlls/kernel/tests/mailslot.c 2004-08-10 01:42:19.000000000 +0200 +++ wine-20050211/dlls/kernel/tests/mailslot.c 2005-02-10 20:19:36.000000000 +0100 @@ -51,7 +51,7 @@ /* open a mailslot that doesn't exist */ hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - ok( hWriter == INVALID_HANDLE_VALUE, "non-existing mailslot\n"); + ok( hWriter == INVALID_HANDLE_VALUE, "nonexistent mailslot\n"); /* open a mailslot without the right name */ hSlot = CreateMailslot( "blah", 0, 0, NULL ); diff -urN wine-20050111/dlls/kernel/tests/path.c wine-20050211/dlls/kernel/tests/path.c --- wine-20050111/dlls/kernel/tests/path.c 2004-06-02 02:36:36.000000000 +0200 +++ wine-20050211/dlls/kernel/tests/path.c 2005-02-10 20:19:36.000000000 +0100 @@ -34,9 +34,9 @@ #define SHORTDIR "shortdir" #define LONGDIR "Long Directory" #define NONFILE_SHORT "noexist.pth" -#define NONFILE_LONG "Non Existent File" +#define NONFILE_LONG "NonExistent File" #define NONDIR_SHORT "notadir" -#define NONDIR_LONG "Non Existent Directory" +#define NONDIR_LONG "NonExistent Directory" #define NOT_A_VALID_DRIVE '@' @@ -223,7 +223,7 @@ characters in the filename. 'valid' indicates whether this would be an allowed filename 'todo' indicates that wine doesn't get this right yet. - NOTE: We always call this routine with a non-existent filename, so + NOTE: We always call this routine with a nonexistent filename, so Get(Short|Long)PathNameA should never pass, but GetFullPathNameA should. */ @@ -413,10 +413,10 @@ so why check it again. */ SetCurrentDirectoryA(newdir); -/* Check that SetCurrentDirectory fails when a non-existent dir is specified */ +/* Check that SetCurrentDirectory fails when a nonexistent dir is specified */ sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT); test_setdir(newdir,tmpstr,NULL,0,"check 3"); -/* Check that SetCurrentDirectory fails for a non-existent lond directory */ +/* Check that SetCurrentDirectory fails for a nonexistent lond directory */ sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG); test_setdir(newdir,tmpstr,NULL,0,"check 4"); /* Check that SetCurrentDirectory passes with a long directory */ @@ -640,7 +640,7 @@ test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13"); sprintf(tmpstr,"%s\\",LONGDIR); test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14"); -/* Non-existent directories */ +/* Nonexistent directories */ sprintf(tmpstr,"%s\\",NONDIR_SHORT); test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15"); sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr); diff -urN wine-20050111/dlls/lzexpand/tests/lzexpand_main.c wine-20050211/dlls/lzexpand/tests/lzexpand_main.c --- wine-20050111/dlls/lzexpand/tests/lzexpand_main.c 2004-12-27 18:46:36.000000000 +0100 +++ wine-20050211/dlls/lzexpand/tests/lzexpand_main.c 2005-02-10 20:19:36.000000000 +0100 @@ -47,11 +47,11 @@ #include #include -static char* filename_ = "testfile.xx_"; +static char filename_[] = "testfile.xx_"; #if 0 -static char* filename = "testfile.xxx"; +static char filename[] = "testfile.xxx"; #endif -static char* filename2 = "testfile.yyy"; +static char filename2[] = "testfile.yyy"; /* This is the hex string representation of the file created by compressing a simple text file with the contents "This is a test file." @@ -80,7 +80,7 @@ DWORD retval; INT file; - /* Check for non-existent file. */ + /* Check for nonexistent file. */ file = LZOpenFile("badfilename_", &test, OF_READ); ok(file == LZERROR_BADINHANDLE, "LZOpenFile succeeded on nonexistent file\n"); diff -urN wine-20050111/dlls/mapi32/tests/prop.c wine-20050211/dlls/mapi32/tests/prop.c --- wine-20050111/dlls/mapi32/tests/prop.c 2005-01-10 14:29:25.000000000 +0100 +++ wine-20050211/dlls/mapi32/tests/prop.c 2005-02-10 20:19:36.000000000 +0100 @@ -636,7 +636,7 @@ ptTypes[i]); pRet = pPpropFindProp(&pvProp, 1u, i ? ptTypes[i-1] : ptTypes[i+1]); - ok(pRet == NULL, "PpropFindProp[%ld]: Found non-existent propery\n", + ok(pRet == NULL, "PpropFindProp[%ld]: Found nonexistent propery\n", ptTypes[i]); } @@ -868,11 +868,11 @@ ptTypes[i]); pRet = pLpValFindProp(PROP_TAG(ptTypes[i], 0u), 1u, &pvProp); - ok(pRet == NULL, "LpValFindProp[%ld]: Found non-existent propery id\n", + ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id\n", ptTypes[i]); pRet = pLpValFindProp(PROP_TAG(PT_NULL, 0u), 1u, &pvProp); - ok(pRet == NULL, "LpValFindProp[%ld]: Found non-existent propery id/type\n", + ok(pRet == NULL, "LpValFindProp[%ld]: Found nonexistent propery id/type\n", ptTypes[i]); pRet = pLpValFindProp(PROP_TAG(PT_NULL, 1u), 1u, &pvProp); @@ -1257,19 +1257,19 @@ tags.aulPropTag[0] = PR_RESPONSE_REQUESTED; sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs); ok(sc == E_ACCESSDENIED && !lpProbs, - "DeleteProps(non-existent): Expected E_ACCESSDENIED null got 0x%08lX %p\n", + "DeleteProps(nonexistent): Expected E_ACCESSDENIED null got 0x%08lX %p\n", sc, lpProbs); /* Set access to read and write */ sc = IPropData_HrSetObjAccess(lpIProp, IPROP_READWRITE); ok(sc == S_OK, "SetObjAcess(WRITE): Expected S_OK got 0x%08lX\n", sc); - /* Delete non-existent item - No error */ + /* Delete nonexistent item - No error */ lpProbs = NULL; tags.aulPropTag[0] = PR_RESPONSE_REQUESTED; sc = IPropData_DeleteProps(lpIProp, (LPSPropTagArray)&tags, &lpProbs); ok(sc == S_OK && !lpProbs, - "DeleteProps(non-existent): Expected S_OK null got 0x%08lX %p\n", + "DeleteProps(nonexistent): Expected S_OK null got 0x%08lX %p\n", sc, lpProbs); /* Delete existing item (r/o) - No error, but lpProbs populated */ diff -urN wine-20050111/dlls/mlang/mlang.c wine-20050211/dlls/mlang/mlang.c --- wine-20050111/dlls/mlang/mlang.c 2004-10-07 05:06:50.000000000 +0200 +++ wine-20050211/dlls/mlang/mlang.c 2005-01-19 21:59:32.000000000 +0100 @@ -187,6 +187,12 @@ MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST, "koi8-r", "koi8-r", "koi8-r" }, + { "Cyrillic (KOI8-U)", + 21866, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | + MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | + MIMECONTF_SAVABLE_BROWSER | MIMECONTF_EXPORT | + MIMECONTF_VALID_NLS | MIMECONTF_MIME_IE4 | MIMECONTF_MIME_LATEST, + "koi8-u", "koi8-u", "koi8-u" }, { "Cyrillic (ISO)", 28595, MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_MINIMAL | MIMECONTF_IMPORT | MIMECONTF_SAVABLE_MAILNEWS | diff -urN wine-20050111/dlls/mpr/mpr.rc wine-20050211/dlls/mpr/mpr.rc --- wine-20050111/dlls/mpr/mpr.rc 2005-01-10 15:27:29.000000000 +0100 +++ wine-20050211/dlls/mpr/mpr.rc 2005-01-17 16:34:50.000000000 +0100 @@ -27,8 +27,9 @@ #include "mpr_Cs.rc" #include "mpr_De.rc" #include "mpr_En.rc" -#include "mpr_Nl.rc" #include "mpr_Es.rc" +#include "mpr_Fr.rc" #include "mpr_It.rc" #include "mpr_Ja.rc" +#include "mpr_Nl.rc" #include "mpr_Pt.rc" diff -urN wine-20050111/dlls/mpr/mpr_De.rc wine-20050211/dlls/mpr/mpr_De.rc --- wine-20050111/dlls/mpr/mpr_De.rc 2004-07-12 21:55:59.000000000 +0200 +++ wine-20050211/dlls/mpr/mpr_De.rc 2005-01-17 14:43:16.000000000 +0100 @@ -24,3 +24,23 @@ { IDS_ENTIRENETWORK "Gesamtes Netzwerk" } + +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" +{ + LTEXT "Bitte geben Sie Benutzernamen und Kennwort ein:", IDC_EXPLAIN, 40, 6, 150, 15 + LTEXT "Proxy", -1, 40, 26, 50, 10 +/* LTEXT "Bereich", -1, 40, 46, 50, 10 */ + LTEXT "Benutzername", -1, 40, 66, 50, 10 + LTEXT "Kennwort", -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 "Dieses Kennwort speichern (unsicher)", 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 "Abbrechen", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} diff -urN wine-20050111/dlls/mpr/mpr_Fr.rc wine-20050211/dlls/mpr/mpr_Fr.rc --- wine-20050111/dlls/mpr/mpr_Fr.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/mpr/mpr_Fr.rc 2005-01-17 16:34:50.000000000 +0100 @@ -0,0 +1,47 @@ +/* + * MPR dll resources + * French language support + * + * Copyright (C) 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_NEUTRAL + +STRINGTABLE DISCARDABLE +{ + IDS_ENTIRENETWORK "Le réseau entier" +} + +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" +{ + 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 +/* LTEXT "Realm", -1, 40, 46, 50, 10 */ + LTEXT "Utilisateur", -1, 40, 66, 50, 10 + LTEXT "Mot de passe", -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 "&Enregistrer ce mot de passe (risqué)", 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 "Annuler", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} diff -urN wine-20050111/dlls/mpr/netspi.h wine-20050211/dlls/mpr/netspi.h --- wine-20050111/dlls/mpr/netspi.h 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/mpr/netspi.h 2005-01-18 12:40:24.000000000 +0100 @@ -0,0 +1,153 @@ +/* + * MPR - Network provider services + * Warning: this file apparently existed as part of the Win98 DDK. Some of + * the declarations in it conflict with those in the Platform SDK's npapi.h, + * therefore this header was made private. Don't try to include both headers. + * + * Copyright (C) 1999 Ulrich Weigand + * + * 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 + */ + +#ifndef _NETSPI_H_ +#define _NETSPI_H_ + +#include "windef.h" +#include "winnetwk.h" + +/* + * Note: The Unicode variants of all these routines/structures + * apparently don't exist, at least not in Win95 ... + */ + +#define HPROVIDER LPVOID +typedef HPROVIDER *PHPROVIDER; + +typedef struct +{ + DWORD cbStructure; + HWND hwndOwner; + LPCSTR lpResource; + LPSTR lpUsername; + DWORD cbUsername; + LPSTR lpPassword; + DWORD cbPassword; + LPSTR lpOrgUnit; + DWORD cbOrgUnit; + LPCSTR lpOUTitle; + LPCSTR lpExplainText; + LPCSTR lpDefaultUserName; + DWORD dwFlags; + +} AUTHDLGSTRUCTA, *LPAUTHDLGSTRUCTA; + +DECL_WINELIB_TYPE_AW(AUTHDLGSTRUCT) +DECL_WINELIB_TYPE_AW(LPAUTHDLGSTRUCT) + +#define AUTHDLG_ENABLECACHE 0x00000001 +#define AUTHDLG_CHECKCACHE 0x00000002 +#define AUTHDLG_CACHEINVALID 0x00000004 +#define AUTHDLG_USE_DEFAULT_NAME 0x00000008 +#define AUTHDLG_CHECKDEFAULT_NAME 0x00000010 +#define AUTHDLG_LOGON 0x00000020 + +#define AUTHDLG_ENABLECACHE 0x00000001 +#define AUTHDLG_CHECKCACHE 0x00000002 +#define AUTHDLG_CACHEINVALID 0x00000004 +#define AUTHDLG_USE_DEFAULT_NAME 0x00000008 +#define AUTHDLG_CHECKDEFAULT_NAME 0x00000010 +#define AUTHDLG_LOGON 0x00000020 + +DWORD WINAPI NPSAuthenticationDialogA(LPAUTHDLGSTRUCTA); +#define NPSAuthenticationDialog WINELIB_NAME_AW(NPSAuthenticationDialog) +DWORD WINAPI NPSGetProviderHandleA(PHPROVIDER); +#define NPSGetProviderHandle WINELIB_NAME_AW(NPSGetProviderHandle) +DWORD WINAPI NPSGetProviderNameA(HPROVIDER,LPCSTR *); +#define NPSGetProviderName WINELIB_NAME_AW(NPSGetProviderName) +DWORD WINAPI NPSGetSectionNameA(HPROVIDER,LPCSTR *lpszSectionName); +#define NPSGetSectionName WINELIB_NAME_AW(NPSGetSectionName) +DWORD WINAPI NPSSetExtendedErrorA(DWORD,LPSTR); +#define NPSSetExtendedError WINELIB_NAME_AW(NPSSetExtendedError) +VOID WINAPI NPSSetCustomTextA(LPSTR); +#define NPSSetCustomText WINELIB_NAME_AW(NPSSetCustomText) +DWORD WINAPI NPSCopyStringA(LPCSTR,LPVOID,LPDWORD); +#define NPSCopyString WINELIB_NAME_AW(NPSCopyString) +DWORD WINAPI NPSDeviceGetNumberA(LPSTR,LPDWORD,LPDWORD); +#define NPSDeviceGetNumber WINELIB_NAME_AW(NPSDeviceGetNumber) +DWORD WINAPI NPSDeviceGetStringA(DWORD,DWORD,LPSTR,LPDWORD); +#define NPSDeviceGetString WINELIB_NAME_AW(NPSDeviceGetString) + + +enum NOTIFYTYPE { NotifyAddConnection, + NotifyCancelConnection, + NotifyGetConnectionPerformance }; + +#define NOTIFY_PRE 0x00 +#define NOTIFY_POST 0x01 + +typedef struct +{ + DWORD cbStructure; + DWORD dwNotifyStatus; + DWORD dwOperationStatus; + LPVOID lpNPContext; + +} NOTIFYINFO, *LPNOTIFYINFO; + +typedef struct +{ + DWORD cbStructure; + HWND hwndOwner; + NETRESOURCEA NetResource; + DWORD dwAddFlags; + LPSTR lpAccessName; + LPDWORD lpBufferSize; + DWORD dwResult; + DWORD dwAddContext; + +} NOTIFYADDA, *LPNOTIFYADDA; + +#define CONNECT_CTXT_RESTORE 0x00000001 +#define CONNECT_CTXT_GLOBAL 0x00000002 +#define CONNECT_CTXT_PROVIDER 0x00000004 +#define CONNECT_CTXT_SINGLE 0x00000008 + +typedef struct +{ + DWORD cbStructure; + LPSTR lpName; + LPSTR lpProvider; + DWORD dwFlags; + BOOL fForce; + +} NOTIFYCANCELA, *LPNOTIFYCANCELA; + +typedef struct +{ + DWORD cbStructure; + LPSTR lpRemoteName; + LPSTR lpProviderName; + LPNETCONNECTINFOSTRUCT lpNetConnectInfo; + +} NOTIFYPERFORMANCEA, *LPNOTIFYPERFORMANCEA; + +typedef DWORD (CALLBACK *NOTIFYCALLBACK)(LPNOTIFYINFO,LPVOID); + +DWORD WINAPI NPSNotifyRegisterA(enum NOTIFYTYPE,NOTIFYCALLBACK); +#define NPSNotifyRegister WINELIB_NAME_AW(NPSNotifyRegister) +LPVOID WINAPI NPSNotifyGetContextA(NOTIFYCALLBACK); +#define NPSNotifyGetContext WINELIB_NAME_AW(NPSNotifyGetContext) + +#endif /* _NETSPI_H_ */ diff -urN wine-20050111/dlls/mpr/nps.c wine-20050211/dlls/mpr/nps.c --- wine-20050111/dlls/mpr/nps.c 2005-01-10 15:27:29.000000000 +0100 +++ wine-20050211/dlls/mpr/nps.c 2005-01-18 12:40:24.000000000 +0100 @@ -26,7 +26,6 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winnetwk.h" #include "netspi.h" #include "wine/debug.h" #include "winerror.h" @@ -212,4 +211,3 @@ FIXME( "(%p): stub\n", pfNotifyCallBack ); return NULL; } - diff -urN wine-20050111/dlls/msdmo/dmoreg.c wine-20050211/dlls/msdmo/dmoreg.c --- wine-20050111/dlls/msdmo/dmoreg.c 2004-12-23 21:20:49.000000000 +0100 +++ wine-20050211/dlls/msdmo/dmoreg.c 2005-01-14 17:16:44.000000000 +0100 @@ -383,7 +383,7 @@ static ULONG WINAPI IEnumDMO_fnAddRef(IEnumDMO * iface) { IEnumDMOImpl *This = (IEnumDMOImpl *)iface; - return ++(This->ref); + return InterlockedIncrement(&This->ref); } @@ -420,15 +420,14 @@ static ULONG WINAPI IEnumDMO_fnRelease(IEnumDMO * iface) { IEnumDMOImpl *This = (IEnumDMOImpl *)iface; + ULONG refCount = InterlockedDecrement(&This->ref); - if (!--(This->ref)) + if (!refCount) { IEnumDMO_Destructor((IEnumDMO*)This); HeapFree(GetProcessHeap(),0,This); - return 0; } - - return This->ref; + return refCount; } diff -urN wine-20050111/dlls/msi/.cvsignore wine-20050211/dlls/msi/.cvsignore --- wine-20050111/dlls/msi/.cvsignore 2004-05-18 22:41:47.000000000 +0200 +++ wine-20050211/dlls/msi/.cvsignore 2005-02-08 13:12:29.000000000 +0100 @@ -2,7 +2,7 @@ cond.tab.c cond.tab.h msi.dll.dbg.c +msi.res msi.spec.def sql.tab.c sql.tab.h -version.res diff -urN wine-20050111/dlls/msi/Makefile.in wine-20050211/dlls/msi/Makefile.in --- wine-20050111/dlls/msi/Makefile.in 2005-01-05 18:11:33.000000000 +0100 +++ wine-20050211/dlls/msi/Makefile.in 2005-02-08 13:12:29.000000000 +0100 @@ -8,15 +8,21 @@ C_SRCS = \ action.c \ + appsearch.c \ create.c \ + custom.c \ + dialog.c \ distinct.c \ + format.c \ handle.c \ insert.c \ msi.c \ msiquery.c \ order.c \ package.c \ + preview.c \ record.c \ + registry.c \ regsvr.c \ select.c \ string.c \ @@ -26,7 +32,7 @@ update.c \ where.c -RC_SRCS = version.rc +RC_SRCS = msi.rc EXTRA_SRCS = sql.y cond.y EXTRA_OBJS = sql.tab.o cond.tab.o diff -urN wine-20050111/dlls/msi/action.c wine-20050211/dlls/msi/action.c --- wine-20050111/dlls/msi/action.c 2005-01-10 14:29:25.000000000 +0100 +++ wine-20050211/dlls/msi/action.c 2005-02-10 18:09:44.000000000 +0100 @@ -48,99 +48,26 @@ #include "shlobj.h" #include "wine/unicode.h" #include "ver.h" +#include "action.h" -#define CUSTOM_ACTION_TYPE_MASK 0x3F #define REG_PROGRESS_VALUE 13200 #define COMPONENT_PROGRESS_VALUE 24000 WINE_DEFAULT_DEBUG_CHANNEL(msi); -typedef struct tagMSIFEATURE -{ - WCHAR Feature[96]; - WCHAR Feature_Parent[96]; - WCHAR Title[0x100]; - WCHAR Description[0x100]; - INT Display; - INT Level; - WCHAR Directory[96]; - INT Attributes; - - INSTALLSTATE Installed; - INSTALLSTATE ActionRequest; - INSTALLSTATE Action; - - INT ComponentCount; - INT Components[1024]; /* yes hardcoded limit.... I am bad */ - INT Cost; -} MSIFEATURE; - -typedef struct tagMSICOMPONENT -{ - WCHAR Component[96]; - WCHAR ComponentId[96]; - WCHAR Directory[96]; - INT Attributes; - WCHAR Condition[0x100]; - WCHAR KeyPath[96]; - - INSTALLSTATE Installed; - INSTALLSTATE ActionRequest; - INSTALLSTATE Action; - - BOOL Enabled; - INT Cost; -} MSICOMPONENT; - -typedef struct tagMSIFOLDER -{ - LPWSTR Directory; - LPWSTR TargetDefault; - LPWSTR SourceDefault; - - LPWSTR ResolvedTarget; - LPWSTR ResolvedSource; - LPWSTR Property; /* initially set property */ - INT ParentIndex; - INT State; - /* 0 = uninitialized */ - /* 1 = existing */ - /* 2 = created remove if empty */ - /* 3 = created persist if empty */ - INT Cost; - INT Space; -}MSIFOLDER; - -typedef struct tagMSIFILE -{ - LPWSTR File; - INT ComponentIndex; - LPWSTR FileName; - INT FileSize; - LPWSTR Version; - LPWSTR Language; - INT Attributes; - INT Sequence; - - INT State; - /* 0 = uninitialize */ - /* 1 = not present */ - /* 2 = present but replace */ - /* 3 = present do not replace */ - /* 4 = Installed */ - LPWSTR SourcePath; - LPWSTR TargetPath; - BOOL Temporary; -}MSIFILE; - /* * Prototypes */ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran); static UINT ACTION_ProcessUISequence(MSIPACKAGE *package); - static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq); -UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action); +static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, + LPWSTR *FilePath); + +/* + * action handlers + */ +typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*); static UINT ACTION_LaunchConditions(MSIPACKAGE *package); static UINT ACTION_CostInitialize(MSIPACKAGE *package); @@ -150,32 +77,26 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package); static UINT ACTION_DuplicateFiles(MSIPACKAGE *package); static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package); -static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action); static UINT ACTION_InstallInitialize(MSIPACKAGE *package); static UINT ACTION_InstallValidate(MSIPACKAGE *package); static UINT ACTION_ProcessComponents(MSIPACKAGE *package); static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package); static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package); static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package); +static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package); +static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package); +static UINT ACTION_RegisterUser(MSIPACKAGE *package); static UINT ACTION_CreateShortcuts(MSIPACKAGE *package); static UINT ACTION_PublishProduct(MSIPACKAGE *package); +static UINT ACTION_WriteIniValues(MSIPACKAGE *package); +static UINT ACTION_SelfRegModules(MSIPACKAGE *package); +static UINT ACTION_PublishFeatures(MSIPACKAGE *package); +static UINT ACTION_RegisterProduct(MSIPACKAGE *package); +static UINT ACTION_InstallExecute(MSIPACKAGE *package); +static UINT ACTION_InstallFinalize(MSIPACKAGE *package); +static UINT ACTION_ForceReboot(MSIPACKAGE *package); +static UINT ACTION_ResolveSource(MSIPACKAGE *package); -static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type); -static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type); -static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type); -static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type); -static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type); - -static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data); -static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, - BOOL source, BOOL set_prop, MSIFOLDER **folder); - -static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); /* * consts and values used @@ -187,31 +108,30 @@ static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0}; static const WCHAR c_collen[] = {'C',':','\\',0}; -static const WCHAR cszlsb[]={'[',0}; -static const WCHAR cszrsb[]={']',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}; const static WCHAR szCostInitialize[] = - {'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}; +{'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}; 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}; @@ -223,6 +143,209 @@ {'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}; +const static WCHAR szWriteIniValues[] = +{'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}; +const static WCHAR szPublishFeatures[] = +{'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}; +const static WCHAR szInstallExecute[] = +{'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}; +const static WCHAR szInstallFinalize[] = +{'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}; +const static WCHAR szResolveSource[] = +{'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}; +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}; +const static WCHAR szBindImage[] = +{'B','i','n','d','I','m','a','g','e',0}; +const static WCHAR szCCPSearch[] = +{'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}; +const static WCHAR szDisableRollback[] = +{'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}; +const static WCHAR szFindRelatedProducts[] = +{'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}; +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}; +const static WCHAR szIsolateComponents[] = +{'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}; +const static WCHAR szMoveFiles[] = +{'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}; +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}; +const static WCHAR szInstallODBC[] = +{'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}; +const static WCHAR szPatchFiles[] = +{'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}; +const static WCHAR szRegisterComPlus[] = +{'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}; +const static WCHAR szRegisterFonts[] = +{'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}; +const static WCHAR szRegisterUser[] = +{'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}; +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}; +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}; +const static WCHAR szRemoveFiles[] = +{'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}; +const static WCHAR szRemoveIniValues[] = +{'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}; +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}; +const static WCHAR szRemoveShortcuts[] = +{'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}; +const static WCHAR szScheduleReboot[] = +{'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}; +const static WCHAR szSetODBCFolders[] = +{'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}; +const static WCHAR szStopServices[] = +{'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}; +const static WCHAR szUnpublishFeatures[] = +{'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}; +const static WCHAR szUnregisterComPlus[] = +{'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}; +const static WCHAR szUnregisterFonts[] = +{'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}; +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}; +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}; +const static WCHAR szValidateProductID[] = +{'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}; + +struct _actions { + LPCWSTR action; + STANDARDACTIONHANDLER handler; +}; + +struct _actions StandardActions[] = { + { szAllocateRegistrySpace, NULL}, + { szAppSearch, ACTION_AppSearch }, + { szBindImage, NULL}, + { szCCPSearch, NULL}, + { szCostFinalize, ACTION_CostFinalize }, + { szCostInitialize, ACTION_CostInitialize }, + { szCreateFolders, ACTION_CreateFolders }, + { szCreateShortcuts, ACTION_CreateShortcuts }, + { szDeleteServices, NULL}, + { szDisableRollback, NULL}, + { szDuplicateFiles, ACTION_DuplicateFiles}, + { szExecuteAction, NULL}, + { szFileCost, ACTION_FileCost }, + { szFindRelatedProducts, NULL}, + { szForceReboot, ACTION_ForceReboot }, + { szInstallAdminPackage, NULL}, + { szInstallExecute, ACTION_InstallExecute }, + { szInstallExecuteAgain, ACTION_InstallExecute }, + { szInstallFiles, ACTION_InstallFiles}, + { szInstallFinalize, ACTION_InstallFinalize }, + { szInstallInitialize, ACTION_InstallInitialize }, + { szInstallSFPCatalogFile, NULL}, + { szInstallValidate, ACTION_InstallValidate }, + { szIsolateComponents, NULL}, + { szLaunchConditions, ACTION_LaunchConditions }, + { szMigrateFeatureStates, NULL}, + { szMoveFiles, NULL}, + { szMsiPublishAssemblies, NULL}, + { szMsiUnpublishAssemblies, NULL}, + { szInstallODBC, NULL}, + { szInstallServices, NULL}, + { szPatchFiles, NULL}, + { szProcessComponents, ACTION_ProcessComponents }, + { szPublishComponents, NULL}, + { szPublishFeatures, ACTION_PublishFeatures }, + { szPublishProduct, ACTION_PublishProduct }, + { szRegisterClassInfo, ACTION_RegisterClassInfo }, + { szRegisterComPlus, NULL}, + { szRegisterExtensionInfo, ACTION_RegisterExtensionInfo }, + { szRegisterFonts, NULL}, + { szRegisterMIMEInfo, ACTION_RegisterMIMEInfo }, + { szRegisterProduct, ACTION_RegisterProduct }, + { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo }, + { szRegisterTypeLibraries, ACTION_RegisterTypeLibraries }, + { szRegisterUser, ACTION_RegisterUser}, + { szRemoveDuplicateFiles, NULL}, + { szRemoveEnvironmentStrings, NULL}, + { szRemoveExistingProducts, NULL}, + { szRemoveFiles, NULL}, + { szRemoveFolders, NULL}, + { szRemoveIniValues, NULL}, + { szRemoveODBC, NULL}, + { szRemoveRegistryValues, NULL}, + { szRemoveShortcuts, NULL}, + { szResolveSource, ACTION_ResolveSource}, + { szRMCCPSearch, NULL}, + { szScheduleReboot, NULL}, + { szSelfRegModules, ACTION_SelfRegModules }, + { szSelfUnregModules, NULL}, + { szSetODBCFolders, NULL}, + { szStartServices, NULL}, + { szStopServices, NULL}, + { szUnpublishComponents, NULL}, + { szUnpublishFeatures, NULL}, + { szUnregisterClassInfo, NULL}, + { szUnregisterComPlus, NULL}, + { szUnregisterExtensionInfo, NULL}, + { szUnregisterFonts, NULL}, + { szUnregisterMIMEInfo, NULL}, + { szUnregisterProgIdInfo, NULL}, + { szUnregisterTypeLibraries, NULL}, + { szValidateProductID, NULL}, + { szWriteEnvironmentStrings, NULL}, + { szWriteIniValues, ACTION_WriteIniValues }, + { szWriteRegistryValues, ACTION_WriteRegistryValues}, + { NULL, NULL}, +}; + /******************************************************** * helper functions to get around current HACKS and such @@ -234,41 +357,7 @@ memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR)); } -inline static char *strdupWtoA( const WCHAR *str ) -{ - char *ret = NULL; - if (str) - { - DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL -); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) - WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); - } - return ret; -} - -inline static WCHAR *strdupAtoW( const char *str ) -{ - WCHAR *ret = NULL; - if (str) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); - } - return ret; -} - -static LPWSTR dupstrW(LPCWSTR src) -{ - LPWSTR dest; - if (!src) return NULL; - dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR)); - strcpyW(dest, src); - return dest; -} - -inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index) +WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index) { UINT rc; DWORD sz; @@ -300,8 +389,7 @@ return ret; } -inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, - UINT* rc) +LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc) { DWORD sz = 0; LPWSTR str; @@ -327,7 +415,7 @@ return str; } -inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component ) +int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component ) { int rc = -1; DWORD i; @@ -343,7 +431,7 @@ return rc; } -inline static int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ) +int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ) { int rc = -1; DWORD i; @@ -359,7 +447,7 @@ return rc; } -inline static int get_loaded_file(MSIPACKAGE* package, LPCWSTR file) +int get_loaded_file(MSIPACKAGE* package, LPCWSTR file) { int rc = -1; DWORD i; @@ -375,8 +463,7 @@ return rc; } - -static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path) +int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path) { DWORD i; DWORD index; @@ -407,7 +494,7 @@ return 0; } -void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package) +static void remove_tracked_tempfiles(MSIPACKAGE* package) { DWORD i; @@ -425,13 +512,43 @@ } } +/* wrapper to resist a need for a full rewrite right now */ +DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ) +{ + if (ptr) + { + MSIRECORD *rec = MSI_CreateRecord(1); + DWORD size = 0; + + MSI_RecordSetStringW(rec,0,ptr); + MSI_FormatRecordW(package,rec,NULL,&size); + if (size >= 0) + { + size++; + *data = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR)); + if (size > 1) + MSI_FormatRecordW(package,rec,*data,&size); + else + *data[0] = 0; + msiobj_release( &rec->hdr ); + return sizeof(WCHAR)*size; + } + msiobj_release( &rec->hdr ); + } + + *data = NULL; + return 0; +} + /* Called when the package is being closed */ -extern void ACTION_free_package_structures( MSIPACKAGE* package) +void ACTION_free_package_structures( MSIPACKAGE* package) { INT i; TRACE("Freeing package action data\n"); + remove_tracked_tempfiles(package); + /* No dynamic buffers in features */ if (package->features && package->loaded_features > 0) HeapFree(GetProcessHeap(),0,package->features); @@ -464,54 +581,16 @@ if (package->files && package->loaded_files > 0) HeapFree(GetProcessHeap(),0,package->files); -} - -static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... ) -{ - LPWSTR szQuery; - LPCWSTR p; - UINT sz, rc; - va_list va; - - /* figure out how much space we need to allocate */ - va_start(va, fmt); - sz = strlenW(fmt) + 1; - p = fmt; - while (*p) - { - p = strchrW(p, '%'); - if (!p) - break; - p++; - switch (*p) - { - case 's': /* a string */ - sz += strlenW(va_arg(va,LPCWSTR)); - break; - case 'd': - case 'i': /* an integer -2147483648 seems to be longest */ - sz += 3*sizeof(int); - (void)va_arg(va,int); - break; - case '%': /* a single % - leave it alone */ - break; - default: - FIXME("Unhandled character type %c\n",*p); - } - p++; - } - va_end(va); - /* construct the string */ - szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR)); - va_start(va, fmt); - vsnprintfW(szQuery, sz, fmt, va); - va_end(va); + for (i = 0; i < package->DeferredActionCount; i++) + HeapFree(GetProcessHeap(),0,package->DeferredAction[i]); + HeapFree(GetProcessHeap(),0,package->DeferredAction); + + for (i = 0; i < package->CommitActionCount; i++) + HeapFree(GetProcessHeap(),0,package->CommitAction[i]); + HeapFree(GetProcessHeap(),0,package->CommitAction); - /* perform the query */ - rc = MSI_DatabaseOpenViewW(db, szQuery, view); - HeapFree(GetProcessHeap(), 0, szQuery); - return rc; + HeapFree(GetProcessHeap(),0,package->PackagePath); } static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d ) @@ -525,6 +604,8 @@ MSI_RecordSetInteger(row,4,d); MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row); msiobj_release(&row->hdr); + + msi_dialog_check_messages(package->dialog, NULL); } static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record) @@ -537,11 +618,11 @@ UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - LPWSTR ptr; + DWORD size; if (!package->LastAction || strcmpW(package->LastAction,action)) { - rc = ACTION_OpenQuery(package->db, &view, Query_t, action); + rc = MSI_OpenQuery(package->db, &view, Query_t, action); if (rc != ERROR_SUCCESS) return; @@ -567,12 +648,10 @@ } /* update the cached actionformat */ - if (package->ActionFormat) - HeapFree(GetProcessHeap(),0,package->ActionFormat); + HeapFree(GetProcessHeap(),0,package->ActionFormat); package->ActionFormat = load_dynamic_stringW(row,3); - if (package->LastAction) - HeapFree(GetProcessHeap(),0,package->LastAction); + HeapFree(GetProcessHeap(),0,package->LastAction); package->LastAction = dupstrW(action); msiobj_release(&row->hdr); @@ -580,38 +659,9 @@ msiobj_release(&view->hdr); } - message[0]=0; - ptr = package->ActionFormat; - while (*ptr) - { - LPWSTR ptr2; - LPWSTR data=NULL; - WCHAR tmp[1023]; - INT field; - - ptr2 = strchrW(ptr,'['); - if (ptr2) - { - strncpyW(tmp,ptr,ptr2-ptr); - tmp[ptr2-ptr]=0; - strcatW(message,tmp); - ptr2++; - field = atoiW(ptr2); - data = load_dynamic_stringW(record,field); - if (data) - { - strcatW(message,data); - HeapFree(GetProcessHeap(),0,data); - } - ptr=strchrW(ptr2,']'); - ptr++; - } - else - { - strcatW(message,ptr); - break; - } - } + MSI_RecordSetStringW(record,0,package->ActionFormat); + size = 1024; + MSI_FormatRecordW(package,record,message,&size); row = MSI_CreateRecord(1); MSI_RecordSetStringW(row,1,message); @@ -640,7 +690,7 @@ GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100); - rc = ACTION_OpenQuery(package->db, &view, Query_t, action); + rc = MSI_OpenQuery(package->db, &view, Query_t, action); if (rc != ERROR_SUCCESS) return; rc = MSI_ViewExecute(view, 0); @@ -764,11 +814,16 @@ WCHAR buffer[10]; UINT rc; static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0}; + static const WCHAR szAction[] = {'A','C','T','I','O','N',0}; + static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0}; + + MSI_SetPropertyW(package, szAction, szInstall); if (szPackagePath) { LPWSTR p, check, path; + package->PackagePath = dupstrW(szPackagePath); path = dupstrW(szPackagePath); p = strrchrW(path,'\\'); if (p) @@ -776,6 +831,13 @@ p++; *p=0; } + else + { + HeapFree(GetProcessHeap(),0,path); + path = HeapAlloc(GetProcessHeap(),0,MAX_PATH*sizeof(WCHAR)); + GetCurrentDirectoryW(MAX_PATH,path); + strcatW(path,cszbs); + } check = load_dynamic_property(package, cszSourceDir,NULL); if (!check) @@ -857,12 +919,25 @@ } else rc = ACTION_ProcessExecSequence(package,FALSE); + + if (rc == -1) + { + /* install was halted but should be considered a success */ + rc = ERROR_SUCCESS; + } /* process the ending type action */ if (rc == ERROR_SUCCESS) - rc = ACTION_PerformActionSequence(package,-1); + ACTION_PerformActionSequence(package,-1); + else if (rc == ERROR_INSTALL_USEREXIT) + ACTION_PerformActionSequence(package,-2); else if (rc == ERROR_FUNCTION_FAILED) - rc = ACTION_PerformActionSequence(package,-3); + ACTION_PerformActionSequence(package,-3); + else if (rc == ERROR_INSTALL_SUSPEND) + ACTION_PerformActionSequence(package,-4); + + /* finish up running custom actions */ + ACTION_FinishCustomActions(package); return rc; } @@ -882,7 +957,7 @@ 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', '=',' ','%','i',0}; - rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq); + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq); if (rc == ERROR_SUCCESS) { @@ -993,7 +1068,7 @@ msiobj_release(&view->hdr); } - rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq); + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq); if (rc == ERROR_SUCCESS) { rc = MSI_ViewExecute(view, 0); @@ -1142,7 +1217,7 @@ break; } - rc = ACTION_PerformAction(package,buffer); + rc = ACTION_PerformUIAction(package,buffer); if (rc == ERROR_FUNCTION_NOT_CALLED) rc = ERROR_SUCCESS; @@ -1168,11 +1243,71 @@ /******************************************************** * ACTION helper functions and functions that perform the actions *******************************************************/ +BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc) +{ + BOOL ret = FALSE; + + int i; + i = 0; + while (StandardActions[i].action != NULL) + { + if (strcmpW(StandardActions[i].action, action)==0) + { + ui_actioninfo(package, action, TRUE, 0); + ui_actionstart(package, action); + if (StandardActions[i].handler) + { + *rc = StandardActions[i].handler(package); + } + else + { + FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action)); + *rc = ERROR_SUCCESS; + } + ui_actioninfo(package, action, FALSE, *rc); + ret = TRUE; + break; + } + i++; + } + return ret; +} + +BOOL ACTION_HandleDialogBox(MSIPACKAGE *package, LPCWSTR dialog, UINT* rc) +{ + BOOL ret = FALSE; + + /* + * for the UI when we get that working + * + if (ACTION_DialogBox(package,dialog) == ERROR_SUCCESS) + { + *rc = package->CurrentInstallState; + ret = TRUE; + } + */ + return ret; +} + +BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc) +{ + BOOL ret=FALSE; + UINT arc; + + arc = ACTION_CustomAction(package,action,FALSE); + + if (arc != ERROR_CALL_NOT_IMPLEMENTED) + { + *rc = arc; + ret = TRUE; + } + return ret; +} /* - * Alot of actions are really important even if they don't do anything - * explicit.. Lots of properties are set at the beginning of the installation - * CostFinalize does a bunch of work to translated the directories and such + * A lot of actions are really important even if they don't do anything + * explicit... Lots of properties are set at the beginning of the installation + * CostFinalize does a bunch of work to translate the directories and such * * But until I get write access to the database that is hard, so I am going to * hack it to see if I can get something to run. @@ -1180,599 +1315,125 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action) { UINT rc = ERROR_SUCCESS; + BOOL handled; TRACE("Performing action (%s)\n",debugstr_w(action)); - ui_actioninfo(package, action, TRUE, 0); - ui_actionstart(package, action); - /* pre install, setup and configuration block */ - if (strcmpW(action,szLaunchConditions)==0) - rc = ACTION_LaunchConditions(package); - else if (strcmpW(action,szCostInitialize)==0) - rc = ACTION_CostInitialize(package); - else if (strcmpW(action,szFileCost)==0) - rc = ACTION_FileCost(package); - else if (strcmpW(action,szCostFinalize)==0) - rc = ACTION_CostFinalize(package); - else if (strcmpW(action,szInstallValidate)==0) - rc = ACTION_InstallValidate(package); - - /* install block */ - else if (strcmpW(action,szProcessComponents)==0) - rc = ACTION_ProcessComponents(package); - else if (strcmpW(action,szInstallInitialize)==0) - rc = ACTION_InstallInitialize(package); - else if (strcmpW(action,szCreateFolders)==0) - rc = ACTION_CreateFolders(package); - else if (strcmpW(action,szInstallFiles)==0) - rc = ACTION_InstallFiles(package); - else if (strcmpW(action,szDuplicateFiles)==0) - rc = ACTION_DuplicateFiles(package); - else if (strcmpW(action,szWriteRegistryValues)==0) - rc = ACTION_WriteRegistryValues(package); - else if (strcmpW(action,szRegisterTypeLibraries)==0) - rc = ACTION_RegisterTypeLibraries(package); - else if (strcmpW(action,szRegisterClassInfo)==0) - rc = ACTION_RegisterClassInfo(package); - else if (strcmpW(action,szRegisterProgIdInfo)==0) - rc = ACTION_RegisterProgIdInfo(package); - else if (strcmpW(action,szCreateShortcuts)==0) - rc = ACTION_CreateShortcuts(package); - else if (strcmpW(action,szPublishProduct)==0) - rc = ACTION_PublishProduct(package); + handled = ACTION_HandleStandardAction(package, action, &rc); - /* - Called during iTunes but unimplemented and seem important + if (!handled) + handled = ACTION_HandleCustomAction(package, action, &rc); - ResolveSource (sets SourceDir) - RegisterProduct - InstallFinalize - */ - else if ((rc = ACTION_CustomAction(package,action)) != ERROR_SUCCESS) - { + if (!handled) + { FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action)); rc = ERROR_FUNCTION_NOT_CALLED; - } + } - ui_actioninfo(package, action, FALSE, rc); + package->CurrentInstallState = rc; return rc; } - -static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action) +UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action) { UINT rc = ERROR_SUCCESS; - MSIQUERY * view; - MSIRECORD * row = 0; - static const WCHAR ExecSeqQuery[] = - {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o' - ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i' - ,'o','n','`',' ','=',' ','`','%','s','`',0}; - UINT type; - LPWSTR source; - LPWSTR target; - WCHAR *deformated=NULL; - - rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action); - if (rc != ERROR_SUCCESS) - return rc; + BOOL handled = FALSE; - rc = MSI_ViewExecute(view, 0); - if (rc != ERROR_SUCCESS) - { - MSI_ViewClose(view); - msiobj_release(&view->hdr); - return rc; - } + TRACE("Performing action (%s)\n",debugstr_w(action)); - rc = MSI_ViewFetch(view,&row); - if (rc != ERROR_SUCCESS) - { - MSI_ViewClose(view); - msiobj_release(&view->hdr); - return rc; - } + handled = ACTION_HandleStandardAction(package, action, &rc); - type = MSI_RecordGetInteger(row,2); + if (!handled) + handled = ACTION_HandleCustomAction(package, action, &rc); - source = load_dynamic_stringW(row,3); - target = load_dynamic_stringW(row,4); + if (!handled) + handled = ACTION_HandleDialogBox(package, action, &rc); - TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type, - debugstr_w(source), debugstr_w(target)); + msi_dialog_check_messages( package->dialog, NULL ); - /* we are ignoring ALOT of flags and important synchronization stuff */ - switch (type & CUSTOM_ACTION_TYPE_MASK) + if (!handled) { - case 1: /* DLL file stored in a Binary table stream */ - rc = HANDLE_CustomType1(package,source,target,type); - break; - case 2: /* EXE file stored in a Binary table strem */ - rc = HANDLE_CustomType2(package,source,target,type); - break; - case 18: /*EXE file installed with package */ - rc = HANDLE_CustomType18(package,source,target,type); - break; - case 50: /*EXE file specified by a property value */ - rc = HANDLE_CustomType50(package,source,target,type); - break; - case 34: /*EXE to be run in specified directory */ - rc = HANDLE_CustomType34(package,source,target,type); - break; - case 35: /* Directory set with formatted text. */ - deformat_string(package,target,&deformated); - MSI_SetTargetPathW(package, source, deformated); - HeapFree(GetProcessHeap(),0,deformated); - break; - case 51: /* Property set with formatted text. */ - deformat_string(package,target,&deformated); - rc = MSI_SetPropertyW(package,source,deformated); - HeapFree(GetProcessHeap(),0,deformated); - break; - default: - FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n", - type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source), - debugstr_w(target)); + FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action)); + rc = ERROR_FUNCTION_NOT_CALLED; } - HeapFree(GetProcessHeap(),0,source); - HeapFree(GetProcessHeap(),0,target); - msiobj_release(&row->hdr); - MSI_ViewClose(view); - msiobj_release(&view->hdr); + package->CurrentInstallState = rc; return rc; } -static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source, - LPWSTR tmp_file) +/*********************************************************************** + * create_full_pathW + * + * Recursively create all directories in the path. + * + * shamelessly stolen from setupapi/queue.c + */ +static BOOL create_full_pathW(const WCHAR *path) { - DWORD sz=MAX_PATH; - - if (MSI_GetPropertyW(package, cszTempFolder, tmp_file, &sz) - != ERROR_SUCCESS) - GetTempPathW(MAX_PATH,tmp_file); - - strcatW(tmp_file,source); + BOOL ret = TRUE; + int len; + WCHAR *new_path; - if (GetFileAttributesW(tmp_file) != INVALID_FILE_ATTRIBUTES) - { - TRACE("File already exists\n"); - return ERROR_SUCCESS; - } - else - { - /* write out the file */ - UINT rc; - MSIQUERY * view; - MSIRECORD * row = 0; - static const WCHAR fmt[] = - {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i' -,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0}; - HANDLE the_file; - CHAR buffer[1024]; + new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * + sizeof(WCHAR)); - if (track_tempfile(package, source, tmp_file)!=0) - FIXME("File Name in temp tracking collision\n"); + strcpyW(new_path, path); - the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (the_file == INVALID_HANDLE_VALUE) - return ERROR_FUNCTION_FAILED; + while((len = strlenW(new_path)) && new_path[len - 1] == '\\') + new_path[len - 1] = 0; - rc = ACTION_OpenQuery(package->db, &view, fmt, source); - if (rc != ERROR_SUCCESS) - return rc; + while(!CreateDirectoryW(new_path, NULL)) + { + WCHAR *slash; + DWORD last_error = GetLastError(); + if(last_error == ERROR_ALREADY_EXISTS) + break; - rc = MSI_ViewExecute(view, 0); - if (rc != ERROR_SUCCESS) + if(last_error != ERROR_PATH_NOT_FOUND) { - MSI_ViewClose(view); - msiobj_release(&view->hdr); - return rc; + ret = FALSE; + break; } - rc = MSI_ViewFetch(view,&row); - if (rc != ERROR_SUCCESS) + if(!(slash = strrchrW(new_path, '\\'))) { - MSI_ViewClose(view); - msiobj_release(&view->hdr); - return rc; + ret = FALSE; + break; } - do + len = slash - new_path; + new_path[len] = 0; + if(!create_full_pathW(new_path)) { - DWORD write; - sz = 1024; - rc = MSI_RecordReadStream(row,2,buffer,&sz); - if (rc != ERROR_SUCCESS) - { - ERR("Failed to get stream\n"); - CloseHandle(the_file); - DeleteFileW(tmp_file); - break; - } - WriteFile(the_file,buffer,sz,&write,NULL); - } while (sz == 1024); - - CloseHandle(the_file); - - msiobj_release(&row->hdr); - MSI_ViewClose(view); - msiobj_release(&view->hdr); + ret = FALSE; + break; + } + new_path[len] = '\\'; } - return ERROR_SUCCESS; + HeapFree(GetProcessHeap(), 0, new_path); + return ret; } -typedef UINT __stdcall CustomEntry(MSIHANDLE); -typedef struct -{ - MSIPACKAGE *package; - WCHAR *target; - WCHAR *source; -} thread_struct; - -static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff) +/* + * Also we cannot enable/disable components either, so for now I am just going + * to do all the directories for all the components. + */ +static UINT ACTION_CreateFolders(MSIPACKAGE *package) { - HANDLE hModule; - LPSTR proc; - CustomEntry *fn; + 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; - TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source), - debugstr_w(stuff->target)); + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view ); + if (rc != ERROR_SUCCESS) + return ERROR_SUCCESS; - hModule = LoadLibraryW(stuff->source); - if (hModule) - { - proc = strdupWtoA( stuff->target ); - fn = (CustomEntry*)GetProcAddress(hModule,proc); - if (fn) - { - MSIHANDLE hPackage; - MSIPACKAGE *package = stuff->package; - - TRACE("Calling function %s\n", proc); - hPackage = msiobj_findhandle( &package->hdr ); - if (hPackage ) - { - fn(hPackage); - msiobj_release( &package->hdr ); - } - else - ERR("Handle for object %p not found\n", package ); - } - else - ERR("Cannot load functon\n"); - - HeapFree(GetProcessHeap(),0,proc); - FreeLibrary(hModule); - } - else - ERR("Unable to load library\n"); - msiobj_release( &stuff->package->hdr ); - HeapFree(GetProcessHeap(),0,stuff->source); - HeapFree(GetProcessHeap(),0,stuff->target); - HeapFree(GetProcessHeap(), 0, stuff); - return 0; -} - -static DWORD WINAPI DllThread(LPVOID info) -{ - thread_struct *stuff; - DWORD rc = 0; - - TRACE("MSI Thread (0x%lx) started for custom action\n", - GetCurrentThreadId()); - - stuff = (thread_struct*)info; - rc = ACTION_CallDllFunction(stuff); - - TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId()); - /* clse all handles for this thread */ - MsiCloseAllHandles(); - return rc; -} - -static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - WCHAR tmp_file[MAX_PATH]; - thread_struct *info; - DWORD ThreadId; - HANDLE ThreadHandle; - - store_binary_to_temp(package, source, tmp_file); - - TRACE("Calling function %s from %s\n",debugstr_w(target), - debugstr_w(tmp_file)); - - if (!strchrW(tmp_file,'.')) - { - static const WCHAR dot[]={'.',0}; - strcatW(tmp_file,dot); - } - - info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); - msiobj_addref( &package->hdr ); - info->package = package; - info->target = dupstrW(target); - info->source = dupstrW(tmp_file); - - ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId); - - if (!(type & 0xc0)) - WaitForSingleObject(ThreadHandle,INFINITE); - - CloseHandle(ThreadHandle); - - return ERROR_SUCCESS; -} - -static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - WCHAR tmp_file[MAX_PATH]; - STARTUPINFOW si; - PROCESS_INFORMATION info; - BOOL rc; - INT len; - WCHAR *deformated; - WCHAR *cmd; - static const WCHAR spc[] = {' ',0}; - - memset(&si,0,sizeof(STARTUPINFOW)); - - store_binary_to_temp(package, source, tmp_file); - - deformat_string(package,target,&deformated); - - len = strlenW(tmp_file) + strlenW(deformated) + 2; - - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); - - strcpyW(cmd,tmp_file); - strcatW(cmd,spc); - strcatW(cmd,deformated); - - HeapFree(GetProcessHeap(),0,deformated); - - TRACE("executing exe %s \n",debugstr_w(cmd)); - - rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); - - HeapFree(GetProcessHeap(),0,cmd); - - if ( !rc ) - { - ERR("Unable to execute command\n"); - return ERROR_SUCCESS; - } - - if (!(type & 0xc0)) - WaitForSingleObject(info.hProcess,INFINITE); - - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - return ERROR_SUCCESS; -} - -static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - STARTUPINFOW si; - PROCESS_INFORMATION info; - BOOL rc; - WCHAR *deformated; - WCHAR *cmd; - INT len; - static const WCHAR spc[] = {' ',0}; - int index; - - memset(&si,0,sizeof(STARTUPINFOW)); - - index = get_loaded_file(package,source); - - len = strlenW(package->files[index].TargetPath); - - deformat_string(package,target,&deformated); - len += strlenW(deformated); - len += 2; - - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR)); - - strcpyW(cmd, package->files[index].TargetPath); - strcatW(cmd, spc); - strcatW(cmd, deformated); - - HeapFree(GetProcessHeap(),0,deformated); - - TRACE("executing exe %s \n",debugstr_w(cmd)); - - rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); - - HeapFree(GetProcessHeap(),0,cmd); - - if ( !rc ) - { - ERR("Unable to execute command\n"); - return ERROR_SUCCESS; - } - - if (!(type & 0xc0)) - WaitForSingleObject(info.hProcess,INFINITE); - - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - return ERROR_SUCCESS; -} - -static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - STARTUPINFOW si; - PROCESS_INFORMATION info; - WCHAR *prop; - BOOL rc; - WCHAR *deformated; - WCHAR *cmd; - INT len; - UINT prc; - static const WCHAR spc[] = {' ',0}; - - memset(&si,0,sizeof(STARTUPINFOW)); - memset(&info,0,sizeof(PROCESS_INFORMATION)); - - prop = load_dynamic_property(package,source,&prc); - if (!prop) - return prc; - - deformat_string(package,target,&deformated); - len = strlenW(prop) + strlenW(deformated) + 2; - cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); - - strcpyW(cmd,prop); - strcatW(cmd,spc); - strcatW(cmd,deformated); - - HeapFree(GetProcessHeap(),0,deformated); - - TRACE("executing exe %s \n",debugstr_w(cmd)); - - rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); - - HeapFree(GetProcessHeap(),0,cmd); - - if ( !rc ) - { - ERR("Unable to execute command\n"); - return ERROR_SUCCESS; - } - - if (!(type & 0xc0)) - WaitForSingleObject(info.hProcess,INFINITE); - - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - return ERROR_SUCCESS; -} - -static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - LPWSTR filename, deformated; - STARTUPINFOW si; - PROCESS_INFORMATION info; - BOOL rc; - - memset(&si,0,sizeof(STARTUPINFOW)); - - filename = resolve_folder(package, source, FALSE, FALSE, NULL); - - if (!filename) - return ERROR_FUNCTION_FAILED; - - SetCurrentDirectoryW(filename); - HeapFree(GetProcessHeap(),0,filename); - - deformat_string(package,target,&deformated); - - TRACE("executing exe %s \n",debugstr_w(deformated)); - - rc = CreateProcessW(NULL, deformated, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); - HeapFree(GetProcessHeap(),0,deformated); - - if ( !rc ) - { - ERR("Unable to execute command\n"); - return ERROR_SUCCESS; - } - - if (!(type & 0xc0)) - WaitForSingleObject(info.hProcess,INFINITE); - - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - return ERROR_SUCCESS; -} - -/*********************************************************************** - * create_full_pathW - * - * Recursively create all directories in the path. - * - * shamelessly stolen from setupapi/queue.c - */ -static BOOL create_full_pathW(const WCHAR *path) -{ - BOOL ret = TRUE; - int len; - WCHAR *new_path; - - new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * - sizeof(WCHAR)); - - strcpyW(new_path, path); - - while((len = strlenW(new_path)) && new_path[len - 1] == '\\') - new_path[len - 1] = 0; - - while(!CreateDirectoryW(new_path, NULL)) - { - WCHAR *slash; - DWORD last_error = GetLastError(); - if(last_error == ERROR_ALREADY_EXISTS) - break; - - if(last_error != ERROR_PATH_NOT_FOUND) - { - ret = FALSE; - break; - } - - if(!(slash = strrchrW(new_path, '\\'))) - { - ret = FALSE; - break; - } - - len = slash - new_path; - new_path[len] = 0; - if(!create_full_pathW(new_path)) - { - ret = FALSE; - break; - } - new_path[len] = '\\'; - } - - HeapFree(GetProcessHeap(), 0, new_path); - return ret; -} - -/* - * Also we cannot enable/disable components either, so for now I am just going - * to do all the directories for all the components. - */ -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 }; - UINT rc; - MSIQUERY *view; - MSIFOLDER *folder; - - rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view ); - if (rc != ERROR_SUCCESS) - return ERROR_SUCCESS; - - rc = MSI_ViewExecute(view, 0); - if (rc != ERROR_SUCCESS) + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) { MSI_ViewClose(view); msiobj_release(&view->hdr); @@ -1944,7 +1605,7 @@ /* load feature components */ - rc = ACTION_OpenQuery(package->db, &view, Query1, package->features[index].Feature); + rc = MSI_OpenQuery(package->db, &view, Query1, package->features[index].Feature); if (rc != ERROR_SUCCESS) return; rc = MSI_ViewExecute(view,0); @@ -1980,7 +1641,7 @@ continue; } - rc = ACTION_OpenQuery(package->db, &view2, Query2, buffer); + rc = MSI_OpenQuery(package->db, &view2, Query2, buffer); if (rc != ERROR_SUCCESS) { msiobj_release( &row2->hdr ); @@ -2020,13 +1681,13 @@ * I am not doing any of the costing functionality yet. * Mostly looking at doing the Component and Feature loading * - * The native MSI does ALOT of modification to tables here. Mostly adding alot - * of temporary columns to the Feature and Component tables. + * The native MSI does A LOT of modification to tables here. Mostly adding + * a lot of temporary columns to the Feature and Component tables. * - * note: native msi also tracks the short filename. but I am only going to + * note: Native msi also tracks the short filename. But I am only going to * track the long ones. Also looking at this directory table * it appears that the directory table does not get the parents - * resolved base on property only based on their entrys in the + * resolved base on property only based on their entries in the * directory table. */ static UINT ACTION_CostInitialize(MSIPACKAGE *package) @@ -2202,7 +1863,7 @@ package->folders[index].Directory = dupstrW(dir); - rc = ACTION_OpenQuery(package->db, &view, Query, dir); + rc = MSI_OpenQuery(package->db, &view, Query, dir); if (rc != ERROR_SUCCESS) return -1; @@ -2258,8 +1919,7 @@ if (targetdir) { TRACE(" TargetDefault = %s\n",debugstr_w(targetdir)); - if (package->folders[index].TargetDefault) - HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault); + HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault); package->folders[index].TargetDefault = dupstrW(targetdir); } @@ -2293,8 +1953,8 @@ } -static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, - BOOL source, BOOL set_prop, MSIFOLDER **folder) +LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, + BOOL set_prop, MSIFOLDER **folder) { DWORD i; LPWSTR p, path = NULL; @@ -2375,7 +2035,8 @@ } else if (!source && package->folders[i].Property) { - path = dupstrW(package->folders[i].Property); + path = build_directory_name(2, package->folders[i].Property, NULL); + TRACE(" internally set to %s\n",debugstr_w(path)); if (set_prop) MSI_SetPropertyW(package,name,path); @@ -2408,6 +2069,57 @@ return path; } +/* update compoennt state based on a feature change */ +void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) +{ + int i; + INSTALLSTATE newstate; + MSIFEATURE *feature; + + i = get_loaded_feature(package,szFeature); + if (i < 0) + return; + + feature = &package->features[i]; + newstate = feature->ActionRequest; + + for( i = 0; i < feature->ComponentCount; i++) + { + MSICOMPONENT* component = &package->components[feature->Components[i]]; + + if (!component->Enabled) + continue; + else + { + if (newstate == INSTALLSTATE_LOCAL) + component->ActionRequest = INSTALLSTATE_LOCAL; + else + { + int j,k; + + component->ActionRequest = newstate; + + /*if any other feature wants is local we need to set it local*/ + for (j = 0; + j < package->loaded_features && + component->ActionRequest != INSTALLSTATE_LOCAL; + j++) + { + for (k = 0; k < package->features[j].ComponentCount; k++) + if ( package->features[j].Components[k] == + feature->Components[i] ) + { + if (package->features[j].ActionRequest == + INSTALLSTATE_LOCAL) + component->ActionRequest = INSTALLSTATE_LOCAL; + break; + } + } + } + } + } +} + static UINT SetFeatureStates(MSIPACKAGE *package) { LPWSTR level; @@ -2540,7 +2252,7 @@ } /* - * Alot is done in this function aside from just the costing. + * A lot is done in this function aside from just the costing. * The costing needs to be implemented at some point but for now I am going * to focus on the directory building * @@ -2627,8 +2339,7 @@ /* calculate target */ p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL); - if (file->TargetPath) - HeapFree(GetProcessHeap(),0,file->TargetPath); + HeapFree(GetProcessHeap(),0,file->TargetPath); TRACE("file %s is named %s\n", debugstr_w(file->File),debugstr_w(file->FileName)); @@ -2660,7 +2371,7 @@ WCHAR filever[0x100]; VS_FIXEDFILEINFO *lpVer; - FIXME("Version comparison.. \n"); + TRACE("Version comparison.. \n"); versize = GetFileVersionInfoSizeW(file->TargetPath,&handle); version = HeapAlloc(GetProcessHeap(),0,versize); GetFileVersionInfoW(file->TargetPath, 0, versize, version); @@ -2997,7 +2708,10 @@ data.package = package; data.cab_path = cab_path; - file_name = strdupWtoA(file); + if (file) + file_name = strdupWtoA(file); + else + file_name = NULL; data.file_name = file_name; ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data); @@ -3035,7 +2749,7 @@ if (sequence <= last_sequence) { TRACE("Media already ready (%u, %u)\n",sequence,last_sequence); - extract_a_cabinet_file(package, source,path,file); + /*extract_a_cabinet_file(package, source,path,file); */ return ERROR_SUCCESS; } @@ -3094,7 +2808,13 @@ GetTempPathW(MAX_PATH,path); } } - rc = !extract_a_cabinet_file(package, source,path,file); + rc = !extract_a_cabinet_file(package, source,path,NULL); + } + else + { + sz = MAX_PATH; + MSI_GetPropertyW(package,cszSourceDir,source,&sz); + strcpyW(path,source); } msiobj_release(&row->hdr); MSI_ViewClose(view); @@ -3104,7 +2824,7 @@ inline static UINT create_component_directory ( MSIPACKAGE* package, INT component) { - UINT rc; + UINT rc = ERROR_SUCCESS; MSIFOLDER *folder; LPWSTR install_path; @@ -3187,8 +2907,7 @@ comp = &package->components[file->ComponentIndex]; p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL); - if (file->TargetPath) - HeapFree(GetProcessHeap(),0,file->TargetPath); + HeapFree(GetProcessHeap(),0,file->TargetPath); file->TargetPath = build_directory_name(2, p, file->FileName); @@ -3254,7 +2973,7 @@ { if (strcmpW(file_key,package->files[index].File)==0) { - if (package->files[index].State >= 3) + if (package->files[index].State >= 2) { *file_source = dupstrW(package->files[index].TargetPath); return ERROR_SUCCESS; @@ -3323,10 +3042,18 @@ INSTALLSTATE_LOCAL) { TRACE("Skipping copy due to disabled component\n"); + + /* the action taken was the same as the current install state */ + package->components[component_index].Action = + package->components[component_index].Installed; + msiobj_release(&row->hdr); continue; } + package->components[component_index].Action = INSTALLSTATE_LOCAL; + package->components[component_index].Installed = INSTALLSTATE_LOCAL; + sz=0x100; rc = MSI_RecordGetStringW(row,3,file_key,&sz); if (rc != ERROR_SUCCESS) @@ -3342,9 +3069,8 @@ { ERR("Original file unknown %s\n",debugstr_w(file_key)); msiobj_release(&row->hdr); - if (file_source) - HeapFree(GetProcessHeap(),0,file_source); - break; + HeapFree(GetProcessHeap(),0,file_source); + continue; } if (MSI_RecordIsNull(row,4)) @@ -3377,8 +3103,7 @@ { ERR("Unable to get destination folder\n"); msiobj_release(&row->hdr); - if (file_source) - HeapFree(GetProcessHeap(),0,file_source); + HeapFree(GetProcessHeap(),0,file_source); break; } } @@ -3409,7 +3134,7 @@ } -/* OK this value is "interpretted" and then formatted based on the +/* OK this value is "interpreted" and then formatted based on the first few characters */ static LPSTR parse_value(MSIPACKAGE *package, WCHAR *value, DWORD *type, DWORD *size) @@ -3465,6 +3190,7 @@ } else { + static const WCHAR szMulti[] = {'[','~',']',0}; WCHAR *ptr; *type=REG_SZ; @@ -3481,6 +3207,9 @@ else ptr=value; + if (strstrW(value,szMulti)) + *type = REG_MULTI_SZ; + *size = deformat_string(package, ptr,(LPWSTR*)&data); } return data; @@ -3556,9 +3285,16 @@ { TRACE("Skipping write due to disabled component\n"); msiobj_release(&row->hdr); + + package->components[component_index].Action = + package->components[component_index].Installed; + goto next; } + 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)) @@ -3644,113 +3380,16 @@ msiobj_release(&row->hdr); RegCloseKey(hkey); next: - if (uikey) - HeapFree(GetProcessHeap(),0,uikey); - if (key) - HeapFree(GetProcessHeap(),0,key); - if (name) - HeapFree(GetProcessHeap(),0,name); - if (component) - HeapFree(GetProcessHeap(),0,component); + HeapFree(GetProcessHeap(),0,uikey); + HeapFree(GetProcessHeap(),0,key); + HeapFree(GetProcessHeap(),0,name); + HeapFree(GetProcessHeap(),0,component); } MSI_ViewClose(view); msiobj_release(&view->hdr); return rc; } -/* - * This helper function should probably go alot of places - * - * Thinking about this, maybe this should become yet another Bison file - */ -static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data) -{ - WCHAR* mark=NULL; - DWORD size=0; - DWORD chunk=0; - WCHAR key[0x100]; - LPWSTR value; - DWORD sz; - UINT rc; - - if (ptr==NULL) - { - TRACE("Deformatting NULL string\n"); - *data = NULL; - return 0; - } - /* scan for special characters */ - if (!strchrW(ptr,'[') || (strchrW(ptr,'[') && !strchrW(ptr,']'))) - { - /* not formatted */ - size = (strlenW(ptr)+1) * sizeof(WCHAR); - *data = HeapAlloc(GetProcessHeap(),0,size); - strcpyW(*data,ptr); - return size; - } - - /* formatted string located */ - mark = strchrW(ptr,'['); - if (mark != ptr) - { - INT cnt = (mark - ptr); - TRACE("%i (%i) characters before marker\n",cnt,(mark-ptr)); - size = cnt * sizeof(WCHAR); - size += sizeof(WCHAR); - *data = HeapAlloc(GetProcessHeap(),0,size); - strncpyW(*data,ptr,cnt); - (*data)[cnt]=0; - } - else - { - size = sizeof(WCHAR); - *data = HeapAlloc(GetProcessHeap(),0,size); - (*data)[0]=0; - } - mark++; - strcpyW(key,mark); - *strchrW(key,']')=0; - mark = strchrW(mark,']'); - mark++; - TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark)); - sz = 0; - rc = MSI_GetPropertyW(package, key, NULL, &sz); - if ((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA)) - { - LPWSTR newdata; - - sz++; - value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR)); - MSI_GetPropertyW(package, key, value, &sz); - - chunk = (strlenW(value)+1) * sizeof(WCHAR); - size+=chunk; - newdata = HeapReAlloc(GetProcessHeap(),0,*data,size); - *data = newdata; - strcatW(*data,value); - } - TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark)); - if (*mark!=0) - { - LPWSTR newdata; - chunk = (strlenW(mark)+1) * sizeof(WCHAR); - size+=chunk; - newdata = HeapReAlloc(GetProcessHeap(),0,*data,size); - *data = newdata; - strcatW(*data,mark); - } - (*data)[strlenW(*data)]=0; - TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark)); - - /* recursively do this to clean up */ - mark = HeapAlloc(GetProcessHeap(),0,size); - strcpyW(mark,*data); - TRACE("String at this point %s\n",debugstr_w(mark)); - size = deformat_string(package,mark,data); - HeapFree(GetProcessHeap(),0,mark); - return size; -} - static UINT ACTION_InstallInitialize(MSIPACKAGE *package) { return ERROR_SUCCESS; @@ -3848,9 +3487,12 @@ if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE) { + LPWSTR deformated; message = load_dynamic_stringW(row,2); - MessageBoxW(NULL,message,title,MB_OK); + deformat_string(package,message,&deformated); + MessageBoxW(NULL,deformated,title,MB_OK); HeapFree(GetProcessHeap(),0,message); + HeapFree(GetProcessHeap(),0,deformated); rc = ERROR_FUNCTION_FAILED; } HeapFree(GetProcessHeap(),0,cond); @@ -3871,16 +3513,78 @@ LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL); return p; } - if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20)) - { - FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n"); - return NULL; - } - else + if (cmp->Attributes & 0x4) { - int j; - j = get_loaded_file(package,cmp->KeyPath); - + 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}; + + rc = MSI_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath); + + if (rc!=ERROR_SUCCESS) + return NULL; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return NULL; + } + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return NULL; + } + + root = MSI_RecordGetInteger(row,2); + key = load_dynamic_stringW(row, 3); + name = load_dynamic_stringW(row, 4); + deformat_string(package, key , &deformated); + deformat_string(package, name, &deformated_name); + + len = strlenW(deformated) + 5; + if (deformated_name) + len+=strlenW(deformated_name); + + buffer = HeapAlloc(GetProcessHeap(),0, len *sizeof(WCHAR)); + + if (deformated_name) + sprintfW(buffer,fmt2,root,deformated,deformated_name); + else + sprintfW(buffer,fmt,root,deformated); + + HeapFree(GetProcessHeap(),0,key); + HeapFree(GetProcessHeap(),0,deformated); + HeapFree(GetProcessHeap(),0,name); + HeapFree(GetProcessHeap(),0,deformated_name); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + + return buffer; + } + else if (cmp->Attributes & 0x20) + { + FIXME("UNIMPLEMENTED keypath as ODBC Source\n"); + return NULL; + } + else + { + int j; + j = get_loaded_file(package,cmp->KeyPath); + if (j>=0) { LPWSTR p = dupstrW(package->files[j].TargetPath); @@ -3900,23 +3604,13 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) { LPWSTR productcode; - WCHAR squished_pc[0x100]; - WCHAR squished_cc[0x100]; + WCHAR squished_pc[GUID_SIZE]; + WCHAR squished_cc[GUID_SIZE]; UINT rc; DWORD i; - HKEY hkey=0,hkey2=0,hkey3=0; + HKEY hkey=0,hkey2=0; static const WCHAR szProductCode[]= {'P','r','o','d','u','c','t','C','o','d','e',0}; - static const WCHAR szInstaller[] = { - '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',0 }; - static const WCHAR szFeatures[] = { - 'F','e','a','t','u','r','e','s',0 }; - static const WCHAR szComponents[] = { - 'C','o','m','p','o','n','e','n','t','s',0 }; if (!package) return ERROR_INVALID_HANDLE; @@ -3926,57 +3620,11 @@ if (!productcode) return rc; - squash_guid(productcode,squished_pc); - rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey); - if (rc != ERROR_SUCCESS) - goto end; - - rc = RegCreateKeyW(hkey,szFeatures,&hkey2); - if (rc != ERROR_SUCCESS) - goto end; - - rc = RegCreateKeyW(hkey2,squished_pc,&hkey3); - if (rc != ERROR_SUCCESS) - goto end; - - /* here the guids are base 85 encoded */ - for (i = 0; i < package->loaded_features; i++) - { - LPWSTR data = NULL; - GUID clsid; - int j; - INT size; - - size = package->features[i].ComponentCount*21*sizeof(WCHAR); - data = HeapAlloc(GetProcessHeap(), 0, size); - - data[0] = 0; - for (j = 0; j < package->features[i].ComponentCount; j++) - { - WCHAR buf[21]; - TRACE("From %s\n",debugstr_w(package->components - [package->features[i].Components[j]].ComponentId)); - CLSIDFromString(package->components - [package->features[i].Components[j]].ComponentId, - &clsid); - encode_base85_guid(&clsid,buf); - TRACE("to %s\n",debugstr_w(buf)); - strcatW(data,buf); - } - - size = strlenW(data)*sizeof(WCHAR); - RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ, - (LPSTR)data,size); - HeapFree(GetProcessHeap(),0,data); - } - - RegCloseKey(hkey3); - RegCloseKey(hkey2); - - rc = RegCreateKeyW(hkey,szComponents,&hkey2); + rc = MSIREG_OpenComponents(&hkey); if (rc != ERROR_SUCCESS) goto end; + squash_guid(productcode,squished_pc); ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0); for (i = 0; i < package->loaded_components; i++) { @@ -3987,16 +3635,16 @@ MSIRECORD * uirow; squash_guid(package->components[i].ComponentId,squished_cc); - rc = RegCreateKeyW(hkey2,squished_cc,&hkey3); + rc = RegCreateKeyW(hkey,squished_cc,&hkey2); if (rc != ERROR_SUCCESS) continue; keypath = resolve_keypath(package,i); if (keypath) { - RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath, + RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath, (strlenW(keypath)+1)*sizeof(WCHAR)); - RegCloseKey(hkey3); + RegCloseKey(hkey2); /* UI stuff */ uirow = MSI_CreateRecord(3); @@ -4012,7 +3660,6 @@ } end: HeapFree(GetProcessHeap(), 0, productcode); - RegCloseKey(hkey2); RegCloseKey(hkey); return rc; } @@ -4076,9 +3723,16 @@ { TRACE("Skipping typelib reg due to disabled component\n"); msiobj_release(&row->hdr); + + package->components[index].Action = + package->components[index].Installed; + continue; } + package->components[index].Action = INSTALLSTATE_LOCAL; + package->components[index].Installed = INSTALLSTATE_LOCAL; + index = get_loaded_file(package,package->components[index].KeyPath); if (index < 0) @@ -4144,7 +3798,7 @@ if (!package) return ERROR_INVALID_HANDLE; - rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, clsid); + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, clsid); if (rc != ERROR_SUCCESS) return rc; @@ -4266,7 +3920,9 @@ 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 }; + static const WCHAR szSpace[] = {' ',0}; HKEY hkey,hkey2,hkey3; + LPWSTR argument,deformated; if (!package) return ERROR_INVALID_HANDLE; @@ -4297,6 +3953,7 @@ WCHAR desc[0x100]; DWORD sz; INT index; + DWORD size; rc = MSI_ViewFetch(view,&row); if (rc != ERROR_SUCCESS) @@ -4320,9 +3977,16 @@ { TRACE("Skipping class reg due to disabled component\n"); msiobj_release(&row->hdr); + + package->components[index].Action = + package->components[index].Installed; + continue; } + package->components[index].Action = INSTALLSTATE_LOCAL; + package->components[index].Installed = INSTALLSTATE_LOCAL; + sz=0x100; MSI_RecordGetStringW(row,1,clsid,&sz); RegCreateKeyW(hkey,clsid,&hkey2); @@ -4344,10 +4008,25 @@ RegCreateKeyW(hkey2,buffer,&hkey3); index = get_loaded_file(package,package->components[index].KeyPath); - RegSetValueExW(hkey3,NULL,0,REG_SZ, - (LPVOID)package->files[index].TargetPath, - (strlenW(package->files[index].TargetPath)+1) - *sizeof(WCHAR)); + + argument = load_dynamic_stringW(row,11); + size = deformat_string(package,argument,&deformated); + if (deformated) + size+=sizeof(WCHAR); + HeapFree(GetProcessHeap(),0,argument); + size += (strlenW(package->files[index].TargetPath))*sizeof(WCHAR); + + argument = (LPWSTR)HeapAlloc(GetProcessHeap(),0,size+sizeof(WCHAR)); + strcpyW(argument,package->files[index].TargetPath); + if (deformated) + { + strcatW(argument,szSpace); + strcatW(argument,deformated); + } + + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size); + HeapFree(GetProcessHeap(),0,deformated); + HeapFree(GetProcessHeap(),0,argument); RegCloseKey(hkey3); @@ -4375,9 +4054,94 @@ register_appid(package,buffer,desc); } - RegCloseKey(hkey2); - FIXME("Process the rest of the fields >7\n"); + if (!MSI_RecordIsNull(row,7)) + { + FIXME("Process field 7\n"); + } + + if (!MSI_RecordIsNull(row,8)) + { + static const WCHAR szDefaultIcon[] = + {'D','e','f','a','u','l','t','I','c','o','n',0}; + + LPWSTR FileName = load_dynamic_stringW(row,8); + LPWSTR FilePath; + INT index; + + RegCreateKeyW(hkey2,szDefaultIcon,&hkey3); + build_icon_path(package,FileName,&FilePath); + if (!MSI_RecordIsNull(row,9)) + { + static const WCHAR index_fmt[] = {',','%','i',0}; + WCHAR index_buf[20]; + index = MSI_RecordGetInteger(row,9); + sprintfW(index_buf,index_fmt,index); + size = strlenW(FilePath)+strlenW(index_buf)+1; + size *= sizeof(WCHAR); + HeapReAlloc(GetProcessHeap(),0,FilePath,size); + } + RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)FilePath, + (strlenW(FilePath)+1) * sizeof(WCHAR)); + HeapFree(GetProcessHeap(),0,FilePath); + HeapFree(GetProcessHeap(),0,FileName); + RegCloseKey(hkey3); + } + + 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}; + 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}; + switch(i) + { + case 1: + size = strlenW(ole2) * sizeof(WCHAR); + RegCreateKeyW(hkey2,szInproc,&hkey3); + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size); + RegCloseKey(hkey3); + break; + case 2: + size = strlenW(ole32) * sizeof(WCHAR); + RegCreateKeyW(hkey2,szInproc32,&hkey3); + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size); + RegCloseKey(hkey3); + break; + case 3: + size = strlenW(ole2) * sizeof(WCHAR); + RegCreateKeyW(hkey2,szInproc,&hkey3); + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size); + RegCloseKey(hkey3); + size = strlenW(ole32) * sizeof(WCHAR); + RegCreateKeyW(hkey2,szInproc32,&hkey3); + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size); + RegCloseKey(hkey3); + break; + } + + } + else + { + RegCreateKeyW(hkey2,szInproc32,&hkey3); + argument = load_dynamic_stringW(row,10); + reduce_to_longfilename(argument); + size = strlenW(argument)*sizeof(WCHAR); + + RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size); + HeapFree(GetProcessHeap(),0,argument); + + RegCloseKey(hkey3); + } + } + + RegCloseKey(hkey2); ui_actiondata(package,szRegisterClassInfo,row); @@ -4391,9 +4155,12 @@ return rc; } -static UINT register_progid_base(MSIRECORD * row, LPWSTR clsid) +static UINT register_progid_base(MSIPACKAGE* package, MSIRECORD * row, + 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}; HKEY hkey,hkey2; WCHAR buffer[0x100]; DWORD sz; @@ -4431,7 +4198,25 @@ return ERROR_FUNCTION_FAILED; } if (!MSI_RecordIsNull(row,5)) - FIXME ("UNHANDLED icon in Progid\n"); + { + INT index = MSI_RecordGetInteger(row,6); + LPWSTR FileName = load_dynamic_stringW(row,5); + LPWSTR FilePath,IconPath; + static const WCHAR fmt[] = {'%','s',',','%','i',0}; + + RegCreateKeyW(hkey,szDefaultIcon,&hkey2); + build_icon_path(package,FileName,&FilePath); + + IconPath = HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)* + sizeof(WCHAR)); + + sprintfW(IconPath,fmt,FilePath,index); + RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)IconPath, + (strlenW(IconPath)+1) * sizeof(WCHAR)); + HeapFree(GetProcessHeap(),0,FilePath); + HeapFree(GetProcessHeap(),0,FileName); + RegCloseKey(hkey2); + } return ERROR_SUCCESS; } @@ -4451,7 +4236,7 @@ if (!package) return ERROR_INVALID_HANDLE; - rc = ACTION_OpenQuery(package->db, &view, Query_t, parent); + rc = MSI_OpenQuery(package->db, &view, Query_t, parent); if (rc != ERROR_SUCCESS) return rc; @@ -4484,13 +4269,15 @@ UINT rc = ERROR_SUCCESS; if (MSI_RecordIsNull(row,2)) - rc = register_progid_base(row,clsid); + rc = register_progid_base(package,row,clsid); else { WCHAR buffer[0x1000]; 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}; /* check if already registered */ sz = 0x100; @@ -4503,6 +4290,11 @@ RegCloseKey(hkey); return rc; } + + sz = 0x100; + MSI_RecordGetStringW(row,2,buffer,&sz); + rc = register_parent_progid(package,buffer,clsid); + /* clsid is same as parent */ RegCreateKeyW(hkey,szCLSID,&hkey2); RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) * @@ -4510,9 +4302,6 @@ RegCloseKey(hkey2); - sz = 0x100; - MSI_RecordGetStringW(row,2,buffer,&sz); - rc = register_parent_progid(package,buffer,clsid); if (!MSI_RecordIsNull(row,4)) { @@ -4523,7 +4312,17 @@ } if (!MSI_RecordIsNull(row,5)) - FIXME ("UNHANDLED icon in Progid\n"); + { + LPWSTR FileName = load_dynamic_stringW(row,5); + LPWSTR FilePath; + RegCreateKeyW(hkey,szDefaultIcon,&hkey2); + build_icon_path(package,FileName,&FilePath); + RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)FilePath, + (strlenW(FilePath)+1) * sizeof(WCHAR)); + HeapFree(GetProcessHeap(),0,FilePath); + HeapFree(GetProcessHeap(),0,FileName); + RegCloseKey(hkey2); + } RegCloseKey(hkey); } @@ -4680,9 +4479,16 @@ { TRACE("Skipping shortcut creation due to disabled component\n"); msiobj_release(&row->hdr); + + package->components[index].Action = + package->components[index].Installed; + continue; } + package->components[index].Action = INSTALLSTATE_LOCAL; + package->components[index].Installed = INSTALLSTATE_LOCAL; + ui_actiondata(package,szCreateShortcuts,row); res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, @@ -4820,20 +4626,33 @@ '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}; + LPWSTR buffer; + DWORD size; + MSIHANDLE hDb, hSumInfo; if (!package) return ERROR_INVALID_HANDLE; rc = MSI_DatabaseOpenViewW(package->db, Query, &view); if (rc != ERROR_SUCCESS) - return ERROR_SUCCESS; + goto next; rc = MSI_ViewExecute(view, 0); if (rc != ERROR_SUCCESS) { MSI_ViewClose(view); msiobj_release(&view->hdr); - return rc; + goto next; } while (1) @@ -4897,74 +4716,978 @@ } MSI_ViewClose(view); msiobj_release(&view->hdr); - return rc; -} +next: + /* ok there is a lot more done here but i need to figure out what */ + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; -/* Msi functions that seem appropriate here */ -UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) -{ - LPWSTR szwAction; - UINT rc; + rc = MSIREG_OpenProductsKey(productcode,&hkey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; - TRACE(" exteral attempt at action %s\n",szAction); + rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; - if (!szAction) - return ERROR_FUNCTION_FAILED; - if (hInstall == 0) - return ERROR_FUNCTION_FAILED; - szwAction = strdupAtoW(szAction); + buffer = load_dynamic_property(package,szProductName,NULL); + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hukey,szProductName,0,REG_SZ, (LPSTR)buffer,size); + HeapFree(GetProcessHeap(),0,buffer); + FIXME("Need to write more keys to the user registry\n"); + + hDb= msiobj_findhandle( &package->db->hdr ); + rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo); + if (rc == ERROR_SUCCESS) + { + WCHAR guidbuffer[0x200]; + size = 0x200; + rc = MsiSummaryInfoGetPropertyW(hSumInfo, 8, NULL, NULL, NULL, + guidbuffer, &size); + if (rc == ERROR_SUCCESS) + { + WCHAR squashed[GUID_SIZE]; + /* for now we only care about the first guid */ + 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); + + } + else + { + ERR("Unable to query Revision_Number... \n"); + rc = ERROR_SUCCESS; + } + MsiCloseHandle(hSumInfo); + } + else + { + ERR("Unable to open Summary Information\n"); + rc = ERROR_SUCCESS; + } - if (!szwAction) - return ERROR_FUNCTION_FAILED; +end: + HeapFree(GetProcessHeap(),0,productcode); + RegCloseKey(hkey); + RegCloseKey(hukey); - rc = MsiDoActionW(hInstall, szwAction); - HeapFree(GetProcessHeap(),0,szwAction); return rc; } -UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction ) +static UINT ACTION_WriteIniValues(MSIPACKAGE *package) { - MSIPACKAGE *package; - UINT ret = ERROR_INVALID_HANDLE; - - TRACE(" external attempt at action %s \n",debugstr_w(szAction)); + 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 szWindowsFolder[] = + {'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; - package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); - if( package ) + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); + if (rc != ERROR_SUCCESS) { - ret = ACTION_PerformAction(package,szAction); - msiobj_release( &package->hdr ); + TRACE("no IniFile table\n"); + return ERROR_SUCCESS; } - return ret; -} -UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, - LPSTR szPathBuf, DWORD* pcchPathBuf) -{ - LPWSTR szwFolder; - LPWSTR szwPathBuf; - UINT rc; + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } - TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf); + while (1) + { + LPWSTR component,filename,dirproperty,section,key,value,identifier; + LPWSTR deformated_section, deformated_key, deformated_value; + LPWSTR folder, fullname = NULL; + MSIRECORD * uirow; + INT component_index,action; - if (!szFolder) - return ERROR_FUNCTION_FAILED; - if (hInstall == 0) - return ERROR_FUNCTION_FAILED; + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } - szwFolder = strdupAtoW(szFolder); + component = load_dynamic_stringW(row, 8); + component_index = get_loaded_component(package,component); + HeapFree(GetProcessHeap(),0,component); - if (!szwFolder) - return ERROR_FUNCTION_FAILED; + if (package->components[component_index].ActionRequest != + INSTALLSTATE_LOCAL) + { + TRACE("Skipping ini file due to disabled component\n"); + msiobj_release(&row->hdr); - szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR)); + package->components[component_index].Action = + package->components[component_index].Installed; - rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf); + continue; + } - WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf, + 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); + dirproperty = load_dynamic_stringW(row,3); + section = load_dynamic_stringW(row,4); + key = load_dynamic_stringW(row,5); + value = load_dynamic_stringW(row,6); + action = MSI_RecordGetInteger(row,7); + + deformat_string(package,section,&deformated_section); + deformat_string(package,key,&deformated_key); + deformat_string(package,value,&deformated_value); + + if (dirproperty) + { + folder = resolve_folder(package, dirproperty, FALSE, FALSE, NULL); + if (!folder) + folder = load_dynamic_property(package,dirproperty,NULL); + } + else + folder = load_dynamic_property(package, szWindowsFolder, NULL); + + if (!folder) + { + ERR("Unable to resolve folder! (%s)\n",debugstr_w(dirproperty)); + goto cleanup; + } + + fullname = build_directory_name(3, folder, filename, NULL); + + if (action == 0) + { + TRACE("Adding value %s to section %s in %s\n", + debugstr_w(deformated_key), debugstr_w(deformated_section), + debugstr_w(fullname)); + WritePrivateProfileStringW(deformated_section, deformated_key, + deformated_value, fullname); + } + else if (action == 1) + { + WCHAR returned[10]; + GetPrivateProfileStringW(deformated_section, deformated_key, NULL, + returned, 10, fullname); + if (returned[0] == 0) + { + TRACE("Adding value %s to section %s in %s\n", + debugstr_w(deformated_key), debugstr_w(deformated_section), + debugstr_w(fullname)); + + WritePrivateProfileStringW(deformated_section, deformated_key, + deformated_value, fullname); + } + } + else if (action == 3) + { + FIXME("Append to existing section not yet implemented\n"); + } + + uirow = MSI_CreateRecord(4); + MSI_RecordSetStringW(uirow,1,identifier); + MSI_RecordSetStringW(uirow,2,deformated_section); + MSI_RecordSetStringW(uirow,3,deformated_key); + MSI_RecordSetStringW(uirow,4,deformated_value); + ui_actiondata(package,szWriteIniValues,uirow); + msiobj_release( &uirow->hdr ); +cleanup: + HeapFree(GetProcessHeap(),0,identifier); + HeapFree(GetProcessHeap(),0,fullname); + HeapFree(GetProcessHeap(),0,filename); + HeapFree(GetProcessHeap(),0,key); + HeapFree(GetProcessHeap(),0,value); + HeapFree(GetProcessHeap(),0,section); + HeapFree(GetProcessHeap(),0,dirproperty); + HeapFree(GetProcessHeap(),0,folder); + HeapFree(GetProcessHeap(),0,deformated_key); + HeapFree(GetProcessHeap(),0,deformated_value); + HeapFree(GetProcessHeap(),0,deformated_section); + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; +} + +static UINT ACTION_SelfRegModules(MSIPACKAGE *package) +{ + 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 ExeStr[] = { +'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','s',' ',0}; + STARTUPINFOW si; + PROCESS_INFORMATION info; + BOOL brc; + + memset(&si,0,sizeof(STARTUPINFOW)); + + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); + if (rc != ERROR_SUCCESS) + { + TRACE("no SelfReg table\n"); + return ERROR_SUCCESS; + } + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } + + while (1) + { + LPWSTR filename; + INT index; + DWORD len; + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + filename = load_dynamic_stringW(row,1); + index = get_loaded_file(package,filename); + + if (index < 0) + { + ERR("Unable to find file id %s\n",debugstr_w(filename)); + HeapFree(GetProcessHeap(),0,filename); + msiobj_release(&row->hdr); + continue; + } + HeapFree(GetProcessHeap(),0,filename); + + len = strlenW(ExeStr); + len += strlenW(package->files[index].TargetPath); + len +=2; + + filename = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + strcpyW(filename,ExeStr); + strcatW(filename,package->files[index].TargetPath); + + TRACE("Registering %s\n",debugstr_w(filename)); + brc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + + if (brc) + msi_dialog_check_messages(package->dialog, info.hProcess); + + HeapFree(GetProcessHeap(),0,filename); + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; +} + +static UINT ACTION_PublishFeatures(MSIPACKAGE *package) +{ + LPWSTR productcode; + UINT rc; + 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; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + rc = MSIREG_OpenFeaturesKey(productcode,&hkey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; + + rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; + + /* here the guids are base 85 encoded */ + for (i = 0; i < package->loaded_features; i++) + { + LPWSTR data = NULL; + GUID clsid; + int j; + INT size; + + size = package->features[i].ComponentCount*21; + size +=1; + if (package->features[i].Feature_Parent[0]) + size += strlenW(package->features[i].Feature_Parent)+2; + + data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); + + data[0] = 0; + for (j = 0; j < package->features[i].ComponentCount; j++) + { + WCHAR buf[21]; + memset(buf,0,sizeof(buf)); + TRACE("From %s\n",debugstr_w(package->components + [package->features[i].Components[j]].ComponentId)); + CLSIDFromString(package->components + [package->features[i].Components[j]].ComponentId, + &clsid); + encode_base85_guid(&clsid,buf); + TRACE("to %s\n",debugstr_w(buf)); + strcatW(data,buf); + } + if (package->features[i].Feature_Parent[0]) + { + static const WCHAR sep[] = {'\2',0}; + strcatW(data,sep); + strcatW(data,package->features[i].Feature_Parent); + } + + size = (strlenW(data)+1)*sizeof(WCHAR); + RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ, + (LPSTR)data,size); + HeapFree(GetProcessHeap(),0,data); + + size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR); + RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ, + (LPSTR)package->features[i].Feature_Parent,size); + } + +end: + RegCloseKey(hkey); + RegCloseKey(hukey); + HeapFree(GetProcessHeap(), 0, productcode); + return rc; +} + +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; + UINT rc,i; + DWORD size; + static WCHAR szNONE[] = {0}; + static const WCHAR szWindowsInstaler[] = + {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; + 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','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}, +{'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}, +{'A','R','P','U','R','L','I','N','F','O','A','B','O','U','T',0}, +{'A','R','P','U','R','L','U','P','D','A','T','E','I','N','F','O',0}, +{0}, + }; + + static const WCHAR szRegKeys[][80] = + { +{'A','u','t','h','o','r','i','z','e','d','C','D','F','P','r','e','f','i','x',0}, +{'C','o','n','t','a','c','t',0}, +{'C','o','m','m','e','n','t','s',0}, +{'D','i','s','p','l','a','y','N','a','m','e',0}, +{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}, +{'H','e','l','p','L','i','n','k',0}, +{'H','e','l','p','T','e','l','e','p','h','o','n','e',0}, +{'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0}, +{'I','n','s','t','a','l','l','S','o','u','r','c','e',0}, +{'P','u','b','l','i','s','h','e','r',0}, +{'R','e','a','d','m','e',0}, +{'S','i','z','e',0}, +{'U','R','L','I','n','f','o','A','b','o','u','t',0}, +{'U','R','L','U','p','d','a','t','e','I','n','f','o',0}, +{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 fmt[] = { + 'C',':','\\','W','i','n','d','o','w','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]; + INT num,start; + + if (!package) + return ERROR_INVALID_HANDLE; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; + + /* dump all the info i can grab */ + FIXME("Flesh out more information \n"); + + i = 0; + while (szPropKeys[i][0]!=0) + { + buffer = load_dynamic_property(package,szPropKeys[i],&rc); + if (rc != ERROR_SUCCESS) + buffer = szNONE; + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size); + i++; + } + + rc = 0x1; + size = sizeof(rc); + RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size); + + /* copy the package locally */ + num = GetTickCount() & 0xffff; + if (!num) + num = 1; + start = num; + sprintfW(packagefile,fmt,num); + do + { + HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); + if (handle != INVALID_HANDLE_VALUE) + { + CloseHandle(handle); + break; + } + if (GetLastError() != ERROR_FILE_EXISTS && + GetLastError() != ERROR_SHARING_VIOLATION) + break; + if (!(++num & 0xffff)) num = 1; + sprintfW(packagefile,fmt,num); + } while (num != start); + + create_full_pathW(path); + TRACE("Copying to local package %s\n",debugstr_w(packagefile)); + CopyFileW(package->PackagePath,packagefile,FALSE); + size = strlenW(packagefile)*sizeof(WCHAR); + RegSetValueExW(hkey,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size); + +end: + HeapFree(GetProcessHeap(),0,productcode); + RegCloseKey(hkey); + + return ERROR_SUCCESS; +} + +static UINT ACTION_InstallExecute(MSIPACKAGE *package) +{ + int i; + if (!package) + return ERROR_INVALID_HANDLE; + + for (i = 0; i < package->DeferredActionCount; i++) + { + LPWSTR action; + action = package->DeferredAction[i]; + ui_actionstart(package, action); + TRACE("Executing Action (%s)\n",debugstr_w(action)); + ACTION_CustomAction(package,action,TRUE); + HeapFree(GetProcessHeap(),0,package->DeferredAction[i]); + } + HeapFree(GetProcessHeap(),0,package->DeferredAction); + + package->DeferredActionCount = 0; + package->DeferredAction = NULL; + + return ERROR_SUCCESS; +} + +static UINT ACTION_InstallFinalize(MSIPACKAGE *package) +{ + int i; + if (!package) + return ERROR_INVALID_HANDLE; + + /* first do the same as an InstallExecute */ + ACTION_InstallExecute(package); + + /* then handle Commit Actions */ + for (i = 0; i < package->CommitActionCount; i++) + { + LPWSTR action; + action = package->CommitAction[i]; + ui_actionstart(package, action); + TRACE("Executing Commit Action (%s)\n",debugstr_w(action)); + ACTION_CustomAction(package,action,TRUE); + HeapFree(GetProcessHeap(),0,package->CommitAction[i]); + } + HeapFree(GetProcessHeap(),0,package->CommitAction); + + package->CommitActionCount = 0; + package->CommitAction = NULL; + + return ERROR_SUCCESS; +} + +static UINT ACTION_ForceReboot(MSIPACKAGE *package) +{ + static const WCHAR RunOnce[] = { + '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','\\', + 'R','u','n','O','n','c','e'}; + 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'}; + + static const WCHAR msiexec_fmt[] = { + 'C',':','\\','W','i','n','d','o','w','s','\\','S','y','s','t','e','m', + '\\','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]; + 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[] = { + 'S','o','u','r','c','e','L','i','s','t',0}; + static const WCHAR szPackageName[] = { + 'P','a','c','k','a','g','e','N','a','m','e',0}; + + if (!package) + return ERROR_INVALID_HANDLE; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + squash_guid(productcode,squished_pc); + + RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey); + sprintfW(buffer,msiexec_fmt,squished_pc); + + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); + RegCloseKey(hkey); + + TRACE("Reboot command %s\n",debugstr_w(buffer)); + + RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey); + sprintfW(buffer,install_fmt,productcode,squished_pc); + RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size); + RegCloseKey(hkey); + + rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE); + if (rc == ERROR_SUCCESS) + { + HKEY hukey2; + LPWSTR buf; + RegCreateKeyW(hukey, szSourceList, &hukey2); + buf = load_dynamic_property(package,cszSourceDir,NULL); + size = strlenW(buf)*sizeof(WCHAR); + RegSetValueExW(hukey2,szLUS,0,REG_SZ,(LPSTR)buf,size); + HeapFree(GetProcessHeap(),0,buf); + + buf = strrchrW(package->PackagePath,'\\'); + if (buf) + { + buf++; + size = strlenW(buf)*sizeof(WCHAR); + RegSetValueExW(hukey2,szPackageName,0,REG_SZ,(LPSTR)buf,size); + } + + RegCloseKey(hukey2); + } + HeapFree(GetProcessHeap(),0,productcode); + + return ERROR_INSTALL_SUSPEND; +} + +UINT ACTION_ResolveSource(MSIPACKAGE* package) +{ + /* + * we are currently doing what should be done here in the top level Install + * however for Adminastrative and uninstalls this step will be needed + */ + return ERROR_SUCCESS; +} + + +static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package) +{ + 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 szContentType[] = +{ 'C','o','n','t','e','n','t',' ','T','y','p','e',0 }; + HKEY hkey; + + if (!package) + return ERROR_INVALID_HANDLE; + + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + goto end; + } + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + goto end; + } + + while (1) + { + WCHAR buffer[0x100]; + WCHAR extension[257]; + LPWSTR exten; + DWORD sz; + INT index; + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + sz=0x100; + MSI_RecordGetStringW(row,2,buffer,&sz); + + index = get_loaded_component(package,buffer); + + if (index < 0) + { + msiobj_release(&row->hdr); + continue; + } + + if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) + { + TRACE("Skipping extension reg due to disabled component\n"); + msiobj_release(&row->hdr); + + package->components[index].Action = + package->components[index].Installed; + + continue; + } + + package->components[index].Action = INSTALLSTATE_LOCAL; + package->components[index].Installed = INSTALLSTATE_LOCAL; + + exten = load_dynamic_stringW(row,1); + extension[0] = '.'; + extension[1] = 0; + strcatW(extension,exten); + HeapFree(GetProcessHeap(),0,exten); + + RegCreateKeyW(HKEY_CLASSES_ROOT,extension,&hkey); + + if (!MSI_RecordIsNull(row,4)) + { + LPWSTR mime = load_dynamic_stringW(row,4); + RegSetValueExW(hkey,szContentType,0,REG_SZ,(LPVOID)mime, + (strlenW(mime)+1)*sizeof(WCHAR)); + HeapFree(GetProcessHeap(),0,mime); + } + + if (!MSI_RecordIsNull(row,3)) + { + static const WCHAR szSN[] = + {'\\','S','h','e','l','l','N','e','w',0}; + HKEY hkey2; + LPWSTR newkey; + LPWSTR progid= load_dynamic_stringW(row,3); + + RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid, + (strlenW(progid)+1)*sizeof(WCHAR)); + + newkey = HeapAlloc(GetProcessHeap(),0, + (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); + + strcpyW(newkey,progid); + strcatW(newkey,szSN); + RegCreateKeyW(hkey,newkey,&hkey2); + RegCloseKey(hkey2); + + HeapFree(GetProcessHeap(),0,progid); + HeapFree(GetProcessHeap(),0,newkey); + } + + + RegCloseKey(hkey); + + ui_actiondata(package,szRegisterExtensionInfo,row); + + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); + +end: + return rc; +} + +static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package) +{ + 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 szExten[] = +{ 'E','x','t','e','n','s','i','o','n',0 }; + HKEY hkey; + + if (!package) + return ERROR_INVALID_HANDLE; + + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + goto end; + } + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + goto end; + } + + while (1) + { + WCHAR extension[257]; + 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}; + LPWSTR key; + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + mime = load_dynamic_stringW(row,1); + exten = load_dynamic_stringW(row,2); + extension[0] = '.'; + extension[1] = 0; + strcatW(extension,exten); + HeapFree(GetProcessHeap(),0,exten); + + key = HeapAlloc(GetProcessHeap(),0,(strlenW(mime)+strlenW(fmt)+1) * + sizeof(WCHAR)); + sprintfW(key,fmt,mime); + RegCreateKeyW(HKEY_CLASSES_ROOT,key,&hkey); + RegSetValueExW(hkey,szExten,0,REG_SZ,(LPVOID)extension, + (strlenW(extension)+1)*sizeof(WCHAR)); + + HeapFree(GetProcessHeap(),0,mime); + HeapFree(GetProcessHeap(),0,key); + + if (!MSI_RecordIsNull(row,3)) + { + FIXME("Handle non null for field 3\n"); + } + + RegCloseKey(hkey); + + ui_actiondata(package,szRegisterMIMEInfo,row); + + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); + +end: + return rc; +} + +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; + LPWSTR buffer; + LPWSTR productcode; + LPWSTR productid; + UINT rc,i; + DWORD size; + + 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}, + }; + + 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}, + }; + + if (!package) + return ERROR_INVALID_HANDLE; + + productid = load_dynamic_property(package,szProductID,&rc); + if (!productid) + return ERROR_SUCCESS; + + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; + + rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE); + if (rc != ERROR_SUCCESS) + goto end; + + i = 0; + while (szPropKeys[i][0]!=0) + { + buffer = load_dynamic_property(package,szPropKeys[i],&rc); + if (rc == ERROR_SUCCESS) + { + size = strlenW(buffer)*sizeof(WCHAR); + RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size); + } + i++; + } + +end: + HeapFree(GetProcessHeap(),0,productcode); + HeapFree(GetProcessHeap(),0,productid); + RegCloseKey(hkey); + + return ERROR_SUCCESS; +} + +/* Msi functions that seem appropriate here */ +UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) +{ + LPWSTR szwAction; + UINT rc; + + TRACE(" exteral attempt at action %s\n",szAction); + + if (!szAction) + return ERROR_FUNCTION_FAILED; + if (hInstall == 0) + return ERROR_FUNCTION_FAILED; + + szwAction = strdupAtoW(szAction); + + if (!szwAction) + return ERROR_FUNCTION_FAILED; + + + rc = MsiDoActionW(hInstall, szwAction); + HeapFree(GetProcessHeap(),0,szwAction); + return rc; +} + +UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction ) +{ + MSIPACKAGE *package; + UINT ret = ERROR_INVALID_HANDLE; + + TRACE(" external attempt at action %s \n",debugstr_w(szAction)); + + package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); + if( package ) + { + ret = ACTION_PerformAction(package,szAction); + msiobj_release( &package->hdr ); + } + return ret; +} + +UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, + LPSTR szPathBuf, DWORD* pcchPathBuf) +{ + LPWSTR szwFolder; + LPWSTR szwPathBuf; + UINT rc; + + TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf); + + if (!szFolder) + return ERROR_FUNCTION_FAILED; + if (hInstall == 0) + return ERROR_FUNCTION_FAILED; + + szwFolder = strdupAtoW(szFolder); + + if (!szwFolder) + return ERROR_FUNCTION_FAILED; + + szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR)); + + rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf); + + WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf, *pcchPathBuf, NULL, NULL ); HeapFree(GetProcessHeap(),0,szwFolder); @@ -5107,7 +5830,6 @@ DWORD i; LPWSTR path = NULL; LPWSTR path2 = NULL; - INT len; MSIFOLDER *folder; TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath)); @@ -5126,22 +5848,10 @@ if (!path) return ERROR_INVALID_PARAMETER; - if (folder->Property) - HeapFree(GetProcessHeap(),0,folder->Property); - - len = strlenW(szFolderPath); - - if (szFolderPath[len-1]!='\\') - { - len +=2; - folder->Property = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); - strcpyW(folder->Property,szFolderPath); - strcatW(folder->Property,cszbs); - } - else - folder->Property = dupstrW(szFolderPath); + HeapFree(GetProcessHeap(),0,folder->Property); + folder->Property = build_directory_name(2, szFolderPath, NULL); - if (strcmpiW(path, szFolderPath) == 0) + if (strcmpiW(path, folder->Property) == 0) { /* * Resolved Target has not really changed, so just @@ -5156,8 +5866,7 @@ { for (i = 0; i < package->loaded_folders; i++) { - if (package->folders[i].ResolvedTarget) - HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget); + HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget); package->folders[i].ResolvedTarget=NULL; } @@ -5204,8 +5913,8 @@ * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation * MSIRUNMODE_CABINET Files from cabinet are installed - * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is supressed - * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is supressed + * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed + * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed * MSIRUNMODE_RESERVED11 Reserved * MSIRUNMODE_WINDOWS9X Running under Windows95/98 * MSIRUNMODE_ZAWENABLED Demand installation is supported @@ -5266,6 +5975,7 @@ return ERROR_UNKNOWN_FEATURE; package->features[index].ActionRequest= iState; + ACTION_UpdateComponentStates(package,szFeature); return ERROR_SUCCESS; } @@ -5353,7 +6063,10 @@ *piInstalled = package->components[index].Installed; if (piAction) - *piInstalled = package->components[index].Action; + *piAction = package->components[index].Action; + + TRACE("states (%i, %i)\n", +(piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1); return ERROR_SUCCESS; } @@ -5383,21 +6096,21 @@ MSIRECORD * row = 0; static const WCHAR ExecSeqQuery[] = {0}; - rc = MsiDatabaseOpenViewW(package->db, ExecSeqQuery, &view); + rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); if (rc != ERROR_SUCCESS) return rc; - rc = MsiViewExecute(view, 0); + rc = MSI_ViewExecute(view, 0); if (rc != ERROR_SUCCESS) { - MsiViewClose(view); + MSI_ViewClose(view); msiobj_release(&view->hdr); return rc; } while (1) { - rc = MsiViewFetch(view,&row); + rc = MSI_ViewFetch(view,&row); if (rc != ERROR_SUCCESS) { rc = ERROR_SUCCESS; @@ -5406,7 +6119,7 @@ msiobj_release(&row->hdr); } - MsiViewClose(view); + MSI_ViewClose(view); msiobj_release(&view->hdr); return rc; } diff -urN wine-20050111/dlls/msi/action.h wine-20050211/dlls/msi/action.h --- wine-20050111/dlls/msi/action.h 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/action.h 2005-02-01 19:46:26.000000000 +0100 @@ -0,0 +1,151 @@ +/* + * Common prototypes for Action handlers + * + * Copyright 2005 Aric Stewart 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 + */ + +typedef struct tagMSIFEATURE +{ + WCHAR Feature[96]; + WCHAR Feature_Parent[96]; + WCHAR Title[0x100]; + WCHAR Description[0x100]; + INT Display; + INT Level; + WCHAR Directory[96]; + INT Attributes; + + INSTALLSTATE Installed; + INSTALLSTATE ActionRequest; + INSTALLSTATE Action; + + INT ComponentCount; + INT Components[1024]; /* yes hardcoded limit.... I am bad */ + INT Cost; +} MSIFEATURE; + +typedef struct tagMSICOMPONENT +{ + WCHAR Component[96]; + WCHAR ComponentId[96]; + WCHAR Directory[96]; + INT Attributes; + WCHAR Condition[0x100]; + WCHAR KeyPath[96]; + + INSTALLSTATE Installed; + INSTALLSTATE ActionRequest; + INSTALLSTATE Action; + + BOOL Enabled; + INT Cost; +} MSICOMPONENT; + +typedef struct tagMSIFOLDER +{ + LPWSTR Directory; + LPWSTR TargetDefault; + LPWSTR SourceDefault; + + LPWSTR ResolvedTarget; + LPWSTR ResolvedSource; + LPWSTR Property; /* initially set property */ + INT ParentIndex; + INT State; + /* 0 = uninitialized */ + /* 1 = existing */ + /* 2 = created remove if empty */ + /* 3 = created persist if empty */ + INT Cost; + INT Space; +}MSIFOLDER; + +typedef struct tagMSIFILE +{ + LPWSTR File; + INT ComponentIndex; + LPWSTR FileName; + INT FileSize; + LPWSTR Version; + LPWSTR Language; + INT Attributes; + INT Sequence; + + INT State; + /* 0 = uninitialize */ + /* 1 = not present */ + /* 2 = present but replace */ + /* 3 = present do not replace */ + /* 4 = Installed */ + LPWSTR SourcePath; + LPWSTR TargetPath; + BOOL Temporary; +}MSIFILE; + + +UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action); +UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action); +void ACTION_FinishCustomActions( MSIPACKAGE* package); +UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute); +void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature); +UINT ACTION_AppSearch(MSIPACKAGE *package); + +DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data ); +WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index); +LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc); +LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, + BOOL set_prop, MSIFOLDER **folder); +int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component ); +int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ); +int get_loaded_file(MSIPACKAGE* package, LPCWSTR file); +int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); + + + +inline static char *strdupWtoA( const WCHAR *str ) +{ + char *ret = NULL; + if (str) + { + DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL +); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) + WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); + } + return ret; +} + +inline static WCHAR *strdupAtoW( const char *str ) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + } + return ret; +} + +inline static LPWSTR dupstrW(LPCWSTR src) +{ + LPWSTR dest; + if (!src) return NULL; + dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR)); + strcpyW(dest, src); + return dest; +} diff -urN wine-20050111/dlls/msi/appsearch.c wine-20050211/dlls/msi/appsearch.c --- wine-20050111/dlls/msi/appsearch.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/appsearch.c 2005-02-08 13:08:49.000000000 +0100 @@ -0,0 +1,855 @@ +/* + * Implementation of the AppSearch action of the Microsoft Installer (msi.dll) + * + * Copyright 2005 Juan Lang + * + * 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 + +#include "windef.h" +#include "winbase.h" +#include "msi.h" +#include "msiquery.h" +#include "winver.h" +#include "wine/unicode.h" +#include "wine/debug.h" +#include "msipriv.h" +#include "action.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +typedef struct tagMSISIGNATURE +{ + LPWSTR Name; /* NOT owned by this structure */ + LPWSTR Property; /* NOT owned by this structure */ + LPWSTR File; + DWORD MinVersionMS; + DWORD MinVersionLS; + DWORD MaxVersionMS; + DWORD MaxVersionLS; + DWORD MinSize; + DWORD MaxSize; + FILETIME MinTime; + FILETIME MaxTime; + LPWSTR Languages; +}MSISIGNATURE; + +static void ACTION_VerStrToInteger(LPCWSTR verStr, PDWORD ms, PDWORD ls) +{ + const WCHAR *ptr; + int x1 = 0, x2 = 0, x3 = 0, x4 = 0; + + x1 = atoiW(verStr); + ptr = strchrW(verStr, '.'); + if (ptr) + { + x2 = atoiW(ptr + 1); + ptr = strchrW(ptr + 1, '.'); + } + if (ptr) + { + x3 = atoiW(ptr + 1); + ptr = strchrW(ptr + 1, '.'); + } + if (ptr) + x4 = atoiW(ptr + 1); + /* FIXME: byte-order dependent? */ + *ms = x1 << 16 | x2; + *ls = x3 << 16 | x4; +} + +/* Fills in sig with the the values from the Signature table, where name is the + * signature to find. Upon return, sig->File will be NULL if the record is not + * found, and not NULL if it is found. + * Warning: clears all fields in sig! + * Returns ERROR_SUCCESS upon success (where not finding the record counts as + * success), something else on error. + */ +static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig, + LPCWSTR name) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'S','i','g','n','a','t','u','r','e',' ', + 'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e',' ','=',' ', + '\'','%','s','\'',0}; + + TRACE("(package %p, sig %p)\n", package, sig); + memset(sig, 0, sizeof(*sig)); + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, name); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + DWORD time; + WCHAR *minVersion, *maxVersion; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewExecute returned %d\n", rc); + goto end; + } + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewFetch returned %d\n", rc); + rc = ERROR_SUCCESS; + goto end; + } + + /* get properties */ + sig->File = load_dynamic_stringW(row,2); + minVersion = load_dynamic_stringW(row,3); + if (minVersion) + { + ACTION_VerStrToInteger(minVersion, &sig->MinVersionMS, + &sig->MinVersionLS); + HeapFree(GetProcessHeap(), 0, minVersion); + } + maxVersion = load_dynamic_stringW(row,4); + if (maxVersion) + { + ACTION_VerStrToInteger(maxVersion, &sig->MaxVersionMS, + &sig->MaxVersionLS); + HeapFree(GetProcessHeap(), 0, maxVersion); + } + sig->MinSize = MSI_RecordGetInteger(row,5); + if (sig->MinSize == MSI_NULL_INTEGER) + sig->MinSize = 0; + sig->MaxSize = MSI_RecordGetInteger(row,6); + if (sig->MaxSize == MSI_NULL_INTEGER) + sig->MaxSize = 0; + sig->Languages = load_dynamic_stringW(row,9); + time = MSI_RecordGetInteger(row,7); + if (time != MSI_NULL_INTEGER) + DosDateTimeToFileTime(HIWORD(time), LOWORD(time), &sig->MinTime); + time = MSI_RecordGetInteger(row,8); + if (time != MSI_NULL_INTEGER) + DosDateTimeToFileTime(HIWORD(time), LOWORD(time), &sig->MaxTime); + TRACE("Found file name %s for Signature_ %s;\n", + debugstr_w(sig->File), debugstr_w(name)); + TRACE("MinVersion is %d.%d.%d.%d\n", HIWORD(sig->MinVersionMS), + LOWORD(sig->MinVersionMS), HIWORD(sig->MinVersionLS), + LOWORD(sig->MinVersionLS)); + TRACE("MaxVersion is %d.%d.%d.%d\n", HIWORD(sig->MaxVersionMS), + LOWORD(sig->MaxVersionMS), HIWORD(sig->MaxVersionLS), + LOWORD(sig->MaxVersionLS)); + TRACE("MinSize is %ld, MaxSize is %ld;\n", sig->MinSize, sig->MaxSize); + TRACE("Languages is %s\n", debugstr_w(sig->Languages)); + +end: + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + { + TRACE("MSI_OpenQuery returned %d\n", rc); + rc = ERROR_SUCCESS; + } + + TRACE("returning %d\n", rc); + return rc; +} + +static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, BOOL *appFound, + MSISIGNATURE *sig) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'C','o','m','p','L','o','c','a','t','o','r',' ', + 'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ', + '\'','%','s','\'',0}; + + TRACE("(package %p, appFound %p, sig %p)\n", package, appFound, sig); + *appFound = FALSE; + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + WCHAR guid[50]; + DWORD sz; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewExecute returned %d\n", rc); + goto end; + } + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewFetch returned %d\n", rc); + rc = ERROR_SUCCESS; + goto end; + } + + /* get GUID */ + guid[0] = 0; + sz=sizeof(guid)/sizeof(guid[0]); + rc = MSI_RecordGetStringW(row,2,guid,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + goto end; + } + FIXME("AppSearch unimplemented for CompLocator table (GUID %s)\n", + debugstr_w(guid)); + +end: + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + { + TRACE("MSI_OpenQuery returned %d\n", rc); + rc = ERROR_SUCCESS; + } + + TRACE("returning %d\n", rc); + return rc; +} + +static UINT ACTION_AppSearchReg(MSIPACKAGE *package, BOOL *appFound, + MSISIGNATURE *sig) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'R','e','g','L','o','c','a','t','o','r',' ', + 'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ', + '\'','%','s','\'',0}; + + TRACE("(package %p, appFound %p, sig %p)\n", package, appFound, sig); + *appFound = FALSE; + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + LPWSTR keyPath; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewExecute returned %d\n", rc); + goto end; + } + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewFetch returned %d\n", rc); + rc = ERROR_SUCCESS; + goto end; + } + + /* get key path */ + keyPath = load_dynamic_stringW(row,3); + FIXME("AppSearch unimplemented for RegLocator (key path %s)\n", + debugstr_w(keyPath)); + HeapFree(GetProcessHeap(), 0, keyPath); + +end: + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + { + TRACE("MSI_OpenQuery returned %d\n", rc); + rc = ERROR_SUCCESS; + } + + TRACE("returning %d\n", rc); + return rc; +} + +static UINT ACTION_AppSearchIni(MSIPACKAGE *package, BOOL *appFound, + MSISIGNATURE *sig) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'I','n','i','L','o','c','a','t','o','r',' ', + 'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ', + '\'','%','s','\'',0}; + + TRACE("(package %p, appFound %p, sig %p)\n", package, appFound, sig); + *appFound = FALSE; + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + LPWSTR fileName; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewExecute returned %d\n", rc); + goto end; + } + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewFetch returned %d\n", rc); + rc = ERROR_SUCCESS; + goto end; + } + + /* get file name */ + fileName = load_dynamic_stringW(row,2); + FIXME("AppSearch unimplemented for IniLocator (ini file name %s)\n", + debugstr_w(fileName)); + HeapFree(GetProcessHeap(), 0, fileName); + +end: + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + { + TRACE("MSI_OpenQuery returned %d\n", rc); + rc = ERROR_SUCCESS; + } + + + TRACE("returning %d\n", rc); + return rc; +} + +/* Expands the value in src into a path without property names and only + * containing long path names into dst. Replaces at most len characters of dst, + * and always NULL-terminates dst if dst is not NULL and len >= 1. + * May modify src. + * Assumes src and dst are non-overlapping. + * FIXME: return code probably needed: + * - what does AppSearch return if the table values are invalid? + * - what if dst is too small? + */ +static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst, + size_t len) +{ + WCHAR *ptr; + size_t copied = 0; + + if (!src || !dst || !len) + return; + + /* Ignore the short portion of the path, don't think we can use it anyway */ + if ((ptr = strchrW(src, '|'))) + ptr++; + else + ptr = src; + while (*ptr && copied < len - 1) + { + WCHAR *prop = strchrW(ptr, '['); + + if (prop) + { + WCHAR *propEnd = strchrW(prop + 1, ']'); + + if (!propEnd) + { + WARN("Unterminated property name in AnyPath: %s\n", + debugstr_w(prop)); + break; + } + else + { + DWORD propLen; + + *propEnd = 0; + propLen = len - copied - 1; + MSI_GetPropertyW(package, prop + 1, dst + copied, &propLen); + ptr = propEnd + 1; + copied += propLen; + } + } + else + { + size_t toCopy = min(strlenW(ptr) + 1, len - copied - 1); + + memcpy(dst + copied, ptr, toCopy * sizeof(WCHAR)); + ptr += toCopy; + copied += toCopy; + } + } + *(dst + copied) = '\0'; +} + +/* Sets *matches to whether the file (whose path is filePath) matches the + * versions set in sig. + * Return ERROR_SUCCESS in case of success (whether or not the file matches), + * something else if a install-halting error occurs. + */ +static UINT ACTION_FileVersionMatches(MSISIGNATURE *sig, LPCWSTR filePath, + BOOL *matches) +{ + UINT rc = ERROR_SUCCESS; + + *matches = FALSE; + if (sig->Languages) + { + FIXME(": need to check version for languages %s\n", + debugstr_w(sig->Languages)); + } + else + { + DWORD zero, size = GetFileVersionInfoSizeW(filePath, &zero); + + if (size) + { + LPVOID buf = HeapAlloc(GetProcessHeap(), 0, size); + + if (buf) + { + static const WCHAR rootW[] = { '\\',0 }; + UINT versionLen; + LPVOID subBlock = NULL; + + if (GetFileVersionInfoW(filePath, 0, size, buf)) + VerQueryValueW(buf, rootW, &subBlock, &versionLen); + if (subBlock) + { + VS_FIXEDFILEINFO *info = + (VS_FIXEDFILEINFO *)subBlock; + + TRACE("Comparing file version %d.%d.%d.%d:\n", + HIWORD(info->dwFileVersionMS), + LOWORD(info->dwFileVersionMS), + HIWORD(info->dwFileVersionLS), + LOWORD(info->dwFileVersionLS)); + if (info->dwFileVersionMS < sig->MinVersionMS + || (info->dwFileVersionMS == sig->MinVersionMS && + info->dwFileVersionLS < sig->MinVersionLS)) + { + TRACE("Less than minimum version %d.%d.%d.%d\n", + HIWORD(sig->MinVersionMS), + LOWORD(sig->MinVersionMS), + HIWORD(sig->MinVersionLS), + LOWORD(sig->MinVersionLS)); + } + else if (info->dwFileVersionMS < sig->MinVersionMS + || (info->dwFileVersionMS == sig->MinVersionMS && + info->dwFileVersionLS < sig->MinVersionLS)) + { + TRACE("Greater than minimum version %d.%d.%d.%d\n", + HIWORD(sig->MaxVersionMS), + LOWORD(sig->MaxVersionMS), + HIWORD(sig->MaxVersionLS), + LOWORD(sig->MaxVersionLS)); + } + else + *matches = TRUE; + } + HeapFree(GetProcessHeap(), 0, buf); + } + else + rc = ERROR_OUTOFMEMORY; + } + } + return rc; +} + +/* Sets *matches to whether the file in findData matches that in sig. + * fullFilePath is assumed to be the full path of the file specified in + * findData, which may be necessary to compare the version. + * Return ERROR_SUCCESS in case of success (whether or not the file matches), + * something else if a install-halting error occurs. + */ +static UINT ACTION_FileMatchesSig(MSISIGNATURE *sig, + LPWIN32_FIND_DATAW findData, LPCWSTR fullFilePath, BOOL *matches) +{ + UINT rc = ERROR_SUCCESS; + + *matches = TRUE; + /* assumes the caller has already ensured the filenames match, so check + * the other fields.. + */ + if (sig->MinTime.dwLowDateTime || sig->MinTime.dwHighDateTime) + { + if (findData->ftCreationTime.dwHighDateTime < + sig->MinTime.dwHighDateTime || + (findData->ftCreationTime.dwHighDateTime == sig->MinTime.dwHighDateTime + && findData->ftCreationTime.dwLowDateTime < + sig->MinTime.dwLowDateTime)) + *matches = FALSE; + } + if (*matches && (sig->MaxTime.dwLowDateTime || sig->MaxTime.dwHighDateTime)) + { + if (findData->ftCreationTime.dwHighDateTime > + sig->MaxTime.dwHighDateTime || + (findData->ftCreationTime.dwHighDateTime == sig->MaxTime.dwHighDateTime + && findData->ftCreationTime.dwLowDateTime > + sig->MaxTime.dwLowDateTime)) + *matches = FALSE; + } + if (*matches && sig->MinSize && findData->nFileSizeLow < sig->MinSize) + *matches = FALSE; + if (*matches && sig->MaxSize && findData->nFileSizeLow > sig->MaxSize) + *matches = FALSE; + if (*matches && (sig->MinVersionMS || sig->MinVersionLS || + sig->MaxVersionMS || sig->MaxVersionLS)) + rc = ACTION_FileVersionMatches(sig, fullFilePath, matches); + return rc; +} + +/* Recursively searches the directory dir for files that match the signature + * sig, up to (depth + 1) levels deep. That is, if depth is 0, it searches dir + * (and only dir). If depth is 1, searches dir and its immediate + * subdirectories. + * Assumes sig->File is not NULL. + * Returns ERROR_SUCCESS on success (which may include non-critical errors), + * something else on failures which should halt the install. + */ +static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, BOOL *appFound, + MSISIGNATURE *sig, LPCWSTR dir, int depth) +{ + static const WCHAR starDotStarW[] = { '*','.','*',0 }; + UINT rc = ERROR_SUCCESS; + size_t dirLen = lstrlenW(dir), fileLen = lstrlenW(sig->File); + WCHAR *buf; + + TRACE("Searching directory %s for file %s, depth %d\n", debugstr_w(dir), + debugstr_w(sig->File), depth); + + if (depth < 0) + return ERROR_INVALID_PARAMETER; + + *appFound = FALSE; + /* We need the buffer in both paths below, so go ahead and allocate it + * here. Add two because we might need to add a backslash if the dir name + * isn't backslash-terminated. + */ + buf = HeapAlloc(GetProcessHeap(), 0, + (dirLen + max(fileLen, lstrlenW(starDotStarW)) + 2) * sizeof(WCHAR)); + if (buf) + { + /* a depth of 0 implies we should search dir, so go ahead and search */ + HANDLE hFind; + WIN32_FIND_DATAW findData; + + memcpy(buf, dir, dirLen * sizeof(WCHAR)); + if (buf[dirLen - 1] != '\\') + buf[dirLen++ - 1] = '\\'; + memcpy(buf + dirLen, sig->File, (fileLen + 1) * sizeof(WCHAR)); + hFind = FindFirstFileW(buf, &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + BOOL matches; + + /* assuming Signature can't contain wildcards for the file name, + * so don't bother with FindNextFileW here. + */ + if (!(rc = ACTION_FileMatchesSig(sig, &findData, buf, &matches)) + && matches) + { + TRACE("found file, setting %s to %s\n", + debugstr_w(sig->Property), debugstr_w(buf)); + rc = MSI_SetPropertyW(package, sig->Property, buf); + *appFound = TRUE; + } + FindClose(hFind); + } + if (rc == ERROR_SUCCESS && !*appFound && depth > 0) + { + HANDLE hFind; + WIN32_FIND_DATAW findData; + + memcpy(buf, dir, dirLen * sizeof(WCHAR)); + if (buf[dirLen - 1] != '\\') + buf[dirLen++ - 1] = '\\'; + lstrcpyW(buf + dirLen, starDotStarW); + hFind = FindFirstFileW(buf, &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + rc = ACTION_RecurseSearchDirectory(package, appFound, + sig, findData.cFileName, depth - 1); + while (rc == ERROR_SUCCESS && !*appFound && + FindNextFileW(hFind, &findData) != 0) + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + rc = ACTION_RecurseSearchDirectory(package, appFound, + sig, findData.cFileName, depth - 1); + } + FindClose(hFind); + } + } + HeapFree(GetProcessHeap(), 0, buf); + } + else + rc = ERROR_OUTOFMEMORY; + + return rc; +} + +static UINT ACTION_CheckDirectory(MSIPACKAGE *package, MSISIGNATURE *sig, + LPCWSTR dir) +{ + UINT rc = ERROR_SUCCESS; + + if (GetFileAttributesW(dir) & FILE_ATTRIBUTE_DIRECTORY) + { + TRACE("directory exists, setting %s to %s\n", + debugstr_w(sig->Property), debugstr_w(dir)); + rc = MSI_SetPropertyW(package, sig->Property, dir); + } + return rc; +} + +static BOOL ACTION_IsFullPath(LPCWSTR path) +{ + WCHAR first = toupperW(path[0]); + BOOL ret; + + if (first >= 'A' && first <= 'A' && path[1] == ':') + ret = TRUE; + else if (path[0] == '\\' && path[1] == '\\') + ret = TRUE; + else + ret = FALSE; + return ret; +} + +static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig, + LPCWSTR expanded, int depth) +{ + UINT rc; + BOOL found; + + if (ACTION_IsFullPath(expanded)) + { + if (sig->File) + rc = ACTION_RecurseSearchDirectory(package, &found, sig, + expanded, depth); + else + { + /* Recursively searching a directory makes no sense when the + * directory to search is the thing you're trying to find. + */ + rc = ACTION_CheckDirectory(package, sig, expanded); + } + } + else + { + WCHAR pathWithDrive[MAX_PATH] = { 'C',':','\\',0 }; + DWORD drives = GetLogicalDrives(); + int i; + + rc = ERROR_SUCCESS; + found = FALSE; + for (i = 0; rc == ERROR_SUCCESS && !found && i < 26; i++) + if (drives & (1 << drives)) + { + pathWithDrive[0] = 'A' + i; + if (GetDriveTypeW(pathWithDrive) == DRIVE_FIXED) + { + strncpyW(pathWithDrive + 3, expanded, + sizeof(pathWithDrive) / sizeof(pathWithDrive[0]) - 3); + if (sig->File) + rc = ACTION_RecurseSearchDirectory(package, &found, sig, + pathWithDrive, depth); + else + rc = ACTION_CheckDirectory(package, sig, pathWithDrive); + } + } + } + return rc; +} + +static UINT ACTION_AppSearchDr(MSIPACKAGE *package, MSISIGNATURE *sig) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'D','r','L','o','c','a','t','o','r',' ', + 'w','h','e','r','e',' ','S','i','g','n','a','t','u','r','e','_',' ','=',' ', + '\'','%','s','\'',0}; + + TRACE("(package %p, sig %p)\n", package, sig); + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, sig->Name); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + WCHAR buffer[MAX_PATH], expanded[MAX_PATH]; + DWORD sz; + int depth; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewExecute returned %d\n", rc); + goto end; + } + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + TRACE("MSI_ViewFetch returned %d\n", rc); + rc = ERROR_SUCCESS; + goto end; + } + + /* check whether parent is set */ + buffer[0] = 0; + sz=sizeof(buffer)/sizeof(buffer[0]); + rc = MSI_RecordGetStringW(row,2,buffer,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + goto end; + } + else if (buffer[0]) + { + FIXME(": searching parent (%s) unimplemented\n", + debugstr_w(buffer)); + goto end; + } + /* no parent, now look for path */ + buffer[0] = 0; + sz=sizeof(buffer)/sizeof(buffer[0]); + rc = MSI_RecordGetStringW(row,3,buffer,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + goto end; + } + if (MSI_RecordIsNull(row,4)) + depth = 0; + else + depth = MSI_RecordGetInteger(row,4); + ACTION_ExpandAnyPath(package, buffer, expanded, + sizeof(expanded) / sizeof(expanded[0])); + rc = ACTION_SearchDirectory(package, sig, expanded, depth); + +end: + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + { + TRACE("MSI_OpenQuery returned %d\n", rc); + rc = ERROR_SUCCESS; + } + + + TRACE("returning %d\n", rc); + return rc; +} + +/* http://msdn.microsoft.com/library/en-us/msi/setup/appsearch_table.asp + * is the best reference for the AppSearch table and how it's used. + */ +UINT ACTION_AppSearch(MSIPACKAGE *package) +{ + MSIQUERY *view; + UINT rc; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'A','p','p','S','e','a','r','c','h',0}; + + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery); + if (rc == ERROR_SUCCESS) + { + MSIRECORD *row = 0; + WCHAR propBuf[0x100], sigBuf[0x100]; + DWORD sz; + MSISIGNATURE sig; + BOOL appFound = FALSE; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + goto end; + + while (!rc) + { + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + /* get property and signature */ + propBuf[0] = 0; + sz=sizeof(propBuf)/sizeof(propBuf[0]); + rc = MSI_RecordGetStringW(row,1,propBuf,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + msiobj_release(&row->hdr); + break; + } + sigBuf[0] = 0; + sz=sizeof(sigBuf)/sizeof(sigBuf[0]); + rc = MSI_RecordGetStringW(row,2,sigBuf,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + msiobj_release(&row->hdr); + break; + } + TRACE("Searching for Property %s, Signature_ %s\n", + debugstr_w(propBuf), debugstr_w(sigBuf)); + /* This clears all the fields, so set Name and Property afterward */ + rc = ACTION_AppSearchGetSignature(package, &sig, sigBuf); + sig.Name = sigBuf; + sig.Property = propBuf; + if (rc == ERROR_SUCCESS) + { + rc = ACTION_AppSearchComponents(package, &appFound, &sig); + if (rc == ERROR_SUCCESS && !appFound) + { + rc = ACTION_AppSearchReg(package, &appFound, &sig); + if (rc == ERROR_SUCCESS && !appFound) + { + rc = ACTION_AppSearchIni(package, &appFound, &sig); + if (rc == ERROR_SUCCESS && !appFound) + rc = ACTION_AppSearchDr(package, &sig); + } + } + } + HeapFree(GetProcessHeap(), 0, sig.File); + HeapFree(GetProcessHeap(), 0, sig.Languages); + msiobj_release(&row->hdr); + } + +end: + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + rc = ERROR_SUCCESS; + + return rc; +} diff -urN wine-20050111/dlls/msi/cond.y wine-20050211/dlls/msi/cond.y --- wine-20050111/dlls/msi/cond.y 2004-07-29 04:36:06.000000000 +0200 +++ wine-20050211/dlls/msi/cond.y 2005-02-09 14:26:16.000000000 +0100 @@ -181,7 +181,7 @@ } | value_s { - $$ = atoiW($1); + $$ = $1[0] ? MSICONDITION_TRUE : MSICONDITION_FALSE; } | value_i comp_op_i value_i { @@ -448,14 +448,22 @@ { DWORD sz; COND_input* cond = (COND_input*) info; - $$ = HeapAlloc( GetProcessHeap(), 0, 0x100*sizeof (WCHAR) ); - /* Lookup the identifier */ - - sz=0x100; - if (MSI_GetPropertyW(cond->package,$1,$$,&sz) != ERROR_SUCCESS) + sz = 0; + MSI_GetPropertyW(cond->package, $1, NULL, &sz); + if (sz == 0) + { + $$ = HeapAlloc( GetProcessHeap(), 0 ,sizeof(WCHAR)); + $$[0] = 0; + } + else { - $$[0]=0; + sz ++; + $$ = HeapAlloc( GetProcessHeap(), 0, sz*sizeof (WCHAR) ); + + /* Lookup the identifier */ + + MSI_GetPropertyW(cond->package,$1,$$,&sz); } HeapFree( GetProcessHeap(), 0, $1 ); } @@ -731,7 +739,7 @@ TRACE("Evaluating %s\n",debugstr_w(szCondition)); - if( !COND_parse( &cond ) ) + if( szCondition && !COND_parse( &cond ) ) r = cond.result; else r = MSICONDITION_ERROR; @@ -767,8 +775,7 @@ r = MsiEvaluateConditionW( hInstall, szwCond ); - if( szwCond ) - HeapFree( GetProcessHeap(), 0, szwCond ); + HeapFree( GetProcessHeap(), 0, szwCond ); return r; } diff -urN wine-20050111/dlls/msi/create.c wine-20050211/dlls/msi/create.c --- wine-20050111/dlls/msi/create.c 2004-08-25 19:31:39.000000000 +0200 +++ wine-20050211/dlls/msi/create.c 2005-02-08 14:44:25.000000000 +0100 @@ -188,11 +188,12 @@ return ERROR_FUNCTION_FAILED; } -static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec) { MSICREATEVIEW *cv = (MSICREATEVIEW*)view; - TRACE("%p %d %ld\n", cv, eModifyMode, hrec ); + TRACE("%p %d %p\n", cv, eModifyMode, rec ); return ERROR_FUNCTION_FAILED; } diff -urN wine-20050111/dlls/msi/custom.c wine-20050211/dlls/msi/custom.c --- wine-20050111/dlls/msi/custom.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/custom.c 2005-02-09 15:05:24.000000000 +0100 @@ -0,0 +1,794 @@ +/* + * Custom Action processing for the Microsoft Installer (msi.dll) + * + * Copyright 2005 Aric Stewart 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 + */ + +/* + * Pages I need + * +http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/summary_list_of_all_custom_action_types.asp + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" +#include "wine/debug.h" +#include "fdi.h" +#include "msi.h" +#include "msiquery.h" +#include "msvcrt/fcntl.h" +#include "objbase.h" +#include "objidl.h" +#include "msipriv.h" +#include "winnls.h" +#include "winuser.h" +#include "shlobj.h" +#include "wine/unicode.h" +#include "ver.h" +#include "action.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +#define CUSTOM_ACTION_TYPE_MASK 0x3F +static const WCHAR c_collen[] = {'C',':','\\',0}; +static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0}; + +typedef struct tagMSIRUNNINGACTION +{ + HANDLE handle; + BOOL process; + LPWSTR name; +} MSIRUNNINGACTION; + +static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); + +UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) +{ + UINT rc = ERROR_SUCCESS; + MSIQUERY * view; + MSIRECORD * row = 0; + static const WCHAR ExecSeqQuery[] = + {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o' + ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i' + ,'o','n','`',' ','=',' ','`','%','s','`',0}; + UINT type; + LPWSTR source; + LPWSTR target; + WCHAR *deformated=NULL; + + rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, action); + if (rc != ERROR_SUCCESS) + return rc; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + type = MSI_RecordGetInteger(row,2); + + source = load_dynamic_stringW(row,3); + target = load_dynamic_stringW(row,4); + + TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type, + debugstr_w(source), debugstr_w(target)); + + /* handle some of the deferred actions */ + if (type & 0x400) + { + if (type & 0x100) + { + FIXME("Rollback only action... rollbacks not supported yet\n"); + HeapFree(GetProcessHeap(),0,source); + HeapFree(GetProcessHeap(),0,target); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return ERROR_SUCCESS; + } + if (!execute) + { + LPWSTR *newbuf = NULL; + INT count; + if (type & 0x200) + { + TRACE("Deferring Commit Action!\n"); + count = package->CommitActionCount; + package->CommitActionCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->CommitAction, + package->CommitActionCount * sizeof(LPWSTR)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); + + newbuf[count] = dupstrW(action); + package->CommitAction = newbuf; + } + else + { + TRACE("Deferring Action!\n"); + count = package->DeferredActionCount; + package->DeferredActionCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->DeferredAction, + package->DeferredActionCount * sizeof(LPWSTR)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); + + newbuf[count] = dupstrW(action); + package->DeferredAction = newbuf; + } + + HeapFree(GetProcessHeap(),0,source); + HeapFree(GetProcessHeap(),0,target); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return ERROR_SUCCESS; + } + else + { + /*Set ActionData*/ + + static const WCHAR szActionData[] = { + 'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0}; + LPWSTR actiondata = load_dynamic_property(package,action,NULL); + if (actiondata) + MSI_SetPropertyW(package,szActionData,actiondata); + } + } + + switch (type & CUSTOM_ACTION_TYPE_MASK) + { + case 1: /* DLL file stored in a Binary table stream */ + rc = HANDLE_CustomType1(package,source,target,type,action); + break; + case 2: /* EXE file stored in a Binary table strem */ + rc = HANDLE_CustomType2(package,source,target,type,action); + break; + case 18: /*EXE file installed with package */ + rc = HANDLE_CustomType18(package,source,target,type,action); + break; + case 19: /* Error that halts install */ + rc = HANDLE_CustomType19(package,source,target,type,action); + break; + case 50: /*EXE file specified by a property value */ + rc = HANDLE_CustomType50(package,source,target,type,action); + break; + case 34: /*EXE to be run in specified directory */ + rc = HANDLE_CustomType34(package,source,target,type,action); + break; + case 35: /* Directory set with formatted text. */ + deformat_string(package,target,&deformated); + MSI_SetTargetPathW(package, source, deformated); + HeapFree(GetProcessHeap(),0,deformated); + break; + case 51: /* Property set with formatted text. */ + deformat_string(package,target,&deformated); + rc = MSI_SetPropertyW(package,source,deformated); + HeapFree(GetProcessHeap(),0,deformated); + break; + default: + FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n", + type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source), + debugstr_w(target)); + } + + HeapFree(GetProcessHeap(),0,source); + HeapFree(GetProcessHeap(),0,target); + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; +} + + +static UINT store_binary_to_temp(MSIPACKAGE *package, LPCWSTR source, + LPWSTR tmp_file) +{ + DWORD sz=MAX_PATH; + static const WCHAR f1[] = {'m','s','i',0}; + WCHAR fmt[MAX_PATH]; + + if (MSI_GetPropertyW(package, cszTempFolder, fmt, &sz) + != ERROR_SUCCESS) + GetTempPathW(MAX_PATH,fmt); + + if (GetTempFileNameW(fmt,f1,0,tmp_file) == 0) + { + TRACE("Unable to create file\n"); + return ERROR_FUNCTION_FAILED; + } + else + { + /* write out the file */ + UINT rc; + MSIQUERY * view; + MSIRECORD * row = 0; + static const WCHAR fmt[] = + {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i' +,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0}; + HANDLE the_file; + CHAR buffer[1024]; + + if (track_tempfile(package, tmp_file, tmp_file)!=0) + FIXME("File Name in temp tracking collision\n"); + + the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (the_file == INVALID_HANDLE_VALUE) + return ERROR_FUNCTION_FAILED; + + rc = MSI_OpenQuery(package->db, &view, fmt, source); + if (rc != ERROR_SUCCESS) + return rc; + + rc = MSI_ViewExecute(view, 0); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; + } + + do + { + DWORD write; + sz = 1024; + rc = MSI_RecordReadStream(row,2,buffer,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Failed to get stream\n"); + CloseHandle(the_file); + DeleteFileW(tmp_file); + break; + } + WriteFile(the_file,buffer,sz,&write,NULL); + } while (sz == 1024); + + CloseHandle(the_file); + + msiobj_release(&row->hdr); + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + + return ERROR_SUCCESS; +} + +static void file_running_action(MSIPACKAGE* package, HANDLE Handle, + BOOL process, LPCWSTR name) +{ + MSIRUNNINGACTION *newbuf = NULL; + INT count; + count = package->RunningActionCount; + package->RunningActionCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->RunningAction, + package->RunningActionCount * sizeof(MSIRUNNINGACTION)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(MSIRUNNINGACTION)); + + newbuf[count].handle = Handle; + newbuf[count].process = process; + newbuf[count].name = dupstrW(name); + + package->RunningAction = newbuf; +} + +static UINT process_action_return_value(UINT type, HANDLE ThreadHandle) +{ + DWORD rc; + + if (type == 2) + { + GetExitCodeProcess(ThreadHandle,&rc); + + if (rc == 0) + return ERROR_SUCCESS; + else + return ERROR_FUNCTION_FAILED; + } + + GetExitCodeThread(ThreadHandle,&rc); + + switch (rc) + { + case ERROR_FUNCTION_NOT_CALLED: + case ERROR_SUCCESS: + case ERROR_INSTALL_USEREXIT: + case ERROR_INSTALL_FAILURE: + return rc; + case ERROR_NO_MORE_ITEMS: + return ERROR_SUCCESS; + default: + return ERROR_FUNCTION_FAILED; + } +} + +static UINT process_handle(MSIPACKAGE* package, UINT type, + HANDLE ThreadHandle, HANDLE ProcessHandle, + LPCWSTR Name) +{ + UINT rc = ERROR_SUCCESS; + + if (!(type & 0x80)) + { + /* synchronous */ + TRACE("Synchronous Execution of action %s\n",debugstr_w(Name)); + if (ProcessHandle) + msi_dialog_check_messages(package->dialog, ProcessHandle); + else + msi_dialog_check_messages(package->dialog, ThreadHandle); + + if (!(type & 0x40)) + { + if (ProcessHandle) + rc = process_action_return_value(2,ProcessHandle); + else + rc = process_action_return_value(1,ThreadHandle); + } + + CloseHandle(ThreadHandle); + if (ProcessHandle); + CloseHandle(ProcessHandle); + } + else + { + TRACE("Asynchronous Execution of action %s\n",debugstr_w(Name)); + /* asynchronous */ + if (type & 0x40) + { + if (ProcessHandle) + { + file_running_action(package, ProcessHandle, TRUE, Name); + CloseHandle(ThreadHandle); + } + else + file_running_action(package, ThreadHandle, FALSE, Name); + } + else + { + CloseHandle(ThreadHandle); + if (ProcessHandle); + CloseHandle(ProcessHandle); + } + } + + return rc; +} + + +typedef UINT __stdcall CustomEntry(MSIHANDLE); + +typedef struct +{ + MSIPACKAGE *package; + WCHAR *target; + WCHAR *source; +} thread_struct; + +static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff) +{ + HANDLE hModule; + LPSTR proc; + CustomEntry *fn; + DWORD rc = ERROR_SUCCESS; + + TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source), + debugstr_w(stuff->target)); + + hModule = LoadLibraryW(stuff->source); + if (hModule) + { + proc = strdupWtoA( stuff->target ); + fn = (CustomEntry*)GetProcAddress(hModule,proc); + if (fn) + { + MSIHANDLE hPackage; + MSIPACKAGE *package = stuff->package; + + TRACE("Calling function %s\n", proc); + hPackage = msiobj_findhandle( &package->hdr ); + if (hPackage ) + { + rc = fn(hPackage); + msiobj_release( &package->hdr ); + } + else + ERR("Handle for object %p not found\n", package ); + } + else + ERR("Cannot load functon\n"); + + HeapFree(GetProcessHeap(),0,proc); + FreeLibrary(hModule); + } + else + ERR("Unable to load library\n"); + msiobj_release( &stuff->package->hdr ); + HeapFree(GetProcessHeap(),0,stuff->source); + HeapFree(GetProcessHeap(),0,stuff->target); + HeapFree(GetProcessHeap(), 0, stuff); + return rc; +} + +static DWORD WINAPI DllThread(LPVOID info) +{ + thread_struct *stuff; + DWORD rc = 0; + + TRACE("MSI Thread (0x%lx) started for custom action\n", + GetCurrentThreadId()); + + stuff = (thread_struct*)info; + rc = ACTION_CallDllFunction(stuff); + + TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId()); + /* clse all handles for this thread */ + MsiCloseAllHandles(); + return rc; +} + +static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + WCHAR tmp_file[MAX_PATH]; + thread_struct *info; + DWORD ThreadId; + HANDLE ThreadHandle; + UINT rc = ERROR_SUCCESS; + + store_binary_to_temp(package, source, tmp_file); + + TRACE("Calling function %s from %s\n",debugstr_w(target), + debugstr_w(tmp_file)); + + if (!strchrW(tmp_file,'.')) + { + static const WCHAR dot[]={'.',0}; + strcatW(tmp_file,dot); + } + + info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); + msiobj_addref( &package->hdr ); + info->package = package; + info->target = dupstrW(target); + info->source = dupstrW(tmp_file); + + ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId); + + rc = process_handle(package, type, ThreadHandle, NULL, action); + + return rc; +} + +static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + WCHAR tmp_file[MAX_PATH]; + STARTUPINFOW si; + PROCESS_INFORMATION info; + BOOL rc; + INT len; + WCHAR *deformated; + WCHAR *cmd; + static const WCHAR spc[] = {' ',0}; + UINT prc = ERROR_SUCCESS; + + memset(&si,0,sizeof(STARTUPINFOW)); + + store_binary_to_temp(package, source, tmp_file); + + deformat_string(package,target,&deformated); + + len = strlenW(tmp_file)+2; + + if (deformated) + len += strlenW(deformated); + + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + + strcpyW(cmd,tmp_file); + if (deformated) + { + strcatW(cmd,spc); + strcatW(cmd,deformated); + + HeapFree(GetProcessHeap(),0,deformated); + } + + TRACE("executing exe %s \n",debugstr_w(cmd)); + + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + + HeapFree(GetProcessHeap(),0,cmd); + + if ( !rc ) + { + ERR("Unable to execute command\n"); + return ERROR_SUCCESS; + } + + prc = process_handle(package, type, info.hThread, info.hProcess, action); + + return prc; +} + +static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + STARTUPINFOW si; + PROCESS_INFORMATION info; + BOOL rc; + WCHAR *deformated; + WCHAR *cmd; + INT len; + static const WCHAR spc[] = {' ',0}; + int index; + UINT prc; + + memset(&si,0,sizeof(STARTUPINFOW)); + + index = get_loaded_file(package,source); + + len = strlenW(package->files[index].TargetPath); + + deformat_string(package,target,&deformated); + if (deformated) + len += strlenW(deformated); + len += 2; + + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR)); + + strcpyW(cmd, package->files[index].TargetPath); + if (deformated) + { + strcatW(cmd, spc); + strcatW(cmd, deformated); + + HeapFree(GetProcessHeap(),0,deformated); + } + + TRACE("executing exe %s \n",debugstr_w(cmd)); + + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + + HeapFree(GetProcessHeap(),0,cmd); + + if ( !rc ) + { + ERR("Unable to execute command\n"); + return ERROR_SUCCESS; + } + + prc = process_handle(package, type, info.hThread, info.hProcess, action); + + return prc; +} + +static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', + 'F','R','O','M',' ','`','E','r','r','o','r','`',' ', + 'W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ','%','s',0 + }; + MSIQUERY *view = NULL; + MSIRECORD *row = 0; + UINT r; + LPWSTR deformated = NULL; + + deformat_string( package, target, &deformated ); + + /* first try treat the error as a number */ + r = MSI_OpenQuery( package->db, &view, query, deformated ); + if( r == ERROR_SUCCESS ) + { + r = MSI_ViewExecute( view, 0 ); + if( r == ERROR_SUCCESS ) + { + r = MSI_ViewFetch( view, &row ); + if( r == ERROR_SUCCESS ) + { + LPCWSTR error = MSI_RecordGetString( row, 1 ); + MessageBoxW( NULL, error, NULL, MB_OK ); + msiobj_release( &row->hdr ); + } + } + MSI_ViewClose( view ); + msiobj_release( &view->hdr ); + } + + if (r != ERROR_SUCCESS ) + { + MessageBoxW( NULL, deformated, NULL, MB_OK ); + HeapFree( GetProcessHeap(), 0, deformated ); + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + STARTUPINFOW si; + PROCESS_INFORMATION info; + WCHAR *prop; + BOOL rc; + WCHAR *deformated; + WCHAR *cmd; + INT len; + UINT prc; + static const WCHAR spc[] = {' ',0}; + + memset(&si,0,sizeof(STARTUPINFOW)); + memset(&info,0,sizeof(PROCESS_INFORMATION)); + + prop = load_dynamic_property(package,source,&prc); + if (!prop) + return prc; + + deformat_string(package,target,&deformated); + len = strlenW(prop) + 2; + if (deformated) + len += strlenW(deformated); + + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + + strcpyW(cmd,prop); + if (deformated) + { + strcatW(cmd,spc); + strcatW(cmd,deformated); + + HeapFree(GetProcessHeap(),0,deformated); + } + + TRACE("executing exe %s \n",debugstr_w(cmd)); + + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + + HeapFree(GetProcessHeap(),0,cmd); + + if ( !rc ) + { + ERR("Unable to execute command\n"); + return ERROR_SUCCESS; + } + + prc = process_handle(package, type, info.hThread, info.hProcess, action); + + return prc; +} + +static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + LPWSTR filename, deformated; + STARTUPINFOW si; + PROCESS_INFORMATION info; + BOOL rc; + UINT prc; + + memset(&si,0,sizeof(STARTUPINFOW)); + + filename = resolve_folder(package, source, FALSE, FALSE, NULL); + + if (!filename) + return ERROR_FUNCTION_FAILED; + + SetCurrentDirectoryW(filename); + HeapFree(GetProcessHeap(),0,filename); + + deformat_string(package,target,&deformated); + + if (!deformated) + return ERROR_FUNCTION_FAILED; + + TRACE("executing exe %s \n",debugstr_w(deformated)); + + rc = CreateProcessW(NULL, deformated, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + HeapFree(GetProcessHeap(),0,deformated); + + if ( !rc ) + { + ERR("Unable to execute command\n"); + return ERROR_SUCCESS; + } + + prc = process_handle(package, type, info.hThread, info.hProcess, action); + + return prc; +} + + +void ACTION_FinishCustomActions(MSIPACKAGE* package) +{ + INT i; + DWORD rc; + + for (i = 0; i < package->RunningActionCount; i++) + { + TRACE("Checking on action %s\n", + debugstr_w(package->RunningAction[i].name)); + + if (package->RunningAction[i].process) + GetExitCodeProcess(package->RunningAction[i].handle, &rc); + else + GetExitCodeThread(package->RunningAction[i].handle, &rc); + + if (rc == STILL_ACTIVE) + { + TRACE("Waiting on action %s\n", + debugstr_w(package->RunningAction[i].name)); + msi_dialog_check_messages(package->dialog, + package->RunningAction[i].handle); + } + + HeapFree(GetProcessHeap(),0,package->RunningAction[i].name); + CloseHandle(package->RunningAction[i].handle); + } + + HeapFree(GetProcessHeap(),0,package->RunningAction); +} diff -urN wine-20050111/dlls/msi/dialog.c wine-20050211/dlls/msi/dialog.c --- wine-20050111/dlls/msi/dialog.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/dialog.c 2005-02-09 14:24:31.000000000 +0100 @@ -0,0 +1,973 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 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 "winuser.h" +#include "winnls.h" +#include "wingdi.h" +#include "msi.h" +#include "msipriv.h" +#include "msidefs.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +#include "action.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + + +const WCHAR szMsiDialogClass[] = { + '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 }; + +struct msi_control_tag; +typedef struct msi_control_tag msi_control; +typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM ); + +struct msi_control_tag +{ + struct msi_control_tag *next; + HWND hwnd; + msi_handler handler; + LPWSTR property; + WCHAR name[1]; +}; + +typedef struct msi_font_tag +{ + struct msi_font_tag *next; + HFONT hfont; + WCHAR name[1]; +} msi_font; + +struct msi_dialog_tag +{ + MSIPACKAGE *package; + msi_dialog_event_handler event_handler; + BOOL finished; + INT scale; + DWORD attributes; + HWND hwnd; + LPWSTR default_font; + msi_font *font_list; + msi_control *control_list; + WCHAR name[1]; +}; + +typedef UINT (*msi_dialog_control_func)( msi_dialog *dialog, MSIRECORD *rec ); +struct control_handler +{ + LPCWSTR control_type; + msi_dialog_control_func func; +}; + +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 ); + + +INT msi_dialog_scale_unit( msi_dialog *dialog, INT val ) +{ + return (dialog->scale * val + 5) / 10; +} + +/* + * msi_dialog_get_style + * + * Extract the {\style} string from the front of the text to display and + * update the pointer. + */ +static LPWSTR msi_dialog_get_style( LPCWSTR *text ) +{ + LPWSTR ret = NULL; + LPCWSTR p = *text, q; + DWORD len; + + if( *p++ != '{' ) + return ret; + q = strchrW( p, '}' ); + if( !q ) + return ret; + *text = ++q; + if( *p++ != '\\' ) + return ret; + len = q - p; + + ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + if( !ret ) + return ret; + strncpyW( ret, p, len ); + ret[len-1] = 0; + return ret; +} + +static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param ) +{ + msi_dialog *dialog = param; + msi_font *font; + LPCWSTR face, name; + LOGFONTW lf; + INT style; + HDC hdc; + + /* create a font and add it to the list */ + name = MSI_RecordGetString( rec, 1 ); + font = HeapAlloc( GetProcessHeap(), 0, + sizeof *font + strlenW( name )*sizeof (WCHAR) ); + strcpyW( font->name, name ); + font->next = dialog->font_list; + dialog->font_list = font; + + memset( &lf, 0, sizeof lf ); + face = MSI_RecordGetString( rec, 2 ); + lf.lfHeight = MSI_RecordGetInteger( rec, 3 ); + style = MSI_RecordGetInteger( rec, 5 ); + if( style & msidbTextStyleStyleBitsBold ) + lf.lfWeight = FW_BOLD; + if( style & msidbTextStyleStyleBitsItalic ) + lf.lfItalic = TRUE; + if( style & msidbTextStyleStyleBitsUnderline ) + lf.lfUnderline = TRUE; + if( style & msidbTextStyleStyleBitsStrike ) + lf.lfStrikeOut = TRUE; + lstrcpynW( lf.lfFaceName, face, LF_FACESIZE ); + + /* adjust the height */ + hdc = GetDC( dialog->hwnd ); + if (hdc) + { + lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); + ReleaseDC( dialog->hwnd, hdc ); + } + + font->hfont = CreateFontIndirectW( &lf ); + + TRACE("Adding font style %s\n", debugstr_w(font->name) ); + + return ERROR_SUCCESS; +} + +static msi_font *msi_dialog_find_font( msi_dialog *dialog, LPCWSTR name ) +{ + msi_font *font; + + for( font = dialog->font_list; font; font = font->next ) + if( !strcmpW( font->name, name ) ) /* FIXME: case sensitive? */ + break; + + return font; +} + +static UINT msi_dialog_set_font( msi_dialog *dialog, HWND hwnd, LPCWSTR name ) +{ + msi_font *font; + + font = msi_dialog_find_font( dialog, name ); + if( font ) + SendMessageW( hwnd, WM_SETFONT, (WPARAM) font->hfont, TRUE ); + else + ERR("No font entry for %s\n", debugstr_w(name)); + return ERROR_SUCCESS; +} + +static UINT msi_dialog_build_font_list( msi_dialog *dialog ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ', + 'F','R','O','M',' ','`','T','e','x','t','S','t','y','l','e','`',' ',0 + }; + UINT r; + MSIQUERY *view = NULL; + + TRACE("dialog %p\n", dialog ); + + r = MSI_OpenQuery( dialog->package->db, &view, query ); + if( r != ERROR_SUCCESS ) + return r; + + r = MSI_IterateRecords( view, NULL, msi_dialog_add_font, dialog ); + msiobj_release( &view->hdr ); + + return r; +} + +static msi_control *msi_dialog_add_control( msi_dialog *dialog, + MSIRECORD *rec, LPCWSTR szCls, DWORD style ) +{ + DWORD x, y, width, height, attributes; + LPCWSTR text, name; + LPWSTR font = NULL, title = NULL; + msi_control *control = NULL; + + style |= WS_CHILD | WS_GROUP; + + name = MSI_RecordGetString( rec, 2 ); + control = HeapAlloc( GetProcessHeap(), 0, + sizeof *control + strlenW(name)*sizeof(WCHAR) ); + strcpyW( control->name, name ); + control->next = dialog->control_list; + dialog->control_list = control; + control->handler = NULL; + control->property = NULL; + + x = MSI_RecordGetInteger( rec, 4 ); + y = MSI_RecordGetInteger( rec, 5 ); + width = MSI_RecordGetInteger( rec, 6 ); + height = MSI_RecordGetInteger( rec, 7 ); + attributes = MSI_RecordGetInteger( rec, 8 ); + text = MSI_RecordGetString( rec, 10 ); + + TRACE("Dialog %s control %s\n", debugstr_w(dialog->name), debugstr_w(text)); + + 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( szCls, title, style, + x, y, width, height, dialog->hwnd, NULL, NULL, NULL ); + msi_dialog_set_font( dialog, control->hwnd, + font ? font : dialog->default_font ); + HeapFree( GetProcessHeap(), 0, font ); + HeapFree( GetProcessHeap(), 0, title ); + return control; +} + +static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + TRACE("%p %p\n", dialog, rec); + + msi_dialog_add_control( dialog, rec, szStatic, 0 ); + return ERROR_SUCCESS; +} + +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); + + control = msi_dialog_add_control( dialog, rec, szButton, 0 ); + control->handler = msi_dialog_button_handler; + + return ERROR_SUCCESS; +} + +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; + + TRACE("%p %p\n", dialog, rec); + + control = msi_dialog_add_control( dialog, rec, szButton, + BS_CHECKBOX | BS_MULTILINE ); + control->handler = msi_dialog_checkbox_handler; + prop = MSI_RecordGetString( rec, 9 ); + if( prop ) + control->property = dupstrW( prop ); + msi_dialog_checkbox_sync_state( dialog, control ); + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + TRACE("%p %p\n", dialog, rec); + + msi_dialog_add_control( dialog, rec, szStatic, SS_ETCHEDHORZ | SS_SUNKEN ); + return ERROR_SUCCESS; +} + +static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + const static WCHAR szEdit[] = { 'E','D','I','T',0 }; + + TRACE("%p %p\n", dialog, rec); + + msi_dialog_add_control( dialog, rec, szEdit, + ES_MULTILINE | WS_VSCROLL | ES_READONLY | ES_AUTOVSCROLL ); + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + TRACE("%p %p\n", dialog, rec); + + msi_dialog_add_control( dialog, rec, szStatic, + SS_BITMAP | SS_LEFT | SS_CENTERIMAGE ); + return ERROR_SUCCESS; +} + +static UINT msi_dialog_combo_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + static const WCHAR szCombo[] = { 'C','O','M','B','O','B','O','X',0 }; + + msi_dialog_add_control( dialog, rec, szCombo, + SS_BITMAP | SS_LEFT | SS_CENTERIMAGE ); + return ERROR_SUCCESS; +} + +static UINT msi_dialog_edit_control( msi_dialog *dialog, MSIRECORD *rec ) +{ + const static WCHAR szEdit[] = { 'E','D','I','T',0 }; + msi_control *control; + LPCWSTR prop; + LPWSTR val; + + control = msi_dialog_add_control( dialog, rec, szEdit, 0 ); + control->handler = msi_dialog_edit_handler; + prop = MSI_RecordGetString( rec, 9 ); + if( prop ) + control->property = dupstrW( prop ); + val = load_dynamic_property( dialog->package, control->property, NULL ); + SetWindowTextW( control->hwnd, val ); + HeapFree( GetProcessHeap(), 0, val ); + return ERROR_SUCCESS; +} + +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 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 }; +static const WCHAR szScrollableText[] = { + 'S','c','r','o','l','l','a','b','l','e','T','e','x','t',0 }; +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 }; + +struct control_handler msi_dialog_handler[] = +{ + { szText, msi_dialog_text_control }, + { szButton, msi_dialog_button_control }, + { szLine, msi_dialog_line_control }, + { szBitmap, msi_dialog_bitmap_control }, + { szCheckBox, msi_dialog_checkbox_control }, + { szScrollableText, msi_dialog_scrolltext_control }, + { szComboBox, msi_dialog_combo_control }, + { szEdit, msi_dialog_edit_control }, + { szMaskedEdit, msi_dialog_edit_control }, +}; + +#define NUM_CONTROL_TYPES (sizeof msi_dialog_handler/sizeof msi_dialog_handler[0]) + +static UINT msi_dialog_create_controls( MSIRECORD *rec, LPVOID param ) +{ + msi_dialog *dialog = param; + LPCWSTR control_type; + UINT i; + + /* find and call the function that can create this type of control */ + control_type = MSI_RecordGetString( rec, 3 ); + for( i=0; ipackage; + + TRACE("%p %s\n", dialog, debugstr_w(dialog->name) ); + + /* query the Control table for all the elements of the control */ + r = MSI_OpenQuery( package->db, &view, query, dialog->name ); + if( r != ERROR_SUCCESS ) + { + ERR("query failed for dialog %s\n", debugstr_w(dialog->name)); + return ERROR_INVALID_PARAMETER; + } + + r = MSI_IterateRecords( view, 0, msi_dialog_create_controls, dialog ); + msiobj_release( &view->hdr ); + + return r; +} + +static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name ) +{ + msi_control *control; + + for( control = dialog->control_list; control; control = control->next ) + if( !strcmpW( control->name, name ) ) /* FIXME: case sensitive? */ + break; + return control; +} + +static msi_control *msi_dialog_find_control_by_hwnd( msi_dialog *dialog, HWND hwnd ) +{ + msi_control *control; + + for( control = dialog->control_list; control; control = control->next ) + if( hwnd == control->hwnd ) + break; + return control; +} + +static UINT msi_dialog_set_control_condition( MSIRECORD *rec, LPVOID param ) +{ + static const WCHAR szHide[] = { 'H','i','d','e',0 }; + static const WCHAR szShow[] = { 'S','h','o','w',0 }; + static const WCHAR szDisable[] = { 'D','i','s','a','b','l','e',0 }; + static const WCHAR szEnable[] = { 'E','n','a','b','l','e',0 }; + msi_dialog *dialog = param; + msi_control *control; + LPCWSTR name, action, condition; + UINT r; + + name = MSI_RecordGetString( rec, 2 ); + action = MSI_RecordGetString( rec, 3 ); + condition = MSI_RecordGetString( rec, 4 ); + r = MSI_EvaluateConditionW( dialog->package, condition ); + control = msi_dialog_find_control( dialog, name ); + if( r && control ) + { + TRACE("%s control %s\n", debugstr_w(action), debugstr_w(name)); + + /* FIXME: case sensitive? */ + if(!strcmpW(action, szHide)) + ShowWindow(control->hwnd, SW_HIDE); + else if(!strcmpW(action, szShow)) + ShowWindow(control->hwnd, SW_SHOW); + else if(!strcmpW(action, szDisable)) + EnableWindow(control->hwnd, FALSE); + else if(!strcmpW(action, szEnable)) + EnableWindow(control->hwnd, TRUE); + else + FIXME("Unhandled action %s\n", debugstr_w(action)); + } + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ', + 'F','R','O','M',' ', + 'C','o','n','t','r','o','l','C','o','n','d','i','t','i','o','n',' ', + 'W','H','E','R','E',' ', + '`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',0 + }; + UINT r; + MSIQUERY *view = NULL; + MSIPACKAGE *package = dialog->package; + + TRACE("%p %s\n", dialog, debugstr_w(dialog->name) ); + + /* query the Control table for all the elements of the control */ + r = MSI_OpenQuery( package->db, &view, query, dialog->name ); + if( r != ERROR_SUCCESS ) + { + ERR("query failed for dialog %s\n", debugstr_w(dialog->name)); + return ERROR_INVALID_PARAMETER; + } + + r = MSI_IterateRecords( view, 0, msi_dialog_set_control_condition, dialog ); + msiobj_release( &view->hdr ); + + return r; +} + +/* figure out the height of 10 point MS Sans Serif */ +static INT msi_dialog_get_sans_serif_height( HWND hwnd ) +{ + static const WCHAR szSansSerif[] = { + 'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0 }; + LOGFONTW lf; + TEXTMETRICW tm; + BOOL r; + LONG height = 0; + HFONT hFont, hOldFont; + HDC hdc; + + hdc = GetDC( hwnd ); + if (hdc) + { + memset( &lf, 0, sizeof lf ); + lf.lfHeight = MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72); + strcpyW( lf.lfFaceName, szSansSerif ); + hFont = CreateFontIndirectW(&lf); + if (hFont) + { + hOldFont = SelectObject( hdc, hFont ); + r = GetTextMetricsW( hdc, &tm ); + if (r) + height = tm.tmHeight; + SelectObject( hdc, hOldFont ); + DeleteObject( hFont ); + } + ReleaseDC( hwnd, hdc ); + } + return height; +} + +static LRESULT msi_dialog_oncreate( HWND hwnd, LPCREATESTRUCTW cs ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ', + 'F','R','O','M',' ','D','i','a','l','o','g',' ', + 'W','H','E','R','E',' ', + '`','D','i','a','l','o','g','`',' ','=',' ','\'','%','s','\'',0}; + static const WCHAR df[] = { + 'D','e','f','a','u','l','t','U','I','F','o','n','t',0 }; + msi_dialog *dialog = (msi_dialog*) cs->lpCreateParams; + MSIPACKAGE *package = dialog->package; + MSIQUERY *view = NULL; + MSIRECORD *rec = NULL; + DWORD width, height; + LPCWSTR text; + LPWSTR title = NULL; + UINT r; + + TRACE("%p %p\n", dialog, package); + + dialog->hwnd = hwnd; + SetWindowLongPtrW( hwnd, GWLP_USERDATA, (LONG_PTR) dialog ); + + /* fetch the associated record from the Dialog table */ + r = MSI_OpenQuery( package->db, &view, query, dialog->name ); + if( r != ERROR_SUCCESS ) + { + ERR("query failed for dialog %s\n", debugstr_w(dialog->name)); + return -1; + } + MSI_ViewExecute( view, NULL ); + MSI_ViewFetch( view, &rec ); + MSI_ViewClose( view ); + msiobj_release( &view->hdr ); + + if( !rec ) + { + TRACE("No record found for dialog %s\n", debugstr_w(dialog->name)); + return -1; + } + + dialog->scale = msi_dialog_get_sans_serif_height(dialog->hwnd); + + width = MSI_RecordGetInteger( rec, 4 ); + height = MSI_RecordGetInteger( rec, 5 ); + dialog->attributes = MSI_RecordGetInteger( rec, 6 ); + text = MSI_RecordGetString( rec, 7 ); + + width = msi_dialog_scale_unit( dialog, width ); + height = msi_dialog_scale_unit( dialog, height ) + 25; /* FIXME */ + + dialog->default_font = load_dynamic_property( dialog->package, df, NULL ); + + deformat_string( dialog->package, text, &title ); + SetWindowTextW( hwnd, title ); + SetWindowPos( hwnd, 0, 0, 0, width, height, + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW ); + + HeapFree( GetProcessHeap(), 0, title ); + msiobj_release( &rec->hdr ); + + msi_dialog_build_font_list( dialog ); + msi_dialog_fill_controls( dialog ); + msi_dialog_evaluate_control_conditions( dialog ); + + return 0; +} + +static UINT msi_dialog_send_event( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg ) +{ + LPWSTR event_fmt = NULL, arg_fmt = NULL; + + TRACE("Sending control event %s %s\n", debugstr_w(event), debugstr_w(arg)); + + deformat_string( dialog->package, event, &event_fmt ); + deformat_string( dialog->package, arg, &arg_fmt ); + + dialog->event_handler( dialog->package, event_fmt, arg_fmt, dialog ); + + HeapFree( GetProcessHeap(), 0, event_fmt ); + HeapFree( GetProcessHeap(), 0, arg_fmt ); + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg ) +{ + static const WCHAR szNullArg[] = { '{','}',0 }; + LPWSTR p, prop, arg_fmt = NULL; + UINT len; + + len = strlenW(event); + prop = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR)); + strcpyW( prop, &event[1] ); + p = strchrW( prop, ']' ); + if( p && p[1] == 0 ) + { + *p = 0; + if( strcmpW( szNullArg, arg ) ) + deformat_string( dialog->package, arg, &arg_fmt ); + MSI_SetPropertyW( dialog->package, prop, arg_fmt ); + } + else + ERR("Badly formatted property string - what happens?\n"); + HeapFree( GetProcessHeap(), 0, prop ); + return ERROR_SUCCESS; +} + +static UINT msi_dialog_control_event( MSIRECORD *rec, LPVOID param ) +{ + msi_dialog *dialog = param; + LPCWSTR condition, event, arg; + UINT r; + + condition = MSI_RecordGetString( rec, 5 ); + r = MSI_EvaluateConditionW( dialog->package, condition ); + if( r ) + { + event = MSI_RecordGetString( rec, 3 ); + arg = MSI_RecordGetString( rec, 4 ); + if( event[0] == '[' ) + msi_dialog_set_property( dialog, event, arg ); + else + msi_dialog_send_event( dialog, event, arg ); + } + + return ERROR_SUCCESS; +} + +static UINT msi_dialog_button_handler( msi_dialog *dialog, + msi_control *control, WPARAM param ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','*',' ', + 'F','R','O','M',' ','C','o','n','t','r','o','l','E','v','e','n','t',' ', + 'W','H','E','R','E',' ', + '`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ', + 'A','N','D',' ', + '`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',' ', + 'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0 + }; + MSIQUERY *view = NULL; + UINT r; + + if( HIWORD(param) != BN_CLICKED ) + return ERROR_SUCCESS; + + r = MSI_OpenQuery( dialog->package->db, &view, query, + dialog->name, control->name ); + if( r != ERROR_SUCCESS ) + { + ERR("query failed\n"); + return 0; + } + + r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog ); + msiobj_release( &view->hdr ); + + return r; +} + +static UINT msi_dialog_get_checkbox_state( msi_dialog *dialog, + msi_control *control ) +{ + WCHAR state[2] = { 0 }; + DWORD sz = 2; + + MSI_GetPropertyW( dialog->package, control->property, state, &sz ); + return atoiW( state ) ? 1 : 0; +} + +static void msi_dialog_set_checkbox_state( msi_dialog *dialog, + msi_control *control, UINT state ) +{ + WCHAR szState[2] = { '0', 0 }; + + if( state ) + szState[0]++; + MSI_SetPropertyW( dialog->package, control->property, szState ); +} + +static void msi_dialog_checkbox_sync_state( msi_dialog *dialog, + msi_control *control ) +{ + UINT state; + + state = msi_dialog_get_checkbox_state( dialog, control ); + SendMessageW( control->hwnd, BM_SETCHECK, + state ? BST_CHECKED : BST_UNCHECKED, 0 ); +} + +static UINT msi_dialog_checkbox_handler( msi_dialog *dialog, + msi_control *control, WPARAM param ) +{ + UINT state; + + if( HIWORD(param) != BN_CLICKED ) + return ERROR_SUCCESS; + + TRACE("clicked checkbox %s, set %s\n", debugstr_w(control->name), + debugstr_w(control->property)); + + state = msi_dialog_get_checkbox_state( dialog, control ); + state = state ? 0 : 1; + msi_dialog_set_checkbox_state( dialog, control, state ); + msi_dialog_checkbox_sync_state( dialog, control ); + + return msi_dialog_button_handler( dialog, control, param ); +} + +static UINT msi_dialog_edit_handler( msi_dialog *dialog, + msi_control *control, WPARAM param ) +{ + UINT sz, r; + LPWSTR buf; + + if( HIWORD(param) != EN_CHANGE ) + return ERROR_SUCCESS; + + TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name), + debugstr_w(control->property)); + + sz = 0x20; + buf = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) ); + while( buf ) + { + r = GetWindowTextW( control->hwnd, buf, sz ); + if( r < (sz-1) ) + break; + sz *= 2; + buf = HeapReAlloc( GetProcessHeap(), 0, buf, sz*sizeof(WCHAR) ); + } + + MSI_SetPropertyW( dialog->package, control->property, buf ); + + HeapFree( GetProcessHeap(), 0, buf ); + + return ERROR_SUCCESS; +} + +static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd ) +{ + msi_control *control; + + TRACE("%p %p %08x\n", dialog, hwnd, param); + + control = msi_dialog_find_control_by_hwnd( dialog, hwnd ); + if( control ) + { + if( control->handler ) + { + control->handler( dialog, control, param ); + msi_dialog_evaluate_control_conditions( dialog ); + } + } + else + ERR("button click from nowhere\n"); + return 0; +} + +static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg, + WPARAM wParam, LPARAM lParam ) +{ + msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA ); + + switch (msg) + { + case WM_CREATE: + return msi_dialog_oncreate( hwnd, (LPCREATESTRUCTW)lParam ); + + case WM_COMMAND: + return msi_dialog_oncommand( dialog, wParam, (HWND)lParam ); + + case WM_DESTROY: + dialog->hwnd = NULL; + return 0; + } + return DefWindowProcW(hwnd, msg, wParam, lParam); +} + +/* functions that interface to other modules within MSI */ + +msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName, + msi_dialog_event_handler event_handler ) +{ + msi_dialog *dialog; + HWND hwnd; + + TRACE("%p %s\n", package, debugstr_w(szDialogName)); + + /* allocate the structure for the dialog to use */ + dialog = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof *dialog + sizeof(WCHAR)*strlenW(szDialogName) ); + if( !dialog ) + return NULL; + strcpyW( dialog->name, szDialogName ); + dialog->package = package; + dialog->event_handler = event_handler; + + /* create the dialog window, don't show it yet */ + hwnd = CreateWindowW( szMsiDialogClass, szDialogName, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, NULL, dialog ); + if( !hwnd ) + { + ERR("Failed to create dialog %s\n", debugstr_w( szDialogName )); + msi_dialog_destroy( dialog ); + return NULL; + } + + return dialog; +} + +void msi_dialog_end_dialog( msi_dialog *dialog ) +{ + dialog->finished = 1; +} + +UINT msi_dialog_run_message_loop( msi_dialog *dialog ) +{ + MSG msg; + + if( dialog->attributes & msidbDialogAttributesVisible ) + { + ShowWindow( dialog->hwnd, SW_SHOW ); + UpdateWindow( dialog->hwnd ); + } + + if( dialog->attributes & msidbDialogAttributesModal ) + { + while( !dialog->finished && GetMessageW( &msg, 0, 0, 0 ) ) + { + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } + } + else + return ERROR_IO_PENDING; + + return ERROR_SUCCESS; +} + +void msi_dialog_check_messages( msi_dialog *dialog, HANDLE handle ) +{ + MSG msg; + DWORD r; + + do + { + while( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } + if( !handle ) + break; + r = MsgWaitForMultipleObjects( 1, &handle, 0, INFINITE, QS_ALLEVENTS ); + } + while( WAIT_OBJECT_0 != r ); +} + +void msi_dialog_do_preview( msi_dialog *dialog ) +{ + dialog->attributes |= msidbDialogAttributesVisible; + dialog->attributes &= ~msidbDialogAttributesModal; + msi_dialog_run_message_loop( dialog ); +} + +void msi_dialog_destroy( msi_dialog *dialog ) +{ + if( dialog->hwnd ) + ShowWindow( dialog->hwnd, SW_HIDE ); + + /* destroy the list of controls */ + while( dialog->control_list ) + { + msi_control *t = dialog->control_list; + dialog->control_list = t->next; + /* leave dialog->hwnd - destroying parent destroys child windows */ + HeapFree( GetProcessHeap(), 0, t->property ); + HeapFree( GetProcessHeap(), 0, t ); + } + + /* destroy the list of fonts */ + while( dialog->font_list ) + { + msi_font *t = dialog->font_list; + dialog->font_list = t->next; + DeleteObject( t->hfont ); + HeapFree( GetProcessHeap(), 0, t ); + } + HeapFree( GetProcessHeap(), 0, dialog->default_font ); + + if( dialog->hwnd ) + DestroyWindow( dialog->hwnd ); + + dialog->package = NULL; + HeapFree( GetProcessHeap(), 0, dialog ); +} + +void msi_dialog_register_class( void ) +{ + WNDCLASSW cls; + + ZeroMemory( &cls, sizeof cls ); + cls.lpfnWndProc = MSIDialog_WndProc; + cls.hInstance = NULL; + cls.hIcon = LoadIconW(0, (LPWSTR)IDI_APPLICATION); + cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); + cls.hbrBackground = (HBRUSH)(COLOR_WINDOW); + cls.lpszMenuName = NULL; + cls.lpszClassName = szMsiDialogClass; + + RegisterClassW( &cls ); +} + +void msi_dialog_unregister_class( void ) +{ + UnregisterClassW( szMsiDialogClass, NULL ); +} diff -urN wine-20050111/dlls/msi/distinct.c wine-20050211/dlls/msi/distinct.c --- wine-20050111/dlls/msi/distinct.c 2004-08-25 19:31:39.000000000 +0200 +++ wine-20050211/dlls/msi/distinct.c 2005-02-08 14:44:25.000000000 +0100 @@ -178,8 +178,7 @@ if( !dv->table ) return ERROR_FUNCTION_FAILED; - if( dv->translation ) - HeapFree( GetProcessHeap(), 0, dv->translation ); + HeapFree( GetProcessHeap(), 0, dv->translation ); dv->translation = NULL; dv->row_count = 0; @@ -218,16 +217,17 @@ return dv->table->ops->get_column_info( dv->table, n, name, type ); } -static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) { MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; - TRACE("%p %d %ld\n", dv, eModifyMode, hrec ); + TRACE("%p %d %p\n", dv, eModifyMode, rec ); if( !dv->table ) return ERROR_FUNCTION_FAILED; - return dv->table->ops->modify( dv->table, eModifyMode, hrec ); + return dv->table->ops->modify( dv->table, eModifyMode, rec ); } static UINT DISTINCT_delete( struct tagMSIVIEW *view ) @@ -239,8 +239,7 @@ if( dv->table ) dv->table->ops->delete( dv->table ); - if( dv->translation ) - HeapFree( GetProcessHeap(), 0, dv->translation ); + HeapFree( GetProcessHeap(), 0, dv->translation ); msiobj_release( &dv->db->hdr ); HeapFree( GetProcessHeap(), 0, dv ); diff -urN wine-20050111/dlls/msi/format.c wine-20050211/dlls/msi/format.c --- wine-20050111/dlls/msi/format.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/format.c 2005-02-09 23:22:25.000000000 +0100 @@ -0,0 +1,583 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2005 Aric Stewart 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 + */ + +/* +http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/msiformatrecord.asp + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" +#include "wine/debug.h" +#include "fdi.h" +#include "msi.h" +#include "msiquery.h" +#include "msvcrt/fcntl.h" +#include "objbase.h" +#include "objidl.h" +#include "msipriv.h" +#include "winnls.h" +#include "winuser.h" +#include "shlobj.h" +#include "wine/unicode.h" +#include "ver.h" +#include "action.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + + +LPWSTR build_default_format(MSIRECORD* record) +{ + int i; + int count; + LPWSTR rc; + static const WCHAR fmt[] = {'%','i',':',' ','[','%','i',']',' ',0}; + WCHAR buf[11]; + + count = MSI_RecordGetFieldCount(record); + + rc = HeapAlloc(GetProcessHeap(),0,(11*count)*sizeof(WCHAR)); + rc[0] = 0; + for (i = 1; i <= count; i++) + { + sprintfW(buf,fmt,i,i); + strcatW(rc,buf); + } + return rc; +} + +static const WCHAR* scanW(LPCWSTR buf, WCHAR token, DWORD len) +{ + DWORD i; + for (i = 0; i < len; i++) + if (buf[i] == token) + return &buf[i]; + return NULL; +} + +/* break out helper functions for deformating */ +static LPWSTR deformat_component(MSIPACKAGE* package, LPCWSTR key, DWORD* sz) +{ + LPWSTR value = NULL; + INT index; + + *sz = 0; + if (!package) + return NULL; + + ERR("POORLY HANDLED DEFORMAT.. [$componentkey] \n"); + index = get_loaded_component(package,key); + if (index >= 0) + { + value = resolve_folder(package, package->components[index].Directory, + FALSE, FALSE, NULL); + *sz = (strlenW(value)) * sizeof(WCHAR); + } + + return value; +} + +static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz) +{ + LPWSTR value = NULL; + INT index; + + *sz = 0; + + if (!package) + return NULL; + + index = get_loaded_file(package,key); + if (index >=0) + { + value = dupstrW(package->files[index].TargetPath); + *sz = (strlenW(value)) * sizeof(WCHAR); + } + + return value; +} + +static LPWSTR deformat_environment(MSIPACKAGE* package, LPCWSTR key, + DWORD* chunk) +{ + LPWSTR value = NULL; + DWORD sz; + + sz = GetEnvironmentVariableW(key,NULL,0); + if (sz > 0) + { + sz++; + value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR)); + GetEnvironmentVariableW(&key[1],value,sz); + *chunk = (strlenW(value)) * sizeof(WCHAR); + } + else + { + ERR("Unknown environment variable\n"); + *chunk = 0; + value = NULL; + } + return value; +} + + +static LPWSTR deformat_NULL(DWORD* chunk) +{ + LPWSTR value; + + value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2); + value[0] = 0; + *chunk = sizeof(WCHAR); + return value; +} + +static LPWSTR deformat_escape(LPCWSTR key, DWORD* chunk) +{ + LPWSTR value; + + value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2); + value[0] = key[0]; + *chunk = sizeof(WCHAR); + + return value; +} + + +static BOOL is_key_number(LPCWSTR key) +{ + INT index = 0; + if (key[0] == 0) + return FALSE; + + while (isdigitW(key[index])) index++; + if (key[index] == 0) + return TRUE; + else + return FALSE; +} + +static LPWSTR deformat_index(MSIRECORD* record, LPCWSTR key, DWORD* chunk ) +{ + INT index; + LPWSTR value; + + index = atoiW(key); + TRACE("record index %i\n",index); + value = load_dynamic_stringW(record,index); + if (value) + *chunk = strlenW(value) * sizeof(WCHAR); + else + { + value = NULL; + *chunk = 0; + } + return value; +} + +static LPWSTR deformat_property(MSIPACKAGE* package, LPCWSTR key, DWORD* chunk) +{ + UINT rc; + LPWSTR value; + + if (!package) + return NULL; + + value = load_dynamic_property(package,key, &rc); + + if (rc == ERROR_SUCCESS) + *chunk = (strlenW(value)) * sizeof(WCHAR); + + return value; +} + +static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, + LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2, + BOOL *nested) +{ + INT count = 0; + INT total_count = 0; + int i; + + *mark = scanW(source,'[',len_remaining); + if (!*mark) + return FALSE; + + count = 1; + total_count = 1; + *nested = FALSE; + for (i = 1; (*mark - source) + i < len_remaining && count > 0; i++) + { + if ((*mark)[i] == '[') + { + count ++; + total_count ++; + *nested = TRUE; + } + else if ((*mark)[i] == ']') + { + count --; + } + } + + if (count > 0) + return FALSE; + + *mark2 = &(*mark)[i-1]; + + i = *mark2 - *mark; + *key = HeapAlloc(GetProcessHeap(),0,i*sizeof(WCHAR)); + /* do not have the [] in the key */ + i -= 1; + strncpyW(*key,&(*mark)[1],i); + (*key)[i] = 0; + + TRACE("Found Key %s\n",debugstr_w(*key)); + return TRUE; +} + + +/* + * len is in WCHARs + * return is also in WCHARs + */ +static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, + WCHAR** data, DWORD len, MSIRECORD* record) +{ + LPCWSTR mark = NULL; + LPCWSTR mark2 = NULL; + DWORD size=0; + DWORD chunk=0; + LPWSTR key; + LPWSTR value = NULL; + DWORD sz; + LPBYTE newdata = NULL; + const WCHAR* progress = NULL; + BOOL nested; + + if (ptr==NULL) + { + TRACE("Deformatting NULL string\n"); + *data = NULL; + return 0; + } + + TRACE("Starting with %s\n",debugstr_w(ptr)); + + /* scan for special characters... fast exit */ + if (!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) + { + /* not formatted */ + *data = HeapAlloc(GetProcessHeap(),0,(len*sizeof(WCHAR))); + memcpy(*data,ptr,len*sizeof(WCHAR)); + TRACE("Returning %s\n",debugstr_w(*data)); + return len; + } + + progress = ptr; + + while (progress - ptr < len) + { + /* formatted string located */ + if (!find_next_outermost_key(progress, len - (progress - ptr), &key, + &mark, &mark2, &nested)) + { + LPBYTE nd2; + + TRACE("after value %s .. %s\n",debugstr_w((LPWSTR)newdata), + debugstr_w(mark)); + chunk = (len - (progress - ptr)) * sizeof(WCHAR); + TRACE("after chunk is %li + %li\n",size,chunk); + if (size) + nd2 = HeapReAlloc(GetProcessHeap(),0,newdata,(size+chunk)); + else + nd2 = HeapAlloc(GetProcessHeap(),0,chunk); + + newdata = nd2; + memcpy(&newdata[size],progress,chunk); + size+=chunk; + break; + } + + if (mark != progress) + { + LPBYTE tgt; + DWORD old_size = size; + INT cnt = (mark - progress); + TRACE("%i (%i) characters before marker\n",cnt,(mark-progress)); + size += cnt * sizeof(WCHAR); + if (!old_size) + tgt = HeapAlloc(GetProcessHeap(),0,size); + else + tgt = HeapReAlloc(GetProcessHeap(),0,newdata,size); + newdata = tgt; + memcpy(&newdata[old_size],progress,(cnt * sizeof(WCHAR))); + } + + progress = mark; + + if (nested) + { + TRACE("Nested key... %s\n",debugstr_w(key)); + deformat_string_internal(package, key, &value, strlenW(key)+1, + record); + + HeapFree(GetProcessHeap(),0,key); + key = value; + } + + TRACE("Current %s .. %s\n",debugstr_w((LPWSTR)newdata),debugstr_w(key)); + + if (!package) + { + /* only deformat number indexs */ + if (is_key_number(key)) + value = deformat_index(record,key,&chunk); + else + { + chunk = (strlenW(key) + 2)*sizeof(WCHAR); + value = HeapAlloc(GetProcessHeap(),0,chunk); + value[0] = '['; + memcpy(&value[1],key,strlenW(key)*sizeof(WCHAR)); + value[strlenW(key)+1] = ']'; + } + } + else + { + sz = 0; + switch (key[0]) + { + case '~': + value = deformat_NULL(&chunk); + break; + case '$': + value = deformat_component(package,&key[1],&chunk); + break; + case '#': + case '!': /* should be short path */ + value = deformat_file(package,&key[1], &chunk); + break; + case '\\': + value = deformat_escape(&key[1],&chunk); + break; + case '%': + value = deformat_environment(package,&key[1],&chunk); + break; + default: + if (is_key_number(key)) + value = deformat_index(record,key,&chunk); + else + value = deformat_property(package,key,&chunk); + break; + } + } + + HeapFree(GetProcessHeap(),0,key); + + if (value!=NULL) + { + LPBYTE nd2; + TRACE("value %s, chunk %li size %li\n",debugstr_w((LPWSTR)value), + chunk, size); + if (size) + nd2= HeapReAlloc(GetProcessHeap(),0,newdata,(size + chunk)); + else + nd2= HeapAlloc(GetProcessHeap(),0,chunk); + newdata = nd2; + memcpy(&newdata[size],value,chunk); + size+=chunk; + HeapFree(GetProcessHeap(),0,value); + } + + progress = mark2+1; + } + + TRACE("after everything %s\n",debugstr_w((LPWSTR)newdata)); + + *data = (LPWSTR)newdata; + return size / sizeof(WCHAR); +} + + +UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, + DWORD *size ) +{ + LPWSTR deformated; + LPWSTR rec; + DWORD len; + UINT rc = ERROR_INVALID_PARAMETER; + + TRACE("%p %p %p %li\n",package, record ,buffer, *size); + + rec = load_dynamic_stringW(record,0); + if (!rec) + rec = build_default_format(record); + + TRACE("(%s)\n",debugstr_w(rec)); + + len = deformat_string_internal(package,rec,&deformated,strlenW(rec), + record); + + if (buffer) + { + if (*size>len) + { + memcpy(buffer,deformated,len*sizeof(WCHAR)); + rc = ERROR_SUCCESS; + buffer[len] = 0; + } + else + { + if (*size > 0) + { + memcpy(buffer,deformated,(*size)*sizeof(WCHAR)); + buffer[(*size)-1] = 0; + } + rc = ERROR_MORE_DATA; + } + } + else + rc = ERROR_SUCCESS; + + *size = len; + + HeapFree(GetProcessHeap(),0,rec); + HeapFree(GetProcessHeap(),0,deformated); + return rc; +} + +UINT MSI_FormatRecordA( MSIPACKAGE* package, MSIRECORD* record, LPSTR buffer, + DWORD *size ) +{ + LPWSTR deformated; + LPWSTR rec; + DWORD len,lenA; + UINT rc = ERROR_INVALID_PARAMETER; + + TRACE("%p %p %p %li\n",package, record ,buffer, *size); + + rec = load_dynamic_stringW(record,0); + if (!rec) + rec = build_default_format(record); + + TRACE("(%s)\n",debugstr_w(rec)); + + len = deformat_string_internal(package,rec,&deformated,strlenW(rec), + record); + lenA = WideCharToMultiByte(CP_ACP,0,deformated,len,NULL,0,NULL,NULL); + + if (buffer) + { + WideCharToMultiByte(CP_ACP,0,deformated,len,buffer,*size,NULL, NULL); + if (*size>lenA) + { + rc = ERROR_SUCCESS; + buffer[lenA] = 0; + } + else + { + rc = ERROR_MORE_DATA; + buffer[(*size)-1] = 0; + } + } + else + rc = ERROR_SUCCESS; + + *size = lenA; + + HeapFree(GetProcessHeap(),0,rec); + HeapFree(GetProcessHeap(),0,deformated); + return rc; +} + + +UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord, + LPWSTR szResult, DWORD *sz ) +{ + UINT r = ERROR_INVALID_HANDLE; + MSIPACKAGE *package; + MSIRECORD *record; + + TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); + + record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); + + if (!record) + return ERROR_INVALID_HANDLE; + if (!sz) + { + msiobj_release( &record->hdr ); + if (szResult) + return ERROR_INVALID_PARAMETER; + else + return ERROR_SUCCESS; + } + + package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); + + if( record ) + { + r = MSI_FormatRecordW( package, record, szResult, sz ); + msiobj_release( &record->hdr ); + } + if (package) + msiobj_release( &package->hdr ); + return r; +} + +UINT WINAPI MsiFormatRecordA( MSIHANDLE hInstall, MSIHANDLE hRecord, + LPSTR szResult, DWORD *sz ) +{ + UINT r = ERROR_INVALID_HANDLE; + MSIPACKAGE *package = NULL; + MSIRECORD *record = NULL; + + TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); + + record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); + + if (!record) + return ERROR_INVALID_HANDLE; + if (!sz) + { + msiobj_release( &record->hdr ); + if (szResult) + return ERROR_INVALID_PARAMETER; + else + return ERROR_SUCCESS; + } + + package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); + + if( record ) + { + r = MSI_FormatRecordA( package, record, szResult, sz ); + msiobj_release( &record->hdr ); + } + if (package) + msiobj_release( &package->hdr ); + return r; +} diff -urN wine-20050111/dlls/msi/handle.c wine-20050211/dlls/msi/handle.c --- wine-20050111/dlls/msi/handle.c 2005-01-06 21:43:04.000000000 +0100 +++ wine-20050211/dlls/msi/handle.c 2005-01-20 21:34:29.000000000 +0100 @@ -157,7 +157,7 @@ return; } - info->refcount++; + InterlockedIncrement(&info->refcount); } void msiobj_lock( MSIOBJECTHDR *info ) @@ -185,12 +185,12 @@ return -1; } - ret = info->refcount--; - if (info->refcount == 0) + ret = InterlockedDecrement( &info->refcount ); + if( ret==0 ) { - if( info->destructor ) + if( info->destructor ) info->destructor( info ); - HeapFree( GetProcessHeap(), 0, info ); + HeapFree( GetProcessHeap(), 0, info ); TRACE("object %p destroyed\n", info); } diff -urN wine-20050111/dlls/msi/insert.c wine-20050211/dlls/msi/insert.c --- wine-20050111/dlls/msi/insert.c 2004-08-25 19:31:39.000000000 +0200 +++ wine-20050211/dlls/msi/insert.c 2005-02-08 14:44:25.000000000 +0100 @@ -44,7 +44,7 @@ MSIDATABASE *db; BOOL bIsTemp; MSIVIEW *sv; - value_list *vals; /* looks like these may be ignored... */ + value_list *vals; } MSIINSERTVIEW; static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) @@ -56,11 +56,62 @@ return ERROR_FUNCTION_FAILED; } +/* + * INSERT_merge_record + * + * Merge a value_list and a record to create a second record. + * Replace wildcard entries in the valuelist with values from the record + */ +static MSIRECORD *INSERT_merge_record( UINT fields, value_list *vl, MSIRECORD *rec ) +{ + MSIRECORD *merged; + DWORD wildcard_count = 1, i; + const WCHAR *str; + + merged = MSI_CreateRecord( fields ); + for( i=1; i <= fields; i++ ) + { + if( !vl ) + { + TRACE("Not enough elements in the list to insert\n"); + goto err; + } + switch( vl->val->type ) + { + case EXPR_SVAL: + TRACE("field %ld -> %s\n", i, debugstr_w(vl->val->u.sval)); + MSI_RecordSetStringW( merged, i, vl->val->u.sval ); + break; + case EXPR_IVAL: + MSI_RecordSetInteger( merged, i, vl->val->u.ival ); + break; + case EXPR_WILDCARD: + if( !rec ) + goto err; + if( MSI_RecordIsNull( rec, wildcard_count ) ) + goto err; + str = MSI_RecordGetString( rec, wildcard_count ); + MSI_RecordSetStringW( merged, i, str ); + wildcard_count++; + break; + default: + ERR("Unknown expression type %d\n", vl->val->type); + } + vl = vl->next; + } + + return merged; +err: + msiobj_release( &merged->hdr ); + return NULL; +} + static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view; UINT n, type, val, r, row, col_count = 0; MSIVIEW *sv; + MSIRECORD *values = NULL; TRACE("%p %p\n", iv, record ); @@ -77,12 +128,13 @@ if( r ) goto err; - n = MSI_RecordGetFieldCount( record ); - if( n != col_count ) - { - ERR("Number of fields do not match\n"); + /* + * Merge the wildcard values into the list of values provided + * in the query, and create a record containing both. + */ + values = INSERT_merge_record( col_count, iv->vals, record ); + if( !values ) goto err; - } row = -1; r = sv->ops->insert_row( sv, &row ); @@ -98,12 +150,12 @@ if( type & MSITYPE_STRING ) { - const WCHAR *str = MSI_RecordGetString( record, n ); + const WCHAR *str = MSI_RecordGetString( values, n ); val = msi_addstringW( iv->db->strings, 0, str, -1, 1 ); } else { - val = MSI_RecordGetInteger( record, n ); + val = MSI_RecordGetInteger( values, n ); val |= 0x8000; } r = sv->ops->set_int( sv, row, n, val ); @@ -112,6 +164,9 @@ } err: + if( values ) + msiobj_release( &values->hdr ); + return ERROR_SUCCESS; } @@ -159,11 +214,11 @@ return sv->ops->get_column_info( sv, n, name, type ); } -static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec) { MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view; - TRACE("%p %d %ld\n", iv, eModifyMode, hrec ); + TRACE("%p %d %p\n", iv, eModifyMode, rec ); return ERROR_FUNCTION_FAILED; } diff -urN wine-20050111/dlls/msi/msi.c wine-20050211/dlls/msi/msi.c --- wine-20050111/dlls/msi/msi.c 2005-01-11 16:46:43.000000000 +0100 +++ wine-20050211/dlls/msi/msi.c 2005-02-10 19:57:42.000000000 +0100 @@ -1,7 +1,7 @@ /* * Implementation of the Microsoft Installer (msi.dll) * - * Copyright 2002,2003,2004 Mike McCormack for CodeWeavers + * Copyright 2002,2003,2004,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 @@ -37,6 +37,7 @@ #include "wine/unicode.h" #include "objbase.h" #include "winver.h" +#include "winuser.h" #include "initguid.h" @@ -50,28 +51,18 @@ */ #define LPCTSTR LPCWSTR -DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); - -static const WCHAR szInstaller[] = { -'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',0 }; - -static const WCHAR szFeatures[] = { -'F','e','a','t','u','r','e','s',0 }; -static const WCHAR szComponents[] = { -'C','o','m','p','o','n','e','n','t','s',0 }; +DEFINE_GUID( CLSID_MsiDatabase, 0x000c1084, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); /* the UI level */ -INSTALLUILEVEL gUILevel; -HWND gUIhwnd; -INSTALLUI_HANDLERA gUIHandler; -INSTALLUI_HANDLERW gUIHandlerW; -DWORD gUIFilter; -LPVOID gUIContext; +INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC; +HWND gUIhwnd = 0; +INSTALLUI_HANDLERA gUIHandlerA = NULL; +INSTALLUI_HANDLERW gUIHandlerW = NULL; +DWORD gUIFilter = 0; +LPVOID gUIContext = NULL; WCHAR gszLogFile[MAX_PATH]; +HINSTANCE msi_hInstance; /* * .MSI file format @@ -80,157 +71,15 @@ * It should contain a number of streams. */ -BOOL unsquash_guid(LPCWSTR in, LPWSTR out) -{ - DWORD i,n=0; - - out[n++]='{'; - for(i=0; i<8; i++) - out[n++] = in[7-i]; - out[n++]='-'; - for(i=0; i<4; i++) - out[n++] = in[11-i]; - out[n++]='-'; - for(i=0; i<4; i++) - out[n++] = in[15-i]; - out[n++]='-'; - for(i=0; i<2; i++) - { - out[n++] = in[17+i*2]; - out[n++] = in[16+i*2]; - } - out[n++]='-'; - for( ; i<8; i++) - { - out[n++] = in[17+i*2]; - out[n++] = in[16+i*2]; - } - out[n++]='}'; - out[n]=0; - return TRUE; -} - -BOOL squash_guid(LPCWSTR in, LPWSTR out) -{ - DWORD i,n=0; - - if(in[n++] != '{') - return FALSE; - for(i=0; i<8; i++) - out[7-i] = in[n++]; - if(in[n++] != '-') - return FALSE; - for(i=0; i<4; i++) - out[11-i] = in[n++]; - if(in[n++] != '-') - return FALSE; - for(i=0; i<4; i++) - out[15-i] = in[n++]; - if(in[n++] != '-') - return FALSE; - for(i=0; i<2; i++) - { - out[17+i*2] = in[n++]; - out[16+i*2] = in[n++]; - } - if(in[n++] != '-') - return FALSE; - for( ; i<8; i++) - { - out[17+i*2] = in[n++]; - out[16+i*2] = in[n++]; - } - out[32]=0; - if(in[n++] != '}') - return FALSE; - if(in[n]) - return FALSE; - return TRUE; -} - -/* tables for encoding and decoding base85 */ -static const unsigned char table_dec85[0x80] = { -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff, -0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17, -0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, -0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36, -0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46, -0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff, -}; - -static const char table_enc85[] = -"!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO" -"PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx" -"yz{}~"; - -/* - * Converts a base85 encoded guid into a GUID pointer - * Base85 encoded GUIDs should be 20 characters long. - * - * returns TRUE if successful, FALSE if not - */ -BOOL decode_base85_guid( LPCWSTR str, GUID *guid ) -{ - DWORD i, val = 0, base = 1, *p; - - p = (DWORD*) guid; - for( i=0; i<20; i++ ) - { - if( (i%5) == 0 ) - { - val = 0; - base = 1; - } - val += table_dec85[str[i]] * base; - if( str[i] >= 0x80 ) - return FALSE; - if( table_dec85[str[i]] == 0xff ) - return FALSE; - if( (i%5) == 4 ) - p[i/5] = val; - base *= 85; - } - return TRUE; -} - -/* - * Encodes a base85 guid given a GUID pointer - * Caller should provide a 21 character buffer for the encoded string. - * - * returns TRUE if successful, FALSE if not - */ -BOOL encode_base85_guid( GUID *guid, LPWSTR str ) -{ - unsigned int x, *p, i; - - p = (unsigned int*) guid; - for( i=0; i<4; i++ ) - { - x = p[i]; - *str++ = table_enc85[x%85]; - x = x/85; - *str++ = table_enc85[x%85]; - x = x/85; - *str++ = table_enc85[x%85]; - x = x/85; - *str++ = table_enc85[x%85]; - x = x/85; - *str++ = table_enc85[x%85]; - } - *str = 0; - - return TRUE; -} - - VOID MSI_CloseDatabase( MSIOBJECTHDR *arg ) { MSIDATABASE *db = (MSIDATABASE *) arg; + DWORD r; free_cached_tables( db ); - IStorage_Release( db->storage ); + r = IStorage_Release( db->storage ); + if( r ) + ERR("database reference count was not zero (%ld)\n", r); } UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb) @@ -381,10 +230,8 @@ r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB ); end: - if( szwPersist ) - HeapFree( GetProcessHeap(), 0, szwPersist ); - if( szwDBPath ) - HeapFree( GetProcessHeap(), 0, szwDBPath ); + HeapFree( GetProcessHeap(), 0, szwPersist ); + HeapFree( GetProcessHeap(), 0, szwDBPath ); return r; } @@ -406,35 +253,24 @@ ret = MsiOpenProductW( szwProd, phProduct ); - if( szwProd ) - HeapFree( GetProcessHeap(), 0, szwProd ); + HeapFree( GetProcessHeap(), 0, szwProd ); return ret; } UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) { - static const WCHAR szKey[] = { - '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','\\', - 'U','n','i','n','s','t','a','l','l',0 }; static const WCHAR szLocalPackage[] = { 'L','o','c','a','l','P','a','c','k','a','g','e', 0 }; LPWSTR path = NULL; UINT r; - HKEY hKeyProduct = NULL, hKeyUninstall = NULL; + HKEY hKeyProduct = NULL; DWORD count, type; TRACE("%s %p\n",debugstr_w(szProduct), phProduct); - r = RegOpenKeyW( HKEY_LOCAL_MACHINE, szKey, &hKeyUninstall ); - if( r != ERROR_SUCCESS ) - return ERROR_UNKNOWN_PRODUCT; - - r = RegOpenKeyW( hKeyUninstall, szProduct, &hKeyProduct ); + r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE); if( r != ERROR_SUCCESS ) { r = ERROR_UNKNOWN_PRODUCT; @@ -467,38 +303,44 @@ r = MsiOpenPackageW( path, phProduct ); end: - if( path ) - HeapFree( GetProcessHeap(), 0, path ); + HeapFree( GetProcessHeap(), 0, path ); if( hKeyProduct ) RegCloseKey( hKeyProduct ); - RegCloseKey( hKeyUninstall ); return r; } -UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage) +UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, + LPCSTR szTransforms, LANGID lgidLanguage) { - FIXME("%s %s %s 0x%08x\n",debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage); + FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath), + debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage) +UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, + LPCWSTR szTransforms, LANGID lgidLanguage) { - FIXME("%s %s %s 0x%08x\n",debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage); + FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath), + debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) +UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, + LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) { - FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n", - debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions); + FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_a(szPackagePath), + debugstr_a(szScriptfilePath), debugstr_a(szTransforms), + lgidLanguage, dwPlatform, dwOptions); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) +UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, + LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) { - FIXME("%s %s %s 0x%08x 0x%08lx 0x%08lx\n", - debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions); + FIXME("%s %s %s %08x %08lx %08lx\n", debugstr_w(szPackagePath), + debugstr_w(szScriptfilePath), debugstr_w(szTransforms), + lgidLanguage, dwPlatform, dwOptions); return ERROR_CALL_NOT_IMPLEMENTED; } @@ -530,11 +372,8 @@ r = MsiInstallProductW( szwPath, szwCommand ); end: - if( szwPath ) - HeapFree( GetProcessHeap(), 0, szwPath ); - - if( szwCommand ) - HeapFree( GetProcessHeap(), 0, szwCommand ); + HeapFree( GetProcessHeap(), 0, szwPath ); + HeapFree( GetProcessHeap(), 0, szwCommand ); return r; } @@ -566,29 +405,148 @@ UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode) { - FIXME("%s 0x%08lx\n", debugstr_a(szProduct), dwReinstallMode); - return ERROR_CALL_NOT_IMPLEMENTED; + FIXME("%s %08lx\n", debugstr_a(szProduct), dwReinstallMode); + return ERROR_CALL_NOT_IMPLEMENTED; } UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode) { - FIXME("%s 0x%08lx\n", debugstr_w(szProduct), dwReinstallMode); - return ERROR_CALL_NOT_IMPLEMENTED; + FIXME("%s %08lx\n", debugstr_w(szProduct), dwReinstallMode); + return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, INSTALLTYPE eInstallType, LPCSTR szCommandLine) +UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, + INSTALLTYPE eInstallType, LPCSTR szCommandLine) { - FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage), eInstallType, debugstr_a(szCommandLine)); - return ERROR_CALL_NOT_IMPLEMENTED; + FIXME("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage), + eInstallType, debugstr_a(szCommandLine)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, + INSTALLTYPE eInstallType, LPCWSTR szCommandLine) +{ + FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage), + eInstallType, debugstr_w(szCommandLine)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, + INSTALLSTATE eInstallState, LPCWSTR szCommandLine) +{ + MSIHANDLE handle; + MSIPACKAGE* package; + UINT rc; + HKEY hkey=0,hkey1=0; + DWORD sz; + static const WCHAR szSouceList[] = { + 'S','o','u','r','c','e','L','i','s','t',0}; + static const WCHAR szLUS[] = { + 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0}; + WCHAR sourcepath[0x200]; + static const WCHAR szInstalled[] = { + ' ','I','n','s','t','a','l','l','e','d','=','1',0}; + LPWSTR commandline; + + FIXME("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState, + debugstr_w(szCommandLine)); + + if (eInstallState != INSTALLSTATE_LOCAL && + eInstallState != INSTALLSTATE_DEFAULT) + { + FIXME("Not implemented for anything other than local installs\n"); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE); + if (rc != ERROR_SUCCESS) + goto end; + + rc = RegOpenKeyW(hkey,szSouceList,&hkey1); + if (rc != ERROR_SUCCESS) + goto end; + + sz = sizeof(sourcepath); + rc = RegQueryValueExW(hkey1, szLUS, NULL, NULL,(LPBYTE)sourcepath, &sz); + if (rc != ERROR_SUCCESS) + goto end; + + RegCloseKey(hkey1); + /* + * ok 1, we need to find the msi file for this product. + * 2, find the source dir for the files + * 3, do the configure/install. + * 4, cleanupany runonce entry. + */ + + rc = MsiOpenProductW(szProduct,&handle); + if (rc != ERROR_SUCCESS) + goto end; + + package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); + + sz = strlenW(szInstalled); + + if (szCommandLine) + sz += strlenW(szCommandLine); + + commandline = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR)); + + if (szCommandLine) + strcpyW(commandline,szCommandLine); + else + commandline[0] = 0; + + if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN) + strcatW(commandline,szInstalled); + + rc = ACTION_DoTopLevelINSTALL(package, sourcepath, commandline); + + msiobj_release( &package->hdr ); + + HeapFree(GetProcessHeap(),0,commandline); +end: + RegCloseKey(hkey); + + return rc; } -UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, INSTALLTYPE eInstallType, LPCWSTR szCommandLine) +UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel, + INSTALLSTATE eInstallState, LPCSTR szCommandLine) { - FIXME("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage), eInstallType, debugstr_w(szCommandLine)); - return ERROR_CALL_NOT_IMPLEMENTED; + LPWSTR szwProduct = NULL; + LPWSTR szwCommandLine = NULL; + UINT hr = ERROR_FUNCTION_FAILED; + + if( szProduct ) + { + UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); + szwProduct = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + if( !szwProduct ) + goto end; + MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); + } + + if( szCommandLine) + { + UINT len = MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, NULL, 0 ); + szwCommandLine= HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + if( !szwCommandLine) + goto end; + MultiByteToWideChar( CP_ACP, 0, szCommandLine, -1, szwCommandLine, len ); + } + + hr = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState, + szwCommandLine ); +end: + HeapFree( GetProcessHeap(), 0, szwProduct ); + HeapFree( GetProcessHeap(), 0, szwCommandLine); + + return hr; } -UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState) +UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, + INSTALLSTATE eInstallState) { LPWSTR szwProduct = NULL; UINT hr = ERROR_SUCCESS; @@ -607,22 +565,25 @@ hr = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState ); end: - if( szwProduct ) - HeapFree( GetProcessHeap(), 0, szwProduct ); + HeapFree( GetProcessHeap(), 0, szwProduct ); return hr; } -UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState) +UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, + INSTALLSTATE eInstallState) { - FIXME("%s %d %d\n",debugstr_w(szProduct), iInstallLevel, eInstallState); - return ERROR_CALL_NOT_IMPLEMENTED; + FIXME("%s %d %d\n", debugstr_w(szProduct), iInstallLevel, eInstallState); + + return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, + NULL); } UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer) { - LPWSTR szwComponent = NULL, szwBuffer = NULL; + LPWSTR szwComponent = NULL; UINT hr = ERROR_INSTALL_FAILURE; + WCHAR szwBuffer[GUID_SIZE]; FIXME("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer)); @@ -633,28 +594,17 @@ if( !szwComponent ) goto end; MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); - } else { - return ERROR_INVALID_PARAMETER; - } - - { - szwBuffer = HeapAlloc( GetProcessHeap(), 0, GUID_SIZE * sizeof(WCHAR) ); - if( !szwBuffer ) - goto end; } + else + return ERROR_INVALID_PARAMETER; hr = MsiGetProductCodeW( szwComponent, szwBuffer ); if( ERROR_SUCCESS == hr ) - { WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL); - } end: - if( szwComponent ) - HeapFree( GetProcessHeap(), 0, szwComponent ); - if( szwBuffer ) - HeapFree( GetProcessHeap(), 0, szwBuffer ); + HeapFree( GetProcessHeap(), 0, szwComponent ); return hr; } @@ -662,25 +612,22 @@ UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer) { FIXME("%s %s\n",debugstr_w(szComponent), debugstr_w(szBuffer)); - if (NULL == szComponent) { - return ERROR_INVALID_PARAMETER; - } + if (NULL == szComponent) + return ERROR_INVALID_PARAMETER; return ERROR_CALL_NOT_IMPLEMENTED; } - - - -UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, DWORD *pcchValueBuf) +UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, + LPSTR szBuffer, DWORD *pcchValueBuf) { LPWSTR szwProduct = NULL, szwAttribute = NULL, szwBuffer = NULL; UINT hr = ERROR_INSTALL_FAILURE; - FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), szBuffer, pcchValueBuf); + FIXME("%s %s %p %p\n",debugstr_a(szProduct), debugstr_a(szAttribute), + szBuffer, pcchValueBuf); - if (NULL != szBuffer && NULL == pcchValueBuf) { - return ERROR_INVALID_PARAMETER; - } + if( NULL != szBuffer && NULL == pcchValueBuf ) + return ERROR_INVALID_PARAMETER; if( szProduct ) { UINT len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); @@ -688,9 +635,9 @@ if( !szwProduct ) goto end; MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); - } else { - return ERROR_INVALID_PARAMETER; } + else + return ERROR_INVALID_PARAMETER; if( szAttribute ) { @@ -699,52 +646,50 @@ if( !szwAttribute ) goto end; MultiByteToWideChar( CP_ACP, 0, szAttribute, -1, szwAttribute, len ); - } else { - hr = ERROR_INVALID_PARAMETER; - goto end; + } + else + { + hr = ERROR_INVALID_PARAMETER; + goto end; } if( szBuffer ) { szwBuffer = HeapAlloc( GetProcessHeap(), 0, (*pcchValueBuf) * sizeof(WCHAR) ); - if( !szwBuffer ) + if( !szwBuffer ) goto end; } hr = MsiGetProductInfoW( szwProduct, szwAttribute, szwBuffer, pcchValueBuf ); if( ERROR_SUCCESS == hr ) - { WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, *pcchValueBuf, NULL, NULL); - } end: - if( szwProduct ) - HeapFree( GetProcessHeap(), 0, szwProduct ); - if( szwAttribute ) - HeapFree( GetProcessHeap(), 0, szwAttribute ); - if( szwBuffer ) - HeapFree( GetProcessHeap(), 0, szwBuffer ); + HeapFree( GetProcessHeap(), 0, szwProduct ); + HeapFree( GetProcessHeap(), 0, szwAttribute ); + HeapFree( GetProcessHeap(), 0, szwBuffer ); return hr; } -UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szBuffer, DWORD *pcchValueBuf) +UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, + LPWSTR szBuffer, DWORD *pcchValueBuf) { MSIHANDLE hProduct; UINT hr; - FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), szBuffer, pcchValueBuf); + FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szAttribute), + szBuffer, pcchValueBuf); - if (NULL != szBuffer && NULL == pcchValueBuf) { - return ERROR_INVALID_PARAMETER; - } - if (NULL == szProduct || NULL == szAttribute) { - return ERROR_INVALID_PARAMETER; - } + if (NULL != szBuffer && NULL == pcchValueBuf) + return ERROR_INVALID_PARAMETER; + if (NULL == szProduct || NULL == szAttribute) + return ERROR_INVALID_PARAMETER; hr = MsiOpenProductW(szProduct, &hProduct); - if (ERROR_SUCCESS != hr) return hr; + if (ERROR_SUCCESS != hr) + return hr; hr = MsiGetPropertyW(hProduct, szAttribute, szBuffer, pcchValueBuf); MsiCloseHandle(hProduct); @@ -777,30 +722,31 @@ if( !szwLogFile ) goto end; MultiByteToWideChar( CP_ACP, 0, szLogFile, -1, szwLogFile, len ); - } else { - return ERROR_INVALID_PARAMETER; } + else + return ERROR_INVALID_PARAMETER; hr = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); end: - if( szwLogFile ) - HeapFree( GetProcessHeap(), 0, szwLogFile ); + HeapFree( GetProcessHeap(), 0, szwLogFile ); return hr; } UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) { - HANDLE the_file = INVALID_HANDLE_VALUE; + HANDLE file = INVALID_HANDLE_VALUE; + TRACE("%08lx %s %08lx\n", dwLogMode, debugstr_w(szLogFile), attributes); + strcpyW(gszLogFile,szLogFile); if (!(attributes & INSTALLLOGATTRIBUTES_APPEND)) DeleteFileW(szLogFile); - the_file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, + file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (the_file != INVALID_HANDLE_VALUE) - CloseHandle(the_file); + if (file != INVALID_HANDLE_VALUE) + CloseHandle(file); else ERR("Unable to enable log %s\n",debugstr_w(szLogFile)); @@ -809,20 +755,65 @@ INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct) { - FIXME("%s\n", debugstr_a(szProduct)); - return INSTALLSTATE_UNKNOWN; + LPWSTR szwProduct; + UINT len; + INSTALLSTATE rc; + + len = MultiByteToWideChar(CP_ACP,0,szProduct,-1,NULL,0); + szwProduct = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP,0,szProduct,-1,szwProduct,len); + rc = MsiQueryProductStateW(szwProduct); + HeapFree(GetProcessHeap(),0,szwProduct); + return rc; } INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct) { - FIXME("%s\n", debugstr_w(szProduct)); - return INSTALLSTATE_UNKNOWN; + UINT rc; + INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN; + HKEY hkey=0; + static const WCHAR szWindowsInstaller[] = { + 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 }; + DWORD sz; + + TRACE("%s\n", debugstr_w(szProduct)); + + rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE); + if (rc != ERROR_SUCCESS) + goto end; + + RegCloseKey(hkey); + + rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE); + if (rc != ERROR_SUCCESS) + goto end; + + sz = sizeof(rrc); + rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&rrc, &sz); + if (rc != ERROR_SUCCESS) + goto end; + + switch (rrc) + { + case 1: + /* default */ + rrc = INSTALLSTATE_DEFAULT; + break; + default: + FIXME("Unknown install state read from registry (%i)\n",rrc); + rrc = INSTALLSTATE_UNKNOWN; + break; + } +end: + RegCloseKey(hkey); + return rrc; } INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd) { INSTALLUILEVEL old = gUILevel; HWND oldwnd = gUIhwnd; + TRACE("%08x %p\n", dwUILevel, phWnd); gUILevel = dwUILevel; @@ -837,10 +828,10 @@ INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, DWORD dwMessageFilter, LPVOID pvContext) { - INSTALLUI_HANDLERA prev = gUIHandler; + INSTALLUI_HANDLERA prev = gUIHandlerA; - TRACE("(%p %lx %p)\n",puiHandler, dwMessageFilter,pvContext); - gUIHandler = puiHandler; + TRACE("%p %lx %p\n",puiHandler, dwMessageFilter,pvContext); + gUIHandlerA = puiHandler; gUIFilter = dwMessageFilter; gUIContext = pvContext; @@ -852,7 +843,7 @@ { INSTALLUI_HANDLERW prev = gUIHandlerW; - TRACE("(%p %lx %p)\n",puiHandler,dwMessageFilter,pvContext); + TRACE("%p %lx %p\n",puiHandler,dwMessageFilter,pvContext); gUIHandlerW = puiHandler; gUIFilter = dwMessageFilter; gUIContext = pvContext; @@ -860,54 +851,122 @@ return prev; } -UINT WINAPI MsiLoadStringA(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax, DWORD e) +/****************************************************************** + * MsiLoadStringW [MSI.@] + * + * Loads a string from MSI's string resources. + * + * PARAMS + * + * handle [I] only -1 is handled currently + * 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 + * + * RETURNS + * + * If successful, this function returns the language id of the string loaded + * If the function fails, the function returns zero. + * + * NOTES + * + * The type of the first parameter is unknown. LoadString's prototype + * suggests that it might be a module handle. I have made it an MSI handle + * for starters, as -1 is an invalid MSI handle, but not an invalid module + * handle. Maybe strings can be stored in an MSI database somehow. + */ +LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer, + int nBufferMax, LANGID lang ) { - /*FIXME("%08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e);*/ - FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e); - return ERROR_CALL_NOT_IMPLEMENTED; + HRSRC hres; + HGLOBAL hResData; + LPWSTR p; + DWORD i, len; + + TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang); + + if( handle != -1 ) + FIXME("don't know how to deal with handle = %08lx\n", handle); + + if( !lang ) + lang = GetUserDefaultLangID(); + + hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING, + (LPWSTR)1, lang ); + if( !hres ) + return 0; + hResData = LoadResource( msi_hInstance, hres ); + if( !hResData ) + return 0; + p = LockResource( hResData ); + if( !p ) + return 0; + + for (i = 0; i < (id&0xf); i++) + p += *p + 1; + len = *p; + + if( nBufferMax <= len ) + return 0; + + memcpy( lpBuffer, p+1, len * sizeof(WCHAR)); + lpBuffer[ len ] = 0; + + TRACE("found -> %s\n", debugstr_w(lpBuffer)); + + return lang; } -UINT WINAPI MsiLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax, DWORD e) +LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer, + int nBufferMax, LANGID lang ) { - FIXME("%p %u %p %d %08lx\n",hInstance,uID,lpBuffer,nBufferMax,e); - /* - int ret = LoadStringW(hInstance,uID,lpBuffer,nBufferMax); - FIXME("%s\n",debugstr_w(lpBuffer)); - return ret; - */ - return ERROR_CALL_NOT_IMPLEMENTED; + LPWSTR bufW; + LANGID r; + DWORD len; + + bufW = HeapAlloc(GetProcessHeap(), 0, nBufferMax*sizeof(WCHAR)); + r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang); + if( r ) + { + len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); + if( len <= nBufferMax ) + WideCharToMultiByte( CP_ACP, 0, bufW, -1, + lpBuffer, nBufferMax, NULL, NULL ); + else + r = 0; + } + HeapFree(GetProcessHeap(), 0, bufW); + return r; } -INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf) +INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, + DWORD *pcchBuf) { FIXME("%s %p %08lx\n", debugstr_a(szComponent), lpPathBuf, *pcchBuf); return INSTALLSTATE_UNKNOWN; } -INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, DWORD *pcchBuf) +INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPSTR lpPathBuf, + DWORD *pcchBuf) { FIXME("%s %p %08lx\n", debugstr_w(szComponent), lpPathBuf, *pcchBuf); return INSTALLSTATE_UNKNOWN; } -#include "winuser.h" - -UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f) +UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, + WORD wLanguageId, DWORD f) { - FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption),uType,wLanguageId,f); - /* - MessageBoxExA(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId); - */ + FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_a(lpText),debugstr_a(lpCaption), + uType,wLanguageId,f); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD f) +UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, + WORD wLanguageId, DWORD f) { - /*FIXME("%08lx %08lx %08lx %08lx %08lx %08lx\n",a,b,c,d,e,f);*/ - FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption),uType,wLanguageId,f); - /* - MessageBoxExW(hWnd,lpText,lpCaption,uType|MB_OK,wLanguageId); - */ + FIXME("%p %s %s %u %08x %08lx\n",hWnd,debugstr_w(lpText),debugstr_w(lpCaption), + uType,wLanguageId,f); return ERROR_CALL_NOT_IMPLEMENTED; } @@ -930,20 +989,16 @@ UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid) { - HKEY hkey = 0, hkeyFeatures = 0; + HKEY hkeyFeatures = 0; DWORD r; WCHAR szKeyName[33]; TRACE("%ld %p\n",index,lpguid); - if (NULL == lpguid) { - return ERROR_INVALID_PARAMETER; - } - r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey); - if( r != ERROR_SUCCESS ) - goto end; + if (NULL == lpguid) + return ERROR_INVALID_PARAMETER; - r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures); + r = MSIREG_OpenFeatures(&hkeyFeatures); if( r != ERROR_SUCCESS ) goto end; @@ -955,8 +1010,6 @@ if( hkeyFeatures ) RegCloseKey(hkeyFeatures); - if( hkey ) - RegCloseKey(hkey); return r; } @@ -989,8 +1042,7 @@ szParent, GUID_SIZE, NULL, NULL); } - if( szwProduct ) - HeapFree( GetProcessHeap(), 0, szwProduct); + HeapFree( GetProcessHeap(), 0, szwProduct); return r; } @@ -998,24 +1050,12 @@ UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, LPWSTR szFeature, LPWSTR szParent) { - HKEY hkey = 0, hkeyFeatures = 0, hkeyProduct = 0; + HKEY hkeyProduct = 0; DWORD r, sz; - WCHAR szRegName[GUID_SIZE]; TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent); - if( !squash_guid(szProduct, szRegName) ) - return ERROR_INVALID_PARAMETER; - - r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegOpenKeyW(hkey, szFeatures, &hkeyFeatures); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegOpenKeyW(hkeyFeatures, szRegName, &hkeyProduct); + r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE); if( r != ERROR_SUCCESS ) goto end; @@ -1025,10 +1065,6 @@ end: if( hkeyProduct ) RegCloseKey(hkeyProduct); - if( hkeyFeatures ) - RegCloseKey(hkeyFeatures); - if( hkey ) - RegCloseKey(hkey); return r; } @@ -1049,17 +1085,13 @@ UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid) { - HKEY hkey = 0, hkeyComponents = 0; + HKEY hkeyComponents = 0; DWORD r; WCHAR szKeyName[33]; TRACE("%ld %p\n",index,lpguid); - r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegOpenKeyW(hkey, szComponents, &hkeyComponents); + r = MSIREG_OpenComponents(&hkeyComponents); if( r != ERROR_SUCCESS ) goto end; @@ -1071,8 +1103,6 @@ if( hkeyComponents ) RegCloseKey(hkeyComponents); - if( hkey ) - RegCloseKey(hkey); return r; } @@ -1102,32 +1132,20 @@ szProduct, GUID_SIZE, NULL, NULL); } - if( szwComponent ) - HeapFree( GetProcessHeap(), 0, szwComponent); + HeapFree( GetProcessHeap(), 0, szwComponent); return r; } UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct) { - HKEY hkey = 0, hkeyComponents = 0, hkeyComp = 0; + HKEY hkeyComp = 0; DWORD r, sz; - WCHAR szRegName[GUID_SIZE], szValName[GUID_SIZE]; + WCHAR szValName[GUID_SIZE]; TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct); - if( !squash_guid(szComponent, szRegName) ) - return ERROR_INVALID_PARAMETER; - - r = RegOpenKeyW(HKEY_LOCAL_MACHINE, szInstaller, &hkey); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegOpenKeyW(hkey, szComponents, &hkeyComponents); - if( r != ERROR_SUCCESS ) - goto end; - - r = RegOpenKeyW(hkeyComponents, szRegName, &hkeyComp); + r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE); if( r != ERROR_SUCCESS ) goto end; @@ -1141,67 +1159,79 @@ end: if( hkeyComp ) RegCloseKey(hkeyComp); - if( hkeyComponents ) - RegCloseKey(hkeyComponents); - if( hkey ) - RegCloseKey(hkey); return r; } -UINT WINAPI MsiEnumComponentQualifiersA( - LPSTR szComponent, DWORD iIndex, LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf) +UINT WINAPI MsiEnumComponentQualifiersA( LPSTR szComponent, DWORD iIndex, + LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf, + LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf) { -FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, 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) +UINT WINAPI MsiEnumComponentQualifiersW( LPWSTR szComponent, DWORD iIndex, + LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf, + LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf ) { -FIXME("%s 0x%08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf, 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) +UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext, + DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, + DWORD* pcchPathBuf ) { - FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", - debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf); + FIXME("%s %s %08lx %08lx %p %p\n", debugstr_a(szAssemblyName), + debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, + pcchPathBuf); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiProvideAssemblyW( - LPCWSTR szAssemblyName, LPCWSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, DWORD* pcchPathBuf) +UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext, + DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, + DWORD* pcchPathBuf ) { - FIXME("%s %s 0x%08lx 0x%08lx %p %p\n", - debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, pcchPathBuf); + FIXME("%s %s %08lx %08lx %p %p\n", debugstr_w(szAssemblyName), + debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, + pcchPathBuf); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs ) +UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, + LPSTR szPath, DWORD *pcchPath, DWORD *pcchArgs ) { FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs ); return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs ) +UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, + LPWSTR szPath, DWORD *pcchPath, DWORD *pcchArgs ) { FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs ); return ERROR_CALL_NOT_IMPLEMENTED; } -HRESULT WINAPI MsiGetFileSignatureInformationA( - LPCSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData) +HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath, + DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, + DWORD* pcbHashData) { - FIXME("%s 0x%08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData); + FIXME("%s %08lx %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags, + ppcCertContext, pbHashData, pcbHashData); return ERROR_CALL_NOT_IMPLEMENTED; } -HRESULT WINAPI MsiGetFileSignatureInformationW( - LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, DWORD* pcbHashData) +HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath, + DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, BYTE* pbHashData, + DWORD* pcbHashData) { - FIXME("%s 0x%08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, ppcCertContext, pbHashData, pcbHashData); + FIXME("%s %08lx %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags, + ppcCertContext, pbHashData, pcbHashData); return ERROR_CALL_NOT_IMPLEMENTED; } @@ -1258,13 +1288,11 @@ INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent, LPSTR lpPathBuf, DWORD* pcchBuf) { + LPWSTR szwProduct = NULL, szwComponent = NULL, lpwPathBuf= NULL; INSTALLSTATE rc; - UINT len; - LPWSTR szwProduct= NULL; - LPWSTR szwComponent= NULL; - LPWSTR lpwPathBuf= NULL; + UINT len, incoming_len; - if( szProduct) + if( szProduct ) { len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); @@ -1273,11 +1301,11 @@ MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } - if( szComponent) + if( szComponent ) { len = MultiByteToWideChar( CP_ACP, 0, szComponent, -1, NULL, 0 ); szwComponent= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - if( !szwComponent) + if( !szwComponent ) { HeapFree( GetProcessHeap(), 0, szwProduct); return ERROR_OUTOFMEMORY; @@ -1285,19 +1313,21 @@ MultiByteToWideChar( CP_ACP, 0, szComponent, -1, szwComponent, len ); } - if (pcchBuf && *pcchBuf > 0) + if( pcchBuf && *pcchBuf > 0 ) lpwPathBuf = HeapAlloc( GetProcessHeap(), 0, *pcchBuf * sizeof(WCHAR)); else lpwPathBuf = NULL; + incoming_len = *pcchBuf; rc = MsiGetComponentPathW(szwProduct, szwComponent, lpwPathBuf, pcchBuf); HeapFree( GetProcessHeap(), 0, szwProduct); HeapFree( GetProcessHeap(), 0, szwComponent); if (lpwPathBuf) { - WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, *pcchBuf, - lpPathBuf, GUID_SIZE, NULL, NULL); + if (rc != INSTALLSTATE_UNKNOWN) + WideCharToMultiByte(CP_ACP, 0, lpwPathBuf, incoming_len, + lpPathBuf, incoming_len, NULL, NULL); HeapFree( GetProcessHeap(), 0, lpwPathBuf); } @@ -1307,10 +1337,46 @@ INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent, LPWSTR lpPathBuf, DWORD* pcchBuf) { - FIXME("STUB: (%s %s %p %p)\n", debugstr_w(szProduct), + WCHAR squished_pc[GUID_SIZE]; + UINT rc; + INSTALLSTATE rrc = INSTALLSTATE_UNKNOWN; + HKEY hkey=0; + + TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szComponent), lpPathBuf, pcchBuf); - return INSTALLSTATE_UNKNOWN; + squash_guid(szProduct,squished_pc); + + rc = MSIREG_OpenProductsKey(szProduct,&hkey,FALSE); + if (rc != ERROR_SUCCESS) + goto end; + + RegCloseKey(hkey); + + rc = MSIREG_OpenComponentsKey(szComponent,&hkey,FALSE); + if (rc != ERROR_SUCCESS) + goto end; + + *pcchBuf *= sizeof(WCHAR); + rc = RegQueryValueExW(hkey,squished_pc,NULL,NULL,(LPVOID)lpPathBuf, + pcchBuf); + *pcchBuf /= sizeof(WCHAR); + + if (rc!= ERROR_SUCCESS) + goto end; + + TRACE("found path of (%s:%s)(%s)\n", debugstr_w(szComponent), + debugstr_w(szProduct), debugstr_w(lpPathBuf)); + + FIXME("Only working for installed files, not registry keys\n"); + if (GetFileAttributesW(lpPathBuf) != INVALID_FILE_ATTRIBUTES) + rrc = INSTALLSTATE_LOCAL; + else + rrc = INSTALLSTATE_ABSENT; + +end: + RegCloseKey(hkey); + return rrc; } INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature) @@ -1320,7 +1386,7 @@ LPWSTR szwProduct= NULL; LPWSTR szwFeature= NULL; - if( szProduct) + if( szProduct ) { len = MultiByteToWideChar( CP_ACP, 0, szProduct, -1, NULL, 0 ); szwProduct= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); @@ -1329,7 +1395,7 @@ MultiByteToWideChar( CP_ACP, 0, szProduct, -1, szwProduct, len ); } - if( szFeature) + if( szFeature ) { len = MultiByteToWideChar( CP_ACP, 0, szFeature, -1, NULL, 0 ); szwFeature= HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); @@ -1351,63 +1417,63 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) { - FIXME("STUB: (%s %s)\n", debugstr_w(szProduct), debugstr_w(szFeature)); + FIXME("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); return INSTALLSTATE_UNKNOWN; } -UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf) +UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, + DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf) { - UINT len; - UINT ret; - LPWSTR szwFilePath = NULL; - LPWSTR lpwVersionBuff = NULL; - LPWSTR lpwLangBuff = NULL; + LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; + UINT len, ret = ERROR_OUTOFMEMORY; - if(szFilePath) { + if( szFilePath ) + { len = MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, NULL, 0 ); szwFilePath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - if( !szwFilePath) - return ERROR_OUTOFMEMORY; + if( !szwFilePath ) + goto end; MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, szwFilePath, len ); } - if(lpVersionBuf && pcchVersionBuf && *pcchVersionBuf) { - lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf * sizeof(WCHAR)); - if( !lpwVersionBuff) - { - ret = ERROR_OUTOFMEMORY; + if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) + { + lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR)); + if( !lpwVersionBuff ) goto end; - } } - if(lpLangBuf && pcchLangBuf && *pcchLangBuf) { - lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf * sizeof(WCHAR)); - if( !lpwLangBuff) - { - ret = ERROR_OUTOFMEMORY; + if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) + { + lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf*sizeof(WCHAR)); + if( !lpwLangBuff ) goto end; - } } - ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, lpwLangBuff, pcchLangBuf); + ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, + lpwLangBuff, pcchLangBuf); - if(lpwVersionBuff) - WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, lpVersionBuf, *pcchVersionBuf, NULL, NULL); - if(lpwLangBuff) - WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, lpLangBuf, *pcchLangBuf, NULL, NULL); + if( lpwVersionBuff ) + WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, + lpVersionBuf, *pcchVersionBuf, NULL, NULL); + if( lpwLangBuff ) + WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, + lpLangBuf, *pcchLangBuf, NULL, NULL); end: - if(szwFilePath) HeapFree(GetProcessHeap(), 0, szwFilePath); - if(lpwVersionBuff) HeapFree(GetProcessHeap(), 0, lpwVersionBuff); - if(lpwLangBuff) HeapFree(GetProcessHeap(), 0, lpwLangBuff); + HeapFree(GetProcessHeap(), 0, szwFilePath); + HeapFree(GetProcessHeap(), 0, lpwVersionBuff); + HeapFree(GetProcessHeap(), 0, lpwLangBuff); return ret; } -UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf) +UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, + DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf) { static const WCHAR szVersionResource[] = {'\\',0}; - static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; + static const WCHAR szVersionFormat[] = { + '%','d','.','%','d','.','%','d','.','%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0}; UINT ret = 0; DWORD dwVerLen; @@ -1416,38 +1482,48 @@ UINT puLen; WCHAR tmp[32]; - TRACE("(%s,%p,%ld,%p,%ld)\n", debugstr_w(szFilePath), + TRACE("%s %p %ld %p %ld\n", debugstr_w(szFilePath), lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0, lpLangBuf, pcchLangBuf?*pcchLangBuf:0); dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL); - if(!dwVerLen) + if( !dwVerLen ) return GetLastError(); lpVer = HeapAlloc(GetProcessHeap(), 0, dwVerLen); - if(!lpVer) { + if( !lpVer ) + { ret = ERROR_OUTOFMEMORY; goto end; } - if(!GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer)) { + if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) ) + { ret = GetLastError(); goto end; } - if(lpVersionBuf && pcchVersionBuf && *pcchVersionBuf) { - if(VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) && puLen > 0) { - wsprintfW(tmp, szVersionFormat, HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS)); + if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) + { + if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) && + (puLen > 0) ) + { + wsprintfW(tmp, szVersionFormat, + HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), + HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS)); lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); *pcchVersionBuf = strlenW(lpVersionBuf); } - else { + else + { *lpVersionBuf = 0; *pcchVersionBuf = 0; } } - if(lpLangBuf && pcchLangBuf && *pcchLangBuf) { + if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) + { DWORD lang = GetUserDefaultLangID(); + FIXME("Retrieve language from file\n"); wsprintfW(tmp, szLangFormat, lang); lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); @@ -1455,152 +1531,125 @@ } end: - if(lpVer) HeapFree(GetProcessHeap(), 0, lpVer); + HeapFree(GetProcessHeap(), 0, lpVer); return ret; } /****************************************************************** - * DllMain - * - * @todo: maybe we can check here if MsiServer service is declared no ? + * DllMain */ -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - if (fdwReason == DLL_PROCESS_ATTACH) { - DisableThreadLibraryCalls(hinstDLL); - /* - * UI Initialization - */ - gUILevel = INSTALLUILEVEL_BASIC; - gUIhwnd = 0; - gUIHandler = NULL; - gUIFilter = 0; - gUIContext = NULL; - gszLogFile[0]=0; - /* FIXME: Initialisation */ - } else if (fdwReason == DLL_PROCESS_DETACH) { - /* FIXME: Cleanup */ - } - /* - static const WCHAR szMSIServerSvc[] = { 'M','S','I','S','e','r','v','e','r',0 }; - static const WCHAR szNull[] = { 0 }; - if (!strcmpW(lpServiceName, szMSIServerSvc)) { - hKey = CreateServiceW(hSCManager, - szMSIServerSvc, - szMSIServerSvc, - SC_MANAGER_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS, - SERVICE_AUTO_START, - SERVICE_ERROR_IGNORE, - szNull, - NULL, - NULL, - NULL, - NULL, - szNull); - */ - return TRUE; -} - -typedef struct { - /* IUnknown fields */ - IClassFactoryVtbl *lpVtbl; - DWORD ref; +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch(fdwReason) + { + case DLL_PROCESS_ATTACH: + msi_hInstance = hinstDLL; + DisableThreadLibraryCalls(hinstDLL); + msi_dialog_register_class(); + break; + case DLL_PROCESS_DETACH: + msi_dialog_unregister_class(); + /* FIXME: Cleanup */ + break; + } + return TRUE; +} + +typedef struct tagIClassFactoryImpl +{ + IClassFactoryVtbl *lpVtbl; } IClassFactoryImpl; -static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %s, %p): stub\n",This,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; +static HRESULT WINAPI MsiCF_QueryInterface(LPCLASSFACTORY iface, + REFIID riid,LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + FIXME("%p %s %p\n",This,debugstr_guid(riid),ppobj); + return E_NOINTERFACE; } -static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return InterlockedIncrement(&This->ref); +static ULONG WINAPI MsiCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; } -static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - return InterlockedDecrement(&This->ref); +static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) +{ + return 1; } -static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME ("(%p, %p, %s, %p): to implement\n", This, pOuter, debugstr_guid(riid), ppobj); - return 0; +static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + + FIXME("%p %p %s %p\n", This, pOuter, debugstr_guid(riid), ppobj); + return E_FAIL; } -static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p, %d): stub\n", This, dolock); - return S_OK; +static HRESULT WINAPI MsiCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + + FIXME("%p %d\n", This, dolock); + return S_OK; } -static IClassFactoryVtbl MsiCF_Vtbl = { - MsiCF_QueryInterface, - MsiCF_AddRef, - MsiCF_Release, - MsiCF_CreateInstance, - MsiCF_LockServer +static IClassFactoryVtbl MsiCF_Vtbl = +{ + MsiCF_QueryInterface, + MsiCF_AddRef, + MsiCF_Release, + MsiCF_CreateInstance, + MsiCF_LockServer }; -static IClassFactoryImpl Msi_CF = {&MsiCF_Vtbl, 1 }; +static IClassFactoryImpl Msi_CF = { &MsiCF_Vtbl }; /****************************************************************** - * DllGetClassObject (MSI.@) + * DllGetClassObject [MSI.@] */ -HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - FIXME("(%s, %s, %p): almost a stub.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); - if (IsEqualCLSID (rclsid, &CLSID_IMsiServer)) { - *ppv = (LPVOID) &Msi_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage)) { - *ppv = (LPVOID) &Msi_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX1)) { - *ppv = (LPVOID) &Msi_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX2)) { - *ppv = (LPVOID) &Msi_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } else if (IsEqualCLSID (rclsid, &CLSID_IMsiServerX3)) { - *ppv = (LPVOID) &Msi_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } - WARN("(%s, %s, %p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); - return CLASS_E_CLASSNOTAVAILABLE; +HRESULT WINAPI MSI_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + + if( IsEqualCLSID (rclsid, &CLSID_IMsiServer) || + IsEqualCLSID (rclsid, &CLSID_IMsiServerMessage) || + IsEqualCLSID (rclsid, &CLSID_IMsiServerX1) || + IsEqualCLSID (rclsid, &CLSID_IMsiServerX2) || + IsEqualCLSID (rclsid, &CLSID_IMsiServerX3) ) + { + *ppv = (LPVOID) &Msi_CF; + return S_OK; + } + return CLASS_E_CLASSNOTAVAILABLE; } /****************************************************************** - * DllGetVersion (MSI.@) + * DllGetVersion [MSI.@] */ HRESULT WINAPI MSI_DllGetVersion(DLLVERSIONINFO *pdvi) { - TRACE("%p\n",pdvi); + TRACE("%p\n",pdvi); - if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) - return E_INVALIDARG; + if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) + return E_INVALIDARG; - pdvi->dwMajorVersion = MSI_MAJORVERSION; - pdvi->dwMinorVersion = MSI_MINORVERSION; - pdvi->dwBuildNumber = MSI_BUILDNUMBER; - pdvi->dwPlatformID = 1; + pdvi->dwMajorVersion = MSI_MAJORVERSION; + pdvi->dwMinorVersion = MSI_MINORVERSION; + pdvi->dwBuildNumber = MSI_BUILDNUMBER; + pdvi->dwPlatformID = 1; - return S_OK; + return S_OK; } /****************************************************************** - * DllCanUnloadNow (MSI.@) + * DllCanUnloadNow [MSI.@] */ BOOL WINAPI MSI_DllCanUnloadNow(void) { - return S_FALSE; + return S_FALSE; } UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, @@ -1634,3 +1683,80 @@ pdwUseCount, pwDateUsed); return ERROR_CALL_NOT_IMPLEMENTED; } + +UINT WINAPI MsiUseFeatureExW(LPCWSTR szProduct, LPCWSTR szFeature, + DWORD dwInstallMode, DWORD dwReserved) +{ + FIXME("%s %s %li %li\n", debugstr_w(szProduct), debugstr_w(szFeature), + dwInstallMode, dwReserved); + + return INSTALLSTATE_LOCAL; +} + +UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, + LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR szProduct, + DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf, + DWORD* pcchPathBuf) +{ + FIXME("%s %s %li %s %li %li %p %p\n", debugstr_w(szComponent), + debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct), + Unused1, Unused2, lpPathBuf, pcchPathBuf); + + return ERROR_INDEX_ABSENT; +} + +USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, LPWSTR lpUserNameBuf, + DWORD* pcchUserNameBuf, LPWSTR lpOrgNameBuf, + DWORD* pcchOrgNameBuf, LPWSTR lpSerialBuf, DWORD* pcchSerialBuf) +{ + FIXME("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf, + pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, + pcchSerialBuf); + + return USERINFOSTATE_UNKNOWN; +} + +USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPSTR lpUserNameBuf, + DWORD* pcchUserNameBuf, LPSTR lpOrgNameBuf, + DWORD* pcchOrgNameBuf, LPSTR lpSerialBuf, DWORD* pcchSerialBuf) +{ + FIXME("%s %p %p %p %p %p %p\n",debugstr_a(szProduct), lpUserNameBuf, + pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, + pcchSerialBuf); + + return USERINFOSTATE_UNKNOWN; +} + +UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct) +{ + FIXME("%s\n",debugstr_w(szProduct)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct) +{ + FIXME("%s\n",debugstr_a(szProduct)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiCreateAndVerifyInstallerDirectory(void) +{ + FIXME("\n"); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget, + LPSTR szProductCode, LPSTR szFeatureId, + LPSTR szComponentCode) +{ + FIXME("\n"); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, + LPWSTR szProductCode, LPWSTR szFeatureId, + LPWSTR szComponentCode) +{ + FIXME("\n"); + return ERROR_CALL_NOT_IMPLEMENTED; +} diff -urN wine-20050111/dlls/msi/msi.rc wine-20050211/dlls/msi/msi.rc --- wine-20050111/dlls/msi/msi.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/msi.rc 2005-02-08 13:12:29.000000000 +0100 @@ -0,0 +1,30 @@ +/* + * Resources for MSI + * + * 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 "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winnls.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#include "version.rc" + +#include "msi_En.rc" diff -urN wine-20050111/dlls/msi/msi.spec wine-20050211/dlls/msi/msi.spec --- wine-20050111/dlls/msi/msi.spec 2005-01-03 17:54:43.000000000 +0100 +++ wine-20050211/dlls/msi/msi.spec 2005-02-10 18:10:14.000000000 +0100 @@ -6,8 +6,8 @@ 6 stdcall MsiAdvertiseProductW(wstr wstr wstr long) 7 stdcall MsiCloseAllHandles() 8 stdcall MsiCloseHandle(long) -9 stub MsiCollectUserInfoA -10 stub MsiCollectUserInfoW +9 stdcall MsiCollectUserInfoA(str) +10 stdcall MsiCollectUserInfoW(wstr) 11 stub MsiConfigureFeatureA 12 stub MsiConfigureFeatureFromDescriptorA 13 stub MsiConfigureFeatureFromDescriptorW @@ -32,7 +32,7 @@ 32 stdcall MsiDatabaseOpenViewW(long wstr ptr) 33 stdcall MsiDoActionA(long str) 34 stdcall MsiDoActionW(long wstr) -35 stub MsiEnableUIPreview +35 stdcall MsiEnableUIPreview(long ptr) 36 stdcall MsiEnumClientsA(str long ptr) 37 stdcall MsiEnumClientsW(wstr long ptr) 38 stdcall MsiEnumComponentQualifiersA(str long str ptr str ptr) @@ -79,7 +79,7 @@ 79 stdcall MsiGetTargetPathA(long str ptr ptr) 80 stdcall MsiGetTargetPathW(long wstr ptr ptr) 81 stub MsiGetUserInfoA -82 stub MsiGetUserInfoW +82 stdcall MsiGetUserInfoW(wstr ptr ptr ptr ptr ptr ptr) 83 stub MsiInstallMissingComponentA 84 stub MsiInstallMissingComponentW 85 stub MsiInstallMissingFileA @@ -94,10 +94,10 @@ 94 stdcall MsiOpenPackageW(wstr ptr) 95 stdcall MsiOpenProductA(str ptr) 96 stdcall MsiOpenProductW(wstr ptr) -97 stub MsiPreviewBillboardA -98 stub MsiPreviewBillboardW -99 stub MsiPreviewDialogA -100 stub MsiPreviewDialogW +97 stdcall MsiPreviewBillboardA(long str str) +98 stdcall MsiPreviewBillboardW(long wstr wstr) +99 stdcall MsiPreviewDialogA(long str) +100 stdcall MsiPreviewDialogW(long wstr) 101 stub MsiProcessAdvertiseScriptA 102 stub MsiProcessAdvertiseScriptW 103 stdcall MsiProcessMessage(long long long) @@ -148,9 +148,9 @@ 148 stdcall MsiSummaryInfoGetPropertyA(long long ptr ptr ptr ptr ptr) 149 stdcall MsiSummaryInfoGetPropertyCount(long ptr) 150 stdcall MsiSummaryInfoGetPropertyW(long long ptr ptr ptr ptr ptr) -151 stub MsiSummaryInfoPersist -152 stub MsiSummaryInfoSetPropertyA -153 stub MsiSummaryInfoSetPropertyW +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 156 stdcall MsiVerifyPackageA(str) @@ -186,21 +186,21 @@ 186 stub MsiCreateTransformSummaryInfoW 187 stub MsiQueryFeatureStateFromDescriptorA 188 stub MsiQueryFeatureStateFromDescriptorW -189 stub MsiConfigureProductExA -190 stub MsiConfigureProductExW +189 stdcall MsiConfigureProductExA(str long long str) +190 stdcall MsiConfigureProductExW(wstr long long wstr) 191 stub MsiInvalidateFeatureCache 192 stub MsiUseFeatureExA -193 stub MsiUseFeatureExW +193 stdcall MsiUseFeatureExW(wstr wstr long long) 194 stdcall MsiGetFileVersionA(str str ptr str ptr) 195 stdcall MsiGetFileVersionW(wstr wstr ptr wstr ptr) 196 stdcall MsiLoadStringA(long long long long long) 197 stdcall MsiLoadStringW(long long long long long) 198 stdcall MsiMessageBoxA(long long long long long long) 199 stdcall MsiMessageBoxW(long long long long long long) -200 stub MsiDecomposeDescriptorA -201 stub MsiDecomposeDescriptorW +200 stdcall MsiDecomposeDescriptorA(str ptr ptr ptr ptr) +201 stdcall MsiDecomposeDescriptorW(wstr ptr ptr ptr ptr) 202 stub MsiProvideQualifiedComponentExA -203 stub MsiProvideQualifiedComponentExW +203 stdcall MsiProvideQualifiedComponentExW(wstr wstr long wstr long long ptr ptr) 204 stdcall MsiEnumRelatedProductsA(str long long ptr) 205 stdcall MsiEnumRelatedProductsW(wstr long long ptr) 206 stub MsiSetFeatureAttributesA @@ -213,13 +213,13 @@ 213 stub MsiSourceListForceResolutionW 214 stub MsiIsProductElevatedA 215 stub MsiIsProductElevatedW -216 stub MsiGetShortcutTargetA -217 stub MsiGetShortcutTargetW +216 stdcall MsiGetShortcutTargetA(str ptr ptr ptr) +217 stdcall MsiGetShortcutTargetW(wstr ptr ptr ptr) 218 stub MsiGetFileHashA 219 stub MsiGetFileHashW 220 stub MsiEnumComponentCostsA 221 stub MsiEnumComponentCostsW -222 stub MsiCreateAndVerifyInstallerDirectory +222 stdcall MsiCreateAndVerifyInstallerDirectory() 223 stdcall MsiGetFileSignatureInformationA(str long ptr ptr ptr) 224 stdcall MsiGetFileSignatureInformationW(wstr long ptr ptr ptr) 225 stdcall MsiProvideAssemblyA(str str long long str ptr) diff -urN wine-20050111/dlls/msi/msi_En.rc wine-20050211/dlls/msi/msi_En.rc --- wine-20050111/dlls/msi/msi_En.rc 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/msi_En.rc 2005-02-08 13:12:29.000000000 +0100 @@ -0,0 +1,33 @@ +/* + * English resources for MSI + * + * 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 + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + 5 "path %s not found" + 9 "insert disk %s" + 10 "bad parameters" + 11 "enter which folder contains %s" + 12 "install source for feature missing" + 13 "network drive for feature missing" + 14 "feature from:" + 15 "choose which folder contains %s" +} diff -urN wine-20050111/dlls/msi/msipriv.h wine-20050211/dlls/msi/msipriv.h --- wine-20050111/dlls/msi/msipriv.h 2005-01-03 15:29:09.000000000 +0100 +++ wine-20050211/dlls/msi/msipriv.h 2005-02-08 14:44:25.000000000 +0100 @@ -1,7 +1,7 @@ /* * Implementation of the Microsoft Installer (msi.dll) * - * Copyright 2002 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 @@ -53,7 +53,7 @@ { UINT magic; UINT type; - UINT refcount; + DWORD refcount; msihandledestructor destructor; struct tagMSIOBJECTHDR *next; struct tagMSIOBJECTHDR *prev; @@ -161,7 +161,7 @@ /* * modify - not yet implemented properly */ - UINT (*modify)( struct tagMSIVIEW *, MSIMODIFY, MSIHANDLE ); + UINT (*modify)( struct tagMSIVIEW *, MSIMODIFY, MSIRECORD * ); /* * delete - destroys the structure completely @@ -182,6 +182,9 @@ MSIVIEWOPS *ops; }; +struct msi_dialog_tag; +typedef struct msi_dialog_tag msi_dialog; + typedef struct tagMSIPACKAGE { MSIOBJECTHDR hdr; @@ -196,14 +199,37 @@ UINT loaded_files; LPWSTR ActionFormat; LPWSTR LastAction; + + LPWSTR *DeferredAction; + UINT DeferredActionCount; + + LPWSTR *CommitAction; + UINT CommitActionCount; + + struct tagMSIRUNNINGACTION *RunningAction; + UINT RunningActionCount; + + LPWSTR PackagePath; + + UINT CurrentInstallState; + msi_dialog *dialog; + LPWSTR next_dialog; } MSIPACKAGE; +typedef struct tagMSIPREVIEW +{ + MSIOBJECTHDR hdr; + MSIPACKAGE *package; + msi_dialog *dialog; +} MSIPREVIEW; + #define MSIHANDLETYPE_ANY 0 #define MSIHANDLETYPE_DATABASE 1 #define MSIHANDLETYPE_SUMMARYINFO 2 #define MSIHANDLETYPE_VIEW 3 #define MSIHANDLETYPE_RECORD 4 #define MSIHANDLETYPE_PACKAGE 5 +#define MSIHANDLETYPE_PREVIEW 6 #define MSI_MAJORVERSION 2 #define MSI_MINORVERSION 0 @@ -212,7 +238,7 @@ #define GUID_SIZE 39 #define MSIHANDLE_MAGIC 0x4d434923 -#define MSIMAXHANDLES 0x80 +#define MSIMAXHANDLES 0xf0 #define MSISUMINFO_OFFSET 0x30LL @@ -271,9 +297,11 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname, USHORT **pdata, UINT *psz ); + +/* action internals */ extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR ); -extern void ACTION_remove_tracked_tempfiles( MSIPACKAGE* ); extern void ACTION_free_package_structures( MSIPACKAGE* ); +extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR); /* record internals */ extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *); @@ -296,6 +324,9 @@ /* database internals */ extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** ); extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** ); +extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... ); +typedef UINT (*record_func)( MSIRECORD *rec, LPVOID param ); +extern UINT MSI_IterateRecords( MSIQUERY *, DWORD *, record_func, LPVOID ); /* view internals */ extern UINT MSI_ViewExecute( MSIQUERY*, MSIRECORD * ); @@ -303,26 +334,51 @@ extern UINT MSI_ViewClose( MSIQUERY* ); /* package internals */ -extern UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE ** ); -extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR); +extern MSIPACKAGE *MSI_CreatePackage( MSIDATABASE * ); +extern UINT MSI_OpenPackageW( LPCWSTR szPackage, MSIPACKAGE ** ); +extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR ); extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR ); -extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD* ); -extern UINT MSI_GetPropertyW( MSIPACKAGE *, LPCWSTR, LPWSTR, DWORD*); +extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD * ); +extern UINT MSI_GetPropertyW( MSIPACKAGE *, LPCWSTR, LPWSTR, DWORD * ); extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR ); extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR ); -extern UINT MSI_GetComponentStateW(MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE *); -extern UINT MSI_GetFeatureStateW(MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE *); +extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * ); +extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * ); +/* for deformating */ +extern UINT MSI_FormatRecordW(MSIPACKAGE* package, MSIRECORD* record, + LPWSTR buffer, DWORD *size); + /* registry data encoding/decoding functions */ -BOOL unsquash_guid(LPCWSTR in, LPWSTR out); -BOOL squash_guid(LPCWSTR in, LPWSTR out); -BOOL encode_base85_guid(GUID *,LPWSTR); -BOOL decode_base85_guid(LPCWSTR,GUID*); +extern BOOL unsquash_guid(LPCWSTR in, LPWSTR out); +extern BOOL squash_guid(LPCWSTR in, LPWSTR out); +extern BOOL encode_base85_guid(GUID *,LPWSTR); +extern BOOL decode_base85_guid(LPCWSTR,GUID*); +extern UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenFeatures(HKEY* key); +extern UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenComponents(HKEY* key); +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); + +/* msi dialog interface */ +typedef VOID (*msi_dialog_event_handler)( MSIPACKAGE*, LPCWSTR, LPCWSTR, msi_dialog* ); +extern msi_dialog *msi_dialog_create( MSIPACKAGE*, LPCWSTR, msi_dialog_event_handler ); +extern UINT msi_dialog_run_message_loop( msi_dialog* ); +extern void msi_dialog_end_dialog( msi_dialog* ); +extern void msi_dialog_check_messages( msi_dialog*, HANDLE ); +extern void msi_dialog_do_preview( msi_dialog* ); +extern void msi_dialog_destroy( msi_dialog* ); +extern void msi_dialog_register_class( void ); +extern void msi_dialog_unregister_class( void ); /* UI globals */ extern INSTALLUILEVEL gUILevel; extern HWND gUIhwnd; -extern INSTALLUI_HANDLERA gUIHandler; +extern INSTALLUI_HANDLERA gUIHandlerA; +extern INSTALLUI_HANDLERW gUIHandlerW; extern DWORD gUIFilter; extern LPVOID gUIContext; extern WCHAR gszLogFile[MAX_PATH]; diff -urN wine-20050111/dlls/msi/msiquery.c wine-20050211/dlls/msi/msiquery.c --- wine-20050111/dlls/msi/msiquery.c 2004-12-10 16:24:52.000000000 +0100 +++ wine-20050211/dlls/msi/msiquery.c 2005-02-08 14:44:25.000000000 +0100 @@ -38,30 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); -#if 0 -typedef struct tagMSIQUERY -{ - MSIOBJECTHDR hdr; - MSIVIEW *view; - UINT row; - MSIDATABASE *db; -} MSIQUERY; -#endif - -UINT WINAPI MsiDatabaseIsTablePersistentA( - MSIHANDLE hDatabase, LPSTR szTableName) -{ - FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName)); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -UINT WINAPI MsiDatabaseIsTablePersistentW( - MSIHANDLE hDatabase, LPWSTR szTableName) -{ - FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName)); - return ERROR_CALL_NOT_IMPLEMENTED; -} - void MSI_CloseView( MSIOBJECTHDR *arg ) { MSIQUERY *query = (MSIQUERY*) arg; @@ -158,6 +134,87 @@ return r; } +UINT MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... ) +{ + LPWSTR szQuery; + LPCWSTR p; + UINT sz, rc; + va_list va; + + /* figure out how much space we need to allocate */ + va_start(va, fmt); + sz = strlenW(fmt) + 1; + p = fmt; + while (*p) + { + p = strchrW(p, '%'); + if (!p) + break; + p++; + switch (*p) + { + case 's': /* a string */ + sz += strlenW(va_arg(va,LPCWSTR)); + break; + case 'd': + case 'i': /* an integer -2147483648 seems to be longest */ + sz += 3*sizeof(int); + (void)va_arg(va,int); + break; + case '%': /* a single % - leave it alone */ + break; + default: + FIXME("Unhandled character type %c\n",*p); + } + p++; + } + va_end(va); + + /* construct the string */ + szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR)); + va_start(va, fmt); + vsnprintfW(szQuery, sz, fmt, va); + va_end(va); + + /* perform the query */ + rc = MSI_DatabaseOpenViewW(db, szQuery, view); + HeapFree(GetProcessHeap(), 0, szQuery); + return rc; +} + +UINT MSI_IterateRecords( MSIQUERY *view, DWORD *count, + record_func func, LPVOID param ) +{ + MSIRECORD *rec = NULL; + UINT r, n = 0, max = 0; + + r = MSI_ViewExecute( view, NULL ); + if( r != ERROR_SUCCESS ) + return r; + + if( count ) + max = *count; + + /* iterate a query */ + for( n = 0; (max == 0) || (n < max); n++ ) + { + r = MSI_ViewFetch( view, &rec ); + if( r != ERROR_SUCCESS ) + break; + r = func( rec, param ); + msiobj_release( &rec->hdr ); + if( r != ERROR_SUCCESS ) + break; + } + + MSI_ViewClose( view ); + + if( count ) + *count = n; + + return r; +} + UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, LPCWSTR szQuery, MSIHANDLE *phView) { @@ -358,7 +415,10 @@ } } + msiobj_lock( &rec->hdr ); ret = MSI_ViewExecute( query, rec ); + msiobj_unlock( &rec->hdr ); + out: if( query ) msiobj_release( &query->hdr ); @@ -370,10 +430,10 @@ UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec) { - MSIVIEW *view; - MSIQUERY *query; - MSIHANDLE handle; - UINT ret, i, count = 0, type; + MSIVIEW *view = NULL; + MSIQUERY *query = NULL; + MSIRECORD *rec = NULL; + UINT r = ERROR_FUNCTION_FAILED, i, count = 0, type; LPWSTR name; TRACE("%ld %d %p\n", hView, info, hRec); @@ -384,34 +444,82 @@ view = query->view; if( !view ) - return ERROR_FUNCTION_FAILED; + goto out; if( !view->ops->get_dimensions ) - return ERROR_FUNCTION_FAILED; + goto out; - ret = view->ops->get_dimensions( view, NULL, &count ); - if( ret ) - return ret; + r = view->ops->get_dimensions( view, NULL, &count ); + if( r ) + goto out; if( !count ) - return ERROR_INVALID_PARAMETER; + { + r = ERROR_INVALID_PARAMETER; + goto out; + } - handle = MsiCreateRecord( count ); - if( !handle ) + rec = MSI_CreateRecord( count ); + if( !rec ) return ERROR_FUNCTION_FAILED; for( i=0; iops->get_column_info( view, i+1, &name, &type ); - if( ret != ERROR_SUCCESS ) + r = view->ops->get_column_info( view, i+1, &name, &type ); + if( r != ERROR_SUCCESS ) continue; - MsiRecordSetStringW( handle, i+1, name ); + MSI_RecordSetStringW( rec, i+1, name ); HeapFree( GetProcessHeap(), 0, name ); } - *hRec = handle; + *hRec = alloc_msihandle( &rec->hdr ); - return ERROR_SUCCESS; +out: + if( query ) + msiobj_release( &query->hdr ); + if( rec ) + msiobj_release( &rec->hdr ); + + return r; +} + +UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode, + MSIHANDLE hRecord) +{ + MSIVIEW *view = NULL; + MSIQUERY *query = NULL; + MSIRECORD *rec = NULL; + UINT r = ERROR_FUNCTION_FAILED; + + TRACE("%ld %x %ld\n", hView, eModifyMode, hRecord); + + query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW ); + if( !query ) + return ERROR_INVALID_HANDLE; + + view = query->view; + if( !view ) + goto out; + + if( !view->ops->modify ) + goto out; + + rec = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); + if( !rec ) + { + r = ERROR_INVALID_HANDLE; + goto out; + } + + r = view->ops->modify( view, eModifyMode, rec ); + +out: + if( query ) + msiobj_release( &query->hdr ); + if( rec ) + msiobj_release( &rec->hdr ); + + return r; } UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, @@ -461,6 +569,8 @@ /* FIXME: unlock the database */ + msiobj_release( &db->hdr ); + return r; } @@ -478,9 +588,16 @@ return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiViewModify(MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE -hRecord) +UINT WINAPI MsiDatabaseIsTablePersistentA( + MSIHANDLE hDatabase, LPSTR szTableName) { - FIXME("%ld %x %ld\n",hView, eModifyMode, hRecord); + FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiDatabaseIsTablePersistentW( + MSIHANDLE hDatabase, LPWSTR szTableName) +{ + FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName)); return ERROR_CALL_NOT_IMPLEMENTED; } diff -urN wine-20050111/dlls/msi/order.c wine-20050211/dlls/msi/order.c --- wine-20050111/dlls/msi/order.c 2004-08-25 19:31:39.000000000 +0200 +++ wine-20050211/dlls/msi/order.c 2005-02-08 14:44:25.000000000 +0100 @@ -187,8 +187,7 @@ if( !ov->table ) return ERROR_FUNCTION_FAILED; - if( ov->reorder ) - HeapFree( GetProcessHeap(), 0, ov->reorder ); + HeapFree( GetProcessHeap(), 0, ov->reorder ); ov->reorder = NULL; return ov->table->ops->close( ov->table ); @@ -219,16 +218,17 @@ return ov->table->ops->get_column_info( ov->table, n, name, type ); } -static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) { MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - TRACE("%p %d %ld\n", ov, eModifyMode, hrec ); + TRACE("%p %d %p\n", ov, eModifyMode, rec ); if( !ov->table ) return ERROR_FUNCTION_FAILED; - return ov->table->ops->modify( ov->table, eModifyMode, hrec ); + return ov->table->ops->modify( ov->table, eModifyMode, rec ); } static UINT ORDER_delete( struct tagMSIVIEW *view ) @@ -240,8 +240,7 @@ if( ov->table ) ov->table->ops->delete( ov->table ); - if( ov->reorder ) - HeapFree( GetProcessHeap(), 0, ov->reorder ); + HeapFree( GetProcessHeap(), 0, ov->reorder ); ov->reorder = NULL; msiobj_release( &ov->db->hdr ); diff -urN wine-20050111/dlls/msi/package.c wine-20050211/dlls/msi/package.c --- wine-20050111/dlls/msi/package.c 2005-01-05 18:11:33.000000000 +0100 +++ wine-20050211/dlls/msi/package.c 2005-02-02 10:55:51.000000000 +0100 @@ -53,36 +53,13 @@ { MSIPACKAGE *package= (MSIPACKAGE*) arg; - ACTION_remove_tracked_tempfiles(package); + if( package->dialog ) + msi_dialog_destroy( package->dialog ); ACTION_free_package_structures(package); msiobj_release( &package->db->hdr ); } -UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) -{ - LPWSTR szwPack = NULL; - UINT len, ret; - - TRACE("%s %p\n",debugstr_a(szPackage), phPackage); - - if( szPackage ) - { - len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 ); - szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); - if( szwPack ) - MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len ); - } - - ret = MsiOpenPackageW( szwPack, phPackage ); - - if( szwPack ) - HeapFree( GetProcessHeap(), 0, szwPack ); - - return ret; -} - - static const UINT clone_properties(MSIDATABASE *db) { MSIQUERY * view = NULL; @@ -102,7 +79,7 @@ '`','_','P','r','o','p','e','r','t','y','`',' ', '(','`','_','P','r','o','p','e','r','t','y','`',',', '`','V','a','l','u','e','`',')',' ', - 'V','A','L','U','E','S',' ','(','?',')',0}; + 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; /* create the temporary properties table */ rc = MSI_DatabaseOpenViewW(db, CreateSql, &view); @@ -377,39 +354,18 @@ ReleaseDC(0, dc); } -UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) +MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) { - UINT rc; - MSIDATABASE *db = NULL; + static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 }; + static const WCHAR szpi[] = {'%','i',0}; MSIPACKAGE *package = NULL; WCHAR uilevel[10]; - UINT ret = ERROR_FUNCTION_FAILED; - - static const WCHAR OriginalDatabase[] = -{'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0}; - static const WCHAR Database[] = -{'D','A','T','A','B','A','S','E',0}; - static const WCHAR szpi[] = {'%','i',0}; - static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 }; - - TRACE("%s %p\n",debugstr_w(szPackage), pPackage); - if (szPackage[0] == '#') - { - INT handle = atoiW(&szPackage[1]); - db = msihandle2msiinfo( handle , MSIHANDLETYPE_DATABASE); - } - else - { - rc = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db); - if (rc != ERROR_SUCCESS) - return ERROR_FUNCTION_FAILED; - } + TRACE("%p\n", db); package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), MSI_FreePackage ); - - if (package) + if( package ) { msiobj_addref( &db->hdr ); @@ -424,35 +380,78 @@ package->loaded_files = 0; package->ActionFormat = NULL; package->LastAction = NULL; + package->dialog = NULL; + package->next_dialog = NULL; /* OK, here is where we do a slew of things to the database to * prep for all that is to come as a package */ clone_properties(db); set_installer_properties(package); - MSI_SetPropertyW(package, OriginalDatabase, szPackage); - MSI_SetPropertyW(package, Database, szPackage); sprintfW(uilevel,szpi,gUILevel); MSI_SetPropertyW(package, szLevel, uilevel); + } + + return package; +} + +UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) +{ + MSIDATABASE *db = NULL; + MSIPACKAGE *package; + MSIHANDLE handle; + + TRACE("%s %p\n", debugstr_w(szPackage), pPackage); - msiobj_addref( &package->hdr ); - *pPackage = package; - ret = ERROR_SUCCESS; + if( szPackage[0] == '#' ) + { + handle = atoiW(&szPackage[1]); + db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); + if( !db ) + return ERROR_INVALID_HANDLE; + } + else + { + UINT r = MSI_OpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db); + if( r != ERROR_SUCCESS ) + return r; } - if( package ) - msiobj_release( &package->hdr ); - if( db ) - msiobj_release( &db->hdr ); + package = MSI_CreatePackage( db ); + msiobj_release( &db->hdr ); + if( !package ) + return ERROR_FUNCTION_FAILED; - return ret; + /* + * FIXME: I don't think this is right. Maybe we should be storing the + * name of the database in the MSIDATABASE structure and fetching this + * info from there, or maybe this is only relevant to cached databases. + */ + if( szPackage[0] != '#' ) + { + static const WCHAR OriginalDatabase[] = + {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0}; + static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0}; + + MSI_SetPropertyW( package, OriginalDatabase, szPackage ); + MSI_SetPropertyW( package, Database, szPackage ); + } + + *pPackage = package; + + return ERROR_SUCCESS; } -UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) +UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) { MSIPACKAGE *package = NULL; UINT ret; + TRACE("%s %08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage); + + if( dwOptions ) + FIXME("dwOptions %08lx not supported\n", dwOptions); + ret = MSI_OpenPackageW( szPackage, &package); if( ret == ERROR_SUCCESS ) { @@ -462,16 +461,34 @@ return ret; } +UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) +{ + return MsiOpenPackageExW( szPackage, 0, phPackage ); +} + UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) { - FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage); - return ERROR_CALL_NOT_IMPLEMENTED; + LPWSTR szwPack = NULL; + UINT len, ret; + + if( szPackage ) + { + len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 ); + szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); + if( szwPack ) + MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len ); + } + + ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); + + HeapFree( GetProcessHeap(), 0, szwPack ); + + return ret; } -UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) +UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) { - FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage); - return ERROR_CALL_NOT_IMPLEMENTED; + return MsiOpenPackageExA( szPackage, 0, phPackage ); } MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) @@ -555,7 +572,7 @@ HeapFree(GetProcessHeap(),0,tmp); } - TRACE("(%p %lx %lx %s)\n",gUIHandler, gUIFilter, log_type, + TRACE("(%p %lx %lx %s)\n",gUIHandlerA, gUIFilter, log_type, debugstr_w(message)); /* convert it to ASCII */ @@ -565,9 +582,9 @@ WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); - if (gUIHandler && (gUIFilter & log_type)) + if (gUIHandlerA && (gUIFilter & log_type)) { - rc = gUIHandler(gUIContext,eMessageType,msg); + rc = gUIHandlerA(gUIContext,eMessageType,msg); } if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) == @@ -649,10 +666,8 @@ hr = MsiSetPropertyW( hInstall, szwName, szwValue); end: - if( szwName ) - HeapFree( GetProcessHeap(), 0, szwName ); - if( szwValue ) - HeapFree( GetProcessHeap(), 0, szwValue ); + HeapFree( GetProcessHeap(), 0, szwName ); + HeapFree( GetProcessHeap(), 0, szwValue ); return hr; } @@ -667,7 +682,7 @@ {'I','N','S','E','R','T',' ','i','n','t','o',' ','`','_','P','r','o','p' ,'e','r','t','y','`',' ','(','`','_','P','r','o','p','e','r','t','y','`' ,',','`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S' -,' ','(','?',')',0}; +,' ','(','?',',','?',')',0}; static const WCHAR Update[]= {'U','P','D','A','T','E',' ','_','P','r','o','p','e' ,'r','t','y',' ','s','e','t',' ','`','V','a','l','u','e','`',' ','=' @@ -848,7 +863,12 @@ return ERROR_INVALID_HANDLE; ret = MSI_GetPropertyA(package, szName, szValueBuf, pchValueBuf ); msiobj_release( &package->hdr ); - return ret; + + /* MsiGetProperty does not return error codes on missing properties */ + if (ret!= ERROR_MORE_DATA) + return ERROR_SUCCESS; + else + return ret; } @@ -870,5 +890,10 @@ return ERROR_INVALID_HANDLE; ret = MSI_GetPropertyW(package, szName, szValueBuf, pchValueBuf ); msiobj_release( &package->hdr ); - return ret; + + /* MsiGetProperty does not return error codes on missing properties */ + if (ret!= ERROR_MORE_DATA) + return ERROR_SUCCESS; + else + return ret; } diff -urN wine-20050111/dlls/msi/preview.c wine-20050211/dlls/msi/preview.c --- wine-20050111/dlls/msi/preview.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/preview.c 2005-02-02 10:55:51.000000000 +0100 @@ -0,0 +1,164 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 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 "winnls.h" +#include "msi.h" +#include "msipriv.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +static void MSI_ClosePreview( MSIOBJECTHDR *arg ) +{ + MSIPREVIEW *preview = (MSIPREVIEW *) arg; + + msiobj_release( &preview->package->hdr ); +} + +MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE *db ) +{ + MSIPREVIEW *preview = NULL; + MSIPACKAGE *package; + + package = MSI_CreatePackage( db ); + if( package ) + { + preview = alloc_msiobject( MSIHANDLETYPE_PREVIEW, sizeof (MSIPREVIEW), + MSI_ClosePreview ); + if( preview ) + { + preview->package = package; + preview->dialog = 0; + msiobj_addref( &package->hdr ); + } + msiobj_release( &package->hdr ); + } + return preview; +} + +UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE* phPreview ) +{ + MSIDATABASE *db; + MSIPREVIEW *preview; + UINT r = ERROR_FUNCTION_FAILED; + + TRACE("%ld %p\n", hdb, phPreview); + + db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE ); + if( !db ) + return ERROR_INVALID_HANDLE; + preview = MSI_EnableUIPreview( db ); + if( preview ) + { + *phPreview = alloc_msihandle( &preview->hdr ); + msiobj_release( &preview->hdr ); + r = ERROR_SUCCESS; + } + + return r; +} + +static VOID preview_event_handler( MSIPACKAGE *package, LPCWSTR event, + LPCWSTR argument, msi_dialog *dialog ) +{ + MESSAGE("Preview dialog event '%s' (arg='%s')\n", + debugstr_w( event ), debugstr_w( argument )); +} + +UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName ) +{ + msi_dialog *dialog = NULL; + UINT r = ERROR_SUCCESS; + + if( preview->dialog ) + msi_dialog_destroy( preview->dialog ); + + /* an empty name means we should just destroy the current preview dialog */ + if( szDialogName ) + { + dialog = msi_dialog_create( preview->package, szDialogName, + preview_event_handler ); + if( dialog ) + msi_dialog_do_preview( dialog ); + else + r = ERROR_FUNCTION_FAILED; + } + preview->dialog = dialog; + + return r; +} + +UINT WINAPI MsiPreviewDialogW( MSIHANDLE hPreview, LPCWSTR szDialogName ) +{ + MSIPREVIEW *preview; + UINT r; + + TRACE("%ld %s\n", hPreview, debugstr_w(szDialogName)); + + preview = msihandle2msiinfo( hPreview, MSIHANDLETYPE_PREVIEW ); + if( !preview ) + return ERROR_INVALID_HANDLE; + + r = MSI_PreviewDialogW( preview, szDialogName ); + + msiobj_release( &preview->hdr ); + + return r; +} + +UINT WINAPI MsiPreviewDialogA( MSIHANDLE hPreview, LPCSTR szDialogName ) +{ + UINT r, len; + LPWSTR strW = NULL; + + TRACE("%ld %s\n", hPreview, debugstr_a(szDialogName)); + + if( szDialogName ) + { + len = MultiByteToWideChar( CP_ACP, 0, szDialogName, -1, NULL, 0 ); + strW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, szDialogName, -1, strW, len ); + } + r = MsiPreviewDialogW( hPreview, strW ); + HeapFree( GetProcessHeap(), 0, strW ); + return r; +} + +UINT WINAPI MsiPreviewBillboardW( MSIHANDLE hPreview, LPCWSTR szControlName, + LPCWSTR szBillboard) +{ + FIXME("%ld %s %s\n", hPreview, debugstr_w(szControlName), + debugstr_w(szBillboard)); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiPreviewBillboardA( MSIHANDLE hPreview, LPCSTR szControlName, + LPCSTR szBillboard) +{ + FIXME("%ld %s %s\n", hPreview, debugstr_a(szControlName), + debugstr_a(szBillboard)); + return ERROR_CALL_NOT_IMPLEMENTED; +} diff -urN wine-20050111/dlls/msi/record.c wine-20050211/dlls/msi/record.c --- wine-20050111/dlls/msi/record.c 2005-01-09 19:24:15.000000000 +0100 +++ wine-20050211/dlls/msi/record.c 2005-01-31 12:30:59.000000000 +0100 @@ -454,12 +454,20 @@ if( iField > rec->count ) return ERROR_INVALID_FIELD; - len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 ); - str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, szValue, -1, str, len ); MSI_FreeField( &rec->fields[iField] ); - rec->fields[iField].type = MSIFIELD_WSTR; - rec->fields[iField].u.szwVal = str; + if( szValue && szValue[0] ) + { + len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 ); + str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, szValue, -1, str, len ); + rec->fields[iField].type = MSIFIELD_WSTR; + rec->fields[iField].u.szwVal = str; + } + else + { + rec->fields[iField].type = MSIFIELD_NULL; + rec->fields[iField].u.szwVal = NULL; + } return 0; } @@ -491,13 +499,22 @@ if( iField > rec->count ) return ERROR_INVALID_FIELD; - len = lstrlenW(szValue) + 1; - str = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR)); - lstrcpyW( str, szValue ); - MSI_FreeField( &rec->fields[iField] ); - rec->fields[iField].type = MSIFIELD_WSTR; - rec->fields[iField].u.szwVal = str; + + if( szValue && szValue[0] ) + { + len = lstrlenW(szValue) + 1; + str = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR)); + lstrcpyW( str, szValue ); + + rec->fields[iField].type = MSIFIELD_WSTR; + rec->fields[iField].u.szwVal = str; + } + else + { + rec->fields[iField].type = MSIFIELD_NULL; + rec->fields[iField].u.szwVal = NULL; + } return 0; } @@ -520,18 +537,6 @@ return ret; } -UINT WINAPI MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, LPSTR szResult, DWORD *sz) -{ - FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szResult, DWORD *sz) -{ - FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); - return ERROR_CALL_NOT_IMPLEMENTED; -} - /* read the data in a file into an IStream */ UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm) { diff -urN wine-20050111/dlls/msi/registry.c wine-20050211/dlls/msi/registry.c --- wine-20050111/dlls/msi/registry.c 1970-01-01 01:00:00.000000000 +0100 +++ wine-20050211/dlls/msi/registry.c 2005-01-26 20:41:13.000000000 +0100 @@ -0,0 +1,486 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2005 Aric Stewart 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 + +#define COBJMACROS +#define NONAMELESSUNION + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winnls.h" +#include "shlwapi.h" +#include "wine/debug.h" +#include "msi.h" +#include "msipriv.h" +#include "wincrypt.h" +#include "wine/unicode.h" +#include "winver.h" +#include "winuser.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + + +/* + * This module will be all the helper functions for registry access by the + * installer bits. + */ +static const WCHAR szUserFeatures_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'I','n','s','t','a','l','l','e','r','\\', +'F','e','a','t','u','r','e','s','\\', +'%','s',0}; + +static const WCHAR szInstaller_Features[] = { +'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','\\', +'F','e','a','t','u','r','e','s',0 }; + +static const WCHAR szInstaller_Features_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','\\', +'F','e','a','t','u','r','e','s','\\', +'%','s',0}; + +static const WCHAR szInstaller_Components[] = { +'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','\\', +'C','o','m','p','o','n','e','n','t','s',0 }; + +static const WCHAR szInstaller_Components_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','\\', +'C','o','m','p','o','n','e','n','t','s','\\', +'%','s',0}; + +static const WCHAR szUninstall_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','\\', +'U','n','i','n','s','t','a','l','l','\\', +'%','s',0 }; + +static const WCHAR szUserProduct_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'I','n','s','t','a','l','l','e','r','\\', +'P','r','o','d','u','c','t','s','\\', +'%','s',0}; + +static const WCHAR szInstaller_Products[] = { +'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','\\', +'P','r','o','d','u','c','t','s',0}; + +static const WCHAR szInstaller_Products_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','\\', +'P','r','o','d','u','c','t','s','\\', +'%','s',0}; + +BOOL unsquash_guid(LPCWSTR in, LPWSTR out) +{ + DWORD i,n=0; + + out[n++]='{'; + for(i=0; i<8; i++) + out[n++] = in[7-i]; + out[n++]='-'; + for(i=0; i<4; i++) + out[n++] = in[11-i]; + out[n++]='-'; + for(i=0; i<4; i++) + out[n++] = in[15-i]; + out[n++]='-'; + for(i=0; i<2; i++) + { + out[n++] = in[17+i*2]; + out[n++] = in[16+i*2]; + } + out[n++]='-'; + for( ; i<8; i++) + { + out[n++] = in[17+i*2]; + out[n++] = in[16+i*2]; + } + out[n++]='}'; + out[n]=0; + return TRUE; +} + +BOOL squash_guid(LPCWSTR in, LPWSTR out) +{ + DWORD i,n=0; + + if(in[n++] != '{') + return FALSE; + for(i=0; i<8; i++) + out[7-i] = in[n++]; + if(in[n++] != '-') + return FALSE; + for(i=0; i<4; i++) + out[11-i] = in[n++]; + if(in[n++] != '-') + return FALSE; + for(i=0; i<4; i++) + out[15-i] = in[n++]; + if(in[n++] != '-') + return FALSE; + for(i=0; i<2; i++) + { + out[17+i*2] = in[n++]; + out[16+i*2] = in[n++]; + } + if(in[n++] != '-') + return FALSE; + for( ; i<8; i++) + { + out[17+i*2] = in[n++]; + out[16+i*2] = in[n++]; + } + out[32]=0; + if(in[n++] != '}') + return FALSE; + if(in[n]) + return FALSE; + return TRUE; +} + + +/* tables for encoding and decoding base85 */ +static const unsigned char table_dec85[0x80] = { +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff, +0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17, +0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, +0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36, +0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46, +0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff, +}; + +static const char table_enc85[] = +"!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO" +"PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx" +"yz{}~"; + +/* + * Converts a base85 encoded guid into a GUID pointer + * Base85 encoded GUIDs should be 20 characters long. + * + * returns TRUE if successful, FALSE if not + */ +BOOL decode_base85_guid( LPCWSTR str, GUID *guid ) +{ + DWORD i, val = 0, base = 1, *p; + + p = (DWORD*) guid; + for( i=0; i<20; i++ ) + { + if( (i%5) == 0 ) + { + val = 0; + base = 1; + } + val += table_dec85[str[i]] * base; + if( str[i] >= 0x80 ) + return FALSE; + if( table_dec85[str[i]] == 0xff ) + return FALSE; + if( (i%5) == 4 ) + p[i/5] = val; + base *= 85; + } + return TRUE; +} + +/* + * Encodes a base85 guid given a GUID pointer + * Caller should provide a 21 character buffer for the encoded string. + * + * returns TRUE if successful, FALSE if not + */ +BOOL encode_base85_guid( GUID *guid, LPWSTR str ) +{ + unsigned int x, *p, i; + + p = (unsigned int*) guid; + for( i=0; i<4; i++ ) + { + x = p[i]; + *str++ = table_enc85[x%85]; + x = x/85; + *str++ = table_enc85[x%85]; + x = x/85; + *str++ = table_enc85[x%85]; + x = x/85; + *str++ = table_enc85[x%85]; + x = x/85; + *str++ = table_enc85[x%85]; + } + *str = 0; + + return TRUE; +} + + +UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR keypath[0x200]; + TRACE("%s\n",debugstr_w(szProduct)); + + sprintfW(keypath,szUninstall_fmt,szProduct); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return rc; +} + +UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szProduct)); + squash_guid(szProduct,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szUserProduct_fmt,squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key); + else + rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key); + + return rc; +} + +UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szProduct)); + squash_guid(szProduct,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szUserFeatures_fmt,squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key); + else + rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key); + + return rc; +} + +UINT MSIREG_OpenFeatures(HKEY* key) +{ + return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Features,key); +} + +UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szProduct)); + squash_guid(szProduct,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szInstaller_Features_fmt,squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key); + + return rc; +} + +UINT MSIREG_OpenComponents(HKEY* key) +{ + return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key); +} + +UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_cc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szComponent)); + squash_guid(szComponent,squished_cc); + TRACE("squished (%s)\n", debugstr_w(squished_cc)); + + sprintfW(keypath,szInstaller_Components_fmt,squished_cc); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key); + + return rc; +} + +UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create) +{ + UINT rc; + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szProduct)); + squash_guid(szProduct,squished_pc); + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szInstaller_Products_fmt,squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key); + + return rc; +} + +/************************************************************************* + * MsiDecomposeDescriptorW [MSI.@] + * + * Decomposes an MSI descriptor into product, feature and component parts. + * An MSI descriptor is a string of the form: + * [base 85 guid] [feature code] '>' [base 85 guid] + * + * PARAMS + * szDescriptor [I] the descriptor to decompose + * szProduct [O] buffer of MAX_FEATURE_CHARS for the product guid + * szFeature [O] buffer of MAX_FEATURE_CHARS for the feature code + * szComponent [O] buffer of MAX_FEATURE_CHARS for the component guid + * pUsed [O] the length of the descriptor + * + * RETURNS + * ERROR_SUCCESS if everything worked correctly + * ERROR_INVALID_PARAMETER if the descriptor was invalid + * + */ +UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct, + LPWSTR szFeature, LPWSTR szComponent, DWORD *pUsed ) +{ + UINT r, len; + LPWSTR p; + GUID product, component; + + TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct, + szFeature, szComponent, pUsed); + + r = decode_base85_guid( szDescriptor, &product ); + if( !r ) + return ERROR_INVALID_PARAMETER; + + TRACE("product %s\n", debugstr_guid( &product )); + + p = strchrW(&szDescriptor[20],'>'); + if( !p ) + return ERROR_INVALID_PARAMETER; + + len = (p - &szDescriptor[20]); + if( len > MAX_FEATURE_CHARS ) + return ERROR_INVALID_PARAMETER; + memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) ); + szFeature[len] = 0; + + TRACE("feature %s\n", debugstr_w( szFeature )); + + r = decode_base85_guid( p+1, &component ); + if( !r ) + return ERROR_INVALID_PARAMETER; + + TRACE("component %s\n", debugstr_guid( &component )); + + StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 ); + StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 ); + len = ( &p[21] - szDescriptor ); + + TRACE("length = %d\n", len); + *pUsed = len; + + return ERROR_SUCCESS; +} + +UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct, + LPSTR szFeature, LPSTR szComponent, DWORD *pUsed ) +{ + WCHAR product[MAX_FEATURE_CHARS+1]; + WCHAR feature[MAX_FEATURE_CHARS+1]; + WCHAR component[MAX_FEATURE_CHARS+1]; + LPWSTR str = NULL; + UINT r, len; + + TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct, + szFeature, szComponent, pUsed); + + if( szDescriptor ) + { + len = MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, NULL, 0 ); + str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, str, len ); + } + + r = MsiDecomposeDescriptorW( str, product, feature, component, pUsed ); + + WideCharToMultiByte( CP_ACP, 0, product, MAX_FEATURE_CHARS+1, + szProduct, MAX_FEATURE_CHARS+1, NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, feature, MAX_FEATURE_CHARS+1, + szFeature, MAX_FEATURE_CHARS+1, NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, component, MAX_FEATURE_CHARS+1, + szComponent, MAX_FEATURE_CHARS+1, NULL, NULL ); + + HeapFree( GetProcessHeap(), 0, str ); + + return r; +} diff -urN wine-20050111/dlls/msi/select.c wine-20050211/dlls/msi/select.c --- wine-20050111/dlls/msi/select.c 2004-07-10 00:25:34.000000000 +0200 +++ wine-20050211/dlls/msi/select.c 2005-02-08 14:44:25.000000000 +0100 @@ -168,16 +168,17 @@ return sv->table->ops->get_column_info( sv->table, n, name, type ); } -static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) { MSISELECTVIEW *sv = (MSISELECTVIEW*)view; - TRACE("%p %d %ld\n", sv, eModifyMode, hrec ); + TRACE("%p %d %p\n", sv, eModifyMode, rec ); if( !sv->table ) return ERROR_FUNCTION_FAILED; - return sv->table->ops->modify( sv->table, eModifyMode, hrec ); + return sv->table->ops->modify( sv->table, eModifyMode, rec ); } static UINT SELECT_delete( struct tagMSIVIEW *view ) diff -urN wine-20050111/dlls/msi/sql.y wine-20050211/dlls/msi/sql.y --- wine-20050111/dlls/msi/sql.y 2004-12-16 15:33:56.000000000 +0100 +++ wine-20050211/dlls/msi/sql.y 2005-01-20 21:39:15.000000000 +0100 @@ -499,18 +499,17 @@ } $$ = vals; } - | constlist TK_COMMA const_val + | const_val TK_COMMA constlist { value_list *vals; vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); if( vals ) { - vals->val = $3; - vals->next = NULL; + vals->val = $1; + vals->next = $3; } - $1->next = vals; - $$ = $1; + $$ = vals; } ; diff -urN wine-20050111/dlls/msi/string.c wine-20050211/dlls/msi/string.c --- wine-20050111/dlls/msi/string.c 2004-08-06 19:30:20.000000000 +0200 +++ wine-20050211/dlls/msi/string.c 2005-01-20 11:36:35.000000000 +0100 @@ -393,8 +393,7 @@ MultiByteToWideChar( st->codepage, 0, buffer, -1, str, sz ); r = msi_string2idW( st, str, id ); - if( str ) - HeapFree( GetProcessHeap(), 0, str ); + HeapFree( GetProcessHeap(), 0, str ); return r; } diff -urN wine-20050111/dlls/msi/suminfo.c wine-20050211/dlls/msi/suminfo.c --- wine-20050111/dlls/msi/suminfo.c 2004-10-07 05:06:50.000000000 +0200 +++ wine-20050211/dlls/msi/suminfo.c 2005-02-01 15:21:03.000000000 +0100 @@ -65,8 +65,7 @@ ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, phSummaryInfo); - if( szwDatabase ) - HeapFree( GetProcessHeap(), 0, szwDatabase ); + HeapFree( GetProcessHeap(), 0, szwDatabase ); return ret; } @@ -223,9 +222,72 @@ MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue, FILETIME *pftValue, LPWSTR szValueBuf, DWORD *pcchValueBuf) { - FIXME("%ld %d %p %p %p %p %p\n", + MSISUMMARYINFO *suminfo; + HRESULT r; + PROPSPEC spec; + PROPVARIANT var; + + TRACE("%ld %d %p %p %p %p %p\n", hSummaryInfo, uiProperty, puiDataType, piValue, pftValue, szValueBuf, pcchValueBuf); - + + suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); + if( !suminfo ) + return ERROR_INVALID_HANDLE; + + spec.ulKind = PRSPEC_PROPID; + spec.u.propid = uiProperty; + + r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); + if( FAILED(r) ) + return ERROR_FUNCTION_FAILED; + + if( puiDataType ) + *puiDataType = var.vt; + + switch( var.vt ) + { + case VT_I4: + if( piValue ) + *piValue = var.u.lVal; + break; + case VT_LPSTR: + if( pcchValueBuf && szValueBuf ) + { + MultiByteToWideChar(CP_ACP, 0, var.u.pszVal, -1, szValueBuf, + *pcchValueBuf ); + *pcchValueBuf = lstrlenA( var.u.pszVal ); + } + break; + case VT_FILETIME: + if( pftValue ) + memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) ); + break; + case VT_EMPTY: + break; + default: + FIXME("Unknown property variant type\n"); + break; + } + + return ERROR_SUCCESS; +} + +UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, + UINT uiDataType, INT iValue, + FILETIME* pftValue, LPSTR szValue) +{ + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE hSummaryInfo, UINT uiProperty, + UINT uiDataType, INT iValue, + FILETIME* pftValue, LPWSTR szValue) +{ + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE hSummaryInfo) +{ return ERROR_CALL_NOT_IMPLEMENTED; } diff -urN wine-20050111/dlls/msi/table.c wine-20050211/dlls/msi/table.c --- wine-20050111/dlls/msi/table.c 2004-12-22 16:22:12.000000000 +0100 +++ wine-20050211/dlls/msi/table.c 2005-02-10 20:19:36.000000000 +0100 @@ -196,8 +196,8 @@ if( FAILED( r ) || !count ) break; decode_streamname( stat.pwcsName, name ); - ERR("stream %2ld -> %s %s\n", n, - debugstr_w(stat.pwcsName), debugstr_w(name) ); + TRACE("stream %2ld -> %s %s\n", n, + debugstr_w(stat.pwcsName), debugstr_w(name) ); n++; } @@ -356,12 +356,12 @@ encname = encode_streamname(TRUE, stname ); r = IStorage_OpenStream( stg, encname, NULL, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &stm); - HeapFree( GetProcessHeap(), 0, encname ); if( FAILED(r) ) { r = IStorage_CreateStream( stg, encname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); } + HeapFree( GetProcessHeap(), 0, encname ); if( FAILED( r ) ) { ERR("open stream failed r = %08lx\n",r); @@ -408,7 +408,7 @@ TRACE("%s\n",debugstr_w(name)); - /* non-existing tables should be interpretted as empty tables */ + /* nonexistent tables should be interpreted as empty tables */ t = HeapAlloc( GetProcessHeap(), 0, sizeof (MSITABLE) + lstrlenW(name)*sizeof (WCHAR) ); if( !t ) @@ -747,10 +747,8 @@ ret = ERROR_SUCCESS; end: - if( pool ) - HeapFree( GetProcessHeap(), 0, pool ); - if( data ) - HeapFree( GetProcessHeap(), 0, data ); + HeapFree( GetProcessHeap(), 0, pool ); + HeapFree( GetProcessHeap(), 0, data ); return ret; } @@ -830,10 +828,8 @@ ret = ERROR_SUCCESS; err: - if( data ) - HeapFree( GetProcessHeap(), 0, data ); - if( pool ) - HeapFree( GetProcessHeap(), 0, pool ); + HeapFree( GetProcessHeap(), 0, data ); + HeapFree( GetProcessHeap(), 0, pool ); return ret; } @@ -1288,9 +1284,10 @@ return ERROR_SUCCESS; } -static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec) { - FIXME("%p %d %ld\n", view, eModifyMode, hrec ); + FIXME("%p %d %p\n", view, eModifyMode, rec ); return ERROR_CALL_NOT_IMPLEMENTED; } diff -urN wine-20050111/dlls/msi/tests/db.c wine-20050211/dlls/msi/tests/db.c --- wine-20050111/dlls/msi/tests/db.c 2005-01-10 14:29:25.000000000 +0100 +++ wine-20050211/dlls/msi/tests/db.c 2005-01-27 11:43:27.000000000 +0100 @@ -24,7 +24,7 @@ #include "wine/test.h" -START_TEST(db) +static void test_msidatabase(void) { MSIHANDLE hdb = 0; CHAR szName[] = "C:\\mytest.msi"; @@ -42,3 +42,317 @@ res = MsiCloseHandle( hdb ); ok( res == ERROR_SUCCESS , "Failed to close database" ); } + +void test_msiinsert(void) +{ + const char *msifile = "winetest.msi"; + MSIHANDLE hdb = 0, hview = 0, hrec = 0; + UINT r; + char *query, buf[80]; + DWORD sz; + + DeleteFile(msifile); + + /* just MsiOpenDatabase should not create a file */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); + + /* create a table */ + query = "CREATE TABLE `phone` ( " + "`id` INT, `name` CHAR(32), `number` CHAR(32) " + "PRIMARY KEY `id`)"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + /* insert a value into it */ + query = "INSERT INTO `phone` ( `id`, `name`, `number` )" + "VALUES('1', 'Abe', '8675309')"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + query = "SELECT * FROM `phone`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + /* check the record contains what we put in it */ + r = MsiRecordGetFieldCount(hrec); + ok(r == 3, "record count wrong\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 1, "field 1 contents wrong\n"); + sz = sizeof buf; + r = MsiRecordGetString(hrec, 2, buf, &sz); + ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n"); + ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n"); + sz = sizeof buf; + r = MsiRecordGetString(hrec, 3, buf, &sz); + ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n"); + ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n"); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + r = MsiDatabaseCommit(hdb); + ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); + + r = MsiCloseHandle(hdb); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + r = DeleteFile(msifile); + ok(r == TRUE, "file didn't exist after commit\n"); +} + +typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *); +fnMsiDecomposeDescriptorA MsiDecomposeDescriptorA; + +void test_msidecomposedesc(void) +{ + char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1]; + char *desc; + UINT r; + DWORD len; + HMODULE hmod; + + hmod = GetModuleHandle("msi.dll"); + if (!hmod) + return; + MsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA) + GetProcAddress(hmod, "MsiDecomposeDescriptorA"); + if (!MsiDecomposeDescriptorA) + return; + + /* test a valid feature descriptor */ + desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk."; + len = 0; + r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len); + ok(r == ERROR_SUCCESS, "returned an error\n"); + ok(len == strlen(desc), "length was wrong\n"); + ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n"); + ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n"); + ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n"); + + /* test an invalid feature descriptor with too many characters */ + desc = "']gAVn-}f(ZXfeAR6.ji" + "ThisWillFailIfTheresMoreThanAGuidsChars>" + "3w2x^IGfe?CxI5heAvk."; + len = 0; + r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len); + ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n"); + + /* + * Test a valid feature descriptor with the + * maximum number of characters and some trailing characters. + */ + desc = "']gAVn-}f(ZXfeAR6.ji" + "ThisWillWorkIfTheresLTEThanAGuidsChars>" + "3w2x^IGfe?CxI5heAvk." + "extra"; + len = 0; + r = MsiDecomposeDescriptorA(desc, prod, feature, comp, &len); + ok(r == ERROR_SUCCESS, "returned wrong error\n"); + ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); +} + +static UINT try_query_param( MSIHANDLE hdb, LPSTR szQuery, MSIHANDLE hrec ) +{ + MSIHANDLE htab = 0; + UINT res; + + res = MsiDatabaseOpenView( hdb, szQuery, &htab ); + if(res == ERROR_SUCCESS ) + { + UINT r; + + r = MsiViewExecute( htab, hrec ); + if(r != ERROR_SUCCESS ) + res = r; + + r = MsiViewClose( htab ); + if(r != ERROR_SUCCESS ) + res = r; + + r = MsiCloseHandle( htab ); + if(r != ERROR_SUCCESS ) + res = r; + } + return res; +} + +static UINT try_query( MSIHANDLE hdb, LPSTR szQuery ) +{ + return try_query_param( hdb, szQuery, 0 ); +} + +static UINT try_insert_query( MSIHANDLE hdb, LPSTR szQuery ) +{ + MSIHANDLE hrec = 0; + UINT r; + + hrec = MsiCreateRecord( 1 ); + MsiRecordSetString( hrec, 1, "Hello"); + + r = try_query_param( hdb, szQuery, hrec ); + + MsiCloseHandle( hrec ); + return r; +} + +void test_msibadqueries() +{ + const char *msifile = "winetest.msi"; + MSIHANDLE hdb = 0; + UINT r; + + DeleteFile(msifile); + + /* just MsiOpenDatabase should not create a file */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); + + r = MsiDatabaseCommit( hdb ); + ok(r == ERROR_SUCCESS , "Failed to commit database\n"); + + r = MsiCloseHandle( hdb ); + ok(r == ERROR_SUCCESS , "Failed to close database\n"); + + /* open it readonly */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb ); + ok(r == ERROR_SUCCESS , "Failed to open database r/o\n"); + + /* add a table to it */ + r = try_query( hdb, "select * from _Tables"); + ok(r == ERROR_SUCCESS , "query 1 failed\n"); + + r = MsiCloseHandle( hdb ); + ok(r == ERROR_SUCCESS , "Failed to close database r/o\n"); + + /* open it read/write */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb ); + ok(r == ERROR_SUCCESS , "Failed to open database r/w\n"); + + /* a bunch of test queries that fail with the native MSI */ + + r = try_query( hdb, "CREATE TABLE"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n"); + + r = try_query( hdb, "CREATE TABLE `a`"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` ()"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n"); + + todo_wine { + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n"); + } + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); + + r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); + + todo_wine { + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_SUCCESS , "valid query 2z failed\n"); + } + + r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n"); + + r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` " + "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)"); + ok(r == ERROR_SUCCESS , "query 4 failed\n"); + + r = MsiDatabaseCommit( hdb ); + ok(r == ERROR_SUCCESS , "Failed to commit database after write"); + + r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL " + "PRIMARY KEY `foo`)"); + ok(r == ERROR_SUCCESS , "query 4 failed\n"); + + r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )"); + ok(r == ERROR_SUCCESS , "failed to insert record in db\n"); + + r = MsiDatabaseCommit( hdb ); + ok(r == ERROR_SUCCESS , "Failed to commit database after write"); + + r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL " + "PRIMARY KEY `ba`)"); + ok(r != ERROR_SUCCESS , "query 5 succeeded\n"); + + r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )"); + ok(r != ERROR_SUCCESS , "query 6 succeeded\n"); + + r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL " + "PRIMARY KEY `t`)"); + ok(r == ERROR_SUCCESS , "query 7 failed\n"); + + r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)"); + ok(r == ERROR_SUCCESS , "query 8 failed\n"); + + r = MsiCloseHandle( hdb ); + ok(r == ERROR_SUCCESS , "Failed to close database transact\n"); + + r = DeleteFile( msifile ); + ok(r == TRUE, "file didn't exist after commit\n"); +} + +START_TEST(db) +{ + test_msidatabase(); + test_msiinsert(); + test_msidecomposedesc(); + test_msibadqueries(); +} diff -urN wine-20050111/dlls/msi/tests/record.c wine-20050211/dlls/msi/tests/record.c --- wine-20050111/dlls/msi/tests/record.c 2005-01-10 14:29:24.000000000 +0100 +++ wine-20050211/dlls/msi/tests/record.c 2005-01-31 12:30:59.000000000 +0100 @@ -119,6 +119,14 @@ ok(r == 1, "failed to get integer\n"); /* same record, but add a string to it */ + r = MsiRecordSetString(h, 0, NULL); + ok(r == ERROR_SUCCESS, "Failed to set null string at 0\n"); + r = MsiRecordIsNull(h, 0); + ok(r == TRUE, "null string not null field\n"); + r = MsiRecordSetString(h, 0, ""); + ok(r == ERROR_SUCCESS, "Failed to set empty string at 0\n"); + r = MsiRecordIsNull(h, 0); + ok(r == TRUE, "null string not null field\n"); r = MsiRecordSetString(h,0,str); ok(r == ERROR_SUCCESS, "Failed to set string at 0\n"); r = MsiRecordGetInteger(h, 0); diff -urN wine-20050111/dlls/msi/update.c wine-20050211/dlls/msi/update.c --- wine-20050111/dlls/msi/update.c 2004-08-25 19:31:39.000000000 +0200 +++ wine-20050211/dlls/msi/update.c 2005-02-08 14:44:25.000000000 +0100 @@ -151,11 +151,12 @@ return wv->ops->get_column_info( wv, n, name, type ); } -static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) { MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; - TRACE("%p %d %ld\n", uv, eModifyMode, hrec ); + TRACE("%p %d %p\n", uv, eModifyMode, rec ); return ERROR_FUNCTION_FAILED; } diff -urN wine-20050111/dlls/msi/where.c wine-20050211/dlls/msi/where.c --- wine-20050111/dlls/msi/where.c 2004-12-22 16:22:12.000000000 +0100 +++ wine-20050211/dlls/msi/where.c 2005-02-08 14:44:25.000000000 +0100 @@ -269,8 +269,7 @@ if( !wv->table ) return ERROR_FUNCTION_FAILED; - if( wv->reorder ) - HeapFree( GetProcessHeap(), 0, wv->reorder ); + HeapFree( GetProcessHeap(), 0, wv->reorder ); wv->reorder = NULL; return wv->table->ops->close( wv->table ); @@ -308,16 +307,17 @@ return wv->table->ops->get_column_info( wv->table, n, name, type ); } -static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec) +static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, + MSIRECORD *rec ) { MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; - TRACE("%p %d %ld\n", wv, eModifyMode, hrec ); + TRACE("%p %d %p\n", wv, eModifyMode, rec ); if( !wv->table ) return ERROR_FUNCTION_FAILED; - return wv->table->ops->modify( wv->table, eModifyMode, hrec ); + return wv->table->ops->modify( wv->table, eModifyMode, rec ); } static UINT WHERE_delete( struct tagMSIVIEW *view ) @@ -329,8 +329,7 @@ if( wv->table ) wv->table->ops->delete( wv->table ); - if( wv->reorder ) - HeapFree( GetProcessHeap(), 0, wv->reorder ); + HeapFree( GetProcessHeap(), 0, wv->reorder ); wv->reorder = NULL; wv->row_count = 0; diff -urN wine-20050111/dlls/msrle32/msrle32.c wine-20050211/dlls/msrle32/msrle32.c --- wine-20050111/dlls/msrle32/msrle32.c 2005-01-09 17:52:51.000000000 +0100 +++ wine-20050211/dlls/msrle32/msrle32.c 2005-02-10 20:19:36.000000000 +0100 @@ -157,7 +157,7 @@ if (DIBWIDTHBYTES(*lpbi) * (DWORD)lpbi->biHeight >= (1UL << 31) - 1) return FALSE; /* image too big ! */ - /* check for non-existent colortable for hi- and true-color DIB's */ + /* check for nonexistent colortable for hi- and true-color DIB's */ if (lpbi->biBitCount >= 15 && lpbi->biClrUsed > 0) return FALSE; diff -urN wine-20050111/dlls/msvcrt/environ.c wine-20050211/dlls/msvcrt/environ.c --- wine-20050111/dlls/msvcrt/environ.c 2004-07-19 23:23:02.000000000 +0200 +++ wine-20050211/dlls/msvcrt/environ.c 2005-02-10 20:19:36.000000000 +0100 @@ -93,7 +93,7 @@ ret = SetEnvironmentVariableA(name, value[0] ? value : NULL) ? 0 : -1; - /* _putenv returns success on deletion of non-existent variable, unlike [Rtl]SetEnvironmentVariable */ + /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */ if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0; /* Update the __p__environ array only when already initialized */ @@ -129,7 +129,7 @@ ret = SetEnvironmentVariableW(name, value[0] ? value : NULL) ? 0 : -1; - /* _putenv returns success on deletion of non-existent variable, unlike [Rtl]SetEnvironmentVariable */ + /* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */ if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0; /* Update the __p__environ array only when already initialized */ diff -urN wine-20050111/dlls/msvcrt/scanf.h wine-20050211/dlls/msvcrt/scanf.h --- wine-20050111/dlls/msvcrt/scanf.h 2004-08-23 20:52:54.000000000 +0200 +++ wine-20050211/dlls/msvcrt/scanf.h 2005-01-28 12:27:26.000000000 +0100 @@ -401,21 +401,25 @@ else goto widecharacter; #endif /* WIDE_SCANF */ character: { /* read single character into char */ - if (!suppress) { - char*c = va_arg(ap, char*); - *c = _CHAR2SUPPORTED_(nch); - } - st = 1; - nch = _GETC_(file); - } + if (nch!=_EOF_) { + if (!suppress) { + char*c = va_arg(ap, char*); + *c = _CHAR2SUPPORTED_(nch); + } + st = 1; + nch = _GETC_(file); + } + } break; - widecharacter: { - if (!suppress) { /* read single character into a wchar_t */ - MSVCRT_wchar_t*c = va_arg(ap, MSVCRT_wchar_t*); - *c = _WIDE2SUPPORTED_(nch); - } - nch = _GETC_(file); - st = 1; + widecharacter: { /* read single character into a wchar_t */ + if (nch!=_EOF_) { + if (!suppress) { + MSVCRT_wchar_t*c = va_arg(ap, MSVCRT_wchar_t*); +