summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2021-11-07 12:05:31 +0300
committerGeorge Hazan <ghazan@miranda.im>2021-11-07 12:05:49 +0300
commit27dab93c710a72ed363b5e0a543827b210ea71af (patch)
treefec437c914def6d356b2568efb2d44707b1351b9 /src
parent66940037defd069b5c6676969b889b60a8ed8fd0 (diff)
let's separate modules for Windows from common ones
Diffstat (limited to 'src')
-rw-r--r--src/mir_core/mir_core.vcxproj165
-rw-r--r--src/mir_core/mir_core.vcxproj.filters202
-rw-r--r--src/mir_core/src/Windows/CCtrlBase.cpp (renamed from src/mir_core/src/CCtrlBase.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlButton.cpp (renamed from src/mir_core/src/CCtrlButton.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlCheck.cpp (renamed from src/mir_core/src/CCtrlCheck.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlClc.cpp (renamed from src/mir_core/src/CCtrlClc.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlColor.cpp (renamed from src/mir_core/src/CCtrlColor.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlCombo.cpp (renamed from src/mir_core/src/CCtrlCombo.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlData.cpp (renamed from src/mir_core/src/CCtrlData.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlEdit.cpp (renamed from src/mir_core/src/CCtrlEdit.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlHyperlink.cpp (renamed from src/mir_core/src/CCtrlHyperlink.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlLabel.cpp (renamed from src/mir_core/src/CCtrlLabel.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlListBox.cpp (renamed from src/mir_core/src/CCtrlListBox.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlListView.cpp (renamed from src/mir_core/src/CCtrlListView.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlMButton.cpp (renamed from src/mir_core/src/CCtrlMButton.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlPages.cpp (renamed from src/mir_core/src/CCtrlPages.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlRichEdit.cpp (renamed from src/mir_core/src/CCtrlRichEdit.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlSlider.cpp (renamed from src/mir_core/src/CCtrlSlider.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlSpin.cpp (renamed from src/mir_core/src/CCtrlSpin.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeOpts.cpp (renamed from src/mir_core/src/CCtrlTreeOpts.cpp)2
-rw-r--r--src/mir_core/src/Windows/CCtrlTreeView.cpp (renamed from src/mir_core/src/CCtrlTreeView.cpp)2
-rw-r--r--src/mir_core/src/Windows/CDbLink.cpp (renamed from src/mir_core/src/CDbLink.cpp)184
-rw-r--r--src/mir_core/src/Windows/CDlgBase.cpp (renamed from src/mir_core/src/CDlgBase.cpp)2
-rw-r--r--src/mir_core/src/Windows/CProgress.cpp (renamed from src/mir_core/src/CProgress.cpp)2
-rw-r--r--src/mir_core/src/Windows/CSplitter.cpp (renamed from src/mir_core/src/CSplitter.cpp)2
-rw-r--r--src/mir_core/src/Windows/CTimer.cpp (renamed from src/mir_core/src/CTimer.cpp)2
-rw-r--r--src/mir_core/src/Windows/cctrldate.cpp (renamed from src/mir_core/src/cctrldate.cpp)2
-rw-r--r--src/mir_core/src/Windows/cmdline.cpp (renamed from src/mir_core/src/cmdline.cpp)154
-rw-r--r--src/mir_core/src/Windows/colourpicker.cpp (renamed from src/mir_core/src/colourpicker.cpp)210
-rw-r--r--src/mir_core/src/Windows/hyperlink.cpp (renamed from src/mir_core/src/hyperlink.cpp)554
-rw-r--r--src/mir_core/src/Windows/icons.cpp (renamed from src/mir_core/src/icons.cpp)148
-rw-r--r--src/mir_core/src/Windows/langpack.cpp (renamed from src/mir_core/src/langpack.cpp)1530
-rw-r--r--src/mir_core/src/Windows/locks.cpp (renamed from src/mir_core/src/locks.cpp)2
-rw-r--r--src/mir_core/src/Windows/miranda.cpp (renamed from src/mir_core/src/miranda.cpp)298
-rw-r--r--src/mir_core/src/Windows/openurl.cpp (renamed from src/mir_core/src/openurl.cpp)152
-rw-r--r--src/mir_core/src/Windows/path.cpp (renamed from src/mir_core/src/path.cpp)492
-rw-r--r--src/mir_core/src/Windows/resizer.cpp (renamed from src/mir_core/src/resizer.cpp)302
-rw-r--r--src/mir_core/src/Windows/subclass.cpp (renamed from src/mir_core/src/subclass.cpp)402
-rw-r--r--src/mir_core/src/Windows/threads.cpp (renamed from src/mir_core/src/threads.cpp)800
-rw-r--r--src/mir_core/src/Windows/timezones.cpp (renamed from src/mir_core/src/timezones.cpp)1184
-rw-r--r--src/mir_core/src/Windows/windowlist.cpp (renamed from src/mir_core/src/windowlist.cpp)210
-rw-r--r--src/mir_core/src/Windows/winutil.cpp (renamed from src/mir_core/src/winutil.cpp)236
-rw-r--r--src/mir_core/src/Windows/winver.cpp (renamed from src/mir_core/src/winver.cpp)744
43 files changed, 4054 insertions, 3963 deletions
diff --git a/src/mir_core/mir_core.vcxproj b/src/mir_core/mir_core.vcxproj
index 23e75824de..f0466fabab 100644
--- a/src/mir_core/mir_core.vcxproj
+++ b/src/mir_core/mir_core.vcxproj
@@ -42,67 +42,150 @@
<ItemGroup>
<ClCompile Include="src\binbuffer.cpp" />
<ClCompile Include="src\bitmaps.cpp" />
- <ClCompile Include="src\CCtrlBase.cpp" />
- <ClCompile Include="src\CCtrlButton.cpp" />
- <ClCompile Include="src\CCtrlCheck.cpp" />
- <ClCompile Include="src\CCtrlClc.cpp" />
- <ClCompile Include="src\CCtrlColor.cpp" />
- <ClCompile Include="src\CCtrlCombo.cpp" />
- <ClCompile Include="src\CCtrlData.cpp" />
- <ClCompile Include="src\cctrldate.cpp" />
- <ClCompile Include="src\CCtrlEdit.cpp" />
- <ClCompile Include="src\CCtrlHyperlink.cpp" />
- <ClCompile Include="src\CCtrlLabel.cpp" />
- <ClCompile Include="src\CCtrlListBox.cpp" />
- <ClCompile Include="src\CCtrlListView.cpp" />
- <ClCompile Include="src\CCtrlMButton.cpp" />
- <ClCompile Include="src\CCtrlPages.cpp" />
- <ClCompile Include="src\CCtrlRichEdit.cpp" />
- <ClCompile Include="src\CCtrlSlider.cpp" />
- <ClCompile Include="src\CCtrlSpin.cpp" />
- <ClCompile Include="src\CCtrlTreeOpts.cpp" />
- <ClCompile Include="src\CCtrlTreeView.cpp" />
- <ClCompile Include="src\CDbLink.cpp" />
- <ClCompile Include="src\CDlgBase.cpp" />
- <ClCompile Include="src\cmdline.cpp" />
- <ClCompile Include="src\colourpicker.cpp" />
- <ClCompile Include="src\CProgress.cpp" />
- <ClCompile Include="src\CSplitter.cpp" />
- <ClCompile Include="src\CTimer.cpp" />
<ClCompile Include="src\db.cpp" />
<ClCompile Include="src\http.cpp" />
- <ClCompile Include="src\hyperlink.cpp" />
- <ClCompile Include="src\icons.cpp" />
- <ClCompile Include="src\langpack.cpp" />
<ClCompile Include="src\lists.cpp" />
- <ClCompile Include="src\locks.cpp" />
<ClCompile Include="src\logger.cpp" />
<ClCompile Include="src\md5.cpp" />
<ClCompile Include="src\memory.cpp" />
- <ClCompile Include="src\miranda.cpp" />
<ClCompile Include="src\modules.cpp" />
<ClCompile Include="src\mstring.cpp" />
- <ClCompile Include="src\openurl.cpp" />
- <ClCompile Include="src\path.cpp" />
- <ClCompile Include="src\resizer.cpp" />
<ClCompile Include="src\sha1.cpp" />
<ClCompile Include="src\sha256.cpp" />
<ClCompile Include="src\stdafx.cxx">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="src\subclass.cpp" />
- <ClCompile Include="src\threads.cpp" />
- <ClCompile Include="src\timezones.cpp" />
<ClCompile Include="src\tinyxml2.cpp" />
<ClCompile Include="src\tinyxml2_utils.cpp" />
<ClCompile Include="src\utf.cpp" />
<ClCompile Include="src\utils.cpp" />
- <ClCompile Include="src\windowlist.cpp" />
- <ClCompile Include="src\winutil.cpp" />
- <ClCompile Include="src\winver.cpp" />
+ <ClCompile Include="src\Windows\CCtrlBase.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlButton.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlCheck.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlClc.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlColor.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlCombo.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlData.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\cctrldate.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlEdit.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlHyperlink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlLabel.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlListBox.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlListView.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlMButton.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlPages.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlRichEdit.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlSlider.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlSpin.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlTreeOpts.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CCtrlTreeView.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CDbLink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CDlgBase.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\cmdline.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\colourpicker.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CProgress.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CSplitter.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\CTimer.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\hyperlink.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\icons.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\langpack.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\locks.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\miranda.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\openurl.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\path.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\resizer.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\subclass.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\threads.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\timezones.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\windowlist.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\winutil.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
+ <ClCompile Include="src\Windows\winver.cpp">
+ <PrecompiledHeaderFile>../stdafx.h</PrecompiledHeaderFile>
+ </ClCompile>
<ClInclude Include="src\miranda.h" />
<ClInclude Include="src\stdafx.h" />
<ClInclude Include="src\tinyxml2.h" />
+ <ClInclude Include="src\Windows\miranda.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\version.rc" />
diff --git a/src/mir_core/mir_core.vcxproj.filters b/src/mir_core/mir_core.vcxproj.filters
index 2eba1c3237..92df544754 100644
--- a/src/mir_core/mir_core.vcxproj.filters
+++ b/src/mir_core/mir_core.vcxproj.filters
@@ -8,173 +8,173 @@
<ClCompile Include="src\bitmaps.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlBase.cpp">
+ <ClCompile Include="src\db.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlButton.cpp">
+ <ClCompile Include="src\http.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlCheck.cpp">
+ <ClCompile Include="src\lists.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlClc.cpp">
+ <ClCompile Include="src\logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlCombo.cpp">
+ <ClCompile Include="src\md5.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlData.cpp">
+ <ClCompile Include="src\memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\cctrldate.cpp">
+ <ClCompile Include="src\modules.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlEdit.cpp">
+ <ClCompile Include="src\mstring.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlHyperlink.cpp">
+ <ClCompile Include="src\sha1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlLabel.cpp">
+ <ClCompile Include="src\sha256.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlListBox.cpp">
+ <ClCompile Include="src\stdafx.cxx">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlListView.cpp">
+ <ClCompile Include="src\tinyxml2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlMButton.cpp">
+ <ClCompile Include="src\tinyxml2_utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlPages.cpp">
+ <ClCompile Include="src\utf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlRichEdit.cpp">
+ <ClCompile Include="src\utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlSpin.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlBase.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlTreeView.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlButton.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CDbLink.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlCheck.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CDlgBase.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlClc.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\cmdline.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlColor.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\colourpicker.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlCombo.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CProgress.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlData.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CSplitter.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\cctrldate.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CTimer.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlEdit.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\db.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlHyperlink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\http.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlLabel.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\hyperlink.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlListBox.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\icons.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlListView.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\langpack.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlMButton.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\lists.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlPages.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\locks.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlRichEdit.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\logger.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlSlider.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\md5.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlSpin.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\memory.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlTreeOpts.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\miranda.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CCtrlTreeView.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\modules.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CDbLink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\mstring.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CDlgBase.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\openurl.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\cmdline.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\path.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\colourpicker.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\resizer.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CProgress.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\sha1.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CSplitter.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\sha256.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\CTimer.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\stdafx.cxx">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\hyperlink.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\subclass.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\icons.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\threads.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\langpack.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\timezones.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\locks.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\tinyxml2.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\miranda.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\tinyxml2_utils.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\openurl.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\utf.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\path.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\utils.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\resizer.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\windowlist.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\subclass.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\winutil.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\threads.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\winver.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\timezones.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlTreeOpts.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\windowlist.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlColor.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\winutil.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
- <ClCompile Include="src\CCtrlSlider.cpp">
- <Filter>Source Files</Filter>
+ <ClCompile Include="src\Windows\winver.cpp">
+ <Filter>Source Files\Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -187,6 +187,9 @@
<ClInclude Include="src\tinyxml2.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\Windows\miranda.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\version.rc">
@@ -197,4 +200,9 @@
<None Include="src\mir_core64.def" />
<None Include="src\mir_core.def" />
</ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files\Windows">
+ <UniqueIdentifier>{af52c09e-568e-4948-95c9-120c030fd932}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/mir_core/src/CCtrlBase.cpp b/src/mir_core/src/Windows/CCtrlBase.cpp
index aa684707e0..83afe7fea6 100644
--- a/src/mir_core/src/CCtrlBase.cpp
+++ b/src/mir_core/src/Windows/CCtrlBase.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
static mir_cs csCtrl;
diff --git a/src/mir_core/src/CCtrlButton.cpp b/src/mir_core/src/Windows/CCtrlButton.cpp
index 75b25e477c..d86ba2e0ad 100644
--- a/src/mir_core/src/CCtrlButton.cpp
+++ b/src/mir_core/src/Windows/CCtrlButton.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlButton
diff --git a/src/mir_core/src/CCtrlCheck.cpp b/src/mir_core/src/Windows/CCtrlCheck.cpp
index ce765274b4..0315e1601b 100644
--- a/src/mir_core/src/CCtrlCheck.cpp
+++ b/src/mir_core/src/Windows/CCtrlCheck.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlCheck class
diff --git a/src/mir_core/src/CCtrlClc.cpp b/src/mir_core/src/Windows/CCtrlClc.cpp
index b5b439cdb7..9239d3d61a 100644
--- a/src/mir_core/src/CCtrlClc.cpp
+++ b/src/mir_core/src/Windows/CCtrlClc.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlClc
diff --git a/src/mir_core/src/CCtrlColor.cpp b/src/mir_core/src/Windows/CCtrlColor.cpp
index 71e913b5b9..dcd841b213 100644
--- a/src/mir_core/src/CCtrlColor.cpp
+++ b/src/mir_core/src/Windows/CCtrlColor.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlColor class
diff --git a/src/mir_core/src/CCtrlCombo.cpp b/src/mir_core/src/Windows/CCtrlCombo.cpp
index 4a67f14720..f481b1554d 100644
--- a/src/mir_core/src/CCtrlCombo.cpp
+++ b/src/mir_core/src/Windows/CCtrlCombo.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlCombo class
diff --git a/src/mir_core/src/CCtrlData.cpp b/src/mir_core/src/Windows/CCtrlData.cpp
index 92c25a4c4d..7f228b159e 100644
--- a/src/mir_core/src/CCtrlData.cpp
+++ b/src/mir_core/src/Windows/CCtrlData.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlData class
diff --git a/src/mir_core/src/CCtrlEdit.cpp b/src/mir_core/src/Windows/CCtrlEdit.cpp
index 3f60855843..4395af9419 100644
--- a/src/mir_core/src/CCtrlEdit.cpp
+++ b/src/mir_core/src/Windows/CCtrlEdit.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlEdit class
diff --git a/src/mir_core/src/CCtrlHyperlink.cpp b/src/mir_core/src/Windows/CCtrlHyperlink.cpp
index 7a4bf2ab28..f63e87ed8e 100644
--- a/src/mir_core/src/CCtrlHyperlink.cpp
+++ b/src/mir_core/src/Windows/CCtrlHyperlink.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlHyperlink
diff --git a/src/mir_core/src/CCtrlLabel.cpp b/src/mir_core/src/Windows/CCtrlLabel.cpp
index 2f95578aba..f4848592d5 100644
--- a/src/mir_core/src/CCtrlLabel.cpp
+++ b/src/mir_core/src/Windows/CCtrlLabel.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlLabel
diff --git a/src/mir_core/src/CCtrlListBox.cpp b/src/mir_core/src/Windows/CCtrlListBox.cpp
index da75fefe19..71519a96ca 100644
--- a/src/mir_core/src/CCtrlListBox.cpp
+++ b/src/mir_core/src/Windows/CCtrlListBox.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlListBox class
diff --git a/src/mir_core/src/CCtrlListView.cpp b/src/mir_core/src/Windows/CCtrlListView.cpp
index 5ac8f4d32e..23f780f170 100644
--- a/src/mir_core/src/CCtrlListView.cpp
+++ b/src/mir_core/src/Windows/CCtrlListView.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlListView
diff --git a/src/mir_core/src/CCtrlMButton.cpp b/src/mir_core/src/Windows/CCtrlMButton.cpp
index 42f5fd3303..6ab2cb0efd 100644
--- a/src/mir_core/src/CCtrlMButton.cpp
+++ b/src/mir_core/src/Windows/CCtrlMButton.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlMButton
diff --git a/src/mir_core/src/CCtrlPages.cpp b/src/mir_core/src/Windows/CCtrlPages.cpp
index 4ca7f1b16d..81ffdd008a 100644
--- a/src/mir_core/src/CCtrlPages.cpp
+++ b/src/mir_core/src/Windows/CCtrlPages.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
static volatile long g_order = 1;
diff --git a/src/mir_core/src/CCtrlRichEdit.cpp b/src/mir_core/src/Windows/CCtrlRichEdit.cpp
index eec1a467c2..44d965a682 100644
--- a/src/mir_core/src/CCtrlRichEdit.cpp
+++ b/src/mir_core/src/Windows/CCtrlRichEdit.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
#include <RichOle.h>
diff --git a/src/mir_core/src/CCtrlSlider.cpp b/src/mir_core/src/Windows/CCtrlSlider.cpp
index df42737d0b..4adbd45506 100644
--- a/src/mir_core/src/CCtrlSlider.cpp
+++ b/src/mir_core/src/Windows/CCtrlSlider.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlSlider class
diff --git a/src/mir_core/src/CCtrlSpin.cpp b/src/mir_core/src/Windows/CCtrlSpin.cpp
index 9f452d6d6f..bf75a67c91 100644
--- a/src/mir_core/src/CCtrlSpin.cpp
+++ b/src/mir_core/src/Windows/CCtrlSpin.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlSpin class
diff --git a/src/mir_core/src/CCtrlTreeOpts.cpp b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
index 4c63a0042f..0867347106 100644
--- a/src/mir_core/src/CCtrlTreeOpts.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeOpts.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };
diff --git a/src/mir_core/src/CCtrlTreeView.cpp b/src/mir_core/src/Windows/CCtrlTreeView.cpp
index 0522bfee03..08b4d57d7b 100644
--- a/src/mir_core/src/CCtrlTreeView.cpp
+++ b/src/mir_core/src/Windows/CCtrlTreeView.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
{
diff --git a/src/mir_core/src/CDbLink.cpp b/src/mir_core/src/Windows/CDbLink.cpp
index e81c5e181a..4515e032f2 100644
--- a/src/mir_core/src/CDbLink.cpp
+++ b/src/mir_core/src/Windows/CDbLink.cpp
@@ -1,92 +1,92 @@
-/*
-
-Object UI extensions
-Copyright (c) 2008 Victor Pavlychko, George Hazan
-Copyright (C) 2012-21 Miranda NG team
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "stdafx.h"
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// CDbLink class
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue)
- : CDataLink(type)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_iDefault = iValue;
- m_szDefault = nullptr;
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue)
- : CDataLink(type),
- m_iDefault(0)
-{
- m_szModule = mir_strdup(szModule);
- m_szSetting = mir_strdup(szSetting);
- m_szDefault = mir_wstrdup(szValue);
- dbv.type = DBVT_DELETED;
-}
-
-CDbLink::~CDbLink()
-{
- mir_free(m_szModule);
- mir_free(m_szSetting);
- mir_free(m_szDefault);
- if (dbv.type != DBVT_DELETED)
- db_free(&dbv);
-}
-
-DWORD CDbLink::LoadInt()
-{
- switch (m_type) {
- case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
- case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
- default: return m_iDefault;
- }
-}
-
-void CDbLink::SaveInt(DWORD value)
-{
- switch (m_type) {
- case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break;
- case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)value); break;
- case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
- }
-}
-
-wchar_t* CDbLink::LoadText()
-{
- if (dbv.type != DBVT_DELETED) db_free(&dbv);
- if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
- if (dbv.type == DBVT_WCHAR)
- return dbv.pwszVal;
- return m_szDefault;
- }
-
- dbv.type = DBVT_DELETED;
- return m_szDefault;
-}
-
-void CDbLink::SaveText(wchar_t *value)
-{
- db_set_ws(0, m_szModule, m_szSetting, value);
-}
+/*
+
+Object UI extensions
+Copyright (c) 2008 Victor Pavlychko, George Hazan
+Copyright (C) 2012-21 Miranda NG team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CDbLink class
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, DWORD iValue)
+ : CDataLink(type)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_iDefault = iValue;
+ m_szDefault = nullptr;
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::CDbLink(const char *szModule, const char *szSetting, BYTE type, wchar_t *szValue)
+ : CDataLink(type),
+ m_iDefault(0)
+{
+ m_szModule = mir_strdup(szModule);
+ m_szSetting = mir_strdup(szSetting);
+ m_szDefault = mir_wstrdup(szValue);
+ dbv.type = DBVT_DELETED;
+}
+
+CDbLink::~CDbLink()
+{
+ mir_free(m_szModule);
+ mir_free(m_szSetting);
+ mir_free(m_szDefault);
+ if (dbv.type != DBVT_DELETED)
+ db_free(&dbv);
+}
+
+DWORD CDbLink::LoadInt()
+{
+ switch (m_type) {
+ case DBVT_BYTE: return db_get_b(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_WORD: return db_get_w(0, m_szModule, m_szSetting, m_iDefault);
+ case DBVT_DWORD: return db_get_dw(0, m_szModule, m_szSetting, m_iDefault);
+ default: return m_iDefault;
+ }
+}
+
+void CDbLink::SaveInt(DWORD value)
+{
+ switch (m_type) {
+ case DBVT_BYTE: db_set_b(0, m_szModule, m_szSetting, (BYTE)value); break;
+ case DBVT_WORD: db_set_w(0, m_szModule, m_szSetting, (WORD)value); break;
+ case DBVT_DWORD: db_set_dw(0, m_szModule, m_szSetting, value); break;
+ }
+}
+
+wchar_t* CDbLink::LoadText()
+{
+ if (dbv.type != DBVT_DELETED) db_free(&dbv);
+ if (!db_get_ws(0, m_szModule, m_szSetting, &dbv)) {
+ if (dbv.type == DBVT_WCHAR)
+ return dbv.pwszVal;
+ return m_szDefault;
+ }
+
+ dbv.type = DBVT_DELETED;
+ return m_szDefault;
+}
+
+void CDbLink::SaveText(wchar_t *value)
+{
+ db_set_ws(0, m_szModule, m_szSetting, value);
+}
diff --git a/src/mir_core/src/CDlgBase.cpp b/src/mir_core/src/Windows/CDlgBase.cpp
index f9f5f47a06..5949057fda 100644
--- a/src/mir_core/src/CDlgBase.cpp
+++ b/src/mir_core/src/Windows/CDlgBase.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
static mir_cs csDialogs;
diff --git a/src/mir_core/src/CProgress.cpp b/src/mir_core/src/Windows/CProgress.cpp
index 3b745b10cd..acc4773aff 100644
--- a/src/mir_core/src/CProgress.cpp
+++ b/src/mir_core/src/Windows/CProgress.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlProgress
diff --git a/src/mir_core/src/CSplitter.cpp b/src/mir_core/src/Windows/CSplitter.cpp
index 7ea0b538c9..24e406f999 100644
--- a/src/mir_core/src/CSplitter.cpp
+++ b/src/mir_core/src/Windows/CSplitter.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CSplitter
diff --git a/src/mir_core/src/CTimer.cpp b/src/mir_core/src/Windows/CTimer.cpp
index dfaa83be0a..367c65249f 100644
--- a/src/mir_core/src/CTimer.cpp
+++ b/src/mir_core/src/Windows/CTimer.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CTimer
diff --git a/src/mir_core/src/cctrldate.cpp b/src/mir_core/src/Windows/cctrldate.cpp
index 415c1571b2..809679aad3 100644
--- a/src/mir_core/src/cctrldate.cpp
+++ b/src/mir_core/src/Windows/cctrldate.cpp
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CCtrlDate class
diff --git a/src/mir_core/src/cmdline.cpp b/src/mir_core/src/Windows/cmdline.cpp
index 4dc74695c4..6aee0efe60 100644
--- a/src/mir_core/src/cmdline.cpp
+++ b/src/mir_core/src/Windows/cmdline.cpp
@@ -1,77 +1,77 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-/* command line support */
-
-struct CmdLineParam
-{
- __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) :
- name(mir_wstrdup(_name)), value(mir_wstrdup(_value))
- {}
-
- ptrW name, value;
-};
-
-static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2)
-{
- return wcscmp(p1->name, p2->name);
-}
-
-static OBJLIST<CmdLineParam> arParams(5, CompareParams);
-
-MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine)
-{
- int nArgs = 0;
- wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs);
- if (pArgs == nullptr)
- return;
-
- for (int i=0; i < nArgs; i++) {
- wchar_t *pOptionName = pArgs[i], *p;
-
- // not an option? skip it
- if (*pOptionName != '/' && *pOptionName != '-')
- continue;
-
- pOptionName++;
- if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string
- arParams.insert(new CmdLineParam(pOptionName, L""));
- break;
- }
-
- // parameter with value
- *p = 0;
- arParams.insert(new CmdLineParam(pOptionName, p+1));
- }
-
- LocalFree(pArgs);
-}
-
-MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter)
-{
- CmdLineParam tmp(ptszParameter, nullptr);
- int idx = arParams.getIndex(&tmp);
- return (idx == -1) ? nullptr : arParams[idx].value.get();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+/* command line support */
+
+struct CmdLineParam
+{
+ __inline CmdLineParam(const wchar_t *_name, const wchar_t *_value) :
+ name(mir_wstrdup(_name)), value(mir_wstrdup(_value))
+ {}
+
+ ptrW name, value;
+};
+
+static int CompareParams(const CmdLineParam *p1, const CmdLineParam *p2)
+{
+ return wcscmp(p1->name, p2->name);
+}
+
+static OBJLIST<CmdLineParam> arParams(5, CompareParams);
+
+MIR_CORE_DLL(void) CmdLine_Parse(const wchar_t *ptszCmdLine)
+{
+ int nArgs = 0;
+ wchar_t **pArgs = CommandLineToArgvW(ptszCmdLine, &nArgs);
+ if (pArgs == nullptr)
+ return;
+
+ for (int i=0; i < nArgs; i++) {
+ wchar_t *pOptionName = pArgs[i], *p;
+
+ // not an option? skip it
+ if (*pOptionName != '/' && *pOptionName != '-')
+ continue;
+
+ pOptionName++;
+ if ((p = wcspbrk(pOptionName, L"=:")) == nullptr) { // no more text in string
+ arParams.insert(new CmdLineParam(pOptionName, L""));
+ break;
+ }
+
+ // parameter with value
+ *p = 0;
+ arParams.insert(new CmdLineParam(pOptionName, p+1));
+ }
+
+ LocalFree(pArgs);
+}
+
+MIR_CORE_DLL(const wchar_t*) CmdLine_GetOption(const wchar_t* ptszParameter)
+{
+ CmdLineParam tmp(ptszParameter, nullptr);
+ int idx = arParams.getIndex(&tmp);
+ return (idx == -1) ? nullptr : arParams[idx].value.get();
+}
diff --git a/src/mir_core/src/colourpicker.cpp b/src/mir_core/src/Windows/colourpicker.cpp
index 181eadd894..464c29abc5 100644
--- a/src/mir_core/src/colourpicker.cpp
+++ b/src/mir_core/src/Windows/colourpicker.cpp
@@ -1,105 +1,105 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-static LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch (message) {
- case WM_CREATE:
- SetWindowLongPtr(hwnd, 0, 0);
- SetWindowLongPtr(hwnd, sizeof(COLORREF), 0);
- break;
-
- case CPM_SETDEFAULTCOLOUR:
- SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam);
- break;
-
- case CPM_GETDEFAULTCOLOUR:
- return GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- case CPM_SETCOLOUR:
- SetWindowLongPtr(hwnd, 0, lParam);
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case CPM_GETCOLOUR:
- return GetWindowLongPtr(hwnd, 0);
-
- case WM_LBUTTONUP:
- {
- COLORREF custColours[16] = { 0 };
- custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF));
-
- CHOOSECOLOR cc = { 0 };
- cc.lStructSize = sizeof(CHOOSECOLOR);
- cc.hwndOwner = hwnd;
- cc.hInstance = (HWND)g_hInst;
- cc.rgbResult = GetWindowLongPtr(hwnd, 0);
- cc.lpCustColors = custColours;
- cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
- if (ChooseColor(&cc)) {
- SetWindowLongPtr(hwnd, 0, cc.rgbResult);
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd);
- InvalidateRect(hwnd, nullptr, FALSE);
- }
- }
- break;
-
- case WM_ENABLE:
- InvalidateRect(hwnd, nullptr, FALSE);
- break;
-
- case WM_NCPAINT:
- case WM_PAINT:
- PAINTSTRUCT ps;
- HDC hdc1 = BeginPaint(hwnd, &ps);
-
- RECT rc;
- GetClientRect(hwnd, &rc);
- DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT);
- InflateRect(&rc, -2, -2);
-
- HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT));
- SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE));
- FillRect(hdc1, &rc, hBrush);
- DeleteObject(hBrush);
-
- EndPaint(hwnd, &ps);
- break;
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-void InitColourPicker(void)
-{
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = ColourPickerWndProc;
- wcl.cbWndExtra = sizeof(COLORREF) * 2;
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER);
- wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
- RegisterClass(&wcl);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+static LRESULT CALLBACK ColourPickerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_CREATE:
+ SetWindowLongPtr(hwnd, 0, 0);
+ SetWindowLongPtr(hwnd, sizeof(COLORREF), 0);
+ break;
+
+ case CPM_SETDEFAULTCOLOUR:
+ SetWindowLongPtr(hwnd, sizeof(COLORREF), lParam);
+ break;
+
+ case CPM_GETDEFAULTCOLOUR:
+ return GetWindowLongPtr(hwnd, sizeof(COLORREF));
+
+ case CPM_SETCOLOUR:
+ SetWindowLongPtr(hwnd, 0, lParam);
+ InvalidateRect(hwnd, nullptr, FALSE);
+ break;
+
+ case CPM_GETCOLOUR:
+ return GetWindowLongPtr(hwnd, 0);
+
+ case WM_LBUTTONUP:
+ {
+ COLORREF custColours[16] = { 0 };
+ custColours[0] = GetWindowLongPtr(hwnd, sizeof(COLORREF));
+
+ CHOOSECOLOR cc = { 0 };
+ cc.lStructSize = sizeof(CHOOSECOLOR);
+ cc.hwndOwner = hwnd;
+ cc.hInstance = (HWND)g_hInst;
+ cc.rgbResult = GetWindowLongPtr(hwnd, 0);
+ cc.lpCustColors = custColours;
+ cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
+ if (ChooseColor(&cc)) {
+ SetWindowLongPtr(hwnd, 0, cc.rgbResult);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), CPN_COLOURCHANGED), (LPARAM)hwnd);
+ InvalidateRect(hwnd, nullptr, FALSE);
+ }
+ }
+ break;
+
+ case WM_ENABLE:
+ InvalidateRect(hwnd, nullptr, FALSE);
+ break;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ PAINTSTRUCT ps;
+ HDC hdc1 = BeginPaint(hwnd, &ps);
+
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ DrawEdge(hdc1, &rc, EDGE_ETCHED, BF_RECT);
+ InflateRect(&rc, -2, -2);
+
+ HBRUSH hBrush = (IsWindowEnabled(hwnd)) ? CreateSolidBrush(GetWindowLongPtr(hwnd, 0)) : CreateHatchBrush(HS_BDIAGONAL, GetSysColor(COLOR_GRAYTEXT));
+ SetBkColor(hdc1, GetSysColor(COLOR_BTNFACE));
+ FillRect(hdc1, &rc, hBrush);
+ DeleteObject(hBrush);
+
+ EndPaint(hwnd, &ps);
+ break;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+void InitColourPicker(void)
+{
+ WNDCLASS wcl = { 0 };
+ wcl.lpfnWndProc = ColourPickerWndProc;
+ wcl.cbWndExtra = sizeof(COLORREF) * 2;
+ wcl.hInstance = g_hInst;
+ wcl.lpszClassName = _T(WNDCLASS_COLOURPICKER);
+ wcl.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+ wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
+ RegisterClass(&wcl);
+}
diff --git a/src/mir_core/src/hyperlink.cpp b/src/mir_core/src/Windows/hyperlink.cpp
index 12aa157522..65ce93c54a 100644
--- a/src/mir_core/src/hyperlink.cpp
+++ b/src/mir_core/src/Windows/hyperlink.cpp
@@ -1,277 +1,277 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-struct HyperlinkWndData
-{
- HFONT hEnableFont, hDisableFont;
- RECT rcText;
- COLORREF enableColor, disableColor, focusColor;
- BYTE flags; /* see HLKF_* */
-};
-
-/* flags */
-#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
-#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
-
-/* internal messages */
-#define HLK_MEASURETEXT (WM_USER+1)
-#define HLK_INVALIDATE (WM_USER+2)
-
-static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0);
-
- HDC hdc;
- RECT rc;
- POINT pt;
- HFONT hFont;
- LOGFONT lf;
- HCURSOR hCursor;
- COLORREF prevColor;
-
- switch (msg) {
- case WM_NCCREATE:
- dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
- if (dat == nullptr)
- return FALSE; /* fail creation */
- SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */
- /* fall thru */
-
- case WM_SYSCOLORCHANGE:
- if (!(dat->flags&HLKF_HASENABLECOLOR)) {
- if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255);
- else dat->enableColor = GetSysColor(COLOR_HOTLIGHT);
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- }
- if (!(dat->flags&HLKF_HASDISABLECOLOR))
- dat->disableColor = GetSysColor(COLOR_GRAYTEXT);
- break;
-
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
- break;
-
- case WM_MOUSEACTIVATE:
- SetFocus(hwnd);
- return MA_ACTIVATE;
-
- case WM_GETDLGCODE:
- if (lParam) {
- MSG *pMsg = (MSG *)lParam;
- if (pMsg->message == WM_KEYDOWN) {
- if (pMsg->wParam == VK_TAB)
- return 0;
- if (pMsg->wParam == VK_ESCAPE)
- return 0;
- }
- else if (pMsg->message == WM_CHAR) {
- if (pMsg->wParam == '\t')
- return 0;
- if (pMsg->wParam == 27)
- return 0;
- }
- }
- return DLGC_WANTMESSAGE;
-
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_SPACE:
- case VK_RETURN:
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- break;
- }
- return 0;
-
- case WM_LBUTTONDOWN:
- POINTSTOPOINT(pt, MAKEPOINTS(lParam));
- if (!PtInRect(&dat->rcText, pt)) break;
- SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
- return 0;
-
- case WM_SETFONT:
- if ((HFONT)wParam == nullptr) { /* use default system color */
- dat->hEnableFont = dat->hDisableFont = nullptr;
- return 0;
- }
- if (GetObject((HFONT)wParam, sizeof(lf), &lf)) {
- lf.lfUnderline = 1;
- hFont = CreateFontIndirect(&lf);
- if (hFont != nullptr) {
- dat->hEnableFont = hFont;
- dat->hDisableFont = (HFONT)wParam;
- if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- SendMessage(hwnd, HLK_MEASURETEXT, 0, 0);
- }
- }
- return 0;
-
- case WM_ERASEBKGND:
- return TRUE;
-
- case WM_ENABLE:
- case HLK_INVALIDATE:
- if (GetWindowRect(hwnd, &rc)) {
- pt.x = rc.left;
- pt.y = rc.top;
-
- HWND hwndParent = GetParent(hwnd);
- if (hwndParent == nullptr)
- hwndParent = hwnd;
- if (!ScreenToClient(hwndParent, &pt))
- break;
-
- rc.right = pt.x + (rc.right - rc.left);
- rc.bottom = pt.y + (rc.bottom - rc.top);
- rc.left = pt.x;
- rc.top = pt.y;
- InvalidateRect(hwndParent, &rc, TRUE);
- }
- return 0;
-
- case WM_GETFONT:
- return (LRESULT)dat->hDisableFont;
-
- case WM_CREATE:
- case HLK_MEASURETEXT:
- wchar_t szText[256];
- if (!GetWindowText(hwnd, szText, _countof(szText))) return 0;
- lParam = (LPARAM)szText;
- /* fall thru */
-
- case WM_SETTEXT:
- hdc = GetDC(hwnd);
- if (hdc == nullptr) /* text change failed */
- return 0;
- else {
- BOOL fMeasured = FALSE;
- HFONT hPrevFont = nullptr;
- if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */
- SIZE textSize;
- if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) {
- if (GetClientRect(hwnd, &rc)) {
- dat->rcText.top = 0;
- dat->rcText.bottom = dat->rcText.top + textSize.cy;
- LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
- if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2;
- else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx;
- else dat->rcText.left = 0;
- dat->rcText.right = dat->rcText.left + textSize.cx;
- fMeasured = TRUE;
- }
- }
- }
- if (dat->hEnableFont != nullptr && hPrevFont != nullptr)
- SelectObject(hdc, hPrevFont);
- ReleaseDC(hwnd, hdc);
- if (!fMeasured) /* text change failed */
- return 0;
-
- SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
- }
- break;
-
- case WM_SETCURSOR:
- if (!GetCursorPos(&pt)) return FALSE;
- if (!ScreenToClient(hwnd, &pt)) return FALSE;
- if (PtInRect(&dat->rcText, pt)) {
- hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR);
- if (hCursor == nullptr)
- hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */
- }
- else hCursor = LoadCursor(nullptr, IDC_ARROW);
- SetCursor(hCursor);
- return TRUE;
-
- case HLK_SETENABLECOLOUR:
- prevColor = dat->enableColor;
- dat->enableColor = (COLORREF)wParam;
- dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
- dat->flags |= HLKF_HASENABLECOLOR;
- return (LRESULT)prevColor;
-
- case HLK_SETDISABLECOLOUR:
- prevColor = dat->disableColor;
- dat->disableColor = (COLORREF)wParam;
- dat->flags |= HLKF_HASDISABLECOLOR;
- return (LRESULT)prevColor;
-
- case WM_NCPAINT:
- return 0;
-
- case WM_PAINT:
- PAINTSTRUCT ps;
- hdc = BeginPaint(hwnd, &ps);
- if (hdc != nullptr) {
- HFONT hPrevFont;
- COLORREF textColor;
- if (IsWindowEnabled(hwnd)) {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
- textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
- }
- else {
- hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont);
- textColor = dat->disableColor;
- }
- if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) {
- BOOL fSmoothing;
- UINT fSmoothingType;
- SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
- SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
- if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
- DrawThemeParentBackground(hwnd, hdc, &rc);
- SetBkMode(hdc, TRANSPARENT);
- SetTextColor(hdc, textColor);
- UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT));
- DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
- }
- if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont);
- EndPaint(hwnd, &ps);
- }
- return 0;
-
- case WM_NCDESTROY:
- if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont);
- mir_free(dat);
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-void InitHyperlink(void)
-{
- g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS);
- g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE);
-
- WNDCLASS wcl = { 0 };
- wcl.lpfnWndProc = HyperlinkWndProc;
- wcl.cbWndExtra = sizeof(struct HyperlinkWndData*);
- wcl.hInstance = g_hInst;
- wcl.lpszClassName = WNDCLASS_HYPERLINK;
- wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
- RegisterClass(&wcl); /* automatically unregistered on exit */
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+struct HyperlinkWndData
+{
+ HFONT hEnableFont, hDisableFont;
+ RECT rcText;
+ COLORREF enableColor, disableColor, focusColor;
+ BYTE flags; /* see HLKF_* */
+};
+
+/* flags */
+#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
+#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
+
+/* internal messages */
+#define HLK_MEASURETEXT (WM_USER+1)
+#define HLK_INVALIDATE (WM_USER+2)
+
+static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HyperlinkWndData *dat = (HyperlinkWndData*)GetWindowLongPtr(hwnd, 0);
+
+ HDC hdc;
+ RECT rc;
+ POINT pt;
+ HFONT hFont;
+ LOGFONT lf;
+ HCURSOR hCursor;
+ COLORREF prevColor;
+
+ switch (msg) {
+ case WM_NCCREATE:
+ dat = (struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
+ if (dat == nullptr)
+ return FALSE; /* fail creation */
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); /* always succeeds */
+ /* fall thru */
+
+ case WM_SYSCOLORCHANGE:
+ if (!(dat->flags&HLKF_HASENABLECOLOR)) {
+ if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) dat->enableColor = RGB(0, 0, 255);
+ else dat->enableColor = GetSysColor(COLOR_HOTLIGHT);
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ }
+ if (!(dat->flags&HLKF_HASDISABLECOLOR))
+ dat->disableColor = GetSysColor(COLOR_GRAYTEXT);
+ break;
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE);
+ break;
+
+ case WM_MOUSEACTIVATE:
+ SetFocus(hwnd);
+ return MA_ACTIVATE;
+
+ case WM_GETDLGCODE:
+ if (lParam) {
+ MSG *pMsg = (MSG *)lParam;
+ if (pMsg->message == WM_KEYDOWN) {
+ if (pMsg->wParam == VK_TAB)
+ return 0;
+ if (pMsg->wParam == VK_ESCAPE)
+ return 0;
+ }
+ else if (pMsg->message == WM_CHAR) {
+ if (pMsg->wParam == '\t')
+ return 0;
+ if (pMsg->wParam == 27)
+ return 0;
+ }
+ }
+ return DLGC_WANTMESSAGE;
+
+ case WM_KEYDOWN:
+ switch (wParam) {
+ case VK_SPACE:
+ case VK_RETURN:
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
+ break;
+ }
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ POINTSTOPOINT(pt, MAKEPOINTS(lParam));
+ if (!PtInRect(&dat->rcText, pt)) break;
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), STN_CLICKED), (LPARAM)hwnd);
+ return 0;
+
+ case WM_SETFONT:
+ if ((HFONT)wParam == nullptr) { /* use default system color */
+ dat->hEnableFont = dat->hDisableFont = nullptr;
+ return 0;
+ }
+ if (GetObject((HFONT)wParam, sizeof(lf), &lf)) {
+ lf.lfUnderline = 1;
+ hFont = CreateFontIndirect(&lf);
+ if (hFont != nullptr) {
+ dat->hEnableFont = hFont;
+ dat->hDisableFont = (HFONT)wParam;
+ if (LOWORD(lParam)) SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
+ SendMessage(hwnd, HLK_MEASURETEXT, 0, 0);
+ }
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_ENABLE:
+ case HLK_INVALIDATE:
+ if (GetWindowRect(hwnd, &rc)) {
+ pt.x = rc.left;
+ pt.y = rc.top;
+
+ HWND hwndParent = GetParent(hwnd);
+ if (hwndParent == nullptr)
+ hwndParent = hwnd;
+ if (!ScreenToClient(hwndParent, &pt))
+ break;
+
+ rc.right = pt.x + (rc.right - rc.left);
+ rc.bottom = pt.y + (rc.bottom - rc.top);
+ rc.left = pt.x;
+ rc.top = pt.y;
+ InvalidateRect(hwndParent, &rc, TRUE);
+ }
+ return 0;
+
+ case WM_GETFONT:
+ return (LRESULT)dat->hDisableFont;
+
+ case WM_CREATE:
+ case HLK_MEASURETEXT:
+ wchar_t szText[256];
+ if (!GetWindowText(hwnd, szText, _countof(szText))) return 0;
+ lParam = (LPARAM)szText;
+ /* fall thru */
+
+ case WM_SETTEXT:
+ hdc = GetDC(hwnd);
+ if (hdc == nullptr) /* text change failed */
+ return 0;
+ else {
+ BOOL fMeasured = FALSE;
+ HFONT hPrevFont = nullptr;
+ if (dat->hEnableFont != nullptr) hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
+ if (dat->hEnableFont == nullptr || hPrevFont != nullptr) { /* select failed? */
+ SIZE textSize;
+ if (GetTextExtentPoint32(hdc, (wchar_t*)lParam, (int)mir_wstrlen((wchar_t*)lParam), &textSize)) {
+ if (GetClientRect(hwnd, &rc)) {
+ dat->rcText.top = 0;
+ dat->rcText.bottom = dat->rcText.top + textSize.cy;
+ LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ if (style & SS_CENTER) dat->rcText.left = (rc.right - textSize.cx) / 2;
+ else if (style & SS_RIGHT) dat->rcText.left = rc.right - textSize.cx;
+ else dat->rcText.left = 0;
+ dat->rcText.right = dat->rcText.left + textSize.cx;
+ fMeasured = TRUE;
+ }
+ }
+ }
+ if (dat->hEnableFont != nullptr && hPrevFont != nullptr)
+ SelectObject(hdc, hPrevFont);
+ ReleaseDC(hwnd, hdc);
+ if (!fMeasured) /* text change failed */
+ return 0;
+
+ SendMessage(hwnd, HLK_INVALIDATE, 0, 0);
+ }
+ break;
+
+ case WM_SETCURSOR:
+ if (!GetCursorPos(&pt)) return FALSE;
+ if (!ScreenToClient(hwnd, &pt)) return FALSE;
+ if (PtInRect(&dat->rcText, pt)) {
+ hCursor = (HCURSOR)GetClassLongPtr(hwnd, GCLP_HCURSOR);
+ if (hCursor == nullptr)
+ hCursor = LoadCursor(nullptr, IDC_HAND); /* Win2000+ */
+ }
+ else hCursor = LoadCursor(nullptr, IDC_ARROW);
+ SetCursor(hCursor);
+ return TRUE;
+
+ case HLK_SETENABLECOLOUR:
+ prevColor = dat->enableColor;
+ dat->enableColor = (COLORREF)wParam;
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ dat->flags |= HLKF_HASENABLECOLOR;
+ return (LRESULT)prevColor;
+
+ case HLK_SETDISABLECOLOUR:
+ prevColor = dat->disableColor;
+ dat->disableColor = (COLORREF)wParam;
+ dat->flags |= HLKF_HASDISABLECOLOR;
+ return (LRESULT)prevColor;
+
+ case WM_NCPAINT:
+ return 0;
+
+ case WM_PAINT:
+ PAINTSTRUCT ps;
+ hdc = BeginPaint(hwnd, &ps);
+ if (hdc != nullptr) {
+ HFONT hPrevFont;
+ COLORREF textColor;
+ if (IsWindowEnabled(hwnd)) {
+ hPrevFont = (HFONT)SelectObject(hdc, dat->hEnableFont);
+ textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
+ }
+ else {
+ hPrevFont = (HFONT)SelectObject(hdc, dat->hDisableFont);
+ textColor = dat->disableColor;
+ }
+ if (GetClientRect(hwnd, &rc) && GetWindowText(hwnd, szText, _countof(szText))) {
+ BOOL fSmoothing;
+ UINT fSmoothingType;
+ SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
+ SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
+ if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
+ DrawThemeParentBackground(hwnd, hdc, &rc);
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextColor(hdc, textColor);
+ UINT alignFlag = (GetWindowLongPtr(hwnd, GWL_STYLE) & (SS_CENTER | SS_RIGHT | SS_LEFT));
+ DrawText(hdc, szText, -1, &rc, alignFlag | DT_NOPREFIX | DT_SINGLELINE | DT_TOP);
+ }
+ if (hPrevFont != nullptr) SelectObject(hdc, hPrevFont);
+ EndPaint(hwnd, &ps);
+ }
+ return 0;
+
+ case WM_NCDESTROY:
+ if (dat->hEnableFont != nullptr) DeleteObject(dat->hEnableFont);
+ mir_free(dat);
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+void InitHyperlink(void)
+{
+ g_hCursorNS = LoadCursor(nullptr, IDC_SIZENS);
+ g_hCursorWE = LoadCursor(nullptr, IDC_SIZEWE);
+
+ WNDCLASS wcl = { 0 };
+ wcl.lpfnWndProc = HyperlinkWndProc;
+ wcl.cbWndExtra = sizeof(struct HyperlinkWndData*);
+ wcl.hInstance = g_hInst;
+ wcl.lpszClassName = WNDCLASS_HYPERLINK;
+ wcl.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
+ RegisterClass(&wcl); /* automatically unregistered on exit */
+}
diff --git a/src/mir_core/src/icons.cpp b/src/mir_core/src/Windows/icons.cpp
index 12ff1f5caf..b187f7ba0c 100644
--- a/src/mir_core/src/icons.cpp
+++ b/src/mir_core/src/Windows/icons.cpp
@@ -1,74 +1,74 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.a = (char*)szSection;
- sid.flags = SIDF_PATH_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.a = pIcons[i].szDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
-
-MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
-{
- wchar_t szFile[MAX_PATH];
- GetModuleFileName(hInst, szFile, MAX_PATH);
-
- SKINICONDESC sid = {};
- sid.defaultFile.w = szFile;
- sid.section.w = (wchar_t*)szSection;
- sid.flags = SIDF_ALL_UNICODE;
-
- for (unsigned i = 0; i < iCount; i++) {
- char szSetting[100];
- if (prefix) {
- mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
- sid.pszName = szSetting;
- }
- else sid.pszName = pIcons[i].szName;
-
- sid.cx = sid.cy = pIcons[i].size;
- sid.description.w = pIcons[i].tszDescr;
- sid.iDefaultIndex = -pIcons[i].defIconID;
- pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
- }
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(void) Icon_Register(HINSTANCE hInst, const char *szSection, IconItem *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
+{
+ wchar_t szFile[MAX_PATH];
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ SKINICONDESC sid = {};
+ sid.defaultFile.w = szFile;
+ sid.section.a = (char*)szSection;
+ sid.flags = SIDF_PATH_UNICODE;
+
+ for (unsigned i = 0; i < iCount; i++) {
+ char szSetting[100];
+ if (prefix) {
+ mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
+ sid.pszName = szSetting;
+ }
+ else sid.pszName = pIcons[i].szName;
+
+ sid.cx = sid.cy = pIcons[i].size;
+ sid.description.a = pIcons[i].szDescr;
+ sid.iDefaultIndex = -pIcons[i].defIconID;
+ pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
+ }
+}
+
+MIR_CORE_DLL(void) Icon_RegisterT(HINSTANCE hInst, const wchar_t *szSection, IconItemT *pIcons, size_t iCount, const char *prefix, HPLUGIN pPlugin)
+{
+ wchar_t szFile[MAX_PATH];
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ SKINICONDESC sid = {};
+ sid.defaultFile.w = szFile;
+ sid.section.w = (wchar_t*)szSection;
+ sid.flags = SIDF_ALL_UNICODE;
+
+ for (unsigned i = 0; i < iCount; i++) {
+ char szSetting[100];
+ if (prefix) {
+ mir_snprintf(szSetting, "%s_%s", prefix, pIcons[i].szName);
+ sid.pszName = szSetting;
+ }
+ else sid.pszName = pIcons[i].szName;
+
+ sid.cx = sid.cy = pIcons[i].size;
+ sid.description.w = pIcons[i].tszDescr;
+ sid.iDefaultIndex = -pIcons[i].defIconID;
+ pIcons[i].hIcolib = IcoLib_AddIcon(&sid, pPlugin);
+ }
+}
diff --git a/src/mir_core/src/langpack.cpp b/src/mir_core/src/Windows/langpack.cpp
index c16ebc878f..f877a7ca5f 100644
--- a/src/mir_core/src/langpack.cpp
+++ b/src/mir_core/src/Windows/langpack.cpp
@@ -1,765 +1,765 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-#include "../../mir_app/src/langpack.h"
-
-#define LANGPACK_BUF_SIZE 4000
-
-static int CompareMuuids(const MUUID *p1, const MUUID *p2)
-{
- return memcmp(p1, p2, sizeof(MUUID));
-}
-
-static LIST<MUUID> lMuuids(10, CompareMuuids);
-static MUUID *pCurrentMuuid = nullptr;
-static HANDLE hevChanged = nullptr;
-
-static BOOL bModuleInitialized = FALSE;
-
-struct LangPackEntry
-{
- DWORD englishHash;
- char *szLocal;
- char *utfLocal;
- wchar_t *wszLocal;
- MUUID *pMuuid;
- LangPackEntry* pNext; // for langpack items with the same hash value
-};
-
-static LANGPACK_INFO langPack;
-static wchar_t g_tszRoot[MAX_PATH];
-
-static LangPackEntry *g_pEntries;
-static int g_entryCount, g_entriesAlloced;
-
-static int IsEmpty(const char *str)
-{
- for (int i = 0; str[i]; i++)
- if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n')
- return 0;
-
- return 1;
-}
-
-static int ConvertBackslashes(char *str, UINT fileCp)
-{
- int shift = 0;
- char *pstr;
- for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) {
- if (*pstr == '\\') {
- shift++;
- switch (pstr[1]) {
- case 'n': *pstr = '\n'; break;
- case 't': *pstr = '\t'; break;
- case 'r': *pstr = '\r'; break;
- case 's': *pstr = ' '; break;
- default: *pstr = pstr[1]; break;
- }
- memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1);
- }
- }
- return shift;
-}
-
-#ifdef _DEBUG
-//#pragma optimize("gt", on)
-#endif
-
-// MurmurHash2
-MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len)
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
- const unsigned int m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
- unsigned int h = len;
-
- // Mix 4 bytes at a time into the hash
- const unsigned char *data = (const unsigned char*)key;
-
- while (len >= 4) {
- unsigned int k = *(unsigned int*)data;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- // Handle the last few bytes of the input array
- switch (len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- }
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-static unsigned int __fastcall hashstrW(const char *key)
-{
- if (key == nullptr) return 0;
- const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
- char *buf = (char*)alloca(len + 1);
- for (unsigned i = 0; i <= len; ++i)
- buf[i] = key[i << 1];
- return mir_hash(buf, len);
-}
-
-static const MUUID* GetMuid(HPLUGIN pPlugin)
-{
- if (!pPlugin)
- return nullptr;
-
- __try {
- return &pPlugin->getInfo().uuid;
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- return nullptr;
- }
-}
-
-static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
-
- return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1;
-}
-
-static void swapBytes(void *p, size_t iSize)
-{
- char *head = (char*)p; // here
- char *tail = head + iSize - 1;
-
- for (; tail > head; --tail, ++head) {
- char temp = *head;
- *head = *tail;
- *tail = temp;
- }
-}
-
-static bool EnterMuuid(const char *p, MUUID &result)
-{
- if (*p++ != '{')
- return false;
-
- BYTE *d = (BYTE*)&result;
-
- for (int nBytes = 0; *p && nBytes < 24; p++) {
- if (*p == '-')
- continue;
-
- if (*p == '}')
- break;
-
- if (!isxdigit(*p))
- return false;
-
- if (!isxdigit(p[1]))
- return false;
-
- int c = 0;
- if (sscanf(p, "%2x", &c) != 1)
- return false;
-
- *d++ = (BYTE)c;
- nBytes++;
- p++;
- }
-
- if (*p != '}')
- return false;
-
- swapBytes(&result.a, sizeof(result.a));
- swapBytes(&result.b, sizeof(result.b));
- swapBytes(&result.c, sizeof(result.c));
- return true;
-}
-
-static void LoadLangPackFile(FILE *fp, char *line)
-{
- while (!feof(fp)) {
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- rtrim(line);
-
- if (line[0] == '#') {
- strlwr(line);
-
- if (!memcmp(line + 1, "include", 7)) {
- wchar_t tszFileName[MAX_PATH];
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- if (p)
- *p = 0;
- mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9));
- if (p)
- *p = '\\';
-
- FILE *fpNew = _wfopen(tszFileName, L"r");
- if (fpNew) {
- line[0] = 0;
- fgets(line, LANGPACK_BUF_SIZE, fpNew);
-
- if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- fseek(fpNew, 3, SEEK_SET);
- else
- fseek(fpNew, 0, SEEK_SET);
-
- LoadLangPackFile(fpNew, line);
- fclose(fpNew);
- }
- }
- else if (!memcmp(line + 1, "muuid", 5)) {
- MUUID t;
- if (!EnterMuuid(line + 7, t))
- continue;
-
- MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID));
- memcpy(pNew, &t, sizeof(t));
- lMuuids.insert(pNew);
- pCurrentMuuid = pNew;
- }
-
- continue;
- }
-
- char cFirst = line[0];
-
- ConvertBackslashes(line, CP_UTF8);
-
- size_t cbLen = strlen(line) - 1;
- if (cFirst == '[' && line[cbLen] == ']') {
- if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr)
- g_entryCount--;
-
- char *pszLine = line + 1;
- line[cbLen] = '\0';
- if (++g_entryCount > g_entriesAlloced) {
- g_entriesAlloced += 128;
- g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced);
- }
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- E->englishHash = mir_hashstr(pszLine);
- E->szLocal = E->utfLocal = nullptr;
- E->wszLocal = nullptr;
- E->pMuuid = pCurrentMuuid;
- E->pNext = nullptr;
- continue;
- }
-
- if (!g_entryCount)
- continue;
-
- LangPackEntry *E = &g_pEntries[g_entryCount - 1];
- int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen;
- if (E->wszLocal == nullptr) {
- iOldLen = 0;
- E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded);
- }
- else {
- iOldLen = (int)wcslen(E->wszLocal);
- E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2)));
- E->wszLocal[iOldLen++] = '\n';
- }
- MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded);
- }
-}
-
-static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine)
-{
- char szLanguage[64]; szLanguage[0] = 0;
- CMStringA szAuthors;
-
- lpinfo.codepage = CP_ACP;
- lpinfo.flags = 0;
- lpinfo.tszLanguage[0] = 0;
-
- fgets(line, LANGPACK_BUF_SIZE, fp);
- size_t lineLen = strlen(line);
- if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
- memmove(line, line + 3, lineLen - 2);
-
- lrtrim(line);
- if (mir_strcmp(line, "Miranda Language Pack Version 1"))
- return 2;
-
- // headers
- while (!feof(fp)) {
- startOfLine = ftell(fp);
- if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
- break;
-
- lrtrim(line);
- if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
- continue;
-
- if (line[0] == '[' || line[0] == '#')
- break;
-
- char *pszColon = strchr(line, ':');
- if (pszColon == nullptr)
- return 3;
-
- *pszColon++ = 0;
- if (!mir_strcmp(line, "Language")) {
- strncpy_s(szLanguage, pszColon, _TRUNCATE);
- lrtrim(szLanguage);
- }
- else if (!mir_strcmp(line, "Last-Modified-Using")) {
- lpinfo.szLastModifiedUsing = pszColon;
- lpinfo.szLastModifiedUsing.Trim();
- }
- else if (!mir_strcmp(line, "Authors")) {
- if (!szAuthors.IsEmpty())
- szAuthors.AppendChar(' ');
- szAuthors.Append(lrtrim(pszColon));
- }
- else if (!mir_strcmp(line, "Locale")) {
- char szBuf[20], *stopped;
-
- lrtrim(pszColon + 1);
- USHORT langID = (USHORT)strtol(pszColon, &stopped, 16);
- lpinfo.Locale = MAKELCID(langID, 0);
- GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
- szBuf[5] = 0; // codepages have max. 5 digits
- lpinfo.codepage = atoi(szBuf);
- }
- }
-
- lpinfo.szAuthors = szAuthors;
-
- ptrW buf(mir_utf8decodeW(szLanguage));
- if (buf)
- wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE);
- else if (lpinfo.Locale != 0)
- GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage));
-
- if (!lpinfo.tszLanguage[0]) {
- wchar_t *p = wcschr(lpinfo.tszFileName, '_');
- wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE);
- p = wcsrchr(lpinfo.tszLanguage, '.');
- if (p != nullptr) *p = '\0';
- }
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack)
-{
- if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L""))
- return 1;
-
- // ensure that a lang's name is a full file name
- wchar_t tszFullPath[MAX_PATH];
- if (!PathIsAbsoluteW(ptszLangPack))
- mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack);
- else
- wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE);
-
- // this lang is already loaded? nothing to do then
- if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath))
- return 0;
-
- // ok... loading a new langpack. remove the old one if needed
- if (g_entryCount)
- UnloadLangPackModule();
-
- langPack.Locale = 0;
- langPack.codepage = CP_ACP;
- langPack.flags = 0;
-
- // exists & not a directory?
- DWORD dwAttrib = GetFileAttributes(tszFullPath);
- if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
- return 3;
-
- // copy the full file name and extract a file name from it
- wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE);
- wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
- wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE);
- CharLower(langPack.tszFileName);
-
- FILE *fp = _wfopen(tszFullPath, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- if (LoadLangDescr(langPack, fp, line, startOfLine)) {
- fclose(fp);
- return 1;
- }
-
- // body
- fseek(fp, startOfLine, SEEK_SET);
-
- LoadLangPackFile(fp, line);
- fclose(fp);
- pCurrentMuuid = nullptr;
-
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- return 0;
-}
-
-MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo)
-{
- if (lpInfo == nullptr)
- return 1;
-
- wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE);
- wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\');
- wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE);
- CharLower(lpInfo->tszFileName);
-
- FILE *fp = _wfopen(ptszLangPack, L"rt");
- if (fp == nullptr)
- return 1;
-
- char line[LANGPACK_BUF_SIZE] = "";
- int startOfLine = 0;
- int res = LoadLangDescr(*lpInfo, fp, line, startOfLine);
- fclose(fp);
- return res;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2)
-{
- if (arg1->englishHash < arg2->englishHash) return -1;
- if (arg1->englishHash > arg2->englishHash) return 1;
- return 0;
-}
-
-char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W)
-{
- if (g_entryCount == 0 || szEnglish == nullptr)
- return (char*)szEnglish;
-
- LangPackEntry key, *entry;
- key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish);
- entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2);
- if (entry == nullptr)
- return (char*)szEnglish;
-
- // try to find the exact match, otherwise the first entry will be returned
- if (pUuid) {
- for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) {
- if (*p->pMuuid == *pUuid) {
- entry = p;
- break;
- }
- }
- }
-
- switch (W) {
- case 0:
- if (entry->szLocal == nullptr && entry->wszLocal != nullptr)
- entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage);
- return entry->szLocal;
-
- case 1:
- return (char*)entry->wszLocal;
-
- case 2:
- if (entry->utfLocal == nullptr && entry->wszLocal != nullptr)
- entry->utfLocal = mir_utf8encodeW(entry->wszLocal);
- return entry->utfLocal;
- }
-
- return nullptr;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultCodePage()
-{
- return langPack.codepage;
-}
-
-MIR_CORE_DLL(int) Langpack_GetDefaultLocale()
-{
- return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale;
-}
-
-MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr)
-{
- if (pszStr == nullptr)
- return nullptr;
-
- int len = (int)strlen(pszStr);
- wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t));
- MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len);
- result[len] = 0;
- return mir_wstrdup(TranslateW_LP(result));
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0);
-}
-
-MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin)
-{
- return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2);
-}
-
-MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin)
-{
- return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1);
-}
-
-MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin)
-{
- const MUUID *uuid = &pPlugin->getInfo().uuid;
-
- MENUITEMINFO mii = { 0 };
- mii.cbSize = sizeof(mii);
-
- for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) {
- wchar_t str[256];
- mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
- mii.dwTypeData = (wchar_t*)str;
- mii.cch = _countof(str);
- GetMenuItemInfo(hMenu, i, TRUE, &mii);
-
- if (mii.cch && mii.dwTypeData) {
- wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE);
- if (result != mii.dwTypeData) {
- mii.dwTypeData = result;
- mii.fMask = MIIM_TYPE;
- SetMenuItemInfo(hMenu, i, TRUE, &mii);
- }
- }
-
- if (mii.hSubMenu != nullptr)
- TranslateMenu_LP(mii.hSubMenu, pPlugin);
- }
-}
-
-static void TranslateWindow(const MUUID *pUuid, HWND hwnd)
-{
- wchar_t title[2048];
- GetWindowText(hwnd, title, _countof(title));
-
- wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE);
- if (result != title)
- SetWindowText(hwnd, result);
-}
-
-static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam)
-{
- HPLUGIN pPlugin = (HPLUGIN)lParam;
- const MUUID *uuid = GetMuid(pPlugin);
-
- wchar_t szClass[32];
- GetClassName(hwnd, szClass, _countof(szClass));
- if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl"))
- TranslateWindow(uuid, hwnd);
- else if (!mir_wstrcmpi(szClass, L"edit")) {
- if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
- TranslateWindow(uuid, hwnd);
- }
- return TRUE;
-}
-
-MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin)
-{
- TranslateWindow(GetMuid(pPlugin), hDlg);
- EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) Langpack_SortDuplicates(void)
-{
- if (g_entryCount == 0)
- return;
-
- LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries;
- DWORD dwSavedHash = g_pEntries->englishHash;
- bool bSortNeeded = false;
-
- for (int i = 1; i < g_entryCount; i++, s++) {
- if (s->englishHash != dwSavedHash) {
- pLast = d;
- if (s != d)
- *d++ = *s;
- else
- d++;
- dwSavedHash = s->englishHash;
- }
- else {
- bSortNeeded = true;
- LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry));
- *p = *s;
- pLast->pNext = p; pLast = p;
- }
- }
-
- if (bSortNeeded) {
- g_entryCount = (int)(d - g_pEntries);
- qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void GetDefaultLang()
-{
- // calculate the langpacks' root
- PathToAbsoluteW(L"\\Languages", g_tszRoot);
- if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists
- PathToAbsoluteW(L".", g_tszRoot);
-
- // look into mirandaboot.ini
- wchar_t tszLangName[256];
- Profile_GetSetting(L"Language/DefaultLanguage", tszLangName);
- if (tszLangName[0]) {
- if (!mir_wstrcmpi(tszLangName, L"default")) {
- db_set_ws(0, "Langpack", "Current", L"default");
- return;
- }
- if (!LoadLangPack(tszLangName)) {
- db_set_ws(0, "Langpack", "Current", tszLangName);
- return;
- }
- }
-
- // try to load langpack that matches UserDefaultUILanguage
- wchar_t tszPath[MAX_PATH];
- if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) {
- mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName));
- if (!LoadLangPack(tszPath)) {
- db_set_ws(0, "Langpack", "Current", tszPath);
- return;
- }
- }
-
- // finally try to load first file
- mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot);
-
- WIN32_FIND_DATA fd;
- HANDLE hFind = FindFirstFile(tszPath, &fd);
- if (hFind != INVALID_HANDLE_VALUE) {
- do {
- /* search first langpack that could be loaded */
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- if (!LoadLangPack(fd.cFileName)) {
- db_set_ws(0, "Langpack", "Current", fd.cFileName);
- break;
- }
- } while (FindNextFile(hFind, &fd));
- FindClose(hFind);
- }
- else db_set_ws(0, "Langpack", "Current", L"default");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr)
-{
- if (pszStr == nullptr)
- pszStr = NEWWSTR_ALLOCA(langPack.tszFileName);
-
- UnloadLangPackModule();
- LoadLangPack(pszStr);
- Langpack_SortDuplicates();
-
- NotifyEventHooks(hevChanged, 0, 0);
-}
-
-static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam)
-{
- ReloadLangpack((wchar_t*)lParam);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) LoadLangPackModule(void)
-{
- bModuleInitialized = TRUE;
- hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED);
- CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack);
- GetDefaultLang();
- return 0;
-}
-
-void UnloadLangPackModule()
-{
- if (!bModuleInitialized) return;
-
- for (auto &it : lMuuids)
- mir_free(it);
- lMuuids.destroy();
-
- LangPackEntry *p = g_pEntries;
- for (int i = 0; i < g_entryCount; i++, p++) {
- if (p->pNext != nullptr) {
- for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) {
- LangPackEntry *p2 = p1; p1 = p1->pNext;
- mir_free(p2->szLocal);
- mir_free(p2->wszLocal);
- mir_free(p2);
- }
- }
-
- mir_free(p->szLocal);
- mir_free(p->wszLocal);
- }
-
- if (g_entryCount) {
- mir_free(g_pEntries);
- g_pEntries = nullptr;
- g_entryCount = g_entriesAlloced = 0;
- }
-
- langPack.tszFileName[0] = langPack.tszFullPath[0] = 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+#include "../../../mir_app/src/langpack.h"
+
+#define LANGPACK_BUF_SIZE 4000
+
+static int CompareMuuids(const MUUID *p1, const MUUID *p2)
+{
+ return memcmp(p1, p2, sizeof(MUUID));
+}
+
+static LIST<MUUID> lMuuids(10, CompareMuuids);
+static MUUID *pCurrentMuuid = nullptr;
+static HANDLE hevChanged = nullptr;
+
+static BOOL bModuleInitialized = FALSE;
+
+struct LangPackEntry
+{
+ DWORD englishHash;
+ char *szLocal;
+ char *utfLocal;
+ wchar_t *wszLocal;
+ MUUID *pMuuid;
+ LangPackEntry* pNext; // for langpack items with the same hash value
+};
+
+static LANGPACK_INFO langPack;
+static wchar_t g_tszRoot[MAX_PATH];
+
+static LangPackEntry *g_pEntries;
+static int g_entryCount, g_entriesAlloced;
+
+static int IsEmpty(const char *str)
+{
+ for (int i = 0; str[i]; i++)
+ if (str[i] != ' ' && str[i] != '\r' && str[i] != '\n')
+ return 0;
+
+ return 1;
+}
+
+static int ConvertBackslashes(char *str, UINT fileCp)
+{
+ int shift = 0;
+ char *pstr;
+ for (pstr = str; *pstr; pstr = CharNextExA(fileCp, pstr, 0)) {
+ if (*pstr == '\\') {
+ shift++;
+ switch (pstr[1]) {
+ case 'n': *pstr = '\n'; break;
+ case 't': *pstr = '\t'; break;
+ case 'r': *pstr = '\r'; break;
+ case 's': *pstr = ' '; break;
+ default: *pstr = pstr[1]; break;
+ }
+ memmove(pstr + 1, pstr + 2, strlen(pstr + 2) + 1);
+ }
+ }
+ return shift;
+}
+
+#ifdef _DEBUG
+//#pragma optimize("gt", on)
+#endif
+
+// MurmurHash2
+MIR_CORE_DLL(unsigned int) mir_hash(const void * key, unsigned int len)
+{
+ // 'm' and 'r' are mixing constants generated offline.
+ // They're not really 'magic', they just happen to work well.
+ const unsigned int m = 0x5bd1e995;
+ const int r = 24;
+
+ // Initialize the hash to a 'random' value
+ unsigned int h = len;
+
+ // Mix 4 bytes at a time into the hash
+ const unsigned char *data = (const unsigned char*)key;
+
+ while (len >= 4) {
+ unsigned int k = *(unsigned int*)data;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ len -= 4;
+ }
+
+ // Handle the last few bytes of the input array
+ switch (len) {
+ case 3: h ^= data[2] << 16;
+ case 2: h ^= data[1] << 8;
+ case 1: h ^= data[0];
+ h *= m;
+ }
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+
+ return h;
+}
+
+static unsigned int __fastcall hashstrW(const char *key)
+{
+ if (key == nullptr) return 0;
+ const unsigned int len = (unsigned int)wcslen((const wchar_t*)key);
+ char *buf = (char*)alloca(len + 1);
+ for (unsigned i = 0; i <= len; ++i)
+ buf[i] = key[i << 1];
+ return mir_hash(buf, len);
+}
+
+static const MUUID* GetMuid(HPLUGIN pPlugin)
+{
+ if (!pPlugin)
+ return nullptr;
+
+ __try {
+ return &pPlugin->getInfo().uuid;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return nullptr;
+ }
+}
+
+static int SortLangPackHashesProc(LangPackEntry *arg1, LangPackEntry *arg2)
+{
+ if (arg1->englishHash < arg2->englishHash) return -1;
+ if (arg1->englishHash > arg2->englishHash) return 1;
+
+ return (arg1->pMuuid < arg2->pMuuid) ? -1 : 1;
+}
+
+static void swapBytes(void *p, size_t iSize)
+{
+ char *head = (char*)p; // here
+ char *tail = head + iSize - 1;
+
+ for (; tail > head; --tail, ++head) {
+ char temp = *head;
+ *head = *tail;
+ *tail = temp;
+ }
+}
+
+static bool EnterMuuid(const char *p, MUUID &result)
+{
+ if (*p++ != '{')
+ return false;
+
+ BYTE *d = (BYTE*)&result;
+
+ for (int nBytes = 0; *p && nBytes < 24; p++) {
+ if (*p == '-')
+ continue;
+
+ if (*p == '}')
+ break;
+
+ if (!isxdigit(*p))
+ return false;
+
+ if (!isxdigit(p[1]))
+ return false;
+
+ int c = 0;
+ if (sscanf(p, "%2x", &c) != 1)
+ return false;
+
+ *d++ = (BYTE)c;
+ nBytes++;
+ p++;
+ }
+
+ if (*p != '}')
+ return false;
+
+ swapBytes(&result.a, sizeof(result.a));
+ swapBytes(&result.b, sizeof(result.b));
+ swapBytes(&result.c, sizeof(result.c));
+ return true;
+}
+
+static void LoadLangPackFile(FILE *fp, char *line)
+{
+ while (!feof(fp)) {
+ if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
+ break;
+
+ if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
+ continue;
+
+ rtrim(line);
+
+ if (line[0] == '#') {
+ strlwr(line);
+
+ if (!memcmp(line + 1, "include", 7)) {
+ wchar_t tszFileName[MAX_PATH];
+ wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
+ if (p)
+ *p = 0;
+ mir_snwprintf(tszFileName, L"%s\\%S", langPack.tszFullPath, ltrim(line + 9));
+ if (p)
+ *p = '\\';
+
+ FILE *fpNew = _wfopen(tszFileName, L"r");
+ if (fpNew) {
+ line[0] = 0;
+ fgets(line, LANGPACK_BUF_SIZE, fpNew);
+
+ if (strlen(line) >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
+ fseek(fpNew, 3, SEEK_SET);
+ else
+ fseek(fpNew, 0, SEEK_SET);
+
+ LoadLangPackFile(fpNew, line);
+ fclose(fpNew);
+ }
+ }
+ else if (!memcmp(line + 1, "muuid", 5)) {
+ MUUID t;
+ if (!EnterMuuid(line + 7, t))
+ continue;
+
+ MUUID *pNew = (MUUID*)mir_alloc(sizeof(MUUID));
+ memcpy(pNew, &t, sizeof(t));
+ lMuuids.insert(pNew);
+ pCurrentMuuid = pNew;
+ }
+
+ continue;
+ }
+
+ char cFirst = line[0];
+
+ ConvertBackslashes(line, CP_UTF8);
+
+ size_t cbLen = strlen(line) - 1;
+ if (cFirst == '[' && line[cbLen] == ']') {
+ if (g_entryCount && g_pEntries[g_entryCount-1].wszLocal == nullptr)
+ g_entryCount--;
+
+ char *pszLine = line + 1;
+ line[cbLen] = '\0';
+ if (++g_entryCount > g_entriesAlloced) {
+ g_entriesAlloced += 128;
+ g_pEntries = (LangPackEntry*)mir_realloc(g_pEntries, sizeof(LangPackEntry)*g_entriesAlloced);
+ }
+
+ LangPackEntry *E = &g_pEntries[g_entryCount - 1];
+ E->englishHash = mir_hashstr(pszLine);
+ E->szLocal = E->utfLocal = nullptr;
+ E->wszLocal = nullptr;
+ E->pMuuid = pCurrentMuuid;
+ E->pNext = nullptr;
+ continue;
+ }
+
+ if (!g_entryCount)
+ continue;
+
+ LangPackEntry *E = &g_pEntries[g_entryCount - 1];
+ int iNeeded = MultiByteToWideChar(CP_UTF8, 0, line, -1, nullptr, 0), iOldLen;
+ if (E->wszLocal == nullptr) {
+ iOldLen = 0;
+ E->wszLocal = (wchar_t *)mir_alloc((iNeeded + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal, iNeeded);
+ }
+ else {
+ iOldLen = (int)wcslen(E->wszLocal);
+ E->wszLocal = (wchar_t*)mir_realloc(E->wszLocal, (sizeof(wchar_t)* (iOldLen + iNeeded + 2)));
+ E->wszLocal[iOldLen++] = '\n';
+ }
+ MultiByteToWideChar(CP_UTF8, 0, line, -1, E->wszLocal + iOldLen, iNeeded);
+ }
+}
+
+static int LoadLangDescr(LANGPACK_INFO &lpinfo, FILE *fp, char *line, int &startOfLine)
+{
+ char szLanguage[64]; szLanguage[0] = 0;
+ CMStringA szAuthors;
+
+ lpinfo.codepage = CP_ACP;
+ lpinfo.flags = 0;
+ lpinfo.tszLanguage[0] = 0;
+
+ fgets(line, LANGPACK_BUF_SIZE, fp);
+ size_t lineLen = strlen(line);
+ if (lineLen >= 3 && line[0] == '\xef' && line[1] == '\xbb' && line[2] == '\xbf')
+ memmove(line, line + 3, lineLen - 2);
+
+ lrtrim(line);
+ if (mir_strcmp(line, "Miranda Language Pack Version 1"))
+ return 2;
+
+ // headers
+ while (!feof(fp)) {
+ startOfLine = ftell(fp);
+ if (fgets(line, LANGPACK_BUF_SIZE, fp) == nullptr)
+ break;
+
+ lrtrim(line);
+ if (IsEmpty(line) || line[0] == ';' || line[0] == 0)
+ continue;
+
+ if (line[0] == '[' || line[0] == '#')
+ break;
+
+ char *pszColon = strchr(line, ':');
+ if (pszColon == nullptr)
+ return 3;
+
+ *pszColon++ = 0;
+ if (!mir_strcmp(line, "Language")) {
+ strncpy_s(szLanguage, pszColon, _TRUNCATE);
+ lrtrim(szLanguage);
+ }
+ else if (!mir_strcmp(line, "Last-Modified-Using")) {
+ lpinfo.szLastModifiedUsing = pszColon;
+ lpinfo.szLastModifiedUsing.Trim();
+ }
+ else if (!mir_strcmp(line, "Authors")) {
+ if (!szAuthors.IsEmpty())
+ szAuthors.AppendChar(' ');
+ szAuthors.Append(lrtrim(pszColon));
+ }
+ else if (!mir_strcmp(line, "Locale")) {
+ char szBuf[20], *stopped;
+
+ lrtrim(pszColon + 1);
+ USHORT langID = (USHORT)strtol(pszColon, &stopped, 16);
+ lpinfo.Locale = MAKELCID(langID, 0);
+ GetLocaleInfoA(lpinfo.Locale, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
+ szBuf[5] = 0; // codepages have max. 5 digits
+ lpinfo.codepage = atoi(szBuf);
+ }
+ }
+
+ lpinfo.szAuthors = szAuthors;
+
+ ptrW buf(mir_utf8decodeW(szLanguage));
+ if (buf)
+ wcsncpy_s(lpinfo.tszLanguage, buf, _TRUNCATE);
+ else if (lpinfo.Locale != 0)
+ GetLocaleInfo(lpinfo.Locale, LOCALE_SENGLANGUAGE, lpinfo.tszLanguage, _countof(lpinfo.tszLanguage));
+
+ if (!lpinfo.tszLanguage[0]) {
+ wchar_t *p = wcschr(lpinfo.tszFileName, '_');
+ wcsncpy_s(lpinfo.tszLanguage, ((p != nullptr) ? (p + 1) : lpinfo.tszFileName), _TRUNCATE);
+ p = wcsrchr(lpinfo.tszLanguage, '.');
+ if (p != nullptr) *p = '\0';
+ }
+ return 0;
+}
+
+MIR_CORE_DLL(int) LoadLangPack(const wchar_t *ptszLangPack)
+{
+ if (ptszLangPack == nullptr || !mir_wstrcmpi(ptszLangPack, L""))
+ return 1;
+
+ // ensure that a lang's name is a full file name
+ wchar_t tszFullPath[MAX_PATH];
+ if (!PathIsAbsoluteW(ptszLangPack))
+ mir_snwprintf(tszFullPath, L"%s\\%s", g_tszRoot, ptszLangPack);
+ else
+ wcsncpy_s(tszFullPath, ptszLangPack, _TRUNCATE);
+
+ // this lang is already loaded? nothing to do then
+ if (!mir_wstrcmp(tszFullPath, langPack.tszFullPath))
+ return 0;
+
+ // ok... loading a new langpack. remove the old one if needed
+ if (g_entryCount)
+ UnloadLangPackModule();
+
+ langPack.Locale = 0;
+ langPack.codepage = CP_ACP;
+ langPack.flags = 0;
+
+ // exists & not a directory?
+ DWORD dwAttrib = GetFileAttributes(tszFullPath);
+ if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
+ return 3;
+
+ // copy the full file name and extract a file name from it
+ wcsncpy_s(langPack.tszFullPath, tszFullPath, _TRUNCATE);
+ wchar_t *p = wcsrchr(langPack.tszFullPath, '\\');
+ wcsncpy_s(langPack.tszFileName, (p == nullptr) ? tszFullPath : p + 1, _TRUNCATE);
+ CharLower(langPack.tszFileName);
+
+ FILE *fp = _wfopen(tszFullPath, L"rt");
+ if (fp == nullptr)
+ return 1;
+
+ char line[LANGPACK_BUF_SIZE] = "";
+ int startOfLine = 0;
+ if (LoadLangDescr(langPack, fp, line, startOfLine)) {
+ fclose(fp);
+ return 1;
+ }
+
+ // body
+ fseek(fp, startOfLine, SEEK_SET);
+
+ LoadLangPackFile(fp, line);
+ fclose(fp);
+ pCurrentMuuid = nullptr;
+
+ qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
+ return 0;
+}
+
+MIR_CORE_DLL(int) LoadLangPackDescr(const wchar_t *ptszLangPack, LANGPACK_INFO *lpInfo)
+{
+ if (lpInfo == nullptr)
+ return 1;
+
+ wcsncpy_s(lpInfo->tszFullPath, ptszLangPack, _TRUNCATE);
+ wchar_t *p = wcsrchr(lpInfo->tszFullPath, '\\');
+ wcsncpy_s(lpInfo->tszFileName, (p == nullptr) ? ptszLangPack : p+1, _TRUNCATE);
+ CharLower(lpInfo->tszFileName);
+
+ FILE *fp = _wfopen(ptszLangPack, L"rt");
+ if (fp == nullptr)
+ return 1;
+
+ char line[LANGPACK_BUF_SIZE] = "";
+ int startOfLine = 0;
+ int res = LoadLangDescr(*lpInfo, fp, line, startOfLine);
+ fclose(fp);
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int SortLangPackHashesProc2(LangPackEntry *arg1, LangPackEntry *arg2)
+{
+ if (arg1->englishHash < arg2->englishHash) return -1;
+ if (arg1->englishHash > arg2->englishHash) return 1;
+ return 0;
+}
+
+char* LangPackTranslateString(const MUUID *pUuid, const char *szEnglish, const int W)
+{
+ if (g_entryCount == 0 || szEnglish == nullptr)
+ return (char*)szEnglish;
+
+ LangPackEntry key, *entry;
+ key.englishHash = (W == 1) ? hashstrW(szEnglish) : mir_hashstr(szEnglish);
+ entry = (LangPackEntry*)bsearch(&key, g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc2);
+ if (entry == nullptr)
+ return (char*)szEnglish;
+
+ // try to find the exact match, otherwise the first entry will be returned
+ if (pUuid) {
+ for (LangPackEntry *p = entry->pNext; p != nullptr; p = p->pNext) {
+ if (*p->pMuuid == *pUuid) {
+ entry = p;
+ break;
+ }
+ }
+ }
+
+ switch (W) {
+ case 0:
+ if (entry->szLocal == nullptr && entry->wszLocal != nullptr)
+ entry->szLocal = mir_u2a_cp(entry->wszLocal, langPack.codepage);
+ return entry->szLocal;
+
+ case 1:
+ return (char*)entry->wszLocal;
+
+ case 2:
+ if (entry->utfLocal == nullptr && entry->wszLocal != nullptr)
+ entry->utfLocal = mir_utf8encodeW(entry->wszLocal);
+ return entry->utfLocal;
+ }
+
+ return nullptr;
+}
+
+MIR_CORE_DLL(int) Langpack_GetDefaultCodePage()
+{
+ return langPack.codepage;
+}
+
+MIR_CORE_DLL(int) Langpack_GetDefaultLocale()
+{
+ return (langPack.Locale == 0) ? LOCALE_USER_DEFAULT : langPack.Locale;
+}
+
+MIR_CORE_DLL(wchar_t*) Langpack_PcharToTchar(const char *pszStr)
+{
+ if (pszStr == nullptr)
+ return nullptr;
+
+ int len = (int)strlen(pszStr);
+ wchar_t *result = (wchar_t*)alloca((len + 1)*sizeof(wchar_t));
+ MultiByteToWideChar(Langpack_GetDefaultCodePage(), 0, pszStr, -1, result, len);
+ result[len] = 0;
+ return mir_wstrdup(TranslateW_LP(result));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(char*) TranslateA_LP(const char *str, HPLUGIN pPlugin)
+{
+ return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 0);
+}
+
+MIR_CORE_DLL(char*) TranslateU_LP(const char *str, HPLUGIN pPlugin)
+{
+ return (char*)LangPackTranslateString(GetMuid(pPlugin), str, 2);
+}
+
+MIR_CORE_DLL(wchar_t*) TranslateW_LP(const wchar_t *str, HPLUGIN pPlugin)
+{
+ return (wchar_t*)LangPackTranslateString(GetMuid(pPlugin), (LPCSTR)str, 1);
+}
+
+MIR_CORE_DLL(void) TranslateMenu_LP(HMENU hMenu, HPLUGIN pPlugin)
+{
+ const MUUID *uuid = &pPlugin->getInfo().uuid;
+
+ MENUITEMINFO mii = { 0 };
+ mii.cbSize = sizeof(mii);
+
+ for (int i = GetMenuItemCount(hMenu) - 1; i >= 0; i--) {
+ wchar_t str[256];
+ mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
+ mii.dwTypeData = (wchar_t*)str;
+ mii.cch = _countof(str);
+ GetMenuItemInfo(hMenu, i, TRUE, &mii);
+
+ if (mii.cch && mii.dwTypeData) {
+ wchar_t *result = (wchar_t*)LangPackTranslateString(uuid, (const char*)mii.dwTypeData, TRUE);
+ if (result != mii.dwTypeData) {
+ mii.dwTypeData = result;
+ mii.fMask = MIIM_TYPE;
+ SetMenuItemInfo(hMenu, i, TRUE, &mii);
+ }
+ }
+
+ if (mii.hSubMenu != nullptr)
+ TranslateMenu_LP(mii.hSubMenu, pPlugin);
+ }
+}
+
+static void TranslateWindow(const MUUID *pUuid, HWND hwnd)
+{
+ wchar_t title[2048];
+ GetWindowText(hwnd, title, _countof(title));
+
+ wchar_t *result = (wchar_t*)LangPackTranslateString(pUuid, (const char*)title, TRUE);
+ if (result != title)
+ SetWindowText(hwnd, result);
+}
+
+static BOOL CALLBACK TranslateDialogEnumProc(HWND hwnd, LPARAM lParam)
+{
+ HPLUGIN pPlugin = (HPLUGIN)lParam;
+ const MUUID *uuid = GetMuid(pPlugin);
+
+ wchar_t szClass[32];
+ GetClassName(hwnd, szClass, _countof(szClass));
+ if (!mir_wstrcmpi(szClass, L"static") || !mir_wstrcmpi(szClass, L"hyperlink") || !mir_wstrcmpi(szClass, L"button") || !mir_wstrcmpi(szClass, L"MButtonClass") || !mir_wstrcmpi(szClass, L"MHeaderbarCtrl"))
+ TranslateWindow(uuid, hwnd);
+ else if (!mir_wstrcmpi(szClass, L"edit")) {
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY)
+ TranslateWindow(uuid, hwnd);
+ }
+ return TRUE;
+}
+
+MIR_CORE_DLL(void) TranslateDialog_LP(HWND hDlg, HPLUGIN pPlugin)
+{
+ TranslateWindow(GetMuid(pPlugin), hDlg);
+ EnumChildWindows(hDlg, TranslateDialogEnumProc, (LPARAM)pPlugin);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) Langpack_SortDuplicates(void)
+{
+ if (g_entryCount == 0)
+ return;
+
+ LangPackEntry *s = g_pEntries + 1, *d = s, *pLast = g_pEntries;
+ DWORD dwSavedHash = g_pEntries->englishHash;
+ bool bSortNeeded = false;
+
+ for (int i = 1; i < g_entryCount; i++, s++) {
+ if (s->englishHash != dwSavedHash) {
+ pLast = d;
+ if (s != d)
+ *d++ = *s;
+ else
+ d++;
+ dwSavedHash = s->englishHash;
+ }
+ else {
+ bSortNeeded = true;
+ LangPackEntry *p = (LangPackEntry*)mir_alloc(sizeof(LangPackEntry));
+ *p = *s;
+ pLast->pNext = p; pLast = p;
+ }
+ }
+
+ if (bSortNeeded) {
+ g_entryCount = (int)(d - g_pEntries);
+ qsort(g_pEntries, g_entryCount, sizeof(LangPackEntry), (int(*)(const void*, const void*))SortLangPackHashesProc);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void GetDefaultLang()
+{
+ // calculate the langpacks' root
+ PathToAbsoluteW(L"\\Languages", g_tszRoot);
+ if (_waccess(g_tszRoot, 0) != 0) // directory Languages exists
+ PathToAbsoluteW(L".", g_tszRoot);
+
+ // look into mirandaboot.ini
+ wchar_t tszLangName[256];
+ Profile_GetSetting(L"Language/DefaultLanguage", tszLangName);
+ if (tszLangName[0]) {
+ if (!mir_wstrcmpi(tszLangName, L"default")) {
+ db_set_ws(0, "Langpack", "Current", L"default");
+ return;
+ }
+ if (!LoadLangPack(tszLangName)) {
+ db_set_ws(0, "Langpack", "Current", tszLangName);
+ return;
+ }
+ }
+
+ // try to load langpack that matches UserDefaultUILanguage
+ wchar_t tszPath[MAX_PATH];
+ if (GetLocaleInfo(MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, tszLangName, _countof(tszLangName))) {
+ mir_snwprintf(tszPath, L"langpack_%s.txt", wcslwr(tszLangName));
+ if (!LoadLangPack(tszPath)) {
+ db_set_ws(0, "Langpack", "Current", tszPath);
+ return;
+ }
+ }
+
+ // finally try to load first file
+ mir_snwprintf(tszPath, L"%s\\langpack_*.txt", g_tszRoot);
+
+ WIN32_FIND_DATA fd;
+ HANDLE hFind = FindFirstFile(tszPath, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ /* search first langpack that could be loaded */
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ if (!LoadLangPack(fd.cFileName)) {
+ db_set_ws(0, "Langpack", "Current", fd.cFileName);
+ break;
+ }
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+ else db_set_ws(0, "Langpack", "Current", L"default");
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) ReloadLangpack(wchar_t *pszStr)
+{
+ if (pszStr == nullptr)
+ pszStr = NEWWSTR_ALLOCA(langPack.tszFileName);
+
+ UnloadLangPackModule();
+ LoadLangPack(pszStr);
+ Langpack_SortDuplicates();
+
+ NotifyEventHooks(hevChanged, 0, 0);
+}
+
+static INT_PTR srvReloadLangpack(WPARAM, LPARAM lParam)
+{
+ ReloadLangpack((wchar_t*)lParam);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) LoadLangPackModule(void)
+{
+ bModuleInitialized = TRUE;
+ hevChanged = CreateHookableEvent(ME_LANGPACK_CHANGED);
+ CreateServiceFunction(MS_LANGPACK_RELOAD, srvReloadLangpack);
+ GetDefaultLang();
+ return 0;
+}
+
+void UnloadLangPackModule()
+{
+ if (!bModuleInitialized) return;
+
+ for (auto &it : lMuuids)
+ mir_free(it);
+ lMuuids.destroy();
+
+ LangPackEntry *p = g_pEntries;
+ for (int i = 0; i < g_entryCount; i++, p++) {
+ if (p->pNext != nullptr) {
+ for (LangPackEntry *p1 = p->pNext; p1 != nullptr;) {
+ LangPackEntry *p2 = p1; p1 = p1->pNext;
+ mir_free(p2->szLocal);
+ mir_free(p2->wszLocal);
+ mir_free(p2);
+ }
+ }
+
+ mir_free(p->szLocal);
+ mir_free(p->wszLocal);
+ }
+
+ if (g_entryCount) {
+ mir_free(g_pEntries);
+ g_pEntries = nullptr;
+ g_entryCount = g_entriesAlloced = 0;
+ }
+
+ langPack.tszFileName[0] = langPack.tszFullPath[0] = 0;
+}
diff --git a/src/mir_core/src/locks.cpp b/src/mir_core/src/Windows/locks.cpp
index 2855974dea..809926f2b9 100644
--- a/src/mir_core/src/locks.cpp
+++ b/src/mir_core/src/Windows/locks.cpp
@@ -22,7 +22,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "stdafx.h"
+#include "../stdafx.h"
mir_cs::mir_cs()
{
diff --git a/src/mir_core/src/miranda.cpp b/src/mir_core/src/Windows/miranda.cpp
index 9a0915e53c..ba7ac7bf96 100644
--- a/src/mir_core/src/miranda.cpp
+++ b/src/mir_core/src/Windows/miranda.cpp
@@ -1,149 +1,149 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "stdafx.h"
-
-HWND hAPCWindow = nullptr;
-
-int InitPathUtils(void);
-void RecalculateTime(void);
-
-void CheckLogs();
-void InitLogs();
-void UninitLogs();
-
-void InitColourPicker();
-void InitHyperlink();
-void InitTimeZones();
-void InitWinver();
-
-HINSTANCE g_hInst = nullptr;
-
-HCURSOR g_hCursorNS, g_hCursorWE;
-HANDLE hThreadQueueEmpty;
-DWORD mir_tls = 0;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam)
-{
- wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH];
- if (lParam)
- wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE);
- else
- GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath));
-
- if (wParam) {
- VARSW profilename(L"%miranda_profilename%");
- mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename);
- }
- else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId());
-
- CallService("CloseAction", 0, 0);
-
- PROCESS_INFORMATION pi;
- STARTUPINFO startupInfo = { 0 };
- startupInfo.cb = sizeof(startupInfo);
- CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// module init
-
-static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- if (msg == WM_USER+1) {
- PAPCFUNC pFunc = (PAPCFUNC)wParam;
- pFunc((ULONG_PTR)lParam);
- return 0;
- }
-
- if (msg == WM_TIMER)
- CheckLogs();
-
- if (msg == WM_TIMECHANGE)
- RecalculateTime();
-
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-static void LoadCoreModule(void)
-{
- INITCOMMONCONTROLSEX icce = {0};
- icce.dwSize = sizeof(icce);
- icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES;
- InitCommonControlsEx(&icce);
-
- hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
- SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW);
- DestroyWindow(hAPCWindow);
-
- hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
- SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc);
- SetTimer(hAPCWindow, 1, 1000, nullptr);
- hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr);
-
- InitWinver();
- InitPathUtils();
- InitLogs();
- InitColourPicker();
- InitHyperlink();
- InitTimeZones();
- InitialiseModularEngine();
-
- CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda);
-
- pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036");
-}
-
-MIR_CORE_DLL(void) UnloadCoreModule(void)
-{
- DestroyWindow(hAPCWindow);
- CloseHandle(hThreadQueueEmpty);
- TlsFree(mir_tls);
-
- DestroyModularEngine();
- UninitLogs();
- UnloadLangPackModule();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// entry point
-
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
-{
- if (fdwReason == DLL_PROCESS_ATTACH) {
- g_hInst = hinstDLL;
- mir_tls = TlsAlloc();
- LoadCoreModule();
- }
- else if (fdwReason == DLL_THREAD_DETACH) {
- HANDLE hEvent = TlsGetValue(mir_tls);
- if (hEvent)
- CloseHandle(hEvent);
- }
- return TRUE;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+HWND hAPCWindow = nullptr;
+
+int InitPathUtils(void);
+void RecalculateTime(void);
+
+void CheckLogs();
+void InitLogs();
+void UninitLogs();
+
+void InitColourPicker();
+void InitHyperlink();
+void InitTimeZones();
+void InitWinver();
+
+HINSTANCE g_hInst = nullptr;
+
+HCURSOR g_hCursorNS, g_hCursorWE;
+HANDLE hThreadQueueEmpty;
+DWORD mir_tls = 0;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR RestartMiranda(WPARAM wParam, LPARAM lParam)
+{
+ wchar_t mirandaPath[MAX_PATH], cmdLine[MAX_PATH];
+ if (lParam)
+ wcsncpy_s(mirandaPath, (const wchar_t*)lParam, _TRUNCATE);
+ else
+ GetModuleFileName(nullptr, mirandaPath, _countof(mirandaPath));
+
+ if (wParam) {
+ VARSW profilename(L"%miranda_profilename%");
+ mir_snwprintf(cmdLine, L"\"%s\" /restart:%d /profile=%s", mirandaPath, GetCurrentProcessId(), (wchar_t*)profilename);
+ }
+ else mir_snwprintf(cmdLine, L"\"%s\" /restart:%d", mirandaPath, GetCurrentProcessId());
+
+ CallService("CloseAction", 0, 0);
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO startupInfo = { 0 };
+ startupInfo.cb = sizeof(startupInfo);
+ CreateProcess(mirandaPath, cmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &pi);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// module init
+
+static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (msg == WM_USER+1) {
+ PAPCFUNC pFunc = (PAPCFUNC)wParam;
+ pFunc((ULONG_PTR)lParam);
+ return 0;
+ }
+
+ if (msg == WM_TIMER)
+ CheckLogs();
+
+ if (msg == WM_TIMECHANGE)
+ RecalculateTime();
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+static void LoadCoreModule(void)
+{
+ INITCOMMONCONTROLSEX icce = {0};
+ icce.dwSize = sizeof(icce);
+ icce.dwICC = ICC_WIN95_CLASSES | ICC_USEREX_CLASSES;
+ InitCommonControlsEx(&icce);
+
+ hAPCWindow = CreateWindowEx(0, L"ComboLBox", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
+ SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW);
+ DestroyWindow(hAPCWindow);
+
+ hAPCWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
+ SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc);
+ SetTimer(hAPCWindow, 1, 1000, nullptr);
+ hThreadQueueEmpty = CreateEvent(nullptr, TRUE, TRUE, nullptr);
+
+ InitWinver();
+ InitPathUtils();
+ InitLogs();
+ InitColourPicker();
+ InitHyperlink();
+ InitTimeZones();
+ InitialiseModularEngine();
+
+ CreateServiceFunction(MS_SYSTEM_RESTART, RestartMiranda);
+
+ pfnRtlGenRandom = (PGENRANDOM)GetProcAddress(GetModuleHandleA("advapi32"), "SystemFunction036");
+}
+
+MIR_CORE_DLL(void) UnloadCoreModule(void)
+{
+ DestroyWindow(hAPCWindow);
+ CloseHandle(hThreadQueueEmpty);
+ TlsFree(mir_tls);
+
+ DestroyModularEngine();
+ UninitLogs();
+ UnloadLangPackModule();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// entry point
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH) {
+ g_hInst = hinstDLL;
+ mir_tls = TlsAlloc();
+ LoadCoreModule();
+ }
+ else if (fdwReason == DLL_THREAD_DETACH) {
+ HANDLE hEvent = TlsGetValue(mir_tls);
+ if (hEvent)
+ CloseHandle(hEvent);
+ }
+ return TRUE;
+}
diff --git a/src/mir_core/src/openurl.cpp b/src/mir_core/src/Windows/openurl.cpp
index abc66f920b..40dc3ca54a 100644
--- a/src/mir_core/src/openurl.cpp
+++ b/src/mir_core/src/Windows/openurl.cpp
@@ -1,76 +1,76 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-#include <ctype.h>
-
-struct TOpenUrlInfo
-{
- TOpenUrlInfo(wchar_t *_url, int _bNew) :
- szUrl(_url),
- newWindow(_bNew)
- {}
-
- ptrW szUrl;
- int newWindow;
-};
-
-static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo)
-{
- // wack a protocol on it
- CMStringW tszUrl;
- if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\')
- tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get());
- else {
- int i;
- for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++);
- if (hUrlInfo->szUrl[i] == ':')
- tszUrl = hUrlInfo->szUrl;
- else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4))
- tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get());
- else
- tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get());
- }
-
- // check user defined browser for opening urls
- ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser"));
- if (tszBrowser)
- ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
- else
- ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
-
- delete hUrlInfo;
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow));
-}
-
-MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow)
-{
- if (pszUrl)
- mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow));
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+#include <ctype.h>
+
+struct TOpenUrlInfo
+{
+ TOpenUrlInfo(wchar_t *_url, int _bNew) :
+ szUrl(_url),
+ newWindow(_bNew)
+ {}
+
+ ptrW szUrl;
+ int newWindow;
+};
+
+static void __cdecl OpenURLThread(TOpenUrlInfo *hUrlInfo)
+{
+ // wack a protocol on it
+ CMStringW tszUrl;
+ if ((isalpha(hUrlInfo->szUrl[0]) && hUrlInfo->szUrl[1] == ':') || hUrlInfo->szUrl[0] == '\\')
+ tszUrl.Format(L"file:///%s", hUrlInfo->szUrl.get());
+ else {
+ int i;
+ for (i = 0; iswalpha(hUrlInfo->szUrl[i]); i++);
+ if (hUrlInfo->szUrl[i] == ':')
+ tszUrl = hUrlInfo->szUrl;
+ else if (!wcsnicmp(hUrlInfo->szUrl, L"ftp.", 4))
+ tszUrl.Format(L"ftp://%s", hUrlInfo->szUrl.get());
+ else
+ tszUrl.Format(L"http://%s", hUrlInfo->szUrl.get());
+ }
+
+ // check user defined browser for opening urls
+ ptrW tszBrowser(db_get_wsa(0, "Miranda", "OpenUrlBrowser"));
+ if (tszBrowser)
+ ShellExecute(nullptr, L"open", tszBrowser, tszUrl, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
+ else
+ ShellExecute(nullptr, L"open", tszUrl, nullptr, nullptr, (hUrlInfo->newWindow) ? SW_NORMAL : SW_SHOWDEFAULT);
+
+ delete hUrlInfo;
+}
+
+MIR_CORE_DLL(void) Utils_OpenUrl(const char *pszUrl, bool bOpenInNewWindow)
+{
+ if (pszUrl)
+ mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_a2u(pszUrl), bOpenInNewWindow));
+}
+
+MIR_CORE_DLL(void) Utils_OpenUrlW(const wchar_t *pszUrl, bool bOpenInNewWindow)
+{
+ if (pszUrl)
+ mir_forkThread<TOpenUrlInfo>(OpenURLThread, new TOpenUrlInfo(mir_wstrdup(pszUrl), bOpenInNewWindow));
+}
diff --git a/src/mir_core/src/path.cpp b/src/mir_core/src/Windows/path.cpp
index c26e712d06..a09c44a1cb 100644
--- a/src/mir_core/src/path.cpp
+++ b/src/mir_core/src/Windows/path.cpp
@@ -1,246 +1,246 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-static char szMirandaPath[MAX_PATH];
-static wchar_t szMirandaPathW[MAX_PATH];
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsolute(const char *path)
-{
- if (path && strlen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- if (!PathIsAbsolute(pSrc))
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPath;
-
- size_t cbBaseLen = strlen(pBase);
- if (!strnicmp(pSrc, pBase, cbBaseLen))
- strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
-
- return (int)strlen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base)
-{
- if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- char buf[MAX_PATH];
- if (pSrc[0] < ' ')
- strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
-
- if (PathIsAbsolute(pSrc))
- return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPath;
-
- if (pSrc[0] == '\\')
- pSrc++;
- mir_snprintf(buf, "%s%s", base, pSrc);
- return GetFullPathNameA(buf, _countof(buf), pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath)
-{
- if (szFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- char *buf = NEWSTR_ALLOCA(szFilePath);
- char *p = strrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTree(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- DWORD dwAttributes = GetFileAttributesA(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- char szTestDir[MAX_PATH];
- mir_strncpy(szTestDir, szDir, _countof(szTestDir));
- char *pszLastBackslash = strrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTree(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path)
-{
- if (path && wcslen(path) > 2)
- if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
- return 1;
- return 0;
-}
-
-MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH)
- return 0;
-
- if (!PathIsAbsoluteW(pSrc))
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- else {
- if (pBase == nullptr)
- pBase = szMirandaPathW;
-
- size_t cbBaseLen = wcslen(pBase);
- if (!wcsnicmp(pSrc, pBase, cbBaseLen))
- wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
- else
- wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
- }
- return (int)wcslen(pOut);
-}
-
-MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base)
-{
- if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) {
- *pOut = 0;
- return 0;
- }
-
- wchar_t buf[MAX_PATH];
- if (pSrc[0] < ' ')
- return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc);
-
- if (PathIsAbsoluteW(pSrc))
- return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr);
-
- if (base == nullptr)
- base = szMirandaPathW;
-
- if (pSrc[0] == '\\')
- pSrc++;
-
- mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc);
- return GetFullPathName(buf, MAX_PATH, pOut, nullptr);
-}
-
-MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath)
-{
- if (wszFilePath == nullptr)
- return ERROR_INVALID_PARAMETER;
-
- wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath);
- wchar_t *p = wcsrchr(buf, '\\');
- if (p == nullptr)
- return 0;
-
- *p = '\0';
- return CreateDirectoryTreeW(buf);
-}
-
-MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir)
-{
- if (szDir == nullptr)
- return 1;
-
- DWORD dwAttributes = GetFileAttributesW(szDir);
- if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
-
- wchar_t szTestDir[MAX_PATH];
- mir_wstrncpy(szTestDir, szDir, _countof(szTestDir));
- wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\');
- if (pszLastBackslash == nullptr)
- return 0;
-
- *pszLastBackslash = '\0';
- CreateDirectoryTreeW(szTestDir);
- *pszLastBackslash = '\\';
- return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0;
-}
-
-MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo)
-{
- if (pwszDir == nullptr)
- return ERROR_BAD_ARGUMENTS;
-
- CMStringW wszPath(pwszDir);
- wszPath.AppendChar(0);
-
- SHFILEOPSTRUCTW file_op = {
- nullptr,
- FO_DELETE,
- wszPath,
- L"",
- FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION,
- false,
- nullptr,
- L"" };
-
- if (bAllowUndo)
- file_op.fFlags |= FOF_ALLOWUNDO;
-
- return SHFileOperationW(&file_op);
-}
-
-int InitPathUtils(void)
-{
- GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath));
- char *p = strrchr(szMirandaPath, '\\');
- if (p)
- p[1] = 0;
-
- GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW));
- wchar_t *tp = wcsrchr(szMirandaPathW, '\\');
- if (tp)
- tp[1] = 0;
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+static char szMirandaPath[MAX_PATH];
+static wchar_t szMirandaPathW[MAX_PATH];
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) PathIsAbsolute(const char *path)
+{
+ if (path && strlen(path) > 2)
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+MIR_CORE_DLL(int) PathToRelative(const char *pSrc, char *pOut, const char *pBase)
+{
+ if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ if (!PathIsAbsolute(pSrc))
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ else {
+ if (pBase == nullptr)
+ pBase = szMirandaPath;
+
+ size_t cbBaseLen = strlen(pBase);
+ if (!strnicmp(pSrc, pBase, cbBaseLen))
+ strncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
+ else
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ }
+
+ return (int)strlen(pOut);
+}
+
+MIR_CORE_DLL(int) PathToAbsolute(const char *pSrc, char *pOut, const char *base)
+{
+ if (!pSrc || !pSrc[0] || strlen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ char buf[MAX_PATH];
+ if (pSrc[0] < ' ')
+ strncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+
+ if (PathIsAbsolute(pSrc))
+ return GetFullPathNameA(pSrc, MAX_PATH, pOut, nullptr);
+
+ if (base == nullptr)
+ base = szMirandaPath;
+
+ if (pSrc[0] == '\\')
+ pSrc++;
+ mir_snprintf(buf, "%s%s", base, pSrc);
+ return GetFullPathNameA(buf, _countof(buf), pOut, nullptr);
+}
+
+MIR_CORE_DLL(int) CreatePathToFile(const char *szFilePath)
+{
+ if (szFilePath == nullptr)
+ return ERROR_INVALID_PARAMETER;
+
+ char *buf = NEWSTR_ALLOCA(szFilePath);
+ char *p = strrchr(buf, '\\');
+ if (p == nullptr)
+ return 0;
+
+ *p = '\0';
+ return CreateDirectoryTree(buf);
+}
+
+MIR_CORE_DLL(int) CreateDirectoryTree(const char *szDir)
+{
+ if (szDir == nullptr)
+ return 1;
+
+ DWORD dwAttributes = GetFileAttributesA(szDir);
+ if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ return 0;
+
+ char szTestDir[MAX_PATH];
+ mir_strncpy(szTestDir, szDir, _countof(szTestDir));
+ char *pszLastBackslash = strrchr(szTestDir, '\\');
+ if (pszLastBackslash == nullptr)
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTree(szTestDir);
+ *pszLastBackslash = '\\';
+ return (CreateDirectoryA(szTestDir, nullptr) == 0) ? GetLastError() : 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) PathIsAbsoluteW(const wchar_t *path)
+{
+ if (path && wcslen(path) > 2)
+ if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
+ return 1;
+ return 0;
+}
+
+MIR_CORE_DLL(int) PathToRelativeW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *pBase)
+{
+ if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH)
+ return 0;
+
+ if (!PathIsAbsoluteW(pSrc))
+ wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ else {
+ if (pBase == nullptr)
+ pBase = szMirandaPathW;
+
+ size_t cbBaseLen = wcslen(pBase);
+ if (!wcsnicmp(pSrc, pBase, cbBaseLen))
+ wcsncpy_s(pOut, MAX_PATH, pSrc + cbBaseLen, _TRUNCATE);
+ else
+ wcsncpy_s(pOut, MAX_PATH, pSrc, _TRUNCATE);
+ }
+ return (int)wcslen(pOut);
+}
+
+MIR_CORE_DLL(int) PathToAbsoluteW(const wchar_t *pSrc, wchar_t *pOut, const wchar_t *base)
+{
+ if (!pSrc || !pSrc[0] || wcslen(pSrc) > MAX_PATH) {
+ *pOut = 0;
+ return 0;
+ }
+
+ wchar_t buf[MAX_PATH];
+ if (pSrc[0] < ' ')
+ return mir_snwprintf(pOut, MAX_PATH, L"%s", pSrc);
+
+ if (PathIsAbsoluteW(pSrc))
+ return GetFullPathName(pSrc, MAX_PATH, pOut, nullptr);
+
+ if (base == nullptr)
+ base = szMirandaPathW;
+
+ if (pSrc[0] == '\\')
+ pSrc++;
+
+ mir_snwprintf(buf, MAX_PATH, L"%s%s", base, pSrc);
+ return GetFullPathName(buf, MAX_PATH, pOut, nullptr);
+}
+
+MIR_CORE_DLL(int) CreatePathToFileW(const wchar_t *wszFilePath)
+{
+ if (wszFilePath == nullptr)
+ return ERROR_INVALID_PARAMETER;
+
+ wchar_t *buf = NEWWSTR_ALLOCA(wszFilePath);
+ wchar_t *p = wcsrchr(buf, '\\');
+ if (p == nullptr)
+ return 0;
+
+ *p = '\0';
+ return CreateDirectoryTreeW(buf);
+}
+
+MIR_CORE_DLL(int) CreateDirectoryTreeW(const wchar_t *szDir)
+{
+ if (szDir == nullptr)
+ return 1;
+
+ DWORD dwAttributes = GetFileAttributesW(szDir);
+ if (dwAttributes != INVALID_FILE_ATTRIBUTES && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ return 0;
+
+ wchar_t szTestDir[MAX_PATH];
+ mir_wstrncpy(szTestDir, szDir, _countof(szTestDir));
+ wchar_t *pszLastBackslash = wcsrchr(szTestDir, '\\');
+ if (pszLastBackslash == nullptr)
+ return 0;
+
+ *pszLastBackslash = '\0';
+ CreateDirectoryTreeW(szTestDir);
+ *pszLastBackslash = '\\';
+ return (CreateDirectoryW(szTestDir, nullptr) == 0) ? GetLastError() : 0;
+}
+
+MIR_CORE_DLL(int) DeleteDirectoryTreeW(const wchar_t *pwszDir, bool bAllowUndo)
+{
+ if (pwszDir == nullptr)
+ return ERROR_BAD_ARGUMENTS;
+
+ CMStringW wszPath(pwszDir);
+ wszPath.AppendChar(0);
+
+ SHFILEOPSTRUCTW file_op = {
+ nullptr,
+ FO_DELETE,
+ wszPath,
+ L"",
+ FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION,
+ false,
+ nullptr,
+ L"" };
+
+ if (bAllowUndo)
+ file_op.fFlags |= FOF_ALLOWUNDO;
+
+ return SHFileOperationW(&file_op);
+}
+
+int InitPathUtils(void)
+{
+ GetModuleFileNameA(nullptr, szMirandaPath, _countof(szMirandaPath));
+ char *p = strrchr(szMirandaPath, '\\');
+ if (p)
+ p[1] = 0;
+
+ GetModuleFileNameW(nullptr, szMirandaPathW, _countof(szMirandaPathW));
+ wchar_t *tp = wcsrchr(szMirandaPathW, '\\');
+ if (tp)
+ tp[1] = 0;
+ return 0;
+}
diff --git a/src/mir_core/src/resizer.cpp b/src/mir_core/src/Windows/resizer.cpp
index 01d65a7916..a8a6be41e4 100644
--- a/src/mir_core/src/resizer.cpp
+++ b/src/mir_core/src/Windows/resizer.cpp
@@ -1,151 +1,151 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-#pragma pack(2)
-
-struct START_OF_DLGITEMTEMPLATEEX
-{
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- short x, y, cx, cy;
- DWORD id;
-};
-
-struct START_OF_DLGTEMPLATEEX
-{
- WORD dlgVer;
- WORD signature;
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- WORD cDlgItems;
- short x, y, cx, cy;
-};
-
-MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam)
-{
- DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5))));
- START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate;
- int extendedDlg = pTemplateEx->signature == 0xFFFF;
- if (extendedDlg && pTemplateEx->dlgVer != 1)
- return 1;
-
- PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1);
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- while (*pWord++); // skip title
- if (extendedDlg) {
- if (pTemplateEx->style & DS_SETFONT) {
- pWord += 3; // font size, weight, italic
- while (*pWord++); // font name
- }
- }
- else {
- if (pTemplate->style & DS_SETFONT) {
- pWord++; // font size
- while (*pWord++); // font name
- }
- }
-
- UTILRESIZECONTROL urc;
- urc.cbSize = sizeof(UTILRESIZECONTROL);
-
- RECT rc;
- rc.left = 0; rc.top = 0;
- if (extendedDlg) {
- rc.right = pTemplateEx->cx;
- rc.bottom = pTemplateEx->cy;
- }
- else {
- rc.right = pTemplate->cx;
- rc.bottom = pTemplate->cy;
- }
-
- MapDialogRect(hwndDlg, &rc);
- urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom;
- GetClientRect(hwndDlg, &rc);
- urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom;
-
- int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit;
-
- HDWP hDwp = BeginDeferWindowPos(itemCount);
- for (int i = 0; i < itemCount; i++) {
- if ((UINT_PTR)pWord & 2) pWord++; //dword align
-
- if (extendedDlg) {
- START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord;
- pWord = (PWORD)(pItemEx + 1);
-
- urc.wId = pItemEx->id;
- urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y;
- urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy;
- }
- else {
- DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord;
- pWord = (PWORD)(pItem + 1);
-
- urc.wId = pItem->id;
- urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y;
- urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy;
- }
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
- if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
- pWord += 1 + (1 + *pWord) / 2; //creation data
-
- if (urc.wId == 65535) // using this breaks the dwp, so just ignore it
- continue;
-
- MapDialogRect(hwndDlg, &urc.rcItem);
- int procResult = (pfnResizer)(hwndDlg, lParam, &urc);
- if (procResult & RD_ANCHORX_RIGHT) {
- urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- }
- else if (procResult & RD_ANCHORX_WIDTH)
- urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
- else if (procResult & RD_ANCHORX_CENTRE) {
- urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
- }
- if (procResult & RD_ANCHORY_BOTTOM) {
- urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- }
- else if (procResult & RD_ANCHORY_HEIGHT)
- urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
- else if (procResult & RD_ANCHORY_CENTRE) {
- urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
- }
-
- HWND hCtrl = GetDlgItem(hwndDlg, urc.wId);
- if (hCtrl != nullptr)
- hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER);
- }
- EndDeferWindowPos(hDwp);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+#pragma pack(2)
+
+struct START_OF_DLGITEMTEMPLATEEX
+{
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ short x, y, cx, cy;
+ DWORD id;
+};
+
+struct START_OF_DLGTEMPLATEEX
+{
+ WORD dlgVer;
+ WORD signature;
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ WORD cDlgItems;
+ short x, y, cx, cy;
+};
+
+MIR_CORE_DLL(int) Utils_ResizeDialog(HWND hwndDlg, HINSTANCE hInstance, LPCSTR lpTemplate, DIALOGRESIZERPROC pfnResizer, LPARAM lParam)
+{
+ DLGTEMPLATE *pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(hInstance, FindResourceA(hInstance, lpTemplate, MAKEINTRESOURCEA(5))));
+ START_OF_DLGTEMPLATEEX *pTemplateEx = (START_OF_DLGTEMPLATEEX*)pTemplate;
+ int extendedDlg = pTemplateEx->signature == 0xFFFF;
+ if (extendedDlg && pTemplateEx->dlgVer != 1)
+ return 1;
+
+ PWORD pWord = (extendedDlg) ? (PWORD)(pTemplateEx + 1) : (PWORD)(pTemplate + 1);
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
+ while (*pWord++); // skip title
+ if (extendedDlg) {
+ if (pTemplateEx->style & DS_SETFONT) {
+ pWord += 3; // font size, weight, italic
+ while (*pWord++); // font name
+ }
+ }
+ else {
+ if (pTemplate->style & DS_SETFONT) {
+ pWord++; // font size
+ while (*pWord++); // font name
+ }
+ }
+
+ UTILRESIZECONTROL urc;
+ urc.cbSize = sizeof(UTILRESIZECONTROL);
+
+ RECT rc;
+ rc.left = 0; rc.top = 0;
+ if (extendedDlg) {
+ rc.right = pTemplateEx->cx;
+ rc.bottom = pTemplateEx->cy;
+ }
+ else {
+ rc.right = pTemplate->cx;
+ rc.bottom = pTemplate->cy;
+ }
+
+ MapDialogRect(hwndDlg, &rc);
+ urc.dlgOriginalSize.cx = rc.right; urc.dlgOriginalSize.cy = rc.bottom;
+ GetClientRect(hwndDlg, &rc);
+ urc.dlgNewSize.cx = rc.right; urc.dlgNewSize.cy = rc.bottom;
+
+ int itemCount = (extendedDlg) ? pTemplateEx->cDlgItems : pTemplate->cdit;
+
+ HDWP hDwp = BeginDeferWindowPos(itemCount);
+ for (int i = 0; i < itemCount; i++) {
+ if ((UINT_PTR)pWord & 2) pWord++; //dword align
+
+ if (extendedDlg) {
+ START_OF_DLGITEMTEMPLATEEX *pItemEx = (START_OF_DLGITEMTEMPLATEEX*)pWord;
+ pWord = (PWORD)(pItemEx + 1);
+
+ urc.wId = pItemEx->id;
+ urc.rcItem.left = pItemEx->x; urc.rcItem.top = pItemEx->y;
+ urc.rcItem.right = urc.rcItem.left + pItemEx->cx; urc.rcItem.bottom = urc.rcItem.top + pItemEx->cy;
+ }
+ else {
+ DLGITEMTEMPLATE *pItem = (DLGITEMTEMPLATE*)pWord;
+ pWord = (PWORD)(pItem + 1);
+
+ urc.wId = pItem->id;
+ urc.rcItem.left = pItem->x; urc.rcItem.top = pItem->y;
+ urc.rcItem.right = urc.rcItem.left + pItem->cx; urc.rcItem.bottom = urc.rcItem.top + pItem->cy;
+ }
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // menu
+ if (*pWord == 0xFFFF) pWord += 2; else while (*pWord++); // class
+ pWord += 1 + (1 + *pWord) / 2; //creation data
+
+ if (urc.wId == 65535) // using this breaks the dwp, so just ignore it
+ continue;
+
+ MapDialogRect(hwndDlg, &urc.rcItem);
+ int procResult = (pfnResizer)(hwndDlg, lParam, &urc);
+ if (procResult & RD_ANCHORX_RIGHT) {
+ urc.rcItem.left += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ }
+ else if (procResult & RD_ANCHORX_WIDTH)
+ urc.rcItem.right += urc.dlgNewSize.cx - urc.dlgOriginalSize.cx;
+ else if (procResult & RD_ANCHORX_CENTRE) {
+ urc.rcItem.left += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
+ urc.rcItem.right += (urc.dlgNewSize.cx - urc.dlgOriginalSize.cx) / 2;
+ }
+ if (procResult & RD_ANCHORY_BOTTOM) {
+ urc.rcItem.top += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ }
+ else if (procResult & RD_ANCHORY_HEIGHT)
+ urc.rcItem.bottom += urc.dlgNewSize.cy - urc.dlgOriginalSize.cy;
+ else if (procResult & RD_ANCHORY_CENTRE) {
+ urc.rcItem.top += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
+ urc.rcItem.bottom += (urc.dlgNewSize.cy - urc.dlgOriginalSize.cy) / 2;
+ }
+
+ HWND hCtrl = GetDlgItem(hwndDlg, urc.wId);
+ if (hCtrl != nullptr)
+ hDwp = DeferWindowPos(hDwp, hCtrl, nullptr, urc.rcItem.left, urc.rcItem.top, urc.rcItem.right - urc.rcItem.left, urc.rcItem.bottom - urc.rcItem.top, SWP_NOZORDER);
+ }
+ EndDeferWindowPos(hDwp);
+ return 0;
+}
diff --git a/src/mir_core/src/subclass.cpp b/src/mir_core/src/Windows/subclass.cpp
index ecf53b470f..99d5d355b2 100644
--- a/src/mir_core/src/subclass.cpp
+++ b/src/mir_core/src/Windows/subclass.cpp
@@ -1,201 +1,201 @@
-/*
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-struct MSubclassData
-{
- HWND m_hWnd;
-
- int m_iHooks;
- WNDPROC *m_hooks;
- WNDPROC m_origWndProc;
-
- ~MSubclassData()
- {
- free(m_hooks);
- }
-};
-
-static LIST<MSubclassData> arSubclass(10, HandleKeySortT);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
- if (p != nullptr) {
- if (p->m_iHooks)
- return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam);
-
- return p->m_origWndProc(hwnd, uMsg, wParam, lParam);
- }
-
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// This is for wine: it return wrong WNDPROC for edit control in some cases.
-#ifdef WIN64
-#define STD_WND_PROC_ADDR_MASK 0x7FFF00000
-#else
-#define STD_WND_PROC_ADDR_MASK 0xFFFF0000
-#endif
-
-MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- if (hWnd == nullptr)
- return;
-
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */
- p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC);
- if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */
- p->m_origWndProc = DefWindowProc;
- }
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr) {
- p = new MSubclassData;
- p->m_hWnd = hWnd;
- p->m_origWndProc = oldWndProc;
- p->m_iHooks = 0;
- p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
- arSubclass.insert(p);
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
- }
- else {
- for (int i=0; i < p->m_iHooks; i++)
- if (p->m_hooks[i] == wndProc)
- return;
-
- void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
- if (tmp == nullptr)
- return;
-
- p->m_hooks = (WNDPROC *)tmp;
- }
-
- p->m_hooks[p->m_iHooks++] = wndProc;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void removeHook(MSubclassData *p, int idx)
-{
- // untie hook from a window to prevent calling mir_callNextSubclass from saveProc
- for (int i = idx + 1; i < p->m_iHooks; i++)
- p->m_hooks[i-1] = p->m_hooks[i];
- p->m_iHooks--;
-}
-
-static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p)
-{
- WNDPROC saveProc = p->m_origWndProc;
- arSubclass.remove(p);
- delete p;
-
- SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc);
- return saveProc;
-}
-
-MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return;
-
- for (int i = 0; i < p->m_iHooks; i++) {
- if (p->m_hooks[i] == wndProc) {
- removeHook(p, i);
- i--;
- }
- }
-
- if (p->m_iHooks == 0)
- finalizeSubclassing(hWnd, p);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
- if (p == nullptr)
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-
- for (int i = p->m_iHooks - 1; i >= 0; i--) {
- if (p->m_hooks[i] != wndProc)
- continue;
-
- // next hook exists, call it
- if (i != 0)
- return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam);
-
- // last hook called, ping the default window procedure
- if (uMsg != WM_NCDESTROY)
- return p->m_origWndProc(hWnd, uMsg, wParam, lParam);
-
- WNDPROC saveProc = finalizeSubclassing(hWnd, p);
- return saveProc(hWnd, uMsg, wParam, lParam);
- }
-
- // invalid / closed hook
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
-{
- for (auto &it : arSubclass.rev_iter()) {
- for (int j = 0; j < it->m_iHooks; j++) {
- if (GetInstByAddress(it->m_hooks[j]) == hInst) {
- removeHook(it, j);
- j--;
- }
- }
-
- if (it->m_iHooks == 0)
- finalizeSubclassing(it->m_hWnd, it);
- }
-}
+/*
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+struct MSubclassData
+{
+ HWND m_hWnd;
+
+ int m_iHooks;
+ WNDPROC *m_hooks;
+ WNDPROC m_origWndProc;
+
+ ~MSubclassData()
+ {
+ free(m_hooks);
+ }
+};
+
+static LIST<MSubclassData> arSubclass(10, HandleKeySortT);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
+ if (p != nullptr) {
+ if (p->m_iHooks)
+ return p->m_hooks[p->m_iHooks-1](hwnd, uMsg, wParam, lParam);
+
+ return p->m_origWndProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// This is for wine: it return wrong WNDPROC for edit control in some cases.
+#ifdef WIN64
+#define STD_WND_PROC_ADDR_MASK 0x7FFF00000
+#else
+#define STD_WND_PROC_ADDR_MASK 0xFFFF0000
+#endif
+
+MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
+{
+ if (hWnd == nullptr)
+ return;
+
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr) {
+ p = new MSubclassData;
+ p->m_hWnd = hWnd;
+ p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
+ if (((SIZE_T)p->m_origWndProc & STD_WND_PROC_ADDR_MASK) == STD_WND_PROC_ADDR_MASK) { /* XXX: fix me. Wine fix. */
+ p->m_origWndProc = (WNDPROC)GetClassLongPtr(hWnd, GCLP_WNDPROC);
+ if (((SIZE_T)p->m_origWndProc & 0x7FFF0000) == 0x7FFF0000) /* Delay crash. */
+ p->m_origWndProc = DefWindowProc;
+ }
+ p->m_iHooks = 0;
+ p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
+ arSubclass.insert(p);
+ }
+ else {
+ for (int i=0; i < p->m_iHooks; i++)
+ if (p->m_hooks[i] == wndProc)
+ return;
+
+ void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
+ if (tmp == nullptr)
+ return;
+
+ p->m_hooks = (WNDPROC *)tmp;
+ }
+
+ p->m_hooks[p->m_iHooks++] = wndProc;
+}
+
+MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC oldWndProc)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr) {
+ p = new MSubclassData;
+ p->m_hWnd = hWnd;
+ p->m_origWndProc = oldWndProc;
+ p->m_iHooks = 0;
+ p->m_hooks = (WNDPROC*)malloc(sizeof(WNDPROC));
+ arSubclass.insert(p);
+
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
+ }
+ else {
+ for (int i=0; i < p->m_iHooks; i++)
+ if (p->m_hooks[i] == wndProc)
+ return;
+
+ void *tmp = realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));
+ if (tmp == nullptr)
+ return;
+
+ p->m_hooks = (WNDPROC *)tmp;
+ }
+
+ p->m_hooks[p->m_iHooks++] = wndProc;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void removeHook(MSubclassData *p, int idx)
+{
+ // untie hook from a window to prevent calling mir_callNextSubclass from saveProc
+ for (int i = idx + 1; i < p->m_iHooks; i++)
+ p->m_hooks[i-1] = p->m_hooks[i];
+ p->m_iHooks--;
+}
+
+static WNDPROC finalizeSubclassing(HWND hWnd, MSubclassData *p)
+{
+ WNDPROC saveProc = p->m_origWndProc;
+ arSubclass.remove(p);
+ delete p;
+
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc);
+ return saveProc;
+}
+
+MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr)
+ return;
+
+ for (int i = 0; i < p->m_iHooks; i++) {
+ if (p->m_hooks[i] == wndProc) {
+ removeHook(p, i);
+ i--;
+ }
+ }
+
+ if (p->m_iHooks == 0)
+ finalizeSubclassing(hWnd, p);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
+ if (p == nullptr)
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+
+ for (int i = p->m_iHooks - 1; i >= 0; i--) {
+ if (p->m_hooks[i] != wndProc)
+ continue;
+
+ // next hook exists, call it
+ if (i != 0)
+ return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam);
+
+ // last hook called, ping the default window procedure
+ if (uMsg != WM_NCDESTROY)
+ return p->m_origWndProc(hWnd, uMsg, wParam, lParam);
+
+ WNDPROC saveProc = finalizeSubclassing(hWnd, p);
+ return saveProc(hWnd, uMsg, wParam, lParam);
+ }
+
+ // invalid / closed hook
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
+{
+ for (auto &it : arSubclass.rev_iter()) {
+ for (int j = 0; j < it->m_iHooks; j++) {
+ if (GetInstByAddress(it->m_hooks[j]) == hInst) {
+ removeHook(it, j);
+ j--;
+ }
+ }
+
+ if (it->m_iHooks == 0)
+ finalizeSubclassing(it->m_hWnd, it);
+ }
+}
diff --git a/src/mir_core/src/threads.cpp b/src/mir_core/src/Windows/threads.cpp
index 917ecc5bb5..fdd9f5e85f 100644
--- a/src/mir_core/src/threads.cpp
+++ b/src/mir_core/src/Windows/threads.cpp
@@ -1,400 +1,400 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "stdafx.h"
-
-#include <m_netlib.h>
-
-static mir_cs csThreads;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// APC and mutex functions
-
-static void __stdcall DummyAPCFunc(ULONG_PTR)
-{
- /* called in the context of thread that cleared it's APC queue */
- return;
-}
-
-static int MirandaWaitForMutex(HANDLE hEvent)
-{
- // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result
- for (;;) {
- DWORD rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
- if (rc == WAIT_OBJECT_0 + 1) {
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */
- continue;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- else if (rc == WAIT_OBJECT_0) { // got object
- return 1;
- }
- else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED)
- return 0;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// exception handling
-
-static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*)
-{
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter;
-
-MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter()
-{
- return pMirandaExceptFilter;
-}
-
-MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter)
-{
- pfnExceptionFilter oldOne = pMirandaExceptFilter;
- if (_mirandaExceptFilter != nullptr)
- pMirandaExceptFilter = _mirandaExceptFilter;
- return oldOne;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// thread support functions
-
-struct THREAD_WAIT_ENTRY
-{
- DWORD dwThreadId; // valid if hThread isn't signalled
- HANDLE hThread;
- HINSTANCE hOwner;
- void *pObject, *pEntryPoint;
-};
-
-static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT);
-
-struct FORK_ARG
-{
- HANDLE hEvent, hThread;
- union
- {
- pThreadFunc threadcode;
- pThreadFuncEx threadcodeex;
- };
- void *arg, *owner;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthread - starts a new thread
-
-DWORD WINAPI forkthread_r(void *arg)
-{
- FORK_ARG *fa = (FORK_ARG*)arg;
- pThreadFunc callercode = fa->threadcode;
- void *cookie = fa->arg;
- HANDLE hThread = fa->hThread;
- Thread_Push((HINSTANCE)callercode);
- SetEvent(fa->hEvent);
-
- callercode(cookie);
-
- CloseHandle(hThread);
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return 0;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg)
-{
- FORK_ARG fa;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
- fa.threadcode = threadcode;
- fa.arg = arg;
-
- DWORD threadID;
- fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID);
- if (fa.hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- CloseHandle(fa.hEvent);
- return fa.hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// forkthreadex - starts a new thread with the extended info and returns the thread id
-
-DWORD WINAPI forkthreadex_r(void * arg)
-{
- struct FORK_ARG *fa = (struct FORK_ARG *)arg;
- pThreadFuncEx threadcode = fa->threadcodeex;
- pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex;
- void *cookie = fa->arg;
- void *owner = fa->owner;
- unsigned long rc = 0;
-
- Thread_Push((HINSTANCE)threadcode, fa->owner);
- SetEvent(fa->hEvent);
- if (owner)
- rc = threadcodeex(owner, cookie);
- else
- rc = threadcode(cookie);
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- Thread_Pop();
- return rc;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = aFunc;
- fa.arg = arg;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID)
-{
- struct FORK_ARG fa = {};
- fa.threadcodeex = (pThreadFuncEx)aFunc;
- fa.arg = arg;
- fa.owner = owner;
- fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- DWORD threadID = 0;
- HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
- if (hThread != nullptr)
- WaitForSingleObject(fa.hEvent, INFINITE);
-
- if (pThreadID != nullptr)
- *pThreadID = threadID;
-
- CloseHandle(fa.hEvent);
- return hThread;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void __cdecl KillObjectThreadsWorker(void* owner)
-{
- HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE));
- int threadCount = 0;
- {
- mir_cslock lck(csThreads);
-
- for (auto &it : threads)
- if (it->pObject == owner)
- threadPool[threadCount++] = it->hThread;
- }
-
- // is there anything to kill?
- if (threadCount == 0)
- return;
-
- // wait'em all
- if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT)
- return;
-
- // forcibly kill all remaining threads after 5 secs
- mir_cslock lck(csThreads);
- auto T = threads.rev_iter();
- for (auto &it : T) {
- if (it->pObject == owner) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId);
- TerminateThread(it->hThread, 9999);
- CloseHandle(it->hThread);
- mir_free(it);
- threads.removeItem(&it);
- }
- }
-}
-
-MIR_CORE_DLL(void) KillObjectThreads(void* owner)
-{
- if (owner == nullptr)
- return;
-
- DWORD dwTicks = GetTickCount() + 6000;
- HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner);
- while (GetTickCount() < dwTicks) {
- int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE);
- if (res == WAIT_OBJECT_0 || res == WAIT_FAILED)
- break;
-
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD)
-{
- mir_cslock lck(csThreads);
- for (auto &p : threads) {
- char szModuleName[MAX_PATH];
- GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName));
- Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint);
- TerminateThread(p->hThread, 9999);
- CloseHandle(p->hThread);
- mir_free(p);
- }
-
- threads.destroy();
-
- SetEvent(hThreadQueueEmpty);
-}
-
-MIR_CORE_DLL(void) Thread_Wait(void)
-{
- // acquire the list and wake up any alertable threads
- {
- mir_cslock lck(csThreads);
- for (auto &p : threads)
- QueueUserAPC(DummyAPCFunc, p->hThread, 0);
- }
-
- // give all unclosed threads 5 seconds to close
- SetTimer(nullptr, 0, 5000, KillAllThreads);
-
- // wait til the thread list is empty
- MirandaWaitForMutex(hThreadQueueEmpty);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
-#define ThreadQuerySetWin32StartAddress 9
-
-static void* GetCurrentThreadEntryPoint()
-{
- pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
- if (NtQueryInformationThread == nullptr)
- return nullptr;
-
- HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess();
- if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) {
- SetLastError(ERROR_ACCESS_DENIED);
- return nullptr;
- }
-
- DWORD_PTR dwStartAddress;
- LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr);
- CloseHandle(hDupHandle);
-
- return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress;
-}
-
-MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
-{
- ResetEvent(hThreadQueueEmpty); // thread list is not empty
-
- mir_cslock lck(csThreads);
-
- THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY));
- DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
- p->dwThreadId = GetCurrentThreadId();
- p->pObject = pOwner;
- p->pEntryPoint = hInst;
-
- // try to find the precise match
- CMPluginBase &pPlugin = GetPluginByInstance(hInst);
- if (pPlugin.getInst() == hInst)
- p->hOwner = hInst;
- else
- GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
-
- threads.insert(p);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(INT_PTR) Thread_Pop()
-{
- DWORD dwThreadId = GetCurrentThreadId();
-
- mir_cslock lck(csThreads);
- THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId);
- if (p == nullptr)
- return 1;
-
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
- CloseHandle(p->hThread);
- threads.remove(p);
- mir_free(p);
-
- if (!threads.getCount()) {
- threads.destroy();
- SetEvent(hThreadQueueEmpty); // thread list is empty now
- }
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-const DWORD MS_VC_EXCEPTION=0x406D1388;
-
-#pragma pack(push,8)
-typedef struct tagTHREADNAME_INFO
-{
- DWORD dwType; // Must be 0x1000.
- LPCSTR szName; // Pointer to name (in user addr space).
- DWORD dwThreadID; // Thread ID (-1=caller thread).
- DWORD dwFlags; // Reserved for future use, must be zero.
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName)
-{
- THREADNAME_INFO info;
- info.dwType = 0x1000;
- info.szName = szThreadName;
- info.dwThreadID = GetCurrentThreadId();
- info.dwFlags = 0;
-
- __try {
- RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "../stdafx.h"
+
+#include <m_netlib.h>
+
+static mir_cs csThreads;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// APC and mutex functions
+
+static void __stdcall DummyAPCFunc(ULONG_PTR)
+{
+ /* called in the context of thread that cleared it's APC queue */
+ return;
+}
+
+static int MirandaWaitForMutex(HANDLE hEvent)
+{
+ // will get WAIT_IO_COMPLETE for QueueUserAPC() which isnt a result
+ for (;;) {
+ DWORD rc = MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+ if (rc == WAIT_OBJECT_0 + 1) {
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ if (msg.hwnd != nullptr && IsDialogMessage(msg.hwnd, &msg)) /* Wine fix. */
+ continue;
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if (rc == WAIT_OBJECT_0) { // got object
+ return 1;
+ }
+ else if (rc == WAIT_ABANDONED_0 || rc == WAIT_FAILED)
+ return 0;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// exception handling
+
+static DWORD __cdecl sttDefaultFilter(DWORD, EXCEPTION_POINTERS*)
+{
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+pfnExceptionFilter pMirandaExceptFilter = sttDefaultFilter;
+
+MIR_CORE_DLL(pfnExceptionFilter) GetExceptionFilter()
+{
+ return pMirandaExceptFilter;
+}
+
+MIR_CORE_DLL(pfnExceptionFilter) SetExceptionFilter(pfnExceptionFilter _mirandaExceptFilter)
+{
+ pfnExceptionFilter oldOne = pMirandaExceptFilter;
+ if (_mirandaExceptFilter != nullptr)
+ pMirandaExceptFilter = _mirandaExceptFilter;
+ return oldOne;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// thread support functions
+
+struct THREAD_WAIT_ENTRY
+{
+ DWORD dwThreadId; // valid if hThread isn't signalled
+ HANDLE hThread;
+ HINSTANCE hOwner;
+ void *pObject, *pEntryPoint;
+};
+
+static LIST<THREAD_WAIT_ENTRY> threads(10, NumericKeySortT);
+
+struct FORK_ARG
+{
+ HANDLE hEvent, hThread;
+ union
+ {
+ pThreadFunc threadcode;
+ pThreadFuncEx threadcodeex;
+ };
+ void *arg, *owner;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// forkthread - starts a new thread
+
+DWORD WINAPI forkthread_r(void *arg)
+{
+ FORK_ARG *fa = (FORK_ARG*)arg;
+ pThreadFunc callercode = fa->threadcode;
+ void *cookie = fa->arg;
+ HANDLE hThread = fa->hThread;
+ Thread_Push((HINSTANCE)callercode);
+ SetEvent(fa->hEvent);
+
+ callercode(cookie);
+
+ CloseHandle(hThread);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ Thread_Pop();
+ return 0;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthread(void(__cdecl *threadcode)(void*), void *arg)
+{
+ FORK_ARG fa;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+
+ DWORD threadID;
+ fa.hThread = CreateThread(nullptr, 0, forkthread_r, &fa, 0, &threadID);
+ if (fa.hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ CloseHandle(fa.hEvent);
+ return fa.hThread;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// forkthreadex - starts a new thread with the extended info and returns the thread id
+
+DWORD WINAPI forkthreadex_r(void * arg)
+{
+ struct FORK_ARG *fa = (struct FORK_ARG *)arg;
+ pThreadFuncEx threadcode = fa->threadcodeex;
+ pThreadFuncOwner threadcodeex = (pThreadFuncOwner)fa->threadcodeex;
+ void *cookie = fa->arg;
+ void *owner = fa->owner;
+ unsigned long rc = 0;
+
+ Thread_Push((HINSTANCE)threadcode, fa->owner);
+ SetEvent(fa->hEvent);
+ if (owner)
+ rc = threadcodeex(owner, cookie);
+ else
+ rc = threadcode(cookie);
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ Thread_Pop();
+ return rc;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthreadex(pThreadFuncEx aFunc, void* arg, unsigned *pThreadID)
+{
+ struct FORK_ARG fa = {};
+ fa.threadcodeex = aFunc;
+ fa.arg = arg;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ DWORD threadID = 0;
+ HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
+ if (hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ if (pThreadID != nullptr)
+ *pThreadID = threadID;
+
+ CloseHandle(fa.hEvent);
+ return hThread;
+}
+
+MIR_CORE_DLL(HANDLE) mir_forkthreadowner(pThreadFuncOwner aFunc, void *owner, void *arg, unsigned *pThreadID)
+{
+ struct FORK_ARG fa = {};
+ fa.threadcodeex = (pThreadFuncEx)aFunc;
+ fa.arg = arg;
+ fa.owner = owner;
+ fa.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
+
+ DWORD threadID = 0;
+ HANDLE hThread = CreateThread(nullptr, 0, forkthreadex_r, &fa, 0, &threadID);
+ if (hThread != nullptr)
+ WaitForSingleObject(fa.hEvent, INFINITE);
+
+ if (pThreadID != nullptr)
+ *pThreadID = threadID;
+
+ CloseHandle(fa.hEvent);
+ return hThread;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void __cdecl KillObjectThreadsWorker(void* owner)
+{
+ HANDLE *threadPool = (HANDLE*)alloca(threads.getCount() * sizeof(HANDLE));
+ int threadCount = 0;
+ {
+ mir_cslock lck(csThreads);
+
+ for (auto &it : threads)
+ if (it->pObject == owner)
+ threadPool[threadCount++] = it->hThread;
+ }
+
+ // is there anything to kill?
+ if (threadCount == 0)
+ return;
+
+ // wait'em all
+ if (WaitForMultipleObjects(threadCount, threadPool, TRUE, 5000) != WAIT_TIMEOUT)
+ return;
+
+ // forcibly kill all remaining threads after 5 secs
+ mir_cslock lck(csThreads);
+ auto T = threads.rev_iter();
+ for (auto &it : T) {
+ if (it->pObject == owner) {
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(it->hOwner, szModuleName, sizeof(szModuleName));
+ Netlib_Logf(nullptr, "Killing object thread %s:%08x", szModuleName, it->dwThreadId);
+ TerminateThread(it->hThread, 9999);
+ CloseHandle(it->hThread);
+ mir_free(it);
+ threads.removeItem(&it);
+ }
+ }
+}
+
+MIR_CORE_DLL(void) KillObjectThreads(void* owner)
+{
+ if (owner == nullptr)
+ return;
+
+ DWORD dwTicks = GetTickCount() + 6000;
+ HANDLE hThread = mir_forkthread(KillObjectThreadsWorker, owner);
+ while (GetTickCount() < dwTicks) {
+ int res = MsgWaitForMultipleObjectsEx(1, &hThread, 50, QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE);
+ if (res == WAIT_OBJECT_0 || res == WAIT_FAILED)
+ break;
+
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void CALLBACK KillAllThreads(HWND, UINT, UINT_PTR, DWORD)
+{
+ mir_cslock lck(csThreads);
+ for (auto &p : threads) {
+ char szModuleName[MAX_PATH];
+ GetModuleFileNameA(p->hOwner, szModuleName, sizeof(szModuleName));
+ Netlib_Logf(nullptr, "Killing thread %s:%08x (%p)", szModuleName, p->dwThreadId, p->pEntryPoint);
+ TerminateThread(p->hThread, 9999);
+ CloseHandle(p->hThread);
+ mir_free(p);
+ }
+
+ threads.destroy();
+
+ SetEvent(hThreadQueueEmpty);
+}
+
+MIR_CORE_DLL(void) Thread_Wait(void)
+{
+ // acquire the list and wake up any alertable threads
+ {
+ mir_cslock lck(csThreads);
+ for (auto &p : threads)
+ QueueUserAPC(DummyAPCFunc, p->hThread, 0);
+ }
+
+ // give all unclosed threads 5 seconds to close
+ SetTimer(nullptr, 0, 5000, KillAllThreads);
+
+ // wait til the thread list is empty
+ MirandaWaitForMutex(hThreadQueueEmpty);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+typedef LONG (WINAPI *pNtQIT)(HANDLE, LONG, PVOID, ULONG, PULONG);
+#define ThreadQuerySetWin32StartAddress 9
+
+static void* GetCurrentThreadEntryPoint()
+{
+ pNtQIT NtQueryInformationThread = (pNtQIT)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
+ if (NtQueryInformationThread == nullptr)
+ return nullptr;
+
+ HANDLE hDupHandle, hCurrentProcess = GetCurrentProcess();
+ if (!DuplicateHandle(hCurrentProcess, GetCurrentThread(), hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return nullptr;
+ }
+
+ DWORD_PTR dwStartAddress;
+ LONG ntStatus = NtQueryInformationThread(hDupHandle, ThreadQuerySetWin32StartAddress, &dwStartAddress, sizeof(DWORD_PTR), nullptr);
+ CloseHandle(hDupHandle);
+
+ return (ntStatus != ERROR_SUCCESS) ? nullptr : (void*)dwStartAddress;
+}
+
+MIR_CORE_DLL(INT_PTR) Thread_Push(HINSTANCE hInst, void* pOwner)
+{
+ ResetEvent(hThreadQueueEmpty); // thread list is not empty
+
+ mir_cslock lck(csThreads);
+
+ THREAD_WAIT_ENTRY *p = (THREAD_WAIT_ENTRY*)mir_calloc(sizeof(THREAD_WAIT_ENTRY));
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ p->dwThreadId = GetCurrentThreadId();
+ p->pObject = pOwner;
+ p->pEntryPoint = hInst;
+
+ // try to find the precise match
+ CMPluginBase &pPlugin = GetPluginByInstance(hInst);
+ if (pPlugin.getInst() == hInst)
+ p->hOwner = hInst;
+ else
+ GetInstByAddress((hInst != nullptr) ? (PVOID)hInst : GetCurrentThreadEntryPoint());
+
+ threads.insert(p);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(INT_PTR) Thread_Pop()
+{
+ DWORD dwThreadId = GetCurrentThreadId();
+
+ mir_cslock lck(csThreads);
+ THREAD_WAIT_ENTRY *p = threads.find((THREAD_WAIT_ENTRY*)&dwThreadId);
+ if (p == nullptr)
+ return 1;
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ CloseHandle(p->hThread);
+ threads.remove(p);
+ mir_free(p);
+
+ if (!threads.getCount()) {
+ threads.destroy();
+ SetEvent(hThreadQueueEmpty); // thread list is empty now
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+const DWORD MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+MIR_CORE_DLL(void) Thread_SetName(const char *szThreadName)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = GetCurrentThreadId();
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {}
+}
diff --git a/src/mir_core/src/timezones.cpp b/src/mir_core/src/Windows/timezones.cpp
index 10d2ad6225..8de5704d30 100644
--- a/src/mir_core/src/timezones.cpp
+++ b/src/mir_core/src/Windows/timezones.cpp
@@ -1,592 +1,592 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-implements services to handle location - based timezones, instead of
-simple UTC offsets.
-*/
-
-#include "stdafx.h"
-
-typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi);
-static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation;
-
-struct REG_TZI_FORMAT
-{
- LONG Bias;
- LONG StandardBias;
- LONG DaylightBias;
- SYSTEMTIME StandardDate;
- SYSTEMTIME DaylightDate;
-};
-
-#define MIM_TZ_DISPLAYLEN 128
-
-struct MIM_TIMEZONE
-{
- unsigned hash;
- int offset;
-
- wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone
- wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs)
- // every hour should be sufficient.
- TIME_ZONE_INFORMATION tzi;
-
- static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2)
- { return p2->tzi.Bias - p1->tzi.Bias;
- }
-};
-
-struct TZ_INT_INFO
-{
- DWORD timestamp; // last time updated
- MIM_TIMEZONE myTZ; // set to my own timezone
-};
-
-static TZ_INT_INFO myInfo;
-
-static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT);
-static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias);
-
-// KB167296
-void UnixTimeToFileTime(mir_time ts, LPFILETIME pft)
-{
- unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
- pft->dwLowDateTime = (DWORD)ll;
- pft->dwHighDateTime = ll >> 32;
-}
-
-mir_time FileTimeToUnixTime(LPFILETIME pft)
-{
- unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
- ll -= 116444736000000000i64;
- return (mir_time)(ll / 10000000);
-}
-
-void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest)
-{
- if (szDest == nullptr || cbDest == 0) return;
-
- CMStringW tszTemp;
-
- for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) {
- DWORD fmt = 0;
- bool date = false, iso = false;
- switch (*pFormat) {
- case 't':
- fmt = TIME_NOSECONDS;
- date = false;
- break;
-
- case 's':
- fmt = 0;
- date = false;
- break;
-
- case 'm':
- fmt = TIME_NOMINUTESORSECONDS;
- date = false;
- break;
-
- case 'd':
- fmt = DATE_SHORTDATE;
- date = true;
- break;
-
- case 'D':
- fmt = DATE_LONGDATE;
- date = true;
- break;
-
- case 'I':
- iso = true;
- break;
-
- default:
- tszTemp.AppendChar(*pFormat);
- continue;
- }
-
- wchar_t dateTimeStr[64];
- if (iso)
- tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond);
- else if (date) {
- GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- else {
- GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
- tszTemp.Append(dateTimeStr);
- }
- }
-
- wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE);
-}
-
-MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st)
-{
- if (st == nullptr) return 1;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == UTC_TIME_HANDLE)
- GetSystemTime(st);
- else if (tz && tz != &myInfo.myTZ) {
- SYSTEMTIME sto;
- GetSystemTime(&sto);
- return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st);
- }
- else
- GetLocalTime(st);
-
- return 0;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- return myInfo.myTZ.tszName;
- if (tz == UTC_TIME_HANDLE)
- return L"UTC";
-
- return tz->tszName;
-}
-
-MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname)
-{
- for (auto &tz : g_timezonesBias)
- if (!mir_wstrcmp(tz->tszName, TZname))
- return tz->szDisplay;
-
- return L"";
-}
-
-static void CalcTsOffset(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
- GetSystemTime(&st);
-
- FILETIME ft;
- SystemTimeToFileTime(&st, &ft);
- mir_time ts1 = FileTimeToUnixTime(&ft);
-
- if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl))
- return;
-
- SystemTimeToFileTime(&stl, &ft);
- mir_time ts2 = FileTimeToUnixTime(&ft);
-
- tz->offset = ts2 - ts1;
-}
-
-static bool IsSameTime(MIM_TIMEZONE *tz)
-{
- SYSTEMTIME st, stl;
-
- if (tz == &myInfo.myTZ)
- return true;
-
- TimeZone_GetTimeZoneTime(tz, &stl);
- TimeZone_GetTimeZoneTime(nullptr, &st);
-
- return st.wHour == stl.wHour && st.wMinute == stl.wMinute;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags)
-{
- if (tszName == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0)
- return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ;
-
- MIM_TIMEZONE tzsearch;
- tzsearch.hash = mir_hashstrT(tszName);
-
- MIM_TIMEZONE *tz = g_timezones.find(&tzsearch);
- if (tz == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (dwFlags & TZF_DIFONLY)
- return IsSameTime(tz) ? nullptr : tz;
-
- return tz;
-}
-
-MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags)
-{
- if (hContact == NULL && szModule == nullptr)
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-
- if (szModule == nullptr) szModule = "UserInfo";
-
- DBVARIANT dbv;
- if (!db_get_ws(hContact, szModule, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
-
- signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1);
- if (timezone == -1) {
- char *szProto = Proto_GetBaseAccountName(hContact);
- if (!db_get_ws(hContact, szProto, "TzName", &dbv)) {
- HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
- db_free(&dbv);
- if (res) return res;
- }
- timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1);
- }
-
- if (timezone != -1) {
- MIM_TIMEZONE tzsearch;
- tzsearch.tzi.Bias = timezone * 30;
- if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) {
- if (dwFlags & TZF_DIFONLY) return nullptr;
- return &myInfo.myTZ;
- }
-
- int i = g_timezonesBias.getIndex(&tzsearch);
- while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i;
-
- int delta = LONG_MAX;
- for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) {
- int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth);
- if (delta1 <= delta) {
- delta = delta1;
- i = j;
- }
- }
-
- if (i >= 0) {
- MIM_TIMEZONE *tz = g_timezonesBias[i];
- return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz;
- }
- }
- return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz) {
- db_set_ws(hContact, szModule, "TzName", tz->tszName);
- db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30));
- }
- else {
- db_unset(hContact, szModule, "TzName");
- db_unset(hContact, szModule, "Timezone");
- }
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)))
- return 1;
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- SYSTEMTIME st;
- if (TimeZone_GetTimeZoneTime(tz, &st))
- return 1;
-
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, DWORD dwFlags)
-{
- if (dest == nullptr)
- return 2;
-
- MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ;
- if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) {
- memset(dest, 0, sizeof(SYSTEMTIME));
- return 1;
- }
-
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- FILETIME ft;
- if (tz == UTC_TIME_HANDLE)
- UnixTimeToFileTime(ts, &ft);
- else {
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- UnixTimeToFileTime(ts + tz->offset, &ft);
- }
-
- FileTimeToSystemTime(&ft, dest);
- return 0;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
-{
- SYSTEMTIME st;
- if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags))
- FormatTime(&st, szFormat, szDest, cbDest);
- return 0;
-}
-
-MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- return tz ? &tz->tzi : &myInfo.myTZ.tzi;
-}
-
-MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts)
-{
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
- if (tz == nullptr)
- tz = &myInfo.myTZ;
-
- if (tz == UTC_TIME_HANDLE)
- return ts;
-
- if (tz->offset == INT_MIN)
- CalcTsOffset(tz);
-
- return ts + tz->offset;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct ListMessages
-{
- UINT addStr, getSel, setSel, getData, setData;
-};
-
-static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA };
-static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA };
-
-static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags)
-{
- if (hWnd == nullptr)
- return nullptr;
-
- if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) {
- wchar_t tszClassName[128];
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (!mir_wstrcmpi(tszClassName, L"COMBOBOX"))
- dwFlags |= TZF_PLF_CB;
- else if (!mir_wstrcmpi(tszClassName, L"LISTBOX"))
- dwFlags |= TZF_PLF_LB;
- }
-
- if (dwFlags & TZF_PLF_CB)
- return &cbMessages;
- if (dwFlags & TZF_PLF_LB)
- return &lbMessages;
- return nullptr;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return -1;
-
- if (szModule == nullptr)
- szModule = "UserInfo";
-
- int iSelection = 0;
- ptrW tszName(db_get_wsa(hContact, szModule, "TzName"));
- if (tszName != NULL) {
- unsigned hash = mir_hashstrT(tszName);
- for (auto &it : g_timezonesBias) {
- if (hash == it->hash) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- else {
- signed char cBias = db_get_b(hContact, szModule, "Timezone", -100);
- if (cBias != -100) {
- int iBias = cBias * 30;
- for (auto &it : g_timezonesBias) {
- if (iBias == it->tzi.Bias) {
- iSelection = g_timezonesBias.indexOf(&it) + 1;
- break;
- }
- }
- }
- }
-
- SendMessage(hWnd, lstMsg->setSel, iSelection, 0);
- return iSelection;
-}
-
-MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg == nullptr)
- return 0;
-
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>"));
-
- for (auto &it : g_timezonesBias) {
- SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay);
- SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it);
- }
-
- return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags);
-}
-
-MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
-{
- if (szModule == nullptr) szModule = "UserInfo";
-
- const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
- if (lstMsg) {
- LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0);
- if (offset > 0) {
- MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0);
- if ((INT_PTR)tz != CB_ERR && tz != nullptr)
- TimeZone_StoreByContact(hContact, szModule, tz);
- }
- else TimeZone_StoreByContact(hContact, szModule, nullptr);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal)
-{
- return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal);
-}
-
-MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest)
-{
- wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t));
- TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0);
- WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr);
- return szDest;
-}
-
-MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest)
-{
- TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0);
- return wszDest;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, DWORD cbLen)
-{
- DWORD dwLength = cbLen * sizeof(wchar_t);
- RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength);
- szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0;
-}
-
-void RecalculateTime(void)
-{
- GetTimeZoneInformation(&myInfo.myTZ.tzi);
- myInfo.timestamp = time(0);
- myInfo.myTZ.offset = INT_MIN;
-
- bool found = false;
- DYNAMIC_TIME_ZONE_INFORMATION dtzi;
-
- if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) {
- wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE);
- found = true;
- }
-
- for (auto &tz : g_timezones) {
- if (tz->offset != INT_MIN)
- tz->offset = INT_MIN;
-
- if (!found) {
- if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) {
- wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE);
- found = true;
- }
- }
- }
-}
-
-void InitTimeZones(void)
-{
- REG_TZI_FORMAT tzi;
- HKEY hKey;
-
- const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
-
- /*
- * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with
- * the registry key name, so finding our own time zone later will be MUCH easier for
- * localized systems or systems with a MUI pack installed
- */
- if (IsWinVerVistaPlus())
- pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation");
-
- if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) {
- DWORD dwIndex = 0;
- HKEY hSubKey;
- wchar_t tszName[MIM_TZ_NAMELEN];
-
- DWORD dwSize = _countof(tszName);
- while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) {
- if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) {
- dwSize = sizeof(tszName);
-
- DWORD dwLength = sizeof(tzi);
- if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength))
- continue;
-
- MIM_TIMEZONE *tz = new MIM_TIMEZONE;
-
- tz->tzi.Bias = tzi.Bias;
- tz->tzi.StandardDate = tzi.StandardDate;
- tz->tzi.StandardBias = tzi.StandardBias;
- tz->tzi.DaylightDate = tzi.DaylightDate;
- tz->tzi.DaylightBias = tzi.DaylightBias;
-
- mir_wstrcpy(tz->tszName, tszName);
- tz->hash = mir_hashstrT(tszName);
- tz->offset = INT_MIN;
-
- GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay));
- GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName));
- GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName));
-
- g_timezones.insert(tz);
- g_timezonesBias.insert(tz);
-
- RegCloseKey(hSubKey);
- }
- dwSize = _countof(tszName);
- }
- RegCloseKey(hKey);
- }
-
- RecalculateTime();
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+implements services to handle location - based timezones, instead of
+simple UTC offsets.
+*/
+
+#include "../stdafx.h"
+
+typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi);
+static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation;
+
+struct REG_TZI_FORMAT
+{
+ LONG Bias;
+ LONG StandardBias;
+ LONG DaylightBias;
+ SYSTEMTIME StandardDate;
+ SYSTEMTIME DaylightDate;
+};
+
+#define MIM_TZ_DISPLAYLEN 128
+
+struct MIM_TIMEZONE
+{
+ unsigned hash;
+ int offset;
+
+ wchar_t tszName[MIM_TZ_NAMELEN]; // windows name for the time zone
+ wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs)
+ // every hour should be sufficient.
+ TIME_ZONE_INFORMATION tzi;
+
+ static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2)
+ { return p2->tzi.Bias - p1->tzi.Bias;
+ }
+};
+
+struct TZ_INT_INFO
+{
+ DWORD timestamp; // last time updated
+ MIM_TIMEZONE myTZ; // set to my own timezone
+};
+
+static TZ_INT_INFO myInfo;
+
+static OBJLIST<MIM_TIMEZONE> g_timezones(55, NumericKeySortT);
+static LIST<MIM_TIMEZONE> g_timezonesBias(55, MIM_TIMEZONE::compareBias);
+
+// KB167296
+void UnixTimeToFileTime(mir_time ts, LPFILETIME pft)
+{
+ unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64;
+ pft->dwLowDateTime = (DWORD)ll;
+ pft->dwHighDateTime = ll >> 32;
+}
+
+mir_time FileTimeToUnixTime(LPFILETIME pft)
+{
+ unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime;
+ ll -= 116444736000000000i64;
+ return (mir_time)(ll / 10000000);
+}
+
+void FormatTime(const SYSTEMTIME *st, const wchar_t *szFormat, wchar_t *szDest, size_t cbDest)
+{
+ if (szDest == nullptr || cbDest == 0) return;
+
+ CMStringW tszTemp;
+
+ for (const wchar_t* pFormat = szFormat; *pFormat; ++pFormat) {
+ DWORD fmt = 0;
+ bool date = false, iso = false;
+ switch (*pFormat) {
+ case 't':
+ fmt = TIME_NOSECONDS;
+ date = false;
+ break;
+
+ case 's':
+ fmt = 0;
+ date = false;
+ break;
+
+ case 'm':
+ fmt = TIME_NOMINUTESORSECONDS;
+ date = false;
+ break;
+
+ case 'd':
+ fmt = DATE_SHORTDATE;
+ date = true;
+ break;
+
+ case 'D':
+ fmt = DATE_LONGDATE;
+ date = true;
+ break;
+
+ case 'I':
+ iso = true;
+ break;
+
+ default:
+ tszTemp.AppendChar(*pFormat);
+ continue;
+ }
+
+ wchar_t dateTimeStr[64];
+ if (iso)
+ tszTemp.AppendFormat(L"%d-%02d-%02dT%02d:%02d:%02dZ", st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond);
+ else if (date) {
+ GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
+ tszTemp.Append(dateTimeStr);
+ }
+ else {
+ GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, nullptr, dateTimeStr, _countof(dateTimeStr));
+ tszTemp.Append(dateTimeStr);
+ }
+ }
+
+ wcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE);
+}
+
+MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st)
+{
+ if (st == nullptr) return 1;
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == UTC_TIME_HANDLE)
+ GetSystemTime(st);
+ else if (tz && tz != &myInfo.myTZ) {
+ SYSTEMTIME sto;
+ GetSystemTime(&sto);
+ return !SystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st);
+ }
+ else
+ GetLocalTime(st);
+
+ return 0;
+}
+
+MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr)
+ return myInfo.myTZ.tszName;
+ if (tz == UTC_TIME_HANDLE)
+ return L"UTC";
+
+ return tz->tszName;
+}
+
+MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname)
+{
+ for (auto &tz : g_timezonesBias)
+ if (!mir_wstrcmp(tz->tszName, TZname))
+ return tz->szDisplay;
+
+ return L"";
+}
+
+static void CalcTsOffset(MIM_TIMEZONE *tz)
+{
+ SYSTEMTIME st, stl;
+ GetSystemTime(&st);
+
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+ mir_time ts1 = FileTimeToUnixTime(&ft);
+
+ if (!SystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl))
+ return;
+
+ SystemTimeToFileTime(&stl, &ft);
+ mir_time ts2 = FileTimeToUnixTime(&ft);
+
+ tz->offset = ts2 - ts1;
+}
+
+static bool IsSameTime(MIM_TIMEZONE *tz)
+{
+ SYSTEMTIME st, stl;
+
+ if (tz == &myInfo.myTZ)
+ return true;
+
+ TimeZone_GetTimeZoneTime(tz, &stl);
+ TimeZone_GetTimeZoneTime(nullptr, &st);
+
+ return st.wHour == stl.wHour && st.wMinute == stl.wMinute;
+}
+
+MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags)
+{
+ if (tszName == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (mir_wstrcmp(myInfo.myTZ.tszName, tszName) == 0)
+ return (dwFlags & TZF_DIFONLY) ? nullptr : &myInfo.myTZ;
+
+ MIM_TIMEZONE tzsearch;
+ tzsearch.hash = mir_hashstrT(tszName);
+
+ MIM_TIMEZONE *tz = g_timezones.find(&tzsearch);
+ if (tz == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (dwFlags & TZF_DIFONLY)
+ return IsSameTime(tz) ? nullptr : tz;
+
+ return tz;
+}
+
+MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags)
+{
+ if (hContact == NULL && szModule == nullptr)
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ DBVARIANT dbv;
+ if (!db_get_ws(hContact, szModule, "TzName", &dbv)) {
+ HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
+ db_free(&dbv);
+ if (res) return res;
+ }
+
+ signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1);
+ if (timezone == -1) {
+ char *szProto = Proto_GetBaseAccountName(hContact);
+ if (!db_get_ws(hContact, szProto, "TzName", &dbv)) {
+ HANDLE res = TimeZone_CreateByName(dbv.pwszVal, dwFlags);
+ db_free(&dbv);
+ if (res) return res;
+ }
+ timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1);
+ }
+
+ if (timezone != -1) {
+ MIM_TIMEZONE tzsearch;
+ tzsearch.tzi.Bias = timezone * 30;
+ if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) {
+ if (dwFlags & TZF_DIFONLY) return nullptr;
+ return &myInfo.myTZ;
+ }
+
+ int i = g_timezonesBias.getIndex(&tzsearch);
+ while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i;
+
+ int delta = LONG_MAX;
+ for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) {
+ int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth);
+ if (delta1 <= delta) {
+ delta = delta1;
+ i = j;
+ }
+ }
+
+ if (i >= 0) {
+ MIM_TIMEZONE *tz = g_timezonesBias[i];
+ return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? nullptr : tz;
+ }
+ }
+ return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? nullptr : &myInfo.myTZ;
+}
+
+MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ)
+{
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz) {
+ db_set_ws(hContact, szModule, "TzName", tz->tszName);
+ db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30));
+ }
+ else {
+ db_unset(hContact, szModule, "TzName");
+ db_unset(hContact, szModule, "Timezone");
+ }
+}
+
+MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)))
+ return 1;
+
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ SYSTEMTIME st;
+ if (TimeZone_GetTimeZoneTime(tz, &st))
+ return 1;
+
+ FormatTime(&st, szFormat, szDest, cbDest);
+ return 0;
+}
+
+MIR_CORE_DLL(int) TimeZone_GetSystemTime(HANDLE hTZ, mir_time ts, SYSTEMTIME *dest, DWORD dwFlags)
+{
+ if (dest == nullptr)
+ return 2;
+
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE *)hTZ;
+ if (tz == nullptr && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) {
+ memset(dest, 0, sizeof(SYSTEMTIME));
+ return 1;
+ }
+
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ FILETIME ft;
+ if (tz == UTC_TIME_HANDLE)
+ UnixTimeToFileTime(ts, &ft);
+ else {
+ if (tz->offset == INT_MIN)
+ CalcTsOffset(tz);
+
+ UnixTimeToFileTime(ts + tz->offset, &ft);
+ }
+
+ FileTimeToSystemTime(&ft, dest);
+ return 0;
+}
+
+MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags)
+{
+ SYSTEMTIME st;
+ if (!TimeZone_GetSystemTime(hTZ, ts, &st, dwFlags))
+ FormatTime(&st, szFormat, szDest, cbDest);
+ return 0;
+}
+
+MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ return tz ? &tz->tzi : &myInfo.myTZ.tzi;
+}
+
+MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts)
+{
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ;
+ if (tz == nullptr)
+ tz = &myInfo.myTZ;
+
+ if (tz == UTC_TIME_HANDLE)
+ return ts;
+
+ if (tz->offset == INT_MIN)
+ CalcTsOffset(tz);
+
+ return ts + tz->offset;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct ListMessages
+{
+ UINT addStr, getSel, setSel, getData, setData;
+};
+
+static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA };
+static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA };
+
+static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags)
+{
+ if (hWnd == nullptr)
+ return nullptr;
+
+ if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) {
+ wchar_t tszClassName[128];
+ GetClassName(hWnd, tszClassName, _countof(tszClassName));
+ if (!mir_wstrcmpi(tszClassName, L"COMBOBOX"))
+ dwFlags |= TZF_PLF_CB;
+ else if (!mir_wstrcmpi(tszClassName, L"LISTBOX"))
+ dwFlags |= TZF_PLF_LB;
+ }
+
+ if (dwFlags & TZF_PLF_CB)
+ return &cbMessages;
+ if (dwFlags & TZF_PLF_LB)
+ return &lbMessages;
+ return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
+{
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg == nullptr)
+ return -1;
+
+ if (szModule == nullptr)
+ szModule = "UserInfo";
+
+ int iSelection = 0;
+ ptrW tszName(db_get_wsa(hContact, szModule, "TzName"));
+ if (tszName != NULL) {
+ unsigned hash = mir_hashstrT(tszName);
+ for (auto &it : g_timezonesBias) {
+ if (hash == it->hash) {
+ iSelection = g_timezonesBias.indexOf(&it) + 1;
+ break;
+ }
+ }
+ }
+ else {
+ signed char cBias = db_get_b(hContact, szModule, "Timezone", -100);
+ if (cBias != -100) {
+ int iBias = cBias * 30;
+ for (auto &it : g_timezonesBias) {
+ if (iBias == it->tzi.Bias) {
+ iSelection = g_timezonesBias.indexOf(&it) + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ SendMessage(hWnd, lstMsg->setSel, iSelection, 0);
+ return iSelection;
+}
+
+MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
+{
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg == nullptr)
+ return 0;
+
+ SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateW_LP(L"<unspecified>"));
+
+ for (auto &it : g_timezonesBias) {
+ SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)it->szDisplay);
+ SendMessage(hWnd, lstMsg->setData, g_timezonesBias.indexOf(&it) + 1, (LPARAM)it);
+ }
+
+ return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags);
+}
+
+MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags)
+{
+ if (szModule == nullptr) szModule = "UserInfo";
+
+ const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags);
+ if (lstMsg) {
+ LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0);
+ if (offset > 0) {
+ MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0);
+ if ((INT_PTR)tz != CB_ERR && tz != nullptr)
+ TimeZone_StoreByContact(hContact, szModule, tz);
+ }
+ else TimeZone_StoreByContact(hContact, szModule, nullptr);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal)
+{
+ return TimeZone_UtcToLocal(nullptr, (mir_time)timeVal);
+}
+
+MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest)
+{
+ wchar_t *szTemp = (wchar_t*)alloca(cchDest*sizeof(wchar_t));
+ TimeZone_PrintTimeStamp(nullptr, timeVal, _A2T(szFormat), szTemp, cchDest, 0);
+ WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, nullptr, nullptr);
+ return szDest;
+}
+
+MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest)
+{
+ TimeZone_PrintTimeStamp(nullptr, timeVal, wszFormat, wszDest, cchDest, 0);
+ return wszDest;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GetLocalizedString(HKEY hSubKey, const wchar_t *szName, wchar_t *szBuf, DWORD cbLen)
+{
+ DWORD dwLength = cbLen * sizeof(wchar_t);
+ RegQueryValueEx(hSubKey, szName, nullptr, nullptr, (unsigned char *)szBuf, &dwLength);
+ szBuf[min(dwLength / sizeof(wchar_t), cbLen - 1)] = 0;
+}
+
+void RecalculateTime(void)
+{
+ GetTimeZoneInformation(&myInfo.myTZ.tzi);
+ myInfo.timestamp = time(0);
+ myInfo.myTZ.offset = INT_MIN;
+
+ bool found = false;
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi;
+
+ if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) {
+ wcsncpy_s(myInfo.myTZ.tszName, dtzi.TimeZoneKeyName, _TRUNCATE);
+ found = true;
+ }
+
+ for (auto &tz : g_timezones) {
+ if (tz->offset != INT_MIN)
+ tz->offset = INT_MIN;
+
+ if (!found) {
+ if (!mir_wstrcmp(tz->tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz->tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) {
+ wcsncpy_s(myInfo.myTZ.tszName, tz->tszName, _TRUNCATE);
+ found = true;
+ }
+ }
+ }
+}
+
+void InitTimeZones(void)
+{
+ REG_TZI_FORMAT tzi;
+ HKEY hKey;
+
+ const wchar_t *tszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
+
+ /*
+ * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with
+ * the registry key name, so finding our own time zone later will be MUCH easier for
+ * localized systems or systems with a MUI pack installed
+ */
+ if (IsWinVerVistaPlus())
+ pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(L"kernel32"), "GetDynamicTimeZoneInformation");
+
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) {
+ DWORD dwIndex = 0;
+ HKEY hSubKey;
+ wchar_t tszName[MIM_TZ_NAMELEN];
+
+ DWORD dwSize = _countof(tszName);
+ while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, nullptr, nullptr, nullptr, nullptr)) {
+ if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) {
+ dwSize = sizeof(tszName);
+
+ DWORD dwLength = sizeof(tzi);
+ if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, L"TZI", nullptr, nullptr, (unsigned char *)&tzi, &dwLength))
+ continue;
+
+ MIM_TIMEZONE *tz = new MIM_TIMEZONE;
+
+ tz->tzi.Bias = tzi.Bias;
+ tz->tzi.StandardDate = tzi.StandardDate;
+ tz->tzi.StandardBias = tzi.StandardBias;
+ tz->tzi.DaylightDate = tzi.DaylightDate;
+ tz->tzi.DaylightBias = tzi.DaylightBias;
+
+ mir_wstrcpy(tz->tszName, tszName);
+ tz->hash = mir_hashstrT(tszName);
+ tz->offset = INT_MIN;
+
+ GetLocalizedString(hSubKey, L"Display", tz->szDisplay, _countof(tz->szDisplay));
+ GetLocalizedString(hSubKey, L"Std", tz->tzi.StandardName, _countof(tz->tzi.StandardName));
+ GetLocalizedString(hSubKey, L"Dlt", tz->tzi.DaylightName, _countof(tz->tzi.DaylightName));
+
+ g_timezones.insert(tz);
+ g_timezonesBias.insert(tz);
+
+ RegCloseKey(hSubKey);
+ }
+ dwSize = _countof(tszName);
+ }
+ RegCloseKey(hKey);
+ }
+
+ RecalculateTime();
+}
diff --git a/src/mir_core/src/windowlist.cpp b/src/mir_core/src/Windows/windowlist.cpp
index 99631cb9a5..6549b28812 100644
--- a/src/mir_core/src/windowlist.cpp
+++ b/src/mir_core/src/Windows/windowlist.cpp
@@ -1,105 +1,105 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-struct TWindowListItem
-{
- TWindowListItem(UINT_PTR _param, HWND _wnd) :
- param(_param),
- hWnd(_wnd)
- {}
-
- UINT_PTR param;
- HWND hWnd;
-};
-
-struct TWindowList : public OBJLIST<TWindowListItem>
-{
- TWindowList() :
- OBJLIST<TWindowListItem>(10, NumericKeySortT)
- {}
-};
-
-MIR_CORE_DLL(MWindowList) WindowList_Create(void)
-{
- return new TWindowList();
-}
-
-MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList)
-{
- delete hList;
- hList = nullptr;
-}
-
-MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param)
-{
- if (hList == nullptr)
- return 1;
-
- hList->insert(new TWindowListItem(param, hwnd));
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd)
-{
- if (hList == nullptr) return 1;
-
- for (auto &it : *hList)
- if (it->hWnd == hwnd) {
- hList->removeItem(&it);
- return 0;
- }
-
- return 1;
-}
-
-MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param)
-{
- if (hList == nullptr)
- return nullptr;
-
- TWindowListItem *p = hList->find((TWindowListItem*)&param);
- return (p == nullptr) ? nullptr : p->hWnd;
-}
-
-MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- SendMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
-
-MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (hList == nullptr)
- return 0;
-
- for (auto &it : hList->rev_iter())
- PostMessage(it->hWnd, message, wParam, lParam);
- return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+struct TWindowListItem
+{
+ TWindowListItem(UINT_PTR _param, HWND _wnd) :
+ param(_param),
+ hWnd(_wnd)
+ {}
+
+ UINT_PTR param;
+ HWND hWnd;
+};
+
+struct TWindowList : public OBJLIST<TWindowListItem>
+{
+ TWindowList() :
+ OBJLIST<TWindowListItem>(10, NumericKeySortT)
+ {}
+};
+
+MIR_CORE_DLL(MWindowList) WindowList_Create(void)
+{
+ return new TWindowList();
+}
+
+MIR_CORE_DLL(void) WindowList_Destroy(MWindowList &hList)
+{
+ delete hList;
+ hList = nullptr;
+}
+
+MIR_CORE_DLL(int) WindowList_Add(MWindowList hList, HWND hwnd, UINT_PTR param)
+{
+ if (hList == nullptr)
+ return 1;
+
+ hList->insert(new TWindowListItem(param, hwnd));
+ return 0;
+}
+
+MIR_CORE_DLL(int) WindowList_Remove(MWindowList hList, HWND hwnd)
+{
+ if (hList == nullptr) return 1;
+
+ for (auto &it : *hList)
+ if (it->hWnd == hwnd) {
+ hList->removeItem(&it);
+ return 0;
+ }
+
+ return 1;
+}
+
+MIR_CORE_DLL(HWND) WindowList_Find(MWindowList hList, UINT_PTR param)
+{
+ if (hList == nullptr)
+ return nullptr;
+
+ TWindowListItem *p = hList->find((TWindowListItem*)&param);
+ return (p == nullptr) ? nullptr : p->hWnd;
+}
+
+MIR_CORE_DLL(int) WindowList_Broadcast(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (hList == nullptr)
+ return 0;
+
+ for (auto &it : hList->rev_iter())
+ SendMessage(it->hWnd, message, wParam, lParam);
+ return 0;
+}
+
+MIR_CORE_DLL(int) WindowList_BroadcastAsync(MWindowList hList, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (hList == nullptr)
+ return 0;
+
+ for (auto &it : hList->rev_iter())
+ PostMessage(it->hWnd, message, wParam, lParam);
+ return 0;
+}
diff --git a/src/mir_core/src/winutil.cpp b/src/mir_core/src/Windows/winutil.cpp
index a09fa90016..dbd729c896 100644
--- a/src/mir_core/src/winutil.cpp
+++ b/src/mir_core/src/Windows/winutil.cpp
@@ -1,118 +1,118 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top);
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags)
-{
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- GetWindowPlacement(hwnd, &wp);
-
- char szSettingName[64];
- mir_snprintf(szSettingName, "%sx", szNamePrefix);
- int x = db_get_dw(hContact, szModule, szSettingName, -1);
- if (x == -1)
- return 1;
-
- mir_snprintf(szSettingName, "%sy", szNamePrefix);
- int y = (int)db_get_dw(hContact, szModule, szSettingName, -1);
-
- if (flags & RWPF_NOSIZE)
- OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top);
- else {
- wp.rcNormalPosition.left = x;
- wp.rcNormalPosition.top = y;
-
- mir_snprintf(szSettingName, "%swidth", szNamePrefix);
- wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1);
-
- mir_snprintf(szSettingName, "%sheight", szNamePrefix);
- wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1);
- }
- wp.flags = 0;
- if (flags & RWPF_HIDDEN)
- wp.showCmd = SW_HIDE;
- if (flags & RWPF_NOACTIVATE)
- wp.showCmd = SW_SHOWNOACTIVATE;
-
- if (!(flags & RWPF_NOMOVE))
- Utils_AssertInsideScreen(&wp.rcNormalPosition);
-
- SetWindowPlacement(hwnd, &wp);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc)
-{
- if (rc == nullptr)
- return -1;
-
- RECT rcScreen;
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE);
- if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL))
- return 0;
-
- MONITORINFO mi = { 0 };
- HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST);
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMonitor, &mi))
- rcScreen = mi.rcWork;
-
- if (rc->top >= rcScreen.bottom)
- OffsetRect(rc, 0, rcScreen.bottom - rc->bottom);
- else if (rc->bottom <= rcScreen.top)
- OffsetRect(rc, 0, rcScreen.top - rc->top);
- if (rc->left >= rcScreen.right)
- OffsetRect(rc, rcScreen.right - rc->right, 0);
- else if (rc->right <= rcScreen.left)
- OffsetRect(rc, rcScreen.left - rc->left, 0);
-
- return 1;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "../stdafx.h"
+
+MIR_CORE_DLL(int) Utils_SaveWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+
+ char szSettingName[64];
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.left);
+
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.top);
+
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.right-wp.rcNormalPosition.left);
+
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ db_set_dw(hContact, szModule, szSettingName, wp.rcNormalPosition.bottom-wp.rcNormalPosition.top);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+EXTERN_C MIR_CORE_DLL(int) Utils_RestoreWindowPosition(HWND hwnd, MCONTACT hContact, const char *szModule, const char *szNamePrefix, int flags)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(wp);
+ GetWindowPlacement(hwnd, &wp);
+
+ char szSettingName[64];
+ mir_snprintf(szSettingName, "%sx", szNamePrefix);
+ int x = db_get_dw(hContact, szModule, szSettingName, -1);
+ if (x == -1)
+ return 1;
+
+ mir_snprintf(szSettingName, "%sy", szNamePrefix);
+ int y = (int)db_get_dw(hContact, szModule, szSettingName, -1);
+
+ if (flags & RWPF_NOSIZE)
+ OffsetRect(&wp.rcNormalPosition, x-wp.rcNormalPosition.left, y-wp.rcNormalPosition.top);
+ else {
+ wp.rcNormalPosition.left = x;
+ wp.rcNormalPosition.top = y;
+
+ mir_snprintf(szSettingName, "%swidth", szNamePrefix);
+ wp.rcNormalPosition.right = wp.rcNormalPosition.left+db_get_dw(hContact, szModule, szSettingName, -1);
+
+ mir_snprintf(szSettingName, "%sheight", szNamePrefix);
+ wp.rcNormalPosition.bottom = wp.rcNormalPosition.top+db_get_dw(hContact, szModule, szSettingName, -1);
+ }
+ wp.flags = 0;
+ if (flags & RWPF_HIDDEN)
+ wp.showCmd = SW_HIDE;
+ if (flags & RWPF_NOACTIVATE)
+ wp.showCmd = SW_SHOWNOACTIVATE;
+
+ if (!(flags & RWPF_NOMOVE))
+ Utils_AssertInsideScreen(&wp.rcNormalPosition);
+
+ SetWindowPlacement(hwnd, &wp);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(int) Utils_AssertInsideScreen(RECT *rc)
+{
+ if (rc == nullptr)
+ return -1;
+
+ RECT rcScreen;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &rcScreen, FALSE);
+ if (MonitorFromRect(rc, MONITOR_DEFAULTTONULL))
+ return 0;
+
+ MONITORINFO mi = { 0 };
+ HMONITOR hMonitor = MonitorFromRect(rc, MONITOR_DEFAULTTONEAREST);
+ mi.cbSize = sizeof(mi);
+ if (GetMonitorInfo(hMonitor, &mi))
+ rcScreen = mi.rcWork;
+
+ if (rc->top >= rcScreen.bottom)
+ OffsetRect(rc, 0, rcScreen.bottom - rc->bottom);
+ else if (rc->bottom <= rcScreen.top)
+ OffsetRect(rc, 0, rcScreen.top - rc->top);
+ if (rc->left >= rcScreen.right)
+ OffsetRect(rc, rcScreen.right - rc->right, 0);
+ else if (rc->right <= rcScreen.left)
+ OffsetRect(rc, rcScreen.left - rc->left, 0);
+
+ return 1;
+}
diff --git a/src/mir_core/src/winver.cpp b/src/mir_core/src/Windows/winver.cpp
index 28ced22337..d519d10478 100644
--- a/src/mir_core/src/winver.cpp
+++ b/src/mir_core/src/Windows/winver.cpp
@@ -1,372 +1,372 @@
-/*
-Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation version 2
-of the License.
-
-This program 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdafx.h"
-
-#ifndef _WIN32_WINNT_WIN8
-#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
-#endif
-
-#ifndef _WIN32_WINNT_WINBLUE
-#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
-#endif
-
-#ifndef _WIN32_WINNT_WIN10
-#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
-#endif
-
-static int dwWinVer;
-
-void InitWinver()
-{
- DWORD dwVer = LOWORD(GetVersion());
- dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer));
-}
-
-MIR_CORE_DLL(BOOL) IsWinVerVistaPlus()
-{
- return dwWinVer >= _WIN32_WINNT_VISTA;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer7Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN7;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer8Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN8;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer81Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WINBLUE;
-}
-
-MIR_CORE_DLL(BOOL) IsWinVer10Plus()
-{
- return dwWinVer >= _WIN32_WINNT_WIN10;
-}
-
-MIR_CORE_DLL(BOOL) IsFullScreen()
-{
- RECT rcScreen = { 0 };
-
- rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
- rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
-
- HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST);
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hMon, &mi))
- rcScreen = mi.rcMonitor;
-
- HWND hWndDesktop = GetDesktopWindow();
- HWND hWndShell = GetShellWindow();
-
- // check foregroundwindow
- HWND hWnd = GetForegroundWindow();
- if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) {
- wchar_t tszClassName[128] = L"";
- GetClassName(hWnd, tszClassName, _countof(tszClassName));
- if (wcscmp(tszClassName, L"WorkerW")) {
- RECT rect, rectw, recti;
- GetWindowRect(hWnd, &rectw);
-
- GetClientRect(hWnd, &rect);
- ClientToScreen(hWnd, (LPPOINT)&rect);
- ClientToScreen(hWnd, (LPPOINT)&rect.right);
-
- if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen))
- return true;
- }
- }
-
- return false;
-}
-
-MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
-{
- HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
- if (hDesk == nullptr)
- return true;
-
- wchar_t tszName[100];
- DWORD cbName;
- BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0);
- CloseDesktop(hDesk);
- return bLocked;
-}
-
-MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
-{
- PVOID pBuffer = nullptr;
- DWORD pBytesReturned = 0;
- BOOL result = FALSE;
-
- if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
- if (*(PDWORD)pBuffer == WTSDisconnected)
- result = TRUE;
-
- if (pBuffer)
- WTSFreeMemory(pBuffer);
- return result;
-}
-
-MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
-{
- BOOL rc = FALSE;
- SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE);
- return rc != 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return false;
-
- mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer));
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifndef PRODUCT_CORE_N // Win8
-#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
-#define PRODUCT_PROFESSIONAL_WMC 0x00000067
-#endif
-
-typedef BOOL(WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
-typedef LPCSTR(WINAPI *WGV)(void);
-
-MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize)
-{
- if (buf == nullptr || bufSize == 0)
- return 0;
-
- buf[0] = 0;
-
- OSVERSIONINFOEX osvi = { 0 };
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
- if (!bOsVersionInfoEx) {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((OSVERSIONINFO*)&osvi))
- return false;
- }
-
- if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4)
- return false;
-
- SYSTEM_INFO sysInfo = { 0 };
- GetNativeSystemInfo(&sysInfo);
-
- CMStringA ret("Microsoft ");
-
- // Test for the specific product.
- if (osvi.dwMajorVersion >= 6) {
- if (osvi.dwMajorVersion == 10) {
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 10 ");
- else
- ret.Append("Windows Server 10 ");
- }
- else switch (osvi.dwMinorVersion) {
- case 0:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows Vista ");
- else
- ret.Append("Windows Server 2008 ");
- break;
-
- case 1:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 7 ");
- else
- ret.Append("Windows Server 2008 R2 ");
- break;
-
- case 2:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8 ");
- else
- ret.Append("Windows Server 2012 ");
- break;
-
- case 3:
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Windows 8.1 ");
- else
- ret.Append("Windows Server 2012 R2 ");
- break;
- }
-
- DWORD dwType = 0;
- HMODULE hKernel = GetModuleHandle(L"kernel32.dll");
- PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo");
- if (pGPI != nullptr)
- pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
-
- switch (dwType) {
- case PRODUCT_ULTIMATE:
- ret.Append("Ultimate Edition");
- break;
- case PRODUCT_PROFESSIONAL:
- ret.Append("Professional Edition");
- break;
- case PRODUCT_PROFESSIONAL_WMC:
- ret.Append("Professional Edition with Media Center");
- break;
- case PRODUCT_HOME_PREMIUM:
- ret.Append("Home Premium Edition");
- break;
- case PRODUCT_HOME_BASIC:
- ret.Append("Home Basic Edition");
- break;
- case PRODUCT_ENTERPRISE:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_BUSINESS:
- ret.Append("Business Edition");
- break;
- case PRODUCT_STARTER:
- ret.Append("Starter Edition");
- break;
- case PRODUCT_CLUSTER_SERVER:
- ret.Append("Cluster Server Edition");
- break;
- case PRODUCT_DATACENTER_SERVER:
- ret.Append("Datacenter Edition");
- break;
- case PRODUCT_DATACENTER_SERVER_CORE:
- ret.Append("Datacenter Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER:
- ret.Append("Enterprise Edition");
- break;
- case PRODUCT_ENTERPRISE_SERVER_CORE:
- ret.Append("Enterprise Edition (core installation)");
- break;
- case PRODUCT_ENTERPRISE_SERVER_IA64:
- ret.Append("Enterprise Edition for Itanium-based Systems");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER:
- ret.Append("Small Business Server");
- break;
- case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
- ret.Append("Small Business Server Premium Edition");
- break;
- case PRODUCT_STANDARD_SERVER:
- ret.Append("Standard Edition");
- break;
- case PRODUCT_STANDARD_SERVER_CORE:
- ret.Append("Standard Edition (core installation)");
- break;
- case PRODUCT_WEB_SERVER:
- ret.Append("Web Server Edition");
- break;
- case PRODUCT_CORE_SINGLELANGUAGE:
- ret.Append("Home Single Language");
- break;
- }
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append(", 64-bit");
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- ret.Append(", 32-bit");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
- if (GetSystemMetrics(SM_SERVERR2))
- ret.Append("Windows Server 2003 R2, ");
- else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
- ret.Append("Windows Storage Server 2003");
- else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
- ret.Append("Windows Home Server");
- else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- ret.Append("Windows XP Professional x64 Edition");
- else
- ret.Append("Windows Server 2003, ");
-
- // Test for the server type.
- if (osvi.wProductType != VER_NT_WORKSTATION) {
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition for Itanium-based Systems");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition for Itanium-based Systems");
- }
- else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter x64 Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise x64 Edition");
- else ret.Append("Standard x64 Edition");
- }
- else {
- if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
- ret.Append("Compute Cluster Edition");
- else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Edition");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Enterprise Edition");
- else if (osvi.wSuiteMask & VER_SUITE_BLADE)
- ret.Append("Web Edition");
- else ret.Append("Standard Edition");
- }
- }
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
- ret.Append("Windows XP ");
- if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- ret.Append("Home Edition");
- else ret.Append("Professional");
- }
-
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
- ret.Append("Windows 2000 ");
-
- if (osvi.wProductType == VER_NT_WORKSTATION)
- ret.Append("Professional");
- else {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- ret.Append("Datacenter Server");
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- ret.Append("Advanced Server");
- else ret.Append("Server");
- }
- }
-
- // Include service pack (if any) and build number.
- if (mir_wstrlen(osvi.szCSDVersion) > 0) {
- ret.Append(" ");
- ret.Append(_T2A(osvi.szCSDVersion));
- }
-
- ret.AppendFormat(" (build %d)", osvi.dwBuildNumber);
-
- HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
- if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version"))
- {
- ret.AppendFormat(" (Wine %s)", wine_get_version());
- }
-
- mir_strncpy(buf, ret, bufSize);
- return true;
-}
+/*
+Copyright (C) 2012-21 Miranda NG team (https://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "../stdafx.h"
+
+#ifndef _WIN32_WINNT_WIN8
+#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
+#endif
+
+#ifndef _WIN32_WINNT_WINBLUE
+#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
+#endif
+
+#ifndef _WIN32_WINNT_WIN10
+#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
+#endif
+
+static int dwWinVer;
+
+void InitWinver()
+{
+ DWORD dwVer = LOWORD(GetVersion());
+ dwWinVer = MAKEWORD(HIBYTE(dwVer), LOBYTE(dwVer));
+}
+
+MIR_CORE_DLL(BOOL) IsWinVerVistaPlus()
+{
+ return dwWinVer >= _WIN32_WINNT_VISTA;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer7Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN7;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer8Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN8;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer81Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WINBLUE;
+}
+
+MIR_CORE_DLL(BOOL) IsWinVer10Plus()
+{
+ return dwWinVer >= _WIN32_WINNT_WIN10;
+}
+
+MIR_CORE_DLL(BOOL) IsFullScreen()
+{
+ RECT rcScreen = { 0 };
+
+ rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
+ rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
+
+ HMONITOR hMon = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ if (GetMonitorInfo(hMon, &mi))
+ rcScreen = mi.rcMonitor;
+
+ HWND hWndDesktop = GetDesktopWindow();
+ HWND hWndShell = GetShellWindow();
+
+ // check foregroundwindow
+ HWND hWnd = GetForegroundWindow();
+ if (hWnd && hWnd != hWndDesktop && hWnd != hWndShell) {
+ wchar_t tszClassName[128] = L"";
+ GetClassName(hWnd, tszClassName, _countof(tszClassName));
+ if (wcscmp(tszClassName, L"WorkerW")) {
+ RECT rect, rectw, recti;
+ GetWindowRect(hWnd, &rectw);
+
+ GetClientRect(hWnd, &rect);
+ ClientToScreen(hWnd, (LPPOINT)&rect);
+ ClientToScreen(hWnd, (LPPOINT)&rect.right);
+
+ if (EqualRect(&rect, &rectw) && IntersectRect(&recti, &rect, &rcScreen) && EqualRect(&recti, &rcScreen))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+MIR_CORE_DLL(BOOL) IsWorkstationLocked(void)
+{
+ HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
+ if (hDesk == nullptr)
+ return true;
+
+ wchar_t tszName[100];
+ DWORD cbName;
+ BOOL bLocked = (!GetUserObjectInformation(hDesk, UOI_NAME, tszName, _countof(tszName), &cbName) || mir_wstrcmpi(tszName, L"default") != 0);
+ CloseDesktop(hDesk);
+ return bLocked;
+}
+
+MIR_CORE_DLL(BOOL) IsTerminalDisconnected(void)
+{
+ PVOID pBuffer = nullptr;
+ DWORD pBytesReturned = 0;
+ BOOL result = FALSE;
+
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState, (LPTSTR *)&pBuffer, &pBytesReturned))
+ if (*(PDWORD)pBuffer == WTSDisconnected)
+ result = TRUE;
+
+ if (pBuffer)
+ WTSFreeMemory(pBuffer);
+ return result;
+}
+
+MIR_CORE_DLL(BOOL) IsScreenSaverRunning(void)
+{
+ BOOL rc = FALSE;
+ SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &rc, FALSE);
+ return rc != 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_CORE_DLL(BOOL) OS_GetShortString(char *buf, size_t bufSize)
+{
+ if (buf == nullptr || bufSize == 0)
+ return false;
+
+ mir_snprintf(buf, bufSize, "Windows NT %d.%d", HIBYTE(dwWinVer), LOBYTE(dwWinVer));
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef PRODUCT_CORE_N // Win8
+#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
+#define PRODUCT_PROFESSIONAL_WMC 0x00000067
+#endif
+
+typedef BOOL(WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
+typedef LPCSTR(WINAPI *WGV)(void);
+
+MIR_CORE_DLL(BOOL) OS_GetDisplayString(char *buf, size_t bufSize)
+{
+ if (buf == nullptr || bufSize == 0)
+ return 0;
+
+ buf[0] = 0;
+
+ OSVERSIONINFOEX osvi = { 0 };
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ BOOL bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi);
+ if (!bOsVersionInfoEx) {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (!GetVersionEx((OSVERSIONINFO*)&osvi))
+ return false;
+ }
+
+ if (VER_PLATFORM_WIN32_NT != osvi.dwPlatformId || osvi.dwMajorVersion <= 4)
+ return false;
+
+ SYSTEM_INFO sysInfo = { 0 };
+ GetNativeSystemInfo(&sysInfo);
+
+ CMStringA ret("Microsoft ");
+
+ // Test for the specific product.
+ if (osvi.dwMajorVersion >= 6) {
+ if (osvi.dwMajorVersion == 10) {
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 10 ");
+ else
+ ret.Append("Windows Server 10 ");
+ }
+ else switch (osvi.dwMinorVersion) {
+ case 0:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows Vista ");
+ else
+ ret.Append("Windows Server 2008 ");
+ break;
+
+ case 1:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 7 ");
+ else
+ ret.Append("Windows Server 2008 R2 ");
+ break;
+
+ case 2:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 8 ");
+ else
+ ret.Append("Windows Server 2012 ");
+ break;
+
+ case 3:
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Windows 8.1 ");
+ else
+ ret.Append("Windows Server 2012 R2 ");
+ break;
+ }
+
+ DWORD dwType = 0;
+ HMODULE hKernel = GetModuleHandle(L"kernel32.dll");
+ PGPI pGPI = (PGPI)GetProcAddress(hKernel, "GetProductInfo");
+ if (pGPI != nullptr)
+ pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
+
+ switch (dwType) {
+ case PRODUCT_ULTIMATE:
+ ret.Append("Ultimate Edition");
+ break;
+ case PRODUCT_PROFESSIONAL:
+ ret.Append("Professional Edition");
+ break;
+ case PRODUCT_PROFESSIONAL_WMC:
+ ret.Append("Professional Edition with Media Center");
+ break;
+ case PRODUCT_HOME_PREMIUM:
+ ret.Append("Home Premium Edition");
+ break;
+ case PRODUCT_HOME_BASIC:
+ ret.Append("Home Basic Edition");
+ break;
+ case PRODUCT_ENTERPRISE:
+ ret.Append("Enterprise Edition");
+ break;
+ case PRODUCT_BUSINESS:
+ ret.Append("Business Edition");
+ break;
+ case PRODUCT_STARTER:
+ ret.Append("Starter Edition");
+ break;
+ case PRODUCT_CLUSTER_SERVER:
+ ret.Append("Cluster Server Edition");
+ break;
+ case PRODUCT_DATACENTER_SERVER:
+ ret.Append("Datacenter Edition");
+ break;
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ ret.Append("Datacenter Edition (core installation)");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER:
+ ret.Append("Enterprise Edition");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ ret.Append("Enterprise Edition (core installation)");
+ break;
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ ret.Append("Enterprise Edition for Itanium-based Systems");
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ ret.Append("Small Business Server");
+ break;
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ ret.Append("Small Business Server Premium Edition");
+ break;
+ case PRODUCT_STANDARD_SERVER:
+ ret.Append("Standard Edition");
+ break;
+ case PRODUCT_STANDARD_SERVER_CORE:
+ ret.Append("Standard Edition (core installation)");
+ break;
+ case PRODUCT_WEB_SERVER:
+ ret.Append("Web Server Edition");
+ break;
+ case PRODUCT_CORE_SINGLELANGUAGE:
+ ret.Append("Home Single Language");
+ break;
+ }
+ if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ ret.Append(", 64-bit");
+ else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ ret.Append(", 32-bit");
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
+ if (GetSystemMetrics(SM_SERVERR2))
+ ret.Append("Windows Server 2003 R2, ");
+ else if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER)
+ ret.Append("Windows Storage Server 2003");
+ else if (osvi.wSuiteMask == VER_SUITE_WH_SERVER)
+ ret.Append("Windows Home Server");
+ else if (osvi.wProductType == VER_NT_WORKSTATION && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+ ret.Append("Windows XP Professional x64 Edition");
+ else
+ ret.Append("Windows Server 2003, ");
+
+ // Test for the server type.
+ if (osvi.wProductType != VER_NT_WORKSTATION) {
+ if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Edition for Itanium-based Systems");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise Edition for Itanium-based Systems");
+ }
+ else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter x64 Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise x64 Edition");
+ else ret.Append("Standard x64 Edition");
+ }
+ else {
+ if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
+ ret.Append("Compute Cluster Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Enterprise Edition");
+ else if (osvi.wSuiteMask & VER_SUITE_BLADE)
+ ret.Append("Web Edition");
+ else ret.Append("Standard Edition");
+ }
+ }
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
+ ret.Append("Windows XP ");
+ if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
+ ret.Append("Home Edition");
+ else ret.Append("Professional");
+ }
+
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
+ ret.Append("Windows 2000 ");
+
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ ret.Append("Professional");
+ else {
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ ret.Append("Datacenter Server");
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ ret.Append("Advanced Server");
+ else ret.Append("Server");
+ }
+ }
+
+ // Include service pack (if any) and build number.
+ if (mir_wstrlen(osvi.szCSDVersion) > 0) {
+ ret.Append(" ");
+ ret.Append(_T2A(osvi.szCSDVersion));
+ }
+
+ ret.AppendFormat(" (build %d)", osvi.dwBuildNumber);
+
+ HMODULE hNtDll = GetModuleHandleA("ntdll.dll");
+ if (WGV wine_get_version = (WGV)GetProcAddress(hNtDll, "wine_get_version"))
+ {
+ ret.AppendFormat(" (Wine %s)", wine_get_version());
+ }
+
+ mir_strncpy(buf, ret, bufSize);
+ return true;
+}