diff --git a/base/applications/paint/paint.exe.amd64.manifest b/base/applications/paint/paint.exe.amd64.manifest new file mode 100644 index 00000000000..1e96c9cb961 --- /dev/null +++ b/base/applications/paint/paint.exe.amd64.manifest @@ -0,0 +1,23 @@ + + + +Paint + + + + + + diff --git a/base/applications/paint/rsrc.rc b/base/applications/paint/rsrc.rc index 49b981acd2f..a1e776d6720 100644 --- a/base/applications/paint/rsrc.rc +++ b/base/applications/paint/rsrc.rc @@ -42,4 +42,9 @@ // THIS WILL MAKE THE PROGRAM USE THE COMMON CONTROLS // LIBRARY VERSION 6.0 (IF IT IS AVAILABLE) // +#ifdef _AMD64_ +1 24 "paint.exe.amd64.manifest" +#elif _X86_ 1 24 "paint.exe.manifest" +#endif + diff --git a/base/applications/rapps/rapps/firefox3.txt b/base/applications/rapps/rapps/firefox3.txt index 072eee6407b..e6051802e00 100644 --- a/base/applications/rapps/rapps/firefox3.txt +++ b/base/applications/rapps/rapps/firefox3.txt @@ -2,10 +2,10 @@ [Section] Name = Mozilla Firefox 3.0 -Version = 3.0.17 +Version = 3.0.18 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Web Browsers out there. -Size = 7.1M +Size = 7.2M Category = 5 URLSite = http://www.mozilla.com/en-US/ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/en-US/Firefox%20Setup%203.0.18.exe @@ -13,7 +13,7 @@ CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Webbrowser. -Size = 6.9M +Size = 7.0M URLSite = http://www.mozilla-europe.org/de/ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest-3.0/win32/de/Firefox%20Setup%203.0.18.exe diff --git a/base/applications/rapps/rapps/mirandaim.txt b/base/applications/rapps/rapps/mirandaim.txt index 5b817e16f37..0fff6a4ea04 100644 --- a/base/applications/rapps/rapps/mirandaim.txt +++ b/base/applications/rapps/rapps/mirandaim.txt @@ -2,13 +2,13 @@ [Section] Name = Miranda IM -Version = 0.8.13 +Version = 0.8.18 Licence = GPL Description = Open source multiprotocol instant messaging application - May not work completely. Size = 1.6MB Category = 5 URLSite = http://www.miranda-im.org/ -URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.8.13-unicode.exe +URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.8.18-unicode.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/openttd.txt b/base/applications/rapps/rapps/openttd.txt index 6220e8ada93..dfc94a95e43 100644 --- a/base/applications/rapps/rapps/openttd.txt +++ b/base/applications/rapps/rapps/openttd.txt @@ -2,13 +2,13 @@ [Section] Name = OpenTTD -Version = 0.7.3 +Version = 0.7.5 Licence = GPL v2 Description = Open Source clone of the "Transport Tycoon Deluxe" game engine. You need a copy of Transport Tycoon. Size = 2.9MB Category = 4 URLSite = http://www.openttd.org/ -URLDownload = http://ovh.dl.sourceforge.net/sourceforge/openttd/openttd-0.7.3-windows-win32.exe +URLDownload = http://binaries.openttd.org/releases/0.7.5/openttd-0.7.5-windows-win32.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/opera.txt b/base/applications/rapps/rapps/opera.txt index 148e79bc9e4..44e49cc61ac 100644 --- a/base/applications/rapps/rapps/opera.txt +++ b/base/applications/rapps/rapps/opera.txt @@ -2,13 +2,13 @@ [Section] Name = Opera -Version = 10.10 +Version = 10.51 Licence = Freeware Description = The popular Opera Browser with many advanced features and including a Mail and BitTorrent client. Size = 11.0M Category = 5 URLSite = http://www.opera.com/ -URLDownload = http://ftp.opera.com/pub/opera/win/1010/int/Opera_1010_in_Setup.exe +URLDownload = http://get4.opera.com/pub/opera/win/1051/int/Opera_1051_int_Setup.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/sambatng.txt b/base/applications/rapps/rapps/sambatng.txt index 4377863c7ac..6cf579a9372 100644 --- a/base/applications/rapps/rapps/sambatng.txt +++ b/base/applications/rapps/rapps/sambatng.txt @@ -2,10 +2,10 @@ [Section] Name = Samba TNG -Version = 0.4.99cvs +Version = 0.5-RC1 Licence = GPL Description = This tool allows you to access your Windows shared folders/printers with ReactOS. -Size = 1MB +Size = 2.1MB Category = 5 URLSite = http://samba-tng.org/ URLDownload = http://svn.reactos.org/packages/samba-tng.exe diff --git a/base/applications/rapps/rapps/seamonkey.txt b/base/applications/rapps/rapps/seamonkey.txt index 69a43d51e90..9c980d30b65 100644 --- a/base/applications/rapps/rapps/seamonkey.txt +++ b/base/applications/rapps/rapps/seamonkey.txt @@ -2,31 +2,31 @@ [Section] Name = Mozilla SeaMonkey -Version = 2.0.2 +Version = 2.0.3 Licence = MPL/GPL/LGPL Description = Mozilla Suite is alive. This is the one and only Browser, Mail, Chat, and Composer bundle you will ever need. -Size = 10.1MB +Size = 10.0MB Category = 5 URLSite = http://www.seamonkey-project.org/ -URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.2/win32/en-US/SeaMonkey%20Setup%202.0.2.exe +URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.3/win32/en-US/SeaMonkey%20Setup%202.0.3.exe CDPath = none [Section.0407] Description = Mozilla Suite lebt. Dies ist das einzige Browser-, Mail-, Chat- and Composerwerkzeug-Bundle welches Sie benötigen. -Size = 10.0MB -URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.2/win32/de/SeaMonkey%20Setup%202.0.2.exe +Size = 10.1MB +URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.3/win32/de/SeaMonkey%20Setup%202.0.3.exe [Section.040a] Description = La suite de Mozilla está viva. Es el primero y único navegador web, gestor de correo, lector de noticias, Chat y editor HTML que necesitarás. Size = 10.0MB -URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.2/win32/es-ES/SeaMonkey%20Setup%202.0.2.exe +URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.3/win32/es-ES/SeaMonkey%20Setup%202.0.3.exe [Section.0415] Description = Pakiet Mozilla żyje. W zestawie: przeglądarka, klient poczty, IRC oraz Edytor HTML - wszystko, czego potrzebujesz. Size = 10.8MB -URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.2/win32/pl/SeaMonkey%20Setup%202.0.2.exe +URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.3/win32/pl/SeaMonkey%20Setup%202.0.3.exe [Section.0419] Description = Продолжение Mozilla Suite. Включает браузер, почтовый клиент, IRC-клиент и HTML-редактор. Size = 10.4MB -URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.2/win32/ru/SeaMonkey%20Setup%202.0.2.exe +URLDownload = http://ftp.df.lth.se/mozilla/seamonkey/releases/2.0.3/win32/ru/SeaMonkey%20Setup%202.0.3.exe diff --git a/base/applications/rapps/rapps/smplayer.txt b/base/applications/rapps/rapps/smplayer.txt index b3071703a1e..a2e47d3acff 100644 --- a/base/applications/rapps/rapps/smplayer.txt +++ b/base/applications/rapps/rapps/smplayer.txt @@ -2,13 +2,13 @@ [Section] Name = SMPlayer -Version = 0.6.8 +Version = 0.6.9 Licence = GPL Description = SMPlayer. -Size = 13.38MB +Size = 14.2MB Category = 1 URLSite = http://smplayer.sourceforge.net/ -URLDownload = http://downloads.sourceforge.net/project/smplayer/SMPlayer/0.6.8/smplayer-0.6.8-win32.exe +URLDownload = http://downloads.sourceforge.net/project/smplayer/SMPlayer/0.6.9/smplayer-0.6.9-win32.exe CDPath = none [Section.0407] diff --git a/base/applications/rapps/rapps/thunderbird.txt b/base/applications/rapps/rapps/thunderbird.txt index ca8fd86bdf9..9f0cd328d89 100644 --- a/base/applications/rapps/rapps/thunderbird.txt +++ b/base/applications/rapps/rapps/thunderbird.txt @@ -2,35 +2,35 @@ [Section] Name = Mozilla Thunderbird -Version = 3.0.1 +Version = 3.0.3 Licence = MPL/GPL/LGPL Description = The most popular and one of the best free Mail Clients out there. Size = 8.6M Category = 5 URLSite = http://www.mozilla-europe.org/en/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.1/win32/en-US/Thunderbird%20Setup%203.0.1.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.3/win32/en-US/Thunderbird%20Setup%203.0.3.exe CDPath = none [Section.0407] Description = Der populärste und einer der besten freien Mail-Clients. Size = 8.4M URLSite = http://www.mozilla-europe.org/de/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.1/win32/de/Thunderbird%20Setup%203.0.1.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.3/win32/de/Thunderbird%20Setup%203.0.3.exe [Section.040a] Description = El más popular y uno de los mejores clientes mail que hay. Size = 8.4M URLSite = http://www.mozilla-europe.org/es/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.1/win32/es-ES/Thunderbird%20Setup%203.0.1.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.3/win32/es-ES/Thunderbird%20Setup%203.0.3.exe [Section.0415] Description = Najpopularniejszy i jeden z najlepszych darmowych klientów poczty. -Size = 9.2M +Size = 9.3M URLSite = http://www.mozilla-europe.org/pl/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.1/win32/pl/Thunderbird%20Setup%203.0.1.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.3/win32/pl/Thunderbird%20Setup%203.0.3.exe [Section.0419] Description = Один из самых популярных и лучших бесплатных почтовых клиентов. Size = 8.8M URLSite = http://www.mozilla-europe.org/ru/products/thunderbird/ -URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.1/win32/ru/Thunderbird%20Setup%203.0.1.exe +URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.0.3/win32/ru/Thunderbird%20Setup%203.0.3.exe diff --git a/base/applications/sndrec32/audio_wavein.hpp b/base/applications/sndrec32/audio_wavein.hpp index 0288ea6824e..7f9285b6b65 100644 --- a/base/applications/sndrec32/audio_wavein.hpp +++ b/base/applications/sndrec32/audio_wavein.hpp @@ -305,7 +305,7 @@ class audio_wavein if ( aud_info.bits() == 16 ) svalue = ( unsigned int ) abs( *(( short * ) (main_buffer + aud_info.bytes_in_samples( nsamp )))); else if ( aud_info.bits() == 8 ) - svalue = (unsigned int)(( unsigned char * ) *(main_buffer + aud_info.bytes_in_samples( nsamp ))); + svalue = (unsigned int)(( ptrdiff_t ) *(main_buffer + aud_info.bytes_in_samples( nsamp ))); else svalue = 0; diff --git a/base/applications/sndrec32/audio_waveout.hpp b/base/applications/sndrec32/audio_waveout.hpp index a36518dc3f3..0e22afdad7e 100644 --- a/base/applications/sndrec32/audio_waveout.hpp +++ b/base/applications/sndrec32/audio_waveout.hpp @@ -229,7 +229,7 @@ class audio_waveout if ( aud_info.bits() == 16 ) svalue = ( unsigned int ) abs( *(( short * ) (main_buffer + aud_info.bytes_in_samples( nsamp )))); else if ( aud_info.bits() == 8 ) - svalue = (unsigned int)(( unsigned char * ) *(main_buffer + aud_info.bytes_in_samples( nsamp ))); + svalue = (unsigned int)(( ptrdiff_t ) *(main_buffer + aud_info.bytes_in_samples( nsamp ))); else svalue = 0; diff --git a/base/setup/usetup/partlist.c b/base/setup/usetup/partlist.c index ca0bdf7ae6a..5c553c2f537 100644 --- a/base/setup/usetup/partlist.c +++ b/base/setup/usetup/partlist.c @@ -846,10 +846,10 @@ AddDiskToList (HANDLE FileHandle, DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack; DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector; - DPRINT ("Cylinders %d\n", DiskEntry->Cylinders); - DPRINT ("TracksPerCylinder %d\n", DiskEntry->TracksPerCylinder); - DPRINT ("SectorsPerTrack %d\n", DiskEntry->SectorsPerTrack); - DPRINT ("BytesPerSector %d\n", DiskEntry->BytesPerSector); + DPRINT ("Cylinders %I64u\n", DiskEntry->Cylinders); + DPRINT ("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder); + DPRINT ("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack); + DPRINT ("BytesPerSector %I64u\n", DiskEntry->BytesPerSector); DiskEntry->TrackSize = (ULONGLONG)DiskGeometry.SectorsPerTrack * diff --git a/base/shell/cmd/cmd.c b/base/shell/cmd/cmd.c index 233cffa8931..59f00eada0a 100644 --- a/base/shell/cmd/cmd.c +++ b/base/shell/cmd/cmd.c @@ -244,7 +244,7 @@ static BOOL IsConsoleProcess(HANDLE Process) return TRUE; } - return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubSystem; + return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubsystem; } diff --git a/baseaddress.rbuild b/baseaddress.rbuild index cacc80f77f3..80401c1db46 100644 --- a/baseaddress.rbuild +++ b/baseaddress.rbuild @@ -118,6 +118,7 @@ + diff --git a/boot/bootdata/bootcd/bootcd.rbuild b/boot/bootdata/bootcd/bootcd.rbuild index 0cadb1b56a9..471a7f4863e 100644 --- a/boot/bootdata/bootcd/bootcd.rbuild +++ b/boot/bootdata/bootcd/bootcd.rbuild @@ -1,5 +1,12 @@ - - isoboot - + + isoboot + + + + isoboot + + diff --git a/boot/bootdata/livecd/livecd.rbuild b/boot/bootdata/livecd/livecd.rbuild index 9c95cc54d56..e92deca42ce 100644 --- a/boot/bootdata/livecd/livecd.rbuild +++ b/boot/bootdata/livecd/livecd.rbuild @@ -1,5 +1,12 @@ - - isoboot - + + isoboot + + + + isoboot + + diff --git a/boot/bootdata/packages/reactos.dff b/boot/bootdata/packages/reactos.dff index 75db78068b1..a58e5c1c6c2 100644 --- a/boot/bootdata/packages/reactos.dff +++ b/boot/bootdata/packages/reactos.dff @@ -262,6 +262,7 @@ dll\win32\atl\atl.dll 1 dll\win32\authz\authz.dll 1 dll\win32\avicap32\avicap32.dll 1 dll\win32\avifil32\avifil32.dll 1 +dll\win32\batt\batt.dll 1 dll\win32\bcrypt\bcrypt.dll 1 dll\win32\beepmidi\beepmidi.dll 1 dll\win32\browseui\browseui.dll 1 diff --git a/boot/freeldr/freeldr/debug.c b/boot/freeldr/freeldr/debug.c index 0de49f52320..4ab90966192 100644 --- a/boot/freeldr/freeldr/debug.c +++ b/boot/freeldr/freeldr/debug.c @@ -351,7 +351,7 @@ KeBugCheckEx( IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4) { - char Buffer[64]; + char Buffer[70]; sprintf(Buffer, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)", BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4); diff --git a/dll/directx/bdaplgin/controlnode.cpp b/dll/directx/bdaplgin/controlnode.cpp index 5cd98ccbdcb..b8b21c71719 100644 --- a/dll/directx/bdaplgin/controlnode.cpp +++ b/dll/directx/bdaplgin/controlnode.cpp @@ -9,7 +9,9 @@ #include "precomp.h" +#ifndef _MSC_VER const GUID IID_IKsPropertySet = {0x31efac30, 0x515c, 0x11d0, {0xa9,0xaa, 0x00,0xaa,0x00,0x61,0xbe,0x93}}; +#endif class CControlNode : public IUnknown { @@ -88,7 +90,6 @@ CControlNode::QueryInterface( HRESULT WINAPI CControlNode_fnConstructor( - HANDLE hFile, IBaseFilter * pFilter, ULONG NodeType, ULONG PinId, @@ -99,6 +100,7 @@ CControlNode_fnConstructor( HRESULT hr; IPin * pPin = NULL; IKsObject * pObject = NULL; + HANDLE hFile = INVALID_HANDLE_VALUE; // store pin id swprintf(Buffer, L"%u", PinId); diff --git a/dll/directx/bdaplgin/devicecontrol.cpp b/dll/directx/bdaplgin/devicecontrol.cpp index 661eba547a0..693232c3b97 100644 --- a/dll/directx/bdaplgin/devicecontrol.cpp +++ b/dll/directx/bdaplgin/devicecontrol.cpp @@ -9,20 +9,24 @@ #include "precomp.h" -const GUID CLSID_DVBTNetworkProvider = {0x216c62df, 0x6d7f, 0x4e9a, {0x85, 0x71, 0x5, 0xf1, 0x4e, 0xdb, 0x76, 0x6a}}; -const GUID IID_IAC3Filter = {0xe4539501, 0xc609, 0x46ea, {0xad, 0x2a, 0x0e, 0x97, 0x00, 0x24, 0x56, 0x83}}; -const GUID IID_IAsyncReader = {0x56A868AA, 0x0AD4, 0x11CE, {0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}}; -const GUID IID_IMatrixMixer = {0xafc57835, 0x2fd1, 0x4541, {0xa6, 0xd9, 0x0d, 0xb7, 0x18, 0x56, 0xe5, 0x89}}; -const GUID IID_IBDA_NetworkProvider = {0xfd501041, 0x8ebe, 0x11ce, {0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa2}}; -const GUID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}}; -const GUID IID_IDistributorNotify = {0x56a868af, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; -const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}}; -const GUID IID_IBDA_Topology = {0x79B56888, 0x7FEA, 0x4690, {0xB4, 0x5D, 0x38, 0xFD, 0x3C, 0x78, 0x49, 0xBE}}; const GUID IID_IKsObject = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; + +#ifndef _MSC_VER +const GUID CLSID_DVBTNetworkProvider = {0x216c62df, 0x6d7f, 0x4e9a, {0x85, 0x71, 0x5, 0xf1, 0x4e, 0xdb, 0x76, 0x6a}}; + const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; -const GUID IID_IBaseFilter = {0x56a86895, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}}; const GUID KSMETHODSETID_BdaChangeSync = {0xfd0a5af3, 0xb41d, 0x11d2, {0x9c, 0x95, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; +const GUID IID_IBaseFilter = {0x56a86895, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}}; +const GUID IID_IAsyncReader = {0x56A868AA, 0x0AD4, 0x11CE, {0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}}; +const GUID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}}; +const GUID IID_IBDA_Topology = {0x79B56888, 0x7FEA, 0x4690, {0xB4, 0x5D, 0x38, 0xFD, 0x3C, 0x78, 0x49, 0xBE}}; +const GUID IID_IBDA_NetworkProvider = {0xfd501041, 0x8ebe, 0x11ce, {0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa2}}; +const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}}; + +const GUID IID_IDistributorNotify = {0x56a868af, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; + +#endif class CBDADeviceControl : public IBDA_DeviceControl, public IBDA_Topology @@ -476,7 +480,7 @@ CBDADeviceControl::GetControlNode(ULONG ulInputPinId, ULONG ulOutputPinId, ULONG if (FAILED(hr)) return hr; - hr = CControlNode_fnConstructor(m_Handle, m_pFilter, ulNodeType, PinId, IID_IUnknown, (LPVOID*)ppControlNode); + hr = CControlNode_fnConstructor(m_pFilter, ulNodeType, PinId, IID_IUnknown, (LPVOID*)ppControlNode); #ifdef BDAPLGIN_TRACE swprintf(Buffer, L"CBDADeviceControl::GetControlNode: hr %lx\n", hr); diff --git a/dll/directx/bdaplgin/digitaldemo.cpp b/dll/directx/bdaplgin/digitaldemo.cpp index 2d1b7ed62d6..d93a31330b7 100644 --- a/dll/directx/bdaplgin/digitaldemo.cpp +++ b/dll/directx/bdaplgin/digitaldemo.cpp @@ -9,8 +9,10 @@ #include "precomp.h" +#ifndef _MSC_VER const GUID IID_IBDA_DigitalDemodulator = {0xef30f379, 0x985b, 0x4d10, {0xb6, 0x40, 0xa7, 0x9d, 0x5e, 0x04, 0xe1, 0xe0}}; const GUID KSPROPSETID_BdaDigitalDemodulator = {0xef30f379, 0x985b, 0x4d10, {0xb6, 0x40, 0xa7, 0x9d, 0x5e, 0x4, 0xe1, 0xe0}}; +#endif class CBDADigitalDemodulator : public IBDA_DigitalDemodulator { diff --git a/dll/directx/bdaplgin/frequencyfilter.cpp b/dll/directx/bdaplgin/frequencyfilter.cpp index 90d1e6a24fa..712fda0e7fa 100644 --- a/dll/directx/bdaplgin/frequencyfilter.cpp +++ b/dll/directx/bdaplgin/frequencyfilter.cpp @@ -9,8 +9,10 @@ #include "precomp.h" +#ifndef _MSC_VER const GUID IID_IBDA_FrequencyFilter = {0x71985f47, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x00, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; const GUID KSPROPSETID_BdaFrequencyFilter = {0x71985f47, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}}; +#endif class CBDAFrequencyFilter : public IBDA_FrequencyFilter { diff --git a/dll/directx/bdaplgin/lnbinfo.cpp b/dll/directx/bdaplgin/lnbinfo.cpp index a6638839289..a3c175fae34 100644 --- a/dll/directx/bdaplgin/lnbinfo.cpp +++ b/dll/directx/bdaplgin/lnbinfo.cpp @@ -9,8 +9,10 @@ #include "precomp.h" +#ifndef _MSC_VER const GUID IID_IBDA_LNBInfo = {0x992cf102, 0x49f9, 0x4719, {0xa6, 0x64, 0xc4, 0xf2, 0x3e, 0x24, 0x08, 0xf4}}; const GUID KSPROPSETID_BdaLNBInfo = {0x992cf102, 0x49f9, 0x4719, {0xa6, 0x64, 0xc4, 0xf2, 0x3e, 0x24, 0x8, 0xf4}}; +#endif class CBDALNBInfo : public IBDA_LNBInfo { diff --git a/dll/directx/bdaplgin/pincontrol.cpp b/dll/directx/bdaplgin/pincontrol.cpp index a5b99128b16..b4dc49b49a7 100644 --- a/dll/directx/bdaplgin/pincontrol.cpp +++ b/dll/directx/bdaplgin/pincontrol.cpp @@ -9,9 +9,12 @@ #include "precomp.h" -const GUID IID_IBDA_PinControl = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}}; +#ifndef _MSC_VER const GUID KSPROPSETID_BdaPinControl = {0x0ded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}}; +const GUID IID_IBDA_PinControl = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}}; const GUID IID_IPin = {0x56a86891, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +#endif + class CBDAPinControl : public IBDA_PinControl { @@ -39,7 +42,7 @@ public: HRESULT STDMETHODCALLTYPE RegistrationContext(ULONG *pulRegistrationCtx); - CBDAPinControl(HANDLE hFile, IBDA_NetworkProvider * pProvider, IPin * pConnectedPin) : m_Ref(0), m_Handle(hFile), m_pProvider(pProvider), m_pConnectedPin(pConnectedPin){}; + CBDAPinControl(HANDLE hFile, IBDA_NetworkProvider * pProvider, IPin * pConnectedPin, ULONG RegistrationCtx) : m_Ref(0), m_Handle(hFile), m_pProvider(pProvider), m_pConnectedPin(pConnectedPin), m_RegistrationCtx(RegistrationCtx){}; virtual ~CBDAPinControl() { //m_pConnectedPin->Release(); @@ -51,6 +54,7 @@ protected: HANDLE m_Handle; IBDA_NetworkProvider * m_pProvider; IPin * m_pConnectedPin; + ULONG m_RegistrationCtx; }; HRESULT @@ -73,15 +77,6 @@ CBDAPinControl::QueryInterface( return NOERROR; } -#ifdef BDAPLGIN_TRACE - WCHAR Buffer[MAX_PATH]; - LPOLESTR lpstr; - StringFromCLSID(refiid, &lpstr); - swprintf(Buffer, L"CBDAPinControl::QueryInterface: NoInterface for %s", lpstr); - OutputDebugStringW(Buffer); - CoTaskMemFree(lpstr); -#endif - return E_NOINTERFACE; } //------------------------------------------------------------------- @@ -142,10 +137,98 @@ STDMETHODCALLTYPE CBDAPinControl::RegistrationContext(ULONG *pulRegistrationCtx) { #ifdef BDAPLGIN_TRACE - OutputDebugStringW(L"CBDAPinControl::RegistrationContext: NotImplemented\n"); + OutputDebugStringW(L"CBDAPinControl::RegistrationContext\n"); #endif - return E_NOTIMPL; + if (!pulRegistrationCtx) + { + // invalid argument + return E_POINTER; + } + + if (m_RegistrationCtx) + { + // is registered + *pulRegistrationCtx = m_RegistrationCtx; + return NOERROR; + } + + //pin not registered + return E_FAIL; +} + +//------------------------------------------------------------------- +HRESULT +GetNetworkProviderFromGraph( + IFilterGraph * pGraph, + IBDA_NetworkProvider ** pOutNetworkProvider) +{ + IEnumFilters *pEnumFilters = NULL; + IBaseFilter * ppFilter[1]; + IBDA_NetworkProvider * pNetworkProvider = NULL; + HRESULT hr; + + // get IEnumFilters interface + hr = pGraph->EnumFilters(&pEnumFilters); + + if (FAILED(hr)) + { + //clean up + *pOutNetworkProvider = NULL; + return hr; + } + + while(pEnumFilters->Next(1, ppFilter, NULL) == S_OK) + { + // check if that filter supports the IBDA_NetworkProvider interface + hr = ppFilter[0]->QueryInterface(IID_IBDA_NetworkProvider, (void**)&pNetworkProvider); + + // release IBaseFilter + ppFilter[0]->Release(); + + if (SUCCEEDED(hr)) + break; + } + + // release IEnumFilters interface + pEnumFilters->Release(); + + //store result + *pOutNetworkProvider = pNetworkProvider; + + if (pNetworkProvider) + return S_OK; + else + return E_FAIL; +} + +HRESULT +CBDAPinControl_RealConstructor( + HANDLE hPin, + IBDA_NetworkProvider *pNetworkProvider, + IPin * pConnectedPin, + ULONG RegistrationCtx, + IUnknown * pUnkOuter, + REFIID riid, + LPVOID * ppv) +{ + CBDAPinControl * handler = new CBDAPinControl(hPin, pNetworkProvider, pConnectedPin, RegistrationCtx); + +#ifdef BDAPLGIN_TRACE + OutputDebugStringW(L"CBDAPinControl_fnConstructor\n"); +#endif + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return NOERROR; } HRESULT @@ -158,26 +241,13 @@ CBDAPinControl_fnConstructor( IPin * pConnectedPin = NULL; IBDA_NetworkProvider * pNetworkProvider = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; - -#if 0 - if (!IsEqualGUID(riid, IID_IUnknown)) - { -#ifdef BDAPLGIN_TRACE - OutputDebugStringW(L"CBDAPinControl_fnConstructor: Expected IUnknown\n"); -#endif - return REGDB_E_CLASSNOTREG; - } - - HRESULT hr; IKsObject * pObject = NULL; IPin * pPin = NULL; - IEnumFilters *pEnumFilters = NULL; - - IBaseFilter * ppFilter[1]; + IUnknown * pUnknown = NULL; PIN_INFO PinInfo; FILTER_INFO FilterInfo; - + ULONG RegistrationCtx = 0; if (!pUnkOuter) return E_POINTER; @@ -209,8 +279,15 @@ CBDAPinControl_fnConstructor( return hr; } + if (!PinInfo.pFilter) + { + //clean up + pObject->Release(); + pPin->Release(); + return hr; + } + // sanity checks - assert(PinInfo.dir == PINDIR_OUTPUT); assert(PinInfo.pFilter != NULL); // query filter info @@ -219,57 +296,73 @@ CBDAPinControl_fnConstructor( // sanity check assert(FilterInfo.pGraph != NULL); - // get IEnumFilters interface - hr = FilterInfo.pGraph->EnumFilters(&pEnumFilters); + // get network provider interface + hr = GetNetworkProviderFromGraph(FilterInfo.pGraph, &pNetworkProvider); - if (FAILED(hr)) + if (SUCCEEDED(hr)) { - //clean up - FilterInfo.pGraph->Release(); - PinInfo.pFilter->Release(); - pObject->Release(); - pPin->Release(); - return hr; + if (PinInfo.dir == PINDIR_OUTPUT) + { + // get connected pin handle + hr = pPin->ConnectedTo(&pConnectedPin); + if (SUCCEEDED(hr)) + { + // get file handle + hFile = pObject->KsGetObjectHandle(); + if (hFile) + { + hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, pConnectedPin, 0, pUnkOuter, riid, ppv); + if (SUCCEEDED(hr)) + { + // set to null to prevent releasing + pNetworkProvider = NULL; + pConnectedPin = NULL; + } + } + else + { + // expected file handle + hr = E_UNEXPECTED; + } + } + } + else + { + // get IUnknown from base filter + hr = PinInfo.pFilter->QueryInterface(IID_IUnknown, (void**)&pUnknown); + if (SUCCEEDED(hr)) + { + // register device filter + hr = pNetworkProvider->RegisterDeviceFilter(pUnknown, &RegistrationCtx); + if (SUCCEEDED(hr)) + { + // get file handle + hFile = pObject->KsGetObjectHandle(); + if (hFile) + { + hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, NULL, RegistrationCtx, pUnkOuter, riid, ppv); + if (SUCCEEDED(hr)) + { + // set to null to prevent releasing + pNetworkProvider = NULL; + } + } + else + { + // expected file handle + hr = E_UNEXPECTED; + } + } + } + } } - while(pEnumFilters->Next(1, ppFilter, NULL) == S_OK) - { - // check if that filter supports the IBDA_NetworkProvider interface - hr = ppFilter[0]->QueryInterface(IID_IBDA_NetworkProvider, (void**)&pNetworkProvider); - - // release IBaseFilter - ppFilter[0]->Release(); - - if (SUCCEEDED(hr)) - break; - } - - // release IEnumFilters interface - pEnumFilters->Release(); - // release IFilterGraph interface FilterInfo.pGraph->Release(); // release IBaseFilter interface PinInfo.pFilter->Release(); - if (pNetworkProvider) - { - // get connected pin handle - hr = pPin->ConnectedTo(&pConnectedPin); - - // get file handle - hFile = pObject->KsGetObjectHandle(); - - if (FAILED(hr) || hFile == INVALID_HANDLE_VALUE) - { - // pin not connected - pNetworkProvider->Release(); - // set zero - pNetworkProvider = NULL; - } - } - // release IPin pPin->Release(); @@ -277,30 +370,23 @@ CBDAPinControl_fnConstructor( pObject->Release(); - if (pNetworkProvider == NULL) + if (pNetworkProvider) { - // no network provider interface in graph - return E_NOINTERFACE; - } -#endif - - CBDAPinControl * handler = new CBDAPinControl(hFile, pNetworkProvider, pConnectedPin); - -#ifdef BDAPLGIN_TRACE - OutputDebugStringW(L"CBDAPinControl_fnConstructor"); -#endif - - DebugBreak(); - - if (!handler) - return E_OUTOFMEMORY; - - if (FAILED(handler->QueryInterface(riid, ppv))) - { - /* not supported */ - delete handler; - return E_NOINTERFACE; + // release network provider + pNetworkProvider->Release(); } - return NOERROR; + if (pConnectedPin) + { + // release connected pin + pConnectedPin->Release(); + } + + if (pUnknown) + { + // release filter + pUnknown->Release(); + } + + return hr; } diff --git a/dll/directx/bdaplgin/precomp.h b/dll/directx/bdaplgin/precomp.h index 771a798f2c3..34c11baffbd 100644 --- a/dll/directx/bdaplgin/precomp.h +++ b/dll/directx/bdaplgin/precomp.h @@ -9,6 +9,7 @@ #include #define __STREAMS__ #include +#include #include #include #include @@ -55,7 +56,6 @@ CBDAPinControl_fnConstructor( HRESULT WINAPI CControlNode_fnConstructor( - HANDLE hFile, IBaseFilter * pFilter, ULONG NodeType, ULONG PinId, @@ -101,4 +101,6 @@ CBDADigitalDemodulator_fnConstructor( REFIID riid, LPVOID * ppv); +extern const GUID IID_IKsObject; + #endif diff --git a/dll/directx/bdaplgin/signalstatistics.cpp b/dll/directx/bdaplgin/signalstatistics.cpp index ae6079e5b23..8c4aa3d2e34 100644 --- a/dll/directx/bdaplgin/signalstatistics.cpp +++ b/dll/directx/bdaplgin/signalstatistics.cpp @@ -9,8 +9,10 @@ #include "precomp.h" +#ifndef _MSC_VER const GUID IID_IBDA_SignalStatistics = {0x1347d106, 0xcf3a, 0x428a, {0xa5, 0xcb, 0xac, 0x0d, 0x9a, 0x2a, 0x43, 0x38}}; const GUID KSPROPSETID_BdaSignalStats = {0x1347d106, 0xcf3a, 0x428a, {0xa5, 0xcb, 0xac, 0xd, 0x9a, 0x2a, 0x43, 0x38}}; +#endif class CBDASignalStatistics : public IBDA_SignalStatistics { diff --git a/dll/directx/ksproxy/allocator.cpp b/dll/directx/ksproxy/allocator.cpp new file mode 100644 index 00000000000..e7c4b1f2436 --- /dev/null +++ b/dll/directx/ksproxy/allocator.cpp @@ -0,0 +1,624 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy + * FILE: dll/directx/ksproxy/allocator.cpp + * PURPOSE: IKsAllocator interface + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +const GUID IID_IKsAllocatorEx = {0x091bb63a, 0x603f, 0x11d1, {0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}}; +const GUID IID_IKsAllocator = {0x8da64899, 0xc0d9, 0x11d0, {0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a}}; + +class CKsAllocator : public IKsAllocatorEx, + public IMemAllocatorCallbackTemp +{ +public: + typedef std::stackMediaSampleStack; + typedef std::listMediaSampleList; + + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); + + STDMETHODIMP_(ULONG) AddRef() + { + InterlockedIncrement(&m_Ref); + return m_Ref; + } + STDMETHODIMP_(ULONG) Release() + { + InterlockedDecrement(&m_Ref); + + if (!m_Ref) + { + delete this; + return 0; + } + return m_Ref; + } + //IKsAllocator + HANDLE STDMETHODCALLTYPE KsGetAllocatorHandle(); + KSALLOCATORMODE STDMETHODCALLTYPE KsGetAllocatorMode(); + HRESULT STDMETHODCALLTYPE KsGetAllocatorStatus(PKSSTREAMALLOCATOR_STATUS AllocatorStatus); + VOID STDMETHODCALLTYPE KsSetAllocatorMode(KSALLOCATORMODE Mode); + + //IKsAllocatorEx + PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE KsGetProperties(); + VOID STDMETHODCALLTYPE KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties); + VOID STDMETHODCALLTYPE KsSetAllocatorHandle(HANDLE AllocatorHandle); + HANDLE STDMETHODCALLTYPE KsCreateAllocatorAndGetHandle(IKsPin* KsPin); + + //IMemAllocator + HRESULT STDMETHODCALLTYPE SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual); + HRESULT STDMETHODCALLTYPE GetProperties(ALLOCATOR_PROPERTIES *pProps); + HRESULT STDMETHODCALLTYPE Commit(); + HRESULT STDMETHODCALLTYPE Decommit(); + HRESULT STDMETHODCALLTYPE GetBuffer(IMediaSample **ppBuffer, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags); + HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample *pBuffer); + + //IMemAllocatorCallbackTemp + HRESULT STDMETHODCALLTYPE SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify); + HRESULT STDMETHODCALLTYPE GetFreeCount(LONG *plBuffersFree); + + + CKsAllocator(); + virtual ~CKsAllocator(){} + VOID STDMETHODCALLTYPE FreeMediaSamples(); +protected: + LONG m_Ref; + HANDLE m_hAllocator; + KSALLOCATORMODE m_Mode; + ALLOCATOR_PROPERTIES_EX m_Properties; + IMemAllocatorNotifyCallbackTemp *m_Notify; + ULONG m_Allocated; + LONG m_cbBuffer; + LONG m_cBuffers; + LONG m_cbAlign; + LONG m_cbPrefix; + BOOL m_Commited; + CRITICAL_SECTION m_CriticalSection; + MediaSampleStack m_FreeList; + MediaSampleList m_UsedList; + LPVOID m_Buffer; + BOOL m_FreeSamples; +}; + + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + if (IsEqualGUID(refiid, IID_IUnknown) || + IsEqualGUID(refiid, IID_IKsAllocator) || + IsEqualGUID(refiid, IID_IKsAllocatorEx)) + { + *Output = PVOID(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + if (IsEqualGUID(refiid, IID_IMemAllocator) || + IsEqualGUID(refiid, IID_IMemAllocatorCallbackTemp)) + { + *Output = (IMemAllocatorCallbackTemp*)(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + + return E_NOINTERFACE; +} + +CKsAllocator::CKsAllocator() : m_Ref(0), + m_hAllocator(0), + m_Mode(KsAllocatorMode_User), + m_Notify(0), + m_Allocated(0), + m_cbBuffer(0), + m_cBuffers(0), + m_cbAlign(0), + m_cbPrefix(0), + m_Commited(FALSE), + m_FreeList(), + m_UsedList(), + m_Buffer(0), + m_FreeSamples(FALSE) +{ + InitializeCriticalSection(&m_CriticalSection); + +} + +//------------------------------------------------------------------- +// IMemAllocator +// +HRESULT +STDMETHODCALLTYPE +CKsAllocator::SetProperties( + ALLOCATOR_PROPERTIES *pRequest, + ALLOCATOR_PROPERTIES *pActual) +{ + SYSTEM_INFO SystemInfo; + + EnterCriticalSection(&m_CriticalSection); + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::SetProperties\n"); +#endif + + if (!pRequest || !pActual) + return E_POINTER; + + // zero output properties + ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES)); + + // get system info + GetSystemInfo(&SystemInfo); + + if (!pRequest->cbAlign || (pRequest->cbAlign - 1) & SystemInfo.dwAllocationGranularity) + { + // bad alignment + LeaveCriticalSection(&m_CriticalSection); + return VFW_E_BADALIGN; + } + + if (m_Mode == KsAllocatorMode_Kernel) + { + // u can't change a kernel allocator + LeaveCriticalSection(&m_CriticalSection); + return VFW_E_ALREADY_COMMITTED; + } + + if (m_Commited) + { + // need to decommit first + LeaveCriticalSection(&m_CriticalSection); + return VFW_E_ALREADY_COMMITTED; + } + + if (m_Allocated != m_FreeList.size()) + { + // outstanding buffers + LeaveCriticalSection(&m_CriticalSection); + return VFW_E_BUFFERS_OUTSTANDING; + } + + pActual->cbAlign = m_cbAlign = pRequest->cbAlign; + pActual->cbBuffer = m_cbBuffer = pRequest->cbBuffer; + pActual->cbPrefix = m_cbPrefix = pRequest->cbPrefix; + pActual->cBuffers = m_cBuffers = pRequest->cBuffers; + + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::GetProperties( + ALLOCATOR_PROPERTIES *pProps) +{ + if (!pProps) + return E_POINTER; + + pProps->cbBuffer = m_cbBuffer; + pProps->cBuffers = m_cBuffers; + pProps->cbAlign = m_cbAlign; + pProps->cbPrefix = m_cbPrefix; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::Commit() +{ + LONG Index; + PUCHAR CurrentBuffer; + IMediaSample * Sample; + HRESULT hr; + + //TODO integer overflow checks + EnterCriticalSection(&m_CriticalSection); + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::Commit\n"); +#endif + + if (m_Mode == KsAllocatorMode_Kernel) + { + /* no-op for kernel allocator */ + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + + if (m_Commited) + { + // already commited + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + + if (m_cbBuffer < 0 || m_cBuffers < 0 || m_cbPrefix < 0) + { + // invalid parameter + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + LONG Size = m_cbBuffer + m_cbPrefix; + + if (m_cbAlign > 1) + { + //check alignment + LONG Mod = Size % m_cbAlign; + if (Mod) + { + // calculate aligned size + Size += m_cbAlign - Mod; + } + } + + LONG TotalSize = Size * m_cBuffers; + + assert(TotalSize); + assert(m_cBuffers); + assert(Size); + + // now allocate buffer + m_Buffer = VirtualAlloc(NULL, TotalSize, MEM_COMMIT, PAGE_READWRITE); + if (!m_Buffer) + { + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + ZeroMemory(m_Buffer, TotalSize); + + CurrentBuffer = (PUCHAR)m_Buffer; + + for (Index = 0; Index < m_cBuffers; Index++) + { + // construct media sample + hr = CMediaSample_Constructor((IMemAllocator*)this, CurrentBuffer + m_cbPrefix, m_cbBuffer, IID_IMediaSample, (void**)&Sample); + if (FAILED(hr)) + { + LeaveCriticalSection(&m_CriticalSection); + return E_OUTOFMEMORY; + } + + // add to free list + m_FreeList.push(Sample); + m_Allocated++; + + //next sample buffer + CurrentBuffer += Size; + } + + // we are now commited + m_Commited = true; + + LeaveCriticalSection(&m_CriticalSection); + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::Decommit() +{ + EnterCriticalSection(&m_CriticalSection); + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::Decommit\n"); +#endif + + if (m_Mode == KsAllocatorMode_Kernel) + { + /* no-op for kernel allocator */ + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + + m_Commited = false; + + if (m_Allocated != m_FreeList.size()) + { + // outstanding buffers + m_FreeSamples = true; + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; + } + else + { + // no outstanding buffers + // free to free them + FreeMediaSamples(); + } + + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; +} + + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::GetBuffer( + IMediaSample **ppBuffer, + REFERENCE_TIME *pStartTime, + REFERENCE_TIME *pEndTime, + DWORD dwFlags) +{ + IMediaSample * Sample = NULL; + + if (!m_Commited) + return VFW_E_NOT_COMMITTED; + + do + { + EnterCriticalSection(&m_CriticalSection); + + if (!m_FreeList.empty()) + { + Sample = m_FreeList.top(); + m_FreeList.pop(); + } + + LeaveCriticalSection(&m_CriticalSection); + + if (dwFlags & AM_GBF_NOWAIT) + { + // never wait untill a buffer becomes available + break; + } + } + while(Sample == NULL); + + if (!Sample) + { + // no sample acquired + //HACKKKKKKK + Sample = m_UsedList.back(); + m_UsedList.pop_back(); + + if (!Sample) + return VFW_E_TIMEOUT; + } + + // store result + *ppBuffer = Sample; + + // store sample in used list + m_UsedList.push_front(Sample); + + // done + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::ReleaseBuffer( + IMediaSample *pBuffer) +{ + EnterCriticalSection(&m_CriticalSection); + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::ReleaseBuffer\n"); +#endif + + // media sample always 1 ref count in free list + pBuffer->AddRef(); + + // add the sample to the free list + m_FreeList.push(pBuffer); + + + if (m_FreeSamples) + { + // pending de-commit + if (m_FreeList.size () == m_Allocated) + { + FreeMediaSamples(); + } + } + + if (m_Notify) + { + //notify caller of an available buffer + m_Notify->NotifyRelease(); + } + + LeaveCriticalSection(&m_CriticalSection); + return S_OK; +} + +//------------------------------------------------------------------- +// IMemAllocatorCallbackTemp +// +HRESULT +STDMETHODCALLTYPE +CKsAllocator::SetNotify( + IMemAllocatorNotifyCallbackTemp *pNotify) +{ + EnterCriticalSection(&m_CriticalSection); + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::SetNotify\n"); +#endif + + if (pNotify) + pNotify->AddRef(); + + if (m_Notify) + m_Notify->Release(); + + m_Notify = pNotify; + + LeaveCriticalSection(&m_CriticalSection); + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::GetFreeCount( + LONG *plBuffersFree) +{ + *plBuffersFree = m_Allocated - m_FreeList.size(); + return S_OK; +} + +//------------------------------------------------------------------- +// IKsAllocator +// +HANDLE +STDMETHODCALLTYPE +CKsAllocator::KsGetAllocatorHandle() +{ + return m_hAllocator; +} + +KSALLOCATORMODE +STDMETHODCALLTYPE +CKsAllocator::KsGetAllocatorMode() +{ + return m_Mode; +} + +HRESULT +STDMETHODCALLTYPE +CKsAllocator::KsGetAllocatorStatus( + PKSSTREAMALLOCATOR_STATUS AllocatorStatus) +{ + return NOERROR; +} +VOID +STDMETHODCALLTYPE +CKsAllocator::KsSetAllocatorMode( + KSALLOCATORMODE Mode) +{ + m_Mode = Mode; +} + +//------------------------------------------------------------------- +// IKsAllocatorEx +// +PALLOCATOR_PROPERTIES_EX +STDMETHODCALLTYPE +CKsAllocator::KsGetProperties() +{ + return &m_Properties; +} + +VOID +STDMETHODCALLTYPE +CKsAllocator::KsSetProperties( + PALLOCATOR_PROPERTIES_EX Properties) +{ + CopyMemory(&m_Properties, Properties, sizeof(ALLOCATOR_PROPERTIES_EX)); +} + +VOID +STDMETHODCALLTYPE +CKsAllocator::KsSetAllocatorHandle( + HANDLE AllocatorHandle) +{ + m_hAllocator = AllocatorHandle; +} + + +HANDLE +STDMETHODCALLTYPE +CKsAllocator::KsCreateAllocatorAndGetHandle( + IKsPin* KsPin) +{ + HRESULT hr; + IKsObject * pObject; + KSALLOCATOR_FRAMING AllocatorFraming; + HANDLE hPin; + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator::KsCreateAllocatorAndGetHandle\n"); +#endif + + if (m_hAllocator) + { + CloseHandle(m_hAllocator); + m_hAllocator = NULL; + } + + // get pin IKsObject interface + hr = KsPin->QueryInterface(IID_IKsObject, (void**)&pObject); + if (FAILED(hr)) + return NULL; + + // get pin handle + hPin = pObject->KsGetObjectHandle(); + + //release IKsObject interface + pObject->Release(); + + if (!hPin || hPin == INVALID_HANDLE_VALUE) + return NULL; + + //setup allocator framing + AllocatorFraming.Frames = m_Properties.cBuffers; + AllocatorFraming.FrameSize = m_Properties.cbBuffer; + AllocatorFraming.FileAlignment = (m_Properties.cbAlign -1); + AllocatorFraming.OptionsFlags = KSALLOCATOR_OPTIONF_SYSTEM_MEMORY; + AllocatorFraming.PoolType = (m_Properties.LogicalMemoryType == KS_MemoryTypeKernelPaged); + + DWORD dwError = KsCreateAllocator(hPin, &AllocatorFraming, &m_hAllocator); + if (dwError) + return NULL; + + return m_hAllocator; +} + +//------------------------------------------------------------------- +VOID +STDMETHODCALLTYPE +CKsAllocator::FreeMediaSamples() +{ + ULONG Index; + + for(Index = 0; Index < m_FreeList.size(); Index++) + { + IMediaSample * Sample = m_FreeList.top(); + m_FreeList.pop(); + delete Sample; + } + + m_FreeSamples = false; + m_Allocated = 0; + + if (m_Buffer) + { + // release buffer + VirtualFree(m_Buffer, 0, MEM_RELEASE); + + m_Buffer = NULL; + } +} + +HRESULT +WINAPI +CKsAllocator_Constructor( + IUnknown * pUnkOuter, + REFIID riid, + LPVOID * ppv) +{ +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsAllocator_Constructor\n"); +#endif + + CKsAllocator * handler = new CKsAllocator(); + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return NOERROR; +} diff --git a/dll/directx/ksproxy/basicaudio.cpp b/dll/directx/ksproxy/basicaudio.cpp index 7fec05f2140..04c53b345a0 100644 --- a/dll/directx/ksproxy/basicaudio.cpp +++ b/dll/directx/ksproxy/basicaudio.cpp @@ -97,7 +97,9 @@ HRESULT STDMETHODCALLTYPE CKsBasicAudio::Stop() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -105,7 +107,10 @@ HRESULT STDMETHODCALLTYPE CKsBasicAudio::Pause() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -114,7 +119,10 @@ STDMETHODCALLTYPE CKsBasicAudio::Run( REFERENCE_TIME tStart) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -123,7 +131,9 @@ STDMETHODCALLTYPE CKsBasicAudio::SetSyncSource( IReferenceClock *pClock) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -131,7 +141,10 @@ HRESULT STDMETHODCALLTYPE CKsBasicAudio::NotifyGraphChange() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -144,7 +157,10 @@ STDMETHODCALLTYPE CKsBasicAudio::GetTypeInfoCount( UINT *pctinfo) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -155,7 +171,9 @@ CKsBasicAudio::GetTypeInfo( LCID lcid, ITypeInfo **ppTInfo) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -168,7 +186,10 @@ CKsBasicAudio::GetIDsOfNames( LCID lcid, DISPID *rgDispId) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -184,7 +205,10 @@ CKsBasicAudio::Invoke( EXCEPINFO *pExcepInfo, UINT *puArgErr) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -197,7 +221,10 @@ STDMETHODCALLTYPE CKsBasicAudio::put_Volume( long lVolume) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -207,7 +234,10 @@ STDMETHODCALLTYPE CKsBasicAudio::get_Volume( long *plVolume) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -217,7 +247,10 @@ STDMETHODCALLTYPE CKsBasicAudio::put_Balance( long lBalance) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -227,7 +260,10 @@ STDMETHODCALLTYPE CKsBasicAudio::get_Balance( long *plBalance) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif + return E_NOTIMPL; } @@ -238,7 +274,9 @@ CKsBasicAudio_Constructor( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsBasicAudio_Constructor\n"); +#endif CKsBasicAudio * handler = new CKsBasicAudio(); diff --git a/dll/directx/ksproxy/clockforward.cpp b/dll/directx/ksproxy/clockforward.cpp index 80bf00fe421..868633edf0e 100644 --- a/dll/directx/ksproxy/clockforward.cpp +++ b/dll/directx/ksproxy/clockforward.cpp @@ -12,6 +12,10 @@ const GUID KSCATEGORY_CLOCK = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; #endif +const GUID IID_IKsClockForwarder = {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; + +DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter); + class CKsClockForwarder : public IDistributorNotify, public IKsObject { @@ -45,14 +49,38 @@ public: // IKsObject interface HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); - CKsClockForwarder(HANDLE handle) : m_Ref(0), m_Handle(handle){} - virtual ~CKsClockForwarder(){ if (m_Handle) CloseHandle(m_Handle);} - + CKsClockForwarder(HANDLE handle); + virtual ~CKsClockForwarder(){}; + HRESULT STDMETHODCALLTYPE SetClockState(KSSTATE State); protected: LONG m_Ref; HANDLE m_Handle; + IReferenceClock * m_Clock; + HANDLE m_hEvent; + HANDLE m_hThread; + BOOL m_ThreadStarted; + BOOL m_PendingStop; + BOOL m_ForceStart; + KSSTATE m_State; + REFERENCE_TIME m_Time; + + friend DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter); }; +CKsClockForwarder::CKsClockForwarder( + HANDLE handle) : m_Ref(0), + m_Handle(handle), + m_Clock(0), + m_hEvent(NULL), + m_hThread(NULL), + m_ThreadStarted(FALSE), + m_PendingStop(FALSE), + m_ForceStart(FALSE), + m_State(KSSTATE_STOP), + m_Time(0) +{ +} + HRESULT STDMETHODCALLTYPE CKsClockForwarder::QueryInterface( @@ -65,7 +93,8 @@ CKsClockForwarder::QueryInterface( reinterpret_cast(*Output)->AddRef(); return NOERROR; } - if (IsEqualGUID(refiid, IID_IKsObject)) + if (IsEqualGUID(refiid, IID_IKsObject) || + IsEqualGUID(refiid, IID_IKsClockForwarder)) { *Output = (IKsObject*)(this); reinterpret_cast(*Output)->AddRef(); @@ -79,15 +108,6 @@ CKsClockForwarder::QueryInterface( return NOERROR; } -#if 0 - if (IsEqualGUID(refiid, IID_IKsClockForwarder)) - { - *Output = PVOID(this); - reinterpret_cast(*Output)->AddRef(); - return NOERROR; - } -#endif - return E_NOINTERFACE; } @@ -100,16 +120,86 @@ HRESULT STDMETHODCALLTYPE CKsClockForwarder::Stop() { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; + swprintf(Buffer, L"CKsClockForwarder::Stop m_ThreadStarted %u m_PendingStop %u m_hThread %p m_hEvent %p m_Handle %p\n", m_ThreadStarted, m_PendingStop, m_hThread, m_hEvent, m_Handle); + OutputDebugStringW(Buffer); +#endif + + m_Time = 0; + if (m_ThreadStarted) + { + // signal pending stop + m_PendingStop = true; + + assert(m_hThread); + assert(m_hEvent); + + // set stop event + SetEvent(m_hEvent); + + // wait untill the thread has finished + WaitForSingleObject(m_hThread, INFINITE); + + // close thread handle + CloseHandle(m_hThread); + + // zero handle + m_hThread = NULL; + } + + if (m_hEvent) + { + // close stop event + CloseHandle(m_hEvent); + m_hEvent = NULL; + } + + m_PendingStop = false; + + SetClockState(KSSTATE_STOP); + return NOERROR; } HRESULT STDMETHODCALLTYPE CKsClockForwarder::Pause() { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugString("CKsClockForwarder::Pause\n"); +#endif + + if (!m_hEvent) + { + m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!m_hEvent) + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); + } + + if (m_State <= KSSTATE_PAUSE) + { + if (m_State == KSSTATE_STOP) + SetClockState(KSSTATE_ACQUIRE); + + if (m_State == KSSTATE_ACQUIRE) + SetClockState(KSSTATE_PAUSE); + } + else + { + if (!m_ForceStart) + { + SetClockState(KSSTATE_PAUSE); + } + } + + if (!m_hThread) + { + m_hThread = CreateThread(NULL, 0, CKsClockForwarder_ThreadStartup, (LPVOID)this, 0, NULL); + if (!m_hThread) + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); + } + + return NOERROR; } HRESULT @@ -117,8 +207,28 @@ STDMETHODCALLTYPE CKsClockForwarder::Run( REFERENCE_TIME tStart) { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugString("CKsClockForwarder::Run\n"); +#endif + + m_Time = tStart; + + if (!m_hEvent || !m_hThread) + { + m_ForceStart = TRUE; + HRESULT hr = Pause(); + m_ForceStart = FALSE; + + if (FAILED(hr)) + return hr; + } + + assert(m_hThread); + + SetClockState(KSSTATE_RUN); + SetEvent(m_hEvent); + + return NOERROR; } HRESULT @@ -126,16 +236,30 @@ STDMETHODCALLTYPE CKsClockForwarder::SetSyncSource( IReferenceClock *pClock) { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugString("CKsClockForwarder::SetSyncSource\n"); +#endif + + if (pClock) + pClock->AddRef(); + + if (m_Clock) + m_Clock->Release(); + + + m_Clock = pClock; + return NOERROR; } HRESULT STDMETHODCALLTYPE CKsClockForwarder::NotifyGraphChange() { - OutputDebugString("UNIMPLEMENTED\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugString("CKsClockForwarder::NotifyGraphChange\n"); +#endif + + return NOERROR; } //------------------------------------------------------------------- @@ -149,6 +273,66 @@ CKsClockForwarder::KsGetObjectHandle() return m_Handle; } +//------------------------------------------------------------------- +HRESULT +STDMETHODCALLTYPE +CKsClockForwarder::SetClockState(KSSTATE State) +{ + KSPROPERTY Property; + ULONG BytesReturned; + + Property.Set = KSPROPSETID_Clock; + Property.Id = KSPROPERTY_CLOCK_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + HRESULT hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &BytesReturned); + if (SUCCEEDED(hr)) + m_State = State; + +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsClockForwarder::SetClockState m_State %u State %u hr %lx\n", m_State, State, hr); + OutputDebugStringW(Buffer); +#endif + + return hr; +} + +DWORD +WINAPI +CKsClockForwarder_ThreadStartup(LPVOID lpParameter) +{ + REFERENCE_TIME Time; + ULONG BytesReturned; + + CKsClockForwarder * Fwd = (CKsClockForwarder*)lpParameter; + + Fwd->m_ThreadStarted = TRUE; + + do + { + if (Fwd->m_PendingStop) + break; + + if (Fwd->m_State != KSSTATE_RUN) + WaitForSingleObject(Fwd->m_hEvent, INFINITE); + + KSPROPERTY Property; + Property.Set = KSPROPSETID_Clock; + Property.Id = KSPROPERTY_CLOCK_TIME; + Property.Flags = KSPROPERTY_TYPE_SET; + + Fwd->m_Clock->GetTime(&Time); + Time -= Fwd->m_Time; + + KsSynchronousDeviceControl(Fwd->m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &Time, sizeof(REFERENCE_TIME), &BytesReturned); + } + while(TRUE); + + Fwd->m_ThreadStarted = FALSE; + return NOERROR; +} + HRESULT WINAPI CKsClockForwarder_Constructor( @@ -159,14 +343,18 @@ CKsClockForwarder_Constructor( HRESULT hr; HANDLE handle; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsClockForwarder_Constructor\n"); +#endif // open default clock hr = KsOpenDefaultDevice(KSCATEGORY_CLOCK, GENERIC_READ | GENERIC_WRITE, &handle); if (hr != NOERROR) { +#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder_Constructor failed to open device\n"); +#endif return hr; } diff --git a/dll/directx/ksproxy/cvpconfig.cpp b/dll/directx/ksproxy/cvpconfig.cpp index 91d2006ad49..1333263e003 100644 --- a/dll/directx/ksproxy/cvpconfig.cpp +++ b/dll/directx/ksproxy/cvpconfig.cpp @@ -102,7 +102,9 @@ HRESULT STDMETHODCALLTYPE CVPConfig::Stop() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -110,7 +112,9 @@ HRESULT STDMETHODCALLTYPE CVPConfig::Pause() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -119,7 +123,9 @@ STDMETHODCALLTYPE CVPConfig::Run( REFERENCE_TIME tStart) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -128,7 +134,9 @@ STDMETHODCALLTYPE CVPConfig::SetSyncSource( IReferenceClock *pClock) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -136,7 +144,9 @@ HRESULT STDMETHODCALLTYPE CVPConfig::NotifyGraphChange() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -149,7 +159,9 @@ CVPConfig::GetConnectInfo( LPDWORD pdwNumConnectInfo, IN OUT LPDDVIDEOPORTCONNECT pddVPConnectInfo) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -158,7 +170,9 @@ STDMETHODCALLTYPE CVPConfig::SetConnectInfo( DWORD dwChosenEntry) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -167,7 +181,9 @@ STDMETHODCALLTYPE CVPConfig::GetVPDataInfo( LPAMVPDATAINFO pamvpDataInfo) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -177,7 +193,9 @@ CVPConfig::GetMaxPixelRate( LPAMVPSIZE pamvpSize, OUT LPDWORD pdwMaxPixelsPerSecond) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -187,7 +205,9 @@ CVPConfig::InformVPInputFormats( DWORD dwNumFormats, IN LPDDPIXELFORMAT pDDPixelFormats) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -197,7 +217,9 @@ CVPConfig::GetVideoFormats( LPDWORD pdwNumFormats, IN OUT LPDDPIXELFORMAT pddPixelFormats) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -206,7 +228,9 @@ STDMETHODCALLTYPE CVPConfig::SetVideoFormat( DWORD dwChosenEntry) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -214,7 +238,9 @@ HRESULT STDMETHODCALLTYPE CVPConfig::SetInvertPolarity() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -223,7 +249,9 @@ STDMETHODCALLTYPE CVPConfig::GetOverlaySurface( LPDIRECTDRAWSURFACE* ppddOverlaySurface) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -232,7 +260,9 @@ STDMETHODCALLTYPE CVPConfig::SetDirectDrawKernelHandle( ULONG_PTR dwDDKernelHandle) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -241,7 +271,9 @@ STDMETHODCALLTYPE CVPConfig::SetVideoPortID( IN DWORD dwVideoPortID) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -252,7 +284,9 @@ CVPConfig::SetDDSurfaceKernelHandles( DWORD cHandles, IN ULONG_PTR *rgDDKernelHandles) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -264,7 +298,9 @@ CVPConfig::SetSurfaceParameters( IN DWORD dwXOrigin, IN DWORD dwYOrigin) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -277,7 +313,9 @@ STDMETHODCALLTYPE CVPConfig::IsVPDecimationAllowed( LPBOOL pbIsDecimationAllowed) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -286,13 +324,13 @@ STDMETHODCALLTYPE CVPConfig::SetScalingFactors( LPAMVPSIZE pamvpSize) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } - - HRESULT WINAPI CVPConfig_Constructor( @@ -300,7 +338,9 @@ CVPConfig_Constructor( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CVPConfig_Constructor\n"); +#endif CVPConfig * handler = new CVPConfig(); diff --git a/dll/directx/ksproxy/cvpvbiconfig.cpp b/dll/directx/ksproxy/cvpvbiconfig.cpp index 016d060aa24..b7b7130b471 100644 --- a/dll/directx/ksproxy/cvpvbiconfig.cpp +++ b/dll/directx/ksproxy/cvpvbiconfig.cpp @@ -98,7 +98,9 @@ HRESULT STDMETHODCALLTYPE CVPVBIConfig::Stop() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -106,7 +108,9 @@ HRESULT STDMETHODCALLTYPE CVPVBIConfig::Pause() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -115,7 +119,9 @@ STDMETHODCALLTYPE CVPVBIConfig::Run( REFERENCE_TIME tStart) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -124,7 +130,9 @@ STDMETHODCALLTYPE CVPVBIConfig::SetSyncSource( IReferenceClock *pClock) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -132,7 +140,9 @@ HRESULT STDMETHODCALLTYPE CVPVBIConfig::NotifyGraphChange() { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -145,7 +155,9 @@ CVPVBIConfig::GetConnectInfo( LPDWORD pdwNumConnectInfo, IN OUT LPDDVIDEOPORTCONNECT pddVPConnectInfo) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -154,7 +166,9 @@ STDMETHODCALLTYPE CVPVBIConfig::SetConnectInfo( DWORD dwChosenEntry) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -163,7 +177,9 @@ STDMETHODCALLTYPE CVPVBIConfig::GetVPDataInfo( LPAMVPDATAINFO pamvpDataInfo) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -173,7 +189,9 @@ CVPVBIConfig::GetMaxPixelRate( LPAMVPSIZE pamvpSize, OUT LPDWORD pdwMaxPixelsPerSecond) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -183,7 +201,9 @@ CVPVBIConfig::InformVPInputFormats( DWORD dwNumFormats, IN LPDDPIXELFORMAT pDDPixelFormats) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -193,7 +213,9 @@ CVPVBIConfig::GetVideoFormats( LPDWORD pdwNumFormats, IN OUT LPDDPIXELFORMAT pddPixelFormats) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -202,7 +224,9 @@ STDMETHODCALLTYPE CVPVBIConfig::SetVideoFormat( DWORD dwChosenEntry) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -210,7 +234,9 @@ HRESULT STDMETHODCALLTYPE CVPVBIConfig::SetInvertPolarity() { - OutputDebugString("UNIMPLEMENTED\n"); + #ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -219,7 +245,9 @@ STDMETHODCALLTYPE CVPVBIConfig::GetOverlaySurface( LPDIRECTDRAWSURFACE* ppddOverlaySurface) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -228,7 +256,9 @@ STDMETHODCALLTYPE CVPVBIConfig::SetDirectDrawKernelHandle( ULONG_PTR dwDDKernelHandle) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -237,7 +267,9 @@ STDMETHODCALLTYPE CVPVBIConfig::SetVideoPortID( IN DWORD dwVideoPortID) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -248,7 +280,9 @@ CVPVBIConfig::SetDDSurfaceKernelHandles( DWORD cHandles, IN ULONG_PTR *rgDDKernelHandles) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -260,7 +294,9 @@ CVPVBIConfig::SetSurfaceParameters( IN DWORD dwXOrigin, IN DWORD dwYOrigin) { - OutputDebugString("UNIMPLEMENTED\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"UNIMPLEMENTED\n"); +#endif return E_NOTIMPL; } @@ -272,7 +308,9 @@ CVPVBIConfig_Constructor( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CVPVBIConfig_Constructor\n"); +#endif CVPVBIConfig * handler = new CVPVBIConfig(); diff --git a/dll/directx/ksproxy/datatype.cpp b/dll/directx/ksproxy/datatype.cpp index 5006b68a121..965e847b55b 100644 --- a/dll/directx/ksproxy/datatype.cpp +++ b/dll/directx/ksproxy/datatype.cpp @@ -103,7 +103,9 @@ CKsDataTypeHandler::KsIsMediaTypeInRanges( ULONG Index; HRESULT hr = S_FALSE; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsDataTypeHandler::KsIsMediaTypeInRanges\n"); +#endif DataList = (PKSMULTIPLE_ITEM)DataRanges; DataRange = (PKSDATARANGE)(DataList + 1); @@ -187,7 +189,9 @@ STDMETHODCALLTYPE CKsDataTypeHandler::KsSetMediaType( IN const AM_MEDIA_TYPE* AmMediaType) { +#ifdef KSPROXY_TRACE OutputDebugString("CKsDataTypeHandler::KsSetMediaType\n"); +#endif if (m_Type) { @@ -228,7 +232,10 @@ CKsDataTypeHandler_Constructor ( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsDataTypeHandler_Constructor\n"); +#endif + CKsDataTypeHandler * handler = new CKsDataTypeHandler(); if (!handler) diff --git a/dll/directx/ksproxy/enum_mediatypes.cpp b/dll/directx/ksproxy/enum_mediatypes.cpp index 462ffda24fc..db2c7a0298e 100644 --- a/dll/directx/ksproxy/enum_mediatypes.cpp +++ b/dll/directx/ksproxy/enum_mediatypes.cpp @@ -64,13 +64,6 @@ CEnumMediaTypes::QueryInterface( return NOERROR; } - WCHAR Buffer[MAX_PATH]; - LPOLESTR lpstr; - StringFromCLSID(refiid, &lpstr); - swprintf(Buffer, L"CEnumMediaTypes::QueryInterface: NoInterface for %s\n", lpstr); - OutputDebugStringW(Buffer); - CoTaskMemFree(lpstr); - return E_NOINTERFACE; } @@ -171,7 +164,9 @@ STDMETHODCALLTYPE CEnumMediaTypes::Clone( IEnumMediaTypes **ppEnum) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CEnumMediaTypes::Clone : NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -189,7 +184,7 @@ CEnumMediaTypes_fnConstructor( WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; StringFromCLSID(riid, &lpstr); - swprintf(Buffer, L"CEnumMediaTypes_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown); + swprintf(Buffer, L"CEnumMediaTypes_fnConstructor riid %s\n", lpstr); OutputDebugStringW(Buffer); #endif diff --git a/dll/directx/ksproxy/enumpins.cpp b/dll/directx/ksproxy/enumpins.cpp index 5c0f0ecd7bd..172ef7a016b 100644 --- a/dll/directx/ksproxy/enumpins.cpp +++ b/dll/directx/ksproxy/enumpins.cpp @@ -132,7 +132,10 @@ STDMETHODCALLTYPE CEnumPins::Clone( IEnumPins **ppEnum) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CEnumPins::Clone : NotImplemented\n"); +#endif + return E_NOTIMPL; } diff --git a/dll/directx/ksproxy/input_pin.cpp b/dll/directx/ksproxy/input_pin.cpp index e95894f4efa..b651d7dafaf 100644 --- a/dll/directx/ksproxy/input_pin.cpp +++ b/dll/directx/ksproxy/input_pin.cpp @@ -62,6 +62,8 @@ class CInputPin : public IPin, public ISpecifyPropertyPages { public: + typedef std::vectorProxyPluginVector; + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); STDMETHODIMP_(ULONG) AddRef() @@ -170,14 +172,15 @@ public: HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); - CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication); + HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); + HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); + CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); virtual ~CInputPin(){}; protected: LONG m_Ref; IBaseFilter * m_ParentFilter; LPCWSTR m_PinName; - HANDLE m_hFilter; HANDLE m_hPin; ULONG m_PinId; IMemAllocator * m_MemAllocator; @@ -185,6 +188,7 @@ protected: KSPIN_COMMUNICATION m_Communication; KSPIN_INTERFACE m_Interface; KSPIN_MEDIUM m_Medium; + AM_MEDIA_TYPE m_MediaFormat; IPin * m_Pin; BOOL m_ReadOnly; IKsInterfaceHandler * m_InterfaceHandler; @@ -195,17 +199,16 @@ protected: LPWSTR m_FilterName; FRAMING_PROP m_FramingProp[4]; PKSALLOCATOR_FRAMING_EX m_FramingEx[4]; + ProxyPluginVector m_Plugins; }; CInputPin::CInputPin( - IBaseFilter * ParentFilter, + IBaseFilter * ParentFilter, LPCWSTR PinName, - HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), - m_hFilter(hFilter), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_MemAllocator(0), @@ -217,10 +220,28 @@ CInputPin::CInputPin( m_KsAllocatorEx(0), m_PipeAllocatorFlag(0), m_bPinBusCacheInitialized(0), - m_FilterName(0) + m_FilterName(0), + m_Plugins() { ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); + + HRESULT hr; + IKsObject * KsObjectParent; + HANDLE hFilter; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + assert(hr == S_OK); + + hFilter = KsObjectParent->KsGetObjectHandle(); + assert(hFilter); + + KsObjectParent->Release(); + + + ZeroMemory(&m_MediaFormat, sizeof(AM_MEDIA_TYPE)); + hr = KsGetMediaType(0, &m_MediaFormat, hFilter, m_PinId); + assert(hr == S_OK); } HRESULT @@ -229,6 +250,8 @@ CInputPin::QueryInterface( IN REFIID refiid, OUT PVOID* Output) { + WCHAR Buffer[100]; + *Output = NULL; if (IsEqualGUID(refiid, IID_IUnknown) || @@ -240,6 +263,13 @@ CInputPin::QueryInterface( } else if (IsEqualGUID(refiid, IID_IMemInputPin)) { + if (m_hPin == INVALID_HANDLE_VALUE) + { + HRESULT hr = CreatePin(&m_MediaFormat); + if (FAILED(hr)) + return hr; + } + *Output = (IMemInputPin*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; @@ -252,6 +282,13 @@ CInputPin::QueryInterface( } else if (IsEqualGUID(refiid, IID_IKsPropertySet)) { + if (m_hPin == INVALID_HANDLE_VALUE) + { + HRESULT hr = CreatePin(&m_MediaFormat); + if (FAILED(hr)) + return hr; + } + *Output = (IKsPropertySet*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; @@ -308,7 +345,6 @@ CInputPin::QueryInterface( return NOERROR; } - WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr); @@ -326,7 +362,10 @@ CInputPin::Notify( IBaseFilter *pSelf, Quality q) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Notify NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -335,7 +374,10 @@ STDMETHODCALLTYPE CInputPin::SetSink( IQualityControl *piqc) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::SetSink NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -348,7 +390,10 @@ STDMETHODCALLTYPE CInputPin::KsAddAggregate( IN REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::KsAddAggregate NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -357,7 +402,10 @@ STDMETHODCALLTYPE CInputPin::KsRemoveAggregate( REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::KsRemoveAggregate NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -381,7 +429,10 @@ CInputPin::Backout( IPin *ppinOut, IGraphBuilder *pGraph) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Backout\n"); +#endif + return S_OK; } @@ -394,7 +445,10 @@ STDMETHODCALLTYPE CInputPin::KsPinFactory( ULONG* PinFactory) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::KsPinFactory\n"); +#endif + *PinFactory = m_PinId; return S_OK; } @@ -570,7 +624,10 @@ HRESULT STDMETHODCALLTYPE CInputPin::GetAllocator(IMemAllocator **ppAllocator) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::GetAllocator\n"); +#endif + return VFW_E_NO_ALLOCATOR; } @@ -578,6 +635,17 @@ HRESULT STDMETHODCALLTYPE CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) { + HRESULT hr; + ALLOCATOR_PROPERTIES Properties; + + hr = pAllocator->GetProperties(&Properties); + +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CInputPin::NotifyAllocator hr %lx bReadOnly, %u cbAlign %u cbBuffer %u cbPrefix %u cBuffers %u\n", hr, bReadOnly, Properties.cbAlign, Properties.cbBuffer, Properties.cbPrefix, Properties.cBuffers); + OutputDebugStringW(Buffer); +#endif + if (pAllocator) { pAllocator->AddRef(); @@ -613,17 +681,28 @@ CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) pProps->cbBuffer = Framing.FrameSize; pProps->cbAlign = Framing.FileAlignment; pProps->cbPrefix = 0; - return hr; } else - return E_NOTIMPL; + hr = E_NOTIMPL; + +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CInputPin::GetAllocatorRequirements hr %lx m_hPin %p cBuffers %u cbBuffer %u cbAlign %u cbPrefix %u\n", hr, m_hPin, pProps->cBuffers, pProps->cbBuffer, pProps->cbAlign, pProps->cbPrefix); + OutputDebugStringW(Buffer); +#endif + + return hr; } HRESULT STDMETHODCALLTYPE CInputPin::Receive(IMediaSample *pSample) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Receive NotImplemented\n"); + DebugBreak(); +#endif + return E_NOTIMPL; } @@ -631,7 +710,11 @@ HRESULT STDMETHODCALLTYPE CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n"); + DebugBreak(); +#endif + return E_NOTIMPL; } @@ -639,7 +722,11 @@ HRESULT STDMETHODCALLTYPE CInputPin::ReceiveCanBlock( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n"); + DebugBreak(); +#endif + return S_FALSE; } @@ -652,7 +739,22 @@ STDMETHODCALLTYPE CInputPin::KsQueryMediums( PKSMULTIPLE_ITEM* MediumList) { - return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); + HRESULT hr; + IKsObject * KsObjectParent; + HANDLE hFilter; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); } HRESULT @@ -660,7 +762,22 @@ STDMETHODCALLTYPE CInputPin::KsQueryInterfaces( PKSMULTIPLE_ITEM* InterfaceList) { - return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); + HRESULT hr; + IKsObject * KsObjectParent; + HANDLE hFilter; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); } HRESULT @@ -669,8 +786,7 @@ CInputPin::KsCreateSinkPinHandle( KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium) { - OutputDebugStringW(L"CInputPin::KsCreateSinkPinHandle NotImplemented\n"); - return E_NOTIMPL; + return CreatePin(&m_MediaFormat); } HRESULT @@ -707,8 +823,25 @@ HRESULT STDMETHODCALLTYPE CInputPin::KsPropagateAcquire() { - OutputDebugStringW(L"CInputPin::KsPropagateAcquire NotImplemented\n"); - return E_NOTIMPL; + KSPROPERTY Property; + KSSTATE State; + ULONG BytesReturned; + HRESULT hr; + + assert(m_hPin != INVALID_HANDLE_VALUE); + + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + State = KSSTATE_ACQUIRE; + + hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); + + //TODO + //propagate to connected pin on the pipe + + return hr; } HRESULT @@ -744,6 +877,7 @@ HRESULT STDMETHODCALLTYPE CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator) { + if (MemAllocator) { MemAllocator->AddRef(); @@ -785,7 +919,11 @@ CInputPin::KsQualityNotify( ULONG Proportion, REFERENCE_TIME TimeDelta) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n"); +#endif + + DebugBreak(); return E_NOTIMPL; } @@ -799,7 +937,9 @@ CInputPin::KsNotifyError( IMediaSample* Sample, HRESULT hr) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n"); +#endif } @@ -815,7 +955,7 @@ CInputPin::KsProperty( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); + assert(m_hPin != INVALID_HANDLE_VALUE); return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); } @@ -828,7 +968,7 @@ CInputPin::KsMethod( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); + assert(m_hPin != INVALID_HANDLE_VALUE); return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); } @@ -841,7 +981,7 @@ CInputPin::KsEvent( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); + assert(m_hPin != INVALID_HANDLE_VALUE); if (EventLength) return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); @@ -972,7 +1112,10 @@ HRESULT STDMETHODCALLTYPE CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Connect NotImplemented\n"); + DebugBreak(); +#endif return NOERROR; } @@ -1023,7 +1166,10 @@ CInputPin::Disconnect( void) m_Pin->Release(); m_Pin = NULL; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Disconnect\n"); +#endif + return S_OK; } HRESULT @@ -1051,7 +1197,11 @@ CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) if (!m_Pin) return VFW_E_NOT_CONNECTED; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n"); + DebugBreak(); +#endif + return E_NOTIMPL; } HRESULT @@ -1103,9 +1253,23 @@ CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) HRESULT hr; ULONG MediaTypeCount = 0, Index; AM_MEDIA_TYPE * MediaTypes; + IKsObject * KsObjectParent; + HANDLE hFilter; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + // query media type count - hr = KsGetMediaTypeCount(m_hFilter, m_PinId, &MediaTypeCount); + hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); if (FAILED(hr) || !MediaTypeCount) return hr; @@ -1123,7 +1287,7 @@ CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) for(Index = 0; Index < MediaTypeCount; Index++) { // get media type - hr = KsGetMediaType(Index, &MediaTypes[Index], m_hFilter, m_PinId); + hr = KsGetMediaType(Index, &MediaTypes[Index], hFilter, m_PinId); if (FAILED(hr)) { // failed @@ -1139,35 +1303,45 @@ HRESULT STDMETHODCALLTYPE CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n"); +#endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CInputPin::EndOfStream( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n"); +#endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CInputPin::BeginFlush( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n"); +#endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CInputPin::EndFlush( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n"); +#endif return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -1178,60 +1352,49 @@ STDMETHODCALLTYPE CInputPin::CheckFormat( const AM_MEDIA_TYPE *pmt) { - KSP_PIN Property; PKSMULTIPLE_ITEM MultipleItem; PKSDATAFORMAT DataFormat; - ULONG BytesReturned; HRESULT hr; - - // prepare request - Property.Property.Set = KSPROPSETID_Pin; - Property.Property.Id = KSPROPERTY_PIN_DATARANGES; - Property.Property.Flags = KSPROPERTY_TYPE_GET; - Property.PinId = m_PinId; - Property.Reserved = 0; + IKsObject * KsObjectParent; + HANDLE hFilter; if (!pmt) return E_POINTER; - // query for size of dataranges - hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; - if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA)) + hFilter = KsObjectParent->KsGetObjectHandle(); + + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + + hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); + if (FAILED(hr)) + return S_FALSE; + + DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); + for(ULONG Index = 0; Index < MultipleItem->Count; Index++) { - // allocate dataranges buffer - MultipleItem = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned); - - if (!MultipleItem) - return E_OUTOFMEMORY; - - // query dataranges - hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); - - if (FAILED(hr)) + if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && + IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && + IsEqualGUID(pmt->formattype, DataFormat->Specifier)) { - // failed to query data ranges + // format is supported CoTaskMemFree(MultipleItem); - return hr; +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CheckFormat format OK\n"); +#endif + return S_OK; } - - DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); - for(ULONG Index = 0; Index < MultipleItem->Count; Index++) - { - if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && - IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && - IsEqualGUID(pmt->formattype, DataFormat->Specifier)) - { - // format is supported - CoTaskMemFree(MultipleItem); - OutputDebugStringW(L"CInputPin::CheckFormat format OK\n"); - return S_OK; - } - DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); - } - //format is not supported - CoTaskMemFree(MultipleItem); + DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); } + //format is not supported + CoTaskMemFree(MultipleItem); return S_FALSE; } @@ -1285,33 +1448,40 @@ CInputPin::CreatePin( if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) { - // now load the IKsInterfaceHandler plugin - hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); - if (FAILED(hr)) + if (!m_InterfaceHandler) { - // failed to load interface handler plugin - OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n"); - CoTaskMemFree(MediumList); - CoTaskMemFree(InterfaceList); + // now load the IKsInterfaceHandler plugin + hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); + if (FAILED(hr)) + { + // failed to load interface handler plugin +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePin failed to load InterfaceHandlerPlugin\n"); +#endif + CoTaskMemFree(MediumList); + CoTaskMemFree(InterfaceList); - return hr; + return hr; + } + + // now set the pin + hr = InterfaceHandler->KsSetPin((IKsPin*)this); + if (FAILED(hr)) + { + // failed to load interface handler plugin +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n"); +#endif + InterfaceHandler->Release(); + CoTaskMemFree(MediumList); + CoTaskMemFree(InterfaceList); + return hr; + } + + // store interface handler + m_InterfaceHandler = InterfaceHandler; } - // now set the pin - hr = InterfaceHandler->KsSetPin((IKsPin*)this); - if (FAILED(hr)) - { - // failed to load interface handler plugin - OutputDebugStringW(L"CInputPin::CreatePin failed to initialize InterfaceHandlerPlugin\n"); - InterfaceHandler->Release(); - CoTaskMemFree(MediumList); - CoTaskMemFree(InterfaceList); - return hr; - } - - // store interface handler - m_InterfaceHandler = InterfaceHandler; - // now create pin hr = CreatePinHandle(Medium, Interface, pmt); if (FAILED(hr)) @@ -1320,6 +1490,16 @@ CInputPin::CreatePin( m_InterfaceHandler = InterfaceHandler; } } + else + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); + OutputDebugStringW(Buffer); + DebugBreak(); +#endif + hr = E_FAIL; + } // free medium / interface / dataformat CoTaskMemFree(MediumList); @@ -1339,6 +1519,32 @@ CInputPin::CreatePinHandle( PKSDATAFORMAT DataFormat; ULONG Length; HRESULT hr; + IKsObject * KsObjectParent; + HANDLE hFilter; + + if (!pmt) + return E_POINTER; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + + if (m_hPin != INVALID_HANDLE_VALUE) + { + // pin already exists + //CloseHandle(m_hPin); + //m_hPin = INVALID_HANDLE_VALUE; + return S_OK; + } + // calc format size Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat; @@ -1378,7 +1584,73 @@ CInputPin::CreatePinHandle( } // create pin - hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin); + hr = KsCreatePin(hFilter, PinConnect, GENERIC_WRITE, &m_hPin); + + if (SUCCEEDED(hr)) + { + // store current interface / medium + CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); + CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); + CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE)); + +#ifdef KSPROXY_TRACE + LPOLESTR pMajor, pSub, pFormat; + StringFromIID(m_MediaFormat.majortype, &pMajor); + StringFromIID(m_MediaFormat.subtype , &pSub); + StringFromIID(m_MediaFormat.formattype, &pFormat); + + WCHAR Buffer[200]; + swprintf(Buffer, L"CInputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); + CoTaskMemFree(pMajor); + CoTaskMemFree(pSub); + CoTaskMemFree(pFormat); + OutputDebugStringW(Buffer); +#endif + + if (pmt->cbFormat) + { + m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); + if (!m_MediaFormat.pbFormat) + { + CoTaskMemFree(PinConnect); + m_MediaFormat.pbFormat = NULL; + m_MediaFormat.cbFormat = 0; + return E_OUTOFMEMORY; + } + CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); + } + + LPGUID pGuid; + ULONG NumGuids = 0; + + // get all supported sets + hr = GetSupportedSets(&pGuid, &NumGuids); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n"); +#endif + return hr; + } + + // load all proxy plugins + hr = LoadProxyPlugins(pGuid, NumGuids); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n"); +#endif + return hr; + } + + // free sets + CoTaskMemFree(pGuid); + + + //TODO + // connect pin pipes + + } // free pin connect CoTaskMemFree(PinConnect); @@ -1386,6 +1658,137 @@ CInputPin::CreatePinHandle( return hr; } +HRESULT +STDMETHODCALLTYPE +CInputPin::GetSupportedSets( + LPGUID * pOutGuid, + PULONG NumGuids) +{ + KSPROPERTY Property; + LPGUID pGuid; + ULONG NumProperty = 0; + ULONG NumMethods = 0; + ULONG NumEvents = 0; + ULONG Length; + ULONG BytesReturned; + HRESULT hr; + + Property.Set = GUID_NULL; + Property.Id = 0; + Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; + + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); + + Length = NumProperty + NumMethods + NumEvents; + + // allocate guid buffer + pGuid = (LPGUID)CoTaskMemAlloc(Length); + if (!pGuid) + { + // failed + return E_OUTOFMEMORY; + } + + NumProperty /= sizeof(GUID); + NumMethods /= sizeof(GUID); + NumEvents /= sizeof(GUID); + + // get all properties + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + + // get all methods + if (Length) + { + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + } + + // get all events + if (Length) + { + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + } + +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; + swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); + OutputDebugStringW(Buffer); +#endif + + *pOutGuid = pGuid; + *NumGuids = NumProperty+NumEvents+NumMethods; + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CInputPin::LoadProxyPlugins( + LPGUID pGuids, + ULONG NumGuids) +{ + ULONG Index; + LPOLESTR pStr; + HKEY hKey, hSubKey; + HRESULT hr; + IUnknown * pUnknown; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + OutputDebugStringW(L"CInputPin::LoadProxyPlugins failed to open MediaInterfaces key\n"); + return E_FAIL; + } + + // enumerate all sets + for(Index = 0; Index < NumGuids; Index++) + { + // convert to string + hr = StringFromCLSID(pGuids[Index], &pStr); + if (FAILED(hr)) + return E_FAIL; + + // now try open class key + if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) + { + // no plugin for that set exists + CoTaskMemFree(pStr); + continue; + } + + // try load plugin + hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); + if (SUCCEEDED(hr)) + { + // store plugin + m_Plugins.push_back(pUnknown); + } + // close key + RegCloseKey(hSubKey); + } + + // close media interfaces key + RegCloseKey(hKey); + return S_OK; +} + HRESULT WINAPI CInputPin_Constructor( @@ -1397,7 +1800,7 @@ CInputPin_Constructor( REFIID riid, LPVOID * ppv) { - CInputPin * handler = new CInputPin(ParentFilter, PinName, hFilter, PinId, Communication); + CInputPin * handler = new CInputPin(ParentFilter, PinName, PinId, Communication); if (!handler) return E_OUTOFMEMORY; diff --git a/dll/directx/ksproxy/interface.cpp b/dll/directx/ksproxy/interface.cpp index 930f7e00b73..7eb0fd284d5 100644 --- a/dll/directx/ksproxy/interface.cpp +++ b/dll/directx/ksproxy/interface.cpp @@ -35,24 +35,25 @@ public: HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment); HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment); - CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0){}; + CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0) {m_PinName[0] = L'\0';}; virtual ~CKsInterfaceHandler(){}; protected: LONG m_Ref; HANDLE m_Handle; IKsPinEx * m_Pin; + WCHAR m_PinName[129]; }; typedef struct { KSSTREAM_SEGMENT StreamSegment; + OVERLAPPED Overlapped; IMediaSample * MediaSample[64]; ULONG SampleCount; ULONG ExtendedSize; PKSSTREAM_HEADER StreamHeader; - OVERLAPPED Overlapped; }KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT; @@ -118,6 +119,22 @@ CKsInterfaceHandler::KsSetPin( Pin->Release(); } } +#if 1 + //DBG code + PIN_INFO PinInfo; + IPin * pPin; + if (SUCCEEDED(KsPin->QueryInterface(IID_IPin, (void**)&pPin))) + { + if (SUCCEEDED(pPin->QueryPinInfo(&PinInfo))) + { + if (PinInfo.pFilter) + PinInfo.pFilter->Release(); + + wcscpy(m_PinName, PinInfo.achName); + } + pPin->Release(); + } +#endif // done return hr; @@ -136,8 +153,6 @@ CKsInterfaceHandler::KsProcessMediaSamples( ULONG ExtendedSize, Index, BytesReturned; HRESULT hr = S_OK; - OutputDebugString("CKsInterfaceHandler::KsProcessMediaSamples\n"); - // sanity check assert(*SampleCount); @@ -237,6 +252,7 @@ CKsInterfaceHandler::KsProcessMediaSamples( // query for IMediaSample2 interface IMediaSample2 * MediaSample; AM_SAMPLE2_PROPERTIES Properties; + ZeroMemory(&Properties, sizeof(AM_SAMPLE2_PROPERTIES)); hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample); if (SUCCEEDED(hr)) @@ -254,7 +270,9 @@ CKsInterfaceHandler::KsProcessMediaSamples( hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer); assert(hr == NOERROR); hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop); - assert(hr == NOERROR); + + Properties.cbBuffer = SampleList[Index]->GetSize(); + assert(Properties.cbBuffer); Properties.dwSampleFlags = 0; @@ -267,10 +285,11 @@ CKsInterfaceHandler::KsProcessMediaSamples( if (SampleList[Index]->IsSyncPoint() == S_OK) Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; } - - WCHAR Buffer[100]; - swprintf(Buffer, L"BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u\n", Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual); +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; + swprintf(Buffer, L"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u dwSampleFlags %lx\n", m_PinName, Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual, Properties.dwSampleFlags); OutputDebugStringW(Buffer); +#endif CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize; CurStreamHeader->PresentationTime.Denominator = 1; @@ -336,8 +355,6 @@ CKsInterfaceHandler::KsCompleteIo( AM_SAMPLE2_PROPERTIES Properties; REFERENCE_TIME Start, Stop; - OutputDebugStringW(L"CKsInterfaceHandler::KsCompleteIo\n"); - // get private stream segment StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment; @@ -463,7 +480,9 @@ CKsInterfaceHandler_Constructor( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsInterfaceHandler_Constructor\n"); +#endif CKsInterfaceHandler * handler = new CKsInterfaceHandler(); diff --git a/dll/directx/ksproxy/ksproxy.cpp b/dll/directx/ksproxy/ksproxy.cpp index f79a154574b..f1e17c96922 100644 --- a/dll/directx/ksproxy/ksproxy.cpp +++ b/dll/directx/ksproxy/ksproxy.cpp @@ -117,7 +117,7 @@ KsOpenDefaultDevice( WCHAR Path[MAX_PATH+sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)]; /* open device list */ - hList = SetupDiGetClassDevsW(&Category, NULL, NULL, DIGCF_DEVICEINTERFACE /* | DIGCF_PRESENT*/); + hList = SetupDiGetClassDevsW(&Category, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (hList == INVALID_HANDLE_VALUE) { @@ -129,7 +129,7 @@ KsOpenDefaultDevice( DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (SetupDiEnumDeviceInterfaces(hList, &DeviceInfoData, &Category, 0, &DeviceInterfaceData)) + if (SetupDiEnumDeviceInterfaces(hList, NULL, &Category, 0, &DeviceInterfaceData)) { /* setup interface data struct */ DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)Path; diff --git a/dll/directx/ksproxy/ksproxy.rbuild b/dll/directx/ksproxy/ksproxy.rbuild index e5bc87e9b4a..86cd50a2c1d 100644 --- a/dll/directx/ksproxy/ksproxy.rbuild +++ b/dll/directx/ksproxy/ksproxy.rbuild @@ -20,7 +20,7 @@ /GR- - + allocator.cpp basicaudio.cpp classfactory.cpp clockforward.cpp @@ -33,6 +33,7 @@ interface.cpp ksproxy.cpp ksproxy.rc + mediasample.cpp node.cpp output_pin.cpp proxy.cpp diff --git a/dll/directx/ksproxy/mediasample.cpp b/dll/directx/ksproxy/mediasample.cpp new file mode 100644 index 00000000000..e0411938444 --- /dev/null +++ b/dll/directx/ksproxy/mediasample.cpp @@ -0,0 +1,368 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy + * FILE: dll/directx/ksproxy/mediasample.cpp + * PURPOSE: IMediaSample interface + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +class CMediaSample : public IMediaSample +{ +public: + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); + + STDMETHODIMP_(ULONG) AddRef() + { + InterlockedIncrement(&m_Ref); + return m_Ref; + } + STDMETHODIMP_(ULONG) Release() + { + InterlockedDecrement(&m_Ref); + DebugBreak(); + if (!m_Ref) + { + if (m_Allocator) + { + m_Allocator->ReleaseBuffer((IMediaSample*)this); + return 0; + } + delete this; + return 0; + } + return m_Ref; + } + + HRESULT STDMETHODCALLTYPE GetPointer(BYTE **ppBuffer); + long STDMETHODCALLTYPE GetSize(void); + HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd); + HRESULT STDMETHODCALLTYPE SetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd); + HRESULT STDMETHODCALLTYPE IsSyncPoint(); + HRESULT STDMETHODCALLTYPE SetSyncPoint(BOOL bIsSyncPoint); + HRESULT STDMETHODCALLTYPE IsPreroll(); + HRESULT STDMETHODCALLTYPE SetPreroll(BOOL bIsPreroll); + long STDMETHODCALLTYPE GetActualDataLength(); + HRESULT STDMETHODCALLTYPE SetActualDataLength(long Length); + HRESULT STDMETHODCALLTYPE GetMediaType(AM_MEDIA_TYPE **ppMediaType); + HRESULT STDMETHODCALLTYPE SetMediaType(AM_MEDIA_TYPE *pMediaType); + HRESULT STDMETHODCALLTYPE IsDiscontinuity(); + HRESULT STDMETHODCALLTYPE SetDiscontinuity(BOOL bDiscontinuity); + HRESULT STDMETHODCALLTYPE GetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd); + HRESULT STDMETHODCALLTYPE SetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd); + + CMediaSample(IMemAllocator * Allocator, BYTE * Buffer, LONG BufferSize); + virtual ~CMediaSample(){} + +protected: + ULONG m_Flags; + ULONG m_TypeFlags; + BYTE * m_Buffer; + LONG m_ActualLength; + LONG m_BufferSize; + IMemAllocator * m_Allocator; + CMediaSample * m_Next; + REFERENCE_TIME m_StartTime; + REFERENCE_TIME m_StopTime; + LONGLONG m_MediaStart; + LONGLONG m_MediaStop; + AM_MEDIA_TYPE * m_MediaType; + ULONG m_StreamId; + +public: + LONG m_Ref; + + BOOL m_bMediaTimeValid; + + +}; + +CMediaSample::CMediaSample( + IMemAllocator * Allocator, + BYTE * Buffer, + LONG BufferSize) : + m_Flags(0), + m_TypeFlags(0), + m_Buffer(Buffer), + m_ActualLength(BufferSize), + m_BufferSize(BufferSize), + m_Allocator(Allocator), + m_Next(0), + m_StartTime(0), + m_StopTime(0), + m_MediaStart(0), + m_MediaStop(0), + m_MediaType(0), + m_StreamId(0), + m_Ref(0), + m_bMediaTimeValid(0) +{ +} + + +HRESULT +STDMETHODCALLTYPE +CMediaSample::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + if (IsEqualGUID(refiid, IID_IUnknown) || + IsEqualGUID(refiid, IID_IMediaSample)) + { + *Output = PVOID(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + if (IsEqualGUID(refiid, IID_IMediaSample2)) + { +#if 0 + *Output = (IMediaSample2*)(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; +#endif + } + + return E_NOINTERFACE; +} + +//------------------------------------------------------------------- +// IMediaSample interface +// +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetPointer( + BYTE **ppBuffer) +{ + if (!ppBuffer) + return E_POINTER; + + *ppBuffer = m_Buffer; + return S_OK; +} + +long +STDMETHODCALLTYPE +CMediaSample::GetSize() +{ + return m_BufferSize; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetTime( + REFERENCE_TIME *pTimeStart, + REFERENCE_TIME *pTimeEnd) +{ + HRESULT hr; + + if (!pTimeStart || !pTimeEnd) + return E_POINTER; + + if (!(m_Flags & (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID))) + { + // no time is set + return VFW_E_SAMPLE_TIME_NOT_SET; + } + + *pTimeStart = m_StartTime; + + if (m_Flags & AM_SAMPLE_STOPVALID) + { + *pTimeEnd = m_StopTime; + hr = NOERROR; + } + else + { + *pTimeEnd = m_StartTime + 1; + hr = VFW_S_NO_STOP_TIME; + } + return hr; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetTime(REFERENCE_TIME *pTimeStart, REFERENCE_TIME *pTimeEnd) +{ + if (!pTimeStart) + { + m_Flags &= ~(AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID); + return NOERROR; + } + + if (!pTimeEnd) + { + m_Flags &= ~(AM_SAMPLE_STOPVALID); + m_Flags |= AM_SAMPLE_TIMEVALID; + m_StartTime = *pTimeStart; + return NOERROR; + } + + + m_Flags |= (AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID); + m_StartTime = *pTimeStart; + m_StopTime = *pTimeEnd; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsSyncPoint() +{ + return (m_Flags & AM_SAMPLE_SPLICEPOINT) ? S_OK : S_FALSE; +} +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetSyncPoint(BOOL bIsSyncPoint) +{ + if (bIsSyncPoint) + m_Flags |= AM_SAMPLE_SPLICEPOINT; + else + m_Flags &= ~AM_SAMPLE_SPLICEPOINT; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsPreroll() +{ + return (m_Flags & AM_SAMPLE_PREROLL) ? S_OK : S_FALSE; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetPreroll(BOOL bIsPreroll) +{ + if (bIsPreroll) + m_Flags |= AM_SAMPLE_PREROLL; + else + m_Flags &= ~AM_SAMPLE_PREROLL; + + return NOERROR; +} + +long +STDMETHODCALLTYPE +CMediaSample::GetActualDataLength() +{ + return m_ActualLength; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetActualDataLength(long Length) +{ + if (Length > m_BufferSize) + return VFW_E_BUFFER_OVERFLOW; + + m_ActualLength = Length; + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetMediaType(AM_MEDIA_TYPE **ppMediaType) +{ + if (!m_MediaType) + { + *ppMediaType = NULL; + return S_FALSE; + } + + assert(0); + return E_NOTIMPL; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetMediaType(AM_MEDIA_TYPE *pMediaType) +{ + OutputDebugStringW(L"CMediaSample::SetMediaType NotImplemented\n"); + DebugBreak(); + return E_NOTIMPL; +} + + +HRESULT +STDMETHODCALLTYPE +CMediaSample::IsDiscontinuity() +{ + return (m_Flags & AM_SAMPLE_DATADISCONTINUITY) ? S_OK : S_FALSE; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetDiscontinuity(BOOL bDiscontinuity) +{ + if (bDiscontinuity) + m_Flags |= AM_SAMPLE_DATADISCONTINUITY; + else + m_Flags &= ~AM_SAMPLE_DATADISCONTINUITY; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::GetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd) +{ + if (!pTimeStart || !pTimeEnd) + return E_POINTER; + + if (!m_bMediaTimeValid) + return VFW_E_MEDIA_TIME_NOT_SET; + + m_MediaStart = *pTimeStart; + m_MediaStop = *pTimeEnd; + + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +CMediaSample::SetMediaTime(LONGLONG *pTimeStart, LONGLONG *pTimeEnd) +{ + if (!pTimeStart || !pTimeEnd) + { + m_bMediaTimeValid = false; + return NOERROR; + } + + m_MediaStart = *pTimeStart; + m_MediaStop = *pTimeEnd; + + return NOERROR; +} + + + + +HRESULT +WINAPI +CMediaSample_Constructor( + IMemAllocator* Allocator, + BYTE* pBuffer, + ULONG BufferSize, + REFIID riid, + LPVOID * ppv) +{ +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CMediaSample_Constructor\n"); +#endif + + CMediaSample * handler = new CMediaSample(Allocator, pBuffer, BufferSize); + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return NOERROR; +} diff --git a/dll/directx/ksproxy/node.cpp b/dll/directx/ksproxy/node.cpp index d2686bb96a4..d3082255346 100644 --- a/dll/directx/ksproxy/node.cpp +++ b/dll/directx/ksproxy/node.cpp @@ -124,7 +124,9 @@ CKsNode_Constructor( HANDLE handle; KSNODE_CREATE NodeCreate; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsNode_Constructor\n"); +#endif //setup request NodeCreate.CreateFlags = 0; diff --git a/dll/directx/ksproxy/output_pin.cpp b/dll/directx/ksproxy/output_pin.cpp index 52f9cc94f7a..c2227caf421 100644 --- a/dll/directx/ksproxy/output_pin.cpp +++ b/dll/directx/ksproxy/output_pin.cpp @@ -26,6 +26,8 @@ class COutputPin : public IPin, { public: + typedef std::vectorProxyPluginVector; + STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); STDMETHODIMP_(ULONG) AddRef() @@ -154,8 +156,19 @@ public: //IMemAllocatorNotifyCallbackTemp HRESULT STDMETHODCALLTYPE NotifyRelease(); - COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId); + //--------------------------------------------------------------- + COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, KSPIN_COMMUNICATION Communication); virtual ~COutputPin(); + HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt); + HRESULT WINAPI IoProcessRoutine(); + HRESULT WINAPI InitializeIOThread(); + HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); + HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); + + friend DWORD WINAPI COutputPin_IoThreadStartup(LPVOID lpParameter); + friend HRESULT STDMETHODCALLTYPE COutputPin_SetState(IPin * Pin, KSSTATE State); protected: LONG m_Ref; @@ -163,7 +176,6 @@ protected: LPCWSTR m_PinName; HANDLE m_hPin; ULONG m_PinId; - IKsObject * m_KsObjectParent; IPin * m_Pin; IKsAllocatorEx * m_KsAllocatorEx; ULONG m_PipeAllocatorFlag; @@ -174,48 +186,73 @@ protected: PKSALLOCATOR_FRAMING_EX m_FramingEx[4]; IMemAllocator * m_MemAllocator; + IMemInputPin * m_MemInputPin; LONG m_IoCount; KSPIN_COMMUNICATION m_Communication; KSPIN_INTERFACE m_Interface; KSPIN_MEDIUM m_Medium; - IMediaSeeking * m_FilterMediaSeeking; + AM_MEDIA_TYPE m_MediaFormat; + ALLOCATOR_PROPERTIES m_Properties; + IKsInterfaceHandler * m_InterfaceHandler; + + HANDLE m_hStartEvent; + HANDLE m_hBufferAvailable; + HANDLE m_hStopEvent; + BOOL m_StopInProgress; + BOOL m_IoThreadStarted; + + KSSTATE m_State; + CRITICAL_SECTION m_Lock; + + ProxyPluginVector m_Plugins; }; COutputPin::~COutputPin() { - if (m_KsObjectParent) - m_KsObjectParent->Release(); } COutputPin::COutputPin( IBaseFilter * ParentFilter, LPCWSTR PinName, - ULONG PinId) : m_Ref(0), - m_ParentFilter(ParentFilter), - m_PinName(PinName), - m_hPin(INVALID_HANDLE_VALUE), - m_PinId(PinId), - m_KsObjectParent(0), - m_Pin(0), - m_KsAllocatorEx(0), - m_PipeAllocatorFlag(0), - m_bPinBusCacheInitialized(0), - m_FilterName(0), - m_MemAllocator(0), - m_IoCount(0), - m_Communication(KSPIN_COMMUNICATION_NONE), - m_FilterMediaSeeking(0) + ULONG PinId, + KSPIN_COMMUNICATION Communication) : m_Ref(0), + m_ParentFilter(ParentFilter), + m_PinName(PinName), + m_hPin(INVALID_HANDLE_VALUE), + m_PinId(PinId), + m_Pin(0), + m_KsAllocatorEx(0), + m_PipeAllocatorFlag(0), + m_bPinBusCacheInitialized(0), + m_FilterName(0), + m_MemAllocator(0), + m_MemInputPin(0), + m_IoCount(0), + m_Communication(Communication), + m_InterfaceHandler(0), + m_hStartEvent(0), + m_hBufferAvailable(0), + m_hStopEvent(0), + m_StopInProgress(0), + m_IoThreadStarted(0), + m_State(KSSTATE_STOP), + m_Plugins() { HRESULT hr; + IKsObject * KsObjectParent; - hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&m_KsObjectParent); - assert(hr == S_OK); - - hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&m_FilterMediaSeeking); + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); assert(hr == S_OK); ZeroMemory(m_FramingProp, sizeof(m_FramingProp)); ZeroMemory(m_FramingEx, sizeof(m_FramingEx)); + + hr = KsGetMediaType(0, &m_MediaFormat, KsObjectParent->KsGetObjectHandle(), m_PinId); + assert(hr == S_OK); + + InitializeCriticalSection(&m_Lock); + + KsObjectParent->Release(); }; HRESULT @@ -228,14 +265,24 @@ COutputPin::QueryInterface( if (IsEqualGUID(refiid, IID_IUnknown) || IsEqualGUID(refiid, IID_IPin)) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IPin\n"); +#endif *Output = PVOID(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsObject)) { + if (m_hPin == INVALID_HANDLE_VALUE) + { + HRESULT hr = CreatePin(&m_MediaFormat); + if (FAILED(hr)) + return hr; + } +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsObject\n"); +#endif *Output = (IKsObject*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; @@ -266,15 +313,24 @@ COutputPin::QueryInterface( } else if (IsEqualGUID(refiid, IID_IKsPropertySet)) { + if (m_hPin == INVALID_HANDLE_VALUE) + { + HRESULT hr = CreatePin(&m_MediaFormat); + if (FAILED(hr)) + return hr; + } +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPropertySet\n"); - DebugBreak(); +#endif *Output = (IKsPropertySet*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_IKsControl)) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsControl\n"); +#endif *Output = (IKsControl*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; @@ -289,14 +345,18 @@ COutputPin::QueryInterface( #endif else if (IsEqualGUID(refiid, IID_IKsPinFactory)) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_IKsPinFactory\n"); +#endif *Output = (IKsPinFactory*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; } else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryInterface IID_ISpecifyPropertyPages\n"); +#endif *Output = (ISpecifyPropertyPages*)(this); reinterpret_cast(*Output)->AddRef(); return NOERROR; @@ -326,12 +386,14 @@ COutputPin::QueryInterface( return NOERROR; } +#ifdef KSPROXY_TRACE WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); - swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s\n", lpstr); + swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s PinId %u PinName %s\n", lpstr, m_PinId, m_PinName); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); +#endif return E_NOINTERFACE; } @@ -344,8 +406,18 @@ STDMETHODCALLTYPE COutputPin::SuggestAllocatorProperties( const ALLOCATOR_PROPERTIES *pprop) { - OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties NotImplemented\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"COutputPin::SuggestAllocatorProperties\n"); +#endif + + if (m_Pin) + { + // pin is already connected + return VFW_E_ALREADY_CONNECTED; + } + + CopyMemory(&m_Properties, pprop, sizeof(ALLOCATOR_PROPERTIES)); + return NOERROR; } HRESULT @@ -353,8 +425,24 @@ STDMETHODCALLTYPE COutputPin::GetAllocatorProperties( ALLOCATOR_PROPERTIES *pprop) { - OutputDebugStringW(L"COutputPin::GetAllocatorProperties NotImplemented\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"COutputPin::GetAllocatorProperties\n"); +#endif + + if (!m_Pin) + { + // you should call this method AFTER you connected + return E_UNEXPECTED; + } + + if (!m_KsAllocatorEx) + { + // something went wrong while creating the allocator + return E_FAIL; + } + + CopyMemory(pprop, &m_Properties, sizeof(ALLOCATOR_PROPERTIES)); + return NOERROR; } //------------------------------------------------------------------- @@ -365,7 +453,9 @@ STDMETHODCALLTYPE COutputPin::SetFormat( AM_MEDIA_TYPE *pmt) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::SetFormat NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -373,7 +463,9 @@ HRESULT STDMETHODCALLTYPE COutputPin::GetFormat(AM_MEDIA_TYPE **ppmt) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetFormat NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -383,7 +475,9 @@ COutputPin::GetNumberOfCapabilities( int *piCount, int *piSize) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetNumberOfCapabilities NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -394,7 +488,9 @@ COutputPin::GetStreamCaps( AM_MEDIA_TYPE **ppmt, BYTE *pSCC) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetStreamCaps NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -405,8 +501,14 @@ HRESULT STDMETHODCALLTYPE COutputPin::NotifyRelease() { - OutputDebugStringW(L"COutputPin::NotifyRelease NotImplemented\n"); - return E_NOTIMPL; +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"COutputPin::NotifyRelease\n"); +#endif + + // notify thread of new available sample + SetEvent(m_hBufferAvailable); + + return NOERROR; } //------------------------------------------------------------------- @@ -417,7 +519,17 @@ STDMETHODCALLTYPE COutputPin::GetCapabilities( DWORD *pCapabilities) { - return m_FilterMediaSeeking->GetCapabilities(pCapabilities); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetCapabilities(pCapabilities); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -425,7 +537,17 @@ STDMETHODCALLTYPE COutputPin::CheckCapabilities( DWORD *pCapabilities) { - return m_FilterMediaSeeking->CheckCapabilities(pCapabilities); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->CheckCapabilities(pCapabilities); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -433,7 +555,17 @@ STDMETHODCALLTYPE COutputPin::IsFormatSupported( const GUID *pFormat) { - return m_FilterMediaSeeking->IsFormatSupported(pFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->IsFormatSupported(pFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -441,7 +573,17 @@ STDMETHODCALLTYPE COutputPin::QueryPreferredFormat( GUID *pFormat) { - return m_FilterMediaSeeking->QueryPreferredFormat(pFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->QueryPreferredFormat(pFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -449,7 +591,17 @@ STDMETHODCALLTYPE COutputPin::GetTimeFormat( GUID *pFormat) { - return m_FilterMediaSeeking->GetTimeFormat(pFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetTimeFormat(pFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -457,7 +609,17 @@ STDMETHODCALLTYPE COutputPin::IsUsingTimeFormat( const GUID *pFormat) { - return m_FilterMediaSeeking->IsUsingTimeFormat(pFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->IsUsingTimeFormat(pFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -465,7 +627,17 @@ STDMETHODCALLTYPE COutputPin::SetTimeFormat( const GUID *pFormat) { - return m_FilterMediaSeeking->SetTimeFormat(pFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->SetTimeFormat(pFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -473,7 +645,17 @@ STDMETHODCALLTYPE COutputPin::GetDuration( LONGLONG *pDuration) { - return m_FilterMediaSeeking->GetDuration(pDuration); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetDuration(pDuration); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -481,7 +663,17 @@ STDMETHODCALLTYPE COutputPin::GetStopPosition( LONGLONG *pStop) { - return m_FilterMediaSeeking->GetStopPosition(pStop); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetStopPosition(pStop); + + FilterMediaSeeking->Release(); + return hr; } @@ -490,7 +682,17 @@ STDMETHODCALLTYPE COutputPin::GetCurrentPosition( LONGLONG *pCurrent) { - return m_FilterMediaSeeking->GetCurrentPosition(pCurrent); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetCurrentPosition(pCurrent); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -501,7 +703,17 @@ COutputPin::ConvertTimeFormat( LONGLONG Source, const GUID *pSourceFormat) { - return m_FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -512,7 +724,17 @@ COutputPin::SetPositions( LONGLONG *pStop, DWORD dwStopFlags) { - return m_FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -521,7 +743,17 @@ COutputPin::GetPositions( LONGLONG *pCurrent, LONGLONG *pStop) { - return m_FilterMediaSeeking->GetPositions(pCurrent, pStop); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetPositions(pCurrent, pStop); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -530,7 +762,17 @@ COutputPin::GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest) { - return m_FilterMediaSeeking->GetAvailable(pEarliest, pLatest); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetAvailable(pEarliest, pLatest); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -538,7 +780,17 @@ STDMETHODCALLTYPE COutputPin::SetRate( double dRate) { - return m_FilterMediaSeeking->SetRate(dRate); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->SetRate(dRate); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -546,7 +798,17 @@ STDMETHODCALLTYPE COutputPin::GetRate( double *pdRate) { - return m_FilterMediaSeeking->GetRate(pdRate); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetRate(pdRate); + + FilterMediaSeeking->Release(); + return hr; } HRESULT @@ -554,7 +816,17 @@ STDMETHODCALLTYPE COutputPin::GetPreroll( LONGLONG *pllPreroll) { - return m_FilterMediaSeeking->GetPreroll(pllPreroll); + IMediaSeeking * FilterMediaSeeking; + HRESULT hr; + + hr = m_ParentFilter->QueryInterface(IID_IMediaSeeking, (LPVOID*)&FilterMediaSeeking); + if (FAILED(hr)) + return hr; + + hr = FilterMediaSeeking->GetPreroll(pllPreroll); + + FilterMediaSeeking->Release(); + return hr; } //------------------------------------------------------------------- @@ -566,7 +838,9 @@ COutputPin::Notify( IBaseFilter *pSelf, Quality q) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Notify NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -575,7 +849,9 @@ STDMETHODCALLTYPE COutputPin::SetSink( IQualityControl *piqc) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::SetSink NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -588,7 +864,9 @@ STDMETHODCALLTYPE COutputPin::KsAddAggregate( IN REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsAddAggregate NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -597,7 +875,9 @@ STDMETHODCALLTYPE COutputPin::KsRemoveAggregate( REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsRemoveAggregate NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -611,8 +891,24 @@ STDMETHODCALLTYPE COutputPin::KsQueryMediums( PKSMULTIPLE_ITEM* MediumList) { - HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle(); - return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); + HRESULT hr; + HANDLE hFilter; + IKsObject * KsObjectParent; + + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return E_NOINTERFACE; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + if (hFilter) + hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList); + else + hr = E_HANDLE; + + KsObjectParent->Release(); + + return hr; } HRESULT @@ -620,9 +916,24 @@ STDMETHODCALLTYPE COutputPin::KsQueryInterfaces( PKSMULTIPLE_ITEM* InterfaceList) { - HANDLE hFilter = m_KsObjectParent->KsGetObjectHandle(); + HRESULT hr; + HANDLE hFilter; + IKsObject * KsObjectParent; - return KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + hFilter = KsObjectParent->KsGetObjectHandle(); + + if (hFilter) + hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList); + else + hr = E_HANDLE; + + KsObjectParent->Release(); + + return hr; } HRESULT @@ -631,7 +942,9 @@ COutputPin::KsCreateSinkPinHandle( KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsCreateSinkPinHandle NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -669,8 +982,33 @@ HRESULT STDMETHODCALLTYPE COutputPin::KsPropagateAcquire() { - OutputDebugStringW(L"COutputPin::KsPropagateAcquire NotImplemented\n"); - return E_NOTIMPL; + KSPROPERTY Property; + KSSTATE State; + ULONG BytesReturned; + HRESULT hr; + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"COutputPin::KsPropagateAcquire\n"); +#endif + + assert(m_hPin != INVALID_HANDLE_VALUE); + + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + State = KSSTATE_ACQUIRE; + + hr = KsProperty(&Property, sizeof(KSPROPERTY), (LPVOID)&State, sizeof(KSSTATE), &BytesReturned); + if (SUCCEEDED(hr)) + { + m_State = State; + } + + //TODO + //propagate to connected pin on the pipe + + return hr; } HRESULT @@ -747,7 +1085,9 @@ COutputPin::KsQualityNotify( ULONG Proportion, REFERENCE_TIME TimeDelta) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsQualityNotify NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -761,7 +1101,9 @@ COutputPin::KsNotifyError( IMediaSample* Sample, HRESULT hr) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsNotifyError NotImplemented\n"); +#endif } @@ -918,7 +1260,9 @@ HRESULT STDMETHODCALLTYPE COutputPin::GetPages(CAUUID *pPages) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::GetPages NotImplemented\n"); +#endif if (!pPages) return E_POINTER; @@ -938,7 +1282,10 @@ STDMETHODCALLTYPE COutputPin::KsPinFactory( ULONG* PinFactory) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsPinFactory\n"); +#endif + *PinFactory = m_PinId; return S_OK; } @@ -954,7 +1301,9 @@ COutputPin::Render( IPin *ppinOut, IGraphBuilder *pGraph) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Render\n"); +#endif return S_OK; } @@ -964,7 +1313,10 @@ COutputPin::Backout( IPin *ppinOut, IGraphBuilder *pGraph) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Backout\n"); +#endif + return S_OK; } //------------------------------------------------------------------- @@ -974,8 +1326,11 @@ HANDLE STDMETHODCALLTYPE COutputPin::KsGetObjectHandle() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsGetObjectHandle\n"); - assert(m_hPin); +#endif + + assert(m_hPin != INVALID_HANDLE_VALUE); return m_hPin; } @@ -991,9 +1346,20 @@ COutputPin::KsProperty( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); - OutputDebugStringW(L"COutputPin::KsProperty\n"); - return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); + HRESULT hr; + + assert(m_hPin != INVALID_HANDLE_VALUE); + + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + LPOLESTR pstr; + StringFromCLSID(Property->Set, &pstr); + swprintf(Buffer, L"COutputPin::KsProperty Set %s Id %lu Flags %x hr %x\n", pstr, Property->Id, Property->Flags, hr); + OutputDebugStringW(Buffer); +#endif + + return hr; } HRESULT @@ -1005,8 +1371,10 @@ COutputPin::KsMethod( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); + assert(m_hPin != INVALID_HANDLE_VALUE); +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsMethod\n"); +#endif return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); } @@ -1019,9 +1387,11 @@ COutputPin::KsEvent( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hPin != 0); + assert(m_hPin != INVALID_HANDLE_VALUE); +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::KsEvent\n"); +#endif if (EventLength) return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); @@ -1045,8 +1415,6 @@ COutputPin::Set( { ULONG BytesReturned; - OutputDebugStringW(L"COutputPin::Set\n"); - if (cbInstanceData) { PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); @@ -1089,8 +1457,6 @@ COutputPin::Get( { ULONG BytesReturned; - OutputDebugStringW(L"COutputPin::Get\n"); - if (cbInstanceData) { PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); @@ -1130,7 +1496,9 @@ COutputPin::QuerySupported( KSPROPERTY Property; ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QuerySupported\n"); +#endif Property.Set = guidPropSet; Property.Id = dwPropID; @@ -1147,11 +1515,15 @@ HRESULT STDMETHODCALLTYPE COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { - AM_MEDIA_TYPE MediaType; HRESULT hr; - HANDLE hFilter; + ALLOCATOR_PROPERTIES Properties; + IMemAllocatorCallbackTemp *pMemCallback; +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; OutputDebugStringW(L"COutputPin::Connect called\n"); +#endif + if (pmt) { hr = pReceivePin->QueryAccept(pmt); @@ -1160,24 +1532,128 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) } else { - // get parent filter handle - hFilter = m_KsObjectParent->KsGetObjectHandle(); - - // get media type count - ZeroMemory(&MediaType, sizeof(AM_MEDIA_TYPE)); - hr = KsGetMediaType(0, &MediaType, hFilter, m_PinId); - if (FAILED(hr)) - return hr; - // query accept - hr = pReceivePin->QueryAccept(&MediaType); + hr = pReceivePin->QueryAccept(&m_MediaFormat); if (FAILED(hr)) return hr; - pmt = &MediaType; + pmt = &m_MediaFormat; } - //FIXME create pin handle + // query for IMemInput interface + hr = pReceivePin->QueryInterface(IID_IMemInputPin, (void**)&m_MemInputPin); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n"); +#endif + + DebugBreak(); + return hr; + } + + // get input pin allocator properties + ZeroMemory(&Properties, sizeof(ALLOCATOR_PROPERTIES)); + m_MemInputPin->GetAllocatorRequirements(&Properties); + + //FIXME determine allocator properties + Properties.cBuffers = 32; + Properties.cbBuffer = 2048 * 188; //2048 frames * MPEG2 TS Payload size + Properties.cbAlign = 4; + + // get input pin allocator +#if 0 + hr = m_MemInputPin->GetAllocator(&m_MemAllocator); + if (SUCCEEDED(hr)) + { + // set allocator properties + hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); + if (FAILED(hr)) + m_MemAllocator->Release(); + } +#endif + + if (1) + { + hr = CKsAllocator_Constructor(NULL, IID_IMemAllocator, (void**)&m_MemAllocator); + if (FAILED(hr)) + return hr; + + // set allocator properties + hr = m_MemAllocator->SetProperties(&Properties, &m_Properties); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::Connect IMemAllocator::SetProperties failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + } + + // commit property changes + hr = m_MemAllocator->Commit(); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::Connect IMemAllocator::Commit failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // get callback interface + hr = m_MemAllocator->QueryInterface(IID_IMemAllocatorCallbackTemp, (void**)&pMemCallback); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::Connect No IMemAllocatorCallbackTemp interface hr %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // set notification routine + hr = pMemCallback->SetNotify((IMemAllocatorNotifyCallbackTemp*)this); + + // release IMemAllocatorNotifyCallbackTemp interface + pMemCallback->Release(); + + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::Connect IMemAllocatorNotifyCallbackTemp::SetNotify failed hr %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + // now set allocator + hr = m_MemInputPin->NotifyAllocator(m_MemAllocator, TRUE); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::Connect IMemInputPin::NotifyAllocator failed with hr %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + m_MemAllocator->Release(); + m_MemInputPin->Release(); + return hr; + } + + if (!m_hPin) + { + //FIXME create pin handle + assert(0); + } // receive connection; hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); @@ -1186,7 +1662,14 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) // increment reference count pReceivePin->AddRef(); m_Pin = pReceivePin; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Connect success\n"); +#endif + } + else + { + m_MemInputPin->Release(); + m_MemAllocator->Release(); } return hr; @@ -1196,14 +1679,15 @@ HRESULT STDMETHODCALLTYPE COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) { - OutputDebugStringW(L"COutputPin::ReceiveConnection\n"); return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::Disconnect( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Disconnect\n"); +#endif if (!m_Pin) { @@ -1216,15 +1700,24 @@ COutputPin::Disconnect( void) m_Pin->Release(); m_Pin = NULL; + m_MemInputPin->Release(); + m_MemAllocator->Release(); + CloseHandle(m_hPin); + m_hPin = INVALID_HANDLE_VALUE; + +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::Disconnect\n"); +#endif return S_OK; } HRESULT STDMETHODCALLTYPE COutputPin::ConnectedTo(IPin **pPin) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::ConnectedTo\n"); +#endif if (!pPin) return E_POINTER; @@ -1244,15 +1737,16 @@ HRESULT STDMETHODCALLTYPE COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n"); +#endif + return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE COutputPin::QueryPinInfo(PIN_INFO *pInfo) { - OutputDebugStringW(L"COutputPin::QueryPinInfo\n"); - wcscpy(pInfo->achName, m_PinName); pInfo->dir = PINDIR_OUTPUT; pInfo->pFilter = m_ParentFilter; @@ -1264,8 +1758,6 @@ HRESULT STDMETHODCALLTYPE COutputPin::QueryDirection(PIN_DIRECTION *pPinDir) { - OutputDebugStringW(L"COutputPin::QueryDirection\n"); - if (pPinDir) { *pPinDir = PINDIR_OUTPUT; @@ -1278,8 +1770,6 @@ HRESULT STDMETHODCALLTYPE COutputPin::QueryId(LPWSTR *Id) { - OutputDebugStringW(L"COutputPin::QueryId\n"); - *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); if (!*Id) return E_OUTOFMEMORY; @@ -1291,7 +1781,10 @@ HRESULT STDMETHODCALLTYPE COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"COutputPin::QueryAccept called\n"); +#endif + return E_NOTIMPL; } HRESULT @@ -1302,23 +1795,22 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) ULONG MediaTypeCount = 0, Index; AM_MEDIA_TYPE * MediaTypes; HANDLE hFilter; + IKsObject * KsObjectParent; - OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n"); - - if (!m_KsObjectParent) - { - // no interface - return E_NOINTERFACE; - } + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; // get parent filter handle - hFilter = m_KsObjectParent->KsGetObjectHandle(); + hFilter = KsObjectParent->KsGetObjectHandle(); + + // release IKsObject + KsObjectParent->Release(); // query media type count hr = KsGetMediaTypeCount(hFilter, m_PinId, &MediaTypeCount); if (FAILED(hr) || !MediaTypeCount) { - OutputDebugStringW(L"COutputPin::EnumMediaTypes failed1\n"); return hr; } @@ -1327,7 +1819,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) if (!MediaTypes) { // not enough memory - OutputDebugStringW(L"COutputPin::EnumMediaTypes CoTaskMemAlloc\n"); return E_OUTOFMEMORY; } @@ -1342,7 +1833,6 @@ COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) { // failed CoTaskMemFree(MediaTypes); - OutputDebugStringW(L"COutputPin::EnumMediaTypes failed\n"); return hr; } } @@ -1353,36 +1843,847 @@ HRESULT STDMETHODCALLTYPE COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) { - OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE COutputPin::EndOfStream( void) { - OutputDebugStringW(L"COutputPin::EndOfStream called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::BeginFlush( void) { - OutputDebugStringW(L"COutputPin::BeginFlush called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::EndFlush( void) { - OutputDebugStringW(L"COutputPin::EndFlush called\n"); - return E_NOTIMPL; + /* should be called only on input pins */ + return E_UNEXPECTED; } HRESULT STDMETHODCALLTYPE COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) { - OutputDebugStringW(L"COutputPin::NewSegment called\n"); - return E_NOTIMPL; + if (!m_Pin) + { + // we are not connected + return VFW_E_NOT_CONNECTED; + } + + return m_Pin->NewSegment(tStart, tStop, dRate); +} + +//------------------------------------------------------------------- +HRESULT +STDMETHODCALLTYPE +COutputPin::CheckFormat( + const AM_MEDIA_TYPE *pmt) +{ + PKSMULTIPLE_ITEM MultipleItem; + PKSDATAFORMAT DataFormat; + HRESULT hr; + IKsObject * KsObjectParent; + HANDLE hFilter; + + if (!pmt) + return E_POINTER; + + // get IKsObject interface + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + // get parent filter handle + hFilter = KsObjectParent->KsGetObjectHandle(); + + // release IKsObject + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + + hr = KsGetMultiplePinFactoryItems(hFilter, m_PinId, KSPROPERTY_PIN_DATARANGES, (PVOID*)&MultipleItem); + if (FAILED(hr)) + return S_FALSE; + + DataFormat = (PKSDATAFORMAT)(MultipleItem + 1); + for(ULONG Index = 0; Index < MultipleItem->Count; Index++) + { + if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) && + IsEqualGUID(pmt->subtype, DataFormat->SubFormat) && + IsEqualGUID(pmt->formattype, DataFormat->Specifier)) + { + // format is supported + CoTaskMemFree(MultipleItem); + return S_OK; + } + DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize); + } + //format is not supported + CoTaskMemFree(MultipleItem); + return S_FALSE; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin::CreatePin( + const AM_MEDIA_TYPE *pmt) +{ + PKSMULTIPLE_ITEM MediumList; + PKSMULTIPLE_ITEM InterfaceList; + PKSPIN_MEDIUM Medium; + PKSPIN_INTERFACE Interface; + IKsInterfaceHandler * InterfaceHandler; + HRESULT hr; + + // query for pin medium + hr = KsQueryMediums(&MediumList); + if (FAILED(hr)) + return hr; + + // query for pin interface + hr = KsQueryInterfaces(&InterfaceList); + if (FAILED(hr)) + { + // failed + CoTaskMemFree(MediumList); + return hr; + } + + if (MediumList->Count) + { + //use first available medium + Medium = (PKSPIN_MEDIUM)(MediumList + 1); + } + else + { + // default to standard medium + Medium = &StandardPinMedium; + } + + if (InterfaceList->Count) + { + //use first available interface + Interface = (PKSPIN_INTERFACE)(InterfaceList + 1); + } + else + { + // default to standard interface + Interface = &StandardPinInterface; + } + + if (m_Communication != KSPIN_COMMUNICATION_BRIDGE && m_Communication != KSPIN_COMMUNICATION_NONE) + { + // now create pin + hr = CreatePinHandle(Medium, Interface, pmt); + if (FAILED(hr)) + { + m_InterfaceHandler->Release(); + m_InterfaceHandler = InterfaceHandler; + } + + if (!m_InterfaceHandler) + { + // now load the IKsInterfaceHandler plugin + hr = CoCreateInstance(Interface->Set, NULL, CLSCTX_INPROC_SERVER, IID_IKsInterfaceHandler, (void**)&InterfaceHandler); + if (FAILED(hr)) + { + // failed to load interface handler plugin + CoTaskMemFree(MediumList); + CoTaskMemFree(InterfaceList); + + return hr; + } + + // now set the pin + hr = InterfaceHandler->KsSetPin((IKsPin*)this); + if (FAILED(hr)) + { + // failed to load interface handler plugin + InterfaceHandler->Release(); + CoTaskMemFree(MediumList); + CoTaskMemFree(InterfaceList); + return hr; + } + + // store interface handler + m_InterfaceHandler = InterfaceHandler; + } + } + else + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); + OutputDebugStringW(Buffer); + DebugBreak(); +#endif + + hr = E_FAIL; + } + + // free medium / interface / dataformat + CoTaskMemFree(MediumList); + CoTaskMemFree(InterfaceList); + + return hr; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin::CreatePinHandle( + PKSPIN_MEDIUM Medium, + PKSPIN_INTERFACE Interface, + const AM_MEDIA_TYPE *pmt) +{ + PKSPIN_CONNECT PinConnect; + PKSDATAFORMAT DataFormat; + ULONG Length; + HRESULT hr; + HANDLE hFilter; + IKsObject * KsObjectParent; + + //KSALLOCATOR_FRAMING Framing; + //KSPROPERTY Property; + //ULONG BytesReturned; + + if (m_hPin != INVALID_HANDLE_VALUE) + { + // pin already exists + //CloseHandle(m_hPin); + //m_hPin = INVALID_HANDLE_VALUE; + return S_OK; + } + + + // calc format size + Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat; + + // allocate pin connect + PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length); + if (!PinConnect) + { + // failed + return E_OUTOFMEMORY; + } + + // setup request + CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE)); + CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM)); + PinConnect->PinId = m_PinId; + PinConnect->PinToHandle = NULL; + PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; + PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL; + + // get dataformat offset + DataFormat = (PKSDATAFORMAT)(PinConnect + 1); + + // copy data format + DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat; + DataFormat->Flags = 0; + DataFormat->SampleSize = pmt->lSampleSize; + DataFormat->Reserved = 0; + CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID)); + CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID)); + CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID)); + + if (pmt->cbFormat) + { + // copy extended format + CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat); + } + + // get IKsObject interface + hr = m_ParentFilter->QueryInterface(IID_IKsObject, (LPVOID*)&KsObjectParent); + if (FAILED(hr)) + return hr; + + // get parent filter handle + hFilter = KsObjectParent->KsGetObjectHandle(); + + // release IKsObject + KsObjectParent->Release(); + + if (!hFilter) + return E_HANDLE; + + // create pin + hr = KsCreatePin(hFilter, PinConnect, GENERIC_READ, &m_hPin); + + if (SUCCEEDED(hr)) + { + // store current interface / medium + CopyMemory(&m_Medium, Medium, sizeof(KSPIN_MEDIUM)); + CopyMemory(&m_Interface, Interface, sizeof(KSPIN_INTERFACE)); + CopyMemory(&m_MediaFormat, pmt, sizeof(AM_MEDIA_TYPE)); + +#ifdef KSPROXY_TRACE + LPOLESTR pMajor, pSub, pFormat; + StringFromIID(m_MediaFormat.majortype, &pMajor); + StringFromIID(m_MediaFormat.subtype , &pSub); + StringFromIID(m_MediaFormat.formattype, &pFormat); + WCHAR Buffer[200]; + swprintf(Buffer, L"COutputPin::CreatePinHandle Major %s SubType %s Format %s pbFormat %p cbFormat %u\n", pMajor, pSub, pFormat, pmt->pbFormat, pmt->cbFormat); + CoTaskMemFree(pMajor); + CoTaskMemFree(pSub); + CoTaskMemFree(pFormat); + OutputDebugStringW(Buffer); +#endif + + if (pmt->cbFormat) + { + m_MediaFormat.pbFormat = (BYTE*)CoTaskMemAlloc(pmt->cbFormat); + if (!m_MediaFormat.pbFormat) + { + CoTaskMemFree(PinConnect); + m_MediaFormat.pbFormat = NULL; + m_MediaFormat.cbFormat = 0; + return E_OUTOFMEMORY; + } + CopyMemory(m_MediaFormat.pbFormat, pmt->pbFormat, pmt->cbFormat); + } +#if 0 + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; + Property.Flags = KSPROPERTY_TYPE_GET; + + ZeroMemory(&Framing, sizeof(KSALLOCATOR_FRAMING)); + hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); + if (SUCCEEDED(hr)) + { + m_Properties.cbAlign = (Framing.FileAlignment + 1); + m_Properties.cbBuffer = Framing.FrameSize; + m_Properties.cbPrefix = 0; //FIXME + m_Properties.cBuffers = Framing.Frames; + } + hr = S_OK; +#endif + + if (FAILED(InitializeIOThread())) + { + OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); + DebugBreak(); + } + + LPGUID pGuid; + ULONG NumGuids = 0; + + // get all supported sets + hr = GetSupportedSets(&pGuid, &NumGuids); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n"); +#endif + return hr; + } + + // load all proxy plugins + hr = LoadProxyPlugins(pGuid, NumGuids); + if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n"); +#endif + return hr; + } + + // free sets + CoTaskMemFree(pGuid); + + + //TODO + // connect pin pipes + + } + // free pin connect + CoTaskMemFree(PinConnect); + + return hr; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin::GetSupportedSets( + LPGUID * pOutGuid, + PULONG NumGuids) +{ + KSPROPERTY Property; + LPGUID pGuid; + ULONG NumProperty = 0; + ULONG NumMethods = 0; + ULONG NumEvents = 0; + ULONG Length; + ULONG BytesReturned; + HRESULT hr; + + Property.Set = GUID_NULL; + Property.Id = 0; + Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; + + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); + KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); + + Length = NumProperty + NumMethods + NumEvents; + + // allocate guid buffer + pGuid = (LPGUID)CoTaskMemAlloc(Length); + if (!pGuid) + { + // failed + return E_OUTOFMEMORY; + } + + NumProperty /= sizeof(GUID); + NumMethods /= sizeof(GUID); + NumEvents /= sizeof(GUID); + + // get all properties + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + + // get all methods + if (Length) + { + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + } + + // get all events + if (Length) + { + hr = KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); + if (FAILED(hr)) + { + CoTaskMemFree(pGuid); + return E_FAIL; + } + Length -= BytesReturned; + } + +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; + swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); + OutputDebugStringW(Buffer); +#endif + + *pOutGuid = pGuid; + *NumGuids = NumProperty+NumEvents+NumMethods; + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin::LoadProxyPlugins( + LPGUID pGuids, + ULONG NumGuids) +{ + ULONG Index; + LPOLESTR pStr; + HKEY hKey, hSubKey; + HRESULT hr; + IUnknown * pUnknown; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); + return E_FAIL; + } + + // enumerate all sets + for(Index = 0; Index < NumGuids; Index++) + { + // convert to string + hr = StringFromCLSID(pGuids[Index], &pStr); + if (FAILED(hr)) + return E_FAIL; + + // now try open class key + if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) + { + // no plugin for that set exists + CoTaskMemFree(pStr); + continue; + } + + // try load plugin + hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); + if (SUCCEEDED(hr)) + { + // store plugin + m_Plugins.push_back(pUnknown); + } + // close key + RegCloseKey(hSubKey); + } + + // close media interfaces key + RegCloseKey(hKey); + return S_OK; +} + + +HRESULT +WINAPI +COutputPin::IoProcessRoutine() +{ + IMediaSample *Sample; + LONG SampleCount; + HRESULT hr; + PKSSTREAM_SEGMENT StreamSegment; + HANDLE hEvent; + IMediaSample * Samples[1]; + +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; +#endif + + // first wait for the start event to signal + WaitForSingleObject(m_hStartEvent, INFINITE); + + assert(m_InterfaceHandler); + do + { + if (m_StopInProgress) + { + // stop io thread + break; + } + + assert(m_State == KSSTATE_RUN); + assert(m_MemAllocator); + + // get buffer + hr = m_MemAllocator->GetBuffer(&Sample, NULL, NULL, AM_GBF_NOWAIT); + + if (FAILED(hr)) + { + WaitForSingleObject(m_hBufferAvailable, INFINITE); + // now retry again + continue; + } + + // fill buffer + SampleCount = 1; + Samples[0] = Sample; + + Sample->SetTime(NULL, NULL); + hr = m_InterfaceHandler->KsProcessMediaSamples(NULL, /* FIXME */ + Samples, + &SampleCount, + KsIoOperation_Read, + &StreamSegment); + if (FAILED(hr) || !StreamSegment) + { +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::IoProcessRoutine KsProcessMediaSamples FAILED PinName %s hr %lx\n", m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + break; + } + + // get completion event + hEvent = StreamSegment->CompletionEvent; + + // wait for i/o completion + WaitForSingleObject(hEvent, INFINITE); + + // perform completion + m_InterfaceHandler->KsCompleteIo(StreamSegment); + + // close completion event + CloseHandle(hEvent); + + if (SUCCEEDED(hr)) + { + assert(m_MemInputPin); + + // now deliver the sample + hr = m_MemInputPin->Receive(Sample); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin::IoProcessRoutine PinName %s IMemInputPin::Receive hr %lx Sample %p m_MemAllocator %p\n", m_PinName, hr, Sample, m_MemAllocator); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + break; + + Sample = NULL; + } + }while(TRUE); + + // signal end of i/o thread + SetEvent(m_hStopEvent); + + m_IoThreadStarted = false; + + return NOERROR; +} + +DWORD +WINAPI +COutputPin_IoThreadStartup( + LPVOID lpParameter) +{ + COutputPin * Pin = (COutputPin*)lpParameter; + assert(Pin); + + return Pin->IoProcessRoutine(); +} + + +HRESULT +WINAPI +COutputPin::InitializeIOThread() +{ + HANDLE hThread; + + if (m_IoThreadStarted) + return NOERROR; + + if (!m_hStartEvent) + m_hStartEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + if (!m_hStartEvent) + return E_OUTOFMEMORY; + + if (!m_hStopEvent) + m_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + if (!m_hStopEvent) + return E_OUTOFMEMORY; + + if (!m_hBufferAvailable) + m_hBufferAvailable = CreateEventW(NULL, FALSE, FALSE, NULL); + + if (!m_hBufferAvailable) + return E_OUTOFMEMORY; + + m_StopInProgress = false; + m_IoThreadStarted = true; + + // now create the startup thread + hThread = CreateThread(NULL, 0, COutputPin_IoThreadStartup, (LPVOID)this, 0, NULL); + if (!hThread) + return E_OUTOFMEMORY; + + + // close thread handle + CloseHandle(hThread); + return NOERROR; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin_SetState( + IPin * Pin, + KSSTATE State) +{ + HRESULT hr = S_OK; + KSPROPERTY Property; + KSSTATE CurState; + ULONG BytesReturned; + COutputPin * pPin = (COutputPin*)Pin; + +#ifdef KSPROXY_TRACE + WCHAR Buffer[200]; +#endif + + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + EnterCriticalSection(&pPin->m_Lock); + + if (pPin->m_State <= State) + { + if (pPin->m_State == KSSTATE_STOP) + { + hr = pPin->InitializeIOThread(); + if (FAILED(hr)) + { + // failed to initialize I/O thread +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"Failed to initialize I/O Thread\n"); +#endif + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + CurState = KSSTATE_ACQUIRE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_STOP KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + + pPin->m_State = CurState; + + if (pPin->m_State == State) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + } + if (pPin->m_State == KSSTATE_ACQUIRE) + { + CurState = KSSTATE_PAUSE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState KSSTATE_ACQUIRE KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + + pPin->m_State = CurState; + + if (pPin->m_State == State) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + } + if (State == KSSTATE_RUN && pPin->m_State == KSSTATE_PAUSE) + { + CurState = KSSTATE_RUN; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_RUN PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (SUCCEEDED(hr)) + { + pPin->m_State = CurState; + // signal start event + SetEvent(pPin->m_hStartEvent); + } + } + + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + else + { + if (pPin->m_State == KSSTATE_RUN) + { + // setting pending stop flag + pPin->m_StopInProgress = true; + + // release any waiting threads + SetEvent(pPin->m_hBufferAvailable); + + // wait until i/o thread is done + WaitForSingleObject(pPin->m_hStopEvent, INFINITE); + + CurState = KSSTATE_PAUSE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_RUN KSSTATE_PAUSE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + + pPin->m_State = CurState; + + if (FAILED(hr)) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + } + if (pPin->m_State == KSSTATE_PAUSE) + { + CurState = KSSTATE_ACQUIRE; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_PAUSE KSSTATE_ACQUIRE PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + + pPin->m_State = CurState; + + if (pPin->m_State == State) + { + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } + } + + CloseHandle(pPin->m_hStopEvent); + CloseHandle(pPin->m_hStartEvent); + CloseHandle(pPin->m_hBufferAvailable); + + /* close event handles */ + pPin->m_hStopEvent = NULL; + pPin->m_hStartEvent = NULL; + pPin->m_hBufferAvailable = NULL; + + CurState = KSSTATE_STOP; + hr = pPin->KsProperty(&Property, sizeof(KSPROPERTY), &CurState, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"COutputPin_SetState Setting State CurState: KSSTATE_ACQUIRE KSSTATE_STOP PinName %s hr %lx\n", pPin->m_PinName, hr); + OutputDebugStringW(Buffer); +#endif + + if (SUCCEEDED(hr)) + { + // store state + pPin->m_State = CurState; + } + + // unset pending stop flag + pPin->m_StopInProgress = false; + + LeaveCriticalSection(&pPin->m_Lock); + return hr; + } } HRESULT @@ -1391,10 +2692,11 @@ COutputPin_Constructor( IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, + KSPIN_COMMUNICATION Communication, REFIID riid, LPVOID * ppv) { - COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId); + COutputPin * handler = new COutputPin(ParentFilter, PinName, PinId, Communication); if (!handler) return E_OUTOFMEMORY; diff --git a/dll/directx/ksproxy/precomp.h b/dll/directx/ksproxy/precomp.h index 2ea89aa0887..eae5de0f1aa 100644 --- a/dll/directx/ksproxy/precomp.h +++ b/dll/directx/ksproxy/precomp.h @@ -3,6 +3,7 @@ #define _FORCENAMELESSUNION #define BUILDING_KS #define _KSDDK_ +//#define KSPROXY_TRACE #include //#include #include @@ -18,6 +19,8 @@ #include #include #include +#include +#include #include #include //#include @@ -134,9 +137,16 @@ COutputPin_Constructor( IBaseFilter * ParentFilter, LPCWSTR PinName, ULONG PinId, + KSPIN_COMMUNICATION Communication, REFIID riid, LPVOID * ppv); +HRESULT +STDMETHODCALLTYPE +COutputPin_SetState( + IPin * Pin, + KSSTATE State); + /* enumpins.cpp */ HRESULT WINAPI @@ -165,8 +175,30 @@ CKsNode_Constructor( REFIID riid, LPVOID * ppv); +/* allocator.cpp */ +HRESULT +WINAPI +CKsAllocator_Constructor( + IUnknown * pUnkOuter, + REFIID riid, + LPVOID * ppv); + +/* mediasample.cpp */ +HRESULT +WINAPI +CMediaSample_Constructor( + IMemAllocator* Allocator, + BYTE* pBuffer, + ULONG BufferSize, + REFIID riid, + LPVOID * ppv); + + extern const GUID IID_IKsObject; extern const GUID IID_IKsPinEx; extern const GUID IID_IKsAggregateControl; extern const GUID IID_IKsPinPipe; extern const GUID IID_IKsPinFactory; +extern const GUID IID_IKsAllocatorEx; +extern KSPIN_INTERFACE StandardPinInterface; +extern KSPIN_MEDIUM StandardPinMedium; diff --git a/dll/directx/ksproxy/proxy.cpp b/dll/directx/ksproxy/proxy.cpp index 371176f2437..bd34ec8184b 100644 --- a/dll/directx/ksproxy/proxy.cpp +++ b/dll/directx/ksproxy/proxy.cpp @@ -63,7 +63,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - delete this; + //delete this; return 0; } return m_Ref; @@ -171,7 +171,7 @@ public: HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); - CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins(), m_DevicePath(0), m_hClock(0) {}; + CKsProxy(); ~CKsProxy() { if (m_hDevice) @@ -189,6 +189,9 @@ public: HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList); HRESULT STDMETHODCALLTYPE CreateClockInstance(); HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize); + HRESULT STDMETHODCALLTYPE SetPinState(KSSTATE State); + + protected: LONG m_Ref; IFilterGraph *m_pGraph; @@ -200,8 +203,23 @@ protected: LPWSTR m_DevicePath; CLSID m_DeviceInterfaceGUID; HANDLE m_hClock; + CRITICAL_SECTION m_Lock; }; +CKsProxy::CKsProxy() : m_Ref(0), + m_pGraph(0), + m_ReferenceClock((IReferenceClock*)this), + m_FilterState(State_Stopped), + m_hDevice(0), + m_Plugins(), + m_Pins(), + m_DevicePath(0), + m_hClock(0) +{ + InitializeCriticalSection(&m_Lock); +} + + HRESULT STDMETHODCALLTYPE CKsProxy::QueryInterface( @@ -329,24 +347,26 @@ CKsProxy::QueryInterface( HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output); if (SUCCEEDED(hr)) { +#ifdef KSPROXY_TRACE WCHAR Buffer[100]; LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); +#endif return hr; } } } - +#ifdef KSPROXY_TRACE WCHAR Buffer[MAX_PATH]; LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); - +#endif return E_NOINTERFACE; } @@ -359,7 +379,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::GetPages(CAUUID *pPages) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetPages NotImplemented\n"); +#endif if (!pPages) return E_POINTER; @@ -475,7 +497,10 @@ STDMETHODCALLTYPE CKsProxy::KsGetTime( LONGLONG* Time) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG)); } @@ -484,7 +509,10 @@ STDMETHODCALLTYPE CKsProxy::KsSetTime( LONGLONG Time) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsSetTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG)); } @@ -493,7 +521,10 @@ STDMETHODCALLTYPE CKsProxy::KsGetPhysicalTime( LONGLONG* Time) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG)); } @@ -502,7 +533,10 @@ STDMETHODCALLTYPE CKsProxy::KsSetPhysicalTime( LONGLONG Time) { - OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime NotImplemented\n"); +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG)); } @@ -511,7 +545,10 @@ STDMETHODCALLTYPE CKsProxy::KsGetCorrelatedTime( KSCORRELATED_TIME* CorrelatedTime) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); } @@ -520,7 +557,9 @@ STDMETHODCALLTYPE CKsProxy::KsSetCorrelatedTime( KSCORRELATED_TIME* CorrelatedTime) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime\n"); +#endif return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); } @@ -529,7 +568,9 @@ STDMETHODCALLTYPE CKsProxy::KsGetCorrelatedPhysicalTime( KSCORRELATED_TIME* CorrelatedTime) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime\n"); +#endif return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); } @@ -538,7 +579,10 @@ STDMETHODCALLTYPE CKsProxy::KsSetCorrelatedPhysicalTime( KSCORRELATED_TIME* CorrelatedTime) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime\n"); +#endif + return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); } @@ -547,7 +591,9 @@ STDMETHODCALLTYPE CKsProxy::KsGetResolution( KSRESOLUTION* Resolution) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetResolution\n"); +#endif return PerformClockProperty(KSPROPERTY_CLOCK_RESOLUTION, KSPROPERTY_TYPE_GET, (PVOID)Resolution, sizeof(KSRESOLUTION)); } @@ -556,7 +602,9 @@ STDMETHODCALLTYPE CKsProxy::KsGetState( KSSTATE* State) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetState\n"); +#endif return PerformClockProperty(KSPROPERTY_CLOCK_STATE, KSPROPERTY_TYPE_GET, (PVOID)State, sizeof(KSSTATE)); } @@ -572,7 +620,9 @@ CKsProxy::GetTime( KSPROPERTY Property; ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetTime\n"); +#endif if (!pTime) return E_POINTER; @@ -617,7 +667,9 @@ CKsProxy::AdviseTime( ULONG BytesReturned; PKSEVENT_TIME_MARK Event; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::AdviseTime\n"); +#endif // //FIXME locks @@ -683,7 +735,9 @@ CKsProxy::AdvisePeriodic( ULONG BytesReturned; PKSEVENT_TIME_INTERVAL Event; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::AdvisePeriodic\n"); +#endif // //FIXME locks @@ -745,7 +799,9 @@ CKsProxy::Unadvise( HRESULT hr; ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Unadvise\n"); +#endif if (m_hClock) { @@ -783,7 +839,10 @@ CKsProxy::GetCapabilities( Property.Id = KSPROPERTY_MEDIASEEKING_CAPABILITIES; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetCapabilities\n"); +#endif + if (!pCapabilities) return E_POINTER; @@ -833,7 +892,9 @@ CKsProxy::CheckCapabilities( DWORD Capabilities; HRESULT hr; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::CheckCapabilities\n"); +#endif if (!pCapabilities) return E_POINTER; @@ -911,11 +972,13 @@ CKsProxy::IsFormatSupported( ULONG Index; HRESULT hr = S_FALSE; +#ifdef KSPROXY_TRACE WCHAR Buffer[100]; LPOLESTR pstr; StringFromCLSID(*pFormat, &pstr); swprintf(Buffer, L"CKsProxy::IsFormatSupported %s\n",pstr); OutputDebugStringW(Buffer); +#endif if (!pFormat) return E_POINTER; @@ -924,8 +987,10 @@ CKsProxy::IsFormatSupported( hr = GetMediaSeekingFormats(&FormatList); if (SUCCEEDED(hr)) { +#ifdef KSPROXY_TRACE swprintf(Buffer, L"CKsProxy::IsFormatSupported NumFormat %lu\n",FormatList->Count); OutputDebugStringW(Buffer); +#endif //iterate through format list pGuid = (LPGUID)(FormatList + 1); @@ -958,7 +1023,9 @@ CKsProxy::IsFormatSupported( { // plugin does not support interface hr = S_FALSE; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::IsFormatSupported plugin does not support IMediaSeeking interface\n"); +#endif break; } @@ -983,7 +1050,9 @@ CKsProxy::QueryPreferredFormat( HRESULT hr; ULONG Index; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::QueryPreferredFormat\n"); +#endif if (!pFormat) return E_POINTER; @@ -1043,7 +1112,9 @@ CKsProxy::GetTimeFormat( Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetTimeFormat\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1083,7 +1154,9 @@ CKsProxy::IsUsingTimeFormat( { GUID Format; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat\n"); +#endif if (FAILED(QueryPreferredFormat(&Format))) return S_FALSE; @@ -1107,7 +1180,9 @@ CKsProxy::SetTimeFormat( Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT; Property.Flags = KSPROPERTY_TYPE_SET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::SetTimeFormat\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1155,7 +1230,9 @@ CKsProxy::GetDuration( Property.Id = KSPROPERTY_MEDIASEEKING_DURATION; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetDuration\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pDuration, sizeof(LONGLONG), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1201,7 +1278,9 @@ CKsProxy::GetStopPosition( Property.Id = KSPROPERTY_MEDIASEEKING_STOPPOSITION; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetStopPosition\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pStop, sizeof(LONGLONG), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1247,7 +1326,9 @@ CKsProxy::GetCurrentPosition( Property.Id = KSPROPERTY_MEDIASEEKING_POSITION; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetCurrentPosition\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pCurrent, sizeof(LONGLONG), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1297,7 +1378,9 @@ CKsProxy::ConvertTimeFormat( Property.Property.Id = KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT; Property.Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::ConvertTimeFormat\n"); +#endif if (!pTargetFormat) { @@ -1380,7 +1463,9 @@ CKsProxy::SetPositions( Positions.Stop = *pStop; Positions.StopFlags = (KS_SEEKING_FLAGS)dwStopFlags; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::SetPositions\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Positions, sizeof(KSPROPERTY_POSITIONS), &BytesReturned); if (SUCCEEDED(hr)) @@ -1441,7 +1526,9 @@ CKsProxy::GetPositions( { HRESULT hr; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetPositions\n"); +#endif hr = GetCurrentPosition(pCurrent); if (SUCCEEDED(hr)) @@ -1465,7 +1552,9 @@ CKsProxy::GetAvailable( Property.Id = KSPROPERTY_MEDIASEEKING_AVAILABLE; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetAvailable\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Media, sizeof(KSPROPERTY_MEDIAAVAILABLE), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1509,7 +1598,9 @@ STDMETHODCALLTYPE CKsProxy::SetRate( double dRate) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::SetRate\n"); +#endif return E_NOTIMPL; } @@ -1518,7 +1609,9 @@ STDMETHODCALLTYPE CKsProxy::GetRate( double *pdRate) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetRate\n"); +#endif return E_NOTIMPL; } @@ -1535,7 +1628,9 @@ CKsProxy::GetPreroll( Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL; Property.Flags = KSPROPERTY_TYPE_GET; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetPreroll\n"); +#endif hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned); if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) @@ -1582,6 +1677,7 @@ CKsProxy::GetMiscFlags() PIN_DIRECTION PinDirection; KSPIN_COMMUNICATION Communication; + for(Index = 0; Index < m_Pins.size(); Index++) { // get current pin @@ -1595,7 +1691,7 @@ CKsProxy::GetMiscFlags() if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId &Communication))) { - if (Communication == KSPIN_COMMUNICATION_NONE || Communication == KSPIN_COMMUNICATION_BRIDGE) + if (Communication != KSPIN_COMMUNICATION_NONE && Communication != KSPIN_COMMUNICATION_BRIDGE) { Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE; } @@ -1604,7 +1700,12 @@ CKsProxy::GetMiscFlags() } } - OutputDebugStringW(L"CKsProxy::GetMiscFlags stub\n"); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::GetMiscFlags stub Flags %x\n", Flags); + OutputDebugStringW(Buffer); +#endif + return Flags; } @@ -1620,8 +1721,11 @@ CKsProxy::KsProperty( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hDevice != 0); +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsProperty\n"); +#endif + + assert(m_hDevice != 0); return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); } @@ -1634,8 +1738,11 @@ CKsProxy::KsMethod( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hDevice != 0); +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsMethod\n"); +#endif + + assert(m_hDevice != 0); return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); } @@ -1648,8 +1755,11 @@ CKsProxy::KsEvent( ULONG DataLength, ULONG* BytesReturned) { - assert(m_hDevice != 0); +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsEvent\n"); +#endif + + assert(m_hDevice != 0); if (EventLength) return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); else @@ -1672,7 +1782,9 @@ CKsProxy::Set( { ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Set\n"); +#endif if (cbInstanceData) { @@ -1716,7 +1828,9 @@ CKsProxy::Get( { ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Get\n"); +#endif if (cbInstanceData) { @@ -1757,7 +1871,9 @@ CKsProxy::QuerySupported( KSPROPERTY Property; ULONG BytesReturned; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::QuerySupported\n"); +#endif Property.Set = guidPropSet; Property.Id = dwPropID; @@ -1782,7 +1898,9 @@ CKsProxy::CreateNodeInstance( { HRESULT hr; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n"); +#endif *Interface = NULL; @@ -1807,7 +1925,9 @@ STDMETHODCALLTYPE CKsProxy::KsAddAggregate( IN REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -1816,7 +1936,10 @@ STDMETHODCALLTYPE CKsProxy::KsRemoveAggregate( REFGUID AggregateClass) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -1829,8 +1952,10 @@ HRESULT STDMETHODCALLTYPE CKsProxy::IsDirty() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n"); DebugBreak(); +#endif return E_NOTIMPL; } @@ -1848,7 +1973,9 @@ CKsProxy::Load( ULONG PinId; LPOLESTR pMajor, pSub, pFormat; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Load\n"); +#endif #if 0 ULONG Version = ReadInt(pStm, hr); @@ -1918,7 +2045,10 @@ CKsProxy::Save( IStream *pStm, BOOL fClearDirty) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Save Notimplemented\n"); +#endif + return E_NOTIMPL; } @@ -1927,8 +2057,11 @@ STDMETHODCALLTYPE CKsProxy::GetSizeMax( ULARGE_INTEGER *pcbSize) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n"); DebugBreak(); +#endif + return E_NOTIMPL; } @@ -1940,8 +2073,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink) { - +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::DeviceInfo\n"); +#endif if (!m_DevicePath) { @@ -1966,7 +2100,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Reassociate(void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Reassociate\n"); +#endif if (!m_DevicePath || m_hDevice) { @@ -1989,7 +2125,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Disassociate(void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Disassociate\n"); +#endif if (!m_hDevice) return E_HANDLE; @@ -2007,7 +2145,10 @@ HANDLE STDMETHODCALLTYPE CKsProxy::KsGetClockHandle() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetClockHandle\n"); +#endif + return m_hClock; } @@ -2020,7 +2161,10 @@ HANDLE STDMETHODCALLTYPE CKsProxy::KsGetObjectHandle() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::KsGetObjectHandle\n"); +#endif + return m_hDevice; } @@ -2031,7 +2175,10 @@ HRESULT STDMETHODCALLTYPE CKsProxy::InitNew( void) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::InitNew\n"); +#endif + return S_OK; } @@ -2318,7 +2465,6 @@ CKsProxy::CreatePins() KSPIN_DATAFLOW DataFlow; KSPIN_COMMUNICATION Communication; HRESULT hr; - WCHAR Buffer[100]; LPWSTR PinName; IPin * pPin; ULONG InputPin = 0; @@ -2373,7 +2519,7 @@ CKsProxy::CreatePins() } else { - hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, IID_IPin, (void**)&pPin); + hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin); if (FAILED(hr)) { CoTaskMemFree(PinName); @@ -2385,8 +2531,12 @@ CKsProxy::CreatePins() // store pins m_Pins.push_back(pPin); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName); OutputDebugStringW(Buffer); +#endif + } return S_OK; @@ -2397,14 +2547,16 @@ STDMETHODCALLTYPE CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) { HRESULT hr; - WCHAR Buffer[100]; VARIANT varName; LPGUID pGuid; ULONG NumGuids = 0; HDEVINFO hList; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; OutputDebugStringW(L"CKsProxy::Load\n"); +#endif // read device path varName.vt = VT_BSTR; @@ -2412,14 +2564,18 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) if (FAILED(hr)) { +#ifdef KSPROXY_TRACE swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr); OutputDebugStringW(Buffer); +#endif return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); } +#ifdef KSPROXY_TRACE OutputDebugStringW(L"DevicePath: "); OutputDebugStringW(varName.bstrVal); OutputDebugStringW(L"\n"); +#endif // create device list hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); @@ -2448,9 +2604,10 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) if (m_hDevice == INVALID_HANDLE_VALUE) { // failed to open device +#ifdef KSPROXY_TRACE swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError()); OutputDebugStringW(Buffer); - +#endif return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); } @@ -2488,7 +2645,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Save\n"); +#endif return E_NOTIMPL; } @@ -2501,7 +2660,9 @@ STDMETHODCALLTYPE CKsProxy::GetClassID( CLSID *pClassID) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetClassID\n"); +#endif CopyMemory(pClassID, &CLSID_Proxy, sizeof(GUID)); return S_OK; @@ -2511,16 +2672,53 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Stop() { - OutputDebugStringW(L"CKsProxy::Stop : NotImplemented\n"); - return E_NOTIMPL; + HRESULT hr; + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsProxy::Stop\n"); +#endif + + EnterCriticalSection(&m_Lock); + + hr = SetPinState(KSSTATE_STOP); + if (SUCCEEDED(hr)) + m_FilterState = State_Stopped; + + LeaveCriticalSection(&m_Lock); + + return hr; } HRESULT STDMETHODCALLTYPE CKsProxy::Pause() { - OutputDebugStringW(L"CKsProxy::Pause : NotImplemented\n"); - return E_NOTIMPL; + HRESULT hr = S_OK; + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsProxy::Pause\n"); +#endif + + EnterCriticalSection(&m_Lock); + + if (m_FilterState == State_Running) + { + hr = SetPinState(KSSTATE_STOP); + } + if (SUCCEEDED(hr)) + { + if (m_FilterState == State_Stopped) + { + hr = SetPinState(KSSTATE_PAUSE); + } + } + + if (SUCCEEDED(hr)) + m_FilterState = State_Paused; + + LeaveCriticalSection(&m_Lock); + return hr; + } HRESULT @@ -2528,8 +2726,110 @@ STDMETHODCALLTYPE CKsProxy::Run( REFERENCE_TIME tStart) { - OutputDebugStringW(L"CKsProxy::Run : NotImplemented\n"); - return E_NOTIMPL; + HRESULT hr; + +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsProxy::Run\n"); +#endif + + EnterCriticalSection(&m_Lock); + + if (m_FilterState == State_Stopped) + { + LeaveCriticalSection(&m_Lock); + // setting filter state to pause + hr = Pause(); + if (FAILED(hr)) + return hr; + + EnterCriticalSection(&m_Lock); + assert(m_FilterState == State_Paused); + } + + hr = SetPinState(KSSTATE_RUN); + + if (SUCCEEDED(hr)) + { + m_FilterState = State_Running; + } + + LeaveCriticalSection(&m_Lock); + return hr; +} + +HRESULT +STDMETHODCALLTYPE +CKsProxy::SetPinState( + KSSTATE State) +{ + HRESULT hr = S_OK; + ULONG Index; + IKsObject *pObject; + ULONG BytesReturned; + KSPROPERTY Property; + PIN_INFO PinInfo; + + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; + + // set all pins to running state + for(Index = 0; Index < m_Pins.size(); Index++) + { + IPin * Pin = m_Pins[Index]; + if (!Pin) + continue; + + //check if the pin is connected + IPin * TempPin; + hr = Pin->ConnectedTo(&TempPin); + if (FAILED(hr)) + { + // skip unconnected pins + continue; + } + + // release connected pin + TempPin->Release(); + + // query for the pin info + hr = Pin->QueryPinInfo(&PinInfo); + + if (SUCCEEDED(hr)) + { + if (PinInfo.pFilter) + PinInfo.pFilter->Release(); + + if (PinInfo.dir == PINDIR_OUTPUT) + { + hr = COutputPin_SetState(Pin, State); + if (SUCCEEDED(hr)) + continue; + } + } + + //query IKsObject interface + hr = Pin->QueryInterface(IID_IKsObject, (void**)&pObject); + + // get pin handle + HANDLE hPin = pObject->KsGetObjectHandle(); + + // sanity check + assert(hPin && hPin != INVALID_HANDLE_VALUE); + + // now set state + hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); + +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::SetPinState Index %u State %u hr %lx\n", Index, State, hr); + OutputDebugStringW(Buffer); +#endif + + if (FAILED(hr)) + return hr; + } + return hr; } HRESULT @@ -2538,6 +2838,9 @@ CKsProxy::GetState( DWORD dwMilliSecsTimeout, FILTER_STATE *State) { + if (!State) + return E_POINTER; + *State = m_FilterState; return S_OK; } @@ -2557,27 +2860,36 @@ CKsProxy::SetSyncSource( ULONG BytesReturned; PIN_DIRECTION PinDir; -// Plug In Distributor: IKsClock +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::SetSyncSource\n"); +#endif // FIXME // need locks - if (!pClock) - return E_POINTER; - - hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock); - if (FAILED(hr)) - return hr; - - // get clock handle - hClock = pKsClock->KsGetClockHandle(); - if (!hClock || hClock == INVALID_HANDLE_VALUE) + if (pClock) { - // failed + hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock); + if (FAILED(hr)) + { + hr = m_ReferenceClock->QueryInterface(IID_IKsClock, (void**)&pKsClock); + if (FAILED(hr)) + return hr; + } + + // get clock handle + hClock = pKsClock->KsGetClockHandle(); + + // release IKsClock interface pKsClock->Release(); - return E_FAIL; + m_hClock = hClock; } + else + { + // no clock handle + m_hClock = NULL; + } + // distribute clock to all pins for(Index = 0; Index < m_Pins.size(); Index++) @@ -2601,7 +2913,7 @@ CKsProxy::SetSyncSource( Property.Flags = KSPROPERTY_TYPE_SET; // set master clock - hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)hClock, sizeof(HANDLE), &BytesReturned); + hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&m_hClock, sizeof(HANDLE), &BytesReturned); if (FAILED(hr)) { @@ -2609,8 +2921,10 @@ CKsProxy::SetSyncSource( hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND)) { // failed to set master clock - pKsClock->Release(); pObject->Release(); + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::SetSyncSource KSPROPERTY_STREAM_MASTERCLOCK failed with %lx\n", hr); + OutputDebugStringW(Buffer); return hr; } } @@ -2642,6 +2956,9 @@ CKsProxy::SetSyncSource( } m_ReferenceClock = pClock; +#ifdef KSPROXY_TRACE + OutputDebugStringW(L"CKsProxy::SetSyncSource done\n"); +#endif return S_OK; } @@ -2650,7 +2967,9 @@ STDMETHODCALLTYPE CKsProxy::GetSyncSource( IReferenceClock **pClock) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetSyncSource\n"); +#endif if (!pClock) return E_POINTER; @@ -2667,7 +2986,10 @@ STDMETHODCALLTYPE CKsProxy::EnumPins( IEnumPins **ppEnum) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::EnumPins\n"); +#endif + return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum); } @@ -2678,7 +3000,9 @@ CKsProxy::FindPin( { ULONG PinId; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::FindPin\n"); +#endif if (!ppPin) return E_POINTER; @@ -2714,7 +3038,9 @@ CKsProxy::QueryFilterInfo( if (!pInfo) return E_POINTER; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::QueryFilterInfo\n"); +#endif pInfo->achName[0] = L'\0'; pInfo->pGraph = m_pGraph; @@ -2731,7 +3057,11 @@ CKsProxy::JoinFilterGraph( IFilterGraph *pGraph, LPCWSTR pName) { - OutputDebugStringW(L"CKsProxy::JoinFilterGraph\n"); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::JoinFilterGraph pName %s pGraph %p m_Ref %u\n", pName, pGraph, m_Ref); + OutputDebugStringW(Buffer); +#endif if (pGraph) { @@ -2753,7 +3083,9 @@ STDMETHODCALLTYPE CKsProxy::QueryVendorInfo( LPWSTR *pVendorInfo) { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::QueryVendorInfo\n"); +#endif return StringFromCLSID(CLSID_Proxy, pVendorInfo); } @@ -2765,7 +3097,10 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Register() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n"); +#endif + return E_NOTIMPL; } @@ -2773,7 +3108,9 @@ HRESULT STDMETHODCALLTYPE CKsProxy::Unregister() { +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n"); +#endif return E_NOTIMPL; } @@ -2784,11 +3121,13 @@ CKsProxy_Constructor( REFIID riid, LPVOID * ppv) { +#ifdef KSPROXY_TRACE WCHAR Buffer[100]; LPOLESTR pstr; StringFromCLSID(riid, &pstr); swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr); OutputDebugStringW(Buffer); +#endif CKsProxy * handler = new CKsProxy(); diff --git a/dll/directx/ksproxy/qualityforward.cpp b/dll/directx/ksproxy/qualityforward.cpp index 88459d8275d..df693b20e3a 100644 --- a/dll/directx/ksproxy/qualityforward.cpp +++ b/dll/directx/ksproxy/qualityforward.cpp @@ -88,7 +88,9 @@ STDMETHODCALLTYPE CKsQualityForwarder::KsFlushClient( IN IKsPin *Pin) { +#ifdef KSPROXY_TRACE OutputDebugString("UNIMPLEMENTED\n"); +#endif } HRESULT @@ -101,14 +103,18 @@ CKsQualityForwarder_Constructor( HRESULT hr; HANDLE handle; +#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsQualityForwarder_Constructor\n"); +#endif // open default clock hr = KsOpenDefaultDevice(KSCATEGORY_QUALITY, GENERIC_READ | GENERIC_WRITE, &handle); if (hr != NOERROR) { +#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder_Constructor failed to open device\n"); +#endif return hr; } diff --git a/dll/directx/qedit/samplegrabber.c b/dll/directx/qedit/samplegrabber.c index d09d5546b19..1875c51c49e 100644 --- a/dll/directx/qedit/samplegrabber.c +++ b/dll/directx/qedit/samplegrabber.c @@ -37,7 +37,7 @@ static WCHAR const pin_in_name[] = { 'I', 'n', 0 }; static WCHAR const pin_out_name[] = { 'O', 'u', 't', 0 }; IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount); -IEnumMediaTypes *mediaenum_create(AM_MEDIA_TYPE *mtype); +IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype); /* Fixed pins enumerator, holds filter referenced */ typedef struct _PE_Impl { @@ -258,7 +258,7 @@ Single_IEnumMediaTypes_Next(IEnumMediaTypes *iface, ULONG nTypes, AM_MEDIA_TYPE return E_INVALIDARG; if (!types || ((nTypes != 1) && !fetched)) return E_POINTER; - if (!This->past) { + if (!This->past && !IsEqualGUID(&This->mtype.majortype,&GUID_NULL)) { AM_MEDIA_TYPE *mtype = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); *mtype = This->mtype; if (mtype->cbFormat) { @@ -324,7 +324,7 @@ static const IEnumMediaTypesVtbl IEnumMediaTypes_VTable = Single_IEnumMediaTypes_Clone, }; -IEnumMediaTypes *mediaenum_create(AM_MEDIA_TYPE *mtype) +IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype) { ME_Impl *obj = CoTaskMemAlloc(sizeof(ME_Impl)); if (obj) { @@ -332,14 +332,18 @@ IEnumMediaTypes *mediaenum_create(AM_MEDIA_TYPE *mtype) obj->me.lpVtbl = &IEnumMediaTypes_VTable; obj->refCount = 1; obj->past = FALSE; - obj->mtype = *mtype; - obj->mtype.pUnk = NULL; - if (mtype->cbFormat) { - obj->mtype.pbFormat = CoTaskMemAlloc(mtype->cbFormat); - CopyMemory(obj->mtype.pbFormat, mtype->pbFormat, mtype->cbFormat); + if (mtype) { + obj->mtype = *mtype; + obj->mtype.pUnk = NULL; + if (mtype->cbFormat) { + obj->mtype.pbFormat = CoTaskMemAlloc(mtype->cbFormat); + CopyMemory(obj->mtype.pbFormat, mtype->pbFormat, mtype->cbFormat); + } + else + obj->mtype.pbFormat = NULL; } else - obj->mtype.pbFormat = NULL; + obj->mtype.majortype = GUID_NULL; } return &obj->me; } @@ -361,6 +365,7 @@ typedef struct _SG_Impl { const IMemInputPinVtbl* IMemInputPin_Vtbl; /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */ LONG refCount; + CRITICAL_SECTION critSect; FILTER_INFO info; FILTER_STATE state; AM_MEDIA_TYPE mtype; @@ -372,6 +377,8 @@ typedef struct _SG_Impl { ISampleGrabberCB *grabberIface; LONG grabberMethod; LONG oneShot; + LONG bufferLen; + void* bufferData; } SG_Impl; enum { @@ -413,6 +420,10 @@ static void SampleGrabber_cleanup(SG_Impl *This) ISampleGrabberCB_Release(This->grabberIface); if (This->mtype.pbFormat) CoTaskMemFree(This->mtype.pbFormat); + if (This->bufferData) + CoTaskMemFree(This->bufferData); + This->critSect.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->critSect); } /* Common helper AddRef called from all interfaces */ @@ -471,11 +482,31 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject) return E_NOINTERFACE; } -/* Helper that calls installed sample callbacks */ +/* Helper that buffers data and/or calls installed sample callbacks */ static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample) { double time = 0.0; REFERENCE_TIME tStart, tEnd; + if (This->bufferLen >= 0) { + BYTE *data = 0; + long size = IMediaSample_GetActualDataLength(sample); + if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) { + if (!data) + size = 0; + EnterCriticalSection(&This->critSect); + if (This->bufferLen != size) { + if (This->bufferData) + CoTaskMemFree(This->bufferData); + This->bufferData = size ? CoTaskMemAlloc(size) : NULL; + This->bufferLen = size; + } + if (size) + CopyMemory(This->bufferData, data, size); + LeaveCriticalSection(&This->critSect); + } + } + if (!This->grabberIface) + return; if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd))) time = 1e-7 * tStart; switch (This->grabberMethod) { @@ -777,11 +808,16 @@ SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MED static HRESULT WINAPI SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm) { - TRACE("(%u)\n", bufferEm); + SG_Impl *This = impl_from_ISampleGrabber(iface); + TRACE("(%p)->(%u)\n", This, bufferEm); + EnterCriticalSection(&This->critSect); if (bufferEm) { - FIXME("buffering not implemented\n"); - return E_NOTIMPL; + if (This->bufferLen < 0) + This->bufferLen = 0; } + else + This->bufferLen = -1; + LeaveCriticalSection(&This->critSect); return S_OK; } @@ -789,10 +825,29 @@ SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL buffer static HRESULT WINAPI SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer) { - FIXME("(%p, %p): stub\n", bufSize, buffer); + SG_Impl *This = impl_from_ISampleGrabber(iface); + HRESULT ret = S_OK; + TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer); if (!bufSize) return E_POINTER; - return E_INVALIDARG; + EnterCriticalSection(&This->critSect); + if (!This->pin_in.pair) + ret = VFW_E_NOT_CONNECTED; + else if (This->bufferLen < 0) + ret = E_INVALIDARG; + else if (This->bufferLen == 0) + ret = VFW_E_WRONG_STATE; + else { + if (buffer) { + if (*bufSize >= This->bufferLen) + CopyMemory(buffer, This->bufferData, This->bufferLen); + else + ret = E_OUTOFMEMORY; + } + *bufSize = This->bufferLen; + } + LeaveCriticalSection(&This->critSect); + return ret; } /* ISampleGrabber */ @@ -896,8 +951,7 @@ SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample) return E_POINTER; if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) return S_FALSE; - if (This->grabberIface) - SampleGrabber_callback(This, sample); + SampleGrabber_callback(This, sample); hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK; if (This->oneShot == OneShot_Wait) { This->oneShot = OneShot_Past; @@ -913,16 +967,14 @@ static HRESULT WINAPI SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed) { SG_Impl *This = impl_from_IMemInputPin(iface); + LONG idx; TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface); if (!samples || !nProcessed) return E_POINTER; if ((This->state != State_Running) || (This->oneShot == OneShot_Past)) return S_FALSE; - if (This->grabberIface) { - LONG idx; - for (idx = 0; idx < nSamples; idx++) - SampleGrabber_callback(This, samples[idx]); - } + for (idx = 0; idx < nSamples; idx++) + SampleGrabber_callback(This, samples[idx]); return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK; } @@ -1048,6 +1100,10 @@ SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_M debugstr_guid(&type->majortype), debugstr_guid(&type->subtype), type->lSampleSize, debugstr_guid(&type->formattype), type->cbFormat); + if (!IsEqualGUID(&type->formattype, &FORMAT_None) && + !IsEqualGUID(&type->formattype, &GUID_NULL) && + !type->pbFormat) + return VFW_E_INVALIDMEDIATYPE; if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) && !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype)) return VFW_E_TYPE_NOT_ACCEPTED; @@ -1058,10 +1114,6 @@ SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_M !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) && !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype)) return VFW_E_TYPE_NOT_ACCEPTED; - if (!IsEqualGUID(&type->formattype, &FORMAT_None) && - !IsEqualGUID(&type->formattype, &GUID_NULL) && - !type->pbFormat) - return VFW_E_TYPE_NOT_ACCEPTED; if (This->sg->mtype.pbFormat) CoTaskMemFree(This->sg->mtype.pbFormat); This->sg->mtype = *type; @@ -1212,7 +1264,7 @@ SampleGrabber_IPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **mtypes) TRACE("(%p)->(%p)\n", This, mtypes); if (!mtypes) return E_POINTER; - *mtypes = mediaenum_create(&This->sg->mtype); + *mtypes = mediaenum_create(This->sg->pin_in.pair ? &This->sg->mtype : (const AM_MEDIA_TYPE *)NULL); return *mtypes ? S_OK : E_OUTOFMEMORY; } @@ -1401,6 +1453,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) obj->pin_out.name = pin_out_name; obj->pin_out.sg = obj; obj->pin_out.pair = NULL; + InitializeCriticalSection(&obj->critSect); + obj->critSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SG_Impl.critSect"); obj->info.achName[0] = 0; obj->info.pGraph = NULL; obj->state = State_Stopped; @@ -1413,6 +1467,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv) obj->grabberIface = NULL; obj->grabberMethod = -1; obj->oneShot = OneShot_None; + obj->bufferLen = -1; + obj->bufferData = NULL; *ppv = obj; return S_OK; diff --git a/dll/directx/quartz/filtermapper.c b/dll/directx/quartz/filtermapper.c index 7b8d95430bf..bacb72950d6 100644 --- a/dll/directx/quartz/filtermapper.c +++ b/dll/directx/quartz/filtermapper.c @@ -479,11 +479,16 @@ static HRESULT WINAPI FilterMapper2_UnregisterFilter( static HRESULT FM2_WriteFriendlyName(IPropertyBag * pPropBag, LPCWSTR szName) { VARIANT var; + HRESULT ret; + BSTR value; V_VT(&var) = VT_BSTR; - V_UNION(&var, bstrVal) = (BSTR)szName; + V_UNION(&var, bstrVal) = value = SysAllocString(szName); - return IPropertyBag_Write(pPropBag, wszFriendlyName, &var); + ret = IPropertyBag_Write(pPropBag, wszFriendlyName, &var); + SysFreeString(value); + + return ret; } static HRESULT FM2_WriteClsid(IPropertyBag * pPropBag, REFCLSID clsid) diff --git a/dll/nls/idndl/idndl.def b/dll/nls/idndl/idndl.def deleted file mode 100644 index 921d731a72c..00000000000 --- a/dll/nls/idndl/idndl.def +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY "idndl.dll" - -EXPORTS - DownlevelGetLocaleScripts = DownlevelGetLocaleScripts@12 @1 - DownlevelGetStringScripts@20 = kernel32.GetStringScripts @2 - DownlevelVerifyScripts@20 = kernel32.VerifyScripts @3 diff --git a/dll/nls/idndl/idndl.rbuild b/dll/nls/idndl/idndl.rbuild index 31f7545f2bd..e1303771eab 100644 --- a/dll/nls/idndl/idndl.rbuild +++ b/dll/nls/idndl/idndl.rbuild @@ -7,5 +7,5 @@ 0x600 idndl.cpp - + diff --git a/dll/nls/idndl/idndl.spec b/dll/nls/idndl/idndl.spec new file mode 100644 index 00000000000..acb2b50f799 --- /dev/null +++ b/dll/nls/idndl/idndl.spec @@ -0,0 +1,4 @@ + + 1 stdcall DownlevelGetLocaleScripts(ptr ptr long) DownlevelGetLocaleScripts + 2 stdcall DownlevelGetStringScripts(long ptr long ptr long) kernel32.GetStringScripts + 3 stdcall DownlevelVerifyScripts(long ptr long ptr long) kernel32.VerifyScripts diff --git a/dll/ntdll/dbg/dbgui.c b/dll/ntdll/dbg/dbgui.c index b27a5e2cc3e..b65e06c5d70 100644 --- a/dll/ntdll/dbg/dbgui.c +++ b/dll/ntdll/dbg/dbgui.c @@ -259,7 +259,7 @@ DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, /* Save the image name from the TIB */ DebugEvent->u.LoadDll.lpImageName = ((PTEB)ThreadBasicInfo.TebBaseAddress)-> - Tib.ArbitraryUserPointer; + NtTib.ArbitraryUserPointer; } else { diff --git a/dll/ntdll/dispatch/dispatch.c b/dll/ntdll/dispatch/dispatch.c index 4fb3c43a9ca..50a9ee88f67 100644 --- a/dll/ntdll/dispatch/dispatch.c +++ b/dll/ntdll/dispatch/dispatch.c @@ -79,8 +79,8 @@ KiUserCallbackDispatcher(ULONG Index, ULONG ArgumentLength) { /* Return with the result of the callback function */ + USER_CALL *KernelCallbackTable = NtCurrentPeb()->KernelCallbackTable; ZwCallbackReturn(NULL, 0, - ((USER_CALL)(NtCurrentPeb()->KernelCallbackTable[Index])) - (Argument, ArgumentLength)); + KernelCallbackTable[Index](Argument, ArgumentLength)); } diff --git a/dll/ntdll/ldr/startup.c b/dll/ntdll/ldr/startup.c index 33353e78517..49a4a2c8527 100644 --- a/dll/ntdll/ldr/startup.c +++ b/dll/ntdll/ldr/startup.c @@ -343,8 +343,6 @@ LdrpInit2(PCONTEXT Context, /* initalize peb lock support */ RtlInitializeCriticalSection(&PebLock); Peb->FastPebLock = &PebLock; - Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; - Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; /* initialize tls bitmaps */ RtlInitializeBitMap(&TlsBitMap, Peb->TlsBitmapBits, TLS_MINIMUM_AVAILABLE); diff --git a/dll/ntdll/ldr/utils.c b/dll/ntdll/ldr/utils.c index 1fc0adfc066..9dcb99960ef 100644 --- a/dll/ntdll/ldr/utils.c +++ b/dll/ntdll/ldr/utils.c @@ -2299,8 +2299,8 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, /* Map the dll into the process */ ViewSize = 0; ImageBase = 0; - ArbitraryUserPointer = NtCurrentTeb()->Tib.ArbitraryUserPointer; - NtCurrentTeb()->Tib.ArbitraryUserPointer = FullDosName.Buffer; + ArbitraryUserPointer = NtCurrentTeb()->NtTib.ArbitraryUserPointer; + NtCurrentTeb()->NtTib.ArbitraryUserPointer = FullDosName.Buffer; Status = NtMapViewOfSection(SectionHandle, NtCurrentProcess(), &ImageBase, @@ -2311,7 +2311,7 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, ViewShare, 0, PAGE_READONLY); - NtCurrentTeb()->Tib.ArbitraryUserPointer = ArbitraryUserPointer; + NtCurrentTeb()->NtTib.ArbitraryUserPointer = ArbitraryUserPointer; if (!NT_SUCCESS(Status)) { DPRINT1("map view of section failed (Status 0x%08lx)\n", Status); diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c index e37e44405fa..90c3ce322fc 100644 --- a/dll/ntdll/rtl/libsupp.c +++ b/dll/ntdll/rtl/libsupp.c @@ -83,7 +83,7 @@ VOID NTAPI RtlAcquirePebLock(VOID) { PPEB Peb = NtCurrentPeb (); - Peb->FastPebLockRoutine (Peb->FastPebLock); + RtlEnterCriticalSection(Peb->FastPebLock); } /* @@ -93,7 +93,7 @@ VOID NTAPI RtlReleasePebLock(VOID) { PPEB Peb = NtCurrentPeb (); - Peb->FastPebUnlockRoutine (Peb->FastPebLock); + RtlLeaveCriticalSection(Peb->FastPebLock); } /* @@ -201,11 +201,24 @@ RtlpCaptureStackLimits(IN ULONG_PTR Ebp, IN ULONG_PTR *StackEnd) { /* FIXME: Verify */ - *StackBegin = (ULONG_PTR)NtCurrentTeb()->Tib.StackLimit; - *StackEnd = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase; + *StackBegin = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit; + *StackEnd = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase; return TRUE; } +#ifdef _AMD64_ +VOID +NTAPI +RtlpGetStackLimits( + OUT PULONG_PTR LowLimit, + OUT PULONG_PTR HighLimit) +{ + *LowLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit; + *HighLimit = (ULONG_PTR)NtCurrentTeb()->NtTib.StackBase; + return; +} +#endif + BOOLEAN NTAPI RtlIsThreadWithinLoaderCallout(VOID) diff --git a/dll/win32/acledit/acledit.c b/dll/win32/acledit/acledit.c index aae903ef93e..4b16cddb403 100644 --- a/dll/win32/acledit/acledit.c +++ b/dll/win32/acledit/acledit.c @@ -16,8 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* $Id: acledit.c 35011 2008-08-01 16:29:40Z sginsberg $ - * +/* * PROJECT: ReactOS Access Control List Editor * FILE: lib/acledit/acledit.c * PURPOSE: Access Control List Editor diff --git a/dll/win32/acledit/stubs.c b/dll/win32/acledit/stubs.c index 0948892b9d9..45d23c78652 100644 --- a/dll/win32/acledit/stubs.c +++ b/dll/win32/acledit/stubs.c @@ -1,5 +1,4 @@ -/* $Id: stubs.c 35011 2008-08-01 16:29:40Z sginsberg $ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Access Control List Editor * FILE: lib/acledit/stubs.c diff --git a/dll/win32/advapi32/reg/reg.c b/dll/win32/advapi32/reg/reg.c index 686101e7f1b..e131cf2e43b 100644 --- a/dll/win32/advapi32/reg/reg.c +++ b/dll/win32/advapi32/reg/reg.c @@ -42,9 +42,9 @@ static VOID CloseDefaultKeys(VOID); NtClose(Handle); \ } #define IsPredefKey(HKey) \ - (((ULONG)(HKey) & 0xF0000000) == 0x80000000) + (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000) #define GetPredefKeyIndex(HKey) \ - ((ULONG)(HKey) & 0x0FFFFFFF) + ((ULONG_PTR)(HKey) & 0x0FFFFFFF) static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle); static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle); diff --git a/dll/win32/advapi32/sec/misc.c b/dll/win32/advapi32/sec/misc.c index 51cf09e1512..d5976974c58 100644 --- a/dll/win32/advapi32/sec/misc.c +++ b/dll/win32/advapi32/sec/misc.c @@ -289,7 +289,7 @@ CheckNtMartaPresent(VOID) { DWORD ErrorCode; - if (InterlockedCompareExchangePointer(&NtMarta, + if (InterlockedCompareExchangePointer((PVOID)&NtMarta, NULL, NULL) == NULL) { @@ -300,7 +300,7 @@ CheckNtMartaPresent(VOID) if (ErrorCode == ERROR_SUCCESS) { /* try change the NtMarta pointer */ - if (InterlockedCompareExchangePointer(&NtMarta, + if (InterlockedCompareExchangePointer((PVOID)&NtMarta, &NtMartaStatic, NULL) != NULL) { @@ -329,7 +329,7 @@ CheckNtMartaPresent(VOID) VOID UnloadNtMarta(VOID) { - if (InterlockedExchangePointer(&NtMarta, + if (InterlockedExchangePointer((PVOID)&NtMarta, NULL) != NULL) { FreeLibrary(NtMartaStatic.hDllInstance); diff --git a/dll/win32/avicap32/avicap32.c b/dll/win32/avicap32/avicap32.c index 7220f7a2e6d..f4ed19b6e11 100644 --- a/dll/win32/avicap32/avicap32.c +++ b/dll/win32/avicap32/avicap32.c @@ -86,7 +86,7 @@ capCreateCaptureWindowW(LPCWSTR lpszWindowName, nWidth, nHeight, hWnd, - (HMENU)nID, + ULongToHandle(nID), hInstance, NULL); } diff --git a/dll/win32/avifil32/api.c b/dll/win32/avifil32/api.c index dd1c2e23488..ac3c35e5a99 100644 --- a/dll/win32/avifil32/api.c +++ b/dll/win32/avifil32/api.c @@ -1030,14 +1030,14 @@ HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving) * First filter is named "All multimedia files" and its filter is a * collection of all possible extensions except "*.*". */ - if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != S_OK) { + if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != ERROR_SUCCESS) { HeapFree(GetProcessHeap(), 0, lp); return AVIERR_ERROR; } - for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)/sizeof(szFileExt[0])) == S_OK;n++) { + for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)/sizeof(szFileExt[0])) == ERROR_SUCCESS;n++) { /* get CLSID to extension */ size = sizeof(szValue); - if (RegQueryValueW(hKey, szFileExt, szValue, &size) != S_OK) + if (RegQueryValueW(hKey, szFileExt, szValue, &size) != ERROR_SUCCESS) break; /* search if the CLSID is already known */ @@ -1078,7 +1078,7 @@ HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving) RegCloseKey(hKey); /* 2. get descriptions for the CLSIDs and fill out szFilter */ - if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != S_OK) { + if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != ERROR_SUCCESS) { HeapFree(GetProcessHeap(), 0, lp); return AVIERR_ERROR; } @@ -1086,7 +1086,7 @@ HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving) /* first the description */ if (n != 0) { size = sizeof(szValue); - if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == S_OK) { + if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == ERROR_SUCCESS) { size = lstrlenW(szValue); lstrcpynW(szFilter, szValue, cbFilter); } diff --git a/dll/win32/batt/batt.c b/dll/win32/batt/batt.c new file mode 100644 index 00000000000..0a46a395cd0 --- /dev/null +++ b/dll/win32/batt/batt.c @@ -0,0 +1,66 @@ +/* + * PROJECT: ReactOS system libraries + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll\win32\batt\batt.c + * PURPOSE: Battery Class installers + * PROGRAMMERS: Copyright 2010 Eric Kohl + */ + + +#include +#include + +#define NDEBUG +#include + + +BOOL +WINAPI +DllMain(HINSTANCE hinstDll, + DWORD dwReason, + LPVOID reserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDll); + break; + + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + + +DWORD +WINAPI +BatteryClassCoInstaller(IN DI_FUNCTION InstallFunction, + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + switch (InstallFunction) + { + default: + DPRINT("Install function %u ignored\n", InstallFunction); + return ERROR_DI_DO_DEFAULT; + } +} + + +DWORD +WINAPI +BatteryClassInstall(IN DI_FUNCTION InstallFunction, + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + switch (InstallFunction) + { + default: + DPRINT("Install function %u ignored\n", InstallFunction); + return ERROR_DI_DO_DEFAULT; + } +} + +/* EOF */ diff --git a/dll/win32/batt/batt.rbuild b/dll/win32/batt/batt.rbuild new file mode 100644 index 00000000000..221bc3dc9e3 --- /dev/null +++ b/dll/win32/batt/batt.rbuild @@ -0,0 +1,9 @@ + + + . + setupapi + kernel32 + ntdll + batt.c + batt.rc + diff --git a/dll/win32/batt/batt.rc b/dll/win32/batt/batt.rc new file mode 100644 index 00000000000..5d3f1c71eff --- /dev/null +++ b/dll/win32/batt/batt.rc @@ -0,0 +1,13 @@ +#include +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "Battery Class Installer\0" +#define REACTOS_STR_INTERNAL_NAME "batt\0" +#define REACTOS_STR_ORIGINAL_FILENAME "batt.dll\0" +#include + + +IDI_BATTERY ICON "resources/battery.ico" diff --git a/dll/win32/batt/batt.spec b/dll/win32/batt/batt.spec new file mode 100644 index 00000000000..efb53f5578a --- /dev/null +++ b/dll/win32/batt/batt.spec @@ -0,0 +1,3 @@ +@ stdcall BatteryClassCoInstaller(long ptr ptr) +@ stdcall BatteryClassInstall(long ptr ptr) + diff --git a/dll/win32/batt/resource.h b/dll/win32/batt/resource.h new file mode 100644 index 00000000000..d506679737b --- /dev/null +++ b/dll/win32/batt/resource.h @@ -0,0 +1 @@ +#define IDI_BATTERY 2 \ No newline at end of file diff --git a/dll/win32/batt/resources/battery.ico b/dll/win32/batt/resources/battery.ico new file mode 100644 index 00000000000..fae101788e4 Binary files /dev/null and b/dll/win32/batt/resources/battery.ico differ diff --git a/dll/win32/beepmidi/beepmidi.c b/dll/win32/beepmidi/beepmidi.c index 696a359f742..6365d05e65c 100644 --- a/dll/win32/beepmidi/beepmidi.c +++ b/dll/win32/beepmidi/beepmidi.c @@ -244,7 +244,7 @@ CallClient( DWORD_PTR parameter1, DWORD_PTR parameter2) { - DPRINT("Calling client - callback 0x%x mmhandle 0x%x\n", (int) device_info->callback, device_info->mme_handle); + DPRINT("Calling client - callback 0x%x mmhandle 0x%x\n", device_info->callback, device_info->mme_handle); return DriverCallback(device_info->callback, HIWORD(device_info->flags), device_info->mme_handle, diff --git a/dll/win32/crypt32/chain.c b/dll/win32/crypt32/chain.c index 6cdd103e666..1724f4254fe 100644 --- a/dll/win32/crypt32/chain.c +++ b/dll/win32/crypt32/chain.c @@ -1306,6 +1306,78 @@ static void CRYPT_CheckChainNameConstraints(PCERT_SIMPLE_CHAIN chain) } } +/* Gets cert's policies info, if any. Free with LocalFree. */ +static CERT_POLICIES_INFO *CRYPT_GetPolicies(PCCERT_CONTEXT cert) +{ + PCERT_EXTENSION ext; + CERT_POLICIES_INFO *policies = NULL; + + ext = CertFindExtension(szOID_KEY_USAGE, cert->pCertInfo->cExtension, + cert->pCertInfo->rgExtension); + if (ext) + { + DWORD size; + + CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_POLICIES, + ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, + &policies, &size); + } + return policies; +} + +static void CRYPT_CheckPolicies(CERT_POLICIES_INFO *policies, CERT_INFO *cert, + DWORD *errorStatus) +{ + DWORD i; + + for (i = 0; i < policies->cPolicyInfo; i++) + { + /* For now, the only accepted policy identifier is the anyPolicy + * identifier. + * FIXME: the policy identifiers should be compared against the + * cert's certificate policies extension, subject to the policy + * mappings extension, and the policy constraints extension. + * See RFC 5280, sections 4.2.1.4, 4.2.1.5, and 4.2.1.11. + */ + if (strcmp(policies->rgPolicyInfo[i].pszPolicyIdentifier, + szOID_ANY_CERT_POLICY)) + { + FIXME("unsupported policy %s\n", + policies->rgPolicyInfo[i].pszPolicyIdentifier); + *errorStatus |= CERT_TRUST_INVALID_POLICY_CONSTRAINTS; + } + } +} + +static void CRYPT_CheckChainPolicies(PCERT_SIMPLE_CHAIN chain) +{ + int i, j; + + for (i = chain->cElement - 1; i > 0; i--) + { + CERT_POLICIES_INFO *policies; + + if ((policies = CRYPT_GetPolicies(chain->rgpElement[i]->pCertContext))) + { + for (j = i - 1; j >= 0; j--) + { + DWORD errorStatus = 0; + + CRYPT_CheckPolicies(policies, + chain->rgpElement[j]->pCertContext->pCertInfo, &errorStatus); + if (errorStatus) + { + chain->rgpElement[i]->TrustStatus.dwErrorStatus |= + errorStatus; + CRYPT_CombineTrustStatus(&chain->TrustStatus, + &chain->rgpElement[i]->TrustStatus); + } + } + LocalFree(policies); + } + } +} + static LPWSTR name_value_to_str(const CERT_NAME_BLOB *name) { DWORD len = cert_name_to_str_with_indent(X509_ASN_ENCODING, 0, name, @@ -1739,6 +1811,8 @@ static BOOL CRYPT_CriticalExtensionsSupported(PCCERT_CONTEXT cert) ret = TRUE; else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME2)) ret = TRUE; + else if (!strcmp(oid, szOID_CERT_POLICIES)) + ret = TRUE; else if (!strcmp(oid, szOID_ENHANCED_KEY_USAGE)) ret = TRUE; else @@ -1883,6 +1957,7 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine, &chain->rgpElement[i]->TrustStatus); } CRYPT_CheckChainNameConstraints(chain); + CRYPT_CheckChainPolicies(chain); if (CRYPT_IsCertificateSelfSigned(rootElement->pCertContext)) { rootElement->TrustStatus.dwInfoStatus |= diff --git a/dll/win32/crypt32/main.c b/dll/win32/crypt32/main.c index 5844b1841e5..db9dc1a946a 100644 --- a/dll/win32/crypt32/main.c +++ b/dll/win32/crypt32/main.c @@ -64,8 +64,8 @@ HCRYPTPROV CRYPT_GetDefaultProvider(void) { HCRYPTPROV prov; - if (!CryptAcquireContextW(&prov, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) + if (!CryptAcquireContextW(&prov, NULL, MS_ENH_RSA_AES_PROV_W, + PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) return hDefProv; InterlockedCompareExchangePointer((PVOID *)&hDefProv, (PVOID)prov, NULL); diff --git a/dll/win32/crypt32/oid.c b/dll/win32/crypt32/oid.c index ea30d9ccd45..ea7b539208b 100644 --- a/dll/win32/crypt32/oid.c +++ b/dll/win32/crypt32/oid.c @@ -1067,6 +1067,9 @@ static const WCHAR rc2[] = { 'r','c','2',0 }; static const WCHAR rc4[] = { 'r','c','4',0 }; static const WCHAR sha[] = { 's','h','a',0 }; static const WCHAR sha1[] = { 's','h','a','1',0 }; +static const WCHAR sha256[] = { 's','h','a','2','5','6',0 }; +static const WCHAR sha384[] = { 's','h','a','3','8','4',0 }; +static const WCHAR sha512[] = { 's','h','a','5','1','2',0 }; static const WCHAR RSA[] = { 'R','S','A',0 }; static const WCHAR RSA_KEYX[] = { 'R','S','A','_','K','E','Y','X',0 }; static const WCHAR RSA_SIGN[] = { 'R','S','A','_','S','I','G','N',0 }; @@ -1086,6 +1089,9 @@ static const WCHAR shaDSA[] = { 's','h','a','D','S','A',0 }; static const WCHAR sha1DSA[] = { 's','h','a','1','D','S','A',0 }; static const WCHAR shaRSA[] = { 's','h','a','R','S','A',0 }; static const WCHAR sha1RSA[] = { 's','h','a','1','R','S','A',0 }; +static const WCHAR sha256RSA[] = { 's','h','a','2','5','6','R','S','A',0 }; +static const WCHAR sha384RSA[] = { 's','h','a','3','8','4','R','S','A',0 }; +static const WCHAR sha512RSA[] = { 's','h','a','5','1','2','R','S','A',0 }; static const WCHAR mosaicUpdatedSig[] = { 'm','o','s','a','i','c','U','p','d','a','t','e','d','S','i','g',0 }; static const WCHAR CN[] = { 'C','N',0 }; @@ -1189,6 +1195,9 @@ static const struct OIDInfoConstructor { { 3, szOID_PKIX_NO_SIGNATURE, CALG_NO_SIGN, NO_SIGN, NULL }, { 4, szOID_RSA_SHA1RSA, CALG_SHA1, sha1RSA, &rsaSignBlob }, + { 4, szOID_RSA_SHA256RSA, CALG_SHA_256, sha256RSA, &rsaSignBlob }, + { 4, szOID_RSA_SHA384RSA, CALG_SHA_384, sha384RSA, &rsaSignBlob }, + { 4, szOID_RSA_SHA512RSA, CALG_SHA_512, sha512RSA, &rsaSignBlob }, { 4, szOID_RSA_MD5RSA, CALG_MD5, md5RSA, &rsaSignBlob }, { 4, szOID_X957_SHA1DSA, CALG_SHA1, sha1DSA, &dssSignBlob }, { 4, szOID_OIWSEC_sha1RSASign, CALG_SHA1, sha1RSA, &rsaSignBlob }, diff --git a/dll/win32/dbghelp/dbghelp_private.h b/dll/win32/dbghelp/dbghelp_private.h index e7e3c7c3c37..5ea2e824b6e 100644 --- a/dll/win32/dbghelp/dbghelp_private.h +++ b/dll/win32/dbghelp/dbghelp_private.h @@ -313,6 +313,36 @@ enum module_type }; struct process; +struct module; + +/* a module can be made of several debug information formats, so we have to + * support them all + */ +enum format_info +{ + DFI_ELF, + DFI_PE, + DFI_MACHO, + DFI_DWARF, + DFI_LAST +}; + +struct module_format +{ + struct module* module; + void (*remove)(struct process* pcs, struct module_format* modfmt); + void (*loc_compute)(struct process* pcs, + const struct module_format* modfmt, + const struct symt_function* func, + struct location* loc); + union + { + struct elf_module_info* elf_info; + struct dwarf2_module_info_s* dwarf2_info; + struct pe_module_info* pe_info; + struct macho_module_info* macho_info; + } u; +}; struct module { @@ -324,10 +354,7 @@ struct module unsigned short is_virtual : 1; /* specific information for debug types */ - struct elf_module_info* elf_info; - struct dwarf2_module_info_s*dwarf2_info; - - struct macho_module_info* macho_info; + struct module_format* format_info[DFI_LAST]; /* memory allocation pool */ struct pool pool; @@ -340,10 +367,6 @@ struct module unsigned sorttab_size; struct symt_ht** addr_sorttab; struct hash_table ht_symbols; - void (*loc_compute)(struct process* pcs, - const struct module* module, - const struct symt_function* func, - struct location* loc); /* types */ struct hash_table ht_types; @@ -471,11 +494,10 @@ extern DWORD calc_crc32(int fd); typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user); /* elf_module.c */ -#define ELF_NO_MAP ((const void*)-1) extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*); extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum); -struct elf_file_map; -extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap); +struct image_file_map; +extern BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap); extern struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned long); extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs); @@ -565,11 +587,7 @@ extern BOOL stabs_parse(struct module* module, unsigned long load_offset /* dwarf.c */ extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const struct elf_thunk_area* thunks, - const unsigned char* debug, unsigned int debug_size, - const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_size, - const unsigned char* line, unsigned int line_size, - const unsigned char* loclist, unsigned int loclist_size); + struct image_file_map* fmap); /* stack.c */ extern BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz); diff --git a/dll/win32/dbghelp/dwarf.c b/dll/win32/dbghelp/dwarf.c index 433dca88ff4..199b3bb4b8a 100644 --- a/dll/win32/dbghelp/dwarf.c +++ b/dll/win32/dbghelp/dwarf.c @@ -51,6 +51,7 @@ #include "oleauto.h" #include "dbghelp_private.h" +#include "image_private.h" #include "wine/debug.h" @@ -139,6 +140,7 @@ struct attribute union { unsigned long uvalue; + ULONGLONG lluvalue; long svalue; const char* string; struct dwarf2_block block; @@ -157,6 +159,7 @@ typedef struct dwarf2_section_s { const unsigned char* address; unsigned size; + DWORD_PTR rva; } dwarf2_section_t; enum dwarf2_sections {section_debug, section_string, section_abbrev, section_line, section_max}; @@ -512,9 +515,8 @@ static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx, break; case DW_FORM_data8: - attr->u.block.size = 8; - attr->u.block.ptr = data; - data += 8; + attr->u.lluvalue = dwarf2_get_u8(data); + TRACE("data8<%s>\n", wine_dbgstr_longlong(attr->u.uvalue)); break; case DW_FORM_ref1: @@ -1480,6 +1482,11 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, v.n1.n2.n3.lVal = value.u.uvalue; break; + case DW_FORM_data8: + v.n1.n2.vt = VT_UI8; + v.n1.n2.n3.llVal = value.u.lluvalue; + break; + case DW_FORM_sdata: v.n1.n2.vt = VT_I4; v.n1.n2.n3.lVal = value.u.svalue; @@ -1511,12 +1518,6 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, } break; - case DW_FORM_data8: - v.n1.n2.vt = VT_I1 | VT_BYREF; - v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size); - memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size); - break; - default: FIXME("Unsupported form for const value %s (%lx)\n", name.u.string, value.form); @@ -1952,7 +1953,7 @@ static BOOL dwarf2_parse_line_numbers(const dwarf2_section_t* sections, const char** p; /* section with line numbers stripped */ - if (sections[section_line].address == ELF_NO_MAP) + if (sections[section_line].address == IMAGE_NO_MAP) return FALSE; traverse.data = sections[section_line].address + offset; @@ -2211,7 +2212,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections, return ret; } -static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start, +static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const BYTE* start, unsigned long ip, dwarf2_traverse_context_t* lctx) { @@ -2219,7 +2220,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start const BYTE* ptr = start; DWORD len; - while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size) + while (ptr < modfmt->u.dwarf2_info->debug_loc.address + modfmt->u.dwarf2_info->debug_loc.size) { beg = dwarf2_get_u4(ptr); ptr += 4; end = dwarf2_get_u4(ptr); ptr += 4; @@ -2240,7 +2241,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start } static enum location_error loc_compute_frame(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, DWORD ip, struct location* frame) { @@ -2266,8 +2267,8 @@ static enum location_error loc_compute_frame(struct process* pcs, break; case loc_dwarf2_location_list: WARN("Searching loclist for %s\n", func->hash_elt.name); - if (!dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + pframe->offset, + if (!dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + pframe->offset, ip, &lctx)) return loc_err_out_of_scope; if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err; @@ -2289,7 +2290,7 @@ static enum location_error loc_compute_frame(struct process* pcs, } static void dwarf2_location_compute(struct process* pcs, - const struct module* module, + const struct module_format* modfmt, const struct symt_function* func, struct location* loc) { @@ -2308,14 +2309,14 @@ static void dwarf2_location_compute(struct process* pcs, /* instruction pointer relative to compiland's start */ ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address; - if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0) + if ((err = loc_compute_frame(pcs, modfmt, func, ip, &frame)) == 0) { switch (loc->kind) { case loc_dwarf2_location_list: /* Then, if the variable has a location list, find it !! */ - if (dwarf2_lookup_loclist(module, - module->dwarf2_info->debug_loc.address + loc->offset, + if (dwarf2_lookup_loclist(modfmt, + modfmt->u.dwarf2_info->debug_loc.address + loc->offset, ip, &lctx)) goto do_compute; err = loc_err_out_of_scope; @@ -2350,56 +2351,115 @@ static void dwarf2_location_compute(struct process* pcs, } } +static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt) +{ + HeapFree(GetProcessHeap(), 0, modfmt->u.dwarf2_info); + HeapFree(GetProcessHeap(), 0, modfmt); +} + +static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap, + const char* sectname, struct image_section_map* ism) +{ + struct image_section_map local_ism; + + if (!ism) ism = &local_ism; + if (!image_find_section(fmap, sectname, ism)) + { + section->address = NULL; + section->size = 0; + section->rva = 0; + return FALSE; + } + + section->address = (const BYTE*)image_map_section(ism); + section->size = image_get_map_size(ism); + section->rva = image_get_map_rva(ism); + return TRUE; +} + BOOL dwarf2_parse(struct module* module, unsigned long load_offset, const struct elf_thunk_area* thunks, - const unsigned char* debug, unsigned int debug_size, - const unsigned char* abbrev, unsigned int abbrev_size, - const unsigned char* str, unsigned int str_size, - const unsigned char* line, unsigned int line_size, - const unsigned char* loclist, unsigned int loclist_size) + struct image_file_map* fmap) { dwarf2_section_t section[section_max]; - unsigned char* ptr; dwarf2_traverse_context_t mod_ctx; + struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect, + debug_line_sect, debug_loclist_sect; + BOOL ret = TRUE; + struct module_format* dwarf2_modfmt; - mod_ctx.start_data = mod_ctx.data = debug; - mod_ctx.end_data = debug + debug_size; + if (!dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect)) + { + /* no Dwarf debug info here, so there's no error */ + return TRUE; + } + dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect); + dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect); + dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect); - module->loc_compute = dwarf2_location_compute; + if (section[section_debug].address == IMAGE_NO_MAP || + section[section_abbrev].address == IMAGE_NO_MAP || + section[section_string].address == IMAGE_NO_MAP) + { + ret = FALSE; + goto leave; + } - section[section_debug].address = debug; - section[section_debug].size = debug_size; - section[section_abbrev].address = abbrev; - section[section_abbrev].size = abbrev_size; - section[section_string].address = str; - section[section_string].size = str_size; - section[section_line].address = line; - section[section_line].size = line_size; + if (fmap->modtype == DMT_ELF) + { + /* debug info might have a different base address than .so file + * when elf file is prelinked after splitting off debug info + * adjust symbol base addresses accordingly + */ + load_offset += fmap->u.elf.elf_start - debug_sect.fmap->u.elf.elf_start; + } - if (loclist_size) + TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName)); + + mod_ctx.start_data = mod_ctx.data = section[section_debug].address; + mod_ctx.end_data = mod_ctx.data + section[section_debug].size; + + + dwarf2_modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(*dwarf2_modfmt)); + if (!dwarf2_modfmt) return FALSE; + dwarf2_modfmt->module = module; + dwarf2_modfmt->remove = dwarf2_module_remove; + dwarf2_modfmt->loc_compute = dwarf2_location_compute; + dwarf2_modfmt->u.dwarf2_info = NULL; + dwarf2_modfmt->module->format_info[DFI_DWARF] = dwarf2_modfmt; + + image_find_section(fmap, ".debug_loc", &debug_loclist_sect); + if (image_get_map_size(&debug_loclist_sect)) { /* initialize the dwarf2 specific info block for this module. - * As we'll need later on the .debug_loc section content, we copy it in - * the module structure for later reuse + * As we'll need later the .debug_loc section content, we won't unmap this + * section upon existing this function */ - module->dwarf2_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*module->dwarf2_info) + loclist_size); - if (!module->dwarf2_info) return FALSE; - ptr = (unsigned char*)(module->dwarf2_info + 1); - memcpy(ptr, loclist, loclist_size); - module->dwarf2_info->debug_loc.address = ptr; - module->dwarf2_info->debug_loc.size = loclist_size; + dwarf2_modfmt->u.dwarf2_info = HeapAlloc(GetProcessHeap(), 0, + sizeof(*dwarf2_modfmt->u.dwarf2_info)); + if (!dwarf2_modfmt->u.dwarf2_info) goto leave; + dwarf2_modfmt->u.dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect); + dwarf2_modfmt->u.dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect); } + else image_unmap_section(&debug_loclist_sect); while (mod_ctx.data < mod_ctx.end_data) { - dwarf2_parse_compilation_unit(section, module, thunks, &mod_ctx, load_offset); + dwarf2_parse_compilation_unit(section, dwarf2_modfmt->module, thunks, &mod_ctx, load_offset); } - module->module.SymType = SymDia; - module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); + dwarf2_modfmt->module->module.SymType = SymDia; + dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24); /* FIXME: we could have a finer grain here */ - module->module.GlobalSymbols = TRUE; - module->module.TypeInfo = TRUE; - module->module.SourceIndexed = TRUE; - module->module.Publics = TRUE; - return TRUE; + dwarf2_modfmt->module->module.GlobalSymbols = TRUE; + dwarf2_modfmt->module->module.TypeInfo = TRUE; + dwarf2_modfmt->module->module.SourceIndexed = TRUE; + dwarf2_modfmt->module->module.Publics = TRUE; + +leave: + image_unmap_section(&debug_sect); + image_unmap_section(&debug_abbrev_sect); + image_unmap_section(&debug_str_sect); + image_unmap_section(&debug_line_sect); + + return ret; } diff --git a/dll/win32/dbghelp/elf_module.c b/dll/win32/dbghelp/elf_module.c index 6a8a1515f9d..573a04065c3 100644 --- a/dll/win32/dbghelp/elf_module.c +++ b/dll/win32/dbghelp/elf_module.c @@ -48,40 +48,11 @@ #include "dbghelp_private.h" -#ifdef HAVE_ELF_H -# include -#endif -#ifdef HAVE_SYS_ELF32_H -# include -#endif -#ifdef HAVE_SYS_EXEC_ELF_H -# include -#endif -#if !defined(DT_NUM) -# if defined(DT_COUNT) -# define DT_NUM DT_COUNT -# else -/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */ -# define DT_NUM 24 -# endif -#endif -#ifdef HAVE_LINK_H -# include -#endif -#ifdef HAVE_SYS_LINK_H -# include -#endif +#include "image_private.h" #include "wine/library.h" #include "wine/debug.h" -struct elf_module_info -{ - DWORD_PTR elf_addr; - unsigned short elf_mark : 1, - elf_loader : 1; -}; - #ifdef __ELF__ #define ELF_INFO_DEBUG_HEADER 0x0001 @@ -98,44 +69,6 @@ struct elf_info const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */ }; -#ifdef _WIN64 -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Dyn Elf64_Dyn -#define Elf_Sym Elf64_Sym -#else -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Phdr Elf32_Phdr -#define Elf_Dyn Elf32_Dyn -#define Elf_Sym Elf32_Sym -#endif - -/* structure holding information while handling an ELF image - * allows one by one section mapping for memory savings - */ -struct elf_file_map -{ - Elf_Ehdr elfhdr; - size_t elf_size; - size_t elf_start; - struct - { - Elf_Shdr shdr; - const char* mapped; - }* sect; - int fd; - const char* shstrtab; - struct elf_file_map* alternate; /* another ELF file (linked to this one) */ -}; - -struct elf_section_map -{ - struct elf_file_map* fmap; - long sidx; -}; - struct symtab_elt { struct hash_table_elt ht_elt; @@ -152,28 +85,39 @@ struct elf_thunk_area unsigned long rva_end; }; +struct elf_module_info +{ + unsigned long elf_addr; + unsigned short elf_mark : 1, + elf_loader : 1; + struct image_file_map file_map; +}; + /****************************************************************** * elf_map_section * * Maps a single section into memory from an ELF file */ -static const char* elf_map_section(struct elf_section_map* esm) +const char* elf_map_section(struct image_section_map* ism) { + struct elf_file_map* fmap = &ism->fmap->u.elf; + unsigned pgsz = getpagesize(); unsigned ofst, size; - if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum || - esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS) - return ELF_NO_MAP; + assert(ism->fmap->modtype == DMT_ELF); + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum || + fmap->sect[ism->sidx].shdr.sh_type == SHT_NOBITS) + return IMAGE_NO_MAP; /* align required information on page size (we assume pagesize is a power of 2) */ - ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1); - size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset + - esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; - esm->fmap->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, - esm->fmap->fd, ofst); - if (esm->fmap->sect[esm->sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP; - return esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1)); + ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((fmap->sect[ism->sidx].shdr.sh_offset + + fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + fmap->sect[ism->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, + fmap->fd, ofst); + if (fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) return IMAGE_NO_MAP; + return fmap->sect[ism->sidx].mapped + (fmap->sect[ism->sidx].shdr.sh_offset & (pgsz - 1)); } /****************************************************************** @@ -182,32 +126,34 @@ static const char* elf_map_section(struct elf_section_map* esm) * Finds a section by name (and type) into memory from an ELF file * or its alternate if any */ -static BOOL elf_find_section(struct elf_file_map* fmap, const char* name, - unsigned sht, struct elf_section_map* esm) +BOOL elf_find_section(struct image_file_map* _fmap, const char* name, + unsigned sht, struct image_section_map* ism) { + struct elf_file_map* fmap; unsigned i; - while (fmap) + while (_fmap) { - if (fmap->shstrtab == ELF_NO_MAP) + fmap = &_fmap->u.elf; + if (fmap->shstrtab == IMAGE_NO_MAP) { - struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx}; - if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == ELF_NO_MAP) break; + struct image_section_map hdr_ism = {_fmap, fmap->elfhdr.e_shstrndx}; + if ((fmap->shstrtab = elf_map_section(&hdr_ism)) == IMAGE_NO_MAP) break; } for (i = 0; i < fmap->elfhdr.e_shnum; i++) { if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 && (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type)) { - esm->fmap = fmap; - esm->sidx = i; + ism->fmap = _fmap; + ism->sidx = i; return TRUE; } } - fmap = fmap->alternate; + _fmap = fmap->alternate; } - esm->fmap = NULL; - esm->sidx = -1; + ism->fmap = NULL; + ism->sidx = -1; return FALSE; } @@ -216,46 +162,67 @@ static BOOL elf_find_section(struct elf_file_map* fmap, const char* name, * * Unmaps a single section from memory */ -static void elf_unmap_section(struct elf_section_map* esm) +void elf_unmap_section(struct image_section_map* ism) { - if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != ELF_NO_MAP) + struct elf_file_map* fmap = &ism->fmap->u.elf; + + if (ism->sidx >= 0 && ism->sidx < fmap->elfhdr.e_shnum && fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP) { unsigned pgsz = getpagesize(); unsigned ofst, size; - ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1); - size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset + - esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; - if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0) + ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1); + size = ((fmap->sect[ism->sidx].shdr.sh_offset + + fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst; + if (munmap((char*)fmap->sect[ism->sidx].mapped, size) < 0) WARN("Couldn't unmap the section\n"); - esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP; + fmap->sect[ism->sidx].mapped = IMAGE_NO_MAP; } } -static void elf_end_find(struct elf_file_map* fmap) +static void elf_end_find(struct image_file_map* fmap) { - struct elf_section_map esm; + struct image_section_map ism; while (fmap) { - esm.fmap = fmap; - esm.sidx = fmap->elfhdr.e_shstrndx; - elf_unmap_section(&esm); - fmap->shstrtab = ELF_NO_MAP; - fmap = fmap->alternate; + ism.fmap = fmap; + ism.sidx = fmap->u.elf.elfhdr.e_shstrndx; + elf_unmap_section(&ism); + fmap->u.elf.shstrtab = IMAGE_NO_MAP; + fmap = fmap->u.elf.alternate; } } +/****************************************************************** + * elf_get_map_rva + * + * Get the RVA of an ELF section + */ +DWORD_PTR elf_get_map_rva(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum) + return 0; + return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_addr - ism->fmap->u.elf.elf_start; +} + /****************************************************************** * elf_get_map_size * * Get the size of an ELF section */ -static inline unsigned elf_get_map_size(const struct elf_section_map* esm) +unsigned elf_get_map_size(const struct image_section_map* ism) { - if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum) + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum) return 0; - return esm->fmap->sect[esm->sidx].shdr.sh_size; + return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_size; +} + +static inline void elf_reset_file_map(struct image_file_map* fmap) +{ + fmap->u.elf.fd = -1; + fmap->u.elf.shstrtab = IMAGE_NO_MAP; + fmap->u.elf.alternate = NULL; } /****************************************************************** @@ -263,7 +230,7 @@ static inline unsigned elf_get_map_size(const struct elf_section_map* esm) * * Maps an ELF file into memory (and checks it's a real ELF file) */ -static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap) +static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap) { static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 }; struct stat statbuf; @@ -278,56 +245,55 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap) if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE; WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL); - fmap->fd = -1; - fmap->shstrtab = ELF_NO_MAP; - fmap->alternate = NULL; + elf_reset_file_map(fmap); + fmap->modtype = DMT_ELF; /* check that the file exists, and that the module hasn't been loaded yet */ if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done; /* Now open the file, so that we can mmap() it. */ - if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done; + if ((fmap->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done; - if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr)) + if (read(fmap->u.elf.fd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr)) != sizeof(fmap->u.elf.elfhdr)) goto done; /* and check for an ELF header */ - if (memcmp(fmap->elfhdr.e_ident, + if (memcmp(fmap->u.elf.elfhdr.e_ident, elf_signature, sizeof(elf_signature))) goto done; /* and check 32 vs 64 size according to current machine */ #ifdef _WIN64 - if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done; + if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done; #else - if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done; + if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done; #endif - fmap->sect = HeapAlloc(GetProcessHeap(), 0, - fmap->elfhdr.e_shnum * sizeof(fmap->sect[0])); - if (!fmap->sect) goto done; + fmap->u.elf.sect = HeapAlloc(GetProcessHeap(), 0, + fmap->u.elf.elfhdr.e_shnum * sizeof(fmap->u.elf.sect[0])); + if (!fmap->u.elf.sect) goto done; - lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET); - for (i = 0; i < fmap->elfhdr.e_shnum; i++) + lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_shoff, SEEK_SET); + for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++) { - read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr)); - fmap->sect[i].mapped = ELF_NO_MAP; + read(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr)); + fmap->u.elf.sect[i].mapped = IMAGE_NO_MAP; } /* grab size of module once loaded in memory */ - lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET); - fmap->elf_size = 0; - fmap->elf_start = ~0L; - for (i = 0; i < fmap->elfhdr.e_phnum; i++) + lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_phoff, SEEK_SET); + fmap->u.elf.elf_size = 0; + fmap->u.elf.elf_start = ~0L; + for (i = 0; i < fmap->u.elf.elfhdr.e_phnum; i++) { - if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) && + if (read(fmap->u.elf.fd, &phdr, sizeof(phdr)) == sizeof(phdr) && phdr.p_type == PT_LOAD) { tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask; - if (fmap->elf_size < tmp) fmap->elf_size = tmp; - if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr; + if (fmap->u.elf.elf_size < tmp) fmap->u.elf.elf_size = tmp; + if (phdr.p_vaddr < fmap->u.elf.elf_start) fmap->u.elf.elf_start = phdr.p_vaddr; } } /* if non relocatable ELF, then remove fixed address from computation * otherwise, all addresses are zero based and start has no effect */ - fmap->elf_size -= fmap->elf_start; + fmap->u.elf.elf_size -= fmap->u.elf.elf_start; ret = TRUE; done: HeapFree(GetProcessHeap(), 0, filename); @@ -339,25 +305,31 @@ done: * * Unmaps an ELF file from memory (previously mapped with elf_map_file) */ -static void elf_unmap_file(struct elf_file_map* fmap) +static void elf_unmap_file(struct image_file_map* fmap) { while (fmap) { - if (fmap->fd != -1) + if (fmap->u.elf.fd != -1) { - struct elf_section_map esm; - esm.fmap = fmap; - for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++) + struct image_section_map ism; + ism.fmap = fmap; + for (ism.sidx = 0; ism.sidx < fmap->u.elf.elfhdr.e_shnum; ism.sidx++) { - elf_unmap_section(&esm); + elf_unmap_section(&ism); } - HeapFree(GetProcessHeap(), 0, fmap->sect); - close(fmap->fd); + HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect); + close(fmap->u.elf.fd); } - fmap = fmap->alternate; + fmap = fmap->u.elf.alternate; } } +static void elf_module_remove(struct process* pcs, struct module_format* modfmt) +{ + elf_unmap_file(&modfmt->u.elf_info->file_map); + HeapFree(GetProcessHeap(), 0, modfmt); +} + /****************************************************************** * elf_is_in_thunk_area * @@ -382,8 +354,8 @@ int elf_is_in_thunk_area(unsigned long addr, * * creating an internal hash table to ease use ELF symtab information lookup */ -static void elf_hash_symtab(struct module* module, struct pool* pool, - struct hash_table* ht_symtab, struct elf_file_map* fmap, +static void elf_hash_symtab(struct module* module, struct pool* pool, + struct hash_table* ht_symtab, struct image_file_map* fmap, struct elf_thunk_area* thunks) { int i, j, nsym; @@ -393,16 +365,20 @@ static void elf_hash_symtab(struct module* module, struct pool* pool, const char* ptr; const Elf_Sym* symp; struct symtab_elt* ste; - struct elf_section_map esm, esm_str; + struct image_section_map ism, ism_str; - if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) && - !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return; - if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return; - esm_str.fmap = fmap; - esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link; - if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return; + if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &ism) && + !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &ism)) return; + if ((symp = (const Elf_Sym*)image_map_section(&ism)) == IMAGE_NO_MAP) return; + ism_str.fmap = ism.fmap; + ism_str.sidx = fmap->u.elf.sect[ism.sidx].shdr.sh_link; + if ((strp = image_map_section(&ism_str)) == IMAGE_NO_MAP) + { + image_unmap_section(&ism); + return; + } - nsym = elf_get_map_size(&esm) / sizeof(*symp); + nsym = image_get_map_size(&ism) / sizeof(*symp); for (j = 0; thunks[j].symname; j++) thunks[j].rva_start = thunks[j].rva_end = 0; @@ -567,6 +543,7 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table void* ptr; struct symt_ht* sym; const Elf_Sym* symp; + struct elf_module_info* elf_info = module->format_info[DFI_ELF]->u.elf_info; hash_table_iter_init(&module->ht_symbols, &hti, NULL); while ((ptr = hash_table_iter_up(&hti))) @@ -575,7 +552,7 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table switch (sym->symt.tag) { case SymTagFunction: - if (((struct symt_function*)sym)->address != module->elf_info->elf_addr && + if (((struct symt_function*)sym)->address != elf_info->elf_addr && ((struct symt_function*)sym)->size) { break; @@ -584,18 +561,17 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table ((struct symt_function*)sym)->container); if (symp) { - if (((struct symt_function*)sym)->address != module->elf_info->elf_addr && - ((struct symt_function*)sym)->address != module->elf_info->elf_addr + symp->st_value) + if (((struct symt_function*)sym)->address != elf_info->elf_addr && + ((struct symt_function*)sym)->address != elf_info->elf_addr + symp->st_value) FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, - ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); + ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value); if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size) FIXME("Changing size for %p/%s!%s from %08lx to %08x\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, ((struct symt_function*)sym)->size, (unsigned int)symp->st_size); - ((struct symt_function*)sym)->address = module->elf_info->elf_addr + - symp->st_value; + ((struct symt_function*)sym)->address = elf_info->elf_addr + symp->st_value; ((struct symt_function*)sym)->size = symp->st_size; } else FIXME("Couldn't find %s!%s\n", @@ -606,19 +582,18 @@ static void elf_finish_stabs_info(struct module* module, const struct hash_table { case DataIsGlobal: case DataIsFileStatic: - if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr) + if (((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr) break; symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, ((struct symt_data*)sym)->container); if (symp) { - if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr && - ((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr + symp->st_value) + if (((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr && + ((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr + symp->st_value) FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n", sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name, - ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value); - ((struct symt_data*)sym)->u.var.offset = module->elf_info->elf_addr + - symp->st_value; + ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value); + ((struct symt_data*)sym)->u.var.offset = elf_info->elf_addr + symp->st_value; ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal; } else @@ -656,7 +631,7 @@ static int elf_new_wine_thunks(struct module* module, const struct hash_table* h { if (ste->used) continue; - addr = module->elf_info->elf_addr + ste->symp->st_value; + addr = module->format_info[DFI_ELF]->u.elf_info->elf_addr + ste->symp->st_value; j = elf_is_in_thunk_area(ste->symp->st_value, thunks); if (j >= 0) /* thunk found */ @@ -748,20 +723,20 @@ static int elf_new_public_symbols(struct module* module, const struct hash_table while ((ste = hash_table_iter_up(&hti))) { symt_new_public(module, ste->compiland, ste->ht_elt.name, - module->elf_info->elf_addr + ste->symp->st_value, + module->format_info[DFI_ELF]->u.elf_info->elf_addr + ste->symp->st_value, ste->symp->st_size); } return TRUE; } -static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc) +static BOOL elf_check_debug_link(const WCHAR* file, struct image_file_map* fmap, DWORD crc) { BOOL ret; if (!elf_map_file(file, fmap)) return FALSE; - if (!(ret = crc == calc_crc32(fmap->fd))) + if (!(ret = crc == calc_crc32(fmap->u.elf.fd))) { WARN("Bad CRC for file %s (got %08x while expecting %08x)\n", - debugstr_w(file), calc_crc32(fmap->fd), crc); + debugstr_w(file), calc_crc32(fmap->u.elf.fd), crc); elf_unmap_file(fmap); } return ret; @@ -786,7 +761,7 @@ static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, D * is the global debug file directory, and execdir has been turned * into a relative path)." (from GDB manual) */ -static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filename, +static BOOL elf_locate_debug_link(struct image_file_map* fmap, const char* filename, const WCHAR* loaded_file, DWORD crc) { static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; @@ -795,7 +770,7 @@ static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filenam size_t filename_len; WCHAR* p = NULL; WCHAR* slash; - struct elf_file_map* fmap_link = NULL; + struct image_file_map* fmap_link = NULL; fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); if (!fmap_link) return FALSE; @@ -838,7 +813,7 @@ static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filenam found: TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p)); HeapFree(GetProcessHeap(), 0, p); - fmap->alternate = fmap_link; + fmap->u.elf.alternate = fmap_link; return TRUE; } @@ -848,7 +823,7 @@ found: * Parses a .gnu_debuglink section and loads the debug info from * the external file specified there. */ -static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module* module, +static BOOL elf_debuglink_parse(struct image_file_map* fmap, const struct module* module, const BYTE* debuglink) { /* The content of a debug link section is: @@ -877,8 +852,8 @@ static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module* * read or parsed) * 1 on success */ -static BOOL elf_load_debug_info_from_map(struct module* module, - struct elf_file_map* fmap, +static BOOL elf_load_debug_info_from_map(struct module* module, + struct image_file_map* fmap, struct pool* pool, struct hash_table* ht_symtab) { @@ -901,18 +876,16 @@ static BOOL elf_load_debug_info_from_map(struct module* module, if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - struct elf_section_map stab_sect, stabstr_sect; - struct elf_section_map debug_sect, debug_str_sect, debug_abbrev_sect, - debug_line_sect, debug_loclist_sect; - struct elf_section_map debuglink_sect; + struct image_section_map stab_sect, stabstr_sect; + struct image_section_map debuglink_sect; /* if present, add the .gnu_debuglink file as an alternate to current one */ if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect)) { const BYTE* dbg_link; - dbg_link = (const BYTE*)elf_map_section(&debuglink_sect); - if (dbg_link != ELF_NO_MAP) + dbg_link = (const BYTE*)image_map_section(&debuglink_sect); + if (dbg_link != IMAGE_NO_MAP) { lret = elf_debuglink_parse(fmap, module, dbg_link); if (!lret) @@ -920,7 +893,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module, debugstr_w(module->module.ModuleName)); ret = ret || lret; } - elf_unmap_section(&debuglink_sect); + image_unmap_section(&debuglink_sect); } if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) && elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect)) @@ -928,14 +901,14 @@ static BOOL elf_load_debug_info_from_map(struct module* module, const char* stab; const char* stabstr; - stab = elf_map_section(&stab_sect); - stabstr = elf_map_section(&stabstr_sect); - if (stab != ELF_NO_MAP && stabstr != ELF_NO_MAP) + stab = image_map_section(&stab_sect); + stabstr = image_map_section(&stabstr_sect); + if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) { /* OK, now just parse all of the stabs. */ - lret = stabs_parse(module, module->elf_info->elf_addr, - stab, elf_get_map_size(&stab_sect), - stabstr, elf_get_map_size(&stabstr_sect), + lret = stabs_parse(module, module->format_info[DFI_ELF]->u.elf_info->elf_addr, + stab, image_get_map_size(&stab_sect), + stabstr, image_get_map_size(&stabstr_sect), NULL, NULL); if (lret) /* and fill in the missing information for stabs */ @@ -945,57 +918,12 @@ static BOOL elf_load_debug_info_from_map(struct module* module, ret = ret || lret; } else lret = FALSE; - elf_unmap_section(&stab_sect); - elf_unmap_section(&stabstr_sect); - } - if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect)) - { - /* Dwarf 2 debug information */ - const BYTE* dw2_debug; - const BYTE* dw2_debug_abbrev; - const BYTE* dw2_debug_str; - const BYTE* dw2_debug_line; - const BYTE* dw2_debug_loclist; - - /* debug info might have a different base address than .so file - * when elf file is prelinked after splitting off debug info - * adjust symbol base addresses accordingly - */ - unsigned long load_offset = module->elf_info->elf_addr + - fmap->elf_start - debug_sect.fmap->elf_start; - - TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName)); - - elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect); - elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect); - elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect); - elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect); - - dw2_debug = (const BYTE*)elf_map_section(&debug_sect); - dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_sect); - dw2_debug_str = (const BYTE*)elf_map_section(&debug_str_sect); - dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect); - dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_sect); - if (dw2_debug != ELF_NO_MAP && dw2_debug_abbrev != ELF_NO_MAP && dw2_debug_str != ELF_NO_MAP) - { - /* OK, now just parse dwarf2 debug infos. */ - lret = dwarf2_parse(module, load_offset, thunks, - dw2_debug, elf_get_map_size(&debug_sect), - dw2_debug_abbrev, elf_get_map_size(&debug_abbrev_sect), - dw2_debug_str, elf_get_map_size(&debug_str_sect), - dw2_debug_line, elf_get_map_size(&debug_line_sect), - dw2_debug_loclist, elf_get_map_size(&debug_loclist_sect)); - - if (!lret) - WARN("Couldn't correctly read dwarf2\n"); - ret = ret || lret; - } - elf_unmap_section(&debug_sect); - elf_unmap_section(&debug_abbrev_sect); - elf_unmap_section(&debug_str_sect); - elf_unmap_section(&debug_line_sect); - elf_unmap_section(&debug_loclist_sect); + image_unmap_section(&stab_sect); + image_unmap_section(&stabstr_sect); } + lret = dwarf2_parse(module, module->format_info[DFI_ELF]->u.elf_info->elf_addr, + thunks, fmap); + ret = ret || lret; } if (strstrW(module->module.ModuleName, S_ElfW) || !strcmpW(module->module.ModuleName, S_WineLoaderW)) @@ -1015,14 +943,15 @@ static BOOL elf_load_debug_info_from_map(struct module* module, * * Loads ELF debugging information from the module image file. */ -BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) +BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap) { - BOOL ret = TRUE; - struct pool pool; - struct hash_table ht_symtab; - struct elf_file_map my_fmap; + BOOL ret = TRUE; + struct pool pool; + struct hash_table ht_symtab; + struct image_file_map my_fmap; + struct module_format* modfmt; - if (module->type != DMT_ELF || !module->elf_info) + if (module->type != DMT_ELF || !(modfmt = module->format_info[DFI_ELF]) || !modfmt->u.elf_info) { ERR("Bad elf module '%s'\n", debugstr_w(module->module.LoadedImageName)); return FALSE; @@ -1039,6 +968,12 @@ BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) if (ret) ret = elf_load_debug_info_from_map(module, fmap, &pool, &ht_symtab); + if (ret) + { + modfmt->u.elf_info->file_map = *fmap; + elf_reset_file_map(fmap); + } + pool_destroy(&pool); if (fmap == &my_fmap) elf_unmap_file(fmap); return ret; @@ -1052,12 +987,12 @@ BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum) { - struct elf_file_map fmap; + struct image_file_map fmap; if (!elf_map_file(name, &fmap)) return FALSE; - if (base) *base = fmap.elf_start; - *size = fmap.elf_size; - *checksum = calc_crc32(fmap.fd); + if (base) *base = fmap.u.elf.elf_start; + *size = fmap.u.elf.elf_size; + *checksum = calc_crc32(fmap.u.elf.fd); elf_unmap_file(&fmap); return TRUE; } @@ -1076,8 +1011,8 @@ BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, unsigned long load_offset, struct elf_info* elf_info) { - BOOL ret = FALSE; - struct elf_file_map fmap; + BOOL ret = FALSE; + struct image_file_map fmap; TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset); @@ -1087,10 +1022,10 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, * this thing. We need the main executable header, and the section * table. */ - if (!fmap.elf_start && !load_offset) + if (!fmap.u.elf.elf_start && !load_offset) ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n", debugstr_w(filename)); - if (fmap.elf_start && load_offset) + if (fmap.u.elf.elf_start && load_offset) { WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. " "Assuming load address is corrupt\n", debugstr_w(filename), load_offset); @@ -1099,12 +1034,12 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, if (elf_info->flags & ELF_INFO_DEBUG_HEADER) { - struct elf_section_map esm; + struct image_section_map ism; - if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm)) + if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &ism)) { Elf_Dyn dyn; - char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr; + char* ptr = (char*)fmap.u.elf.sect[ism.sidx].shdr.sh_addr; unsigned long len; do @@ -1126,29 +1061,40 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename, if (elf_info->flags & ELF_INFO_MODULE) { - struct elf_module_info *elf_module_info = - HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info)); - if (!elf_module_info) goto leave; + struct elf_module_info *elf_module_info; + struct module_format* modfmt; + + modfmt = HeapAlloc(GetProcessHeap(), 0, + sizeof(struct module_format) + sizeof(struct elf_module_info)); + if (!modfmt) goto leave; elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE, - (load_offset) ? load_offset : fmap.elf_start, - fmap.elf_size, 0, calc_crc32(fmap.fd)); + (load_offset) ? load_offset : fmap.u.elf.elf_start, + fmap.u.elf.elf_size, 0, calc_crc32(fmap.u.elf.fd)); if (!elf_info->module) { - HeapFree(GetProcessHeap(), 0, elf_module_info); + HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } - elf_info->module->elf_info = elf_module_info; - elf_info->module->elf_info->elf_addr = load_offset; + elf_module_info = (void*)(modfmt + 1); + elf_info->module->format_info[DFI_ELF] = modfmt; + modfmt->module = elf_info->module; + modfmt->remove = elf_module_remove; + modfmt->loc_compute = NULL; + modfmt->u.elf_info = elf_module_info; + + elf_module_info->elf_addr = load_offset; if (dbghelp_options & SYMOPT_DEFERRED_LOADS) { elf_info->module->module.SymType = SymDeferred; + elf_module_info->file_map = fmap; + elf_reset_file_map(&fmap); ret = TRUE; } else ret = elf_load_debug_info(elf_info->module, &fmap); - elf_info->module->elf_info->elf_mark = 1; - elf_info->module->elf_info->elf_loader = 0; + elf_module_info->elf_mark = 1; + elf_module_info->elf_loader = 0; } else ret = TRUE; if (elf_info->flags & ELF_INFO_NAME) @@ -1260,7 +1206,7 @@ static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename, if ((module = module_is_already_loaded(pcs, filename))) { elf_info->module = module; - module->elf_info->elf_mark = 1; + elf_info->module->format_info[DFI_ELF]->u.elf_info->elf_mark = 1; return module->module.SymType; } @@ -1352,7 +1298,7 @@ BOOL elf_synchronize_module_list(struct process* pcs) for (module = pcs->lmodules; module; module = module->next) { if (module->type == DMT_ELF && !module->is_virtual) - module->elf_info->elf_mark = 0; + module->format_info[DFI_ELF]->u.elf_info->elf_mark = 0; } es.pcs = pcs; @@ -1363,14 +1309,19 @@ BOOL elf_synchronize_module_list(struct process* pcs) module = pcs->lmodules; while (module) { - if (module->type == DMT_ELF && !module->is_virtual && - !module->elf_info->elf_mark && !module->elf_info->elf_loader) + if (module->type == DMT_ELF && !module->is_virtual) { - module_remove(pcs, module); - /* restart all over */ - module = pcs->lmodules; + struct elf_module_info* elf_info = module->format_info[DFI_ELF]->u.elf_info; + + if (!elf_info->elf_mark && !elf_info->elf_loader) + { + module_remove(pcs, module); + /* restart all over */ + module = pcs->lmodules; + continue; + } } - else module = module->next; + module = module->next; } return TRUE; } @@ -1415,7 +1366,7 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs) elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE; if (!elf_search_loader(pcs, &elf_info)) return FALSE; - elf_info.module->elf_info->elf_loader = 1; + elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1; module_set_module(elf_info.module, S_WineLoaderW); return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0; } @@ -1516,6 +1467,30 @@ struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned #else /* !__ELF__ */ +BOOL elf_find_section(struct image_file_map* fmap, const char* name, + unsigned sht, struct image_section_map* ism) +{ + return FALSE; +} + +const char* elf_map_section(struct image_section_map* ism) +{ + return NULL; +} + +void elf_unmap_section(struct image_section_map* ism) +{} + +unsigned elf_get_map_size(const struct image_section_map* ism) +{ + return 0; +} + +DWORD_PTR elf_get_map_rva(const struct image_section_map* ism) +{ + return 0; +} + BOOL elf_synchronize_module_list(struct process* pcs) { return FALSE; @@ -1542,7 +1517,7 @@ struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned return NULL; } -BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap) +BOOL elf_load_debug_info(struct module* module, struct image_file_map* fmap) { return FALSE; } diff --git a/dll/win32/dbghelp/image_private.h b/dll/win32/dbghelp/image_private.h new file mode 100644 index 00000000000..b768deb91e3 --- /dev/null +++ b/dll/win32/dbghelp/image_private.h @@ -0,0 +1,182 @@ +/* + * File elf_private.h - definitions for processing of ELF files + * + * Copyright (C) 1996, Eric Youngdale. + * 1999-2007 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_ELF_H +# include +#endif +#ifdef HAVE_SYS_ELF32_H +# include +#endif +#ifdef HAVE_SYS_EXEC_ELF_H +# include +#endif +#if !defined(DT_NUM) +# if defined(DT_COUNT) +# define DT_NUM DT_COUNT +# else +/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */ +# define DT_NUM 24 +# endif +#endif +#ifdef HAVE_LINK_H +# include +#endif +#ifdef HAVE_SYS_LINK_H +# include +#endif + +#define IMAGE_NO_MAP ((void*)-1) + +#ifdef __ELF__ + +#ifdef _WIN64 +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Dyn Elf64_Dyn +#define Elf_Sym Elf64_Sym +#else +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Dyn Elf32_Dyn +#define Elf_Sym Elf32_Sym +#endif +#else +#ifndef SHT_NULL +#define SHT_NULL 0 +#endif +#endif + +/* structure holding information while handling an ELF image + * allows one by one section mapping for memory savings + */ +struct image_file_map +{ + enum module_type modtype; + union + { + struct elf_file_map + { + size_t elf_size; + size_t elf_start; + int fd; + const char* shstrtab; + struct image_file_map* alternate; /* another ELF file (linked to this one) */ +#ifdef __ELF__ + Elf_Ehdr elfhdr; + struct + { + Elf_Shdr shdr; + const char* mapped; + }* sect; +#endif + } elf; + struct pe_file_map + { + HANDLE hMap; + IMAGE_NT_HEADERS ntheader; + unsigned full_count; + void* full_map; + struct + { + IMAGE_SECTION_HEADER shdr; + const char* mapped; + }* sect; + const char* strtable; + } pe; + } u; +}; + +struct image_section_map +{ + struct image_file_map* fmap; + long sidx; +}; + +extern BOOL elf_find_section(struct image_file_map* fmap, const char* name, + unsigned sht, struct image_section_map* ism); +extern const char* elf_map_section(struct image_section_map* ism); +extern void elf_unmap_section(struct image_section_map* ism); +extern DWORD_PTR elf_get_map_rva(const struct image_section_map* ism); +extern unsigned elf_get_map_size(const struct image_section_map* ism); + +extern BOOL pe_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism); +extern const char* pe_map_section(struct image_section_map* psm); +extern void pe_unmap_section(struct image_section_map* psm); +extern DWORD_PTR pe_get_map_rva(const struct image_section_map* psm); +extern unsigned pe_get_map_size(const struct image_section_map* psm); + +static inline BOOL image_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism) +{ + switch (fmap->modtype) + { + case DMT_ELF: return elf_find_section(fmap, name, SHT_NULL, ism); + case DMT_PE: return pe_find_section(fmap, name, ism); + default: assert(0); return FALSE; + } +} + +static inline const char* image_map_section(struct image_section_map* ism) +{ + if (!ism->fmap) return NULL; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_map_section(ism); + case DMT_PE: return pe_map_section(ism); + default: assert(0); return NULL; + } +} + +static inline void image_unmap_section(struct image_section_map* ism) +{ + if (!ism->fmap) return; + switch (ism->fmap->modtype) + { + case DMT_ELF: elf_unmap_section(ism); break; + case DMT_PE: pe_unmap_section(ism); break; + default: assert(0); return; + } +} + +static inline DWORD_PTR image_get_map_rva(struct image_section_map* ism) +{ + if (!ism->fmap) return 0; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_get_map_rva(ism); + case DMT_PE: return pe_get_map_rva(ism); + default: assert(0); return 0; + } +} + +static inline unsigned image_get_map_size(struct image_section_map* ism) +{ + if (!ism->fmap) return 0; + switch (ism->fmap->modtype) + { + case DMT_ELF: return elf_get_map_size(ism); + case DMT_PE: return pe_get_map_size(ism); + default: assert(0); return 0; + } +} diff --git a/dll/win32/dbghelp/macho_module.c b/dll/win32/dbghelp/macho_module.c index 379596b2f58..44fa4f2da1c 100644 --- a/dll/win32/dbghelp/macho_module.c +++ b/dll/win32/dbghelp/macho_module.c @@ -655,9 +655,10 @@ static int macho_parse_symtab(struct macho_file_map* fmap, sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr)) return 0; - if (!stabs_parse(mdi->module, mdi->module->macho_info->load_addr - fmap->segs_start, - stab, sc->nsyms * sizeof(struct nlist), - stabstr, sc->strsize, macho_stabs_def_cb, mdi)) + if (!stabs_parse(mdi->module, + mdi->module->format_info[DFI_MACHO]->u.macho_info->load_addr - fmap->segs_start, + stab, sc->nsyms * sizeof(struct nlist), + stabstr, sc->strsize, macho_stabs_def_cb, mdi)) ret = -1; macho_unmap_ranges(fmap, sc->symoff, sc->nsyms * sizeof(struct nlist), @@ -703,7 +704,7 @@ static void macho_finish_stabs(struct module* module, struct hash_table* ht_symt { case SymTagFunction: func = (struct symt_function*)sym; - if (func->address == module->macho_info->load_addr) + if (func->address == module->format_info[DFI_MACHO]->u.macho_info->load_addr) { TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func, debugstr_w(module->module.ModuleName), sym->hash_elt.name, @@ -720,7 +721,7 @@ static void macho_finish_stabs(struct module* module, struct hash_table* ht_symt { case DataIsGlobal: case DataIsFileStatic: - if (data->u.var.offset == module->macho_info->load_addr) + if (data->u.var.offset == module->format_info[DFI_MACHO]->u.macho_info->load_addr) { TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n", data, debugstr_w(module->module.ModuleName), sym->hash_elt.name, @@ -879,7 +880,7 @@ BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap) TRACE("(%p, %p/%d)\n", module, fmap, fmap ? fmap->fd : -1); - if (module->type != DMT_MACHO || !module->macho_info) + if (module->type != DMT_MACHO || !module->format_info[DFI_MACHO]->u.macho_info) { ERR("Bad Mach-O module '%s'\n", debugstr_w(module->module.LoadedImageName)); return FALSE; @@ -963,26 +964,34 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, if (macho_info->flags & MACHO_INFO_MODULE) { - struct macho_module_info *macho_module_info = - HeapAlloc(GetProcessHeap(), 0, sizeof(struct macho_module_info)); - if (!macho_module_info) goto leave; + struct macho_module_info *macho_module_info; + struct module_format* modfmt = + HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info)); + if (!modfmt) goto leave; macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr, fmap.segs_size, 0, calc_crc32(fmap.fd)); if (!macho_info->module) { - HeapFree(GetProcessHeap(), 0, macho_module_info); + HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } - macho_info->module->macho_info = macho_module_info; - macho_info->module->macho_info->load_addr = load_addr; + macho_module_info = (void*)(modfmt + 1); + macho_info->module->format_info[DFI_MACHO] = modfmt; + + modfmt->module = macho_info->module; + modfmt->remove = NULL; + modfmt->loc_compute = NULL; + modfmt->u.macho_info = macho_module_info; + + macho_module_info->load_addr = load_addr; if (dbghelp_options & SYMOPT_DEFERRED_LOADS) macho_info->module->module.SymType = SymDeferred; else if (!macho_load_debug_info(macho_info->module, &fmap)) ret = FALSE; - macho_info->module->macho_info->in_use = 1; - macho_info->module->macho_info->is_loader = 0; + macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; + macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0; TRACE("module = %p\n", macho_info->module); } @@ -1109,7 +1118,7 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam if ((module = module_is_already_loaded(pcs, filename))) { macho_info->module = module; - module->macho_info->in_use = 1; + module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; return module->module.SymType; } @@ -1231,7 +1240,7 @@ BOOL macho_synchronize_module_list(struct process* pcs) for (module = pcs->lmodules; module; module = module->next) { if (module->type == DMT_MACHO && !module->is_virtual) - module->macho_info->in_use = 0; + module->format_info[DFI_MACHO]->u.macho_info->in_use = 0; } ms.pcs = pcs; @@ -1243,7 +1252,8 @@ BOOL macho_synchronize_module_list(struct process* pcs) while (module) { if (module->type == DMT_MACHO && !module->is_virtual && - !module->macho_info->in_use && !module->macho_info->is_loader) + !module->format_info[DFI_MACHO]->u.macho_info->in_use && + !module->format_info[DFI_MACHO]->u.macho_info->is_loader) { module_remove(pcs, module); /* restart all over */ @@ -1297,7 +1307,7 @@ BOOL macho_read_wine_loader_dbg_info(struct process* pcs) TRACE("(%p/%p)\n", pcs, pcs->handle); macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_MODULE; if (!macho_search_loader(pcs, &macho_info)) return FALSE; - macho_info.module->macho_info->is_loader = 1; + macho_info.module->format_info[DFI_MACHO]->u.macho_info->is_loader = 1; module_set_module(macho_info.module, S_WineLoaderW); return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0; } diff --git a/dll/win32/dbghelp/module.c b/dll/win32/dbghelp/module.c index 53f56c25129..250c5a5854a 100644 --- a/dll/win32/dbghelp/module.c +++ b/dll/win32/dbghelp/module.c @@ -126,6 +126,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, unsigned long stamp, unsigned long checksum) { struct module* module; + unsigned i; assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO); if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module)))) @@ -168,6 +169,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->type = type; module->is_virtual = virtual ? TRUE : FALSE; + for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; module->addr_sorttab = NULL; @@ -621,14 +623,21 @@ DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, */ BOOL module_remove(struct process* pcs, struct module* module) { + struct module_format*modfmt; struct module** p; + unsigned i; TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); + + for (i = 0; i < DFI_LAST; i++) + { + if ((modfmt = module->format_info[i]) && modfmt->remove) + modfmt->remove(pcs, module->format_info[i]); + } hash_table_destroy(&module->ht_symbols); hash_table_destroy(&module->ht_types); HeapFree(GetProcessHeap(), 0, module->sources); HeapFree(GetProcessHeap(), 0, module->addr_sorttab); - HeapFree(GetProcessHeap(), 0, module->dwarf2_info); pool_destroy(&module->pool); /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here * so do we diff --git a/dll/win32/dbghelp/pe_module.c b/dll/win32/dbghelp/pe_module.c index 76d81ee5512..63a2b9a9e4e 100644 --- a/dll/win32/dbghelp/pe_module.c +++ b/dll/win32/dbghelp/pe_module.c @@ -30,11 +30,239 @@ #include #include "dbghelp_private.h" +#include "image_private.h" #include "winternl.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); +struct pe_module_info +{ + struct image_file_map fmap; +}; + +static void* pe_map_full(struct image_file_map* fmap, IMAGE_NT_HEADERS** nth) +{ + if (!fmap->u.pe.full_map) + { + fmap->u.pe.full_map = MapViewOfFile(fmap->u.pe.hMap, FILE_MAP_READ, 0, 0, 0); + } + if (fmap->u.pe.full_map) + { + if (nth) *nth = RtlImageNtHeader(fmap->u.pe.full_map); + fmap->u.pe.full_count++; + return fmap->u.pe.full_map; + } + return IMAGE_NO_MAP; +} + +static void pe_unmap_full(struct image_file_map* fmap) +{ + if (fmap->u.pe.full_count && !--fmap->u.pe.full_count) + { + UnmapViewOfFile(fmap->u.pe.full_map); + fmap->u.pe.full_map = NULL; + } +} + +/****************************************************************** + * pe_map_section + * + * Maps a single section into memory from an PE file + */ +const char* pe_map_section(struct image_section_map* ism) +{ + void* mapping; + struct pe_file_map* fmap = &ism->fmap->u.pe; + + if (ism->sidx >= 0 && ism->sidx < fmap->ntheader.FileHeader.NumberOfSections && + fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) + { + IMAGE_NT_HEADERS* nth; + /* FIXME: that's rather drastic, but that will do for now + * that's ok if the full file map exists, but we could be less agressive otherwise and + * only map the relevant section + */ + if ((mapping = pe_map_full(ism->fmap, &nth))) + { + fmap->sect[ism->sidx].mapped = RtlImageRvaToVa(nth, mapping, + fmap->sect[ism->sidx].shdr.VirtualAddress, + NULL); + return fmap->sect[ism->sidx].mapped; + } + } + return IMAGE_NO_MAP; +} + +/****************************************************************** + * pe_find_section + * + * Finds a section by name (and type) into memory from an PE file + * or its alternate if any + */ +BOOL pe_find_section(struct image_file_map* fmap, const char* name, + struct image_section_map* ism) +{ + const char* sectname; + unsigned i; + char tmp[IMAGE_SIZEOF_SHORT_NAME + 1]; + + for (i = 0; i < fmap->u.pe.ntheader.FileHeader.NumberOfSections; i++) + { + sectname = (const char*)fmap->u.pe.sect[i].shdr.Name; + /* long section names start with a '/' (at least on MinGW32) */ + if (sectname[0] == '/' && fmap->u.pe.strtable) + sectname = fmap->u.pe.strtable + atoi(sectname + 1); + else + { + /* the section name may not be null terminated */ + sectname = memcpy(tmp, sectname, IMAGE_SIZEOF_SHORT_NAME); + tmp[IMAGE_SIZEOF_SHORT_NAME] = '\0'; + } + if (!strcasecmp(sectname, name)) + { + ism->fmap = fmap; + ism->sidx = i; + return TRUE; + } + } + ism->fmap = NULL; + ism->sidx = -1; + + return FALSE; +} + +/****************************************************************** + * pe_unmap_section + * + * Unmaps a single section from memory + */ +void pe_unmap_section(struct image_section_map* ism) +{ + if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections && + ism->fmap->u.pe.sect[ism->sidx].mapped != IMAGE_NO_MAP) + { + pe_unmap_full(ism->fmap); + ism->fmap->u.pe.sect[ism->sidx].mapped = IMAGE_NO_MAP; + } +} + +/****************************************************************** + * pe_get_map_rva + * + * Get the RVA of an PE section + */ +DWORD_PTR pe_get_map_rva(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + return 0; + return ism->fmap->u.pe.sect[ism->sidx].shdr.VirtualAddress; +} + +/****************************************************************** + * pe_get_map_size + * + * Get the size of an PE section + */ +unsigned pe_get_map_size(const struct image_section_map* ism) +{ + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + return 0; + return ism->fmap->u.pe.sect[ism->sidx].shdr.SizeOfRawData; +} + +/****************************************************************** + * pe_map_file + * + * Maps an PE file into memory (and checks it's a real PE file) + */ +static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) +{ + void* mapping; + + fmap->modtype = mt; + fmap->u.pe.hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); + if (fmap->u.pe.hMap == 0) return FALSE; + fmap->u.pe.full_count = 0; + fmap->u.pe.full_map = NULL; + if (!(mapping = pe_map_full(fmap, NULL))) goto error; + + switch (mt) + { + case DMT_PE: + { + IMAGE_NT_HEADERS* nthdr; + IMAGE_SECTION_HEADER* section; + unsigned i; + + if (!(nthdr = RtlImageNtHeader(mapping))) goto error; + memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader)); + section = (IMAGE_SECTION_HEADER*) + ((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader); + fmap->u.pe.sect = HeapAlloc(GetProcessHeap(), 0, + nthdr->FileHeader.NumberOfSections * sizeof(fmap->u.pe.sect[0])); + if (!fmap->u.pe.sect) goto error; + for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++) + { + memcpy(&fmap->u.pe.sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER)); + fmap->u.pe.sect[i].mapped = IMAGE_NO_MAP; + } + if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols) + { + /* FIXME ugly: should rather map the relevant content instead of copying it */ + const char* src = (const char*)mapping + + nthdr->FileHeader.PointerToSymbolTable + + nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL); + char* dst; + DWORD sz = *(DWORD*)src; + + if ((dst = HeapAlloc(GetProcessHeap(), 0, sz))) + memcpy(dst, src, sz); + fmap->u.pe.strtable = dst; + } + else fmap->u.pe.strtable = NULL; + } + break; + default: assert(0); goto error; + } + pe_unmap_full(fmap); + + return TRUE; +error: + pe_unmap_full(fmap); + CloseHandle(fmap->u.pe.hMap); + return FALSE; +} + +/****************************************************************** + * pe_unmap_file + * + * Unmaps an PE file from memory (previously mapped with pe_map_file) + */ +static void pe_unmap_file(struct image_file_map* fmap) +{ + if (fmap->u.pe.hMap != 0) + { + struct image_section_map ism; + ism.fmap = fmap; + for (ism.sidx = 0; ism.sidx < fmap->u.pe.ntheader.FileHeader.NumberOfSections; ism.sidx++) + { + pe_unmap_section(&ism); + } + while (fmap->u.pe.full_count) pe_unmap_full(fmap); + HeapFree(GetProcessHeap(), 0, fmap->u.pe.sect); + HeapFree(GetProcessHeap(), 0, (void*)fmap->u.pe.strtable); /* FIXME ugly (see pe_map_file) */ + CloseHandle(fmap->u.pe.hMap); + fmap->u.pe.hMap = NULL; + } +} + +static void pe_module_remove(struct process* pcs, struct module_format* modfmt) +{ + pe_unmap_file(&modfmt->u.pe_info->fmap); + HeapFree(GetProcessHeap(), 0, modfmt); +} + /****************************************************************** * pe_locate_with_coff_symbol_table * @@ -43,37 +271,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); * Mingw32 requires this for stabs debug information as address for global variables isn't filled in * (this is similar to what is done in elf_module.c when using the .symtab ELF section) */ -static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping) +static BOOL pe_locate_with_coff_symbol_table(struct module* module) { + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; const IMAGE_SYMBOL* isym; int i, numsym, naux; - const char* strtable; char tmp[9]; const char* name; struct hash_table_iter hti; void* ptr; struct symt_data* sym; - const IMAGE_SECTION_HEADER* sect; + const char* mapping; - numsym = nth->FileHeader.NumberOfSymbols; - if (!nth->FileHeader.PointerToSymbolTable || !numsym) + numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; + if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) return TRUE; - isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable); - /* FIXME: no way to get strtable size */ - strtable = (const char*)&isym[numsym]; - sect = IMAGE_FIRST_SECTION(nth); + if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; + isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable); for (i = 0; i < numsym; i+= naux, isym += naux) { if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) { if (isym->N.Name.Short) { name = memcpy(tmp, isym->N.ShortName, 8); tmp[8] = '\0'; } - else name = strtable + isym->N.Name.Long; + else name = fmap->u.pe.strtable + isym->N.Name.Long; if (name[0] == '_') name++; hash_table_iter_init(&module->ht_symbols, &hti, name); while ((ptr = hash_table_iter_up(&hti))) @@ -86,15 +312,17 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEA TRACE("Changing absolute address for %d.%s: %lx -> %s\n", isym->SectionNumber, name, sym->u.var.offset, wine_dbgstr_longlong(module->module.BaseOfImage + - sect[isym->SectionNumber - 1].VirtualAddress + isym->Value)); + fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + + isym->Value)); sym->u.var.offset = module->module.BaseOfImage + - sect[isym->SectionNumber - 1].VirtualAddress + isym->Value; + fmap->u.pe.sect[isym->SectionNumber - 1].shdr.VirtualAddress + isym->Value; break; } } } naux = isym->NumberOfAuxSymbols + 1; } + pe_unmap_full(fmap); return TRUE; } @@ -103,8 +331,9 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEA * * Load public symbols out of the COFF symbol table (if any). */ -static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping) +static BOOL pe_load_coff_symbol_table(struct module* module) { + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; const IMAGE_SYMBOL* isym; int i, numsym, naux; const char* strtable; @@ -113,14 +342,16 @@ static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* n const char* lastfilename = NULL; struct symt_compiland* compiland = NULL; const IMAGE_SECTION_HEADER* sect; + const char* mapping; - numsym = nth->FileHeader.NumberOfSymbols; - if (!nth->FileHeader.PointerToSymbolTable || !numsym) + numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; + if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) return TRUE; - isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable); + if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; + isym = (const IMAGE_SYMBOL*)((char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable); /* FIXME: no way to get strtable size */ strtable = (const char*)&isym[numsym]; - sect = IMAGE_FIRST_SECTION(nth); + sect = IMAGE_FIRST_SECTION(&fmap->u.pe.ntheader); for (i = 0; i < numsym; i+= naux, isym += naux) { @@ -130,7 +361,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* n compiland = NULL; } if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) { if (isym->N.Name.Short) { @@ -143,9 +374,12 @@ static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* n if (!compiland && lastfilename) compiland = symt_new_compiland(module, 0, source_new(module, NULL, lastfilename)); - symt_new_public(module, compiland, name, - module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + isym->Value, - 1); + + if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) + symt_new_public(module, compiland, name, + module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + + isym->Value, + 1); } naux = isym->NumberOfAuxSymbols + 1; } @@ -155,6 +389,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* n module->module.TypeInfo = FALSE; module->module.SourceIndexed = FALSE; module->module.Publics = TRUE; + pe_unmap_full(fmap); return TRUE; } @@ -176,30 +411,30 @@ static inline DWORD pe_get_sect_size(IMAGE_SECTION_HEADER* sect) * look for stabs information in PE header (it's how the mingw compiler provides * its debugging information) */ -static BOOL pe_load_stabs(const struct process* pcs, struct module* module, - void* mapping, IMAGE_NT_HEADERS* nth) +static BOOL pe_load_stabs(const struct process* pcs, struct module* module) { - IMAGE_SECTION_HEADER* section; - IMAGE_SECTION_HEADER* sect_stabs = NULL; - IMAGE_SECTION_HEADER* sect_stabstr = NULL; - int i; + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; + struct image_section_map sect_stabs, sect_stabstr; BOOL ret = FALSE; - section = (IMAGE_SECTION_HEADER*) - ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader); - for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) + if (pe_find_section(fmap, ".stab", §_stabs) && pe_find_section(fmap, ".stabstr", §_stabstr)) { - if (!strcasecmp((const char*)section->Name, ".stab")) sect_stabs = section; - else if (!strncasecmp((const char*)section->Name, ".stabstr", 8)) sect_stabstr = section; - } - if (sect_stabs && sect_stabstr) - { - ret = stabs_parse(module, - module->module.BaseOfImage - nth->OptionalHeader.ImageBase, - pe_get_sect(nth, mapping, sect_stabs), pe_get_sect_size(sect_stabs), - pe_get_sect(nth, mapping, sect_stabstr), pe_get_sect_size(sect_stabstr), - NULL, NULL); - if (ret) pe_locate_with_coff_symbol_table(module, nth, mapping); + const char* stab; + const char* stabstr; + + stab = image_map_section(§_stabs); + stabstr = image_map_section(§_stabstr); + if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) + { + ret = stabs_parse(module, + module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + stab, image_get_map_size(§_stabs), + stabstr, image_get_map_size(§_stabstr), + NULL, NULL); + } + image_unmap_section(§_stabs); + image_unmap_section(§_stabstr); + if (ret) pe_locate_with_coff_symbol_table(module); } TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load"); @@ -212,51 +447,15 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module, * look for dwarf information in PE header (it's also a way for the mingw compiler * to provide its debugging information) */ -static BOOL pe_load_dwarf(const struct process* pcs, struct module* module, - void* mapping, IMAGE_NT_HEADERS* nth) +static BOOL pe_load_dwarf(struct module* module) { - IMAGE_SECTION_HEADER* section; - IMAGE_SECTION_HEADER* sect_debuginfo = NULL; - IMAGE_SECTION_HEADER* sect_debugstr = NULL; - IMAGE_SECTION_HEADER* sect_debugabbrev = NULL; - IMAGE_SECTION_HEADER* sect_debugline = NULL; - IMAGE_SECTION_HEADER* sect_debugloc = NULL; - int i; - const char* strtable; - const char* sectname; + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; BOOL ret = FALSE; - if (nth->FileHeader.PointerToSymbolTable && nth->FileHeader.NumberOfSymbols) - /* FIXME: no way to get strtable size */ - strtable = (const char*)mapping + nth->FileHeader.PointerToSymbolTable + - nth->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL); - else strtable = NULL; - - section = (IMAGE_SECTION_HEADER*) - ((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader); - for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++) - { - sectname = (const char*)section->Name; - /* long section names start with a '/' (at least on MinGW32) */ - if (*sectname == '/' && strtable) - sectname = strtable + atoi(sectname + 1); - if (!strcasecmp(sectname, ".debug_info")) sect_debuginfo = section; - else if (!strcasecmp(sectname, ".debug_str")) sect_debugstr = section; - else if (!strcasecmp(sectname, ".debug_abbrev")) sect_debugabbrev = section; - else if (!strcasecmp(sectname, ".debug_line")) sect_debugline = section; - else if (!strcasecmp(sectname, ".debug_loc")) sect_debugloc = section; - } - if (sect_debuginfo) - { - ret = dwarf2_parse(module, - module->module.BaseOfImage - nth->OptionalHeader.ImageBase, - NULL, /* FIXME: some thunks to deal with ? */ - pe_get_sect(nth, mapping, sect_debuginfo), pe_get_sect_size(sect_debuginfo), - pe_get_sect(nth, mapping, sect_debugabbrev), pe_get_sect_size(sect_debugabbrev), - pe_get_sect(nth, mapping, sect_debugstr), pe_get_sect_size(sect_debugstr), - pe_get_sect(nth, mapping, sect_debugline), pe_get_sect_size(sect_debugline), - pe_get_sect(nth, mapping, sect_debugloc), pe_get_sect_size(sect_debugloc)); - } + ret = dwarf2_parse(module, + module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + NULL, /* FIXME: some thunks to deal with ? */ + fmap); TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load"); return ret; @@ -314,19 +513,21 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module, * * Process MSC debug information in PE file. */ -static BOOL pe_load_msc_debug_info(const struct process* pcs, - struct module* module, - void* mapping, const IMAGE_NT_HEADERS* nth) +static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* module) { + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; BOOL ret = FALSE; const IMAGE_DATA_DIRECTORY* dir; const IMAGE_DEBUG_DIRECTORY*dbg = NULL; int nDbg; + void* mapping; + IMAGE_NT_HEADERS* nth; + if (!(mapping = pe_map_full(fmap, &nth))) return FALSE; /* Read in debug directory */ dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG; nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY); - if (!nDbg) return FALSE; + if (!nDbg) goto done; dbg = RtlImageRvaToVa(nth, mapping, dir->VirtualAddress, NULL); @@ -353,26 +554,29 @@ static BOOL pe_load_msc_debug_info(const struct process* pcs, const IMAGE_SECTION_HEADER *sectp = (const IMAGE_SECTION_HEADER*)((const char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader); /* Debug info is embedded into PE module */ ret = pe_load_debug_directory(pcs, module, mapping, sectp, - nth->FileHeader.NumberOfSections, dbg, nDbg); + nth->FileHeader.NumberOfSections, dbg, nDbg); } - +done: + pe_unmap_full(fmap); return ret; } /*********************************************************************** * pe_load_export_debug_info */ -static BOOL pe_load_export_debug_info(const struct process* pcs, - struct module* module, - void* mapping, const IMAGE_NT_HEADERS* nth) +static BOOL pe_load_export_debug_info(const struct process* pcs, struct module* module) { + struct image_file_map* fmap = &module->format_info[DFI_PE]->u.pe_info->fmap; unsigned int i; const IMAGE_EXPORT_DIRECTORY* exports; DWORD base = module->module.BaseOfImage; DWORD size; + IMAGE_NT_HEADERS* nth; + void* mapping; if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE; + if (!(mapping = pe_map_full(fmap, &nth))) return FALSE; #if 0 /* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */ /* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */ @@ -435,6 +639,8 @@ static BOOL pe_load_export_debug_info(const struct process* pcs, /* no real debug info, only entry points */ if (module->module.SymType == SymDeferred) module->module.SymType = SymExport; + pe_unmap_full(fmap); + return TRUE; } @@ -445,39 +651,21 @@ static BOOL pe_load_export_debug_info(const struct process* pcs, BOOL pe_load_debug_info(const struct process* pcs, struct module* module) { BOOL ret = FALSE; - HANDLE hFile; - HANDLE hMap; - void* mapping; - IMAGE_NT_HEADERS* nth; - hFile = CreateFileW(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return ret; - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) + if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) { - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) - { - nth = RtlImageNtHeader(mapping); - - if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) - { - ret = pe_load_stabs(pcs, module, mapping, nth) || - pe_load_dwarf(pcs, module, mapping, nth) || - pe_load_msc_debug_info(pcs, module, mapping, nth) || - pe_load_coff_symbol_table(module, nth, mapping); - /* if we still have no debug info (we could only get SymExport at this - * point), then do the SymExport except if we have an ELF container, - * in which case we'll rely on the export's on the ELF side - */ - } -/* FIXME shouldn't we check that? if (!module_get_debug(pcs, module))l */ - if (pe_load_export_debug_info(pcs, module, mapping, nth) && !ret) - ret = TRUE; - UnmapViewOfFile(mapping); - } - CloseHandle(hMap); + ret = pe_load_stabs(pcs, module); + ret = pe_load_dwarf(module) || ret; + ret = pe_load_msc_debug_info(pcs, module) || ret; + ret = ret || pe_load_coff_symbol_table(module); /* FIXME */ + /* if we still have no debug info (we could only get SymExport at this + * point), then do the SymExport except if we have an ELF container, + * in which case we'll rely on the export's on the ELF side + */ } - CloseHandle(hFile); + /* FIXME shouldn't we check that? if (!module_get_debug(pcs, module)) */ + if (pe_load_export_debug_info(pcs, module) && !ret) + ret = TRUE; return ret; } @@ -489,15 +677,14 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module) struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, HANDLE hFile, DWORD base, DWORD size) { - struct module* module = NULL; - BOOL opened = FALSE; - HANDLE hMap; - WCHAR loaded_name[MAX_PATH]; + struct module* module = NULL; + BOOL opened = FALSE; + struct module_format* modfmt; + WCHAR loaded_name[MAX_PATH]; loaded_name[0] = '\0'; if (!hFile) { - assert(name); if ((hFile = FindExecutableImageExW(name, pcs->search_path, loaded_name, NULL, NULL)) == NULL) @@ -507,37 +694,37 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, else if (name) strcpyW(loaded_name, name); else if (dbghelp_options & SYMOPT_DEFERRED_LOADS) FIXME("Trouble ahead (no module name passed in deferred mode)\n"); - - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) + if (!(modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct pe_module_info)))) + return NULL; + modfmt->u.pe_info = (struct pe_module_info*)(modfmt + 1); + if (pe_map_file(hFile, &modfmt->u.pe_info->fmap, DMT_PE)) { - void* mapping; + if (!base) base = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase; + if (!size) size = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.SizeOfImage; - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) + module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, + modfmt->u.pe_info->fmap.u.pe.ntheader.FileHeader.TimeDateStamp, + modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.CheckSum); + if (module) { - IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); + modfmt->module = module; + modfmt->remove = pe_module_remove; + modfmt->loc_compute = NULL; - if (nth) - { - if (!base) base = nth->OptionalHeader.ImageBase; - if (!size) size = nth->OptionalHeader.SizeOfImage; - - module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, - nth->FileHeader.TimeDateStamp, - nth->OptionalHeader.CheckSum); - if (module) - { - if (dbghelp_options & SYMOPT_DEFERRED_LOADS) - module->module.SymType = SymDeferred; - else - pe_load_debug_info(pcs, module); - } - else - ERR("could not load the module '%s'\n", debugstr_w(loaded_name)); - } - UnmapViewOfFile(mapping); + module->format_info[DFI_PE] = modfmt; + if (dbghelp_options & SYMOPT_DEFERRED_LOADS) + module->module.SymType = SymDeferred; + else + pe_load_debug_info(pcs, module); + } + else + { + ERR("could not load the module '%s'\n", debugstr_w(loaded_name)); + pe_unmap_file(&modfmt->u.pe_info->fmap); } - CloseHandle(hMap); } + if (!module) HeapFree(GetProcessHeap(), 0, modfmt); + if (opened) CloseHandle(hFile); return module; diff --git a/dll/win32/dbghelp/symbol.c b/dll/win32/dbghelp/symbol.c index 07ba9a37cef..650f6a28086 100644 --- a/dll/win32/dbghelp/symbol.c +++ b/dll/win32/dbghelp/symbol.c @@ -693,8 +693,20 @@ static void symt_fill_sym_info(struct module_pair* pair, struct location loc = data->u.var; if (loc.kind >= loc_user) - pair->effective->loc_compute(pair->pcs, pair->effective, func, &loc); + { + unsigned i; + struct module_format* modfmt; + for (i = 0; i < DFI_LAST; i++) + { + modfmt = pair->effective->format_info[i]; + if (modfmt && modfmt->loc_compute) + { + modfmt->loc_compute(pair->pcs, modfmt, func, &loc); + break; + } + } + } switch (loc.kind) { case loc_error: diff --git a/dll/win32/fusion/fusion.c b/dll/win32/fusion/fusion.c index 7c94100039d..ad772330487 100644 --- a/dll/win32/fusion/fusion.c +++ b/dll/win32/fusion/fusion.c @@ -52,6 +52,15 @@ HRESULT WINAPI CreateInstallReferenceEnum(IInstallReferenceEnum **ppRefEnum, return E_NOTIMPL; } +/****************************************************************** + * CreateApplicationContext (FUSION.@) + */ +HRESULT WINAPI CreateApplicationContext(IAssemblyName *name, void *ctx) +{ + FIXME("%p, %p\n", name, ctx); + return E_NOTIMPL; +} + static HRESULT (WINAPI *pGetCORVersion)(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength); diff --git a/dll/win32/fusion/fusion.spec b/dll/win32/fusion/fusion.spec index e589ad17e08..54e4eadd715 100644 --- a/dll/win32/fusion/fusion.spec +++ b/dll/win32/fusion/fusion.spec @@ -1,6 +1,6 @@ @ stub CopyPDBs @ stdcall ClearDownloadCache() -@ stub CreateApplicationContext +@ stdcall CreateApplicationContext(ptr ptr) @ stdcall CreateAssemblyCache(ptr long) @ stdcall CreateAssemblyEnum(ptr ptr ptr long ptr) @ stdcall CreateAssemblyNameObject(ptr wstr long ptr) diff --git a/dll/win32/gdiplus/brush.c b/dll/win32/gdiplus/brush.c index 2f2143dba58..2d28004c95d 100644 --- a/dll/win32/gdiplus/brush.c +++ b/dll/win32/gdiplus/brush.c @@ -865,7 +865,10 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image, (*texture)->brush.gdibrush = CreateBrushIndirect(&(*texture)->brush.lb); (*texture)->brush.bt = BrushTypeTextureFill; - (*texture)->wrap = imageattr->wrap; + if (imageattr) + (*texture)->wrap = imageattr->wrap; + else + (*texture)->wrap = WrapModeTile; (*texture)->image = new_image; exit: diff --git a/dll/win32/gdiplus/image.c b/dll/win32/gdiplus/image.c index d72d4cfbb8a..58f3c6570be 100644 --- a/dll/win32/gdiplus/image.c +++ b/dll/win32/gdiplus/image.c @@ -2108,6 +2108,8 @@ GpStatus WINGDIPAPI GdipGetMetafileHeaderFromMetafile(GpMetafile * metafile, if(!(calls++)) FIXME("not implemented\n"); + memset(header, 0, sizeof(MetafileHeader)); + return Ok; } @@ -2194,6 +2196,7 @@ struct image_format_dimension image_format_dimensions[] = {NULL} }; +/* FIXME: Need to handle multi-framed images */ GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, GDIPCONST GUID* dimensionID, UINT* count) { @@ -2201,13 +2204,15 @@ GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, TRACE("(%p,%s,%p)\n", image, debugstr_guid(dimensionID), count); - if(!image || !dimensionID || !count) + if(!image || !count) return InvalidParameter; if(!(calls++)) - FIXME("not implemented\n"); + FIXME("returning frame count of 1\n"); - return NotImplemented; + *count = 1; + + return Ok; } GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage *image, diff --git a/dll/win32/hlink/browse_ctx.c b/dll/win32/hlink/browse_ctx.c index a5b73c10bc1..1e15c13a543 100644 --- a/dll/win32/hlink/browse_ctx.c +++ b/dll/win32/hlink/browse_ctx.c @@ -155,6 +155,9 @@ static HRESULT WINAPI IHlinkBC_SetBrowseWindowInfo(IHlinkBrowseContext* iface, HlinkBCImpl *This = (HlinkBCImpl*)iface; TRACE("(%p)->(%p)\n", This, phlbwi); + if(!phlbwi) + return E_INVALIDARG; + heap_free(This->BrowseWindowInfo); This->BrowseWindowInfo = heap_alloc(phlbwi->cbSize); memcpy(This->BrowseWindowInfo, phlbwi, phlbwi->cbSize); @@ -165,8 +168,18 @@ static HRESULT WINAPI IHlinkBC_SetBrowseWindowInfo(IHlinkBrowseContext* iface, static HRESULT WINAPI IHlinkBC_GetBrowseWindowInfo(IHlinkBrowseContext* iface, HLBWINFO *phlbwi) { - FIXME("\n"); - return E_NOTIMPL; + HlinkBCImpl *This = (HlinkBCImpl*)iface; + TRACE("(%p)->(%p)\n", This, phlbwi); + + if(!phlbwi) + return E_INVALIDARG; + + if(!This->BrowseWindowInfo) + phlbwi->cbSize = 0; + else + memcpy(phlbwi, This->BrowseWindowInfo, This->BrowseWindowInfo->cbSize); + + return S_OK; } static HRESULT WINAPI IHlinkBC_SetInitialHlink(IHlinkBrowseContext* iface, diff --git a/dll/win32/hlink/hlink_main.c b/dll/win32/hlink/hlink_main.c index d07901aea4a..e96f206645f 100644 --- a/dll/win32/hlink/hlink_main.c +++ b/dll/win32/hlink/hlink_main.c @@ -99,6 +99,8 @@ HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation, { IHlink *hl = NULL; HRESULT r = S_OK; + WCHAR *hash, *tgt; + const WCHAR *loc; TRACE("%s %s %s %p %i %p %s %p\n", debugstr_w(pwzTarget), debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), pihlsite, @@ -108,8 +110,44 @@ HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation, if (FAILED(r)) return r; - IHlink_SetStringReference(hl, HLINKSETF_TARGET | HLINKSETF_LOCATION, - pwzTarget, pwzLocation); + if (pwzTarget) + { + hash = strchrW(pwzTarget, '#'); + if (hash) + { + if (hash == pwzTarget) + tgt = NULL; + else + { + int tgt_len = hash - pwzTarget; + tgt = heap_alloc((tgt_len + 1) * sizeof(WCHAR)); + if (!tgt) + return E_OUTOFMEMORY; + memcpy(tgt, pwzTarget, tgt_len * sizeof(WCHAR)); + tgt[tgt_len] = 0; + } + if (!pwzLocation) + loc = hash + 1; + else + loc = pwzLocation; + } + else + { + tgt = hlink_strdupW(pwzTarget); + if (!tgt) + return E_OUTOFMEMORY; + loc = pwzLocation; + } + } + else + { + tgt = NULL; + loc = pwzLocation; + } + + IHlink_SetStringReference(hl, HLINKSETF_TARGET | HLINKSETF_LOCATION, tgt, loc); + + heap_free(tgt); if (pwzFriendlyName) IHlink_SetFriendlyName(hl, pwzFriendlyName); diff --git a/dll/win32/hlink/link.c b/dll/win32/hlink/link.c index 52197ccf6fd..ffd3cda854b 100644 --- a/dll/win32/hlink/link.c +++ b/dll/win32/hlink/link.c @@ -291,7 +291,9 @@ static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface, if (grfHLSETF & HLINKSETF_LOCATION) { heap_free(This->Location); - This->Location = hlink_strdupW( pwzLocation ); + This->Location = NULL; + if (pwzLocation && *pwzLocation) + This->Location = hlink_strdupW( pwzLocation ); } return S_OK; diff --git a/dll/win32/iphlpapi/iphlpapi_private.h b/dll/win32/iphlpapi/iphlpapi_private.h index 90efff74da0..766f7f4e6ee 100644 --- a/dll/win32/iphlpapi/iphlpapi_private.h +++ b/dll/win32/iphlpapi/iphlpapi_private.h @@ -19,8 +19,6 @@ # include #endif -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x500 #define WIN32_NO_STATUS #include #include diff --git a/dll/win32/iphlpapi/resinfo_reactos.c b/dll/win32/iphlpapi/resinfo_reactos.c index 2b551949b57..02bcb3b9129 100644 --- a/dll/win32/iphlpapi/resinfo_reactos.c +++ b/dll/win32/iphlpapi/resinfo_reactos.c @@ -58,7 +58,7 @@ NTAPI RtlAllocateHeap ( HANDLE Heap, ULONG Flags, - ULONG Size + SIZE_T Size ); NTSYSAPI diff --git a/dll/win32/kernel32/misc/dllmain.c b/dll/win32/kernel32/misc/dllmain.c index a828f72ef5a..02199f9349d 100644 --- a/dll/win32/kernel32/misc/dllmain.c +++ b/dll/win32/kernel32/misc/dllmain.c @@ -402,6 +402,12 @@ DllMain(HANDLE hDll, return TRUE; } +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedExchange +#undef InterlockedExchangeAdd +#undef InterlockedCompareExchange + LONG WINAPI InterlockedIncrement(IN OUT LONG volatile *lpAddend) diff --git a/dll/win32/kernel32/misc/toolhelp.c b/dll/win32/kernel32/misc/toolhelp.c index ad2f2b7db2a..ab591b1d9f9 100644 --- a/dll/win32/kernel32/misc/toolhelp.c +++ b/dll/win32/kernel32/misc/toolhelp.c @@ -400,11 +400,11 @@ TH32CreateSnapshotSectionInitialize(DWORD dwFlags, ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W); ProcessListEntry->cntUsage = 0; /* no longer used */ - ProcessListEntry->th32ProcessID = (ULONG)ProcessInfo->UniqueProcessId; + ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId; ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */ ProcessListEntry->th32ModuleID = 0; /* no longer used */ ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads; - ProcessListEntry->th32ParentProcessID = (ULONG)ProcessInfo->InheritedFromUniqueProcessId; + ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId; ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority; ProcessListEntry->dwFlags = 0; /* no longer used */ if(ProcessInfo->ImageName.Buffer != NULL) @@ -447,8 +447,8 @@ TH32CreateSnapshotSectionInitialize(DWORD dwFlags, { ThreadListEntry->dwSize = sizeof(THREADENTRY32); ThreadListEntry->cntUsage = 0; /* no longer used */ - ThreadListEntry->th32ThreadID = (ULONG)ThreadInfo->ClientId.UniqueThread; - ThreadListEntry->th32OwnerProcessID = (ULONG)ThreadInfo->ClientId.UniqueProcess; + ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread; + ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess; ThreadListEntry->tpBasePri = ThreadInfo->BasePriority; ThreadListEntry->tpDeltaPri = 0; /* no longer used */ ThreadListEntry->dwFlags = 0; /* no longer used */ diff --git a/dll/win32/kernel32/synch/critical.c b/dll/win32/kernel32/synch/critical.c index 474a5d6c543..ac5280a60bd 100644 --- a/dll/win32/kernel32/synch/critical.c +++ b/dll/win32/kernel32/synch/critical.c @@ -55,4 +55,30 @@ InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection, return TRUE; } +/* + * @implemented + */ +BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, + IN DWORD dwSpinCount, + IN DWORD flags ) +{ + NTSTATUS Status; + + /* FIXME: Flags ignored */ + + /* Initialize the critical section */ + Status = RtlInitializeCriticalSectionAndSpinCount( + (PRTL_CRITICAL_SECTION)lpCriticalSection, + dwSpinCount); + if (!NT_SUCCESS(Status)) + { + /* Set failure code */ + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} + /* EOF */ diff --git a/dll/win32/kernel32/thread/fiber.c b/dll/win32/kernel32/thread/fiber.c index 58aa6e9d4c6..656bc6ee19d 100644 --- a/dll/win32/kernel32/thread/fiber.c +++ b/dll/win32/kernel32/thread/fiber.c @@ -47,9 +47,9 @@ ConvertFiberToThread(VOID) pTeb->HasFiberData = FALSE; /* free the fiber */ - if (pTeb->Tib.FiberData != NULL) + if(pTeb->NtTib.FiberData != NULL) { - RtlFreeHeap(GetProcessHeap(), 0, pTeb->Tib.FiberData); + RtlFreeHeap(GetProcessHeap(), 0, pTeb->NtTib.FiberData); } /* success */ @@ -69,7 +69,7 @@ ConvertThreadToFiberEx(LPVOID lpParameter, DPRINT1("Converting Thread to Fiber\n"); /* the current thread is already a fiber */ - if(pTeb->HasFiberData && pTeb->Tib.FiberData) return pTeb->Tib.FiberData; + if(pTeb->HasFiberData && pTeb->NtTib.FiberData) return pTeb->NtTib.FiberData; /* allocate the fiber */ pfCurFiber = (PFIBER)RtlAllocateHeap(GetProcessHeap(), @@ -85,9 +85,9 @@ ConvertThreadToFiberEx(LPVOID lpParameter, /* copy some contextual data from the thread to the fiber */ pfCurFiber->Parameter = lpParameter; - pfCurFiber->ExceptionList = pTeb->Tib.ExceptionList; - pfCurFiber->StackBase = pTeb->Tib.StackBase; - pfCurFiber->StackLimit = pTeb->Tib.StackLimit; + pfCurFiber->ExceptionList = pTeb->NtTib.ExceptionList; + pfCurFiber->StackBase = pTeb->NtTib.StackBase; + pfCurFiber->StackLimit = pTeb->NtTib.StackLimit; pfCurFiber->DeallocationStack = pTeb->DeallocationStack; pfCurFiber->FlsData = pTeb->FlsData; pfCurFiber->GuaranteedStackBytes = pTeb->GuaranteedStackBytes; @@ -101,7 +101,7 @@ ConvertThreadToFiberEx(LPVOID lpParameter, } /* associate the fiber to the current thread */ - pTeb->Tib.FiberData = pfCurFiber; + pTeb->NtTib.FiberData = pfCurFiber; pTeb->HasFiberData = TRUE; /* success */ @@ -227,7 +227,7 @@ DeleteFiber(LPVOID lpFiber) RtlFreeHeap(GetProcessHeap(), 0, lpFiber); /* the fiber is deleting itself: let the system deallocate the stack */ - if(NtCurrentTeb()->Tib.FiberData == lpFiber) ExitThread(1); + if(NtCurrentTeb()->NtTib.FiberData == lpFiber) ExitThread(1); /* deallocate the stack */ NtFreeVirtualMemory(NtCurrentProcess(), diff --git a/dll/win32/mshtml/De.rc b/dll/win32/mshtml/De.rc index 43e0cfe85a5..50d519d70a7 100644 --- a/dll/win32/mshtml/De.rc +++ b/dll/win32/mshtml/De.rc @@ -72,4 +72,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Abbrechen", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/Fr.rc b/dll/win32/mshtml/Fr.rc index 84ee453128f..0d14f452e8b 100644 --- a/dll/win32/mshtml/Fr.rc +++ b/dll/win32/mshtml/Fr.rc @@ -72,4 +72,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Annuler", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/It.rc b/dll/win32/mshtml/It.rc index 4b262c56e3a..36660cca6bf 100644 --- a/dll/win32/mshtml/It.rc +++ b/dll/win32/mshtml/It.rc @@ -69,4 +69,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Annulla", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/Ja.rc b/dll/win32/mshtml/Ja.rc index 40db7b5f867..04fc32e785b 100644 --- a/dll/win32/mshtml/Ja.rc +++ b/dll/win32/mshtml/Ja.rc @@ -69,4 +69,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "キャンセル", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/Lt.rc b/dll/win32/mshtml/Lt.rc index 560cc08dd16..8f7e772a3a7 100644 --- a/dll/win32/mshtml/Lt.rc +++ b/dll/win32/mshtml/Lt.rc @@ -69,4 +69,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "Gerai", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Atsisakyti", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/No.rc b/dll/win32/mshtml/No.rc index 3a3b45d7a42..4592599edf3 100644 --- a/dll/win32/mshtml/No.rc +++ b/dll/win32/mshtml/No.rc @@ -70,4 +70,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "OK", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Avbryt", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/Si.rc b/dll/win32/mshtml/Si.rc index 500081bc790..6881addcd5b 100644 --- a/dll/win32/mshtml/Si.rc +++ b/dll/win32/mshtml/Si.rc @@ -68,4 +68,3 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "V redu", IDOK, 40, 65, 45, 15, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Prekliči", IDCANCEL, 115, 65, 45, 15, WS_GROUP | WS_TABSTOP } -#pragma code_page(default) diff --git a/dll/win32/mshtml/htmldoc.c b/dll/win32/mshtml/htmldoc.c index 8adfdb14b43..12aa8c002dc 100644 --- a/dll/win32/mshtml/htmldoc.c +++ b/dll/win32/mshtml/htmldoc.c @@ -554,9 +554,12 @@ static HRESULT WINAPI HTMLDocument_get_vlinkColor(IHTMLDocument2 *iface, VARIANT static HRESULT WINAPI HTMLDocument_get_referrer(IHTMLDocument2 *iface, BSTR *p) { HTMLDocument *This = HTMLDOC_THIS(iface); + FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; -} + + *p = NULL; + return S_OK; + } static HRESULT WINAPI HTMLDocument_get_location(IHTMLDocument2 *iface, IHTMLLocation **p) { @@ -1474,7 +1477,7 @@ static void HTMLDocument_on_advise(IUnknown *iface, cp_static_data_t *cp) HTMLDocument *This = HTMLDOC_THIS(iface); if(This->window) - update_cp_events(This->window, cp); + update_cp_events(This->window, &This->doc_node->node.event_target, cp, This->doc_node->node.nsnode); } #undef HTMLDOC_THIS @@ -1596,6 +1599,11 @@ static HRESULT WINAPI DocDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID { HTMLDocument *This = DISPEX_THIS(iface); + if(This->window && id == DISPID_IHTMLDOCUMENT2_LOCATION && (wFlags & DISPATCH_PROPERTYPUT)) + return IDispatchEx_InvokeEx(DISPATCHEX(This->window), DISPID_IHTMLWINDOW2_LOCATION, lcid, wFlags, + pdp, pvarRes, pei, pspCaller); + + return IDispatchEx_InvokeEx(This->dispex, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); } diff --git a/dll/win32/mshtml/htmldoc3.c b/dll/win32/mshtml/htmldoc3.c index 9079bbc79c7..e28297fce14 100644 --- a/dll/win32/mshtml/htmldoc3.c +++ b/dll/win32/mshtml/htmldoc3.c @@ -182,7 +182,7 @@ static HRESULT WINAPI HTMLDocument3_attachEvent(IHTMLDocument3 *iface, BSTR even TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult); - return attach_event(&This->doc_node->node.event_target, This, event, pDisp, pfResult); + return attach_event(&This->doc_node->node.event_target, This->doc_node->node.nsnode, This, event, pDisp, pfResult); } static HRESULT WINAPI HTMLDocument3_detachEvent(IHTMLDocument3 *iface, BSTR event, diff --git a/dll/win32/mshtml/htmlelem2.c b/dll/win32/mshtml/htmlelem2.c index cd877ceaf30..548bab8b2f5 100644 --- a/dll/win32/mshtml/htmlelem2.c +++ b/dll/win32/mshtml/htmlelem2.c @@ -649,7 +649,7 @@ static HRESULT WINAPI HTMLElement2_attachEvent(IHTMLElement2 *iface, BSTR event, TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult); - return attach_event(get_node_event_target(&This->node), &This->node.doc->basedoc, event, pDisp, pfResult); + return attach_event(get_node_event_target(&This->node), This->node.nsnode, &This->node.doc->basedoc, event, pDisp, pfResult); } static HRESULT WINAPI HTMLElement2_detachEvent(IHTMLElement2 *iface, BSTR event, IDispatch *pDisp) diff --git a/dll/win32/mshtml/htmlevent.c b/dll/win32/mshtml/htmlevent.c index 54429c34a20..eef006c962c 100644 --- a/dll/win32/mshtml/htmlevent.c +++ b/dll/win32/mshtml/htmlevent.c @@ -40,6 +40,7 @@ typedef struct { } handler_vector_t; struct event_target_t { + DWORD node_handlers_mask; handler_vector_t *event_table[EVENTID_LAST]; }; @@ -129,6 +130,7 @@ typedef struct { #define EVENT_DEFAULTLISTENER 0x0001 #define EVENT_BUBBLE 0x0002 #define EVENT_FORWARDBODY 0x0004 +#define EVENT_NODEHANDLER 0x0008 static const event_info_t event_info[] = { {beforeunloadW, onbeforeunloadW, EVENTT_NONE, DISPID_EVMETH_ONBEFOREUNLOAD, @@ -152,7 +154,7 @@ static const event_info_t event_info[] = { {keyupW, onkeyupW, EVENTT_KEY, DISPID_EVMETH_ONKEYUP, EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, {loadW, onloadW, EVENTT_HTML, DISPID_EVMETH_ONLOAD, - 0}, + EVENT_NODEHANDLER}, {mousedownW, onmousedownW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEDOWN, EVENT_DEFAULTLISTENER|EVENT_BUBBLE}, {mouseoutW, onmouseoutW, EVENTT_MOUSE, DISPID_EVMETH_ONMOUSEOUT, @@ -171,6 +173,8 @@ static const event_info_t event_info[] = { 0} }; +static const eventid_t node_handled_list[] = { EVENTID_LOAD }; + eventid_t str_to_eid(LPCWSTR str) { int i; @@ -196,6 +200,19 @@ static eventid_t attr_to_eid(LPCWSTR str) return EVENTID_LAST; } +static DWORD get_node_handler_mask(eventid_t eid) +{ + DWORD i; + + for(i=0; ibasedoc.window->event; - event_obj = doc->basedoc.window->event = create_event(get_node(doc, target, TRUE), eid, nsevent); + if(set_event) + event_obj = create_event(get_node(doc, target, TRUE), eid, nsevent); + doc->basedoc.window->event = event_obj; nsIDOMNode_GetNodeType(target, &node_type); nsnode = target; @@ -949,7 +968,8 @@ void fire_event(HTMLDocumentNode *doc, eventid_t eid, nsIDOMNode *target, nsIDOM if(nsnode) nsIDOMNode_Release(nsnode); - IHTMLEventObj_Release(event_obj); + if(event_obj) + IHTMLEventObj_Release(event_obj); doc->basedoc.window->event = prev_event; } @@ -971,7 +991,7 @@ HRESULT dispatch_event(HTMLDOMNode *node, const WCHAR *event_name, VARIANT *even return E_NOTIMPL; } - fire_event(node->doc, eid, node->nsnode, NULL); + fire_event(node->doc, eid, TRUE, node->nsnode, NULL); *cancelled = VARIANT_TRUE; /* FIXME */ return S_OK; @@ -989,7 +1009,7 @@ HRESULT call_event(HTMLDOMNode *node, eventid_t eid) return hres; } - fire_event(node->doc, eid, node->nsnode, NULL); + fire_event(node->doc, eid, TRUE, node->nsnode, NULL); return S_OK; } @@ -1021,9 +1041,24 @@ static BOOL alloc_handler_vector(event_target_t *event_target, eventid_t eid, in return TRUE; } -static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, eventid_t eid) +static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, event_target_t *event_target, nsIDOMNode *nsnode, eventid_t eid) { - if(!doc->nsdoc || !(event_info[eid].flags & EVENT_DEFAULTLISTENER)) + if(!doc->nsdoc) + return S_OK; + + if(event_info[eid].flags & EVENT_NODEHANDLER) { + DWORD mask; + + mask = get_node_handler_mask(eid); + if(event_target->node_handlers_mask & mask) + return S_OK; + + add_nsevent_listener(doc, nsnode, event_info[eid].name); + event_target->node_handlers_mask |= mask; + return S_OK; + } + + if(!(event_info[eid].flags & EVENT_DEFAULTLISTENER)) return S_OK; if(!doc->event_vector) { @@ -1034,17 +1069,30 @@ static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, eventid_t eid) if(!doc->event_vector[eid]) { doc->event_vector[eid] = TRUE; - add_nsevent_listener(doc, event_info[eid].name); + add_nsevent_listener(doc, NULL, event_info[eid].name); } return S_OK; } -static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDocumentNode *doc, +static HRESULT remove_event_handler(event_target_t **event_target, eventid_t eid) +{ + if(*event_target && (*event_target)->event_table[eid]->handler_prop) { + IDispatch_Release((*event_target)->event_table[eid]->handler_prop); + (*event_target)->event_table[eid]->handler_prop = NULL; + } + + return S_OK; +} + +static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocumentNode *doc, eventid_t eid, IDispatch *disp) { event_target_t *event_target; + if(!disp) + return remove_event_handler(event_target_ptr, eid); + event_target = get_event_target(event_target_ptr); if(!event_target) return E_OUTOFMEMORY; @@ -1056,25 +1104,19 @@ static HRESULT set_event_handler_disp(event_target_t **event_target_ptr, HTMLDoc IDispatch_Release(event_target->event_table[eid]->handler_prop); event_target->event_table[eid]->handler_prop = disp; - if(!disp) - return S_OK; IDispatch_AddRef(disp); - return ensure_nsevent_handler(doc, eid); + return ensure_nsevent_handler(doc, event_target, nsnode, eid); } -HRESULT set_event_handler(event_target_t **event_target, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var) +HRESULT set_event_handler(event_target_t **event_target, nsIDOMNode *nsnode, HTMLDocumentNode *doc, eventid_t eid, VARIANT *var) { switch(V_VT(var)) { case VT_NULL: - if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) { - IDispatch_Release((*event_target)->event_table[eid]->handler_prop); - (*event_target)->event_table[eid]->handler_prop = NULL; - } - break; + return remove_event_handler(event_target, eid); case VT_DISPATCH: - return set_event_handler_disp(event_target, doc, eid, V_DISPATCH(var)); + return set_event_handler_disp(event_target, nsnode, doc, eid, V_DISPATCH(var)); default: FIXME("not supported vt=%d\n", V_VT(var)); @@ -1098,7 +1140,8 @@ HRESULT get_event_handler(event_target_t **event_target, eventid_t eid, VARIANT return S_OK; } -HRESULT attach_event(event_target_t **event_target_ptr, HTMLDocument *doc, BSTR name, IDispatch *disp, VARIANT_BOOL *res) +HRESULT attach_event(event_target_t **event_target_ptr, nsIDOMNode *nsnode, HTMLDocument *doc, BSTR name, + IDispatch *disp, VARIANT_BOOL *res) { event_target_t *event_target; eventid_t eid; @@ -1128,7 +1171,7 @@ HRESULT attach_event(event_target_t **event_target_ptr, HTMLDocument *doc, BSTR event_target->event_table[eid]->handlers[i] = disp; *res = VARIANT_TRUE; - return ensure_nsevent_handler(doc->doc_node, eid); + return ensure_nsevent_handler(doc->doc_node, event_target, nsnode, eid); } HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name, IDispatch *disp) @@ -1159,13 +1202,18 @@ HRESULT detach_event(event_target_t *event_target, HTMLDocument *doc, BSTR name, return S_OK; } -void update_cp_events(HTMLWindow *window, cp_static_data_t *cp) +void update_cp_events(HTMLWindow *window, event_target_t **event_target_ptr, cp_static_data_t *cp, nsIDOMNode *nsnode) { + event_target_t *event_target; int i; + event_target = get_event_target(event_target_ptr); + if(!event_target) + return; /* FIXME */ + for(i=0; i < EVENTID_LAST; i++) { if((event_info[i].flags & EVENT_DEFAULTLISTENER) && is_cp_event(cp, event_info[i].dispid)) - ensure_nsevent_handler(window->doc, i); + ensure_nsevent_handler(window->doc, event_target, nsnode, i); } } @@ -1194,7 +1242,7 @@ void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem) disp = script_parse_event(doc->basedoc.window, attr_value); if(disp) { node = get_node(doc, (nsIDOMNode*)nselem, TRUE); - set_event_handler_disp(get_node_event_target(node), node->doc, i, disp); + set_event_handler_disp(get_node_event_target(node), node->nsnode, node->doc, i, disp); IDispatch_Release(disp); } } diff --git a/dll/win32/mshtml/htmlevent.h b/dll/win32/mshtml/htmlevent.h index 96ff4cdab5b..6ba2fe29dc7 100644 --- a/dll/win32/mshtml/htmlevent.h +++ b/dll/win32/mshtml/htmlevent.h @@ -42,14 +42,14 @@ typedef enum { eventid_t str_to_eid(LPCWSTR); void check_event_attr(HTMLDocumentNode*,nsIDOMElement*); void release_event_target(event_target_t*); -void fire_event(HTMLDocumentNode*,eventid_t,nsIDOMNode*,nsIDOMEvent*); -HRESULT set_event_handler(event_target_t**,HTMLDocumentNode*,eventid_t,VARIANT*); +void fire_event(HTMLDocumentNode*,eventid_t,BOOL,nsIDOMNode*,nsIDOMEvent*); +HRESULT set_event_handler(event_target_t**,nsIDOMNode*,HTMLDocumentNode*,eventid_t,VARIANT*); HRESULT get_event_handler(event_target_t**,eventid_t,VARIANT*); -HRESULT attach_event(event_target_t**,HTMLDocument*,BSTR,IDispatch*,VARIANT_BOOL*); +HRESULT attach_event(event_target_t**,nsIDOMNode*,HTMLDocument*,BSTR,IDispatch*,VARIANT_BOOL*); HRESULT detach_event(event_target_t*,HTMLDocument*,BSTR,IDispatch*); HRESULT dispatch_event(HTMLDOMNode*,const WCHAR*,VARIANT*,VARIANT_BOOL*); HRESULT call_event(HTMLDOMNode*,eventid_t); -void update_cp_events(HTMLWindow*,cp_static_data_t*); +void update_cp_events(HTMLWindow*,event_target_t**,cp_static_data_t*,nsIDOMNode*); static inline event_target_t **get_node_event_target(HTMLDOMNode *node) { @@ -58,7 +58,7 @@ static inline event_target_t **get_node_event_target(HTMLDOMNode *node) static inline HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var) { - return set_event_handler(get_node_event_target(node), node->doc, eid, var); + return set_event_handler(get_node_event_target(node), node->nsnode, node->doc, eid, var); } static inline HRESULT get_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var) diff --git a/dll/win32/mshtml/htmlimg.c b/dll/win32/mshtml/htmlimg.c index 17b6cceac95..a4448f9588f 100644 --- a/dll/win32/mshtml/htmlimg.c +++ b/dll/win32/mshtml/htmlimg.c @@ -28,6 +28,7 @@ #include "wine/debug.h" #include "mshtml_private.h" +#include "htmlevent.h" WINE_DEFAULT_DEBUG_CHANNEL(mshtml); @@ -388,15 +389,19 @@ static HRESULT WINAPI HTMLImgElement_get_align(IHTMLImgElement *iface, BSTR *p) static HRESULT WINAPI HTMLImgElement_put_onload(IHTMLImgElement *iface, VARIANT v) { HTMLImgElement *This = HTMLIMG_THIS(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + + TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); + + return set_node_event(&This->element.node, EVENTID_LOAD, &v); } static HRESULT WINAPI HTMLImgElement_get_onload(IHTMLImgElement *iface, VARIANT *p) { HTMLImgElement *This = HTMLIMG_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + return get_node_event(&This->element.node, EVENTID_LOAD, p); } static HRESULT WINAPI HTMLImgElement_put_onerror(IHTMLImgElement *iface, VARIANT v) diff --git a/dll/win32/mshtml/htmlwindow.c b/dll/win32/mshtml/htmlwindow.c index 491625ed241..2aafaa3e4b4 100644 --- a/dll/win32/mshtml/htmlwindow.c +++ b/dll/win32/mshtml/htmlwindow.c @@ -126,7 +126,7 @@ static inline HRESULT set_window_event(HTMLWindow *window, eventid_t eid, VARIAN return E_FAIL; } - return set_event_handler(&window->doc->body_event_target, window->doc, eid, var); + return set_event_handler(&window->doc->body_event_target, NULL, window->doc, eid, var); } static inline HRESULT get_window_event(HTMLWindow *window, eventid_t eid, VARIANT *var) @@ -1419,7 +1419,7 @@ static HRESULT WINAPI HTMLWindow3_attachEvent(IHTMLWindow3 *iface, BSTR event, I return E_FAIL; } - return attach_event(&This->doc->body_event_target, &This->doc->basedoc, event, pDisp, pfResult); + return attach_event(&This->doc->body_event_target, NULL, &This->doc->basedoc, event, pDisp, pfResult); } static HRESULT WINAPI HTMLWindow3_detachEvent(IHTMLWindow3 *iface, BSTR event, IDispatch *pDisp) diff --git a/dll/win32/mshtml/mshtml_private.h b/dll/win32/mshtml/mshtml_private.h index 5a409b3cae5..228be35864e 100644 --- a/dll/win32/mshtml/mshtml_private.h +++ b/dll/win32/mshtml/mshtml_private.h @@ -736,7 +736,7 @@ nsresult get_nsinterface(nsISupports*,REFIID,void**); void init_nsevents(HTMLDocumentNode*); void release_nsevents(HTMLDocumentNode*); -void add_nsevent_listener(HTMLDocumentNode*,LPCWSTR); +void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR); void set_window_bscallback(HTMLWindow*,nsChannelBSC*); void set_current_mon(HTMLWindow*,IMoniker*); diff --git a/dll/win32/mshtml/mutation.c b/dll/win32/mshtml/mutation.c index 61ceca83525..a7942043557 100644 --- a/dll/win32/mshtml/mutation.c +++ b/dll/win32/mshtml/mutation.c @@ -338,6 +338,9 @@ static void handle_end_load(HTMLDocumentNode *This) TRACE("\n"); + if(!This->basedoc.doc_obj) + return; + if(This != This->basedoc.doc_obj->basedoc.doc_node) { set_ready_state(This->basedoc.window, READYSTATE_INTERACTIVE); return; diff --git a/dll/win32/mshtml/navigate.c b/dll/win32/mshtml/navigate.c index a09ea7f64d6..cc2aeb3f6c2 100644 --- a/dll/win32/mshtml/navigate.c +++ b/dll/win32/mshtml/navigate.c @@ -972,8 +972,11 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) on_start_nsrequest(This); - if(This->window) + if(This->window) { update_window_doc(This->window); + if(This->window->readystate != READYSTATE_LOADING) + set_ready_state(This->window, READYSTATE_LOADING); + } } This->bsc.readed += This->nsstream->buf_size; diff --git a/dll/win32/mshtml/nsevents.c b/dll/win32/mshtml/nsevents.c index 65bcae05c31..c491424fdd4 100644 --- a/dll/win32/mshtml/nsevents.c +++ b/dll/win32/mshtml/nsevents.c @@ -216,7 +216,7 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event TRACE("(%p)\n", doc); - if(!doc) + if(!doc || !doc->basedoc.window) return NS_ERROR_FAILURE; doc_obj = doc->basedoc.doc_obj; @@ -254,7 +254,7 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); if(nsbody) { - fire_event(doc, EVENTID_LOAD, (nsIDOMNode*)nsbody, event); + fire_event(doc, EVENTID_LOAD, TRUE, (nsIDOMNode*)nsbody, event); nsIDOMHTMLElement_Release(nsbody); } @@ -271,6 +271,8 @@ static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent * eventid_t eid; nsresult nsres; + TRACE("\n"); + nsAString_Init(&type_str, NULL); nsIDOMEvent_GetType(event, &type_str); nsAString_GetData(&type_str, &type); @@ -290,7 +292,7 @@ static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent * return NS_OK; } - fire_event(doc, eid, nsnode, event); + fire_event(doc, eid, TRUE, nsnode, event); nsIDOMNode_Release(nsnode); @@ -334,12 +336,15 @@ static void init_listener(nsEventListener *This, nsDocumentEventListener *listen This->This = listener; } -void add_nsevent_listener(HTMLDocumentNode *doc, LPCWSTR type) +void add_nsevent_listener(HTMLDocumentNode *doc, nsIDOMNode *nsnode, LPCWSTR type) { nsIDOMEventTarget *target; nsresult nsres; - nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target); + if(nsnode) + nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMEventTarget, (void**)&target); + else + nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target); if(NS_FAILED(nsres)) { ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres); return; diff --git a/dll/win32/mshtml/nsio.c b/dll/win32/mshtml/nsio.c index f4e6f4bcb56..88a4e55254b 100644 --- a/dll/win32/mshtml/nsio.c +++ b/dll/win32/mshtml/nsio.c @@ -904,7 +904,7 @@ static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListen open = FALSE; }else { - open = before_async_open(This, window->doc_obj->nscontainer); + open = !before_async_open(This, window->doc_obj->nscontainer); if(!open) { TRACE("canceled\n"); nsres = NS_ERROR_UNEXPECTED; diff --git a/dll/win32/mshtml/omnavigator.c b/dll/win32/mshtml/omnavigator.c index dc0fb4a8ca4..d127eef57f7 100644 --- a/dll/win32/mshtml/omnavigator.c +++ b/dll/win32/mshtml/omnavigator.c @@ -160,19 +160,28 @@ static HRESULT WINAPI OmNavigator_get_appVersion(IOmNavigator *iface, BSTR *p) { OmNavigator *This = OMNAVIGATOR_THIS(iface); - /* FIXME: Should we return something smarter? */ - static const WCHAR app_verW[] = - {'4','.','0',' ','(','c','o','m','p','a','t','i','b','l','e',';', - ' ','M','S','I','E',' ','7','.','0',';', - ' ','W','i','n','d','o','w','s',' ','N','T',' ','5','.','1',';', - ' ','M','o','z','i','l','l','a','/','4','.','0',')',0}; + char user_agent[512]; + DWORD size; + HRESULT hres; TRACE("(%p)->(%p)\n", This, p); - *p = SysAllocString(app_verW); + size = sizeof(user_agent); + hres = ObtainUserAgentString(0, user_agent, &size); + if(FAILED(hres)) + return hres; + + if(strncmp(user_agent, "Mozilla/", 8)) { + FIXME("Unsupported user agent\n"); + return E_FAIL; + } + + size = MultiByteToWideChar(CP_ACP, 0, user_agent+8, -1, NULL, 0); + *p = SysAllocStringLen(NULL, size-1); if(!*p) return E_OUTOFMEMORY; + MultiByteToWideChar(CP_ACP, 0, user_agent+8, -1, *p, size); return S_OK; } diff --git a/dll/win32/mshtml/persist.c b/dll/win32/mshtml/persist.c index 720a58edbf8..44ccd0f6b2c 100644 --- a/dll/win32/mshtml/persist.c +++ b/dll/win32/mshtml/persist.c @@ -108,6 +108,7 @@ static void set_progress_proc(task_t *_task) V_I4(&progress) = 0; /* FIXME */ IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER, &progress, NULL); + IOleCommandTarget_Release(olecmd); } if(doc->usermode == EDITMODE && doc->hostui) { @@ -282,11 +283,15 @@ HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, nsChannel void set_ready_state(HTMLWindow *window, READYSTATE readystate) { window->readystate = readystate; + if(window->doc_obj && window->doc_obj->basedoc.window == window) call_property_onchanged(&window->doc_obj->basedoc.cp_propnotif, DISPID_READYSTATE); + + fire_event(window->doc, EVENTID_READYSTATECHANGE, FALSE, window->doc->node.nsnode, NULL); + if(window->frame_element) fire_event(window->frame_element->element.node.doc, EVENTID_READYSTATECHANGE, - window->frame_element->element.node.nsnode, NULL); + TRUE, window->frame_element->element.node.nsnode, NULL); } static HRESULT get_doc_string(HTMLDocumentNode *This, char **str) diff --git a/dll/win32/msi/database.c b/dll/win32/msi/database.c index 8ec2411cb59..cfa11e97ed5 100644 --- a/dll/win32/msi/database.c +++ b/dll/win32/msi/database.c @@ -2057,7 +2057,7 @@ static ULONG WINAPI mrd_Release( IWineMsiRemoteDatabase *iface ) } static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface, - BSTR table, MSICONDITION *persistent ) + LPCWSTR table, MSICONDITION *persistent ) { msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); *persistent = MsiDatabaseIsTablePersistentW(This->database, table); @@ -2065,7 +2065,7 @@ static HRESULT WINAPI mrd_IsTablePersistent( IWineMsiRemoteDatabase *iface, } static HRESULT WINAPI mrd_GetPrimaryKeys( IWineMsiRemoteDatabase *iface, - BSTR table, MSIHANDLE *keys ) + LPCWSTR table, MSIHANDLE *keys ) { msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); UINT r = MsiDatabaseGetPrimaryKeysW(This->database, table, keys); @@ -2081,7 +2081,7 @@ static HRESULT WINAPI mrd_GetSummaryInformation( IWineMsiRemoteDatabase *iface, } static HRESULT WINAPI mrd_OpenView( IWineMsiRemoteDatabase *iface, - BSTR query, MSIHANDLE *view ) + LPCWSTR query, MSIHANDLE *view ) { msi_remote_database_impl *This = mrd_from_IWineMsiRemoteDatabase( iface ); UINT r = MsiDatabaseOpenViewW(This->database, query, view); diff --git a/dll/win32/msi/msi_De.rc b/dll/win32/msi/msi_De.rc index 7307621b768..e0cccf07806 100644 --- a/dll/win32/msi/msi_De.rc +++ b/dll/win32/msi/msi_De.rc @@ -36,4 +36,3 @@ STRINGTABLE DISCARDABLE 14 "Feature von:" 15 "Wählen Sie das Verzeichnis aus, dass %s enthält." } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_Fr.rc b/dll/win32/msi/msi_Fr.rc index 08b90497745..f7f733803bc 100644 --- a/dll/win32/msi/msi_Fr.rc +++ b/dll/win32/msi/msi_Fr.rc @@ -37,4 +37,3 @@ STRINGTABLE DISCARDABLE 14 "fonctionnalité depuis :" 15 "sélectionnez le dossier contenant %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_It.rc b/dll/win32/msi/msi_It.rc index 11525add056..a40a7303425 100644 --- a/dll/win32/msi/msi_It.rc +++ b/dll/win32/msi/msi_It.rc @@ -37,4 +37,3 @@ STRINGTABLE DISCARDABLE 14 "funzionalità da:" 15 "selezionare la cartella che contiene %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_Lt.rc b/dll/win32/msi/msi_Lt.rc index 76602612bd5..1cf1c52924e 100644 --- a/dll/win32/msi/msi_Lt.rc +++ b/dll/win32/msi/msi_Lt.rc @@ -37,4 +37,3 @@ STRINGTABLE DISCARDABLE 14 "komponentas iš:" 15 "parinkite aplanką, kuris turi %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_Ro.rc b/dll/win32/msi/msi_Ro.rc index 436f83b491b..b877b42a34e 100644 --- a/dll/win32/msi/msi_Ro.rc +++ b/dll/win32/msi/msi_Ro.rc @@ -35,4 +35,3 @@ STRINGTABLE DISCARDABLE 14 "caracteristică de la:" 15 "selectați fișierul care conține %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_Ru.rc b/dll/win32/msi/msi_Ru.rc index 3e59873c228..8e7aafdda31 100644 --- a/dll/win32/msi/msi_Ru.rc +++ b/dll/win32/msi/msi_Ru.rc @@ -37,4 +37,3 @@ STRINGTABLE DISCARDABLE 14 "возможность из:" 15 "выберите каталог, содержащий %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msi_Si.rc b/dll/win32/msi/msi_Si.rc index df7a9f1dc04..75823390635 100644 --- a/dll/win32/msi/msi_Si.rc +++ b/dll/win32/msi/msi_Si.rc @@ -36,4 +36,3 @@ STRINGTABLE DISCARDABLE 14 "funkcija z:" 15 "izberite mapo, ki vsebuje %s" } -#pragma code_page(default) diff --git a/dll/win32/msi/msiquery.c b/dll/win32/msi/msiquery.c index b673832b0c4..f2723affca9 100644 --- a/dll/win32/msi/msiquery.c +++ b/dll/win32/msi/msiquery.c @@ -262,7 +262,7 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, if ( !remote_database ) return ERROR_INVALID_HANDLE; - hr = IWineMsiRemoteDatabase_OpenView( remote_database, (BSTR)szQuery, phView ); + hr = IWineMsiRemoteDatabase_OpenView( remote_database, szQuery, phView ); IWineMsiRemoteDatabase_Release( remote_database ); if (FAILED(hr)) @@ -943,7 +943,7 @@ UINT WINAPI MsiDatabaseGetPrimaryKeysW( MSIHANDLE hdb, if ( !remote_database ) return ERROR_INVALID_HANDLE; - hr = IWineMsiRemoteDatabase_GetPrimaryKeys( remote_database, (BSTR)table, phRec ); + hr = IWineMsiRemoteDatabase_GetPrimaryKeys( remote_database, table, phRec ); IWineMsiRemoteDatabase_Release( remote_database ); if (FAILED(hr)) @@ -1030,7 +1030,7 @@ MSICONDITION WINAPI MsiDatabaseIsTablePersistentW( return MSICONDITION_ERROR; hr = IWineMsiRemoteDatabase_IsTablePersistent( remote_database, - (BSTR)szTableName, &condition ); + szTableName, &condition ); IWineMsiRemoteDatabase_Release( remote_database ); if (FAILED(hr)) diff --git a/dll/win32/msi/msiserver.idl b/dll/win32/msi/msiserver.idl index 25210fee155..e74c22c0b19 100644 --- a/dll/win32/msi/msiserver.idl +++ b/dll/win32/msi/msiserver.idl @@ -38,10 +38,10 @@ cpp_quote("#endif") ] interface IWineMsiRemoteDatabase : IUnknown { - HRESULT IsTablePersistent( [in] BSTR table, [out] MSICONDITION *persistent ); - HRESULT GetPrimaryKeys( [in] BSTR table, [out] MSIHANDLE *keys ); + HRESULT IsTablePersistent( [in] LPCWSTR table, [out] MSICONDITION *persistent ); + HRESULT GetPrimaryKeys( [in] LPCWSTR table, [out] MSIHANDLE *keys ); HRESULT GetSummaryInformation( [in] UINT updatecount, [out] MSIHANDLE *suminfo ); - HRESULT OpenView( [in] BSTR query, [out] MSIHANDLE *view ); + HRESULT OpenView( [in] LPCWSTR query, [out] MSIHANDLE *view ); HRESULT SetMsiHandle( [in] MSIHANDLE handle ); } diff --git a/dll/win32/msvcrt/msvcrt.def b/dll/win32/msvcrt/msvcrt.def index a78d2cc87ef..f7d9e100a2f 100644 --- a/dll/win32/msvcrt/msvcrt.def +++ b/dll/win32/msvcrt/msvcrt.def @@ -316,7 +316,7 @@ EXPORTS ; _getwche @310 _getws @311 _global_unwind2 @312 -; _gmtime64 @313 + _gmtime64 @313 _heapadd @314 _heapchk @315 _heapmin @316 @@ -373,7 +373,7 @@ EXPORTS _lfind @366 _loaddll @367 _local_unwind2 @368 -; _localtime64 @369 + _localtime64 @369 _lock @370 _locking @371 _logb @372 @@ -539,7 +539,7 @@ EXPORTS _tell @532 _telli64 @533 _tempnam @534 -; _time64 @535 + _time64 @535 _timezone @536 DATA _tolower @537 _toupper @538 diff --git a/dll/win32/msxml3/domdoc.c b/dll/win32/msxml3/domdoc.c index a29e9b2fb3e..aae8a343500 100644 --- a/dll/win32/msxml3/domdoc.c +++ b/dll/win32/msxml3/domdoc.c @@ -1650,19 +1650,20 @@ static HRESULT WINAPI domdoc_abort( static BOOL bstr_to_utf8( BSTR bstr, char **pstr, int *plen ) { - UINT len, blen = SysStringLen( bstr ); + UINT len; LPSTR str; - len = WideCharToMultiByte( CP_UTF8, 0, bstr, blen, NULL, 0, NULL, NULL ); + len = WideCharToMultiByte( CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL ); str = heap_alloc( len ); if ( !str ) return FALSE; - WideCharToMultiByte( CP_UTF8, 0, bstr, blen, str, len, NULL, NULL ); + WideCharToMultiByte( CP_UTF8, 0, bstr, -1, str, len, NULL, NULL ); *plen = len; *pstr = str; return TRUE; } +/* don't rely on data to be in BSTR format, treat it as WCHAR string */ static HRESULT WINAPI domdoc_loadXML( IXMLDOMDocument2 *iface, BSTR bstrXML, diff --git a/dll/win32/ole32/compobj.c b/dll/win32/ole32/compobj.c index 583a9cbcd00..12f83146113 100644 --- a/dll/win32/ole32/compobj.c +++ b/dll/win32/ole32/compobj.c @@ -2956,7 +2956,7 @@ HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew) HRESULT res = S_OK; LONG len = sizeof(szClsidNew); - FIXME("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew); + TRACE("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew); *clsidNew = *clsidOld; /* copy over old value */ res = COM_OpenKeyForCLSID(clsidOld, wszTreatAs, KEY_READ, &hkey); diff --git a/dll/win32/ole32/ifs.h b/dll/win32/ole32/ifs.h deleted file mode 100644 index 4c4287f319e..00000000000 --- a/dll/win32/ole32/ifs.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 1997 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __WINE_OLE_IFS_H -#define __WINE_OLE_IFS_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "objbase.h" - -typedef CHAR OLECHAR16; -typedef LPSTR LPOLESTR16; -typedef LPCSTR LPCOLESTR16; - -#define STDMETHOD16CALLTYPE __cdecl -#define STDMETHOD16(m) HRESULT (STDMETHOD16CALLTYPE *m) -#define STDMETHOD16_(t,m) t (STDMETHOD16CALLTYPE *m) - - -/*********************************************************************** - * IMalloc16 interface - */ - -typedef struct IMalloc16 *LPMALLOC16; - -#define INTERFACE IMalloc16 -DECLARE_INTERFACE_(IMalloc16,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD16_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD16_(ULONG,AddRef)(THIS) PURE; - STDMETHOD16_(ULONG,Release)(THIS) PURE; - /*** IMalloc16 methods ***/ - STDMETHOD16_(LPVOID,Alloc)(THIS_ DWORD cb) PURE; - STDMETHOD16_(LPVOID,Realloc)(THIS_ LPVOID pv, DWORD cb) PURE; - STDMETHOD16_(void,Free)(THIS_ LPVOID pv) PURE; - STDMETHOD16_(DWORD,GetSize)(THIS_ LPVOID pv) PURE; - STDMETHOD16_(INT16,DidAlloc)(THIS_ LPVOID pv) PURE; - STDMETHOD16_(LPVOID,HeapMinimize)(THIS) PURE; -}; -#undef INTERFACE - -/**********************************************************************/ - -typedef struct ILockBytes16 *LPLOCKBYTES16; - -#define INTERFACE ILockBytes16 -DECLARE_INTERFACE_(ILockBytes16,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD16_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD16_(ULONG,AddRef)(THIS) PURE; - STDMETHOD16_(ULONG,Release)(THIS) PURE; - /*** ILockBytes16 methods ***/ - STDMETHOD16(ReadAt)(THIS_ ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead) PURE; - STDMETHOD16(WriteAt)(THIS_ ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten) PURE; - STDMETHOD16(Flush)(THIS) PURE; - STDMETHOD16(SetSize)(THIS_ ULARGE_INTEGER cb) PURE; - STDMETHOD16(LockRegion)(THIS_ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) PURE; - STDMETHOD16(UnlockRegion)(THIS_ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) PURE; - STDMETHOD16(Stat)(THIS_ STATSTG *pstatstg, DWORD grfStatFlag) PURE; -}; -#undef INTERFACE - -/**********************************************************************/ - -typedef struct tagSTATSTG16 -{ - LPOLESTR16 pwcsName; - DWORD type; - ULARGE_INTEGER cbSize; - FILETIME mtime; - FILETIME ctime; - FILETIME atime; - DWORD grfMode; - DWORD grfLocksSupported; - CLSID clsid; - DWORD grfStateBits; - DWORD reserved; -} STATSTG16; - -typedef struct IStream16 *LPSTREAM16; - -#define INTERFACE IStream16 -DECLARE_INTERFACE_(IStream16,ISequentialStream) -{ - /*** IUnknown methods ***/ - STDMETHOD16_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD16_(ULONG,AddRef)(THIS) PURE; - STDMETHOD16_(ULONG,Release)(THIS) PURE; - /*** ISequentialStream methods ***/ - STDMETHOD16_(HRESULT,Read)(THIS_ void* pv, ULONG cb, ULONG* pcbRead) PURE; - STDMETHOD16_(HRESULT,Write)(THIS_ const void* pv, ULONG cb, ULONG* pcbWritten) PURE; - /*** IStream16 methods ***/ - STDMETHOD16(Seek)(THIS_ LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) PURE; - STDMETHOD16(SetSize)(THIS_ ULARGE_INTEGER libNewSize) PURE; - STDMETHOD16(CopyTo)(THIS_ IStream16* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) PURE; - STDMETHOD16(Commit)(THIS_ DWORD grfCommitFlags) PURE; - STDMETHOD16(Revert)(THIS) PURE; - STDMETHOD16(LockRegion)(THIS_ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) PURE; - STDMETHOD16(UnlockRegion)(THIS_ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) PURE; - STDMETHOD16(Stat)(THIS_ STATSTG* pstatstg, DWORD grfStatFlag) PURE; - STDMETHOD16(Clone)(THIS_ IStream16** ppstm) PURE; -}; -#undef INTERFACE - -/**********************************************************************/ - -typedef OLECHAR16 **SNB16; - -typedef struct IStorage16 *LPSTORAGE16; - -#define INTERFACE IStorage16 -DECLARE_INTERFACE_(IStorage16,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD16_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD16_(ULONG,AddRef)(THIS) PURE; - STDMETHOD16_(ULONG,Release)(THIS) PURE; - /*** IStorage16 methods ***/ - STDMETHOD16_(HRESULT,CreateStream)(THIS_ LPCOLESTR16 pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream16** ppstm) PURE; - STDMETHOD16_(HRESULT,OpenStream)(THIS_ LPCOLESTR16 pwcsName, void* reserved1, DWORD grfMode, DWORD reserved2, IStream16** ppstm) PURE; - STDMETHOD16_(HRESULT,CreateStorage)(THIS_ LPCOLESTR16 pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage16** ppstg) PURE; - STDMETHOD16_(HRESULT,OpenStorage)(THIS_ LPCOLESTR16 pwcsName, IStorage16* pstgPriority, DWORD grfMode, SNB16 snbExclude, DWORD reserved, IStorage16** ppstg) PURE; - STDMETHOD16_(HRESULT,CopyTo)(THIS_ DWORD ciidExclude, const IID* rgiidExclude, SNB16 snbExclude, IStorage16* pstgDest) PURE; - STDMETHOD16_(HRESULT,MoveElementTo)(THIS_ LPCOLESTR16 pwcsName, IStorage16* pstgDest, LPCOLESTR16 pwcsNewName, DWORD grfFlags) PURE; - STDMETHOD16_(HRESULT,Commit)(THIS_ DWORD grfCommitFlags) PURE; - STDMETHOD16_(HRESULT,Revert)(THIS) PURE; - STDMETHOD16_(HRESULT,EnumElements)(THIS_ DWORD reserved1, void* reserved2, DWORD reserved3, IEnumSTATSTG** ppenum) PURE; - STDMETHOD16_(HRESULT,DestroyElement)(THIS_ LPCOLESTR16 pwcsName) PURE; - STDMETHOD16_(HRESULT,RenameElement)(THIS_ LPCOLESTR16 pwcsOldName, LPCOLESTR16 pwcsNewName) PURE; - STDMETHOD16_(HRESULT,SetElementTimes)(THIS_ LPCOLESTR16 pwcsName, const FILETIME* pctime, const FILETIME* patime, const FILETIME* pmtime) PURE; - STDMETHOD16_(HRESULT,SetClass)(THIS_ REFCLSID clsid) PURE; - STDMETHOD16_(HRESULT,SetStateBits)(THIS_ DWORD grfStateBits, DWORD grfMask) PURE; - STDMETHOD16_(HRESULT,Stat)(THIS_ STATSTG* pstatstg, DWORD grfStatFlag) PURE; -}; -#undef INTERFACE - -#endif /* __WINE_OLE_IFS_H */ diff --git a/dll/win32/ole32/ole16.c b/dll/win32/ole32/ole16.c deleted file mode 100644 index 1e1cf452f79..00000000000 --- a/dll/win32/ole32/ole16.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * 16 bit ole functions - * - * Copyright 1995 Martin von Loewis - * Copyright 1998 Justin Bradford - * Copyright 1999 Francis Beaudet - * Copyright 1999 Sylvain St-Germain - * Copyright 2002 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "objbase.h" -#include "ole2.h" -#include "rpc.h" -#include "winerror.h" -#include "winreg.h" -#include "wownt32.h" -#include "wtypes.h" -#include "wine/unicode.h" -#include "wine/winbase16.h" -#include "compobj_private.h" -#include "ifs.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -static HTASK16 hETask = 0; -static WORD Table_ETask[62]; - -static LPMALLOC16 currentMalloc16=NULL; - -/* --- IMalloc16 implementation */ - - -typedef struct -{ - /* IUnknown fields */ - const IMalloc16Vtbl *lpVtbl; - DWORD ref; - /* IMalloc16 fields */ -} IMalloc16Impl; - -/****************************************************************************** - * IMalloc16_QueryInterface [COMPOBJ.500] - */ -HRESULT CDECL IMalloc16_fnQueryInterface(IMalloc16* iface,REFIID refiid,LPVOID *obj) { - IMalloc16Impl *This = (IMalloc16Impl *)iface; - - TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj); - if ( !memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)) || - !memcmp(&IID_IMalloc,refiid,sizeof(IID_IMalloc)) - ) { - *obj = This; - return 0; - } - return OLE_E_ENUM_NOMORE; -} - -/****************************************************************************** - * IMalloc16_AddRef [COMPOBJ.501] - */ -ULONG CDECL IMalloc16_fnAddRef(IMalloc16* iface) { - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->AddRef()\n",This); - return 1; /* cannot be freed */ -} - -/****************************************************************************** - * IMalloc16_Release [COMPOBJ.502] - */ -ULONG CDECL IMalloc16_fnRelease(IMalloc16* iface) { - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->Release()\n",This); - return 1; /* cannot be freed */ -} - -/****************************************************************************** - * IMalloc16_Alloc [COMPOBJ.503] - */ -SEGPTR CDECL IMalloc16_fnAlloc(IMalloc16* iface,DWORD cb) { - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->Alloc(%d)\n",This,cb); - return MapLS( HeapAlloc( GetProcessHeap(), 0, cb ) ); -} - -/****************************************************************************** - * IMalloc16_Free [COMPOBJ.505] - */ -VOID CDECL IMalloc16_fnFree(IMalloc16* iface,SEGPTR pv) -{ - void *ptr = MapSL(pv); - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->Free(%08x)\n",This,pv); - UnMapLS(pv); - HeapFree( GetProcessHeap(), 0, ptr ); -} - -/****************************************************************************** - * IMalloc16_Realloc [COMPOBJ.504] - */ -SEGPTR CDECL IMalloc16_fnRealloc(IMalloc16* iface,SEGPTR pv,DWORD cb) -{ - SEGPTR ret; - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->Realloc(%08x,%d)\n",This,pv,cb); - if (!pv) - ret = IMalloc16_fnAlloc(iface, cb); - else if (cb) { - ret = MapLS( HeapReAlloc( GetProcessHeap(), 0, MapSL(pv), cb ) ); - UnMapLS(pv); - } else { - IMalloc16_fnFree(iface, pv); - ret = 0; - } - return ret; -} - -/****************************************************************************** - * IMalloc16_GetSize [COMPOBJ.506] - */ -DWORD CDECL IMalloc16_fnGetSize(IMalloc16* iface,SEGPTR pv) -{ - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->GetSize(%08x)\n",This,pv); - return HeapSize( GetProcessHeap(), 0, MapSL(pv) ); -} - -/****************************************************************************** - * IMalloc16_DidAlloc [COMPOBJ.507] - */ -INT16 CDECL IMalloc16_fnDidAlloc(IMalloc16* iface,LPVOID pv) { - IMalloc16 *This = iface; - TRACE("(%p)->DidAlloc(%p)\n",This,pv); - return (INT16)-1; -} - -/****************************************************************************** - * IMalloc16_HeapMinimize [COMPOBJ.508] - */ -LPVOID CDECL IMalloc16_fnHeapMinimize(IMalloc16* iface) { - IMalloc16Impl *This = (IMalloc16Impl *)iface; - TRACE("(%p)->HeapMinimize()\n",This); - return NULL; -} - -/****************************************************************************** - * IMalloc16_Constructor [VTABLE] - */ -static LPMALLOC16 -IMalloc16_Constructor(void) -{ - static IMalloc16Vtbl vt16; - static SEGPTR msegvt16; - IMalloc16Impl* This; - HMODULE16 hcomp = GetModuleHandle16("COMPOBJ"); - - This = HeapAlloc( GetProcessHeap(), 0, sizeof(IMalloc16Impl) ); - if (!msegvt16) - { -#define VTENT(x) vt16.x = (void*)GetProcAddress16(hcomp,"IMalloc16_"#x);assert(vt16.x) - VTENT(QueryInterface); - VTENT(AddRef); - VTENT(Release); - VTENT(Alloc); - VTENT(Realloc); - VTENT(Free); - VTENT(GetSize); - VTENT(DidAlloc); - VTENT(HeapMinimize); -#undef VTENT - msegvt16 = MapLS( &vt16 ); - } - This->lpVtbl = (const IMalloc16Vtbl*)msegvt16; - This->ref = 1; - return (LPMALLOC16)MapLS( This ); -} - - -/*********************************************************************** - * CoGetMalloc [COMPOBJ.4] - * - * Retrieve the current win16 IMalloc interface. - * - * RETURNS - * The current win16 IMalloc - */ -HRESULT WINAPI CoGetMalloc16( - DWORD dwMemContext, /* [in] unknown */ - LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */ -) { - if(!currentMalloc16) - currentMalloc16 = IMalloc16_Constructor(); - *lpMalloc = currentMalloc16; - return S_OK; -} - -/*********************************************************************** - * CoCreateStandardMalloc [COMPOBJ.71] - */ -HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext, - LPMALLOC16 *lpMalloc) -{ - /* FIXME: docu says we shouldn't return the same allocator as in - * CoGetMalloc16 */ - *lpMalloc = IMalloc16_Constructor(); - return S_OK; -} - -/****************************************************************************** - * CoInitialize [COMPOBJ.2] - * Set the win16 IMalloc used for memory management - */ -HRESULT WINAPI CoInitialize16( - LPVOID lpReserved /* [in] pointer to win16 malloc interface */ -) { - currentMalloc16 = (LPMALLOC16)lpReserved; - return S_OK; -} - -/*********************************************************************** - * CoUninitialize [COMPOBJ.3] - * Don't know what it does. - * 3-Nov-98 -- this was originally misspelled, I changed it to what I - * believe is the correct spelling - */ -void WINAPI CoUninitialize16(void) -{ - TRACE("()\n"); - CoFreeAllLibraries(); -} - -/*********************************************************************** - * IsEqualGUID [COMPOBJ.18] - * - * Compares two Unique Identifiers. - * - * RETURNS - * TRUE if equal - */ -BOOL16 WINAPI IsEqualGUID16( - GUID* g1, /* [in] unique id 1 */ - GUID* g2) /* [in] unique id 2 */ -{ - return !memcmp( g1, g2, sizeof(GUID) ); -} - -/****************************************************************************** - * CLSIDFromString [COMPOBJ.20] - * Converts a unique identifier from its string representation into - * the GUID struct. - * - * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6] - * - * RETURNS - * the converted GUID - */ -HRESULT WINAPI CLSIDFromString16( - LPCOLESTR16 idstr, /* [in] string representation of guid */ - CLSID *id) /* [out] GUID converted from string */ -{ - const BYTE *s; - int i; - BYTE table[256]; - - if (!idstr) { - memset( id, 0, sizeof (CLSID) ); - return S_OK; - } - - /* validate the CLSID string */ - if (strlen(idstr) != 38) - return CO_E_CLASSSTRING; - - s = (const BYTE *) idstr; - if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}')) - return CO_E_CLASSSTRING; - - for (i=1; i<37; i++) { - if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue; - if (!(((s[i] >= '0') && (s[i] <= '9')) || - ((s[i] >= 'a') && (s[i] <= 'f')) || - ((s[i] >= 'A') && (s[i] <= 'F')))) - return CO_E_CLASSSTRING; - } - - TRACE("%s -> %p\n", s, id); - - /* quick lookup table */ - memset(table, 0, 256); - - for (i = 0; i < 10; i++) { - table['0' + i] = i; - } - for (i = 0; i < 6; i++) { - table['A' + i] = i+10; - table['a' + i] = i+10; - } - - /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ - - id->Data1 = (table[s[1]] << 28 | table[s[2]] << 24 | table[s[3]] << 20 | table[s[4]] << 16 | - table[s[5]] << 12 | table[s[6]] << 8 | table[s[7]] << 4 | table[s[8]]); - id->Data2 = table[s[10]] << 12 | table[s[11]] << 8 | table[s[12]] << 4 | table[s[13]]; - id->Data3 = table[s[15]] << 12 | table[s[16]] << 8 | table[s[17]] << 4 | table[s[18]]; - - /* these are just sequential bytes */ - id->Data4[0] = table[s[20]] << 4 | table[s[21]]; - id->Data4[1] = table[s[22]] << 4 | table[s[23]]; - id->Data4[2] = table[s[25]] << 4 | table[s[26]]; - id->Data4[3] = table[s[27]] << 4 | table[s[28]]; - id->Data4[4] = table[s[29]] << 4 | table[s[30]]; - id->Data4[5] = table[s[31]] << 4 | table[s[32]]; - id->Data4[6] = table[s[33]] << 4 | table[s[34]]; - id->Data4[7] = table[s[35]] << 4 | table[s[36]]; - - return S_OK; -} - -/****************************************************************************** - * _xmalloc16 [internal] - * Allocates size bytes from the standard ole16 allocator. - * - * RETURNS - * the allocated segmented pointer and a HRESULT - */ -static HRESULT -_xmalloc16(DWORD size, SEGPTR *ptr) { - LPMALLOC16 mllc; - DWORD args[2]; - - if (CoGetMalloc16(0,&mllc)) - return E_OUTOFMEMORY; - - args[0] = (DWORD)mllc; - args[1] = size; - /* No need for a Callback entry, we have WOWCallback16Ex which does - * everything we need. - */ - if (!WOWCallback16Ex( - (DWORD)((const IMalloc16Vtbl*)MapSL( - (SEGPTR)((LPMALLOC16)MapSL((SEGPTR)mllc))->lpVtbl ) - )->Alloc, - WCB16_CDECL, - 2*sizeof(DWORD), - (LPVOID)args, - (LPDWORD)ptr - )) { - ERR("CallTo16 IMalloc16 (%d) failed\n",size); - return E_FAIL; - } - return S_OK; -} - -/****************************************************************************** - * StringFromCLSID [COMPOBJ.19] - * Converts a GUID into the respective string representation. - * The target string is allocated using the OLE IMalloc. - * - * RETURNS - * the string representation and HRESULT - */ - -HRESULT WINAPI StringFromCLSID16( - REFCLSID id, /* [in] the GUID to be converted */ - LPOLESTR16 *idstr /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */ - -) { - HRESULT ret; - - ret = _xmalloc16(40,(SEGPTR*)idstr); - if (ret != S_OK) - return ret; - return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr)); -} - -/****************************************************************************** - * ProgIDFromCLSID [COMPOBJ.62] - * - * Converts a class id into the respective Program ID. (By using a registry lookup) - * - * RETURNS - * S_OK on success - * riid associated with the progid - */ -HRESULT WINAPI ProgIDFromCLSID16( - REFCLSID clsid, /* [in] class id as found in registry */ - LPOLESTR16 *lplpszProgID/* [out] associated Program ID */ -) { - static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0}; - HKEY hkey; - HRESULT ret; - LONG len; - char *buffer; - - ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey); - if (FAILED(ret)) - return ret; - - if (RegQueryValueA(hkey, NULL, NULL, &len)) - ret = REGDB_E_READREGDB; - - if (ret == S_OK) - { - buffer = HeapAlloc(GetProcessHeap(), 0, len); - if (RegQueryValueA(hkey, NULL, buffer, &len)) - ret = REGDB_E_READREGDB; - - if (ret == S_OK) - { - ret = _xmalloc16(len, (SEGPTR*)lplpszProgID); - if (ret == S_OK) - strcpy(MapSL((SEGPTR)*lplpszProgID),buffer); - } - HeapFree(GetProcessHeap(), 0, buffer); - } - RegCloseKey(hkey); - return ret; -} - -/*********************************************************************** - * LookupETask (COMPOBJ.94) - */ -HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) { - FIXME("(%p,%p),stub!\n",hTask,p); - if ((*hTask = GetCurrentTask()) == hETask) { - memcpy(p, Table_ETask, sizeof(Table_ETask)); - } - return 0; -} - -/*********************************************************************** - * SetETask (COMPOBJ.95) - */ -HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) { - FIXME("(%04x,%p),stub!\n",hTask,p); - hETask = hTask; - return 0; -} - -/*********************************************************************** - * CALLOBJECTINWOW (COMPOBJ.201) - */ -HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) { - FIXME("(%p,%p),stub!\n",p1,p2); - return 0; -} - -/****************************************************************************** - * CoRegisterClassObject [COMPOBJ.5] - * - * Don't know where it registers it ... - */ -HRESULT WINAPI CoRegisterClassObject16( - REFCLSID rclsid, - LPUNKNOWN pUnk, - DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */ - DWORD flags, /* [in] REGCLS flags indicating how connections are made */ - LPDWORD lpdwRegister -) { - FIXME("(%s,%p,0x%08x,0x%08x,%p),stub\n", - debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister - ); - return 0; -} - -/****************************************************************************** - * CoRevokeClassObject [COMPOBJ.6] - * - */ -HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */ -{ - FIXME("(0x%08x),stub!\n", dwRegister); - return 0; -} - -/****************************************************************************** - * CoFileTimeToDosDateTime [COMPOBJ.30] - */ -BOOL16 WINAPI CoFileTimeToDosDateTime16(const FILETIME *ft, LPWORD lpDosDate, LPWORD lpDosTime) -{ - return FileTimeToDosDateTime(ft, lpDosDate, lpDosTime); -} - -/****************************************************************************** - * CoDosDateTimeToFileTime [COMPOBJ.31] - */ -BOOL16 WINAPI CoDosDateTimeToFileTime16(WORD wDosDate, WORD wDosTime, FILETIME *ft) -{ - return DosDateTimeToFileTime(wDosDate, wDosTime, ft); -} - -/****************************************************************************** - * CoRegisterMessageFilter [COMPOBJ.27] - */ -HRESULT WINAPI CoRegisterMessageFilter16( - LPMESSAGEFILTER lpMessageFilter, - LPMESSAGEFILTER *lplpMessageFilter -) { - FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter); - return 0; -} - -/****************************************************************************** - * CoLockObjectExternal [COMPOBJ.63] - */ -HRESULT WINAPI CoLockObjectExternal16( - LPUNKNOWN pUnk, /* [in] object to be locked */ - BOOL16 fLock, /* [in] do lock */ - BOOL16 fLastUnlockReleases /* [in] ? */ -) { - FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases); - return S_OK; -} - -/*********************************************************************** - * CoGetState [COMPOBJ.115] - */ -HRESULT WINAPI CoGetState16(LPDWORD state) -{ - FIXME("(%p),stub!\n", state); - - *state = 0; - return S_OK; -} - -/*********************************************************************** - * DllEntryPoint [COMPOBJ.116] - * - * Initialization code for the COMPOBJ DLL - * - * RETURNS: - */ -BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2) -{ - TRACE("(%08x, %04x, %04x, %04x, %08x, %04x)\n", Reason, hInst, ds, HeapSize, res1, res2); - return TRUE; -} - -/*********************************************************************** - * CoMemAlloc [COMPOBJ.151] - */ -SEGPTR WINAPI CoMemAlloc(DWORD size, DWORD dwMemContext, DWORD x) { - HRESULT hres; - SEGPTR segptr; - - /* FIXME: check context handling */ - TRACE("(%d, 0x%08x, 0x%08x)\n", size, dwMemContext, x); - hres = _xmalloc16(size, &segptr); - if (hres != S_OK) - return 0; - return segptr; -} - -/****************************************************************************** - * CLSIDFromProgID [COMPOBJ.61] - * - * Converts a program ID into the respective GUID. - * - * PARAMS - * progid [I] program id as found in registry - * riid [O] associated CLSID - * - * RETURNS - * Success: S_OK - * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found. - */ -HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid) -{ - char *buf,buf2[80]; - LONG buf2len; - HRESULT err; - HKEY xhkey; - - buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8); - sprintf(buf,"%s\\CLSID",progid); - if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) { - HeapFree(GetProcessHeap(),0,buf); - return CO_E_CLASSSTRING; - } - HeapFree(GetProcessHeap(),0,buf); - buf2len = sizeof(buf2); - if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) { - RegCloseKey(xhkey); - return CO_E_CLASSSTRING; - } - RegCloseKey(xhkey); - return CLSIDFromString16(buf2,riid); -} - -/*********************************************************************** - * CoGetClassObject [COMPOBJ.7] - * - */ -HRESULT WINAPI CoGetClassObject16( - REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, - REFIID iid, LPVOID *ppv) -{ - FIXME(", stub!\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); - - if (pServerInfo) { - FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName)); - FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo); - } - return E_NOTIMPL; -} - -/*********************************************************************** - * CoCreateInstance [COMPOBJ.13] - */ -HRESULT WINAPI CoCreateInstance16( - REFCLSID rclsid, - LPUNKNOWN pUnkOuter, - DWORD dwClsContext, - REFIID iid, - LPVOID *ppv) -{ - FIXME("(%s, %p, %x, %s, %p), stub!\n", - debugstr_guid(rclsid), pUnkOuter, dwClsContext, debugstr_guid(iid), - ppv - ); - return E_NOTIMPL; -} - -/*********************************************************************** - * CoDisconnectObject [COMPOBJ.15] - */ -HRESULT WINAPI CoDisconnectObject16( LPUNKNOWN lpUnk, DWORD reserved ) -{ - FIXME("(%p, 0x%08x): stub!\n", lpUnk, reserved); - return E_NOTIMPL; -} - -/*********************************************************************** - * DllGetClassObject [OLE2.4] - */ -HRESULT WINAPI DllGetClassObject16(REFCLSID rclsid, REFIID iid, LPVOID *ppv) -{ - FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv); - return E_NOTIMPL; -} - -/****************************************************************************** - * GetRunningObjectTable (OLE2.30) - */ -HRESULT WINAPI -GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) -{ - FIXME("(%d,%p),stub!\n",reserved,pprot); - return E_NOTIMPL; -} diff --git a/dll/win32/ole32/stg_bigblockfile.c b/dll/win32/ole32/stg_bigblockfile.c index 19151b96382..77abbf6286b 100644 --- a/dll/win32/ole32/stg_bigblockfile.c +++ b/dll/win32/ole32/stg_bigblockfile.c @@ -63,19 +63,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage); /* We map in PAGE_SIZE-sized chunks. Must be a multiple of 4096. */ #define PAGE_SIZE 131072 -#define BLOCKS_PER_PAGE (PAGE_SIZE / BIG_BLOCK_SIZE) - /* We keep a list of recently-discarded pages. This controls the * size of that list. */ #define MAX_VICTIM_PAGES 16 -/* This structure provides one bit for each block in a page. - * Use BIGBLOCKFILE_{Test,Set,Clear}Bit to manipulate it. */ -typedef struct -{ - unsigned int bits[BLOCKS_PER_PAGE / (CHAR_BIT * sizeof(unsigned int))]; -} BlockBits; - /*** * This structure identifies the paged that are mapped * from the file and their position in memory. It is @@ -96,16 +87,12 @@ struct MappedPage DWORD mapped_bytes; LPVOID lpBytes; LONG refcnt; - - BlockBits readable_blocks; - BlockBits writable_blocks; }; struct BigBlockFile { BOOL fileBased; ULARGE_INTEGER filesize; - ULONG blocksize; HANDLE hfile; HANDLE hfilemap; DWORD flProtect; @@ -123,39 +110,6 @@ struct BigBlockFile * pass expressions with side effects. */ #define ROUND_UP(a, b) ((((a) + (b) - 1)/(b))*(b)) -/*********************************************************** - * Blockbits functions. - */ -static inline BOOL BIGBLOCKFILE_TestBit(const BlockBits *bb, - unsigned int index) -{ - unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); - unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); - - return bb->bits[array_index] & (1 << bit_index); -} - -static inline void BIGBLOCKFILE_SetBit(BlockBits *bb, unsigned int index) -{ - unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); - unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); - - bb->bits[array_index] |= (1 << bit_index); -} - -static inline void BIGBLOCKFILE_ClearBit(BlockBits *bb, unsigned int index) -{ - unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); - unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); - - bb->bits[array_index] &= ~(1 << bit_index); -} - -static inline void BIGBLOCKFILE_Zero(BlockBits *bb) -{ - memset(bb->bits, 0, sizeof(bb->bits)); -} - /****************************************************************************** * BIGBLOCKFILE_FileInit * @@ -302,9 +256,6 @@ static MappedPage *BIGBLOCKFILE_CreatePage(BigBlockFile *This, ULONG page_index) return NULL; } - BIGBLOCKFILE_Zero(&page->readable_blocks); - BIGBLOCKFILE_Zero(&page->writable_blocks); - return page; } @@ -328,9 +279,6 @@ static void * BIGBLOCKFILE_GetMappedView( if (page) { This->num_victim_pages--; - - BIGBLOCKFILE_Zero(&page->readable_blocks); - BIGBLOCKFILE_Zero(&page->writable_blocks); } } @@ -709,7 +657,7 @@ static HRESULT ImplBIGBLOCKFILE_WriteAt( * and the blocks in use list. */ BigBlockFile *BIGBLOCKFILE_Construct(HANDLE hFile, ILockBytes* pLkByt, DWORD openFlags, - ULONG blocksize, BOOL fileBased) + BOOL fileBased) { BigBlockFile *This; @@ -720,7 +668,6 @@ BigBlockFile *BIGBLOCKFILE_Construct(HANDLE hFile, ILockBytes* pLkByt, DWORD ope This->fileBased = fileBased; This->flProtect = BIGBLOCKFILE_GetProtectMode(openFlags); - This->blocksize = blocksize; This->maplist = NULL; This->victimhead = NULL; @@ -863,31 +810,19 @@ static HRESULT BIGBLOCKFILE_GetSize(BigBlockFile *This, ULARGE_INTEGER *size) } /****************************************************************************** - * BIGBLOCKFILE_EnsureExists + * BIGBLOCKFILE_Expand * - * Grows the file if necessary to make sure the block is valid. + * Grows the file to the specified size if necessary. */ -HRESULT BIGBLOCKFILE_EnsureExists(BigBlockFile *This, ULONG index) +HRESULT BIGBLOCKFILE_Expand(BigBlockFile *This, ULARGE_INTEGER newSize) { ULARGE_INTEGER size; HRESULT hr; - /* Block index starts at -1 translate to zero based index */ - if (index == 0xffffffff) - index = 0; - else - index++; - hr = BIGBLOCKFILE_GetSize(This, &size); if(FAILED(hr)) return hr; - /* make sure that the block physically exists */ - if ((This->blocksize * (index + 1)) > size.QuadPart) - { - ULARGE_INTEGER newSize; - - newSize.QuadPart = This->blocksize * (index + 1); + if (newSize.QuadPart > size.QuadPart) hr = BIGBLOCKFILE_SetSize(This, newSize); - } return hr; } diff --git a/dll/win32/ole32/stg_prop.c b/dll/win32/ole32/stg_prop.c index 52153a20d44..b3362bc21de 100644 --- a/dll/win32/ole32/stg_prop.c +++ b/dll/win32/ole32/stg_prop.c @@ -181,7 +181,9 @@ static HRESULT WINAPI IPropertyStorage_fnQueryInterface( { PropertyStorage_impl *This = (PropertyStorage_impl *)iface; - if ( (This==0) || (ppvObject==0) ) + TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject); + + if (!ppvObject) return E_INVALIDARG; *ppvObject = 0; diff --git a/dll/win32/ole32/storage32.c b/dll/win32/ole32/storage32.c index 837365bdb9d..f1706da72fb 100644 --- a/dll/win32/ole32/storage32.c +++ b/dll/win32/ole32/storage32.c @@ -269,14 +269,9 @@ static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This); ** Block Functions */ -static ULONG BLOCK_GetBigBlockOffset(ULONG index) +static ULONG StorageImpl_GetBigBlockOffset(StorageImpl* This, ULONG index) { - if (index == 0xffffffff) - index = 0; - else - index ++; - - return index * BIG_BLOCK_SIZE; + return (index+1) * This->bigBlockSize; } /************************************************************************ @@ -1599,11 +1594,15 @@ static HRESULT WINAPI StorageBaseImpl_CopyTo( SNB snbExclude, /* [unique][in] */ IStorage* pstgDest) /* [unique][in] */ { + StorageBaseImpl* const This=(StorageBaseImpl*)iface; + IEnumSTATSTG *elements = 0; STATSTG curElement, strStat; HRESULT hr; IStorage *pstgTmp, *pstgChild; IStream *pstrTmp, *pstrChild; + DirRef srcEntryRef; + DirEntry srcEntry; BOOL skip = FALSE, skip_storage = FALSE, skip_stream = FALSE; int i; @@ -1728,11 +1727,25 @@ static HRESULT WINAPI StorageBaseImpl_CopyTo( goto cleanup; /* - * open child stream storage + * open child stream storage. This operation must succeed even if the + * stream is already open, so we use internal functions to do it. */ - hr = IStorage_OpenStream( iface, curElement.pwcsName, NULL, - STGM_READ|STGM_SHARE_EXCLUSIVE, - 0, &pstrChild ); + srcEntryRef = findElement( This, This->storageDirEntry, curElement.pwcsName, + &srcEntry); + if (!srcEntryRef) + { + ERR("source stream not found\n"); + hr = STG_E_DOCFILECORRUPT; + } + + if (hr == S_OK) + { + pstrChild = (IStream*)StgStreamImpl_Construct(This, STGM_READ|STGM_SHARE_EXCLUSIVE, srcEntryRef); + if (pstrChild) + IStream_AddRef(pstrChild); + else + hr = E_OUTOFMEMORY; + } if (hr == S_OK) { @@ -2626,7 +2639,6 @@ static HRESULT StorageImpl_Construct( This->bigBlockFile = BIGBLOCKFILE_Construct(hFile, pLkbyt, openFlags, - This->bigBlockSize, fileBased); if (This->bigBlockFile == 0) @@ -2638,7 +2650,7 @@ static HRESULT StorageImpl_Construct( if (create) { ULARGE_INTEGER size; - BYTE bigBlockBuffer[BIG_BLOCK_SIZE]; + BYTE bigBlockBuffer[MAX_BIG_BLOCK_SIZE]; /* * Initialize all header variables: @@ -2835,13 +2847,14 @@ static ULONG StorageImpl_GetNextFreeBigBlock( StorageImpl* This) { ULONG depotBlockIndexPos; - BYTE depotBuffer[BIG_BLOCK_SIZE]; + BYTE depotBuffer[MAX_BIG_BLOCK_SIZE]; BOOL success; ULONG depotBlockOffset; ULONG blocksPerDepot = This->bigBlockSize / sizeof(ULONG); ULONG nextBlockIndex = BLOCK_SPECIAL; int depotIndex = 0; ULONG freeBlock = BLOCK_UNUSED; + ULARGE_INTEGER neededSize; depotIndex = This->prevFreeBlock / blocksPerDepot; depotBlockOffset = (This->prevFreeBlock % blocksPerDepot) * sizeof(ULONG); @@ -2955,7 +2968,8 @@ static ULONG StorageImpl_GetNextFreeBigBlock( /* * make sure that the block physically exists before using it */ - BIGBLOCKFILE_EnsureExists(This->bigBlockFile, freeBlock); + neededSize.QuadPart = StorageImpl_GetBigBlockOffset(This, freeBlock)+This->bigBlockSize; + BIGBLOCKFILE_Expand(This->bigBlockFile, neededSize); This->prevFreeBlock = freeBlock; @@ -2970,7 +2984,7 @@ static ULONG StorageImpl_GetNextFreeBigBlock( */ static void Storage32Impl_AddBlockDepot(StorageImpl* This, ULONG blockIndex) { - BYTE blockBuffer[BIG_BLOCK_SIZE]; + BYTE blockBuffer[MAX_BIG_BLOCK_SIZE]; /* * Initialize blocks as free @@ -3053,7 +3067,7 @@ static ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This) { ULONG numExtBlocks = This->extBigBlockDepotCount; ULONG nextExtBlock = This->extBigBlockDepotStart; - BYTE depotBuffer[BIG_BLOCK_SIZE]; + BYTE depotBuffer[MAX_BIG_BLOCK_SIZE]; ULONG index = BLOCK_UNUSED; ULONG nextBlockOffset = This->bigBlockSize - sizeof(ULONG); ULONG blocksPerDepotBlock = This->bigBlockSize / sizeof(ULONG); @@ -3143,10 +3157,10 @@ static HRESULT StorageImpl_GetNextBlockInChain( ULONG offsetInDepot = blockIndex * sizeof (ULONG); ULONG depotBlockCount = offsetInDepot / This->bigBlockSize; ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize; - BYTE depotBuffer[BIG_BLOCK_SIZE]; + BYTE depotBuffer[MAX_BIG_BLOCK_SIZE]; BOOL success; ULONG depotBlockIndexPos; - int index; + int index, num_blocks; *nextBlockIndex = BLOCK_SPECIAL; @@ -3181,7 +3195,9 @@ static HRESULT StorageImpl_GetNextBlockInChain( if (!success) return STG_E_READFAULT; - for (index = 0; index < NUM_BLOCKS_PER_DEPOT_BLOCK; index++) + num_blocks = This->bigBlockSize / 4; + + for (index = 0; index < num_blocks; index++) { StorageUtl_ReadDWord(depotBuffer, index*sizeof(ULONG), nextBlockIndex); This->blockDepotCached[index] = *nextBlockIndex; @@ -3272,26 +3288,31 @@ static void StorageImpl_SetNextBlockInChain( /****************************************************************************** * Storage32Impl_LoadFileHeader * - * This method will read in the file header, i.e. big block index -1. + * This method will read in the file header */ static HRESULT StorageImpl_LoadFileHeader( StorageImpl* This) { - HRESULT hr = STG_E_FILENOTFOUND; - BYTE headerBigBlock[BIG_BLOCK_SIZE]; - BOOL success; + HRESULT hr; + BYTE headerBigBlock[HEADER_SIZE]; int index; + ULARGE_INTEGER offset; + DWORD bytes_read; TRACE("\n"); /* * Get a pointer to the big block of data containing the header. */ - success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock); + offset.u.HighPart = 0; + offset.u.LowPart = 0; + hr = StorageImpl_ReadAt(This, offset, headerBigBlock, HEADER_SIZE, &bytes_read); + if (SUCCEEDED(hr) && bytes_read != HEADER_SIZE) + hr = STG_E_FILENOTFOUND; /* * Extract the information from the header. */ - if (success) + if (SUCCEEDED(hr)) { /* * Check for the "magic number" signature and return an error if it is not @@ -3360,7 +3381,7 @@ static HRESULT StorageImpl_LoadFileHeader( * Right now, the code is making some assumptions about the size of the * blocks, just make sure they are what we're expecting. */ - if (This->bigBlockSize != DEF_BIG_BLOCK_SIZE || + if ((This->bigBlockSize != MIN_BIG_BLOCK_SIZE && This->bigBlockSize != MAX_BIG_BLOCK_SIZE) || This->smallBlockSize != DEF_SMALL_BLOCK_SIZE) { WARN("Broken OLE storage file\n"); @@ -3376,29 +3397,35 @@ static HRESULT StorageImpl_LoadFileHeader( /****************************************************************************** * Storage32Impl_SaveFileHeader * - * This method will save to the file the header, i.e. big block -1. + * This method will save to the file the header */ static void StorageImpl_SaveFileHeader( StorageImpl* This) { - BYTE headerBigBlock[BIG_BLOCK_SIZE]; + BYTE headerBigBlock[HEADER_SIZE]; int index; - BOOL success; + HRESULT hr; + ULARGE_INTEGER offset; + DWORD bytes_read, bytes_written; /* * Get a pointer to the big block of data containing the header. */ - success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock); + offset.u.HighPart = 0; + offset.u.LowPart = 0; + hr = StorageImpl_ReadAt(This, offset, headerBigBlock, HEADER_SIZE, &bytes_read); + if (SUCCEEDED(hr) && bytes_read != HEADER_SIZE) + hr = STG_E_FILENOTFOUND; /* * If the block read failed, the file is probably new. */ - if (!success) + if (FAILED(hr)) { /* * Initialize for all unknown fields. */ - memset(headerBigBlock, 0, BIG_BLOCK_SIZE); + memset(headerBigBlock, 0, HEADER_SIZE); /* * Initialize the magic number. @@ -3469,7 +3496,7 @@ static void StorageImpl_SaveFileHeader( /* * Write the big block back to the file. */ - StorageImpl_WriteBigBlock(This, -1, headerBigBlock); + StorageImpl_WriteAt(This, offset, headerBigBlock, HEADER_SIZE, &bytes_written); } /****************************************************************************** @@ -3711,7 +3738,7 @@ static BOOL StorageImpl_ReadBigBlock( DWORD read; ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex); StorageImpl_ReadAt(This, ulOffset, buffer, This->bigBlockSize, &read); return (read == This->bigBlockSize); @@ -3728,7 +3755,7 @@ static BOOL StorageImpl_ReadDWordFromBigBlock( DWORD tmp; ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex); ulOffset.u.LowPart += offset; StorageImpl_ReadAt(This, ulOffset, &tmp, sizeof(DWORD), &read); @@ -3745,7 +3772,7 @@ static BOOL StorageImpl_WriteBigBlock( DWORD wrote; ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex); StorageImpl_WriteAt(This, ulOffset, buffer, This->bigBlockSize, &wrote); return (wrote == This->bigBlockSize); @@ -3761,7 +3788,7 @@ static BOOL StorageImpl_WriteDWordToBigBlock( DWORD wrote; ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex); + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This, blockIndex); ulOffset.u.LowPart += offset; value = htole32(value); @@ -5151,7 +5178,7 @@ HRESULT BlockChainStream_ReadAt(BlockChainStream* This, TRACE("block %i\n",blockIndex); ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex) + + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) + offsetInBlock; StorageImpl_ReadAt(This->parentStorage, @@ -5247,7 +5274,7 @@ HRESULT BlockChainStream_WriteAt(BlockChainStream* This, TRACE("block %i\n",blockIndex); ulOffset.u.HighPart = 0; - ulOffset.u.LowPart = BLOCK_GetBigBlockOffset(blockIndex) + + ulOffset.u.LowPart = StorageImpl_GetBigBlockOffset(This->parentStorage, blockIndex) + offsetInBlock; StorageImpl_WriteAt(This->parentStorage, @@ -5721,7 +5748,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock( ULONG sbdIndex = This->parentStorage->smallBlockDepotStart; ULONG nextBlock, newsbdIndex; - BYTE smallBlockDepot[BIG_BLOCK_SIZE]; + BYTE smallBlockDepot[MAX_BIG_BLOCK_SIZE]; nextBlock = sbdIndex; while (nextBlock != BLOCK_END_OF_CHAIN) diff --git a/dll/win32/ole32/storage32.h b/dll/win32/ole32/storage32.h index 03328b29708..fad5d7766f7 100644 --- a/dll/win32/ole32/storage32.h +++ b/dll/win32/ole32/storage32.h @@ -79,6 +79,11 @@ static const ULONG DIRENTRY_NULL = 0xFFFFFFFF; #define RAW_DIRENTRY_SIZE 0x00000080 +#define HEADER_SIZE 512 + +#define MIN_BIG_BLOCK_SIZE 0x200 +#define MAX_BIG_BLOCK_SIZE 0x1000 + /* * Type of child entry link */ @@ -91,15 +96,8 @@ static const ULONG DIRENTRY_NULL = 0xFFFFFFFF; */ #define STGTY_ROOT 0x05 -/* - * These defines assume a hardcoded blocksize. The code will assert - * if the blocksize is different. Some changes will have to be done if it - * becomes the case. - */ -#define BIG_BLOCK_SIZE 0x200 #define COUNT_BBDEPOTINHEADER 109 #define LIMIT_TO_USE_SMALL_BLOCK 0x1000 -#define NUM_BLOCKS_PER_DEPOT_BLOCK 128 #define STGM_ACCESS_MODE(stgm) ((stgm)&0x0000f) #define STGM_SHARE_MODE(stgm) ((stgm)&0x000f0) @@ -163,10 +161,9 @@ typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE; BigBlockFile* BIGBLOCKFILE_Construct(HANDLE hFile, ILockBytes* pLkByt, DWORD openFlags, - ULONG blocksize, BOOL fileBased); void BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This); -HRESULT BIGBLOCKFILE_EnsureExists(LPBIGBLOCKFILE This, ULONG index); +HRESULT BIGBLOCKFILE_Expand(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); HRESULT BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); HRESULT BIGBLOCKFILE_ReadAt(LPBIGBLOCKFILE This, ULARGE_INTEGER offset, void* buffer, ULONG size, ULONG* bytesRead); @@ -359,7 +356,7 @@ struct StorageImpl ULONG extBigBlockDepotCount; ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER]; - ULONG blockDepotCached[NUM_BLOCKS_PER_DEPOT_BLOCK]; + ULONG blockDepotCached[MAX_BIG_BLOCK_SIZE / 4]; ULONG indexBlockDepotCached; ULONG prevFreeBlock; diff --git a/dll/win32/oleaut32/typelib.c b/dll/win32/oleaut32/typelib.c index 445eac5c51e..b09f7ab64d1 100644 --- a/dll/win32/oleaut32/typelib.c +++ b/dll/win32/oleaut32/typelib.c @@ -4722,6 +4722,7 @@ static HRESULT WINAPI ITypeLibComp_fnBind( { ITypeLibImpl *This = impl_from_ITypeComp(iface); ITypeInfoImpl *pTypeInfo; + int typemismatch=0; TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); @@ -4761,6 +4762,8 @@ static HRESULT WINAPI ITypeLibComp_fnBind( TRACE("found in module or in enum: %s\n", debugstr_w(szName)); return S_OK; } + else if (hr == TYPE_E_TYPEMISMATCH) + typemismatch = 1; } if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) && @@ -4833,11 +4836,21 @@ static HRESULT WINAPI ITypeLibComp_fnBind( ITypeInfo_AddRef(*ppTInfo); return S_OK; } + else if (hr == TYPE_E_TYPEMISMATCH) + typemismatch = 1; } } - TRACE("name not found %s\n", debugstr_w(szName)); - return S_OK; + if (typemismatch) + { + TRACE("type mismatch %s\n", debugstr_w(szName)); + return TYPE_E_TYPEMISMATCH; + } + else + { + TRACE("name not found %s\n", debugstr_w(szName)); + return S_OK; + } } static HRESULT WINAPI ITypeLibComp_fnBindType( @@ -5568,6 +5581,11 @@ static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface, return S_OK; } *pImplTypeFlags=0; + + if(This->TypeAttr.typekind==TKIND_DISPATCH && !index) + return S_OK; + + WARN("ImplType %d not found\n", index); return TYPE_E_ELEMENTNOTFOUND; } @@ -6052,9 +6070,6 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( hres = DISP_E_PARAMNOTFOUND; goto func_fail; } - /* ignore the DISPID_PROPERTYPUT named argument from now on */ - cNamedArgs--; - rgdispidNamedArgs++; } if (func_desc->cParamsOpt < 0 && cNamedArgs) @@ -6092,7 +6107,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( USHORT j; src_arg = NULL; for (j = 0; j < cNamedArgs; j++) - if (rgdispidNamedArgs[j] == i) + if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT)) { src_arg = &pDispParams->rgvarg[j]; break; @@ -6859,7 +6874,8 @@ static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - FIXME("(%p) stub!\n", This); + FIXME("(%p %d) stub!\n", This, memid); + *pBstrMops = NULL; return S_OK; } diff --git a/dll/win32/oleaut32/typelib2.c b/dll/win32/oleaut32/typelib2.c index 4544317a512..6b1aea062ba 100644 --- a/dll/win32/oleaut32/typelib2.c +++ b/dll/win32/oleaut32/typelib2.c @@ -199,9 +199,11 @@ typedef struct tagICreateTypeInfo2Impl struct tagCyclicList *typedata; /* tail of cyclic list */ + TYPEKIND typekind; int datawidth; struct tagICreateTypeInfo2Impl *next_typeinfo; + struct tagICreateTypeInfo2Impl *dual; } ICreateTypeInfo2Impl; static inline ICreateTypeInfo2Impl *impl_from_ITypeInfo2( ITypeInfo2 *iface ) @@ -1177,6 +1179,7 @@ static HRESULT ctl2_add_default_value( { VARIANT v; HRESULT hres; + int mask = 0; TRACE("%p %d %d\n", This, V_VT(value), arg_type); @@ -1194,7 +1197,6 @@ static HRESULT ctl2_add_default_value( /* Check if default value can be stored in encoded_value */ switch(arg_type) { - int mask = 0; case VT_I4: case VT_UI4: mask = 0x3ffffff; @@ -1313,7 +1315,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface( if(*ppvObject) { - ICreateTypeLib2_AddRef(iface); + ICreateTypeInfo2_AddRef(iface); TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); return S_OK; } @@ -1333,6 +1335,9 @@ static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface) TRACE("(%p)->ref was %u\n",This, ref - 1); + if(ref==1 && This->typelib) + ICreateTypeLib2_AddRef((ICreateTypeLib2 *)This->typelib); + return ref; } @@ -1406,43 +1411,63 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, U TRACE("(%p,0x%x)\n", iface, uTypeFlags); - This->typeinfo->flags = uTypeFlags; + if(uTypeFlags & TYPEFLAG_FDUAL) { + This->typeinfo->typekind |= 0x10; + This->typeinfo->typekind &= ~0x0f; + This->typeinfo->typekind |= TKIND_DISPATCH; - if (uTypeFlags & TYPEFLAG_FDISPATCHABLE) { - MSFT_GuidEntry foo; - int guidoffset; - int fileoffset; - MSFT_ImpInfo impinfo; - static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 }; + if(!This->dual) { + This->dual = HeapAlloc(GetProcessHeap(), 0, sizeof(ICreateTypeInfo2Impl)); + if(!This->dual) + return E_OUTOFMEMORY; - foo.guid = IID_StdOle; - foo.hreftype = 2; - foo.next_hash = -1; - guidoffset = ctl2_alloc_guid(This->typelib, &foo); - if (guidoffset == -1) return E_OUTOFMEMORY; + memcpy(This->dual, This, sizeof(ICreateTypeInfo2Impl)); + This->dual->ref = 0; + This->dual->typekind = This->typekind==TKIND_DISPATCH ? + TKIND_INTERFACE : TKIND_DISPATCH; + This->dual->dual = This; + } - fileoffset = ctl2_alloc_importfile(This->typelib, guidoffset, - This->typelib->typelib_header.lcid2, 2, 0, stdole2tlb); - if (fileoffset == -1) return E_OUTOFMEMORY; + /* Make sure dispatch is in typeinfos queue */ + if(This->typekind != TKIND_DISPATCH) { + if(This->typelib->last_typeinfo == This) + This->typelib->last_typeinfo = This->dual; - foo.guid = IID_IDispatch; - foo.hreftype = 1; - foo.next_hash = -1; - guidoffset = ctl2_alloc_guid(This->typelib, &foo); - if (guidoffset == -1) return E_OUTOFMEMORY; + if(This->typelib->typeinfos == This) + This->typelib->typeinfos = This->dual; + else { + ICreateTypeInfo2Impl *iter; - impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID; - impinfo.oImpFile = fileoffset; - impinfo.oGuid = guidoffset; - ctl2_alloc_importinfo(This->typelib, &impinfo); - - This->typelib->typelib_header.dispatchpos = 1; - - This->typeinfo->typekind |= 0x10; - This->typeinfo->typekind &= ~0x0f; - This->typeinfo->typekind |= TKIND_DISPATCH; + for(iter=This->typelib->typeinfos; iter->next_typeinfo!=This; iter=iter->next_typeinfo); + iter->next_typeinfo = This->dual; + } + } else + iface = (ICreateTypeInfo2*)&This->dual->lpVtbl; } + if (uTypeFlags & (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL)) { + static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 }; + ITypeLib *stdole; + ITypeInfo *dispatch; + HREFTYPE hreftype; + HRESULT hres; + + hres = LoadTypeLib(stdole2tlb, &stdole); + if(FAILED(hres)) + return hres; + + hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch); + ITypeLib_Release(stdole); + if(FAILED(hres)) + return hres; + + hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype); + ITypeInfo_Release(dispatch); + if(FAILED(hres)) + return hres; + } + + This->typeinfo->flags = uTypeFlags; return S_OK; } @@ -1541,25 +1566,21 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo( /* Process locally defined TypeInfo */ *phRefType = This->typelib->typelib_typeinfo_offsets[index]; } else { - static const WCHAR regkey[] = {'T','y','p','e','L','i','b','\\','{', - '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%', - '0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x', - '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x', - '}','\\','%','d','.','%','d','\\','0','\\','w','i','n','3','2',0}; - - WCHAR name[MAX_PATH], *p; + BSTR name; TLIBATTR *tlibattr; TYPEATTR *typeattr; + TYPEKIND typekind; MSFT_GuidEntry guid, *check_guid; MSFT_ImpInfo impinfo; int guid_offset, import_offset; - DWORD len; HRESULT hres; /* Allocate container GUID */ hres = ITypeLib_GetLibAttr(container, &tlibattr); - if(FAILED(hres)) + if(FAILED(hres)) { + ITypeLib_Release(container); return hres; + } guid.guid = tlibattr->guid; guid.hreftype = This->typelib->typelib_guids*12+2; @@ -1568,6 +1589,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo( guid_offset = ctl2_alloc_guid(This->typelib, &guid); if(guid_offset == -1) { ITypeLib_ReleaseTLibAttr(container, tlibattr); + ITypeLib_Release(container); return E_OUTOFMEMORY; } @@ -1576,50 +1598,50 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo( This->typelib->typelib_guids++; /* Get import file name */ - /* Check HKEY_CLASSES_ROOT\TypeLib\{GUID}\{Ver}\0\win32 */ - len = MAX_PATH; - sprintfW(name, regkey, guid.guid.Data1, guid.guid.Data2, - guid.guid.Data3, guid.guid.Data4[0], guid.guid.Data4[1], - guid.guid.Data4[2], guid.guid.Data4[3], guid.guid.Data4[4], - guid.guid.Data4[5], guid.guid.Data4[6], guid.guid.Data4[7], - tlibattr->wMajorVerNum, tlibattr->wMinorVerNum); - - if(RegGetValueW(HKEY_CLASSES_ROOT, name, NULL, RRF_RT_REG_SZ, NULL, name, &len)!=ERROR_SUCCESS - || (p=strrchrW(name, '\\'))==NULL) { - ERR("Error guessing typelib filename\n"); + hres = QueryPathOfRegTypeLib(&guid.guid, tlibattr->wMajorVerNum, + tlibattr->wMinorVerNum, tlibattr->lcid, &name); + if(FAILED(hres)) { ITypeLib_ReleaseTLibAttr(container, tlibattr); - return E_NOTIMPL; + ITypeLib_Release(container); + return hres; } - memmove(name, p+1, strlenW(p)*sizeof(WCHAR)); /* Import file */ - import_offset = ctl2_alloc_importfile(This->typelib, guid_offset, - tlibattr->lcid, tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, name); + import_offset = ctl2_alloc_importfile(This->typelib, guid_offset, tlibattr->lcid, + tlibattr->wMajorVerNum, tlibattr->wMinorVerNum, strrchrW(name, '\\')+1); ITypeLib_ReleaseTLibAttr(container, tlibattr); + SysFreeString(name); - if(import_offset == -1) + if(import_offset == -1) { + ITypeLib_Release(container); return E_OUTOFMEMORY; + } /* Allocate referenced guid */ hres = ITypeInfo_GetTypeAttr(pTInfo, &typeattr); - if(FAILED(hres)) + if(FAILED(hres)) { + ITypeLib_Release(container); return hres; + } guid.guid = typeattr->guid; guid.hreftype = This->typelib->typeinfo_guids*12+1; guid.next_hash = -1; + typekind = typeattr->typekind; ITypeInfo_ReleaseTypeAttr(pTInfo, typeattr); guid_offset = ctl2_alloc_guid(This->typelib, &guid); - if(guid_offset == -1) + if(guid_offset == -1) { + ITypeLib_Release(container); return E_OUTOFMEMORY; + } check_guid = (MSFT_GuidEntry*)&This->typelib->typelib_segment_data[MSFT_SEG_GUID][guid_offset]; if(check_guid->hreftype == guid.hreftype) This->typelib->typeinfo_guids++; /* Allocate importinfo */ - impinfo.flags = ((This->typeinfo->typekind&0xf)<<24) | MSFT_IMPINFO_OFFSET_IS_GUID; + impinfo.flags = (typekind<<24) | MSFT_IMPINFO_OFFSET_IS_GUID; impinfo.oImpFile = import_offset; impinfo.oGuid = guid_offset; *phRefType = ctl2_alloc_importinfo(This->typelib, &impinfo)+1; @@ -1652,7 +1674,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc( TRACE("(%p,%d,%p)\n", iface, index, pFuncDesc); - if(!pFuncDesc || (pFuncDesc->memid>0x7fffffff && pFuncDesc->memid!=MEMBERID_NIL)) + if(!pFuncDesc || pFuncDesc->oVft&3) return E_INVALIDARG; TRACE("{%d,%p,%p,%d,%d,%d,%d,%d,%d,%d,{%d},%d}\n", pFuncDesc->memid, @@ -1661,7 +1683,10 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc( pFuncDesc->cParamsOpt, pFuncDesc->oVft, pFuncDesc->cScodes, pFuncDesc->elemdescFunc.tdesc.vt, pFuncDesc->wFuncFlags); - switch(This->typeinfo->typekind&0xf) { + if(pFuncDesc->cParamsOpt || pFuncDesc->cScodes) + FIXME("Unimplemented parameter - created typelib will be incorrect\n"); + + switch(This->typekind) { case TKIND_MODULE: if(pFuncDesc->funckind != FUNC_STATIC) return TYPE_E_BADMODULEKIND; @@ -1688,12 +1713,15 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc( num_defaults++; if (!This->typedata) { - This->typedata = HeapAlloc(GetProcessHeap(), 0, sizeof(CyclicList)); + This->typedata = HeapAlloc(GetProcessHeap(), 0, sizeof(CyclicList)); if(!This->typedata) return E_OUTOFMEMORY; This->typedata->next = This->typedata; - This->typedata->u.val = 0; + This->typedata->u.val = 0; + + if(This->dual) + This->dual->typedata = This->typedata; } /* allocate type data space for us */ @@ -1711,7 +1739,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc( typedata[0] = 0x18 + pFuncDesc->cParams*(num_defaults?16:12); ctl2_encode_typedesc(This->typelib, &pFuncDesc->elemdescFunc.tdesc, &typedata[1], NULL, NULL, &decoded_size); typedata[2] = pFuncDesc->wFuncFlags; - typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | This->typeinfo->cbSizeVft; + typedata[3] = ((sizeof(FUNCDESC) + decoded_size) << 16) | (unsigned short)(pFuncDesc->oVft?pFuncDesc->oVft+1:0); typedata[4] = (pFuncDesc->callconv << 8) | (pFuncDesc->invkind << 3) | pFuncDesc->funckind; if(num_defaults) typedata[4] |= 0x1000; typedata[5] = pFuncDesc->cParams; @@ -1758,6 +1786,9 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc( insert->next = This->typedata->next; This->typedata->next = insert; This->typedata = insert; + + if(This->dual) + This->dual->typedata = This->typedata; } else { iter = This->typedata->next; for(i=0; itypeinfo->typekind & 15) == TKIND_COCLASS) { + if (This->typekind == TKIND_COCLASS) { int offset; MSFT_RefRecord *ref; @@ -1822,21 +1853,26 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType( ref->flags = 0; ref->oCustData = -1; ref->onext = -1; - } else if ((This->typeinfo->typekind & 15) == TKIND_DISPATCH) { - FIXME("dispatch case unhandled.\n"); - } else if ((This->typeinfo->typekind & 15) == TKIND_INTERFACE) { + This->typeinfo->cImplTypes++; + } else if (This->typekind == TKIND_INTERFACE) { if (This->typeinfo->cImplTypes && index==1) return TYPE_E_BADMODULEKIND; if( index != 0) return TYPE_E_ELEMENTNOTFOUND; This->typeinfo->datatype1 = hRefType; + This->typeinfo->cImplTypes = 1; + } else if (This->typekind == TKIND_DISPATCH) { + if(index != 0) return TYPE_E_ELEMENTNOTFOUND; + + /* FIXME: Check if referenced typeinfo is IDispatch */ + This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE; + This->typeinfo->cImplTypes = 1; } else { - FIXME("AddImplType unsupported on typekind %d\n", This->typeinfo->typekind & 15); + FIXME("AddImplType unsupported on typekind %d\n", This->typekind); return E_OUTOFMEMORY; } - This->typeinfo->cImplTypes++; return S_OK; } @@ -1856,7 +1892,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags( TRACE("(%p,%d,0x%x)\n", iface, index, implTypeFlags); - if ((This->typeinfo->typekind & 15) != TKIND_COCLASS) { + if (This->typekind != TKIND_COCLASS) { return TYPE_E_BADMODULEKIND; } @@ -1889,7 +1925,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment( This->typeinfo->typekind |= cbAlignment << 6; /* FIXME: There's probably some way to simplify this. */ - switch (This->typeinfo->typekind & 15) { + switch (This->typekind) { case TKIND_ALIAS: default: break; @@ -1963,6 +1999,9 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc( This->typedata->next = This->typedata; This->typedata->u.val = 0; + + if(This->dual) + This->dual->typedata = This->typedata; } /* allocate type data space for us */ @@ -1979,6 +2018,9 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc( This->typedata->next = insert; This->typedata = insert; + if(This->dual) + This->dual->typedata = This->typedata; + This->typedata->next->u.val += 0x14; typedata = This->typedata->u.data; @@ -2003,6 +2045,8 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc( /* add the new variable to the total data width */ This->datawidth += var_datawidth; + if(This->dual) + This->dual->datawidth = This->datawidth; /* add type description size to total required allocation */ typedata[3] += var_type_size << 16; @@ -2125,7 +2169,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName( *((INT *)namedata) = This->typelib->typelib_typeinfo_offsets[This->typeinfo->typekind >> 16]; namedata[9] |= 0x10; } - if ((This->typeinfo->typekind & 15) == TKIND_ENUM) { + if (This->typekind == TKIND_ENUM) { namedata[9] |= 0x20; } @@ -2151,7 +2195,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias( int encoded_typedesc; int width; - if ((This->typeinfo->typekind & 15) != TKIND_ALIAS) { + if (This->typekind != TKIND_ALIAS) { return TYPE_E_WRONGTYPEKIND; } @@ -2225,8 +2269,42 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext( UINT index, DWORD dwHelpContext) { - FIXME("(%p,%d,%d), stub!\n", iface, index, dwHelpContext); - return E_OUTOFMEMORY; + ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface; + CyclicList *func; + int *typedata; + int size; + + TRACE("(%p,%d,%d)\n", iface, index, dwHelpContext); + + if(This->typeinfo->cElementtypeinfo->cElement == index) + func = This->typedata; + else + for(func=This->typedata->next->next; func!=This->typedata; func=func->next) + if(index-- == 0) + break; + + typedata = func->u.data; + + /* Compute func size without arguments */ + size = typedata[0] - typedata[5]*(typedata[4]&0x1000?16:12); + + /* Allocate memory for HelpContext if needed */ + if(size < 7*sizeof(int)) { + typedata = HeapReAlloc(GetProcessHeap(), 0, typedata, typedata[0]+sizeof(int)); + if(!typedata) + return E_OUTOFMEMORY; + + memmove(&typedata[7], &typedata[6], typedata[0]-sizeof(int)*6); + typedata[0] += sizeof(int); + This->typedata->next->u.val += sizeof(int); + func->u.data = typedata; + } + + typedata[6] = dwHelpContext; + return S_OK; } /****************************************************************************** @@ -2282,11 +2360,13 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( CyclicList *iter, *iter2, **typedata; HREFTYPE hreftype; HRESULT hres; + unsigned user_vft = 0; int i; TRACE("(%p)\n", iface); - if((This->typeinfo->typekind&0xf) == TKIND_COCLASS) + /* FIXME: LayOut should be run on all ImplTypes */ + if(This->typekind == TKIND_COCLASS) return S_OK; /* Validate inheritance */ @@ -2317,15 +2397,17 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( return hres; hres = ITypeInfo_GetRefTypeInfo(next, hreftype, &cur); + ITypeInfo_Release(next); if(FAILED(hres)) return hres; - ITypeInfo_Release(next); while(1) { hres = ITypeInfo_GetTypeAttr(cur, &typeattr); - if(FAILED(hres)) + if(FAILED(hres)) { + ITypeInfo_Release(cur); return hres; + } if(!memcmp(&typeattr->guid, &IID_IDispatch, sizeof(IDispatch))) This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE; @@ -2336,19 +2418,51 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( hres = ITypeInfo_GetRefTypeOfImplType(cur, 0, &hreftype); if(hres == TYPE_E_ELEMENTNOTFOUND) break; - if(FAILED(hres)) + if(FAILED(hres)) { + ITypeInfo_Release(cur); return hres; + } hres = ITypeInfo_GetRefTypeInfo(cur, hreftype, &next); - if(FAILED(hres)) + if(FAILED(hres)) { + ITypeInfo_Release(cur); return hres; + } ITypeInfo_Release(cur); cur = next; } + ITypeInfo_Release(cur); } - This->typeinfo->cbSizeVft = (This->typeinfo->datatype2>>16) * 4; + /* Get cbSizeVft of inherited interface */ + /* Makes LayOut running recursively */ + if(This->typeinfo->datatype1 != -1) { + ITypeInfo *cur, *inherited; + TYPEATTR *typeattr; + + hres = ICreateTypeInfo_QueryInterface(iface, &IID_ITypeInfo, (void**)&cur); + if(FAILED(hres)) + return hres; + + hres = ITypeInfo_GetRefTypeInfo(cur, This->typeinfo->datatype1, &inherited); + ITypeInfo_Release(cur); + if(FAILED(hres)) + return hres; + + hres = ITypeInfo_GetTypeAttr(inherited, &typeattr); + if(FAILED(hres)) { + ITypeInfo_Release(inherited); + return hres; + } + + This->typeinfo->cbSizeVft = typeattr->cbSizeVft; + + ITypeInfo_ReleaseTypeAttr(inherited, typeattr); + ITypeInfo_Release(inherited); + } else + This->typeinfo->cbSizeVft = 0; + if(!This->typedata) return S_OK; @@ -2358,6 +2472,9 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( /* Assign IDs and VTBL entries */ i = 0; + if(This->typedata->u.data[3]&1) + user_vft = This->typedata->u.data[3]&0xffff; + for(iter=This->typedata->next->next; iter!=This->typedata->next; iter=iter->next) { /* Assign MEMBERID if MEMBERID_NIL was specified */ if(iter->indice == MEMBERID_NIL) { @@ -2370,8 +2487,10 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( for(iter2=This->typedata->next->next; iter2!=This->typedata->next; iter2=iter2->next) { if(iter == iter2) continue; - if(iter2->indice == iter->indice) + if(iter2->indice == iter->indice) { + HeapFree(GetProcessHeap(), 0, typedata); return E_ACCESSDENIED; + } } break; @@ -2383,7 +2502,20 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( iter->u.data[0] = (iter->u.data[0]&0xffff) | (i<<16); - if((This->typeinfo->typekind&0xf) != TKIND_MODULE) { + if((iter->u.data[3]&1) != (user_vft&1)) { + HeapFree(GetProcessHeap(), 0, typedata); + return TYPE_E_INVALIDID; + } + + if(user_vft&1) { + if(user_vft < (iter->u.data[3]&0xffff)) + user_vft = (iter->u.data[3]&0xffff); + + if((iter->u.data[3]&0xffff) < This->typeinfo->cbSizeVft) { + HeapFree(GetProcessHeap(), 0, typedata); + return TYPE_E_INVALIDID; + } + } else if(This->typekind != TKIND_MODULE) { iter->u.data[3] = (iter->u.data[3]&0xffff0000) | This->typeinfo->cbSizeVft; This->typeinfo->cbSizeVft += 4; } @@ -2406,6 +2538,9 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut( i++; } + if(user_vft) + This->typeinfo->cbSizeVft = user_vft+3; + for(i=0; i<(This->typeinfo->cElement&0xffff); i++) { if(typedata[i]->u.data[4]>>16 > i) { int inv; @@ -2787,11 +2922,13 @@ static HRESULT WINAPI ITypeInfo2_fnGetTypeAttr( (*ppTypeAttr)->lcid = This->typelib->typelib_header.lcid; (*ppTypeAttr)->cbSizeInstance = This->typeinfo->size; - (*ppTypeAttr)->typekind = This->typeinfo->typekind&0xf; + (*ppTypeAttr)->typekind = This->typekind; (*ppTypeAttr)->cFuncs = This->typeinfo->cElement&0xffff; + if(This->typeinfo->flags&TYPEFLAG_FDUAL && This->typekind==TKIND_DISPATCH) + (*ppTypeAttr)->cFuncs += 7; (*ppTypeAttr)->cVars = This->typeinfo->cElement>>16; (*ppTypeAttr)->cImplTypes = This->typeinfo->cImplTypes; - (*ppTypeAttr)->cbSizeVft = This->typeinfo->cbSizeVft; + (*ppTypeAttr)->cbSizeVft = This->typekind==TKIND_DISPATCH ? 28 : This->typeinfo->cbSizeVft; (*ppTypeAttr)->cbAlignment = (This->typeinfo->typekind>>11) & 0x1f; (*ppTypeAttr)->wTypeFlags = This->typeinfo->flags; (*ppTypeAttr)->wMajorVerNum = This->typeinfo->version&0xffff; @@ -2879,15 +3016,21 @@ static HRESULT WINAPI ITypeInfo2_fnGetRefTypeOfImplType( if(!pRefType) return E_INVALIDARG; - if(index == -1) { - FIXME("Dual interfaces not handled yet\n"); - return E_NOTIMPL; + if(This->typeinfo->flags&TYPEFLAG_FDUAL) { + if(index == -1) { + *pRefType = -2; + return S_OK; + } + + if(This->typekind == TKIND_DISPATCH) + return ITypeInfo2_GetRefTypeOfImplType((ITypeInfo2*)&This->dual->lpVtblTypeInfo2, + index, pRefType); } - if(index >= This->typeinfo->cImplTypes) + if(index>=This->typeinfo->cImplTypes) return TYPE_E_ELEMENTNOTFOUND; - if((This->typeinfo->typekind&0xf) == TKIND_INTERFACE) { + if(This->typekind == TKIND_INTERFACE) { *pRefType = This->typeinfo->datatype1 + 2; return S_OK; } @@ -2923,7 +3066,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetImplTypeFlags( if(index >= This->typeinfo->cImplTypes) return TYPE_E_ELEMENTNOTFOUND; - if((This->typeinfo->typekind&0xf) != TKIND_COCLASS) { + if(This->typekind != TKIND_COCLASS) { *pImplTypeFlags = 0; return S_OK; } @@ -3022,6 +3165,12 @@ static HRESULT WINAPI ITypeInfo2_fnGetRefTypeInfo( if(!ppTInfo) return E_INVALIDARG; + if(hRefType==-2 && This->dual) { + *ppTInfo = (ITypeInfo*)&This->dual->lpVtblTypeInfo2; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + if(hRefType&1) { ITypeLib *tl; MSFT_ImpInfo *impinfo; @@ -3124,7 +3273,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetContainingTypeLib( TRACE("(%p,%p,%p)\n", iface, ppTLib, pIndex); *ppTLib = (ITypeLib *)&This->typelib->lpVtblTypeLib2; - This->typelib->ref++; + ICreateTypeLib_AddRef((ICreateTypeLib*)This->typelib); *pIndex = This->typeinfo->typekind >> 16; return S_OK; @@ -3573,7 +3722,7 @@ static ICreateTypeInfo2 *ICreateTypeInfo2_Constructor(ICreateTypeLib2Impl *typel pCreateTypeInfo2Impl->ref = 1; pCreateTypeInfo2Impl->typelib = typelib; - typelib->ref++; + ICreateTypeLib_AddRef((ICreateTypeLib*)typelib); nameoffset = ctl2_alloc_name(typelib, szName); typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset); @@ -3584,6 +3733,7 @@ static ICreateTypeInfo2 *ICreateTypeInfo2_Constructor(ICreateTypeLib2Impl *typel pCreateTypeInfo2Impl->typeinfo = typeinfo; + pCreateTypeInfo2Impl->typekind = tkind; typeinfo->typekind |= tkind | 0x20; ICreateTypeInfo2_SetAlignment((ICreateTypeInfo2 *)pCreateTypeInfo2Impl, 4); @@ -3717,7 +3867,9 @@ static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface) HeapFree(GetProcessHeap(), 0, rem); } } - HeapFree(GetProcessHeap(), 0, typeinfo); + + HeapFree(GetProcessHeap(), 0, typeinfo->dual); + HeapFree(GetProcessHeap(), 0, typeinfo); } HeapFree(GetProcessHeap(),0,This); diff --git a/dll/win32/oledlg/oledlg_De.rc b/dll/win32/oledlg/oledlg_De.rc index 498fa80196b..9aad9ba52f8 100644 --- a/dll/win32/oledlg/oledlg_De.rc +++ b/dll/win32/oledlg/oledlg_De.rc @@ -97,4 +97,3 @@ STRINGTABLE DISCARDABLE IDS_PS_UNKNOWN_SRC "Unbekannte Quelle" IDS_PS_UNKNOWN_APP "dem Erzeugerprogramm" } -#pragma code_page(default) diff --git a/dll/win32/oledlg/oledlg_Fr.rc b/dll/win32/oledlg/oledlg_Fr.rc index 5a64ab09b88..176cc87f70f 100644 --- a/dll/win32/oledlg/oledlg_Fr.rc +++ b/dll/win32/oledlg/oledlg_Fr.rc @@ -102,4 +102,3 @@ STRINGTABLE DISCARDABLE IDS_PS_UNKNOWN_SRC "Source inconnue" IDS_PS_UNKNOWN_APP "le programme avec lequel il a été créé" } -#pragma code_page(default) diff --git a/dll/win32/oledlg/oledlg_Ja.rc b/dll/win32/oledlg/oledlg_Ja.rc index e6680dd7f21..0029ff35f11 100644 --- a/dll/win32/oledlg/oledlg_Ja.rc +++ b/dll/win32/oledlg/oledlg_Ja.rc @@ -58,4 +58,3 @@ STRINGTABLE DISCARDABLE IDS_NOTOLEMOD "ファイルは有効なOLEモジュールではないようです。OLEコントロールを登録できません。" IDS_NOTOLEMODCAPTION "コントロールを追加" } -#pragma code_page(default) diff --git a/dll/win32/oledlg/oledlg_Lt.rc b/dll/win32/oledlg/oledlg_Lt.rc index 02451c470cf..961fd1d996f 100644 --- a/dll/win32/oledlg/oledlg_Lt.rc +++ b/dll/win32/oledlg/oledlg_Lt.rc @@ -98,4 +98,3 @@ STRINGTABLE DISCARDABLE IDS_PS_UNKNOWN_SRC "Nežinomas šaltinis" IDS_PS_UNKNOWN_APP "programa, kuri jį sukūrė" } -#pragma code_page(default) diff --git a/dll/win32/oledlg/oledlg_Si.rc b/dll/win32/oledlg/oledlg_Si.rc index 55af95ec373..0f737af2d61 100644 --- a/dll/win32/oledlg/oledlg_Si.rc +++ b/dll/win32/oledlg/oledlg_Si.rc @@ -97,4 +97,3 @@ STRINGTABLE DISCARDABLE IDS_PS_UNKNOWN_SRC "Neznan vir" IDS_PS_UNKNOWN_APP "Neznan program" } -#pragma code_page(default) diff --git a/dll/win32/riched20/caret.c b/dll/win32/riched20/caret.c index 1cb44bcdbcd..a72a42b0937 100644 --- a/dll/win32/riched20/caret.c +++ b/dll/win32/riched20/caret.c @@ -24,27 +24,55 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -static BOOL -ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs); - -void ME_GetSelection(ME_TextEditor *editor, int *from, int *to) +void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor) { - *from = ME_GetCursorOfs(editor, 0); - *to = ME_GetCursorOfs(editor, 1); - + cursor->pPara = editor->pBuffer->pFirst->member.para.next_para; + cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun); + cursor->nOffset = 0; +} + +static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor) +{ + cursor->pPara = editor->pBuffer->pLast->member.para.prev_para; + cursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); + cursor->nOffset = 0; +} + + +int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to) +{ + *from = ME_GetCursorOfs(&editor->pCursors[0]); + *to = ME_GetCursorOfs(&editor->pCursors[1]); + if (*from > *to) { int tmp = *from; *from = *to; - *to = tmp; + *to = tmp; + return 1; + } + return 0; +} + +int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to) +{ + if (ME_GetCursorOfs(&editor->pCursors[0]) < ME_GetCursorOfs(&editor->pCursors[1])) + { + *from = &editor->pCursors[0]; + *to = &editor->pCursors[1]; + return 0; + } else { + *from = &editor->pCursors[1]; + *to = &editor->pCursors[0]; + return 1; } } int ME_GetTextLength(ME_TextEditor *editor) { - ME_DisplayItem *pLast = editor->pBuffer->pLast; - return ME_CharOfsFromRunOfs(editor, pLast->member.para.prev_para, - ME_FindItemBack(pLast, diRun), 0); + ME_Cursor cursor; + ME_SetCursorToEnd(editor, &cursor); + return ME_GetCursorOfs(&cursor); } @@ -63,8 +91,10 @@ int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) && (how->flags & GTL_USECRLF) && !editor->bEmulateVersion10) /* Ignore GTL_USECRLF flag in 1.0 emulation */ length += editor->nParagraphs - 1; - - if (how->flags & GTL_NUMBYTES) + + if (how->flags & GTL_NUMBYTES || + (how->flags & GTL_PRECISE && /* GTL_PRECISE seems to imply GTL_NUMBYTES */ + !(how->flags & GTL_NUMCHARS))) /* unless GTL_NUMCHARS is given */ { CPINFO cpinfo; @@ -95,12 +125,8 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) /* select all */ if (from == 0 && to == -1) { - editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para; - editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun); - editor->pCursors[1].nOffset = 0; - editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; - editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - editor->pCursors[0].nOffset = 0; + ME_SetCursorToStart(editor, &editor->pCursors[1]); + ME_SetCursorToEnd(editor, &editor->pCursors[0]); ME_InvalidateSelection(editor); ME_ClearTempStyle(editor); return len + 1; @@ -119,7 +145,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) if (from < 0) { int start, end; - ME_GetSelection(editor, &start, &end); + ME_GetSelectionOfs(editor, &start, &end); editor->pCursors[1] = editor->pCursors[0]; ME_Repaint(editor); ME_ClearTempStyle(editor); @@ -148,9 +174,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) if (selectionEnd) { - editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; - editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - editor->pCursors[0].nOffset = 0; + ME_SetCursorToEnd(editor, &editor->pCursors[0]); editor->pCursors[1] = editor->pCursors[0]; ME_InvalidateSelection(editor); ME_ClearTempStyle(editor); @@ -158,7 +182,8 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) } ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]); - ME_CursorFromCharOfs(editor, to, &editor->pCursors[0]); + editor->pCursors[0] = editor->pCursors[1]; + ME_MoveCursorChars(editor, &editor->pCursors[0], to - from); /* Selection is not allowed in the middle of an end paragraph run. */ if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA) editor->pCursors[1].nOffset = 0; @@ -258,23 +283,22 @@ void ME_HideCaret(ME_TextEditor *ed) } } -BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, - BOOL bForce) +BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, + int nChars, BOOL bForce) { - ME_Cursor c; + ME_Cursor c = *start; + int nOfs = ME_GetCursorOfs(start); int shift = 0; int totalChars = nChars; ME_DisplayItem *start_para; /* Prevent deletion past last end of paragraph run. */ nChars = min(nChars, ME_GetTextLength(editor) - nOfs); - - ME_CursorFromCharOfs(editor, nOfs, &c); start_para = c.pPara; if (!bForce) { - ME_ProtectPartialTableDeletion(editor, nOfs, &nChars); + ME_ProtectPartialTableDeletion(editor, &c, &nChars); if (nChars == 0) return FALSE; } @@ -289,8 +313,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, { /* We aren't deleting anything in this run, so we will go back to the * last run we are deleting text in. */ - c.pRun = ME_FindItemBack(c.pRun, diRun); - c.pPara = ME_GetParagraph(c.pRun); + ME_PrevRun(&c.pPara, &c.pRun); c.nOffset = c.pRun->member.run.strText->nLen; } run = &c.pRun->member.run; @@ -422,12 +445,12 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, } BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars) -{ +{ assert(nCursor>=0 && nCursornCursors); /* text operations set modified state */ editor->nModifyStep = 1; - return ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars, - FALSE); + return ME_InternalDeleteText(editor, &editor->pCursors[nCursor], + nChars, FALSE); } static ME_DisplayItem * @@ -459,7 +482,7 @@ void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCur MERF_GRAPHICS); di->member.run.ole_obj = ALLOC_OBJ(*reo); ME_CopyReObject(di->member.run.ole_obj, reo); - ME_SendSelChange(editor); + ME_ReleaseStyle(pStyle); } @@ -475,7 +498,7 @@ void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor) di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, MERF_ENDROW); - ME_SendSelChange(editor); + ME_ReleaseStyle(pStyle); } @@ -565,7 +588,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, /* ME_SplitParagraph increases style refcount */ tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0); p->pRun = ME_FindItemFwd(tp, diRun); - p->pPara = ME_GetParagraph(p->pRun); + p->pPara = tp; end_run = ME_FindItemBack(tp, diRun); ME_ReleaseStyle(end_run->member.run.style); end_run->member.run.style = tmp_style; @@ -577,77 +600,85 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, } } - -static BOOL -ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) +/* Move the cursor nRelOfs characters (either forwards or backwards) + * + * returns the actual number of characters moved. + **/ +int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { - ME_DisplayItem *pRun = pCursor->pRun; - - if (nRelOfs == -1) + cursor->nOffset += nRelOfs; + if (cursor->nOffset < 0) { - if (!pCursor->nOffset) + cursor->nOffset += cursor->pRun->member.run.nCharOfs; + if (cursor->nOffset >= 0) { - ME_DisplayItem *pPara = pCursor->pPara; + /* new offset in the same paragraph */ do { - pRun = ME_FindItemBack(pRun, diRunOrParagraph); - assert(pRun); - switch (pRun->type) - { - case diRun: - break; - case diParagraph: - pPara = pRun; - if (pPara->member.para.prev_para->type == diTextStart) - return FALSE; - pRun = ME_FindItemBack(pPara, diRunOrParagraph); - pPara = pPara->member.para.prev_para; - /* every paragraph ought to have at least one run */ - assert(pRun && pRun->type == diRun); - assert(pRun->member.run.nFlags & MERF_ENDPARA); - break; - default: - assert(pRun->type != diRun && pRun->type != diParagraph); - return FALSE; - } - } while (RUN_IS_HIDDEN(&pRun->member.run) || - pRun->member.run.nFlags & MERF_HIDDEN); - pCursor->pPara = pPara; - pCursor->pRun = pRun; - if (pRun->member.run.nFlags & MERF_ENDPARA) - pCursor->nOffset = 0; - else - pCursor->nOffset = pRun->member.run.strText->nLen; + cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); + } while (cursor->nOffset < cursor->pRun->member.run.nCharOfs); + cursor->nOffset -= cursor->pRun->member.run.nCharOfs; + return nRelOfs; } - if (pCursor->nOffset) - pCursor->nOffset = pCursor->nOffset + nRelOfs; - return TRUE; - } - else - { - if (!(pRun->member.run.nFlags & MERF_ENDPARA)) + cursor->nOffset += cursor->pPara->member.para.nCharOfs; + if (cursor->nOffset <= 0) { - int new_ofs = pCursor->nOffset + nRelOfs; - - if (new_ofs < pRun->member.run.strText->nLen) - { - pCursor->nOffset = new_ofs; - return TRUE; - } + /* moved to the start of the text */ + nRelOfs -= cursor->nOffset; + ME_SetCursorToStart(editor, cursor); + return nRelOfs; } + + /* new offset in a previous paragraph */ do { - pRun = ME_FindItemFwd(pRun, diRun); - } while (pRun && (RUN_IS_HIDDEN(&pRun->member.run) || - pRun->member.run.nFlags & MERF_HIDDEN)); - if (pRun) - { - pCursor->pPara = ME_GetParagraph(pRun); - pCursor->pRun = pRun; - pCursor->nOffset = 0; - return TRUE; + cursor->pPara = cursor->pPara->member.para.prev_para; + } while (cursor->nOffset < cursor->pPara->member.para.nCharOfs); + cursor->nOffset -= cursor->pPara->member.para.nCharOfs; + + cursor->pRun = ME_FindItemBack(cursor->pPara->member.para.next_para, diRun); + while (cursor->nOffset < cursor->pRun->member.run.nCharOfs) { + cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); } - } - return FALSE; + cursor->nOffset -= cursor->pRun->member.run.nCharOfs; + } else if (cursor->nOffset >= cursor->pRun->member.run.strText->nLen) { + ME_DisplayItem *next_para; + int new_offset; + + new_offset = ME_GetCursorOfs(cursor); + next_para = cursor->pPara->member.para.next_para; + if (new_offset < next_para->member.para.nCharOfs) + { + /* new offset in the same paragraph */ + do { + cursor->nOffset -= cursor->pRun->member.run.strText->nLen; + cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); + } while (cursor->nOffset >= cursor->pRun->member.run.strText->nLen); + return nRelOfs; + } + + if (new_offset >= ME_GetTextLength(editor)) + { + /* new offset at the end of the text */ + ME_SetCursorToEnd(editor, cursor); + nRelOfs -= new_offset - ME_GetTextLength(editor); + return nRelOfs; + } + + /* new offset in a following paragraph */ + do { + cursor->pPara = next_para; + next_para = next_para->member.para.next_para; + } while (new_offset >= next_para->member.para.nCharOfs); + + cursor->nOffset = new_offset - cursor->pPara->member.para.nCharOfs; + cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun); + while (cursor->nOffset >= cursor->pRun->member.run.strText->nLen) + { + cursor->nOffset -= cursor->pRun->member.run.strText->nLen; + cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); + } + } /* else new offset is in the same run */ + return nRelOfs; } @@ -655,8 +686,9 @@ static BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { ME_DisplayItem *pRun = cursor->pRun, *pOtherRun; + ME_DisplayItem *pPara = cursor->pPara; int nOffset = cursor->nOffset; - + if (nRelOfs == -1) { /* Backward movement */ @@ -684,14 +716,16 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { if (cursor->pRun == pRun && cursor->nOffset == 0) { + pPara = pOtherRun; /* Skip empty start of table row paragraph */ - if (pOtherRun->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) - pOtherRun = pOtherRun->member.para.prev_para; + if (pPara->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) + pPara = pPara->member.para.prev_para; /* Paragraph breaks are treated as separate words */ - if (pOtherRun->member.para.prev_para->type == diTextStart) + if (pPara->member.para.prev_para->type == diTextStart) return FALSE; - pRun = ME_FindItemBack(pOtherRun, diRun); + pRun = ME_FindItemBack(pPara, diRun); + pPara = pPara->member.para.prev_para; } break; } @@ -723,8 +757,10 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { if (pOtherRun->member.para.nFlags & MEPF_ROWSTART) pOtherRun = pOtherRun->member.para.next_para; - if (cursor->pRun == pRun) - pRun = ME_FindItemFwd(pOtherRun, diRun); + if (cursor->pRun == pRun) { + pPara = pOtherRun; + pRun = ME_FindItemFwd(pPara, diRun); + } nOffset = 0; break; } @@ -737,7 +773,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) } } } - cursor->pPara = ME_GetParagraph(pRun); + cursor->pPara = pPara; cursor->pRun = pRun; cursor->nOffset = nOffset; return TRUE; @@ -793,12 +829,8 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) case stDocument: /* Select everything with cursor anchored from the start of the text */ editor->nSelectionType = stDocument; - editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para; - editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun); - editor->pCursors[1].nOffset = 0; - editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; - editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - editor->pCursors[0].nOffset = 0; + ME_SetCursorToStart(editor, &editor->pCursors[1]); + ME_SetCursorToEnd(editor, &editor->pCursors[0]); break; default: assert(0); } @@ -807,11 +839,10 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) editor->pCursors[3] = editor->pCursors[1]; } -int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor) +int ME_GetCursorOfs(const ME_Cursor *cursor) { - ME_Cursor *pCursor = &editor->pCursors[nCursor]; - return pCursor->pPara->member.para.nCharOfs - + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset; + return cursor->pPara->member.para.nCharOfs + + cursor->pRun->member.run.nCharOfs + cursor->nOffset; } /* Helper function for ME_FindPixelPos to find paragraph within tables */ @@ -862,9 +893,9 @@ static BOOL ME_ReturnFoundPos(ME_TextEditor *editor, ME_DisplayItem *found, rx = 0; result->pRun = found; result->nOffset = ME_CharFromPointCursor(editor, rx, &found->member.run); - if (editor->pCursors[0].nOffset == found->member.run.strText->nLen && rx) + if (result->nOffset == found->member.run.strText->nLen && rx) { - result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun); + result->pRun = ME_FindItemFwd(result->pRun, diRun); result->nOffset = 0; } result->pPara = ME_GetParagraph(result->pRun); @@ -975,30 +1006,32 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, } -/* Returns the character offset closest to the pixel position +/* Sets the cursor to the position closest to the pixel position * * x & y are pixel positions in client coordinates. * * isExact will be set to TRUE if the run is directly under the pixel * position, FALSE if it not, unless isExact is set to NULL. + * + * return FALSE if outside client area and the cursor is not set, + * otherwise TRUE is returned. */ -int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact) +BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y, + ME_Cursor *cursor, BOOL *isExact) { - ME_Cursor cursor; RECT rc; BOOL bResult; ITextHost_TxGetClientRect(editor->texthost, &rc); if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom) { if (isExact) *isExact = FALSE; - return -1; + return FALSE; } x += editor->horz_si.nPos; y += editor->vert_si.nPos; - bResult = ME_FindPixelPos(editor, x, y, &cursor, NULL); + bResult = ME_FindPixelPos(editor, x, y, cursor, NULL); if (isExact) *isExact = bResult; - return cursor.pPara->member.para.nCharOfs - + cursor.pRun->member.run.nCharOfs + cursor.nOffset; + return TRUE; } @@ -1019,9 +1052,9 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) int curOfs, anchorStartOfs, anchorEndOfs; if (editor->nSelectionType == stPosition || editor->nSelectionType == stDocument) return; - curOfs = ME_GetCursorOfs(editor, 0); - anchorStartOfs = ME_GetCursorOfs(editor, 3); - anchorEndOfs = ME_GetCursorOfs(editor, 2); + curOfs = ME_GetCursorOfs(&editor->pCursors[0]); + anchorStartOfs = ME_GetCursorOfs(&editor->pCursors[3]); + anchorEndOfs = ME_GetCursorOfs(&editor->pCursors[2]); tmp_cursor = editor->pCursors[0]; editor->pCursors[0] = editor->pCursors[2]; @@ -1231,14 +1264,14 @@ static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) { ME_DisplayItem *pRun = pCursor->pRun; - ME_DisplayItem *pItem, *pOldPara, *pNewPara; + ME_DisplayItem *pOldPara = pCursor->pPara; + ME_DisplayItem *pItem, *pNewPara; int x = ME_GetXForArrow(editor, pCursor); if (editor->bCaretAtEnd && !pCursor->nOffset) - pRun = ME_FindItemBack(pRun, diRun); - if (!pRun) - return; - pOldPara = ME_GetParagraph(pRun); + if (!ME_PrevRun(&pOldPara, &pRun)) + return; + if (nRelOfs == -1) { /* start of this row */ @@ -1313,9 +1346,7 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) if (editor->vert_si.nPos < p->member.row.nHeight) { - pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para; - pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun); - pCursor->nOffset = 0; + ME_SetCursorToStart(editor, pCursor); editor->bCaretAtEnd = FALSE; /* Native clears seems to clear this x value on page up at the top * of the text, but not on page down at the end of the text. @@ -1380,9 +1411,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) if (editor->vert_si.nPos >= y - editor->sizeWindow.cy) { - pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para; - pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - pCursor->nOffset = 0; + ME_SetCursorToEnd(editor, pCursor); editor->bCaretAtEnd = FALSE; } else { ME_DisplayItem *pRun = pCursor->pRun; @@ -1451,9 +1480,7 @@ static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) { - pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para; - pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun); - pCursor->nOffset = 0; + ME_SetCursorToStart(editor, pCursor); editor->bCaretAtEnd = FALSE; } @@ -1484,33 +1511,21 @@ static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { - pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para; - pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - assert(pCursor->pRun->member.run.nFlags & MERF_ENDPARA); - pCursor->nOffset = 0; + ME_SetCursorToEnd(editor, pCursor); editor->bCaretAtEnd = FALSE; } BOOL ME_IsSelection(ME_TextEditor *editor) { - return memcmp(&editor->pCursors[0], &editor->pCursors[1], sizeof(ME_Cursor))!=0; -} - -static int ME_GetSelCursor(ME_TextEditor *editor, int dir) -{ - int cdir = ME_GetCursorOfs(editor, 0) - ME_GetCursorOfs(editor, 1); - - if (cdir*dir>0) - return 0; - else - return 1; + return editor->pCursors[0].pRun != editor->pCursors[1].pRun || + editor->pCursors[0].nOffset != editor->pCursors[1].nOffset; } void ME_DeleteSelection(ME_TextEditor *editor) { int from, to; - ME_GetSelection(editor, &from, &to); - ME_DeleteTextAtCursor(editor, ME_GetSelCursor(editor,-1), to-from); + int nStartCursor = ME_GetSelectionOfs(editor, &from, &to); + ME_DeleteTextAtCursor(editor, nStartCursor, to - from); } ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) @@ -1525,12 +1540,14 @@ void ME_SendSelChange(ME_TextEditor *editor) if (!(editor->nEventMask & ENM_SELCHANGE)) return; + sc.nmhdr.hwndFrom = NULL; + sc.nmhdr.idFrom = 0; sc.nmhdr.code = EN_SELCHANGE; - ME_GetSelection(editor, &sc.chrg.cpMin, &sc.chrg.cpMax); + ME_GetSelectionOfs(editor, &sc.chrg.cpMin, &sc.chrg.cpMax); sc.seltyp = SEL_EMPTY; if (sc.chrg.cpMin != sc.chrg.cpMax) sc.seltyp |= SEL_TEXT; - if (sc.chrg.cpMin < sc.chrg.cpMax+1) /* wth were RICHEDIT authors thinking ? */ + if (sc.chrg.cpMin < sc.chrg.cpMax+1) /* what were RICHEDIT authors thinking ? */ sc.seltyp |= SEL_MULTICHAR; TRACE("cpMin=%d cpMax=%d seltyp=%d (%s %s)\n", sc.chrg.cpMin, sc.chrg.cpMax, sc.seltyp, diff --git a/dll/win32/riched20/clipboard.c b/dll/win32/riched20/clipboard.c index cf4fe4b37a9..15ce97b943f 100644 --- a/dll/win32/riched20/clipboard.c +++ b/dll/win32/riched20/clipboard.c @@ -326,18 +326,23 @@ static const IDataObjectVtbl VT_DataObjectImpl = DataObjectImpl_EnumDAdvise }; -static HGLOBAL get_unicode_text(ME_TextEditor *editor, const CHARRANGE *lpchrg) +static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, int nChars) { - int pars, len; + int pars = 0; WCHAR *data; HANDLE ret; + ME_DisplayItem *para; + int nEnd = ME_GetCursorOfs(start) + nChars; - pars = ME_CountParagraphsBetween(editor, lpchrg->cpMin, lpchrg->cpMax); - len = lpchrg->cpMax-lpchrg->cpMin; - ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR)*(len+pars+1)); + /* count paragraphs in range */ + para = start->pPara; + while((para = para->member.para.next_para) && + para->member.para.nCharOfs <= nEnd) + pars++; + + ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1)); data = GlobalLock(ret); - len = ME_GetTextW(editor, data, lpchrg->cpMin, len, TRUE); - data[len] = 0; + ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE); GlobalUnlock(ret); return ret; } @@ -370,7 +375,7 @@ static DWORD CALLBACK ME_AppendToHGLOBAL(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG return 0; } -static HGLOBAL get_rtf_text(ME_TextEditor *editor, const CHARRANGE *lpchrg) +static HGLOBAL get_rtf_text(ME_TextEditor *editor, const ME_Cursor *start, int nChars) { EDITSTREAM es; ME_GlobalDestStruct gds; @@ -379,15 +384,16 @@ static HGLOBAL get_rtf_text(ME_TextEditor *editor, const CHARRANGE *lpchrg) gds.nLength = 0; es.dwCookie = (DWORD_PTR)&gds; es.pfnCallback = ME_AppendToHGLOBAL; - ME_StreamOutRange(editor, SF_RTF, lpchrg->cpMin, lpchrg->cpMax, &es); + ME_StreamOutRange(editor, SF_RTF, start, nChars, &es); GlobalReAlloc(gds.hData, gds.nLength+1, 0); return gds.hData; } -HRESULT ME_GetDataObject(ME_TextEditor *editor, const CHARRANGE *lpchrg, LPDATAOBJECT *lplpdataobj) +HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, + int nChars, LPDATAOBJECT *lplpdataobj) { DataObjectImpl *obj; - TRACE("(%p,%d,%d)\n", editor, lpchrg->cpMin, lpchrg->cpMax); + TRACE("(%p,%d,%d)\n", editor, ME_GetCursorOfs(start), nChars); obj = heap_alloc(sizeof(DataObjectImpl)); if(cfRTF == 0) @@ -395,7 +401,7 @@ HRESULT ME_GetDataObject(ME_TextEditor *editor, const CHARRANGE *lpchrg, LPDATAO obj->lpVtbl = &VT_DataObjectImpl; obj->ref = 1; - obj->unicode = get_unicode_text(editor, lpchrg); + obj->unicode = get_unicode_text(editor, start, nChars); obj->rtf = NULL; obj->fmtetc_cnt = 1; @@ -404,7 +410,7 @@ HRESULT ME_GetDataObject(ME_TextEditor *editor, const CHARRANGE *lpchrg, LPDATAO obj->fmtetc = GlobalAlloc(GMEM_ZEROINIT, obj->fmtetc_cnt*sizeof(FORMATETC)); InitFormatEtc(obj->fmtetc[0], CF_UNICODETEXT, TYMED_HGLOBAL); if(editor->mode & TM_RICHTEXT) { - obj->rtf = get_rtf_text(editor, lpchrg); + obj->rtf = get_rtf_text(editor, start, nChars); InitFormatEtc(obj->fmtetc[1], cfRTF, TYMED_HGLOBAL); } diff --git a/dll/win32/riched20/editor.c b/dll/win32/riched20/editor.c index 278b9aaa843..7a116472917 100644 --- a/dll/win32/riched20/editor.c +++ b/dll/win32/riched20/editor.c @@ -141,8 +141,8 @@ + WM_PASTE + WM_SETFONT + WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode - - WM_STYLECHANGING - - WM_STYLECHANGED (things like read-only flag) + + WM_STYLECHANGING (seems to do nothing) + + WM_STYLECHANGED (seems to do nothing) + WM_UNICHAR + WM_VSCROLL @@ -241,10 +241,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); static BOOL ME_RegisterEditorClass(HINSTANCE); -static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max); +static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, ME_Cursor *start, int nChars); -static const WCHAR RichEdit20W[] = {'R', 'i', 'c', 'h', 'E', 'd', 'i', 't', '2', '0', 'W', 0}; -static const WCHAR RichEdit50W[] = {'R', 'i', 'c', 'h', 'E', 'd', 'i', 't', '5', '0', 'W', 0}; static const WCHAR REListBox20W[] = {'R','E','L','i','s','t','B','o','x','2','0','W', 0}; static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0}; static HCURSOR hLeft; @@ -422,7 +420,10 @@ void ME_RTFCharAttrHook(RTF_Info *info) else if (info->rtfParam != rtfNoParam) { RTFColor *c = RTFGetColor(info, info->rtfParam); - fmt.crTextColor = (c->rtfCBlue<<16)|(c->rtfCGreen<<8)|(c->rtfCRed); + if (c && c->rtfCBlue >= 0) + fmt.crTextColor = (c->rtfCBlue<<16)|(c->rtfCGreen<<8)|(c->rtfCRed); + else + fmt.dwEffects = CFE_AUTOBACKCOLOR; } break; case rtfForeColor: @@ -433,10 +434,11 @@ void ME_RTFCharAttrHook(RTF_Info *info) else if (info->rtfParam != rtfNoParam) { RTFColor *c = RTFGetColor(info, info->rtfParam); - if (c) + if (c && c->rtfCBlue >= 0) fmt.crTextColor = (c->rtfCBlue<<16)|(c->rtfCGreen<<8)|(c->rtfCRed); - else - fmt.crTextColor = 0; + else { + fmt.dwEffects = CFE_AUTOCOLOR; + } } break; case rtfFontNum: @@ -1011,9 +1013,10 @@ void ME_RTFSpecialCharHook(RTF_Info *info) info->editor->pCursors[1].pRun = run; info->editor->pCursors[1].pPara = ME_GetParagraph(run); info->editor->pCursors[1].nOffset = 0; - nOfs = ME_GetCursorOfs(info->editor, 1); - nChars = ME_GetCursorOfs(info->editor, 0) - nOfs; - ME_InternalDeleteText(info->editor, nOfs, nChars, TRUE); + nOfs = ME_GetCursorOfs(&info->editor->pCursors[1]); + nChars = ME_GetCursorOfs(&info->editor->pCursors[0]) - nOfs; + ME_InternalDeleteText(info->editor, &info->editor->pCursors[1], + nChars, TRUE); } para = ME_InsertTableRowEndFromCursor(info->editor); @@ -1146,8 +1149,8 @@ static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE hemf, HBITMAP hbm reobject.dwFlags = 0; /* FIXME */ reobject.dwUser = 0; - /* FIXME: could be simpler */ - ret = IRichEditOle_InsertObject(info->lpRichEditOle, &reobject) == S_OK; + ME_InsertOLEFromCursor(info->editor, &reobject, 0); + ret = TRUE; } if (lpObject) IOleObject_Release(lpObject); @@ -1341,7 +1344,8 @@ static void ME_RTFReadHook(RTF_Info *info) { case rtfBeginGroup: if (info->stackTop < maxStack) { - info->stack[info->stackTop].fmt = info->style->fmt; + info->stack[info->stackTop].style = info->style; + ME_AddRefStyle(info->style); info->stack[info->stackTop].codePage = info->codePage; info->stack[info->stackTop].unicodeLength = info->unicodeLength; } @@ -1350,23 +1354,17 @@ static void ME_RTFReadHook(RTF_Info *info) break; case rtfEndGroup: { - ME_Style *s; RTFFlushOutputBuffer(info); info->stackTop--; - if (info->stackTop<=0) { + if (info->stackTop <= 0) info->rtfClass = rtfEOF; + if (info->stackTop < 0) return; - } - assert(info->stackTop >= 0); - if (info->styleChanged) - { - /* FIXME too slow ? how come ? */ - s = ME_ApplyStyle(info->style, &info->stack[info->stackTop].fmt); - ME_ReleaseStyle(info->style); - info->style = s; - info->codePage = info->stack[info->stackTop].codePage; - info->unicodeLength = info->stack[info->stackTop].unicodeLength; - } + + ME_ReleaseStyle(info->style); + info->style = info->stack[info->stackTop].style; + info->codePage = info->stack[info->stackTop].codePage; + info->unicodeLength = info->stack[info->stackTop].unicodeLength; break; } } @@ -1388,19 +1386,22 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre { RTF_Info parser; ME_Style *style; - int from, to, to2, nUndoMode; + int from, to, nUndoMode; int nEventMask = editor->nEventMask; ME_InStream inStream; BOOL invalidRTF = FALSE; + ME_Cursor *selStart, *selEnd; TRACE("stream==%p editor==%p format==0x%X\n", stream, editor, format); editor->nEventMask = 0; - ME_GetSelection(editor, &from, &to); - if ((format & SFF_SELECTION) && (editor->mode & TM_RICHTEXT)) { + ME_GetSelectionOfs(editor, &from, &to); + if (format & SFF_SELECTION && editor->mode & TM_RICHTEXT) + { + ME_GetSelection(editor, &selStart, &selEnd); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from, FALSE); + ME_InternalDeleteText(editor, selStart, to - from, FALSE); /* Don't insert text at the end of the table row */ if (!editor->bEmulateVersion10) { /* v4.1 */ @@ -1425,12 +1426,12 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_IsInTable(editor->pCursors[0].pRun)) return 0; } - } - else { + } else { style = editor->pBuffer->pDefaultStyle; ME_AddRefStyle(style); ME_SetSelection(editor, 0, 0); - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); + ME_InternalDeleteText(editor, &editor->pCursors[1], + ME_GetTextLength(editor), FALSE); from = to = 0; ME_ClearTempStyle(editor); ME_SetDefaultParaFormat(editor->pCursors[0].pPara->member.para.pFmt); @@ -1519,9 +1520,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre editor->pCursors[1].pPara = para; editor->pCursors[1].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[1].nOffset = 0; - nOfs = ME_GetCursorOfs(editor, 1); - nChars = ME_GetCursorOfs(editor, 0) - nOfs; - ME_InternalDeleteText(editor, nOfs, nChars, TRUE); + nOfs = ME_GetCursorOfs(&editor->pCursors[1]); + nChars = ME_GetCursorOfs(&editor->pCursors[0]) - nOfs; + ME_InternalDeleteText(editor, &editor->pCursors[1], nChars, TRUE); if (parser.tableDef) parser.tableDef->tableRowStart = NULL; } @@ -1531,23 +1532,34 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (parser.lpRichEditOle) IRichEditOle_Release(parser.lpRichEditOle); - if (!inStream.editstream->dwError && parser.stackTop > 0) - inStream.editstream->dwError = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + if (parser.stackTop > 0) + { + while (--parser.stackTop >= 0) + { + ME_ReleaseStyle(parser.style); + parser.style = parser.stack[parser.stackTop].style; + } + if (!inStream.editstream->dwError) + inStream.editstream->dwError = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + } /* Remove last line break, as mandated by tests. This is not affected by CR/LF counters, since RTF streaming presents only \para tokens, which are converted according to the standard rules: \r for 2.0, \r\n for 1.0 */ if (stripLastCR) { - int newfrom, newto; - ME_GetSelection(editor, &newfrom, &newto); + int newto; + ME_GetSelection(editor, &selStart, &selEnd); + newto = ME_GetCursorOfs(selEnd); if (newto > to + (editor->bEmulateVersion10 ? 1 : 0)) { WCHAR lastchar[3] = {'\0', '\0'}; int linebreakSize = editor->bEmulateVersion10 ? 2 : 1; + ME_Cursor linebreakCursor = *selEnd; - ME_GetTextW(editor, lastchar, newto - linebreakSize, linebreakSize, 0); + ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize); + ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, 0); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { - ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize, FALSE); + ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE); } } } @@ -1558,7 +1570,6 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_StreamInText(editor, format, &inStream, style); else ERR("EM_STREAMIN without SF_TEXT or SF_RTF\n"); - ME_GetSelection(editor, &to, &to2); /* put the cursor at the top */ if (!(format & SFF_SELECTION)) ME_SetSelection(editor, 0, 0); @@ -1629,10 +1640,8 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH { const int nLen = lstrlenW(text); const int nTextLen = ME_GetTextLength(editor); - int nStart, nEnd; int nMin, nMax; - ME_DisplayItem *item; - ME_DisplayItem *para; + ME_Cursor cursor; WCHAR wLastChar = ' '; TRACE("flags==0x%08x, chrg->cpMin==%d, chrg->cpMax==%d text==%s\n", @@ -1693,17 +1702,17 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* If possible, find the character before where the search starts */ if ((flags & FR_WHOLEWORD) && nMin) { - ME_RunOfsFromCharOfs(editor, nMin - 1, NULL, &item, &nStart); - wLastChar = item->member.run.strText->szData[nStart]; + ME_CursorFromCharOfs(editor, nMin - 1, &cursor); + wLastChar = cursor.pRun->member.run.strText->szData[cursor.nOffset]; + ME_MoveCursorChars(editor, &cursor, 1); + } else { + ME_CursorFromCharOfs(editor, nMin, &cursor); } - ME_RunOfsFromCharOfs(editor, nMin, ¶, &item, &nStart); - - while (item - && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen <= nMax) + while (cursor.pRun && ME_GetCursorOfs(&cursor) + nLen <= nMax) { - ME_DisplayItem *pCurItem = item; - int nCurStart = nStart; + ME_DisplayItem *pCurItem = cursor.pRun; + int nCurStart = cursor.nOffset; int nMatched = 0; while (pCurItem && ME_CharCompare(pCurItem->member.run.strText->szData[nCurStart + nMatched], text[nMatched], (flags & FR_MATCHCASE))) @@ -1736,14 +1745,14 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH break; } - nStart += para->member.para.nCharOfs + item->member.run.nCharOfs; + cursor.nOffset += cursor.pPara->member.para.nCharOfs + cursor.pRun->member.run.nCharOfs; if (chrgText) { - chrgText->cpMin = nStart; - chrgText->cpMax = nStart + nLen; + chrgText->cpMin = cursor.nOffset; + chrgText->cpMax = cursor.nOffset + nLen; } - TRACE("found at %d-%d\n", nStart, nStart + nLen); - return nStart; + TRACE("found at %d-%d\n", cursor.nOffset, cursor.nOffset + nLen); + return cursor.nOffset; } if (nCurStart + nMatched == pCurItem->member.run.strText->nLen) { @@ -1756,12 +1765,11 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH else wLastChar = ' '; - nStart++; - if (nStart == item->member.run.strText->nLen) + cursor.nOffset++; + if (cursor.nOffset == cursor.pRun->member.run.strText->nLen) { - item = ME_FindItemFwd(item, diRun); - para = ME_GetParagraph(item); - nStart = 0; + ME_NextRun(&cursor.pPara, &cursor.pRun); + cursor.nOffset = 0; } } } @@ -1770,22 +1778,23 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* If possible, find the character after where the search ends */ if ((flags & FR_WHOLEWORD) && nMax < nTextLen - 1) { - ME_RunOfsFromCharOfs(editor, nMax + 1, NULL, &item, &nEnd); - wLastChar = item->member.run.strText->szData[nEnd]; + ME_CursorFromCharOfs(editor, nMax + 1, &cursor); + wLastChar = cursor.pRun->member.run.strText->szData[cursor.nOffset]; + ME_MoveCursorChars(editor, &cursor, -1); + } else { + ME_CursorFromCharOfs(editor, nMax, &cursor); } - ME_RunOfsFromCharOfs(editor, nMax, ¶, &item, &nEnd); - - while (item - && para->member.para.nCharOfs + item->member.run.nCharOfs + nEnd - nLen >= nMin) + while (cursor.pRun && ME_GetCursorOfs(&cursor) - nLen >= nMin) { - ME_DisplayItem *pCurItem = item; - int nCurEnd = nEnd; + ME_DisplayItem *pCurItem = cursor.pRun; + ME_DisplayItem *pCurPara = cursor.pPara; + int nCurEnd = cursor.nOffset; int nMatched = 0; if (nCurEnd == 0) { - pCurItem = ME_FindItemBack(pCurItem, diRun); + ME_PrevRun(&pCurPara, &pCurItem); nCurEnd = pCurItem->member.run.strText->nLen + nMatched; } @@ -1800,6 +1809,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH ME_DisplayItem *pPrevItem = pCurItem; int nPrevEnd = nCurEnd; WCHAR wPrevChar; + int nStart; /* Check to see if previous character is a whitespace */ if (flags & FR_WHOLEWORD) @@ -1820,7 +1830,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH break; } - nStart = ME_GetParagraph(pCurItem)->member.para.nCharOfs + nStart = pCurPara->member.para.nCharOfs + pCurItem->member.run.nCharOfs + nCurEnd - nMatched; if (chrgText) { @@ -1832,7 +1842,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH } if (nCurEnd - nMatched == 0) { - pCurItem = ME_FindItemBack(pCurItem, diRun); + ME_PrevRun(&pCurPara, &pCurItem); /* Don't care about pCurItem becoming NULL here; it's already taken * care of in the exterior loop condition */ nCurEnd = pCurItem->member.run.strText->nLen + nMatched; @@ -1843,12 +1853,11 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH else wLastChar = ' '; - nEnd--; - if (nEnd < 0) + cursor.nOffset--; + if (cursor.nOffset < 0) { - item = ME_FindItemBack(item, diRun); - para = ME_GetParagraph(item); - nEnd = item->member.run.strText->nLen; + ME_PrevRun(&cursor.pPara, &cursor.pRun); + cursor.nOffset = cursor.pRun->member.run.strText->nLen; } } } @@ -1860,25 +1869,30 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) { - int nStart, nCount; /* in chars */ + int nChars; + ME_Cursor start; + + if (!ex->cb || !pText) return 0; if (ex->flags & ~(GT_SELECTION | GT_USECRLF)) FIXME("GETTEXTEX flags 0x%08x not supported\n", ex->flags & ~(GT_SELECTION | GT_USECRLF)); if (ex->flags & GT_SELECTION) { - ME_GetSelection(editor, &nStart, &nCount); - nCount -= nStart; + int from, to; + int nStartCur = ME_GetSelectionOfs(editor, &from, &to); + start = editor->pCursors[nStartCur]; + nChars = to - from; } else { - nStart = 0; - nCount = 0x7fffffff; + ME_SetCursorToStart(editor, &start); + nChars = INT_MAX; } if (ex->codepage == 1200) { - nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1); - return ME_GetTextW(editor, (LPWSTR)pText, nStart, nCount, ex->flags & GT_USECRLF); + return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1, + &start, nChars, ex->flags & GT_USECRLF); } else { @@ -1888,16 +1902,15 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) occurs only in richedit 2.0 mode, in which line breaks have only one CR */ int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1; + DWORD buflen; LPWSTR buffer; - DWORD buflen = ex->cb; LRESULT rc; - DWORD flags = 0; - nCount = min(nCount, ex->cb - 1); - buffer = heap_alloc((crlfmul*nCount + 1) * sizeof(WCHAR)); + buflen = min(crlfmul * nChars, ex->cb - 1); + buffer = heap_alloc((buflen + 1) * sizeof(WCHAR)); - buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF); - rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen+1, + nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF); + rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1, (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ @@ -1907,13 +1920,16 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) } static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, - int start, int nLen, BOOL unicode) + const ME_Cursor *start, int nLen, BOOL unicode) { + if (!strText) return 0; if (unicode) { - return ME_GetTextW(editor, strText, start, nLen, 0); + return ME_GetTextW(editor, strText, INT_MAX, start, nLen, 0); } else { + int nChars; WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); - int nChars = ME_GetTextW(editor, p, start, nLen, 0); + if (!p) return 0; + nChars = ME_GetTextW(editor, p, nLen, start, nLen, 0); WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, nLen+1, NULL, NULL); FREE_OBJ(p); @@ -1989,7 +2005,7 @@ static BOOL ME_Paste(ME_TextEditor *editor) return TRUE; } -static BOOL ME_Copy(ME_TextEditor *editor, CHARRANGE *range) +static BOOL ME_Copy(ME_TextEditor *editor, const ME_Cursor *start, int nChars) { LPDATAOBJECT dataObj = NULL; HRESULT hr = S_OK; @@ -1998,9 +2014,14 @@ static BOOL ME_Copy(ME_TextEditor *editor, CHARRANGE *range) return FALSE; /* Copying or Cutting masked text isn't allowed */ if(editor->lpOleCallback) - hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, range, RECO_COPY, &dataObj); + { + CHARRANGE range; + range.cpMin = ME_GetCursorOfs(start); + range.cpMax = range.cpMin + nChars; + hr = IRichEditOleCallback_GetClipboardData(editor->lpOleCallback, &range, RECO_COPY, &dataObj); + } if(FAILED(hr) || !dataObj) - hr = ME_GetDataObject(editor, range, &dataObj); + hr = ME_GetDataObject(editor, start, nChars, &dataObj); if(SUCCEEDED(hr)) { hr = OleSetClipboard(dataObj); IDataObject_Release(dataObj); @@ -2014,14 +2035,14 @@ ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) { MSGFILTER msgf; - if (!editor->hWnd) return FALSE; + if (!editor->hWnd || !editor->hwndParent) return FALSE; msgf.nmhdr.hwndFrom = editor->hWnd; msgf.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); msgf.nmhdr.code = EN_MSGFILTER; msgf.msg = msg; msgf.wParam = *wParam; msgf.lParam = *lParam; - if (SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf)) + if (SendMessageW(editor->hwndParent, WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf)) return FALSE; *wParam = msgf.wParam; *lParam = msgf.lParam; @@ -2034,24 +2055,28 @@ static void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor) { ME_DisplayItem *startPara, *endPara; ME_DisplayItem *prev_para; - int from, to; + ME_Cursor *from, *to; + ME_Cursor start; + int nChars; if (!editor->AutoURLDetect_bEnable) return; ME_GetSelection(editor, &from, &to); /* Find paragraph previous to the one that contains start cursor */ - ME_RunOfsFromCharOfs(editor, from, &startPara, NULL, NULL); + startPara = from->pPara; prev_para = startPara->member.para.prev_para; if (prev_para->type == diParagraph) startPara = prev_para; /* Find paragraph that contains end cursor */ - ME_RunOfsFromCharOfs(editor, to, &endPara, NULL, NULL); - endPara = endPara->member.para.next_para; + endPara = to->pPara->member.para.next_para; - ME_UpdateLinkAttribute(editor, - startPara->member.para.nCharOfs, - endPara->member.para.nCharOfs); + start.pPara = startPara; + start.pRun = ME_FindItemFwd(startPara, diRun); + start.nOffset = 0; + nChars = endPara->member.para.nCharOfs - startPara->member.para.nCharOfs; + + ME_UpdateLinkAttribute(editor, &start, nChars); } static BOOL @@ -2120,6 +2145,31 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ME_SendRequestResize(editor, FALSE); return TRUE; case VK_RETURN: + if (editor->bDialogMode) + { + if (ctrl_is_down) + return TRUE; + + if (!(editor->styleFlags & ES_WANTRETURN)) + { + if (editor->hwndParent) + { + DWORD dw; + dw = SendMessageW(editor->hwndParent, DM_GETDEFID, 0, 0); + if (HIWORD(dw) == DC_HASDEFID) + { + HWND hwDefCtrl = GetDlgItem(editor->hwndParent, LOWORD(dw)); + if (hwDefCtrl) + { + SendMessageW(editor->hwndParent, WM_NEXTDLGCTL, (WPARAM)hwDefCtrl, TRUE); + PostMessageW(hwDefCtrl, WM_KEYDOWN, VK_RETURN, 0); + } + } + } + return TRUE; + } + } + if (editor->styleFlags & ES_MULTILINE) { ME_Cursor cursor = editor->pCursors[0]; @@ -2133,7 +2183,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) return TRUE; } - ME_GetSelection(editor, &from, &to); + ME_GetSelectionOfs(editor, &from, &to); if (editor->nTextLimit > ME_GetTextLength(editor) - (to-from)) { if (!editor->bEmulateVersion10) { /* v4.1 */ @@ -2239,6 +2289,14 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) return TRUE; } break; + case VK_ESCAPE: + if (editor->bDialogMode && editor->hwndParent) + PostMessageW(editor->hwndParent, WM_CLOSE, 0, 0); + return TRUE; + case VK_TAB: + if (editor->bDialogMode && editor->hwndParent) + SendMessageW(editor->hwndParent, WM_NEXTDLGCTL, shift_is_down, 0); + return TRUE; case 'A': if (ctrl_is_down) { @@ -2254,14 +2312,16 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) case 'X': if (ctrl_is_down) { - CHARRANGE range; BOOL result; + int nOfs, nChars; + int nStartCur = ME_GetSelectionOfs(editor, &nOfs, &nChars); + ME_Cursor *selStart = &editor->pCursors[nStartCur]; - ME_GetSelection(editor, &range.cpMin, &range.cpMax); - result = ME_Copy(editor, &range); + nChars -= nOfs; + result = ME_Copy(editor, selStart, nChars); if (result && nKey == 'X') { - ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); + ME_InternalDeleteText(editor, selStart, nChars, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); } @@ -2334,7 +2394,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, ME_DisplayItem *para = cursor.pPara; int from, to; BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; - ME_GetSelection(editor, &from, &to); + ME_GetSelectionOfs(editor, &from, &to); if (wstr == '\t' && /* v4.1 allows tabs to be inserted with ctrl key down */ !(ctrl_is_down && !editor->bEmulateVersion10)) @@ -2345,7 +2405,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, para = cursor.pPara; if (ME_IsSelection(editor) && cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 && - to == ME_GetCursorOfs(editor, 0) && + to == ME_GetCursorOfs(&editor->pCursors[0]) && para->member.para.prev_para->type == diParagraph) { para = para->member.para.prev_para; @@ -2453,9 +2513,9 @@ static int ME_CalculateClickCount(ME_TextEditor *editor, UINT msg, WPARAM wParam static BOOL ME_SetCursor(ME_TextEditor *editor) { + ME_Cursor cursor; POINT pt; BOOL isExact; - int offset; SCROLLBARINFO sbi; DWORD messagePos = GetMessagePos(); pt.x = (short)LOWORD(messagePos); @@ -2510,13 +2570,11 @@ static BOOL ME_SetCursor(ME_TextEditor *editor) ITextHost_TxSetCursor(editor->texthost, hLeft, FALSE); return TRUE; } - offset = ME_CharFromPos(editor, pt.x, pt.y, &isExact); + ME_CharFromPos(editor, pt.x, pt.y, &cursor, &isExact); if (isExact) { - ME_Cursor cursor; ME_Run *run; - ME_CursorFromCharOfs(editor, offset, &cursor); run = &cursor.pRun->member.run; if (run->style->fmt.dwMask & CFM_LINK && run->style->fmt.dwEffects & CFE_LINK) @@ -2530,7 +2588,9 @@ static BOOL ME_SetCursor(ME_TextEditor *editor) if (ME_IsSelection(editor)) { int selStart, selEnd; - ME_GetSelection(editor, &selStart, &selEnd); + int offset = ME_GetCursorOfs(&cursor); + + ME_GetSelectionOfs(editor, &selStart, &selEnd); if (selStart <= offset && selEnd >= offset) { ITextHost_TxSetCursor(editor->texthost, LoadCursorW(NULL, (WCHAR*)IDC_ARROW), @@ -2559,7 +2619,7 @@ static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y) int seltype = 0; if(!editor->lpOleCallback || !editor->hWnd) return FALSE; - ME_GetSelection(editor, &selrange.cpMin, &selrange.cpMax); + ME_GetSelectionOfs(editor, &selrange.cpMin, &selrange.cpMax); if(selrange.cpMin == selrange.cpMax) seltype |= SEL_EMPTY; else @@ -2571,7 +2631,7 @@ static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y) } if(SUCCEEDED(IRichEditOleCallback_GetContextMenu(editor->lpOleCallback, seltype, NULL, &selrange, &menu))) { - TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, GetParent(editor->hWnd), NULL); + TrackPopupMenu(menu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, editor->hwndParent, NULL); DestroyMenu(menu); } return TRUE; @@ -2585,8 +2645,11 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) LONG selbarwidth; ed->hWnd = NULL; + ed->hwndParent = NULL; + ed->sizeWindow.cx = ed->sizeWindow.cy = 0; ed->texthost = texthost; ed->bEmulateVersion10 = bEmulateVersion10; + ed->styleFlags = 0; ITextHost_TxGetPropertyBits(texthost, (TXTBIT_RICHTEXT|TXTBIT_MULTILINE| TXTBIT_READONLY|TXTBIT_USEPASSWORD| @@ -2599,6 +2662,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ES_AUTOHSCROLL|ES_DISABLENOSCROLL); ed->pBuffer = ME_MakeText(); ed->nZoomNumerator = ed->nZoomDenominator = 0; + ed->nAvailWidth = 0; /* wrap to client area */ ME_MakeFirstParagraph(ed); /* The four cursors are for: * 0 - The position where the caret is shown @@ -2608,9 +2672,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) */ ed->nCursors = 4; ed->pCursors = ALLOC_N_OBJ(ME_Cursor, ed->nCursors); - ed->pCursors[0].pPara = ed->pBuffer->pFirst->member.para.next_para; - ed->pCursors[0].pRun = ME_FindItemFwd(ed->pCursors[0].pPara, diRun); - ed->pCursors[0].nOffset = 0; + ME_SetCursorToStart(ed, &ed->pCursors[0]); ed->pCursors[1] = ed->pCursors[0]; ed->pCursors[2] = ed->pCursors[0]; ed->pCursors[3] = ed->pCursors[1]; @@ -2630,8 +2692,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->nUndoMode = umAddToUndo; ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; - ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph); - ed->nAvailWidth = 0; /* wrap to client area */ + ed->pLastSelStartPara = ed->pLastSelEndPara = ed->pCursors[0].pPara; ed->bHideSelection = FALSE; ed->pfnWordBreak = NULL; ed->lpOleCallback = NULL; @@ -2639,6 +2700,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->mode |= (props & TXTBIT_RICHTEXT) ? TM_RICHTEXT : TM_PLAINTEXT; ed->AutoURLDetect_bEnable = FALSE; ed->bHaveFocus = FALSE; + ed->bDialogMode = FALSE; ed->bMouseCaptured = FALSE; for (i=0; imember.run.style->fmt.dwMask & CFM_LINK) - && (run->member.run.style->fmt.dwEffects & CFE_LINK)) + if (cursor.pRun->member.run.style->fmt.dwMask & CFM_LINK && + cursor.pRun->member.run.style->fmt.dwEffects & CFE_LINK) { /* The clicked run has CFE_LINK set */ - info.nmhdr.hwndFrom = editor->hWnd; - info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); + info.nmhdr.hwndFrom = NULL; + info.nmhdr.idFrom = 0; info.nmhdr.code = EN_LINK; info.msg = msg; info.wParam = wParam; info.lParam = lParam; - info.chrg.cpMin = ME_CharOfsFromRunOfs(editor, para, run, 0); - info.chrg.cpMax = info.chrg.cpMin + run->member.run.strText->nLen; - SendMessageW(GetParent(editor->hWnd), WM_NOTIFY,info.nmhdr.idFrom, (LPARAM)&info); + cursor.nOffset = 0; + info.chrg.cpMin = ME_GetCursorOfs(&cursor); + info.chrg.cpMax = info.chrg.cpMin + cursor.pRun->member.run.strText->nLen; + ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info); } } @@ -2974,8 +3034,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, UNSUPPORTED_MSG(EM_SETTABSTOPS) UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS) UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX) - UNSUPPORTED_MSG(WM_STYLECHANGING) - UNSUPPORTED_MSG(WM_STYLECHANGED) /* Messages specific to Richedit controls */ @@ -2986,6 +3044,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_GETDLGCODE: { UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL; + if (lParam) + editor->bDialogMode = TRUE; if (editor->styleFlags & ES_MULTILINE) code |= DLGC_WANTMESSAGE; return code; @@ -2999,7 +3059,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, UINT from, to; PUINT pfrom = wParam ? (PUINT)wParam : &from; PUINT pto = lParam ? (PUINT)lParam : &to; - ME_GetSelection(editor, (int *)pfrom, (int *)pto); + ME_GetSelectionOfs(editor, (int *)pfrom, (int *)pto); if ((*pfrom|*pto) & 0xFFFF0000) return -1; return MAKELONG(*pfrom,*pto); @@ -3007,7 +3067,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_EXGETSEL: { CHARRANGE *pRange = (CHARRANGE *)lParam; - ME_GetSelection(editor, &pRange->cpMin, &pRange->cpMax); + ME_GetSelectionOfs(editor, &pRange->cpMin, &pRange->cpMax); TRACE("EM_EXGETSEL = (%d,%d)\n", pRange->cpMin, pRange->cpMax); return 0; } @@ -3194,7 +3254,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, /* If we detect ascii rtf at the start of the string, * we know it isn't unicode. */ bRtf = (lParam && (!strncmp((char *)lParam, "{\\rtf", 5) || - !strncmp((char *)lParam, "{\\urtf}", 6))); + !strncmp((char *)lParam, "{\\urtf", 6))); bUnicode = !bRtf && pStruct->codepage == 1200; TRACE("EM_SETTEXTEX - %s, flags %d, cp %d\n", @@ -3203,18 +3263,20 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, bSelection = (pStruct->flags & ST_SELECTION) != 0; if (bSelection) { - ME_GetSelection(editor, &from, &to); + int nStartCursor = ME_GetSelectionOfs(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to - from, FALSE); + ME_InternalDeleteText(editor, &editor->pCursors[nStartCursor], to - from, FALSE); } else { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); + ME_Cursor start; + ME_SetCursorToStart(editor, &start); + ME_InternalDeleteText(editor, &start, ME_GetTextLength(editor), FALSE); style = editor->pBuffer->pDefaultStyle; } if (bRtf) { ME_StreamInRTFString(editor, bSelection, (char *)lParam); if (bSelection) { - /* FIXME: The length returned is doesn't include the rtf control + /* FIXME: The length returned doesn't include the rtf control * characters, only the actual text. */ len = lParam ? strlen((char *)lParam) : 0; } @@ -3223,14 +3285,17 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, wszText = lParam ? ME_ToUnicode(bUnicode, (void *)lParam) : NULL; len = wszText ? lstrlenW(wszText) : 0; ME_InsertTextFromCursor(editor, 0, wszText, len, style); + ME_EndToUnicode(bUnicode, wszText); } if (bSelection) { ME_ReleaseStyle(style); ME_UpdateSelectionLinkAttribute(editor); } else { + ME_Cursor cursor; len = 1; - ME_UpdateLinkAttribute(editor, 0, -1); + ME_SetCursorToStart(editor, &cursor); + ME_UpdateLinkAttribute(editor, &cursor, INT_MAX); } ME_CommitUndo(editor); if (!(pStruct->flags & ST_KEEPUNDO)) @@ -3307,17 +3372,17 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, if (editor->mode & TM_PLAINTEXT) ME_SetDefaultCharFormat(editor, p); else { - ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), p); + ME_Cursor start; + ME_SetCursorToStart(editor, &start); + ME_SetCharFormat(editor, &start, NULL, p); editor->nModifyStep = 1; } } else if (editor->mode & TM_PLAINTEXT) { return 0; } else { - int from, to; - ME_GetSelection(editor, &from, &to); - bRepaint = (from != to); + bRepaint = ME_IsSelection(editor); ME_SetSelectionCharFormat(editor, p); - if (from != to) editor->nModifyStep = 1; + if (bRepaint) editor->nModifyStep = 1; } ME_CommitUndo(editor); if (bRepaint) @@ -3396,23 +3461,23 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_CLEAR: { int from, to; - ME_GetSelection(editor, &from, &to); - ME_InternalDeleteText(editor, from, to-from, FALSE); + int nStartCursor = ME_GetSelectionOfs(editor, &from, &to); + ME_InternalDeleteText(editor, &editor->pCursors[nStartCursor], to-from, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); return 0; } case EM_REPLACESEL: { - int from, to; + int from, to, nStartCursor; ME_Style *style; LPWSTR wszText = lParam ? ME_ToUnicode(unicode, (void *)lParam) : NULL; size_t len = wszText ? lstrlenW(wszText) : 0; TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText)); - ME_GetSelection(editor, &from, &to); + nStartCursor = ME_GetSelectionOfs(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from, FALSE); + ME_InternalDeleteText(editor, &editor->pCursors[nStartCursor], to-from, FALSE); ME_InsertTextFromCursor(editor, 0, wszText, len, style); ME_ReleaseStyle(style); /* drop temporary style if line end */ @@ -3439,6 +3504,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, CHARFORMAT2W fmt; HDC hDC; BOOL bRepaint = LOWORD(lParam); + ME_Cursor start; if (!wParam) wParam = (WPARAM)GetStockObject(SYSTEM_FONT); @@ -3446,7 +3512,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, hDC = ITextHost_TxGetDC(editor->texthost); ME_CharFormatFromLogFont(hDC, &lf, &fmt); ITextHost_TxReleaseDC(editor->texthost, hDC); - ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), &fmt); + ME_SetCursorToStart(editor, &start); + ME_SetCharFormat(editor, &start, NULL, &fmt); ME_SetDefaultCharFormat(editor, &fmt); ME_CommitUndo(editor); @@ -3459,11 +3526,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case WM_SETTEXT: { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); + ME_Cursor cursor; + ME_SetCursorToStart(editor, &cursor); + ME_InternalDeleteText(editor, &cursor, ME_GetTextLength(editor), FALSE); if (lParam) { TRACE("WM_SETTEXT lParam==%lx\n",lParam); - if (!unicode && !strncmp((char *)lParam, "{\\rtf", 5)) + if (!strncmp((char *)lParam, "{\\rtf", 5) || + !strncmp((char *)lParam, "{\\urtf", 6)) { /* Undocumented: WM_SETTEXT supports RTF text */ ME_StreamInRTFString(editor, 0, (char *)lParam); @@ -3492,7 +3562,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } else TRACE("WM_SETTEXT - NULL\n"); - ME_UpdateLinkAttribute(editor, 0, -1); + ME_SetCursorToStart(editor, &cursor); + ME_UpdateLinkAttribute(editor, &cursor, INT_MAX); ME_SetSelection(editor, 0, 0); editor->nModifyStep = 0; ME_CommitUndo(editor); @@ -3515,12 +3586,13 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_CUT: case WM_COPY: { - CHARRANGE range; - ME_GetSelection(editor, &range.cpMin, &range.cpMax); + int nFrom, nTo, nStartCur = ME_GetSelectionOfs(editor, &nFrom, &nTo); + int nChars = nTo - nFrom; + ME_Cursor *selStart = &editor->pCursors[nStartCur]; - if (ME_Copy(editor, &range) && msg == WM_CUT) + if (ME_Copy(editor, selStart, nChars) && msg == WM_CUT) { - ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); + ME_InternalDeleteText(editor, selStart, nChars, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); } @@ -3540,67 +3612,51 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_GETTEXT: { GETTEXTEX ex; - LRESULT rc; - LPSTR bufferA = NULL; - LPWSTR bufferW = NULL; - - if (unicode) - bufferW = heap_alloc((wParam + 2) * sizeof(WCHAR)); - else - bufferA = heap_alloc(wParam + 2); - - ex.cb = (wParam + 2) * (unicode ? sizeof(WCHAR) : sizeof(CHAR)); + ex.cb = wParam * (unicode ? sizeof(WCHAR) : sizeof(CHAR)); ex.flags = GT_USECRLF; ex.codepage = unicode ? 1200 : CP_ACP; ex.lpDefaultChar = NULL; ex.lpUsedDefChar = NULL; - - rc = ME_GetTextEx(editor, &ex, unicode ? (LPARAM)bufferW : (LPARAM)bufferA); - - if (unicode) - { - memcpy((LPWSTR)lParam, bufferW, wParam * sizeof(WCHAR)); - if (strlenW(bufferW) >= wParam) rc = 0; - } - else - { - memcpy((LPSTR)lParam, bufferA, wParam); - if (strlen(bufferA) >= wParam) rc = 0; - } - heap_free(bufferA); - heap_free(bufferW); - return rc; + return ME_GetTextEx(editor, &ex, lParam); } case EM_GETTEXTEX: return ME_GetTextEx(editor, (GETTEXTEX*)wParam, lParam); case EM_GETSELTEXT: { - int from, to; - ME_GetSelection(editor, &from, &to); + int nFrom, nTo, nStartCur = ME_GetSelectionOfs(editor, &nFrom, &nTo); + ME_Cursor *from = &editor->pCursors[nStartCur]; return ME_GetTextRange(editor, (WCHAR *)lParam, from, - to - from, unicode); + nTo - nFrom, unicode); } case EM_GETSCROLLPOS: { POINT *point = (POINT *)lParam; point->x = editor->horz_si.nPos; point->y = editor->vert_si.nPos; + /* 16-bit scaled value is returned as stored in scrollinfo */ + if (editor->horz_si.nMax > 0xffff) + point->x = MulDiv(point->x, 0xffff, editor->horz_si.nMax); + if (editor->vert_si.nMax > 0xffff) + point->y = MulDiv(point->y, 0xffff, editor->vert_si.nMax); return 1; } case EM_GETTEXTRANGE: { TEXTRANGEW *rng = (TEXTRANGEW *)lParam; - int start = rng->chrg.cpMin; - int end = rng->chrg.cpMax; + ME_Cursor start; + int nStart = rng->chrg.cpMin; + int nEnd = rng->chrg.cpMax; int textlength = ME_GetTextLength(editor); - TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d emul1.0=%d length=%d\n", - rng->chrg.cpMin, rng->chrg.cpMax, unicode, - editor->bEmulateVersion10, ME_GetTextLength(editor)); - if (start < 0) return 0; - if ((start == 0 && end == -1) || end > textlength) - end = textlength; - if (start >= end) return 0; - return ME_GetTextRange(editor, rng->lpstrText, start, end - start, unicode); + + TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d textlength=%d\n", + rng->chrg.cpMin, rng->chrg.cpMax, unicode, textlength); + if (nStart < 0) return 0; + if ((nStart == 0 && nEnd == -1) || nEnd > textlength) + nEnd = textlength; + if (nStart >= nEnd) return 0; + + ME_CursorFromCharOfs(editor, nStart, &start); + return ME_GetTextRange(editor, rng->lpstrText, &start, nEnd - nStart, unicode); } case EM_GETLINE: { @@ -3686,14 +3742,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_LINEFROMCHAR: { if (wParam == -1) - return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor, 1)); + return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(&editor->pCursors[1])); else return ME_RowNumberFromCharOfs(editor, wParam); } case EM_EXLINEFROMCHAR: { if (lParam == -1) - return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor,1)); + return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(&editor->pCursors[1])); else return ME_RowNumberFromCharOfs(editor, lParam); } @@ -3809,7 +3865,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_SETZOOM: return ME_SetZoom(editor, wParam, lParam); case EM_CHARFROMPOS: - return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y, NULL); + { + ME_Cursor cursor; + if (ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y, + &cursor, NULL)) + return ME_GetCursorOfs(&cursor); + else + return -1; + } case EM_POSFROMCHAR: { ME_DisplayItem *pPara, *pRun; @@ -3841,23 +3904,29 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case WM_CREATE: { - SCROLLINFO si; + INT max; ME_SetDefaultFormatRect(editor); - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE; + max = (editor->styleFlags & ES_DISABLENOSCROLL) ? 1 : 0; + if (~editor->styleFlags & ES_DISABLENOSCROLL || editor->styleFlags & WS_VSCROLL) + ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, 0, max, TRUE); + + if (~editor->styleFlags & ES_DISABLENOSCROLL || editor->styleFlags & WS_HSCROLL) + ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, 0, max, TRUE); + if (editor->styleFlags & ES_DISABLENOSCROLL) - si.fMask |= SIF_DISABLENOSCROLL; - si.nMax = (si.fMask & SIF_DISABLENOSCROLL) ? 1 : 0; - si.nMin = 0; - si.nPage = 0; - if (editor->hWnd) { - SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE); - SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE); - } else { - ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, TRUE); - ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, TRUE); + { + if (editor->styleFlags & WS_VSCROLL) + { + ITextHost_TxEnableScrollBar(editor->texthost, SB_VERT, ESB_DISABLE_BOTH); + ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, TRUE); + } + if (editor->styleFlags & WS_HSCROLL) + { + ITextHost_TxEnableScrollBar(editor->texthost, SB_HORZ, ESB_DISABLE_BOTH); + ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, TRUE); + } } ME_CommitUndo(editor); @@ -4004,15 +4073,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case SB_THUMBTRACK: case SB_THUMBPOSITION: { - SCROLLINFO sbi; - sbi.cbSize = sizeof(sbi); - sbi.fMask = SIF_TRACKPOS; - /* Try to get 32-bit track position value. */ - if (!GetScrollInfo(editor->hWnd, SB_HORZ, &sbi)) - /* GetScrollInfo failed, settle for 16-bit value in wParam. */ - sbi.nTrackPos = HIWORD(wParam); - - ME_HScrollAbs(editor, sbi.nTrackPos); + int pos = HIWORD(wParam); + if (editor->horz_si.nMax > 0xffff) + pos = MulDiv(pos, editor->horz_si.nMax, 0xffff); + ME_HScrollAbs(editor, pos); break; } } @@ -4056,15 +4120,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case SB_THUMBTRACK: case SB_THUMBPOSITION: { - SCROLLINFO sbi; - sbi.cbSize = sizeof(sbi); - sbi.fMask = SIF_TRACKPOS; - /* Try to get 32-bit track position value. */ - if (!GetScrollInfo(editor->hWnd, SB_VERT, &sbi)) - /* GetScrollInfo failed, settle for 16-bit value in wParam. */ - sbi.nTrackPos = HIWORD(wParam); - - ME_VScrollAbs(editor, sbi.nTrackPos); + int pos = HIWORD(wParam); + if (editor->vert_si.nMax > 0xffff) + pos = MulDiv(pos, editor->vert_si.nMax, 0xffff); + ME_VScrollAbs(editor, pos); break; } } @@ -4186,7 +4245,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return 0; case WM_IME_STARTCOMPOSITION: { - editor->imeStartIndex=ME_GetCursorOfs(editor,0); + editor->imeStartIndex=ME_GetCursorOfs(&editor->pCursors[0]); ME_DeleteSelection(editor); ME_CommitUndo(editor); ME_UpdateRepaint(editor); @@ -4350,7 +4409,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ITextHost *texthost; TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - texthost = ME_CreateTextHost(hWnd, FALSE); + texthost = ME_CreateTextHost(hWnd, pcs, FALSE); return texthost != NULL; } else if (msg != WM_NCDESTROY) @@ -4480,7 +4539,7 @@ LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam; TRACE("WM_NCCREATE: hWnd %p style 0x%08x\n", hWnd, pcs->style); - texthost = ME_CreateTextHost(hWnd, TRUE); + texthost = ME_CreateTextHost(hWnd, pcs, TRUE); return texthost != NULL; } return RichEditANSIWndProc(hWnd, msg, wParam, lParam); @@ -4491,81 +4550,71 @@ void ME_SendOldNotify(ME_TextEditor *editor, int nCode) ITextHost_TxNotify(editor->texthost, nCode, NULL); } -int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to) +/* Fill buffer with srcChars unicode characters from the start cursor. + * + * buffer: destination buffer + * buflen: length of buffer in characters excluding the NULL terminator. + * start: start of editor text to copy into buffer. + * srcChars: Number of characters to use from the editor text. + * bCRLF: if true, replaces all end of lines with \r\n pairs. + * + * returns the number of characters written excluding the NULL terminator. + * + * The written text is always NULL terminated. + */ +int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, + const ME_Cursor *start, int srcChars, BOOL bCRLF) { - ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); - int i = 0; - - while(item && item->member.para.next_para->member.para.nCharOfs <= from) - item = item->member.para.next_para; - if (!item) - return 0; - while(item && item->member.para.next_para->member.para.nCharOfs <= to) { - item = item->member.para.next_para; - i++; - } - return i; -} - - -int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, - int nChars, int bCRLF) -{ - ME_DisplayItem *pRun; - int nOffset, nWritten = 0; - WCHAR *pStart = buffer; - - ME_RunOfsFromCharOfs(editor, nStart, NULL, &pRun, &nOffset); + ME_DisplayItem *pRun, *pNextRun; + const WCHAR *pStart = buffer; + const WCHAR cr_lf[] = {'\r', '\n', 0}; + const WCHAR *str; + int nLen; /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */ if (editor->bEmulateVersion10) bCRLF = 0; - while (nChars && pRun) + pRun = start->pRun; + assert(pRun); + pNextRun = ME_FindItemFwd(pRun, diRun); + + nLen = pRun->member.run.strText->nLen - start->nOffset; + str = pRun->member.run.strText->szData + start->nOffset; + + /* No '\r' is appended to the last paragraph. */ + while (srcChars && buflen && pNextRun) { - int nLen; + int nFlags = pRun->member.run.nFlags; - if (pRun->member.run.nFlags & MERF_ENDCELL && - pRun->member.run.nFlags & MERF_ENDPARA) + if (bCRLF && nFlags & MERF_ENDPARA && ~nFlags & MERF_ENDCELL) { - *buffer = '\t'; - nLen = 1; - } else if (pRun->member.run.nFlags & MERF_ENDPARA) { - if (!ME_FindItemFwd(pRun, diRun)) { - /* No '\r' is appended to the last paragraph. */ - nLen = 0; - } else if (bCRLF && nChars == 1) { - nLen = 0; - nChars = 0; - } else { - WCHAR cr_lf[] = {'\r', '\n', 0}; - WCHAR *szData; - - if (bCRLF) - { - nLen = 2; - szData = cr_lf; - } else { - nLen = pRun->member.run.strText->nLen; - szData = pRun->member.run.strText->szData; - } - nLen = min(nChars, nLen - nOffset); - CopyMemory(buffer, szData + nOffset, sizeof(WCHAR) * nLen); - } + if (buflen == 1) break; + /* FIXME: native fails to reduce srcChars here for WM_GETTEXT or + * EM_GETTEXTEX, however, this is done for copying text which + * also uses this function. */ + srcChars -= min(nLen, srcChars); + nLen = 2; + str = cr_lf; } else { - nLen = min(nChars, pRun->member.run.strText->nLen - nOffset); - CopyMemory(buffer, pRun->member.run.strText->szData + nOffset, - sizeof(WCHAR) * nLen); + nLen = min(nLen, srcChars); + srcChars -= nLen; } - nChars -= nLen; - nWritten += nLen; - buffer += nLen; - nOffset = 0; - pRun = ME_FindItemFwd(pRun, diRun); + nLen = min(nLen, buflen); + buflen -= nLen; + + CopyMemory(buffer, str, sizeof(WCHAR) * nLen); + + buffer += nLen; + + pRun = pNextRun; + pNextRun = ME_FindItemFwd(pRun, diRun); + + nLen = pRun->member.run.strText->nLen; + str = pRun->member.run.strText->szData; } *buffer = 0; - TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart); - return nWritten; + return buffer - pStart; } static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) @@ -4585,9 +4634,9 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) if (is_version_nt()) { - wcW.lpszClassName = RichEdit20W; + wcW.lpszClassName = RICHEDIT_CLASS20W; if (!RegisterClassW(&wcW)) return FALSE; - wcW.lpszClassName = RichEdit50W; + wcW.lpszClassName = MSFTEDIT_CLASS; if (!RegisterClassW(&wcW)) return FALSE; } else @@ -4608,7 +4657,7 @@ static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) wcA.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_IBEAM)); wcA.hbrBackground = GetStockObject(NULL_BRUSH); wcA.lpszMenuName = NULL; - wcA.lpszClassName = "RichEdit20A"; + wcA.lpszClassName = RICHEDIT_CLASS20A; if (!RegisterClassA(&wcA)) return FALSE; wcA.lpszClassName = "RichEdit50A"; if (!RegisterClassA(&wcA)) return FALSE; @@ -4688,145 +4737,135 @@ static BOOL isurlspecial(WCHAR c) * or one of the following special characters: *|/\+%#@ and must consist entirely * of the characters allowed to start the URL, plus : (colon) which may occur * at most once, and not at either end. - * - * sel_max == -1 indicates scan to end of text. */ -static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_max, - int * candidate_min, int * candidate_max) +static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, + const ME_Cursor *start, + int nChars, + ME_Cursor *candidate_min, + ME_Cursor *candidate_max) { - ME_DisplayItem * item; - ME_DisplayItem * para; - int nStart; + ME_Cursor cursor = *start; BOOL foundColon = FALSE; + BOOL candidateStarted = FALSE; WCHAR lastAcceptedChar = '\0'; - TRACE("sel_min = %d sel_max = %d\n", sel_min, sel_max); - - *candidate_min = *candidate_max = -1; - ME_RunOfsFromCharOfs(editor, sel_min, ¶, &item, &nStart); - TRACE("nStart = %d\n", nStart); - if (sel_max == -1) sel_max = ME_GetTextLength(editor); - while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart < sel_max) + while (nChars > 0) { - ME_DisplayItem * next_item; + WCHAR *strStart = cursor.pRun->member.run.strText->szData; + WCHAR *str = strStart + cursor.nOffset; + int nLen = cursor.pRun->member.run.strText->nLen - cursor.nOffset; + nChars -= nLen; - if (!(item->member.run.nFlags & MERF_ENDPARA)) { + if (~cursor.pRun->member.run.nFlags & MERF_ENDPARA) + { /* Find start of candidate */ - if (*candidate_min == -1) { - while (nStart < item->member.run.strText->nLen && - !(isalnumW(item->member.run.strText->szData[nStart]) || - isurlspecial(item->member.run.strText->szData[nStart]))) { - nStart++; - } - if (nStart < item->member.run.strText->nLen && - (isalnumW(item->member.run.strText->szData[nStart]) || - isurlspecial(item->member.run.strText->szData[nStart]))) { - *candidate_min = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; - lastAcceptedChar = item->member.run.strText->szData[nStart]; - nStart++; + if (!candidateStarted) + { + while (nLen) + { + nLen--; + if (isalnumW(*str) || isurlspecial(*str)) + { + cursor.nOffset = str - strStart; + *candidate_min = cursor; + candidateStarted = TRUE; + lastAcceptedChar = *str++; + break; + } + str++; } } /* Find end of candidate */ - if (*candidate_min >= 0) { - while (nStart < item->member.run.strText->nLen && - (isalnumW(item->member.run.strText->szData[nStart]) || - isurlspecial(item->member.run.strText->szData[nStart]) || - (!foundColon && item->member.run.strText->szData[nStart] == ':') )) { - if (item->member.run.strText->szData[nStart] == ':') foundColon = TRUE; - lastAcceptedChar = item->member.run.strText->szData[nStart]; - nStart++; - } - if (nStart < item->member.run.strText->nLen && - !(isalnumW(item->member.run.strText->szData[nStart]) || - isurlspecial(item->member.run.strText->szData[nStart]) )) { - *candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; - nStart++; - if (lastAcceptedChar == ':') (*candidate_max)--; - return TRUE; + if (candidateStarted) { + while (nLen) + { + nLen--; + if (*str == ':' && !foundColon) { + foundColon = TRUE; + } else if (!isalnumW(*str) && !isurlspecial(*str)) { + cursor.nOffset = str - strStart; + if (lastAcceptedChar == ':') + ME_MoveCursorChars(editor, &cursor, -1); + *candidate_max = cursor; + return TRUE; + } + lastAcceptedChar = *str++; } } } else { /* End of paragraph: skip it if before candidate span, or terminates current active span */ - if (*candidate_min >= 0) { - *candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs; - if (lastAcceptedChar == ':') (*candidate_max)--; + if (candidateStarted) { + if (lastAcceptedChar == ':') + ME_MoveCursorChars(editor, &cursor, -1); + *candidate_max = cursor; return TRUE; } } /* Reaching this point means no span was found, so get next span */ - next_item = ME_FindItemFwd(item, diRun); - if (!next_item) { - if (*candidate_min >= 0) { + if (!ME_NextRun(&cursor.pPara, &cursor.pRun)) { + if (candidateStarted) { /* There are no further runs, so take end of text as end of candidate */ - *candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; - if (lastAcceptedChar == ':') (*candidate_max)--; + cursor.nOffset = str - strStart; + if (lastAcceptedChar == ':') + ME_MoveCursorChars(editor, &cursor, -1); + *candidate_max = cursor; return TRUE; } + *candidate_max = *candidate_min = cursor; + return FALSE; } - item = next_item; - para = ME_GetParagraph(item); - nStart = 0; + cursor.nOffset = 0; } - if (item) { - if (*candidate_min >= 0) { - /* There are no further runs, so take end of text as end of candidate */ - *candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; - if (lastAcceptedChar == ':') (*candidate_max)--; - return TRUE; - } + if (candidateStarted) { + /* There are no further runs, so take end of text as end of candidate */ + if (lastAcceptedChar == ':') + ME_MoveCursorChars(editor, &cursor, -1); + *candidate_max = cursor; + return TRUE; } + *candidate_max = *candidate_min = cursor; return FALSE; } /** * This proc evaluates the selection and returns TRUE if it can be considered an URL */ -static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) +static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, int nChars) { +#define MAX_PREFIX_LEN 9 struct prefix_s { - const char *text; + const WCHAR text[MAX_PREFIX_LEN]; int length; - } prefixes[12] = { - /* Code below depends on these being in decreasing length order! */ - {"prospero:", 10}, - {"telnet:", 8}, - {"gopher:", 8}, - {"mailto:", 8}, - {"https:", 7}, - {"file:", 6}, - {"news:", 6}, - {"wais:", 6}, - {"nntp:", 6}, - {"http:", 5}, - {"www.", 5}, - {"ftp:", 5}, + }prefixes[] = { + {{'p','r','o','s','p','e','r','o',':'}, 9}, + {{'t','e','l','n','e','t',':'}, 7}, + {{'g','o','p','h','e','r',':'}, 7}, + {{'m','a','i','l','t','o',':'}, 7}, + {{'h','t','t','p','s',':'}, 6}, + {{'f','i','l','e',':'}, 5}, + {{'n','e','w','s',':'}, 5}, + {{'w','a','i','s',':'}, 5}, + {{'n','n','t','p',':'}, 5}, + {{'h','t','t','p',':'}, 5}, + {{'w','w','w','.'}, 4}, + {{'f','t','p',':'}, 4}, }; - LPWSTR bufferW = NULL; - WCHAR bufW[32]; + WCHAR bufferW[MAX_PREFIX_LEN + 1]; unsigned int i; - if (sel_max == -1) sel_max = ME_GetTextLength(editor); - assert(sel_min <= sel_max); - for (i = 0; i < sizeof(prefixes) / sizeof(struct prefix_s); i++) + ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, 0); + for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++) { - if (sel_max - sel_min < prefixes[i].length) continue; - if (bufferW == NULL) { - bufferW = heap_alloc((sel_max - sel_min + 1) * sizeof(WCHAR)); - } - ME_GetTextW(editor, bufferW, sel_min, min(sel_max - sel_min, lstrlenA(prefixes[i].text)), 0); - MultiByteToWideChar(CP_ACP, 0, prefixes[i].text, -1, bufW, 32); - if (!lstrcmpW(bufW, bufferW)) - { - heap_free(bufferW); + if (nChars < prefixes[i].length) continue; + if (!memcmp(prefixes[i].text, bufferW, prefixes[i].length * sizeof(WCHAR))) return TRUE; - } } - heap_free(bufferW); return FALSE; +#undef MAX_PREFIX_LEN } /** @@ -4835,53 +4874,48 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) * their proper CFE_LINK attributes set or unset. If the CFE_LINK attribute is * not what it is supposed to be, this proc sets or unsets it as appropriate. * + * Since this function can cause runs to be split, do not depend on the value + * of the start cursor at the end of the function. + * + * nChars may be set to INT_MAX to update to the end of the text. + * * Returns TRUE if at least one section was modified. */ -static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_max) +static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, ME_Cursor *start, int nChars) { BOOL modified = FALSE; - int cMin, cMax; + ME_Cursor startCur = *start; if (!editor->AutoURLDetect_bEnable) return FALSE; - if (sel_max == -1) sel_max = ME_GetTextLength(editor); do { - int beforeURL[2]; - int inURL[2]; CHARFORMAT2W link; + ME_Cursor candidateStart, candidateEnd; - if (ME_FindNextURLCandidate(editor, sel_min, sel_max, &cMin, &cMax)) + if (ME_FindNextURLCandidate(editor, &startCur, nChars, + &candidateStart, &candidateEnd)) { /* Section before candidate is not an URL */ - beforeURL[0] = sel_min; - beforeURL[1] = cMin; + int cMin = ME_GetCursorOfs(&candidateStart); + int cMax = ME_GetCursorOfs(&candidateEnd); - if (ME_IsCandidateAnURL(editor, cMin, cMax)) - { - inURL[0] = cMin; inURL[1] = cMax; - } - else - { - beforeURL[1] = cMax; - inURL[0] = inURL[1] = -1; - } - sel_min = cMax; + if (!ME_IsCandidateAnURL(editor, &candidateStart, cMax - cMin)) + candidateStart = candidateEnd; + nChars -= cMax - ME_GetCursorOfs(&startCur); } else { /* No more candidates until end of selection */ - beforeURL[0] = sel_min; - beforeURL[1] = sel_max; - inURL[0] = inURL[1] = -1; - sel_min = sel_max; + nChars = 0; } - if (beforeURL[0] < beforeURL[1]) + if (startCur.pRun != candidateStart.pRun || + startCur.nOffset != candidateStart.nOffset) { /* CFE_LINK effect should be consistently unset */ link.cbSize = sizeof(link); - ME_GetCharFormat(editor, beforeURL[0], beforeURL[1], &link); + ME_GetCharFormat(editor, &startCur, &candidateStart, &link); if (!(link.dwMask & CFM_LINK) || (link.dwEffects & CFE_LINK)) { /* CFE_LINK must be unset from this range */ @@ -4889,15 +4923,24 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_m link.cbSize = sizeof(link); link.dwMask = CFM_LINK; link.dwEffects = 0; - ME_SetCharFormat(editor, beforeURL[0], beforeURL[1] - beforeURL[0], &link); + ME_SetCharFormat(editor, &startCur, &candidateStart, &link); + /* Update candidateEnd since setting character formats may split + * runs, which can cause a cursor to be at an invalid offset within + * a split run. */ + while (candidateEnd.nOffset >= candidateEnd.pRun->member.run.strText->nLen) + { + candidateEnd.nOffset -= candidateEnd.pRun->member.run.strText->nLen; + candidateEnd.pRun = ME_FindItemFwd(candidateEnd.pRun, diRun); + } modified = TRUE; } } - if (inURL[0] < inURL[1]) + if (candidateStart.pRun != candidateEnd.pRun || + candidateStart.nOffset != candidateEnd.nOffset) { /* CFE_LINK effect should be consistently set */ link.cbSize = sizeof(link); - ME_GetCharFormat(editor, inURL[0], inURL[1], &link); + ME_GetCharFormat(editor, &candidateStart, &candidateEnd, &link); if (!(link.dwMask & CFM_LINK) || !(link.dwEffects & CFE_LINK)) { /* CFE_LINK must be set on this range */ @@ -4905,10 +4948,11 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_m link.cbSize = sizeof(link); link.dwMask = CFM_LINK; link.dwEffects = CFE_LINK; - ME_SetCharFormat(editor, inURL[0], inURL[1] - inURL[0], &link); + ME_SetCharFormat(editor, &candidateStart, &candidateEnd, &link); modified = TRUE; } } - } while (sel_min < sel_max); + startCur = candidateEnd; + } while (nChars > 0); return modified; } diff --git a/dll/win32/riched20/editor.h b/dll/win32/riched20/editor.h index 0929e828497..9739eeab95b 100644 --- a/dll/win32/riched20/editor.h +++ b/dll/win32/riched20/editor.h @@ -77,6 +77,8 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt); / /* list.c */ void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat); void ME_Remove(ME_DisplayItem *diWhere); +BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run); +BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run); ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass); ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass); ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass); @@ -95,7 +97,6 @@ ME_String *ME_VSplitString(ME_String *orig, int nVPos); int ME_IsWhitespaces(const ME_String *s); int ME_IsSplitable(const ME_String *s); int ME_FindNonWhitespaceV(const ME_String *s, int nVChar); -int ME_FindWhitespaceV(ME_String *s, int nVChar); int ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code); void ME_StrDeleteV(ME_String *s, int nVChar, int nChars); /* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */ @@ -120,14 +121,11 @@ int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar); /* row.c */ ME_DisplayItem *ME_RowStart(ME_DisplayItem *item); /* ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item); */ -void ME_RenumberParagraphs(ME_DisplayItem *item); /* TODO */ ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow); int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs); /* run.c */ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags); -/* note: ME_InsertRun inserts a copy of the specified run - so you need to destroy the original */ -ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem); ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags); void ME_CheckCharOffsets(ME_TextEditor *editor); @@ -136,49 +134,49 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run); /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run); int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset); -int ME_GetLastSplittablePlace(ME_Context *c, ME_Run *run); int ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2); void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p); ME_DisplayItem *ME_SplitRun(ME_WrapContext *wc, ME_DisplayItem *item, int nChar); ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, int nChar); -int ME_FindSplitPoint(ME_Context *c, POINT *pt, ME_Run *run, int desperate); void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run); -ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *run); void ME_CalcRunExtent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Run *run); SIZE ME_GetRunSize(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx); void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor); void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppPara, ME_DisplayItem **ppRun, int *pOfs); int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, const ME_DisplayItem *pRun, int nOfs); void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift); -void ME_SetCharFormat(ME_TextEditor *editor, int nFrom, int nLen, CHARFORMAT2W *pFmt); +void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt); void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt); -void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nLen, CHARFORMAT2W *pFmt); +void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, + const ME_Cursor *to, CHARFORMAT2W *pFmt); void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt); void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt); void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod); /* caret.c */ +void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor); int ME_SetSelection(ME_TextEditor *editor, int from, int to); void ME_HideCaret(ME_TextEditor *ed); void ME_ShowCaret(ME_TextEditor *ed); void ME_MoveCaret(ME_TextEditor *ed); -int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact); +BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y, ME_Cursor *cursor, BOOL *isExact); void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum); void ME_MouseMove(ME_TextEditor *editor, int x, int y); BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars); void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style); void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor); +int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs); BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl); -int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor); -void ME_GetSelection(ME_TextEditor *editor, int *from, int *to); -int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to); +int ME_GetCursorOfs(const ME_Cursor *cursor); +int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to); +int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to); BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); -BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, BOOL bForce); +BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, BOOL bForce); int ME_GetTextLength(ME_TextEditor *editor); int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how); ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor); @@ -231,8 +229,7 @@ void ME_ScrollRight(ME_TextEditor *editor, int cx); void ME_UpdateScrollBar(ME_TextEditor *editor); /* other functions in paint.c */ -int ME_GetParaBorderWidth(ME_TextEditor *editor, int); -int ME_GetParaLineSpace(ME_Context *c, ME_Paragraph*); +int ME_GetParaBorderWidth(ME_Context *c, int flags); /* richole.c */ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); @@ -246,14 +243,14 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10); LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode, HRESULT* phresult); void ME_SendOldNotify(ME_TextEditor *editor, int nCode); -int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, BOOL bCRLF); +int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, + const ME_Cursor *start, int srcChars, BOOL bCRLF); void ME_RTFCharAttrHook(struct _RTF_Info *info); void ME_RTFParAttrHook(struct _RTF_Info *info); void ME_RTFTblAttrHook(struct _RTF_Info *info); void ME_RTFSpecialCharHook(struct _RTF_Info *info); void ME_StreamInFill(ME_InStream *stream); extern int me_debug; -extern void DoWrap(ME_TextEditor *editor); /* table.c */ BOOL ME_IsInTable(ME_DisplayItem *pItem); @@ -265,7 +262,7 @@ ME_DisplayItem *ME_InsertTableRowEndFromCursor(ME_TextEditor *editor); ME_DisplayItem *ME_GetTableRowEnd(ME_DisplayItem *para); ME_DisplayItem *ME_GetTableRowStart(ME_DisplayItem *para); void ME_CheckTablesForCorruption(ME_TextEditor *editor); -void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars); +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars); ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *table_row); void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow); void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor); @@ -273,7 +270,7 @@ struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor); void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef); /* txthost.c */ -ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10); +ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10); #ifdef __i386__ /* Use wrappers to perform thiscall on i386 */ #define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl) #else /* __i386__ */ @@ -330,8 +327,8 @@ BOOL ME_Redo(ME_TextEditor *editor); void ME_EmptyUndoStack(ME_TextEditor *editor); /* writer.c */ -LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, int nStart, int nTo, EDITSTREAM *stream); +LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, const ME_Cursor *start, int nChars, EDITSTREAM *stream); LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream); /* clipboard.c */ -HRESULT ME_GetDataObject(ME_TextEditor *editor, const CHARRANGE *lpchrg, LPDATAOBJECT *lplpdataobj); +HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, int nChars, LPDATAOBJECT *lplpdataobj); diff --git a/dll/win32/riched20/editstr.h b/dll/win32/riched20/editstr.h index a4af8fe9c0c..9b8d645199e 100644 --- a/dll/win32/riched20/editstr.h +++ b/dll/win32/riched20/editstr.h @@ -29,6 +29,7 @@ #include #include #include +#include #define COBJMACROS #define NONAMELESSUNION @@ -50,7 +51,7 @@ #include "wine/debug.h" #ifdef __i386__ -extern struct ITextHostVtbl itextHostStdcallVtbl; +extern const struct ITextHostVtbl itextHostStdcallVtbl; #endif /* __i386__ */ typedef struct tagME_String @@ -325,7 +326,7 @@ typedef struct tagME_FontCacheItem typedef struct tagME_TextEditor { - HWND hWnd; + HWND hWnd, hwndParent; ITextHost *texthost; BOOL bEmulateVersion10; ME_TextBuffer *pBuffer; @@ -369,6 +370,7 @@ typedef struct tagME_TextEditor BOOL AutoURLDetect_bEnable; WCHAR cPasswordMask; BOOL bHaveFocus; + BOOL bDialogMode; /* Indicates that we are inside a dialog window */ /*for IME */ int imeStartIndex; DWORD selofs; /* The size of the selection bar on the left side of control */ diff --git a/dll/win32/riched20/list.c b/dll/win32/riched20/list.c index d3d9463c04b..bb91bc4de65 100644 --- a/dll/win32/riched20/list.c +++ b/dll/win32/riched20/list.c @@ -44,22 +44,63 @@ void ME_Remove(ME_DisplayItem *diWhere) static BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass) { - if (type==nTypeOrClass) - return TRUE; - if (nTypeOrClass==diRunOrParagraph && (type==diRun || type==diParagraph)) - return TRUE; - if (nTypeOrClass==diRunOrStartRow && (type==diRun || type==diStartRow)) - return TRUE; - if (nTypeOrClass==diParagraphOrEnd && (type==diTextEnd || type==diParagraph)) - return TRUE; - if (nTypeOrClass==diStartRowOrParagraph && (type==diStartRow || type==diParagraph)) - return TRUE; - if (nTypeOrClass==diStartRowOrParagraphOrEnd - && (type==diStartRow || type==diParagraph || type==diTextEnd)) - return TRUE; - if (nTypeOrClass==diRunOrParagraphOrEnd - && (type==diRun || type==diParagraph || type==diTextEnd)) - return TRUE; + switch (nTypeOrClass) + { + case diRunOrParagraph: + return type == diRun || type == diParagraph; + case diRunOrStartRow: + return type == diRun || type == diStartRow; + case diParagraphOrEnd: + return type == diTextEnd || type == diParagraph; + case diStartRowOrParagraph: + return type == diStartRow || type == diParagraph; + case diStartRowOrParagraphOrEnd: + return type == diStartRow || type == diParagraph || type == diTextEnd; + case diRunOrParagraphOrEnd: + return type == diRun || type == diParagraph || type == diTextEnd; + default: + return type == nTypeOrClass; + } +} + +/* Modifies run pointer to point to the next run, and modify the + * paragraph pointer if moving into the next paragraph. + * + * Returns TRUE if next run is found, otherwise returns FALSE. */ +BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run) +{ + ME_DisplayItem *p = (*run)->next; + while (p->type != diTextEnd) + { + if (p->type == diParagraph) { + *para = p; + } else if (p->type == diRun) { + *run = p; + return TRUE; + } + p = p->next; + } + return FALSE; +} + +/* Modifies run pointer to point to the previous run, and modify the + * paragraph pointer if moving into the previous paragraph. + * + * Returns TRUE if previous run is found, otherwise returns FALSE. */ +BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run) +{ + ME_DisplayItem *p = (*run)->prev; + while (p->type != diTextStart) + { + if (p->type == diParagraph) { + if (p->member.para.prev_para->type == diParagraph) + *para = p->member.para.prev_para; + } else if (p->type == diRun) { + *run = p; + return TRUE; + } + p = p->prev; + } return FALSE; } diff --git a/dll/win32/riched20/paint.c b/dll/win32/riched20/paint.c index 620ac69160c..2b01e3c2693 100644 --- a/dll/win32/riched20/paint.c +++ b/dll/win32/riched20/paint.c @@ -413,7 +413,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa return; start = ME_FindItemBack(rundi, diStartRow); - ME_GetSelection(c->editor, &nSelFrom, &nSelTo); + ME_GetSelectionOfs(c->editor, &nSelFrom, &nSelTo); /* Draw selected end-of-paragraph mark */ if (run->nFlags & MERF_ENDPARA) @@ -461,19 +461,21 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa } } -static const struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;} border_details[] = { - /* none */ {0, 1, PS_SOLID, FALSE}, - /* 3/4 */ {3, 4, PS_SOLID, FALSE}, - /* 1 1/2 */ {3, 2, PS_SOLID, FALSE}, - /* 2 1/4 */ {9, 4, PS_SOLID, FALSE}, - /* 3 */ {3, 1, PS_SOLID, FALSE}, - /* 4 1/2 */ {9, 2, PS_SOLID, FALSE}, - /* 6 */ {6, 1, PS_SOLID, FALSE}, - /* 3/4 double */ {3, 4, PS_SOLID, TRUE}, - /* 1 1/2 double */ {3, 2, PS_SOLID, TRUE}, - /* 2 1/4 double */ {9, 4, PS_SOLID, TRUE}, - /* 3/4 gray */ {3, 4, PS_DOT /* FIXME */, FALSE}, - /* 1 1/2 dashed */ {3, 2, PS_DASH, FALSE}, +/* The documented widths are in points (72 dpi), but converting them to + * 96 dpi (standard display resolution) avoids dealing with fractions. */ +static const struct {unsigned width : 8, pen_style : 4, dble : 1;} border_details[] = { + /* none */ {0, PS_SOLID, FALSE}, + /* 3/4 */ {1, PS_SOLID, FALSE}, + /* 1 1/2 */ {2, PS_SOLID, FALSE}, + /* 2 1/4 */ {3, PS_SOLID, FALSE}, + /* 3 */ {4, PS_SOLID, FALSE}, + /* 4 1/2 */ {6, PS_SOLID, FALSE}, + /* 6 */ {8, PS_SOLID, FALSE}, + /* 3/4 double */ {1, PS_SOLID, TRUE}, + /* 1 1/2 double */ {2, PS_SOLID, TRUE}, + /* 2 1/4 double */ {3, PS_SOLID, TRUE}, + /* 3/4 gray */ {1, PS_DOT /* FIXME */, FALSE}, + /* 1 1/2 dashed */ {2, PS_DASH, FALSE}, }; static const COLORREF pen_colors[16] = { @@ -487,25 +489,20 @@ static const COLORREF pen_colors[16] = { /* Dark gray */ RGB(0x80, 0x80, 0x80), /* Light gray */ RGB(0xc0, 0xc0, 0xc0), }; -static int ME_GetBorderPenWidth(ME_TextEditor* editor, int idx) +static int ME_GetBorderPenWidth(ME_Context* c, int idx) { - int width; + int width = border_details[idx].width; + + if (c->dpi.cx != 96) + width = MulDiv(width, c->dpi.cx, 96); + + if (c->editor->nZoomNumerator != 0) + width = MulDiv(width, c->editor->nZoomNumerator, c->editor->nZoomDenominator); - if (editor->nZoomNumerator == 0) - { - width = border_details[idx].width_num + border_details[idx].width_den / 2; - width /= border_details[idx].width_den; - } - else - { - width = border_details[idx].width_num * editor->nZoomNumerator; - width += border_details[idx].width_den * editor->nZoomNumerator / 2; - width /= border_details[idx].width_den * editor->nZoomDenominator; - } return width; } -int ME_GetParaBorderWidth(ME_TextEditor* editor, int flags) +int ME_GetParaBorderWidth(ME_Context* c, int flags) { int idx = (flags >> 8) & 0xF; int width; @@ -515,34 +512,11 @@ int ME_GetParaBorderWidth(ME_TextEditor* editor, int flags) FIXME("Unsupported border value %d\n", idx); return 0; } - width = ME_GetBorderPenWidth(editor, idx); + width = ME_GetBorderPenWidth(c, idx); if (border_details[idx].dble) width = width * 2 + 1; return width; } -int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) -{ - int sp = 0, ls = 0; - if (!(para->pFmt->dwMask & PFM_LINESPACING)) return 0; - - /* FIXME: how to compute simply the line space in ls ??? */ - /* FIXME: does line spacing include the line itself ??? */ - switch (para->pFmt->bLineSpacingRule) - { - case 0: sp = ls; break; - case 1: sp = (3 * ls) / 2; break; - case 2: sp = 2 * ls; break; - case 3: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break; - case 4: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); break; - case 5: sp = para->pFmt->dyLineSpacing / 20; break; - default: FIXME("Unsupported spacing rule value %d\n", para->pFmt->bLineSpacingRule); - } - if (c->editor->nZoomNumerator == 0) - return sp; - else - return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator; -} - static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT* bounds) { int idx, border_width, top_border, bottom_border; @@ -588,7 +562,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT */ if (para->pFmt->wBorders & 0x00B0) FIXME("Unsupported border flags %x\n", para->pFmt->wBorders); - border_width = ME_GetParaBorderWidth(c->editor, para->pFmt->wBorders); + border_width = ME_GetParaBorderWidth(c, para->pFmt->wBorders); if (para->pFmt->wBorders & 4) top_border = border_width; if (para->pFmt->wBorders & 8) bottom_border = border_width; } @@ -630,7 +604,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT rightEdge = c->pt.x + max(c->editor->sizeWindow.cx, c->editor->nTotalWidth); - pen_width = ME_GetBorderPenWidth(c->editor, idx); + pen_width = ME_GetBorderPenWidth(c, idx); pen = CreatePen(border_details[idx].pen_style, pen_width, pencr); oldpen = SelectObject(c->hDC, pen); MoveToEx(c->hDC, 0, 0, &pt); @@ -1036,17 +1010,21 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) if (editor->horz_si.nPos != x) { x = min(x, editor->horz_si.nMax); x = max(x, editor->horz_si.nMin); - ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE); scrollX = editor->horz_si.nPos - x; editor->horz_si.nPos = x; + if (editor->horz_si.nMax > 0xFFFF) /* scale to 16-bit value */ + x = MulDiv(x, 0xFFFF, editor->horz_si.nMax); + ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, x, TRUE); } if (editor->vert_si.nPos != y) { y = min(y, editor->vert_si.nMax - (int)editor->vert_si.nPage); y = max(y, editor->vert_si.nMin); - ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE); scrollY = editor->vert_si.nPos - y; editor->vert_si.nPos = y; + if (editor->vert_si.nMax > 0xFFFF) /* scale to 16-bit value */ + y = MulDiv(y, 0xFFFF, editor->vert_si.nMax); + ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, y, TRUE); } if (abs(scrollX) > editor->sizeWindow.cx || @@ -1061,22 +1039,28 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) if (editor->hWnd) { LONG winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE); - bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0; - bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx - && (editor->styleFlags & WS_HSCROLL)) - || (editor->styleFlags & ES_DISABLENOSCROLL); - if (bScrollBarIsVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, - bScrollBarWillBeVisible); + if (editor->styleFlags & WS_HSCROLL) + { + bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0; + bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx + && (editor->styleFlags & WS_HSCROLL)) + || (editor->styleFlags & ES_DISABLENOSCROLL); + if (bScrollBarIsVisible != bScrollBarWillBeVisible) + ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, + bScrollBarWillBeVisible); + } - bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0; - bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy - && (editor->styleFlags & WS_VSCROLL) - && (editor->styleFlags & ES_MULTILINE)) - || (editor->styleFlags & ES_DISABLENOSCROLL); - if (bScrollBarIsVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, - bScrollBarWillBeVisible); + if (editor->styleFlags & WS_VSCROLL) + { + bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0; + bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy + && (editor->styleFlags & WS_VSCROLL) + && (editor->styleFlags & ES_MULTILINE)) + || (editor->styleFlags & ES_DISABLENOSCROLL); + if (bScrollBarIsVisible != bScrollBarWillBeVisible) + ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, + bScrollBarWillBeVisible); + } } ME_UpdateScrollBar(editor); } @@ -1136,6 +1120,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) si.cbSize = sizeof(si); si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + si.nMin = 0; if (editor->styleFlags & ES_DISABLENOSCROLL) si.fMask |= SIF_DISABLENOSCROLL; @@ -1150,20 +1135,25 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) return; } - si.nMin = 0; si.nMax = editor->nTotalWidth; si.nPos = editor->horz_si.nPos; si.nPage = editor->sizeWindow.cx; - if (si.nMin != editor->horz_si.nMin || - si.nMax != editor->horz_si.nMax || + if (si.nMax != editor->horz_si.nMax || si.nPage != editor->horz_si.nPage) { TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage); - editor->horz_si.nMin = si.nMin; editor->horz_si.nMax = si.nMax; editor->horz_si.nPage = si.nPage; - if (bScrollBarWillBeVisible || bScrollBarWasVisible) { + if ((bScrollBarWillBeVisible || bScrollBarWasVisible) && + editor->styleFlags & WS_HSCROLL) + { + if (si.nMax > 0xFFFF) + { + /* Native scales the scrollbar info to 16-bit external values. */ + si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax); + si.nMax = 0xFFFF; + } if (editor->hWnd) { SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE); } else { @@ -1175,14 +1165,17 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) } } - if (si.fMask & SIF_DISABLENOSCROLL) { - bScrollBarWillBeVisible = TRUE; - } else if (!(editor->styleFlags & WS_HSCROLL)) { - bScrollBarWillBeVisible = FALSE; - } + if (editor->styleFlags & WS_HSCROLL) + { + if (si.fMask & SIF_DISABLENOSCROLL) { + bScrollBarWillBeVisible = TRUE; + } else if (!(editor->styleFlags & WS_HSCROLL)) { + bScrollBarWillBeVisible = FALSE; + } - if (bScrollBarWasVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, bScrollBarWillBeVisible); + if (bScrollBarWasVisible != bScrollBarWillBeVisible) + ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, bScrollBarWillBeVisible); + } /* Update vertical scrollbar */ bScrollBarWasVisible = editor->vert_si.nMax > editor->vert_si.nPage; @@ -1201,15 +1194,21 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) si.nPos = editor->vert_si.nPos; si.nPage = editor->sizeWindow.cy; - if (si.nMin != editor->vert_si.nMin || - si.nMax != editor->vert_si.nMax || + if (si.nMax != editor->vert_si.nMax || si.nPage != editor->vert_si.nPage) { TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage); - editor->vert_si.nMin = si.nMin; editor->vert_si.nMax = si.nMax; editor->vert_si.nPage = si.nPage; - if (bScrollBarWillBeVisible || bScrollBarWasVisible) { + if ((bScrollBarWillBeVisible || bScrollBarWasVisible) && + editor->styleFlags & WS_VSCROLL) + { + if (si.nMax > 0xFFFF) + { + /* Native scales the scrollbar info to 16-bit external values. */ + si.nPos = MulDiv(si.nPos, 0xFFFF, si.nMax); + si.nMax = 0xFFFF; + } if (editor->hWnd) { SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE); } else { @@ -1221,15 +1220,18 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) } } - if (si.fMask & SIF_DISABLENOSCROLL) { - bScrollBarWillBeVisible = TRUE; - } else if (!(editor->styleFlags & WS_VSCROLL)) { - bScrollBarWillBeVisible = FALSE; - } + if (editor->styleFlags & WS_VSCROLL) + { + if (si.fMask & SIF_DISABLENOSCROLL) { + bScrollBarWillBeVisible = TRUE; + } else if (!(editor->styleFlags & WS_VSCROLL)) { + bScrollBarWillBeVisible = FALSE; + } - if (bScrollBarWasVisible != bScrollBarWillBeVisible) - ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, - bScrollBarWillBeVisible); + if (bScrollBarWasVisible != bScrollBarWillBeVisible) + ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, + bScrollBarWillBeVisible); + } } void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) @@ -1242,11 +1244,24 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) assert(pRow); assert(pPara); - x = pRun->pt.x + ME_PointFromChar(editor, pRun, pCursor->nOffset); - if (x > editor->horz_si.nPos + editor->sizeWindow.cx) - x = x + 1 - editor->sizeWindow.cx; - else if (x > editor->horz_si.nPos) + if (editor->styleFlags & ES_AUTOHSCROLL) + { + x = pRun->pt.x + ME_PointFromChar(editor, pRun, pCursor->nOffset); + if (x > editor->horz_si.nPos + editor->sizeWindow.cx) + x = x + 1 - editor->sizeWindow.cx; + else if (x > editor->horz_si.nPos) + x = editor->horz_si.nPos; + + if (~editor->styleFlags & ES_AUTOVSCROLL) + { + ME_HScrollAbs(editor, x); + return; + } + } else { + if (~editor->styleFlags & ES_AUTOVSCROLL) + return; x = editor->horz_si.nPos; + } y = pPara->member.para.pt.y + pRow->member.row.pt.y; yheight = pRow->member.row.nHeight; @@ -1267,7 +1282,7 @@ ME_InvalidateSelection(ME_TextEditor *editor) int nStart, nEnd; int len = ME_GetTextLength(editor); - ME_GetSelection(editor, &nStart, &nEnd); + ME_GetSelectionOfs(editor, &nStart, &nEnd); /* if both old and new selection are 0-char (= caret only), then there's no (inverted) area to be repainted, neither old nor new */ if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd) @@ -1300,7 +1315,7 @@ ME_InvalidateSelection(ME_TextEditor *editor) ME_InvalidateMarkedParagraphs(editor); /* remember the last invalidated position */ - ME_GetSelection(editor, &editor->nLastSelStart, &editor->nLastSelEnd); + ME_GetSelectionOfs(editor, &editor->nLastSelStart, &editor->nLastSelEnd); ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara); assert(editor->pLastSelStartPara->type == diParagraph); assert(editor->pLastSelEndPara->type == diParagraph); diff --git a/dll/win32/riched20/para.c b/dll/win32/riched20/para.c index 94ef7ae709f..b6319e73aa2 100644 --- a/dll/win32/riched20/para.c +++ b/dll/win32/riched20/para.c @@ -335,6 +335,8 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, int i, shift; ME_UndoItem *undo = NULL; int end_len; + CHARFORMAT2W fmt; + ME_Cursor startCur, endCur; assert(tp->type == diParagraph); assert(tp->member.para.next_para); @@ -351,12 +353,15 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, end_len = pRun->member.run.strText->nLen; - { - /* null char format operation to store the original char format for the ENDPARA run */ - CHARFORMAT2W fmt; - ME_InitCharFormat2W(&fmt); - ME_SetCharFormat(editor, pNext->member.para.nCharOfs - end_len, end_len, &fmt); - } + /* null char format operation to store the original char format for the ENDPARA run */ + ME_InitCharFormat2W(&fmt); + endCur.pPara = pNext; + endCur.pRun = ME_FindItemFwd(pNext, diRun); + endCur.nOffset = 0; + startCur = endCur; + ME_PrevRun(&startCur.pPara, &startCur.pRun); + ME_SetCharFormat(editor, &startCur, &endCur, &fmt); + undo = ME_AddUndoItem(editor, diUndoSplitParagraph, pNext); if (undo) { diff --git a/dll/win32/riched20/reader.c b/dll/win32/riched20/reader.c index b6a6f44f255..9f88cf77554 100644 --- a/dll/win32/riched20/reader.c +++ b/dll/win32/riched20/reader.c @@ -442,7 +442,11 @@ static void RTFUngetToken(RTF_Info *info) * increment the value to compensate for it being decremented * twice due to the RTFUngetToken. */ if(RTFCheckCM (info, rtfGroup, rtfEndGroup)) + { + info->stack[info->stackTop].style = info->style; + ME_AddRefStyle(info->style); info->stackTop++; + } } @@ -783,7 +787,6 @@ static void ReadFontTbl(RTF_Info *info) RTFFont *fp = NULL; char buf[rtfBufSiz], *bp; int old = -1; - const char *fn = "ReadFontTbl"; for (;;) { @@ -799,19 +802,19 @@ static void ReadFontTbl(RTF_Info *info) else if (RTFCheckCM (info, rtfGroup, rtfBeginGroup)) old = 0; /* brace */ else /* can't tell! */ - ERR ( "%s: Cannot determine format\n", fn); + ERR ("cannot determine format\n"); } if (old == 0) /* need to find "{" here */ { if (!RTFCheckCM (info, rtfGroup, rtfBeginGroup)) - ERR ( "%s: missing \"{\"\n", fn); + ERR ("missing \"{\"\n"); RTFGetToken (info); /* yes, skip to next token */ if (info->rtfClass == rtfEOF) break; } fp = New (RTFFont); if (fp == NULL) { - ERR ( "%s: cannot allocate font entry\n", fn); + ERR ("cannot allocate font entry\n"); break; } @@ -837,8 +840,8 @@ static void ReadFontTbl(RTF_Info *info) { default: /* ignore token but announce it */ - WARN ("%s: unknown token \"%s\"\n", - fn, info->rtfTextBuf); + WARN ("unknown token \"%s\"\n", + info->rtfTextBuf); break; case rtfFontFamily: fp->rtfFFamily = info->rtfMinor; @@ -899,7 +902,7 @@ static void ReadFontTbl(RTF_Info *info) *bp = '\0'; fp->rtfFName = RTFStrSave (buf); if (fp->rtfFName == NULL) - ERR ( "%s: cannot allocate font name\n", fn); + ERR ("cannot allocate font name\n"); /* already have next token; don't read one */ /* at bottom of loop */ continue; @@ -907,8 +910,7 @@ static void ReadFontTbl(RTF_Info *info) else { /* ignore token but announce it */ - WARN ( "%s: unknown token \"%s\"\n", - fn,info->rtfTextBuf); + WARN ("unknown token \"%s\"\n", info->rtfTextBuf); } RTFGetToken (info); if (info->rtfClass == rtfEOF) @@ -920,7 +922,7 @@ static void ReadFontTbl(RTF_Info *info) { RTFGetToken (info); if (!RTFCheckCM (info, rtfGroup, rtfEndGroup)) - ERR ( "%s: missing \"}\"\n", fn); + ERR ("missing \"}\"\n"); if (info->rtfClass == rtfEOF) break; } @@ -934,7 +936,7 @@ static void ReadFontTbl(RTF_Info *info) } } if (!fp || (fp->rtfFNum == -1)) - ERR( "%s: missing font number\n", fn); + ERR("missing font number\n"); /* * Could check other pieces of structure here, too, I suppose. */ @@ -963,7 +965,6 @@ static void ReadColorTbl(RTF_Info *info) { RTFColor *cp; int cnum = 0; - const char *fn = "ReadColorTbl"; int group_level = 1; for (;;) @@ -986,27 +987,30 @@ static void ReadColorTbl(RTF_Info *info) cp = New (RTFColor); if (cp == NULL) { - ERR ( "%s: cannot allocate color entry\n", fn); + ERR ("cannot allocate color entry\n"); break; } cp->rtfCNum = cnum++; - cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1; cp->rtfNextColor = info->colorList; info->colorList = cp; - while (RTFCheckCM (info, rtfControl, rtfColorName)) - { - switch (info->rtfMinor) - { - case rtfRed: cp->rtfCRed = info->rtfParam; break; - case rtfGreen: cp->rtfCGreen = info->rtfParam; break; - case rtfBlue: cp->rtfCBlue = info->rtfParam; break; - } - RTFGetToken (info); + if (!RTFCheckCM (info, rtfControl, rtfColorName)) + cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = -1; + else { + cp->rtfCRed = cp->rtfCGreen = cp->rtfCBlue = 0; + do { + switch (info->rtfMinor) + { + case rtfRed: cp->rtfCRed = info->rtfParam & 0xFF; break; + case rtfGreen: cp->rtfCGreen = info->rtfParam & 0xFF; break; + case rtfBlue: cp->rtfCBlue = info->rtfParam & 0xFF; break; + } + RTFGetToken (info); + } while (RTFCheckCM (info, rtfControl, rtfColorName)); } if (info->rtfClass == rtfEOF) break; if (!RTFCheckCM (info, rtfText, ';')) - ERR ("%s: malformed entry\n", fn); + ERR ("malformed entry\n"); } RTFRouteToken (info); /* feed "}" back to router */ } @@ -1022,7 +1026,6 @@ static void ReadStyleSheet(RTF_Info *info) RTFStyle *sp; RTFStyleElt *sep, *sepLast; char buf[rtfBufSiz], *bp; - const char *fn = "ReadStyleSheet"; int real_style; for (;;) @@ -1034,7 +1037,7 @@ static void ReadStyleSheet(RTF_Info *info) break; sp = New (RTFStyle); if (sp == NULL) { - ERR ( "%s: cannot allocate stylesheet entry\n", fn); + ERR ("cannot allocate stylesheet entry\n"); break; } sp->rtfSName = NULL; @@ -1048,7 +1051,7 @@ static void ReadStyleSheet(RTF_Info *info) sp->rtfExpanding = 0; info->styleList = sp; if (!RTFCheckCM (info, rtfGroup, rtfBeginGroup)) - ERR ( "%s: missing \"{\"\n", fn); + ERR ("missing \"{\"\n"); real_style = TRUE; for (;;) { @@ -1060,7 +1063,7 @@ static void ReadStyleSheet(RTF_Info *info) { if (RTFCheckMM (info, rtfSpecialChar, rtfOptDest)) { RTFGetToken(info); - ERR( "%s: skipping optional destination\n", fn); + ERR("skipping optional destination\n"); RTFSkipGroup(info); info->rtfClass = rtfGroup; info->rtfMajor = rtfEndGroup; @@ -1102,14 +1105,17 @@ static void ReadStyleSheet(RTF_Info *info) } sep = New (RTFStyleElt); if (sep == NULL) - ERR ( "%s: cannot allocate style element\n", fn); + { + ERR ("cannot allocate style element\n"); + break; + } sep->rtfSEClass = info->rtfClass; sep->rtfSEMajor = info->rtfMajor; sep->rtfSEMinor = info->rtfMinor; sep->rtfSEParam = info->rtfParam; sep->rtfSEText = RTFStrSave (info->rtfTextBuf); if (sep->rtfSEText == NULL) - ERR ( "%s: cannot allocate style element text\n", fn); + ERR ("cannot allocate style element text\n"); if (sepLast == NULL) sp->rtfSSEList = sep; /* first element */ else /* add to end */ @@ -1123,7 +1129,7 @@ static void ReadStyleSheet(RTF_Info *info) * This passes over "{\*\keycode ... }, among * other things. A temporary (perhaps) hack. */ - ERR( "%s: skipping begin\n", fn); + ERR("skipping begin\n"); RTFSkipGroup (info); continue; } @@ -1144,19 +1150,18 @@ static void ReadStyleSheet(RTF_Info *info) *bp = '\0'; sp->rtfSName = RTFStrSave (buf); if (sp->rtfSName == NULL) - ERR ( "%s: cannot allocate style name\n", fn); + ERR ("cannot allocate style name\n"); } else /* unrecognized */ { /* ignore token but announce it */ - WARN ( "%s: unknown token \"%s\"\n", - fn, info->rtfTextBuf); + WARN ("unknown token \"%s\"\n", info->rtfTextBuf); } } if (real_style) { RTFGetToken (info); if (!RTFCheckCM (info, rtfGroup, rtfEndGroup)) - ERR ( "%s: missing \"}\"\n", fn); + ERR ("missing \"}\"\n"); /* * Check over the style structure. A name is a must. * If no style number was specified, check whether it's the @@ -1168,12 +1173,12 @@ static void ReadStyleSheet(RTF_Info *info) * Some German RTF writers use "Standard" instead of "Normal". */ if (sp->rtfSName == NULL) - ERR ( "%s: missing style name\n", fn); + ERR ("missing style name\n"); if (sp->rtfSNum < 0) { if (strncmp (buf, "Normal", 6) != 0 && strncmp (buf, "Standard", 8) != 0) - ERR ( "%s: missing style number\n", fn); + ERR ("missing style number\n"); sp->rtfSNum = rtfNormalStyleNum; } if (sp->rtfSNextPar == -1) /* if \snext not given, */ diff --git a/dll/win32/riched20/richole.c b/dll/win32/riched20/richole.c index 326ecc537d5..5b6b2b666f7 100644 --- a/dll/win32/riched20/richole.c +++ b/dll/win32/riched20/richole.c @@ -315,16 +315,21 @@ IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg, DWORD reco, LPDATAOBJECT *lplpdataobj) { IRichEditOleImpl *This = impl_from_IRichEditOle(me); - CHARRANGE tmpchrg; + ME_Cursor start; + int nChars; TRACE("(%p,%p,%d)\n",This, lpchrg, reco); if(!lplpdataobj) return E_INVALIDARG; if(!lpchrg) { - ME_GetSelection(This->editor, &tmpchrg.cpMin, &tmpchrg.cpMax); - lpchrg = &tmpchrg; + int nFrom, nTo, nStartCur = ME_GetSelectionOfs(This->editor, &nFrom, &nTo); + start = This->editor->pCursors[nStartCur]; + nChars = nTo - nFrom; + } else { + ME_CursorFromCharOfs(This->editor, lpchrg->cpMin, &start); + nChars = lpchrg->cpMax - lpchrg->cpMin; } - return ME_GetDataObject(This->editor, lpchrg, lplpdataobj); + return ME_GetDataObject(This->editor, &start, nChars, lplpdataobj); } static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me) @@ -383,11 +388,10 @@ IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo) TRACE("(%p,%p)\n", This, reo); if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER; - if (reo->poleobj) IOleObject_AddRef(reo->poleobj); - if (reo->pstg) IStorage_AddRef(reo->pstg); - if (reo->polesite) IOleClientSite_AddRef(reo->polesite); ME_InsertOLEFromCursor(This->editor, reo, 0); + ME_CommitUndo(This->editor); + ME_UpdateRepaint(This->editor); return S_OK; } @@ -1725,6 +1729,11 @@ void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize) if (run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0) { convert_sizel(c, &run->ole_obj->sizel, pSize); + if (c->editor->nZoomNumerator != 0) + { + pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + } return; } @@ -1815,53 +1824,45 @@ void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run, GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect); hMemDC = CreateCompatibleDC(c->hDC); SelectObject(hMemDC, stgm.u.hBitmap); - if (!has_size && c->editor->nZoomNumerator == 0) + if (has_size) { - sz.cx = dibsect.dsBm.bmWidth; - sz.cy = dibsect.dsBm.bmHeight; - BitBlt(c->hDC, x, y - dibsect.dsBm.bmHeight, + convert_sizel(c, &run->ole_obj->sizel, &sz); + } else { + sz.cx = MulDiv(dibsect.dsBm.bmWidth, c->dpi.cx, 96); + sz.cy = MulDiv(dibsect.dsBm.bmHeight, c->dpi.cy, 96); + } + if (c->editor->nZoomNumerator != 0) + { + sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + } + if (sz.cx == dibsect.dsBm.bmWidth && sz.cy == dibsect.dsBm.bmHeight) + { + BitBlt(c->hDC, x, y - sz.cy, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, hMemDC, 0, 0, SRCCOPY); - } - else - { - if (has_size) - { - convert_sizel(c, &run->ole_obj->sizel, &sz); - } - else - { - sz.cx = MulDiv(dibsect.dsBm.bmWidth, - c->editor->nZoomNumerator, c->editor->nZoomDenominator); - sz.cy = MulDiv(dibsect.dsBm.bmHeight, - c->editor->nZoomNumerator, c->editor->nZoomDenominator); - } + } else { StretchBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, - hMemDC, 0, 0, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, SRCCOPY); + hMemDC, 0, 0, dibsect.dsBm.bmWidth, + dibsect.dsBm.bmHeight, SRCCOPY); } if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap); break; case TYMED_ENHMF: GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh); - if (!has_size && c->editor->nZoomNumerator == 0) + if (has_size) { - sz.cy = emh.rclBounds.bottom - emh.rclBounds.top; - sz.cx = emh.rclBounds.right - emh.rclBounds.left; + convert_sizel(c, &run->ole_obj->sizel, &sz); + } else { + sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top, c->dpi.cx, 96); + sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left, c->dpi.cy, 96); } - else + if (c->editor->nZoomNumerator != 0) { - if (has_size) - { - convert_sizel(c, &run->ole_obj->sizel, &sz); - } - else - { - sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top, - c->editor->nZoomNumerator, c->editor->nZoomDenominator); - sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left, - c->editor->nZoomNumerator, c->editor->nZoomDenominator); - } + sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator); } + { RECT rc; diff --git a/dll/win32/riched20/rtf.h b/dll/win32/riched20/rtf.h index 3277301b3a2..d8ac32396a8 100644 --- a/dll/win32/riched20/rtf.h +++ b/dll/win32/riched20/rtf.h @@ -1095,7 +1095,7 @@ typedef void (*RTFFuncPtr) (RTF_Info *); /* generic function pointer */ /* RTF parser stack element */ struct tagRTFState { - CHARFORMAT2W fmt; + ME_Style *style; int codePage; int unicodeLength; }; diff --git a/dll/win32/riched20/run.c b/dll/win32/riched20/run.c index cf6c1fcb10f..cd282ec2d84 100644 --- a/dll/win32/riched20/run.c +++ b/dll/win32/riched20/run.c @@ -347,27 +347,6 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags) return item; } -/****************************************************************************** - * ME_InsertRun - * - * Inserts a run at a given character position (offset). - */ -ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem) -{ - ME_Cursor tmp; - ME_DisplayItem *pDI; - - assert(pItem->type == diRun || pItem->type == diUndoInsertRun); - - ME_CursorFromCharOfs(editor, nCharOfs, &tmp); - pDI = ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style, - pItem->member.run.strText->szData, - pItem->member.run.strText->nLen, - pItem->member.run.nFlags); - - return pDI; -} - /****************************************************************************** * ME_InsertRunAtCursor * @@ -571,9 +550,14 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size) { HGDIOBJ hOldFont; - hOldFont = ME_SelectStyleFont(c, s); - GetTextExtentPoint32W(c->hDC, szText, nChars, size); - ME_UnselectStyleFont(c, s, hOldFont); + if (c->hDC) { + hOldFont = ME_SelectStyleFont(c, s); + GetTextExtentPoint32W(c->hDC, szText, nChars, size); + ME_UnselectStyleFont(c, s, hOldFont); + } else { + size->cx = 0; + size->cy = 0; + } } /****************************************************************************** @@ -726,15 +710,13 @@ void ME_CalcRunExtent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Ru /****************************************************************************** * ME_SetSelectionCharFormat - * + * * Applies a style change, either to a current selection, or to insert cursor * (ie. the style next typed characters will use). - */ + */ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) { - int nFrom, nTo; - ME_GetSelection(editor, &nFrom, &nTo); - if (nFrom == nTo) + if (!ME_IsSelection(editor)) { ME_Style *s; if (!editor->pBuffer->pCharStyle) @@ -742,57 +724,85 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) s = ME_ApplyStyle(editor->pBuffer->pCharStyle, pFmt); ME_ReleaseStyle(editor->pBuffer->pCharStyle); editor->pBuffer->pCharStyle = s; + } else { + ME_Cursor *from, *to; + ME_GetSelection(editor, &from, &to); + ME_SetCharFormat(editor, from, to, pFmt); } - else - ME_SetCharFormat(editor, nFrom, nTo-nFrom, pFmt); } /****************************************************************************** * ME_SetCharFormat - * + * * Applies a style change to the specified part of the text - */ -void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt) + * + * The start and end cursors specify the part of the text. These cursors will + * be updated to stay valid, but this function may invalidate other + * non-selection cursors. The end cursor may be NULL to specify all the text + * following the start cursor. + * + * If no text is selected, then nothing is done. + */ +void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt) { - ME_Cursor tmp, tmp2; ME_DisplayItem *para; + ME_DisplayItem *run; + ME_DisplayItem *end_run = NULL; - ME_CursorFromCharOfs(editor, nOfs, &tmp); - if (tmp.nOffset) - tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset); + if (end && start->pRun == end->pRun && start->nOffset == end->nOffset) + return; - ME_CursorFromCharOfs(editor, nOfs+nChars, &tmp2); - if (tmp2.nOffset) - tmp2.pRun = ME_SplitRunSimple(editor, tmp2.pRun, tmp2.nOffset); + if (start->nOffset) + { + /* SplitRunSimple may or may not update the cursors, depending on whether they + * are selection cursors, but we need to make sure they are valid. */ + ME_DisplayItem *split_run = start->pRun; + int split_offset = start->nOffset; + start->pRun = ME_SplitRunSimple(editor, split_run, split_offset); + start->nOffset = 0; + if (end && end->pRun == split_run) + { + end->pRun = start->pRun; + end->nOffset -= split_offset; + } + } - para = tmp.pPara; + if (end && end->nOffset) + { + end_run = end->pRun = ME_SplitRunSimple(editor, end->pRun, end->nOffset); + end->nOffset = 0; + } else if (end) { + end_run = end->pRun; + } + + run = start->pRun; + para = start->pPara; para->member.para.nFlags |= MEPF_REWRAP; - while(tmp.pRun != tmp2.pRun) + while(run != end_run) { ME_UndoItem *undo = NULL; - ME_Style *new_style = ME_ApplyStyle(tmp.pRun->member.run.style, pFmt); + ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt); /* ME_DumpStyle(new_style); */ undo = ME_AddUndoItem(editor, diUndoSetCharFormat, NULL); if (undo) { - undo->nStart = tmp.pRun->member.run.nCharOfs+para->member.para.nCharOfs; - undo->nLen = tmp.pRun->member.run.strText->nLen; - undo->di.member.ustyle = tmp.pRun->member.run.style; + undo->nStart = run->member.run.nCharOfs+para->member.para.nCharOfs; + undo->nLen = run->member.run.strText->nLen; + undo->di.member.ustyle = run->member.run.style; /* we'd have to addref undo...ustyle and release tmp...style but they'd cancel each other out so we can do nothing instead */ } else - ME_ReleaseStyle(tmp.pRun->member.run.style); - tmp.pRun->member.run.style = new_style; - tmp.pRun = ME_FindItemFwd(tmp.pRun, diRunOrParagraph); - if (tmp.pRun->type == diParagraph) + ME_ReleaseStyle(run->member.run.style); + run->member.run.style = new_style; + run = ME_FindItemFwd(run, diRunOrParagraph); + if (run && run->type == diParagraph) { - para = tmp.pRun; - tmp.pRun = ME_FindItemFwd(tmp.pRun, diRun); - if (tmp.pRun != tmp2.pRun) + para = run; + run = ME_FindItemFwd(run, diRun); + if (run != end_run) para->member.para.nFlags |= MEPF_REWRAP; } - assert(tmp.pRun); } } @@ -842,20 +852,20 @@ void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) /****************************************************************************** * ME_GetSelectionCharFormat - * + * * If selection exists, it returns all style elements that are set consistently - * in the whole selection. If not, it just returns the current style. - */ + * in the whole selection. If not, it just returns the current style. + */ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) { - int nFrom, nTo; - ME_GetSelection(editor, &nFrom, &nTo); - if (nFrom == nTo && editor->pBuffer->pCharStyle) + ME_Cursor *from, *to; + if (!ME_IsSelection(editor) && editor->pBuffer->pCharStyle) { ME_CopyCharFormat(pFmt, &editor->pBuffer->pCharStyle->fmt); return; } - ME_GetCharFormat(editor, nFrom, nTo, pFmt); + ME_GetSelection(editor, &from, &to); + ME_GetCharFormat(editor, from, to, pFmt); } /****************************************************************************** @@ -864,16 +874,17 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) * Returns the style consisting of those attributes which are consistently set * in the whole character range. */ -void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *pFmt) +void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, + const ME_Cursor *to, CHARFORMAT2W *pFmt) { ME_DisplayItem *run, *run_end; - int nOffset, nOffset2; CHARFORMAT2W tmp; - ME_RunOfsFromCharOfs(editor, nFrom, NULL, &run, &nOffset); - if (nFrom == nTo) /* special case - if selection is empty, take previous char's formatting */ + run = from->pRun; + /* special case - if selection is empty, take previous char's formatting */ + if (from->pRun == to->pRun && from->nOffset == to->nOffset) { - if (!nOffset) + if (!from->nOffset) { ME_DisplayItem *tmp_run = ME_FindItemBack(run, diRunOrParagraph); if (tmp_run->type == diRun) { @@ -884,10 +895,10 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p ME_GetRunCharFormat(editor, run, pFmt); return; } - - if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */ - nTo--; - ME_RunOfsFromCharOfs(editor, nTo, NULL, &run_end, &nOffset2); + + run_end = to->pRun; + if (!to->nOffset) + run_end = ME_FindItemBack(run_end, diRun); ME_GetRunCharFormat(editor, run, pFmt); diff --git a/dll/win32/riched20/style.c b/dll/win32/riched20/style.c index a3b532ebd43..bb2f808954a 100644 --- a/dll/win32/riched20/style.c +++ b/dll/win32/riched20/style.c @@ -156,6 +156,7 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style) { s->hFont = NULL; s->tm.tmAscent = -1; all_refs++; + TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs); return s; } @@ -449,6 +450,7 @@ void ME_AddRefStyle(ME_Style *s) assert(s->nRefs>0); /* style with 0 references isn't supposed to exist */ s->nRefs++; all_refs++; + TRACE_(richedit_style)("ME_AddRefStyle %p, new refs=%d, total refs=%d\n", s, s->nRefs, all_refs); } void ME_ReleaseStyle(ME_Style *s) @@ -465,16 +467,15 @@ void ME_ReleaseStyle(ME_Style *s) ME_DestroyStyle(s); } -ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) { +ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) +{ if (ME_IsSelection(editor)) { - ME_Cursor c; - int from, to; - + ME_Cursor *from, *to; + ME_GetSelection(editor, &from, &to); - ME_CursorFromCharOfs(editor, from, &c); - ME_AddRefStyle(c.pRun->member.run.style); - return c.pRun->member.run.style; + ME_AddRefStyle(from->pRun->member.run.style); + return from->pRun->member.run.style; } if (editor->pBuffer->pCharStyle) { ME_AddRefStyle(editor->pBuffer->pCharStyle); diff --git a/dll/win32/riched20/table.c b/dll/win32/riched20/table.c index 6c8ca76c4e7..cbfa2b3f771 100644 --- a/dll/win32/riched20/table.c +++ b/dll/win32/riched20/table.c @@ -70,6 +70,7 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor, } tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, paraFlags); + ME_ReleaseStyle(pStyle); cursor->pPara = tp; cursor->pRun = ME_FindItemFwd(tp, diRun); return tp; @@ -95,6 +96,7 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; startRowPara = ME_InsertTableRowStartFromCursor(editor); + savedCursor.pPara = ME_GetParagraph(savedCursor.pRun); editor->pCursors[0] = savedCursor; editor->pCursors[1] = editor->pCursors[0]; @@ -121,8 +123,8 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor) { ME_DisplayItem *para; - WCHAR cr = '\r'; - ME_String *eol_str = ME_MakeStringN(&cr, 1); + WCHAR tab = '\t'; + ME_String *eol_str = ME_MakeStringN(&tab, 1); para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_CELL); return para; } @@ -273,13 +275,14 @@ BOOL ME_IsInTable(ME_DisplayItem *pItem) } /* Table rows should either be deleted completely or not at all. */ -void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars) +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) { - ME_Cursor c, c2; - ME_DisplayItem *this_para, *end_para; - ME_CursorFromCharOfs(editor, nOfs, &c); - this_para = c.pPara; - ME_CursorFromCharOfs(editor, nOfs + *nChars, &c2); + int nOfs = ME_GetCursorOfs(c); + ME_Cursor c2 = *c; + ME_DisplayItem *this_para = c->pPara; + ME_DisplayItem *end_para; + + ME_MoveCursorChars(editor, &c2, *nChars); end_para = c2.pPara; if (c2.pRun->member.run.nFlags & MERF_ENDPARA) { /* End offset might be in the middle of the end paragraph run. @@ -355,27 +358,32 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars) this_para->member.para.pFmt->dwMask & PFM_TABLE && this_para->member.para.pFmt->wEffects & PFE_TABLE) { - pRun = c.pRun; + pRun = c->pRun; /* Find the next tab or end paragraph to use as a delete boundary */ while (!(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) pRun = ME_FindItemFwd(pRun, diRun); nCharsToBoundary = pRun->member.run.nCharOfs - - c.pRun->member.run.nCharOfs - - c.nOffset; + - c->pRun->member.run.nCharOfs + - c->nOffset; *nChars = min(*nChars, nCharsToBoundary); } else if (end_para->member.para.pFmt->dwMask & PFM_TABLE && end_para->member.para.pFmt->wEffects & PFE_TABLE) { /* The deletion starts from before the row, so don't join it with * previous non-empty paragraphs. */ + ME_DisplayItem *curPara; pRun = NULL; - if (nOfs > this_para->member.para.nCharOfs) + if (nOfs > this_para->member.para.nCharOfs) { pRun = ME_FindItemBack(end_para, diRun); - if (!pRun) + curPara = end_para->member.para.prev_para; + } + if (!pRun) { pRun = ME_FindItemFwd(end_para, diRun); + curPara = end_para; + } if (pRun) { - nCharsToBoundary = ME_GetParagraph(pRun)->member.para.nCharOfs + nCharsToBoundary = curPara->member.para.nCharOfs + pRun->member.run.nCharOfs - nOfs; if (nCharsToBoundary >= 0) @@ -549,8 +557,8 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) ME_InvalidateSelection(editor); { int from, to; - from = ME_GetCursorOfs(editor, 0); - to = ME_GetCursorOfs(editor, 1); + from = ME_GetCursorOfs(&editor->pCursors[0]); + to = ME_GetCursorOfs(&editor->pCursors[1]); if (from <= to) { fromCursor = editor->pCursors[0]; diff --git a/dll/win32/riched20/txthost.c b/dll/win32/riched20/txthost.c index 8fabd8388d1..68f44372659 100644 --- a/dll/win32/riched20/txthost.c +++ b/dll/win32/riched20/txthost.c @@ -42,9 +42,9 @@ typedef struct ITextHostImpl { BOOL bEmulateVersion10; } ITextHostImpl; -static ITextHostVtbl textHostVtbl; +static const ITextHostVtbl textHostVtbl; -ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10) +ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) { ITextHostImpl *texthost; texthost = CoTaskMemAlloc(sizeof(*texthost)); @@ -59,7 +59,9 @@ ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10) editor = ME_MakeEditor((ITextHost*)texthost, bEmulateVersion10); editor->exStyleFlags = GetWindowLongW(hwnd, GWL_EXSTYLE); + editor->styleFlags |= GetWindowLongW(hwnd, GWL_STYLE) & ES_WANTRETURN; editor->hWnd = hwnd; /* FIXME: Remove editor's dependence on hWnd */ + editor->hwndParent = cs->hwndParent; SetWindowLongPtrW(hwnd, 0, (LONG_PTR)editor); } @@ -448,9 +450,13 @@ HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, void *pv) { ITextHostImpl *This = (ITextHostImpl *)iface; + ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongPtrW(This->hWnd, 0); HWND hwnd = This->hWnd; - HWND parent = GetParent(hwnd); - UINT id = GetWindowLongW(hwnd, GWLP_ID); + UINT id; + + if (!editor || !editor->hwndParent) return S_OK; + + id = GetWindowLongW(hwnd, GWLP_ID); switch (iNotify) { @@ -471,13 +477,13 @@ HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, info->hwndFrom = hwnd; info->idFrom = id; info->code = iNotify; - SendMessageW(parent, WM_NOTIFY, id, (LPARAM)info); + SendMessageW(editor->hwndParent, WM_NOTIFY, id, (LPARAM)info); break; } case EN_UPDATE: /* Only sent when the window is visible. */ - if (!IsWindowVisible(This->hWnd)) + if (!IsWindowVisible(hwnd)) break; /* Fall through */ case EN_CHANGE: @@ -487,7 +493,7 @@ HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, case EN_MAXTEXT: case EN_SETFOCUS: case EN_VSCROLL: - SendMessageW(parent, WM_COMMAND, MAKEWPARAM(id, iNotify), (LPARAM)hwnd); + SendMessageW(editor->hwndParent, WM_COMMAND, MAKEWPARAM(id, iNotify), (LPARAM)hwnd); break; case EN_MSGFILTER: @@ -528,159 +534,114 @@ HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface, #ifdef __i386__ /* thiscall functions are i386-specific */ #define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern typeof(func) THISCALL(func); \ - __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ + __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext); -DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth); - -static ITextHostVtbl textHostVtbl = { - ITextHostImpl_QueryInterface, - ITextHostImpl_AddRef, - ITextHostImpl_Release, - THISCALL(ITextHostImpl_TxGetDC), - THISCALL(ITextHostImpl_TxReleaseDC), - THISCALL(ITextHostImpl_TxShowScrollBar), - THISCALL(ITextHostImpl_TxEnableScrollBar), - THISCALL(ITextHostImpl_TxSetScrollRange), - THISCALL(ITextHostImpl_TxSetScrollPos), - THISCALL(ITextHostImpl_TxInvalidateRect), - THISCALL(ITextHostImpl_TxViewChange), - THISCALL(ITextHostImpl_TxCreateCaret), - THISCALL(ITextHostImpl_TxShowCaret), - THISCALL(ITextHostImpl_TxSetCaretPos), - THISCALL(ITextHostImpl_TxSetTimer), - THISCALL(ITextHostImpl_TxKillTimer), - THISCALL(ITextHostImpl_TxScrollWindowEx), - THISCALL(ITextHostImpl_TxSetCapture), - THISCALL(ITextHostImpl_TxSetFocus), - THISCALL(ITextHostImpl_TxSetCursor), - THISCALL(ITextHostImpl_TxScreenToClient), - THISCALL(ITextHostImpl_TxClientToScreen), - THISCALL(ITextHostImpl_TxActivate), - THISCALL(ITextHostImpl_TxDeactivate), - THISCALL(ITextHostImpl_TxGetClientRect), - THISCALL(ITextHostImpl_TxGetViewInset), - THISCALL(ITextHostImpl_TxGetCharFormat), - THISCALL(ITextHostImpl_TxGetParaFormat), - THISCALL(ITextHostImpl_TxGetSysColor), - THISCALL(ITextHostImpl_TxGetBackStyle), - THISCALL(ITextHostImpl_TxGetMaxLength), - THISCALL(ITextHostImpl_TxGetScrollBars), - THISCALL(ITextHostImpl_TxGetPasswordChar), - THISCALL(ITextHostImpl_TxGetAcceleratorPos), - THISCALL(ITextHostImpl_TxGetExtent), - THISCALL(ITextHostImpl_OnTxCharFormatChange), - THISCALL(ITextHostImpl_OnTxParaFormatChange), - THISCALL(ITextHostImpl_TxGetPropertyBits), - THISCALL(ITextHostImpl_TxNotify), - THISCALL(ITextHostImpl_TxImmGetContext), - THISCALL(ITextHostImpl_TxImmReleaseContext), - THISCALL(ITextHostImpl_TxGetSelectionBarWidth), -}; +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetDC,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxReleaseDC,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowScrollBar,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxEnableScrollBar,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollRange,20) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetScrollPos,16) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxInvalidateRect,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxViewChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxCreateCaret,16) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxShowCaret,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCaretPos,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetTimer,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxKillTimer,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScrollWindowEx,32) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCapture,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetFocus,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxSetCursor,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxScreenToClient,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxClientToScreen,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxActivate,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxDeactivate,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetClientRect,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetViewInset,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetCharFormat,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetParaFormat,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSysColor,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetBackStyle,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetMaxLength,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetScrollBars,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPasswordChar,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetAcceleratorPos,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetExtent,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxCharFormatChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_OnTxParaFormatChange,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetPropertyBits,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxNotify,12) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmGetContext,4) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxImmReleaseContext,8) +DEFINE_THISCALL_WRAPPER(ITextHostImpl_TxGetSelectionBarWidth,8) #ifdef __i386__ /* thiscall functions are i386-specific */ #define STDCALL(func) __stdcall_ ## func -#define DEFINE_STDCALL_WRAPPER(num,func) \ +#define DEFINE_STDCALL_WRAPPER(num,func,args) \ extern typeof(func) __stdcall_ ## func; \ - __ASM_GLOBAL_FUNC(__stdcall_ ## func, \ + __ASM_STDCALL_FUNC(__stdcall_ ## func, args, \ "popl %eax\n\t" \ "popl %ecx\n\t" \ "pushl %eax\n\t" \ "movl (%ecx), %eax\n\t" \ "jmp *(4*(" #num "))(%eax)" ) -DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC); -DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC); -DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar); -DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar); -DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange); -DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos); -DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect); -DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange); -DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret); -DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret); -DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos); -DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer); -DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer); -DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx); -DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture); -DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus); -DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor); -DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient); -DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen); -DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate); -DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate); -DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect); -DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset); -DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat); -DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat); -DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor); -DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle); -DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength); -DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars); -DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar); -DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos); -DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent); -DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange); -DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange); -DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits); -DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify); -DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext); -DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext); -DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth); +DEFINE_STDCALL_WRAPPER(3,ITextHostImpl_TxGetDC,4) +DEFINE_STDCALL_WRAPPER(4,ITextHostImpl_TxReleaseDC,8) +DEFINE_STDCALL_WRAPPER(5,ITextHostImpl_TxShowScrollBar,12) +DEFINE_STDCALL_WRAPPER(6,ITextHostImpl_TxEnableScrollBar,12) +DEFINE_STDCALL_WRAPPER(7,ITextHostImpl_TxSetScrollRange,20) +DEFINE_STDCALL_WRAPPER(8,ITextHostImpl_TxSetScrollPos,16) +DEFINE_STDCALL_WRAPPER(9,ITextHostImpl_TxInvalidateRect,12) +DEFINE_STDCALL_WRAPPER(10,ITextHostImpl_TxViewChange,8) +DEFINE_STDCALL_WRAPPER(11,ITextHostImpl_TxCreateCaret,16) +DEFINE_STDCALL_WRAPPER(12,ITextHostImpl_TxShowCaret,8) +DEFINE_STDCALL_WRAPPER(13,ITextHostImpl_TxSetCaretPos,12) +DEFINE_STDCALL_WRAPPER(14,ITextHostImpl_TxSetTimer,12) +DEFINE_STDCALL_WRAPPER(15,ITextHostImpl_TxKillTimer,8) +DEFINE_STDCALL_WRAPPER(16,ITextHostImpl_TxScrollWindowEx,32) +DEFINE_STDCALL_WRAPPER(17,ITextHostImpl_TxSetCapture,8) +DEFINE_STDCALL_WRAPPER(18,ITextHostImpl_TxSetFocus,4) +DEFINE_STDCALL_WRAPPER(19,ITextHostImpl_TxSetCursor,12) +DEFINE_STDCALL_WRAPPER(20,ITextHostImpl_TxScreenToClient,8) +DEFINE_STDCALL_WRAPPER(21,ITextHostImpl_TxClientToScreen,8) +DEFINE_STDCALL_WRAPPER(22,ITextHostImpl_TxActivate,8) +DEFINE_STDCALL_WRAPPER(23,ITextHostImpl_TxDeactivate,8) +DEFINE_STDCALL_WRAPPER(24,ITextHostImpl_TxGetClientRect,8) +DEFINE_STDCALL_WRAPPER(25,ITextHostImpl_TxGetViewInset,8) +DEFINE_STDCALL_WRAPPER(26,ITextHostImpl_TxGetCharFormat,8) +DEFINE_STDCALL_WRAPPER(27,ITextHostImpl_TxGetParaFormat,8) +DEFINE_STDCALL_WRAPPER(28,ITextHostImpl_TxGetSysColor,8) +DEFINE_STDCALL_WRAPPER(29,ITextHostImpl_TxGetBackStyle,8) +DEFINE_STDCALL_WRAPPER(30,ITextHostImpl_TxGetMaxLength,8) +DEFINE_STDCALL_WRAPPER(31,ITextHostImpl_TxGetScrollBars,8) +DEFINE_STDCALL_WRAPPER(32,ITextHostImpl_TxGetPasswordChar,8) +DEFINE_STDCALL_WRAPPER(33,ITextHostImpl_TxGetAcceleratorPos,8) +DEFINE_STDCALL_WRAPPER(34,ITextHostImpl_TxGetExtent,8) +DEFINE_STDCALL_WRAPPER(35,ITextHostImpl_OnTxCharFormatChange,8) +DEFINE_STDCALL_WRAPPER(36,ITextHostImpl_OnTxParaFormatChange,8) +DEFINE_STDCALL_WRAPPER(37,ITextHostImpl_TxGetPropertyBits,12) +DEFINE_STDCALL_WRAPPER(38,ITextHostImpl_TxNotify,12) +DEFINE_STDCALL_WRAPPER(39,ITextHostImpl_TxImmGetContext,4) +DEFINE_STDCALL_WRAPPER(40,ITextHostImpl_TxImmReleaseContext,8) +DEFINE_STDCALL_WRAPPER(41,ITextHostImpl_TxGetSelectionBarWidth,8) -ITextHostVtbl itextHostStdcallVtbl = { +const ITextHostVtbl itextHostStdcallVtbl = { NULL, NULL, NULL, @@ -726,3 +687,48 @@ ITextHostVtbl itextHostStdcallVtbl = { }; #endif /* __i386__ */ + +static const ITextHostVtbl textHostVtbl = { + ITextHostImpl_QueryInterface, + ITextHostImpl_AddRef, + ITextHostImpl_Release, + THISCALL(ITextHostImpl_TxGetDC), + THISCALL(ITextHostImpl_TxReleaseDC), + THISCALL(ITextHostImpl_TxShowScrollBar), + THISCALL(ITextHostImpl_TxEnableScrollBar), + THISCALL(ITextHostImpl_TxSetScrollRange), + THISCALL(ITextHostImpl_TxSetScrollPos), + THISCALL(ITextHostImpl_TxInvalidateRect), + THISCALL(ITextHostImpl_TxViewChange), + THISCALL(ITextHostImpl_TxCreateCaret), + THISCALL(ITextHostImpl_TxShowCaret), + THISCALL(ITextHostImpl_TxSetCaretPos), + THISCALL(ITextHostImpl_TxSetTimer), + THISCALL(ITextHostImpl_TxKillTimer), + THISCALL(ITextHostImpl_TxScrollWindowEx), + THISCALL(ITextHostImpl_TxSetCapture), + THISCALL(ITextHostImpl_TxSetFocus), + THISCALL(ITextHostImpl_TxSetCursor), + THISCALL(ITextHostImpl_TxScreenToClient), + THISCALL(ITextHostImpl_TxClientToScreen), + THISCALL(ITextHostImpl_TxActivate), + THISCALL(ITextHostImpl_TxDeactivate), + THISCALL(ITextHostImpl_TxGetClientRect), + THISCALL(ITextHostImpl_TxGetViewInset), + THISCALL(ITextHostImpl_TxGetCharFormat), + THISCALL(ITextHostImpl_TxGetParaFormat), + THISCALL(ITextHostImpl_TxGetSysColor), + THISCALL(ITextHostImpl_TxGetBackStyle), + THISCALL(ITextHostImpl_TxGetMaxLength), + THISCALL(ITextHostImpl_TxGetScrollBars), + THISCALL(ITextHostImpl_TxGetPasswordChar), + THISCALL(ITextHostImpl_TxGetAcceleratorPos), + THISCALL(ITextHostImpl_TxGetExtent), + THISCALL(ITextHostImpl_OnTxCharFormatChange), + THISCALL(ITextHostImpl_OnTxParaFormatChange), + THISCALL(ITextHostImpl_TxGetPropertyBits), + THISCALL(ITextHostImpl_TxNotify), + THISCALL(ITextHostImpl_TxImmGetContext), + THISCALL(ITextHostImpl_TxImmReleaseContext), + THISCALL(ITextHostImpl_TxGetSelectionBarWidth), +}; diff --git a/dll/win32/riched20/txtsrv.c b/dll/win32/riched20/txtsrv.c index a6d81703528..7ab2af45162 100644 --- a/dll/win32/riched20/txtsrv.c +++ b/dll/win32/riched20/txtsrv.c @@ -37,17 +37,17 @@ #ifdef __i386__ /* thiscall functions are i386-specific */ #define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func) \ +#define DEFINE_THISCALL_WRAPPER(func,args) \ extern typeof(func) THISCALL(func); \ - __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ + __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ "popl %eax\n\t" \ "pushl %ecx\n\t" \ "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) ) + "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) #else /* __i386__ */ #define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func) /* nothing */ +#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ #endif /* __i386__ */ @@ -87,6 +87,8 @@ HRESULT WINAPI CreateTextServices(IUnknown * pUnkOuter, ITextImpl->pMyHost = pITextHost; ITextImpl->lpVtbl = &textservices_Vtbl; ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE); + ITextImpl->editor->exStyleFlags = 0; + ITextImpl->editor->rcFormat = (RECT){0,0,0,0}; ME_HandleMessage(ITextImpl->editor, WM_CREATE, 0, 0, TRUE, &hres); if (pUnkOuter) @@ -292,12 +294,14 @@ HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, length = ME_GetTextLength(This->editor); if (length) { + ME_Cursor start; BSTR bstr; bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR)); if (bstr == NULL) return E_OUTOFMEMORY; - ME_GetTextW(This->editor, bstr , 0, length, FALSE); + ME_CursorFromCharOfs(This->editor, 0, &start); + ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE); *pbstrText = bstr; } else { *pbstrText = NULL; @@ -310,9 +314,11 @@ HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText) { ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface); + ME_Cursor cursor; - ME_InternalDeleteText(This->editor, 0, ME_GetTextLength(This->editor), - FALSE); + ME_SetCursorToStart(This->editor, &cursor); + ME_InternalDeleteText(This->editor, &cursor, + ME_GetTextLength(This->editor), FALSE); ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle); ME_SetSelection(This->editor, 0, 0); @@ -387,24 +393,24 @@ HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface, return E_NOTIMPL; } -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget) -DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) static const ITextServicesVtbl textservices_Vtbl = { diff --git a/dll/win32/riched20/undo.c b/dll/win32/riched20/undo.c index c2f7125b621..8db971186ca 100644 --- a/dll/win32/riched20/undo.c +++ b/dll/win32/riched20/undo.c @@ -298,17 +298,28 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) } case diUndoSetCharFormat: { - ME_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt); + ME_Cursor start, end; + ME_CursorFromCharOfs(editor, pUItem->nStart, &start); + end = start; + ME_MoveCursorChars(editor, &end, pUItem->nLen); + ME_SetCharFormat(editor, &start, &end, &pItem->member.ustyle->fmt); break; } case diUndoInsertRun: { - ME_InsertRun(editor, pItem->member.run.nCharOfs, pItem); + ME_Cursor tmp; + ME_CursorFromCharOfs(editor, pItem->member.run.nCharOfs, &tmp); + ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style, + pItem->member.run.strText->szData, + pItem->member.run.strText->nLen, + pItem->member.run.nFlags); break; } case diUndoDeleteRun: { - ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen, TRUE); + ME_Cursor tmp; + ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp); + ME_InternalDeleteText(editor, &tmp, pUItem->nLen, TRUE); break; } case diUndoJoinParagraphs: diff --git a/dll/win32/riched20/wrap.c b/dll/win32/riched20/wrap.c index 579f33ae19f..3b154904f58 100644 --- a/dll/win32/riched20/wrap.c +++ b/dll/win32/riched20/wrap.c @@ -456,6 +456,29 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) return p->next; } +static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) +{ + int sp = 0, ls = 0; + if (!(para->pFmt->dwMask & PFM_LINESPACING)) return 0; + + /* FIXME: how to compute simply the line space in ls ??? */ + /* FIXME: does line spacing include the line itself ??? */ + switch (para->pFmt->bLineSpacingRule) + { + case 0: sp = ls; break; + case 1: sp = (3 * ls) / 2; break; + case 2: sp = 2 * ls; break; + case 3: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break; + case 4: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); break; + case 5: sp = para->pFmt->dyLineSpacing / 20; break; + default: FIXME("Unsupported spacing rule value %d\n", para->pFmt->bLineSpacingRule); + } + if (c->editor->nZoomNumerator == 0) + return sp; + else + return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator; +} + static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp); static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { @@ -499,7 +522,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && pFmt->dwMask & PFM_BORDER) { - border = ME_GetParaBorderWidth(c->editor, tp->member.para.pFmt->wBorders); + border = ME_GetParaBorderWidth(c, tp->member.para.pFmt->wBorders); if (pFmt->wBorders & 1) { wc.nFirstMargin += border; wc.nLeftMargin += border; @@ -580,7 +603,6 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) ME_DisplayItem *item; ME_Context c; BOOL bModified = FALSE; - int yStart = -1; int totalWidth = 0; ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); @@ -598,11 +620,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) ME_WrapTextParagraph(&c, item); if (bRedraw) - { item->member.para.nFlags |= MEPF_REPAINT; - if (yStart == -1) - yStart = c.pt.y; - } bModified = bModified | bRedraw; @@ -776,6 +794,8 @@ ME_SendRequestResize(ME_TextEditor *editor, BOOL force) { REQRESIZE info; + info.nmhdr.hwndFrom = NULL; + info.nmhdr.idFrom = 0; info.nmhdr.code = EN_REQUESTRESIZE; info.rc = rc; info.rc.right = editor->nTotalWidth; diff --git a/dll/win32/riched20/writer.c b/dll/win32/riched20/writer.c index 6cadbd44425..107fadfc70f 100644 --- a/dll/win32/riched20/writer.c +++ b/dll/win32/riched20/writer.c @@ -762,23 +762,23 @@ ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars) } -static BOOL -ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, int dwFormat) +static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, + const ME_Cursor *start, int nChars, int dwFormat) { - ME_DisplayItem *p, *pEnd, *pPara; - int nOffset, nEndLen; + ME_Cursor cursor = *start; + ME_DisplayItem *prev_para = cursor.pPara; + ME_Cursor endCur = cursor; - ME_RunOfsFromCharOfs(editor, nStart, &pPara, &p, &nOffset); - ME_RunOfsFromCharOfs(editor, nStart+nChars, NULL, &pEnd, &nEndLen); + ME_MoveCursorChars(editor, &endCur, nChars); if (!ME_StreamOutRTFHeader(pStream, dwFormat)) return FALSE; - if (!ME_StreamOutRTFFontAndColorTbl(pStream, p, pEnd)) + if (!ME_StreamOutRTFFontAndColorTbl(pStream, cursor.pRun, endCur.pRun)) return FALSE; - + /* TODO: stylesheet table */ - + /* FIXME: maybe emit something smarter for the generator? */ if (!ME_StreamOutPrint(pStream, "{\\*\\generator Wine Riched20 2.0.????;}")) return FALSE; @@ -791,138 +791,129 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC /* TODO: section formatting properties */ - if (!ME_StreamOutRTFParaProps(editor, pStream, ME_GetParagraph(p))) + if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara)) return FALSE; - while(1) - { - switch(p->type) + do { + if (cursor.pPara != prev_para) { - case diParagraph: - if (!editor->bEmulateVersion10) { /* v4.1 */ - if (p->member.para.nFlags & MEPF_ROWSTART) { - pStream->nNestingLevel++; - if (pStream->nNestingLevel == 1) { - if (!ME_StreamOutRTFTableProps(editor, pStream, p)) - return FALSE; - } - } else if (p->member.para.nFlags & MEPF_ROWEND) { - pStream->nNestingLevel--; - if (pStream->nNestingLevel >= 1) { - if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) - return FALSE; - if (!ME_StreamOutRTFTableProps(editor, pStream, p)) - return FALSE; - if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n")) - return FALSE; - } else { - if (!ME_StreamOutPrint(pStream, "\\row \r\n")) - return FALSE; - } - } else if (!ME_StreamOutRTFParaProps(editor, pStream, p)) { - return FALSE; - } - } else { /* v1.0 - 3.0 */ - if (p->member.para.pFmt->dwMask & PFM_TABLE && - p->member.para.pFmt->wEffects & PFE_TABLE) - { - if (!ME_StreamOutRTFTableProps(editor, pStream, p)) + prev_para = cursor.pPara; + if (!editor->bEmulateVersion10) { /* v4.1 */ + if (cursor.pPara->member.para.nFlags & MEPF_ROWSTART) { + pStream->nNestingLevel++; + if (pStream->nNestingLevel == 1) { + if (!ME_StreamOutRTFTableProps(editor, pStream, cursor.pPara)) return FALSE; } - if (!ME_StreamOutRTFParaProps(editor, pStream, p)) - return FALSE; - } - pPara = p; - break; - case diRun: - if (p == pEnd && !nEndLen) - break; - TRACE("flags %xh\n", p->member.run.nFlags); - /* TODO: emit embedded objects */ - if (pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) - break; - if (p->member.run.nFlags & MERF_GRAPHICS) { - FIXME("embedded objects are not handled\n"); - } else if (p->member.run.nFlags & MERF_TAB) { - if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - pPara->member.para.pFmt->dwMask & PFM_TABLE && - pPara->member.para.pFmt->wEffects & PFE_TABLE) - { - if (!ME_StreamOutPrint(pStream, "\\cell ")) + } else if (cursor.pPara->member.para.nFlags & MEPF_ROWEND) { + pStream->nNestingLevel--; + if (pStream->nNestingLevel >= 1) { + if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops")) + return FALSE; + if (!ME_StreamOutRTFTableProps(editor, pStream, cursor.pPara)) + return FALSE; + if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n")) return FALSE; } else { - if (!ME_StreamOutPrint(pStream, "\\tab ")) - return FALSE; - } - } else if (p->member.run.nFlags & MERF_ENDCELL) { - if (pStream->nNestingLevel > 1) { - if (!ME_StreamOutPrint(pStream, "\\nestcell ")) - return FALSE; - } else { - if (!ME_StreamOutPrint(pStream, "\\cell ")) - return FALSE; - } - nChars--; - } else if (p->member.run.nFlags & MERF_ENDPARA) { - if (pPara->member.para.pFmt->dwMask & PFM_TABLE && - pPara->member.para.pFmt->wEffects & PFE_TABLE && - !(pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))) - { if (!ME_StreamOutPrint(pStream, "\\row \r\n")) return FALSE; - } else { - if (!ME_StreamOutPrint(pStream, "\r\n\\par")) - return FALSE; } - /* Skip as many characters as required by current line break */ - nChars = max(0, nChars - p->member.run.strText->nLen); - } else if (p->member.run.nFlags & MERF_ENDROW) { - if (!ME_StreamOutPrint(pStream, "\\line \r\n")) - return FALSE; - nChars--; - } else { - int nEnd; - - if (!ME_StreamOutPrint(pStream, "{")) - return FALSE; - TRACE("style %p\n", p->member.run.style); - if (!ME_StreamOutRTFCharProps(pStream, &p->member.run.style->fmt)) - return FALSE; - - nEnd = (p == pEnd) ? nEndLen : p->member.run.strText->nLen; - if (!ME_StreamOutRTFText(pStream, p->member.run.strText->szData + nOffset, nEnd - nOffset)) - return FALSE; - nOffset = 0; - if (!ME_StreamOutPrint(pStream, "}")) + } else if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara)) { + return FALSE; + } + } else { /* v1.0 - 3.0 */ + if (cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE && + cursor.pPara->member.para.pFmt->wEffects & PFE_TABLE) + { + if (!ME_StreamOutRTFTableProps(editor, pStream, cursor.pPara)) return FALSE; } - break; - default: /* we missed the last item */ - assert(0); + if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara)) + return FALSE; + } } - if (p == pEnd) + + if (cursor.pRun == endCur.pRun && !endCur.nOffset) break; - p = ME_FindItemFwd(p, diRunOrParagraphOrEnd); - } + TRACE("flags %xh\n", cursor.pRun->member.run.nFlags); + /* TODO: emit embedded objects */ + if (cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) + break; + if (cursor.pRun->member.run.nFlags & MERF_GRAPHICS) { + FIXME("embedded objects are not handled\n"); + } else if (cursor.pRun->member.run.nFlags & MERF_TAB) { + if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ + cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE && + cursor.pPara->member.para.pFmt->wEffects & PFE_TABLE) + { + if (!ME_StreamOutPrint(pStream, "\\cell ")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\\tab ")) + return FALSE; + } + } else if (cursor.pRun->member.run.nFlags & MERF_ENDCELL) { + if (pStream->nNestingLevel > 1) { + if (!ME_StreamOutPrint(pStream, "\\nestcell ")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\\cell ")) + return FALSE; + } + nChars--; + } else if (cursor.pRun->member.run.nFlags & MERF_ENDPARA) { + if (cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE && + cursor.pPara->member.para.pFmt->wEffects & PFE_TABLE && + !(cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL))) + { + if (!ME_StreamOutPrint(pStream, "\\row \r\n")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\r\n\\par")) + return FALSE; + } + /* Skip as many characters as required by current line break */ + nChars = max(0, nChars - cursor.pRun->member.run.strText->nLen); + } else if (cursor.pRun->member.run.nFlags & MERF_ENDROW) { + if (!ME_StreamOutPrint(pStream, "\\line \r\n")) + return FALSE; + nChars--; + } else { + int nEnd; + + if (!ME_StreamOutPrint(pStream, "{")) + return FALSE; + TRACE("style %p\n", cursor.pRun->member.run.style); + if (!ME_StreamOutRTFCharProps(pStream, &cursor.pRun->member.run.style->fmt)) + return FALSE; + + nEnd = (cursor.pRun == endCur.pRun) ? endCur.nOffset : cursor.pRun->member.run.strText->nLen; + if (!ME_StreamOutRTFText(pStream, cursor.pRun->member.run.strText->szData + cursor.nOffset, + nEnd - cursor.nOffset)) + return FALSE; + cursor.nOffset = 0; + if (!ME_StreamOutPrint(pStream, "}")) + return FALSE; + } + } while (cursor.pRun != endCur.pRun && ME_NextRun(&cursor.pPara, &cursor.pRun)); + if (!ME_StreamOutMove(pStream, "}\0", 2)) return FALSE; return TRUE; } -static BOOL -ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, DWORD dwFormat) +static BOOL ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, + const ME_Cursor *start, int nChars, DWORD dwFormat) { - ME_DisplayItem *item; + ME_Cursor cursor = *start; int nLen; UINT nCodePage = CP_ACP; char *buffer = NULL; int nBufLen = 0; BOOL success = TRUE; - ME_RunOfsFromCharOfs(editor, nStart, NULL, &item, &nStart); - - if (!item) + if (!cursor.pRun) return FALSE; if (dwFormat & SF_USECODEPAGE) @@ -930,10 +921,10 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n /* TODO: Handle SF_TEXTIZED */ - while (success && nChars && item) { - nLen = min(nChars, item->member.run.strText->nLen - nStart); + while (success && nChars && cursor.pRun) { + nLen = min(nChars, cursor.pRun->member.run.strText->nLen - cursor.nOffset); - if (!editor->bEmulateVersion10 && item->member.run.nFlags & MERF_ENDPARA) + if (!editor->bEmulateVersion10 && cursor.pRun->member.run.nFlags & MERF_ENDPARA) { static const WCHAR szEOL[2] = { '\r', '\n' }; @@ -944,27 +935,27 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n success = ME_StreamOutMove(pStream, "\r\n", 2); } else { if (dwFormat & SF_UNICODE) - success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart), + success = ME_StreamOutMove(pStream, (const char *)(cursor.pRun->member.run.strText->szData + cursor.nOffset), sizeof(WCHAR) * nLen); else { int nSize; - nSize = WideCharToMultiByte(nCodePage, 0, item->member.run.strText->szData + nStart, + nSize = WideCharToMultiByte(nCodePage, 0, cursor.pRun->member.run.strText->szData + cursor.nOffset, nLen, NULL, 0, NULL, NULL); if (nSize > nBufLen) { FREE_OBJ(buffer); buffer = ALLOC_N_OBJ(char, nSize); nBufLen = nSize; } - WideCharToMultiByte(nCodePage, 0, item->member.run.strText->szData + nStart, + WideCharToMultiByte(nCodePage, 0, cursor.pRun->member.run.strText->szData + cursor.nOffset, nLen, buffer, nSize, NULL, NULL); success = ME_StreamOutMove(pStream, buffer, nSize); } } nChars -= nLen; - nStart = 0; - item = ME_FindItemFwd(item, diRun); + cursor.nOffset = 0; + cursor.pRun = ME_FindItemFwd(cursor.pRun, diRun); } FREE_OBJ(buffer); @@ -972,24 +963,16 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n } -LRESULT -ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, int nStart, int nTo, EDITSTREAM *stream) +LRESULT ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, + const ME_Cursor *start, + int nChars, EDITSTREAM *stream) { ME_OutStream *pStream = ME_StreamOutInit(editor, stream); - if (nTo == -1) - { - nTo = ME_GetTextLength(editor); - /* Generate an end-of-paragraph at the end of SCF_ALL RTF output */ - if (dwFormat & SF_RTF) - nTo++; - } - TRACE("from %d to %d\n", nStart, nTo); - if (dwFormat & SF_RTF) - ME_StreamOutRTF(editor, pStream, nStart, nTo - nStart, dwFormat); + ME_StreamOutRTF(editor, pStream, start, nChars, dwFormat); else if (dwFormat & SF_TEXT || dwFormat & SF_TEXTIZED) - ME_StreamOutText(editor, pStream, nStart, nTo - nStart, dwFormat); + ME_StreamOutText(editor, pStream, start, nChars, dwFormat); if (!pStream->stream->dwError) ME_StreamOutFlush(pStream); return ME_StreamOutFree(pStream); @@ -998,13 +981,19 @@ ME_StreamOutRange(ME_TextEditor *editor, DWORD dwFormat, int nStart, int nTo, ED LRESULT ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream) { - int nStart, nTo; + ME_Cursor start; + int nChars; - if (dwFormat & SFF_SELECTION) - ME_GetSelection(editor, &nStart, &nTo); - else { - nStart = 0; - nTo = -1; + if (dwFormat & SFF_SELECTION) { + int nStart, nTo; + start = editor->pCursors[ME_GetSelectionOfs(editor, &nStart, &nTo)]; + nChars = nTo - nStart; + } else { + ME_SetCursorToStart(editor, &start); + nChars = ME_GetTextLength(editor); + /* Generate an end-of-paragraph at the end of SCF_ALL RTF output */ + if (dwFormat & SF_RTF) + nChars++; } - return ME_StreamOutRange(editor, dwFormat, nStart, nTo, stream); + return ME_StreamOutRange(editor, dwFormat, &start, nChars, stream); } diff --git a/dll/win32/rpcrt4/cproxy.c b/dll/win32/rpcrt4/cproxy.c index 6c26d181978..9ce555f7146 100644 --- a/dll/win32/rpcrt4/cproxy.c +++ b/dll/win32/rpcrt4/cproxy.c @@ -2,6 +2,7 @@ * COM proxy implementation * * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2009 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,6 +21,9 @@ * TODO: Handle non-i386 architectures */ +#include "config.h" +#include "wine/port.h" + #include #define COBJMACROS @@ -37,21 +41,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); -struct StublessThunk; - /* I don't know what MS's std proxy structure looks like, so this probably doesn't match, but that shouldn't matter */ typedef struct { const IRpcProxyBufferVtbl *lpVtbl; LPVOID *PVtbl; LONG RefCount; - const MIDL_STUBLESS_PROXY_INFO *stubless; const IID* piid; LPUNKNOWN pUnkOuter; + IUnknown *base_object; /* must be at offset 0x10 from PVtbl */ + IRpcProxyBuffer *base_proxy; PCInterfaceName name; LPPSFACTORYBUFFER pPSFactory; LPRPCCHANNELBUFFER pChannel; - struct StublessThunk *thunks; } StdProxyImpl; static const IRpcProxyBufferVtbl StdProxy_Vtbl; @@ -62,66 +64,111 @@ static const IRpcProxyBufferVtbl StdProxy_Vtbl; #include "pshpack1.h" -struct StublessThunk { +struct thunk { BYTE push; DWORD index; - BYTE call; + BYTE jmp; LONG handler; - BYTE ret; - WORD bytes; - BYTE pad[3]; }; #include "poppack.h" -/* adjust the stack size since we don't use Windows's method */ -#define STACK_ADJUST sizeof(DWORD) +extern void call_stubless_func(void); +__ASM_GLOBAL_FUNC(call_stubless_func, + "pushl %esp\n\t" /* pointer to index */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "call " __ASM_NAME("ObjectStubless") __ASM_STDCALL(4) "\n\t" + "popl %edx\n\t" /* args size */ + __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") + "movl (%esp),%ecx\n\t" /* return address */ + "addl %edx,%esp\n\t" + "jmp *%ecx" ); -#define FILL_STUBLESS(x,idx,stk) \ - x->push = 0x68; /* pushl [immediate] */ \ - x->index = (idx); \ - x->call = 0xe8; /* call [near] */ \ - x->handler = (char*)ObjectStubless - (char*)&x->ret; \ - x->ret = 0xc2; /* ret [immediate] */ \ - x->bytes = stk; \ - x->pad[0] = 0x8d; /* leal (%esi),%esi */ \ - x->pad[1] = 0x76; \ - x->pad[2] = 0x00; - -static HRESULT WINAPI ObjectStubless(DWORD index) +HRESULT WINAPI ObjectStubless(DWORD *args) { - char *args = (char*)(&index + 2); - LPVOID iface = *(LPVOID*)args; + DWORD index = args[0]; + void **iface = (void **)args[2]; + const void **vtbl = (const void **)*iface; + const MIDL_STUBLESS_PROXY_INFO *stubless = *(const MIDL_STUBLESS_PROXY_INFO **)(vtbl - 2); + const PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[index]; - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + /* store bytes to remove from stack */ + args[0] = *(const WORD*)(fs + 8); + TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, args[0], args[1]); - PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index]; - unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; - TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, bytes, *(DWORD*)(args+bytes)); + return NdrClientCall2(stubless->pStubDesc, fs, args + 2); +} - return NdrClientCall2(This->stubless->pStubDesc, fs, args); +#define BLOCK_SIZE 1024 +#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ + +static const struct thunk *method_blocks[MAX_BLOCKS]; + +static const struct thunk *allocate_block( unsigned int num ) +{ + unsigned int i; + struct thunk *prev, *block; + + block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block), + MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); + if (!block) return NULL; + + for (i = 0; i < BLOCK_SIZE; i++) + { + block[i].push = 0x68; /* pushl */ + block[i].index = BLOCK_SIZE * num + i + 3; + block[i].jmp = 0xe9; /* jmp */ + block[i].handler = (char *)call_stubless_func - (char *)(&block[i].handler + 1); + } + VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL ); + prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); + if (prev) /* someone beat us to it */ + { + VirtualFree( block, 0, MEM_RELEASE ); + block = prev; + } + return block; +} + +static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) +{ + const void **entry = (const void **)(vtbl + 1); + DWORD i, j; + + if (num - 3 > BLOCK_SIZE * MAX_BLOCKS) + { + FIXME( "%u methods not supported\n", num ); + return FALSE; + } + for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++) + { + const struct thunk *block = method_blocks[i]; + if (!block && !(block = allocate_block( i ))) return FALSE; + for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++) + if (*entry == (LPVOID)-1) *entry = &block[j]; + } + return TRUE; } #else /* __i386__ */ -/* can't do that on this arch */ -struct StublessThunk { int dummy; }; -#define FILL_STUBLESS(x,idx,stk) \ - ERR("stubless proxies are not supported on this architecture\n"); -#define STACK_ADJUST 0 +static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) +{ + ERR("stubless proxies are not supported on this architecture\n"); + return FALSE; +} #endif /* __i386__ */ -HRESULT WINAPI StdProxy_Construct(REFIID riid, - LPUNKNOWN pUnkOuter, - const ProxyFileInfo *ProxyInfo, - int Index, - LPPSFACTORYBUFFER pPSFactory, - LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppvObj) +HRESULT StdProxy_Construct(REFIID riid, + LPUNKNOWN pUnkOuter, + const ProxyFileInfo *ProxyInfo, + int Index, + LPPSFACTORYBUFFER pPSFactory, + LPRPCPROXYBUFFER *ppProxy, + LPVOID *ppvObj) { StdProxyImpl *This; - const MIDL_STUBLESS_PROXY_INFO *stubless = NULL; PCInterfaceName name = ProxyInfo->pNamesArray[Index]; CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index]; @@ -129,14 +176,12 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid, /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */ if (ProxyInfo->TableVersion > 1) { - stubless = *(const void **)vtbl; + ULONG count = ProxyInfo->pStubVtblList[Index]->header.DispatchTableCount; vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1); - TRACE("stubless=%p\n", stubless); + TRACE("stubless vtbl %p: count=%d\n", vtbl->Vtbl, count ); + fill_stubless_table( (IUnknownVtbl *)vtbl->Vtbl, count ); } - TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); - TRACE("vtbl=%p\n", vtbl->Vtbl); - if (!IsEqualGUID(vtbl->header.piid, riid)) { ERR("IID mismatch during proxy creation\n"); return RPC_E_UNEXPECTED; @@ -145,51 +190,37 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid, This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl)); if (!This) return E_OUTOFMEMORY; - if (stubless) { - CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index]; - unsigned long i, count = svtbl->header.DispatchTableCount; - /* Maybe the original vtbl is just modified directly to point at - * ObjectStublessClientXXX thunks in real Windows, but I don't like it - */ - TRACE("stubless thunks: count=%ld\n", count); - This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count); - This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count); - for (i=0; ithunks[i]; - if (vtbl->Vtbl[i] == (LPVOID)-1) { - PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i]; - unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; - TRACE("method %ld: stacksize=%d\n", i, bytes); - FILL_STUBLESS(thunk, i, bytes) - This->PVtbl[i] = thunk; - } - else { - memset(thunk, 0, sizeof(struct StublessThunk)); - This->PVtbl[i] = vtbl->Vtbl[i]; - } - } - } - else - This->PVtbl = vtbl->Vtbl; - + if (!pUnkOuter) pUnkOuter = (IUnknown *)This; This->lpVtbl = &StdProxy_Vtbl; + This->PVtbl = vtbl->Vtbl; /* one reference for the proxy */ This->RefCount = 1; - This->stubless = stubless; This->piid = vtbl->header.piid; + This->base_object = NULL; + This->base_proxy = NULL; This->pUnkOuter = pUnkOuter; This->name = name; This->pPSFactory = pPSFactory; This->pChannel = NULL; + + if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index]) + { + HRESULT r = create_proxy( ProxyInfo->pDelegatedIIDs[Index], NULL, + &This->base_proxy, (void **)&This->base_object ); + if (FAILED(r)) + { + HeapFree( GetProcessHeap(), 0, This ); + return r; + } + } + *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl; *ppvObj = &This->PVtbl; - /* if there is no outer unknown then the caller will control the lifetime - * of the proxy object through the proxy buffer, so no need to increment the - * ref count of the proxy object */ - if (pUnkOuter) - IUnknown_AddRef((IUnknown *)*ppvObj); + IUnknown_AddRef((IUnknown *)*ppvObj); IPSFactoryBuffer_AddRef(pPSFactory); + TRACE( "iid=%s this %p proxy %p obj %p vtbl %p base proxy %p base obj %p\n", + debugstr_guid(riid), This, *ppProxy, *ppvObj, This->PVtbl, This->base_proxy, This->base_object ); return S_OK; } @@ -200,11 +231,10 @@ static void StdProxy_Destruct(LPRPCPROXYBUFFER iface) if (This->pChannel) IRpcProxyBuffer_Disconnect(iface); + if (This->base_object) IUnknown_Release( This->base_object ); + if (This->base_proxy) IRpcProxyBuffer_Release( This->base_proxy ); + IPSFactoryBuffer_Release(This->pPSFactory); - if (This->thunks) { - HeapFree(GetProcessHeap(),0,This->PVtbl); - HeapFree(GetProcessHeap(),0,This->thunks); - } HeapFree(GetProcessHeap(),0,This); } @@ -259,6 +289,7 @@ static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, This->pChannel = pChannel; IRpcChannelBuffer_AddRef(pChannel); + if (This->base_proxy) IRpcProxyBuffer_Connect( This->base_proxy, pChannel ); return S_OK; } @@ -267,6 +298,8 @@ static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface) ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); TRACE("(%p)->Disconnect()\n",This); + if (This->base_proxy) IRpcProxyBuffer_Disconnect( This->base_proxy ); + IRpcChannelBuffer_Release(This->pChannel); This->pChannel = NULL; } diff --git a/dll/win32/rpcrt4/cpsf.c b/dll/win32/rpcrt4/cpsf.c index bece899d964..ac1eccf56fa 100644 --- a/dll/win32/rpcrt4/cpsf.c +++ b/dll/win32/rpcrt4/cpsf.c @@ -145,6 +145,41 @@ static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl = CStdPSFactory_CreateStub }; + +static void init_psfactory( CStdPSFactoryBuffer *psfac, const ProxyFileInfo **file_list ) +{ + DWORD i, j, k; + + psfac->lpVtbl = &CStdPSFactory_Vtbl; + psfac->RefCount = 0; + psfac->pProxyFileList = file_list; + for (i = 0; file_list[i]; i++) + { + const PCInterfaceProxyVtblList *proxies = file_list[i]->pProxyVtblList; + const PCInterfaceStubVtblList *stubs = file_list[i]->pStubVtblList; + + for (j = 0; j < file_list[i]->TableSize; j++) + { + /* FIXME: i think that different vtables should be copied for + * async interfaces */ + void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl; + void **pRpcStubVtbl = (void **)&stubs[j]->Vtbl; + + if (file_list[i]->pDelegatedIIDs && file_list[i]->pDelegatedIIDs[j]) + { + void **vtbl = proxies[j]->Vtbl; + if (file_list[i]->TableVersion > 1) vtbl++; + fill_delegated_proxy_table( (IUnknownVtbl *)vtbl, stubs[j]->header.DispatchTableCount ); + pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl; + } + + for (k = 0; k < sizeof(IRpcStubBufferVtbl)/sizeof(void *); k++) + if (!pRpcStubVtbl[k]) pRpcStubVtbl[k] = pSrcRpcStubVtbl[k]; + } + } +} + + /*********************************************************************** * NdrDllGetClassObject [RPCRT4.@] */ @@ -158,35 +193,8 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv, pPSFactoryBuffer); *ppv = NULL; - if (!pPSFactoryBuffer->lpVtbl) { - const ProxyFileInfo **pProxyFileList2; - DWORD max_delegating_vtbl_size = 0; - pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl; - pPSFactoryBuffer->RefCount = 0; - pPSFactoryBuffer->pProxyFileList = pProxyFileList; - for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) { - int i; - for (i = 0; i < (*pProxyFileList2)->TableSize; i++) { - /* FIXME: i think that different vtables should be copied for - * async interfaces */ - void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl; - void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl; - unsigned int j; + if (!pPSFactoryBuffer->lpVtbl) init_psfactory( pPSFactoryBuffer, pProxyFileList ); - if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) { - pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl; - if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size) - max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount; - } - - for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++) - if (!pRpcStubVtbl[j]) - pRpcStubVtbl[j] = pSrcRpcStubVtbl[j]; - } - } - if(max_delegating_vtbl_size > 0) - create_delegating_vtbl(max_delegating_vtbl_size); - } if (pclsid && IsEqualGUID(rclsid, pclsid)) return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); else { @@ -207,7 +215,7 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv, */ HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer) { - return !(pPSFactoryBuffer->RefCount); + return pPSFactoryBuffer->RefCount != 0 ? S_FALSE : S_OK; } @@ -266,7 +274,7 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, if (len && len < sizeof(module)) { TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module)); if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) { - RegSetValueExW(subkey, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW)); + RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW)); if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) { RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR)); RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW)); diff --git a/dll/win32/rpcrt4/cpsf.h b/dll/win32/rpcrt4/cpsf.h index d8867d40e60..9cc046ff7ca 100644 --- a/dll/win32/rpcrt4/cpsf.h +++ b/dll/win32/rpcrt4/cpsf.h @@ -21,36 +21,25 @@ #ifndef __WINE_CPSF_H #define __WINE_CPSF_H -HRESULT WINAPI StdProxy_Construct(REFIID riid, - LPUNKNOWN pUnkOuter, - const ProxyFileInfo *ProxyInfo, - int Index, - LPPSFACTORYBUFFER pPSFactory, - LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppvObj); +HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo, + int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy, + LPVOID *ppvObj); -HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub); +HRESULT CStdStubBuffer_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name, + CInterfaceStubVtbl *vtbl, LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub); -HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - REFIID delegating_iid, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub); +HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name, + CInterfaceStubVtbl *vtbl, REFIID delegating_iid, + LPPSFACTORYBUFFER pPSFactory, LPRPCSTUBBUFFER *ppStub); const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface); const IRpcStubBufferVtbl CStdStubBuffer_Vtbl; const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl; -void create_delegating_vtbl(DWORD num_methods); - +BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num); +HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv); HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub); #endif /* __WINE_CPSF_H */ diff --git a/dll/win32/rpcrt4/cstub.c b/dll/win32/rpcrt4/cstub.c index 85411cd81e9..95ac1d89af2 100644 --- a/dll/win32/rpcrt4/cstub.c +++ b/dll/win32/rpcrt4/cstub.c @@ -2,6 +2,7 @@ * COM stub (CStdStubBuffer) implementation * * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2009 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -61,12 +62,12 @@ static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer)); } -HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub) +HRESULT CStdStubBuffer_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub) { CStdStubBuffer *This; IUnknown *pvServer; @@ -113,20 +114,16 @@ typedef struct { DWORD ref; DWORD size; - void **methods; IUnknownVtbl vtbl; /* remaining entries in vtbl */ } ref_counted_vtbl; -static struct -{ - ref_counted_vtbl *table; -} current_vtbl; +static ref_counted_vtbl *current_vtbl; static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv) { - *ppv = (void *)pUnk; + *ppv = pUnk; return S_OK; } @@ -161,87 +158,137 @@ typedef struct { } vtbl_method_t; #include "poppack.h" -static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) -{ - vtbl_method_t *method; - void **entry; - DWORD i; +#define BLOCK_SIZE 1024 +#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ +static const vtbl_method_t *method_blocks[MAX_BLOCKS]; + +static const vtbl_method_t *allocate_block( unsigned int num ) +{ + unsigned int i; + vtbl_method_t *prev, *block; + + block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block), + MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); + if (!block) return NULL; + + for (i = 0; i < BLOCK_SIZE; i++) + { + block[i].mov1 = 0x0424448b; + block[i].mov2 = 0x408b; + block[i].sixteen = 0x10; + block[i].mov3 = 0x04244489; + block[i].mov4 = 0x008b; + block[i].mov5 = 0x808b; + block[i].offset = (BLOCK_SIZE * num + i + 3) << 2; + block[i].jmp = 0xe0ff; + block[i].pad[0] = 0x8d; + block[i].pad[1] = 0x76; + block[i].pad[2] = 0x00; + } + VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL ); + prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); + if (prev) /* someone beat us to it */ + { + VirtualFree( block, 0, MEM_RELEASE ); + block = prev; + } + return block; +} + +static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num) +{ + const void **entry = (const void **)(vtbl + 1); + DWORD i, j; + + if (num - 3 > BLOCK_SIZE * MAX_BLOCKS) + { + FIXME( "%u methods not supported\n", num ); + return FALSE; + } vtbl->QueryInterface = delegating_QueryInterface; vtbl->AddRef = delegating_AddRef; vtbl->Release = delegating_Release; - - method = (vtbl_method_t*)methods; - entry = (void**)(vtbl + 1); - - for(i = 3; i < num; i++) + for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++) { - *entry = method; - method->mov1 = 0x0424448b; - method->mov2 = 0x408b; - method->sixteen = 0x10; - method->mov3 = 0x04244489; - method->mov4 = 0x008b; - method->mov5 = 0x808b; - method->offset = i << 2; - method->jmp = 0xe0ff; - method->pad[0] = 0x8d; - method->pad[1] = 0x76; - method->pad[2] = 0x00; - - method++; - entry++; + const vtbl_method_t *block = method_blocks[i]; + if (!block && !(block = allocate_block( i ))) return FALSE; + for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++) *entry++ = &block[j]; } + return TRUE; +} + +BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) +{ + const void **entry = (const void **)(vtbl + 1); + DWORD i, j; + + if (num - 3 > BLOCK_SIZE * MAX_BLOCKS) + { + FIXME( "%u methods not supported\n", num ); + return FALSE; + } + vtbl->QueryInterface = IUnknown_QueryInterface_Proxy; + vtbl->AddRef = IUnknown_AddRef_Proxy; + vtbl->Release = IUnknown_Release_Proxy; + for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++) + { + const vtbl_method_t *block = method_blocks[i]; + if (!block && !(block = allocate_block( i ))) return FALSE; + for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++) + if (!*entry) *entry = &block[j]; + } + return TRUE; } #else /* __i386__ */ -typedef struct {int dummy;} vtbl_method_t; -static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) +static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num) { ERR("delegated stubs are not supported on this architecture\n"); + return FALSE; +} + +BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) +{ + ERR("delegated proxies are not supported on this architecture\n"); + return FALSE; } #endif /* __i386__ */ -void create_delegating_vtbl(DWORD num_methods) -{ - TRACE("%d\n", num_methods); - if(num_methods <= 3) - { - ERR("should have more than %d methods\n", num_methods); - return; - } - - EnterCriticalSection(&delegating_vtbl_section); - if(!current_vtbl.table || num_methods > current_vtbl.table->size) - { - DWORD size; - DWORD old_protect; - if(current_vtbl.table && current_vtbl.table->ref == 0) - { - TRACE("freeing old table\n"); - VirtualFree(current_vtbl.table->methods, 0, MEM_RELEASE); - HeapFree(GetProcessHeap(), 0, current_vtbl.table); - } - size = (num_methods - 3) * sizeof(vtbl_method_t); - current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); - current_vtbl.table->ref = 0; - current_vtbl.table->size = num_methods; - current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - fill_table(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods); - VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect); - } - LeaveCriticalSection(&delegating_vtbl_section); -} - -static IUnknownVtbl *get_delegating_vtbl(void) +static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods) { IUnknownVtbl *ret; + if (num_methods < 256) num_methods = 256; /* avoid frequent reallocations */ + EnterCriticalSection(&delegating_vtbl_section); - current_vtbl.table->ref++; - ret = ¤t_vtbl.table->vtbl; + + if(!current_vtbl || num_methods > current_vtbl->size) + { + ref_counted_vtbl *table = HeapAlloc(GetProcessHeap(), 0, + FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); + if (!table) + { + LeaveCriticalSection(&delegating_vtbl_section); + return NULL; + } + + table->ref = 0; + table->size = num_methods; + fill_delegated_stub_table(&table->vtbl, num_methods); + + if (current_vtbl && current_vtbl->ref == 0) + { + TRACE("freeing old table\n"); + HeapFree(GetProcessHeap(), 0, current_vtbl); + } + current_vtbl = table; + } + + current_vtbl->ref++; + ret = ¤t_vtbl->vtbl; LeaveCriticalSection(&delegating_vtbl_section); return ret; } @@ -253,22 +300,21 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl) EnterCriticalSection(&delegating_vtbl_section); table->ref--; TRACE("ref now %d\n", table->ref); - if(table->ref == 0 && table != current_vtbl.table) + if(table->ref == 0 && table != current_vtbl) { TRACE("... and we're not current so free'ing\n"); - VirtualFree(current_vtbl.table->methods, 0, MEM_RELEASE); HeapFree(GetProcessHeap(), 0, table); } LeaveCriticalSection(&delegating_vtbl_section); } -HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - REFIID delegating_iid, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub) +HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + REFIID delegating_iid, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub) { cstdstubbuffer_delegating_t *This; IUnknown *pvServer; @@ -294,7 +340,7 @@ HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, return E_OUTOFMEMORY; } - This->base_obj = get_delegating_vtbl(); + This->base_obj = get_delegating_vtbl( vtbl->header.DispatchTableCount ); r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub); if(FAILED(r)) { diff --git a/dll/win32/rpcrt4/ndr_contexthandle.c b/dll/win32/rpcrt4/ndr_contexthandle.c index 15192a72878..cab0fc5d86e 100644 --- a/dll/win32/rpcrt4/ndr_contexthandle.c +++ b/dll/win32/rpcrt4/ndr_contexthandle.c @@ -59,7 +59,7 @@ static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 }; static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext) { - struct context_handle_entry *che = (struct context_handle_entry*) CContext; + struct context_handle_entry *che = CContext; if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) return NULL; @@ -111,7 +111,7 @@ void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff) } else { - ndr_context_handle *wire_data = (ndr_context_handle *)pBuff; + ndr_context_handle *wire_data = pBuff; wire_data->attributes = 0; wire_data->uuid = GUID_NULL; } diff --git a/dll/win32/rpcrt4/ndr_fullpointer.c b/dll/win32/rpcrt4/ndr_fullpointer.c index b686683f6f4..2bbd2b2b1aa 100644 --- a/dll/win32/rpcrt4/ndr_fullpointer.c +++ b/dll/win32/rpcrt4/ndr_fullpointer.c @@ -161,6 +161,9 @@ int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, { TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); + if (!RefId) + return 1; + expand_pointer_table_if_necessary(pXlatTables, RefId); pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId); diff --git a/dll/win32/rpcrt4/ndr_marshall.c b/dll/win32/rpcrt4/ndr_marshall.c index d1b57fd187a..9946bd13d57 100644 --- a/dll/win32/rpcrt4/ndr_marshall.c +++ b/dll/win32/rpcrt4/ndr_marshall.c @@ -39,6 +39,7 @@ #include "ndr_misc.h" #include "rpcndr.h" +#include "ndrtypes.h" #include "wine/unicode.h" #include "wine/rpcfc.h" @@ -113,6 +114,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); #define NDR_TABLE_SIZE 128 #define NDR_TABLE_MASK 127 +#define NDRSContextFromValue(user_context) (NDR_SCONTEXT)((char *)(user_context) - (char *)NDRSContextValue((NDR_SCONTEXT)NULL)) + static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); @@ -548,7 +551,8 @@ PFORMAT_STRING ComputeConformanceOrVariance( } break; default: - FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); + FIXME("unknown conformance type %x, expect crash.\n", pFormat[0] & 0xf0); + goto finish_conf; } switch (pFormat[1]) { @@ -935,7 +939,7 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (type == RPC_FC_FP) NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, - base_ptr_val); + *pPointer); } TRACE("pointer=%p\n", *pPointer); @@ -1778,7 +1782,7 @@ static inline void array_compute_and_size_conformance( break; case RPC_FC_C_CSTRING: case RPC_FC_C_WSTRING: - if (pFormat[0] == RPC_FC_C_CSTRING) + if (fc == RPC_FC_C_CSTRING) { TRACE("string=%s\n", debugstr_a((const char *)pMemory)); pStubMsg->ActualCount = strlen((const char *)pMemory)+1; @@ -1789,7 +1793,7 @@ static inline void array_compute_and_size_conformance( pStubMsg->ActualCount = strlenW((LPCWSTR)pMemory)+1; } - if (fc == RPC_FC_STRING_SIZED) + if (pFormat[1] == RPC_FC_STRING_SIZED) pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); else pStubMsg->MaxCount = pStubMsg->ActualCount; @@ -2692,17 +2696,33 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, safe_copy_to_buffer(pStubMsg, pMemory, 4); pMemory += 4; break; + case RPC_FC_FLOAT: + TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); + pMemory += sizeof(float); + break; case RPC_FC_HYPER: TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); safe_copy_to_buffer(pStubMsg, pMemory, 8); pMemory += 8; break; + case RPC_FC_DOUBLE: + TRACE("double=%f <= %p\n", *(double*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double)); + pMemory += sizeof(double); + break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); TRACE("pStubMsg->Buffer before %p\n", pStubMsg->Buffer); + if (*pFormat != RPC_FC_POINTER) + pPointer = pFormat; if (*pPointer != RPC_FC_RP) ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; @@ -2724,7 +2744,10 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } TRACE("pStubMsg->Buffer after %p\n", pStubMsg->Buffer); - pPointer += 4; + if (*pFormat == RPC_FC_POINTER) + pPointer += 4; + else + pFormat += 4; pMemory += sizeof(void *); break; } @@ -2821,16 +2844,32 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); pMemory += 4; break; + case RPC_FC_FLOAT: + safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float)); + TRACE("float=%f => %p\n", *(float*)pMemory, pMemory); + pMemory += sizeof(float); + break; case RPC_FC_HYPER: safe_copy_from_buffer(pStubMsg, pMemory, 8); TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); pMemory += 8; break; + case RPC_FC_DOUBLE: + safe_copy_from_buffer(pStubMsg, pMemory, sizeof(double)); + TRACE("double=%f => %p\n", *(double*)pMemory, pMemory); + pMemory += sizeof(double); + break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; TRACE("pointer => %p\n", pMemory); + if (*pFormat != RPC_FC_POINTER) + pPointer = pFormat; if (*pPointer != RPC_FC_RP) ALIGN_POINTER(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; @@ -2852,7 +2891,10 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } - pPointer += 4; + if (*pFormat == RPC_FC_POINTER) + pPointer += 4; + else + pFormat += 4; pMemory += sizeof(void *); break; } @@ -2946,14 +2988,22 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: + case RPC_FC_FLOAT: safe_buffer_length_increment(pStubMsg, 4); pMemory += 4; break; case RPC_FC_HYPER: + case RPC_FC_DOUBLE: safe_buffer_length_increment(pStubMsg, 8); pMemory += 8; break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: + if (*pFormat != RPC_FC_POINTER) + pPointer = pFormat; if (!pStubMsg->IgnoreEmbeddedPointers) { int saved_buffer_length = pStubMsg->BufferLength; @@ -2970,7 +3020,10 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ALIGN_LENGTH(pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } - pPointer += 4; + if (*pFormat == RPC_FC_POINTER) + pPointer += 4; + else + pFormat += 4; pMemory += sizeof(void*); break; case RPC_FC_ALIGNM2: @@ -3049,14 +3102,25 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_ULONG: case RPC_FC_ENUM16: case RPC_FC_ENUM32: + case RPC_FC_FLOAT: pMemory += 4; break; case RPC_FC_HYPER: + case RPC_FC_DOUBLE: pMemory += 8; break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: + if (*pFormat != RPC_FC_POINTER) + pPointer = pFormat; NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); - pPointer += 4; + if (*pFormat == RPC_FC_POINTER) + pPointer += 4; + else + pFormat += 4; pMemory += sizeof(void *); break; case RPC_FC_ALIGNM2: @@ -3137,17 +3201,25 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: + case RPC_FC_FLOAT: size += 4; safe_buffer_increment(pStubMsg, 4); break; case RPC_FC_HYPER: + case RPC_FC_DOUBLE: size += 8; safe_buffer_increment(pStubMsg, 8); break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: { unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; + if (*pFormat != RPC_FC_POINTER) + pPointer = pFormat; if (*pPointer != RPC_FC_RP) ALIGN_POINTER(pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; @@ -3170,7 +3242,10 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (*pPointer != RPC_FC_RP) safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ } - pPointer += 4; + if (*pFormat == RPC_FC_POINTER) + pPointer += 4; + else + pFormat += 4; size += sizeof(void *); break; } @@ -3232,13 +3307,21 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) case RPC_FC_ULONG: case RPC_FC_ENUM16: case RPC_FC_ENUM32: + case RPC_FC_FLOAT: size += 4; break; case RPC_FC_HYPER: + case RPC_FC_DOUBLE: size += 8; break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: case RPC_FC_POINTER: size += sizeof(void *); + if (*pFormat != RPC_FC_POINTER) + pFormat += 4; break; case RPC_FC_ALIGNM2: ALIGN_LENGTH(size, 2); @@ -6687,10 +6770,19 @@ static unsigned char *WINAPI NdrContextHandleMarshall( } TRACE("flags: 0x%02x\n", pFormat[1]); - if (pFormat[1] & 0x80) - NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); + if (pStubMsg->IsClient) + { + if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR) + NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); + else + NdrClientContextMarshall(pStubMsg, pMemory, FALSE); + } else - NdrClientContextMarshall(pStubMsg, pMemory, FALSE); + { + NDR_SCONTEXT ctxt = NDRSContextFromValue(pMemory); + NDR_RUNDOWN rundown = pStubMsg->StubDesc->apfnNdrRundownRoutines[pFormat[2]]; + NdrServerContextNewMarshall(pStubMsg, ctxt, rundown, pFormat); + } return NULL; } @@ -6714,10 +6806,22 @@ static unsigned char *WINAPI NdrContextHandleUnmarshall( } TRACE("flags: 0x%02x\n", pFormat[1]); - /* [out]-only or [ret] param */ - if ((pFormat[1] & 0x60) == 0x20) - **(NDR_CCONTEXT **)ppMemory = NULL; - NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); + if (pStubMsg->IsClient) + { + /* [out]-only or [ret] param */ + if ((pFormat[1] & (HANDLE_PARAM_IS_IN|HANDLE_PARAM_IS_OUT)) == HANDLE_PARAM_IS_OUT) + **(NDR_CCONTEXT **)ppMemory = NULL; + NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); + } + else + { + NDR_SCONTEXT ctxt; + ctxt = NdrServerContextNewUnmarshall(pStubMsg, pFormat); + if (pFormat[1] & HANDLE_PARAM_IS_VIA_PTR) + *(void **)ppMemory = NDRSContextValue(ctxt); + else + *(void **)ppMemory = *NDRSContextValue(ctxt); + } return NULL; } diff --git a/dll/win32/rpcrt4/ndr_misc.h b/dll/win32/rpcrt4/ndr_misc.h index c3beff4d725..b0150c3a2eb 100644 --- a/dll/win32/rpcrt4/ndr_misc.h +++ b/dll/win32/rpcrt4/ndr_misc.h @@ -62,6 +62,6 @@ extern const NDR_BUFFERSIZE NdrBufferSizer[]; extern const NDR_MEMORYSIZE NdrMemorySizer[]; extern const NDR_FREE NdrFreer[]; -unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat); +ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat); #endif /* __WINE_NDR_MISC_H */ diff --git a/dll/win32/rpcrt4/ndr_ole.c b/dll/win32/rpcrt4/ndr_ole.c index a3264e70122..a4c23c2c5c2 100644 --- a/dll/win32/rpcrt4/ndr_ole.c +++ b/dll/win32/rpcrt4/ndr_ole.c @@ -369,6 +369,30 @@ void WINAPI NdrOleFree(void *NodeToFree) COM_MemFree(NodeToFree); } +/*********************************************************************** + * Helper function to create a proxy. + * Probably similar to NdrpCreateProxy. + */ +HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv) +{ + CLSID clsid; + IPSFactoryBuffer *psfac; + HRESULT r; + + if(!LoadCOM()) return E_FAIL; + + r = COM_GetPSClsid( iid, &clsid ); + if(FAILED(r)) return r; + + r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); + if(FAILED(r)) return r; + + r = IPSFactoryBuffer_CreateProxy(psfac, pUnkOuter, iid, pproxy, ppv); + + IPSFactoryBuffer_Release(psfac); + return r; +} + /*********************************************************************** * Helper function to create a stub. * This probably looks very much like NdrpCreateStub. diff --git a/dll/win32/rpcrt4/rpc_transport.c b/dll/win32/rpcrt4/rpc_transport.c index b9077a3dc1a..2da72909c23 100644 --- a/dll/win32/rpcrt4/rpc_transport.c +++ b/dll/win32/rpcrt4/rpc_transport.c @@ -762,7 +762,7 @@ typedef struct _RpcConnection_tcp { RpcConnection common; int sock; - int cancel_fds[2]; + SOCKET cancel_fds[2]; } RpcConnection_tcp; static RpcConnection *rpcrt4_conn_tcp_alloc(void) @@ -814,7 +814,7 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) { - int val; + char val; if (TRACE_ON(rpc)) { @@ -1091,7 +1091,7 @@ static int rpcrt4_conn_tcp_close(RpcConnection *Connection) static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection) { RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - char dummy = 1; + SOCKET dummy = 1; TRACE("%p\n", Connection); @@ -1271,7 +1271,7 @@ static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); if (ps) { - int fds[2]; + SOCKET fds[2]; if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) { fcntl(fds[0], F_SETFL, O_NONBLOCK); diff --git a/dll/win32/rsaenh/implglue.c b/dll/win32/rsaenh/implglue.c index b73eba93ec6..7ecfc289ecf 100644 --- a/dll/win32/rsaenh/implglue.c +++ b/dll/win32/rsaenh/implglue.c @@ -67,6 +67,18 @@ BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext) case CALG_SHA: A_SHAInit(&pHashContext->sha); break; + + case CALG_SHA_256: + SHA256_Init(&pHashContext->sha256); + break; + + case CALG_SHA_384: + SHA384_Init(&pHashContext->sha384); + break; + + case CALG_SHA_512: + SHA512_Init(&pHashContext->sha512); + break; } return TRUE; @@ -93,6 +105,18 @@ BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pb A_SHAUpdate(&pHashContext->sha, pbData, dwDataLen); break; + case CALG_SHA_256: + SHA256_Update(&pHashContext->sha256, pbData, dwDataLen); + break; + + case CALG_SHA_384: + SHA384_Update(&pHashContext->sha384, pbData, dwDataLen); + break; + + case CALG_SHA_512: + SHA512_Update(&pHashContext->sha512, pbData, dwDataLen); + break; + default: SetLastError(NTE_BAD_ALGID); return FALSE; @@ -123,6 +147,18 @@ BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHash A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue); break; + case CALG_SHA_256: + SHA256_Final(pbHashValue, &pHashContext->sha256); + break; + + case CALG_SHA_384: + SHA384_Final(pbHashValue, &pHashContext->sha384); + break; + + case CALG_SHA_512: + SHA512_Final(pbHashValue, &pHashContext->sha512); + break; + default: SetLastError(NTE_BAD_ALGID); return FALSE; diff --git a/dll/win32/rsaenh/implglue.h b/dll/win32/rsaenh/implglue.h index 5deaf53e58a..63553204c5b 100644 --- a/dll/win32/rsaenh/implglue.h +++ b/dll/win32/rsaenh/implglue.h @@ -25,6 +25,7 @@ #define __WINE_IMPLGLUE_H #include "tomcrypt.h" +#include "sha2.h" /* Next typedef copied from dlls/advapi32/crypt_md4.c */ typedef struct tagMD4_CTX { @@ -57,6 +58,9 @@ typedef union tagHASH_CONTEXT { MD4_CTX md4; MD5_CTX md5; SHA_CTX sha; + SHA256_CTX sha256; + SHA384_CTX sha384; + SHA512_CTX sha512; } HASH_CONTEXT; typedef union tagKEY_CONTEXT { diff --git a/dll/win32/rsaenh/rsaenh.c b/dll/win32/rsaenh/rsaenh.c index 665bc40056f..74ad392f2f2 100644 --- a/dll/win32/rsaenh/rsaenh.c +++ b/dll/win32/rsaenh/rsaenh.c @@ -241,6 +241,9 @@ static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] = {CALG_AES_192, 192,192, 192,0, 8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"}, {CALG_AES_256, 256,256, 256,0, 8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"}, {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, + {CALG_SHA_256, 256,256, 256,CRYPT_FLAG_SIGNING, 6,"SHA-256", 30,"Secure Hash Algorithm (SHA-256)"}, + {CALG_SHA_384, 384,384, 384,CRYPT_FLAG_SIGNING, 6,"SHA-384", 30,"Secure Hash Algorithm (SHA-284)"}, + {CALG_SHA_512, 512,512, 512,CRYPT_FLAG_SIGNING, 6,"SHA-512", 30,"Secure Hash Algorithm (SHA-512)"}, {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"}, {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"}, {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"}, @@ -1422,8 +1425,8 @@ static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid, static const struct tagOIDDescriptor { ALG_ID aiAlgid; DWORD dwLen; - CONST BYTE abOID[18]; - } aOIDDescriptor[5] = { + CONST BYTE abOID[19]; + } aOIDDescriptor[8] = { { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } }, { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, @@ -1432,6 +1435,15 @@ static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } }, { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } }, + { CALG_SHA_256, 19, { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, 0x04, 0x20 } }, + { CALG_SHA_384, 19, { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, 0x04, 0x30 } }, + { CALG_SHA_384, 19, { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, 0x04, 0x40 } }, { 0, 0, { 0 } } }; DWORD dwIdxOID, i, j; diff --git a/dll/win32/rsaenh/rsaenh.rbuild b/dll/win32/rsaenh/rsaenh.rbuild index fab9eb9011a..49973032b7e 100644 --- a/dll/win32/rsaenh/rsaenh.rbuild +++ b/dll/win32/rsaenh/rsaenh.rbuild @@ -17,6 +17,7 @@ rc4.c rsa.c rsaenh.c + sha2.c version.rc wine crypt32 diff --git a/dll/win32/rsaenh/sha2.c b/dll/win32/rsaenh/sha2.c new file mode 100644 index 00000000000..559323c54e5 --- /dev/null +++ b/dll/win32/rsaenh/sha2.c @@ -0,0 +1,1003 @@ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + +#define SHA2_WORD64_CONST(dw1, dw2) (((sha2_word64)(dw1) << 32) | (dw2)) + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#ifndef WORDS_BIGENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00) >> 8) | ((tmp & 0x00ff00ff) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & SHA2_WORD64_CONST(0xff00ff00, 0xff00ff00)) >> 8) | \ + ((tmp & SHA2_WORD64_CONST(0x00ff00ff, 0x00ff00ff)) << 8); \ + (x) = ((tmp & SHA2_WORD64_CONST(0xffff0000, 0xffff0000)) >> 16) | \ + ((tmp & SHA2_WORD64_CONST(0x0000ffff, 0x0000ffff)) << 16); \ +} +#endif + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void SHA512_Last(SHA512_CTX*); +void SHA256_Transform(SHA256_CTX*, const sha2_word32*); +void SHA512_Transform(SHA512_CTX*, const sha2_word64*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +static const sha2_word32 K256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* Initial hash value H for SHA-256: */ +static const sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +static const sha2_word64 K512[80] = { + SHA2_WORD64_CONST(0x428a2f98, 0xd728ae22), SHA2_WORD64_CONST(0x71374491, 0x23ef65cd), + SHA2_WORD64_CONST(0xb5c0fbcf, 0xec4d3b2f), SHA2_WORD64_CONST(0xe9b5dba5, 0x8189dbbc), + SHA2_WORD64_CONST(0x3956c25b, 0xf348b538), SHA2_WORD64_CONST(0x59f111f1, 0xb605d019), + SHA2_WORD64_CONST(0x923f82a4, 0xaf194f9b), SHA2_WORD64_CONST(0xab1c5ed5, 0xda6d8118), + SHA2_WORD64_CONST(0xd807aa98, 0xa3030242), SHA2_WORD64_CONST(0x12835b01, 0x45706fbe), + SHA2_WORD64_CONST(0x243185be, 0x4ee4b28c), SHA2_WORD64_CONST(0x550c7dc3, 0xd5ffb4e2), + SHA2_WORD64_CONST(0x72be5d74, 0xf27b896f), SHA2_WORD64_CONST(0x80deb1fe, 0x3b1696b1), + SHA2_WORD64_CONST(0x9bdc06a7, 0x25c71235), SHA2_WORD64_CONST(0xc19bf174, 0xcf692694), + SHA2_WORD64_CONST(0xe49b69c1, 0x9ef14ad2), SHA2_WORD64_CONST(0xefbe4786, 0x384f25e3), + SHA2_WORD64_CONST(0x0fc19dc6, 0x8b8cd5b5), SHA2_WORD64_CONST(0x240ca1cc, 0x77ac9c65), + SHA2_WORD64_CONST(0x2de92c6f, 0x592b0275), SHA2_WORD64_CONST(0x4a7484aa, 0x6ea6e483), + SHA2_WORD64_CONST(0x5cb0a9dc, 0xbd41fbd4), SHA2_WORD64_CONST(0x76f988da, 0x831153b5), + SHA2_WORD64_CONST(0x983e5152, 0xee66dfab), SHA2_WORD64_CONST(0xa831c66d, 0x2db43210), + SHA2_WORD64_CONST(0xb00327c8, 0x98fb213f), SHA2_WORD64_CONST(0xbf597fc7, 0xbeef0ee4), + SHA2_WORD64_CONST(0xc6e00bf3, 0x3da88fc2), SHA2_WORD64_CONST(0xd5a79147, 0x930aa725), + SHA2_WORD64_CONST(0x06ca6351, 0xe003826f), SHA2_WORD64_CONST(0x14292967, 0x0a0e6e70), + SHA2_WORD64_CONST(0x27b70a85, 0x46d22ffc), SHA2_WORD64_CONST(0x2e1b2138, 0x5c26c926), + SHA2_WORD64_CONST(0x4d2c6dfc, 0x5ac42aed), SHA2_WORD64_CONST(0x53380d13, 0x9d95b3df), + SHA2_WORD64_CONST(0x650a7354, 0x8baf63de), SHA2_WORD64_CONST(0x766a0abb, 0x3c77b2a8), + SHA2_WORD64_CONST(0x81c2c92e, 0x47edaee6), SHA2_WORD64_CONST(0x92722c85, 0x1482353b), + SHA2_WORD64_CONST(0xa2bfe8a1, 0x4cf10364), SHA2_WORD64_CONST(0xa81a664b, 0xbc423001), + SHA2_WORD64_CONST(0xc24b8b70, 0xd0f89791), SHA2_WORD64_CONST(0xc76c51a3, 0x0654be30), + SHA2_WORD64_CONST(0xd192e819, 0xd6ef5218), SHA2_WORD64_CONST(0xd6990624, 0x5565a910), + SHA2_WORD64_CONST(0xf40e3585, 0x5771202a), SHA2_WORD64_CONST(0x106aa070, 0x32bbd1b8), + SHA2_WORD64_CONST(0x19a4c116, 0xb8d2d0c8), SHA2_WORD64_CONST(0x1e376c08, 0x5141ab53), + SHA2_WORD64_CONST(0x2748774c, 0xdf8eeb99), SHA2_WORD64_CONST(0x34b0bcb5, 0xe19b48a8), + SHA2_WORD64_CONST(0x391c0cb3, 0xc5c95a63), SHA2_WORD64_CONST(0x4ed8aa4a, 0xe3418acb), + SHA2_WORD64_CONST(0x5b9cca4f, 0x7763e373), SHA2_WORD64_CONST(0x682e6ff3, 0xd6b2b8a3), + SHA2_WORD64_CONST(0x748f82ee, 0x5defb2fc), SHA2_WORD64_CONST(0x78a5636f, 0x43172f60), + SHA2_WORD64_CONST(0x84c87814, 0xa1f0ab72), SHA2_WORD64_CONST(0x8cc70208, 0x1a6439ec), + SHA2_WORD64_CONST(0x90befffa, 0x23631e28), SHA2_WORD64_CONST(0xa4506ceb, 0xde82bde9), + SHA2_WORD64_CONST(0xbef9a3f7, 0xb2c67915), SHA2_WORD64_CONST(0xc67178f2, 0xe372532b), + SHA2_WORD64_CONST(0xca273ece, 0xea26619c), SHA2_WORD64_CONST(0xd186b8c7, 0x21c0c207), + SHA2_WORD64_CONST(0xeada7dd6, 0xcde0eb1e), SHA2_WORD64_CONST(0xf57d4f7f, 0xee6ed178), + SHA2_WORD64_CONST(0x06f067aa, 0x72176fba), SHA2_WORD64_CONST(0x0a637dc5, 0xa2c898a6), + SHA2_WORD64_CONST(0x113f9804, 0xbef90dae), SHA2_WORD64_CONST(0x1b710b35, 0x131c471b), + SHA2_WORD64_CONST(0x28db77f5, 0x23047d84), SHA2_WORD64_CONST(0x32caab7b, 0x40c72493), + SHA2_WORD64_CONST(0x3c9ebe0a, 0x15c9bebc), SHA2_WORD64_CONST(0x431d67c4, 0x9c100d4c), + SHA2_WORD64_CONST(0x4cc5d4be, 0xcb3e42b6), SHA2_WORD64_CONST(0x597f299c, 0xfc657e2a), + SHA2_WORD64_CONST(0x5fcb6fab, 0x3ad6faec), SHA2_WORD64_CONST(0x6c44198c, 0x4a475817) +}; + +/* Initial hash value H for SHA-384 */ +static const sha2_word64 sha384_initial_hash_value[8] = { + SHA2_WORD64_CONST(0xcbbb9d5d, 0xc1059ed8), + SHA2_WORD64_CONST(0x629a292a, 0x367cd507), + SHA2_WORD64_CONST(0x9159015a, 0x3070dd17), + SHA2_WORD64_CONST(0x152fecd8, 0xf70e5939), + SHA2_WORD64_CONST(0x67332667, 0xffc00b31), + SHA2_WORD64_CONST(0x8eb44a87, 0x68581511), + SHA2_WORD64_CONST(0xdb0c2e0d, 0x64f98fa7), + SHA2_WORD64_CONST(0x47b5481d, 0xbefa4fa4) +}; + +/* Initial hash value H for SHA-512 */ +static const sha2_word64 sha512_initial_hash_value[8] = { + SHA2_WORD64_CONST(0x6a09e667, 0xf3bcc908), + SHA2_WORD64_CONST(0xbb67ae85, 0x84caa73b), + SHA2_WORD64_CONST(0x3c6ef372, 0xfe94f82b), + SHA2_WORD64_CONST(0xa54ff53a, 0x5f1d36f1), + SHA2_WORD64_CONST(0x510e527f, 0xade682d1), + SHA2_WORD64_CONST(0x9b05688c, 0x2b3e6c1f), + SHA2_WORD64_CONST(0x1f83d9ab, 0xfb41bd6b), + SHA2_WORD64_CONST(0x5be0cd19, 0x137e2179) +}; + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char sha2_hex_digits[] = "0123456789abcdef"; + + +/*** SHA-256: *********************************************************/ +void SHA256_Init(SHA256_CTX* context) { + if (context == (SHA256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#ifndef WORDS_BIGENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#ifndef WORDS_BIGENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (sha2_word32*)data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; +#ifndef WORDS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(context)); + usedspace = 0; +} + +char *SHA256_End(SHA256_CTX* context, char buffer[]) { + sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + if (buffer != (char*)0) { + SHA256_Final(digest, context); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); + return buffer; +} + +char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { + SHA256_CTX context; + + SHA256_Init(&context); + SHA256_Update(&context, data, len); + return SHA256_End(&context, digest); +} + + +/*** SHA-512: *********************************************************/ +void SHA512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#ifndef WORDS_BIGENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#ifndef WORDS_BIGENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (sha2_word64*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; +#ifndef WORDS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); +} + +void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last(context); + + /* Save the hash data for output: */ +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(context)); +} + +char *SHA512_End(SHA512_CTX* context, char buffer[]) { + sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + if (buffer != (char*)0) { + SHA512_Final(digest, context); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); + return buffer; +} + +char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { + SHA512_CTX context; + + SHA512_Init(&context); + SHA512_Update(&context, data, len); + return SHA512_End(&context, digest); +} + + +/*** SHA-384: *********************************************************/ +void SHA384_Init(SHA384_CTX* context) { + if (context == (SHA384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { + SHA512_Update((SHA512_CTX*)context, data, len); +} + +void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last((SHA512_CTX*)context); + + /* Save the hash data for output: */ +#ifndef WORDS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(context)); +} + +char *SHA384_End(SHA384_CTX* context, char buffer[]) { + sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + if (buffer != (char*)0) { + SHA384_Final(digest, context); + + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); + return buffer; +} + +char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { + SHA384_CTX context; + + SHA384_Init(&context); + SHA384_Update(&context, data, len); + return SHA384_End(&context, digest); +} diff --git a/dll/win32/rsaenh/sha2.h b/dll/win32/rsaenh/sha2.h new file mode 100644 index 00000000000..2dda41230c1 --- /dev/null +++ b/dll/win32/rsaenh/sha2.h @@ -0,0 +1,89 @@ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#include + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ +typedef UINT8 sha2_byte; /* Exactly 1 byte */ +typedef UINT32 sha2_word32; /* Exactly 4 bytes */ +typedef UINT64 sha2_word64; /* Exactly 8 bytes */ + +typedef struct _SHA256_CTX { + sha2_word32 state[8]; + sha2_word64 bitcount; + sha2_byte buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + sha2_word64 state[8]; + sha2_word64 bitcount[2]; + sha2_byte buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +typedef SHA512_CTX SHA384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ + +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX*, const sha2_byte*, size_t); +void SHA256_Final(sha2_byte[SHA256_DIGEST_LENGTH], SHA256_CTX*); +char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); +char* SHA256_Data(const sha2_byte*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); + +void SHA384_Init(SHA384_CTX*); +void SHA384_Update(SHA384_CTX*, const sha2_byte*, size_t); +void SHA384_Final(sha2_byte[SHA384_DIGEST_LENGTH], SHA384_CTX*); +char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); +char* SHA384_Data(const sha2_byte*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); + +void SHA512_Init(SHA512_CTX*); +void SHA512_Update(SHA512_CTX*, const sha2_byte*, size_t); +void SHA512_Final(sha2_byte[SHA512_DIGEST_LENGTH], SHA512_CTX*); +char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); +char* SHA512_Data(const sha2_byte*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); + +#endif /* __SHA2_H__ */ diff --git a/dll/win32/shdocvw/dochost.c b/dll/win32/shdocvw/dochost.c index e8982e4f12a..2196eb9c02e 100644 --- a/dll/win32/shdocvw/dochost.c +++ b/dll/win32/shdocvw/dochost.c @@ -21,9 +21,14 @@ #include "hlink.h" #include "exdispid.h" #include "mshtml.h" +#include "initguid.h" WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); +DEFINE_OLEGUID(CGID_DocHostCmdPriv, 0x000214D4L, 0, 0); + +#define DOCHOST_DOCCANNAVIGATE 0 + static ATOM doc_view_atom = 0; void push_dochost_task(DocHost *This, task_header_t *task, task_proc_t proc, BOOL send) @@ -154,16 +159,23 @@ static void advise_prop_notif(DocHost *This, BOOL set) This->is_prop_notif = set; } +void set_doc_state(DocHost *This, READYSTATE doc_state) +{ + This->doc_state = doc_state; + if(doc_state > This->ready_state) + This->ready_state = doc_state; +} + static void update_ready_state(DocHost *This, READYSTATE ready_state) { - if(ready_state > READYSTATE_LOADING && This->ready_state <= READYSTATE_LOADING) { + if(ready_state > READYSTATE_LOADING && This->doc_state <= READYSTATE_LOADING) notif_complete(This, DISPID_NAVIGATECOMPLETE2); - This->ready_state = ready_state; - } - if(ready_state == READYSTATE_COMPLETE && This->ready_state < READYSTATE_COMPLETE) { - This->ready_state = READYSTATE_COMPLETE; + if(ready_state == READYSTATE_COMPLETE && This->doc_state < READYSTATE_COMPLETE) { + set_doc_state(This, READYSTATE_COMPLETE); notif_complete(This, DISPID_DOCUMENTCOMPLETE); + }else { + set_doc_state(This, ready_state); } } @@ -236,7 +248,7 @@ HRESULT dochost_object_available(DocHost *This, IUnknown *doc) if(SUCCEEDED(hres)) { if(ready_state == READYSTATE_COMPLETE) push_ready_state_task(This, READYSTATE_COMPLETE); - else + if(ready_state != READYSTATE_COMPLETE || This->doc_navigate) advise_prop_notif(This, TRUE); } @@ -314,6 +326,11 @@ void deactivate_document(DocHost *This) IHlinkTarget *hlink = NULL; HRESULT hres; + if(This->doc_navigate) { + IUnknown_Release(This->doc_navigate); + This->doc_navigate = NULL; + } + if(This->is_prop_notif) advise_prop_notif(This, FALSE); @@ -425,8 +442,34 @@ static HRESULT WINAPI ClOleCommandTarget_Exec(IOleCommandTarget *iface, VARIANT *pvaOut) { DocHost *This = OLECMD_THIS(iface); - FIXME("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, - nCmdexecopt, pvaIn, pvaOut); + + TRACE("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID, + nCmdexecopt, debugstr_variant(pvaIn), debugstr_variant(pvaOut)); + + if(!pguidCmdGroup) { + FIXME("Unimplemented cmdid %d\n", nCmdID); + return E_NOTIMPL; + } + + if(IsEqualGUID(pguidCmdGroup, &CGID_DocHostCmdPriv)) { + switch(nCmdID) { + case DOCHOST_DOCCANNAVIGATE: + if(!pvaIn || V_VT(pvaIn) != VT_UNKNOWN) + return E_INVALIDARG; + + if(This->doc_navigate) + IUnknown_Release(This->doc_navigate); + IUnknown_AddRef(V_UNKNOWN(pvaIn)); + This->doc_navigate = V_UNKNOWN(pvaIn); + return S_OK; + + default: + FIXME("unsupported command %d of CGID_DocHostCmdPriv\n", nCmdID); + return E_NOTIMPL; + } + } + + FIXME("Unimplemented group %s\n", debugstr_guid(pguidCmdGroup)); return E_NOTIMPL; } @@ -709,7 +752,7 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D if(FAILED(hres)) return hres; - if(ready_state == READYSTATE_COMPLETE) + if(ready_state == READYSTATE_COMPLETE && !This->doc_navigate) advise_prop_notif(This, FALSE); push_ready_state_task(This, ready_state); diff --git a/dll/win32/shdocvw/iexplore.c b/dll/win32/shdocvw/iexplore.c index ca2c868d13d..d65810f58f9 100644 --- a/dll/win32/shdocvw/iexplore.c +++ b/dll/win32/shdocvw/iexplore.c @@ -163,7 +163,7 @@ HRESULT InternetExplorer_Create(IUnknown *pOuter, REFIID riid, void **ppv) TRACE("(%p %s %p)\n", pOuter, debugstr_guid(riid), ppv); - ret = heap_alloc(sizeof(InternetExplorer)); + ret = heap_alloc_zero(sizeof(InternetExplorer)); ret->ref = 0; ret->doc_host.disp = (IDispatch*)WEBBROWSER2(ret); diff --git a/dll/win32/shdocvw/navigate.c b/dll/win32/shdocvw/navigate.c index ec23fcc7b38..8ba5f692740 100644 --- a/dll/win32/shdocvw/navigate.c +++ b/dll/win32/shdocvw/navigate.c @@ -27,6 +27,7 @@ #include "winreg.h" #include "shlwapi.h" #include "wininet.h" +#include "mshtml.h" WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); @@ -378,8 +379,7 @@ static BindStatusCallback *create_callback(DocHost *doc_host, LPCWSTR url, PBYTE return ret; } -static void on_before_navigate2(DocHost *This, LPCWSTR url, const BYTE *post_data, - ULONG post_data_len, LPWSTR headers, VARIANT_BOOL *cancel) +static void on_before_navigate2(DocHost *This, LPCWSTR url, SAFEARRAY *post_data, LPWSTR headers, VARIANT_BOOL *cancel) { VARIANT var_url, var_flags, var_frame_name, var_post_data, var_post_data2, var_headers; DISPPARAMS dispparams; @@ -404,18 +404,12 @@ static void on_before_navigate2(DocHost *This, LPCWSTR url, const BYTE *post_dat V_VARIANTREF(params+2) = &var_post_data2; V_VT(&var_post_data2) = (VT_BYREF|VT_VARIANT); V_VARIANTREF(&var_post_data2) = &var_post_data; - VariantInit(&var_post_data); - - if(post_data_len) { - SAFEARRAYBOUND bound = {post_data_len, 0}; - void *data; + if(post_data) { V_VT(&var_post_data) = VT_UI1|VT_ARRAY; - V_ARRAY(&var_post_data) = SafeArrayCreate(VT_UI1, 1, &bound); - - SafeArrayAccessData(V_ARRAY(&var_post_data), &data); - memcpy(data, post_data, post_data_len); - SafeArrayUnaccessData(V_ARRAY(&var_post_data)); + V_ARRAY(&var_post_data) = post_data; + }else { + V_VT(&var_post_data) = VT_EMPTY; } V_VT(params+3) = (VT_BYREF|VT_VARIANT); @@ -439,8 +433,6 @@ static void on_before_navigate2(DocHost *This, LPCWSTR url, const BYTE *post_dat call_sink(This->cps.wbe2, DISPID_BEFORENAVIGATE2, &dispparams); SysFreeString(V_BSTR(&var_url)); - if(post_data_len) - SafeArrayDestroy(V_ARRAY(&var_post_data)); } /* FIXME: urlmon should handle it */ @@ -543,15 +535,153 @@ static HRESULT bind_to_object(DocHost *This, IMoniker *mon, LPCWSTR url, IBindCt return S_OK; } -static HRESULT navigate_bsc(DocHost *This, BindStatusCallback *bsc, IMoniker *mon) +static void html_window_navigate(DocHost *This, IHTMLPrivateWindow *window, BSTR url, BSTR headers, SAFEARRAY *post_data) { - IBindCtx *bindctx; - VARIANT_BOOL cancel = VARIANT_FALSE; + VARIANT headers_var, post_data_var; + WCHAR *new_url; + BSTR empty_str; + DWORD size; HRESULT hres; - This->ready_state = READYSTATE_LOADING; + size = (strlenW(url)+1)*sizeof(WCHAR); + new_url = CoTaskMemAlloc(size); + if(!new_url) + return; + memcpy(new_url, url, size); + CoTaskMemFree(This->url); + This->url = new_url; - on_before_navigate2(This, bsc->url, bsc->post_data, bsc->post_data_len, bsc->headers, &cancel); + empty_str = SysAllocStringLen(NULL, 0); + + if(headers) { + V_VT(&headers_var) = VT_BSTR; + V_BSTR(&headers_var) = headers; + }else { + V_VT(&headers_var) = VT_EMPTY; + } + + if(post_data) { + V_VT(&post_data_var) = VT_UI1|VT_ARRAY; + V_ARRAY(&post_data_var) = post_data; + }else { + V_VT(&post_data_var) = VT_EMPTY; + } + + set_doc_state(This, READYSTATE_LOADING); + hres = IHTMLPrivateWindow_SuperNavigate(window, url, empty_str, NULL, NULL, &post_data_var, &headers_var, 0); + SysFreeString(empty_str); + if(FAILED(hres)) + WARN("SuprtNavigate failed: %08x\n", hres); +} + +typedef struct { + task_header_t header; + BSTR url; + BSTR headers; + SAFEARRAY *post_data; + BOOL async_notif; +} task_doc_navigate_t; + +static HRESULT free_doc_navigate_task(task_doc_navigate_t *task, BOOL free_task) +{ + SysFreeString(task->url); + SysFreeString(task->headers); + if(task->post_data) + SafeArrayDestroy(task->post_data); + if(free_task) + heap_free(task); + return E_OUTOFMEMORY; +} + +static void doc_navigate_proc(DocHost *This, task_header_t *t) +{ + task_doc_navigate_t *task = (task_doc_navigate_t*)t; + IHTMLPrivateWindow *priv_window; + HRESULT hres; + + if(!This->doc_navigate) + return; + + if(task->async_notif) { + VARIANT_BOOL cancel = VARIANT_FALSE; + on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel); + if(cancel) { + TRACE("Navigation calnceled\n"); + free_doc_navigate_task(task, FALSE); + return; + } + } + + hres = IUnknown_QueryInterface(This->doc_navigate, &IID_IHTMLPrivateWindow, (void**)&priv_window); + if(SUCCEEDED(hres)) { + html_window_navigate(This, priv_window, task->url, task->headers, task->post_data); + IHTMLPrivateWindow_Release(priv_window); + }else { + WARN("Could not get IHTMLPrivateWindow iface: %08x\n", hres); + } + + free_doc_navigate_task(task, FALSE); +} + +static HRESULT async_doc_navigate(DocHost *This, LPCWSTR url, LPCWSTR headers, PBYTE post_data, ULONG post_data_size, + BOOL async_notif) +{ + task_doc_navigate_t *task; + + task = heap_alloc_zero(sizeof(*task)); + if(!task) + return E_OUTOFMEMORY; + + task->url = SysAllocString(url); + if(!task->url) + return free_doc_navigate_task(task, TRUE); + + if(headers) { + task->headers = SysAllocString(headers); + if(!task->headers) + return free_doc_navigate_task(task, TRUE); + } + + if(task->post_data) { + task->post_data = SafeArrayCreateVector(VT_UI1, 0, post_data_size); + if(!task->post_data) + return free_doc_navigate_task(task, TRUE); + memcpy(task->post_data->pvData, post_data, post_data_size); + } + + if(!async_notif) { + VARIANT_BOOL cancel = VARIANT_FALSE; + + on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel); + if(cancel) { + TRACE("Navigation calnceled\n"); + free_doc_navigate_task(task, TRUE); + return S_OK; + } + } + + task->async_notif = async_notif; + push_dochost_task(This, &task->header, doc_navigate_proc, FALSE); + return S_OK; +} + +static HRESULT navigate_bsc(DocHost *This, BindStatusCallback *bsc, IMoniker *mon) +{ + VARIANT_BOOL cancel = VARIANT_FALSE; + SAFEARRAY *post_data = NULL; + IBindCtx *bindctx; + HRESULT hres; + + set_doc_state(This, READYSTATE_LOADING); + + if(bsc->post_data) { + post_data = SafeArrayCreateVector(VT_UI1, 0, bsc->post_data_len); + memcpy(post_data->pvData, post_data, bsc->post_data_len); + } + + on_before_navigate2(This, bsc->url, post_data, bsc->headers, &cancel); + if(post_data) + SafeArrayDestroy(post_data); if(cancel) { FIXME("Navigation canceled\n"); return S_OK; @@ -596,10 +726,10 @@ static void navigate_bsc_proc(DocHost *This, task_header_t *t) HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags, const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) { - task_navigate_bsc_t *task; PBYTE post_data = NULL; ULONG post_data_len = 0; LPWSTR headers = NULL; + HRESULT hres = S_OK; TRACE("navigating to %s\n", debugstr_w(url)); @@ -626,15 +756,23 @@ HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags, TRACE("Headers: %s\n", debugstr_w(headers)); } - task = heap_alloc(sizeof(*task)); - task->bsc = create_callback(This, url, post_data, post_data_len, headers); + set_doc_state(This, READYSTATE_LOADING); + This->ready_state = READYSTATE_LOADING; + + if(This->doc_navigate) { + hres = async_doc_navigate(This, url, headers, post_data, post_data_len, TRUE); + }else { + task_navigate_bsc_t *task; + + task = heap_alloc(sizeof(*task)); + task->bsc = create_callback(This, url, post_data, post_data_len, headers); + push_dochost_task(This, &task->header, navigate_bsc_proc, This->url == NULL); + } if(post_data) SafeArrayUnaccessData(V_ARRAY(PostData)); - push_dochost_task(This, &task->header, navigate_bsc_proc, This->url == NULL); - - return S_OK; + return hres; } static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx, @@ -649,6 +787,10 @@ static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx, DWORD bindf = 0; HRESULT hres; + hres = IMoniker_GetDisplayName(mon, 0, NULL, &url); + if(FAILED(hres)) + FIXME("GetDisplayName failed: %08x\n", hres); + hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate, (void**)&http_negotiate); if(SUCCEEDED(hres)) { @@ -670,16 +812,15 @@ static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx, post_data = bindinfo.stgmedData.u.hGlobal; } - hres = IMoniker_GetDisplayName(mon, 0, NULL, &url); - if(FAILED(hres)) - FIXME("GetDisplayName failed: %08x\n", hres); + if(This->doc_navigate) { + hres = async_doc_navigate(This, url, headers, post_data, post_data_len, FALSE); + }else { + bsc = create_callback(This, url, post_data, post_data_len, headers); + hres = navigate_bsc(This, bsc, mon); + IBindStatusCallback_Release(BINDSC(bsc)); + } - bsc = create_callback(This, url, post_data, post_data_len, headers); CoTaskMemFree(url); - - hres = navigate_bsc(This, bsc, mon); - - IBindStatusCallback_Release(BINDSC(bsc)); CoTaskMemFree(headers); ReleaseBindInfo(&bindinfo); diff --git a/dll/win32/shdocvw/oleobject.c b/dll/win32/shdocvw/oleobject.c index f67edb7583e..933b5629cea 100644 --- a/dll/win32/shdocvw/oleobject.c +++ b/dll/win32/shdocvw/oleobject.c @@ -960,17 +960,6 @@ void WebBrowser_OleObject_Init(WebBrowser *This) This->lpOleInPlaceActiveObjectVtbl = &OleInPlaceActiveObjectVtbl; This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl; - This->client = NULL; - This->inplace = NULL; - This->container = NULL; - This->frame_hwnd = NULL; - This->uiwindow = NULL; - This->shell_embedding_hwnd = NULL; - - memset(&This->pos_rect, 0, sizeof(RECT)); - memset(&This->clip_rect, 0, sizeof(RECT)); - memset(&This->frameinfo, 0, sizeof(OLEINPLACEFRAMEINFO)); - /* Default size is 50x20 pixels, in himetric units */ This->extent.cx = MulDiv( 50, 2540, dpi_x ); This->extent.cy = MulDiv( 20, 2540, dpi_y ); diff --git a/dll/win32/shdocvw/shdocvw.h b/dll/win32/shdocvw/shdocvw.h index c5b9c9a1be5..1184298dca9 100644 --- a/dll/win32/shdocvw/shdocvw.h +++ b/dll/win32/shdocvw/shdocvw.h @@ -92,6 +92,7 @@ struct DocHost { IUnknown *document; IOleDocumentView *view; + IUnknown *doc_navigate; HWND hwnd; HWND frame_hwnd; @@ -103,6 +104,7 @@ struct DocHost { VARIANT_BOOL busy; READYSTATE ready_state; + READYSTATE doc_state; DWORD prop_notif_cookie; BOOL is_prop_notif; @@ -222,6 +224,7 @@ HRESULT dochost_object_available(DocHost*,IUnknown*); void call_sink(ConnectionPoint*,DISPID,DISPPARAMS*); HRESULT navigate_url(DocHost*,LPCWSTR,const VARIANT*,const VARIANT*,VARIANT*,VARIANT*); HRESULT go_home(DocHost*); +void set_doc_state(DocHost*,READYSTATE); #define WM_DOCHOSTTASK (WM_USER+0x300) void push_dochost_task(DocHost*,task_header_t*,task_proc_t,BOOL); @@ -262,6 +265,11 @@ static inline void *heap_alloc(size_t len) return HeapAlloc(GetProcessHeap(), 0, len); } +static inline void *heap_alloc_zero(size_t len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + static inline void *heap_realloc(void *mem, size_t len) { return HeapReAlloc(GetProcessHeap(), 0, mem, len); diff --git a/dll/win32/shdocvw/webbrowser.c b/dll/win32/shdocvw/webbrowser.c index b0633b03f19..2ac9b9985d5 100644 --- a/dll/win32/shdocvw/webbrowser.c +++ b/dll/win32/shdocvw/webbrowser.c @@ -1115,23 +1115,20 @@ static HRESULT WebBrowser_Create(INT version, IUnknown *pOuter, REFIID riid, voi TRACE("(%p %s %p) version=%d\n", pOuter, debugstr_guid(riid), ppv, version); - ret = heap_alloc(sizeof(WebBrowser)); + ret = heap_alloc_zero(sizeof(WebBrowser)); ret->lpWebBrowser2Vtbl = &WebBrowser2Vtbl; ret->lpServiceProviderVtbl = &ServiceProviderVtbl; - ret->ref = 0; + ret->ref = 1; ret->version = version; DocHost_Init(&ret->doc_host, (IDispatch*)WEBBROWSER2(ret)); - ret->register_browser = VARIANT_FALSE; ret->visible = VARIANT_TRUE; ret->menu_bar = VARIANT_TRUE; ret->address_bar = VARIANT_TRUE; ret->status_bar = VARIANT_TRUE; ret->tool_bar = VARIANT_TRUE; - ret->full_screen = VARIANT_FALSE; - ret->theater_mode = VARIANT_FALSE; WebBrowser_OleObject_Init(ret); WebBrowser_ViewObject_Init(ret); @@ -1139,14 +1136,11 @@ static HRESULT WebBrowser_Create(INT version, IUnknown *pOuter, REFIID riid, voi WebBrowser_ClassInfo_Init(ret); WebBrowser_HlinkFrame_Init(ret); - hres = IWebBrowser_QueryInterface(WEBBROWSER(ret), riid, ppv); - if(SUCCEEDED(hres)) { - SHDOCVW_LockModule(); - }else { - heap_free(ret); - return hres; - } + SHDOCVW_LockModule(); + hres = IWebBrowser_QueryInterface(WEBBROWSER(ret), riid, ppv); + + IWebBrowser2_Release(WEBBROWSER(ret)); return hres; } diff --git a/dll/win32/shell32/autocomplete.c b/dll/win32/shell32/autocomplete.c index a637988939f..a0ace20c051 100644 --- a/dll/win32/shell32/autocomplete.c +++ b/dll/win32/shell32/autocomplete.c @@ -214,7 +214,7 @@ static HRESULT WINAPI IAutoComplete_fnInit( static const WCHAR lbName[] = {'L','i','s','t','B','o','x',0}; TRACE("(%p)->(0x%08lx, %p, %s, %s)\n", - This, (long)hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); + This, hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); if (This->options & ACO_AUTOSUGGEST) TRACE(" ACO_AUTOSUGGEST\n"); if (This->options & ACO_AUTOAPPEND) TRACE(" ACO_AUTOAPPEND\n"); diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 375ddaf7ad2..364bbfe8af8 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -402,7 +402,9 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown) V_VT(&var) = VT_UNKNOWN; V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc; - hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var); + property = SysAllocString(szProperty); + hRet = IWebBrowserApp_PutProperty(pBrowser, property, var); + SysFreeString(property); if (FAILED(hRet)) { IEnumFORMATETC_Release(pIEnumFormatEtc); @@ -4854,3 +4856,127 @@ BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLON } return hr; } + +/* return flags for SHGetObjectCompatFlags, names derived from registry value names */ +#define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001 +#define OBJCOMPAT_NO_WEBVIEW 0x00000002 +#define OBJCOMPAT_UNBINDABLE 0x00000004 +#define OBJCOMPAT_PINDLL 0x00000008 +#define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010 +#define OBJCOMPAT_NOTAFILESYSTEM 0x00000020 +#define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040 +#define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080 +#define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100 +#define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200 +#define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400 +#define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000 +#define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000 + +/* a search table for compatibility flags */ +struct objcompat_entry { + const WCHAR name[30]; + DWORD value; +}; + +/* expected to be sorted by name */ +static const struct objcompat_entry objcompat_table[] = { + { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0}, + OBJCOMPAT_COCREATESHELLFOLDERONLY }, + { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0}, + OBJCOMPAT_CTXMENU_LIMITEDQI }, + { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0}, + OBJCOMPAT_CTXMENU_LIMITEDQI }, + { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0}, + OBJCOMPAT_CTXMENU_XPQCMFLAGS }, + { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0}, + OBJCOMPAT_NEEDSFILESYSANCESTOR }, + { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0}, + OBJCOMPAT_NEEDSSTORAGEANCESTOR }, + { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0}, + OBJCOMPAT_NOIPROPERTYSTORE }, + { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0}, + OBJCOMPAT_NOLEGACYWEBVIEW }, + { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0}, + OBJCOMPAT_NOTAFILESYSTEM }, + { {'N','O','_','W','E','B','V','I','E','W',0}, + OBJCOMPAT_NO_WEBVIEW }, + { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0}, + OBJCOMPAT_OTNEEDSSFCACHE }, + { {'P','I','N','D','L','L',0}, + OBJCOMPAT_PINDLL }, + { {'U','N','B','I','N','D','A','B','L','E',0}, + OBJCOMPAT_UNBINDABLE } +}; + +/************************************************************************** + * SHGetObjectCompatFlags (SHLWAPI.476) + * + * Function returns an integer representation of compatibility flags stored + * in registry for CLSID under ShellCompatibility subkey. + * + * PARAMS + * pUnk: pointer to object IUnknown interface, idetifies CLSID + * clsid: pointer to CLSID to retrieve data for + * + * RETURNS + * 0 on failure, flags set on success + */ +DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid) +{ + static const WCHAR compatpathW[] = + {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\', + 'O','b','j','e','c','t','s','\\','%','s',0}; + WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */]; + DWORD ret, length = sizeof(strW)/sizeof(WCHAR); + OLECHAR *clsid_str; + HKEY key; + INT i; + + TRACE("%p %s\n", pUnk, debugstr_guid(clsid)); + + if (!pUnk && !clsid) return 0; + + if (pUnk && !clsid) + { + FIXME("iface not handled\n"); + return 0; + } + + StringFromCLSID(clsid, &clsid_str); + sprintfW(strW, compatpathW, clsid_str); + CoTaskMemFree(clsid_str); + + ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key); + if (ret != ERROR_SUCCESS) return 0; + + /* now collect flag values */ + ret = 0; + for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++) + { + INT left, right, res, x; + + /* search in table */ + left = 0; + right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1; + + while (right >= left) { + x = (left + right) / 2; + res = strcmpW(strW, objcompat_table[x].name); + if (res == 0) + { + ret |= objcompat_table[x].value; + break; + } + else if (res < 0) + right = x - 1; + else + left = x + 1; + } + + length = sizeof(strW)/sizeof(WCHAR); + } + + return ret; +} diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec index 3091783f580..d899232f9c5 100644 --- a/dll/win32/shlwapi/shlwapi.spec +++ b/dll/win32/shlwapi/shlwapi.spec @@ -473,7 +473,7 @@ 473 stub -noname SHGetIniStringUTF7W 474 stub -noname SHSetIniStringUTF7W 475 stdcall -noname GetShellSecurityDescriptor(ptr long) -476 stub -noname SHGetObjectCompatFlags +476 stdcall -noname SHGetObjectCompatFlags(ptr ptr) 477 stub -noname SHCreatePropertyBagOnMemory 478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr) 479 stdcall -noname IUnknown_UIActivateIO(ptr long ptr) @@ -559,6 +559,7 @@ @ stdcall ColorAdjustLuma(long long long) @ stdcall ColorHLSToRGB(long long long) @ stdcall ColorRGBToHLS(long ptr ptr ptr) +@ stdcall DelayLoadFailureHook(str str) kernel32.DelayLoadFailureHook @ stdcall -private DllGetVersion(ptr) @ stdcall GetMenuPosFromID(ptr long) @ stdcall HashData (ptr long ptr long) diff --git a/dll/win32/shlwapi/string.c b/dll/win32/shlwapi/string.c index cfb59ea4400..e00a92582e0 100644 --- a/dll/win32/shlwapi/string.c +++ b/dll/win32/shlwapi/string.c @@ -507,23 +507,33 @@ LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc) * Copy a string to another string, up to a maximum number of characters. * * PARAMS - * lpszStr [O] Destination string - * lpszSrc [I] Source string - * iLen [I] Maximum number of chars to copy + * dst [O] Destination string + * src [I] Source string + * count [I] Maximum number of chars to copy * * RETURNS - * lpszStr. + * dst. */ -LPWSTR WINAPI StrCpyNW(LPWSTR lpszStr, LPCWSTR lpszSrc, int iLen) +LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count) { - TRACE("(%p,%s,%i)\n", lpszStr, debugstr_w(lpszSrc), iLen); + LPWSTR d = dst; + LPCWSTR s = src; - lstrcpynW(lpszStr, lpszSrc, iLen); - return lpszStr; + TRACE("(%p,%s,%i)\n", dst, debugstr_w(src), count); + + if (s) + { + while ((count > 1) && *s) + { + count--; + *d++ = *s++; + } + } + if (count) *d = 0; + + return dst; } - - /************************************************************************* * SHLWAPI_StrStrHelperA * diff --git a/dll/win32/shlwapi/url.c b/dll/win32/shlwapi/url.c index 2fdae3de523..958a8429f53 100644 --- a/dll/win32/shlwapi/url.c +++ b/dll/win32/shlwapi/url.c @@ -359,6 +359,7 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, if (*wk1 != '/') {state = 6; break;} *wk2++ = *wk1++; if((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszLocalhost) + && !strncmpW(wszFile, pszUrl, sizeof(wszFile)/sizeof(WCHAR)) && !memcmp(wszLocalhost, wk1, sizeof(wszLocalhost))){ wk1 += sizeof(wszLocalhost)/sizeof(WCHAR); while(*wk1 == '\\' && (dwFlags & URL_FILE_USE_PATHURL)) @@ -2051,6 +2052,9 @@ HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, LPWSTR in, out; DWORD ret, len, len2; + if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0) + return E_INVALIDARG; + in = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR)); out = in + INTERNET_MAX_URL_LENGTH; @@ -2067,7 +2071,7 @@ HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, len2 = WideCharToMultiByte(0, 0, out, len, 0, 0, 0, 0); if (len2 > *pcchOut) { - *pcchOut = len2; + *pcchOut = len2+1; HeapFree(GetProcessHeap(), 0, in); return E_POINTER; } @@ -2093,20 +2097,25 @@ HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, TRACE("(%s %p %p(%d) %08x %08x)\n", debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags); + if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0) + return E_INVALIDARG; + + *pszOut = '\0'; + addr = strchrW(pszIn, ':'); if(!addr) - return E_FAIL; - - scheme = get_scheme_code(pszIn, addr-pszIn); + scheme = URL_SCHEME_UNKNOWN; + else + scheme = get_scheme_code(pszIn, addr-pszIn); ret = URL_ParseUrl(pszIn, &pl); - if (ret == S_OK) { - schaddr = pl.pScheme; - schsize = pl.szScheme; switch (dwPart) { case URL_PART_SCHEME: - if (!pl.szScheme) return E_INVALIDARG; + if (!pl.szScheme || scheme == URL_SCHEME_UNKNOWN) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pScheme; size = pl.szScheme; break; @@ -2121,55 +2130,76 @@ HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, case URL_SCHEME_HTTPS: break; default: + *pcchOut = 0; return E_FAIL; } if(scheme==URL_SCHEME_FILE && (!pl.szHostName || (pl.szHostName==1 && *(pl.pHostName+1)==':'))) { - if(pcchOut) - *pszOut = '\0'; *pcchOut = 0; return S_FALSE; } - if (!pl.szHostName) return E_INVALIDARG; + if (!pl.szHostName) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pHostName; size = pl.szHostName; break; case URL_PART_USERNAME: - if (!pl.szUserName) return E_INVALIDARG; + if (!pl.szUserName) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pUserName; size = pl.szUserName; break; case URL_PART_PASSWORD: - if (!pl.szPassword) return E_INVALIDARG; + if (!pl.szPassword) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pPassword; size = pl.szPassword; break; case URL_PART_PORT: - if (!pl.szPort) return E_INVALIDARG; + if (!pl.szPort) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pPort; size = pl.szPort; break; case URL_PART_QUERY: - if (!pl.szQuery) return E_INVALIDARG; + if (!pl.szQuery) { + *pcchOut = 0; + return S_FALSE; + } addr = pl.pQuery; size = pl.szQuery; break; default: + *pcchOut = 0; return E_INVALIDARG; } if (dwFlags == URL_PARTFLAG_KEEPSCHEME) { + if(!pl.pScheme || !pl.szScheme) { + *pcchOut = 0; + return E_FAIL; + } + schaddr = pl.pScheme; + schsize = pl.szScheme; if (*pcchOut < schsize + size + 2) { *pcchOut = schsize + size + 2; - return E_POINTER; - } + return E_POINTER; + } memcpy(pszOut, schaddr, schsize*sizeof(WCHAR)); pszOut[schsize] = ':'; memcpy(pszOut+schsize+1, addr, size*sizeof(WCHAR)); @@ -2183,12 +2213,6 @@ HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, *pcchOut = size; } TRACE("len=%d %s\n", *pcchOut, debugstr_w(pszOut)); - }else if(dwPart==URL_PART_HOSTNAME && scheme==URL_SCHEME_FILE) { - if(*pcchOut) - *pszOut = '\0'; - *pcchOut = 0; - return S_FALSE; - } return ret; } diff --git a/dll/win32/syssetup/install.c b/dll/win32/syssetup/install.c index 6a1a1f7dac6..c212916252b 100644 --- a/dll/win32/syssetup/install.c +++ b/dll/win32/syssetup/install.c @@ -511,7 +511,7 @@ cleanup: } -static BOOL CALLBACK +static INT_PTR CALLBACK StatusMessageWindowProc( IN HWND hwndDlg, IN UINT uMsg, diff --git a/dll/win32/urlmon/internet.c b/dll/win32/urlmon/internet.c index 6a79e48b526..3d41defe8f6 100644 --- a/dll/win32/urlmon/internet.c +++ b/dll/win32/urlmon/internet.c @@ -405,3 +405,12 @@ HRESULT WINAPI CoInternetSetFeatureEnabled(INTERNETFEATURELIST feature, DWORD fl FIXME("%d, 0x%08x, %x, stub\n", feature, flags, enable); return E_NOTIMPL; } + +/*********************************************************************** + * CoInternetIsFeatureEnabled (URLMON.@) + */ +HRESULT WINAPI CoInternetIsFeatureEnabled(INTERNETFEATURELIST feature, DWORD flags) +{ + FIXME("%d, 0x%08x, stub\n", feature, flags); + return E_NOTIMPL; +} diff --git a/dll/win32/urlmon/sec_mgr.c b/dll/win32/urlmon/sec_mgr.c index 81f2f507d0d..f984aa4e907 100644 --- a/dll/win32/urlmon/sec_mgr.c +++ b/dll/win32/urlmon/sec_mgr.c @@ -1287,11 +1287,13 @@ HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUA return S_OK; } - hres = CoInternetParseUrl(url, PARSE_ROOTDOCUMENT, 0, domain, 0, &len, 0); - if(hres == S_FALSE) { - hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, domain, - INTERNET_MAX_URL_LENGTH, &len, 0); - if(hres == S_OK) { + hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, domain, + INTERNET_MAX_URL_LENGTH, &len, 0); + if(hres == S_OK){ + const WCHAR fileW[] = {'f','i','l','e',0}; + if(!strcmpW(domain, fileW)){ + hres = CoInternetParseUrl(url, PARSE_ROOTDOCUMENT, 0, domain, INTERNET_MAX_URL_LENGTH, &len, 0); + }else{ domain[len] = ':'; hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, domain+len+1, INTERNET_MAX_URL_LENGTH-len-1, &len, 0); @@ -1305,7 +1307,8 @@ HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUA return S_OK; } } - } + }else + return hres; len = lstrlenW(url)+1; *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR)); diff --git a/dll/win32/urlmon/uri.c b/dll/win32/urlmon/uri.c index d4d6b47e5ab..668aa9b7109 100644 --- a/dll/win32/urlmon/uri.c +++ b/dll/win32/urlmon/uri.c @@ -26,7 +26,13 @@ typedef struct { LONG ref; } Uri; -#define URI(x) ((IUri*) &(x)->lpIUriVtbl) +typedef struct { + const IUriBuilderVtbl *lpIUriBuilderVtbl; + LONG ref; +} UriBuilder; + +#define URI(x) ((IUri*) &(x)->lpIUriVtbl) +#define URIBUILDER(x) ((IUriBuilder*) &(x)->lpIUriBuilderVtbl) #define URI_THIS(iface) DEFINE_THIS(Uri, IUri, iface) @@ -300,3 +306,273 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU *ppURI = URI(ret); return S_OK; } + +#define URIBUILDER_THIS(iface) DEFINE_THIS(UriBuilder, IUriBuilder, iface) + +static HRESULT WINAPI UriBuilder_QueryInterface(IUriBuilder *iface, REFIID riid, void **ppv) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = URIBUILDER(This); + }else if(IsEqualGUID(&IID_IUriBuilder, riid)) { + TRACE("(%p)->(IID_IUri %p)\n", This, ppv); + *ppv = URIBUILDER(This); + }else { + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI UriBuilder_AddRef(IUriBuilder *iface) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI UriBuilder_Release(IUriBuilder *iface) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) + heap_free(This); + + return ref; +} + +static HRESULT WINAPI UriBuilder_CreateUriSimple(IUriBuilder *iface, + DWORD dwAllowEncodingPropertyMask, + DWORD_PTR dwReserved, + IUri **ppIUri) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_CreateUri(IUriBuilder *iface, + DWORD dwCreateFlags, + DWORD dwAllowEncodingPropertyMask, + DWORD_PTR dwReserved, + IUri **ppIUri) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface, + DWORD dwCreateFlags, + DWORD dwUriBuilderFlags, + DWORD dwAllowEncodingPropertyMask, + DWORD_PTR dwReserved, + IUri **ppIUri) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags, + dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetIUri(IUriBuilder *iface, IUri **ppIUri) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p)\n", This, ppIUri); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetIUri(IUriBuilder *iface, IUri *pIUri) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p)\n", This, pIUri); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFragment, LPCWSTR *ppwzFragment) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LPCWSTR *ppwzHost) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchHost, ppwzHost); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetPassword(IUriBuilder *iface, DWORD *pcchPassword, LPCWSTR *ppwzPassword) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchPassword, ppwzPassword); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetPath(IUriBuilder *iface, DWORD *pcchPath, LPCWSTR *ppwzPath) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchPath, ppwzPath); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetPort(IUriBuilder *iface, BOOL *pfHasPort, DWORD *pdwPort) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pfHasPort, pdwPort); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetQuery(IUriBuilder *iface, DWORD *pcchQuery, LPCWSTR *ppwzQuery) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchQuery, ppwzQuery); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetSchemeName(IUriBuilder *iface, DWORD *pcchSchemeName, LPCWSTR *ppwzSchemeName) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchSchemeName, ppwzSchemeName); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUserName, LPCWSTR *ppwzUserName) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, pcchUserName, ppwzUserName); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetPassword(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetPath(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetPort(IUriBuilder *iface, BOOL fHasPort, DWORD dwNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%d %d)\n", This, fHasPort, dwNewValue); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetQuery(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetSchemeName(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_SetUserName(IUriBuilder *iface, LPCWSTR pwzNewValue) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_RemoveProperties(IUriBuilder *iface, DWORD dwPropertyMask) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(0x%08x)\n", This, dwPropertyMask); + return E_NOTIMPL; +} + +static HRESULT WINAPI UriBuilder_HasBeenModified(IUriBuilder *iface, BOOL *pfModified) +{ + UriBuilder *This = URIBUILDER_THIS(iface); + FIXME("(%p)->(%p)\n", This, pfModified); + return E_NOTIMPL; +} + +#undef URIBUILDER_THIS + +static const IUriBuilderVtbl UriBuilderVtbl = { + UriBuilder_QueryInterface, + UriBuilder_AddRef, + UriBuilder_Release, + UriBuilder_CreateUriSimple, + UriBuilder_CreateUri, + UriBuilder_CreateUriWithFlags, + UriBuilder_GetIUri, + UriBuilder_SetIUri, + UriBuilder_GetFragment, + UriBuilder_GetHost, + UriBuilder_GetPassword, + UriBuilder_GetPath, + UriBuilder_GetPort, + UriBuilder_GetQuery, + UriBuilder_GetSchemeName, + UriBuilder_GetUserName, + UriBuilder_SetFragment, + UriBuilder_SetHost, + UriBuilder_SetPassword, + UriBuilder_SetPath, + UriBuilder_SetPort, + UriBuilder_SetQuery, + UriBuilder_SetSchemeName, + UriBuilder_SetUserName, + UriBuilder_RemoveProperties, + UriBuilder_HasBeenModified, +}; + +/*********************************************************************** + * CreateIUriBuilder (urlmon.@) + */ +HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserved, IUriBuilder **ppIUriBuilder) +{ + UriBuilder *ret; + + TRACE("(%p %x %x %p)\n", pIUri, dwFlags, (DWORD)dwReserved, ppIUriBuilder); + + ret = heap_alloc(sizeof(UriBuilder)); + if(!ret) + return E_OUTOFMEMORY; + + ret->lpIUriBuilderVtbl = &UriBuilderVtbl; + ret->ref = 1; + + *ppIUriBuilder = URIBUILDER(ret); + return S_OK; +} diff --git a/dll/win32/urlmon/urlmon.spec b/dll/win32/urlmon/urlmon.spec index a67004a9b0b..e79850c4f19 100644 --- a/dll/win32/urlmon/urlmon.spec +++ b/dll/win32/urlmon/urlmon.spec @@ -17,6 +17,7 @@ @ stub CoInternetGetProtocolFlags @ stdcall CoInternetGetSecurityUrl(ptr ptr long long) @ stdcall CoInternetGetSession(long ptr long) +@ stdcall CoInternetIsFeatureEnabled(long long) @ stdcall CoInternetParseUrl(wstr long long wstr long ptr long) @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) @ stdcall CoInternetSetFeatureEnabled(long long long) @@ -26,6 +27,7 @@ @ stdcall CreateAsyncBindCtx(long ptr ptr ptr) @ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long) @ stdcall CreateFormatEnumerator(long ptr ptr) +@ stdcall CreateIUriBuilder(ptr long long ptr) @ stdcall CreateUri(wstr long long ptr) @ stdcall CreateURLMoniker(ptr wstr ptr) @ stdcall CreateURLMonikerEx(ptr wstr ptr long) diff --git a/dll/win32/user32/include/dde_private.h b/dll/win32/user32/include/dde_private.h index 8583efdc3b0..beca7483ac5 100644 --- a/dll/win32/user32/include/dde_private.h +++ b/dll/win32/user32/include/dde_private.h @@ -208,7 +208,7 @@ extern WDML_CONV* WDML_GetConvFromWnd(HWND hWnd); extern WDML_CONV* WDML_FindConv(WDML_INSTANCE* pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic); extern BOOL WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, - BOOL fBusy, BOOL fAck, UINT pmt, LPARAM lParam, UINT oldMsg); + BOOL fBusy, BOOL fAck, UINT_PTR pmt, LPARAM lParam, UINT oldMsg); extern void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, UINT wType, HSZ hszItem, UINT wFmt); extern WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, diff --git a/dll/win32/user32/include/user32.h b/dll/win32/user32/include/user32.h index 174d71ebb3b..99f48a1a9a2 100644 --- a/dll/win32/user32/include/user32.h +++ b/dll/win32/user32/include/user32.h @@ -153,7 +153,7 @@ DesktopPtrToUser(PVOID Ptr) /* NOTE: This is slow as it requires a call to win32k. This should only be neccessary if a thread wants to access an object on a different desktop */ - return NtUserGetDesktopMapping(Ptr); + return (PVOID)NtUserGetDesktopMapping(Ptr); } } diff --git a/dll/win32/user32/misc/dllmain.c b/dll/win32/user32/misc/dllmain.c index 044f493fda4..7a1abc97d1e 100644 --- a/dll/win32/user32/misc/dllmain.c +++ b/dll/win32/user32/misc/dllmain.c @@ -217,23 +217,25 @@ BOOL Init(VOID) { USERCONNECT UserCon; + PVOID *KernelCallbackTable; /* Set up the kernel callbacks. */ - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] = + KernelCallbackTable = NtCurrentPeb()->KernelCallbackTable; + KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] = (PVOID)User32CallWindowProcFromKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] = + KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] = (PVOID)User32CallSendAsyncProcForKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] = + KernelCallbackTable[USER32_CALLBACK_LOADSYSMENUTEMPLATE] = (PVOID)User32LoadSysMenuTemplateForKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] = + KernelCallbackTable[USER32_CALLBACK_LOADDEFAULTCURSORS] = (PVOID)User32SetupDefaultCursors; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] = + KernelCallbackTable[USER32_CALLBACK_HOOKPROC] = (PVOID)User32CallHookProcFromKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_EVENTPROC] = + KernelCallbackTable[USER32_CALLBACK_EVENTPROC] = (PVOID)User32CallEventProcFromKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_LOADMENU] = + KernelCallbackTable[USER32_CALLBACK_LOADMENU] = (PVOID)User32CallLoadMenuFromKernel; - NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_CLIENTTHREADSTARTUP] = + KernelCallbackTable[USER32_CALLBACK_CLIENTTHREADSTARTUP] = (PVOID)User32CallClientThreadSetupFromKernel; NtUserProcessConnect( NtCurrentProcess(), diff --git a/dll/win32/user32/windows/defwnd.c b/dll/win32/user32/windows/defwnd.c index ee6def9cdab..890076b0286 100644 --- a/dll/win32/user32/windows/defwnd.c +++ b/dll/win32/user32/windows/defwnd.c @@ -30,6 +30,7 @@ LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam); void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest ); +void MENU_EndMenu( HWND ); /* GLOBALS *******************************************************************/ @@ -1480,7 +1481,8 @@ User32DefWindowProc(HWND hWnd, { iMenuSysKey = 0; /* FIXME: Check for a desktop. */ - if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu(); + //if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu(); + MENU_EndMenu( hWnd ); if (GetCapture() == hWnd) { ReleaseCapture(); @@ -2049,7 +2051,6 @@ RealDefWindowProcW(HWND hWnd, LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam; /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP) * may have child window IDs instead of window name */ - if (HIWORD(cs->lpszName)) { DefSetText(hWnd, cs->lpszName, FALSE); diff --git a/dll/win32/user32/windows/draw.c b/dll/win32/user32/windows/draw.c index cb67e30f46b..2eb68d11988 100644 --- a/dll/win32/user32/windows/draw.c +++ b/dll/win32/user32/windows/draw.c @@ -1574,7 +1574,7 @@ FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1)) { - hbr = GetSysColorBrush((int)hbr - 1); + hbr = GetSysColorBrush(PtrToUlong(hbr) - 1); } if ((prevhbr = SelectObject(hDC, hbr)) == NULL) { diff --git a/dll/win32/user32/windows/menu.c b/dll/win32/user32/windows/menu.c index 58c4a95243e..ade437c840a 100644 --- a/dll/win32/user32/windows/menu.c +++ b/dll/win32/user32/windows/menu.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll * FILE: user32/windows/menu.c @@ -34,7 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu); /* Internal MenuTrackMenu() flags */ #define TPM_INTERNAL 0xF0000000 -#define TPM_ENTERIDLEEX 0x80000000 /* set owner window for WM_ENTERIDLE */ #define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */ #define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */ @@ -58,6 +56,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(menu); /* Use global popup window because there's no way 2 menus can * be tracked at the same time. */ static HWND top_popup; +static HMENU top_popup_hmenu; /* Flag set by EndMenu() to force an exit from menu tracking */ static BOOL fEndMenu = FALSE; @@ -540,7 +539,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, ItemInfo = Items; for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++) { - if ((ItemInfo->Text) && NULL != ItemInfo->dwTypeData) + if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData) { WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2; do @@ -576,8 +575,7 @@ static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, * * Get the size of a bitmap item. */ -static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, - HWND WndOwner) +static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, HWND WndOwner) { BITMAP bm; HBITMAP bmp = lpitem->hbmpItem; @@ -808,7 +806,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN return; } - lpitem->XTab = 0; + lpitem->dxTab = 0; if (lpitem->hbmpItem) { @@ -831,12 +829,12 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN if( !(MenuInfo->dwStyle & MNS_NOCHECK)) lpitem->Rect.right += 2 * check_bitmap_width; lpitem->Rect.right += 4 + MenuCharSize.cx; - lpitem->XTab = lpitem->Rect.right; + lpitem->dxTab = lpitem->Rect.right; lpitem->Rect.right += check_bitmap_width; } else /* hbmpItem & MenuBar */ { MenuGetBitmapItemSize(lpitem, &size, hwndOwner ); lpitem->Rect.right += size.cx; - if( lpitem->Text) lpitem->Rect.right += 2; + if( lpitem->lpstr) lpitem->Rect.right += 2; itemheight = size.cy; /* Special case: Minimize button doesn't have a space behind it. */ @@ -849,12 +847,12 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN if( !(MenuInfo->dwStyle & MNS_NOCHECK)) lpitem->Rect.right += check_bitmap_width; lpitem->Rect.right += 4 + MenuCharSize.cx; - lpitem->XTab = lpitem->Rect.right; + lpitem->dxTab = lpitem->Rect.right; lpitem->Rect.right += check_bitmap_width; } /* it must be a text item - unless it's the system menu */ - if (!(lpitem->fType & MF_SYSMENU) && lpitem->Text) { + if (!(lpitem->fType & MF_SYSMENU) && lpitem->lpstr) { HFONT hfontOld = NULL; RECT rc = lpitem->Rect; LONG txtheight, txtwidth; @@ -883,7 +881,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN /* get text size after the tab */ tmpheight = DrawTextW( hdc, p, -1, &tmprc, DT_SINGLELINE|DT_CALCRECT); - lpitem->XTab += txtwidth; + lpitem->dxTab += txtwidth; txtheight = max( txtheight, tmpheight); txtwidth += MenuCharSize.cx + /* space for the tab */ tmprc.right - tmprc.left; /* space for the short cut */ @@ -891,7 +889,7 @@ static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMEN txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc, DT_SINGLELINE|DT_CALCRECT); txtwidth = rc.right - rc.left; - lpitem->XTab += txtwidth; + lpitem->dxTab += txtwidth; } lpitem->Rect.right += 2 + txtwidth; itemheight = max( itemheight, @@ -967,10 +965,10 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) // } maxX = max(maxX, lpitem.Rect.right); orgY = lpitem.Rect.bottom; - if ((lpitem.Text) && lpitem.XTab ) + if ((lpitem.lpstr) && lpitem.dxTab ) { - maxTab = max( maxTab, lpitem.XTab ); - maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.XTab); + maxTab = max( maxTab, lpitem.dxTab ); + maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab); } } @@ -981,9 +979,9 @@ static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem)) { lpitem.Rect.right = maxX; - if ((lpitem.Text) && 0 != lpitem.XTab) + if ((lpitem.lpstr) && 0 != lpitem.dxTab) { - lpitem.XTab = maxTab; + lpitem.dxTab = maxTab; } MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem); } @@ -1381,7 +1379,7 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd } /* process text if present */ - if (lpitem->Text) + if (lpitem->lpstr) { register int i = 0; HFONT hfontOld = 0; @@ -1431,12 +1429,12 @@ static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND Wnd { if (L'\t' == Text[i]) { - rect.left = lpitem->XTab; + rect.left = lpitem->dxTab; uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE; } else { - rect.right = lpitem->XTab; + rect.right = lpitem->dxTab; uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE; } @@ -1635,6 +1633,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE; if (!top_popup) { top_popup = MenuInfo.Wnd; + top_popup_hmenu = hmenu; } /* Display the window */ @@ -1645,6 +1644,7 @@ static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT fl return TRUE; } + /*********************************************************************** * MenuSelectItem */ @@ -1663,6 +1663,7 @@ static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIn else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW); if (!top_popup) { top_popup = hmenu->Wnd; + top_popup_hmenu = hmenu->Self; } SelectObject( hdc, hMenuFont ); @@ -1834,6 +1835,7 @@ LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM l if (Wnd == top_popup) { top_popup = NULL; + top_popup_hmenu = NULL; } break; @@ -1906,6 +1908,7 @@ PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) if (Wnd == top_popup) { top_popup = NULL; + top_popup_hmenu = NULL; } break; @@ -2354,13 +2357,30 @@ MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Fl return Ret; } +/********************************************************************** + * MENU_EndMenu + * + * Calls EndMenu() if the hwnd parameter belongs to the menu owner + * + * Does the (menu stuff) of the default window handling of WM_CANCELMODE + */ +void MENU_EndMenu( HWND hwnd ) +{ + ROSMENUINFO MenuInfo; + BOOL Ret = FALSE; + if (top_popup_hmenu) + Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu); + if (Ret && hwnd == MenuInfo.WndOwner) EndMenu(); +} + /*********************************************************************** * MenuHideSubPopups * * Hide the sub-popup menus of this menu. */ static void FASTCALL -MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect) +MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, + BOOL SendMenuSelect, UINT wFlags) { ROSMENUINFO SubMenuInfo; ROSMENUITEMINFO ItemInfo; @@ -2368,28 +2388,32 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect) TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect); if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem) - { + { MenuInitRosMenuItemInfo(&ItemInfo); ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE; if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo) || 0 == (ItemInfo.fType & MF_POPUP) || 0 == (ItemInfo.fState & MF_MOUSESELECT)) - { + { MenuCleanupRosMenuItemInfo(&ItemInfo); return; - } + } ItemInfo.fState &= ~MF_MOUSESELECT; ItemInfo.fMask |= MIIM_STATE; MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) - { - MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE); + { + MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags); MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL); DestroyWindow(SubMenuInfo.Wnd); SubMenuInfo.Wnd = NULL; MenuSetRosMenuInfo(&SubMenuInfo); - } - } + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) ); + } + } } /*********************************************************************** @@ -2398,7 +2422,7 @@ MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SendMenuSelect) * Helper function for menu navigation routines. */ static void FASTCALL -MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index) +MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlags) { ROSMENUINFO TopMenuInfo; @@ -2409,13 +2433,13 @@ MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index) 0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MF_POPUP)) { /* both are top level menus (system and menu-bar) */ - MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE); + MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, NO_SELECTED_ITEM, FALSE, NULL); Mt->TopMenu = PtMenuInfo->Self; } else { - MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE); + MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE, wFlags); } MenuSelectItem(Mt->OwnerWnd, PtMenuInfo, Index, TRUE, NULL); @@ -2531,7 +2555,7 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) { if (MenuInfo.FocusedItem != Index) { - MenuSwitchTracking(Mt, &MenuInfo, Index); + MenuSwitchTracking(Mt, &MenuInfo, Index, Flags); } /* If the popup menu is not already "popped" */ @@ -2714,7 +2738,7 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) && !(ItemInfo.fType & MF_SEPARATOR)) { - MenuSwitchTracking(Mt, &MenuInfo, Index); + MenuSwitchTracking(Mt, &MenuInfo, Index, Flags); if (!(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED))) Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); } @@ -2763,7 +2787,7 @@ MenuGetSubPopup(HMENU Menu) * NOTE: WM_NEXTMENU documented in Win32 is a bit different. */ static LRESULT FASTCALL -MenuDoNextMenu(MTRACKER* Mt, UINT Vk) +MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags) { ROSMENUINFO TopMenuInfo; ROSMENUINFO MenuInfo; @@ -2858,7 +2882,7 @@ MenuDoNextMenu(MTRACKER* Mt, UINT Vk) FALSE, 0 ); if (Mt->CurrentMenu != Mt->TopMenu) { - MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE); + MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); } } @@ -2949,7 +2973,7 @@ MenuKeyEscape(MTRACKER *Mt, UINT Flags) if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev)) { - MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE); + MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE, Flags); } Mt->CurrentMenu = MenuPrev; EndMenu = FALSE; @@ -3001,7 +3025,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) { return; } - MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE); + MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE, Flags); Mt->CurrentMenu = MenuPrev; if (! MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu)) @@ -3012,7 +3036,7 @@ MenuKeyLeft(MTRACKER* Mt, UINT Flags) { /* move menu bar selection if no more popups are left */ - if (! MenuDoNextMenu(Mt, VK_LEFT)) + if (! MenuDoNextMenu(Mt, VK_LEFT, Flags)) { MenuMoveSelection(Mt->OwnerWnd, &TopMenuInfo, ITEM_PREV); } @@ -3082,7 +3106,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) { if (Mt->CurrentMenu != Mt->TopMenu) { - MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE ); + MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); hmenutmp = Mt->CurrentMenu = Mt->TopMenu; } else @@ -3091,7 +3115,7 @@ static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) } /* try to move to the next item */ - if ( !MenuDoNextMenu(Mt, VK_RIGHT)) + if ( !MenuDoNextMenu(Mt, VK_RIGHT, Flags)) MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT); if ( hmenutmp || Mt->TrackFlags & TF_SUSPENDPOPUP ) @@ -3135,6 +3159,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (!IsMenu(hmenu)) { + WARN("Invalid menu handle %p\n", hmenu); SetLastError( ERROR_INVALID_MENU_HANDLE ); return FALSE; } @@ -3177,7 +3202,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, { if (!enterIdleSent) { - HWND win = (wFlags & TPM_ENTERIDLEEX) && (MenuInfo.Flags & MF_POPUP) ? MenuInfo.Wnd : NULL; + HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL; enterIdleSent = TRUE; SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win); } @@ -3242,6 +3267,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (hmenu) { executedMenuId = MenuButtonUp( &mt, hmenu, wFlags); + TRACE("executedMenuId %d\n", executedMenuId); /* End the loop if executedMenuId is an item ID */ /* or if the job was done (executedMenuId = 0). */ @@ -3261,7 +3287,6 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, if (hmenu) fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags ); - break; } /* switch(msg.message) - mouse */ } @@ -3401,6 +3426,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); else mt.TrackFlags &= ~TF_SKIPREMOVE; } + ERR("MenuTrackMenu 2\n"); (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL); SetCapture(NULL); /* release the capture */ @@ -3415,7 +3441,7 @@ static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, { if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) { - MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE); + MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags); if (MenuInfo.Flags & MF_POPUP) { @@ -3464,31 +3490,35 @@ static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION ); + MenuGetRosMenuInfo(&MenuInfo, hMenu); + if (!(wFlags & TPM_NONOTIFY)) { SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 ); + /* If an app changed/recreated menu bar entries in WM_INITMENU + * menu sizes will be recalculated once the menu created/shown. + */ - MenuGetRosMenuInfo(&MenuInfo, hMenu); - - if (!MenuInfo.Height) - { - /* app changed/recreated menu bar entries in WM_INITMENU - Recalculate menu sizes else clicks will not work */ - SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + if (!MenuInfo.Height) + { + /* app changed/recreated menu bar entries in WM_INITMENU + Recalculate menu sizes else clicks will not work */ + SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); - } - /* This makes the menus of applications built with Delphi work. - * It also enables menus to be displayed in more than one window, - * but there are some bugs left that need to be fixed in this case. - */ - if(MenuInfo.Self == hMenu) - { - MenuInfo.Wnd = hWnd; - MenuSetRosMenuInfo(&MenuInfo); - } + } } + /* This makes the menus of applications built with Delphi work. + * It also enables menus to be displayed in more than one window, + * but there are some bugs left that need to be fixed in this case. + */ + if(MenuInfo.Self == hMenu) + { + MenuInfo.Wnd = hWnd; + MenuSetRosMenuInfo(&MenuInfo); + } + return TRUE; } /*********************************************************************** @@ -3501,6 +3531,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd) SendMessageW( hWnd, WM_EXITMENULOOP, 0, 0 ); ShowCaret(0); top_popup = 0; + top_popup_hmenu = NULL; return TRUE; } @@ -3512,7 +3543,7 @@ static BOOL FASTCALL MenuExitTracking(HWND hWnd) VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt) { HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd); - UINT wFlags = TPM_ENTERIDLEEX | TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON; + UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON; TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y); @@ -3542,7 +3573,7 @@ VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) UINT uItem = NO_SELECTED_ITEM; HMENU hTrackMenu; ROSMENUINFO MenuInfo; - UINT wFlags = TPM_ENTERIDLEEX | TPM_LEFTALIGN | TPM_LEFTBUTTON; + UINT wFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON; TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hwnd, wParam, wChar); @@ -3611,17 +3642,6 @@ track_menu: */ BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, HWND Wnd, LPTPMPARAMS Tpm) -{ - /* Not fully implemented */ - return TrackPopupMenu(Menu, Flags, x, y, 0, Wnd, - NULL != Tpm ? &Tpm->rcExclude : NULL); -} - -/********************************************************************** - * TrackPopupMenu (USER32.@) - */ -BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, - int Reserved, HWND Wnd, CONST RECT *Rect) { BOOL ret = FALSE; @@ -3638,11 +3658,21 @@ BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0); if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 )) - ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, Rect); + ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, + Tpm ? &Tpm->rcExclude : NULL); MenuExitTracking(Wnd); return ret; } +/********************************************************************** + * TrackPopupMenu (USER32.@) + */ +BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, + int Reserved, HWND Wnd, CONST RECT *Rect) +{ + return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL); +} + /* * From MSDN: * The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined @@ -4035,7 +4065,6 @@ DrawMenuBar(HWND hWnd) return TRUE; } - /* * @implemented */ @@ -4057,11 +4086,48 @@ EndMenu(VOID) guii.cbSize = sizeof(GUITHREADINFO); if(GetGUIThreadInfo(GetCurrentThreadId(), &guii) && guii.hwndMenuOwner) { - PostMessageW(guii.hwndMenuOwner, WM_CANCELMODE, 0, 0); + if (!fEndMenu && + top_popup && + guii.hwndMenuOwner != top_popup ) + { + ERR("Capture GUI pti hWnd does not match top_popup!\n"); + } + } + + /* if we are in the menu code, and it is active */ + if (!fEndMenu && top_popup) + { + /* terminate the menu handling code */ + fEndMenu = TRUE; + + /* needs to be posted to wakeup the internal menu handler */ + /* which will now terminate the menu, in the event that */ + /* the main window was minimized, or lost focus, so we */ + /* don't end up with an orphaned menu */ + PostMessageW( top_popup, WM_CANCELMODE, 0, 0); } return TRUE; } +// So this one maybe one day it will be a callback! +BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID, + UINT wHilite ) +{ + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO mii; + TRACE("(%p, %p, %04x, %04x);\n", hWnd, hMenu, wItemID, wHilite); + if (!hWnd) + { + SetLastError(ERROR_INVALID_WINDOW_HANDLE); + return FALSE; + } + if (!NtUserMenuItemInfo(hMenu, wItemID, wHilite, &mii, FALSE)) return FALSE; + if (!NtUserMenuInfo(hMenu, &MenuInfo, FALSE)) return FALSE; + if (MenuInfo.FocusedItem == wItemID) return TRUE; + MenuHideSubPopups( hWnd, &MenuInfo, FALSE, 0 ); + MenuSelectItem( hWnd, &MenuInfo, wItemID, TRUE, 0 ); + return TRUE; +} /* * @implemented diff --git a/dll/win32/user32/windows/message.c b/dll/win32/user32/windows/message.c index 81d0d96be09..5631469c03c 100644 --- a/dll/win32/user32/windows/message.c +++ b/dll/win32/user32/windows/message.c @@ -2448,7 +2448,7 @@ TranslateMessageEx(CONST MSG *lpMsg, DWORD unk) case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: - return(NtUserTranslateMessage((LPMSG)lpMsg, (HKL)unk)); + return(NtUserTranslateMessage((LPMSG)lpMsg, unk)); default: if ( lpMsg->message & ~WM_MAXIMUM ) diff --git a/dll/win32/usp10/usp10.c b/dll/win32/usp10/usp10.c index 1a68ae0201a..cdd6d7b2919 100644 --- a/dll/win32/usp10/usp10.c +++ b/dll/win32/usp10/usp10.c @@ -1308,7 +1308,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, { WORD glyph; if (!hdc) return E_PENDING; - if (GetGlyphIndicesW(hdc, &pwcChars[i], 1, &glyph, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE; + if (GetGlyphIndicesW(hdc, &pwcChars[i], 1, &glyph, 0) == GDI_ERROR) return S_FALSE; pwOutGlyphs[i] = set_cache_glyph(psc, pwcChars[i], glyph); } } diff --git a/dll/win32/version/info.c b/dll/win32/version/info.c index 5bdcbd7a9d6..e7f7077e72b 100644 --- a/dll/win32/version/info.c +++ b/dll/win32/version/info.c @@ -29,15 +29,17 @@ #include "windef.h" #include "winbase.h" #include "winver.h" -#include "winternl.h" #include "winuser.h" -#include "wine/winuser16.h" +#include "winternl.h" +#include "lzexpand.h" #include "wine/unicode.h" #include "winerror.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ver); +extern DWORD find_version_resource( HFILE lzfd, DWORD *reslen, DWORD *offset ); + /****************************************************************************** * * This function will print via standard TRACE, debug info regarding @@ -230,225 +232,16 @@ typedef struct #define VersionInfo32_Next( ver ) \ (VS_VERSION_INFO_STRUCT32 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) ) -/*********************************************************************** - * VERSION_GetFileVersionInfo_PE [internal] - * - * NOTE: returns size of the PE VERSION resource or 0xFFFFFFFF - * in the case the file is a PE module, but VERSION_INFO not found. - */ -static DWORD VERSION_GetFileVersionInfo_PE( LPCWSTR filename, DWORD datasize, LPVOID data ) -{ - const VS_FIXEDFILEINFO *vffi; - DWORD len; - BYTE *buf; - HMODULE hModule; - HRSRC hRsrc; - HGLOBAL hMem; - - TRACE("%s\n", debugstr_w(filename)); - - if (!GetModuleHandleExW(0, filename, &hModule)) - hModule = LoadLibraryExW(filename, 0, LOAD_LIBRARY_AS_DATAFILE); - - if(!hModule) - { - WARN("Could not load %s\n", debugstr_w(filename)); - - return 0; - } - hRsrc = FindResourceW(hModule, - MAKEINTRESOURCEW(VS_VERSION_INFO), - MAKEINTRESOURCEW(VS_FILE_INFO)); - if(!hRsrc) - { - WARN("Could not find VS_VERSION_INFO in %s\n", debugstr_w(filename)); - FreeLibrary(hModule); - return 0xFFFFFFFF; - } - len = SizeofResource(hModule, hRsrc); - hMem = LoadResource(hModule, hRsrc); - if(!hMem) - { - WARN("Could not load VS_VERSION_INFO from %s\n", debugstr_w(filename)); - FreeLibrary(hModule); - return 0xFFFFFFFF; - } - buf = LockResource(hMem); - - vffi = (VS_FIXEDFILEINFO *)VersionInfo32_Value( (VS_VERSION_INFO_STRUCT32 *)buf ); - - if ( vffi->dwSignature != VS_FFI_SIGNATURE ) - { - WARN("vffi->dwSignature is 0x%08x, but not 0x%08lx!\n", - vffi->dwSignature, VS_FFI_SIGNATURE ); - len = 0xFFFFFFFF; - goto END; - } - - if ( TRACE_ON(ver) ) - print_vffi_debug( vffi ); - - if(data) - { - if(datasize < len) - len = datasize; /* truncate data */ - if(len) - memcpy(data, buf, len); - else - len = 0xFFFFFFFF; - } -END: - FreeResource(hMem); - FreeLibrary(hModule); - - return len; -} - -#ifndef __REACTOS__ -/*********************************************************************** - * VERSION_GetFileVersionInfo_16 [internal] - * - * NOTE: returns size of the 16-bit VERSION resource or 0xFFFFFFFF - * in the case the file exists, but VERSION_INFO not found. - */ -static DWORD VERSION_GetFileVersionInfo_16( LPCSTR filename, DWORD datasize, LPVOID data ) -{ - const VS_FIXEDFILEINFO *vffi; - DWORD len, offset; - BYTE *buf; - HMODULE16 hModule; - HRSRC16 hRsrc; - HGLOBAL16 hMem; - char dllname[20], owner[20], *p; - const char *basename; - BOOL is_builtin = FALSE; - - TRACE("%s\n", debugstr_a(filename)); - - /* strip path information */ - - basename = filename; - if (basename[0] && basename[1] == ':') basename += 2; /* strip drive specification */ - if ((p = strrchr( basename, '\\' ))) basename = p + 1; - if ((p = strrchr( basename, '/' ))) basename = p + 1; - - if (strlen(basename) < sizeof(dllname)-4) - { - int file_exists; - - strcpy( dllname, basename ); - p = strrchr( dllname, '.' ); - if (!p) strcat( dllname, ".dll" ); - for (p = dllname; *p; p++) if (*p >= 'A' && *p <= 'Z') *p += 32; - - if (wine_dll_get_owner( dllname, owner, sizeof(owner), &file_exists ) == 0) - is_builtin = TRUE; - } - - /* first try without loading a 16-bit module */ - if (is_builtin) - len = 0; - else - len = GetFileResourceSize16( filename, - MAKEINTRESOURCEA(VS_FILE_INFO), - MAKEINTRESOURCEA(VS_VERSION_INFO), - &offset ); - if (len) - { - if (!data) return len; - - len = GetFileResource16( filename, - MAKEINTRESOURCEA(VS_FILE_INFO), - MAKEINTRESOURCEA(VS_VERSION_INFO), - offset, datasize, data ); - if (len) - { - vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)data ); - - if ( vffi->dwSignature == VS_FFI_SIGNATURE ) - { - if ( ((VS_VERSION_INFO_STRUCT16 *)data)->wLength < len ) - len = ((VS_VERSION_INFO_STRUCT16 *)data)->wLength; - - if ( TRACE_ON(ver) ) - print_vffi_debug( vffi ); - - return len; - } - } - } - - /* this might be a builtin 16-bit module */ - hModule = LoadLibrary16(filename); - if(hModule < 32) - { - WARN("Could not load %s\n", debugstr_a(filename)); - if (hModule == ERROR_BAD_FORMAT) - return 0xFFFFFFFF; - else - return 0x0; - } - hRsrc = FindResource16(hModule, - MAKEINTRESOURCEA(VS_VERSION_INFO), - MAKEINTRESOURCEA(VS_FILE_INFO)); - if(!hRsrc) - { - WARN("Could not find VS_VERSION_INFO in %s\n", debugstr_a(filename)); - FreeLibrary16(hModule); - return 0xFFFFFFFF; - } - len = SizeofResource16(hModule, hRsrc); - hMem = LoadResource16(hModule, hRsrc); - if(!hMem) - { - WARN("Could not load VS_VERSION_INFO from %s\n", debugstr_a(filename)); - FreeLibrary16(hModule); - return 0xFFFFFFFF; - } - buf = LockResource16(hMem); - - if(!VersionInfoIs16(buf)) - { - len = 0xFFFFFFFF; - goto END; - } - - vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)buf ); - - if ( vffi->dwSignature != VS_FFI_SIGNATURE ) - { - WARN("vffi->dwSignature is 0x%08x, but not 0x%08lx!\n", - vffi->dwSignature, VS_FFI_SIGNATURE ); - len = 0xFFFFFFFF; - goto END; - } - - if ( TRACE_ON(ver) ) - print_vffi_debug( vffi ); - - if(data) - { - if(datasize < len) - len = datasize; /* truncate data */ - if(len) - memcpy(data, buf, len); - else - len = 0xFFFFFFFF; - } -END: - FreeResource16(hMem); - FreeLibrary16(hModule); - - return len; -} -#endif /* ! __REACTOS__ */ /*********************************************************************** * GetFileVersionInfoSizeW [VERSION.@] */ DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle ) { - DWORD len; + DWORD len, offset, magic = 1; + HFILE lzfd; + HMODULE hModule; + OFSTRUCT ofs; TRACE("(%s,%p)\n", debugstr_w(filename), handle ); @@ -465,40 +258,27 @@ DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle ) return 0; } - len = VERSION_GetFileVersionInfo_PE(filename, 0, NULL); - /* 0xFFFFFFFF means: file is a PE module, but VERSION_INFO not found */ - if(len == 0xFFFFFFFF) + if ((lzfd = LZOpenFileW( (LPWSTR)filename, &ofs, OF_READ )) != HFILE_ERROR) { - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return 0; + magic = find_version_resource( lzfd, &len, &offset ); + LZClose( lzfd ); } - if (!len) + if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE ))) { -#ifdef __REACTOS__ - SetLastError(ERROR_FILE_NOT_FOUND); - return 0; -#else /* __REACTOS__ */ - LPSTR filenameA; - - len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL ); - filenameA = HeapAlloc( GetProcessHeap(), 0, len ); - WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL ); - - len = VERSION_GetFileVersionInfo_16(filenameA, 0, NULL); - HeapFree( GetProcessHeap(), 0, filenameA ); - /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */ - if (!len) + HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO), + MAKEINTRESOURCEW(VS_FILE_INFO) ); + if (hRsrc) { - SetLastError(ERROR_FILE_NOT_FOUND); - return 0; - } - if (len == 0xFFFFFFFF) - { - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return 0; + magic = IMAGE_NT_SIGNATURE; + len = SizeofResource( hModule, hRsrc ); } + FreeLibrary( hModule ); + } + switch (magic) + { + case IMAGE_OS2_SIGNATURE: /* We have a 16bit resource. * * XP/W2K/W2K3 uses a buffer which is more than the actual needed space: @@ -509,21 +289,22 @@ DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle ) * info->wLength should be the same as len. Currently it isn't but that * doesn't seem to be a problem (len is bigger than info->wLength). */ - len = (len - sizeof(VS_FIXEDFILEINFO)) * 4; -#endif /* ! __REACTOS__ */ - } - else - { + SetLastError(0); + return (len - sizeof(VS_FIXEDFILEINFO)) * 4; + + case IMAGE_NT_SIGNATURE: /* We have a 32bit resource. * * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X" * This extra buffer is used for Unicode to ANSI conversions in A-Calls */ - len = (len * 2) + 4; - } + SetLastError(0); + return (len * 2) + 4; - SetLastError(0); - return len; + default: + SetLastError( lzfd == HFILE_ERROR ? ofs.nErrCode : ERROR_RESOURCE_DATA_NOT_FOUND ); + return 0; + } } /*********************************************************************** @@ -554,7 +335,11 @@ DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle ) BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data ) { - DWORD len; + static const char signature[4] = "FE2X"; + DWORD len, offset, magic = 1; + HFILE lzfd; + OFSTRUCT ofs; + HMODULE hModule; VS_VERSION_INFO_STRUCT32* vvis = data; TRACE("(%s,%d,size=%d,data=%p)\n", @@ -565,59 +350,58 @@ BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle, SetLastError(ERROR_INVALID_DATA); return FALSE; } - len = VERSION_GetFileVersionInfo_PE(filename, datasize, data); - /* 0xFFFFFFFF means: file is a PE module, but VERSION_INFO not found */ - if (len == 0xFFFFFFFF) + + if ((lzfd = LZOpenFileW( (LPWSTR)filename, &ofs, OF_READ )) != HFILE_ERROR) { - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return FALSE; - } - - if (!len) - { -#ifdef __REACTOS__ - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return FALSE; -#else /* __REACTOS__ */ - LPSTR filenameA; - - len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL ); - filenameA = HeapAlloc( GetProcessHeap(), 0, len ); - WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL ); - - len = VERSION_GetFileVersionInfo_16(filenameA, datasize, data); - HeapFree( GetProcessHeap(), 0, filenameA ); - /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */ - if (!len || len == 0xFFFFFFFF) + if ((magic = find_version_resource( lzfd, &len, &offset )) > 1) { - SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); - return FALSE; + LZSeek( lzfd, offset, 0 /* SEEK_SET */ ); + len = LZRead( lzfd, data, min( len, datasize ) ); } - /* We have a 16bit resource. */ -#endif /* ! __REACTOS__ */ + LZClose( lzfd ); } - else + + if ((magic == 1) && (hModule = LoadLibraryExW( filename, 0, LOAD_LIBRARY_AS_DATAFILE ))) { - static const char signature[] = "FE2X"; - DWORD bufsize = vvis->wLength + strlen(signature); - DWORD convbuf; - + HRSRC hRsrc = FindResourceW( hModule, MAKEINTRESOURCEW(VS_VERSION_INFO), + MAKEINTRESOURCEW(VS_FILE_INFO) ); + if (hRsrc) + { + HGLOBAL hMem = LoadResource( hModule, hRsrc ); + magic = IMAGE_NT_SIGNATURE; + len = min( SizeofResource(hModule, hRsrc), datasize ); + memcpy( data, LockResource( hMem ), len ); + FreeResource( hMem ); + } + FreeLibrary( hModule ); + } + + switch (magic) + { + case IMAGE_OS2_SIGNATURE: + /* We have a 16bit resource. */ + if (TRACE_ON(ver)) + print_vffi_debug( (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)data )); + SetLastError(0); + return TRUE; + + case IMAGE_NT_SIGNATURE: /* We have a 32bit resource. * * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X" * This extra buffer is used for Unicode to ANSI conversions in A-Calls */ + len = vvis->wLength + sizeof(signature); + if (datasize >= len) memcpy( (char*)data + vvis->wLength, signature, sizeof(signature) ); + if (TRACE_ON(ver)) + print_vffi_debug( (VS_FIXEDFILEINFO *)VersionInfo32_Value( vvis )); + SetLastError(0); + return TRUE; - /* information is truncated to datasize bytes */ - if (datasize >= bufsize) - { - convbuf = datasize - vvis->wLength; - memcpy( ((char*)(data))+vvis->wLength, signature, convbuf > 4 ? 4 : convbuf ); - } + default: + SetLastError( lzfd == HFILE_ERROR ? ofs.nErrCode : ERROR_RESOURCE_DATA_NOT_FOUND ); + return FALSE; } - - SetLastError(0); - return TRUE; } /*********************************************************************** diff --git a/dll/win32/version/resource.c b/dll/win32/version/resource.c index a1123c55bf7..e7d34e08a88 100644 --- a/dll/win32/version/resource.c +++ b/dll/win32/version/resource.c @@ -36,15 +36,16 @@ #include "windef.h" #include "winbase.h" #include "lzexpand.h" +#include "winuser.h" +#include "winver.h" +#undef VS_FILE_INFO +#define VS_FILE_INFO 16 #include "wine/unicode.h" #include "wine/winbase16.h" #include "wine/debug.h" -/* winnt.h */ -#define IMAGE_FILE_RESOURCE_DIRECTORY 2 - WINE_DEFAULT_DEBUG_CHANNEL(ver); @@ -91,56 +92,6 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_ } -/********************************************************************** - * find_entry_by_name - * - * Find an entry by name in a resource directory - * Copied from loader/pe_resource.c - */ -static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( const IMAGE_RESOURCE_DIRECTORY *dir, - LPCSTR name, const void *root ) -{ - const IMAGE_RESOURCE_DIRECTORY *ret = NULL; - LPWSTR nameW; - DWORD namelen; - - if (!HIWORD(name)) return find_entry_by_id( dir, LOWORD(name), root ); - if (name[0] == '#') - { - return find_entry_by_id( dir, atoi(name+1), root ); - } - - namelen = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 ); - if ((nameW = HeapAlloc( GetProcessHeap(), 0, namelen * sizeof(WCHAR) ))) - { - const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; - const IMAGE_RESOURCE_DIR_STRING_U *str; - int min, max, res, pos; - - MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, namelen ); - namelen--; /* remove terminating null */ - entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); - min = 0; - max = dir->NumberOfNamedEntries - 1; - while (min <= max) - { - pos = (min + max) / 2; - str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const char *)root + entry[pos].u1.s1.NameOffset); - res = strncmpiW( nameW, str->NameString, str->Length ); - if (!res && namelen == str->Length) - { - ret = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].u2.s3.OffsetToDirectory); - break; - } - if (res < 0) max = pos - 1; - else min = pos + 1; - } - HeapFree( GetProcessHeap(), 0, nameW ); - } - return ret; -} - - /*********************************************************************** * read_xx_header [internal] */ @@ -153,7 +104,11 @@ static int read_xx_header( HFILE lzfd ) if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) ) return 0; if ( mzh.e_magic != IMAGE_DOS_SIGNATURE ) + { + if (!memcmp( &mzh, "\177ELF", 4 )) return 1; /* ELF */ + if (*(UINT *)&mzh == 0xfeedface || *(UINT *)&mzh == 0xcefaedfe) return 1; /* Mach-O */ return 0; + } LZSeek( lzfd, mzh.e_lfanew, SEEK_SET ); if ( 2 != LZRead( lzfd, magic, 2 ) ) @@ -171,13 +126,13 @@ static int read_xx_header( HFILE lzfd ) return 0; } -#ifndef __REACTOS__ /*********************************************************************** * find_ne_resource [internal] */ -static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, - DWORD *resLen, DWORD *resOff ) +static BOOL find_ne_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff ) { + const WORD typeid = VS_FILE_INFO | 0x8000; + const WORD resid = VS_VERSION_INFO | 0x8000; IMAGE_OS2_HEADER nehd; NE_TYPEINFO *typeInfo; NE_NAMEINFO *nameInfo; @@ -210,55 +165,23 @@ static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, /* Find resource */ typeInfo = (NE_TYPEINFO *)(resTab + 2); - - if (HIWORD(typeid) != 0) /* named type */ + while (typeInfo->type_id) { - BYTE len = strlen( typeid ); - while (typeInfo->type_id) - { - if (!(typeInfo->type_id & 0x8000)) - { - BYTE *p = resTab + typeInfo->type_id; - if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type; - } - typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + - typeInfo->count * sizeof(NE_NAMEINFO)); - } + if (typeInfo->type_id == typeid) goto found_type; + typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + + typeInfo->count * sizeof(NE_NAMEINFO)); } - else /* numeric type id */ - { - WORD id = LOWORD(typeid) | 0x8000; - while (typeInfo->type_id) - { - if (typeInfo->type_id == id) goto found_type; - typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + - typeInfo->count * sizeof(NE_NAMEINFO)); - } - } - TRACE("No typeid entry found for %p\n", typeid ); + TRACE("No typeid entry found\n" ); HeapFree( GetProcessHeap(), 0, resTab ); return FALSE; found_type: nameInfo = (NE_NAMEINFO *)(typeInfo + 1); - if (HIWORD(resid) != 0) /* named resource */ - { - BYTE len = strlen( resid ); - for (count = typeInfo->count; count > 0; count--, nameInfo++) - { - BYTE *p = resTab + nameInfo->id; - if (nameInfo->id & 0x8000) continue; - if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name; - } - } - else /* numeric resource id */ - { - WORD id = LOWORD(resid) | 0x8000; - for (count = typeInfo->count; count > 0; count--, nameInfo++) - if (nameInfo->id == id) goto found_name; - } - TRACE("No resid entry found for %p\n", typeid ); + for (count = typeInfo->count; count > 0; count--, nameInfo++) + if (nameInfo->id == resid) goto found_name; + + TRACE("No resid entry found\n" ); HeapFree( GetProcessHeap(), 0, resTab ); return FALSE; @@ -270,13 +193,11 @@ static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, HeapFree( GetProcessHeap(), 0, resTab ); return TRUE; } -#endif /* ! __REACTOS__ */ /*********************************************************************** * find_pe_resource [internal] */ -static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, - DWORD *resLen, DWORD *resOff ) +static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff ) { IMAGE_NT_HEADERS pehd; DWORD pehdoffset; @@ -349,22 +270,22 @@ static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress); resPtr = resDir; - resPtr = find_entry_by_name( resPtr, typeid, resDir ); + resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir ); if ( !resPtr ) { - TRACE("No typeid entry found for %p\n", typeid ); + TRACE("No typeid entry found\n" ); goto done; } - resPtr = find_entry_by_name( resPtr, resid, resDir ); + resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir ); if ( !resPtr ) { - TRACE("No resid entry found for %p\n", resid ); + TRACE("No resid entry found\n" ); goto done; } resPtr = find_entry_default( resPtr, resDir ); if ( !resPtr ) { - TRACE("No default language entry found for %p\n", resid ); + TRACE("No default language entry found\n" ); goto done; } @@ -395,95 +316,21 @@ static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, } -/************************************************************************* - * GetFileResourceSize [VER.2] +/*********************************************************************** + * find_version_resource [internal] */ -DWORD WINAPI GetFileResourceSize16( LPCSTR lpszFileName, LPCSTR lpszResType, - LPCSTR lpszResId, LPDWORD lpdwFileOffset ) +DWORD find_version_resource( HFILE lzfd, DWORD *reslen, DWORD *offset ) { - BOOL retv = FALSE; - HFILE lzfd; - OFSTRUCT ofs; - DWORD reslen; + DWORD magic = read_xx_header( lzfd ); - TRACE("(%s,type=%p,id=%p,off=%p)\n", - debugstr_a(lpszFileName), lpszResType, lpszResId, lpszResId ); - - lzfd = LZOpenFileA( (LPSTR)lpszFileName, &ofs, OF_READ ); - if ( lzfd < 0 ) return 0; - - switch ( read_xx_header( lzfd ) ) + switch (magic) { case IMAGE_OS2_SIGNATURE: -#ifdef __REACTOS__ - ERR("OS2 Images not supported under ReactOS at this time."); - retv = 0; -#else - retv = find_ne_resource( lzfd, lpszResType, lpszResId, - &reslen, lpdwFileOffset ); -#endif + if (!find_ne_resource( lzfd, reslen, offset )) magic = 0; break; - case IMAGE_NT_SIGNATURE: - retv = find_pe_resource( lzfd, lpszResType, lpszResId, - &reslen, lpdwFileOffset ); + if (!find_pe_resource( lzfd, reslen, offset )) magic = 0; break; } - - LZClose( lzfd ); - return retv? reslen : 0; -} - - -/************************************************************************* - * GetFileResource [VER.3] - */ -DWORD WINAPI GetFileResource16( LPCSTR lpszFileName, LPCSTR lpszResType, - LPCSTR lpszResId, DWORD dwFileOffset, - DWORD dwResLen, LPVOID lpvData ) -{ - BOOL retv = FALSE; - HFILE lzfd; - OFSTRUCT ofs; - DWORD reslen = dwResLen; - - TRACE("(%s,type=%p,id=%p,off=%d,len=%d,data=%p)\n", - debugstr_a(lpszFileName), lpszResType, lpszResId, - dwFileOffset, dwResLen, lpvData ); - - lzfd = LZOpenFileA( (LPSTR)lpszFileName, &ofs, OF_READ ); - if ( lzfd < 0 ) return 0; - - if ( !dwFileOffset ) - { - switch ( read_xx_header( lzfd ) ) - { - case IMAGE_OS2_SIGNATURE: -#ifdef __REACTOS__ - ERR("OS2 Images not supported under ReactOS at this time."); - retv = 0; -#else - retv = find_ne_resource( lzfd, lpszResType, lpszResId, - &reslen, &dwFileOffset ); -#endif - break; - - case IMAGE_NT_SIGNATURE: - retv = find_pe_resource( lzfd, lpszResType, lpszResId, - &reslen, &dwFileOffset ); - break; - } - - if ( !retv ) - { - LZClose( lzfd ); - return 0; - } - } - - LZSeek( lzfd, dwFileOffset, SEEK_SET ); - reslen = LZRead( lzfd, lpvData, min( reslen, dwResLen ) ); - LZClose( lzfd ); - - return reslen; + return magic; } diff --git a/dll/win32/version/version_ros.diff b/dll/win32/version/version_ros.diff deleted file mode 100644 index 20e89e533dd..00000000000 --- a/dll/win32/version/version_ros.diff +++ /dev/null @@ -1,124 +0,0 @@ -Index: info.c -=================================================================== ---- info.c (revision 23123) -+++ info.c (working copy) -@@ -30,6 +30,7 @@ - #include "winbase.h" - #include "winver.h" - #include "winternl.h" -+#include "winuser.h" - #include "wine/winuser16.h" - #include "wine/unicode.h" - #include "winerror.h" -@@ -303,6 +304,7 @@ - return len; - } - -+#ifndef __REACTOS__ - /*********************************************************************** - * VERSION_GetFileVersionInfo_16 [internal] - * -@@ -439,6 +442,7 @@ - - return len; - } -+#endif /* ! __REACTOS__ */ - - /*********************************************************************** - * GetFileVersionInfoSizeW [VERSION.@] -@@ -472,6 +475,10 @@ - - if (!len) - { -+#ifdef __REACTOS__ -+ SetLastError(ERROR_FILE_NOT_FOUND); -+ return 0; -+#else /* __REACTOS__ */ - LPSTR filenameA; - - len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL ); -@@ -503,6 +510,7 @@ - * doesn't seem to be a problem (len is bigger than info->wLength). - */ - len = (len - sizeof(VS_FIXEDFILEINFO)) * 4; -+#endif /* ! __REACTOS__ */ - } - else - { -@@ -567,6 +575,10 @@ - - if (!len) - { -+#ifdef __REACTOS__ -+ SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND); -+ return FALSE; -+#else /* __REACTOS__ */ - LPSTR filenameA; - - len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL ); -@@ -582,6 +594,7 @@ - return FALSE; - } - /* We have a 16bit resource. */ -+#endif /* ! __REACTOS__ */ - } - else - { -Index: resource.c -=================================================================== ---- resource.c (revision 23123) -+++ resource.c (working copy) -@@ -42,6 +42,9 @@ - - #include "wine/debug.h" - -+/* winnt.h */ -+#define IMAGE_FILE_RESOURCE_DIRECTORY 2 -+ - WINE_DEFAULT_DEBUG_CHANNEL(ver); - - -@@ -168,6 +171,7 @@ - return 0; - } - -+#ifndef __REACTOS__ - /*********************************************************************** - * load_ne_resource [internal] - */ -@@ -266,6 +271,7 @@ - HeapFree( GetProcessHeap(), 0, resTab ); - return TRUE; - } -+#endif /* ! __REACTOS__ */ - - /*********************************************************************** - * load_pe_resource [internal] -@@ -411,8 +416,13 @@ - switch ( read_xx_header( lzfd ) ) - { - case IMAGE_OS2_SIGNATURE: -+#ifdef __REACTOS__ -+ ERR("OS2 Images not supported under ReactOS at this time."); -+ retv = 0; -+#else - retv = find_ne_resource( lzfd, lpszResType, lpszResId, - &reslen, lpdwFileOffset ); -+#endif - break; - - case IMAGE_NT_SIGNATURE: -@@ -450,8 +460,13 @@ - switch ( read_xx_header( lzfd ) ) - { - case IMAGE_OS2_SIGNATURE: -+#ifdef __REACTOS__ -+ ERR("OS2 Images not supported under ReactOS at this time."); -+ retv = 0; -+#else - retv = find_ne_resource( lzfd, lpszResType, lpszResId, - &reslen, &dwFileOffset ); -+#endif - break; - - case IMAGE_NT_SIGNATURE: diff --git a/dll/win32/win32.rbuild b/dll/win32/win32.rbuild index 9ff3319d54f..ad862f5169e 100644 --- a/dll/win32/win32.rbuild +++ b/dll/win32/win32.rbuild @@ -31,6 +31,9 @@ + + + diff --git a/dll/win32/windowscodecs/info.c b/dll/win32/windowscodecs/info.c index f909d3a6b6e..2e558a80619 100644 --- a/dll/win32/windowscodecs/info.c +++ b/dll/win32/windowscodecs/info.c @@ -726,6 +726,7 @@ typedef struct { LONG ref; struct list objects; struct list *cursor; + CRITICAL_SECTION lock; /* Must be held when reading or writing cursor */ } ComponentEnum; typedef struct { @@ -783,6 +784,8 @@ static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface) list_remove(&cursor->entry); HeapFree(GetProcessHeap(), 0, cursor); } + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); HeapFree(GetProcessHeap(), 0, This); } @@ -795,15 +798,17 @@ static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt, ComponentEnum *This = (ComponentEnum*)iface; int num_fetched=0; ComponentEnumItem *item; + HRESULT hr=S_OK; TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched); + EnterCriticalSection(&This->lock); while (num_fetchedcursor) { - *pceltFetched = num_fetched; - return S_FALSE; + hr = S_FALSE; + break; } item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry); IUnknown_AddRef(item->unk); @@ -811,24 +816,31 @@ static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt, num_fetched++; This->cursor = list_next(&This->objects, This->cursor); } + LeaveCriticalSection(&This->lock); *pceltFetched = num_fetched; - return S_OK; + return hr; } static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt) { ComponentEnum *This = (ComponentEnum*)iface; int i; + HRESULT hr=S_OK; TRACE("(%p,%u)\n", iface, celt); + EnterCriticalSection(&This->lock); for (i=0; icursor) - return S_FALSE; + { + hr = S_FALSE; + break; + } This->cursor = list_next(&This->objects, This->cursor); } - return S_OK; + LeaveCriticalSection(&This->lock); + return hr; } static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface) @@ -837,7 +849,9 @@ static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface) TRACE("(%p)\n", iface); + EnterCriticalSection(&This->lock); This->cursor = list_head(&This->objects); + LeaveCriticalSection(&This->lock); return S_OK; } @@ -847,6 +861,7 @@ static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **pp ComponentEnum *new_enum; ComponentEnumItem *old_item, *new_item; HRESULT ret=S_OK; + struct list *old_cursor; new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum)); if (!new_enum) @@ -858,8 +873,14 @@ static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **pp new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl; new_enum->ref = 1; new_enum->cursor = NULL; - list_init(&new_enum->objects); + InitializeCriticalSection(&new_enum->lock); + new_enum->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock"); + + EnterCriticalSection(&This->lock); + old_cursor = This->cursor; + LeaveCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry) { new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem)); @@ -871,7 +892,7 @@ static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **pp new_item->unk = old_item->unk; list_add_tail(&new_enum->objects, &new_item->entry); IUnknown_AddRef(new_item->unk); - if (&old_item->entry == This->cursor) new_enum->cursor = &new_item->entry; + if (&old_item->entry == old_cursor) new_enum->cursor = &new_item->entry; } if (FAILED(ret)) @@ -923,6 +944,8 @@ HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnkn This->IEnumUnknown_Vtbl = &ComponentEnumVtbl; This->ref = 1; list_init(&This->objects); + InitializeCriticalSection(&This->lock); + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ComponentEnum.lock"); for (category=categories; category->type && hr == S_OK; category++) { diff --git a/dll/win32/windowscodecs/jpegformat.c b/dll/win32/windowscodecs/jpegformat.c index 6f788216fbe..017e6045790 100644 --- a/dll/win32/windowscodecs/jpegformat.c +++ b/dll/win32/windowscodecs/jpegformat.c @@ -570,7 +570,7 @@ HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { - ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n"); + ERR("Trying to load JPEG picture, but JPEG support is not compiled in.\n"); return E_FAIL; } diff --git a/dll/win32/windowscodecs/pngformat.c b/dll/win32/windowscodecs/pngformat.c index 22b37b063f4..5af680e876c 100644 --- a/dll/win32/windowscodecs/pngformat.c +++ b/dll/win32/windowscodecs/pngformat.c @@ -1320,13 +1320,13 @@ HRESULT PngEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) HRESULT PngDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { - ERR("Trying to load PNG picture, but PNG supported not compiled in.\n"); + ERR("Trying to load PNG picture, but PNG support is not compiled in.\n"); return E_FAIL; } HRESULT PngEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) { - ERR("Trying to save PNG picture, but PNG supported not compiled in.\n"); + ERR("Trying to save PNG picture, but PNG support is not compiled in.\n"); return E_FAIL; } diff --git a/dll/win32/wininet/http.c b/dll/win32/wininet/http.c index 5b7459db6f7..57b73729a10 100644 --- a/dll/win32/wininet/http.c +++ b/dll/win32/wininet/http.c @@ -1345,9 +1345,12 @@ static WCHAR *HTTP_BuildProxyRequestUrl(http_request_t *req) static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *lpwhs, http_request_t *lpwhr) { WCHAR buf[MAXHOSTNAME]; + WCHAR protoProxy[MAXHOSTNAME + 15]; + DWORD protoProxyLen = sizeof(protoProxy) / sizeof(protoProxy[0]); WCHAR proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */ static WCHAR szNul[] = { 0 }; URL_COMPONENTSW UrlComponents; + static const WCHAR protoHttp[] = { 'h','t','t','p',0 }; static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 }; static const WCHAR szFormat[] = { 'h','t','t','p',':','/','/','%','s',0 }; @@ -1356,11 +1359,13 @@ static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *lpwhs, http_reque UrlComponents.lpszHostName = buf; UrlComponents.dwHostNameLength = MAXHOSTNAME; + if (!INTERNET_FindProxyForProtocol(hIC->lpszProxy, protoHttp, protoProxy, &protoProxyLen)) + return FALSE; if( CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, - hIC->lpszProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) ) - sprintfW(proxy, szFormat, hIC->lpszProxy); + protoProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) ) + sprintfW(proxy, szFormat, protoProxy); else - strcpyW(proxy, hIC->lpszProxy); + strcpyW(proxy, protoProxy); if( !InternetCrackUrlW(proxy, 0, 0, &UrlComponents) ) return FALSE; if( UrlComponents.dwHostNameLength == 0 ) @@ -4253,8 +4258,6 @@ DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName, } if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) { - if(strchrW(hIC->lpszProxy, ' ')) - FIXME("Several proxies not implemented.\n"); if(hIC->lpszProxyBypass) FIXME("Proxy bypass is ignored.\n"); } diff --git a/dll/win32/wininet/internet.c b/dll/win32/wininet/internet.c index 45b6aa791f3..f4b8a0a3abd 100644 --- a/dll/win32/wininet/internet.c +++ b/dll/win32/wininet/internet.c @@ -362,6 +362,98 @@ static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi ) return ERROR_SUCCESS; } +/*********************************************************************** + * INTERNET_FindProxyForProtocol + * + * Searches the proxy string for a proxy of the given protocol. + * Returns the found proxy, or the default proxy if none of the given + * protocol is found. + * + * PARAMETERS + * szProxy [In] proxy string to search + * proto [In] protocol to search for, e.g. "http" + * foundProxy [Out] found proxy + * foundProxyLen [In/Out] length of foundProxy buffer, in WCHARs + * + * RETURNS + * TRUE if a proxy is found, FALSE if not. If foundProxy is too short, + * *foundProxyLen is set to the required size in WCHARs, including the + * NULL terminator, and the last error is set to ERROR_INSUFFICIENT_BUFFER. + */ +BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) +{ + LPCWSTR ptr; + BOOL ret = FALSE; + + TRACE("(%s, %s)\n", debugstr_w(szProxy), debugstr_w(proto)); + + /* First, look for the specified protocol (proto=scheme://host:port) */ + for (ptr = szProxy; !ret && ptr && *ptr; ) + { + LPCWSTR end, equal; + + if (!(end = strchrW(ptr, ' '))) + end = ptr + strlenW(ptr); + if ((equal = strchrW(ptr, '=')) && equal < end && + equal - ptr == strlenW(proto) && + !strncmpiW(proto, ptr, strlenW(proto))) + { + if (end - equal > *foundProxyLen) + { + WARN("buffer too short for %s\n", + debugstr_wn(equal + 1, end - equal - 1)); + *foundProxyLen = end - equal; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + else + { + memcpy(foundProxy, equal + 1, (end - equal) * sizeof(WCHAR)); + foundProxy[end - equal] = 0; + ret = TRUE; + } + } + if (*end == ' ') + ptr = end + 1; + else + ptr = end; + } + if (!ret) + { + /* It wasn't found: look for no protocol */ + for (ptr = szProxy; !ret && ptr && *ptr; ) + { + LPCWSTR end, equal; + + if (!(end = strchrW(ptr, ' '))) + end = ptr + strlenW(ptr); + if (!(equal = strchrW(ptr, '='))) + { + if (end - ptr + 1 > *foundProxyLen) + { + WARN("buffer too short for %s\n", + debugstr_wn(ptr, end - ptr)); + *foundProxyLen = end - ptr + 1; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + else + { + memcpy(foundProxy, ptr, (end - ptr) * sizeof(WCHAR)); + foundProxy[end - ptr] = 0; + ret = TRUE; + } + } + if (*end == ' ') + ptr = end + 1; + else + ptr = end; + } + } + if (ret) + TRACE("found proxy for %s: %s\n", debugstr_w(proto), + debugstr_w(foundProxy)); + return ret; +} + /*********************************************************************** * InternetInitializeAutoProxyDll (WININET.@) * diff --git a/dll/win32/wininet/internet.h b/dll/win32/wininet/internet.h index e45176bb2c0..8fcc0cf3565 100644 --- a/dll/win32/wininet/internet.h +++ b/dll/win32/wininet/internet.h @@ -422,6 +422,7 @@ VOID SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext, VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo, DWORD dwStatusInfoLength); +BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen); BOOL NETCON_connected(WININET_NETCONNECTION *connection); DWORD NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL); diff --git a/dll/win32/ws2_32/misc/stubs.c b/dll/win32/ws2_32/misc/stubs.c index 408f28294a6..10dd98e1ded 100644 --- a/dll/win32/ws2_32/misc/stubs.c +++ b/dll/win32/ws2_32/misc/stubs.c @@ -30,7 +30,7 @@ getpeername(IN SOCKET s, return SOCKET_ERROR; } - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) + if (!ReferenceProviderByHandle((HANDLE)(ULONG_PTR)(s), &Provider)) { WSASetLastError(WSAENOTSOCK); return SOCKET_ERROR; diff --git a/drivers/base/bootvid/bootvid.rbuild b/drivers/base/bootvid/bootvid.rbuild index fc9f3ec3bf5..0c996310194 100644 --- a/drivers/base/bootvid/bootvid.rbuild +++ b/drivers/base/bootvid/bootvid.rbuild @@ -6,7 +6,7 @@ . ntoskrnl hal - + bootvid.c bootdata.c diff --git a/drivers/base/bootvid/i386/bootvid.c b/drivers/base/bootvid/i386/bootvid.c index c55ffc16255..3d0ae503167 100644 --- a/drivers/base/bootvid/i386/bootvid.c +++ b/drivers/base/bootvid/i386/bootvid.c @@ -355,7 +355,7 @@ BOOLEAN NTAPI VidInitialize(IN BOOLEAN SetMode) { - ULONG Context = 0; + ULONG_PTR Context = 0; PHYSICAL_ADDRESS TranslatedAddress; PHYSICAL_ADDRESS NullAddress = {{0, 0}}, VgaAddress; ULONG AddressSpace = 1; diff --git a/drivers/base/bootvid/i386/vga.c b/drivers/base/bootvid/i386/vga.c index e11aae77fab..eeb06fe8df5 100644 --- a/drivers/base/bootvid/i386/vga.c +++ b/drivers/base/bootvid/i386/vga.c @@ -319,8 +319,8 @@ VgaScroll(ULONG Scroll) do { /* Write value in the new position so that we can do the scroll */ - WRITE_REGISTER_UCHAR((PUCHAR)j, - READ_REGISTER_UCHAR((PUCHAR)j + i)); + WRITE_REGISTER_UCHAR(UlongToPtr(j), + READ_REGISTER_UCHAR(UlongToPtr(j + i))); /* Move to the next memory location to write to */ j++; @@ -1197,7 +1197,7 @@ VidSolidColorFill(IN ULONG Left, __outpw(0x3CE, 7); /* Calculate pixel position for the read */ - Offset = VgaBase + (Top * 80) + (PUCHAR)LeftOffset; + Offset = VgaBase + (Top * 80) + (PUCHAR)(ULONG_PTR)LeftOffset; /* Select the bitmask register and write the mask */ __outpw(0x3CE, (USHORT)lMask); @@ -1221,7 +1221,7 @@ VidSolidColorFill(IN ULONG Left, if (Distance) { /* Calculate new pixel position */ - Offset = VgaBase + (Top * 80) + (PUCHAR)RightOffset; + Offset = VgaBase + (Top * 80) + (PUCHAR)(ULONG_PTR)RightOffset; Distance--; /* Select the bitmask register and write the mask */ @@ -1247,7 +1247,7 @@ VidSolidColorFill(IN ULONG Left, if (Distance) { /* Calculate new pixel position */ - Offset = VgaBase + (Top * 80) + (PUCHAR)(LeftOffset + 1); + Offset = VgaBase + (Top * 80) + (PUCHAR)(ULONG_PTR)(LeftOffset + 1); /* Set the bitmask to 0xFF for all 4 planes */ __outpw(0x3CE, 0xFF08); diff --git a/drivers/battery/battc/battc.c b/drivers/battery/battc/battc.c index b945615a95e..7e4854c9ef2 100644 --- a/drivers/battery/battc/battc.c +++ b/drivers/battery/battc/battc.c @@ -51,26 +51,9 @@ BatteryClassSystemControl(PVOID ClassData, PIRP Irp, PVOID Disposition) { - NTSTATUS Status; - UNIMPLEMENTED - /* FIXME: Uncomment when WmiCompleteRequest is implemented */ -#if 0 - Status = STATUS_WMI_GUID_NOT_FOUND; - WmiCompleteRequest(DeviceObject, - Irp, - Status, - 0, - IO_NO_INCREMENT); -#else - Irp->IoStatus.Status = Status = STATUS_WMI_GUID_NOT_FOUND; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); -#endif - - return Status; + return STATUS_WMI_GUID_NOT_FOUND; } BCLASSAPI diff --git a/drivers/bus/acpi/acpi.rbuild b/drivers/bus/acpi/acpi.rbuild index cbc124a26f5..c3e5b7dac90 100644 --- a/drivers/bus/acpi/acpi.rbuild +++ b/drivers/bus/acpi/acpi.rbuild @@ -7,6 +7,9 @@ + + + @@ -26,6 +29,8 @@ osl.c acpienum.c + eval.c + interface.c pnp.c power.c buspdo.c diff --git a/drivers/bus/acpi/busmgr/bus.c b/drivers/bus/acpi/busmgr/bus.c index 34aa0766c04..6309f20cfdb 100644 --- a/drivers/bus/acpi/busmgr/bus.c +++ b/drivers/bus/acpi/busmgr/bus.c @@ -1262,9 +1262,15 @@ acpi_bus_add ( hid = ACPI_THERMAL_HID; break; case ACPI_BUS_TYPE_POWER_BUTTON: + hid = ACPI_BUTTON_HID_POWER; + break; + case ACPI_BUS_TYPE_POWER_BUTTONF: hid = ACPI_BUTTON_HID_POWERF; break; case ACPI_BUS_TYPE_SLEEP_BUTTON: + hid = ACPI_BUTTON_HID_SLEEP; + break; + case ACPI_BUS_TYPE_SLEEP_BUTTONF: hid = ACPI_BUTTON_HID_SLEEPF; break; } @@ -1326,7 +1332,9 @@ acpi_bus_add ( */ switch (type) { case ACPI_BUS_TYPE_POWER_BUTTON: + case ACPI_BUS_TYPE_POWER_BUTTONF: case ACPI_BUS_TYPE_SLEEP_BUTTON: + case ACPI_BUS_TYPE_SLEEP_BUTTONF: break; default: status = AcpiAttachData(device->handle, @@ -1530,16 +1538,40 @@ acpi_bus_scan_fixed ( if (!root) return_VALUE(AE_NOT_FOUND); - /* - * Enumerate all fixed-feature devices. + /* If ACPI_FADT_POWER_BUTTON is set, then a control + * method power button is present. Otherwise, a fixed + * power button is present. */ if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) result = acpi_bus_add(&device, acpi_root, NULL, ACPI_BUS_TYPE_POWER_BUTTON); + else + { + /* Enable the fixed power button so we get notified if it is pressed */ + AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1); + result = acpi_bus_add(&device, acpi_root, + NULL, ACPI_BUS_TYPE_POWER_BUTTONF); + } + + /* This one is a bit more complicated and we do it wrong + * right now. If ACPI_FADT_SLEEP_BUTTON is set but no + * device object is present then no sleep button is present, but + * if the flags is clear and there is no device object then it is + * a fixed sleep button. If the flag is set and there is a device object + * the we have a control method button just like above. + */ if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) result = acpi_bus_add(&device, acpi_root, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON); + else + { + /* Enable the fixed sleep button so we get notified if it is pressed */ + AcpiWriteBitRegister(ACPI_BITREG_SLEEP_BUTTON_ENABLE, 1); + + result = acpi_bus_add(&device, acpi_root, + NULL, ACPI_BUS_TYPE_SLEEP_BUTTONF); + } return_VALUE(result); } @@ -1549,120 +1581,6 @@ acpi_bus_scan_fixed ( Initialization/Cleanup -------------------------------------------------------------------------- */ -static int -acpi_bus_init_irq (void) -{ - ACPI_STATUS status = AE_OK; - ACPI_OBJECT arg = {ACPI_TYPE_INTEGER}; - ACPI_OBJECT_LIST arg_list = {1, &arg}; - //char *message = NULL; - - DPRINT("acpi_bus_init_irq"); - - /* - * Let the system know what interrupt model we are using by - * evaluating the \_PIC object, if exists. - */ - - //switch (acpi_irq_model) { - //case ACPI_IRQ_MODEL_PIC: - // message = "PIC"; - // break; - //case ACPI_IRQ_MODEL_IOAPIC: - // message = "IOAPIC"; - // break; - //case ACPI_IRQ_MODEL_IOSAPIC: - // message = "IOSAPIC"; - // break; - //default: - // DPRINT1("Unknown interrupt routing model\n"); - // return_VALUE(AE_NOT_FOUND); - //} - - //DPRINT("Using %s for interrupt routing\n", message); - - //arg.Integer.Value = acpi_irq_model; - - //status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL); - //if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { - // ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n")); - // return_VALUE(AE_NOT_FOUND); - //} - - return_VALUE(0); -} - - -//void -//acpi_early_init (void) -//{ -// ACPI_STATUS status = AE_OK; -// -// DPRINT("acpi_early_init"); -// -// if (acpi_disabled) -// return_VOID; -// - /* enable workarounds, unless strict ACPI spec. compliance */ -// if (!acpi_strict) -// acpi_gbl_enable_interpreter_slack = TRUE; -// -// status = acpi_reallocate_root_table(); -// if (ACPI_FAILURE(status)) { -// printk(KERN_ERR PREFIX -// "Unable to reallocate ACPI tables\n"); -// goto error0; -// } -// -// status = acpi_initialize_subsystem(); -// if (ACPI_FAILURE(status)) { -// printk(KERN_ERR PREFIX -// "Unable to initialize the ACPI Interpreter\n"); -// goto error0; -// } -// -// status = acpi_load_tables(); -// if (ACPI_FAILURE(status)) { -// printk(KERN_ERR PREFIX -// "Unable to load the System Description Tables\n"); -// goto error0; -// } -// -//#ifdef CONFIG_X86 -// if (!acpi_ioapic) { -// /* compatible (0) means level (3) */ -// if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) { -// acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK; -// acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL; -// } -// /* Set PIC-mode SCI trigger type */ -// acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt, -// (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2); -// } else { -// /* -// * now that acpi_gbl_FADT is initialized, -// * update it with result from INT_SRC_OVR parsing -// */ -// acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; -// } -//#endif -// -// status = -// acpi_enable_subsystem(~ -// (ACPI_NO_HARDWARE_INIT | -// ACPI_NO_ACPI_ENABLE)); -// if (ACPI_FAILURE(status)) { -// printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); -// goto error0; -// } -// -// return; -// -// error0: -// disable_acpi(); -// return; -//} - int acpi_bus_init (void) { @@ -1701,13 +1619,6 @@ acpi_bus_init (void) /* Initialize sleep structures */ //acpi_sleep_init(); - /* - * Get the system interrupt model and evaluate \_PIC. - */ - result = acpi_bus_init_irq(); - if (result) - goto error1; - /* * Register the for all standard device notifications. */ @@ -1726,6 +1637,7 @@ acpi_bus_init (void) if (result) goto error2; + /* * Enumerate devices in the ACPI namespace. */ @@ -1736,7 +1648,6 @@ acpi_bus_init (void) if (result) DPRINT1("acpi_bus_scan failed\n"); - //acpi_motherboard_init(); return_VALUE(0); /* Mimic structured exception handling */ diff --git a/drivers/bus/acpi/busmgr/button.c b/drivers/bus/acpi/busmgr/button.c index 5e3eb2b5f0f..9344a5f1f7d 100644 --- a/drivers/bus/acpi/busmgr/button.c +++ b/drivers/bus/acpi/busmgr/button.c @@ -57,6 +57,11 @@ struct acpi_button { UINT8 type; unsigned long pushed; }; + +struct acpi_device *power_button; +struct acpi_device *sleep_button; +struct acpi_device *lid_button; + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -113,10 +118,6 @@ acpi_button_add ( ACPI_STATUS status = AE_OK; struct acpi_button *button = NULL; - static struct acpi_device *power_button; - static struct acpi_device *sleep_button; - static struct acpi_device *lid_button; - ACPI_FUNCTION_TRACE("acpi_button_add"); if (!device) diff --git a/drivers/bus/acpi/buspdo.c b/drivers/bus/acpi/buspdo.c index 4a9498e7ad4..84bd1d8fe11 100644 --- a/drivers/bus/acpi/buspdo.c +++ b/drivers/bus/acpi/buspdo.c @@ -8,6 +8,9 @@ #include #include +#include +#include + #define NDEBUG #include @@ -33,9 +36,13 @@ Bus_PDO_PnP ( { NTSTATUS status; POWER_STATE state; + struct acpi_device *device = NULL; PAGED_CODE (); + if (DeviceData->AcpiHandle) + acpi_bus_get_device(DeviceData->AcpiHandle, &device); + // // NB: Because we are a bus enumerator, we have no one to whom we could // defer these irps. Therefore we do not pass them down but merely @@ -45,7 +52,6 @@ Bus_PDO_PnP ( switch (IrpStack->MinorFunction) { case IRP_MN_START_DEVICE: - // // Here we do what ever initialization and ``turning on'' that is // required to allow others to access this device. @@ -59,6 +65,43 @@ Bus_PDO_PnP ( break; } + DeviceData->InterfaceName.Length = 0; + + if (!device) + { + IoRegisterDeviceInterface(DeviceData->Common.Self, + &GUID_DEVICE_SYS_BUTTON, + NULL, + &DeviceData->InterfaceName); + } + else if (device->flags.hardware_id && + strstr(device->pnp.hardware_id, ACPI_THERMAL_HID)) + { + IoRegisterDeviceInterface(DeviceData->Common.Self, + &GUID_DEVICE_THERMAL_ZONE, + NULL, + &DeviceData->InterfaceName); + } + else if (device->flags.hardware_id && + strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID)) + { + IoRegisterDeviceInterface(DeviceData->Common.Self, + &GUID_DEVICE_LID, + NULL, + &DeviceData->InterfaceName); + } + else if (device->flags.hardware_id && + strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID)) + { + IoRegisterDeviceInterface(DeviceData->Common.Self, + &GUID_DEVICE_PROCESSOR, + NULL, + &DeviceData->InterfaceName); + } + + if (DeviceData->InterfaceName.Length != 0) + IoSetDeviceInterfaceState(&DeviceData->InterfaceName, TRUE); + state.DeviceState = PowerDeviceD0; PoSetPowerState(DeviceData->Common.Self, DevicePowerState, state); DeviceData->Common.DevicePowerState = PowerDeviceD0; @@ -68,6 +111,9 @@ Bus_PDO_PnP ( case IRP_MN_STOP_DEVICE: + if (DeviceData->InterfaceName.Length != 0) + IoSetDeviceInterfaceState(&DeviceData->InterfaceName, FALSE); + // // Here we shut down the device and give up and unmap any resources // we acquired for the device. @@ -176,6 +222,12 @@ Bus_PDO_PnP ( break; + case IRP_MN_QUERY_INTERFACE: + + status = Bus_PDO_QueryInterface(DeviceData, Irp); + + break; + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: @@ -325,20 +377,17 @@ Bus_PDO_QueryDeviceCaps( deviceCapabilities->UniqueID = device->flags.unique_id; deviceCapabilities->NoDisplayInUI = !device->status.show_in_ui; deviceCapabilities->Address = device->pnp.bus_address; - deviceCapabilities->RawDeviceOK = FALSE; } - else - { - deviceCapabilities->EjectSupported = FALSE; - deviceCapabilities->HardwareDisabled = FALSE; - deviceCapabilities->Removable = FALSE; - deviceCapabilities->SurpriseRemovalOK = FALSE; - deviceCapabilities->UniqueID = FALSE; - deviceCapabilities->NoDisplayInUI = FALSE; - deviceCapabilities->Address = 0; - /* The ACPI driver will run fixed buttons */ - deviceCapabilities->RawDeviceOK = TRUE; + if (!device || + (device->flags.hardware_id && + (strstr(device->pnp.hardware_id, ACPI_BUTTON_HID_LID) || + strstr(device->pnp.hardware_id, ACPI_THERMAL_HID) || + strstr(device->pnp.hardware_id, ACPI_PROCESSOR_HID)))) + { + /* Allow ACPI to control the device if it is a lid button, + * a thermal zone, a processor, or a fixed feature button */ + deviceCapabilities->RawDeviceOK = TRUE; } deviceCapabilities->SilentInstall = FALSE; diff --git a/drivers/bus/acpi/cmbatt/cmbatt.c b/drivers/bus/acpi/cmbatt/cmbatt.c index 1957597a678..747ac9ea952 100644 --- a/drivers/bus/acpi/cmbatt/cmbatt.c +++ b/drivers/bus/acpi/cmbatt/cmbatt.c @@ -13,46 +13,267 @@ /* GLOBALS ********************************************************************/ ULONG CmBattDebug; - +PCALLBACK_OBJECT CmBattPowerCallBackObject; +PVOID CmBattPowerCallBackRegistration; +UNICODE_STRING GlobalRegistryPath; +KTIMER CmBattWakeDpcTimerObject; +KDPC CmBattWakeDpcObject; +PDEVICE_OBJECT AcAdapterPdo; +LARGE_INTEGER CmBattWakeDpcDelay; + /* FUNCTIONS ******************************************************************/ VOID NTAPI -CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension, - PVOID Argument1, - PVOID Argument2) +CmBattPowerCallBack(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Action, + IN ULONG Value) { - UNIMPLEMENTED; + BOOLEAN Cancelled; + PDEVICE_OBJECT DeviceObject; + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerCallBack: action: %d, value: %d \n", Action, Value); + + /* Check if a transition is going to happen */ + if (Action == PO_CB_SYSTEM_STATE_LOCK) + { + /* We have just re-entered S0: call the wake DPC in 10 seconds */ + if (Value == 1) + { + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerCallBack: Calling CmBattWakeDpc after 10 seconds.\n"); + Cancelled = KeSetTimer(&CmBattWakeDpcTimerObject, CmBattWakeDpcDelay, &CmBattWakeDpcObject); + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerCallBack: timerCanceled = %d.\n", Cancelled); + } + else if (Value == 0) + { + /* We are exiting the S0 state: loop all devices to set the delay flag */ + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerCallBack: Delaying Notifications\n"); + for (DeviceObject = DeviceExtension->DeviceObject; + DeviceObject; + DeviceObject = DeviceObject->NextDevice) + { + /* Set the delay flag */ + DeviceExtension = DeviceObject->DeviceExtension; + DeviceExtension->DelayNotification = TRUE; + } + } + else if (CmBattDebug & 0x10) + { + /* Unknown value */ + DbgPrint("CmBattPowerCallBack: unknown argument2 = %08x\n"); + } + } } VOID NTAPI -CmBattWakeDpc(PKDPC Dpc, - PCMBATT_DEVICE_EXTENSION FdoExtension, - PVOID SystemArgument1, - PVOID SystemArgument2) +CmBattWakeDpc(IN PKDPC Dpc, + IN PCMBATT_DEVICE_EXTENSION FdoExtension, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) { - UNIMPLEMENTED; + PDEVICE_OBJECT CurrentObject; + BOOLEAN AcNotify = FALSE; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + ULONG ArFlag; + if (CmBattDebug & 2) DbgPrint("CmBattWakeDpc: Entered.\n"); + + /* Loop all device objects */ + for (CurrentObject = FdoExtension->DeviceObject; + CurrentObject; + CurrentObject = CurrentObject->NextDevice) + { + /* Turn delay flag off, we're back in S0 */ + DeviceExtension = CurrentObject->DeviceExtension; + DeviceExtension->DelayNotification = 0; + + /* Check if this is an AC adapter */ + if (DeviceExtension->FdoType == CmBattAcAdapter) + { + /* Was there a pending notify? */ + if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY) + { + /* We'll send a notify on the next pass */ + AcNotify = TRUE; + DeviceExtension->ArFlag = 0; + if (CmBattDebug & 0x20) + DbgPrint("CmBattWakeDpc: AC adapter notified\n"); + } + } + } + + /* Loop the device objects again */ + for (CurrentObject = FdoExtension->DeviceObject; + CurrentObject; + CurrentObject = CurrentObject->NextDevice) + { + /* Check if this is a battery */ + DeviceExtension = CurrentObject->DeviceExtension; + if (DeviceExtension->FdoType == CmBattBattery) + { + /* Check what ARs are pending */ + ArFlag = DeviceExtension->ArFlag; + if (CmBattDebug & 0x20) + DbgPrint("CmBattWakeDpc: Performing delayed ARs: %01x\n", ArFlag); + + /* Insert notification, clear the lock value */ + if (ArFlag & CMBATT_AR_INSERT) InterlockedExchange(&DeviceExtension->ArLockValue, 0); + + /* Removal, clear the battery tag */ + if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0; + + /* Notification (or AC/DC adapter change from first pass above) */ + if ((ArFlag & CMBATT_AR_NOTIFY) || (AcNotify)) + { + /* Notify the class driver */ + BatteryClassStatusNotify(DeviceExtension->ClassData); + } + } + } } VOID NTAPI -CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG NotifyValue) +CmBattNotifyHandler(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG NotifyValue) { - UNIMPLEMENTED; + ULONG ArFlag; + PCMBATT_DEVICE_EXTENSION FdoExtension; + PDEVICE_OBJECT DeviceObject; + + if (CmBattDebug & (CMBATT_ACPI_ASSERT | CMBATT_PNP_INFO)) + DbgPrint("CmBattNotifyHandler: CmBatt 0x%08x Type %d Number %d Notify Value: %x\n", + DeviceExtension, + DeviceExtension->FdoType, + DeviceExtension->DeviceId, + NotifyValue); + + /* Check what kind of notification was received */ + switch (NotifyValue) + { + /* ACPI Specification says is sends a "Bus Check" when power source changes */ + case ACPI_BUS_CHECK: + + /* We treat it as possible physical change */ + DeviceExtension->ArFlag |= (CMBATT_AR_NOTIFY | CMBATT_AR_INSERT); + if ((DeviceExtension->Tag) && + (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING))) + DbgPrint("CmBattNotifyHandler: Received battery #%x insertion, but tag was not invalid.\n", + DeviceExtension->DeviceId); + break; + + /* Status of the battery has changed */ + case ACPI_BATT_NOTIFY_STATUS: + + /* All we'll do is notify the class driver */ + DeviceExtension->ArFlag |= CMBATT_AR_NOTIFY; + break; + + /* Information on the battery has changed, such as physical presence */ + case ACPI_DEVICE_CHECK: + case ACPI_BATT_NOTIFY_INFO: + + /* Reset all state and let the class driver re-evaluate it all */ + DeviceExtension->ArFlag |= (CMBATT_AR_NOTIFY | + CMBATT_AR_INSERT | + CMBATT_AR_REMOVE); + break; + + default: + + if (CmBattDebug & CMBATT_PNP_INFO) + DbgPrint("CmBattNotifyHandler: Unknown Notify Value: %x\n", NotifyValue); + } + + /* Check if we're supposed to delay the notification till later */ + if (DeviceExtension->DelayNotification) + { + /* We'll handle this when we get a status query later on */ + if (CmBattDebug & CMBATT_PNP_INFO) + DbgPrint("CmBattNotifyHandler: Notification delayed: ARs = %01x\n", + DeviceExtension->ArFlag); + return; + } + + /* We're going to handle this now */ + if (CmBattDebug & CMBATT_PNP_INFO) + DbgPrint("CmBattNotifyHandler: Performing ARs: %01x\n", DeviceExtension->ArFlag); + + /* Check if this is a battery or AC adapter notification */ + if (DeviceExtension->FdoType == CmBattBattery) + { + /* Reset the current trip point */ + DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; + + /* Check what ARs have to be done */ + ArFlag = DeviceExtension->ArFlag; + + /* New battery inserted, reset lock value */ + if (ArFlag & CMBATT_AR_INSERT) InterlockedExchange(&DeviceExtension->ArLockValue, 0); + + /* Check if the battery may have been removed */ + if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0; + + /* Check if there's been any sort of change to the battery */ + if (ArFlag & CMBATT_AR_NOTIFY) + { + /* We'll probably end up re-evaluating _BIF and _BST */ + DeviceExtension->NotifySent = TRUE; + BatteryClassStatusNotify(DeviceExtension->ClassData); + } + } + else if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY) + { + /* The only known notification is AC/DC change. Loop device objects. */ + for (DeviceObject = DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject; + DeviceObject; + DeviceObject = DeviceObject->NextDevice) + { + /* Is this a battery? */ + FdoExtension = DeviceObject->DeviceExtension; + if (FdoExtension->FdoType == CmBattBattery) + { + /* Send a notification to the class driver */ + FdoExtension->NotifySent = TRUE; + BatteryClassStatusNotify(FdoExtension->ClassData); + } + } + } + + /* ARs have been processed */ + DeviceExtension->ArFlag = 0; } VOID NTAPI -CmBattUnload(PDEVICE_OBJECT DeviceObject) +CmBattUnload(IN PDRIVER_OBJECT DriverObject) { - UNIMPLEMENTED; + if (CmBattDebug & CMBATT_GENERIC_INFO) DPRINT("CmBattUnload: \n"); + + /* Check if we have a registered power callback */ + if (CmBattPowerCallBackObject) + { + /* Get rid of it */ + ExUnregisterCallback(CmBattPowerCallBackRegistration); + ObfDereferenceObject(CmBattPowerCallBackObject); + } + + /* Free the registry buffer if it exists */ + if (GlobalRegistryPath.Buffer) ExFreePool(GlobalRegistryPath.Buffer); + + /* Make sure we don't still have references to the DO */ + if ((DriverObject->DeviceObject) && (CmBattDebug & CMBATT_GENERIC_WARNING)) + { + DbgPrint("Unload called before all devices removed.\n"); + } } NTSTATUS NTAPI -CmBattVerifyStaticInfo(ULONG StaData, +CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension, ULONG BatteryTag) { UNIMPLEMENTED; @@ -61,89 +282,1047 @@ CmBattVerifyStaticInfo(ULONG StaData, NTSTATUS NTAPI -CmBattOpenClose(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +CmBattOpenClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IoStackLocation; + UCHAR Major; + ULONG Count; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + PAGED_CODE(); + if (CmBattDebug & CMBATT_GENERIC_INFO) DPRINT("CmBattOpenClose\n"); + + /* Grab the device extension and lock it */ + DeviceExtension = DeviceObject->DeviceExtension; + ExAcquireFastMutex(&DeviceExtension->FastMutex); + + /* Check if someone is trying to open a device that doesn't exist yet */ + Count = DeviceExtension->HandleCount; + if (Count == 0xFFFFFFFF) + { + /* Fail the request */ + Status = STATUS_NO_SUCH_DEVICE; + if (CmBattDebug & CMBATT_PNP_INFO) + { + DbgPrint("CmBattOpenClose: Failed (UID = %x)(device being removed).\n", + DeviceExtension->Tag); + } + goto Complete; + } + + /* Check if this is an open or close */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + Major = IoStackLocation->MajorFunction; + if (Major == IRP_MJ_CREATE) + { + /* Increment the open count */ + DeviceExtension->HandleCount = Count + 1; + if (CmBattDebug & CMBATT_PNP_INFO) + { + DbgPrint("CmBattOpenClose: Open (DeviceNumber = %x)(count = %x).\n", + DeviceExtension->DeviceId, Count + 1); + } + } + else if (Major == IRP_MJ_CLOSE) + { + /* Decrement the open count */ + DeviceExtension->HandleCount = Count - 1; + if (CmBattDebug & CMBATT_PNP_INFO) + { + DbgPrint("CmBattOpenClose: Close (DeviceNumber = %x)(count = %x).\n", + DeviceExtension->DeviceId, Count + 1); + } + } + +Complete: + /* Release lock and complete request */ + ExReleaseFastMutex(&DeviceExtension->FastMutex); + Irp->IoStatus.Status = Status; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; } NTSTATUS NTAPI -CmBattIoctl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +CmBattIoctl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + PIO_STACK_LOCATION IoStackLocation; + ULONG IoControlCode, OutputBufferLength, InputBufferLength; + PAGED_CODE(); + if (CmBattDebug & 2) DbgPrint("CmBattIoctl\n"); + + /* Acquire the remove lock */ + Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0); + if (!NT_SUCCESS(Status)) + { + /* It's too late, fail */ + Irp->IoStatus.Status = STATUS_DEVICE_REMOVED; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_DEVICE_REMOVED; + } + + /* There's nothing to do for an AC adapter */ + if (DeviceExtension->FdoType == CmBattAcAdapter) + { + /* Pass it down, and release the remove lock */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); + return Status; + } + + /* Send to class driver */ + Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp); + if (Status == STATUS_NOT_SUPPORTED) + { + /* Read IOCTL information from IRP stack */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode; + OutputBufferLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; + InputBufferLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; + if (CmBattDebug & 4) + DbgPrint("CmBattIoctl: Received Direct Access IOCTL %x\n", IoControlCode); + + /* Handle internal IOCTLs */ + switch (IoControlCode) + { + case IOCTL_BATTERY_QUERY_UNIQUE_ID: + + /* Data is 4 bytes long */ + if (OutputBufferLength == sizeof(ULONG)) + { + /* Query it */ + Status = CmBattGetUniqueId(DeviceExtension->PdoDeviceObject, + Irp->AssociatedIrp.SystemBuffer); + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG); + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + case IOCTL_BATTERY_QUERY_STA: + + /* Data is 4 bytes long */ + if (OutputBufferLength == sizeof(ULONG)) + { + /* Query it */ + Status = CmBattGetStaData(DeviceExtension->PdoDeviceObject, + Irp->AssociatedIrp.SystemBuffer); + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG); + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + case IOCTL_BATTERY_QUERY_PSR: + + /* Data is 4 bytes long */ + if (OutputBufferLength == sizeof(ULONG)) + { + /* Do we have an AC adapter? */ + if (AcAdapterPdo) + { + /* Query it */ + Status = CmBattGetPsrData(AcAdapterPdo, + Irp->AssociatedIrp.SystemBuffer); + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ULONG); + } + else + { + /* No adapter, just a battery, so fail */ + Status = STATUS_NO_SUCH_DEVICE; + } + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + case IOCTL_BATTERY_SET_TRIP_POINT: + + /* Data is 4 bytes long */ + if (InputBufferLength == sizeof(ULONG)) + { + /* Query it */ + Status = CmBattSetTripPpoint(DeviceExtension, + *(PULONG)Irp->AssociatedIrp.SystemBuffer); + Irp->IoStatus.Information = 0; + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + case IOCTL_BATTERY_QUERY_BIF: + + /* Data is 1060 bytes long */ + if (OutputBufferLength == sizeof(ACPI_BIF_DATA)) + { + /* Query it */ + Status = CmBattGetBifData(DeviceExtension, + Irp->AssociatedIrp.SystemBuffer); + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ACPI_BIF_DATA); + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + case IOCTL_BATTERY_QUERY_BST: + + /* Data is 16 bytes long */ + if (OutputBufferLength == sizeof(ACPI_BST_DATA)) + { + /* Query it */ + Status = CmBattGetBstData(DeviceExtension, + Irp->AssociatedIrp.SystemBuffer); + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(ACPI_BST_DATA); + } + else + { + /* Buffer size invalid */ + Status = STATUS_INVALID_BUFFER_SIZE; + } + break; + + default: + + /* Unknown, let us pass it on to ACPI */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattIoctl: Unknown IOCTL %x\n", IoControlCode); + break; + } + + /* Did someone pick it up? */ + if (Status != STATUS_NOT_SUPPORTED) + { + /* Complete the request */ + Irp->IoStatus.Status = Status; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + { + /* Still unsupported, try ACPI */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + } + + /* Release the remove lock and return status */ + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); + return Status; } NTSTATUS NTAPI -CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension, - PULONG BatteryTag) +CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + OUT PULONG Tag) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PDEVICE_OBJECT PdoDevice; + ULONG StaData; + ULONG NewTag; + NTSTATUS Status; + PAGED_CODE(); + if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO)) + DbgPrint("CmBattQueryTag - Tag (%d), Battery %x, Device %d\n", + *Tag, DeviceExtension, DeviceExtension->DeviceId); + + /* Get PDO and clear notification flag */ + PdoDevice = DeviceExtension->PdoDeviceObject; + DeviceExtension->NotifySent = 0; + + /* Get _STA from PDO (we need the machine status, not the battery status) */ + Status = CmBattGetStaData(PdoDevice, &StaData); + if (NT_SUCCESS(Status)) + { + /* Is a battery present? */ + if (StaData & ACPI_STA_BATTERY_PRESENT) + { + /* Do we not have a tag yet? */ + if (!DeviceExtension->Tag) + { + /* Set the new tag value, reset tags if we reached the maximum */ + NewTag = DeviceExtension->TagData; + if (DeviceExtension->TagData++ == 0xFFFFFFFF) NewTag = 1; + DeviceExtension->Tag = NewTag; + if (CmBattDebug & CMBATT_GENERIC_INFO) + DbgPrint("CmBattQueryTag - New Tag: (%d)\n", DeviceExtension->Tag); + + /* Reset trip point data */ + DeviceExtension->TripPointOld = 0; + DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; + + /* Clear AR lock and set new interrupt time */ + InterlockedExchange(&DeviceExtension->ArLockValue, 0); + DeviceExtension->InterruptTime = KeQueryInterruptTime(); + } + } + else + { + /* No battery, so no tag */ + DeviceExtension->Tag = 0; + Status = STATUS_NO_SUCH_DEVICE; + } + } + + /* Return the tag and status result */ + *Tag = DeviceExtension->Tag; + if (CmBattDebug & CMBATT_ACPI_WARNING) + DbgPrint("CmBattQueryTag: Returning Tag: 0x%x, status 0x%x\n", *Tag, Status); + return Status; } NTSTATUS NTAPI -CmBattDisableStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension) +CmBattDisableStatusNotify(IN PCMBATT_DEVICE_EXTENSION DeviceExtension) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PAGED_CODE(); + if (CmBattDebug & 0xA) DbgPrint("CmBattDisableStatusNotify\n"); + + /* Do we have a trip point */ + if (DeviceExtension->TripPointSet) + { + /* Is there a current value set? */ + if (DeviceExtension->TripPointValue) + { + /* Reset it back to 0 */ + DeviceExtension->TripPointValue = 0; + Status = CmBattSetTripPpoint(DeviceExtension, 0); + if (!NT_SUCCESS(Status)) + { + /* If it failed, set unknown/invalid value */ + DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; + if (CmBattDebug & 8) + DbgPrint("CmBattDisableStatusNotify: SetTripPoint failed - %x\n", Status); + } + } + else + { + /* No trip point set, so this is a successful no-op */ + Status = STATUS_SUCCESS; + } + } + else + { + /* Nothing we can do */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* Return status */ + return Status; } NTSTATUS NTAPI -CmBattSetStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG BatteryTag, - PBATTERY_NOTIFY BatteryNotify) +CmBattSetStatusNotify(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG BatteryTag, + IN PBATTERY_NOTIFY BatteryNotify) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + ACPI_BST_DATA BstData; + ULONG Capacity, NewTripPoint, TripPoint, DesignVoltage; + BOOLEAN Charging; + PAGED_CODE(); + if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO)) + DbgPrint("CmBattSetStatusNotify: Tag (%d) Target(0x%x)\n", + BatteryTag, BatteryNotify->LowCapacity); + + /* Update any ACPI evaluations */ + Status = CmBattVerifyStaticInfo(DeviceExtension, BatteryTag); + if (!NT_SUCCESS(Status)) return Status; + + /* Trip point not supported, fail */ + if (!DeviceExtension->TripPointSet) return STATUS_OBJECT_NAME_NOT_FOUND; + + /* Are both capacities known? */ + if ((BatteryNotify->HighCapacity == BATTERY_UNKNOWN_CAPACITY) || + (BatteryNotify->LowCapacity == BATTERY_UNKNOWN_CAPACITY)) + { + /* We can't set trip points without these */ + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattSetStatusNotify: Failing request because of BATTERY_UNKNOWN_CAPACITY.\n"); + return STATUS_NOT_SUPPORTED; + } + + /* Is the battery charging? */ + Charging = DeviceExtension->BstData.State & ACPI_BATT_STAT_CHARGING; + if (Charging) + { + /* Then the trip point is when we hit the cap */ + Capacity = BatteryNotify->HighCapacity; + NewTripPoint = BatteryNotify->HighCapacity; + } + else + { + /* Otherwise it's when we discharge to the bottom */ + Capacity = BatteryNotify->LowCapacity; + NewTripPoint = BatteryNotify->LowCapacity; + } + + /* Do we have data in Amps or Watts? */ + if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS) + { + /* We need the voltage to do the conversion */ + DesignVoltage = DeviceExtension->BifData.DesignVoltage; + if ((DesignVoltage != BATTERY_UNKNOWN_VOLTAGE) && (DesignVoltage)) + { + /* Convert from mAh into Ah */ + TripPoint = 1000 * NewTripPoint; + if (Charging) + { + /* Scale the high trip point */ + NewTripPoint = (TripPoint + 500) / DesignVoltage + ((TripPoint + 500) % DesignVoltage != 0); + } + else + { + /* Scale the low trip point */ + NewTripPoint = (TripPoint - 500) / DesignVoltage - ((TripPoint - 500) % DesignVoltage == 0); + } + } + else + { + /* Without knowing the voltage, Amps are not enough data on consumption */ + Status = STATUS_NOT_SUPPORTED; + if (CmBattDebug & CMBATT_ACPI_WARNING) + DbgPrint("CmBattSetStatusNotify: Can't calculate BTP, DesignVoltage = 0x%08x\n", + DesignVoltage); + } + } + else if (Charging) + { + /* Make it trip just one past the charge cap */ + ++NewTripPoint; + } + else if (NewTripPoint > 0) + { + /* Make it trip just one below the drain cap */ + --NewTripPoint; + } + + /* Do we actually have a new trip point? */ + if (NewTripPoint == DeviceExtension->TripPointValue) + { + /* No, so there is no work to be done */ + if (CmBattDebug & CMBATT_GENERIC_STATUS) + DbgPrint("CmBattSetStatusNotify: Keeping original setting: %X\n", DeviceExtension->TripPointValue); + return STATUS_SUCCESS; + } + + /* Set the trip point with ACPI and check for success */ + DeviceExtension->TripPointValue = NewTripPoint; + Status = CmBattSetTripPpoint(DeviceExtension, NewTripPoint); + if (!(NewTripPoint) && (Capacity)) Status = STATUS_NOT_SUPPORTED; + if (!NT_SUCCESS(Status)) + { + /* We failed to set the trip point, or there wasn't one settable */ + DeviceExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; + if (CmBattDebug & (CMBATT_GENERIC_WARNING | CMBATT_ACPI_WARNING)) + DbgPrint("CmBattSetStatusNotify: SetTripPoint failed - %x\n", Status); + return Status; + } + + /* Read the new BST data to see the latest state */ + Status = CmBattGetBstData(DeviceExtension, &BstData); + if (!NT_SUCCESS(Status)) + { + /* We'll return failure to the caller */ + if (CmBattDebug & (CMBATT_GENERIC_WARNING | CMBATT_ACPI_WARNING)) + DbgPrint("CmBattSetStatusNotify: GetBstData - %x\n", Status); + } + else if ((Charging) && (BstData.RemainingCapacity >= NewTripPoint)) + { + /* We are charging and our capacity is past the trip point, so trip now */ + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattSetStatusNotify: Trip point already crossed (1): TP = %08x, remaining capacity = %08x\n", + NewTripPoint, BstData.RemainingCapacity); + CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS); + } + else if ((BstData.RemainingCapacity) && (Capacity)) + { + /* We are discharging, and our capacity is below the trip point, trip now */ + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattSetStatusNotify: Trip point already crossed (1): TP = %08x, remaining capacity = %08x\n", + NewTripPoint, BstData.RemainingCapacity); + CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS); + } + + /* All should've went well if we got here, unless BST failed... return! */ + if (CmBattDebug & CMBATT_GENERIC_STATUS) + DbgPrint("CmBattSetStatusNotify: Want %X CurrentCap %X\n", + Capacity, DeviceExtension->RemainingCapacity); + if (CmBattDebug & CMBATT_ACPI_WARNING) + DbgPrint("CmBattSetStatusNotify: Set to: [%#08lx][%#08lx][%#08lx] Status %x\n", + BatteryNotify->PowerState, + BatteryNotify->LowCapacity, + BatteryNotify->HighCapacity); + return Status; } NTSTATUS NTAPI -CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG BatteryTag) +CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + ULONG PsrData = 0; + NTSTATUS Status; + ULONG BstState; + ULONG DesignVoltage, PresentRate, RemainingCapacity; + PAGED_CODE(); + if (CmBattDebug & CMBATT_GENERIC_INFO) + DbgPrint("CmBattGetBatteryStatus - CmBatt (%08x) Tag (%d)\n", DeviceExtension, Tag); + + /* Validate ACPI data */ + Status = CmBattVerifyStaticInfo(DeviceExtension, Tag); + if (!NT_SUCCESS(Status)) return Status; + + /* Check for delayed status notifications */ + if (DeviceExtension->DelayNotification) + { + /* Process them now and don't do any other work */ + CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS); + return Status; + } + + /* Get _BST from ACPI */ + Status = CmBattGetBstData(DeviceExtension, &DeviceExtension->BstData); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + InterlockedExchange(&DeviceExtension->ArLockValue, 0); + return Status; + } + + /* Clear current BST information */ + DeviceExtension->State = 0; + DeviceExtension->RemainingCapacity = 0; + DeviceExtension->PresentVoltage = 0; + DeviceExtension->Rate = 0; + + /* Get battery state */ + BstState = DeviceExtension->BstData.State; + + /* Is the battery both charging and discharging? */ + if ((BstState & ACPI_BATT_STAT_DISCHARG) && (BstState & ACPI_BATT_STAT_CHARGING) && + (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING))) + DbgPrint("************************ ACPI BIOS BUG ********************\n* " + "CmBattGetBatteryStatus: Invalid state: _BST method returned 0x%08x for Battery State.\n" + "* One battery cannot be charging and discharging at the same time.\n", + BstState); + + /* Is the battery discharging? */ + if (BstState & ACPI_BATT_STAT_DISCHARG) + { + /* Set power state and check if it just started discharging now */ + DeviceExtension->State |= BATTERY_DISCHARGING; + if (!(DeviceExtension->State & ACPI_BATT_STAT_DISCHARG)) + { + /* Remember the time when the state changed */ + DeviceExtension->InterruptTime = KeQueryInterruptTime(); + } + } + else if (BstState & ACPI_BATT_STAT_CHARGING) + { + /* Battery is charging, update power state */ + DeviceExtension->State |= (BATTERY_CHARGING | BATTERY_POWER_ON_LINE); + } + + /* Is the battery in a critical state? */ + if (BstState & ACPI_BATT_STAT_CRITICAL) DeviceExtension->State |= BATTERY_CRITICAL; + + /* Read the voltage data */ + DeviceExtension->PresentVoltage = DeviceExtension->BstData.PresentVoltage; + + /* Check if we have an A/C adapter */ + if (AcAdapterPdo) + { + /* Query information on it */ + CmBattGetPsrData(AcAdapterPdo, &PsrData); + } + else + { + /* Otherwise, check if the battery is charging */ + if (BstState & ACPI_BATT_STAT_CHARGING) + { + /* Then we'll assume there's a charger */ + PsrData = 1; + } + else + { + /* Assume no charger */ + PsrData = 0; + } + } + + /* Is there a charger? */ + if (PsrData) + { + /* Set the power state flag to reflect this */ + DeviceExtension->State |= BATTERY_POWER_ON_LINE; + if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS)) + DbgPrint("CmBattGetBatteryStatus: AC adapter is connected\n"); + } + else if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS)) + { + DbgPrint("CmBattGetBatteryStatus: AC adapter is NOT connected\n"); + } + + /* Get some data we'll need */ + DesignVoltage = DeviceExtension->BifData.DesignVoltage; + PresentRate = DeviceExtension->BstData.PresentRate; + RemainingCapacity = DeviceExtension->BstData.RemainingCapacity; + + /* Check if we have battery data in Watts instead of Amps */ + if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_WATTS) + { + /* Get the data from the BST */ + DeviceExtension->RemainingCapacity = RemainingCapacity; + DeviceExtension->Rate = PresentRate; + + /* Check if the rate is invalid */ + if (PresentRate > CM_MAX_VALUE) + { + /* Set an unknown rate and don't touch the old value */ + DeviceExtension->Rate = BATTERY_UNKNOWN_RATE; + if ((PresentRate != CM_UNKNOWN_VALUE) && (CmBattDebug & CMBATT_ACPI_WARNING)) + { + DbgPrint("CmBattGetBatteryStatus - Rate is greater than CM_MAX_VALUE\n"); + DbgPrint("---------------------- PresentRate = 0x%08x\n", PresentRate); + } + } + } + else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage)) + { + /* We have voltage data, what about capacity? */ + if (RemainingCapacity == CM_UNKNOWN_VALUE) + { + /* Unable to calculate it */ + DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY; + if (CmBattDebug & CMBATT_ACPI_WARNING) + { + DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity \n"); + DbgPrint("---------------------- RemainingCapacity = CM_UNKNOWN_VALUE\n"); + } + } + else + { + /* Compute the capacity with the information we have */ + DeviceExtension->RemainingCapacity = (DesignVoltage * RemainingCapacity + 500) / 1000; + } + + /* Check if we have a rate */ + if (PresentRate != CM_UNKNOWN_VALUE) + { + /* Make sure the rate isn't too large */ + if (PresentRate > (-500 / DesignVoltage)) + { + /* It is, so set unknown state */ + DeviceExtension->Rate = BATTERY_UNKNOWN_RATE; + if (CmBattDebug & CMBATT_ACPI_WARNING) + { + DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n"); + DbgPrint("---------------------- Overflow: PresentRate = 0x%08x\n", PresentRate); + } + } + + /* Compute the rate */ + DeviceExtension->Rate = (PresentRate * DesignVoltage + 500) / 1000; + } + else + { + /* We don't have a rate, so set unknown value */ + DeviceExtension->Rate = BATTERY_UNKNOWN_RATE; + if (CmBattDebug & CMBATT_ACPI_WARNING) + { + DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n"); + DbgPrint("---------------------- Present Rate = CM_UNKNOWN_VALUE\n"); + } + } + } + else + { + /* We have no rate, and no capacity, set unknown values */ + DeviceExtension->Rate = BATTERY_UNKNOWN_RATE; + DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY; + if (CmBattDebug & CMBATT_ACPI_WARNING) + { + DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity and Rate \n"); + DbgPrint("---------------------- DesignVoltage = 0x%08x\n", DesignVoltage); + } + } + + /* Check if we have an unknown rate */ + if (DeviceExtension->Rate == BATTERY_UNKNOWN_RATE) + { + /* The battery is discharging but we don't know by how much... this is bad! */ + if ((BstState & ACPI_BATT_STAT_DISCHARG) && + (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING))) + DbgPrint("CmBattGetBatteryStatus: battery rate is unkown when battery is not charging!\n"); + } + else if (DeviceExtension->State & BATTERY_DISCHARGING) + { + /* The battery is discharging, so treat the rate as a negative rate */ + DeviceExtension->Rate = -DeviceExtension->Rate; + } + else if (!(DeviceExtension->State & BATTERY_CHARGING) && (DeviceExtension->Rate)) + { + /* We are not charging, not discharging, but have a rate? Ignore it! */ + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattGetBatteryStatus: battery is not charging or discharging, but rate = %x\n", + DeviceExtension->Rate); + DeviceExtension->Rate = 0; + } + + /* Done */ + return STATUS_SUCCESS; } NTSTATUS NTAPI -CmBattQueryInformation(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG BatteryTag, - BATTERY_QUERY_INFORMATION_LEVEL Level, - OPTIONAL LONG AtRate, - PVOID Buffer, - ULONG BufferLength, - PULONG ReturnedLength) +CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION FdoExtension, + IN ULONG Tag, + IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel, + IN OPTIONAL LONG AtRate, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PVOID QueryData = NULL; + ULONG QueryLength = 0; + ULONG RemainingTime = 0; + ANSI_STRING TempString; + UNICODE_STRING TempString2; + WCHAR InfoBuffer[256]; + WCHAR TempBuffer[256]; + UNICODE_STRING InfoString; + ULONG RemainingCapacity; + BATTERY_REPORTING_SCALE BatteryReportingScale[2]; + LONG Rate; + PAGED_CODE(); + if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO)) + DbgPrint("CmBattQueryInformation - Tag (%d) Device %d, Informationlevel %d\n", + Tag, + FdoExtension->DeviceId, + InfoLevel); + + /* Check ACPI Data */ + Status = CmBattVerifyStaticInfo(FdoExtension, Tag); + if (!NT_SUCCESS(Status)) return Status; + + /* Check what caller wants */ + switch (InfoLevel) + { + case BatteryInformation: + /* Just return our static information */ + QueryData = &FdoExtension->BatteryInformation; + QueryLength = sizeof(BATTERY_INFORMATION); + break; + + case BatteryGranularityInformation: + + /* Return our static information, we have two scales */ + BatteryReportingScale[0].Granularity = FdoExtension->BatteryCapacityGranularity1; + BatteryReportingScale[0].Capacity = FdoExtension->BatteryInformation.DefaultAlert1; + BatteryReportingScale[1].Granularity = FdoExtension->BatteryCapacityGranularity2; + BatteryReportingScale[1].Capacity = FdoExtension->BatteryInformation.DesignedCapacity; + QueryData = BatteryReportingScale; + QueryLength = sizeof(BATTERY_REPORTING_SCALE) * 2; + break; + + case BatteryEstimatedTime: + + /* Check if it's been more than 2 1/2 minutes since the last change */ + if ((KeQueryInterruptTime() - 150000000) > (FdoExtension->InterruptTime)) + { + /* Get new battery status */ + CmBattGetBatteryStatus(FdoExtension, FdoExtension->Tag); + + /* If the caller didn't specify a rate, use our static one */ + Rate = AtRate; + if (!Rate) Rate = FdoExtension->Rate; + + /* If we don't have a valid negative rate, use unknown value */ + if (Rate >= 0) Rate = BATTERY_UNKNOWN_RATE; + + /* Grab the remaining capacity */ + RemainingCapacity = FdoExtension->RemainingCapacity; + + /* See if we don't know one or the other */ + if ((Rate == BATTERY_UNKNOWN_RATE) || + (RemainingCapacity == BATTERY_UNKNOWN_CAPACITY)) + { + /* If the battery is discharging, we can't give out a time */ + if ((FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG) && + (CmBattDebug & CMBATT_GENERIC_WARNING)) + DbgPrint("CmBattQueryInformation: Can't calculate EstimatedTime.\n"); + + /* Check if we don't have a rate and capacity is going down */ + if ((FdoExtension->Rate == BATTERY_UNKNOWN_RATE) && + (FdoExtension->BstData.State & ACPI_BATT_STAT_DISCHARG)) + { + /* We have to fail, since we lack data */ + Status = STATUS_INVALID_DEVICE_REQUEST; + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("---------------------- PresentRate = BATTERY_UNKNOWN_RATE\n"); + } + + /* If we don't have capacity, the rate is useless */ + if (RemainingCapacity == BATTERY_UNKNOWN_CAPACITY) + { + /* We have to fail the request */ + Status = STATUS_INVALID_DEVICE_REQUEST; + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("---------------------- RemainingCapacity = BATTERY_UNKNOWN_CAPACITY\n"); + } + } + else + { + /* We have data, but is it valid? */ + if (RemainingCapacity > 0x123456) + { + /* The capacity seems bogus, so don't use it */ + if (CmBattDebug & CMBATT_ACPI_WARNING) + DbgPrint("CmBattQueryInformation: Data Overflow in calculating Remaining Capacity.\n"); + } + else + { + /* Compute the remaining time in seconds, based on rate */ + RemainingTime = (RemainingCapacity * 3600) / -Rate; + } + } + } + + /* Return the remaining time */ + QueryData = &RemainingTime; + QueryLength = sizeof(ULONG); + break; + + case BatteryDeviceName: + + /* Build the model number string */ + RtlInitAnsiString(&TempString, FdoExtension->ModelNumber); + + /* Convert it to Unicode */ + InfoString.Buffer = InfoBuffer; + InfoString.MaximumLength = sizeof(InfoBuffer); + Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0); + + /* Return the unicode buffer */ + QueryData = InfoString.Buffer; + QueryLength = InfoString.Length; + break; + + case BatteryTemperature: + case BatteryManufactureDate: + + /* We don't support these */ + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case BatteryManufactureName: + + /* Build the OEM info string */ + RtlInitAnsiString(&TempString, FdoExtension->OemInfo); + + /* Convert it to Unicode */ + InfoString.Buffer = InfoBuffer; + InfoString.MaximumLength = sizeof(InfoBuffer); + Status = RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0); + + /* Return the unicode buffer */ + QueryData = InfoString.Buffer; + QueryLength = InfoString.Length; + break; + + case BatteryUniqueID: + + /* Build the serial number string */ + RtlInitAnsiString(&TempString, FdoExtension->SerialNumber); + + /* Convert it to Unicode */ + InfoString.Buffer = InfoBuffer; + InfoString.MaximumLength = sizeof(InfoBuffer); + RtlAnsiStringToUnicodeString(&InfoString, &TempString, 0); + + /* Setup a temporary string for concatenation */ + TempString2.Buffer = TempBuffer; + TempString2.MaximumLength = sizeof(TempBuffer); + + /* Check if there's an OEM string */ + if (FdoExtension->OemInfo[0]) + { + /* Build the OEM info string */ + RtlInitAnsiString(&TempString, FdoExtension->OemInfo); + + /* Convert it to Unicode and append it */ + RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0); + RtlAppendUnicodeStringToString(&InfoString, &TempString2); + } + + /* Build the model number string */ + RtlInitAnsiString(&TempString, FdoExtension->ModelNumber); + + /* Convert it to Unicode and append it */ + RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0); + RtlAppendUnicodeStringToString(&InfoString, &TempString2); + + /* Return the final appended string */ + QueryData = InfoString.Buffer; + QueryLength = InfoString.Length; + break; + + default: + + /* Everything else is unknown */ + Status = STATUS_INVALID_PARAMETER; + break; + } + + /* Return the required length and check if the caller supplied enough */ + *ReturnedLength = QueryLength; + if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL; + + /* Copy the data if there's enough space and it exists */ + if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength); + + /* Return function result */ + return Status; } NTSTATUS NTAPI -CmBattQueryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG BatteryTag, - PBATTERY_STATUS BatteryStatus) +CmBattQueryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag, + IN PBATTERY_STATUS BatteryStatus) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PAGED_CODE(); + if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO)) + DbgPrint("CmBattQueryStatus - Tag (%d) Device %x\n", Tag, DeviceExtension->DeviceId); + + /* Query ACPI information */ + Status = CmBattGetBatteryStatus(DeviceExtension, Tag); + if (NT_SUCCESS(Status)) + { + BatteryStatus->PowerState = DeviceExtension->State; + BatteryStatus->Capacity = DeviceExtension->RemainingCapacity; + BatteryStatus->Voltage = DeviceExtension->PresentVoltage; + BatteryStatus->Rate = DeviceExtension->Rate; + } + + /* Return status */ + if (CmBattDebug & (CMBATT_GENERIC_INFO)) + DbgPrint("CmBattQueryStatus: Returning [%#08lx][%#08lx][%#08lx][%#08lx]\n", + BatteryStatus->PowerState, + BatteryStatus->Capacity, + BatteryStatus->Voltage, + BatteryStatus->Rate); + return Status; } NTSTATUS NTAPI -DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PDRIVER_EXTENSION DriverExtension; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING CallbackName; + + /* Allocate registry path */ + GlobalRegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); + GlobalRegistryPath.Length = RegistryPath->Length; + GlobalRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, + GlobalRegistryPath.MaximumLength, + 'MtaB'); + if (!GlobalRegistryPath.Buffer) + { + /* Fail if we're out of memory this early */ + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBatt: Couldn't allocate pool for registry path."); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Buffer allocated, copy the string */ + RtlCopyUnicodeString(&GlobalRegistryPath, RegistryPath); + if (CmBattDebug & CMBATT_GENERIC_INFO) + DbgPrint("CmBatt DriverEntry - Obj (%08x) Path \"%ws\"\n", + DriverObject, + RegistryPath->Buffer); + + /* Setup the major dispatchers */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = CmBattOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = CmBattOpenClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CmBattIoctl; + DriverObject->MajorFunction[IRP_MJ_POWER] = CmBattPowerDispatch; + DriverObject->MajorFunction[IRP_MJ_PNP] = CmBattPnpDispatch; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CmBattSystemControl; + + /* And the unload routine */ + DriverObject->DriverUnload = CmBattUnload; + + /* And the add device routine */ + DriverExtension = DriverObject->DriverExtension; + DriverExtension->AddDevice = CmBattAddDevice; + + /* Create a power callback */ + RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState"); + InitializeObjectAttributes(&ObjectAttributes, + &CallbackName, + OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ExCreateCallback(&CmBattPowerCallBackObject, &ObjectAttributes, 0, TRUE); + if (!NT_SUCCESS(Status)) + { + /* No callback, fail */ + CmBattPowerCallBackObject = 0; + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status); + } + else + { + /* Register the power callback now */ + CmBattPowerCallBackRegistration = ExRegisterCallback(CmBattPowerCallBackObject, + (PVOID)CmBattPowerCallBack, + DriverObject); + if (CmBattPowerCallBackRegistration) + { + /* Last thing: setup our DPC and timer for battery wake */ + KeInitializeDpc(&CmBattWakeDpcObject, (PVOID)CmBattWakeDpc, DriverObject); + KeInitializeTimer(&CmBattWakeDpcTimerObject); + } + else + { + ObfDereferenceObject(CmBattPowerCallBackObject); + if (CmBattDebug & CMBATT_GENERIC_WARNING) + DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n"); + } + + /* All good */ + Status = STATUS_SUCCESS; + } + + /* Return failure or success */ + return Status; } /* EOF */ diff --git a/drivers/bus/acpi/cmbatt/cmbatt.h b/drivers/bus/acpi/cmbatt/cmbatt.h index 0443c4c86bb..8f952d20200 100644 --- a/drivers/bus/acpi/cmbatt/cmbatt.h +++ b/drivers/bus/acpi/cmbatt/cmbatt.h @@ -11,8 +11,27 @@ #include #include #include +#include #include +#define IOCTL_BATTERY_QUERY_UNIQUE_ID \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x101, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x294404 + +#define IOCTL_BATTERY_QUERY_STA \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x102, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x294408 + +#define IOCTL_BATTERY_QUERY_PSR \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x103, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x29440C + +#define IOCTL_BATTERY_SET_TRIP_POINT \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x104, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x294410 + +#define IOCTL_BATTERY_QUERY_BIF \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x105, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x294414 + +#define IOCTL_BATTERY_QUERY_BST \ + CTL_CODE(FILE_DEVICE_BATTERY, 0x106, METHOD_BUFFERED, FILE_READ_ACCESS) // 0x294418 + #define CMBATT_GENERIC_STATUS 0x01 #define CMBATT_GENERIC_INFO 0x02 #define CMBATT_GENERIC_WARNING 0x04 @@ -29,6 +48,25 @@ typedef enum _CMBATT_EXTENSION_TYPE CmBattBattery } CMBATT_EXTENSION_TYPE; +#define ACPI_BUS_CHECK 0x00 +#define ACPI_DEVICE_CHECK 0x01 + +#define ACPI_STA_PRESENT 0x01 +#define ACPI_STA_ENABLED 0x02 +#define ACPI_STA_SHOW_UI 0x04 +#define ACPI_STA_FUNCTIONAL 0x08 +#define ACPI_STA_BATTERY_PRESENT 0x10 + +#define ACPI_BATT_NOTIFY_STATUS 0x80 +#define ACPI_BATT_NOTIFY_INFO 0x81 + +#define ACPI_BATT_STAT_DISCHARG 0x0001 +#define ACPI_BATT_STAT_CHARGING 0x0002 +#define ACPI_BATT_STAT_CRITICAL 0x0004 + +#define CM_MAX_VALUE 0x7FFFFFFF +#define CM_UNKNOWN_VALUE 0xFFFFFFFF + typedef struct _ACPI_BST_DATA { ULONG State; @@ -37,6 +75,9 @@ typedef struct _ACPI_BST_DATA ULONG PresentVoltage; } ACPI_BST_DATA, *PACPI_BST_DATA; +#define ACPI_BATT_POWER_UNIT_WATTS 0x0 +#define ACPI_BATT_POWER_UNIT_AMPS 0x1 + typedef struct _ACPI_BIF_DATA { ULONG PowerUnit; @@ -54,6 +95,10 @@ typedef struct _ACPI_BIF_DATA CHAR OemInfo[256]; } ACPI_BIF_DATA, *PACPI_BIF_DATA; +#define CMBATT_AR_NOTIFY 0x01 +#define CMBATT_AR_INSERT 0x02 +#define CMBATT_AR_REMOVE 0x04 + typedef struct _CMBATT_DEVICE_EXTENSION { CMBATT_EXTENSION_TYPE FdoType; @@ -66,18 +111,17 @@ typedef struct _CMBATT_DEVICE_EXTENSION PIRP PowerIrp; POWER_STATE PowerState; WMILIB_CONTEXT WmiLibInfo; - ULONG WaitWakeEnable; - ULONG WmiCount; - KEVENT WmiEvent; + BOOLEAN WaitWakeEnable; + IO_REMOVE_LOCK RemoveLock; ULONG DeviceId; PUNICODE_STRING DeviceName; - ACPI_INTERFACE_STANDARD2 AcpiInterface; - BOOLEAN DelayAr; - BOOLEAN DelayedArFlag; + ACPI_INTERFACE_STANDARD AcpiInterface; + BOOLEAN DelayNotification; + BOOLEAN ArFlag; PVOID ClassData; BOOLEAN Started; BOOLEAN NotifySent; - ULONG ArLock; + LONG ArLockValue; ULONG TagData; ULONG Tag; ULONG ModelNumberLength; @@ -93,7 +137,7 @@ typedef struct _CMBATT_DEVICE_EXTENSION ULONG RemainingCapacity; ULONG PresentVoltage; ULONG Rate; - BATTERY_INFORMATION StaticBatteryInformation; + BATTERY_INFORMATION BatteryInformation; ULONG BatteryCapacityGranularity1; ULONG BatteryCapacityGranularity2; BOOLEAN TripPointSet; @@ -101,5 +145,138 @@ typedef struct _CMBATT_DEVICE_EXTENSION ULONG TripPointOld; ULONGLONG InterruptTime; } CMBATT_DEVICE_EXTENSION, *PCMBATT_DEVICE_EXTENSION; - + +NTSTATUS +NTAPI +CmBattPowerDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp +); + +NTSTATUS +NTAPI +CmBattPnpDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp +); + +NTSTATUS +NTAPI +CmBattAddDevice( + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject +); + +NTSTATUS +NTAPI +CmBattSystemControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp +); + +NTSTATUS +NTAPI +CmBattGetBstData( + PCMBATT_DEVICE_EXTENSION DeviceExtension, + PACPI_BST_DATA BstData +); + +NTSTATUS +NTAPI +CmBattGetPsrData( + PDEVICE_OBJECT DeviceObject, + PULONG PsrData +); + +NTSTATUS +NTAPI +CmBattGetStaData( + PDEVICE_OBJECT DeviceObject, + PULONG StaData +); + +NTSTATUS +NTAPI +CmBattGetBifData( + PCMBATT_DEVICE_EXTENSION DeviceExtension, + PACPI_BIF_DATA BifData +); + +NTSTATUS +NTAPI +CmBattSetTripPpoint( + PCMBATT_DEVICE_EXTENSION DeviceExtension, + ULONG AlarmValue +); + +VOID +NTAPI +CmBattNotifyHandler( + IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG NotifyValue +); + +NTSTATUS +NTAPI +CmBattWmiDeRegistration( + PCMBATT_DEVICE_EXTENSION DeviceExtension +); + +NTSTATUS +NTAPI +CmBattWmiRegistration( + PCMBATT_DEVICE_EXTENSION DeviceExtension +); + +NTSTATUS +NTAPI +CmBattGetUniqueId( + PDEVICE_OBJECT DeviceObject, + PULONG UniqueId +); + +NTSTATUS +NTAPI +CmBattQueryInformation( + IN PCMBATT_DEVICE_EXTENSION FdoExtension, + IN ULONG Tag, + IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel, + IN OPTIONAL LONG AtRate, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength +); + +NTSTATUS +NTAPI +CmBattQueryStatus( + IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag, + IN PBATTERY_STATUS BatteryStatus +); + +NTSTATUS +NTAPI +CmBattSetStatusNotify( + IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG BatteryTag, + IN PBATTERY_NOTIFY BatteryNotify +); + +NTSTATUS +NTAPI +CmBattDisableStatusNotify( + IN PCMBATT_DEVICE_EXTENSION DeviceExtension +); + +NTSTATUS +NTAPI +CmBattQueryTag( + IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + OUT PULONG Tag +); + +extern PDEVICE_OBJECT AcAdapterPdo; +extern ULONG CmBattDebug; + /* EOF */ diff --git a/drivers/bus/acpi/cmbatt/cmbatt.rbuild b/drivers/bus/acpi/cmbatt/cmbatt.rbuild index c8a09e31b44..34c85adccf1 100644 --- a/drivers/bus/acpi/cmbatt/cmbatt.rbuild +++ b/drivers/bus/acpi/cmbatt/cmbatt.rbuild @@ -4,10 +4,12 @@ ntoskrnl hal battc + wmilib . cmbatt.c cmexec.c cmbpnp.c cmbwmi.c cmbatt.rc + cmbatt.h diff --git a/drivers/bus/acpi/cmbatt/cmbpnp.c b/drivers/bus/acpi/cmbatt/cmbpnp.c index fee3ec80b47..55d3ae63d49 100644 --- a/drivers/bus/acpi/cmbatt/cmbpnp.c +++ b/drivers/bus/acpi/cmbatt/cmbpnp.c @@ -12,93 +12,864 @@ /* FUNCTIONS ******************************************************************/ +VOID +NTAPI +CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock) +{ + NTSTATUS Status; + PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + if (CmBattDebug & 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n"); + + /* Check for success */ + if ((NT_SUCCESS(IoStatusBlock->Status)) && (DeviceExtension->WaitWakeEnable)) + { + /* Request a new power IRP */ + if (CmBattDebug & 2) DbgPrint("CmBattWaitWakeLoop: completed successfully\n"); + Status = PoRequestPowerIrp(DeviceObject, + MinorFunction, + PowerState, + CmBattWaitWakeLoop, + Context, + &DeviceExtension->PowerIrp); + if (CmBattDebug & 2) + DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status = 0x%08x.\n", + Status); + } + else + { + /* Clear the power IRP, we failed */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n", + IoStatusBlock->Status); + DeviceExtension->PowerIrp = NULL; + } +} + NTSTATUS NTAPI -CmBattIoCompletion(PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PKEVENT Event) +CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PKEVENT Event) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + if (CmBattDebug & 2) DbgPrint("CmBattIoCompletion: Event (%x)\n", Event); + + /* Set the completion event */ + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS NTAPI -CmBattGetAcpiInterfaces(PDEVICE_OBJECT DeviceObject, - PACPI_INTERFACE_STANDARD2 *AcpiInterface) +CmBattGetAcpiInterfaces(IN PDEVICE_OBJECT DeviceObject, + IN OUT PACPI_INTERFACE_STANDARD AcpiInterface) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIRP Irp; + NTSTATUS Status; + PIO_STACK_LOCATION IoStackLocation; + KEVENT Event; + + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, 0); + if (!Irp) + { + /* Fail */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattGetAcpiInterfaces: Failed to allocate Irp\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Set default error code */ + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + /* Build the query */ + IoStackLocation = IoGetNextIrpStackLocation(Irp); + IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_ACPI_INTERFACE_STANDARD; + IoStackLocation->Parameters.QueryInterface.Size = sizeof(ACPI_INTERFACE_STANDARD); + IoStackLocation->Parameters.QueryInterface.Version = 1; + IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)AcpiInterface; + IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL; + + /* Set default ACPI interface data */ + AcpiInterface->Size = sizeof(ACPI_INTERFACE_STANDARD); + AcpiInterface->Version = 1; + + /* Initialize our wait event */ + KeInitializeEvent(&Event, SynchronizationEvent, 0); + + /* Set the completion routine */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + (PVOID)CmBattIoCompletion, + &Event, + TRUE, + TRUE, + TRUE); + + /* Now call ACPI */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = Irp->IoStatus.Status; + } + + /* Free the IRP */ + IoFreeIrp(Irp); + + /* Return status */ + if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC)) + DbgPrint("CmBattGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status); + return Status; } VOID NTAPI -CmBattDestroyFdo(PDEVICE_OBJECT DeviceObject) +CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED; + PAGED_CODE(); + if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n"); + + /* Delete the device */ + IoDeleteDevice(DeviceObject); + if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo: done.\n"); } NTSTATUS NTAPI -CmBattRemoveDevice(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + PVOID Context; + DeviceExtension = DeviceObject->DeviceExtension; + if (CmBattDebug & 2) + DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n", + DeviceExtension, + DeviceExtension->FdoType, + DeviceExtension->DeviceId); + + /* Make sure it's safe to go ahead */ + IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, 0); + + /* Check for pending power IRP */ + if (DeviceExtension->PowerIrp) + { + /* Cancel and clear */ + IoCancelIrp(DeviceExtension->PowerIrp); + DeviceExtension->PowerIrp = NULL; + } + + /* Check what type of FDO is being removed */ + Context = DeviceExtension->AcpiInterface.Context; + if (DeviceExtension->FdoType == CmBattBattery) + { + /* Unregister battery FDO */ + DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context, + (PVOID)CmBattNotifyHandler); + CmBattWmiDeRegistration(DeviceExtension); + if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension->ClassData))) ASSERT(FALSE); + } + else + { + /* Unregister AC adapter FDO */ + DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context, + (PVOID)CmBattNotifyHandler); + CmBattWmiDeRegistration(DeviceExtension); + AcAdapterPdo = NULL; + } + + /* Detach and delete */ + IoDetachDevice(DeviceExtension->AttachedDevice); + IoDeleteDevice(DeviceExtension->DeviceObject); + return STATUS_SUCCESS; } NTSTATUS NTAPI -CmBattPowerDispatch(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +CmBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStackLocation; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + if (CmBattDebug & 0x210) DbgPrint("CmBattPowerDispatch\n"); + + /* Get stack location and device extension */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + switch (IoStackLocation->MinorFunction) + { + case IRP_MN_WAIT_WAKE: + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n"); + break; + + case IRP_MN_POWER_SEQUENCE: + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n"); + break; + + case IRP_MN_QUERY_POWER: + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n"); + break; + + case IRP_MN_SET_POWER: + if (CmBattDebug & 0x10) + DbgPrint("CmBattPowerDispatch: IRP_MN_SET_POWER type: %d, State: %d \n", + IoStackLocation->Parameters.Power.Type, + IoStackLocation->Parameters.Power.State); + break; + + default: + + if (CmBattDebug & 1) + DbgPrint("CmBattPowerDispatch: minor %d\n", IoStackLocation->MinorFunction); + break; + } + + /* Start the next IRP and see if we're attached */ + PoStartNextPowerIrp(Irp); + if (DeviceExtension->AttachedDevice) + { + /* Call ACPI */ + IoSkipCurrentIrpStackLocation(Irp); + Status = PoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + else + { + /* Complete the request here */ + Status = Irp->IoStatus.Status; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + } + + /* Return status */ + return Status; } NTSTATUS NTAPI -CmBattCreateFdo(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT DeviceObject, - ULONG DeviceExtensionSize, - PDEVICE_OBJECT *NewDeviceObject) +CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStackLocation; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + KEVENT Event; + PAGED_CODE(); + + /* Get stack location and device extension */ + IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + + /* Set default error */ + Status = STATUS_NOT_SUPPORTED; + + /* Try to acquire the lock before doing anything */ + Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0); + if (!NT_SUCCESS(Status)) + { + /* Complete the request */ + Irp->IoStatus.Status = STATUS_DEVICE_REMOVED; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_DEVICE_REMOVED; + } + + /* What's the operation? */ + switch (IoStackLocation->MinorFunction) + { + case IRP_MN_QUERY_PNP_DEVICE_STATE: + + /* Initialize our wait event */ + KeInitializeEvent(&Event, SynchronizationEvent, 0); + + /* Set the completion routine */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + (PVOID)CmBattIoCompletion, + &Event, + TRUE, + TRUE, + TRUE); + + /* Now call ACPI to inherit its PnP Device State */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = Irp->IoStatus.Status; + } + + /* However, a battery CAN be disabled */ + Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE; + + /* Release the remove lock and complete the request */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); + return Status; + + case IRP_MN_SURPRISE_REMOVAL: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n"); + + /* Lock the device extension and set the handle count to invalid */ + ExAcquireFastMutex(&DeviceExtension->FastMutex); + DeviceExtension->HandleCount = -1; + ExReleaseFastMutex(&DeviceExtension->FastMutex); + Status = STATUS_SUCCESS; + break; + + case IRP_MN_START_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n"); + + /* Mark the extension as started */ + if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = TRUE; + Status = STATUS_SUCCESS; + break; + + case IRP_MN_STOP_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n"); + + /* Mark the extension as stopped */ + if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = FALSE; + Status = STATUS_SUCCESS; + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n"); + + /* Lock the extension and get the current handle count */ + ExAcquireFastMutex(&DeviceExtension->FastMutex); + if (DeviceExtension->HandleCount == 0) + { + /* No handles. Mark it as invalid since it'll be removed */ + DeviceExtension->HandleCount = -1; + Status = STATUS_SUCCESS; + } + else if (DeviceExtension->HandleCount == -1) + { + /* Don't do anything, but this is strange since it's already removed */ + Status = STATUS_SUCCESS; + if (CmBattDebug & 4) + DbgPrint("CmBattPnpDispatch: Recieved two consecutive QUERY_REMOVE requests.\n"); + } + else + { + /* Fail because there's still open handles */ + Status = STATUS_UNSUCCESSFUL; + } + + /* Release the lock and return */ + ExReleaseFastMutex(&DeviceExtension->FastMutex); + break; + + case IRP_MN_REMOVE_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n"); + + /* Call the remove code */ + Status = CmBattRemoveDevice(DeviceObject, Irp); + break; + + case IRP_MN_CANCEL_REMOVE_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n"); + + /* Lock the extension and get the handle count */ + ExAcquireFastMutex(&DeviceExtension->FastMutex); + if (DeviceExtension->HandleCount == -1) + { + /* A remove was in progress, set the handle count back to 0 */ + DeviceExtension->HandleCount = 0; + } + else if (CmBattDebug & 2) + { + /* Nop, but warn about it */ + DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount == %x\n", + DeviceExtension->HandleCount); + } + + /* Return success in all cases, and release the lock */ + Status = STATUS_SUCCESS; + ExReleaseFastMutex(&DeviceExtension->FastMutex); + break; + + case IRP_MN_QUERY_STOP_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n"); + + /* There's no real support for this */ + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n"); + + /* There's no real support for this */ + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_CAPABILITIES: + + /* Initialize our wait event */ + KeInitializeEvent(&Event, SynchronizationEvent, 0); + + /* Set the completion routine */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + (PVOID)CmBattIoCompletion, + &Event, + TRUE, + TRUE, + TRUE); + + /* Now call ACPI */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = Irp->IoStatus.Status; + } + + /* Get the wake power state */ + DeviceExtension->PowerState.SystemState = IoStackLocation->Parameters.DeviceCapabilities.Capabilities->SystemWake; + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d Capabilities->SystemWake = %x\n", + DeviceExtension->FdoType, + DeviceExtension->PowerState); + + /* Check if it's invalid */ + if (DeviceExtension->PowerState.SystemState == PowerSystemUnspecified) + { + /* Wait wake is not supported in this scenario */ + DeviceExtension->WaitWakeEnable = FALSE; + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not supported.\n"); + } + else if (!(DeviceExtension->PowerIrp) && + (DeviceExtension->WaitWakeEnable)) + { + /* If it was requested in the registry, request the power IRP for it */ + PoRequestPowerIrp(DeviceExtension->DeviceObject, + 0, + DeviceExtension->PowerState, + CmBattWaitWakeLoop, + 0, + &DeviceExtension->PowerIrp); + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake irp sent.\n"); + } + + /* Release the remove lock and complete the request */ + IofCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); + return Status; + + default: + /* Unsupported */ + if (CmBattDebug & 0x20) + DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n", + IoStackLocation->MinorFunction); + break; + } + + /* Release the remove lock */ + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp); + + /* Set IRP status if we have one */ + if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; + + /* Did someone pick it up? */ + if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED)) + { + /* Still unsupported, try ACPI */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + else + { + /* Complete the request */ + Status = Irp->IoStatus.Status; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + } + + /* Release the remove lock and return status */ + return Status; } NTSTATUS NTAPI -CmBattPnpDispatch(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceExtensionSize, + IN PDEVICE_OBJECT *NewDeviceObject) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PDEVICE_OBJECT FdoDeviceObject; + HANDLE KeyHandle; + PCMBATT_DEVICE_EXTENSION FdoExtension; + UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer; + NTSTATUS Status; + UNICODE_STRING KeyString; + ULONG UniqueId; + ULONG ResultLength; + PAGED_CODE(); + if (CmBattDebug & 0x220) DbgPrint("CmBattCreateFdo: Entered\n"); + + /* Get unique ID */ + Status = CmBattGetUniqueId(DeviceObject, &UniqueId); + if (!NT_SUCCESS(Status)) + { + /* Assume 0 */ + UniqueId = 0; + if (CmBattDebug & 2) + DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status); + } + + /* Create the FDO */ + Status = IoCreateDevice(DriverObject, + DeviceExtensionSize, + 0, + FILE_DEVICE_BATTERY, + FILE_DEVICE_SECURE_OPEN, + 0, + &FdoDeviceObject); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status); + return Status; + } + + /* Set FDO flags */ + FdoDeviceObject->Flags |= DO_BUFFERED_IO; + FdoDeviceObject->Flags |= DO_MAP_IO_BUFFER; + FdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + /* Initialize the extension */ + FdoExtension = FdoDeviceObject->DeviceExtension; + RtlZeroMemory(FdoExtension, DeviceExtensionSize); + FdoExtension->DeviceObject = FdoDeviceObject; + FdoExtension->FdoDeviceObject = FdoDeviceObject; + FdoExtension->PdoDeviceObject = DeviceObject; + + /* Attach to ACPI */ + FdoExtension->AttachedDevice = IoAttachDeviceToDeviceStack(FdoDeviceObject, + DeviceObject); + if (!FdoExtension->AttachedDevice) + { + /* Destroy and fail */ + CmBattDestroyFdo(FdoExtension->FdoDeviceObject); + if (CmBattDebug & 0xC) + DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n"); + return STATUS_UNSUCCESSFUL; + } + + /* Get ACPI interface for EVAL */ + Status = CmBattGetAcpiInterfaces(FdoExtension->AttachedDevice, + &FdoExtension->AcpiInterface); + if (!FdoExtension->AttachedDevice) + { + /* Detach, destroy, and fail */ + IoDetachDevice(FdoExtension->AttachedDevice); + CmBattDestroyFdo(FdoExtension->FdoDeviceObject); + if (CmBattDebug & 0xC) + DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status); + return STATUS_UNSUCCESSFUL; + } + + /* Setup the rest of the extension */ + ExInitializeFastMutex(&FdoExtension->FastMutex); + IoInitializeRemoveLock(&FdoExtension->RemoveLock, 0, 0, 0); + FdoExtension->HandleCount = 0; + FdoExtension->WaitWakeEnable = FALSE; + FdoExtension->DeviceId = UniqueId; + FdoExtension->DeviceName = NULL; + FdoExtension->DelayNotification = FALSE; + FdoExtension->ArFlag = 0; + + /* Open the device key */ + Status = IoOpenDeviceRegistryKey(DeviceObject, + PLUGPLAY_REGKEY_DEVICE, + KEY_READ, + &KeyHandle); + if (NT_SUCCESS(Status)) + { + /* Read wait wake value */ + RtlInitUnicodeString(&KeyString, L"WaitWakeEnabled"); + Status = ZwQueryValueKey(KeyHandle, + &KeyString, + KeyValuePartialInformation, + PartialInfo, + sizeof(Buffer), + &ResultLength); + if (NT_SUCCESS(Status)) + { + /* Set value */ + FdoExtension->WaitWakeEnable = *(PULONG)PartialInfo->Data; + } + + /* Close the handle */ + ZwClose(KeyHandle); + } + + /* Return success and the new FDO */ + *NewDeviceObject = FdoDeviceObject; + if (CmBattDebug & 0x220) + DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject); + return STATUS_SUCCESS; } NTSTATUS NTAPI -CmBattAddBattery(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT DeviceObject) +CmBattAddBattery(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + BATTERY_MINIPORT_INFO MiniportInfo; + NTSTATUS Status; + PDEVICE_OBJECT FdoDeviceObject; + PCMBATT_DEVICE_EXTENSION FdoExtension; + PAGED_CODE(); + if (CmBattDebug & 0x220) + DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject); + + /* Create the FDO */ + Status = CmBattCreateFdo(DriverObject, + DeviceObject, + sizeof(CMBATT_DEVICE_EXTENSION), + &FdoDeviceObject); + if (!NT_SUCCESS(Status)) + { + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status); + return Status; + } + + /* Build the FDO extensio, check if we support trip points */ + FdoExtension = FdoDeviceObject->DeviceExtension; + FdoExtension->FdoType = CmBattBattery; + FdoExtension->Started = 0; + FdoExtension->NotifySent = TRUE; + InterlockedExchange(&FdoExtension->ArLockValue, 0); + FdoExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY; + FdoExtension->Tag = 0; + FdoExtension->InterruptTime = KeQueryInterruptTime(); + FdoExtension->TripPointSet = CmBattSetTripPpoint(FdoExtension, 0) != + STATUS_OBJECT_NAME_NOT_FOUND; + + /* Setup the battery miniport information structure */ + RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo)); + MiniportInfo.Pdo = DeviceObject; + MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; + MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION; + MiniportInfo.Context = FdoExtension; + MiniportInfo.QueryTag = (PVOID)CmBattQueryTag; + MiniportInfo.QueryInformation = (PVOID)CmBattQueryInformation; + MiniportInfo.SetInformation = NULL; + MiniportInfo.QueryStatus = (PVOID)CmBattQueryStatus; + MiniportInfo.SetStatusNotify = (PVOID)CmBattSetStatusNotify; + MiniportInfo.DisableStatusNotify = (PVOID)CmBattDisableStatusNotify; + MiniportInfo.DeviceName = FdoExtension->DeviceName; + + /* Register with the class driver */ + Status = BatteryClassInitializeDevice(&MiniportInfo, &FdoExtension->ClassData); + if (!NT_SUCCESS(Status)) + { + IoDetachDevice(FdoExtension->AttachedDevice); + CmBattDestroyFdo(FdoExtension->FdoDeviceObject); + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status); + return Status; + } + + /* Register WMI */ + Status = CmBattWmiRegistration(FdoExtension); + if (!NT_SUCCESS(Status)) + { + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status); + return Status; + } + + /* Register ACPI */ + Status = FdoExtension->AcpiInterface.RegisterForDeviceNotifications(FdoExtension->AcpiInterface.Context, + (PVOID)CmBattNotifyHandler, + FdoExtension); + if (!NT_SUCCESS(Status)) + { + CmBattWmiDeRegistration(FdoExtension); + BatteryClassUnload(FdoExtension->ClassData); + IoDetachDevice(FdoExtension->AttachedDevice); + CmBattDestroyFdo(FdoExtension->FdoDeviceObject); + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status); + } + + /* Return status */ + return Status; } NTSTATUS NTAPI -CmBattAddAcAdapter(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT DeviceObject) +CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PdoDeviceObject) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PDEVICE_OBJECT FdoDeviceObject; + NTSTATUS Status; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + PAGED_CODE(); + if (CmBattDebug & 0x220) + DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject); + + /* Check if we already have an AC adapter */ + if (AcAdapterPdo) + { + /* Don't do anything */ + if (CmBattDebug & 0xC) + DbgPrint("CmBatt: Second AC adapter found. Current version of driver only supports 1 aadapter.\n"); + } + else + { + /* Set this as the AC adapter's PDO */ + AcAdapterPdo = PdoDeviceObject; + } + + /* Create the FDO for the adapter */ + Status = CmBattCreateFdo(DriverObject, + PdoDeviceObject, + sizeof(CMBATT_DEVICE_EXTENSION), + &FdoDeviceObject); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status); + return Status; + } + + /* Set the type and do WMI registration */ + DeviceExtension = FdoDeviceObject->DeviceExtension; + DeviceExtension->FdoType = CmBattAcAdapter; + Status = CmBattWmiRegistration(DeviceExtension); + if (!NT_SUCCESS(Status)) + { + /* We can go on without WMI */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status); + } + + /* Register with ACPI */ + Status = DeviceExtension->AcpiInterface.RegisterForDeviceNotifications(DeviceExtension->AcpiInterface.Context, + (PVOID)CmBattNotifyHandler, + DeviceExtension); + if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC)) + DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status); + + /* Send the first manual notification */ + CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS); + return STATUS_SUCCESS; } -NTSTATUS NTAPI CmBattAddDevice(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT DeviceObject) +NTSTATUS +NTAPI +CmBattAddDevice(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PdoDeviceObject) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + HANDLE KeyHandle; + ULONG ResultLength; + UNICODE_STRING KeyString; + UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer; + ULONG PowerSourceType; + PAGED_CODE(); + if (CmBattDebug & 0x220) + DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject); + + /* Make sure we have a PDO */ + if (!PdoDeviceObject) + { + /* Should not be having as one */ + if (CmBattDebug & 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n"); + return STATUS_NO_MORE_ENTRIES; + } + + /* Open the driver key */ + Status = IoOpenDeviceRegistryKey(PdoDeviceObject, + PLUGPLAY_REGKEY_DRIVER, + KEY_READ, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status); + return Status; + } + + /* Read the power source type */ + RtlInitUnicodeString(&KeyString, L"PowerSourceType"); + Status = ZwQueryValueKey(KeyHandle, + &KeyString, + KeyValuePartialInformation, + PartialInfo, + sizeof(Buffer), + &ResultLength); + ZwClose(KeyHandle); + if (!NT_SUCCESS(Status)) + { + /* We need the data, fail without it */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status); + return Status; + } + + /* Check what kind of power source this is */ + PowerSourceType = *(PULONG)PartialInfo->Data; + if (PowerSourceType == 1) + { + /* Create an AC adapter */ + Status = CmBattAddAcAdapter(DriverObject, PdoDeviceObject); + } + else if (PowerSourceType == 0) + { + /* Create a battery */ + Status = CmBattAddBattery(DriverObject, PdoDeviceObject); + } + else + { + /* Unknown type, fail */ + if (CmBattDebug & 0xC) + DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType); + return STATUS_UNSUCCESSFUL; + } + + /* Return whatever the FDO creation routine did */ + return Status; } /* EOF */ diff --git a/drivers/bus/acpi/cmbatt/cmbwmi.c b/drivers/bus/acpi/cmbatt/cmbwmi.c index 848c920dd0b..1274f04280b 100644 --- a/drivers/bus/acpi/cmbatt/cmbwmi.c +++ b/drivers/bus/acpi/cmbatt/cmbwmi.c @@ -10,8 +10,46 @@ #include "cmbatt.h" +/* GLOBALS ********************************************************************/ + +WMIGUIDREGINFO CmBattWmiGuidList[1] = +{ + {&GUID_POWER_DEVICE_WAKE_ENABLE, 1, 0} +}; + /* FUNCTIONS ******************************************************************/ +PCHAR +NTAPI +WMIMinorFunctionString(IN UCHAR MinorFunction) +{ + switch (MinorFunction) + { + case IRP_MN_CHANGE_SINGLE_INSTANCE: + return "IRP_MN_CHANGE_SINGLE_INSTANCE"; + case IRP_MN_CHANGE_SINGLE_ITEM: + return "IRP_MN_CHANGE_SINGLE_ITEM"; + case IRP_MN_DISABLE_COLLECTION: + return "IRP_MN_DISABLE_COLLECTION"; + case IRP_MN_DISABLE_EVENTS: + return "IRP_MN_DISABLE_EVENTS"; + case IRP_MN_ENABLE_COLLECTION: + return "IRP_MN_ENABLE_COLLECTION"; + case IRP_MN_ENABLE_EVENTS: + return "IRP_MN_ENABLE_EVENTS"; + case IRP_MN_EXECUTE_METHOD: + return "IRP_MN_EXECUTE_METHOD"; + case IRP_MN_QUERY_ALL_DATA: + return "IRP_MN_QUERY_ALL_DATA"; + case IRP_MN_QUERY_SINGLE_INSTANCE: + return "IRP_MN_QUERY_SINGLE_INSTANCE"; + case IRP_MN_REGINFO: + return "IRP_MN_REGINFO"; + default: + return "IRP_MN_?????"; + } +} + NTSTATUS NTAPI CmBattQueryWmiRegInfo(PDEVICE_OBJECT DeviceObject, @@ -69,26 +107,115 @@ CmBattSetWmiDataItem(PDEVICE_OBJECT DeviceObject, NTSTATUS NTAPI -CmBattWmiDeRegistration(PCMBATT_DEVICE_EXTENSION DeviceExtension) +CmBattWmiDeRegistration(IN PCMBATT_DEVICE_EXTENSION DeviceExtension) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PAGED_CODE(); + + /* De-register */ + return IoWMIRegistrationControl(DeviceExtension->FdoDeviceObject, + WMIREG_ACTION_DEREGISTER); } NTSTATUS NTAPI -CmBattWmiRegistration(PCMBATT_DEVICE_EXTENSION DeviceExtension) +CmBattWmiRegistration(IN PCMBATT_DEVICE_EXTENSION DeviceExtension) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PAGED_CODE(); + + /* GUID information */ + DeviceExtension->WmiLibInfo.GuidCount = sizeof(CmBattWmiGuidList) / + sizeof(WMIGUIDREGINFO); + DeviceExtension->WmiLibInfo.GuidList = CmBattWmiGuidList; + + /* Callbacks */ + DeviceExtension->WmiLibInfo.QueryWmiRegInfo = CmBattQueryWmiRegInfo; + DeviceExtension->WmiLibInfo.QueryWmiDataBlock = CmBattQueryWmiDataBlock; + DeviceExtension->WmiLibInfo.SetWmiDataBlock = CmBattSetWmiDataBlock; + DeviceExtension->WmiLibInfo.SetWmiDataItem = CmBattSetWmiDataItem; + DeviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL; + DeviceExtension->WmiLibInfo.WmiFunctionControl = NULL; + + /* Register */ + return IoWMIRegistrationControl(DeviceExtension->FdoDeviceObject, + WMIREG_ACTION_REGISTER); } NTSTATUS NTAPI -CmBattSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +CmBattSystemControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PCMBATT_DEVICE_EXTENSION DeviceExtension; + PWMILIB_CONTEXT WmiLibContext; + SYSCTL_IRP_DISPOSITION Disposition = IrpForward; + PAGED_CODE(); + if (CmBattDebug & 2) + DbgPrint("CmBatt: SystemControl: %s\n", + WMIMinorFunctionString(IoGetCurrentIrpStackLocation(Irp)->MinorFunction)); + + /* Acquire the remove lock */ + DeviceExtension = DeviceObject->DeviceExtension; + Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0); + if (!NT_SUCCESS(Status)) + { + /* It's too late, fail */ + Irp->IoStatus.Status = STATUS_DEVICE_REMOVED; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_DEVICE_REMOVED; + } + + /* What kind of device is this? */ + WmiLibContext = &DeviceExtension->WmiLibInfo; + if (DeviceExtension->FdoType == CmBattBattery) + { + /* For batteries, let the class driver handle it */ + Status = BatteryClassSystemControl(DeviceExtension->ClassData, + WmiLibContext, + DeviceObject, + Irp, + &Disposition); + } + else + { + /* Otherwise, call the wmi library directly */ + Status = WmiSystemControl(WmiLibContext, + DeviceObject, + Irp, + &Disposition); + } + + /* Check what happened */ + switch (Disposition) + { + case IrpNotCompleted: + + /* Complete it here */ + if (CmBattDebug & 2) DbgPrint("CmBatt: SystemControl: Irp Not Completed.\n"); + IofCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IrpForward: + + /* Forward it to ACPI */ + if (CmBattDebug & 2) DbgPrint("CmBatt: SystemControl: Irp Forward.\n"); + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + break; + + case IrpProcessed: + + /* Nothing to do */ + if (CmBattDebug & 2) DbgPrint("CmBatt: SystemControl: Irp Processed.\n"); + break; + + default: + ASSERT(FALSE); + } + + /* Release the lock and return */ + IoReleaseRemoveLock(&DeviceExtension->RemoveLock, 0); + return Status; } /* EOF */ diff --git a/drivers/bus/acpi/cmbatt/cmexec.c b/drivers/bus/acpi/cmbatt/cmexec.c index a41865c5e4c..beb646ab509 100644 --- a/drivers/bus/acpi/cmbatt/cmexec.c +++ b/drivers/bus/acpi/cmbatt/cmexec.c @@ -14,29 +14,307 @@ NTSTATUS NTAPI -GetDwordElement(PACPI_METHOD_ARGUMENT Argument, - PULONG Value) +GetDwordElement(IN PACPI_METHOD_ARGUMENT Argument, + OUT PULONG Value) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + + /* Must have an integer */ + if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) + { + /* Not an integer, fail */ + Status = STATUS_ACPI_INVALID_DATA; + if (CmBattDebug & 0x4C) + DbgPrint("GetDwordElement: Object contained wrong data type - %d\n", + Argument->Type); + } + else + { + /* Read the integer value */ + *Value = Argument->Argument; + Status = STATUS_SUCCESS; + } + + /* Return status */ + return Status; } NTSTATUS NTAPI -GetStringElement(PACPI_METHOD_ARGUMENT Argument, - PCHAR Value) +GetStringElement(IN PACPI_METHOD_ARGUMENT Argument, + OUT PCHAR Value) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + + /* Must have a string of buffer */ + if ((Argument->Type == ACPI_METHOD_ARGUMENT_STRING) || + (Argument->Type == ACPI_METHOD_ARGUMENT_BUFFER)) + { + /* String must be less than 256 characters */ + if (Argument->DataLength < 256) + { + /* Copy the buffer */ + RtlCopyMemory(Value, Argument->Data, Argument->DataLength); + Status = STATUS_SUCCESS; + } + else + { + /* The buffer is too small (the string is too large) */ + Status = STATUS_BUFFER_TOO_SMALL; + if (CmBattDebug & 0x4C) + DbgPrint("GetStringElement: return buffer not big enough - %d\n", Argument->DataLength); + } + } + else + { + /* Not valid string data */ + Status = STATUS_ACPI_INVALID_DATA; + if (CmBattDebug & 0x4C) + DbgPrint("GetStringElement: Object contained wrong data type - %d\n", Argument->Type); + } + + /* Return the status */ + return Status; } NTSTATUS NTAPI -CmBattGetPsrData(PDEVICE_OBJECT DeviceObject, - PULONG PsrData) +CmBattSendDownStreamIrp(IN PDEVICE_OBJECT DeviceObject, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + IN PACPI_EVAL_OUTPUT_BUFFER OutputBuffer, + IN ULONG OutputBufferLength) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIRP Irp; + NTSTATUS Status; + KEVENT Event; + IO_STATUS_BLOCK IoStatusBlock; + PAGED_CODE(); + + /* Initialize our wait event */ + KeInitializeEvent(&Event, SynchronizationEvent, 0); + + /* Allocate the IRP */ + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + DeviceObject, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength, + 0, + &Event, + &IoStatusBlock); + if (!Irp) + { + /* No IRP, fail */ + if (CmBattDebug & 0x4C) + DbgPrint("CmBattSendDownStreamIrp: Failed to allocate Irp\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Call ACPI */ + if (CmBattDebug & 0x40) + DbgPrint("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n", + Irp, KeGetCurrentThread()); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = Irp->IoStatus.Status; + } + + /* Check if caller wanted output */ + if (OutputBuffer) + { + /* Make sure it's valid ACPI output buffer */ + if ((OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) || + !(OutputBuffer->Count)) + { + /* It isn't, so set failure code */ + Status = STATUS_ACPI_INVALID_DATA; + } + } + + /* Return status */ + if (CmBattDebug & 0x40) + DbgPrint("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n", + Irp, Status, KeGetCurrentThread()); + return Status; +} + +NTSTATUS +NTAPI +CmBattGetPsrData(IN PDEVICE_OBJECT DeviceObject, + OUT PULONG PsrData) +{ + NTSTATUS Status; + ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; + ACPI_EVAL_INPUT_BUFFER InputBuffer; + PAGED_CODE(); + if (CmBattDebug & 0x40) + DbgPrint("CmBattGetPsrData: Entered with Pdo %x Tid %x\n", + DeviceObject, KeGetCurrentThread()); + + /* Initialize to zero */ + ASSERT(PsrData != NULL); + *PsrData = 0; + + /* Request the _PSR method */ + *(PULONG)InputBuffer.MethodName = 'RSP_'; + InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; + + /* Send it to ACPI */ + Status = CmBattSendDownStreamIrp(DeviceObject, + IOCTL_ACPI_EVAL_METHOD, + &InputBuffer, + sizeof(InputBuffer), + &OutputBuffer, + sizeof(OutputBuffer)); + if (NT_SUCCESS(Status)) + { + /* Read the result */ + Status = GetDwordElement(OutputBuffer.Argument, PsrData); + if (CmBattDebug & 0x440) + DbgPrint("CmBattGetPsrData: _PSR method returned %x \n", *PsrData); + } + else if (CmBattDebug & 0x44C) + { + /* Failure */ + DbgPrint("CmBattGetPsrData: Failed _PSR method - Status (0x%x)\n", Status); + } + + /* Return status */ + return Status; +} + +NTSTATUS +NTAPI +CmBattGetStaData(IN PDEVICE_OBJECT DeviceObject, + OUT PULONG StaData) +{ + NTSTATUS Status; + ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; + ACPI_EVAL_INPUT_BUFFER InputBuffer; + PAGED_CODE(); + if (CmBattDebug & 0x40) + DbgPrint("CmBattGetStaData: Entered with Pdo %x Tid %x\n", + DeviceObject, KeGetCurrentThread()); + + /* Initialize to zero */ + ASSERT(StaData != NULL); + *StaData = 0; + + /* Request the _PSR method */ + *(PULONG)InputBuffer.MethodName = 'ATS_'; + InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; + + /* Send it to ACPI */ + Status = CmBattSendDownStreamIrp(DeviceObject, + IOCTL_ACPI_EVAL_METHOD, + &InputBuffer, + sizeof(InputBuffer), + &OutputBuffer, + sizeof(OutputBuffer)); + if (NT_SUCCESS(Status)) + { + /* Read the result */ + Status = GetDwordElement(OutputBuffer.Argument, StaData); + if (CmBattDebug & 0x440) + DbgPrint("CmBattGetStaData: _STA method returned %x \n", *StaData); + } + else if (CmBattDebug & 0x44C) + { + /* Failure */ + DbgPrint("CmBattGetStaData: Failed _STA method - Status (0x%x)\n", Status); + Status = STATUS_NO_SUCH_DEVICE; + } + + /* Return status */ + return Status; +} + +NTSTATUS +NTAPI +CmBattGetUniqueId(IN PDEVICE_OBJECT DeviceObject, + OUT PULONG UniqueId) +{ + NTSTATUS Status; + ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; + ACPI_EVAL_INPUT_BUFFER InputBuffer; + PAGED_CODE(); + if (CmBattDebug & 0x40) + DbgPrint("CmBattGetUniqueId: Entered with Pdo %x Tid %x\n", + DeviceObject, KeGetCurrentThread()); + + /* Initialize to zero */ + ASSERT(UniqueId != NULL); + *UniqueId = 0; + + /* Request the _PSR method */ + *(PULONG)InputBuffer.MethodName = 'DIU_'; + InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; + + /* Send it to ACPI */ + Status = CmBattSendDownStreamIrp(DeviceObject, + IOCTL_ACPI_EVAL_METHOD, + &InputBuffer, + sizeof(InputBuffer), + &OutputBuffer, + sizeof(OutputBuffer)); + if (NT_SUCCESS(Status)) + { + /* Read the result */ + Status = GetDwordElement(OutputBuffer.Argument, UniqueId); + if (CmBattDebug & 0x440) + DbgPrint("CmBattGetUniqueId: _UID method returned %x \n", *UniqueId); + } + else if (CmBattDebug & 0x44C) + { + /* Failure */ + DbgPrint("CmBattGetUniqueId: Failed _UID method - Status (0x%x)\n", Status); + Status = STATUS_NO_SUCH_DEVICE; + } + + /* Return status */ + return Status; +} + +NTSTATUS +NTAPI +CmBattSetTripPpoint(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG AlarmValue) +{ + NTSTATUS Status; + ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER InputBuffer; + PAGED_CODE(); + if (CmBattDebug & 0x440) + DbgPrint("CmBattSetTripPpoint: _BTP Alarm Value %x Device %x Tid %x\n", + AlarmValue, DeviceExtension->DeviceId, KeGetCurrentThread); + + /* Request the _BTP method */ + *(PULONG)InputBuffer.MethodName = 'PTB_'; + InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE; + InputBuffer.IntegerArgument = AlarmValue; + + /* Send it to ACPI */ + Status = CmBattSendDownStreamIrp(DeviceExtension->AttachedDevice, + IOCTL_ACPI_EVAL_METHOD, + &InputBuffer, + sizeof(InputBuffer), + NULL, + 0); + if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0x440)) + DbgPrint("CmBattSetTripPpoint: Failed _BTP method on device %x - Status (0x%x)\n", + DeviceExtension->DeviceId, Status); + + /* Return status */ + return Status; } NTSTATUS @@ -55,46 +333,6 @@ CmBattGetBstData(PCMBATT_DEVICE_EXTENSION DeviceExtension, { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -CmBattGetStaData(PDEVICE_OBJECT DeviceObject, - PULONG StaData) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; } -NTSTATUS -NTAPI -CmBattGetUniqueId(PDEVICE_OBJECT DeviceObject, - PULONG UniqueId) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -CmBattSetTripPpoint(PCMBATT_DEVICE_EXTENSION DeviceExtension, - ULONG AlarmValue) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -CmBattSendDownStreamIrp(PDEVICE_OBJECT DeviceObject, - ULONG IoControlCode, - PVOID InputBuffer, - ULONG InputBufferLength, - PACPI_EVAL_OUTPUT_BUFFER OutputBuffer, - ULONG OutputBufferLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - /* EOF */ diff --git a/drivers/bus/acpi/compbatt/compbatt.c b/drivers/bus/acpi/compbatt/compbatt.c new file mode 100644 index 00000000000..03d587c46ad --- /dev/null +++ b/drivers/bus/acpi/compbatt/compbatt.c @@ -0,0 +1,168 @@ +/* + * PROJECT: ReactOS Composite Battery Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/bus/acpi/compbatt/compbatt.c + * PURPOSE: Main Initialization Code and IRP Handling + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include "compbatt.h" + +/* GLOBALS ********************************************************************/ + +ULONG CompBattDebug; + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +CompBattOpenClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattSystemControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattMonitorIrpComplete(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PKEVENT Event) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattMonitorIrpCompleteWorker(IN PCOMPBATT_BATTERY_ENTRY BatteryData) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattRecalculateTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattIoctl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattQueryTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + OUT PULONG Tag) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattDisableStatusNotify(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattSetStatusNotify(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG BatteryTag, + IN PBATTERY_NOTIFY BatteryNotify) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetBatteryStatus(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattQueryStatus(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag, + IN PBATTERY_STATUS BatteryStatus) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetBatteryInformation(OUT PBATTERY_INFORMATION BatteryInformation, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetBatteryGranularity(OUT PBATTERY_REPORTING_SCALE ReportingScale, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetEstimatedTime(OUT PULONG Time, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattQueryInformation(IN PCOMPBATT_DEVICE_EXTENSION FdoExtension, + IN ULONG Tag, + IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel, + IN OPTIONAL LONG AtRate, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/drivers/bus/acpi/compbatt/compbatt.h b/drivers/bus/acpi/compbatt/compbatt.h new file mode 100644 index 00000000000..701f1362641 --- /dev/null +++ b/drivers/bus/acpi/compbatt/compbatt.h @@ -0,0 +1,57 @@ +/* + * PROJECT: ReactOS Composite Battery Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/bus/acpi/compbatt/compbatt.h + * PURPOSE: Main Header File + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +#include +#include +#include +#include + +typedef struct _COMPBATT_BATTERY_ENTRY +{ + LIST_ENTRY BatteryLink; + IO_REMOVE_LOCK RemoveLock; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + WORK_QUEUE_ITEM WorkItem; + BOOLEAN WaitFlag; + BATTERY_WAIT_STATUS WaitStatus; + union + { + BATTERY_WAIT_STATUS WorkerWaitStatus; + BATTERY_STATUS WorkerStatus; + }; + ULONG Tag; + ULONG Flags; + BATTERY_INFORMATION BatteryInformation; + BATTERY_STATUS BatteryStatus; + ULONGLONG InterruptTime; + UNICODE_STRING BatteryName; +} COMPBATT_BATTERY_ENTRY, *PCOMPBATT_BATTERY_ENTRY; + +typedef struct _COMPBATT_DEVICE_EXTENSION +{ + PVOID ClassData; + ULONG NextTag; + LIST_ENTRY BatteryList; + FAST_MUTEX Lock; + ULONG Tag; + ULONG Flags; + BATTERY_INFORMATION BatteryInformation; + BATTERY_STATUS BatteryStatus; + ULONGLONG InterruptTime; + POWER_STATE PowerState; + ULONG LowCapacity; + ULONG HighCapacity; + PDEVICE_OBJECT AttachedDevice; + PDEVICE_OBJECT DeviceObject; + PVOID NotificationEntry; +} COMPBATT_DEVICE_EXTENSION, *PCOMPBATT_DEVICE_EXTENSION; + +extern ULONG CmBattDebug; + +/* EOF */ diff --git a/drivers/bus/acpi/compbatt/compbatt.rbuild b/drivers/bus/acpi/compbatt/compbatt.rbuild new file mode 100644 index 00000000000..6a92873c0e1 --- /dev/null +++ b/drivers/bus/acpi/compbatt/compbatt.rbuild @@ -0,0 +1,13 @@ + + + + ntoskrnl + hal + battc + . + compbatt.c + compmisc.c + comppnp.c + compbatt.rc + compbatt.h + diff --git a/drivers/bus/acpi/compbatt/compbatt.rc b/drivers/bus/acpi/compbatt/compbatt.rc new file mode 100644 index 00000000000..a7ec82048fc --- /dev/null +++ b/drivers/bus/acpi/compbatt/compbatt.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "Composite Battery Driver\0" +#define REACTOS_STR_INTERNAL_NAME "compbatt\0" +#define REACTOS_STR_ORIGINAL_FILENAME "compbatt.sys\0" +#include diff --git a/drivers/bus/acpi/compbatt/compmisc.c b/drivers/bus/acpi/compbatt/compmisc.c new file mode 100644 index 00000000000..3f75d4b9abf --- /dev/null +++ b/drivers/bus/acpi/compbatt/compmisc.c @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS Composite Battery Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/bus/acpi/compbatt/compmisc.c + * PURPOSE: Miscellaneous Support Routines + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include "compbatt.h" + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +BatteryIoctl(IN ULONG IoControlCode, + IN PDEVICE_OBJECT DeviceObject, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + IN PVOID OutputBuffer, + IN ULONG OutputBufferLength, + IN BOOLEAN InternalDeviceIoControl) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetDeviceObjectPointer(IN PCUNICODE_STRING DeviceName, + IN ACCESS_MASK DesiredAccess, + OUT PFILE_OBJECT *FileObject, + OUT PDEVICE_OBJECT *DeviceObject) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/drivers/bus/acpi/compbatt/comppnp.c b/drivers/bus/acpi/compbatt/comppnp.c new file mode 100644 index 00000000000..a767c18ab80 --- /dev/null +++ b/drivers/bus/acpi/compbatt/comppnp.c @@ -0,0 +1,95 @@ +/* + * PROJECT: ReactOS Composite Battery Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/bus/acpi/compbatt/comppnp.c + * PURPOSE: Plug-and-Play IOCTL/IRP Handling + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include "compbatt.h" + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +PCOMPBATT_BATTERY_ENTRY +NTAPI +RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return NULL; +} + +BOOLEAN +NTAPI +IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return FALSE; +} + +NTSTATUS +NTAPI +CompBattAddNewBattery(IN PCUNICODE_STRING BatteryName, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification, + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattAddDevice(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PdoDeviceObject) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/drivers/bus/acpi/eval.c b/drivers/bus/acpi/eval.c new file mode 100644 index 00000000000..68af8573f42 --- /dev/null +++ b/drivers/bus/acpi/eval.c @@ -0,0 +1,180 @@ +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#define NDEBUG +#include + +NTSTATUS +NTAPI +Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData, + PIRP Irp) +{ + ULONG Signature; + NTSTATUS Status; + ACPI_OBJECT_LIST ParamList; + PACPI_EVAL_INPUT_BUFFER EvalInputBuff = Irp->AssociatedIrp.SystemBuffer; + ACPI_BUFFER RetBuff = {ACPI_ALLOCATE_BUFFER, NULL}; + PACPI_EVAL_OUTPUT_BUFFER OutputBuf; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER *SimpleInt; + ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING *SimpleStr; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) + return STATUS_INVALID_PARAMETER; + + Signature = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + + switch (Signature) + { + case ACPI_EVAL_INPUT_BUFFER_SIGNATURE: + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 0; + break; + + case ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE: + SimpleInt = Irp->AssociatedIrp.SystemBuffer; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 1; + + ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT)); + if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES; + + ParamList.Pointer[0].Type = ACPI_TYPE_INTEGER; + ParamList.Pointer[0].Integer.Value = SimpleInt->IntegerArgument; + break; + + case ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE: + SimpleStr = Irp->AssociatedIrp.SystemBuffer; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 1; + + ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT)); + if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES; + + ParamList.Pointer[0].String.Pointer = (CHAR*)SimpleStr->String; + ParamList.Pointer[0].String.Length = SimpleStr->StringLength; + break; + + default: + DPRINT1("Unsupported input buffer signature: %d\n", Signature); + return STATUS_NOT_IMPLEMENTED; + } + + Status = AcpiEvaluateObject(DeviceData->AcpiHandle, + (CHAR*)EvalInputBuff->MethodName, + &ParamList, + &RetBuff); + + if (ParamList.Count != 0) + ExFreePool(ParamList.Pointer); + + if (ACPI_SUCCESS(Status)) + { + ACPI_OBJECT *Obj = RetBuff.Pointer; + ULONG ExtraParamLength; + + /* If we didn't get anything back then we're done */ + if (!RetBuff.Pointer || RetBuff.Length == 0) + return STATUS_SUCCESS; + + switch (Obj->Type) + { + case ACPI_TYPE_INTEGER: + ExtraParamLength = sizeof(ULONG); + break; + + case ACPI_TYPE_STRING: + ExtraParamLength = Obj->String.Length; + break; + + case ACPI_TYPE_BUFFER: + ExtraParamLength = Obj->Buffer.Length; + break; + + case ACPI_TYPE_PACKAGE: + DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n"); + return STATUS_UNSUCCESSFUL; + + default: + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + + /* Enough space for a ULONG is always included */ + if (ExtraParamLength >= sizeof(ULONG)) + ExtraParamLength -= sizeof(ULONG); + else + ExtraParamLength = 0; + + OutputBuf = ExAllocatePool(NonPagedPool, sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength); + if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES; + + OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE; + OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT); + OutputBuf->Count = 1; + + switch (Obj->Type) + { + case ACPI_TYPE_INTEGER: + ACPI_METHOD_SET_ARGUMENT_INTEGER(OutputBuf->Argument, Obj->Integer.Value); + break; + + case ACPI_TYPE_STRING: + ACPI_METHOD_SET_ARGUMENT_STRING(OutputBuf->Argument, Obj->String.Pointer); + break; + + case ACPI_TYPE_BUFFER: + ACPI_METHOD_SET_ARGUMENT_BUFFER(OutputBuf->Argument, Obj->Buffer.Pointer, Obj->Buffer.Length); + break; + + case ACPI_TYPE_PACKAGE: + DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n"); + return STATUS_UNSUCCESSFUL; + + default: + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength); + Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + ExtraParamLength; + ExFreePool(OutputBuf); + return STATUS_SUCCESS; + } + else + { + ExFreePool(OutputBuf); + return STATUS_BUFFER_TOO_SMALL; + } + } + else + { + DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, DeviceData->AcpiHandle); + return STATUS_UNSUCCESSFUL; + } +} diff --git a/drivers/bus/acpi/include/acpi_bus.h b/drivers/bus/acpi/include/acpi_bus.h index d5fe9efccc6..d2dc22d02a9 100644 --- a/drivers/bus/acpi/include/acpi_bus.h +++ b/drivers/bus/acpi/include/acpi_bus.h @@ -73,6 +73,8 @@ enum acpi_bus_device_type { ACPI_BUS_TYPE_SYSTEM, ACPI_BUS_TYPE_POWER_BUTTON, ACPI_BUS_TYPE_SLEEP_BUTTON, + ACPI_BUS_TYPE_POWER_BUTTONF, + ACPI_BUS_TYPE_SLEEP_BUTTONF, ACPI_BUS_DEVICE_TYPE_COUNT }; diff --git a/drivers/bus/acpi/include/acpisys.h b/drivers/bus/acpi/include/acpisys.h index 368ac97c83f..adf2a0c592a 100644 --- a/drivers/bus/acpi/include/acpisys.h +++ b/drivers/bus/acpi/include/acpisys.h @@ -39,6 +39,7 @@ typedef struct _PDO_DEVICE_DATA // Link point to hold all the PDOs for a single bus together LIST_ENTRY Link; ULONG InterfaceRefCount; + UNICODE_STRING InterfaceName; } PDO_DEVICE_DATA, *PPDO_DEVICE_DATA; @@ -64,10 +65,6 @@ typedef struct _FDO_DEVICE_DATA // A synchronization for access to the device extension. FAST_MUTEX Mutex; - // The name returned from IoRegisterDeviceInterface, - // which is used as a handle for IoSetDeviceInterfaceState. - UNICODE_STRING InterfaceName; - } FDO_DEVICE_DATA, *PFDO_DEVICE_DATA; #define FDO_FROM_PDO(pdoData) \ @@ -90,6 +87,11 @@ NTSTATUS ACPIEnumerateDevices( PFDO_DEVICE_DATA DeviceExtension); +NTSTATUS +NTAPI +Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData, + PIRP Irp); + NTSTATUS NTAPI Bus_CreateClose ( diff --git a/drivers/bus/acpi/interface.c b/drivers/bus/acpi/interface.c new file mode 100644 index 00000000000..59717056484 --- /dev/null +++ b/drivers/bus/acpi/interface.c @@ -0,0 +1,138 @@ +#include + +#include + +#include +#include +#include + +#include +#define NDEBUG +#include + +VOID +NTAPI +AcpiInterfaceReference(PVOID Context) +{ + UNIMPLEMENTED +} + +VOID +NTAPI +AcpiInterfaceDereference(PVOID Context) +{ + UNIMPLEMENTED +} + +NTSTATUS +AcpiInterfaceConnectVector(PDEVICE_OBJECT Context, + ULONG GpeNumber, + KINTERRUPT_MODE Mode, + BOOLEAN Shareable, + PGPE_SERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PVOID *ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceDisconnectVector(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceEnableEvent(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceDisableEvent(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceClearStatus(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceNotificationsRegister(PDEVICE_OBJECT Context, + PDEVICE_NOTIFY_CALLBACK NotificationHandler, + PVOID NotificationContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +VOID +AcpiInterfaceNotificationsUnregister(PDEVICE_OBJECT Context, + PDEVICE_NOTIFY_CALLBACK NotificationHandler) +{ + UNIMPLEMENTED +} + +NTSTATUS +Bus_PDO_QueryInterface(PPDO_DEVICE_DATA DeviceData, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PACPI_INTERFACE_STANDARD AcpiInterface; + + if (IrpSp->Parameters.QueryInterface.Version != 1) + { + DPRINT1("Invalid version number: %d\n", + IrpSp->Parameters.QueryInterface.Version); + return STATUS_INVALID_PARAMETER; + } + + if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType, + &GUID_ACPI_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID)) + { + DPRINT("GUID_ACPI_INTERFACE_STANDARD\n"); + + if (IrpSp->Parameters.QueryInterface.Size < sizeof(ACPI_INTERFACE_STANDARD)) + { + DPRINT1("Buffer too small! (%d)\n", IrpSp->Parameters.QueryInterface.Size); + return STATUS_BUFFER_TOO_SMALL; + } + + AcpiInterface = (PACPI_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface; + + AcpiInterface->InterfaceReference = AcpiInterfaceReference; + AcpiInterface->InterfaceDereference = AcpiInterfaceDereference; + AcpiInterface->GpeConnectVector = AcpiInterfaceConnectVector; + AcpiInterface->GpeDisconnectVector = AcpiInterfaceDisconnectVector; + AcpiInterface->GpeEnableEvent = AcpiInterfaceEnableEvent; + AcpiInterface->GpeDisableEvent = AcpiInterfaceDisableEvent; + AcpiInterface->GpeClearStatus = AcpiInterfaceClearStatus; + AcpiInterface->RegisterForDeviceNotifications = AcpiInterfaceNotificationsRegister; + AcpiInterface->UnregisterForDeviceNotifications = AcpiInterfaceNotificationsUnregister; + + return STATUS_SUCCESS; + } + else + { + DPRINT1("Invalid GUID\n"); + return STATUS_INVALID_PARAMETER; + } +} diff --git a/drivers/bus/acpi/main.c b/drivers/bus/acpi/main.c index 3d1170eefd6..4cbdfda4468 100644 --- a/drivers/bus/acpi/main.c +++ b/drivers/bus/acpi/main.c @@ -6,6 +6,9 @@ #include #include +#include +#include + #define NDEBUG #include @@ -15,7 +18,8 @@ #endif - +extern struct acpi_device *sleep_button; +extern struct acpi_device *power_button; NTSTATUS NTAPI @@ -29,7 +33,9 @@ Bus_AddDevice( PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; +#ifndef NDEBUG ULONG nameLength; +#endif PAGED_CODE (); @@ -162,38 +168,119 @@ End: } +NTSTATUS +NTAPI +ACPIDispatchCreateClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + NTSTATUS NTAPI ACPIDispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - PIO_STACK_LOCATION IrpSp; - NTSTATUS Status; + PIO_STACK_LOCATION irpStack; + NTSTATUS status = STATUS_NOT_SUPPORTED; + PCOMMON_DEVICE_DATA commonData; + ULONG Caps = 0; - DPRINT("Called. IRP is at (0x%X)\n", Irp); + PAGED_CODE (); + + irpStack = IoGetCurrentIrpStackLocation (Irp); + ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction); + + commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; Irp->IoStatus.Information = 0; - IrpSp = IoGetCurrentIrpStackLocation(Irp); - switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { - default: - DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); - Status = STATUS_NOT_IMPLEMENTED; - break; - } + if (!commonData->IsFDO) + { + switch (irpStack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_ACPI_EVAL_METHOD: + status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData, + Irp); + break; - if (Status != STATUS_PENDING) { - Irp->IoStatus.Status = Status; + case IOCTL_GET_SYS_BUTTON_CAPS: + if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } - DPRINT("Completing IRP at 0x%X\n", Irp); + if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D")) + { + DPRINT1("Lid button reported to power manager\n"); + Caps |= SYS_BUTTON_LID; + } + else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL) + { + /* We have to return both at the same time because since we + * have a NULL handle we are the fixed feature DO and we will + * only be called once (not once per device) + */ + if (power_button) + { + DPRINT1("Fixed power button reported to power manager\n"); + Caps |= SYS_BUTTON_POWER; + } + if (sleep_button) + { + DPRINT1("Fixed sleep button reported to power manager\n"); + Caps |= SYS_BUTTON_SLEEP; + } + } + if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C")) + { + DPRINT1("Control method power button reported to power manager\n"); + Caps |= SYS_BUTTON_POWER; + } + else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E")) + { + DPRINT1("Control method sleep reported to power manager\n"); + Caps |= SYS_BUTTON_SLEEP; + } + else + { + DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n"); + status = STATUS_INVALID_PARAMETER; + } - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } + if (Caps != 0) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &Caps, sizeof(Caps)); + Irp->IoStatus.Information = sizeof(Caps); + status = STATUS_SUCCESS; + } + break; - DPRINT("Leaving. Status 0x%X\n", Status); + /* TODO: Implement other IOCTLs */ - return Status; + default: + DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode); + break; + } + } + else + DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n"); + + if (status != STATUS_PENDING) + { + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return status; } NTSTATUS @@ -211,6 +298,8 @@ DriverEntry ( DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ACPIDispatchDeviceControl; DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP; DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power; + DriverObject->MajorFunction [IRP_MJ_CREATE] = ACPIDispatchCreateClose; + DriverObject->MajorFunction [IRP_MJ_CLOSE] = ACPIDispatchCreateClose; DriverObject->DriverExtension->AddDevice = Bus_AddDevice; diff --git a/drivers/bus/acpi/osl.c b/drivers/bus/acpi/osl.c index f2549951e7e..a5df0c0d620 100644 --- a/drivers/bus/acpi/osl.c +++ b/drivers/bus/acpi/osl.c @@ -576,7 +576,12 @@ AcpiOsWaitSemaphore( DPRINT("Waiting for semaphore %p\n", Handle); ASSERT(Mutex); - ExAcquireFastMutex(Mutex); + /* HACK: We enter here at a high IRQL sometimes + * because we get called from DPCs and ISRs and + * we can't use a fast mutex at that IRQL */ + if (KeGetCurrentIrql() <= APC_LEVEL) + ExAcquireFastMutex(Mutex); + return AE_OK; } @@ -590,7 +595,12 @@ AcpiOsSignalSemaphore ( DPRINT("AcpiOsSignalSemaphore %p\n",Handle); ASSERT(Mutex); - ExReleaseFastMutex(Mutex); + /* HACK: We enter here at a high IRQL sometimes + * because we get called from DPCs and ISRs and + * we can't use a fast mutex at that IRQL */ + if (KeGetCurrentIrql() <= APC_LEVEL) + ExReleaseFastMutex(Mutex); + return AE_OK; } diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 2c27302f8ab..37262c3aa87 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -153,7 +153,7 @@ static VOID WriteUlong(UCHAR Index, ULONG Value) } #endif -static __inline VOID SetReadDataPort(ULONG Port) +static __inline VOID SetReadDataPort(ULONG_PTR Port) { IsaPnPReadPort = (PUCHAR)Port; WriteUchar(0x00, (UCHAR) (Port >> 2)); @@ -214,13 +214,13 @@ static VOID DeactivateLogicalDevice(UCHAR LogicalDevice) #define READ_DATA_PORT_STEP 32 /* Minimum is 4 */ -static ULONG FindNextReadPort(VOID) +static ULONG_PTR FindNextReadPort(VOID) { - ULONG Port; + ULONG_PTR Port; - Port = (ULONG)IsaPnPReadPort; + Port = (ULONG_PTR)IsaPnPReadPort; while (TRUE) { @@ -260,7 +260,7 @@ static ULONG FindNextReadPort(VOID) static BOOLEAN IsolateReadDataPortSelect(VOID) { - ULONG Port; + ULONG_PTR Port; SendWait(); SendKey(); @@ -333,7 +333,7 @@ static ULONG IsolatePnPCards(VOID) KeStallExecutionProcessor(250); iteration++; SendWake(0x00); - SetReadDataPort((ULONG)IsaPnPReadPort); + SetReadDataPort((ULONG_PTR)IsaPnPReadPort); KeStallExecutionProcessor(1000); WriteAddress(0x01); KeStallExecutionProcessor(1000); @@ -1304,7 +1304,7 @@ static NTSTATUS BuildResourceLists(PISAPNP_LOGICAL_DEVICE LogicalDevice) do { Status = BuildResourceList(LogicalDevice, p, Priority); if (NT_SUCCESS(Status)) { - p = (PIO_RESOURCE_LIST)((ULONG)p + SingleListSize); + p = (PIO_RESOURCE_LIST)((ULONG_PTR)p + SingleListSize); Priority++; } } while (Status != STATUS_NOT_FOUND); @@ -1476,7 +1476,7 @@ ISAPNPQueryBusRelations( CurrentEntry = CurrentEntry->Flink; } - Irp->IoStatus.Information = (ULONG)Relations; + Irp->IoStatus.Information = (ULONG_PTR)Relations; return Status; } diff --git a/drivers/directx/dxapi/dxapi_driver.h b/drivers/directx/dxapi/dxapi_driver.h index 322d6d1d67f..996353c7f2d 100644 --- a/drivers/directx/dxapi/dxapi_driver.h +++ b/drivers/directx/dxapi/dxapi_driver.h @@ -1,10 +1,10 @@ /* DDK/NDK/SDK Headers */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -16,7 +16,7 @@ #include -#include +#include /* Prototypes */ VOID DxGetVersionNumber(PVOID lpvInBuffer, LPDDGETVERSIONNUMBER lpvOutBuffer); diff --git a/drivers/directx/dxg/ddhmg.c b/drivers/directx/dxg/ddhmg.c index 39e0721d339..caa5cafeb15 100644 --- a/drivers/directx/dxg/ddhmg.c +++ b/drivers/directx/dxg/ddhmg.c @@ -24,7 +24,7 @@ BOOL FASTCALL VerifyObjectOwner(PDD_ENTRY pEntry) { - DWORD Pid = (DWORD) PsGetCurrentProcessId() & 0xFFFFFFFC; + DWORD Pid = (DWORD)(DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFC; DWORD check = pEntry->ObjectOwner.ulObj & 0xFFFFFFFE; return ( (check == Pid) || (!check)); } @@ -145,7 +145,7 @@ FASTCALL DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned) { - DWORD Index = (DWORD)DdHandle & 0x1FFFFF; + DWORD Index = (DWORD)(DWORD_PTR)DdHandle & 0x1FFFFF; PDD_ENTRY pEntry = NULL; PVOID Object = NULL; diff --git a/drivers/directx/dxg/dxg_int.h b/drivers/directx/dxg/dxg_int.h index b457e6d5c3d..ccb2204a781 100644 --- a/drivers/directx/dxg/dxg_int.h +++ b/drivers/directx/dxg/dxg_int.h @@ -1,9 +1,9 @@ /* DDK/NDK/SDK Headers */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* Win32 Headers */ #define WINBASEAPI diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c index 95a5af6630b..e334ba98b00 100644 --- a/drivers/filesystems/ntfs/attrib.c +++ b/drivers/filesystems/ntfs/attrib.c @@ -88,7 +88,7 @@ FindRun (PNONRESIDENT_ATTRIBUTE NresAttr, *lcn = 0; - for (run = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset); + for (run = (PUCHAR)((ULONG_PTR)NresAttr + NresAttr->RunArrayOffset); *run != 0; run += RunLength(run)) { *lcn += RunLCN(run); @@ -248,7 +248,7 @@ NtfsDumpAttribute (PATTRIBUTE Attribute) { Name.Length = Attribute->NameLength * sizeof(WCHAR); Name.MaximumLength = Name.Length; - Name.Buffer = (PWCHAR)((ULONG)Attribute + Attribute->NameOffset); + Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset); DbgPrint("'%wZ' ", &Name); } diff --git a/drivers/input/i8042prt/keyboard.c b/drivers/input/i8042prt/keyboard.c index 3aa2b1b24b4..0550c907a29 100644 --- a/drivers/input/i8042prt/keyboard.c +++ b/drivers/input/i8042prt/keyboard.c @@ -200,7 +200,7 @@ i8042PowerWorkItem( /* Register GUID_DEVICE_SYS_BUTTON interface and report capability */ if (DeviceExtension->NewCaps != DeviceExtension->ReportedCaps) { - WaitingIrp = InterlockedExchangePointer(&DeviceExtension->PowerIrp, NULL); + WaitingIrp = InterlockedExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL); if (WaitingIrp) { /* Cancel the current power irp, as capability changed */ @@ -255,7 +255,7 @@ i8042PowerWorkItem( } /* Directly complete the IOCTL_GET_SYS_BUTTON_EVENT Irp (if any) */ - WaitingIrp = InterlockedExchangePointer(&DeviceExtension->PowerIrp, NULL); + WaitingIrp = InterlockedExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL); if (WaitingIrp) { PULONG pEvent = (PULONG)WaitingIrp->AssociatedIrp.SystemBuffer; @@ -413,7 +413,7 @@ i8042KbdDeviceControl( else { WaitingIrp = InterlockedCompareExchangePointer( - &DeviceExtension->PowerIrp, + (PVOID)&DeviceExtension->PowerIrp, Irp, NULL); /* Check if an Irp is already pending */ @@ -431,7 +431,7 @@ i8042KbdDeviceControl( PowerKey = InterlockedExchange((PLONG)&DeviceExtension->LastPowerKey, 0); if (PowerKey != 0) { - (VOID)InterlockedCompareExchangePointer(&DeviceExtension->PowerIrp, NULL, Irp); + (VOID)InterlockedCompareExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL, Irp); *(PULONG)Irp->AssociatedIrp.SystemBuffer = PowerKey; Status = STATUS_SUCCESS; Irp->IoStatus.Status = Status; diff --git a/drivers/network/dd/ne2000/include/ne2000.h b/drivers/network/dd/ne2000/include/ne2000.h index 0785c4187d2..4c4e28bdbcd 100644 --- a/drivers/network/dd/ne2000/include/ne2000.h +++ b/drivers/network/dd/ne2000/include/ne2000.h @@ -80,7 +80,7 @@ typedef struct _NIC_ADAPTER NDIS_MINIPORT_INTERRUPT Interrupt; /* I/O base address and interrupt number of adapter */ - ULONG IoBaseAddress; + ULONG_PTR IoBaseAddress; ULONG InterruptLevel; ULONG InterruptVector; BOOLEAN InterruptShared; @@ -222,24 +222,24 @@ VOID NICUpdateCounters( VOID NICReadDataAlign( PNIC_ADAPTER Adapter, PUSHORT Target, - ULONG Source, + ULONG_PTR Source, USHORT Length); VOID NICWriteDataAlign( PNIC_ADAPTER Adapter, - ULONG Target, + ULONG_PTR Target, PUSHORT Source, USHORT Length); VOID NICReadData( PNIC_ADAPTER Adapter, PUCHAR Target, - ULONG Source, + ULONG_PTR Source, USHORT Length); VOID NICWriteData( PNIC_ADAPTER Adapter, - ULONG Target, + ULONG_PTR Target, PUCHAR Source, USHORT Length); diff --git a/drivers/network/dd/ne2000/ne2000/8390.c b/drivers/network/dd/ne2000/ne2000/8390.c index c055d43f276..d7ceafba106 100644 --- a/drivers/network/dd/ne2000/ne2000/8390.c +++ b/drivers/network/dd/ne2000/ne2000/8390.c @@ -11,10 +11,10 @@ #include /* Null-terminated array of ports to probe. This is "semi-risky" (Don Becker). */ -ULONG ProbeAddressList[] = { 0x280, 0x300, 0x320, 0x340, 0x360, 0x380, 0 }; +ULONG_PTR ProbeAddressList[] = { 0x280, 0x300, 0x320, 0x340, 0x360, 0x380, 0 }; static BOOLEAN ProbeAddressForNIC( - ULONG address) + ULONG_PTR address) /* * FUNCTION: Probes an address for a NIC * ARGUMENTS: @@ -129,7 +129,7 @@ static BOOLEAN NICTestRAM( * Start at 1KB and test for every 1KB up to 64KB */ { - ULONG Base; + ULONG_PTR Base; NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); diff --git a/drivers/network/ndis/include/ndissys.h b/drivers/network/ndis/include/ndissys.h index d97f1f0ab41..10c6a26ede4 100644 --- a/drivers/network/ndis/include/ndissys.h +++ b/drivers/network/ndis/include/ndissys.h @@ -59,6 +59,13 @@ NTAPI ExGetCurrentProcessorCpuUsage( PULONG CpuUsage); +/* portability fixes */ +#ifdef _M_AMD64 +#define KfReleaseSpinLock KeReleaseSpinLock +#define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel +#define KefReleaseSpinLockFromDpcLevel KeReleaseSpinLockFromDpcLevel +#endif + #endif /* __NDISSYS_H */ /* EOF */ diff --git a/drivers/network/ndis/ndis/io.c b/drivers/network/ndis/ndis/io.c index b843997e6bd..0f809bf2890 100644 --- a/drivers/network/ndis/ndis/io.c +++ b/drivers/network/ndis/ndis/io.c @@ -106,7 +106,7 @@ NdisImmediateReadPortUchar( OUT PUCHAR Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - *Data = READ_PORT_UCHAR((PUCHAR)Port); // FIXME: What to do with WrapperConfigurationContext? + *Data = READ_PORT_UCHAR(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? } @@ -121,7 +121,7 @@ NdisImmediateReadPortUlong( OUT PULONG Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - *Data = READ_PORT_ULONG((PULONG)Port); // FIXME: What to do with WrapperConfigurationContext? + *Data = READ_PORT_ULONG(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? } @@ -136,7 +136,7 @@ NdisImmediateReadPortUshort( OUT PUSHORT Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - *Data = READ_PORT_USHORT((PUSHORT)Port); // FIXME: What to do with WrapperConfigurationContext? + *Data = READ_PORT_USHORT(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext? } @@ -151,7 +151,7 @@ NdisImmediateWritePortUchar( IN UCHAR Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - WRITE_PORT_UCHAR((PUCHAR)Port, Data); // FIXME: What to do with WrapperConfigurationContext? + WRITE_PORT_UCHAR(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? } @@ -166,7 +166,7 @@ NdisImmediateWritePortUlong( IN ULONG Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - WRITE_PORT_ULONG((PULONG)Port, Data); // FIXME: What to do with WrapperConfigurationContext? + WRITE_PORT_ULONG(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? } @@ -181,7 +181,7 @@ NdisImmediateWritePortUshort( IN USHORT Data) { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - WRITE_PORT_USHORT((PUSHORT)Port, Data); // FIXME: What to do with WrapperConfigurationContext? + WRITE_PORT_USHORT(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? } @@ -880,7 +880,7 @@ NdisMRegisterIoPortRange( if(AddressSpace) { ASSERT(TranslatedAddress.u.HighPart == 0); - *PortOffset = (PVOID) TranslatedAddress.u.LowPart; + *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart; NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset)); return NDIS_STATUS_SUCCESS; } diff --git a/drivers/network/ndis/ndis/miniport.c b/drivers/network/ndis/ndis/miniport.c index 05c750d8ebe..2a9934c355e 100644 --- a/drivers/network/ndis/ndis/miniport.c +++ b/drivers/network/ndis/ndis/miniport.c @@ -2109,6 +2109,7 @@ NdisIDeviceIoControl( PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension; PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); NDIS_STATUS Status = STATUS_NOT_SUPPORTED; + ULONG Written; Irp->IoStatus.Information = 0; @@ -2121,7 +2122,8 @@ NdisIDeviceIoControl( *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer, Stack->Parameters.DeviceIoControl.OutputBufferLength, MmGetSystemAddressForMdl(Irp->MdlAddress), - &Irp->IoStatus.Information); + &Written); + Irp->IoStatus.Information = Written; break; default: diff --git a/drivers/network/ndis/ndis/misc.c b/drivers/network/ndis/ndis/misc.c index f8b05a80849..dca3726dcba 100644 --- a/drivers/network/ndis/ndis/misc.c +++ b/drivers/network/ndis/ndis/misc.c @@ -426,7 +426,7 @@ NdisInterlockedPopEntrySList( * NDIS 5.0 */ { - return ExInterlockedPopEntrySList ( ListHead, Lock ); + return (PSINGLE_LIST_ENTRY)ExInterlockedPopEntrySList ( ListHead, Lock ); } @@ -447,7 +447,7 @@ NdisInterlockedPushEntrySList( * NDIS 5.0 */ { - return ExInterlockedPushEntrySList ( ListHead, ListEntry, Lock ); + return (PSINGLE_LIST_ENTRY)ExInterlockedPushEntrySList ( ListHead, (PSLIST_ENTRY)ListEntry, Lock ); } diff --git a/drivers/network/tcpip/datalink/lan.c b/drivers/network/tcpip/datalink/lan.c index fd0b818ac1b..890330e202d 100644 --- a/drivers/network/tcpip/datalink/lan.c +++ b/drivers/network/tcpip/datalink/lan.c @@ -684,7 +684,7 @@ VOID LANTransmit( if (Adapter->MTU < Size) { /* This is NOT a pointer. MSDN explicitly says so. */ NDIS_PER_PACKET_INFO_FROM_PACKET(NdisPacket, - TcpLargeSendPacketInfo) = (PVOID)((ULONG)Adapter->MTU); + TcpLargeSendPacketInfo) = (PVOID)((ULONG_PTR)Adapter->MTU); } TcpipAcquireSpinLock( &Adapter->Lock, &OldIrql ); diff --git a/drivers/network/tcpip/tcpip/dispatch.c b/drivers/network/tcpip/tcpip/dispatch.c index fb77376d68f..f216ed5f678 100644 --- a/drivers/network/tcpip/tcpip/dispatch.c +++ b/drivers/network/tcpip/tcpip/dispatch.c @@ -688,7 +688,7 @@ NTSTATUS DispTdiQueryInformation( AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress); Address = (PTA_IP_ADDRESS)&AddressInfo->Address; - switch ((ULONG)IrpSp->FileObject->FsContext2) { + switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { case TDI_TRANSPORT_ADDRESS_FILE: AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; @@ -732,7 +732,7 @@ NTSTATUS DispTdiQueryInformation( AddressInfo = (PTDI_CONNECTION_INFORMATION) MmGetSystemAddressForMdl(Irp->MdlAddress); - switch ((ULONG)IrpSp->FileObject->FsContext2) { + switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { case TDI_TRANSPORT_ADDRESS_FILE: AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; Endpoint = AddrFile ? AddrFile->Connection : NULL; @@ -1039,12 +1039,16 @@ NTSTATUS DispTdiSendDatagram( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) ) + { + ULONG DataUsed = 0; Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( Request.Handle.AddressHandle, DgramInfo->SendDatagramInformation, DataBuffer, BufferSize, - &Irp->IoStatus.Information); + &DataUsed); + Irp->IoStatus.Information = DataUsed; + } else { Status = STATUS_UNSUCCESSFUL; ASSERT(FALSE); @@ -1310,7 +1314,7 @@ NTSTATUS DispTdiQueryInformationEx( TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; - switch ((ULONG)IrpSp->FileObject->FsContext2) { + switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { case TDI_TRANSPORT_ADDRESS_FILE: Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; break; @@ -1485,7 +1489,7 @@ NTSTATUS DispTdiSetInformationEx( TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer; - switch ((ULONG)IrpSp->FileObject->FsContext2) { + switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { case TDI_TRANSPORT_ADDRESS_FILE: Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; break; diff --git a/drivers/serial/serenum/detect.c b/drivers/serial/serenum/detect.c index 87af5890236..8391ddbd427 100644 --- a/drivers/serial/serenum/detect.c +++ b/drivers/serial/serenum/detect.c @@ -532,7 +532,7 @@ SerenumDetectLegacyDevice( /* Fill the read buffer */ TRACE_(SERENUM, "Fill the read buffer\n"); - Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), &Count); + Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), (PVOID)&Count); if (!NT_SUCCESS(Status)) goto ByeBye; RtlInitUnicodeString(&DeviceId, L"Serenum\\Mouse"); diff --git a/drivers/serial/serial/devctrl.c b/drivers/serial/serial/devctrl.c index f37002dfebd..2f8f563d6a0 100644 --- a/drivers/serial/serial/devctrl.c +++ b/drivers/serial/serial/devctrl.c @@ -802,7 +802,7 @@ SerialDeviceControl( * as pending, it might be possible to complete the * Irp before pending it, leading to a crash! */ WaitingIrp = InterlockedCompareExchangePointer( - &DeviceExtension->WaitOnMaskIrp, + (PVOID)&DeviceExtension->WaitOnMaskIrp, Irp, NULL); diff --git a/drivers/storage/class/class2/class2.c b/drivers/storage/class/class2/class2.c index 517ddd4061e..cb8d1f7108c 100644 --- a/drivers/storage/class/class2/class2.c +++ b/drivers/storage/class/class2/class2.c @@ -1314,7 +1314,7 @@ Return Value: // of original IRP. // - nextIrpStack->Parameters.Others.Argument1 = (PVOID) irpCount; + nextIrpStack->Parameters.Others.Argument1 = (PVOID)(ULONG_PTR) irpCount; for (i = 0; i < irpCount; i++) { @@ -1502,7 +1502,7 @@ Return Value: srb, irpStack->MajorFunction, irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, - MAXIMUM_RETRIES - ((ULONG)irpStack->Parameters.Others.Argument4), + MAXIMUM_RETRIES - ((ULONG_PTR)irpStack->Parameters.Others.Argument4), &status); // @@ -1517,7 +1517,7 @@ Return Value: retry = TRUE; } - if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG)irpStack->Parameters.Others.Argument4-1))) { + if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { // // Retry request. @@ -1654,7 +1654,7 @@ Return Value: srb, irpStack->MajorFunction, irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, - MAXIMUM_RETRIES - ((ULONG)irpStack->Parameters.Others.Argument4), + MAXIMUM_RETRIES - ((ULONG_PTR)irpStack->Parameters.Others.Argument4), &status); // @@ -1669,7 +1669,7 @@ Return Value: retry = TRUE; } - if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG)irpStack->Parameters.Others.Argument4-1))) { + if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { // // Retry request. If the class driver has supplied a StartIo, diff --git a/drivers/storage/floppy/floppy.c b/drivers/storage/floppy/floppy.c index 712f8d85468..05d15983fe9 100644 --- a/drivers/storage/floppy/floppy.c +++ b/drivers/storage/floppy/floppy.c @@ -520,7 +520,7 @@ static NTSTATUS NTAPI ConfigCallback(PVOID Context, if(AddressSpace == 0) gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, FDC_PORT_BYTES, MmNonCached); else - gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)TranslatedAddress.u.LowPart; + gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)(ULONG_PTR)TranslatedAddress.QuadPart; } else if(PartialDescriptor->Type == CmResourceTypeDma) diff --git a/drivers/storage/ide/atapi/atapi.c b/drivers/storage/ide/atapi/atapi.c index ddcd417eae8..fe3c9808c95 100644 --- a/drivers/storage/ide/atapi/atapi.c +++ b/drivers/storage/ide/atapi/atapi.c @@ -2744,7 +2744,7 @@ Return Value: { PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; - ULONG nativeModeAdapterTableIndex = (ULONG)Context; + ULONG nativeModeAdapterTableIndex = (ULONG_PTR)Context; ULONG channel; PUCHAR ioSpace; BOOLEAN atapiOnly, @@ -6260,7 +6260,7 @@ Return Value: newStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, - (PVOID) i); + (PVOID)(ULONG_PTR)i); if (newStatus < statusToReturn) statusToReturn = newStatus; } diff --git a/drivers/storage/scsiport/scsiport.c b/drivers/storage/scsiport/scsiport.c index be9fc55c237..3e3fb5488e8 100644 --- a/drivers/storage/scsiport/scsiport.c +++ b/drivers/storage/scsiport/scsiport.c @@ -552,7 +552,7 @@ ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, /* i/o space */ if (AddressSpace != 0) - return((PVOID)TranslatedAddress.u.LowPart); + return((PVOID)(ULONG_PTR)TranslatedAddress.QuadPart); MappedAddress = MmMapIoSpace(TranslatedAddress, NumberOfBytes, @@ -1223,8 +1223,8 @@ CreatePortConfig: PortConfig->AccessRanges = (PVOID)(PortConfig+1); /* Align to LONGLONG */ - PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) + 7); - PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) & ~7); + PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7); + PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7); /* Copy the data */ RtlCopyMemory(PortConfig->AccessRanges, diff --git a/drivers/storage/scsiport/scsiport.pspec b/drivers/storage/scsiport/scsiport.pspec new file mode 100644 index 00000000000..65c75471c4d --- /dev/null +++ b/drivers/storage/scsiport/scsiport.pspec @@ -0,0 +1,51 @@ +#ifdef __x86_64__ +#define MAYBEFWD(x) +#else +#define MAYBEFWD(x) x +#endif + +@ cdecl ScsiDebugPrint() +@ stdcall ScsiPortCompleteRequest(ptr long long long long) +@ stdcall ScsiPortConvertPhysicalAddressToUlong(long long) +@ stdcall ScsiPortConvertUlongToPhysicalAddress(long) MAYBEFWD(NTOSKRNL.RtlConvertUlongToLargeInteger) +@ stdcall ScsiPortFlushDma(ptr) +@ stdcall ScsiPortFreeDeviceBase(ptr ptr) +@ stdcall ScsiPortGetBusData(ptr long long long ptr long) +@ stdcall ScsiPortGetDeviceBase(ptr long long long long long long) +@ stdcall ScsiPortGetLogicalUnit(ptr long long long) +@ stdcall ScsiPortGetPhysicalAddress(ptr ptr ptr long) +@ stdcall ScsiPortGetSrb(ptr long long long long) +@ stdcall ScsiPortGetUncachedExtension(ptr ptr long) +@ stdcall ScsiPortGetVirtualAddress(ptr long long) +@ stdcall ScsiPortInitialize(ptr ptr ptr ptr) +@ stdcall ScsiPortIoMapTransfer(ptr ptr long long) +@ stdcall ScsiPortLogError(ptr ptr long long long long long) +@ stdcall ScsiPortMoveMemory(ptr ptr long) +@ cdecl ScsiPortNotification() +@ stdcall ScsiPortReadPortBufferUchar(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_UCHAR) +@ stdcall ScsiPortReadPortBufferUshort(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_USHORT) +@ stdcall ScsiPortReadPortBufferUlong(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_ULONG) +@ stdcall ScsiPortReadPortUchar(ptr) MAYBEFWD(HAL.READ_PORT_UCHAR) +@ stdcall ScsiPortReadPortUshort(ptr) MAYBEFWD(HAL.READ_PORT_USHORT) +@ stdcall ScsiPortReadPortUlong(ptr) MAYBEFWD(HAL.READ_PORT_ULONG) +@ stdcall ScsiPortReadRegisterBufferUchar(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_UCHAR) +@ stdcall ScsiPortReadRegisterBufferUshort(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_USHORT) +@ stdcall ScsiPortReadRegisterBufferUlong(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_ULONG) +@ stdcall ScsiPortReadRegisterUchar(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_UCHAR) +@ stdcall ScsiPortReadRegisterUshort(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_USHORT) +@ stdcall ScsiPortReadRegisterUlong(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_ULONG) +@ stdcall ScsiPortSetBusDataByOffset(ptr long long long ptr long long) +@ stdcall ScsiPortStallExecution(long) HAL.KeStallExecutionProcessor +@ stdcall ScsiPortValidateRange(ptr long long long long long long) +@ stdcall ScsiPortWritePortBufferUchar(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_UCHAR) +@ stdcall ScsiPortWritePortBufferUshort(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_USHORT) +@ stdcall ScsiPortWritePortBufferUlong(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_ULONG) +@ stdcall ScsiPortWritePortUchar(ptr long) MAYBEFWD(HAL.WRITE_PORT_UCHAR) +@ stdcall ScsiPortWritePortUshort(ptr long) MAYBEFWD(HAL.WRITE_PORT_USHORT) +@ stdcall ScsiPortWritePortUlong(ptr long) MAYBEFWD(HAL.WRITE_PORT_ULONG) +@ stdcall ScsiPortWriteRegisterBufferUchar(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_UCHAR) +@ stdcall ScsiPortWriteRegisterBufferUshort(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_USHORT) +@ stdcall ScsiPortWriteRegisterBufferUlong(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_ULONG) +@ stdcall ScsiPortWriteRegisterUchar(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_UCHAR) +@ stdcall ScsiPortWriteRegisterUshort(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_USHORT) +@ stdcall ScsiPortWriteRegisterUlong(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_ULONG) diff --git a/drivers/storage/scsiport/scsiport.rbuild b/drivers/storage/scsiport/scsiport.rbuild index 57750f9a6b0..556d742680f 100644 --- a/drivers/storage/scsiport/scsiport.rbuild +++ b/drivers/storage/scsiport/scsiport.rbuild @@ -3,10 +3,11 @@ - + . ntoskrnl hal scsiport.c + stubs.c scsiport.rc diff --git a/drivers/storage/scsiport/scsiport.spec b/drivers/storage/scsiport/scsiport.spec deleted file mode 100644 index b779b1ee557..00000000000 --- a/drivers/storage/scsiport/scsiport.spec +++ /dev/null @@ -1,45 +0,0 @@ -@ cdecl ScsiDebugPrint() -@ stdcall ScsiPortCompleteRequest(ptr long long long long) -@ stdcall ScsiPortConvertPhysicalAddressToUlong(long long) -@ stdcall ScsiPortConvertUlongToPhysicalAddress(long) NTOSKRNL.RtlConvertUlongToLargeInteger -@ stdcall ScsiPortFlushDma(ptr) -@ stdcall ScsiPortFreeDeviceBase(ptr ptr) -@ stdcall ScsiPortGetBusData(ptr long long long ptr long) -@ stdcall ScsiPortGetDeviceBase(ptr long long long long long long) -@ stdcall ScsiPortGetLogicalUnit(ptr long long long) -@ stdcall ScsiPortGetPhysicalAddress(ptr ptr ptr long) -@ stdcall ScsiPortGetSrb(ptr long long long long) -@ stdcall ScsiPortGetUncachedExtension(ptr ptr long) -@ stdcall ScsiPortGetVirtualAddress(ptr long long) -@ stdcall ScsiPortInitialize(ptr ptr ptr ptr) -@ stdcall ScsiPortIoMapTransfer(ptr ptr long long) -@ stdcall ScsiPortLogError(ptr ptr long long long long long) -@ stdcall ScsiPortMoveMemory(ptr ptr long) -@ cdecl ScsiPortNotification() -@ stdcall ScsiPortReadPortBufferUchar(ptr ptr long) HAL.READ_PORT_BUFFER_UCHAR -@ stdcall ScsiPortReadPortBufferUshort(ptr ptr long) HAL.READ_PORT_BUFFER_USHORT -@ stdcall ScsiPortReadPortBufferUlong(ptr ptr long) HAL.READ_PORT_BUFFER_ULONG -@ stdcall ScsiPortReadPortUchar(ptr) HAL.READ_PORT_UCHAR -@ stdcall ScsiPortReadPortUshort(ptr) HAL.READ_PORT_USHORT -@ stdcall ScsiPortReadPortUlong(ptr) HAL.READ_PORT_ULONG -@ stdcall ScsiPortReadRegisterBufferUchar(ptr ptr long) NTOSKRNL.READ_REGISTER_BUFFER_UCHAR -@ stdcall ScsiPortReadRegisterBufferUshort(ptr ptr long) NTOSKRNL.READ_REGISTER_BUFFER_USHORT -@ stdcall ScsiPortReadRegisterBufferUlong(ptr ptr long) NTOSKRNL.READ_REGISTER_BUFFER_ULONG -@ stdcall ScsiPortReadRegisterUchar(ptr) NTOSKRNL.READ_REGISTER_UCHAR -@ stdcall ScsiPortReadRegisterUshort(ptr) NTOSKRNL.READ_REGISTER_USHORT -@ stdcall ScsiPortReadRegisterUlong(ptr) NTOSKRNL.READ_REGISTER_ULONG -@ stdcall ScsiPortSetBusDataByOffset(ptr long long long ptr long long) -@ stdcall ScsiPortStallExecution(long) HAL.KeStallExecutionProcessor -@ stdcall ScsiPortValidateRange(ptr long long long long long long) -@ stdcall ScsiPortWritePortBufferUchar(ptr ptr long) HAL.WRITE_PORT_BUFFER_UCHAR -@ stdcall ScsiPortWritePortBufferUshort(ptr ptr long) HAL.WRITE_PORT_BUFFER_USHORT -@ stdcall ScsiPortWritePortBufferUlong(ptr ptr long) HAL.WRITE_PORT_BUFFER_ULONG -@ stdcall ScsiPortWritePortUchar(ptr long) HAL.WRITE_PORT_UCHAR -@ stdcall ScsiPortWritePortUshort(ptr long) HAL.WRITE_PORT_USHORT -@ stdcall ScsiPortWritePortUlong(ptr long) HAL.WRITE_PORT_ULONG -@ stdcall ScsiPortWriteRegisterBufferUchar(ptr ptr long) NTOSKRNL.WRITE_REGISTER_BUFFER_UCHAR -@ stdcall ScsiPortWriteRegisterBufferUshort(ptr ptr long) NTOSKRNL.WRITE_REGISTER_BUFFER_USHORT -@ stdcall ScsiPortWriteRegisterBufferUlong(ptr ptr long) NTOSKRNL.WRITE_REGISTER_BUFFER_ULONG -@ stdcall ScsiPortWriteRegisterUchar(ptr long) NTOSKRNL.WRITE_REGISTER_UCHAR -@ stdcall ScsiPortWriteRegisterUshort(ptr long) NTOSKRNL.WRITE_REGISTER_USHORT -@ stdcall ScsiPortWriteRegisterUlong(ptr long) NTOSKRNL.WRITE_REGISTER_ULONG diff --git a/drivers/storage/scsiport/stubs.c b/drivers/storage/scsiport/stubs.c new file mode 100644 index 00000000000..478c35b4d08 --- /dev/null +++ b/drivers/storage/scsiport/stubs.c @@ -0,0 +1,246 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Storage Stack + * FILE: drivers/storage/scsiport/stubs.c + * PURPOSE: SCSI port driver + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +SCSI_PHYSICAL_ADDRESS +NTAPI +ScsiPortConvertUlongToPhysicalAddress( + IN ULONG UlongAddress) +{ + return RtlConvertUlongToLargeInteger(UlongAddress); +} + +VOID +NTAPI +ScsiPortReadPortBufferUchar( + IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +NTAPI +ScsiPortReadPortBufferUshort( + IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +NTAPI +ScsiPortReadPortBufferUlong( + IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +UCHAR +NTAPI +ScsiPortReadPortUchar( + IN PUCHAR Port) +{ + return READ_PORT_UCHAR(Port); +} + +USHORT +NTAPI +ScsiPortReadPortUshort( + IN PUSHORT Port) +{ + return READ_PORT_USHORT(Port); +} + +ULONG +NTAPI +ScsiPortReadPortUlong( + IN PULONG Port) +{ + return READ_PORT_ULONG(Port); +} + +VOID +NTAPI +ScsiPortReadRegisterBufferUchar( + IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +NTAPI +ScsiPortReadRegisterBufferUshort( + IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +NTAPI +ScsiPortReadRegisterBufferUlong( + IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +UCHAR +NTAPI +ScsiPortReadRegisterUchar( + IN PUCHAR Register) +{ + return READ_REGISTER_UCHAR(Register); +} + +USHORT +NTAPI +ScsiPortReadRegisterUshort( + IN PUSHORT Register) +{ + return READ_REGISTER_USHORT(Register); +} + +ULONG +NTAPI +ScsiPortReadRegisterUlong( + IN PULONG Register) +{ + return READ_REGISTER_ULONG(Register); +} + +VOID +NTAPI +ScsiPortWritePortBufferUchar( + IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWritePortBufferUshort( + IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWritePortBufferUlong( + IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWritePortUchar( + IN PUCHAR Port, + IN UCHAR Value) +{ + WRITE_PORT_UCHAR(Port, Value); +} + +VOID +NTAPI +ScsiPortWritePortUshort( + IN PUSHORT Port, + IN USHORT Value) +{ + WRITE_PORT_USHORT(Port, Value); +} + +VOID +NTAPI +ScsiPortWritePortUlong( + IN PULONG Port, + IN ULONG Value) +{ + WRITE_PORT_ULONG(Port, Value); +} + +VOID +NTAPI +ScsiPortWriteRegisterBufferUchar( + IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWriteRegisterBufferUshort( + IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWriteRegisterBufferUlong( + IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +VOID +NTAPI +ScsiPortWriteRegisterUchar( + IN PUCHAR Register, + IN ULONG Value) +{ + WRITE_REGISTER_UCHAR(Register, Value); +} + +VOID +NTAPI +ScsiPortWriteRegisterUshort( + IN PUSHORT Register, + IN USHORT Value) +{ + WRITE_REGISTER_USHORT(Register, Value); +} + +VOID +NTAPI +ScsiPortWriteRegisterUlong( + IN PULONG Register, + IN ULONG Value) +{ + WRITE_REGISTER_ULONG(Register, Value); +} + diff --git a/drivers/video/displays/framebuf_new/framebuf_new.rbuild b/drivers/video/displays/framebuf_new/framebuf_new.rbuild index 991954e44e2..de7c4a1d3be 100644 --- a/drivers/video/displays/framebuf_new/framebuf_new.rbuild +++ b/drivers/video/displays/framebuf_new/framebuf_new.rbuild @@ -10,10 +10,12 @@ pointer.c screen.c framebuf_new.rc - - -mrtd - -fno-builtin - -Wno-unused-variable - + + + -mrtd + -fno-builtin + -Wno-unused-variable + + driver.h diff --git a/drivers/video/displays/vga/main/enable.c b/drivers/video/displays/vga/main/enable.c index 2d1a943ee76..80d032cddfb 100644 --- a/drivers/video/displays/vga/main/enable.c +++ b/drivers/video/displays/vga/main/enable.c @@ -574,7 +574,7 @@ DrvGetModes(IN HANDLE Driver, /* next DEVMODE entry */ OutputModes--; - DM = (PDEVMODEW) ( ((ULONG)DM) + sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + DM = (PDEVMODEW) ( ((ULONG_PTR)DM) + sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); OutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); } diff --git a/drivers/video/font/bmfd/font.c b/drivers/video/font/bmfd/font.c index 4760fac40a9..3afdc4fb360 100644 --- a/drivers/video/font/bmfd/font.c +++ b/drivers/video/font/bmfd/font.c @@ -389,7 +389,7 @@ BmfdQueryFontTree( { PBMFD_FILE pfile = (PBMFD_FILE)iFile; PBMFD_FACE pface; - ULONG i, j, cjOffset, cjSize, cGlyphs, cRuns; + ULONG i, j, cjSize, cGlyphs, cRuns; CHAR ch, chFirst, ach[256]; WCHAR wc, awc[256]; PFD_GLYPHSET pGlyphSet; @@ -475,14 +475,13 @@ BmfdQueryFontTree( pwcrun[0].wcLow = awc[0]; pwcrun[0].cGlyphs = 1; pwcrun[0].phg = phglyphs; - phglyphs[0] = (HGLYPH)pface->pCharTable; + phglyphs[0] = 0; /* Walk through all supported chars */ for (i = 1, j = 0; i < cGlyphs; i++) { - /* Use pointer to glyph entry as hglyph */ - cjOffset = (ach[i] - chFirst) * pface->cjEntrySize; - phglyphs[i] = (HGLYPH)(pface->pCharTable + cjOffset); + /* Use offset to glyph entry as hglyph */ + phglyphs[i] = (ach[i] - chFirst) * pface->cjEntrySize; /* Check whether we can append the wchar to a run */ if (awc[i] == awc[i - 1] + 1) diff --git a/drivers/video/font/bmfd/glyph.c b/drivers/video/font/bmfd/glyph.c index fc88b45b710..a2ce39f157f 100644 --- a/drivers/video/font/bmfd/glyph.c +++ b/drivers/video/font/bmfd/glyph.c @@ -80,7 +80,7 @@ BmfdQueryGlyphAndBitmap( ULONG cjSize) { PBMFD_FACE pface = pfont->pface; - PGLYPHENTRY pge = (PGLYPHENTRY)hg; + PGLYPHENTRY pge = (PGLYPHENTRY)(pface->pCharTable + hg); ULONG xSrc, ySrc, cxSrc, cySrc; ULONG xDst, yDst, cxDst, cyDst; ULONG xScale, yScale; diff --git a/drivers/video/videoprt/agp.c b/drivers/video/videoprt/agp.c index ff390af0932..768e6d92f0a 100644 --- a/drivers/video/videoprt/agp.c +++ b/drivers/video/videoprt/agp.c @@ -275,7 +275,7 @@ IntAgpCommitVirtual( else /* ProcessHandle != NULL */ { /* Release some virtual memory */ - ULONG Size = Pages * PAGE_SIZE; + SIZE_T Size = Pages * PAGE_SIZE; ULONG OffsetInBytes = Offset * PAGE_SIZE; BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + OffsetInBytes); @@ -349,7 +349,7 @@ IntAgpFreeVirtual( else /* ProcessHandle != NULL */ { /* Unmap the section view */ - ULONG Size = Pages * PAGE_SIZE; + SIZE_T Size = Pages * PAGE_SIZE; ULONG OffsetInBytes = Offset * PAGE_SIZE; BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + OffsetInBytes); @@ -400,7 +400,7 @@ IntAgpReleaseVirtual( else /* ProcessHandle != NULL */ { /* Release the allocated virtual memory */ - ULONG Size = VirtualMapping->AgpMapping->NumberOfPages * PAGE_SIZE; + SIZE_T Size = VirtualMapping->AgpMapping->NumberOfPages * PAGE_SIZE; Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle, &VirtualMapping->MappedAddress, &Size, MEM_RELEASE); @@ -452,7 +452,7 @@ IntAgpReserveVirtual( else /* ProcessHandle != NULL */ { /* Reserve memory for usermode */ - ULONG Size = AgpMapping->NumberOfPages * PAGE_SIZE; + SIZE_T Size = AgpMapping->NumberOfPages * PAGE_SIZE; MappedAddress = NULL; Status = ZwAllocateVirtualMemory(ProcessHandle, &MappedAddress, 0, &Size, MEM_RESERVE, PAGE_NOACCESS); diff --git a/drivers/video/videoprt/int10.c b/drivers/video/videoprt/int10.c index 7930c87ca72..5f5458aa89f 100644 --- a/drivers/video/videoprt/int10.c +++ b/drivers/video/videoprt/int10.c @@ -24,6 +24,7 @@ /* PRIVATE FUNCTIONS **********************************************************/ +#if defined(_M_IX86) VP_STATUS NTAPI IntInt10AllocateBuffer( IN PVOID Context, @@ -190,6 +191,7 @@ IntInt10CallBios( if (NT_SUCCESS(Status)) return NO_ERROR; return ERROR_INVALID_PARAMETER; } +#endif /* PUBLIC FUNCTIONS ***********************************************************/ @@ -202,6 +204,7 @@ VideoPortInt10( IN PVOID HwDeviceExtension, IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments) { +#if defined(_M_IX86) CONTEXT BiosContext; NTSTATUS Status; PKPROCESS CallingProcess = (PKPROCESS)PsGetCurrentProcess(); @@ -243,4 +246,9 @@ VideoPortInt10( IntDetachFromCSRSS(&CallingProcess, &ApcState); if (NT_SUCCESS(Status)) return NO_ERROR; return ERROR_INVALID_PARAMETER; +#else + /* Not implemented for anything else than X86*/ + DPRINT1("Int10 not available on non-x86!\n"); + return ERROR_INVALID_FUNCTION; +#endif } diff --git a/drivers/video/videoprt/interrupt.c b/drivers/video/videoprt/interrupt.c index 54a5b9566cb..b15ebdf974c 100644 --- a/drivers/video/videoprt/interrupt.c +++ b/drivers/video/videoprt/interrupt.c @@ -110,6 +110,7 @@ VP_STATUS NTAPI VideoPortEnableInterrupt(IN PVOID HwDeviceExtension) { +#ifndef _M_AMD64 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; BOOLEAN InterruptValid; @@ -133,6 +134,11 @@ VideoPortEnableInterrupt(IN PVOID HwDeviceExtension) /* Return to caller */ return NO_ERROR; +#else + /* FIXME: Function still present? If so what to use instead of HalEnableSystemInterrupt? */ + UNIMPLEMENTED; + return ERROR_INVALID_ACCESS; +#endif } /* @@ -142,6 +148,7 @@ VP_STATUS NTAPI VideoPortDisableInterrupt(IN PVOID HwDeviceExtension) { +#ifndef _M_AMD64 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; /* Get the device extension */ @@ -158,4 +165,9 @@ VideoPortDisableInterrupt(IN PVOID HwDeviceExtension) HalDisableSystemInterrupt(DeviceExtension->InterruptVector, 0); return NO_ERROR; +#else + /* FIXME: Function still present? If so what to use instead of HalDisableSystemInterrupt? */ + UNIMPLEMENTED; + return ERROR_INVALID_ACCESS; +#endif } diff --git a/drivers/video/videoprt/resource.c b/drivers/video/videoprt/resource.c index 2ed6417c2ef..b17edb75500 100644 --- a/drivers/video/videoprt/resource.c +++ b/drivers/video/videoprt/resource.c @@ -163,7 +163,7 @@ IntVideoPortMapMemory( if (Status) *Status = NO_ERROR; - return (PVOID)TranslatedAddress.u.LowPart; + return (PVOID)(ULONG_PTR)TranslatedAddress.u.LowPart; } /* user space */ @@ -271,7 +271,7 @@ IntVideoPortUnmapMemory( Status = ZwUnmapViewOfSection(NtCurrentProcess(), MappedAddress); if (!NT_SUCCESS(Status)) { - WARN_(VIDEOPRT, "Warning: Mapping for address 0x%x not found!\n", (ULONG)MappedAddress); + WARN_(VIDEOPRT, "Warning: Mapping for address 0x%p not found!\n", MappedAddress); } } diff --git a/drivers/video/videoprt/services.c b/drivers/video/videoprt/services.c index fbf69a8aff2..5b9f3cf5036 100644 --- a/drivers/video/videoprt/services.c +++ b/drivers/video/videoprt/services.c @@ -43,6 +43,7 @@ VideoPortQueryServices( switch (ServicesType) { +#if defined(_M_IX86) case VideoPortServicesInt10: if (Interface->Version >= VIDEO_PORT_INT10_INTERFACE_VERSION_1 || Interface->Size >= sizeof(VIDEO_PORT_INT10_INTERFACE)) @@ -60,7 +61,7 @@ VideoPortQueryServices( return NO_ERROR; } break; - +#endif case VideoPortServicesAGP: if ((Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_2 && Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE_2)) || diff --git a/drivers/video/videoprt/videoprt.c b/drivers/video/videoprt/videoprt.c index 19a64f7b53c..33c6fedc7f8 100644 --- a/drivers/video/videoprt/videoprt.c +++ b/drivers/video/videoprt/videoprt.c @@ -330,7 +330,7 @@ IntVideoPortFindAdapter( { WCHAR DeviceVideoBuffer[20]; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; - ULONG Size; + SIZE_T Size; NTSTATUS Status; VIDEO_PORT_CONFIG_INFO ConfigInfo; SYSTEM_BASIC_INFORMATION SystemBasicInfo; diff --git a/drivers/wdm/audio/legacy/wdmaud/interface.h b/drivers/wdm/audio/legacy/wdmaud/interface.h index 211045cf0c9..aa5e7b25f28 100644 --- a/drivers/wdm/audio/legacy/wdmaud/interface.h +++ b/drivers/wdm/audio/legacy/wdmaud/interface.h @@ -26,7 +26,7 @@ typedef struct { KSSTREAM_HEADER Header; SOUND_DEVICE_TYPE DeviceType; - ULONG DeviceIndex; + ULONG_PTR DeviceIndex; HANDLE hDevice; ULONG DeviceCount; diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index 7ccfa08bc99..61c23d3077a 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -3135,6 +3135,9 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { ULONG64 LastExceptionFromRip; } CONTEXT; +#define PCR_MINOR_VERSION 1 +#define PCR_MAJOR_VERSION 1 + typedef struct _KPCR { _ANONYMOUS_UNION union @@ -3380,13 +3383,14 @@ ExRaiseDatatypeMisalignment(VOID); /* Hardware Abstraction Layer Functions */ +#if (NTDDI_VERSION >= NTDDI_WIN2K) + #if defined(USE_DMA_MACROS) && !defined(_NTHAL_) && (defined(_NTDDK_) || defined(_NTDRIVER_)) || defined(_WDM_INCLUDED_) +/* Nothing here */ +#else /* USE_DMA_MACROS ... */ -#else - -#if (NTDDI_VERSION >= NTDDI_WIN2K) //DECLSPEC_DEPRECATED_DDK NTHALAPI VOID @@ -3452,16 +3456,9 @@ HalAllocateAdapterChannel( IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine); -#endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ - - -#endif - +#endif /* USE_DMA_MACROS ... */ #if !defined(NO_LEGACY_DRIVERS) - -#if (NTDDI_VERSION >= NTDDI_WIN2K) - NTHALAPI NTSTATUS NTAPI @@ -3511,13 +3508,8 @@ BOOLEAN NTAPI HalMakeBeep( IN ULONG Frequency); - -#endif - #endif /* !defined(NO_LEGACY_DRIVERS) */ -#if (NTDDI_VERSION >= NTDDI_WIN2K) - NTHALAPI PADAPTER_OBJECT NTAPI @@ -3605,7 +3597,7 @@ HalExamineMBR( IN ULONG SectorSize, IN ULONG MBRTypeIdentifier, OUT PVOID *Buffer); -#endif +#endif /* (NTDDI_VERSION >= NTDDI_WINXP) */ #if (NTDDI_VERSION >= NTDDI_WIN7) @@ -3622,7 +3614,7 @@ NTAPI HalFreeHardwareCounters( IN HANDLE CounterSetHandle); -#endif +#endif /* (NTDDI_VERSION >= NTDDI_WIN7) */ #if defined(_IA64_) #if (NTDDI_VERSION >= NTDDI_WIN2K) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a8d34bcb3fc..2742d758ed8 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1694,7 +1694,7 @@ typedef enum _MM_SYSTEM_SIZE { MmLargeSystem } MM_SYSTEMSIZE; -extern PBOOLEAN Mm64BitPhysicalAddress; +extern NTKERNELAPI BOOLEAN Mm64BitPhysicalAddress; extern PVOID MmBadPointer; @@ -13297,6 +13297,8 @@ FASTCALL ExInterlockedFlushSList( IN OUT PSLIST_HEADER ListHead); +#endif /* !defined(_WIN64) */ + #if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_) NTKERNELAPI @@ -13327,12 +13329,14 @@ ExFreeToPagedLookasideList( IN OUT PPAGED_LOOKASIDE_LIST Lookaside, IN PVOID Entry); -#else +#else /* !_WIN2K_COMPAT_SLIST_USAGE */ +#if !defined(_WIN64) #define ExInterlockedPopEntrySList(_ListHead, _Lock) \ InterlockedPopEntrySList(_ListHead) #define ExInterlockedPushEntrySList(_ListHead, _ListEntry, _Lock) \ InterlockedPushEntrySList(_ListHead, _ListEntry) +#endif static __inline PVOID @@ -13369,7 +13373,6 @@ ExFreeToPagedLookasideList( #endif /* _WIN2K_COMPAT_SLIST_USAGE */ -#endif /* !defined(_WIN64) */ /* ERESOURCE_THREAD * ExGetCurrentResourceThread( @@ -14592,8 +14595,9 @@ KdChangeOption( #endif /* Hardware Abstraction Layer Functions */ -#if defined(USE_DMA_MACROS) && !defined(_NTHAL_) && (defined(_NTDDK_) || defined(_NTDRIVER_)) || defined(_WDM_INCLUDED_) +#if (NTDDI_VERSION >= NTDDI_WIN2K) +#if defined(USE_DMA_MACROS) && !defined(_NTHAL_) && (defined(_NTDDK_) || defined(_NTDRIVER_)) || defined(_WDM_INCLUDED_) FORCEINLINE PVOID @@ -14659,9 +14663,8 @@ HalGetDmaAlignment( return alignment; } - - -#endif +#endif /* USE_DMA_MACROS ... */ +#endif /* (NTDDI_VERSION >= NTDDI_WIN2K) */ #ifndef _NTTMAPI_ #define _NTTMAPI_ diff --git a/include/ndk/peb_teb.h b/include/ndk/peb_teb.h new file mode 100644 index 00000000000..ec4b2d33617 --- /dev/null +++ b/include/ndk/peb_teb.h @@ -0,0 +1,393 @@ +#define PASTE2(x,y) x##y +#define PASTE(x,y) PASTE2(x,y) + +#ifdef EXPLICIT_32BIT + #define STRUCT(x) PASTE(x,32) + #define PTR(x) ULONG +#elif defined(EXPLICIT_64BIT) + #define STRUCT(x) PASTE(x,64) + #define PTR(x) ULONG64 +#else + #define STRUCT(x) x + #define PTR(x) x +#endif + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) + #define GDI_HANDLE_BUFFER_SIZE 60 +#else + #define GDI_HANDLE_BUFFER_SIZE 34 +#endif + +#if defined(_NTDDK_INCLUDED_) || defined(_NTIFS_) +#define PPEB PPEB_RENAMED +#endif + +typedef struct STRUCT(_PEB) +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; +#if (NTDDI_VERSION >= NTDDI_WS03) + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages:1; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + BOOLEAN IsProtectedProcess:1; + BOOLEAN IsLegacyProcess:1; + BOOLEAN IsImageDynamicallyRelocated:1; + BOOLEAN SkipPatchingUser32Forwarders:1; + BOOLEAN SpareBits:3; +#else + BOOLEAN SpareBits:7; +#endif + }; + }; +#else + BOOLEAN SpareBool; +#endif + PTR(HANDLE) Mutant; + PTR(PVOID) ImageBaseAddress; + PTR(PPEB_LDR_DATA) Ldr; + PTR(struct _RTL_USER_PROCESS_PARAMETERS*) ProcessParameters; + PTR(PVOID) SubSystemData; + PTR(PVOID) ProcessHeap; + PTR(struct _RTL_CRITICAL_SECTION*) FastPebLock; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) AltThunkSListPtr; + PTR(PVOID) IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob:1; + ULONG ProcessInitializing:1; + ULONG ProcessUsingVEH:1; + ULONG ProcessUsingVCH:1; + ULONG ReservedBits0:28; + }; + }; + union + { + PTR(PVOID) KernelCallbackTable; + PTR(PVOID) UserSharedInfoPtr; + }; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID) AltThunkSListPtr; + PTR(PVOID) SparePtr2; + ULONG EnvironmentUpdateCount; + PTR(PVOID) KernelCallbackTable; +#else + PTR(PPEBLOCKROUTINE) FastPebLockRoutine; + PTR(PPEBLOCKROUTINE) FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PTR(PVOID) KernelCallbackTable; +#endif + ULONG SystemReserved[1]; + ULONG SpareUlong; // AtlThunkSListPtr32 + PTR(PPEB_FREE_BLOCK) FreeList; + ULONG TlsExpansionCounter; + PTR(PVOID) TlsBitmap; + ULONG TlsBitmapBits[2]; + PTR(PVOID) ReadOnlySharedMemoryBase; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) HotpatchInformation; +#else + PTR(PVOID) ReadOnlySharedMemoryHeap; +#endif + PTR(PVOID*) ReadOnlyStaticServerData; + PTR(PVOID) AnsiCodePageData; + PTR(PVOID) OemCodePageData; + PTR(PVOID) UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + LARGE_INTEGER CriticalSectionTimeout; + PTR(ULONG_PTR) HeapSegmentReserve; + PTR(ULONG_PTR) HeapSegmentCommit; + PTR(ULONG_PTR) HeapDeCommitTotalFreeThreshold; + PTR(ULONG_PTR) HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PTR(PVOID*) ProcessHeaps; + PTR(PVOID) GdiSharedHandleTable; + PTR(PVOID) ProcessStarterHelper; + ULONG GdiDCAttributeList; + PTR(struct _RTL_CRITICAL_SECTION*) LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + PTR(ULONG_PTR) ImageProcessAffinityMask; + ULONG GdiHandleBuffer[GDI_HANDLE_BUFFER_SIZE]; + PTR(PPOST_PROCESS_INIT_ROUTINE) PostProcessInitRoutine; + PTR(PVOID) TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + ULONG SessionId; +#if (NTDDI_VERSION >= NTDDI_WINXP) + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PTR(PVOID) pShimData; + PTR(PVOID) AppCompatInfo; + STRUCT(UNICODE_STRING) CSDVersion; + PTR(struct _ACTIVATION_CONTEXT_DATA*) ActivationContextData; + PTR(struct _ASSEMBLY_STORAGE_MAP*) ProcessAssemblyStorageMap; + PTR(struct _ACTIVATION_CONTEXT_DATA*) SystemDefaultActivationContextData; + PTR(struct _ASSEMBLY_STORAGE_MAP*) SystemAssemblyStorageMap; + PTR(ULONG_PTR) MinimumStackCommit; +#endif +#if (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID*) FlsCallback; + STRUCT(LIST_ENTRY) FlsListHead; + PTR(PVOID) FlsBitmap; + ULONG FlsBitmapBits[4]; + ULONG FlsHighIndex; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) WerRegistrationData; + PTR(PVOID) WerShipAssertPtr; +#endif +} STRUCT(PEB), *STRUCT(PPEB); + +#undef PPEB + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Mutant) == 0x08); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Ldr) == 0x18); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FastPebLock) == 0x038); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), TlsExpansionCounter) == 0x070); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), NtGlobalFlag) == 0x0BC); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), GdiSharedHandleTable) == 0x0F8); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), LoaderLock) == 0x110); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageSubsystem) == 0x128); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageProcessAffinityMask) == 0x138); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), PostProcessInitRoutine) == 0x230); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), SessionId) == 0x2C0); +#if (NTDDI_VERSION >= NTDDI_WS03) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FlsHighIndex) == 0x350); +#endif +#else +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Mutant) == 0x04); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Ldr) == 0x0C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FastPebLock) == 0x01C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), TlsExpansionCounter) == 0x03C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), NtGlobalFlag) == 0x068); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), GdiSharedHandleTable) == 0x094); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), LoaderLock) == 0x0A0); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageSubsystem) == 0x0B4); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageProcessAffinityMask) == 0x0C0); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), PostProcessInitRoutine) == 0x14C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), SessionId) == 0x1D4); +#if (NTDDI_VERSION >= NTDDI_WS03) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FlsHighIndex) == 0x22C); +#endif +#endif + +// +// GDI Batch Descriptor +// +typedef struct STRUCT(_GDI_TEB_BATCH) +{ + ULONG Offset; + PTR(HANDLE) HDC; + ULONG Buffer[0x136]; +} STRUCT(GDI_TEB_BATCH), *STRUCT(PGDI_TEB_BATCH); + +// +// Thread Environment Block (TEB) +// +typedef struct STRUCT(_TEB) +{ + STRUCT(NT_TIB) NtTib; + PTR(PVOID) EnvironmentPointer; + STRUCT(CLIENT_ID) ClientId; + PTR(PVOID) ActiveRpcHandle; + PTR(PVOID) ThreadLocalStoragePointer; + PTR(STRUCT(PPEB)) ProcessEnvironmentBlock; + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PTR(PVOID) CsrClientThread; + PTR(PVOID) Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PTR(PVOID) WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PTR(PVOID) SystemReserved1[54]; + LONG ExceptionCode; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(struct _ACTIVATION_CONTEXT_STACK*) ActivationContextStackPointer; + UCHAR SpareBytes1[0x30 - 3 * sizeof(PTR(PVOID))]; + ULONG TxFsContext; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(struct _ACTIVATION_CONTEXT_STACK*) ActivationContextStackPointer; + UCHAR SpareBytes1[0x34 - 3 * sizeof(PTR(PVOID))]; +#else + ACTIVATION_CONTEXT_STACK ActivationContextStack; + UCHAR SpareBytes1[24]; +#endif + STRUCT(GDI_TEB_BATCH) GdiTebBatch; + STRUCT(CLIENT_ID) RealClientId; + PTR(PVOID) GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PTR(PVOID) GdiThreadLocalInfo; + PTR(SIZE_T) Win32ClientInfo[62]; + PTR(PVOID) glDispatchTable[233]; + PTR(SIZE_T) glReserved1[29]; + PTR(PVOID) glReserved2; + PTR(PVOID) glSectionInfo; + PTR(PVOID) glSection; + PTR(PVOID) glTable; + PTR(PVOID) glCurrentRC; + PTR(PVOID) glContext; + NTSTATUS LastStatusValue; + STRUCT(UNICODE_STRING) StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + PTR(PVOID) DeallocationStack; + PTR(PVOID) TlsSlots[64]; + STRUCT(LIST_ENTRY) TlsLinks; + PTR(PVOID) Vdm; + PTR(PVOID) ReservedForNtRpc; + PTR(PVOID) DbgSsReserved[2]; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG HardErrorMode; +#else + ULONG HardErrorsAreDisabled; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) Instrumentation[13 - sizeof(GUID)/sizeof(PTR(PVOID))]; + GUID ActivityId; + PTR(PVOID) SubProcessTag; + PTR(PVOID) EtwLocalData; + PTR(PVOID) EtwTraceData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID) Instrumentation[14]; + PTR(PVOID) SubProcessTag; + PTR(PVOID) EtwLocalData; +#else + PTR(PVOID) Instrumentation[16]; +#endif + PTR(PVOID) WinSockData; + ULONG GdiBatchCount; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + BOOLEAN SpareBool0; + BOOLEAN SpareBool1; + BOOLEAN SpareBool2; +#else + BOOLEAN InDbgPrint; + BOOLEAN FreeStackOnTermination; + BOOLEAN HasFiberData; +#endif + UCHAR IdealProcessor; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG GuaranteedStackBytes; +#else + ULONG Spare3; +#endif + PTR(PVOID) ReservedForPerf; + PTR(PVOID) ReservedForOle; + ULONG WaitingOnLoaderLock; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) SavedPriorityState; + PTR(ULONG_PTR) SoftPatchPtr1; + PTR(ULONG_PTR) ThreadPoolData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(ULONG_PTR) SparePointer1; + PTR(ULONG_PTR) SoftPatchPtr1; + PTR(ULONG_PTR) SoftPatchPtr2; +#else + Wx86ThreadState Wx86Thread; +#endif + PTR(PVOID*) TlsExpansionSlots; +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) + PTR(PVOID) DeallocationBStore; + PTR(PVOID) BStoreLimit; +#endif + ULONG ImpersonationLocale; + ULONG IsImpersonating; + PTR(PVOID) NlsCache; + PTR(PVOID) pShimData; + ULONG HeapVirtualAffinity; + PTR(HANDLE) CurrentTransactionHandle; + PTR(PTEB_ACTIVE_FRAME) ActiveFrame; +#if (NTDDI_VERSION >= NTDDI_WS03) + PVOID FlsData; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PVOID PreferredLangauges; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + union + { + struct + { + USHORT SpareCrossTebFlags:16; + }; + USHORT CrossTebFlags; + }; + union + { + struct + { + USHORT DbgSafeThunkCall:1; + USHORT DbgInDebugPrint:1; + USHORT DbgHasFiberData:1; + USHORT DbgSkipThreadAttach:1; + USHORT DbgWerInShipAssertCode:1; + USHORT DbgIssuedInitialBp:1; + USHORT DbgClonedThread:1; + USHORT SpareSameTebBits:9; + }; + USHORT SameTebFlags; + }; + PTR(PVOID) TxnScopeEntercallback; + PTR(PVOID) TxnScopeExitCAllback; + PTR(PVOID) TxnScopeContext; + ULONG LockCount; + ULONG ProcessRundown; + ULONG64 LastSwitchTime; + ULONG64 TotalSwitchOutTime; + LARGE_INTEGER WaitReasonBitMap; +#else + BOOLEAN SafeThunkCall; + BOOLEAN BooleanSpare[3]; +#endif +} STRUCT(TEB), *STRUCT(PTEB); + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), EnvironmentPointer) == 0x038); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ExceptionCode) == 0x2C0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiTebBatch) == 0x2F0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), LastStatusValue) == 0x1250); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), Vdm) == 0x1690); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), HardErrorMode) == 0x16B0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiBatchCount) == 0x1740); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), IdealProcessor) == 0x1747); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), WaitingOnLoaderLock) == 0x1760); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), TlsExpansionSlots) == 0x1780); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), WaitingOnLoaderLock) == 0x1760); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ActiveFrame) == 0x17C0); +#else +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), EnvironmentPointer) == 0x01C); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ExceptionCode) == 0x1A4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiTebBatch) == 0x1D4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), LastStatusValue) == 0xBF4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), Vdm) == 0xF18); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiBatchCount) == 0xF70); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), TlsExpansionSlots) == 0xF94); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ActiveFrame) == 0xFB0); +#endif + +#undef PTR +#undef STRUCT +#undef PASTE +#undef PASTE2 +#undef GDI_HANDLE_BUFFER_SIZE diff --git a/include/ndk/pstypes.h b/include/ndk/pstypes.h index 6cc8d37efb8..43b44680960 100644 --- a/include/ndk/pstypes.h +++ b/include/ndk/pstypes.h @@ -26,6 +26,7 @@ Author: #include #include #include +#include #ifndef NTOS_MODE_USER #include #include @@ -616,137 +617,6 @@ typedef struct _INITIAL_PEB HANDLE Mutant; } INITIAL_PEB, *PINITIAL_PEB; -// -// Process Environment Block (PEB) -// -typedef struct _PEB -{ - BOOLEAN InheritedAddressSpace; - BOOLEAN ReadImageFileExecOptions; - BOOLEAN BeingDebugged; -#if (NTDDI_VERSION >= NTDDI_WS03) - struct - { - BOOLEAN ImageUsesLargePages:1; - #if (NTDDI_VERSION >= NTDDI_LONGHORN) - BOOLEAN IsProtectedProcess:1; - BOOLEAN IsLegacyProcess:1; - BOOLEAN SpareBits:5; - #else - BOOLEAN SpareBits:7; - #endif - }; -#else - BOOLEAN SpareBool; -#endif - HANDLE Mutant; - PVOID ImageBaseAddress; - PPEB_LDR_DATA Ldr; - struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters; - PVOID SubSystemData; - PVOID ProcessHeap; -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - struct _RTL_CRITICAL_SECTION *FastPebLock; - PVOID AltThunkSListPtr; - PVOID IFEOKey; - ULONG Spare; - union - { - PVOID* KernelCallbackTable; - PVOID UserSharedInfoPtr; - }; - ULONG SystemReserved[1]; - ULONG SpareUlong; -#else - PVOID FastPebLock; - PPEBLOCKROUTINE FastPebLockRoutine; - PPEBLOCKROUTINE FastPebUnlockRoutine; - ULONG EnvironmentUpdateCount; - PVOID* KernelCallbackTable; - PVOID EventLogSection; - PVOID EventLog; -#endif - PPEB_FREE_BLOCK FreeList; - ULONG TlsExpansionCounter; - PVOID TlsBitmap; - ULONG TlsBitmapBits[0x2]; - PVOID ReadOnlySharedMemoryBase; - PVOID ReadOnlySharedMemoryHeap; - PVOID* ReadOnlyStaticServerData; - PVOID AnsiCodePageData; - PVOID OemCodePageData; - PVOID UnicodeCaseTableData; - ULONG NumberOfProcessors; - ULONG NtGlobalFlag; - LARGE_INTEGER CriticalSectionTimeout; - ULONG HeapSegmentReserve; - ULONG HeapSegmentCommit; - ULONG HeapDeCommitTotalFreeThreshold; - ULONG HeapDeCommitFreeBlockThreshold; - ULONG NumberOfHeaps; - ULONG MaximumNumberOfHeaps; - PVOID* ProcessHeaps; - PVOID GdiSharedHandleTable; - PVOID ProcessStarterHelper; - ULONG GdiDCAttributeList; -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - struct _RTL_CRITICAL_SECTION *LoaderLock; -#else - PVOID LoaderLock; -#endif - ULONG OSMajorVersion; - ULONG OSMinorVersion; - USHORT OSBuildNumber; - USHORT OSCSDVersion; - ULONG OSPlatformId; - ULONG ImageSubSystem; - ULONG ImageSubSystemMajorVersion; - ULONG ImageSubSystemMinorVersion; - ULONG ImageProcessAffinityMask; - ULONG GdiHandleBuffer[0x22]; - PPOST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; - struct _RTL_BITMAP *TlsExpansionBitmap; - ULONG TlsExpansionBitmapBits[0x20]; - ULONG SessionId; -#if (NTDDI_VERSION >= NTDDI_WINXP) - ULARGE_INTEGER AppCompatFlags; - ULARGE_INTEGER AppCompatFlagsUser; - PVOID pShimData; - PVOID AppCompatInfo; - UNICODE_STRING CSDVersion; - struct _ACTIVATION_CONTEXT_DATA *ActivationContextData; - struct _ASSEMBLY_STORAGE_MAP *ProcessAssemblyStorageMap; - struct _ACTIVATION_CONTEXT_DATA *SystemDefaultActivationContextData; - struct _ASSEMBLY_STORAGE_MAP *SystemAssemblyStorageMap; - ULONG MinimumStackCommit; -#endif -#if (NTDDI_VERSION >= NTDDI_WS03) - PVOID *FlsCallback; - LIST_ENTRY FlsListHead; - struct _RTL_BITMAP *FlsBitmap; - ULONG FlsBitmapBits[4]; - ULONG FlsHighIndex; -#endif -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - PVOID WerRegistrationData; - PVOID WerShipAssertPtr; -#endif -} PEB; - -#if !defined(_NTDDK_) && !defined(_NTIFS_INCLUDED_) -typedef PEB *PPEB; -#endif - -// -// GDI Batch Descriptor -// -typedef struct _GDI_TEB_BATCH -{ - ULONG Offset; - HANDLE HDC; - ULONG Buffer[0x136]; -} GDI_TEB_BATCH, *PGDI_TEB_BATCH; - // // Initial TEB // @@ -775,146 +645,50 @@ typedef struct _TEB_ACTIVE_FRAME PTEB_ACTIVE_FRAME_CONTEXT Context; } TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; +typedef struct _CLIENT_ID32 +{ + ULONG UniqueProcess; + ULONG UniqueThread; +} CLIENT_ID32, *PCLIENT_ID32; + +typedef struct _CLIENT_ID64 +{ + ULONG64 UniqueProcess; + ULONG64 UniqueThread; +} CLIENT_ID64, *PCLIENT_ID64; + +#if (NTDDI_VERSION < NTDDI_WS03) +typedef struct _Wx86ThreadState +{ + PULONG CallBx86Eip; + PVOID DeallocationCpu; + BOOLEAN UseKnownWx86Dll; + CHAR OleStubInvoked; +} Wx86ThreadState, *PWx86ThreadState; +#endif + + // +// Process Environment Block (PEB) // Thread Environment Block (TEB) // -typedef struct _TEB -{ - NT_TIB Tib; - PVOID EnvironmentPointer; - CLIENT_ID ClientId; - PVOID ActiveRpcHandle; - PVOID ThreadLocalStoragePointer; - struct _PEB *ProcessEnvironmentBlock; - ULONG LastErrorValue; - ULONG CountOfOwnedCriticalSections; - PVOID CsrClientThread; - struct _W32THREAD* Win32ThreadInfo; - ULONG User32Reserved[0x1A]; - ULONG UserReserved[5]; - PVOID WOW32Reserved; - LCID CurrentLocale; - ULONG FpSoftwareStatusRegister; - PVOID SystemReserved1[0x36]; - LONG ExceptionCode; - struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; +#include "peb_teb.h" + #ifdef _WIN64 - UCHAR SpareBytes1[24]; -#else - UCHAR SpareBytes1[0x24]; +// +// Explicit 32 bit PEB/TEB +// +#define EXPLICIT_32BIT +#include "peb_teb.h" +#undef EXPLICIT_32BIT + +// +// Explicit 64 bit PEB/TEB +// +#define EXPLICIT_64BIT +#include "peb_teb.h" +#undef EXPLICIT_64BIT #endif - ULONG TxFsContext; - GDI_TEB_BATCH GdiTebBatch; - CLIENT_ID RealClientId; - PVOID GdiCachedProcessHandle; - ULONG GdiClientPID; - ULONG GdiClientTID; - PVOID GdiThreadLocalInfo; - SIZE_T Win32ClientInfo[62]; - PVOID glDispatchTable[0xE9]; - SIZE_T glReserved1[0x1D]; - PVOID glReserved2; - PVOID glSectionInfo; - PVOID glSection; - PVOID glTable; - PVOID glCurrentRC; - PVOID glContext; - NTSTATUS LastStatusValue; - UNICODE_STRING StaticUnicodeString; - WCHAR StaticUnicodeBuffer[0x105]; - PVOID DeallocationStack; - PVOID TlsSlots[0x40]; - LIST_ENTRY TlsLinks; - PVOID Vdm; - PVOID ReservedForNtRpc; - PVOID DbgSsReserved[0x2]; - ULONG HardErrorDisabled; -#ifdef _WIN64 - PVOID Instrumentation[11]; -#else - PVOID Instrumentation[9]; -#endif - GUID ActivityId; - PVOID SubProcessTag; - PVOID EtwTraceData; -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - PVOID EtwLocalData; -#endif - PVOID WinSockData; - ULONG GdiBatchCount; -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - BOOLEAN SpareBool0; - BOOLEAN SpareBool1; - BOOLEAN SpareBool2; -#else - BOOLEAN InDbgPrint; - BOOLEAN FreeStackOnTermination; - BOOLEAN HasFiberData; -#endif - UCHAR IdealProcessor; - ULONG GuaranteedStackBytes; - PVOID ReservedForPerf; - PVOID ReservedForOle; - ULONG WaitingOnLoaderLock; -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - PVOID SavedPriorityState; -#else - ULONG SparePointer1; -#endif - ULONG SoftPatchPtr1; - ULONG SoftPatchPtr2; - PVOID *TlsExpansionSlots; - ULONG ImpersonationLocale; - ULONG IsImpersonating; - PVOID NlsCache; - PVOID pShimData; - ULONG HeapVirualAffinity; - PVOID CurrentTransactionHandle; - PTEB_ACTIVE_FRAME ActiveFrame; -#if (NTDDI_VERSION >= NTDDI_WS03) - PVOID FlsData; -#endif -#if (NTDDI_VERSION >= NTDDI_LONGHORN) - PVOID PreferredLangauges; - PVOID UserPrefLanguages; - PVOID MergedPrefLanguages; - ULONG MuiImpersonation; - union - { - struct - { - USHORT SpareCrossTebFlags:16; - }; - USHORT CrossTebFlags; - }; - union - { - struct - { - USHORT DbgSafeThunkCall:1; - USHORT DbgInDebugPrint:1; - USHORT DbgHasFiberData:1; - USHORT DbgSkipThreadAttach:1; - USHORT DbgWerInShipAssertCode:1; - USHORT DbgIssuedInitialBp:1; - USHORT DbgClonedThread:1; - USHORT SpareSameTebBits:9; - }; - USHORT SameTebFlags; - }; - PVOID TxnScopeEntercallback; - PVOID TxnScopeExitCAllback; - PVOID TxnScopeContext; - ULONG LockCount; - ULONG ProcessRundown; - ULONGLONG LastSwitchTime; - ULONGLONG TotalSwitchOutTime; - LARGE_INTEGER WaitReasonBitMap; -#else - UCHAR SafeThunkCall; - UCHAR BooleanSpare[3]; -#endif -} TEB, *PTEB; #ifdef NTOS_MODE_USER diff --git a/include/ndk/rtlfuncs.h b/include/ndk/rtlfuncs.h index e7365ee0fd0..18aa4749ad4 100644 --- a/include/ndk/rtlfuncs.h +++ b/include/ndk/rtlfuncs.h @@ -25,6 +25,7 @@ Author: #include #include #include +#include #include #include "in6addr.h" #include "inaddr.h" diff --git a/include/ndk/rtltypes.h b/include/ndk/rtltypes.h index 70aa3ed5bdc..aa6d8607fb6 100644 --- a/include/ndk/rtltypes.h +++ b/include/ndk/rtltypes.h @@ -23,7 +23,8 @@ Author: // Dependencies // #include -#include +#include +#include // // Maximum Atom Length @@ -760,6 +761,7 @@ typedef struct _RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED } RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, *PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED; +#if (NTDDI_VERSION >= NTDDI_WS03) typedef struct _ACTIVATION_CONTEXT_STACK { PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame; @@ -769,6 +771,15 @@ typedef struct _ACTIVATION_CONTEXT_STACK ULONG StackId; } ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; +#else +typedef struct _ACTIVATION_CONTEXT_STACK +{ + ULONG Flags; + ULONG NextCookieSequenceNumber; + PVOID ActiveFrame; + LIST_ENTRY FrameListCache; +} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; +#endif #endif diff --git a/include/ndk/umtypes.h b/include/ndk/umtypes.h index 7e02d7664b8..95c1c8f2f53 100644 --- a/include/ndk/umtypes.h +++ b/include/ndk/umtypes.h @@ -151,6 +151,8 @@ typedef struct _CSTRING CONST CHAR *Buffer; } CSTRING, *PCSTRING; +#endif + typedef struct _STRING32 { USHORT Length; USHORT MaximumLength; @@ -167,7 +169,6 @@ typedef struct _STRING64 { UNICODE_STRING64, *PUNICODE_STRING64, ANSI_STRING64, *PANSI_STRING64; -#endif typedef struct _OBJECT_ATTRIBUTES { diff --git a/include/psdk/cfgmgr32.h b/include/psdk/cfgmgr32.h index 85f0a25fd98..f0d40aa541d 100644 --- a/include/psdk/cfgmgr32.h +++ b/include/psdk/cfgmgr32.h @@ -543,11 +543,6 @@ typedef struct BusNumber_Resource_s { BUSNUMBER_RANGE BusNumber_Data[ANYSIZE_ARRAY]; } BUSNUMBER_RESOURCE, *PBUSNUMBER_RESOURCE; -typedef struct IRQ_Resource_s { - IRQ_DES IRQ_Header; - IRQ_RANGE IRQ_Data[ANYSIZE_ARRAY]; -} IRQ_RESOURCE, *PIRQ_RESOURCE; - #define CM_HWPI_NOT_DOCKABLE 0x00000000 #define CM_HWPI_UNDOCKED 0x00000001 #define CM_HWPI_DOCKED 0x00000002 diff --git a/include/psdk/urlmon.idl b/include/psdk/urlmon.idl index d16a3b5d7ec..2ab3b2b021d 100644 --- a/include/psdk/urlmon.idl +++ b/include/psdk/urlmon.idl @@ -24,6 +24,7 @@ import "msxml.idl"; cpp_quote("#ifdef WINE_NO_UNICODE_MACROS") cpp_quote("#undef GetUserName") +cpp_quote("#undef SetPort") cpp_quote("#endif") interface IInternetProtocolSink; @@ -1716,6 +1717,105 @@ interface IUriContainer : IUnknown HRESULT GetIUri([out] IUri **ppIUri); } +/***************************************************************************** + * IUriBuilder interface + */ +[ + local, + object, + uuid(4221b2e1-8955-46c0-bd5b-de9897565de7), + pointer_default(unique) +] +interface IUriBuilder: IUnknown +{ + HRESULT CreateUriSimple( + [in] DWORD dwAllowEncodingPropertyMask, + [in] DWORD_PTR dwReserved, + [out] IUri **ppIUri); + + HRESULT CreateUri( + [in] DWORD dwCreateFlags, + [in] DWORD dwAllowEncodingPropertyMask, + [in] DWORD_PTR dwReserved, + [out] IUri **ppIUri); + + HRESULT CreateUriWithFlags( + [in] DWORD dwCreateFlags, + [in] DWORD dwUriBuilderFlags, + [in] DWORD dwAllowEncodingPropertyMask, + [in] DWORD_PTR dwReserved, + [out] IUri **ppIUri); + + HRESULT GetIUri( + [out] IUri **ppIUri); + + HRESULT SetIUri( + [in, unique] IUri *pIUri); + + HRESULT GetFragment( + [out] DWORD *pcchFragment, + [out] LPCWSTR *ppwzFragment); + + HRESULT GetHost( + [out] DWORD *pcchHost, + [out] LPCWSTR *ppwzHost); + + HRESULT GetPassword( + [out] DWORD *pcchPassword, + [out] LPCWSTR *ppwzPassword); + + HRESULT GetPath( + [out] DWORD *pcchPath, + [out] LPCWSTR *ppwzPath); + + HRESULT GetPort( + [out] BOOL *pfHasPort, + [out] DWORD *pdwPort); + + HRESULT GetQuery( + [out] DWORD *pcchQuery, + [out] LPCWSTR *ppwzQuery); + + HRESULT GetSchemeName( + [out] DWORD *pcchSchemeName, + [out] LPCWSTR *ppwzSchemeName); + + HRESULT GetUserName( + [out] DWORD *pcchUserName, + [out] LPCWSTR *ppwzUserName); + + HRESULT SetFragment( + [in] LPCWSTR pwzNewValue); + + HRESULT SetHost( + [in] LPCWSTR pwzNewValue); + + HRESULT SetPassword( + [in] LPCWSTR pwzNewValue); + + HRESULT SetPath( + [in] LPCWSTR pwzNewValue); + + HRESULT SetPort( + [in] BOOL fHasPort, + [in] DWORD dwNewValue); + + HRESULT SetQuery( + [in] LPCWSTR pwzNewValue); + + HRESULT SetSchemeName( + [in] LPCWSTR pwzNewValue); + + HRESULT SetUserName( + [in] LPCWSTR pwzNewValue); + + HRESULT RemoveProperties( + [in] DWORD dwPropertyMask); + + HRESULT HasBeenModified( + [out] BOOL *pfModified); +}; + /***************************************************************************** * IInternetProtocolEx interface */ diff --git a/include/psdk/wincodec.idl b/include/psdk/wincodec.idl index 8e8dfe60475..1bcb2cd1bad 100644 --- a/include/psdk/wincodec.idl +++ b/include/psdk/wincodec.idl @@ -72,6 +72,14 @@ typedef enum WICBitmapEncoderCacheOption { WICBITMAPENCODERCACHEOPTION_FORCE_DWORD = CODEC_FORCE_DWORD } WICBitmapEncoderCacheOption; +typedef enum WICBitmapInterpolationMode { + WICBitmapInterpolationModeNearestNeighbor = 0x00000000, + WICBitmapInterpolationModeLinear = 0x00000001, + WICBitmapInterpolationModeCubic = 0x00000002, + WICBitmapInterpolationModeFaint = 0x00000003, + WICBITMAPINTERPOLATIONMODE_FORCE_DWORD = CODEC_FORCE_DWORD +} WICBitmapInterpolationMode; + typedef enum WICBitmapPaletteType { WICBitmapPaletteTypeCustom = 0x00000000, WICBitmapPaletteTypeMedianCut = 0x00000001, @@ -169,9 +177,7 @@ cpp_quote("#define WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT 0x88982f80") cpp_quote("#define WINCODEC_ERR_UNSUPPORTEDOPERATION 0x88982f81") cpp_quote("#define WINCODEC_ERR_INSUFFICIENTBUFFER 0x88982f8c") -interface IWICBitmap; interface IWICPalette; -interface IWICBitmapScaler; interface IWICBitmapClipper; interface IWICBitmapFlipRotator; interface IWICColorContext; @@ -207,6 +213,46 @@ interface IWICBitmapSource : IUnknown [out, size_is(cbBufferSize)] BYTE *pbBuffer); } +[ + object, + uuid(00000123-a8f2-4877-ba0a-fd2b6645fb94) +] +interface IWICBitmapLock : IUnknown +{ + HRESULT GetSize( + [out] UINT *pWidth, + [out] UINT *pHeight); + + HRESULT GetStride( + [out] UINT *pcbStride); + + HRESULT GetDataPointer( + [out] UINT *pcbBufferSize, + [out, size_is(,*pcbBufferSize)] BYTE **ppbData); + + HRESULT GetPixelFormat( + [out] WICPixelFormatGUID *pPixelFormat); +} + +[ + object, + uuid(00000121-a8f2-4877-ba0a-fd2b6645fb94) +] +interface IWICBitmap : IWICBitmapSource +{ + HRESULT Lock( + [in] const WICRect *prcLock, + [in] DWORD flags, + [out] IWICBitmapLock **ppILock); + + HRESULT SetPalette( + [in] IWICPalette *pIPalette); + + HRESULT SetResolution( + [in] double dpiX, + [in] double dpiY); +} + [ object, uuid(00000040-a8f2-4877-ba0a-fd2b6645fb94) @@ -586,6 +632,19 @@ interface IWICStream : IStream [in] ULARGE_INTEGER ulMaxSize); } +[ + object, + uuid(00000302-a8f2-4877-ba0a-fd2b6645fb94) +] +interface IWICBitmapScaler : IWICBitmapSource +{ + HRESULT Initialize( + [in] IWICBitmapSource *pISource, + [in] UINT uiWidth, + [in] UINT uiHeight, + [in] WICBitmapInterpolationMode mode); +} + cpp_quote("DEFINE_GUID(CLSID_WICImagingFactory, 0xcacaf262,0x9370,0x4615,0xa1,0x3b,0x9f,0x55,0x39,0xda,0x4c,0x0a);") [ diff --git a/include/psdk/wincrypt.h b/include/psdk/wincrypt.h index af79c64240d..3f7f4ed6e5b 100644 --- a/include/psdk/wincrypt.h +++ b/include/psdk/wincrypt.h @@ -1339,14 +1339,18 @@ typedef struct _CRYPT_URL_INFO { DWORD *rgcGroupEntry; } CRYPT_URL_INFO, *PCRYPT_URL_INFO; -#define URL_OID_CERTIFICATE_ISSUER ((LPCSTR)1) -#define URL_OID_CERTIFICATE_CRL_DIST_POINT ((LPCSTR)2) -#define URL_OID_CTL_ISSUER ((LPCSTR)3) -#define URL_OID_CTL_NEXT_UPDATE ((LPCSTR)4) -#define URL_OID_CRL_ISSUER ((LPCSTR)5) -#define URL_OID_CERTIFICATE_FRESHEST_CRL ((LPCSTR)6) -#define URL_OID_CRL_FRESHEST_CRL ((LPCSTR)7) -#define URL_OID_CROSS_CERT_DIST_POINT ((LPCSTR)8) +#define URL_OID_CERTIFICATE_ISSUER ((LPCSTR)1) +#define URL_OID_CERTIFICATE_CRL_DIST_POINT ((LPCSTR)2) +#define URL_OID_CTL_ISSUER ((LPCSTR)3) +#define URL_OID_CTL_NEXT_UPDATE ((LPCSTR)4) +#define URL_OID_CRL_ISSUER ((LPCSTR)5) +#define URL_OID_CERTIFICATE_FRESHEST_CRL ((LPCSTR)6) +#define URL_OID_CRL_FRESHEST_CRL ((LPCSTR)7) +#define URL_OID_CROSS_CERT_DIST_POINT ((LPCSTR)8) +#define URL_OID_CERTIFICATE_OCSP ((LPCSTR)9) +#define URL_OID_CERTIFICATE_OCSP_AND_CRL_DIST_POINT ((LPCSTR)10) +#define URL_OID_CERTIFICATE_CRL_DIST_POINT_AND_OCSP ((LPCSTR)11) +#define URL_OID_CROSS_CERT_SUBJECT_INFO_ACCESS ((LPCSTR)12) #define URL_OID_GET_OBJECT_URL_FUNC "UrlDllGetObjectUrl" @@ -2778,6 +2782,9 @@ typedef struct _CTL_FIND_SUBJECT_PARA #define szOID_RSA_MD5RSA "1.2.840.113549.1.1.4" #define szOID_RSA_SHA1RSA "1.2.840.113549.1.1.5" #define szOID_RSA_SET0AEP_RSA "1.2.840.113549.1.1.6" +#define szOID_RSA_SHA256RSA "1.2.840.113549.1.1.11" +#define szOID_RSA_SHA384RSA "1.2.840.113549.1.1.12" +#define szOID_RSA_SHA512RSA "1.2.840.113549.1.1.13" #define szOID_RSA_DH "1.2.840.113549.1.3.1" #define szOID_RSA_data "1.2.840.113549.1.7.1" #define szOID_RSA_signedData "1.2.840.113549.1.7.2" diff --git a/include/reactos/win32k/ntuser.h b/include/reactos/win32k/ntuser.h index 8e59d26b4cc..53a8f6a3311 100644 --- a/include/reactos/win32k/ntuser.h +++ b/include/reactos/win32k/ntuser.h @@ -2977,7 +2977,7 @@ BOOL NTAPI NtUserTranslateMessage( LPMSG lpMsg, - HKL dwhkl ); + UINT flags ); BOOL NTAPI @@ -3279,8 +3279,8 @@ typedef struct tagROSMENUITEMINFO HBITMAP hbmpItem; /* ----------- Extra ----------- */ RECT Rect; /* Item area (relative to menu window) */ - UINT XTab; /* X position of text after Tab */ - LPWSTR Text; /* Copy of the text pointer in MenuItem->Text */ + UINT dxTab; /* X position of text after Tab */ + LPWSTR lpstr; /* Copy of the text pointer in MenuItem->Text */ } ROSMENUITEMINFO, *PROSMENUITEMINFO; BOOL diff --git a/include/reactos/wine/config.h b/include/reactos/wine/config.h index b677544aa1b..406b5fb895d 100644 --- a/include/reactos/wine/config.h +++ b/include/reactos/wine/config.h @@ -979,17 +979,28 @@ #define YYTEXT_POINTER 1 /* Define to a macro to output a .cfi assembly pseudo-op */ -#define __ASM_CFI(x) +#define __ASM_CFI(str) str + +/* Define to a macro to define an assembly function */ +#define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t.globl _" #name suffix "\n\t.def _" #name suffix "; .scl 2; .type 32; .endef\n_" #name suffix ":\n\t.cfi_startproc\n\t" code "\n\t.cfi_endproc"); /* Define to a macro to generate an assembly function directive */ #define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef" +/* Define to a macro to generate an assembly function with C calling + convention */ +#define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code) + /* Define to a macro to generate an assembly name from a C symbol */ #define __ASM_NAME(name) "_" name /* Define to a macro to generate an stdcall suffix */ #define __ASM_STDCALL(args) "@" #args +/* Define to a macro to generate an assembly function with stdcall calling + convention */ +#define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(name,__ASM_STDCALL(args),code) + /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ diff --git a/include/reactos/wine/port.h b/include/reactos/wine/port.h index 3b1b1c06d3c..6b293173ec2 100644 --- a/include/reactos/wine/port.h +++ b/include/reactos/wine/port.h @@ -148,29 +148,6 @@ struct statfs; #endif -/* Macros to define assembler functions somewhat portably */ - -#if defined(__GNUC__) && !defined(__INTERIX) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(__APPLE__) -# define __ASM_GLOBAL_FUNC(name,code) \ - __asm__( ".text\n\t" \ - ".align 4\n\t" \ - ".globl " __ASM_NAME(#name) "\n\t" \ - __ASM_FUNC(#name) "\n" \ - __ASM_NAME(#name) ":\n\t" \ - code \ - "\n\t.previous" ); -#else /* defined(__GNUC__) && !defined(__MINGW32__) && !defined(__APPLE__) */ -# define __ASM_GLOBAL_FUNC(name,code) \ - void __asm_dummy_##name(void) { \ - asm( ".align 4\n\t" \ - ".globl " __ASM_NAME(#name) "\n\t" \ - __ASM_FUNC(#name) "\n" \ - __ASM_NAME(#name) ":\n\t" \ - code ); \ - } -#endif /* __GNUC__ */ - - /* Constructor functions */ #ifdef __GNUC__ diff --git a/lib/sdk/crt/math/i386/pow_asm.s b/lib/sdk/crt/math/i386/pow_asm.s index 6b722fef068..0b79aa5883e 100644 --- a/lib/sdk/crt/math/i386/pow_asm.s +++ b/lib/sdk/crt/math/i386/pow_asm.s @@ -1,121 +1,368 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Run-Time Library - * FILE: lib/rtl/i386/pow.S - * PROGRAMER: Alex Ionescu (alex@relsoft.net) - * - * Copyright (C) 2002 Michael Ringgaard. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. +/* ix87 specific implementation of pow function. + Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES// LOSS OF USE, DATA, OR PROFITS// OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -.globl _pow - - /* DATA ********************************************************************/ + The GNU C 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. -fzero: - .long 0 // Floating point zero - .long 0 // Floating point zero + The GNU C 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. -.intel_syntax noprefix + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ -/* FUNCTIONS ***************************************************************/ +/* Reacros modifications */ +#define ALIGNARG(log2) log2 +#define ASM_TYPE_DIRECTIVE(name,typearg) +#define ASM_SIZE_DIRECTIVE(name) +#define cfi_adjust_cfa_offset(x) +#define ENTRY(x) +#define END(x) +.global _pow + .text + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(infinity,@object) +inf_zero: +infinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f + ASM_SIZE_DIRECTIVE(infinity) + ASM_TYPE_DIRECTIVE(zero,@object) +zero: .double 0.0 + ASM_SIZE_DIRECTIVE(zero) + ASM_TYPE_DIRECTIVE(minf_mzero,@object) +minf_mzero: +minfinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff +mzero: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + ASM_SIZE_DIRECTIVE(minf_mzero) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + ASM_TYPE_DIRECTIVE(p63,@object) +p63: .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43 + ASM_SIZE_DIRECTIVE(p63) + +#ifdef PIC +#define MO(op) op##@GOTOFF(%ecx) +#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f) +#else +#define MO(op) op +#define MOX(op,x,f) op(,x,f) +#endif + + .text _pow: - push ebp - mov ebp,esp - sub esp,12 // Allocate temporary space - push edi // Save register edi - push eax // Save register eax - mov dword ptr [ebp-12],0 // Set negation flag to zero - fld qword ptr [ebp+16] // Load real from stack - fld qword ptr [ebp+8] // Load real from stack - mov edi,offset flat:fzero // Point to real zero - fcom qword ptr [edi] // Compare x with zero - fstsw ax // Get the FPU status word - mov al,ah // Move condition flags to AL - lahf // Load Flags into AH - and al, 0b01000101 // Isolate C0, C2 and C3 - and ah, 0b10111010 // Turn off CF, PF and ZF - or ah,al // Set new CF, PF and ZF - sahf // Store AH into Flags - jb __fpow1 // Re-direct if x < 0 - ja __fpow2 // Re-direct if x > 0 - fxch // Swap st, st(1) - fcom qword ptr [edi] // Compare y with zero - fxch // Restore x as top of stack - fstsw ax // Get the FPU status word - mov al,ah // Move condition flags to AL - lahf // Load Flags into AH - and al, 0b01000101 // Isolate C0, C2 and C3 - and ah, 0b10111010 // Turn off CF, PF and ZF - or ah,al // Set new CF, PF and ZF - sahf // Store AH into Flags - jmp __fpow2 // Re-direct -__fpow1: fxch // Put y on top of stack - fld st // Duplicate y as st(1) - frndint // Round to integer - fxch // Put y on top of stack - fcomp // y = int(y) ? - fstsw ax // Get the FPU status word - mov al,ah // Move condition flags to AL - lahf // Load Flags into AH - and al, 0b01000101 // Isolate C0, C2 and C3 - and ah, 0b10111010 // Turn off CF, PF and ZF - or ah,al // Set new CF, PF and ZF - sahf // Store AH into Flags - jne __fpow4 // Proceed if y = int(y) - fist dword ptr [ebp-12] // Store y as integer - and dword ptr [ebp-12],1 // Set bit if y is odd - fxch // Put x on top of stack - fabs // x = |x| -__fpow2: fldln2 // Load log base e of 2 - fxch st(1) // Exchange st, st(1) - fyl2x // Compute the natural log(x) - fmulp // Compute y * ln(x) - fldl2e // Load log base 2(e) - fmulp st(1),st // Multiply x * log base 2(e) - fst st(1) // Push result - frndint // Round to integer - fsub st(1),st // Subtract - fxch // Exchange st, st(1) - f2xm1 // Compute 2 to the (x - 1) - fld1 // Load real number 1 - faddp // 2 to the x - fscale // Scale by power of 2 - fstp st(1) // Set new stack top and pop - test dword ptr [ebp-12],1 // Negation required ? - jz __fpow3 // No, re-direct - fchs // Negate the result -__fpow3: fstp qword ptr [ebp-8] // Save (double)pow(x, y) - fld qword ptr [ebp-8] // Load (double)pow(x, y) -__fpow4: pop eax // Restore register eax - pop edi // Restore register edi - mov esp,ebp // Deallocate temporary space - pop ebp - ret +ENTRY(__ieee754_pow) + fldl 12(%esp) // y + fxam + +#ifdef PIC + LOAD_PIC_REG (cx) +#endif + + fnstsw + movb %ah, %dl + andb $0x45, %ah + cmpb $0x40, %ah // is y == 0 ? + je 11f + + cmpb $0x05, %ah // is y == inf ? + je 12f + + cmpb $0x01, %ah // is y == NaN ? + je 30f + + fldl 4(%esp) // x : y + + subl $8,%esp + cfi_adjust_cfa_offset (8) + + fxam + fnstsw + movb %ah, %dh + andb $0x45, %ah + cmpb $0x40, %ah + je 20f // x is 0 + + cmpb $0x05, %ah + je 15f // x is inf + + fxch // y : x + + /* fistpll raises invalid exception for |y| >= 1L<<63. */ + fld %st // y : y : x + fabs // |y| : y : x + fcompl MO(p63) // y : x + fnstsw + sahf + jnc 2f + + /* First see whether `y' is a natural number. In this case we + can use a more precise algorithm. */ + fld %st // y : y : x + fistpll (%esp) // y : x + fildll (%esp) // int(y) : y : x + fucomp %st(1) // y : x + fnstsw + sahf + jne 2f + + /* OK, we have an integer value for y. */ + popl %eax + cfi_adjust_cfa_offset (-4) + popl %edx + cfi_adjust_cfa_offset (-4) + orl $0, %edx + fstp %st(0) // x + jns 4f // y >= 0, jump + fdivrl MO(one) // 1/x (now referred to as x) + negl %eax + adcl $0, %edx + negl %edx +4: fldl MO(one) // 1 : x + fxch + +6: shrdl $1, %edx, %eax + jnc 5f + fxch + fmul %st(1) // x : ST*x + fxch +5: fmul %st(0), %st // x*x : ST*x + shrl $1, %edx + movl %eax, %ecx + orl %edx, %ecx + jnz 6b + fstp %st(0) // ST*x + ret + + /* y is NAN */ +30: fldl 4(%esp) // x : y + fldl MO(one) // 1.0 : x : y + fucomp %st(1) // x : y + fnstsw + sahf + je 31f + fxch // y : x +31: fstp %st(1) + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) +2: /* y is a real number. */ + fxch // x : y + fldl MO(one) // 1.0 : x : y + fldl MO(limit) // 0.29 : 1.0 : x : y + fld %st(2) // x : 0.29 : 1.0 : x : y + fsub %st(2) // x-1 : 0.29 : 1.0 : x : y + fabs // |x-1| : 0.29 : 1.0 : x : y + fucompp // 1.0 : x : y + fnstsw + fxch // x : 1.0 : y + sahf + ja 7f + fsub %st(1) // x-1 : 1.0 : y + fyl2xp1 // log2(x) : y + jmp 8f + +7: fyl2x // log2(x) : y +8: fmul %st(1) // y*log2(x) : y + fst %st(1) // y*log2(x) : y*log2(x) + frndint // int(y*log2(x)) : y*log2(x) + fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x)) + fxch // fract(y*log2(x)) : int(y*log2(x)) + f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x)) + faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x)) + fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x)) + addl $8, %esp + cfi_adjust_cfa_offset (-8) + fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x)) + ret + + + // pow(x,0) = 1 + .align ALIGNARG(4) +11: fstp %st(0) // pop y + fldl MO(one) + ret + + // y == inf + .align ALIGNARG(4) +12: fstp %st(0) // pop y + fldl MO(one) // 1 + fldl 4(%esp) // x : 1 + fabs // abs(x) : 1 + fucompp // < 1, == 1, or > 1 + fnstsw + andb $0x45, %ah + cmpb $0x45, %ah + je 13f // jump if x is NaN + + cmpb $0x40, %ah + je 14f // jump if |x| == 1 + + shlb $1, %ah + xorb %ah, %dl + andl $2, %edx + fldl MOX(inf_zero, %edx, 4) + ret + + .align ALIGNARG(4) +14: fldl MO(one) + ret + + .align ALIGNARG(4) +13: fldl 4(%esp) // load x == NaN + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) + // x is inf +15: fstp %st(0) // y + testb $2, %dh + jz 16f // jump if x == +inf + + // We must find out whether y is an odd integer. + fld %st // y : y + fistpll (%esp) // y + fildll (%esp) // int(y) : y + fucompp // + fnstsw + sahf + jne 17f + + // OK, the value is an integer, but is the number of bits small + // enough so that all are coming from the mantissa? + popl %eax + cfi_adjust_cfa_offset (-4) + popl %edx + cfi_adjust_cfa_offset (-4) + andb $1, %al + jz 18f // jump if not odd + movl %edx, %eax + orl %edx, %edx + jns 155f + negl %eax +155: cmpl $0x00200000, %eax + ja 18f // does not fit in mantissa bits + // It's an odd integer. + shrl $31, %edx + fldl MOX(minf_mzero, %edx, 8) + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) +16: fcompl MO(zero) + addl $8, %esp + cfi_adjust_cfa_offset (-8) + fnstsw + shrl $5, %eax + andl $8, %eax + fldl MOX(inf_zero, %eax, 1) + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) +17: shll $30, %edx // sign bit for y in right position + addl $8, %esp + cfi_adjust_cfa_offset (-8) +18: shrl $31, %edx + fldl MOX(inf_zero, %edx, 8) + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) + // x is 0 +20: fstp %st(0) // y + testb $2, %dl + jz 21f // y > 0 + + // x is 0 and y is < 0. We must find out whether y is an odd integer. + testb $2, %dh + jz 25f + + fld %st // y : y + fistpll (%esp) // y + fildll (%esp) // int(y) : y + fucompp // + fnstsw + sahf + jne 26f + + // OK, the value is an integer, but is the number of bits small + // enough so that all are coming from the mantissa? + popl %eax + cfi_adjust_cfa_offset (-4) + popl %edx + cfi_adjust_cfa_offset (-4) + andb $1, %al + jz 27f // jump if not odd + cmpl $0xffe00000, %edx + jbe 27f // does not fit in mantissa bits + // It's an odd integer. + // Raise divide-by-zero exception and get minus infinity value. + fldl MO(one) + fdivl MO(zero) + fchs + ret + + cfi_adjust_cfa_offset (8) +25: fstp %st(0) +26: addl $8, %esp + cfi_adjust_cfa_offset (-8) +27: // Raise divide-by-zero exception and get infinity value. + fldl MO(one) + fdivl MO(zero) + ret + + cfi_adjust_cfa_offset (8) + .align ALIGNARG(4) + // x is 0 and y is > 0. We must find out whether y is an odd integer. +21: testb $2, %dh + jz 22f + + fld %st // y : y + fistpll (%esp) // y + fildll (%esp) // int(y) : y + fucompp // + fnstsw + sahf + jne 23f + + // OK, the value is an integer, but is the number of bits small + // enough so that all are coming from the mantissa? + popl %eax + cfi_adjust_cfa_offset (-4) + popl %edx + cfi_adjust_cfa_offset (-4) + andb $1, %al + jz 24f // jump if not odd + cmpl $0xffe00000, %edx + jae 24f // does not fit in mantissa bits + // It's an odd integer. + fldl MO(mzero) + ret + + cfi_adjust_cfa_offset (8) +22: fstp %st(0) +23: addl $8, %esp // Don't use 2 x pop + cfi_adjust_cfa_offset (-8) +24: fldl MO(zero) + ret + +END(__ieee754_pow) + + diff --git a/media/doc/README.WINE b/media/doc/README.WINE index a588c563353..828e413dbc1 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -22,7 +22,7 @@ When porting a new DLL from Wine to ReactOS, please do the following steps The following build tools are shared with Wine. reactos/tools/unicode # Synced to Wine-20081105 (~Wine-1.1.7) -reactos/tools/widl # Synced to Wine-1_1_39 +reactos/tools/widl # Synced to Wine-1_1_41 reactos/tools/winebuild # Synced to Wine-1_1_13 reactos/tools/wmc # Synced to Wine-20081105 (~Wine-1.1.7) reactos/tools/wpp # Synced to Wine-20081105 (~Wine-1.1.7) @@ -137,7 +137,7 @@ reactos/dll/win32/pstorec # Autosync reactos/dll/win32/query # Autosync reactos/dll/win32/rasapi32 # Autosync reactos/dll/win32/resutils # Autosync -reactos/dll/win32/riched20 # Autosync ?? +reactos/dll/win32/riched20 # Autosync reactos/dll/win32/riched32 # Autosync reactos/dll/win32/rpcrt4 # Synced to Wine-0_9_55 reactos/dll/win32/rsabase # Autosync diff --git a/media/inf/battery.inf b/media/inf/battery.inf index 33a8fb887a2..70583c10f03 100644 Binary files a/media/inf/battery.inf and b/media/inf/battery.inf differ diff --git a/media/inf/cpu.inf b/media/inf/cpu.inf index 12416a0d2b6..7f5dc35d4bb 100644 Binary files a/media/inf/cpu.inf and b/media/inf/cpu.inf differ diff --git a/media/inf/inf.rbuild b/media/inf/inf.rbuild index 44ea108fd6e..34d024bee2b 100644 --- a/media/inf/inf.rbuild +++ b/media/inf/inf.rbuild @@ -5,6 +5,7 @@ audio.inf battery.inf cdrom.inf + cpu.inf display.inf fdc.inf font.inf @@ -23,6 +24,7 @@ ports.inf scsi.inf syssetup.inf + usb.inf usbport.inf usbstor.inf xboxdisp.inf diff --git a/ntoskrnl/dbgk/dbgkutil.c b/ntoskrnl/dbgk/dbgkutil.c index 0d5d5713c09..2937d35c4cb 100644 --- a/ntoskrnl/dbgk/dbgkutil.c +++ b/ntoskrnl/dbgk/dbgkutil.c @@ -243,10 +243,10 @@ DbgkCreateThread(IN PETHREAD Thread, wcsncpy(Teb->StaticUnicodeBuffer, L"ntdll.dll", sizeof(Teb->StaticUnicodeBuffer) / sizeof(WCHAR)); - Teb->Tib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer; + Teb->NtTib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer; /* Return it in the debug event as well */ - LoadDll->NamePointer = &Teb->Tib.ArbitraryUserPointer; + LoadDll->NamePointer = &Teb->NtTib.ArbitraryUserPointer; } /* Get a handle */ diff --git a/ntoskrnl/include/internal/i386/ke.h b/ntoskrnl/include/internal/i386/ke.h index ebe474890ea..701688ead1f 100644 --- a/ntoskrnl/include/internal/i386/ke.h +++ b/ntoskrnl/include/internal/i386/ke.h @@ -397,9 +397,9 @@ Ki386HandleOpcodeV86( IN PKTRAP_FRAME TrapFrame ); +DECLSPEC_NORETURN VOID FASTCALL -DECLSPEC_NORETURN KiEoiHelper( IN PKTRAP_FRAME TrapFrame ); @@ -416,9 +416,9 @@ KiExitV86Mode( IN PKTRAP_FRAME TrapFrame ); +DECLSPEC_NORETURN VOID NTAPI -DECLSPEC_NORETURN KiDispatchExceptionFromTrapFrame( IN NTSTATUS Code, IN ULONG_PTR Address, @@ -620,6 +620,7 @@ KiSystemCallTrampoline(IN PVOID Handler, * later to function like this as well. * */ +#ifdef __GNUC__ __asm__ __volatile__ ( "subl %1, %%esp\n" @@ -635,7 +636,23 @@ KiSystemCallTrampoline(IN PVOID Handler, "r"(Handler) : "%esp", "%esi", "%edi" ); - +#elif defined(_MSC_VER) + __asm + { + mov ecx, StackBytes + mov edx, Arguments + sub esp, ecx + mov edi, esp + mov esi, edx + shr ecx, 2 + rep movsd + call Handler + mov Result, eax + } +#else +#error Unknown Compiler +#endif + return Result; } @@ -702,6 +719,7 @@ KiConvertToGuiThread(VOID) * on its merry way. * */ +#ifdef __GNUC__ __asm__ __volatile__ ( "movl %%ebp, %1\n" @@ -714,7 +732,20 @@ KiConvertToGuiThread(VOID) : : "%esp", "%ecx", "%edx", "memory" ); - +#elif defined(_MSC_VER) + NTSTATUS NTAPI PsConvertToGuiThread(VOID); + __asm + { + mov StackFrame, ebp + sub StackFrame, esp + call PsConvertToGuiThread + add StackFrame, esp + mov ebp, StackFrame + mov Result, eax + } +#else +#error Unknown Compiler +#endif return Result; } @@ -726,7 +757,8 @@ FORCEINLINE KiSwitchToBootStack(IN ULONG_PTR InitialStack) { /* We have to switch to a new stack before continuing kernel initialization */ - __asm__ __volatile__ +#ifdef __GNUC__ + __asm__ ( "movl %0, %%esp\n" "subl %1, %%esp\n" @@ -738,6 +770,19 @@ KiSwitchToBootStack(IN ULONG_PTR InitialStack) "i"(CR0_EM | CR0_TS | CR0_MP) : "%esp" ); +#elif defined(_MSC_VER) + VOID NTAPI KiSystemStartupBootStack(VOID); + __asm + { + mov ecx, InitialStack + mov esp, ecx + sub esp, (NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH) + push (CR0_EM | CR0_TS | CR0_MP) + jmp KiSystemStartupBootStack + } +#else +#error Unknown Compiler +#endif } // diff --git a/ntoskrnl/include/internal/ke.h b/ntoskrnl/include/internal/ke.h index b1752aff4da..c7aa3038e8e 100644 --- a/ntoskrnl/include/internal/ke.h +++ b/ntoskrnl/include/internal/ke.h @@ -1092,9 +1092,9 @@ KiIdleLoop( VOID ); +DECLSPEC_NORETURN VOID FASTCALL -DECLSPEC_NORETURN KiSystemFatalException( IN ULONG ExceptionCode, IN PKTRAP_FRAME TrapFrame diff --git a/ntoskrnl/include/internal/trap_x.h b/ntoskrnl/include/internal/trap_x.h index 93c5d1fc6c0..3da69917d70 100644 --- a/ntoskrnl/include/internal/trap_x.h +++ b/ntoskrnl/include/internal/trap_x.h @@ -192,17 +192,17 @@ KiExitSystemCallDebugChecks(IN ULONG SystemCall, // // Generic Exit Routine // -VOID FASTCALL DECLSPEC_NORETURN KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame); -VOID FASTCALL DECLSPEC_NORETURN KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame); -VOID FASTCALL DECLSPEC_NORETURN KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame); -VOID FASTCALL DECLSPEC_NORETURN KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame); -VOID FASTCALL DECLSPEC_NORETURN KiTrapReturn(IN PKTRAP_FRAME TrapFrame); -VOID FASTCALL DECLSPEC_NORETURN KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame); +DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame); typedef VOID (FASTCALL -*PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame) DECLSPEC_NORETURN; +*PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame); extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler; diff --git a/ntoskrnl/io/iomgr/drvrlist.c b/ntoskrnl/io/iomgr/drvrlist.c index ecc9980db46..e15aab2a2cd 100644 --- a/ntoskrnl/io/iomgr/drvrlist.c +++ b/ntoskrnl/io/iomgr/drvrlist.c @@ -414,8 +414,20 @@ static INIT_FUNCTION NTSTATUS IopLoadDriver(PSERVICE Service) { NTSTATUS Status = STATUS_UNSUCCESSFUL; + PUNICODE_STRING ImagePath = &Service->ImagePath; + PWCHAR ImageName; + UNICODE_STRING ImageNameU; + + ImageName = wcsrchr(ImagePath->Buffer, L'\\'); + if (!ImageName) + ImageName = ImagePath->Buffer; + else + ImageName++; + + RtlInitUnicodeString(&ImageNameU, ImageName); + + IopDisplayLoadingMessage(&ImageNameU); - IopDisplayLoadingMessage(&Service->ServiceName); Status = ZwLoadDriver(&Service->RegistryPath); IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE); if (!NT_SUCCESS(Status)) diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c index e6346378566..9cd6347e957 100644 --- a/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -1847,6 +1847,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, PUNICODE_STRING Service; UNICODE_STRING ClassGUID; NTSTATUS Status; + DEVICE_CAPABILITIES DeviceCaps; DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context); @@ -1920,9 +1921,22 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, if (Service->Buffer == NULL) { - IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps)) && + DeviceCaps.RawDeviceOK) + { + DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName); - if (ClassGUID.Length != 0) + DeviceNode->ServiceName.Length = 0; + DeviceNode->ServiceName.MaximumLength = ParentDeviceNode->ServiceName.MaximumLength; + DeviceNode->ServiceName.Buffer = ExAllocatePool(PagedPool, DeviceNode->ServiceName.MaximumLength); + if (!DeviceNode->ServiceName.Buffer) + return STATUS_SUCCESS; + + RtlCopyUnicodeString(&DeviceNode->ServiceName, &ParentDeviceNode->ServiceName); + + IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER); + } + else if (ClassGUID.Length != 0) { /* Device has a ClassGUID value, but no Service value. * Suppose it is using the NULL driver, so state the @@ -1930,6 +1944,10 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode, DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath); IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); } + else + { + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + } return STATUS_SUCCESS; } diff --git a/ntoskrnl/ke/i386/usercall.c b/ntoskrnl/ke/i386/usercall.c index a07a0550e01..07ce4442df4 100644 --- a/ntoskrnl/ke/i386/usercall.c +++ b/ntoskrnl/ke/i386/usercall.c @@ -169,7 +169,7 @@ KeUserModeCallback(IN ULONG RoutineIndex, /* Save the exception list */ Teb = KeGetCurrentThread()->Teb; - ExceptionList = Teb->Tib.ExceptionList; + ExceptionList = Teb->NtTib.ExceptionList; /* Jump to user mode */ *UserEsp = NewStack; @@ -177,7 +177,7 @@ KeUserModeCallback(IN ULONG RoutineIndex, if (CallbackStatus != STATUS_CALLBACK_POP_STACK) { /* Only restore the exception list if we didn't crash in ring 3 */ - Teb->Tib.ExceptionList = ExceptionList; + Teb->NtTib.ExceptionList = ExceptionList; CallbackStatus = STATUS_SUCCESS; } else diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index e12ad48fe59..24bd11a2586 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -517,9 +517,9 @@ MmCreatePeb(IN PEPROCESS Process, // // Write subsystem data // - Peb->ImageSubSystem = NtHeaders->OptionalHeader.Subsystem; - Peb->ImageSubSystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion; - Peb->ImageSubSystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion; + Peb->ImageSubsystem = NtHeaders->OptionalHeader.Subsystem; + Peb->ImageSubsystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion; + Peb->ImageSubsystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion; // // Check for version data @@ -635,13 +635,13 @@ MmCreateTeb(IN PEPROCESS Process, // // Set TIB Data // - Teb->Tib.ExceptionList = EXCEPTION_CHAIN_END; - Teb->Tib.Self = (PNT_TIB)Teb; + Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END; + Teb->NtTib.Self = (PNT_TIB)Teb; // // Identify this as an OS/2 V3.0 ("Cruiser") TIB // - Teb->Tib.Version = 30 << 8; + Teb->NtTib.Version = 30 << 8; // // Set TEB Data @@ -660,8 +660,8 @@ MmCreateTeb(IN PEPROCESS Process, // // Use initial TEB values // - Teb->Tib.StackBase = InitialTeb->StackBase; - Teb->Tib.StackLimit = InitialTeb->StackLimit; + Teb->NtTib.StackBase = InitialTeb->StackBase; + Teb->NtTib.StackLimit = InitialTeb->StackLimit; Teb->DeallocationStack = InitialTeb->AllocatedStackBase; } else @@ -669,8 +669,8 @@ MmCreateTeb(IN PEPROCESS Process, // // Use grandparent TEB values // - Teb->Tib.StackBase = InitialTeb->PreviousStackBase; - Teb->Tib.StackLimit = InitialTeb->PreviousStackLimit; + Teb->NtTib.StackBase = InitialTeb->PreviousStackBase; + Teb->NtTib.StackLimit = InitialTeb->PreviousStackLimit; } // diff --git a/ntoskrnl/mm/mminit.c b/ntoskrnl/mm/mminit.c index 6a3492415c0..8a9fd4297c3 100644 --- a/ntoskrnl/mm/mminit.c +++ b/ntoskrnl/mm/mminit.c @@ -48,7 +48,7 @@ MemType[] = "LoaderXIPRom " }; -PBOOLEAN Mm64BitPhysicalAddress = FALSE; +BOOLEAN Mm64BitPhysicalAddress = FALSE; ULONG MmReadClusterSize; // // 0 | 1 is on/off paging, 2 is undocumented diff --git a/ntoskrnl/po/power.c b/ntoskrnl/po/power.c index 96a211b5680..e8d37b855fd 100644 --- a/ntoskrnl/po/power.c +++ b/ntoskrnl/po/power.c @@ -47,10 +47,11 @@ PopRequestPowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject, RequestPowerItem->PowerState, RequestPowerItem->Context, &Irp->IoStatus); - - ExFreePool(&Irp->IoStatus); + ExFreePool(Context); + IoFreeIrp(Irp); + return STATUS_SUCCESS; } @@ -137,7 +138,7 @@ PoInitSystem(IN ULONG BootPhase) { /* Registry power button notification */ IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, - 0, /* The registry has not been initialized yet */ + PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVICE_SYS_BUTTON, IopRootDeviceNode-> PhysicalDeviceObject->DriverObject, @@ -358,7 +359,6 @@ PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT TopDeviceObject; PIO_STACK_LOCATION Stack; PIRP Irp; - PIO_STATUS_BLOCK IoStatusBlock; PREQUEST_POWER_ITEM RequestPowerItem; NTSTATUS Status; @@ -370,27 +370,19 @@ PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject, RequestPowerItem = ExAllocatePool(NonPagedPool, sizeof(REQUEST_POWER_ITEM)); if (!RequestPowerItem) return STATUS_INSUFFICIENT_RESOURCES; - IoStatusBlock = ExAllocatePool(NonPagedPool, sizeof(IO_STATUS_BLOCK)); - if (!IoStatusBlock) - { - ExFreePool(RequestPowerItem); - return STATUS_INSUFFICIENT_RESOURCES; - } /* Always call the top of the device stack */ TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, - TopDeviceObject, - NULL, - 0, - NULL, - NULL, - IoStatusBlock); + Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_POWER, + TopDeviceObject, + NULL, + 0, + NULL, + NULL); if (!Irp) { ExFreePool(RequestPowerItem); - ExFreePool(IoStatusBlock); return STATUS_INSUFFICIENT_RESOURCES; } @@ -404,7 +396,10 @@ PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject, if (MinorFunction == IRP_MN_WAIT_WAKE) Stack->Parameters.WaitWake.PowerState = PowerState.SystemState; else - Stack->Parameters.WaitWake.PowerState = PowerState.DeviceState; + { + Stack->Parameters.Power.Type = DevicePowerState; + Stack->Parameters.Power.State = PowerState; + } RequestPowerItem->CompletionRoutine = CompletionFunction; RequestPowerItem->PowerState = PowerState; diff --git a/ntoskrnl/rtl/libsupp.c b/ntoskrnl/rtl/libsupp.c index ae87fc53d32..27f78952c72 100644 --- a/ntoskrnl/rtl/libsupp.c +++ b/ntoskrnl/rtl/libsupp.c @@ -340,8 +340,8 @@ RtlWalkFrameChain(OUT PVOID *Callers, } /* Get the stack limits */ - StackBegin = (ULONG_PTR)Teb->Tib.StackLimit; - StackEnd = (ULONG_PTR)Teb->Tib.StackBase; + StackBegin = (ULONG_PTR)Teb->NtTib.StackLimit; + StackEnd = (ULONG_PTR)Teb->NtTib.StackBase; #ifdef _M_IX86 Stack = TrapFrame->Ebp; #elif defined(_M_PPC) diff --git a/ntoskrnl/se/semgr.c b/ntoskrnl/se/semgr.c index 8ed056becb8..38b1274970c 100644 --- a/ntoskrnl/se/semgr.c +++ b/ntoskrnl/se/semgr.c @@ -704,6 +704,27 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_SUCCESS; } + /* Protect probe in SEH */ + _SEH2_TRY + { + /* Probe all pointers */ + ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG)); + ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG)); + ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG)); + ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG)); + ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + + /* Check for unmapped access rights */ + if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)) + return STATUS_GENERIC_NOT_MAPPED; + /* Reference the token */ Status = ObReferenceObjectByHandle(TokenHandle, TOKEN_QUERY, @@ -722,7 +743,15 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, { DPRINT1("No impersonation token\n"); ObDereferenceObject(Token); - return STATUS_ACCESS_DENIED; + return STATUS_NO_IMPERSONATION_TOKEN; + } + + /* Check the impersonation level */ + if (Token->ImpersonationLevel < SecurityIdentification) + { + DPRINT1("Impersonation level < SecurityIdentification\n"); + ObDereferenceObject(Token); + return STATUS_BAD_IMPERSONATION_LEVEL; } /* Set up the subject context, and lock it */ diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c index c27d7f8c40a..8f73312fde4 100644 --- a/ntoskrnl/se/token.c +++ b/ntoskrnl/se/token.c @@ -1347,6 +1347,14 @@ NtQueryInformationToken(IN HANDLE TokenHandle, PSECURITY_IMPERSONATION_LEVEL sil = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation; DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n"); + + /* Fail if the token is not an impersonation token */ + if (Token->TokenType != TokenImpersonation) + { + Status = STATUS_INVALID_INFO_CLASS; + break; + } + RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL); _SEH2_TRY @@ -2187,7 +2195,7 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle, { PETHREAD Thread, NewThread; HANDLE hToken; - PTOKEN Token, NewToken, PrimaryToken; + PTOKEN Token, NewToken = NULL, PrimaryToken; BOOLEAN CopyOnOpen, EffectiveOnly; SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; SE_IMPERSONATION_STATE ImpersonationState; @@ -2313,9 +2321,9 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle, } if (NewToken) ObDereferenceObject(NewToken); - + if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread); - + if(NT_SUCCESS(Status)) { _SEH2_TRY diff --git a/subsystems/win32/win32k/eng/surface.c b/subsystems/win32/win32k/eng/surface.c index 464e7d0c3c1..5a85d1ac1b6 100644 --- a/subsystems/win32/win32k/eng/surface.c +++ b/subsystems/win32/win32k/eng/surface.c @@ -624,7 +624,6 @@ SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo, else { /* Compressed surfaces don't have scanlines! */ - ASSERT(FALSE); // Should not get here on ENGDDI pso->lDelta = 0; pso->cjBits = BitmapInfo->Size; diff --git a/subsystems/win32/win32k/include/menu.h b/subsystems/win32/win32k/include/menu.h index a9ad71eb3a2..94d7106baa3 100644 --- a/subsystems/win32/win32k/include/menu.h +++ b/subsystems/win32/win32k/include/menu.h @@ -23,7 +23,7 @@ typedef struct _MENU_ITEM UNICODE_STRING Text; HBITMAP hbmpItem; RECTL Rect; - UINT XTab; + UINT dxTab; } MENU_ITEM, *PMENU_ITEM; typedef struct _MENU_OBJECT diff --git a/subsystems/win32/win32k/include/msgqueue.h b/subsystems/win32/win32k/include/msgqueue.h index eadc3ab1ecf..5752481c9d4 100644 --- a/subsystems/win32/win32k/include/msgqueue.h +++ b/subsystems/win32/win32k/include/msgqueue.h @@ -187,7 +187,7 @@ co_IntSendMessageTimeout(HWND hWnd, LRESULT FASTCALL IntDispatchMessage(MSG* Msg); BOOL FASTCALL -IntTranslateKbdMessage(LPMSG lpMsg, HKL dwhkl); +IntTranslateKbdMessage(LPMSG lpMsg, UINT flags); VOID FASTCALL co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/subsystems/win32/win32k/ntuser/keyboard.c b/subsystems/win32/win32k/ntuser/keyboard.c index 443919cbb99..0c935a478e0 100644 --- a/subsystems/win32/win32k/ntuser/keyboard.c +++ b/subsystems/win32/win32k/ntuser/keyboard.c @@ -419,7 +419,7 @@ CLEANUP: BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, - HKL dwhkl) + UINT flags) { PTHREADINFO pti; static INT dead_char = 0; diff --git a/subsystems/win32/win32k/ntuser/menu.c b/subsystems/win32/win32k/ntuser/menu.c index f030481a636..9bdbe026cf8 100644 --- a/subsystems/win32/win32k/ntuser/menu.c +++ b/subsystems/win32/win32k/ntuser/menu.c @@ -690,8 +690,8 @@ IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */ if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { lpmii->Rect = MenuItem->Rect; - lpmii->XTab = MenuItem->XTab; - lpmii->Text = MenuItem->Text.Buffer; + lpmii->dxTab = MenuItem->dxTab; + lpmii->lpstr = MenuItem->Text.Buffer; // Use DesktopHeap! } return TRUE; @@ -842,8 +842,8 @@ IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINF if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize) { MenuItem->Rect = lpmii->Rect; - MenuItem->XTab = lpmii->XTab; - lpmii->Text = MenuItem->Text.Buffer; /* Send back new allocated string or zero */ + MenuItem->dxTab = lpmii->dxTab; + lpmii->lpstr = MenuItem->Text.Buffer; /* Use DesktopHeap! Send back new allocated string or zero */ } return TRUE; @@ -1002,8 +1002,8 @@ IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax) mii.hbmpUnchecked = CurItem->hbmpUnchecked; mii.hSubMenu = CurItem->hSubMenu; mii.Rect = CurItem->Rect; - mii.XTab = CurItem->XTab; - mii.Text = CurItem->Text.Buffer; + mii.dxTab = CurItem->dxTab; + mii.lpstr = CurItem->Text.Buffer; // Use DesktopHeap! Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO)); if (! NT_SUCCESS(Status)) diff --git a/subsystems/win32/win32k/ntuser/message.c b/subsystems/win32/win32k/ntuser/message.c index e7265c06220..1b244b0e038 100644 --- a/subsystems/win32/win32k/ntuser/message.c +++ b/subsystems/win32/win32k/ntuser/message.c @@ -2285,7 +2285,7 @@ NtUserDispatchMessage(PMSG UnsafeMsgInfo) BOOL APIENTRY NtUserTranslateMessage(LPMSG lpMsg, - HKL dwhkl) + UINT flags) { NTSTATUS Status; MSG SafeMsg; @@ -2301,7 +2301,7 @@ NtUserTranslateMessage(LPMSG lpMsg, RETURN( FALSE); } - RETURN( IntTranslateKbdMessage(&SafeMsg, dwhkl)); + RETURN( IntTranslateKbdMessage(&SafeMsg, flags)); CLEANUP: DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_); diff --git a/subsystems/win32/win32k/objects/gdibatch.c b/subsystems/win32/win32k/objects/gdibatch.c index b0c8ec9a1e0..b958ad4835d 100644 --- a/subsystems/win32/win32k/objects/gdibatch.c +++ b/subsystems/win32/win32k/objects/gdibatch.c @@ -66,14 +66,34 @@ ULONG FASTCALL GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) { + BOOL Hit = FALSE; + ULONG Cmd = 0, Size = 0; PDC_ATTR pdcattr = NULL; if (dc) { - pdcattr = dc->pdcattr; + pdcattr = dc->pdcattr; } - // The thread is approaching the end of sunset. - switch(pHdr->Cmd) + + _SEH2_TRY + { + Cmd = pHdr->Cmd; + Size = pHdr->Size; // Return the full size of the structure. + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END; + + if (Hit) + { + DPRINT1("WARNING! GdiBatch Fault!\n"); + return 0; + } + + // FYI! The thread is approaching the end of sunset. + switch(Cmd) { case GdiBCPatBlt: // Highest pri first! break; @@ -113,7 +133,7 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr) break; } - return pHdr->Size; // Return the full size of the structure. + return Size; } /* @@ -162,8 +182,11 @@ NtGdiFlushUserBatch(VOID) // No need to init anything, just go! for (; GdiBatchCount > 0; GdiBatchCount--) { + ULONG Size; // Process Gdi Batch! - pHdr += GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr); + Size = GdiFlushUserBatch(pDC, (PGDIBATCHHDR) pHdr); + if (!Size) break; + pHdr += Size; } if (pDC) diff --git a/subsystems/win32/win32k/pch.h b/subsystems/win32/win32k/pch.h index 3eae2acdda9..4bbbeb9c148 100644 --- a/subsystems/win32/win32k/pch.h +++ b/subsystems/win32/win32k/pch.h @@ -13,11 +13,11 @@ #define _NO_COM /* DDK/NDK/SDK Headers */ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* Win32 Headers */ /* FIXME: Defines in winbase.h that we need... */