From 19b4f9bbfc88b19c6d496784ab70b92f7b5d01c8 Mon Sep 17 00:00:00 2001 From: alur Date: Thu, 12 Jul 2012 23:50:13 -0700 Subject: [PATCH 01/50] Added files for vs11 --- litestep/litestep_vc11.vcxproj | 170 ++++++++++++++++++++++++++++++++ litestep_vc11.sln | 31 ++++++ lsapi/lsapi_vc11.vcxproj | 175 +++++++++++++++++++++++++++++++++ utility/utility_vc11.vcxproj | 122 +++++++++++++++++++++++ 4 files changed, 498 insertions(+) create mode 100644 litestep/litestep_vc11.vcxproj create mode 100644 litestep_vc11.sln create mode 100644 lsapi/lsapi_vc11.vcxproj create mode 100644 utility/utility_vc11.vcxproj diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj new file mode 100644 index 0000000..a822f58 --- /dev/null +++ b/litestep/litestep_vc11.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + litestep + {994556EE-2F21-4811-A85D-6925F7F84B0D} + litestep + Win32Proj + $(VCTargetsPath11) + + + + Application + MultiByte + true + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11\ + Debug_VC11\ + true + ../Release_VC11\ + Release_VC11\ + false + + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + EditAndContinue + Default + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + NotSet + false + true + true + + + Level4 + false + + + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2feca0a4-cb2f-44ca-97ab-de78ebbdecfa} + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + + \ No newline at end of file diff --git a/litestep_vc11.sln b/litestep_vc11.sln new file mode 100644 index 0000000..8e73a21 --- /dev/null +++ b/litestep_vc11.sln @@ -0,0 +1,31 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc11.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc11.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc11.vcxproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj new file mode 100644 index 0000000..18eb9ea --- /dev/null +++ b/lsapi/lsapi_vc11.vcxproj @@ -0,0 +1,175 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + lsapi + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} + lsapi + Win32Proj + $(VCTargetsPath11) + + + + DynamicLibrary + MultiByte + true + v110 + + + DynamicLibrary + MultiByte + v110 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11\ + Debug_VC11\ + true + ../Release_VC11\ + Release_VC11\ + false + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + EditAndContinue + Default + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + MachineX86 + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + + \ No newline at end of file diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj new file mode 100644 index 0000000..d436aa9 --- /dev/null +++ b/utility/utility_vc11.vcxproj @@ -0,0 +1,122 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + utility + {2213036F-018C-416A-8A6A-7934C936CFFC} + utility + Win32Proj + $(VCTargetsPath11) + + + + StaticLibrary + MultiByte + true + v110 + + + StaticLibrary + MultiByte + v110 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11\ + Debug_VC11\ + ../Release_VC11\ + Release_VC11\ + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + EditAndContinue + Default + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + + + $(OutDir)utility.lib + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 12b2c0d2ca1f655b3ed748197d99361c2dab08f3 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 00:05:44 -0700 Subject: [PATCH 02/50] Fixed missing header (at least for vs11). --- litestep/litestep.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index 78870ed..da379ad 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -40,13 +40,12 @@ #include "../utility/core.hpp" #include #include - +#include // namespace stuff using std::for_each; using std::mem_fun; - //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // GetAppPath From b061a1518dadb9e22accca18473a7a75e3cef388 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 00:11:48 -0700 Subject: [PATCH 03/50] Restored some deleted newlines --- litestep/litestep.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index da379ad..1748212 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -42,10 +42,12 @@ #include #include + // namespace stuff using std::for_each; using std::mem_fun; + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // GetAppPath From 2cf5f6e56e8aeb13ea3307bd37284bffdfc33141 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 00:29:34 -0700 Subject: [PATCH 04/50] Added support for Windows 8 and Windows Server 2012 to the GetWinVer functions. --- lsapi/aboutbox.cpp | 2 ++ utility/shellhlp.cpp | 4 +++- utility/shellhlp.h | 8 +++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index fbe1eb3..65b2efc 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -641,6 +641,7 @@ static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) case WINVER_WINXP: pszTemp = _T("Windows XP"); break; case WINVER_VISTA: pszTemp = _T("Windows Vista"); break; case WINVER_WIN7: pszTemp = _T("Windows 7"); break; + case WINVER_WIN8: pszTemp = _T("Windows 8"); break; case WINVER_WIN2003: if (GetSystemMetrics(SM_SERVERR2)) { @@ -653,6 +654,7 @@ static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) break; case WINVER_WHS: pszTemp = _T("Windows Home Server"); break; case WINVER_WIN2008: pszTemp = _T("Windows Server 2008"); break; + case WINVER_WIN2012: pszTemp = _T("Windows Server 2012"); break; default: pszTemp = _T(""); break; } diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index 0c919cd..c964ae7 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -631,7 +631,9 @@ UINT GetWindowsVersion() { 6, 0, WVM_WORKSTATION, WINVER_VISTA }, { 6, 0, WVM_SERVER, WINVER_WIN2008 }, - { 6, 1, WVM_ANY, WINVER_WIN7 } + { 6, 1, WVM_ANY, WINVER_WIN7 }, + { 6, 2, WVM_SERVER, WINVER_WIN2012 }, + { 6, 2, WVM_ANY, WINVER_WIN8 } }; for (size_t idx = 0; idx < COUNTOF(versions); ++idx) diff --git a/utility/shellhlp.h b/utility/shellhlp.h index 0284f49..85832e7 100644 --- a/utility/shellhlp.h +++ b/utility/shellhlp.h @@ -88,11 +88,13 @@ UINT GetWindowsVersion(); #define WINVER_WINXP 6 #define WINVER_VISTA 7 #define WINVER_WIN7 8 +#define WINVER_WIN8 9 // Windows NT Server -#define WINVER_WIN2003 9 -#define WINVER_WHS 10 -#define WINVER_WIN2008 11 +#define WINVER_WIN2003 10 +#define WINVER_WHS 11 +#define WINVER_WIN2008 12 +#define WINVER_WIN2012 13 //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= From 6f139eb6630b11e8932313cbfed3752d69d39b8f Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 00:35:09 -0700 Subject: [PATCH 05/50] Enabled multi processor compilation for release builds --- litestep/litestep_vc11.vcxproj | 1 + lsapi/lsapi_vc11.vcxproj | 1 + utility/utility_vc11.vcxproj | 1 + 3 files changed, 3 insertions(+) diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index a822f58..ebcdce6 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -103,6 +103,7 @@ Default true + true ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 18eb9ea..58fcd35 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -101,6 +101,7 @@ Default true + true advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index d436aa9..31ec861 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -93,6 +93,7 @@ Default true + true $(OutDir)utility.lib From 1a260f9646c240e0bc77c13234bd8ec02e8df637 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 00:50:17 -0700 Subject: [PATCH 06/50] Fixed about box not showing more than 4GB of memory. --- lsapi/aboutbox.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 65b2efc..a343b2b 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -49,7 +49,7 @@ static void AboutSysInfo(HWND hListView); // Utility static HFONT CreateSimpleFont(LPCSTR pszName, int nSizeInPoints, bool bBold); static int GetClientWidth(HWND hWnd); -static void FormatBytes(size_t stBytes, LPSTR pszBuffer, size_t cchBuffer); +static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -721,8 +721,8 @@ static void AboutSysInfo(HWND hListView) // memory information DWORD dwMemoryLoad; - DWORD dwTotalPhys, dwAvailPhys; - DWORD dwTotalPageFile, dwAvailPageFile; + DWORDLONG dwTotalPhys, dwAvailPhys; + DWORDLONG dwTotalPageFile, dwAvailPageFile; typedef BOOL (WINAPI *GMSExFunctionType)(LPMEMORYSTATUSEX); GMSExFunctionType fpGlobalMemoryStatusEx = (GMSExFunctionType)GetProcAddress( @@ -734,11 +734,11 @@ static void AboutSysInfo(HWND hListView) ms.dwLength = sizeof(MEMORYSTATUSEX); fpGlobalMemoryStatusEx(&ms); - dwMemoryLoad = ms.dwMemoryLoad; - dwTotalPhys = ms.ullTotalPhys > MAXDWORD ? MAXDWORD : (DWORD)ms.ullTotalPhys; - dwAvailPhys = ms.ullAvailPhys > MAXDWORD ? MAXDWORD : (DWORD)ms.ullAvailPhys; - dwTotalPageFile = ms.ullTotalPageFile > MAXDWORD ? MAXDWORD : (DWORD)ms.ullTotalPageFile; - dwAvailPageFile = ms.ullAvailPageFile > MAXDWORD ? MAXDWORD : (DWORD)ms.ullAvailPageFile; + dwMemoryLoad = (DWORD)ms.dwMemoryLoad; + dwTotalPhys = (DWORDLONG)ms.ullTotalPhys; + dwAvailPhys = (DWORDLONG)ms.ullAvailPhys; + dwTotalPageFile = (DWORDLONG)ms.ullTotalPageFile; + dwAvailPageFile = (DWORDLONG)ms.ullAvailPageFile; } else { @@ -747,10 +747,10 @@ static void AboutSysInfo(HWND hListView) GlobalMemoryStatus(&ms); dwMemoryLoad = (DWORD)ms.dwMemoryLoad; - dwTotalPhys = (DWORD)ms.dwTotalPhys; - dwAvailPhys = (DWORD)ms.dwAvailPhys; - dwTotalPageFile = (DWORD)ms.dwTotalPageFile; - dwAvailPageFile = (DWORD)ms.dwAvailPageFile; + dwTotalPhys = (DWORDLONG)ms.dwTotalPhys; + dwAvailPhys = (DWORDLONG)ms.dwAvailPhys; + dwTotalPageFile = (DWORDLONG)ms.dwTotalPageFile; + dwAvailPageFile = (DWORDLONG)ms.dwAvailPageFile; } strcpy(text, "Memory Load"); @@ -845,12 +845,9 @@ static int GetClientWidth(HWND hWnd) // FormatBytes // Formats a byte count into a string suitable for display to the user // -// Note: Max value of stBytes is 4 GB, so no need to be concerned of -// overrunning units[] index. -// -static LPCSTR units[] = { "bytes", "KB", "MB", "GB" }; +static LPCSTR units[] = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; -static void FormatBytes(size_t stBytes, LPSTR pszBuffer, size_t cchBuffer) +static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer) { double dValue = (double)stBytes; unsigned int uUnit = 0; From 2a6485ad4ec444f48eeabc44c0ef25ad40d99239 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 01:23:58 -0700 Subject: [PATCH 07/50] Added a very basic performance page to the about dialog. --- litestep/Module.cpp | 5 +++ litestep/Module.h | 13 ++++++- litestep/ModuleManager.cpp | 19 +++++++++ litestep/ModuleManager.h | 14 +++++++ litestep/litestep.cpp | 14 +++++++ lsapi/aboutbox.cpp | 79 +++++++++++++++++++++++++++++++++++--- lsapi/lsapi.cpp | 6 +++ lsapi/lsapidefines.h | 3 ++ 8 files changed, 146 insertions(+), 7 deletions(-) diff --git a/litestep/Module.cpp b/litestep/Module.cpp index 2be1cf6..cd432a8 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -36,6 +36,7 @@ Module::Module(const std::string& sLocation, DWORD dwFlags) m_hInitCopyEvent = NULL; m_pQuit = NULL; m_dwFlags = dwFlags; + m_dwLoadTime = 0; m_tzLocation = sLocation; } @@ -174,6 +175,8 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) { ASSERT(NULL == m_hInstance); + DWORD dwStartTime = GetTickCount(); + // delaying the LoadLibrary call until this point is necessary to make // grdtransparent work (it hooks LoadLibrary) if (_LoadDll()) @@ -204,6 +207,8 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) CallInit(); } + m_dwLoadTime = GetTickCount() - dwStartTime; + return true; } diff --git a/litestep/Module.h b/litestep/Module.h index 4448460..ebc529b 100644 --- a/litestep/Module.h +++ b/litestep/Module.h @@ -59,6 +59,9 @@ class Module /** Flags used to load module */ DWORD m_dwFlags; + + /** The amount of time it took to load the module */ + DWORD m_dwLoadTime; /** * Event that is triggered when a threaded module completes initialization @@ -185,7 +188,15 @@ class Module { return m_dwFlags; } - + + /** + * Returns how long this module took to load. + */ + DWORD GetLoadTime() const + { + return m_dwLoadTime; + } + /** * Returns a pointer to this module's quitModule function. */ diff --git a/litestep/ModuleManager.cpp b/litestep/ModuleManager.cpp index 6efd488..71a904d 100644 --- a/litestep/ModuleManager.cpp +++ b/litestep/ModuleManager.cpp @@ -416,3 +416,22 @@ HRESULT ModuleManager::EnumModules(LSENUMMODULESPROC pfnCallback, LPARAM lParam) return hr; } + + +HRESULT ModuleManager::EnumPerformance(LSENUMPERFORMANCEPROC pfnCallback, LPARAM lParam) const +{ + HRESULT hr = S_OK; + + for (ModuleQueue::const_iterator iter = m_ModuleQueue.begin(); + iter != m_ModuleQueue.end(); ++iter) + { + if (!pfnCallback((*iter)->GetLocation(), (*iter)->GetLoadTime(), + lParam)) + { + hr = S_FALSE; + break; + } + } + + return hr; +} \ No newline at end of file diff --git a/litestep/ModuleManager.h b/litestep/ModuleManager.h index a14ce76..c927aed 100644 --- a/litestep/ModuleManager.h +++ b/litestep/ModuleManager.h @@ -129,6 +129,20 @@ class ModuleManager: public IManager */ HRESULT EnumModules(LSENUMMODULESPROC pfnCallback, LPARAM lParam) const; + /** + * Enumerates performance statistics for loaded modules. Calls the callback + * function once for each loaded module. Continues until all modules have + * been enumerated or the callback function returns FALSE. + * + * @param pfnCallback pointer to callback function + * @param lParam application-defined value passed to the callback + * function + * @return S_OK if all modules were enumerated, + * S_FALSE if the callback function returned + * FALSE, or an error code + */ + HRESULT EnumPerformance(LSENUMPERFORMANCEPROC pfnCallback, LPARAM lParam) const; + private: /** * Loads all the modules specified in step.rc. diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index 1748212..7adccfe 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -883,6 +883,20 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } break; + case LM_ENUMPERFORMANCE: + { + HRESULT hr = E_FAIL; + + if (m_pModuleManager) + { + hr = m_pModuleManager->EnumPerformance((LSENUMPERFORMANCEPROC)wParam, + lParam); + } + + return hr; + } + break; + case LM_RECYCLE: { switch (wParam) diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index a343b2b..be8bf61 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -45,6 +45,7 @@ static void AboutLicense(HWND hEdit); static void AboutModules(HWND hListView); static void AboutRevIDs(HWND hListView); static void AboutSysInfo(HWND hListView); +static void AboutPerformance(HWND hListView); // Utility static HFONT CreateSimpleFont(LPCSTR pszName, int nSizeInPoints, bool bBold); @@ -65,6 +66,7 @@ enum ,ABOUT_MODULES ,ABOUT_REVIDS ,ABOUT_SYSINFO + ,ABOUT_PERFORMANCE }; struct AboutOptions @@ -74,12 +76,13 @@ struct AboutOptions } static const g_aboutOptions[] = \ { - { "Bang Commands", AboutBangs } - ,{ "Development Team", AboutDevTeam } - ,{ "License", AboutLicense } - ,{ "Loaded Modules", AboutModules } - ,{ "Revision IDs", AboutRevIDs } - ,{ "System Information", AboutSysInfo } + { "Bang Commands", AboutBangs } + ,{ "Development Team", AboutDevTeam } + ,{ "License", AboutLicense } + ,{ "Loaded Modules", AboutModules } + ,{ "Performance", AboutPerformance } + ,{ "Revision IDs", AboutRevIDs } + ,{ "System Information", AboutSysInfo } }; @@ -337,6 +340,7 @@ static INT_PTR OnCommand( case ABOUT_BANGS: case ABOUT_DEVTEAM: case ABOUT_MODULES: + case ABOUT_PERFORMANCE: case ABOUT_SYSINFO: // set the current display to the list view g_aboutOptions[i].function(hListView); @@ -571,6 +575,69 @@ static void AboutModules(HWND hListView) } +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// PerformanceCallback +// Used by AboutPerformance +// +static BOOL CALLBACK PerformanceCallback(LPCSTR pszPath, DWORD dwLoadTime, LPARAM lParam) +{ + CallbackInfo* pCi = (CallbackInfo*)lParam; + + CHAR szModule[MAX_PATH] = { 0 }; + strcpy(szModule, pszPath); + PathStripPath(szModule); + + LVITEM itemInfo; + itemInfo.mask = LVIF_TEXT; + itemInfo.iItem = pCi->nItem; + itemInfo.pszText = szModule; + itemInfo.iSubItem = 0; + + ListView_InsertItem(pCi->hListView, &itemInfo); + + sprintf(szModule, "%dms", dwLoadTime); + ListView_SetItemText(pCi->hListView, pCi->nItem, 1, szModule); + + ++pCi->nItem; + return TRUE; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// AboutPerformance +// +static void AboutPerformance(HWND hListView) +{ + LVCOLUMN columnInfo; + char text[32]; + + int width = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); + + strcpy(text, "Module"); + columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + columnInfo.fmt = LVCFMT_LEFT; + columnInfo.cx = width / 2; + columnInfo.pszText = text; + columnInfo.iSubItem = 0; + + ListView_InsertColumn(hListView, 0, &columnInfo); + + strcpy(text, "Load Time"); + columnInfo.cx = width - columnInfo.cx; + columnInfo.pszText = text; + columnInfo.iSubItem = 1; + + ListView_InsertColumn(hListView, 1, &columnInfo); + + CallbackInfo ci = { 0 }; + ci.hListView = hListView; + + EnumLSData(ELD_PERFORMANCE, (FARPROC)PerformanceCallback, (LPARAM)&ci); +} + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // RevIDCallback diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index cb26d99..5041141 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -715,6 +715,12 @@ HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) } break; + case ELD_PERFORMANCE: + { + hr = (HRESULT)SendMessage(GetLitestepWnd(), LM_ENUMPERFORMANCE, + (WPARAM)pfnCallback, lParam); + } + default: { // do nothing diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index db77329..4cd584d 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -127,6 +127,7 @@ #define LM_BANGCOMMAND 9420 #define LM_ENUMREVIDS 9430 #define LM_ENUMMODULES 9431 +#define LM_ENUMPERFORMANCE 9432 #endif @@ -258,6 +259,7 @@ typedef struct LSDESKTOPINFO #define ELD_MODULES 2 #define ELD_REVIDS 3 #define ELD_BANGS_V2 4 +#define ELD_PERFORMANCE 5 // ELD_MODULES: possible dwFlags values #define LS_MODULE_THREADED 0x0001 @@ -267,5 +269,6 @@ typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); #endif // LSAPIDEFINES_H From d615d0439a8b791aa5c2c8a5746a83c8111c8771 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 02:00:50 -0700 Subject: [PATCH 08/50] Updated picopng and removed warnings in debug mode. --- lsapi/picopng.cpp | 1081 +++++++++++++++++++++++---------------------- 1 file changed, 543 insertions(+), 538 deletions(-) diff --git a/lsapi/picopng.cpp b/lsapi/picopng.cpp index 934dc31..dddb0c2 100644 --- a/lsapi/picopng.cpp +++ b/lsapi/picopng.cpp @@ -1,538 +1,543 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2011 LiteStep Development 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 "../litestep/buildoptions.h" - -#if defined(LS_USE_PICOPNG) - -#include - -// These were moved outside of "decodePNG()" for VC7.1/8 compiler support -static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; -static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; -static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; -static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; -static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths - -int decodePNG(std::vector& out_image_32bit, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) -{ - // picoPNG version 20080503 - // Copyright (c) 2005-2008 Lode Vandevenne - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // picoPNG is a PNG decoder in one C++ function. Use picoPNG for programs that need - // only 1 .cpp file. Apologies for the compact code style, it's to make it tiny. - - struct Zlib //nested functions for zlib decompression - { - static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} - static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) - { - unsigned long result = 0; - for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; - return result; - } - struct HuffmanTree - { - int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) - { //make tree given the lengths - unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; - std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); - for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length - for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; - for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes - tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet - for(unsigned long n = 0; n < numcodes; n++) //the codes - for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code - { - unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; - if(treepos > numcodes - 2) return 55; - if(tree2d[2 * treepos + bit] == 32767) //not yet filled in - { - if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit - else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes - } - else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value - } - return 0; - } - int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const - { //Decodes a symbol from the tree - unsigned long numcodes = (unsigned long)tree2d.size() / 2; - if(treepos >= numcodes) return 11; //error: you appeared outside the codetree - result = tree2d[2 * treepos + bit]; - decoded = (result < numcodes); - treepos = decoded ? 0 : result - numcodes; - return 0; - } - std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. - }; - struct Inflator - { - int error; - void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) - { - size_t bp = 0, pos = 0; //bit pointer and byte pointer - error = 0; - unsigned long BFINAL = 0; - while(!BFINAL && !error) - { - if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory - BFINAL = readBitFromStream(bp, &in[inpos]); - unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); - if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE - else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); - else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); - } - if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that - } - void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree - { - std::vector bitlen(288, 8), bitlenD(32, 5);; - for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; - for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; - tree.makeFromLengths(bitlen, 15); - treeD.makeFromLengths(bitlenD, 15); - } - HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes - unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) - { //decode a single symbol from given list of bits with given code tree. return value is the symbol - bool decoded; unsigned long ct; - for(size_t treepos = 0;;) - { - if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode - error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened - if(decoded) return ct; - } - } - void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) - { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree - std::vector bitlen(288, 0), bitlenD(32, 0); - if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory - size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 - size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 - size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 - std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree - for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; - error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; - size_t i = 0, replength; - while(i < HLIT + HDIST) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; - if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code - else if(code == 16) //repeat previous - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 2); - unsigned long value; //set value to the previous code - if((i - 1) < HLIT) value = bitlen[i - 1]; - else value = bitlenD[i - HLIT - 1]; - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; - } - } - else if(code == 17) //repeat "0" 3-10 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 3); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else if(code == 18) //repeat "0" 11-138 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 11 + readBitsFromStream(bp, in, 7); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. - } - if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 - error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done - error = treeD.makeFromLengths(bitlenD, 15); if(error) return; - } - void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) - { - if(btype == 1) { generateFixedTrees(codetree, codetreeD); } - else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } - for(;;) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; - if(code == 256) return; //end code - else if(code <= 255) //literal symbol - { - if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room - out[pos++] = (unsigned char)(code); - } - else if(code >= 257 && code <= 285) //length code - { - size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - length += readBitsFromStream(bp, in, numextrabits); - unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; - if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) - unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - dist += readBitsFromStream(bp, in, numextrabitsD); - size_t start = pos, back = start - dist; //backwards - if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room - for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } - } - } - } - void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) - { - while((bp & 0x7) != 0) bp++; //go to first boundary of byte - size_t p = bp / 8; - if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory - unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; - if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN - if(pos + LEN >= out.size()) out.resize(pos + LEN); - if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer - for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data - bp = p * 8; - } - }; - int decompress(std::vector& out, const std::vector& in) //returns error value - { - Inflator inflator; - if(in.size() < 2) { return 53; } //error, size of zlib data too small - if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way - unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; - if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec - if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." - inflator.inflate(out, in, 2); - return inflator.error; //note: adler32 checksum was skipped and ignored - } - }; - struct PNG //nested functions for PNG decoding - { - struct Info - { - unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; - bool key_defined; //is a transparent color key given? - std::vector palette; - } info; - int error; - void decode(std::vector& out, const unsigned char* in, unsigned long size) - { - error = 0; - if(size == 0 || in == 0) { error = 48; return; } //the given data is empty - readPngHeader(&in[0], size); if(error) return; - size_t pos = 33; //first byte of the first chunk after the header - std::vector idat; //the data from idat chunks - bool IEND = false, known_type = true; - info.key_defined = false; - while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer - { - if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk - size_t chunkLength = read32bitInt(&in[pos]); pos += 4; - if(chunkLength > 2147483647) { error = 63; return; } - if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk - if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data - { - idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); - pos += (4 + chunkLength); - } - else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } - else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) - { - pos += 4; //go after the 4 letters - info.palette.resize(4 * (chunkLength / 3)); - if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big - for(size_t i = 0; i < info.palette.size(); i += 4) - { - for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB - info.palette[i + 3] = 255; //alpha - } - } - else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) - { - pos += 4; //go after the 4 letters - if(info.colorType == 3) - { - if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries - for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; - } - else if(info.colorType == 0) - { - if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image - info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else if(info.colorType == 2) - { - if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image - info.key_defined = 1; - info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else { error = 42; return; } //error: tRNS chunk not allowed for other color models - } - else //it's not an implemented chunk type, so ignore it: skip over the data - { - if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) - pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk - known_type = false; - } - pos += 4; //step over CRC (which is ignored) - } - unsigned long bpp = getBpp(info); - std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled - Zlib zlib; //decompress with the Zlib decompressor - error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error - size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; - out.resize(outlength); //time to fill the out buffer - unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization - if(info.interlaceMethod == 0) //no interlace, just filter - { - size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte - if(bpp >= 8) //byte per byte - for(unsigned long y = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - linestart += (1 + linelength); //go to start of next scanline - } - else //less than 8 bits per pixel, so fill it up bit per bit - { - std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 - for(size_t y = 0, obp = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); - linestart += (1 + linelength); //go to start of next scanline - } - } - } - else //interlaceMethod is 1 (Adam7) - { - size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; - size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; - size_t passstart[7] = {0}; - size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes - for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); - std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline - for(int i = 0; i < 7; i++) - adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); - } - if(info.colorType != 6 || info.bitDepth != 8) //conversion needed - { - std::vector data = out; - error = convert(out, &data[0], info, info.width, info.height); - } - } - void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info - { - if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header - if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature - if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! - info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); - info.bitDepth = in[24]; info.colorType = in[25]; - info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification - info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification - info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification - error = checkColorValidity(info.colorType, info.bitDepth); - } - void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) - { - switch(filterType) - { - case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; - case 1: - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; - break; - case 2: - if(precon) for(size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; - else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; - break; - case 3: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; - } - break; - case 4: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(0, precon[i], 0)); - for(size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)); - } - break; - default: error = 36; return; //error: unexisting filter type given - } - } - void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) - { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. - if(passw == 0) return; - size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); - for(unsigned long y = 0; y < passh; y++) - { - unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; - unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; - if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel - out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; - else for(size_t i = 0; i < passw; i++) - { - size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; - for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); - } - unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" - } - } - static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} - static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) - { - unsigned long result = 0; - for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); - return result; - } - void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } - unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } - int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code - { - if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } - else return 31; //unexisting color type - } - unsigned long getBpp(const Info& info) - { - if(info.colorType == 2) return (3 * info.bitDepth); - else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; - else return info.bitDepth; - } - int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) - { //converts from any color type to 32-bit. return value = LodePNG error code - size_t numpixels = w * h, bp = 0; - out.resize(numpixels * 4); - unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization - if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; - out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; - out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) - for(size_t i = 0; i < numpixels; i++) - { - if(4U * in[i] >= infoIn.palette.size()) return 46; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; - out_[4 * i + 3] = in[2 * i + 1]; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha - else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; - out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; - out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte - out_[4 * i + 3] = in[4 * i + 2]; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha - else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); - out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; - } - else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); - if(4 * value >= infoIn.palette.size()) return 47; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette - } - return 0; - } - long paethPredictor(long a, long b, long c) //Paeth predicter, used by PNG filter type 4 - { - long p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); - return (pa <= pb && pa <= pc) ? a : pb <= pc ? b : c; - } - }; - PNG decoder; decoder.decode(out_image_32bit, in_png, in_size); - image_width = decoder.info.width; image_height = decoder.info.height; - return decoder.error; -} - -#endif // LS_USE_PICOPNG +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2009 LiteStep Development 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 "../litestep/buildoptions.h" + +#if defined(LS_USE_PICOPNG) + +#include + +// These were moved outside of "decodePNG()" for VC7.1/8 compiler support +static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; +static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; +static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; +static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; +static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths + +//int decodePNG(std::vector& out_image_32bit, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) +int decodePNG(std::vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) +{ + // picoPNG version 20101224 + // Copyright (c) 2005-2010 Lode Vandevenne + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for + // programs that need only 1 .cpp file. Since it's a single function, it's very limited, + // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or + // with no color conversion at all. For anything more complex, another tiny library + // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. + // Apologies for the compact code style, it's to make this tiny. + + struct Zlib //nested functions for zlib decompression + { + static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} + static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) + { + unsigned long result = 0; + for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; + return result; + } + struct HuffmanTree + { + int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) + { //make tree given the lengths + unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; + std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); + for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length + for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; + for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes + tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet + for(unsigned long n = 0; n < numcodes; n++) //the codes + for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code + { + unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; + if(treepos > numcodes - 2) return 55; + if(tree2d[2 * treepos + bit] == 32767) //not yet filled in + { + if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit + else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes + } + else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value + } + return 0; + } + int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const + { //Decodes a symbol from the tree + unsigned long numcodes = (unsigned long)tree2d.size() / 2; + if(treepos >= numcodes) return 11; //error: you appeared outside the codetree + result = tree2d[2 * treepos + bit]; + decoded = (result < numcodes); + treepos = decoded ? 0 : result - numcodes; + return 0; + } + std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. + }; + struct Inflator + { + int error; + void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) + { + size_t bp = 0, pos = 0; //bit pointer and byte pointer + error = 0; + unsigned long BFINAL = 0; + while(!BFINAL && !error) + { + if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory + BFINAL = readBitFromStream(bp, &in[inpos]); + unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); + if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE + else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); + else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); + } + if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that + } + void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree + { + std::vector bitlen(288, 8), bitlenD(32, 5);; + for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; + for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; + tree.makeFromLengths(bitlen, 15); + treeD.makeFromLengths(bitlenD, 15); + } + HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes + unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) + { //decode a single symbol from given list of bits with given code tree. return value is the symbol + bool decoded; unsigned long ct; + for(size_t treepos = 0;;) + { + if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode + error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened + if(decoded) return ct; + } + } + void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) + { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree + std::vector bitlen(288, 0), bitlenD(32, 0); + if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory + size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 + size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 + size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 + std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree + for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; + error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; + size_t i = 0, replength; + while(i < HLIT + HDIST) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; + if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code + else if(code == 16) //repeat previous + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 2); + unsigned long value; //set value to the previous code + if((i - 1) < HLIT) value = bitlen[i - 1]; + else value = bitlenD[i - HLIT - 1]; + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; + } + } + else if(code == 17) //repeat "0" 3-10 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 3); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else if(code == 18) //repeat "0" 11-138 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 11 + readBitsFromStream(bp, in, 7); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. + } + if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 + error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done + error = treeD.makeFromLengths(bitlenD, 15); if(error) return; + } + void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) + { + if(btype == 1) { generateFixedTrees(codetree, codetreeD); } + else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } + for(;;) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; + if(code == 256) return; //end code + else if(code <= 255) //literal symbol + { + if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room + out[pos++] = (unsigned char)(code); + } + else if(code >= 257 && code <= 285) //length code + { + size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + length += readBitsFromStream(bp, in, numextrabits); + unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; + if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) + unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + dist += readBitsFromStream(bp, in, numextrabitsD); + size_t start = pos, back = start - dist; //backwards + if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room + for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } + } + } + } + void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) + { + while((bp & 0x7) != 0) bp++; //go to first boundary of byte + size_t p = bp / 8; + if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory + unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; + if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN + if(pos + LEN >= out.size()) out.resize(pos + LEN); + if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer + for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data + bp = p * 8; + } + }; + int decompress(std::vector& out, const std::vector& in) //returns error value + { + Inflator inflator; + if(in.size() < 2) { return 53; } //error, size of zlib data too small + if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way + unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; + if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec + if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." + inflator.inflate(out, in, 2); + return inflator.error; //note: adler32 checksum was skipped and ignored + } + }; + struct PNG //nested functions for PNG decoding + { + struct Info + { + unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; + bool key_defined; //is a transparent color key given? + std::vector palette; + } info; + int error; + void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) + { + error = 0; + if(size == 0 || in == 0) { error = 48; return; } //the given data is empty + readPngHeader(&in[0], size); if(error) return; + size_t pos = 33; //first byte of the first chunk after the header + std::vector idat; //the data from idat chunks + bool IEND = false, known_type = true; + info.key_defined = false; + while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer + { + if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk + size_t chunkLength = read32bitInt(&in[pos]); pos += 4; + if(chunkLength > 2147483647) { error = 63; return; } + if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk + if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data + { + idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); + pos += (4 + chunkLength); + } + else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } + else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) + { + pos += 4; //go after the 4 letters + info.palette.resize(4 * (chunkLength / 3)); + if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big + for(size_t i = 0; i < info.palette.size(); i += 4) + { + for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB + info.palette[i + 3] = 255; //alpha + } + } + else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) + { + pos += 4; //go after the 4 letters + if(info.colorType == 3) + { + if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries + for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; + } + else if(info.colorType == 0) + { + if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image + info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else if(info.colorType == 2) + { + if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image + info.key_defined = 1; + info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else { error = 42; return; } //error: tRNS chunk not allowed for other color models + } + else //it's not an implemented chunk type, so ignore it: skip over the data + { + if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) + pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk + known_type = false; + } + pos += 4; //step over CRC (which is ignored) + } + unsigned long bpp = getBpp(info); + std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled + Zlib zlib; //decompress with the Zlib decompressor + error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error + size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; + out.resize(outlength); //time to fill the out buffer + unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization + if(info.interlaceMethod == 0) //no interlace, just filter + { + size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte + if(bpp >= 8) //byte per byte + for(unsigned long y = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + linestart += (1 + linelength); //go to start of next scanline + } + else //less than 8 bits per pixel, so fill it up bit per bit + { + std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 + for(size_t y = 0, obp = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); + linestart += (1 + linelength); //go to start of next scanline + } + } + } + else //interlaceMethod is 1 (Adam7) + { + size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; + size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; + size_t passstart[7] = {0}; + size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes + for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); + std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline + for(int i = 0; i < 7; i++) + adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); + } + if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed + { + std::vector data = out; + error = convert(out, &data[0], info, info.width, info.height); + } + } + void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info + { + if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature + if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! + info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); + info.bitDepth = in[24]; info.colorType = in[25]; + info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification + info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification + info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification + error = checkColorValidity(info.colorType, info.bitDepth); + } + void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) + { + switch(filterType) + { + case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; + case 1: + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth]) & 0xFF; + break; + case 2: + if(precon) for(size_t i = 0; i < length; i++) recon[i] = (scanline[i] + precon[i]) & 0xFF; + else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; + break; + case 3: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + precon[i] / 2) & 0xFF; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2)) & 0xFF; + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth] / 2) & 0xFF; + } + break; + case 4: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + paethPredictor(0, precon[i], 0)) & 0xFF; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])) & 0xFF; + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)) & 0xFF; + } + break; + default: error = 36; return; //error: unexisting filter type given + } + } + void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) + { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. + if(passw == 0) return; + size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); + for(unsigned long y = 0; y < passh; y++) + { + unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; + unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; + if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel + out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; + else for(size_t i = 0; i < passw; i++) + { + size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; + for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); + } + unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" + } + } + static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} + static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) + { + unsigned long result = 0; + for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); + return result; + } + void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } + unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } + int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code + { + if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } + else return 31; //unexisting color type + } + unsigned long getBpp(const Info& info) + { + if(info.colorType == 2) return (3 * info.bitDepth); + else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; + else return info.bitDepth; + } + int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) + { //converts from any color type to 32-bit. return value = LodePNG error code + size_t numpixels = w * h, bp = 0; + out.resize(numpixels * 4); + unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization + if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; + out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; + out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) + for(size_t i = 0; i < numpixels; i++) + { + if(4U * in[i] >= infoIn.palette.size()) return 46; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; + out_[4 * i + 3] = in[2 * i + 1]; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha + else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; + out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; + out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte + out_[4 * i + 3] = in[4 * i + 2]; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha + else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); + out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; + } + else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); + if(4 * value >= infoIn.palette.size()) return 47; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette + } + return 0; + } + unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 + { + short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); + return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); + } + }; + PNG decoder; decoder.decode(out_image, in_png, in_size, true); + image_width = decoder.info.width; image_height = decoder.info.height; + return decoder.error; +} + +#endif // LS_USE_PICOPNG From d8db249a456defbffa3b1a73e30a8d0b6726e9c9 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 02:10:24 -0700 Subject: [PATCH 09/50] Updated the copyright year --- litestep/DDEService.cpp | 2 +- litestep/DDEService.h | 2 +- litestep/DDEStub.cpp | 2 +- litestep/DDEStub.h | 2 +- litestep/DDEWorker.cpp | 2 +- litestep/DDEWorker.h | 2 +- litestep/DataStore.cpp | 2 +- litestep/DataStore.h | 2 +- litestep/MessageManager.cpp | 2 +- litestep/MessageManager.h | 2 +- litestep/Module.cpp | 2 +- litestep/Module.h | 2 +- litestep/ModuleManager.cpp | 2 +- litestep/ModuleManager.h | 2 +- litestep/RecoveryMenu.cpp | 2 +- litestep/RecoveryMenu.h | 2 +- litestep/StartupRunner.cpp | 2 +- litestep/StartupRunner.h | 2 +- litestep/TrayAppBar.h | 2 +- litestep/TrayNotifyIcon.cpp | 2 +- litestep/TrayNotifyIcon.h | 2 +- litestep/TrayService.cpp | 2 +- litestep/TrayService.h | 2 +- litestep/WinMain.cpp | 2 +- litestep/buildoptions.h | 2 +- litestep/litestep.cpp | 2 +- litestep/litestep.h | 2 +- lsapi/BangCommand.cpp | 2 +- lsapi/BangCommand.h | 2 +- lsapi/BangManager.cpp | 2 +- lsapi/BangManager.h | 2 +- lsapi/MathEvaluate.cpp | 2 +- lsapi/MathEvaluate.h | 2 +- lsapi/MathException.h | 2 +- lsapi/MathParser.cpp | 2 +- lsapi/MathParser.h | 2 +- lsapi/MathScanner.cpp | 2 +- lsapi/MathScanner.h | 2 +- lsapi/MathToken.cpp | 2 +- lsapi/MathToken.h | 2 +- lsapi/MathValue.cpp | 2 +- lsapi/MathValue.h | 2 +- lsapi/SettingsDefines.h | 2 +- lsapi/SettingsFileParser.cpp | 2 +- lsapi/SettingsFileParser.h | 2 +- lsapi/SettingsIterator.cpp | 2 +- lsapi/SettingsIterator.h | 2 +- lsapi/SettingsManager.h | 2 +- lsapi/ThreadedBangCommand.h | 2 +- lsapi/aboutbox.cpp | 2 +- lsapi/bangs.cpp | 2 +- lsapi/graphics.cpp | 2 +- lsapi/lsapi.cpp | 2 +- lsapi/lsapi.h | 2 +- lsapi/lsapiInit.cpp | 2 +- lsapi/lsapiInit.h | 2 +- lsapi/lsapidefines.h | 2 +- lsapi/match.cpp | 2 +- lsapi/picopng.cpp | 2 +- lsapi/picopng.h | 2 +- lsapi/png_support.cpp | 2 +- lsapi/png_support.h | 2 +- lsapi/settings.cpp | 2 +- lsapi/settingsmanager.cpp | 2 +- lsapi/stubs.cpp | 2 +- utility/Base.h | 2 +- utility/ILiteStep.h | 2 +- utility/IManager.h | 2 +- utility/IService.h | 2 +- utility/common.h | 2 +- utility/core.hpp | 2 +- utility/criticalsection.h | 2 +- utility/debug.cpp | 2 +- utility/debug.hpp | 2 +- utility/fixup.h | 2 +- utility/macros.h | 2 +- utility/shellhlp.cpp | 2 +- utility/shellhlp.h | 2 +- utility/stringutility.h | 2 +- 79 files changed, 79 insertions(+), 79 deletions(-) diff --git a/litestep/DDEService.cpp b/litestep/DDEService.cpp index 87b8686..664f2dc 100644 --- a/litestep/DDEService.cpp +++ b/litestep/DDEService.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEService.h b/litestep/DDEService.h index 4f4801f..1b2d88c 100644 --- a/litestep/DDEService.h +++ b/litestep/DDEService.h @@ -3,7 +3,7 @@ // This is a part of the Litestep Shell source code. // // Copyright (C) 1998 (e) -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEStub.cpp b/litestep/DDEStub.cpp index 83b82f2..e0a23fb 100644 --- a/litestep/DDEStub.cpp +++ b/litestep/DDEStub.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEStub.h b/litestep/DDEStub.h index 1486b8c..6ab0836 100644 --- a/litestep/DDEStub.h +++ b/litestep/DDEStub.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEWorker.cpp b/litestep/DDEWorker.cpp index 8af7cf9..d609715 100644 --- a/litestep/DDEWorker.cpp +++ b/litestep/DDEWorker.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEWorker.h b/litestep/DDEWorker.h index eac4c98..bdf0df2 100644 --- a/litestep/DDEWorker.h +++ b/litestep/DDEWorker.h @@ -3,7 +3,7 @@ // This is a part of the Litestep Shell source code. // // Copyright (C) 1998 (e) -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DataStore.cpp b/litestep/DataStore.cpp index 13a7533..e7f5670 100644 --- a/litestep/DataStore.cpp +++ b/litestep/DataStore.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DataStore.h b/litestep/DataStore.h index e671c08..feaa747 100644 --- a/litestep/DataStore.h +++ b/litestep/DataStore.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/MessageManager.cpp b/litestep/MessageManager.cpp index 07ff690..03a541f 100644 --- a/litestep/MessageManager.cpp +++ b/litestep/MessageManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/MessageManager.h b/litestep/MessageManager.h index e36801f..9848331 100644 --- a/litestep/MessageManager.h +++ b/litestep/MessageManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/Module.cpp b/litestep/Module.cpp index cd432a8..0bd42a3 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/Module.h b/litestep/Module.h index ebc529b..15c0866 100644 --- a/litestep/Module.h +++ b/litestep/Module.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ModuleManager.cpp b/litestep/ModuleManager.cpp index 71a904d..a835699 100644 --- a/litestep/ModuleManager.cpp +++ b/litestep/ModuleManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ModuleManager.h b/litestep/ModuleManager.h index c927aed..1c2345c 100644 --- a/litestep/ModuleManager.h +++ b/litestep/ModuleManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/RecoveryMenu.cpp b/litestep/RecoveryMenu.cpp index 81c511b..c8a9667 100644 --- a/litestep/RecoveryMenu.cpp +++ b/litestep/RecoveryMenu.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/RecoveryMenu.h b/litestep/RecoveryMenu.h index 9effdbd..9b2262e 100644 --- a/litestep/RecoveryMenu.h +++ b/litestep/RecoveryMenu.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/StartupRunner.cpp b/litestep/StartupRunner.cpp index a73aa9e..b5d94c2 100644 --- a/litestep/StartupRunner.cpp +++ b/litestep/StartupRunner.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/StartupRunner.h b/litestep/StartupRunner.h index 1568e71..2f7275e 100644 --- a/litestep/StartupRunner.h +++ b/litestep/StartupRunner.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayAppBar.h b/litestep/TrayAppBar.h index 9285115..87917f5 100644 --- a/litestep/TrayAppBar.h +++ b/litestep/TrayAppBar.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index 660e812..a8a8e02 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index c9de723..933d3af 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 17a25b0..01e1621 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayService.h b/litestep/TrayService.h index 22c63fc..e4b9eea 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/WinMain.cpp b/litestep/WinMain.cpp index 0b30971..f922c41 100644 --- a/litestep/WinMain.cpp +++ b/litestep/WinMain.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/buildoptions.h b/litestep/buildoptions.h index 1635e51..780f632 100644 --- a/litestep/buildoptions.h +++ b/litestep/buildoptions.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index 7adccfe..a2a1ebc 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/litestep.h b/litestep/litestep.h index 19a71bb..878f278 100644 --- a/litestep/litestep.h +++ b/litestep/litestep.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangCommand.cpp b/lsapi/BangCommand.cpp index 157f30e..0a60ad0 100644 --- a/lsapi/BangCommand.cpp +++ b/lsapi/BangCommand.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangCommand.h b/lsapi/BangCommand.h index 9cfd0eb..2e088ad 100644 --- a/lsapi/BangCommand.h +++ b/lsapi/BangCommand.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangManager.cpp b/lsapi/BangManager.cpp index a2fc57d..1a736ae 100644 --- a/lsapi/BangManager.cpp +++ b/lsapi/BangManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangManager.h b/lsapi/BangManager.h index 4f634bd..c2241eb 100644 --- a/lsapi/BangManager.h +++ b/lsapi/BangManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathEvaluate.cpp b/lsapi/MathEvaluate.cpp index 52f00c1..711042c 100644 --- a/lsapi/MathEvaluate.cpp +++ b/lsapi/MathEvaluate.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathEvaluate.h b/lsapi/MathEvaluate.h index b2842ac..7f9ab0c 100644 --- a/lsapi/MathEvaluate.h +++ b/lsapi/MathEvaluate.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathException.h b/lsapi/MathException.h index b7ed25a..f27adb8 100644 --- a/lsapi/MathException.h +++ b/lsapi/MathException.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathParser.cpp b/lsapi/MathParser.cpp index 06a9e6c..6f57d23 100644 --- a/lsapi/MathParser.cpp +++ b/lsapi/MathParser.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathParser.h b/lsapi/MathParser.h index 065c7a2..b1c8823 100644 --- a/lsapi/MathParser.h +++ b/lsapi/MathParser.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathScanner.cpp b/lsapi/MathScanner.cpp index 7351545..081b979 100644 --- a/lsapi/MathScanner.cpp +++ b/lsapi/MathScanner.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathScanner.h b/lsapi/MathScanner.h index 0f24f9e..7f9d8d6 100644 --- a/lsapi/MathScanner.h +++ b/lsapi/MathScanner.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathToken.cpp b/lsapi/MathToken.cpp index 2a5ecd3..211a0ae 100644 --- a/lsapi/MathToken.cpp +++ b/lsapi/MathToken.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathToken.h b/lsapi/MathToken.h index f60b7d1..be23bd4 100644 --- a/lsapi/MathToken.h +++ b/lsapi/MathToken.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathValue.cpp b/lsapi/MathValue.cpp index 6d492b5..31c5d0c 100644 --- a/lsapi/MathValue.cpp +++ b/lsapi/MathValue.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathValue.h b/lsapi/MathValue.h index 493cb18..5f33fad 100644 --- a/lsapi/MathValue.h +++ b/lsapi/MathValue.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsDefines.h b/lsapi/SettingsDefines.h index 9e134b7..b5bde51 100644 --- a/lsapi/SettingsDefines.h +++ b/lsapi/SettingsDefines.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsFileParser.cpp b/lsapi/SettingsFileParser.cpp index b0c4a7b..fb4f54c 100644 --- a/lsapi/SettingsFileParser.cpp +++ b/lsapi/SettingsFileParser.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsFileParser.h b/lsapi/SettingsFileParser.h index b1e933b..8b35696 100644 --- a/lsapi/SettingsFileParser.h +++ b/lsapi/SettingsFileParser.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsIterator.cpp b/lsapi/SettingsIterator.cpp index 41de07c..af7f20c 100644 --- a/lsapi/SettingsIterator.cpp +++ b/lsapi/SettingsIterator.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsIterator.h b/lsapi/SettingsIterator.h index 0265b8d..0fb2e5d 100644 --- a/lsapi/SettingsIterator.h +++ b/lsapi/SettingsIterator.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsManager.h b/lsapi/SettingsManager.h index ad31e29..50a04c0 100644 --- a/lsapi/SettingsManager.h +++ b/lsapi/SettingsManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/ThreadedBangCommand.h b/lsapi/ThreadedBangCommand.h index 3fe8f76..f2a8cae 100644 --- a/lsapi/ThreadedBangCommand.h +++ b/lsapi/ThreadedBangCommand.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index be8bf61..90d0764 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index cd566c5..44be2c3 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/graphics.cpp b/lsapi/graphics.cpp index 752bb42..5f82c2a 100644 --- a/lsapi/graphics.cpp +++ b/lsapi/graphics.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index 5041141..f8c9d36 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapi.h b/lsapi/lsapi.h index 866fde2..d268d80 100644 --- a/lsapi/lsapi.h +++ b/lsapi/lsapi.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index 6229067..ea2714b 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapiInit.h b/lsapi/lsapiInit.h index af670f3..6d6fde3 100644 --- a/lsapi/lsapiInit.h +++ b/lsapi/lsapiInit.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index 4cd584d..ab41c8d 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/match.cpp b/lsapi/match.cpp index 85127f0..7e18d5b 100644 --- a/lsapi/match.cpp +++ b/lsapi/match.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/picopng.cpp b/lsapi/picopng.cpp index dddb0c2..f233d21 100644 --- a/lsapi/picopng.cpp +++ b/lsapi/picopng.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2009 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/picopng.h b/lsapi/picopng.h index 429c561..c6f4000 100644 --- a/lsapi/picopng.h +++ b/lsapi/picopng.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/png_support.cpp b/lsapi/png_support.cpp index 90110d1..09a59b8 100644 --- a/lsapi/png_support.cpp +++ b/lsapi/png_support.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/png_support.h b/lsapi/png_support.h index 534001e..d2e0ae2 100644 --- a/lsapi/png_support.h +++ b/lsapi/png_support.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/settings.cpp b/lsapi/settings.cpp index ae60851..a3ddbab 100644 --- a/lsapi/settings.cpp +++ b/lsapi/settings.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/settingsmanager.cpp b/lsapi/settingsmanager.cpp index 6966eb2..a72f2a9 100644 --- a/lsapi/settingsmanager.cpp +++ b/lsapi/settingsmanager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/stubs.cpp b/lsapi/stubs.cpp index 871ddca..8d5e851 100644 --- a/lsapi/stubs.cpp +++ b/lsapi/stubs.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/Base.h b/utility/Base.h index 8117336..4b8a252 100644 --- a/utility/Base.h +++ b/utility/Base.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/ILiteStep.h b/utility/ILiteStep.h index 287bbd0..24275fb 100644 --- a/utility/ILiteStep.h +++ b/utility/ILiteStep.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/IManager.h b/utility/IManager.h index f1b8ad7..4b67028 100644 --- a/utility/IManager.h +++ b/utility/IManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/IService.h b/utility/IService.h index 362d741..0918858 100644 --- a/utility/IService.h +++ b/utility/IService.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/common.h b/utility/common.h index a14ad2d..47f3ecb 100644 --- a/utility/common.h +++ b/utility/common.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/core.hpp b/utility/core.hpp index 94eb151..7f48a09 100644 --- a/utility/core.hpp +++ b/utility/core.hpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/criticalsection.h b/utility/criticalsection.h index ad1dfc6..7af0c88 100644 --- a/utility/criticalsection.h +++ b/utility/criticalsection.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/debug.cpp b/utility/debug.cpp index e1fb5cb..c947f3e 100644 --- a/utility/debug.cpp +++ b/utility/debug.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/debug.hpp b/utility/debug.hpp index 31ccb1c..a8d73aa 100644 --- a/utility/debug.hpp +++ b/utility/debug.hpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/fixup.h b/utility/fixup.h index 8284c36..77b82f3 100644 --- a/utility/fixup.h +++ b/utility/fixup.h @@ -2,7 +2,7 @@ // // This is a part of the LiteStep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/macros.h b/utility/macros.h index 2e8d815..0605b60 100644 --- a/utility/macros.h +++ b/utility/macros.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index c964ae7..e4ce05c 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/shellhlp.h b/utility/shellhlp.h index 85832e7..a2d1622 100644 --- a/utility/shellhlp.h +++ b/utility/shellhlp.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/stringutility.h b/utility/stringutility.h index 6b8bbde..8af822d 100644 --- a/utility/stringutility.h +++ b/utility/stringutility.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2011 LiteStep Development Team +// Copyright (C) 1997-2012 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License From ae240eb0501f2932688cc1f11468c409787c29ae Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 13 Jul 2012 08:16:43 -0700 Subject: [PATCH 10/50] Converted tabs to spaces --- lsapi/aboutbox.cpp | 4 ++-- utility/shellhlp.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 90d0764..863df2e 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -708,7 +708,7 @@ static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) case WINVER_WINXP: pszTemp = _T("Windows XP"); break; case WINVER_VISTA: pszTemp = _T("Windows Vista"); break; case WINVER_WIN7: pszTemp = _T("Windows 7"); break; - case WINVER_WIN8: pszTemp = _T("Windows 8"); break; + case WINVER_WIN8: pszTemp = _T("Windows 8"); break; case WINVER_WIN2003: if (GetSystemMetrics(SM_SERVERR2)) { @@ -721,7 +721,7 @@ static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) break; case WINVER_WHS: pszTemp = _T("Windows Home Server"); break; case WINVER_WIN2008: pszTemp = _T("Windows Server 2008"); break; - case WINVER_WIN2012: pszTemp = _T("Windows Server 2012"); break; + case WINVER_WIN2012: pszTemp = _T("Windows Server 2012"); break; default: pszTemp = _T(""); break; } diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index e4ce05c..65b7afb 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -632,8 +632,8 @@ UINT GetWindowsVersion() { 6, 0, WVM_WORKSTATION, WINVER_VISTA }, { 6, 0, WVM_SERVER, WINVER_WIN2008 }, { 6, 1, WVM_ANY, WINVER_WIN7 }, - { 6, 2, WVM_SERVER, WINVER_WIN2012 }, - { 6, 2, WVM_ANY, WINVER_WIN8 } + { 6, 2, WVM_SERVER, WINVER_WIN2012 }, + { 6, 2, WVM_ANY, WINVER_WIN8 } }; for (size_t idx = 0; idx < COUNTOF(versions); ++idx) From d2f08705bfc445042f2a28b08972a88aaec14e6d Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 5 Aug 2012 15:56:49 -0700 Subject: [PATCH 11/50] Added win8/2012 definitions --- lsapi/lsapiInit.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index ea2714b..15a244a 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -241,10 +241,12 @@ void LSAPIInit::setLitestepVars() { WINVER_WINXP, _T("WinXP") }, { WINVER_VISTA, _T("WinVista") }, { WINVER_WIN7, _T("Win7") }, + { WINVER_WIN8, _T("Win8") }, { WINVER_WIN2003, _T("Win2003") }, { WINVER_WHS, _T("Win2003") }, // WHS is Win2003 in disguise - { WINVER_WIN2008, _T("Win2008") } + { WINVER_WIN2008, _T("Win2008") }, + { WINVER_WIN2012, _T("Win2012") } }; UINT uVersion = GetWindowsVersion(); From e86d33865997560d64053c46354e787c1e5fdb34 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 5 Aug 2012 15:57:11 -0700 Subject: [PATCH 12/50] 64bit build targets --- litestep/litestep_vc11.vcxproj | 106 ++++++++++++++++++++++++++++++++- litestep_vc11.sln | 26 ++++++-- lsapi/lsapi_vc11.vcxproj | 106 ++++++++++++++++++++++++++++++++- utility/utility_vc11.vcxproj | 82 ++++++++++++++++++++++++- 4 files changed, 307 insertions(+), 13 deletions(-) diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index ebcdce6..6e8306b 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + litestep @@ -24,11 +32,22 @@ true v110 + + Application + MultiByte + true + v110 + Application MultiByte v110 + + Application + MultiByte + v110 + @@ -36,25 +55,38 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11\ + C:\LiteStep\debug\ Debug_VC11\ true + true ../Release_VC11\ Release_VC11\ false + false + + + C:\LiteStep64\debug\ Disabled WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true + false EnableFastChecks true MultiThreadedDebugDLL @@ -66,6 +98,7 @@ false EditAndContinue Default + true ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) @@ -78,6 +111,34 @@ MachineX86 + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + + MaxSpeed @@ -91,7 +152,7 @@ false MultiThreadedDLL true - NotSet + StreamingSIMDExtensions2 false true true @@ -118,6 +179,45 @@ MachineX86 + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + NotSet + false + true + true + + + Level4 + false + + + Default + true + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + + diff --git a/litestep_vc11.sln b/litestep_vc11.sln index 8e73a21..7f5091f 100644 --- a/litestep_vc11.sln +++ b/litestep_vc11.sln @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc11.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc11.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" @@ -9,21 +9,35 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 58fcd35..29dffac 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + lsapi @@ -24,11 +32,22 @@ true v110 + + DynamicLibrary + MultiByte + true + v110 + DynamicLibrary MultiByte v110 + + DynamicLibrary + MultiByte + v110 + @@ -36,25 +55,38 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11\ + C:\LiteStep\debug\ Debug_VC11\ true + true ../Release_VC11\ Release_VC11\ false + false + + + C:\LiteStep64\debug\ Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true + false EnableFastChecks true MultiThreadedDebugDLL @@ -66,6 +98,7 @@ false EditAndContinue Default + true advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) @@ -79,6 +112,35 @@ MachineX86 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + + MaxSpeed @@ -90,7 +152,7 @@ true MultiThreadedDLL true - NotSet + StreamingSIMDExtensions2 true true @@ -116,6 +178,42 @@ MachineX86 + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + + @@ -126,7 +224,9 @@ $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index 31ec861..1c64ae4 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + utility @@ -24,11 +32,22 @@ true v110 + + StaticLibrary + MultiByte + true + v110 + StaticLibrary MultiByte v110 + + StaticLibrary + MultiByte + v110 + @@ -36,10 +55,18 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 @@ -53,7 +80,7 @@ /wd4201 %(AdditionalOptions) Disabled WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true + false EnableFastChecks true MultiThreadedDebugDLL @@ -65,12 +92,65 @@ false EditAndContinue Default + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true $(OutDir)utility.lib + + /wd4201 %(AdditionalOptions) + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions2 + true + true + + + Level4 + false + + + Default + true + true + + + $(OutDir)utility.lib + + + /wd4201 %(AdditionalOptions) MaxSpeed From 5f3af64c5e6f9d65dde27bc799ab7f3a0d2d6129 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 5 Aug 2012 16:10:23 -0700 Subject: [PATCH 13/50] Fixed tray icons for 64bit builds. --- litestep/TrayNotifyIcon.cpp | 10 +++++----- litestep/TrayNotifyIcon.h | 39 +++++++++++++++++++++---------------- litestep/TrayService.h | 2 +- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index a8a8e02..ff78620 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -58,7 +58,7 @@ NotifyIcon::IcVtr NotifyIcon::s_icVtr; // NotifyIcon::NotifyIcon(const NID_XX& nidSource) - :m_hWnd(nidSource.hWnd) + :m_hWnd((HWND)nidSource.hWnd) ,m_uID(nidSource.uID) ,m_uFlags(0) ,m_uCallbackMessage(0) @@ -124,7 +124,7 @@ void NotifyIcon::copy_message(PCNID_XX pnidSource) void NotifyIcon::copy_icon(PCNID_XX pnidSource) { // ignore if we are being told to use the same icon as before. - if (NIF_ICON & pnidSource->uFlags && m_hOriginalIcon != pnidSource->hIcon) + if (NIF_ICON & pnidSource->uFlags && m_hOriginalIcon != (HICON)pnidSource->hIcon) { HICON hNewIcon = NULL; @@ -135,7 +135,7 @@ void NotifyIcon::copy_icon(PCNID_XX pnidSource) { const NotifyIcon* p = *it; - if (p->m_hOriginalIcon == pnidSource->hIcon) + if (p->m_hOriginalIcon == (HICON)pnidSource->hIcon) { m_hSharedWnd = (HANDLE)p->m_hWnd; m_uSharedID = p->m_uID; @@ -146,7 +146,7 @@ void NotifyIcon::copy_icon(PCNID_XX pnidSource) } else { - hNewIcon = CopyIcon(pnidSource->hIcon); + hNewIcon = CopyIcon((HICON)pnidSource->hIcon); } // Update if we have a new icon, or we were told @@ -159,7 +159,7 @@ void NotifyIcon::copy_icon(PCNID_XX pnidSource) } m_hIcon = hNewIcon; - m_hOriginalIcon = pnidSource->hIcon; + m_hOriginalIcon = (HICON)pnidSource->hIcon; } if (!m_hIcon) diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index 933d3af..47994ce 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -69,15 +69,20 @@ typedef const LSNOTIFYICONDATA * PCLSNOTIFYICONDATA; // NOTIFYICONDATA variants // +// For 64bit builds. +// Handles are 64bits on 64bit builds, while the structure we receive still contain 32bits. +typedef DWORD HWND32; +typedef DWORD HICON32; + // Win9x typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; CHAR szTip[64]; } NID_4A; @@ -85,11 +90,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; WCHAR szTip[64]; } NID_4W; @@ -97,11 +102,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; CHAR szTip[128]; DWORD dwState; DWORD dwStateMask; @@ -119,11 +124,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; WCHAR szTip[128]; DWORD dwState; DWORD dwStateMask; @@ -141,11 +146,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; CHAR szTip[128]; DWORD dwState; DWORD dwStateMask; @@ -164,11 +169,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; WCHAR szTip[128]; DWORD dwState; DWORD dwStateMask; @@ -187,11 +192,11 @@ typedef struct typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; WCHAR szTip[128]; DWORD dwState; DWORD dwStateMask; @@ -204,18 +209,18 @@ typedef struct WCHAR szInfoTitle[64]; DWORD dwInfoFlags; GUID guidItem; - HICON hBalloonIcon; + HICON32 hBalloonIcon; } NID_7W; // sub structure common to all others typedef struct { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; - HICON hIcon; + HICON32 hIcon; } NID_XX, *PNID_XX; typedef const NID_XX * PCNID_XX; diff --git a/litestep/TrayService.h b/litestep/TrayService.h index e4b9eea..8ed6503 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -201,7 +201,7 @@ class TrayService : public IService inline IconVector::iterator findIcon(const NID_XX& nid) { - return findIcon(nid.hWnd, nid.uID); + return findIcon((HWND)nid.hWnd, nid.uID); } // From b63b555261d038ab3094f4e7f0b52955e0de75cb Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 5 Aug 2012 16:32:31 -0700 Subject: [PATCH 14/50] Tabs -> Spaces for Win2012/Win8 variables. Fixed VC11 project paths. --- litestep/litestep_vc11.vcxproj | 15 ++++++++++----- lsapi/lsapiInit.cpp | 4 ++-- lsapi/lsapi_vc11.vcxproj | 15 ++++++++++----- utility/utility_vc11.vcxproj | 16 ++++++++++++---- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 6e8306b..6889077 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -70,17 +70,22 @@ <_ProjectFileVersion>10.0.30319.1 - C:\LiteStep\debug\ - Debug_VC11\ + ../Debug_VC11_32\ + Debug_VC11_32\ true true - ../Release_VC11\ - Release_VC11\ + ../Release_VC11_32\ + Release_VC11_32\ false false - C:\LiteStep64\debug\ + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index 15a244a..54cc6be 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -241,12 +241,12 @@ void LSAPIInit::setLitestepVars() { WINVER_WINXP, _T("WinXP") }, { WINVER_VISTA, _T("WinVista") }, { WINVER_WIN7, _T("Win7") }, - { WINVER_WIN8, _T("Win8") }, + { WINVER_WIN8, _T("Win8") }, { WINVER_WIN2003, _T("Win2003") }, { WINVER_WHS, _T("Win2003") }, // WHS is Win2003 in disguise { WINVER_WIN2008, _T("Win2008") }, - { WINVER_WIN2012, _T("Win2012") } + { WINVER_WIN2012, _T("Win2012") } }; UINT uVersion = GetWindowsVersion(); diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 29dffac..7760c3d 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -70,17 +70,22 @@ <_ProjectFileVersion>10.0.30319.1 - C:\LiteStep\debug\ - Debug_VC11\ + ../Debug_VC11_32\ + Debug_VC11_32\ true true - ../Release_VC11\ - Release_VC11\ + ../Release_VC11_32\ + Release_VC11_32\ false false - C:\LiteStep64\debug\ + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index 1c64ae4..911e2e1 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -70,10 +70,18 @@ <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11\ - Debug_VC11\ - ../Release_VC11\ - Release_VC11\ + ../Debug_VC11_32\ + Debug_VC11_32\ + ../Release_VC11_32\ + Release_VC11_32\ + + + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ From 3e2845242cc65c81ceb72ffb052a413b14e9c179 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 04:51:09 -0700 Subject: [PATCH 15/50] Added missing HSHELL_ messages to lsapidefines.h --- lsapi/lsapidefines.h | 3 +++ utility/common.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index ab41c8d..3cb1509 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -144,6 +144,9 @@ #define LM_LANGUAGE (LM_SHELLHOOK + HSHELL_LANGUAGE) #define LM_ACCESSIBILITYSTATE (LM_SHELLHOOK + HSHELL_ACCESSIBILITYSTATE) #define LM_APPCOMMAND (LM_SHELLHOOK + HSHELL_APPCOMMAND) +#define LM_WINDOWREPLACED (LM_SHELLHOOK + HSHELL_WINDOWREPLACED) +#define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) +#define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) //----------------------------------------------------------------------------- diff --git a/utility/common.h b/utility/common.h index 47f3ecb..62941f1 100644 --- a/utility/common.h +++ b/utility/common.h @@ -29,7 +29,7 @@ #else -# define _WIN32_WINNT 0x0600 +# define _WIN32_WINNT 0x0602 # define _WIN32_IE 0x0603 # define WIN32_LEAN_AND_MEAN From c326835b5671ee1f64da1f7b9fd514c4c60a9f19 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 16:59:25 -0700 Subject: [PATCH 16/50] Fixed appbars on 64bit builds. Partial implementation of TrayInfoEvent. --- litestep/TrayAppBar.h | 14 +- litestep/TrayNotifyIcon.cpp | 24 + litestep/TrayNotifyIcon.h | 7 + litestep/TrayService.cpp | 4601 ++++++++++++++++++----------------- litestep/TrayService.h | 457 ++-- lsapi/lsapidefines.h | 553 ++--- 6 files changed, 2867 insertions(+), 2789 deletions(-) diff --git a/litestep/TrayAppBar.h b/litestep/TrayAppBar.h index 87917f5..6376229 100644 --- a/litestep/TrayAppBar.h +++ b/litestep/TrayAppBar.h @@ -30,10 +30,14 @@ #define ABS_OVERLAPAUTOHIDE 0x00020000 #define ABS_CLEANRECT 0x00040000 +// Maintains 32bit handles on 64bit builds +typedef DWORD HANDLE32; +typedef DWORD HWND32; + typedef struct _APPBARDATAV1 { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uCallbackMessage; UINT uEdge; RECT rc; @@ -43,7 +47,7 @@ typedef struct _APPBARDATAV1 typedef struct _APPBARDATAV2 { DWORD cbSize; - HWND hWnd; + HWND32 hWnd; UINT uCallbackMessage; UINT uEdge; RECT rc; @@ -57,7 +61,7 @@ typedef struct _APPBARMSGDATAV1 APPBARDATAV1 abd; /**/ DWORD dwMessage; - HANDLE hSharedMemory; + HANDLE32 hSharedMemory; DWORD dwSourceProcessId; /**/ } APPBARMSGDATAV1, *PAPPBARMSGDATAV1; @@ -69,7 +73,7 @@ typedef struct _APPBARMSGDATAV2 APPBARDATAV2 abd; /**/ DWORD dwMessage; - HANDLE hSharedMemory; + HANDLE32 hSharedMemory; DWORD dwSourceProcessId; /**/ DWORD dw64BitAlign; @@ -85,7 +89,7 @@ typedef struct _APPBARMSGDATAV3 DWORD dwMessage; DWORD dwPadding1; /**/ - HANDLE hSharedMemory; + HANDLE32 hSharedMemory; DWORD dwPadding2; /**/ DWORD dwSourceProcessId; diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index ff78620..5460469 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -98,6 +98,9 @@ void NotifyIcon::Update(const NID_XX& nidSource) // Copy persistent values only // + // GUID + copy_guid(&nidSource); + // state values copy_state(&nidSource); @@ -121,6 +124,27 @@ void NotifyIcon::copy_message(PCNID_XX pnidSource) } } +void NotifyIcon::copy_guid(PCNID_XX pnidSource) +{ + if ((pnidSource->uFlags & NIF_GUID) == NIF_GUID) + { + switch (pnidSource->cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + m_guidItem = ((NID_6W*)pnidSource)->guidItem; + break; + + case NID_6A_SIZE: + m_guidItem = ((NID_6A*)pnidSource)->guidItem; + break; + + default: + break; + } + } +} + void NotifyIcon::copy_icon(PCNID_XX pnidSource) { // ignore if we are being told to use the same icon as before. diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index 47994ce..1516882 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -288,6 +288,11 @@ class NotifyIcon return m_uID; } + inline GUID GetGUID() const + { + return m_guidItem; + } + inline void CopyLSNID(LSNOTIFYICONDATA * plsnid) const { CopyLSNID(plsnid, (UINT)-1); @@ -296,6 +301,7 @@ class NotifyIcon void CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const; private: + void copy_guid(PCNID_XX pnidSource); void copy_message(PCNID_XX pnidSource); void copy_icon(PCNID_XX pnidSource); void copy_tip(PCNID_XX pnidSource); @@ -306,6 +312,7 @@ class NotifyIcon // Preserved Notify Icon Data members const HWND m_hWnd; /* persistent & non volatile */ const UINT m_uID; /* persistent & non volatile */ + GUID m_guidItem; /* ? & ? */ UINT m_uFlags; /* persistent & volatile */ UINT m_uCallbackMessage; /* persistent & volatile */ diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 01e1621..5062db7 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -1,2285 +1,2316 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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 "TrayService.h" -#include "../utility/core.hpp" -#include -#include -#include - - -#if !defined(REGSTR_PATH_SHELLSERVICEOBJECTDELAYED) -#define REGSTR_PATH_SHELLSERVICEOBJECTDELAYED \ - _T("Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad") -#endif - -static const TCHAR szTrayClass[] = _T("Shell_TrayWnd"); -static const TCHAR szTrayTitle[] = _T("LiteStep Tray Manager"); -static const TCHAR szNotifyClass[] = _T("TrayNotifyWnd"); - - -// -// CLSID_SysTrayObject - {35CEC8A3-2BE6-11D2-8773-92E220524153} -// -// This appears to be the SSO responsible for starting up all other "approved" -// SSOs on Vista. Name derived from "stobject.dll". -// -const GUID CLSID_SysTrayObject = \ -{0x35CEC8A3, 0x2BE6, 0x11D2, {0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53}}; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// TrayService -// -TrayService::TrayService() : -m_uWorkAreaDirty(0), m_hNotifyWnd(NULL), m_hTrayWnd(NULL), -m_hLiteStep(NULL), m_hInstance(NULL) -{ - // do nothing -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ~TrayService -// -TrayService::~TrayService() -{ - // do nothing -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// Start() -// -HRESULT TrayService::Start() -{ - ASSERT(NULL == m_hTrayWnd); - HRESULT hr = E_FAIL; - - m_hLiteStep = GetLitestepWnd(); - m_hInstance = GetModuleHandle(NULL); - - if (m_hLiteStep && m_hInstance) - { - // clear work area of primary monitor - SetRect(&m_rWorkAreaDef, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - setWorkArea(&m_rWorkAreaDef); - CopyRect(&m_rWorkAreaCur, &m_rWorkAreaDef); - - hr = createWindows(); - - if (SUCCEEDED(hr)) - { - SetWindowLongPtr(m_hTrayWnd, GWLP_USERDATA, magicDWord); - SetWindowLongPtr(m_hTrayWnd, 0, (LONG_PTR)this); - - // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1427677&SiteID=1 - // - // Re: TaskbarCreated message (not working in Vista) - // - // > The code is still in there to broadcast the message. - // > SendNotifyMessage(HWND_BROADCAST, - // > RegisterWindowMessage(TEXT("TaskbarCreated")), 0, 0); - // - // >> It looks as though applications running as admin cannot - // >> receive the message. Presumably, this is because Explorer, - // >> which publishes the message, is not running as admin - // - // >>> The message is blocked by User Interface Privilege - // >>> Isolation, Administrative applications that need to see it - // >>> can allow it through by calling ChangeWindowMessageFilter - // >>> after making sure the necessary security precautions are in - // >>> place. - - // tell apps to reregister their icons - SendNotifyMessage(HWND_BROADCAST, - RegisterWindowMessage(_T("TaskbarCreated")), 0, 0); - - if (IsVistaOrAbove()) - { - // On Vista and up there's a single SSO responsible for loading - // all the supported objects (volume icon, network icon, etc.) - loadShellServiceObject(CLSID_SysTrayObject); - } - else if (IsOS(OS_WIN2000ORGREATER)) - { - // On previous versions the object list is in the registry - loadShellServiceObjects(); - } - } - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// Stop() -// -HRESULT TrayService::Stop() -{ - HRESULT hr = S_OK; - - unloadShellServiceObjects(); - destroyWindows(); - - while (!m_siVector.empty()) - { - delete m_siVector.back(); - m_siVector.pop_back(); - } - - while (!m_abVector.empty()) - { - delete m_abVector.back(); - m_abVector.pop_back(); - } - - // clear the work area of primary monitor - SetRect(&m_rWorkAreaDef, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - setWorkArea(&m_rWorkAreaDef); - - m_hLiteStep = NULL; - m_hInstance = NULL; - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// createWindows -// -HRESULT TrayService::createWindows() -{ - HRESULT hr = E_FAIL; - - // - // Register tray window class - // - WNDCLASSEX wc = { 0 }; - wc.cbSize = sizeof(WNDCLASSEX); - wc.cbWndExtra = sizeof(TrayService*); - wc.lpfnWndProc = TrayService::WindowTrayProc; - wc.hInstance = m_hInstance; - wc.lpszClassName = szTrayClass; - wc.style = CS_DBLCLKS; - - if (!RegisterClassEx(&wc)) - { - hr = HrGetLastError(); - } - else - { - // - // Window which receives the tray messages - // - m_hTrayWnd = CreateWindowEx( - WS_EX_TOPMOST | WS_EX_TOOLWINDOW, - szTrayClass, szTrayTitle, - WS_POPUP, - 0, 0, 0, 0, - NULL, NULL, - m_hInstance, - NULL); - - if (NULL == m_hTrayWnd) - { - hr = HrGetLastError(); - UnregisterClass(szTrayClass, m_hInstance); - } - else - { - // Our main window is enough to start up, we can do without the - // TrayNotifyWnd if necessary. - hr = S_OK; - - // - // Register "TrayNotifyWnd" class and create window - // - ZeroMemory(&wc, sizeof(wc)); - wc.cbSize = sizeof(WNDCLASSEX); - wc.lpfnWndProc = TrayService::WindowNotifyProc; - wc.hInstance = m_hInstance; - wc.lpszClassName = szNotifyClass; - wc.style = CS_DBLCLKS; - - if (RegisterClassEx(&wc)) - { - m_hNotifyWnd = CreateWindowEx( - 0, - szNotifyClass, NULL, - WS_CHILD, - 0, 0, 0, 0, - m_hTrayWnd, NULL, - m_hInstance, - NULL); - - if (!m_hNotifyWnd) - { - UnregisterClass(szNotifyClass, m_hInstance); - } - } - } - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// destroyWindows -// -void TrayService::destroyWindows() -{ - if (m_hNotifyWnd) - { - DestroyWindow(m_hNotifyWnd); - m_hNotifyWnd = NULL; - - UnregisterClass(szNotifyClass, m_hInstance); - } - - if (m_hTrayWnd) - { - DestroyWindow(m_hTrayWnd); - m_hTrayWnd = NULL; - - UnregisterClass(szTrayClass, m_hInstance); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// loadShellServiceObject -// -HRESULT TrayService::loadShellServiceObject(REFCLSID rclsid) -{ -#if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; - CLSIDToString(rclsid, szBuffer, COUNTOF(szBuffer)); - - TRACE("loadShellServiceObject(\"%s\")", szBuffer); -#endif - - // The SSO might have a custom manifest. - // Activate it before loading the object. - ULONG_PTR ulCookie; - HANDLE hContext = LSActivateActCtxForClsid(rclsid, &ulCookie); - - IOleCommandTarget* pCmdTarget = NULL; - - HRESULT hr = CoCreateInstance(rclsid, NULL, - CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, - IID_IOleCommandTarget, (void **)&pCmdTarget); - - if (SUCCEEDED(hr)) - { - hr = pCmdTarget->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, - OLECMDEXECOPT_DODEFAULT, NULL, NULL); - - m_ssoVector.push_back(pCmdTarget); - } - - if (hContext != INVALID_HANDLE_VALUE) - { - LSDeactivateActCtx(hContext, &ulCookie); - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// loadShellServiceObjects -// -// Start the COM based shell services listed in the registry. -// -void TrayService::loadShellServiceObjects() -{ - HKEY hkeyServices; - int nCounter = 0; - - LONG lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, - 0, KEY_READ, &hkeyServices); - - while (lErrorCode == ERROR_SUCCESS) - { - TCHAR szValueName[32] = { 0 }; - char szData[40] = { 0 }; - DWORD cchValueName = sizeof(szValueName) / sizeof(szValueName[0]); - DWORD cbData = sizeof(szData); - DWORD dwDataType; - - lErrorCode = RegEnumValue(hkeyServices, nCounter, szValueName, - &cchValueName, NULL, &dwDataType, (LPBYTE)szData, &cbData); - - if (lErrorCode == ERROR_SUCCESS) - { - WCHAR wszCLSID[40] = { 0 }; - CLSID clsid = CLSID_NULL; - - MultiByteToWideChar(CP_ACP, 0, szData, cbData, wszCLSID, 40); - CLSIDFromString(wszCLSID, &clsid); - - loadShellServiceObject(clsid); - } - - ++nCounter; - } - - RegCloseKey(hkeyServices); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// unloadShellServiceObjects -// -// Shut down the COM based shell services. -// -// -void TrayService::unloadShellServiceObjects() -{ - while (!m_ssoVector.empty()) - { - m_ssoVector.back()->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, - OLECMDEXECOPT_DODEFAULT, NULL, NULL); - - m_ssoVector.back()->Release(); - m_ssoVector.pop_back(); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// WindowTrayProc -// -// Redirects all messages to the appropriate handler -// -LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) -{ - static TrayService* pTrayService = NULL; - - if (!pTrayService) - { - pTrayService = (TrayService*)GetWindowLongPtr(hWnd, 0); - } - - if (pTrayService) - { - LRESULT lResult = 0; - - switch (uMsg) - { - case WM_COPYDATA: - { - // - // Undocumented: This is how we can make our own system tray - // and handle app bar windows. Once a window in the system has - // the "Shell_TrayWnd" class name, it receives this message! - // - COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam; - - switch (pcds->dwData) - { - case SH_APPBAR_DATA: - { - // - // Application Bar Message - // - lResult = pTrayService->HandleAppBarCopydata( - pcds->cbData, pcds->lpData); - } - break; - - case SH_TRAY_DATA: - { - // - // System Tray Notification - // - PSHELLTRAYDATA pstd = (PSHELLTRAYDATA)pcds->lpData; - - lResult = (LRESULT)pTrayService->HandleNotification(pstd); - } - break; - - case SH_LOADPROC_DATA: - { - // - // LoadInProc messages - // - if (pcds->cbData == sizeof(CLSID)) - { - // Classic SHLoadInProc message - lResult = pTrayService->HandleLoadInProc( - (REFCLSID)pcds->lpData, 1); - } - else if (pcds->cbData == sizeof(SHELLINPROCDATA)) - { - PSHELLINPROCDATA pipd = (PSHELLINPROCDATA)pcds->lpData; - - lResult = pTrayService->HandleLoadInProc( - pipd->clsid, pipd->dwMessage); - } - else - { - TRACE("Unknown SHLoadInProc size: %u", pcds->cbData); - lResult = E_NOTIMPL; - } - } - break; - - default: - { - TRACE("Unsupported tray message: %u", pcds->dwData); - } - break; - } - } - break; - - case ABP_NOTIFYPOSCHANGED: - { - const BarVector abTempV = pTrayService->m_abVector; - BarVector::const_reverse_iterator rit; - - HMONITOR hMon = (HMONITOR)lParam; - HWND hSkip = (HWND)wParam; - AppBar* p = NULL; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - if (hSkip != (*rit)->hWnd()) - { - if((*rit)->hMon() == hMon && - (!p || p->uEdge() != (*rit)->uEdge())) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_POSCHANGED - ,0 - ); - } - } - else - { - p = *rit; - } - } - - pTrayService->adjustWorkArea(hMon); - } - break; - - case ABP_NOTIFYSTATECHANGE: - { - const BarVector abTempV = pTrayService->m_abVector; - BarVector::const_reverse_iterator rit; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - if (!(*rit)->IsOverLap()) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_STATECHANGE - ,0 - ); - } - } - } - break; - - case ABP_RAISEAUTOHIDEHWND: - { - HWND hRaise = (HWND)wParam; - //UINT uEdge = (UINT)lParam; - - SetWindowPos( - hRaise, HWND_TOP - ,0,0,0,0 - ,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER - ); - } - break; - - case WM_SETTINGCHANGE: - { - TRACE("WM_SETTINGCHANGE(%.4X, \"%s\")", - wParam, (LPCTSTR)lParam); - - if (SPI_SETWORKAREA == wParam) - { - RECT rc; - - SystemParametersInfo( - SPI_GETWORKAREA - ,0 - ,&rc - ,0 - ); - - // Always update the Current workarea - CopyRect(&pTrayService->m_rWorkAreaCur, &rc); - - // This will be the case when we updated the workarea - // ourselves. - if (pTrayService->m_uWorkAreaDirty) - { - --pTrayService->m_uWorkAreaDirty; - break; - } - - // Only update the Default workarea when set externally. - CopyRect(&pTrayService->m_rWorkAreaDef, &rc); - - // Clean up any dead app bars before repositioning - pTrayService->removeDeadAppBars(); - - // Now reposition our appbars based on the new default - // workarea. - PostMessage( - pTrayService->m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)NULL - ,(LPARAM)MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY) - ); - } - } - break; - - default: - if (uMsg >= WM_USER) - { - DbgTraceWindowMessage("Shell_TrayWnd", uMsg, wParam, lParam); - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return lResult; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// WindowNotifyProc -// -// Redirects all messages to the appropriate handler -// -LRESULT CALLBACK TrayService::WindowNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleLoadInProc -// -// Handler for SHLoadInProc and SHEnableServiceObject (where available) -// -HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) -{ -#if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; - CLSIDToString(clsid, szBuffer, COUNTOF(szBuffer)); - - if (dwMessage == 1) - { - TRACE("SHLoadInProc(\"%s\")", szBuffer); - } - else if (dwMessage == 2) - { - TRACE("SHEnableServiceObject(\"%s\", FALSE)", szBuffer); - } - else if (dwMessage == 3) - { - TRACE("SHEnableServiceObject(\"%s\", TRUE)", szBuffer); - } - else - { - TRACE("Unknown LoadInProc message: %u", dwMessage); - } -#else - UNREFERENCED_PARAMETER(clsid); - UNREFERENCED_PARAMETER(dwMessage); -#endif - - // This is not actually implemented - return E_NOTIMPL; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleAppBarCopydata -// -LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) -{ - LRESULT lr = 0; - - switch (cbData) - { - case sizeof(APPBARMSGDATAV3): - { - PAPPBARMSGDATAV3 pamd = (PAPPBARMSGDATAV3)lpData; - - if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) - { - TRACE("PAPPBARMSGDATAV3 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - case sizeof(APPBARMSGDATAV2): - { - PAPPBARMSGDATAV2 pamd = (PAPPBARMSGDATAV2)lpData; - - if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) - { - TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - case sizeof(APPBARMSGDATAV1): - { - PAPPBARMSGDATAV1 pamd = (PAPPBARMSGDATAV1)lpData; - - if (sizeof(APPBARDATAV1) != pamd->abd.cbSize) - { - TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - default: - { - TRACE("Unknown APPBARMSGDATA size: %u", cbData); - } - break; - } - - return lr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleAppBarMessage -// -// Handler for all AppBar Messages -// -LRESULT TrayService::HandleAppBarMessage(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - - removeDeadAppBars(); - - TRACE("SHAppBarMessage(%u, ...)", psad->dwMessage); - - switch(psad->dwMessage) - { - case ABM_NEW: - lResult = barCreate(psad->abd); - break; - - case ABM_REMOVE: - lResult = barDestroy(psad->abd); - break; - - case ABM_QUERYPOS: - lResult = barQueryPos(psad); - break; - - case ABM_SETPOS: - lResult = barSetPos(psad); - break; - - case ABM_GETSTATE: - lResult = barGetTaskBarState(); - break; - - case ABM_GETTASKBARPOS: - lResult = barGetTaskBarPos(psad); - break; - - case ABM_ACTIVATE: - lResult = barActivate(psad->abd); - break; - - case ABM_GETAUTOHIDEBAR: - lResult = barGetAutoHide(psad->abd); - break; - - case ABM_SETAUTOHIDEBAR: - lResult = barSetAutoHide(psad->abd); - break; - - case ABM_WINDOWPOSCHANGED: - lResult = barPosChanged(psad->abd); - break; - - case ABM_SETSTATE: - lResult = barSetTaskBarState(psad->abd); - break; - - default: - TRACE("ABM unknown: %u", psad->dwMessage); - break; - } - - return lResult; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// NotifyRudeApp -// -// External interface to let us know a window has gone/left full screen mode -// -void TrayService::NotifyRudeApp(HMONITOR hFullScreenMonitor) const -{ - const BarVector abTempV = m_abVector; - BarVector::const_reverse_iterator rit; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_FULLSCREENAPP - ,(LPARAM)(hFullScreenMonitor ? 1 : 0) - ); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// removeDeadAppBars -// -// Removes all "dead" appBars. ie. Those that no longer have a valid HWND -// associated with them. -// -void TrayService::removeDeadAppBars() -{ - BarVector::iterator it = m_abVector.begin(); - - while (it != m_abVector.end()) - { - if (IsWindow((*it)->hWnd())) - { - ++it; - continue; - } - - delete *it; - it = m_abVector.erase(it); - } - - return; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barCreate -// -// Creates a new AppBar. -// -// ABM_NEW -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uCallbackMessage -// -LRESULT TrayService::barCreate(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - - if (IsWindow(abd.hWnd) && !isBar(abd.hWnd)) - { - m_abVector.push_back(new AppBar(abd.hWnd, abd.uCallbackMessage)); - lResult = 1; - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barDestroy -// -// Removes the specified AppBar. -// -// ABM_REMOVE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barDestroy(const APPBARDATAV1& abd) -{ - BarVector::iterator itBar; - LRESULT lResult = 0; - - if (getBar(abd.hWnd, itBar)) - { - lResult = 1; - - HMONITOR hMon = (*itBar)->hMon(); - - delete *itBar; - m_abVector.erase(itBar); - - PostMessage( - m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)NULL - ,(LPARAM)hMon - ); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barQueryPos -// -// Queries for an acceptable position for the specified appbar -// -// ABM_QUERYPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// rc -// -LRESULT TrayService::barQueryPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - const APPBARDATAV1& abd = psad->abd; - - if (pabd) - { - AppBar* p; - - if (getBar(abd.hWnd, p)) - { - lResult = 1; - - if (p->IsOverLap()) - { - modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); - } - else - { - modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, abd.hWnd); - } - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetPos -// -// Sets the position of the specified appbar -// -// ABM_SETPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// rc -// -LRESULT TrayService::barSetPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - const APPBARDATAV1& abd = psad->abd; - - if (pabd) - { - AppBar* p; - - if (getBar(abd.hWnd, p)) - { - lResult = 1; - - if (p->IsOverLap()) - { - modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); - } - else - { - modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, abd.hWnd); - - // If this is the first time to position the bar or if - // the new position is different than the previous, then - // notify all other appbars. - if ((ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) - || !EqualRect(&p->GetRectRef(), &pabd->rc)) - { - // Notify other bars - PostMessage( - m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)abd.hWnd - ,(LPARAM)MonitorFromRect(&pabd->rc, MONITOR_DEFAULTTOPRIMARY) - ); - } - } - - // Update the appbar stored parameters - CopyRect(&p->GetRectRef(), &pabd->rc); - p->lParam(p->lParam() | ABS_CLEANRECT); - p->uEdge(abd.uEdge); - p->hMon(MonitorFromRect(&p->GetRectRef(), MONITOR_DEFAULTTOPRIMARY)); - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetTaskBarState -// -// Returns the current TaskBar state (autohide, alwaysontop) -// -// ABM_GETSTATE -// -// Valid APPBARDATA members: -// -// cbSize -// -LRESULT TrayService::barGetTaskBarState() -{ - // Zero means neither always-on-top nor autohide, - // which is the safest guess for most LS setups - return 0; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetTaskBarPos -// -// Gets the current TaskBar position -// -// ABM_GETTASKBARPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge (undocumented) -// -LRESULT TrayService::barGetTaskBarPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - - if (pabd) - { - if (GetWindowRect(m_hNotifyWnd, &pabd->rc)) - { - lResult = 1; - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(!GetMonitorInfo(MonitorFromWindow(m_hNotifyWnd, MONITOR_DEFAULTTOPRIMARY), &mi)) - { - SetRect(&mi.rcMonitor, 0, 0, - GetSystemMetrics(SM_CXSCREEN), - GetSystemMetrics(SM_CYSCREEN)); - } - - INT nHeight, nWidth, nScreenHeight, nScreenWidth; - - nHeight = pabd->rc.bottom - pabd->rc.top; - nWidth = pabd->rc.right - pabd->rc.left; - - nScreenHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; - nScreenWidth = mi.rcMonitor.right - mi.rcMonitor.left; - - if(nHeight > nWidth) - { - if(pabd->rc.left > nScreenWidth / 2) - { - pabd->uEdge = ABE_RIGHT; - } - else - { - pabd->uEdge = ABE_LEFT; - } - } - else - { - if(pabd->rc.top > nScreenHeight / 2) - { - pabd->uEdge = ABE_BOTTOM; - } - else - { - pabd->uEdge = ABE_TOP; - } - } - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barActivate -// -// Ensures that any autohide appbar has the topmost zOrder when any appbar is -// activated. -// -// ABM_ACTIVATE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barActivate(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - AppBar* p; - - if (getBar(abd.hWnd, p)) - { - lResult = 1; - - BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - PostMessage( - m_hTrayWnd - ,ABP_RAISEAUTOHIDEHWND - ,(WPARAM)(*itBar)->hWnd() - ,(LPARAM)(*itBar)->uEdge() - ); - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetAutoHide -// -// Returns the HWND of the autohide appbar on the specified screen edge -// -// ABM_GETAUTOHIDEBAR -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// -LRESULT TrayService::barGetAutoHide(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - BarVector::iterator itBar = findBar( - MonitorFromWindow(abd.hWnd, MONITOR_DEFAULTTOPRIMARY), - abd.uEdge, ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - lResult = (LRESULT)(*itBar)->hWnd(); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetAutoHide -// -// Sets the specified AppBar to autohide if it already exists, otherwise -// if the specified AppBar does not exist, it creates it and sets it to as -// an overlap autohide AppBar. -// -// ABM_SETAUTOHIDEBAR -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// lParam -// -LRESULT TrayService::barSetAutoHide(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - - BarVector::iterator itBar = findBar(abd.hWnd); - BarVector::iterator itAutoHideBar = findBar( - MonitorFromWindow(abd.hWnd, MONITOR_DEFAULTTOPRIMARY), - abd.uEdge, ABS_AUTOHIDE); - - if (abd.lParam) // Set Auto Hide - { - lResult = 1; - - // Does an autohide bar already exist on this edge? - if (itAutoHideBar != m_abVector.end()) - { - // Return true if this appbar is the autohide bar. - return (itBar == itAutoHideBar); - } - - // if bar doesn't exist, create it and set it as an overlap bar - if (itBar == m_abVector.end()) - { - if (!barCreate(abd)) - { - return 0; - } - - itBar = m_abVector.end()-1; - (*itBar)->lParam((*itBar)->lParam() | ABS_OVERLAPAUTOHIDE); - } - - // set its assigned edge, and set it as an autohide bar - (*itBar)->uEdge(abd.uEdge); - (*itBar)->lParam((*itBar)->lParam() | ABS_AUTOHIDE); - } - else // Clear Auto Hide - { - // if the bar was the auto hide bar proceed - if (itBar != m_abVector.end() && itBar == itAutoHideBar) - { - lResult = 1; - - // if bar was overlap, destroy it - if ((*itBar)->IsOverLap()) - { - barDestroy(abd); - } - else - { - // otherwise clear its autohide status. - (*itBar)->lParam((*itBar)->lParam() & ~ABS_AUTOHIDE); - } - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barPosChanged -// -// Ensures that any autohide appbar has the topmost zOrder when any non autohide -// appbar's position has changed. -// -// ABM_WINDOWPOSCHANGED -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barPosChanged(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - AppBar* p; - - if (getBar(abd.hWnd, p) && !p->IsAutoHide()) - { - lResult = 1; - - BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - PostMessage( - m_hTrayWnd - ,ABP_RAISEAUTOHIDEHWND - ,(WPARAM)(*itBar)->hWnd() - ,(LPARAM)(*itBar)->uEdge() - ); - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetTaskBarState -// -// Sets the current TaskBar state (autohide, alwaysontop) -// -// ABM_SETSTATE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// lParam -// -LRESULT TrayService::barSetTaskBarState(const APPBARDATAV1& abd) -{ - return 0; - UNREFERENCED_PARAMETER(abd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyOverlapBar -// -// Helper function to barSetPos and barQueryPos -// -void TrayService::modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - // Use entire screen for default rectangle - HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(GetMonitorInfo(hMon, &mi)) - { - CopyRect(&rcDst, &mi.rcMonitor); - } - else - { - SetRect(&rcDst, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - } - - // Set the bar's extent - modifyBarExtent(rcDst, rcOrg, uEdge); - - // The bar's position is anchored at the desktop edge - so nothing to do - - // Set the bar's breadth - modifyBarBreadth(rcDst, rcOrg, uEdge); - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyNormalBar -// -// Helper function to barSetPos and barQueryPos -// -void TrayService::modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd) -{ - BarVector::const_iterator it; - AppBar* p; - bool bFound = FALSE; - - // Use entire screen for default rectangle - HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); - HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); - - if(hMonPrimary == hMon) - { - // Use only the original workarea for the default rectangle - CopyRect(&rcDst, &m_rWorkAreaDef); - } - else - { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(GetMonitorInfo(hMon, &mi)) - { - CopyRect(&rcDst, &mi.rcMonitor); - } - else - { - ASSERT(FALSE); - - // Use only the original workarea for the default rectangle - CopyRect(&rcDst, &m_rWorkAreaDef); - hMon = hMonPrimary; - } - } - - // Set the bar's extent - modifyBarExtent(rcDst, rcOrg, uEdge); - - // Set the bar's position - for (it = m_abVector.begin(); it != m_abVector.end(); ++it) - { - p = *it; - - // ignore overlap bars and invalid windows and other monitors - if(!p || p->IsOverLap() || hMon != p->hMon()) - { - // do nothing - } - // if this is our appbar, mark it found and continue - else if (hWnd == p->hWnd()) - { - bFound = true; - } - // ignore bars that haven't been initialized - else if (ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) - { - // do nothing - } - // Ignore other edge appbars for the most part - else if (uEdge != p->uEdge()) - { - // Left/Right bars must resize to top/bottom bars - if (ABE_HORIZONTAL != (ABE_HORIZONTAL & uEdge) - && - ABE_HORIZONTAL == (ABE_HORIZONTAL & p->uEdge())) - { - RECT rc; // dummy - - // If our destination rectangle currently intersects - // then resize it - if (IntersectRect(&rc, &p->GetRectRef(), &rcDst)) - { - if (ABE_TOP == p->uEdge()) - { - rcDst.top = p->GetRectRef().bottom; - } - else - { - rcDst.bottom = p->GetRectRef().top; - } - } - } - } - // Keep moving the destination appbar while we are looking - // at same edge appbars before our own. Once we find our - // own, then we ignore all same edge appbars after ours. - else if (!bFound) - { - switch (uEdge) - { - case ABE_LEFT: - rcDst.left = p->GetRectRef().right; - break; - case ABE_TOP: - rcDst.top = p->GetRectRef().bottom; - break; - case ABE_RIGHT: - rcDst.right = p->GetRectRef().left; - break; - case ABE_BOTTOM: - rcDst.bottom = p->GetRectRef().top; - break; - } - } - } - - // Set the bar's breadth - modifyBarBreadth(rcDst, rcOrg, uEdge); - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyBarExtent -// -// Helper function to modifyNormalBar and modifyOverlapBar -// -void TrayService::modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - switch (uEdge) - { - case ABE_LEFT: - case ABE_RIGHT: - rcDst.top = std::max(rcDst.top, rcOrg.top); - rcDst.bottom = std::min(rcDst.bottom, rcOrg.bottom); - break; - case ABE_TOP: - case ABE_BOTTOM: - rcDst.left = std::max(rcDst.left, rcOrg.left); - rcDst.right = std::min(rcDst.right, rcOrg.right); - break; - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyBarBreadth -// -// Helper function to modifyBarNormal and modifyBarOverlap -// -void TrayService::modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - switch (uEdge) - { - case ABE_LEFT: - rcDst.right = rcDst.left + (rcOrg.right - rcOrg.left); - break; - case ABE_TOP: - rcDst.bottom = rcDst.top + (rcOrg.bottom - rcOrg.top); - break; - case ABE_RIGHT: - rcDst.left = rcDst.right - (rcOrg.right - rcOrg.left); - break; - case ABE_BOTTOM: - rcDst.top = rcDst.bottom - (rcOrg.bottom - rcOrg.top); - break; - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// adjustWorkArea -// -// Helper function to barSetPos (via ABP_NOTIFYPOSCHANGED) -// -void TrayService::adjustWorkArea(HMONITOR hMon) -{ - RECT rcWorker, rcMonitor, rcWorkArea; - - HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); - - if (hMon != hMonPrimary) - { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if (!GetMonitorInfo(hMon, &mi)) - { - return; - } - - CopyRect(&rcMonitor, &mi.rcMonitor); - CopyRect(&rcWorkArea, &mi.rcWork); - } - else - { - CopyRect(&rcMonitor, &m_rWorkAreaDef); // yes, we actually want this - CopyRect(&rcWorkArea, &m_rWorkAreaCur); - } - - CopyRect(&rcWorker, &rcMonitor); - - for ( - BarVector::iterator it = m_abVector.begin() - ;it != m_abVector.end() - ;++it - ) - { - AppBar* p = *it; - - if(p && !p->IsOverLap() && p->hMon() == hMon && - (ABS_CLEANRECT == (ABS_CLEANRECT & p->lParam()))) - { - if (!IsWindow(p->hWnd())) - { - continue; - } - - RECT rcBarEx; - - CopyRect(&rcBarEx, &rcMonitor); - - switch (p->uEdge()) - { - case ABE_LEFT: - rcBarEx.right = p->GetRectRef().right; - break; - case ABE_RIGHT: - rcBarEx.left = p->GetRectRef().left; - break; - case ABE_TOP: - rcBarEx.bottom = p->GetRectRef().bottom; - break; - case ABE_BOTTOM: - rcBarEx.top = p->GetRectRef().top; - break; - } - - SubtractRect(&rcWorker, &rcWorker, &rcBarEx); - } - } - - if(!EqualRect(&rcWorker, &rcWorkArea)) - { - setWorkArea(&rcWorker); - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setWorkArea -// -// Helper function for setting the specified work area -// -void TrayService::setWorkArea(LPRECT prcWorkArea) -{ - if (m_hTrayWnd) - { - m_uWorkAreaDirty++; - } - - SystemParametersInfo( - SPI_SETWORKAREA - ,1 // readjust maximized windows - ,prcWorkArea - ,0 // SPIF_SENDCHANGE - see below - ); - SendNotifyMessage( // used in place of SPIF_SENDCHANGE above to avoid lockups - HWND_BROADCAST // see http://blogs.msdn.com/oldnewthing/archive/2005/03/10/392118.aspx - ,WM_SETTINGCHANGE - ,SPI_SETWORKAREA - ,0 - ); - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ABLock -// -// Calls SHLockShared API for the specified Shell AppBar memory -// -// Returns a pointer to shared memory location for an AppBarData structure -// -PAPPBARDATAV1 TrayService::ABLock(PSHELLAPPBARDATA psad) -{ - return (PAPPBARDATAV1)SHLockShared( - psad->hSharedMemory, psad->dwSourceProcessId); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ABUnlock -// -// Calls SHUnlockShared API for the specified AppBarData* memory -// -void TrayService::ABUnLock(PAPPBARDATAV1 pabd) -{ - SHUnlockShared(pabd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// FindAppBarPredicate_hWnd -// -// Predicate for std::find_if, used by findBar variants -// Needs to be at global scope because of mingw issues -// -// Find the appbar matching the specified hWnd -// -struct FindAppBarPredicate_hWnd -{ - FindAppBarPredicate_hWnd(HWND hWnd) : - m_hWnd(hWnd) - { - // do nothing - } - FindAppBarPredicate_hWnd(const FindAppBarPredicate_hWnd& copy) : - m_hWnd(copy.m_hWnd) - { - // do nothing - } - - bool operator() (const AppBar* pab) const - { - return (pab->hWnd() == m_hWnd); - } - -private: - const HWND m_hWnd; - -private: - // Not implemented - FindAppBarPredicate_hWnd& operator=(const FindAppBarPredicate_hWnd&); -}; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// FindAppBarPredicate_MatchLParam -// -// Predicate for std::find_if, used by findBar variants -// Needs to be at global scope because of mingw issues -// -// Find the appbar on the specified edge that has a matching lParam value -// -struct FindAppBarPredicate_MatchLParam -{ - FindAppBarPredicate_MatchLParam(HMONITOR hMon, UINT uEdge, LPARAM lParam) : - m_hMon(hMon), m_uEdge(uEdge), m_lParam(lParam) - { - // do nothing - } - FindAppBarPredicate_MatchLParam(const FindAppBarPredicate_MatchLParam& copy) : - m_hMon(copy.m_hMon), m_uEdge(copy.m_uEdge), m_lParam(copy.m_lParam) - { - // do nothing - } - - bool operator() (const AppBar* pab) const - { - return (pab->hMon() == m_hMon && pab->uEdge() == m_uEdge && - m_lParam == (pab->lParam() & m_lParam)); - } - -private: - const HMONITOR m_hMon; - const UINT m_uEdge; - const LPARAM m_lParam; - -private: - // Not implemented - FindAppBarPredicate_MatchLParam& operator=(const FindAppBarPredicate_MatchLParam&); -}; - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// findBar -// -// Looks up an AppBar in the AppBarList -// -BarVector::iterator TrayService::findBar(HWND hWnd) -{ - return std::find_if(m_abVector.begin(), m_abVector.end(), - FindAppBarPredicate_hWnd(hWnd)); -} -BarVector::iterator TrayService::findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam) -{ - return std::find_if(m_abVector.begin(), m_abVector.end(), - FindAppBarPredicate_MatchLParam(hMon, uEdge, lParam)); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// isBar -// -// Determines whether the HWND is associated with any current AppBar. -// -bool TrayService::isBar(HWND hWnd) -{ - return m_abVector.end() != findBar(hWnd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// getBar -// -// Looks up an BarVector iterator based on the HWND -// -// returns true if found, otherwise false. -// -bool TrayService::getBar(HWND hWnd, BarVector::iterator& itBar) -{ - bool bReturn = false; - - itBar = findBar(hWnd); - - if (itBar != m_abVector.end()) - { - bReturn = true; - } - - return bReturn; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// getBar -// -// Looks up an AppBar* based on the HWND -// -// Returns true if found, otherwise false. -// -bool TrayService::getBar(HWND hWnd, AppBar*& pBarRef) -{ - bool bReturn = false; - BarVector::iterator itBar; - - if (getBar(hWnd, itBar)) - { - pBarRef = *itBar; - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleNotification -// -// Handler for all system tray notifications -// -BOOL TrayService::HandleNotification(PSHELLTRAYDATA pstd) -{ - bool bReturn = false; - - switch (pstd->dwMessage) - { - case NIM_ADD: - bReturn = addIcon(pstd->nid); - break; - - case NIM_MODIFY: - bReturn = modifyIcon(pstd->nid); - break; - - case NIM_DELETE: - bReturn = deleteIcon(pstd->nid); - break; - - case NIM_SETFOCUS: - bReturn = setFocusIcon(pstd->nid); - break; - - case NIM_SETVERSION: - bReturn = setVersionIcon(pstd->nid); - break; - - default: - TRACE("Unknown NIM: %u", pstd->dwMessage); - break; - } - - return bReturn ? TRUE : FALSE; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// notify -// -// Notify all listeners of a systray event -// -bool TrayService::notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const -{ - return 0 != SendMessage(m_hLiteStep, LM_SYSTRAY, - dwMessage, (LPARAM)pclsnid); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// SendSystemTray -// -// Resend all icon data; systray modules will request this via LM_SYSTRAYREADY -// during their startup. -// -HWND TrayService::SendSystemTray() -{ - removeDeadIcons(); - - for (IconVector::const_iterator it = m_siVector.begin(); - it != m_siVector.end(); ++it) - { - if ((*it)->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - (*it)->CopyLSNID(&lsnid); - - notify(NIM_ADD, &lsnid); - } - } - - return m_hNotifyWnd; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// removeDeadIcons -// -// Removes all "dead" icons. ie. Those that no longer have a valid HWND -// associated with them. -// -void TrayService::removeDeadIcons() -{ - IconVector::iterator it = m_siVector.begin(); - - while (it != m_siVector.end()) - { - if (IsWindow((*it)->GetHwnd())) - { - ++it; - continue; - } - - delete *it; - it = m_siVector.erase(it); - } - - return; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// extendNIDCopy -// -// Copies all non-persistent data that is not stored in NotifyIcon. -// -bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const -{ - // Copy Info Tips - if (nid.uFlags & NIF_INFO) - { - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - case NID_5W_SIZE: - { - NID_5W* pnid = (NID_5W*)&nid; - - int nReturn; - WCHAR szTemp[256]; - - memcpy(szTemp, pnid->szInfo, sizeof(WCHAR)*256); - szTemp[255] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfo, TRAY_MAX_INFO_LENGTH, NULL, NULL); - - if (!nReturn) - { - lsnid.szInfo[0] = 0; - } - - memcpy(szTemp, pnid->szInfoTitle, sizeof(WCHAR)*64); - szTemp[63] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfoTitle, TRAY_MAX_INFOTITLE_LENGTH, NULL, NULL); - - if (!nReturn) - { - lsnid.szInfoTitle[0] = 0; - } - - lsnid.dwInfoFlags = pnid->dwInfoFlags; - lsnid.uTimeout = pnid->uTimeout; - lsnid.uFlags |= NIF_INFO; - } - break; - case NID_6A_SIZE: - case NID_5A_SIZE: - { - NID_5A* pnid = (NID_5A*)&nid; - - HRESULT hr; - - hr = StringCchCopy(lsnid.szInfo, - TRAY_MAX_INFO_LENGTH, pnid->szInfo); - - if (FAILED(hr)) - { - lsnid.szInfo[0] = 0; - } - - hr = StringCchCopy(lsnid.szInfoTitle, - TRAY_MAX_INFOTITLE_LENGTH, pnid->szInfoTitle); - - if (FAILED(hr)) - { - lsnid.szInfoTitle[0] = 0; - } - - lsnid.dwInfoFlags = pnid->dwInfoFlags; - lsnid.uTimeout = pnid->uTimeout; - lsnid.uFlags |= NIF_INFO; - } - break; - default: - { - // do nothing - } - break; - } - } - - // Copy GUID - if (nid.uFlags & NIF_GUID) - { - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - { - NID_6W* pnid = (NID_6W*)&nid; - - lsnid.guidItem = pnid->guidItem; - lsnid.uFlags |= NIF_GUID; - } - break; - case NID_6A_SIZE: - { - NID_6A* pnid = (NID_6A*)&nid; - - lsnid.guidItem = pnid->guidItem; - lsnid.uFlags |= NIF_GUID; - } - break; - default: - { - // do nothing - } - break; - } - } - - return true; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// addIcon -// -bool TrayService::addIcon(const NID_XX& nid) -{ - bool bReturn = false; - - if (m_siVector.end() == findIcon(nid)) - { - NotifyIcon * pni = new NotifyIcon(nid); - - if (pni) - { - // Fail shared icons, unless a valid hIcon exists - if (IsWindow(pni->GetHwnd()) && - (!pni->IsShared() || pni->HasIcon())) - { - m_siVector.push_back(pni); - - if (pni->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - pni->CopyLSNID(&lsnid); - extendNIDCopy(lsnid, nid); - - notify(NIM_ADD, &lsnid); - } - bReturn = true; - } - else - { - delete pni; - } - } - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyIcon -// -bool TrayService::modifyIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it && *it) - { - NotifyIcon * pni = *it; - - bool bWasValid = pni->IsValid(); - - // Update stored NotifyIcon - pni->Update(nid); - - if (pni->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - if (!bWasValid) - { - // This is a "new" icon, send entire stored NotifyIcon - pni->CopyLSNID(&lsnid); - extendNIDCopy(lsnid, nid); - - notify(NIM_ADD, &lsnid); - } - else - { - // This icon already exists, just send updated flags - pni->CopyLSNID(&lsnid, nid.uFlags); - extendNIDCopy(lsnid, nid); - - notify(NIM_MODIFY, &lsnid); - } - } - else if (bWasValid) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,pni->GetHwnd() - ,pni->GetuID() - ,0 - }; - - // This icon is no longer visible, remove - notify(NIM_DELETE, &lsnid); - } - - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// deleteIcon -// -// Remove an icon from the icon list -// -bool TrayService::deleteIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - notify(NIM_DELETE, &lsnid); - - delete *it; - m_siVector.erase(it); - - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setFocusIcon -// -// Sets selection focus to the specified icon -// -bool TrayService::setFocusIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - bReturn = notify(NIM_SETFOCUS, &lsnid); - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setVersionIcon -// -// Sets compatibility version for specified icon -// -bool TrayService::setVersionIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - case NID_5W_SIZE: - lsnid.uVersion = ((NID_5W&)nid).uVersion; - break; - - case NID_6A_SIZE: - case NID_5A_SIZE: - lsnid.uVersion = ((NID_5A&)nid).uVersion; - break; - - default: - break; - } - - bReturn = notify(NIM_SETVERSION, &lsnid); - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// FindIconPredicate -// -// Predicate for std::find_if, used by findIcon -// Needs to be at global scope because of mingw issues -// -struct FindIconPredicate -{ - FindIconPredicate(HWND hWnd, UINT uID) : - m_hWnd(hWnd), m_uID(uID) - { - // do nothing - } - FindIconPredicate(const FindIconPredicate& copy) : - m_hWnd(copy.m_hWnd), m_uID(copy.m_uID) - { - // do nothing - } - - bool operator() (const NotifyIcon* pni) const - { - return (pni->GetHwnd() == m_hWnd && pni->GetuID() == m_uID); - } - -private: - const HWND m_hWnd; - const UINT m_uID; - -private: - // Not implemented - FindIconPredicate& operator=(const FindIconPredicate&); -}; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// findIcon -// -// Looks up an icon in the SystrayIconList -// -IconVector::iterator TrayService::findIcon(HWND hWnd, UINT uId) -{ - return std::find_if(m_siVector.begin(), - m_siVector.end(), FindIconPredicate(hWnd, uId)); -} +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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 "TrayService.h" +#include "../utility/core.hpp" +#include +#include +#include + + +#if !defined(REGSTR_PATH_SHELLSERVICEOBJECTDELAYED) +#define REGSTR_PATH_SHELLSERVICEOBJECTDELAYED \ + _T("Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad") +#endif + +static const TCHAR szTrayClass[] = _T("Shell_TrayWnd"); +static const TCHAR szTrayTitle[] = _T("LiteStep Tray Manager"); +static const TCHAR szNotifyClass[] = _T("TrayNotifyWnd"); + + +// +// CLSID_SysTrayObject - {35CEC8A3-2BE6-11D2-8773-92E220524153} +// +// This appears to be the SSO responsible for starting up all other "approved" +// SSOs on Vista. Name derived from "stobject.dll". +// +const GUID CLSID_SysTrayObject = \ +{0x35CEC8A3, 0x2BE6, 0x11D2, {0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53}}; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayService +// +TrayService::TrayService() : +m_uWorkAreaDirty(0), m_hNotifyWnd(NULL), m_hTrayWnd(NULL), +m_hLiteStep(NULL), m_hInstance(NULL) +{ + // do nothing +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ~TrayService +// +TrayService::~TrayService() +{ + // do nothing +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// Start() +// +HRESULT TrayService::Start() +{ + ASSERT(NULL == m_hTrayWnd); + HRESULT hr = E_FAIL; + + m_hLiteStep = GetLitestepWnd(); + m_hInstance = GetModuleHandle(NULL); + + if (m_hLiteStep && m_hInstance) + { + // clear work area of primary monitor + SetRect(&m_rWorkAreaDef, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + setWorkArea(&m_rWorkAreaDef); + CopyRect(&m_rWorkAreaCur, &m_rWorkAreaDef); + + hr = createWindows(); + + if (SUCCEEDED(hr)) + { + SetWindowLongPtr(m_hTrayWnd, GWLP_USERDATA, magicDWord); + SetWindowLongPtr(m_hTrayWnd, 0, (LONG_PTR)this); + + // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1427677&SiteID=1 + // + // Re: TaskbarCreated message (not working in Vista) + // + // > The code is still in there to broadcast the message. + // > SendNotifyMessage(HWND_BROADCAST, + // > RegisterWindowMessage(TEXT("TaskbarCreated")), 0, 0); + // + // >> It looks as though applications running as admin cannot + // >> receive the message. Presumably, this is because Explorer, + // >> which publishes the message, is not running as admin + // + // >>> The message is blocked by User Interface Privilege + // >>> Isolation, Administrative applications that need to see it + // >>> can allow it through by calling ChangeWindowMessageFilter + // >>> after making sure the necessary security precautions are in + // >>> place. + + // tell apps to reregister their icons + SendNotifyMessage(HWND_BROADCAST, + RegisterWindowMessage(_T("TaskbarCreated")), 0, 0); + + if (IsVistaOrAbove()) + { + // On Vista and up there's a single SSO responsible for loading + // all the supported objects (volume icon, network icon, etc.) + loadShellServiceObject(CLSID_SysTrayObject); + } + else if (IsOS(OS_WIN2000ORGREATER)) + { + // On previous versions the object list is in the registry + loadShellServiceObjects(); + } + } + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// Stop() +// +HRESULT TrayService::Stop() +{ + HRESULT hr = S_OK; + + unloadShellServiceObjects(); + destroyWindows(); + + while (!m_siVector.empty()) + { + delete m_siVector.back(); + m_siVector.pop_back(); + } + + while (!m_abVector.empty()) + { + delete m_abVector.back(); + m_abVector.pop_back(); + } + + // clear the work area of primary monitor + SetRect(&m_rWorkAreaDef, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + setWorkArea(&m_rWorkAreaDef); + + m_hLiteStep = NULL; + m_hInstance = NULL; + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// createWindows +// +HRESULT TrayService::createWindows() +{ + HRESULT hr = E_FAIL; + + // + // Register tray window class + // + WNDCLASSEX wc = { 0 }; + wc.cbSize = sizeof(WNDCLASSEX); + wc.cbWndExtra = sizeof(TrayService*); + wc.lpfnWndProc = TrayService::WindowTrayProc; + wc.hInstance = m_hInstance; + wc.lpszClassName = szTrayClass; + wc.style = CS_DBLCLKS; + + if (!RegisterClassEx(&wc)) + { + hr = HrGetLastError(); + } + else + { + // + // Window which receives the tray messages + // + m_hTrayWnd = CreateWindowEx( + WS_EX_TOPMOST | WS_EX_TOOLWINDOW, + szTrayClass, szTrayTitle, + WS_POPUP, + 0, 0, 0, 0, + NULL, NULL, + m_hInstance, + NULL); + + if (NULL == m_hTrayWnd) + { + hr = HrGetLastError(); + UnregisterClass(szTrayClass, m_hInstance); + } + else + { + // Our main window is enough to start up, we can do without the + // TrayNotifyWnd if necessary. + hr = S_OK; + + // + // Register "TrayNotifyWnd" class and create window + // + ZeroMemory(&wc, sizeof(wc)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = TrayService::WindowNotifyProc; + wc.hInstance = m_hInstance; + wc.lpszClassName = szNotifyClass; + wc.style = CS_DBLCLKS; + + if (RegisterClassEx(&wc)) + { + m_hNotifyWnd = CreateWindowEx( + 0, + szNotifyClass, NULL, + WS_CHILD, + 0, 0, 0, 0, + m_hTrayWnd, NULL, + m_hInstance, + NULL); + + if (!m_hNotifyWnd) + { + UnregisterClass(szNotifyClass, m_hInstance); + } + } + } + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// destroyWindows +// +void TrayService::destroyWindows() +{ + if (m_hNotifyWnd) + { + DestroyWindow(m_hNotifyWnd); + m_hNotifyWnd = NULL; + + UnregisterClass(szNotifyClass, m_hInstance); + } + + if (m_hTrayWnd) + { + DestroyWindow(m_hTrayWnd); + m_hTrayWnd = NULL; + + UnregisterClass(szTrayClass, m_hInstance); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// loadShellServiceObject +// +HRESULT TrayService::loadShellServiceObject(REFCLSID rclsid) +{ +#if defined(TRACE_ENABLED) + CHAR szBuffer[MAX_PATH] = { 0 }; + CLSIDToString(rclsid, szBuffer, COUNTOF(szBuffer)); + + TRACE("loadShellServiceObject(\"%s\")", szBuffer); +#endif + + // The SSO might have a custom manifest. + // Activate it before loading the object. + ULONG_PTR ulCookie; + HANDLE hContext = LSActivateActCtxForClsid(rclsid, &ulCookie); + + IOleCommandTarget* pCmdTarget = NULL; + + HRESULT hr = CoCreateInstance(rclsid, NULL, + CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + IID_IOleCommandTarget, (void **)&pCmdTarget); + + if (SUCCEEDED(hr)) + { + hr = pCmdTarget->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, + OLECMDEXECOPT_DODEFAULT, NULL, NULL); + + m_ssoVector.push_back(pCmdTarget); + } + + if (hContext != INVALID_HANDLE_VALUE) + { + LSDeactivateActCtx(hContext, &ulCookie); + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// loadShellServiceObjects +// +// Start the COM based shell services listed in the registry. +// +void TrayService::loadShellServiceObjects() +{ + HKEY hkeyServices; + int nCounter = 0; + + LONG lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, + 0, KEY_READ, &hkeyServices); + + while (lErrorCode == ERROR_SUCCESS) + { + TCHAR szValueName[32] = { 0 }; + char szData[40] = { 0 }; + DWORD cchValueName = sizeof(szValueName) / sizeof(szValueName[0]); + DWORD cbData = sizeof(szData); + DWORD dwDataType; + + lErrorCode = RegEnumValue(hkeyServices, nCounter, szValueName, + &cchValueName, NULL, &dwDataType, (LPBYTE)szData, &cbData); + + if (lErrorCode == ERROR_SUCCESS) + { + WCHAR wszCLSID[40] = { 0 }; + CLSID clsid = CLSID_NULL; + + MultiByteToWideChar(CP_ACP, 0, szData, cbData, wszCLSID, 40); + CLSIDFromString(wszCLSID, &clsid); + + loadShellServiceObject(clsid); + } + + ++nCounter; + } + + RegCloseKey(hkeyServices); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// unloadShellServiceObjects +// +// Shut down the COM based shell services. +// +// +void TrayService::unloadShellServiceObjects() +{ + while (!m_ssoVector.empty()) + { + m_ssoVector.back()->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, + OLECMDEXECOPT_DODEFAULT, NULL, NULL); + + m_ssoVector.back()->Release(); + m_ssoVector.pop_back(); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// WindowTrayProc +// +// Redirects all messages to the appropriate handler +// +LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +{ + static TrayService* pTrayService = NULL; + + if (!pTrayService) + { + pTrayService = (TrayService*)GetWindowLongPtr(hWnd, 0); + } + + if (pTrayService) + { + LRESULT lResult = 0; + + switch (uMsg) + { + case WM_COPYDATA: + { + // + // Undocumented: This is how we can make our own system tray + // and handle app bar windows. Once a window in the system has + // the "Shell_TrayWnd" class name, it receives this message! + // + COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam; + + switch (pcds->dwData) + { + case SH_APPBAR_DATA: + { + // + // Application Bar Message + // + lResult = pTrayService->HandleAppBarCopydata( + pcds->cbData, pcds->lpData); + } + break; + + case SH_TRAY_DATA: + { + // + // System Tray Notification + // + PSHELLTRAYDATA pstd = (PSHELLTRAYDATA)pcds->lpData; + + lResult = (LRESULT)pTrayService->HandleNotification(pstd); + } + break; + + case SH_LOADPROC_DATA: + { + // + // LoadInProc messages + // + if (pcds->cbData == sizeof(CLSID)) + { + // Classic SHLoadInProc message + lResult = pTrayService->HandleLoadInProc( + (REFCLSID)pcds->lpData, 1); + } + else if (pcds->cbData == sizeof(SHELLINPROCDATA)) + { + PSHELLINPROCDATA pipd = (PSHELLINPROCDATA)pcds->lpData; + + lResult = pTrayService->HandleLoadInProc( + pipd->clsid, pipd->dwMessage); + } + else + { + TRACE("Unknown SHLoadInProc size: %u", pcds->cbData); + lResult = E_NOTIMPL; + } + } + break; + case SH_TRAYINFO_DATA: + { + lResult = pTrayService->TrayInfoEvent(pcds->cbData, pcds->lpData); + } + break; + + default: + { + TRACE("Unsupported tray message: %u", pcds->dwData); + } + break; + } + } + break; + + case ABP_NOTIFYPOSCHANGED: + { + const BarVector abTempV = pTrayService->m_abVector; + BarVector::const_reverse_iterator rit; + + HMONITOR hMon = (HMONITOR)lParam; + HWND hSkip = (HWND)wParam; + AppBar* p = NULL; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + if (hSkip != (*rit)->hWnd()) + { + if((*rit)->hMon() == hMon && + (!p || p->uEdge() != (*rit)->uEdge())) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_POSCHANGED + ,0 + ); + } + } + else + { + p = *rit; + } + } + + pTrayService->adjustWorkArea(hMon); + } + break; + + case ABP_NOTIFYSTATECHANGE: + { + const BarVector abTempV = pTrayService->m_abVector; + BarVector::const_reverse_iterator rit; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + if (!(*rit)->IsOverLap()) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_STATECHANGE + ,0 + ); + } + } + } + break; + + case ABP_RAISEAUTOHIDEHWND: + { + HWND hRaise = (HWND)wParam; + //UINT uEdge = (UINT)lParam; + + SetWindowPos( + hRaise, HWND_TOP + ,0,0,0,0 + ,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER + ); + } + break; + + case WM_SETTINGCHANGE: + { + TRACE("WM_SETTINGCHANGE(%.4X, \"%s\")", + wParam, (LPCTSTR)lParam); + + if (SPI_SETWORKAREA == wParam) + { + RECT rc; + + SystemParametersInfo( + SPI_GETWORKAREA + ,0 + ,&rc + ,0 + ); + + // Always update the Current workarea + CopyRect(&pTrayService->m_rWorkAreaCur, &rc); + + // This will be the case when we updated the workarea + // ourselves. + if (pTrayService->m_uWorkAreaDirty) + { + --pTrayService->m_uWorkAreaDirty; + break; + } + + // Only update the Default workarea when set externally. + CopyRect(&pTrayService->m_rWorkAreaDef, &rc); + + // Clean up any dead app bars before repositioning + pTrayService->removeDeadAppBars(); + + // Now reposition our appbars based on the new default + // workarea. + PostMessage( + pTrayService->m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)NULL + ,(LPARAM)MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY) + ); + } + } + break; + + default: + if (uMsg >= WM_USER) + { + DbgTraceWindowMessage("Shell_TrayWnd", uMsg, wParam, lParam); + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return lResult; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// WindowNotifyProc +// +// Redirects all messages to the appropriate handler +// +LRESULT CALLBACK TrayService::WindowNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleLoadInProc +// +// Handler for SHLoadInProc and SHEnableServiceObject (where available) +// +HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) +{ +#if defined(TRACE_ENABLED) + CHAR szBuffer[MAX_PATH] = { 0 }; + CLSIDToString(clsid, szBuffer, COUNTOF(szBuffer)); + + if (dwMessage == 1) + { + TRACE("SHLoadInProc(\"%s\")", szBuffer); + } + else if (dwMessage == 2) + { + TRACE("SHEnableServiceObject(\"%s\", FALSE)", szBuffer); + } + else if (dwMessage == 3) + { + TRACE("SHEnableServiceObject(\"%s\", TRUE)", szBuffer); + } + else + { + TRACE("Unknown LoadInProc message: %u", dwMessage); + } +#else + UNREFERENCED_PARAMETER(clsid); + UNREFERENCED_PARAMETER(dwMessage); +#endif + + // This is not actually implemented + return E_NOTIMPL; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayInfoEvent +// +// Handles tray info events +// +LRESULT TrayService::TrayInfoEvent(DWORD /* cbData */, LPVOID lpData) // size, data +{ + LRESULT lr = 0; + LPNOTIFYICONIDENTIFIER_MSGV1 s = (LPNOTIFYICONIDENTIFIER_MSGV1)lpData; + + // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. + + if (s->dwMessage == 2) // Icon size? + { + return MAKELONG(16,16); + } + + POINT p; + GetCursorPos(&p); + + if (s->dwMessage == 1) // Icon position + { + return MAKELPARAM(p.x, p.y); + } + + return lr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleAppBarCopydata +// +LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) +{ + LRESULT lr = 0; + + switch (cbData) + { + case sizeof(APPBARMSGDATAV3): + { + PAPPBARMSGDATAV3 pamd = (PAPPBARMSGDATAV3)lpData; + + if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) + { + TRACE("PAPPBARMSGDATAV3 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + case sizeof(APPBARMSGDATAV2): + { + PAPPBARMSGDATAV2 pamd = (PAPPBARMSGDATAV2)lpData; + + if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) + { + TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + case sizeof(APPBARMSGDATAV1): + { + PAPPBARMSGDATAV1 pamd = (PAPPBARMSGDATAV1)lpData; + + if (sizeof(APPBARDATAV1) != pamd->abd.cbSize) + { + TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + default: + { + TRACE("Unknown APPBARMSGDATA size: %u", cbData); + } + break; + } + + return lr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleAppBarMessage +// +// Handler for all AppBar Messages +// +LRESULT TrayService::HandleAppBarMessage(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + + removeDeadAppBars(); + + TRACE("SHAppBarMessage(%u, ...)", psad->dwMessage); + + switch(psad->dwMessage) + { + case ABM_NEW: + lResult = barCreate(psad->abd); + break; + + case ABM_REMOVE: + lResult = barDestroy(psad->abd); + break; + + case ABM_QUERYPOS: + lResult = barQueryPos(psad); + break; + + case ABM_SETPOS: + lResult = barSetPos(psad); + break; + + case ABM_GETSTATE: + lResult = barGetTaskBarState(); + break; + + case ABM_GETTASKBARPOS: + lResult = barGetTaskBarPos(psad); + break; + + case ABM_ACTIVATE: + lResult = barActivate(psad->abd); + break; + + case ABM_GETAUTOHIDEBAR: + lResult = barGetAutoHide(psad->abd); + break; + + case ABM_SETAUTOHIDEBAR: + lResult = barSetAutoHide(psad->abd); + break; + + case ABM_WINDOWPOSCHANGED: + lResult = barPosChanged(psad->abd); + break; + + case ABM_SETSTATE: + lResult = barSetTaskBarState(psad->abd); + break; + + default: + TRACE("ABM unknown: %u", psad->dwMessage); + break; + } + + return lResult; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// NotifyRudeApp +// +// External interface to let us know a window has gone/left full screen mode +// +void TrayService::NotifyRudeApp(HMONITOR hFullScreenMonitor) const +{ + const BarVector abTempV = m_abVector; + BarVector::const_reverse_iterator rit; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_FULLSCREENAPP + ,(LPARAM)(hFullScreenMonitor ? 1 : 0) + ); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// removeDeadAppBars +// +// Removes all "dead" appBars. ie. Those that no longer have a valid HWND +// associated with them. +// +void TrayService::removeDeadAppBars() +{ + BarVector::iterator it = m_abVector.begin(); + + while (it != m_abVector.end()) + { + if (IsWindow((*it)->hWnd())) + { + ++it; + continue; + } + + delete *it; + it = m_abVector.erase(it); + } + + return; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barCreate +// +// Creates a new AppBar. +// +// ABM_NEW +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uCallbackMessage +// +LRESULT TrayService::barCreate(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + + if (IsWindow((HWND)abd.hWnd) && !isBar((HWND)abd.hWnd)) + { + m_abVector.push_back(new AppBar((HWND)abd.hWnd, abd.uCallbackMessage)); + lResult = 1; + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barDestroy +// +// Removes the specified AppBar. +// +// ABM_REMOVE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barDestroy(const APPBARDATAV1& abd) +{ + BarVector::iterator itBar; + LRESULT lResult = 0; + + if (getBar((HWND)abd.hWnd, itBar)) + { + lResult = 1; + + HMONITOR hMon = (*itBar)->hMon(); + + delete *itBar; + m_abVector.erase(itBar); + + PostMessage( + m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)NULL + ,(LPARAM)hMon + ); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barQueryPos +// +// Queries for an acceptable position for the specified appbar +// +// ABM_QUERYPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// rc +// +LRESULT TrayService::barQueryPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + const APPBARDATAV1& abd = psad->abd; + + if (pabd) + { + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + if (p->IsOverLap()) + { + modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); + } + else + { + modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); + } + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetPos +// +// Sets the position of the specified appbar +// +// ABM_SETPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// rc +// +LRESULT TrayService::barSetPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + const APPBARDATAV1& abd = psad->abd; + + if (pabd) + { + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + if (p->IsOverLap()) + { + modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); + } + else + { + modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); + + // If this is the first time to position the bar or if + // the new position is different than the previous, then + // notify all other appbars. + if ((ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) + || !EqualRect(&p->GetRectRef(), &pabd->rc)) + { + // Notify other bars + PostMessage( + m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)abd.hWnd + ,(LPARAM)MonitorFromRect(&pabd->rc, MONITOR_DEFAULTTOPRIMARY) + ); + } + } + + // Update the appbar stored parameters + CopyRect(&p->GetRectRef(), &pabd->rc); + p->lParam(p->lParam() | ABS_CLEANRECT); + p->uEdge(abd.uEdge); + p->hMon(MonitorFromRect(&p->GetRectRef(), MONITOR_DEFAULTTOPRIMARY)); + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetTaskBarState +// +// Returns the current TaskBar state (autohide, alwaysontop) +// +// ABM_GETSTATE +// +// Valid APPBARDATA members: +// +// cbSize +// +LRESULT TrayService::barGetTaskBarState() +{ + // Zero means neither always-on-top nor autohide, + // which is the safest guess for most LS setups + return 0; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetTaskBarPos +// +// Gets the current TaskBar position +// +// ABM_GETTASKBARPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge (undocumented) +// +LRESULT TrayService::barGetTaskBarPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + + if (pabd) + { + if (GetWindowRect(m_hNotifyWnd, &pabd->rc)) + { + lResult = 1; + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(!GetMonitorInfo(MonitorFromWindow(m_hNotifyWnd, MONITOR_DEFAULTTOPRIMARY), &mi)) + { + SetRect(&mi.rcMonitor, 0, 0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN)); + } + + INT nHeight, nWidth, nScreenHeight, nScreenWidth; + + nHeight = pabd->rc.bottom - pabd->rc.top; + nWidth = pabd->rc.right - pabd->rc.left; + + nScreenHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; + nScreenWidth = mi.rcMonitor.right - mi.rcMonitor.left; + + if(nHeight > nWidth) + { + if(pabd->rc.left > nScreenWidth / 2) + { + pabd->uEdge = ABE_RIGHT; + } + else + { + pabd->uEdge = ABE_LEFT; + } + } + else + { + if(pabd->rc.top > nScreenHeight / 2) + { + pabd->uEdge = ABE_BOTTOM; + } + else + { + pabd->uEdge = ABE_TOP; + } + } + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barActivate +// +// Ensures that any autohide appbar has the topmost zOrder when any appbar is +// activated. +// +// ABM_ACTIVATE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barActivate(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + PostMessage( + m_hTrayWnd + ,ABP_RAISEAUTOHIDEHWND + ,(WPARAM)(*itBar)->hWnd() + ,(LPARAM)(*itBar)->uEdge() + ); + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetAutoHide +// +// Returns the HWND of the autohide appbar on the specified screen edge +// +// ABM_GETAUTOHIDEBAR +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// +LRESULT TrayService::barGetAutoHide(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + BarVector::iterator itBar = findBar( + MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), + abd.uEdge, ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + lResult = (LRESULT)(*itBar)->hWnd(); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetAutoHide +// +// Sets the specified AppBar to autohide if it already exists, otherwise +// if the specified AppBar does not exist, it creates it and sets it to as +// an overlap autohide AppBar. +// +// ABM_SETAUTOHIDEBAR +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// lParam +// +LRESULT TrayService::barSetAutoHide(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + + BarVector::iterator itBar = findBar((HWND)abd.hWnd); + BarVector::iterator itAutoHideBar = findBar( + MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), + abd.uEdge, ABS_AUTOHIDE); + + if (abd.lParam) // Set Auto Hide + { + lResult = 1; + + // Does an autohide bar already exist on this edge? + if (itAutoHideBar != m_abVector.end()) + { + // Return true if this appbar is the autohide bar. + return (itBar == itAutoHideBar); + } + + // if bar doesn't exist, create it and set it as an overlap bar + if (itBar == m_abVector.end()) + { + if (!barCreate(abd)) + { + return 0; + } + + itBar = m_abVector.end()-1; + (*itBar)->lParam((*itBar)->lParam() | ABS_OVERLAPAUTOHIDE); + } + + // set its assigned edge, and set it as an autohide bar + (*itBar)->uEdge(abd.uEdge); + (*itBar)->lParam((*itBar)->lParam() | ABS_AUTOHIDE); + } + else // Clear Auto Hide + { + // if the bar was the auto hide bar proceed + if (itBar != m_abVector.end() && itBar == itAutoHideBar) + { + lResult = 1; + + // if bar was overlap, destroy it + if ((*itBar)->IsOverLap()) + { + barDestroy(abd); + } + else + { + // otherwise clear its autohide status. + (*itBar)->lParam((*itBar)->lParam() & ~ABS_AUTOHIDE); + } + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barPosChanged +// +// Ensures that any autohide appbar has the topmost zOrder when any non autohide +// appbar's position has changed. +// +// ABM_WINDOWPOSCHANGED +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barPosChanged(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + AppBar* p; + + if (getBar((HWND)abd.hWnd, p) && !p->IsAutoHide()) + { + lResult = 1; + + BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + PostMessage( + m_hTrayWnd + ,ABP_RAISEAUTOHIDEHWND + ,(WPARAM)(*itBar)->hWnd() + ,(LPARAM)(*itBar)->uEdge() + ); + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetTaskBarState +// +// Sets the current TaskBar state (autohide, alwaysontop) +// +// ABM_SETSTATE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// lParam +// +LRESULT TrayService::barSetTaskBarState(const APPBARDATAV1& abd) +{ + return 0; + UNREFERENCED_PARAMETER(abd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyOverlapBar +// +// Helper function to barSetPos and barQueryPos +// +void TrayService::modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + // Use entire screen for default rectangle + HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(GetMonitorInfo(hMon, &mi)) + { + CopyRect(&rcDst, &mi.rcMonitor); + } + else + { + SetRect(&rcDst, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + } + + // Set the bar's extent + modifyBarExtent(rcDst, rcOrg, uEdge); + + // The bar's position is anchored at the desktop edge - so nothing to do + + // Set the bar's breadth + modifyBarBreadth(rcDst, rcOrg, uEdge); + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyNormalBar +// +// Helper function to barSetPos and barQueryPos +// +void TrayService::modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd) +{ + BarVector::const_iterator it; + AppBar* p; + bool bFound = FALSE; + + // Use entire screen for default rectangle + HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); + HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); + + if(hMonPrimary == hMon) + { + // Use only the original workarea for the default rectangle + CopyRect(&rcDst, &m_rWorkAreaDef); + } + else + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(GetMonitorInfo(hMon, &mi)) + { + CopyRect(&rcDst, &mi.rcMonitor); + } + else + { + ASSERT(FALSE); + + // Use only the original workarea for the default rectangle + CopyRect(&rcDst, &m_rWorkAreaDef); + hMon = hMonPrimary; + } + } + + // Set the bar's extent + modifyBarExtent(rcDst, rcOrg, uEdge); + + // Set the bar's position + for (it = m_abVector.begin(); it != m_abVector.end(); ++it) + { + p = *it; + + // ignore overlap bars and invalid windows and other monitors + if(!p || p->IsOverLap() || hMon != p->hMon()) + { + // do nothing + } + // if this is our appbar, mark it found and continue + else if (hWnd == p->hWnd()) + { + bFound = true; + } + // ignore bars that haven't been initialized + else if (ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) + { + // do nothing + } + // Ignore other edge appbars for the most part + else if (uEdge != p->uEdge()) + { + // Left/Right bars must resize to top/bottom bars + if (ABE_HORIZONTAL != (ABE_HORIZONTAL & uEdge) + && + ABE_HORIZONTAL == (ABE_HORIZONTAL & p->uEdge())) + { + RECT rc; // dummy + + // If our destination rectangle currently intersects + // then resize it + if (IntersectRect(&rc, &p->GetRectRef(), &rcDst)) + { + if (ABE_TOP == p->uEdge()) + { + rcDst.top = p->GetRectRef().bottom; + } + else + { + rcDst.bottom = p->GetRectRef().top; + } + } + } + } + // Keep moving the destination appbar while we are looking + // at same edge appbars before our own. Once we find our + // own, then we ignore all same edge appbars after ours. + else if (!bFound) + { + switch (uEdge) + { + case ABE_LEFT: + rcDst.left = p->GetRectRef().right; + break; + case ABE_TOP: + rcDst.top = p->GetRectRef().bottom; + break; + case ABE_RIGHT: + rcDst.right = p->GetRectRef().left; + break; + case ABE_BOTTOM: + rcDst.bottom = p->GetRectRef().top; + break; + } + } + } + + // Set the bar's breadth + modifyBarBreadth(rcDst, rcOrg, uEdge); + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyBarExtent +// +// Helper function to modifyNormalBar and modifyOverlapBar +// +void TrayService::modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + switch (uEdge) + { + case ABE_LEFT: + case ABE_RIGHT: + rcDst.top = std::max(rcDst.top, rcOrg.top); + rcDst.bottom = std::min(rcDst.bottom, rcOrg.bottom); + break; + case ABE_TOP: + case ABE_BOTTOM: + rcDst.left = std::max(rcDst.left, rcOrg.left); + rcDst.right = std::min(rcDst.right, rcOrg.right); + break; + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyBarBreadth +// +// Helper function to modifyBarNormal and modifyBarOverlap +// +void TrayService::modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + switch (uEdge) + { + case ABE_LEFT: + rcDst.right = rcDst.left + (rcOrg.right - rcOrg.left); + break; + case ABE_TOP: + rcDst.bottom = rcDst.top + (rcOrg.bottom - rcOrg.top); + break; + case ABE_RIGHT: + rcDst.left = rcDst.right - (rcOrg.right - rcOrg.left); + break; + case ABE_BOTTOM: + rcDst.top = rcDst.bottom - (rcOrg.bottom - rcOrg.top); + break; + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// adjustWorkArea +// +// Helper function to barSetPos (via ABP_NOTIFYPOSCHANGED) +// +void TrayService::adjustWorkArea(HMONITOR hMon) +{ + RECT rcWorker, rcMonitor, rcWorkArea; + + HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); + + if (hMon != hMonPrimary) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if (!GetMonitorInfo(hMon, &mi)) + { + return; + } + + CopyRect(&rcMonitor, &mi.rcMonitor); + CopyRect(&rcWorkArea, &mi.rcWork); + } + else + { + CopyRect(&rcMonitor, &m_rWorkAreaDef); // yes, we actually want this + CopyRect(&rcWorkArea, &m_rWorkAreaCur); + } + + CopyRect(&rcWorker, &rcMonitor); + + for ( + BarVector::iterator it = m_abVector.begin() + ;it != m_abVector.end() + ;++it + ) + { + AppBar* p = *it; + + if(p && !p->IsOverLap() && p->hMon() == hMon && + (ABS_CLEANRECT == (ABS_CLEANRECT & p->lParam()))) + { + if (!IsWindow(p->hWnd())) + { + continue; + } + + RECT rcBarEx; + + CopyRect(&rcBarEx, &rcMonitor); + + switch (p->uEdge()) + { + case ABE_LEFT: + rcBarEx.right = p->GetRectRef().right; + break; + case ABE_RIGHT: + rcBarEx.left = p->GetRectRef().left; + break; + case ABE_TOP: + rcBarEx.bottom = p->GetRectRef().bottom; + break; + case ABE_BOTTOM: + rcBarEx.top = p->GetRectRef().top; + break; + } + + SubtractRect(&rcWorker, &rcWorker, &rcBarEx); + } + } + + if(!EqualRect(&rcWorker, &rcWorkArea)) + { + setWorkArea(&rcWorker); + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setWorkArea +// +// Helper function for setting the specified work area +// +void TrayService::setWorkArea(LPRECT prcWorkArea) +{ + if (m_hTrayWnd) + { + m_uWorkAreaDirty++; + } + + SystemParametersInfo( + SPI_SETWORKAREA + ,1 // readjust maximized windows + ,prcWorkArea + ,0 // SPIF_SENDCHANGE - see below + ); + SendNotifyMessage( // used in place of SPIF_SENDCHANGE above to avoid lockups + HWND_BROADCAST // see http://blogs.msdn.com/oldnewthing/archive/2005/03/10/392118.aspx + ,WM_SETTINGCHANGE + ,SPI_SETWORKAREA + ,0 + ); + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ABLock +// +// Calls SHLockShared API for the specified Shell AppBar memory +// +// Returns a pointer to shared memory location for an AppBarData structure +// +PAPPBARDATAV1 TrayService::ABLock(PSHELLAPPBARDATA psad) +{ + return (PAPPBARDATAV1)SHLockShared( + psad->hSharedMemory, psad->dwSourceProcessId); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ABUnlock +// +// Calls SHUnlockShared API for the specified AppBarData* memory +// +void TrayService::ABUnLock(PAPPBARDATAV1 pabd) +{ + SHUnlockShared(pabd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// FindAppBarPredicate_hWnd +// +// Predicate for std::find_if, used by findBar variants +// Needs to be at global scope because of mingw issues +// +// Find the appbar matching the specified hWnd +// +struct FindAppBarPredicate_hWnd +{ + FindAppBarPredicate_hWnd(HWND hWnd) : + m_hWnd(hWnd) + { + // do nothing + } + FindAppBarPredicate_hWnd(const FindAppBarPredicate_hWnd& copy) : + m_hWnd(copy.m_hWnd) + { + // do nothing + } + + bool operator() (const AppBar* pab) const + { + return (pab->hWnd() == m_hWnd); + } + +private: + const HWND m_hWnd; + +private: + // Not implemented + FindAppBarPredicate_hWnd& operator=(const FindAppBarPredicate_hWnd&); +}; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// FindAppBarPredicate_MatchLParam +// +// Predicate for std::find_if, used by findBar variants +// Needs to be at global scope because of mingw issues +// +// Find the appbar on the specified edge that has a matching lParam value +// +struct FindAppBarPredicate_MatchLParam +{ + FindAppBarPredicate_MatchLParam(HMONITOR hMon, UINT uEdge, LPARAM lParam) : + m_hMon(hMon), m_uEdge(uEdge), m_lParam(lParam) + { + // do nothing + } + FindAppBarPredicate_MatchLParam(const FindAppBarPredicate_MatchLParam& copy) : + m_hMon(copy.m_hMon), m_uEdge(copy.m_uEdge), m_lParam(copy.m_lParam) + { + // do nothing + } + + bool operator() (const AppBar* pab) const + { + return (pab->hMon() == m_hMon && pab->uEdge() == m_uEdge && + m_lParam == (pab->lParam() & m_lParam)); + } + +private: + const HMONITOR m_hMon; + const UINT m_uEdge; + const LPARAM m_lParam; + +private: + // Not implemented + FindAppBarPredicate_MatchLParam& operator=(const FindAppBarPredicate_MatchLParam&); +}; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// findBar +// +// Looks up an AppBar in the AppBarList +// +BarVector::iterator TrayService::findBar(HWND hWnd) +{ + return std::find_if(m_abVector.begin(), m_abVector.end(), + FindAppBarPredicate_hWnd(hWnd)); +} +BarVector::iterator TrayService::findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam) +{ + return std::find_if(m_abVector.begin(), m_abVector.end(), + FindAppBarPredicate_MatchLParam(hMon, uEdge, lParam)); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// isBar +// +// Determines whether the HWND is associated with any current AppBar. +// +bool TrayService::isBar(HWND hWnd) +{ + return m_abVector.end() != findBar(hWnd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// getBar +// +// Looks up an BarVector iterator based on the HWND +// +// returns true if found, otherwise false. +// +bool TrayService::getBar(HWND hWnd, BarVector::iterator& itBar) +{ + bool bReturn = false; + + itBar = findBar(hWnd); + + if (itBar != m_abVector.end()) + { + bReturn = true; + } + + return bReturn; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// getBar +// +// Looks up an AppBar* based on the HWND +// +// Returns true if found, otherwise false. +// +bool TrayService::getBar(HWND hWnd, AppBar*& pBarRef) +{ + bool bReturn = false; + BarVector::iterator itBar; + + if (getBar(hWnd, itBar)) + { + pBarRef = *itBar; + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleNotification +// +// Handler for all system tray notifications +// +BOOL TrayService::HandleNotification(PSHELLTRAYDATA pstd) +{ + bool bReturn = false; + + switch (pstd->dwMessage) + { + case NIM_ADD: + bReturn = addIcon(pstd->nid); + break; + + case NIM_MODIFY: + bReturn = modifyIcon(pstd->nid); + break; + + case NIM_DELETE: + bReturn = deleteIcon(pstd->nid); + break; + + case NIM_SETFOCUS: + bReturn = setFocusIcon(pstd->nid); + break; + + case NIM_SETVERSION: + bReturn = setVersionIcon(pstd->nid); + break; + + default: + TRACE("Unknown NIM: %u", pstd->dwMessage); + break; + } + + return bReturn ? TRUE : FALSE; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// notify +// +// Notify all listeners of a systray event +// +bool TrayService::notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const +{ + return 0 != SendMessage(m_hLiteStep, LM_SYSTRAY, + dwMessage, (LPARAM)pclsnid); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// SendSystemTray +// +// Resend all icon data; systray modules will request this via LM_SYSTRAYREADY +// during their startup. +// +HWND TrayService::SendSystemTray() +{ + removeDeadIcons(); + + for (IconVector::const_iterator it = m_siVector.begin(); + it != m_siVector.end(); ++it) + { + if ((*it)->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + (*it)->CopyLSNID(&lsnid); + + notify(NIM_ADD, &lsnid); + } + } + + return m_hNotifyWnd; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// removeDeadIcons +// +// Removes all "dead" icons. ie. Those that no longer have a valid HWND +// associated with them. +// +void TrayService::removeDeadIcons() +{ + IconVector::iterator it = m_siVector.begin(); + + while (it != m_siVector.end()) + { + if (IsWindow((*it)->GetHwnd())) + { + ++it; + continue; + } + + delete *it; + it = m_siVector.erase(it); + } + + return; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// extendNIDCopy +// +// Copies all non-persistent data that is not stored in NotifyIcon. +// +bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const +{ + // Copy Info Tips + if (nid.uFlags & NIF_INFO) + { + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_5W_SIZE: + { + NID_5W* pnid = (NID_5W*)&nid; + + int nReturn; + WCHAR szTemp[256]; + + memcpy(szTemp, pnid->szInfo, sizeof(WCHAR)*256); + szTemp[255] = 0; + nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, + lsnid.szInfo, TRAY_MAX_INFO_LENGTH, NULL, NULL); + + if (!nReturn) + { + lsnid.szInfo[0] = 0; + } + + memcpy(szTemp, pnid->szInfoTitle, sizeof(WCHAR)*64); + szTemp[63] = 0; + nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, + lsnid.szInfoTitle, TRAY_MAX_INFOTITLE_LENGTH, NULL, NULL); + + if (!nReturn) + { + lsnid.szInfoTitle[0] = 0; + } + + lsnid.dwInfoFlags = pnid->dwInfoFlags; + lsnid.uTimeout = pnid->uTimeout; + lsnid.uFlags |= NIF_INFO; + } + break; + case NID_6A_SIZE: + case NID_5A_SIZE: + { + NID_5A* pnid = (NID_5A*)&nid; + + HRESULT hr; + + hr = StringCchCopy(lsnid.szInfo, + TRAY_MAX_INFO_LENGTH, pnid->szInfo); + + if (FAILED(hr)) + { + lsnid.szInfo[0] = 0; + } + + hr = StringCchCopy(lsnid.szInfoTitle, + TRAY_MAX_INFOTITLE_LENGTH, pnid->szInfoTitle); + + if (FAILED(hr)) + { + lsnid.szInfoTitle[0] = 0; + } + + lsnid.dwInfoFlags = pnid->dwInfoFlags; + lsnid.uTimeout = pnid->uTimeout; + lsnid.uFlags |= NIF_INFO; + } + break; + default: + { + // do nothing + } + break; + } + } + + // Copy GUID + if (nid.uFlags & NIF_GUID) + { + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + { + NID_6W* pnid = (NID_6W*)&nid; + + lsnid.guidItem = pnid->guidItem; + lsnid.uFlags |= NIF_GUID; + } + break; + case NID_6A_SIZE: + { + NID_6A* pnid = (NID_6A*)&nid; + + lsnid.guidItem = pnid->guidItem; + lsnid.uFlags |= NIF_GUID; + } + break; + default: + { + // do nothing + } + break; + } + } + + return true; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// addIcon +// +bool TrayService::addIcon(const NID_XX& nid) +{ + bool bReturn = false; + + if (m_siVector.end() == findIcon(nid)) + { + NotifyIcon * pni = new NotifyIcon(nid); + + if (pni) + { + // Fail shared icons, unless a valid hIcon exists + if (IsWindow(pni->GetHwnd()) && + (!pni->IsShared() || pni->HasIcon())) + { + m_siVector.push_back(pni); + + if (pni->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + pni->CopyLSNID(&lsnid); + extendNIDCopy(lsnid, nid); + + notify(NIM_ADD, &lsnid); + } + bReturn = true; + } + else + { + delete pni; + } + } + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyIcon +// +bool TrayService::modifyIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it && *it) + { + NotifyIcon * pni = *it; + + bool bWasValid = pni->IsValid(); + + // Update stored NotifyIcon + pni->Update(nid); + + if (pni->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + if (!bWasValid) + { + // This is a "new" icon, send entire stored NotifyIcon + pni->CopyLSNID(&lsnid); + extendNIDCopy(lsnid, nid); + + notify(NIM_ADD, &lsnid); + } + else + { + // This icon already exists, just send updated flags + pni->CopyLSNID(&lsnid, nid.uFlags); + extendNIDCopy(lsnid, nid); + + notify(NIM_MODIFY, &lsnid); + } + } + else if (bWasValid) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,pni->GetHwnd() + ,pni->GetuID() + ,0 + }; + + // This icon is no longer visible, remove + notify(NIM_DELETE, &lsnid); + } + + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// deleteIcon +// +// Remove an icon from the icon list +// +bool TrayService::deleteIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + notify(NIM_DELETE, &lsnid); + + delete *it; + m_siVector.erase(it); + + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setFocusIcon +// +// Sets selection focus to the specified icon +// +bool TrayService::setFocusIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + bReturn = notify(NIM_SETFOCUS, &lsnid); + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setVersionIcon +// +// Sets compatibility version for specified icon +// +bool TrayService::setVersionIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_5W_SIZE: + lsnid.uVersion = ((NID_5W&)nid).uVersion; + break; + + case NID_6A_SIZE: + case NID_5A_SIZE: + lsnid.uVersion = ((NID_5A&)nid).uVersion; + break; + + default: + break; + } + + bReturn = notify(NIM_SETVERSION, &lsnid); + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// findIcon +// +// Looks up an icon in the SystrayIconList +// +IconVector::iterator TrayService::findIcon(const NID_XX& nid) +{ + GUID guidItem; + + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + guidItem = ((NID_6W&)nid).guidItem; + break; + + case NID_6A_SIZE: + guidItem = ((NID_6A&)nid).guidItem; + break; + + default: + break; + } + + for (IconVector::iterator iter = m_siVector.begin(); iter != m_siVector.end(); iter++) + { + // If the GUID is valid, we ignore the uID and hWnd + if ((nid.uFlags & NIF_GUID) == NIF_GUID) + { + if (guidItem == (*iter)->GetGUID()) + { + return iter; + } + } + else if((*iter)->GetuID() == nid.uID && (*iter)->GetHwnd() == (HWND)nid.hWnd) + { + return iter; + } + } + + return m_siVector.end(); +} diff --git a/litestep/TrayService.h b/litestep/TrayService.h index 8ed6503..6af622a 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -1,223 +1,234 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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. -// -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#if !defined(TRAYSERVICE_H) -#define TRAYSERVICE_H - -#include "TrayNotifyIcon.h" -#include "TrayAppBar.h" -#include "../utility/common.h" -#include "../utility/IService.h" -#include -#include - -// shell copy data types -#define SH_APPBAR_DATA (0) -#define SH_TRAY_DATA (1) -#define SH_LOADPROC_DATA (2) - -// internally posted AppBar messages -#define ABP_NOTIFYPOSCHANGED (WM_USER+350) -#define ABP_NOTIFYSTATECHANGE (WM_USER+351) -#define ABP_RAISEAUTOHIDEHWND (WM_USER+360) - -// data sent by shell via Shell_NotifyIcon -typedef struct _SHELLTRAYDATA -{ - DWORD dwUnknown; - DWORD dwMessage; - NID_XX nid; -} *PSHELLTRAYDATA; - -// Data sent with AppBar Message -typedef struct _SHELLAPPBARDATA -{ - _SHELLAPPBARDATA(APPBARDATAV1& abdsrc):abd(abdsrc) - { - // do nothing - } - - const APPBARDATAV1& abd; - /**/ - DWORD dwMessage; - HANDLE hSharedMemory; - DWORD dwSourceProcessId; - /**/ - -private: - // Not implemented - _SHELLAPPBARDATA(const _SHELLAPPBARDATA&); - _SHELLAPPBARDATA& operator=(const _SHELLAPPBARDATA&); -} SHELLAPPBARDATA, *PSHELLAPPBARDATA; - - -// Data sent with SHLoadInProc/SHEnableServiceObject on XP and up -// Earlier versions don't have SHEnableServiceObject and only send the CLSID -typedef struct _SHELLINPROCDATA -{ - CLSID clsid; - DWORD dwMessage; -} SHELLINPROCDATA, *PSHELLINPROCDATA; - -typedef std::vector IconVector; -typedef std::vector BarVector; -typedef std::vector SsoVector; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// TrayService -// -// This is the tray service handler. It keeps track of all systray icons and -// loads ShellService-objects. If an icon is added/removed/modified/... it -// notifies all listeners (usually the systray module) via LM_SYSTRAY. -// -class TrayService : public IService -{ -public: - ~TrayService(); - TrayService(); - - // - // IService methods - // - virtual HRESULT Start(); - virtual HRESULT Stop(); - - // resend all icon data - HWND SendSystemTray(); - - // Notify TrayService of full screen app change - void NotifyRudeApp(HMONITOR hFullScreenMonitor) const; - - // Message Handler - static LRESULT CALLBACK WindowTrayProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK WindowNotifyProc(HWND, UINT, WPARAM, LPARAM); - -private: - HRESULT createWindows(); - void destroyWindows(); - - // - // manage COM based shell services - // - HRESULT loadShellServiceObject(REFCLSID rclsid); - void loadShellServiceObjects(); - void unloadShellServiceObjects(); - - // Handlers for AppBar messages - LRESULT HandleAppBarCopydata(DWORD cbData, LPVOID lpData); - LRESULT HandleAppBarMessage(PSHELLAPPBARDATA psad); - - // Handler for system tray notifications - BOOL HandleNotification(PSHELLTRAYDATA pstd); - - // Handler for LoadInProc messages - HRESULT HandleLoadInProc(REFCLSID clsid, DWORD dwMessage); - - // - // ABM_* Notification handlers - // - LRESULT barCreate(const APPBARDATAV1& abd); - LRESULT barDestroy(const APPBARDATAV1& abd); - LRESULT barQueryPos(PSHELLAPPBARDATA psad); - LRESULT barSetPos(PSHELLAPPBARDATA psad); - LRESULT barGetTaskBarState(); - LRESULT barGetTaskBarPos(PSHELLAPPBARDATA psad); - LRESULT barActivate(const APPBARDATAV1& abd); - LRESULT barGetAutoHide(const APPBARDATAV1& abd); - LRESULT barSetAutoHide(const APPBARDATAV1& abd); - LRESULT barPosChanged(const APPBARDATAV1& abd); - LRESULT barSetTaskBarState(const APPBARDATAV1& abd); - - // - // barSetPos and barQueryPos helpers - // - void modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd); - void modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void adjustWorkArea(HMONITOR hMon); - void setWorkArea(LPRECT prcWorkArea); - - // Remove any "dead" appbars - void removeDeadAppBars(); - - // - // AppBar Un/Lock handlers for shared data - // - PAPPBARDATAV1 ABLock(PSHELLAPPBARDATA psad); - void ABUnLock(PAPPBARDATAV1 pabd); - - // - // findBar variants and wrappers - // - BarVector::iterator findBar(HWND hWnd); - BarVector::iterator findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam); - bool isBar(HWND hWnd); - bool getBar(HWND hWnd, BarVector::iterator& itAppBar); - bool getBar(HWND hWnd, AppBar*& pBarRef); - - // - // NIM_* Notification handlers - // - bool addIcon(const NID_XX& nid); // NIM_ADD - bool modifyIcon(const NID_XX& nid); // NIM_MODIFY - bool deleteIcon(const NID_XX& nid); // NIM_DELETE - bool setFocusIcon(const NID_XX& nid); // NIM_SETFOCUS - bool setVersionIcon(const NID_XX& nid); // NIM_SETVERSION - - // - // Send icon notifications on to LiteStep (thus systray modules) - // - bool notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const; - bool extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const; - - // Remove any "dead" icons - void removeDeadIcons(); - - // - // findIcon variants - // - IconVector::iterator findIcon(HWND hWnd, UINT uId); - - inline IconVector::iterator findIcon(const NID_XX& nid) - { - return findIcon((HWND)nid.hWnd, nid.uID); - } - - // - // - // - UINT m_uWorkAreaDirty; - RECT m_rWorkAreaDef; // The Working Area without any appbars. - RECT m_rWorkAreaCur; // The Working Area with the appbars. - HWND m_hNotifyWnd; - HWND m_hTrayWnd; - HWND m_hLiteStep; - HINSTANCE m_hInstance; - - SsoVector m_ssoVector; - IconVector m_siVector; - BarVector m_abVector; -}; - -#endif // TRAYSERVICE_H +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(TRAYSERVICE_H) +#define TRAYSERVICE_H + +#include "TrayNotifyIcon.h" +#include "TrayAppBar.h" +#include "../utility/common.h" +#include "../utility/IService.h" +#include +#include + +// shell copy data types +#define SH_APPBAR_DATA (0) +#define SH_TRAY_DATA (1) +#define SH_LOADPROC_DATA (2) +#define SH_TRAYINFO_DATA (3) + +// internally posted AppBar messages +#define ABP_NOTIFYPOSCHANGED (WM_USER+350) +#define ABP_NOTIFYSTATECHANGE (WM_USER+351) +#define ABP_RAISEAUTOHIDEHWND (WM_USER+360) + +// data sent to TrayInfoEvent +typedef struct _NOTIFYICONIDENTIFIER_MSGV1 +{ + DWORD dwMagic; + DWORD dwMessage; + DWORD cbSize; + DWORD dwPadding; + HWND hWnd; + UINT uID; + GUID guidItem; +} NOTIFYICONIDENTIFIER_MSGV1, *LPNOTIFYICONIDENTIFIER_MSGV1; + +// data sent by shell via Shell_NotifyIcon +typedef struct _SHELLTRAYDATA +{ + DWORD dwUnknown; + DWORD dwMessage; + NID_XX nid; +} *PSHELLTRAYDATA; + +// Data sent with AppBar Message +typedef struct _SHELLAPPBARDATA +{ + _SHELLAPPBARDATA(APPBARDATAV1& abdsrc):abd(abdsrc) + { + // do nothing + } + + const APPBARDATAV1& abd; + /**/ + DWORD dwMessage; + HANDLE hSharedMemory; + DWORD dwSourceProcessId; + /**/ + +private: + // Not implemented + _SHELLAPPBARDATA(const _SHELLAPPBARDATA&); + _SHELLAPPBARDATA& operator=(const _SHELLAPPBARDATA&); +} SHELLAPPBARDATA, *PSHELLAPPBARDATA; + + +// Data sent with SHLoadInProc/SHEnableServiceObject on XP and up +// Earlier versions don't have SHEnableServiceObject and only send the CLSID +typedef struct _SHELLINPROCDATA +{ + CLSID clsid; + DWORD dwMessage; +} SHELLINPROCDATA, *PSHELLINPROCDATA; + +typedef std::vector IconVector; +typedef std::vector BarVector; +typedef std::vector SsoVector; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayService +// +// This is the tray service handler. It keeps track of all systray icons and +// loads ShellService-objects. If an icon is added/removed/modified/... it +// notifies all listeners (usually the systray module) via LM_SYSTRAY. +// +class TrayService : public IService +{ +public: + ~TrayService(); + TrayService(); + + // + // IService methods + // + virtual HRESULT Start(); + virtual HRESULT Stop(); + + // resend all icon data + HWND SendSystemTray(); + + // Notify TrayService of full screen app change + void NotifyRudeApp(HMONITOR hFullScreenMonitor) const; + + // Message Handler + static LRESULT CALLBACK WindowTrayProc(HWND, UINT, WPARAM, LPARAM); + static LRESULT CALLBACK WindowNotifyProc(HWND, UINT, WPARAM, LPARAM); + +private: + HRESULT createWindows(); + void destroyWindows(); + + // + // manage COM based shell services + // + HRESULT loadShellServiceObject(REFCLSID rclsid); + void loadShellServiceObjects(); + void unloadShellServiceObjects(); + + // Handlers for AppBar messages + LRESULT HandleAppBarCopydata(DWORD cbData, LPVOID lpData); + LRESULT HandleAppBarMessage(PSHELLAPPBARDATA psad); + + // Handler for tray info event + LRESULT TrayInfoEvent(DWORD cbData, LPVOID lpData); + + // Handler for system tray notifications + BOOL HandleNotification(PSHELLTRAYDATA pstd); + + // Handler for LoadInProc messages + HRESULT HandleLoadInProc(REFCLSID clsid, DWORD dwMessage); + + // + // ABM_* Notification handlers + // + LRESULT barCreate(const APPBARDATAV1& abd); + LRESULT barDestroy(const APPBARDATAV1& abd); + LRESULT barQueryPos(PSHELLAPPBARDATA psad); + LRESULT barSetPos(PSHELLAPPBARDATA psad); + LRESULT barGetTaskBarState(); + LRESULT barGetTaskBarPos(PSHELLAPPBARDATA psad); + LRESULT barActivate(const APPBARDATAV1& abd); + LRESULT barGetAutoHide(const APPBARDATAV1& abd); + LRESULT barSetAutoHide(const APPBARDATAV1& abd); + LRESULT barPosChanged(const APPBARDATAV1& abd); + LRESULT barSetTaskBarState(const APPBARDATAV1& abd); + + // + // barSetPos and barQueryPos helpers + // + void modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd); + void modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void adjustWorkArea(HMONITOR hMon); + void setWorkArea(LPRECT prcWorkArea); + + // Remove any "dead" appbars + void removeDeadAppBars(); + + // + // AppBar Un/Lock handlers for shared data + // + PAPPBARDATAV1 ABLock(PSHELLAPPBARDATA psad); + void ABUnLock(PAPPBARDATAV1 pabd); + + // + // findBar variants and wrappers + // + BarVector::iterator findBar(HWND hWnd); + BarVector::iterator findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam); + bool isBar(HWND hWnd); + bool getBar(HWND hWnd, BarVector::iterator& itAppBar); + bool getBar(HWND hWnd, AppBar*& pBarRef); + + // + // NIM_* Notification handlers + // + bool addIcon(const NID_XX& nid); // NIM_ADD + bool modifyIcon(const NID_XX& nid); // NIM_MODIFY + bool deleteIcon(const NID_XX& nid); // NIM_DELETE + bool setFocusIcon(const NID_XX& nid); // NIM_SETFOCUS + bool setVersionIcon(const NID_XX& nid); // NIM_SETVERSION + + // + // Send icon notifications on to LiteStep (thus systray modules) + // + bool notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const; + bool extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const; + + // Remove any "dead" icons + void removeDeadIcons(); + + // + // finds the icon which matches the specified nid + // + IconVector::iterator findIcon(const NID_XX& nid); + + // + // + // + UINT m_uWorkAreaDirty; + RECT m_rWorkAreaDef; // The Working Area without any appbars. + RECT m_rWorkAreaCur; // The Working Area with the appbars. + HWND m_hNotifyWnd; + HWND m_hTrayWnd; + HWND m_hLiteStep; + HINSTANCE m_hInstance; + + SsoVector m_ssoVector; + IconVector m_siVector; + BarVector m_abVector; +}; + +#endif // TRAYSERVICE_H diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index 3cb1509..ee8703c 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -1,277 +1,278 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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. -// -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#if !defined(LSAPIDEFINES_H) -#define LSAPIDEFINES_H - -/* -* IMPORTANT: -* The exports and definitions included -* with LSAPI_PRIVATE are for INTERNAL USE ONLY! -* -* They MUST NOT be used by any module. -* Their names and/or functionality may be changed at ANY time! -* -*/ - -#include "../utility/common.h" - - -//----------------------------------------------------------------------------- -// MATCH.CPP DEFINES -//----------------------------------------------------------------------------- -#define MATCH_PATTERN 6 /* bad pattern */ -#define MATCH_LITERAL 5 /* match failure on literal match */ -#define MATCH_RANGE 4 /* match failure on [..] construct */ -#define MATCH_ABORT 3 /* premature end of text string */ -#define MATCH_END 2 /* premature end of pattern string */ -#define MATCH_VALID 1 /* valid match */ - -/* pattern defines */ -#define PATTERN_VALID 0 /* valid pattern */ -#define PATTERN_ESC -1 /* literal escape at end of pattern */ -#define PATTERN_RANGE -2 /* malformed range in [..] construct */ -#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */ -#define PATTERN_EMPTY -4 /* [..] contstruct is empty */ - - -//----------------------------------------------------------------------------- -// MESSAGE DEFINES -//----------------------------------------------------------------------------- -#define LM_SHUTDOWN 8889 -#define LM_REPAINT 8890 -#define LM_BRINGTOFRONT 8891 -#define LM_SAVEDATA 8892 -#define LM_RESTOREDATA 8893 -#define LM_POPUP 9182 -#define LM_HIDEPOPUP 9183 -#define LM_FIRSTDESKTOPPAINT 9184 // Deprecated -#define LM_LSSELECT 9185 -#define LM_SETTASKBARONTOP 9186 // Deprecated -#define LM_SAVESYSTRAY 9210 // Deprecated -#define LM_RESTORESYSTRAY 9211 // Deprecated -#define LM_CHECKFORAPPBAR 9212 // Deprecated -#define LM_SENDSYSTRAY 9213 -#define LM_SYSTRAY 9214 -#define LM_SYSTRAYREADY 9215 - -// Shell Hook Messages (obsolete!) -#define LM_SHELLMESSAGE 9219 -#define LM_ACCESSSTATE 9220 -#define LM_ACTIVESHELLWIN LM_ACCESSSTATE + 1 -#define LM_APPCOMMANDX LM_ACCESSSTATE + 2 -#define LM_MINMAXWIN LM_ACCESSSTATE + 3 -#define LM_LANGUAGEX LM_ACCESSSTATE + 4 -#define LM_REDRAWX LM_ACCESSSTATE + 5 -#define LM_TASKMANX LM_ACCESSSTATE + 6 -#define LM_ACTIVEWIN LM_ACCESSSTATE + 7 -#define LM_ADDWINDOW LM_ACCESSSTATE + 8 -#define LM_REMOVEWINDOW LM_ACCESSSTATE + 9 //9229 - -#define LM_RECYCLE 9260 -#define LM_REGISTERMESSAGE 9263 -#define LM_UNREGISTERMESSAGE 9264 -#define LM_GETREVID 9265 -#define LM_UNLOADMODULE 9266 -#define LM_RELOADMODULE 9267 -#define LM_REGISTERHOOKMESSAGE 9268 // Deprecated -#define LM_UNREGISTERHOOKMESSAGE 9269 // Deprecated -#define LM_SHADETOGGLE 9300 -#define LM_REFRESH 9305 - -// Threaded Module Messages -#if defined(LSAPI_PRIVATE) -#define LM_THREAD_BANGCOMMAND 9310 -#define LM_THREADREADY 9311 -#define LM_THREADFINISHED 9312 -#endif - -// VWM Messages -#define LM_VWMUP 9350 -#define LM_VWMDOWN 9351 -#define LM_VWMLEFT 9352 -#define LM_VWMRIGHT 9353 -#define LM_VWMNAV 9354 -#define LM_SWITCHTON 9355 -#define LM_ISSTICKY 9356 -#define LM_STICK 9357 -#define LM_UNSTICK 9358 -#define LM_LISTDESKTOPS 9359 -#define LM_DESKTOPINFO 9360 -#define LM_GETDESKTOPOF 9361 - -// Core Messages -#if defined(LSAPI_PRIVATE) -#define LM_GETLSOBJECT 9400 // Deprecated -#define LM_WINDOWLIST 9401 // Deprecated -#define LM_DATASTORE 9410 // Deprecated -#define LM_MESSAGEMANAGER 9411 // Deprecated -#define LM_BANGCOMMAND 9420 -#define LM_ENUMREVIDS 9430 -#define LM_ENUMMODULES 9431 -#define LM_ENUMPERFORMANCE 9432 -#endif - - -#define LM_SHELLHOOK 9500 // not an actual message - -// shell hook messages -#define LM_WINDOWCREATED (LM_SHELLHOOK + HSHELL_WINDOWCREATED) -#define LM_WINDOWDESTROYED (LM_SHELLHOOK + HSHELL_WINDOWDESTROYED) -#define LM_ACTIVATESHELLWINDOW (LM_SHELLHOOK + HSHELL_ACTIVATESHELLWINDOW) -#define LM_WINDOWACTIVATED (LM_SHELLHOOK + HSHELL_WINDOWACTIVATED) -#define LM_GETMINRECT (LM_SHELLHOOK + HSHELL_GETMINRECT) -#define LM_REDRAW (LM_SHELLHOOK + HSHELL_REDRAW) -#define LM_TASKMAN (LM_SHELLHOOK + HSHELL_TASKMAN) -#define LM_LANGUAGE (LM_SHELLHOOK + HSHELL_LANGUAGE) -#define LM_ACCESSIBILITYSTATE (LM_SHELLHOOK + HSHELL_ACCESSIBILITYSTATE) -#define LM_APPCOMMAND (LM_SHELLHOOK + HSHELL_APPCOMMAND) +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(LSAPIDEFINES_H) +#define LSAPIDEFINES_H + +/* +* IMPORTANT: +* The exports and definitions included +* with LSAPI_PRIVATE are for INTERNAL USE ONLY! +* +* They MUST NOT be used by any module. +* Their names and/or functionality may be changed at ANY time! +* +*/ + +#include "../utility/common.h" + + +//----------------------------------------------------------------------------- +// MATCH.CPP DEFINES +//----------------------------------------------------------------------------- +#define MATCH_PATTERN 6 /* bad pattern */ +#define MATCH_LITERAL 5 /* match failure on literal match */ +#define MATCH_RANGE 4 /* match failure on [..] construct */ +#define MATCH_ABORT 3 /* premature end of text string */ +#define MATCH_END 2 /* premature end of pattern string */ +#define MATCH_VALID 1 /* valid match */ + +/* pattern defines */ +#define PATTERN_VALID 0 /* valid pattern */ +#define PATTERN_ESC -1 /* literal escape at end of pattern */ +#define PATTERN_RANGE -2 /* malformed range in [..] construct */ +#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */ +#define PATTERN_EMPTY -4 /* [..] contstruct is empty */ + + +//----------------------------------------------------------------------------- +// MESSAGE DEFINES +//----------------------------------------------------------------------------- +#define LM_SHUTDOWN 8889 +#define LM_REPAINT 8890 +#define LM_BRINGTOFRONT 8891 +#define LM_SAVEDATA 8892 +#define LM_RESTOREDATA 8893 +#define LM_POPUP 9182 +#define LM_HIDEPOPUP 9183 +#define LM_FIRSTDESKTOPPAINT 9184 // Deprecated +#define LM_LSSELECT 9185 +#define LM_SETTASKBARONTOP 9186 // Deprecated +#define LM_SAVESYSTRAY 9210 // Deprecated +#define LM_RESTORESYSTRAY 9211 // Deprecated +#define LM_CHECKFORAPPBAR 9212 // Deprecated +#define LM_SENDSYSTRAY 9213 +#define LM_SYSTRAY 9214 +#define LM_SYSTRAYREADY 9215 +#define LM_SYSTRAYINFOEVENT 9216 + +// Shell Hook Messages (obsolete!) +#define LM_SHELLMESSAGE 9219 +#define LM_ACCESSSTATE 9220 +#define LM_ACTIVESHELLWIN LM_ACCESSSTATE + 1 +#define LM_APPCOMMANDX LM_ACCESSSTATE + 2 +#define LM_MINMAXWIN LM_ACCESSSTATE + 3 +#define LM_LANGUAGEX LM_ACCESSSTATE + 4 +#define LM_REDRAWX LM_ACCESSSTATE + 5 +#define LM_TASKMANX LM_ACCESSSTATE + 6 +#define LM_ACTIVEWIN LM_ACCESSSTATE + 7 +#define LM_ADDWINDOW LM_ACCESSSTATE + 8 +#define LM_REMOVEWINDOW LM_ACCESSSTATE + 9 //9229 + +#define LM_RECYCLE 9260 +#define LM_REGISTERMESSAGE 9263 +#define LM_UNREGISTERMESSAGE 9264 +#define LM_GETREVID 9265 +#define LM_UNLOADMODULE 9266 +#define LM_RELOADMODULE 9267 +#define LM_REGISTERHOOKMESSAGE 9268 // Deprecated +#define LM_UNREGISTERHOOKMESSAGE 9269 // Deprecated +#define LM_SHADETOGGLE 9300 +#define LM_REFRESH 9305 + +// Threaded Module Messages +#if defined(LSAPI_PRIVATE) +#define LM_THREAD_BANGCOMMAND 9310 +#define LM_THREADREADY 9311 +#define LM_THREADFINISHED 9312 +#endif + +// VWM Messages +#define LM_VWMUP 9350 +#define LM_VWMDOWN 9351 +#define LM_VWMLEFT 9352 +#define LM_VWMRIGHT 9353 +#define LM_VWMNAV 9354 +#define LM_SWITCHTON 9355 +#define LM_ISSTICKY 9356 +#define LM_STICK 9357 +#define LM_UNSTICK 9358 +#define LM_LISTDESKTOPS 9359 +#define LM_DESKTOPINFO 9360 +#define LM_GETDESKTOPOF 9361 + +// Core Messages +#if defined(LSAPI_PRIVATE) +#define LM_GETLSOBJECT 9400 // Deprecated +#define LM_WINDOWLIST 9401 // Deprecated +#define LM_DATASTORE 9410 // Deprecated +#define LM_MESSAGEMANAGER 9411 // Deprecated +#define LM_BANGCOMMAND 9420 +#define LM_ENUMREVIDS 9430 +#define LM_ENUMMODULES 9431 +#define LM_ENUMPERFORMANCE 9432 +#endif + + +#define LM_SHELLHOOK 9500 // not an actual message + +// shell hook messages +#define LM_WINDOWCREATED (LM_SHELLHOOK + HSHELL_WINDOWCREATED) +#define LM_WINDOWDESTROYED (LM_SHELLHOOK + HSHELL_WINDOWDESTROYED) +#define LM_ACTIVATESHELLWINDOW (LM_SHELLHOOK + HSHELL_ACTIVATESHELLWINDOW) +#define LM_WINDOWACTIVATED (LM_SHELLHOOK + HSHELL_WINDOWACTIVATED) +#define LM_GETMINRECT (LM_SHELLHOOK + HSHELL_GETMINRECT) +#define LM_REDRAW (LM_SHELLHOOK + HSHELL_REDRAW) +#define LM_TASKMAN (LM_SHELLHOOK + HSHELL_TASKMAN) +#define LM_LANGUAGE (LM_SHELLHOOK + HSHELL_LANGUAGE) +#define LM_ACCESSIBILITYSTATE (LM_SHELLHOOK + HSHELL_ACCESSIBILITYSTATE) +#define LM_APPCOMMAND (LM_SHELLHOOK + HSHELL_APPCOMMAND) #define LM_WINDOWREPLACED (LM_SHELLHOOK + HSHELL_WINDOWREPLACED) -#define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) -#define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) - - -//----------------------------------------------------------------------------- -// CONSTANT DEFINES -//----------------------------------------------------------------------------- -#define MAX_BANGCOMMAND 64 -#define MAX_BANGARGS 256 -#define MAX_RCCOMMAND 64 -#define MAX_LINE_LENGTH 4096 -#define MAX_PATH_LENGTH 1024 - -#define WHITESPACEW L" \t\n\r" -#define WHITESPACEA " \t\n\r" - -#define RESERVEDCHARSW L"\"\'[];$" -#define RESERVEDCHARSA "\"\'[];$" - -#if defined(_UNICODE) -#define WHITESPACE WHITESPACEW -#define RESERVEDCHARS RESERVEDCHARSW -#else -#define WHITESPACE WHITESPACEA -#define RESERVEDCHARS RESERVEDCHARSA -#endif - -#define HIDEmagicDWord 0x59474541 -#define magicDWord 0x49474541 - - -//----------------------------------------------------------------------------- -// MODULE ENTRY POINTS DEFINES -//----------------------------------------------------------------------------- -typedef int (__cdecl* initModuleExProc)(HWND, HINSTANCE, LPCSTR); -typedef void (__cdecl* quitModuleProc)(HINSTANCE); - - -//----------------------------------------------------------------------------- -// BANG COMMAND DEFINES -//----------------------------------------------------------------------------- -typedef void (__cdecl *BangCommand)(HWND hSender, LPCSTR pszArgs); -typedef void (__cdecl *BangCommandEx) \ - (HWND hSender, LPCSTR pszCommand, LPCSTR pszArgs); - -typedef struct _LMBANGCOMMANDA -{ - UINT cbSize; - HWND hWnd; - CHAR szCommand[MAX_BANGCOMMAND]; - CHAR szArgs[MAX_BANGARGS]; - // -} LMBANGCOMMANDA, *PLMBANGCOMMANDA; - -typedef struct _LMBANGCOMMANDW -{ - UINT cbSize; - HWND hWnd; - WCHAR wzCommand[MAX_BANGCOMMAND]; - WCHAR wzArgs[MAX_BANGARGS]; - // -} LMBANGCOMMANDW, *PLMBANGCOMMANDW; - -#if defined(_UNICODE) -#define LMBANGCOMMAND LMBANGCOMMANDW -#define PLMBANGCOMMAND PLMBANGCOMMANDW -#else // _UNICODE -#define LMBANGCOMMAND LMBANGCOMMANDA -#define PLMBANGCOMMAND PLMBANGCOMMANDA -#endif // _UNICODE - -//----------------------------------------------------------------------------- -// VWM DEFINES -//----------------------------------------------------------------------------- -typedef struct LSDESKTOPINFO -{ - int size; - char name[32]; - HICON icon; - BOOL isCurrent; - int number; - // -} LSDESKTOPINFO; - - -//----------------------------------------------------------------------------- -// LM_RECYCLE DEFINES -//----------------------------------------------------------------------------- -#define LR_RECYCLE 0 -#define LR_LOGOFF 1 -#define LR_QUIT 2 -#define LR_MSSHUTDOWN 3 - - -//----------------------------------------------------------------------------- -// LM_UN/RELOADMODULE DEFINES -//----------------------------------------------------------------------------- -#define LMM_PATH 0x0000 -#define LMM_HINSTANCE 0x1000 - - -//----------------------------------------------------------------------------- -// LSLOG LOG LEVEL CONSTANTS -//----------------------------------------------------------------------------- -#define LOG_ERROR 1 -#define LOG_WARNING 2 -#define LOG_NOTICE 3 -#define LOG_DEBUG 4 - - -//----------------------------------------------------------------------------- -// ENUMLSDATA DEFINES -//----------------------------------------------------------------------------- -#define ELD_BANGS 1 -#define ELD_MODULES 2 -#define ELD_REVIDS 3 -#define ELD_BANGS_V2 4 -#define ELD_PERFORMANCE 5 - -// ELD_MODULES: possible dwFlags values -#define LS_MODULE_THREADED 0x0001 -// LS_MODULE_NOTPUMPED 0x0002 no longer used - -typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); -typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); - -#endif // LSAPIDEFINES_H +#define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) +#define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) + + +//----------------------------------------------------------------------------- +// CONSTANT DEFINES +//----------------------------------------------------------------------------- +#define MAX_BANGCOMMAND 64 +#define MAX_BANGARGS 256 +#define MAX_RCCOMMAND 64 +#define MAX_LINE_LENGTH 4096 +#define MAX_PATH_LENGTH 1024 + +#define WHITESPACEW L" \t\n\r" +#define WHITESPACEA " \t\n\r" + +#define RESERVEDCHARSW L"\"\'[];$" +#define RESERVEDCHARSA "\"\'[];$" + +#if defined(_UNICODE) +#define WHITESPACE WHITESPACEW +#define RESERVEDCHARS RESERVEDCHARSW +#else +#define WHITESPACE WHITESPACEA +#define RESERVEDCHARS RESERVEDCHARSA +#endif + +#define HIDEmagicDWord 0x59474541 +#define magicDWord 0x49474541 + + +//----------------------------------------------------------------------------- +// MODULE ENTRY POINTS DEFINES +//----------------------------------------------------------------------------- +typedef int (__cdecl* initModuleExProc)(HWND, HINSTANCE, LPCSTR); +typedef void (__cdecl* quitModuleProc)(HINSTANCE); + + +//----------------------------------------------------------------------------- +// BANG COMMAND DEFINES +//----------------------------------------------------------------------------- +typedef void (__cdecl *BangCommand)(HWND hSender, LPCSTR pszArgs); +typedef void (__cdecl *BangCommandEx) \ + (HWND hSender, LPCSTR pszCommand, LPCSTR pszArgs); + +typedef struct _LMBANGCOMMANDA +{ + UINT cbSize; + HWND hWnd; + CHAR szCommand[MAX_BANGCOMMAND]; + CHAR szArgs[MAX_BANGARGS]; + // +} LMBANGCOMMANDA, *PLMBANGCOMMANDA; + +typedef struct _LMBANGCOMMANDW +{ + UINT cbSize; + HWND hWnd; + WCHAR wzCommand[MAX_BANGCOMMAND]; + WCHAR wzArgs[MAX_BANGARGS]; + // +} LMBANGCOMMANDW, *PLMBANGCOMMANDW; + +#if defined(_UNICODE) +#define LMBANGCOMMAND LMBANGCOMMANDW +#define PLMBANGCOMMAND PLMBANGCOMMANDW +#else // _UNICODE +#define LMBANGCOMMAND LMBANGCOMMANDA +#define PLMBANGCOMMAND PLMBANGCOMMANDA +#endif // _UNICODE + +//----------------------------------------------------------------------------- +// VWM DEFINES +//----------------------------------------------------------------------------- +typedef struct LSDESKTOPINFO +{ + int size; + char name[32]; + HICON icon; + BOOL isCurrent; + int number; + // +} LSDESKTOPINFO; + + +//----------------------------------------------------------------------------- +// LM_RECYCLE DEFINES +//----------------------------------------------------------------------------- +#define LR_RECYCLE 0 +#define LR_LOGOFF 1 +#define LR_QUIT 2 +#define LR_MSSHUTDOWN 3 + + +//----------------------------------------------------------------------------- +// LM_UN/RELOADMODULE DEFINES +//----------------------------------------------------------------------------- +#define LMM_PATH 0x0000 +#define LMM_HINSTANCE 0x1000 + + +//----------------------------------------------------------------------------- +// LSLOG LOG LEVEL CONSTANTS +//----------------------------------------------------------------------------- +#define LOG_ERROR 1 +#define LOG_WARNING 2 +#define LOG_NOTICE 3 +#define LOG_DEBUG 4 + + +//----------------------------------------------------------------------------- +// ENUMLSDATA DEFINES +//----------------------------------------------------------------------------- +#define ELD_BANGS 1 +#define ELD_MODULES 2 +#define ELD_REVIDS 3 +#define ELD_BANGS_V2 4 +#define ELD_PERFORMANCE 5 + +// ELD_MODULES: possible dwFlags values +#define LS_MODULE_THREADED 0x0001 +// LS_MODULE_NOTPUMPED 0x0002 no longer used + +typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); + +#endif // LSAPIDEFINES_H From 777006a43b1d9aa4cef9b4632a598c4c6ed54457 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 17:09:30 -0700 Subject: [PATCH 17/50] Changed some years and added special build notices. --- litestep/litestep.rc | 4 ++-- lsapi/aboutbox.cpp | 3 ++- lsapi/lsapi.rc | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/litestep/litestep.rc b/litestep/litestep.rc index 4eb04e3..735253d 100644 --- a/litestep/litestep.rc +++ b/litestep/litestep.rc @@ -150,11 +150,11 @@ BEGIN VALUE "FileDescription", "LiteStep" VALUE "FileVersion", "0.25.0 Alpha" VALUE "InternalName", "LiteStep Core" - VALUE "LegalCopyright", "Copyright © 1997 - 2011" + VALUE "LegalCopyright", "Copyright © 1997 - 2012" VALUE "OriginalFilename", "litestep.exe" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" - VALUE "SpecialBuild", "CVS HEAD Test Release" + VALUE "SpecialBuild", "alur's windows 8/x64 branch" END END BLOCK "VarFileInfo" diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 863df2e..848f250 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -98,6 +98,7 @@ struct TheDevTeam static const g_theDevTeam[] = \ { { "Acidfire", "Alexander Vermaat" } + ,{ "alur", "Erik Welander" } ,{ "ilmcuts", "Simon" } ,{ "jugg", "Chris Rempel" } ,{ "Maduin", "Kevin Schaffer" } @@ -115,7 +116,7 @@ static const CHAR g_szLicense[] = \ "LiteStep is a replacement shell for the standard Windows® Explorer shell.\r\n" "\r\n" "Copyright (C) 1997-1998 Francis Gastellu\r\n" - "Copyright (C) 1998-2011 LiteStep Development Team\r\n" + "Copyright (C) 1998-2012 LiteStep Development Team\r\n" "\r\n" "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 " diff --git a/lsapi/lsapi.rc b/lsapi/lsapi.rc index f3386c1..bb1ea41 100644 --- a/lsapi/lsapi.rc +++ b/lsapi/lsapi.rc @@ -48,11 +48,11 @@ BEGIN VALUE "FileDescription", "LiteStep Module API" VALUE "FileVersion", "0.25.0 Alpha" VALUE "InternalName", "LiteStep API" - VALUE "LegalCopyright", "Copyright © 1997 - 2011" + VALUE "LegalCopyright", "Copyright © 1997 - 2012" VALUE "OriginalFilename", "lsapi.dll" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" - VALUE "SpecialBuild", "CVS HEAD Test Release" + VALUE "SpecialBuild", "alur's windows 8/x64 branch" END END BLOCK "VarFileInfo" From 25236902962f3a3e2ebd4cf3ab63cadb87378793 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 17:14:13 -0700 Subject: [PATCH 18/50] Fixed inconsistent line endings --- litestep/TrayService.cpp | 4632 +++++++++++++++++++------------------- litestep/TrayService.h | 468 ++-- lsapi/lsapidefines.h | 556 ++--- 3 files changed, 2828 insertions(+), 2828 deletions(-) diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 5062db7..5d05511 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -1,2316 +1,2316 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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 "TrayService.h" -#include "../utility/core.hpp" -#include -#include -#include - - -#if !defined(REGSTR_PATH_SHELLSERVICEOBJECTDELAYED) -#define REGSTR_PATH_SHELLSERVICEOBJECTDELAYED \ - _T("Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad") -#endif - -static const TCHAR szTrayClass[] = _T("Shell_TrayWnd"); -static const TCHAR szTrayTitle[] = _T("LiteStep Tray Manager"); -static const TCHAR szNotifyClass[] = _T("TrayNotifyWnd"); - - -// -// CLSID_SysTrayObject - {35CEC8A3-2BE6-11D2-8773-92E220524153} -// -// This appears to be the SSO responsible for starting up all other "approved" -// SSOs on Vista. Name derived from "stobject.dll". -// -const GUID CLSID_SysTrayObject = \ -{0x35CEC8A3, 0x2BE6, 0x11D2, {0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53}}; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// TrayService -// -TrayService::TrayService() : -m_uWorkAreaDirty(0), m_hNotifyWnd(NULL), m_hTrayWnd(NULL), -m_hLiteStep(NULL), m_hInstance(NULL) -{ - // do nothing -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ~TrayService -// -TrayService::~TrayService() -{ - // do nothing -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// Start() -// -HRESULT TrayService::Start() -{ - ASSERT(NULL == m_hTrayWnd); - HRESULT hr = E_FAIL; - - m_hLiteStep = GetLitestepWnd(); - m_hInstance = GetModuleHandle(NULL); - - if (m_hLiteStep && m_hInstance) - { - // clear work area of primary monitor - SetRect(&m_rWorkAreaDef, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - setWorkArea(&m_rWorkAreaDef); - CopyRect(&m_rWorkAreaCur, &m_rWorkAreaDef); - - hr = createWindows(); - - if (SUCCEEDED(hr)) - { - SetWindowLongPtr(m_hTrayWnd, GWLP_USERDATA, magicDWord); - SetWindowLongPtr(m_hTrayWnd, 0, (LONG_PTR)this); - - // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1427677&SiteID=1 - // - // Re: TaskbarCreated message (not working in Vista) - // - // > The code is still in there to broadcast the message. - // > SendNotifyMessage(HWND_BROADCAST, - // > RegisterWindowMessage(TEXT("TaskbarCreated")), 0, 0); - // - // >> It looks as though applications running as admin cannot - // >> receive the message. Presumably, this is because Explorer, - // >> which publishes the message, is not running as admin - // - // >>> The message is blocked by User Interface Privilege - // >>> Isolation, Administrative applications that need to see it - // >>> can allow it through by calling ChangeWindowMessageFilter - // >>> after making sure the necessary security precautions are in - // >>> place. - - // tell apps to reregister their icons - SendNotifyMessage(HWND_BROADCAST, - RegisterWindowMessage(_T("TaskbarCreated")), 0, 0); - - if (IsVistaOrAbove()) - { - // On Vista and up there's a single SSO responsible for loading - // all the supported objects (volume icon, network icon, etc.) - loadShellServiceObject(CLSID_SysTrayObject); - } - else if (IsOS(OS_WIN2000ORGREATER)) - { - // On previous versions the object list is in the registry - loadShellServiceObjects(); - } - } - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// Stop() -// -HRESULT TrayService::Stop() -{ - HRESULT hr = S_OK; - - unloadShellServiceObjects(); - destroyWindows(); - - while (!m_siVector.empty()) - { - delete m_siVector.back(); - m_siVector.pop_back(); - } - - while (!m_abVector.empty()) - { - delete m_abVector.back(); - m_abVector.pop_back(); - } - - // clear the work area of primary monitor - SetRect(&m_rWorkAreaDef, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - setWorkArea(&m_rWorkAreaDef); - - m_hLiteStep = NULL; - m_hInstance = NULL; - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// createWindows -// -HRESULT TrayService::createWindows() -{ - HRESULT hr = E_FAIL; - - // - // Register tray window class - // - WNDCLASSEX wc = { 0 }; - wc.cbSize = sizeof(WNDCLASSEX); - wc.cbWndExtra = sizeof(TrayService*); - wc.lpfnWndProc = TrayService::WindowTrayProc; - wc.hInstance = m_hInstance; - wc.lpszClassName = szTrayClass; - wc.style = CS_DBLCLKS; - - if (!RegisterClassEx(&wc)) - { - hr = HrGetLastError(); - } - else - { - // - // Window which receives the tray messages - // - m_hTrayWnd = CreateWindowEx( - WS_EX_TOPMOST | WS_EX_TOOLWINDOW, - szTrayClass, szTrayTitle, - WS_POPUP, - 0, 0, 0, 0, - NULL, NULL, - m_hInstance, - NULL); - - if (NULL == m_hTrayWnd) - { - hr = HrGetLastError(); - UnregisterClass(szTrayClass, m_hInstance); - } - else - { - // Our main window is enough to start up, we can do without the - // TrayNotifyWnd if necessary. - hr = S_OK; - - // - // Register "TrayNotifyWnd" class and create window - // - ZeroMemory(&wc, sizeof(wc)); - wc.cbSize = sizeof(WNDCLASSEX); - wc.lpfnWndProc = TrayService::WindowNotifyProc; - wc.hInstance = m_hInstance; - wc.lpszClassName = szNotifyClass; - wc.style = CS_DBLCLKS; - - if (RegisterClassEx(&wc)) - { - m_hNotifyWnd = CreateWindowEx( - 0, - szNotifyClass, NULL, - WS_CHILD, - 0, 0, 0, 0, - m_hTrayWnd, NULL, - m_hInstance, - NULL); - - if (!m_hNotifyWnd) - { - UnregisterClass(szNotifyClass, m_hInstance); - } - } - } - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// destroyWindows -// -void TrayService::destroyWindows() -{ - if (m_hNotifyWnd) - { - DestroyWindow(m_hNotifyWnd); - m_hNotifyWnd = NULL; - - UnregisterClass(szNotifyClass, m_hInstance); - } - - if (m_hTrayWnd) - { - DestroyWindow(m_hTrayWnd); - m_hTrayWnd = NULL; - - UnregisterClass(szTrayClass, m_hInstance); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// loadShellServiceObject -// -HRESULT TrayService::loadShellServiceObject(REFCLSID rclsid) -{ -#if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; - CLSIDToString(rclsid, szBuffer, COUNTOF(szBuffer)); - - TRACE("loadShellServiceObject(\"%s\")", szBuffer); -#endif - - // The SSO might have a custom manifest. - // Activate it before loading the object. - ULONG_PTR ulCookie; - HANDLE hContext = LSActivateActCtxForClsid(rclsid, &ulCookie); - - IOleCommandTarget* pCmdTarget = NULL; - - HRESULT hr = CoCreateInstance(rclsid, NULL, - CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, - IID_IOleCommandTarget, (void **)&pCmdTarget); - - if (SUCCEEDED(hr)) - { - hr = pCmdTarget->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, - OLECMDEXECOPT_DODEFAULT, NULL, NULL); - - m_ssoVector.push_back(pCmdTarget); - } - - if (hContext != INVALID_HANDLE_VALUE) - { - LSDeactivateActCtx(hContext, &ulCookie); - } - - return hr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// loadShellServiceObjects -// -// Start the COM based shell services listed in the registry. -// -void TrayService::loadShellServiceObjects() -{ - HKEY hkeyServices; - int nCounter = 0; - - LONG lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, - 0, KEY_READ, &hkeyServices); - - while (lErrorCode == ERROR_SUCCESS) - { - TCHAR szValueName[32] = { 0 }; - char szData[40] = { 0 }; - DWORD cchValueName = sizeof(szValueName) / sizeof(szValueName[0]); - DWORD cbData = sizeof(szData); - DWORD dwDataType; - - lErrorCode = RegEnumValue(hkeyServices, nCounter, szValueName, - &cchValueName, NULL, &dwDataType, (LPBYTE)szData, &cbData); - - if (lErrorCode == ERROR_SUCCESS) - { - WCHAR wszCLSID[40] = { 0 }; - CLSID clsid = CLSID_NULL; - - MultiByteToWideChar(CP_ACP, 0, szData, cbData, wszCLSID, 40); - CLSIDFromString(wszCLSID, &clsid); - - loadShellServiceObject(clsid); - } - - ++nCounter; - } - - RegCloseKey(hkeyServices); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// unloadShellServiceObjects -// -// Shut down the COM based shell services. -// -// -void TrayService::unloadShellServiceObjects() -{ - while (!m_ssoVector.empty()) - { - m_ssoVector.back()->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, - OLECMDEXECOPT_DODEFAULT, NULL, NULL); - - m_ssoVector.back()->Release(); - m_ssoVector.pop_back(); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// WindowTrayProc -// -// Redirects all messages to the appropriate handler -// -LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, - WPARAM wParam, LPARAM lParam) -{ - static TrayService* pTrayService = NULL; - - if (!pTrayService) - { - pTrayService = (TrayService*)GetWindowLongPtr(hWnd, 0); - } - - if (pTrayService) - { - LRESULT lResult = 0; - - switch (uMsg) - { - case WM_COPYDATA: - { - // - // Undocumented: This is how we can make our own system tray - // and handle app bar windows. Once a window in the system has - // the "Shell_TrayWnd" class name, it receives this message! - // - COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam; - - switch (pcds->dwData) - { - case SH_APPBAR_DATA: - { - // - // Application Bar Message - // - lResult = pTrayService->HandleAppBarCopydata( - pcds->cbData, pcds->lpData); - } - break; - - case SH_TRAY_DATA: - { - // - // System Tray Notification - // - PSHELLTRAYDATA pstd = (PSHELLTRAYDATA)pcds->lpData; - - lResult = (LRESULT)pTrayService->HandleNotification(pstd); - } - break; - - case SH_LOADPROC_DATA: - { - // - // LoadInProc messages - // - if (pcds->cbData == sizeof(CLSID)) - { - // Classic SHLoadInProc message - lResult = pTrayService->HandleLoadInProc( - (REFCLSID)pcds->lpData, 1); - } - else if (pcds->cbData == sizeof(SHELLINPROCDATA)) - { - PSHELLINPROCDATA pipd = (PSHELLINPROCDATA)pcds->lpData; - - lResult = pTrayService->HandleLoadInProc( - pipd->clsid, pipd->dwMessage); - } - else - { - TRACE("Unknown SHLoadInProc size: %u", pcds->cbData); - lResult = E_NOTIMPL; - } - } - break; - case SH_TRAYINFO_DATA: - { - lResult = pTrayService->TrayInfoEvent(pcds->cbData, pcds->lpData); - } - break; - - default: - { - TRACE("Unsupported tray message: %u", pcds->dwData); - } - break; - } - } - break; - - case ABP_NOTIFYPOSCHANGED: - { - const BarVector abTempV = pTrayService->m_abVector; - BarVector::const_reverse_iterator rit; - - HMONITOR hMon = (HMONITOR)lParam; - HWND hSkip = (HWND)wParam; - AppBar* p = NULL; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - if (hSkip != (*rit)->hWnd()) - { - if((*rit)->hMon() == hMon && - (!p || p->uEdge() != (*rit)->uEdge())) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_POSCHANGED - ,0 - ); - } - } - else - { - p = *rit; - } - } - - pTrayService->adjustWorkArea(hMon); - } - break; - - case ABP_NOTIFYSTATECHANGE: - { - const BarVector abTempV = pTrayService->m_abVector; - BarVector::const_reverse_iterator rit; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - if (!(*rit)->IsOverLap()) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_STATECHANGE - ,0 - ); - } - } - } - break; - - case ABP_RAISEAUTOHIDEHWND: - { - HWND hRaise = (HWND)wParam; - //UINT uEdge = (UINT)lParam; - - SetWindowPos( - hRaise, HWND_TOP - ,0,0,0,0 - ,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER - ); - } - break; - - case WM_SETTINGCHANGE: - { - TRACE("WM_SETTINGCHANGE(%.4X, \"%s\")", - wParam, (LPCTSTR)lParam); - - if (SPI_SETWORKAREA == wParam) - { - RECT rc; - - SystemParametersInfo( - SPI_GETWORKAREA - ,0 - ,&rc - ,0 - ); - - // Always update the Current workarea - CopyRect(&pTrayService->m_rWorkAreaCur, &rc); - - // This will be the case when we updated the workarea - // ourselves. - if (pTrayService->m_uWorkAreaDirty) - { - --pTrayService->m_uWorkAreaDirty; - break; - } - - // Only update the Default workarea when set externally. - CopyRect(&pTrayService->m_rWorkAreaDef, &rc); - - // Clean up any dead app bars before repositioning - pTrayService->removeDeadAppBars(); - - // Now reposition our appbars based on the new default - // workarea. - PostMessage( - pTrayService->m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)NULL - ,(LPARAM)MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY) - ); - } - } - break; - - default: - if (uMsg >= WM_USER) - { - DbgTraceWindowMessage("Shell_TrayWnd", uMsg, wParam, lParam); - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return lResult; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// WindowNotifyProc -// -// Redirects all messages to the appropriate handler -// -LRESULT CALLBACK TrayService::WindowNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleLoadInProc -// -// Handler for SHLoadInProc and SHEnableServiceObject (where available) -// -HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) -{ -#if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; - CLSIDToString(clsid, szBuffer, COUNTOF(szBuffer)); - - if (dwMessage == 1) - { - TRACE("SHLoadInProc(\"%s\")", szBuffer); - } - else if (dwMessage == 2) - { - TRACE("SHEnableServiceObject(\"%s\", FALSE)", szBuffer); - } - else if (dwMessage == 3) - { - TRACE("SHEnableServiceObject(\"%s\", TRUE)", szBuffer); - } - else - { - TRACE("Unknown LoadInProc message: %u", dwMessage); - } -#else - UNREFERENCED_PARAMETER(clsid); - UNREFERENCED_PARAMETER(dwMessage); -#endif - - // This is not actually implemented - return E_NOTIMPL; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// TrayInfoEvent -// -// Handles tray info events -// -LRESULT TrayService::TrayInfoEvent(DWORD /* cbData */, LPVOID lpData) // size, data -{ - LRESULT lr = 0; - LPNOTIFYICONIDENTIFIER_MSGV1 s = (LPNOTIFYICONIDENTIFIER_MSGV1)lpData; - - // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. - - if (s->dwMessage == 2) // Icon size? - { - return MAKELONG(16,16); - } - - POINT p; - GetCursorPos(&p); - - if (s->dwMessage == 1) // Icon position - { - return MAKELPARAM(p.x, p.y); - } - - return lr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleAppBarCopydata -// -LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) -{ - LRESULT lr = 0; - - switch (cbData) - { - case sizeof(APPBARMSGDATAV3): - { - PAPPBARMSGDATAV3 pamd = (PAPPBARMSGDATAV3)lpData; - - if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) - { - TRACE("PAPPBARMSGDATAV3 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - case sizeof(APPBARMSGDATAV2): - { - PAPPBARMSGDATAV2 pamd = (PAPPBARMSGDATAV2)lpData; - - if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) - { - TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - case sizeof(APPBARMSGDATAV1): - { - PAPPBARMSGDATAV1 pamd = (PAPPBARMSGDATAV1)lpData; - - if (sizeof(APPBARDATAV1) != pamd->abd.cbSize) - { - TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u", pamd->abd.cbSize); - - break; - } - - SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); - sbd.dwMessage = pamd->dwMessage; - sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; - sbd.dwSourceProcessId = pamd->dwSourceProcessId; - - lr = HandleAppBarMessage(&sbd); - } - break; - - default: - { - TRACE("Unknown APPBARMSGDATA size: %u", cbData); - } - break; - } - - return lr; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleAppBarMessage -// -// Handler for all AppBar Messages -// -LRESULT TrayService::HandleAppBarMessage(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - - removeDeadAppBars(); - - TRACE("SHAppBarMessage(%u, ...)", psad->dwMessage); - - switch(psad->dwMessage) - { - case ABM_NEW: - lResult = barCreate(psad->abd); - break; - - case ABM_REMOVE: - lResult = barDestroy(psad->abd); - break; - - case ABM_QUERYPOS: - lResult = barQueryPos(psad); - break; - - case ABM_SETPOS: - lResult = barSetPos(psad); - break; - - case ABM_GETSTATE: - lResult = barGetTaskBarState(); - break; - - case ABM_GETTASKBARPOS: - lResult = barGetTaskBarPos(psad); - break; - - case ABM_ACTIVATE: - lResult = barActivate(psad->abd); - break; - - case ABM_GETAUTOHIDEBAR: - lResult = barGetAutoHide(psad->abd); - break; - - case ABM_SETAUTOHIDEBAR: - lResult = barSetAutoHide(psad->abd); - break; - - case ABM_WINDOWPOSCHANGED: - lResult = barPosChanged(psad->abd); - break; - - case ABM_SETSTATE: - lResult = barSetTaskBarState(psad->abd); - break; - - default: - TRACE("ABM unknown: %u", psad->dwMessage); - break; - } - - return lResult; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// NotifyRudeApp -// -// External interface to let us know a window has gone/left full screen mode -// -void TrayService::NotifyRudeApp(HMONITOR hFullScreenMonitor) const -{ - const BarVector abTempV = m_abVector; - BarVector::const_reverse_iterator rit; - - for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) - { - SendMessage( - (*rit)->hWnd() - ,(*rit)->uMsg() - ,ABN_FULLSCREENAPP - ,(LPARAM)(hFullScreenMonitor ? 1 : 0) - ); - } -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// removeDeadAppBars -// -// Removes all "dead" appBars. ie. Those that no longer have a valid HWND -// associated with them. -// -void TrayService::removeDeadAppBars() -{ - BarVector::iterator it = m_abVector.begin(); - - while (it != m_abVector.end()) - { - if (IsWindow((*it)->hWnd())) - { - ++it; - continue; - } - - delete *it; - it = m_abVector.erase(it); - } - - return; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barCreate -// -// Creates a new AppBar. -// -// ABM_NEW -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uCallbackMessage -// -LRESULT TrayService::barCreate(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - - if (IsWindow((HWND)abd.hWnd) && !isBar((HWND)abd.hWnd)) - { - m_abVector.push_back(new AppBar((HWND)abd.hWnd, abd.uCallbackMessage)); - lResult = 1; - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barDestroy -// -// Removes the specified AppBar. -// -// ABM_REMOVE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barDestroy(const APPBARDATAV1& abd) -{ - BarVector::iterator itBar; - LRESULT lResult = 0; - - if (getBar((HWND)abd.hWnd, itBar)) - { - lResult = 1; - - HMONITOR hMon = (*itBar)->hMon(); - - delete *itBar; - m_abVector.erase(itBar); - - PostMessage( - m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)NULL - ,(LPARAM)hMon - ); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barQueryPos -// -// Queries for an acceptable position for the specified appbar -// -// ABM_QUERYPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// rc -// -LRESULT TrayService::barQueryPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - const APPBARDATAV1& abd = psad->abd; - - if (pabd) - { - AppBar* p; - - if (getBar((HWND)abd.hWnd, p)) - { - lResult = 1; - - if (p->IsOverLap()) - { - modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); - } - else - { - modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); - } - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetPos -// -// Sets the position of the specified appbar -// -// ABM_SETPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// rc -// -LRESULT TrayService::barSetPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - const APPBARDATAV1& abd = psad->abd; - - if (pabd) - { - AppBar* p; - - if (getBar((HWND)abd.hWnd, p)) - { - lResult = 1; - - if (p->IsOverLap()) - { - modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); - } - else - { - modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); - - // If this is the first time to position the bar or if - // the new position is different than the previous, then - // notify all other appbars. - if ((ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) - || !EqualRect(&p->GetRectRef(), &pabd->rc)) - { - // Notify other bars - PostMessage( - m_hTrayWnd - ,ABP_NOTIFYPOSCHANGED - ,(WPARAM)abd.hWnd - ,(LPARAM)MonitorFromRect(&pabd->rc, MONITOR_DEFAULTTOPRIMARY) - ); - } - } - - // Update the appbar stored parameters - CopyRect(&p->GetRectRef(), &pabd->rc); - p->lParam(p->lParam() | ABS_CLEANRECT); - p->uEdge(abd.uEdge); - p->hMon(MonitorFromRect(&p->GetRectRef(), MONITOR_DEFAULTTOPRIMARY)); - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetTaskBarState -// -// Returns the current TaskBar state (autohide, alwaysontop) -// -// ABM_GETSTATE -// -// Valid APPBARDATA members: -// -// cbSize -// -LRESULT TrayService::barGetTaskBarState() -{ - // Zero means neither always-on-top nor autohide, - // which is the safest guess for most LS setups - return 0; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetTaskBarPos -// -// Gets the current TaskBar position -// -// ABM_GETTASKBARPOS -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge (undocumented) -// -LRESULT TrayService::barGetTaskBarPos(PSHELLAPPBARDATA psad) -{ - LRESULT lResult = 0; - PAPPBARDATAV1 pabd = ABLock(psad); - - if (pabd) - { - if (GetWindowRect(m_hNotifyWnd, &pabd->rc)) - { - lResult = 1; - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(!GetMonitorInfo(MonitorFromWindow(m_hNotifyWnd, MONITOR_DEFAULTTOPRIMARY), &mi)) - { - SetRect(&mi.rcMonitor, 0, 0, - GetSystemMetrics(SM_CXSCREEN), - GetSystemMetrics(SM_CYSCREEN)); - } - - INT nHeight, nWidth, nScreenHeight, nScreenWidth; - - nHeight = pabd->rc.bottom - pabd->rc.top; - nWidth = pabd->rc.right - pabd->rc.left; - - nScreenHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; - nScreenWidth = mi.rcMonitor.right - mi.rcMonitor.left; - - if(nHeight > nWidth) - { - if(pabd->rc.left > nScreenWidth / 2) - { - pabd->uEdge = ABE_RIGHT; - } - else - { - pabd->uEdge = ABE_LEFT; - } - } - else - { - if(pabd->rc.top > nScreenHeight / 2) - { - pabd->uEdge = ABE_BOTTOM; - } - else - { - pabd->uEdge = ABE_TOP; - } - } - } - - ABUnLock(pabd); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barActivate -// -// Ensures that any autohide appbar has the topmost zOrder when any appbar is -// activated. -// -// ABM_ACTIVATE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barActivate(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - AppBar* p; - - if (getBar((HWND)abd.hWnd, p)) - { - lResult = 1; - - BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - PostMessage( - m_hTrayWnd - ,ABP_RAISEAUTOHIDEHWND - ,(WPARAM)(*itBar)->hWnd() - ,(LPARAM)(*itBar)->uEdge() - ); - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barGetAutoHide -// -// Returns the HWND of the autohide appbar on the specified screen edge -// -// ABM_GETAUTOHIDEBAR -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// -LRESULT TrayService::barGetAutoHide(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - BarVector::iterator itBar = findBar( - MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), - abd.uEdge, ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - lResult = (LRESULT)(*itBar)->hWnd(); - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetAutoHide -// -// Sets the specified AppBar to autohide if it already exists, otherwise -// if the specified AppBar does not exist, it creates it and sets it to as -// an overlap autohide AppBar. -// -// ABM_SETAUTOHIDEBAR -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// uEdge -// lParam -// -LRESULT TrayService::barSetAutoHide(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - - BarVector::iterator itBar = findBar((HWND)abd.hWnd); - BarVector::iterator itAutoHideBar = findBar( - MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), - abd.uEdge, ABS_AUTOHIDE); - - if (abd.lParam) // Set Auto Hide - { - lResult = 1; - - // Does an autohide bar already exist on this edge? - if (itAutoHideBar != m_abVector.end()) - { - // Return true if this appbar is the autohide bar. - return (itBar == itAutoHideBar); - } - - // if bar doesn't exist, create it and set it as an overlap bar - if (itBar == m_abVector.end()) - { - if (!barCreate(abd)) - { - return 0; - } - - itBar = m_abVector.end()-1; - (*itBar)->lParam((*itBar)->lParam() | ABS_OVERLAPAUTOHIDE); - } - - // set its assigned edge, and set it as an autohide bar - (*itBar)->uEdge(abd.uEdge); - (*itBar)->lParam((*itBar)->lParam() | ABS_AUTOHIDE); - } - else // Clear Auto Hide - { - // if the bar was the auto hide bar proceed - if (itBar != m_abVector.end() && itBar == itAutoHideBar) - { - lResult = 1; - - // if bar was overlap, destroy it - if ((*itBar)->IsOverLap()) - { - barDestroy(abd); - } - else - { - // otherwise clear its autohide status. - (*itBar)->lParam((*itBar)->lParam() & ~ABS_AUTOHIDE); - } - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barPosChanged -// -// Ensures that any autohide appbar has the topmost zOrder when any non autohide -// appbar's position has changed. -// -// ABM_WINDOWPOSCHANGED -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// -LRESULT TrayService::barPosChanged(const APPBARDATAV1& abd) -{ - LRESULT lResult = 0; - AppBar* p; - - if (getBar((HWND)abd.hWnd, p) && !p->IsAutoHide()) - { - lResult = 1; - - BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); - - if (itBar != m_abVector.end()) - { - PostMessage( - m_hTrayWnd - ,ABP_RAISEAUTOHIDEHWND - ,(WPARAM)(*itBar)->hWnd() - ,(LPARAM)(*itBar)->uEdge() - ); - } - } - - return lResult; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// barSetTaskBarState -// -// Sets the current TaskBar state (autohide, alwaysontop) -// -// ABM_SETSTATE -// -// Valid APPBARDATA members: -// -// cbSize -// hWnd -// lParam -// -LRESULT TrayService::barSetTaskBarState(const APPBARDATAV1& abd) -{ - return 0; - UNREFERENCED_PARAMETER(abd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyOverlapBar -// -// Helper function to barSetPos and barQueryPos -// -void TrayService::modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - // Use entire screen for default rectangle - HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); - - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(GetMonitorInfo(hMon, &mi)) - { - CopyRect(&rcDst, &mi.rcMonitor); - } - else - { - SetRect(&rcDst, - 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - } - - // Set the bar's extent - modifyBarExtent(rcDst, rcOrg, uEdge); - - // The bar's position is anchored at the desktop edge - so nothing to do - - // Set the bar's breadth - modifyBarBreadth(rcDst, rcOrg, uEdge); - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyNormalBar -// -// Helper function to barSetPos and barQueryPos -// -void TrayService::modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd) -{ - BarVector::const_iterator it; - AppBar* p; - bool bFound = FALSE; - - // Use entire screen for default rectangle - HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); - HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); - - if(hMonPrimary == hMon) - { - // Use only the original workarea for the default rectangle - CopyRect(&rcDst, &m_rWorkAreaDef); - } - else - { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if(GetMonitorInfo(hMon, &mi)) - { - CopyRect(&rcDst, &mi.rcMonitor); - } - else - { - ASSERT(FALSE); - - // Use only the original workarea for the default rectangle - CopyRect(&rcDst, &m_rWorkAreaDef); - hMon = hMonPrimary; - } - } - - // Set the bar's extent - modifyBarExtent(rcDst, rcOrg, uEdge); - - // Set the bar's position - for (it = m_abVector.begin(); it != m_abVector.end(); ++it) - { - p = *it; - - // ignore overlap bars and invalid windows and other monitors - if(!p || p->IsOverLap() || hMon != p->hMon()) - { - // do nothing - } - // if this is our appbar, mark it found and continue - else if (hWnd == p->hWnd()) - { - bFound = true; - } - // ignore bars that haven't been initialized - else if (ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) - { - // do nothing - } - // Ignore other edge appbars for the most part - else if (uEdge != p->uEdge()) - { - // Left/Right bars must resize to top/bottom bars - if (ABE_HORIZONTAL != (ABE_HORIZONTAL & uEdge) - && - ABE_HORIZONTAL == (ABE_HORIZONTAL & p->uEdge())) - { - RECT rc; // dummy - - // If our destination rectangle currently intersects - // then resize it - if (IntersectRect(&rc, &p->GetRectRef(), &rcDst)) - { - if (ABE_TOP == p->uEdge()) - { - rcDst.top = p->GetRectRef().bottom; - } - else - { - rcDst.bottom = p->GetRectRef().top; - } - } - } - } - // Keep moving the destination appbar while we are looking - // at same edge appbars before our own. Once we find our - // own, then we ignore all same edge appbars after ours. - else if (!bFound) - { - switch (uEdge) - { - case ABE_LEFT: - rcDst.left = p->GetRectRef().right; - break; - case ABE_TOP: - rcDst.top = p->GetRectRef().bottom; - break; - case ABE_RIGHT: - rcDst.right = p->GetRectRef().left; - break; - case ABE_BOTTOM: - rcDst.bottom = p->GetRectRef().top; - break; - } - } - } - - // Set the bar's breadth - modifyBarBreadth(rcDst, rcOrg, uEdge); - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyBarExtent -// -// Helper function to modifyNormalBar and modifyOverlapBar -// -void TrayService::modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - switch (uEdge) - { - case ABE_LEFT: - case ABE_RIGHT: - rcDst.top = std::max(rcDst.top, rcOrg.top); - rcDst.bottom = std::min(rcDst.bottom, rcOrg.bottom); - break; - case ABE_TOP: - case ABE_BOTTOM: - rcDst.left = std::max(rcDst.left, rcOrg.left); - rcDst.right = std::min(rcDst.right, rcOrg.right); - break; - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyBarBreadth -// -// Helper function to modifyBarNormal and modifyBarOverlap -// -void TrayService::modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge) -{ - switch (uEdge) - { - case ABE_LEFT: - rcDst.right = rcDst.left + (rcOrg.right - rcOrg.left); - break; - case ABE_TOP: - rcDst.bottom = rcDst.top + (rcOrg.bottom - rcOrg.top); - break; - case ABE_RIGHT: - rcDst.left = rcDst.right - (rcOrg.right - rcOrg.left); - break; - case ABE_BOTTOM: - rcDst.top = rcDst.bottom - (rcOrg.bottom - rcOrg.top); - break; - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// adjustWorkArea -// -// Helper function to barSetPos (via ABP_NOTIFYPOSCHANGED) -// -void TrayService::adjustWorkArea(HMONITOR hMon) -{ - RECT rcWorker, rcMonitor, rcWorkArea; - - HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); - - if (hMon != hMonPrimary) - { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - - if (!GetMonitorInfo(hMon, &mi)) - { - return; - } - - CopyRect(&rcMonitor, &mi.rcMonitor); - CopyRect(&rcWorkArea, &mi.rcWork); - } - else - { - CopyRect(&rcMonitor, &m_rWorkAreaDef); // yes, we actually want this - CopyRect(&rcWorkArea, &m_rWorkAreaCur); - } - - CopyRect(&rcWorker, &rcMonitor); - - for ( - BarVector::iterator it = m_abVector.begin() - ;it != m_abVector.end() - ;++it - ) - { - AppBar* p = *it; - - if(p && !p->IsOverLap() && p->hMon() == hMon && - (ABS_CLEANRECT == (ABS_CLEANRECT & p->lParam()))) - { - if (!IsWindow(p->hWnd())) - { - continue; - } - - RECT rcBarEx; - - CopyRect(&rcBarEx, &rcMonitor); - - switch (p->uEdge()) - { - case ABE_LEFT: - rcBarEx.right = p->GetRectRef().right; - break; - case ABE_RIGHT: - rcBarEx.left = p->GetRectRef().left; - break; - case ABE_TOP: - rcBarEx.bottom = p->GetRectRef().bottom; - break; - case ABE_BOTTOM: - rcBarEx.top = p->GetRectRef().top; - break; - } - - SubtractRect(&rcWorker, &rcWorker, &rcBarEx); - } - } - - if(!EqualRect(&rcWorker, &rcWorkArea)) - { - setWorkArea(&rcWorker); - } - - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setWorkArea -// -// Helper function for setting the specified work area -// -void TrayService::setWorkArea(LPRECT prcWorkArea) -{ - if (m_hTrayWnd) - { - m_uWorkAreaDirty++; - } - - SystemParametersInfo( - SPI_SETWORKAREA - ,1 // readjust maximized windows - ,prcWorkArea - ,0 // SPIF_SENDCHANGE - see below - ); - SendNotifyMessage( // used in place of SPIF_SENDCHANGE above to avoid lockups - HWND_BROADCAST // see http://blogs.msdn.com/oldnewthing/archive/2005/03/10/392118.aspx - ,WM_SETTINGCHANGE - ,SPI_SETWORKAREA - ,0 - ); - return; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ABLock -// -// Calls SHLockShared API for the specified Shell AppBar memory -// -// Returns a pointer to shared memory location for an AppBarData structure -// -PAPPBARDATAV1 TrayService::ABLock(PSHELLAPPBARDATA psad) -{ - return (PAPPBARDATAV1)SHLockShared( - psad->hSharedMemory, psad->dwSourceProcessId); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// ABUnlock -// -// Calls SHUnlockShared API for the specified AppBarData* memory -// -void TrayService::ABUnLock(PAPPBARDATAV1 pabd) -{ - SHUnlockShared(pabd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// FindAppBarPredicate_hWnd -// -// Predicate for std::find_if, used by findBar variants -// Needs to be at global scope because of mingw issues -// -// Find the appbar matching the specified hWnd -// -struct FindAppBarPredicate_hWnd -{ - FindAppBarPredicate_hWnd(HWND hWnd) : - m_hWnd(hWnd) - { - // do nothing - } - FindAppBarPredicate_hWnd(const FindAppBarPredicate_hWnd& copy) : - m_hWnd(copy.m_hWnd) - { - // do nothing - } - - bool operator() (const AppBar* pab) const - { - return (pab->hWnd() == m_hWnd); - } - -private: - const HWND m_hWnd; - -private: - // Not implemented - FindAppBarPredicate_hWnd& operator=(const FindAppBarPredicate_hWnd&); -}; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// FindAppBarPredicate_MatchLParam -// -// Predicate for std::find_if, used by findBar variants -// Needs to be at global scope because of mingw issues -// -// Find the appbar on the specified edge that has a matching lParam value -// -struct FindAppBarPredicate_MatchLParam -{ - FindAppBarPredicate_MatchLParam(HMONITOR hMon, UINT uEdge, LPARAM lParam) : - m_hMon(hMon), m_uEdge(uEdge), m_lParam(lParam) - { - // do nothing - } - FindAppBarPredicate_MatchLParam(const FindAppBarPredicate_MatchLParam& copy) : - m_hMon(copy.m_hMon), m_uEdge(copy.m_uEdge), m_lParam(copy.m_lParam) - { - // do nothing - } - - bool operator() (const AppBar* pab) const - { - return (pab->hMon() == m_hMon && pab->uEdge() == m_uEdge && - m_lParam == (pab->lParam() & m_lParam)); - } - -private: - const HMONITOR m_hMon; - const UINT m_uEdge; - const LPARAM m_lParam; - -private: - // Not implemented - FindAppBarPredicate_MatchLParam& operator=(const FindAppBarPredicate_MatchLParam&); -}; - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// findBar -// -// Looks up an AppBar in the AppBarList -// -BarVector::iterator TrayService::findBar(HWND hWnd) -{ - return std::find_if(m_abVector.begin(), m_abVector.end(), - FindAppBarPredicate_hWnd(hWnd)); -} -BarVector::iterator TrayService::findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam) -{ - return std::find_if(m_abVector.begin(), m_abVector.end(), - FindAppBarPredicate_MatchLParam(hMon, uEdge, lParam)); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// isBar -// -// Determines whether the HWND is associated with any current AppBar. -// -bool TrayService::isBar(HWND hWnd) -{ - return m_abVector.end() != findBar(hWnd); -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// getBar -// -// Looks up an BarVector iterator based on the HWND -// -// returns true if found, otherwise false. -// -bool TrayService::getBar(HWND hWnd, BarVector::iterator& itBar) -{ - bool bReturn = false; - - itBar = findBar(hWnd); - - if (itBar != m_abVector.end()) - { - bReturn = true; - } - - return bReturn; -} - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// getBar -// -// Looks up an AppBar* based on the HWND -// -// Returns true if found, otherwise false. -// -bool TrayService::getBar(HWND hWnd, AppBar*& pBarRef) -{ - bool bReturn = false; - BarVector::iterator itBar; - - if (getBar(hWnd, itBar)) - { - pBarRef = *itBar; - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// HandleNotification -// -// Handler for all system tray notifications -// -BOOL TrayService::HandleNotification(PSHELLTRAYDATA pstd) -{ - bool bReturn = false; - - switch (pstd->dwMessage) - { - case NIM_ADD: - bReturn = addIcon(pstd->nid); - break; - - case NIM_MODIFY: - bReturn = modifyIcon(pstd->nid); - break; - - case NIM_DELETE: - bReturn = deleteIcon(pstd->nid); - break; - - case NIM_SETFOCUS: - bReturn = setFocusIcon(pstd->nid); - break; - - case NIM_SETVERSION: - bReturn = setVersionIcon(pstd->nid); - break; - - default: - TRACE("Unknown NIM: %u", pstd->dwMessage); - break; - } - - return bReturn ? TRUE : FALSE; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// notify -// -// Notify all listeners of a systray event -// -bool TrayService::notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const -{ - return 0 != SendMessage(m_hLiteStep, LM_SYSTRAY, - dwMessage, (LPARAM)pclsnid); -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// SendSystemTray -// -// Resend all icon data; systray modules will request this via LM_SYSTRAYREADY -// during their startup. -// -HWND TrayService::SendSystemTray() -{ - removeDeadIcons(); - - for (IconVector::const_iterator it = m_siVector.begin(); - it != m_siVector.end(); ++it) - { - if ((*it)->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - (*it)->CopyLSNID(&lsnid); - - notify(NIM_ADD, &lsnid); - } - } - - return m_hNotifyWnd; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// removeDeadIcons -// -// Removes all "dead" icons. ie. Those that no longer have a valid HWND -// associated with them. -// -void TrayService::removeDeadIcons() -{ - IconVector::iterator it = m_siVector.begin(); - - while (it != m_siVector.end()) - { - if (IsWindow((*it)->GetHwnd())) - { - ++it; - continue; - } - - delete *it; - it = m_siVector.erase(it); - } - - return; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// extendNIDCopy -// -// Copies all non-persistent data that is not stored in NotifyIcon. -// -bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const -{ - // Copy Info Tips - if (nid.uFlags & NIF_INFO) - { - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - case NID_5W_SIZE: - { - NID_5W* pnid = (NID_5W*)&nid; - - int nReturn; - WCHAR szTemp[256]; - - memcpy(szTemp, pnid->szInfo, sizeof(WCHAR)*256); - szTemp[255] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfo, TRAY_MAX_INFO_LENGTH, NULL, NULL); - - if (!nReturn) - { - lsnid.szInfo[0] = 0; - } - - memcpy(szTemp, pnid->szInfoTitle, sizeof(WCHAR)*64); - szTemp[63] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfoTitle, TRAY_MAX_INFOTITLE_LENGTH, NULL, NULL); - - if (!nReturn) - { - lsnid.szInfoTitle[0] = 0; - } - - lsnid.dwInfoFlags = pnid->dwInfoFlags; - lsnid.uTimeout = pnid->uTimeout; - lsnid.uFlags |= NIF_INFO; - } - break; - case NID_6A_SIZE: - case NID_5A_SIZE: - { - NID_5A* pnid = (NID_5A*)&nid; - - HRESULT hr; - - hr = StringCchCopy(lsnid.szInfo, - TRAY_MAX_INFO_LENGTH, pnid->szInfo); - - if (FAILED(hr)) - { - lsnid.szInfo[0] = 0; - } - - hr = StringCchCopy(lsnid.szInfoTitle, - TRAY_MAX_INFOTITLE_LENGTH, pnid->szInfoTitle); - - if (FAILED(hr)) - { - lsnid.szInfoTitle[0] = 0; - } - - lsnid.dwInfoFlags = pnid->dwInfoFlags; - lsnid.uTimeout = pnid->uTimeout; - lsnid.uFlags |= NIF_INFO; - } - break; - default: - { - // do nothing - } - break; - } - } - - // Copy GUID - if (nid.uFlags & NIF_GUID) - { - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - { - NID_6W* pnid = (NID_6W*)&nid; - - lsnid.guidItem = pnid->guidItem; - lsnid.uFlags |= NIF_GUID; - } - break; - case NID_6A_SIZE: - { - NID_6A* pnid = (NID_6A*)&nid; - - lsnid.guidItem = pnid->guidItem; - lsnid.uFlags |= NIF_GUID; - } - break; - default: - { - // do nothing - } - break; - } - } - - return true; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// addIcon -// -bool TrayService::addIcon(const NID_XX& nid) -{ - bool bReturn = false; - - if (m_siVector.end() == findIcon(nid)) - { - NotifyIcon * pni = new NotifyIcon(nid); - - if (pni) - { - // Fail shared icons, unless a valid hIcon exists - if (IsWindow(pni->GetHwnd()) && - (!pni->IsShared() || pni->HasIcon())) - { - m_siVector.push_back(pni); - - if (pni->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - pni->CopyLSNID(&lsnid); - extendNIDCopy(lsnid, nid); - - notify(NIM_ADD, &lsnid); - } - bReturn = true; - } - else - { - delete pni; - } - } - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// modifyIcon -// -bool TrayService::modifyIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it && *it) - { - NotifyIcon * pni = *it; - - bool bWasValid = pni->IsValid(); - - // Update stored NotifyIcon - pni->Update(nid); - - if (pni->IsValid()) - { - LSNOTIFYICONDATA lsnid = { 0 }; - - if (!bWasValid) - { - // This is a "new" icon, send entire stored NotifyIcon - pni->CopyLSNID(&lsnid); - extendNIDCopy(lsnid, nid); - - notify(NIM_ADD, &lsnid); - } - else - { - // This icon already exists, just send updated flags - pni->CopyLSNID(&lsnid, nid.uFlags); - extendNIDCopy(lsnid, nid); - - notify(NIM_MODIFY, &lsnid); - } - } - else if (bWasValid) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,pni->GetHwnd() - ,pni->GetuID() - ,0 - }; - - // This icon is no longer visible, remove - notify(NIM_DELETE, &lsnid); - } - - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// deleteIcon -// -// Remove an icon from the icon list -// -bool TrayService::deleteIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - notify(NIM_DELETE, &lsnid); - - delete *it; - m_siVector.erase(it); - - bReturn = true; - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setFocusIcon -// -// Sets selection focus to the specified icon -// -bool TrayService::setFocusIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - bReturn = notify(NIM_SETFOCUS, &lsnid); - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// setVersionIcon -// -// Sets compatibility version for specified icon -// -bool TrayService::setVersionIcon(const NID_XX& nid) -{ - bool bReturn = false; - - IconVector::iterator it = findIcon(nid); - - if (m_siVector.end() != it) - { - LSNOTIFYICONDATA lsnid = { - sizeof(LSNOTIFYICONDATA) - ,(*it)->GetHwnd() - ,(*it)->GetuID() - ,0 - }; - - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - case NID_5W_SIZE: - lsnid.uVersion = ((NID_5W&)nid).uVersion; - break; - - case NID_6A_SIZE: - case NID_5A_SIZE: - lsnid.uVersion = ((NID_5A&)nid).uVersion; - break; - - default: - break; - } - - bReturn = notify(NIM_SETVERSION, &lsnid); - } - - return bReturn; -} - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// findIcon -// -// Looks up an icon in the SystrayIconList -// -IconVector::iterator TrayService::findIcon(const NID_XX& nid) -{ - GUID guidItem; - - switch (nid.cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - guidItem = ((NID_6W&)nid).guidItem; - break; - - case NID_6A_SIZE: - guidItem = ((NID_6A&)nid).guidItem; - break; - - default: - break; - } - - for (IconVector::iterator iter = m_siVector.begin(); iter != m_siVector.end(); iter++) - { - // If the GUID is valid, we ignore the uID and hWnd - if ((nid.uFlags & NIF_GUID) == NIF_GUID) - { - if (guidItem == (*iter)->GetGUID()) - { - return iter; - } - } - else if((*iter)->GetuID() == nid.uID && (*iter)->GetHwnd() == (HWND)nid.hWnd) - { - return iter; - } - } - - return m_siVector.end(); -} +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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 "TrayService.h" +#include "../utility/core.hpp" +#include +#include +#include + + +#if !defined(REGSTR_PATH_SHELLSERVICEOBJECTDELAYED) +#define REGSTR_PATH_SHELLSERVICEOBJECTDELAYED \ + _T("Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad") +#endif + +static const TCHAR szTrayClass[] = _T("Shell_TrayWnd"); +static const TCHAR szTrayTitle[] = _T("LiteStep Tray Manager"); +static const TCHAR szNotifyClass[] = _T("TrayNotifyWnd"); + + +// +// CLSID_SysTrayObject - {35CEC8A3-2BE6-11D2-8773-92E220524153} +// +// This appears to be the SSO responsible for starting up all other "approved" +// SSOs on Vista. Name derived from "stobject.dll". +// +const GUID CLSID_SysTrayObject = \ +{0x35CEC8A3, 0x2BE6, 0x11D2, {0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53}}; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayService +// +TrayService::TrayService() : +m_uWorkAreaDirty(0), m_hNotifyWnd(NULL), m_hTrayWnd(NULL), +m_hLiteStep(NULL), m_hInstance(NULL) +{ + // do nothing +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ~TrayService +// +TrayService::~TrayService() +{ + // do nothing +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// Start() +// +HRESULT TrayService::Start() +{ + ASSERT(NULL == m_hTrayWnd); + HRESULT hr = E_FAIL; + + m_hLiteStep = GetLitestepWnd(); + m_hInstance = GetModuleHandle(NULL); + + if (m_hLiteStep && m_hInstance) + { + // clear work area of primary monitor + SetRect(&m_rWorkAreaDef, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + setWorkArea(&m_rWorkAreaDef); + CopyRect(&m_rWorkAreaCur, &m_rWorkAreaDef); + + hr = createWindows(); + + if (SUCCEEDED(hr)) + { + SetWindowLongPtr(m_hTrayWnd, GWLP_USERDATA, magicDWord); + SetWindowLongPtr(m_hTrayWnd, 0, (LONG_PTR)this); + + // http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1427677&SiteID=1 + // + // Re: TaskbarCreated message (not working in Vista) + // + // > The code is still in there to broadcast the message. + // > SendNotifyMessage(HWND_BROADCAST, + // > RegisterWindowMessage(TEXT("TaskbarCreated")), 0, 0); + // + // >> It looks as though applications running as admin cannot + // >> receive the message. Presumably, this is because Explorer, + // >> which publishes the message, is not running as admin + // + // >>> The message is blocked by User Interface Privilege + // >>> Isolation, Administrative applications that need to see it + // >>> can allow it through by calling ChangeWindowMessageFilter + // >>> after making sure the necessary security precautions are in + // >>> place. + + // tell apps to reregister their icons + SendNotifyMessage(HWND_BROADCAST, + RegisterWindowMessage(_T("TaskbarCreated")), 0, 0); + + if (IsVistaOrAbove()) + { + // On Vista and up there's a single SSO responsible for loading + // all the supported objects (volume icon, network icon, etc.) + loadShellServiceObject(CLSID_SysTrayObject); + } + else if (IsOS(OS_WIN2000ORGREATER)) + { + // On previous versions the object list is in the registry + loadShellServiceObjects(); + } + } + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// Stop() +// +HRESULT TrayService::Stop() +{ + HRESULT hr = S_OK; + + unloadShellServiceObjects(); + destroyWindows(); + + while (!m_siVector.empty()) + { + delete m_siVector.back(); + m_siVector.pop_back(); + } + + while (!m_abVector.empty()) + { + delete m_abVector.back(); + m_abVector.pop_back(); + } + + // clear the work area of primary monitor + SetRect(&m_rWorkAreaDef, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + setWorkArea(&m_rWorkAreaDef); + + m_hLiteStep = NULL; + m_hInstance = NULL; + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// createWindows +// +HRESULT TrayService::createWindows() +{ + HRESULT hr = E_FAIL; + + // + // Register tray window class + // + WNDCLASSEX wc = { 0 }; + wc.cbSize = sizeof(WNDCLASSEX); + wc.cbWndExtra = sizeof(TrayService*); + wc.lpfnWndProc = TrayService::WindowTrayProc; + wc.hInstance = m_hInstance; + wc.lpszClassName = szTrayClass; + wc.style = CS_DBLCLKS; + + if (!RegisterClassEx(&wc)) + { + hr = HrGetLastError(); + } + else + { + // + // Window which receives the tray messages + // + m_hTrayWnd = CreateWindowEx( + WS_EX_TOPMOST | WS_EX_TOOLWINDOW, + szTrayClass, szTrayTitle, + WS_POPUP, + 0, 0, 0, 0, + NULL, NULL, + m_hInstance, + NULL); + + if (NULL == m_hTrayWnd) + { + hr = HrGetLastError(); + UnregisterClass(szTrayClass, m_hInstance); + } + else + { + // Our main window is enough to start up, we can do without the + // TrayNotifyWnd if necessary. + hr = S_OK; + + // + // Register "TrayNotifyWnd" class and create window + // + ZeroMemory(&wc, sizeof(wc)); + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = TrayService::WindowNotifyProc; + wc.hInstance = m_hInstance; + wc.lpszClassName = szNotifyClass; + wc.style = CS_DBLCLKS; + + if (RegisterClassEx(&wc)) + { + m_hNotifyWnd = CreateWindowEx( + 0, + szNotifyClass, NULL, + WS_CHILD, + 0, 0, 0, 0, + m_hTrayWnd, NULL, + m_hInstance, + NULL); + + if (!m_hNotifyWnd) + { + UnregisterClass(szNotifyClass, m_hInstance); + } + } + } + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// destroyWindows +// +void TrayService::destroyWindows() +{ + if (m_hNotifyWnd) + { + DestroyWindow(m_hNotifyWnd); + m_hNotifyWnd = NULL; + + UnregisterClass(szNotifyClass, m_hInstance); + } + + if (m_hTrayWnd) + { + DestroyWindow(m_hTrayWnd); + m_hTrayWnd = NULL; + + UnregisterClass(szTrayClass, m_hInstance); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// loadShellServiceObject +// +HRESULT TrayService::loadShellServiceObject(REFCLSID rclsid) +{ +#if defined(TRACE_ENABLED) + CHAR szBuffer[MAX_PATH] = { 0 }; + CLSIDToString(rclsid, szBuffer, COUNTOF(szBuffer)); + + TRACE("loadShellServiceObject(\"%s\")", szBuffer); +#endif + + // The SSO might have a custom manifest. + // Activate it before loading the object. + ULONG_PTR ulCookie; + HANDLE hContext = LSActivateActCtxForClsid(rclsid, &ulCookie); + + IOleCommandTarget* pCmdTarget = NULL; + + HRESULT hr = CoCreateInstance(rclsid, NULL, + CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, + IID_IOleCommandTarget, (void **)&pCmdTarget); + + if (SUCCEEDED(hr)) + { + hr = pCmdTarget->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, + OLECMDEXECOPT_DODEFAULT, NULL, NULL); + + m_ssoVector.push_back(pCmdTarget); + } + + if (hContext != INVALID_HANDLE_VALUE) + { + LSDeactivateActCtx(hContext, &ulCookie); + } + + return hr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// loadShellServiceObjects +// +// Start the COM based shell services listed in the registry. +// +void TrayService::loadShellServiceObjects() +{ + HKEY hkeyServices; + int nCounter = 0; + + LONG lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + REGSTR_PATH_SHELLSERVICEOBJECTDELAYED, + 0, KEY_READ, &hkeyServices); + + while (lErrorCode == ERROR_SUCCESS) + { + TCHAR szValueName[32] = { 0 }; + char szData[40] = { 0 }; + DWORD cchValueName = sizeof(szValueName) / sizeof(szValueName[0]); + DWORD cbData = sizeof(szData); + DWORD dwDataType; + + lErrorCode = RegEnumValue(hkeyServices, nCounter, szValueName, + &cchValueName, NULL, &dwDataType, (LPBYTE)szData, &cbData); + + if (lErrorCode == ERROR_SUCCESS) + { + WCHAR wszCLSID[40] = { 0 }; + CLSID clsid = CLSID_NULL; + + MultiByteToWideChar(CP_ACP, 0, szData, cbData, wszCLSID, 40); + CLSIDFromString(wszCLSID, &clsid); + + loadShellServiceObject(clsid); + } + + ++nCounter; + } + + RegCloseKey(hkeyServices); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// unloadShellServiceObjects +// +// Shut down the COM based shell services. +// +// +void TrayService::unloadShellServiceObjects() +{ + while (!m_ssoVector.empty()) + { + m_ssoVector.back()->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, + OLECMDEXECOPT_DODEFAULT, NULL, NULL); + + m_ssoVector.back()->Release(); + m_ssoVector.pop_back(); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// WindowTrayProc +// +// Redirects all messages to the appropriate handler +// +LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, + WPARAM wParam, LPARAM lParam) +{ + static TrayService* pTrayService = NULL; + + if (!pTrayService) + { + pTrayService = (TrayService*)GetWindowLongPtr(hWnd, 0); + } + + if (pTrayService) + { + LRESULT lResult = 0; + + switch (uMsg) + { + case WM_COPYDATA: + { + // + // Undocumented: This is how we can make our own system tray + // and handle app bar windows. Once a window in the system has + // the "Shell_TrayWnd" class name, it receives this message! + // + COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam; + + switch (pcds->dwData) + { + case SH_APPBAR_DATA: + { + // + // Application Bar Message + // + lResult = pTrayService->HandleAppBarCopydata( + pcds->cbData, pcds->lpData); + } + break; + + case SH_TRAY_DATA: + { + // + // System Tray Notification + // + PSHELLTRAYDATA pstd = (PSHELLTRAYDATA)pcds->lpData; + + lResult = (LRESULT)pTrayService->HandleNotification(pstd); + } + break; + + case SH_LOADPROC_DATA: + { + // + // LoadInProc messages + // + if (pcds->cbData == sizeof(CLSID)) + { + // Classic SHLoadInProc message + lResult = pTrayService->HandleLoadInProc( + (REFCLSID)pcds->lpData, 1); + } + else if (pcds->cbData == sizeof(SHELLINPROCDATA)) + { + PSHELLINPROCDATA pipd = (PSHELLINPROCDATA)pcds->lpData; + + lResult = pTrayService->HandleLoadInProc( + pipd->clsid, pipd->dwMessage); + } + else + { + TRACE("Unknown SHLoadInProc size: %u", pcds->cbData); + lResult = E_NOTIMPL; + } + } + break; + case SH_TRAYINFO_DATA: + { + lResult = pTrayService->TrayInfoEvent(pcds->cbData, pcds->lpData); + } + break; + + default: + { + TRACE("Unsupported tray message: %u", pcds->dwData); + } + break; + } + } + break; + + case ABP_NOTIFYPOSCHANGED: + { + const BarVector abTempV = pTrayService->m_abVector; + BarVector::const_reverse_iterator rit; + + HMONITOR hMon = (HMONITOR)lParam; + HWND hSkip = (HWND)wParam; + AppBar* p = NULL; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + if (hSkip != (*rit)->hWnd()) + { + if((*rit)->hMon() == hMon && + (!p || p->uEdge() != (*rit)->uEdge())) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_POSCHANGED + ,0 + ); + } + } + else + { + p = *rit; + } + } + + pTrayService->adjustWorkArea(hMon); + } + break; + + case ABP_NOTIFYSTATECHANGE: + { + const BarVector abTempV = pTrayService->m_abVector; + BarVector::const_reverse_iterator rit; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + if (!(*rit)->IsOverLap()) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_STATECHANGE + ,0 + ); + } + } + } + break; + + case ABP_RAISEAUTOHIDEHWND: + { + HWND hRaise = (HWND)wParam; + //UINT uEdge = (UINT)lParam; + + SetWindowPos( + hRaise, HWND_TOP + ,0,0,0,0 + ,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER + ); + } + break; + + case WM_SETTINGCHANGE: + { + TRACE("WM_SETTINGCHANGE(%.4X, \"%s\")", + wParam, (LPCTSTR)lParam); + + if (SPI_SETWORKAREA == wParam) + { + RECT rc; + + SystemParametersInfo( + SPI_GETWORKAREA + ,0 + ,&rc + ,0 + ); + + // Always update the Current workarea + CopyRect(&pTrayService->m_rWorkAreaCur, &rc); + + // This will be the case when we updated the workarea + // ourselves. + if (pTrayService->m_uWorkAreaDirty) + { + --pTrayService->m_uWorkAreaDirty; + break; + } + + // Only update the Default workarea when set externally. + CopyRect(&pTrayService->m_rWorkAreaDef, &rc); + + // Clean up any dead app bars before repositioning + pTrayService->removeDeadAppBars(); + + // Now reposition our appbars based on the new default + // workarea. + PostMessage( + pTrayService->m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)NULL + ,(LPARAM)MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY) + ); + } + } + break; + + default: + if (uMsg >= WM_USER) + { + DbgTraceWindowMessage("Shell_TrayWnd", uMsg, wParam, lParam); + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + + return lResult; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// WindowNotifyProc +// +// Redirects all messages to the appropriate handler +// +LRESULT CALLBACK TrayService::WindowNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleLoadInProc +// +// Handler for SHLoadInProc and SHEnableServiceObject (where available) +// +HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) +{ +#if defined(TRACE_ENABLED) + CHAR szBuffer[MAX_PATH] = { 0 }; + CLSIDToString(clsid, szBuffer, COUNTOF(szBuffer)); + + if (dwMessage == 1) + { + TRACE("SHLoadInProc(\"%s\")", szBuffer); + } + else if (dwMessage == 2) + { + TRACE("SHEnableServiceObject(\"%s\", FALSE)", szBuffer); + } + else if (dwMessage == 3) + { + TRACE("SHEnableServiceObject(\"%s\", TRUE)", szBuffer); + } + else + { + TRACE("Unknown LoadInProc message: %u", dwMessage); + } +#else + UNREFERENCED_PARAMETER(clsid); + UNREFERENCED_PARAMETER(dwMessage); +#endif + + // This is not actually implemented + return E_NOTIMPL; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayInfoEvent +// +// Handles tray info events +// +LRESULT TrayService::TrayInfoEvent(DWORD /* cbData */, LPVOID lpData) // size, data +{ + LRESULT lr = 0; + LPNOTIFYICONIDENTIFIER_MSGV1 s = (LPNOTIFYICONIDENTIFIER_MSGV1)lpData; + + // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. + + if (s->dwMessage == 2) // Icon size? + { + return MAKELONG(16,16); + } + + POINT p; + GetCursorPos(&p); + + if (s->dwMessage == 1) // Icon position + { + return MAKELPARAM(p.x, p.y); + } + + return lr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleAppBarCopydata +// +LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) +{ + LRESULT lr = 0; + + switch (cbData) + { + case sizeof(APPBARMSGDATAV3): + { + PAPPBARMSGDATAV3 pamd = (PAPPBARMSGDATAV3)lpData; + + if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) + { + TRACE("PAPPBARMSGDATAV3 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + case sizeof(APPBARMSGDATAV2): + { + PAPPBARMSGDATAV2 pamd = (PAPPBARMSGDATAV2)lpData; + + if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) + { + TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + case sizeof(APPBARMSGDATAV1): + { + PAPPBARMSGDATAV1 pamd = (PAPPBARMSGDATAV1)lpData; + + if (sizeof(APPBARDATAV1) != pamd->abd.cbSize) + { + TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u", pamd->abd.cbSize); + + break; + } + + SHELLAPPBARDATA sbd((APPBARDATAV1&)(pamd->abd)); + sbd.dwMessage = pamd->dwMessage; + sbd.hSharedMemory = (HANDLE)pamd->hSharedMemory; + sbd.dwSourceProcessId = pamd->dwSourceProcessId; + + lr = HandleAppBarMessage(&sbd); + } + break; + + default: + { + TRACE("Unknown APPBARMSGDATA size: %u", cbData); + } + break; + } + + return lr; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleAppBarMessage +// +// Handler for all AppBar Messages +// +LRESULT TrayService::HandleAppBarMessage(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + + removeDeadAppBars(); + + TRACE("SHAppBarMessage(%u, ...)", psad->dwMessage); + + switch(psad->dwMessage) + { + case ABM_NEW: + lResult = barCreate(psad->abd); + break; + + case ABM_REMOVE: + lResult = barDestroy(psad->abd); + break; + + case ABM_QUERYPOS: + lResult = barQueryPos(psad); + break; + + case ABM_SETPOS: + lResult = barSetPos(psad); + break; + + case ABM_GETSTATE: + lResult = barGetTaskBarState(); + break; + + case ABM_GETTASKBARPOS: + lResult = barGetTaskBarPos(psad); + break; + + case ABM_ACTIVATE: + lResult = barActivate(psad->abd); + break; + + case ABM_GETAUTOHIDEBAR: + lResult = barGetAutoHide(psad->abd); + break; + + case ABM_SETAUTOHIDEBAR: + lResult = barSetAutoHide(psad->abd); + break; + + case ABM_WINDOWPOSCHANGED: + lResult = barPosChanged(psad->abd); + break; + + case ABM_SETSTATE: + lResult = barSetTaskBarState(psad->abd); + break; + + default: + TRACE("ABM unknown: %u", psad->dwMessage); + break; + } + + return lResult; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// NotifyRudeApp +// +// External interface to let us know a window has gone/left full screen mode +// +void TrayService::NotifyRudeApp(HMONITOR hFullScreenMonitor) const +{ + const BarVector abTempV = m_abVector; + BarVector::const_reverse_iterator rit; + + for (rit = abTempV.rbegin(); rit != abTempV.rend(); ++rit) + { + SendMessage( + (*rit)->hWnd() + ,(*rit)->uMsg() + ,ABN_FULLSCREENAPP + ,(LPARAM)(hFullScreenMonitor ? 1 : 0) + ); + } +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// removeDeadAppBars +// +// Removes all "dead" appBars. ie. Those that no longer have a valid HWND +// associated with them. +// +void TrayService::removeDeadAppBars() +{ + BarVector::iterator it = m_abVector.begin(); + + while (it != m_abVector.end()) + { + if (IsWindow((*it)->hWnd())) + { + ++it; + continue; + } + + delete *it; + it = m_abVector.erase(it); + } + + return; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barCreate +// +// Creates a new AppBar. +// +// ABM_NEW +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uCallbackMessage +// +LRESULT TrayService::barCreate(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + + if (IsWindow((HWND)abd.hWnd) && !isBar((HWND)abd.hWnd)) + { + m_abVector.push_back(new AppBar((HWND)abd.hWnd, abd.uCallbackMessage)); + lResult = 1; + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barDestroy +// +// Removes the specified AppBar. +// +// ABM_REMOVE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barDestroy(const APPBARDATAV1& abd) +{ + BarVector::iterator itBar; + LRESULT lResult = 0; + + if (getBar((HWND)abd.hWnd, itBar)) + { + lResult = 1; + + HMONITOR hMon = (*itBar)->hMon(); + + delete *itBar; + m_abVector.erase(itBar); + + PostMessage( + m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)NULL + ,(LPARAM)hMon + ); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barQueryPos +// +// Queries for an acceptable position for the specified appbar +// +// ABM_QUERYPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// rc +// +LRESULT TrayService::barQueryPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + const APPBARDATAV1& abd = psad->abd; + + if (pabd) + { + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + if (p->IsOverLap()) + { + modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); + } + else + { + modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); + } + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetPos +// +// Sets the position of the specified appbar +// +// ABM_SETPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// rc +// +LRESULT TrayService::barSetPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + const APPBARDATAV1& abd = psad->abd; + + if (pabd) + { + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + if (p->IsOverLap()) + { + modifyOverlapBar(pabd->rc, abd.rc, abd.uEdge); + } + else + { + modifyNormalBar(pabd->rc, abd.rc, abd.uEdge, (HWND)abd.hWnd); + + // If this is the first time to position the bar or if + // the new position is different than the previous, then + // notify all other appbars. + if ((ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) + || !EqualRect(&p->GetRectRef(), &pabd->rc)) + { + // Notify other bars + PostMessage( + m_hTrayWnd + ,ABP_NOTIFYPOSCHANGED + ,(WPARAM)abd.hWnd + ,(LPARAM)MonitorFromRect(&pabd->rc, MONITOR_DEFAULTTOPRIMARY) + ); + } + } + + // Update the appbar stored parameters + CopyRect(&p->GetRectRef(), &pabd->rc); + p->lParam(p->lParam() | ABS_CLEANRECT); + p->uEdge(abd.uEdge); + p->hMon(MonitorFromRect(&p->GetRectRef(), MONITOR_DEFAULTTOPRIMARY)); + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetTaskBarState +// +// Returns the current TaskBar state (autohide, alwaysontop) +// +// ABM_GETSTATE +// +// Valid APPBARDATA members: +// +// cbSize +// +LRESULT TrayService::barGetTaskBarState() +{ + // Zero means neither always-on-top nor autohide, + // which is the safest guess for most LS setups + return 0; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetTaskBarPos +// +// Gets the current TaskBar position +// +// ABM_GETTASKBARPOS +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge (undocumented) +// +LRESULT TrayService::barGetTaskBarPos(PSHELLAPPBARDATA psad) +{ + LRESULT lResult = 0; + PAPPBARDATAV1 pabd = ABLock(psad); + + if (pabd) + { + if (GetWindowRect(m_hNotifyWnd, &pabd->rc)) + { + lResult = 1; + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(!GetMonitorInfo(MonitorFromWindow(m_hNotifyWnd, MONITOR_DEFAULTTOPRIMARY), &mi)) + { + SetRect(&mi.rcMonitor, 0, 0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN)); + } + + INT nHeight, nWidth, nScreenHeight, nScreenWidth; + + nHeight = pabd->rc.bottom - pabd->rc.top; + nWidth = pabd->rc.right - pabd->rc.left; + + nScreenHeight = mi.rcMonitor.bottom - mi.rcMonitor.top; + nScreenWidth = mi.rcMonitor.right - mi.rcMonitor.left; + + if(nHeight > nWidth) + { + if(pabd->rc.left > nScreenWidth / 2) + { + pabd->uEdge = ABE_RIGHT; + } + else + { + pabd->uEdge = ABE_LEFT; + } + } + else + { + if(pabd->rc.top > nScreenHeight / 2) + { + pabd->uEdge = ABE_BOTTOM; + } + else + { + pabd->uEdge = ABE_TOP; + } + } + } + + ABUnLock(pabd); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barActivate +// +// Ensures that any autohide appbar has the topmost zOrder when any appbar is +// activated. +// +// ABM_ACTIVATE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barActivate(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + AppBar* p; + + if (getBar((HWND)abd.hWnd, p)) + { + lResult = 1; + + BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + PostMessage( + m_hTrayWnd + ,ABP_RAISEAUTOHIDEHWND + ,(WPARAM)(*itBar)->hWnd() + ,(LPARAM)(*itBar)->uEdge() + ); + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barGetAutoHide +// +// Returns the HWND of the autohide appbar on the specified screen edge +// +// ABM_GETAUTOHIDEBAR +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// +LRESULT TrayService::barGetAutoHide(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + BarVector::iterator itBar = findBar( + MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), + abd.uEdge, ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + lResult = (LRESULT)(*itBar)->hWnd(); + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetAutoHide +// +// Sets the specified AppBar to autohide if it already exists, otherwise +// if the specified AppBar does not exist, it creates it and sets it to as +// an overlap autohide AppBar. +// +// ABM_SETAUTOHIDEBAR +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// uEdge +// lParam +// +LRESULT TrayService::barSetAutoHide(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + + BarVector::iterator itBar = findBar((HWND)abd.hWnd); + BarVector::iterator itAutoHideBar = findBar( + MonitorFromWindow((HWND)abd.hWnd, MONITOR_DEFAULTTOPRIMARY), + abd.uEdge, ABS_AUTOHIDE); + + if (abd.lParam) // Set Auto Hide + { + lResult = 1; + + // Does an autohide bar already exist on this edge? + if (itAutoHideBar != m_abVector.end()) + { + // Return true if this appbar is the autohide bar. + return (itBar == itAutoHideBar); + } + + // if bar doesn't exist, create it and set it as an overlap bar + if (itBar == m_abVector.end()) + { + if (!barCreate(abd)) + { + return 0; + } + + itBar = m_abVector.end()-1; + (*itBar)->lParam((*itBar)->lParam() | ABS_OVERLAPAUTOHIDE); + } + + // set its assigned edge, and set it as an autohide bar + (*itBar)->uEdge(abd.uEdge); + (*itBar)->lParam((*itBar)->lParam() | ABS_AUTOHIDE); + } + else // Clear Auto Hide + { + // if the bar was the auto hide bar proceed + if (itBar != m_abVector.end() && itBar == itAutoHideBar) + { + lResult = 1; + + // if bar was overlap, destroy it + if ((*itBar)->IsOverLap()) + { + barDestroy(abd); + } + else + { + // otherwise clear its autohide status. + (*itBar)->lParam((*itBar)->lParam() & ~ABS_AUTOHIDE); + } + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barPosChanged +// +// Ensures that any autohide appbar has the topmost zOrder when any non autohide +// appbar's position has changed. +// +// ABM_WINDOWPOSCHANGED +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// +LRESULT TrayService::barPosChanged(const APPBARDATAV1& abd) +{ + LRESULT lResult = 0; + AppBar* p; + + if (getBar((HWND)abd.hWnd, p) && !p->IsAutoHide()) + { + lResult = 1; + + BarVector::iterator itBar = findBar(p->hMon(), p->uEdge(), ABS_AUTOHIDE); + + if (itBar != m_abVector.end()) + { + PostMessage( + m_hTrayWnd + ,ABP_RAISEAUTOHIDEHWND + ,(WPARAM)(*itBar)->hWnd() + ,(LPARAM)(*itBar)->uEdge() + ); + } + } + + return lResult; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// barSetTaskBarState +// +// Sets the current TaskBar state (autohide, alwaysontop) +// +// ABM_SETSTATE +// +// Valid APPBARDATA members: +// +// cbSize +// hWnd +// lParam +// +LRESULT TrayService::barSetTaskBarState(const APPBARDATAV1& abd) +{ + return 0; + UNREFERENCED_PARAMETER(abd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyOverlapBar +// +// Helper function to barSetPos and barQueryPos +// +void TrayService::modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + // Use entire screen for default rectangle + HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); + + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(GetMonitorInfo(hMon, &mi)) + { + CopyRect(&rcDst, &mi.rcMonitor); + } + else + { + SetRect(&rcDst, + 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + } + + // Set the bar's extent + modifyBarExtent(rcDst, rcOrg, uEdge); + + // The bar's position is anchored at the desktop edge - so nothing to do + + // Set the bar's breadth + modifyBarBreadth(rcDst, rcOrg, uEdge); + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyNormalBar +// +// Helper function to barSetPos and barQueryPos +// +void TrayService::modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd) +{ + BarVector::const_iterator it; + AppBar* p; + bool bFound = FALSE; + + // Use entire screen for default rectangle + HMONITOR hMon = MonitorFromRect(&rcOrg, MONITOR_DEFAULTTOPRIMARY); + HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); + + if(hMonPrimary == hMon) + { + // Use only the original workarea for the default rectangle + CopyRect(&rcDst, &m_rWorkAreaDef); + } + else + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if(GetMonitorInfo(hMon, &mi)) + { + CopyRect(&rcDst, &mi.rcMonitor); + } + else + { + ASSERT(FALSE); + + // Use only the original workarea for the default rectangle + CopyRect(&rcDst, &m_rWorkAreaDef); + hMon = hMonPrimary; + } + } + + // Set the bar's extent + modifyBarExtent(rcDst, rcOrg, uEdge); + + // Set the bar's position + for (it = m_abVector.begin(); it != m_abVector.end(); ++it) + { + p = *it; + + // ignore overlap bars and invalid windows and other monitors + if(!p || p->IsOverLap() || hMon != p->hMon()) + { + // do nothing + } + // if this is our appbar, mark it found and continue + else if (hWnd == p->hWnd()) + { + bFound = true; + } + // ignore bars that haven't been initialized + else if (ABS_CLEANRECT != (ABS_CLEANRECT & p->lParam())) + { + // do nothing + } + // Ignore other edge appbars for the most part + else if (uEdge != p->uEdge()) + { + // Left/Right bars must resize to top/bottom bars + if (ABE_HORIZONTAL != (ABE_HORIZONTAL & uEdge) + && + ABE_HORIZONTAL == (ABE_HORIZONTAL & p->uEdge())) + { + RECT rc; // dummy + + // If our destination rectangle currently intersects + // then resize it + if (IntersectRect(&rc, &p->GetRectRef(), &rcDst)) + { + if (ABE_TOP == p->uEdge()) + { + rcDst.top = p->GetRectRef().bottom; + } + else + { + rcDst.bottom = p->GetRectRef().top; + } + } + } + } + // Keep moving the destination appbar while we are looking + // at same edge appbars before our own. Once we find our + // own, then we ignore all same edge appbars after ours. + else if (!bFound) + { + switch (uEdge) + { + case ABE_LEFT: + rcDst.left = p->GetRectRef().right; + break; + case ABE_TOP: + rcDst.top = p->GetRectRef().bottom; + break; + case ABE_RIGHT: + rcDst.right = p->GetRectRef().left; + break; + case ABE_BOTTOM: + rcDst.bottom = p->GetRectRef().top; + break; + } + } + } + + // Set the bar's breadth + modifyBarBreadth(rcDst, rcOrg, uEdge); + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyBarExtent +// +// Helper function to modifyNormalBar and modifyOverlapBar +// +void TrayService::modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + switch (uEdge) + { + case ABE_LEFT: + case ABE_RIGHT: + rcDst.top = std::max(rcDst.top, rcOrg.top); + rcDst.bottom = std::min(rcDst.bottom, rcOrg.bottom); + break; + case ABE_TOP: + case ABE_BOTTOM: + rcDst.left = std::max(rcDst.left, rcOrg.left); + rcDst.right = std::min(rcDst.right, rcOrg.right); + break; + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyBarBreadth +// +// Helper function to modifyBarNormal and modifyBarOverlap +// +void TrayService::modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge) +{ + switch (uEdge) + { + case ABE_LEFT: + rcDst.right = rcDst.left + (rcOrg.right - rcOrg.left); + break; + case ABE_TOP: + rcDst.bottom = rcDst.top + (rcOrg.bottom - rcOrg.top); + break; + case ABE_RIGHT: + rcDst.left = rcDst.right - (rcOrg.right - rcOrg.left); + break; + case ABE_BOTTOM: + rcDst.top = rcDst.bottom - (rcOrg.bottom - rcOrg.top); + break; + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// adjustWorkArea +// +// Helper function to barSetPos (via ABP_NOTIFYPOSCHANGED) +// +void TrayService::adjustWorkArea(HMONITOR hMon) +{ + RECT rcWorker, rcMonitor, rcWorkArea; + + HMONITOR hMonPrimary = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY); + + if (hMon != hMonPrimary) + { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + + if (!GetMonitorInfo(hMon, &mi)) + { + return; + } + + CopyRect(&rcMonitor, &mi.rcMonitor); + CopyRect(&rcWorkArea, &mi.rcWork); + } + else + { + CopyRect(&rcMonitor, &m_rWorkAreaDef); // yes, we actually want this + CopyRect(&rcWorkArea, &m_rWorkAreaCur); + } + + CopyRect(&rcWorker, &rcMonitor); + + for ( + BarVector::iterator it = m_abVector.begin() + ;it != m_abVector.end() + ;++it + ) + { + AppBar* p = *it; + + if(p && !p->IsOverLap() && p->hMon() == hMon && + (ABS_CLEANRECT == (ABS_CLEANRECT & p->lParam()))) + { + if (!IsWindow(p->hWnd())) + { + continue; + } + + RECT rcBarEx; + + CopyRect(&rcBarEx, &rcMonitor); + + switch (p->uEdge()) + { + case ABE_LEFT: + rcBarEx.right = p->GetRectRef().right; + break; + case ABE_RIGHT: + rcBarEx.left = p->GetRectRef().left; + break; + case ABE_TOP: + rcBarEx.bottom = p->GetRectRef().bottom; + break; + case ABE_BOTTOM: + rcBarEx.top = p->GetRectRef().top; + break; + } + + SubtractRect(&rcWorker, &rcWorker, &rcBarEx); + } + } + + if(!EqualRect(&rcWorker, &rcWorkArea)) + { + setWorkArea(&rcWorker); + } + + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setWorkArea +// +// Helper function for setting the specified work area +// +void TrayService::setWorkArea(LPRECT prcWorkArea) +{ + if (m_hTrayWnd) + { + m_uWorkAreaDirty++; + } + + SystemParametersInfo( + SPI_SETWORKAREA + ,1 // readjust maximized windows + ,prcWorkArea + ,0 // SPIF_SENDCHANGE - see below + ); + SendNotifyMessage( // used in place of SPIF_SENDCHANGE above to avoid lockups + HWND_BROADCAST // see http://blogs.msdn.com/oldnewthing/archive/2005/03/10/392118.aspx + ,WM_SETTINGCHANGE + ,SPI_SETWORKAREA + ,0 + ); + return; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ABLock +// +// Calls SHLockShared API for the specified Shell AppBar memory +// +// Returns a pointer to shared memory location for an AppBarData structure +// +PAPPBARDATAV1 TrayService::ABLock(PSHELLAPPBARDATA psad) +{ + return (PAPPBARDATAV1)SHLockShared( + psad->hSharedMemory, psad->dwSourceProcessId); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// ABUnlock +// +// Calls SHUnlockShared API for the specified AppBarData* memory +// +void TrayService::ABUnLock(PAPPBARDATAV1 pabd) +{ + SHUnlockShared(pabd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// FindAppBarPredicate_hWnd +// +// Predicate for std::find_if, used by findBar variants +// Needs to be at global scope because of mingw issues +// +// Find the appbar matching the specified hWnd +// +struct FindAppBarPredicate_hWnd +{ + FindAppBarPredicate_hWnd(HWND hWnd) : + m_hWnd(hWnd) + { + // do nothing + } + FindAppBarPredicate_hWnd(const FindAppBarPredicate_hWnd& copy) : + m_hWnd(copy.m_hWnd) + { + // do nothing + } + + bool operator() (const AppBar* pab) const + { + return (pab->hWnd() == m_hWnd); + } + +private: + const HWND m_hWnd; + +private: + // Not implemented + FindAppBarPredicate_hWnd& operator=(const FindAppBarPredicate_hWnd&); +}; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// FindAppBarPredicate_MatchLParam +// +// Predicate for std::find_if, used by findBar variants +// Needs to be at global scope because of mingw issues +// +// Find the appbar on the specified edge that has a matching lParam value +// +struct FindAppBarPredicate_MatchLParam +{ + FindAppBarPredicate_MatchLParam(HMONITOR hMon, UINT uEdge, LPARAM lParam) : + m_hMon(hMon), m_uEdge(uEdge), m_lParam(lParam) + { + // do nothing + } + FindAppBarPredicate_MatchLParam(const FindAppBarPredicate_MatchLParam& copy) : + m_hMon(copy.m_hMon), m_uEdge(copy.m_uEdge), m_lParam(copy.m_lParam) + { + // do nothing + } + + bool operator() (const AppBar* pab) const + { + return (pab->hMon() == m_hMon && pab->uEdge() == m_uEdge && + m_lParam == (pab->lParam() & m_lParam)); + } + +private: + const HMONITOR m_hMon; + const UINT m_uEdge; + const LPARAM m_lParam; + +private: + // Not implemented + FindAppBarPredicate_MatchLParam& operator=(const FindAppBarPredicate_MatchLParam&); +}; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// findBar +// +// Looks up an AppBar in the AppBarList +// +BarVector::iterator TrayService::findBar(HWND hWnd) +{ + return std::find_if(m_abVector.begin(), m_abVector.end(), + FindAppBarPredicate_hWnd(hWnd)); +} +BarVector::iterator TrayService::findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam) +{ + return std::find_if(m_abVector.begin(), m_abVector.end(), + FindAppBarPredicate_MatchLParam(hMon, uEdge, lParam)); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// isBar +// +// Determines whether the HWND is associated with any current AppBar. +// +bool TrayService::isBar(HWND hWnd) +{ + return m_abVector.end() != findBar(hWnd); +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// getBar +// +// Looks up an BarVector iterator based on the HWND +// +// returns true if found, otherwise false. +// +bool TrayService::getBar(HWND hWnd, BarVector::iterator& itBar) +{ + bool bReturn = false; + + itBar = findBar(hWnd); + + if (itBar != m_abVector.end()) + { + bReturn = true; + } + + return bReturn; +} + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// getBar +// +// Looks up an AppBar* based on the HWND +// +// Returns true if found, otherwise false. +// +bool TrayService::getBar(HWND hWnd, AppBar*& pBarRef) +{ + bool bReturn = false; + BarVector::iterator itBar; + + if (getBar(hWnd, itBar)) + { + pBarRef = *itBar; + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// HandleNotification +// +// Handler for all system tray notifications +// +BOOL TrayService::HandleNotification(PSHELLTRAYDATA pstd) +{ + bool bReturn = false; + + switch (pstd->dwMessage) + { + case NIM_ADD: + bReturn = addIcon(pstd->nid); + break; + + case NIM_MODIFY: + bReturn = modifyIcon(pstd->nid); + break; + + case NIM_DELETE: + bReturn = deleteIcon(pstd->nid); + break; + + case NIM_SETFOCUS: + bReturn = setFocusIcon(pstd->nid); + break; + + case NIM_SETVERSION: + bReturn = setVersionIcon(pstd->nid); + break; + + default: + TRACE("Unknown NIM: %u", pstd->dwMessage); + break; + } + + return bReturn ? TRUE : FALSE; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// notify +// +// Notify all listeners of a systray event +// +bool TrayService::notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const +{ + return 0 != SendMessage(m_hLiteStep, LM_SYSTRAY, + dwMessage, (LPARAM)pclsnid); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// SendSystemTray +// +// Resend all icon data; systray modules will request this via LM_SYSTRAYREADY +// during their startup. +// +HWND TrayService::SendSystemTray() +{ + removeDeadIcons(); + + for (IconVector::const_iterator it = m_siVector.begin(); + it != m_siVector.end(); ++it) + { + if ((*it)->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + (*it)->CopyLSNID(&lsnid); + + notify(NIM_ADD, &lsnid); + } + } + + return m_hNotifyWnd; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// removeDeadIcons +// +// Removes all "dead" icons. ie. Those that no longer have a valid HWND +// associated with them. +// +void TrayService::removeDeadIcons() +{ + IconVector::iterator it = m_siVector.begin(); + + while (it != m_siVector.end()) + { + if (IsWindow((*it)->GetHwnd())) + { + ++it; + continue; + } + + delete *it; + it = m_siVector.erase(it); + } + + return; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// extendNIDCopy +// +// Copies all non-persistent data that is not stored in NotifyIcon. +// +bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const +{ + // Copy Info Tips + if (nid.uFlags & NIF_INFO) + { + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_5W_SIZE: + { + NID_5W* pnid = (NID_5W*)&nid; + + int nReturn; + WCHAR szTemp[256]; + + memcpy(szTemp, pnid->szInfo, sizeof(WCHAR)*256); + szTemp[255] = 0; + nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, + lsnid.szInfo, TRAY_MAX_INFO_LENGTH, NULL, NULL); + + if (!nReturn) + { + lsnid.szInfo[0] = 0; + } + + memcpy(szTemp, pnid->szInfoTitle, sizeof(WCHAR)*64); + szTemp[63] = 0; + nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, + lsnid.szInfoTitle, TRAY_MAX_INFOTITLE_LENGTH, NULL, NULL); + + if (!nReturn) + { + lsnid.szInfoTitle[0] = 0; + } + + lsnid.dwInfoFlags = pnid->dwInfoFlags; + lsnid.uTimeout = pnid->uTimeout; + lsnid.uFlags |= NIF_INFO; + } + break; + case NID_6A_SIZE: + case NID_5A_SIZE: + { + NID_5A* pnid = (NID_5A*)&nid; + + HRESULT hr; + + hr = StringCchCopy(lsnid.szInfo, + TRAY_MAX_INFO_LENGTH, pnid->szInfo); + + if (FAILED(hr)) + { + lsnid.szInfo[0] = 0; + } + + hr = StringCchCopy(lsnid.szInfoTitle, + TRAY_MAX_INFOTITLE_LENGTH, pnid->szInfoTitle); + + if (FAILED(hr)) + { + lsnid.szInfoTitle[0] = 0; + } + + lsnid.dwInfoFlags = pnid->dwInfoFlags; + lsnid.uTimeout = pnid->uTimeout; + lsnid.uFlags |= NIF_INFO; + } + break; + default: + { + // do nothing + } + break; + } + } + + // Copy GUID + if (nid.uFlags & NIF_GUID) + { + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + { + NID_6W* pnid = (NID_6W*)&nid; + + lsnid.guidItem = pnid->guidItem; + lsnid.uFlags |= NIF_GUID; + } + break; + case NID_6A_SIZE: + { + NID_6A* pnid = (NID_6A*)&nid; + + lsnid.guidItem = pnid->guidItem; + lsnid.uFlags |= NIF_GUID; + } + break; + default: + { + // do nothing + } + break; + } + } + + return true; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// addIcon +// +bool TrayService::addIcon(const NID_XX& nid) +{ + bool bReturn = false; + + if (m_siVector.end() == findIcon(nid)) + { + NotifyIcon * pni = new NotifyIcon(nid); + + if (pni) + { + // Fail shared icons, unless a valid hIcon exists + if (IsWindow(pni->GetHwnd()) && + (!pni->IsShared() || pni->HasIcon())) + { + m_siVector.push_back(pni); + + if (pni->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + pni->CopyLSNID(&lsnid); + extendNIDCopy(lsnid, nid); + + notify(NIM_ADD, &lsnid); + } + bReturn = true; + } + else + { + delete pni; + } + } + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// modifyIcon +// +bool TrayService::modifyIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it && *it) + { + NotifyIcon * pni = *it; + + bool bWasValid = pni->IsValid(); + + // Update stored NotifyIcon + pni->Update(nid); + + if (pni->IsValid()) + { + LSNOTIFYICONDATA lsnid = { 0 }; + + if (!bWasValid) + { + // This is a "new" icon, send entire stored NotifyIcon + pni->CopyLSNID(&lsnid); + extendNIDCopy(lsnid, nid); + + notify(NIM_ADD, &lsnid); + } + else + { + // This icon already exists, just send updated flags + pni->CopyLSNID(&lsnid, nid.uFlags); + extendNIDCopy(lsnid, nid); + + notify(NIM_MODIFY, &lsnid); + } + } + else if (bWasValid) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,pni->GetHwnd() + ,pni->GetuID() + ,0 + }; + + // This icon is no longer visible, remove + notify(NIM_DELETE, &lsnid); + } + + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// deleteIcon +// +// Remove an icon from the icon list +// +bool TrayService::deleteIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + notify(NIM_DELETE, &lsnid); + + delete *it; + m_siVector.erase(it); + + bReturn = true; + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setFocusIcon +// +// Sets selection focus to the specified icon +// +bool TrayService::setFocusIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + bReturn = notify(NIM_SETFOCUS, &lsnid); + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// setVersionIcon +// +// Sets compatibility version for specified icon +// +bool TrayService::setVersionIcon(const NID_XX& nid) +{ + bool bReturn = false; + + IconVector::iterator it = findIcon(nid); + + if (m_siVector.end() != it) + { + LSNOTIFYICONDATA lsnid = { + sizeof(LSNOTIFYICONDATA) + ,(*it)->GetHwnd() + ,(*it)->GetuID() + ,0 + }; + + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_5W_SIZE: + lsnid.uVersion = ((NID_5W&)nid).uVersion; + break; + + case NID_6A_SIZE: + case NID_5A_SIZE: + lsnid.uVersion = ((NID_5A&)nid).uVersion; + break; + + default: + break; + } + + bReturn = notify(NIM_SETVERSION, &lsnid); + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// findIcon +// +// Looks up an icon in the SystrayIconList +// +IconVector::iterator TrayService::findIcon(const NID_XX& nid) +{ + GUID guidItem; + + switch (nid.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + guidItem = ((NID_6W&)nid).guidItem; + break; + + case NID_6A_SIZE: + guidItem = ((NID_6A&)nid).guidItem; + break; + + default: + break; + } + + for (IconVector::iterator iter = m_siVector.begin(); iter != m_siVector.end(); iter++) + { + // If the GUID is valid, we ignore the uID and hWnd + if ((nid.uFlags & NIF_GUID) == NIF_GUID) + { + if (guidItem == (*iter)->GetGUID()) + { + return iter; + } + } + else if((*iter)->GetuID() == nid.uID && (*iter)->GetHwnd() == (HWND)nid.hWnd) + { + return iter; + } + } + + return m_siVector.end(); +} diff --git a/litestep/TrayService.h b/litestep/TrayService.h index 6af622a..0b6bb09 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -1,234 +1,234 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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. -// -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#if !defined(TRAYSERVICE_H) -#define TRAYSERVICE_H - -#include "TrayNotifyIcon.h" -#include "TrayAppBar.h" -#include "../utility/common.h" -#include "../utility/IService.h" -#include -#include - -// shell copy data types -#define SH_APPBAR_DATA (0) -#define SH_TRAY_DATA (1) -#define SH_LOADPROC_DATA (2) -#define SH_TRAYINFO_DATA (3) - -// internally posted AppBar messages -#define ABP_NOTIFYPOSCHANGED (WM_USER+350) -#define ABP_NOTIFYSTATECHANGE (WM_USER+351) -#define ABP_RAISEAUTOHIDEHWND (WM_USER+360) - -// data sent to TrayInfoEvent -typedef struct _NOTIFYICONIDENTIFIER_MSGV1 -{ - DWORD dwMagic; - DWORD dwMessage; - DWORD cbSize; - DWORD dwPadding; - HWND hWnd; - UINT uID; - GUID guidItem; -} NOTIFYICONIDENTIFIER_MSGV1, *LPNOTIFYICONIDENTIFIER_MSGV1; - -// data sent by shell via Shell_NotifyIcon -typedef struct _SHELLTRAYDATA -{ - DWORD dwUnknown; - DWORD dwMessage; - NID_XX nid; -} *PSHELLTRAYDATA; - -// Data sent with AppBar Message -typedef struct _SHELLAPPBARDATA -{ - _SHELLAPPBARDATA(APPBARDATAV1& abdsrc):abd(abdsrc) - { - // do nothing - } - - const APPBARDATAV1& abd; - /**/ - DWORD dwMessage; - HANDLE hSharedMemory; - DWORD dwSourceProcessId; - /**/ - -private: - // Not implemented - _SHELLAPPBARDATA(const _SHELLAPPBARDATA&); - _SHELLAPPBARDATA& operator=(const _SHELLAPPBARDATA&); -} SHELLAPPBARDATA, *PSHELLAPPBARDATA; - - -// Data sent with SHLoadInProc/SHEnableServiceObject on XP and up -// Earlier versions don't have SHEnableServiceObject and only send the CLSID -typedef struct _SHELLINPROCDATA -{ - CLSID clsid; - DWORD dwMessage; -} SHELLINPROCDATA, *PSHELLINPROCDATA; - -typedef std::vector IconVector; -typedef std::vector BarVector; -typedef std::vector SsoVector; - - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// -// TrayService -// -// This is the tray service handler. It keeps track of all systray icons and -// loads ShellService-objects. If an icon is added/removed/modified/... it -// notifies all listeners (usually the systray module) via LM_SYSTRAY. -// -class TrayService : public IService -{ -public: - ~TrayService(); - TrayService(); - - // - // IService methods - // - virtual HRESULT Start(); - virtual HRESULT Stop(); - - // resend all icon data - HWND SendSystemTray(); - - // Notify TrayService of full screen app change - void NotifyRudeApp(HMONITOR hFullScreenMonitor) const; - - // Message Handler - static LRESULT CALLBACK WindowTrayProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK WindowNotifyProc(HWND, UINT, WPARAM, LPARAM); - -private: - HRESULT createWindows(); - void destroyWindows(); - - // - // manage COM based shell services - // - HRESULT loadShellServiceObject(REFCLSID rclsid); - void loadShellServiceObjects(); - void unloadShellServiceObjects(); - - // Handlers for AppBar messages - LRESULT HandleAppBarCopydata(DWORD cbData, LPVOID lpData); - LRESULT HandleAppBarMessage(PSHELLAPPBARDATA psad); - - // Handler for tray info event - LRESULT TrayInfoEvent(DWORD cbData, LPVOID lpData); - - // Handler for system tray notifications - BOOL HandleNotification(PSHELLTRAYDATA pstd); - - // Handler for LoadInProc messages - HRESULT HandleLoadInProc(REFCLSID clsid, DWORD dwMessage); - - // - // ABM_* Notification handlers - // - LRESULT barCreate(const APPBARDATAV1& abd); - LRESULT barDestroy(const APPBARDATAV1& abd); - LRESULT barQueryPos(PSHELLAPPBARDATA psad); - LRESULT barSetPos(PSHELLAPPBARDATA psad); - LRESULT barGetTaskBarState(); - LRESULT barGetTaskBarPos(PSHELLAPPBARDATA psad); - LRESULT barActivate(const APPBARDATAV1& abd); - LRESULT barGetAutoHide(const APPBARDATAV1& abd); - LRESULT barSetAutoHide(const APPBARDATAV1& abd); - LRESULT barPosChanged(const APPBARDATAV1& abd); - LRESULT barSetTaskBarState(const APPBARDATAV1& abd); - - // - // barSetPos and barQueryPos helpers - // - void modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd); - void modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge); - void adjustWorkArea(HMONITOR hMon); - void setWorkArea(LPRECT prcWorkArea); - - // Remove any "dead" appbars - void removeDeadAppBars(); - - // - // AppBar Un/Lock handlers for shared data - // - PAPPBARDATAV1 ABLock(PSHELLAPPBARDATA psad); - void ABUnLock(PAPPBARDATAV1 pabd); - - // - // findBar variants and wrappers - // - BarVector::iterator findBar(HWND hWnd); - BarVector::iterator findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam); - bool isBar(HWND hWnd); - bool getBar(HWND hWnd, BarVector::iterator& itAppBar); - bool getBar(HWND hWnd, AppBar*& pBarRef); - - // - // NIM_* Notification handlers - // - bool addIcon(const NID_XX& nid); // NIM_ADD - bool modifyIcon(const NID_XX& nid); // NIM_MODIFY - bool deleteIcon(const NID_XX& nid); // NIM_DELETE - bool setFocusIcon(const NID_XX& nid); // NIM_SETFOCUS - bool setVersionIcon(const NID_XX& nid); // NIM_SETVERSION - - // - // Send icon notifications on to LiteStep (thus systray modules) - // - bool notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const; - bool extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const; - - // Remove any "dead" icons - void removeDeadIcons(); - - // - // finds the icon which matches the specified nid - // - IconVector::iterator findIcon(const NID_XX& nid); - - // - // - // - UINT m_uWorkAreaDirty; - RECT m_rWorkAreaDef; // The Working Area without any appbars. - RECT m_rWorkAreaCur; // The Working Area with the appbars. - HWND m_hNotifyWnd; - HWND m_hTrayWnd; - HWND m_hLiteStep; - HINSTANCE m_hInstance; - - SsoVector m_ssoVector; - IconVector m_siVector; - BarVector m_abVector; -}; - -#endif // TRAYSERVICE_H +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(TRAYSERVICE_H) +#define TRAYSERVICE_H + +#include "TrayNotifyIcon.h" +#include "TrayAppBar.h" +#include "../utility/common.h" +#include "../utility/IService.h" +#include +#include + +// shell copy data types +#define SH_APPBAR_DATA (0) +#define SH_TRAY_DATA (1) +#define SH_LOADPROC_DATA (2) +#define SH_TRAYINFO_DATA (3) + +// internally posted AppBar messages +#define ABP_NOTIFYPOSCHANGED (WM_USER+350) +#define ABP_NOTIFYSTATECHANGE (WM_USER+351) +#define ABP_RAISEAUTOHIDEHWND (WM_USER+360) + +// data sent to TrayInfoEvent +typedef struct _NOTIFYICONIDENTIFIER_MSGV1 +{ + DWORD dwMagic; + DWORD dwMessage; + DWORD cbSize; + DWORD dwPadding; + HWND hWnd; + UINT uID; + GUID guidItem; +} NOTIFYICONIDENTIFIER_MSGV1, *LPNOTIFYICONIDENTIFIER_MSGV1; + +// data sent by shell via Shell_NotifyIcon +typedef struct _SHELLTRAYDATA +{ + DWORD dwUnknown; + DWORD dwMessage; + NID_XX nid; +} *PSHELLTRAYDATA; + +// Data sent with AppBar Message +typedef struct _SHELLAPPBARDATA +{ + _SHELLAPPBARDATA(APPBARDATAV1& abdsrc):abd(abdsrc) + { + // do nothing + } + + const APPBARDATAV1& abd; + /**/ + DWORD dwMessage; + HANDLE hSharedMemory; + DWORD dwSourceProcessId; + /**/ + +private: + // Not implemented + _SHELLAPPBARDATA(const _SHELLAPPBARDATA&); + _SHELLAPPBARDATA& operator=(const _SHELLAPPBARDATA&); +} SHELLAPPBARDATA, *PSHELLAPPBARDATA; + + +// Data sent with SHLoadInProc/SHEnableServiceObject on XP and up +// Earlier versions don't have SHEnableServiceObject and only send the CLSID +typedef struct _SHELLINPROCDATA +{ + CLSID clsid; + DWORD dwMessage; +} SHELLINPROCDATA, *PSHELLINPROCDATA; + +typedef std::vector IconVector; +typedef std::vector BarVector; +typedef std::vector SsoVector; + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// TrayService +// +// This is the tray service handler. It keeps track of all systray icons and +// loads ShellService-objects. If an icon is added/removed/modified/... it +// notifies all listeners (usually the systray module) via LM_SYSTRAY. +// +class TrayService : public IService +{ +public: + ~TrayService(); + TrayService(); + + // + // IService methods + // + virtual HRESULT Start(); + virtual HRESULT Stop(); + + // resend all icon data + HWND SendSystemTray(); + + // Notify TrayService of full screen app change + void NotifyRudeApp(HMONITOR hFullScreenMonitor) const; + + // Message Handler + static LRESULT CALLBACK WindowTrayProc(HWND, UINT, WPARAM, LPARAM); + static LRESULT CALLBACK WindowNotifyProc(HWND, UINT, WPARAM, LPARAM); + +private: + HRESULT createWindows(); + void destroyWindows(); + + // + // manage COM based shell services + // + HRESULT loadShellServiceObject(REFCLSID rclsid); + void loadShellServiceObjects(); + void unloadShellServiceObjects(); + + // Handlers for AppBar messages + LRESULT HandleAppBarCopydata(DWORD cbData, LPVOID lpData); + LRESULT HandleAppBarMessage(PSHELLAPPBARDATA psad); + + // Handler for tray info event + LRESULT TrayInfoEvent(DWORD cbData, LPVOID lpData); + + // Handler for system tray notifications + BOOL HandleNotification(PSHELLTRAYDATA pstd); + + // Handler for LoadInProc messages + HRESULT HandleLoadInProc(REFCLSID clsid, DWORD dwMessage); + + // + // ABM_* Notification handlers + // + LRESULT barCreate(const APPBARDATAV1& abd); + LRESULT barDestroy(const APPBARDATAV1& abd); + LRESULT barQueryPos(PSHELLAPPBARDATA psad); + LRESULT barSetPos(PSHELLAPPBARDATA psad); + LRESULT barGetTaskBarState(); + LRESULT barGetTaskBarPos(PSHELLAPPBARDATA psad); + LRESULT barActivate(const APPBARDATAV1& abd); + LRESULT barGetAutoHide(const APPBARDATAV1& abd); + LRESULT barSetAutoHide(const APPBARDATAV1& abd); + LRESULT barPosChanged(const APPBARDATAV1& abd); + LRESULT barSetTaskBarState(const APPBARDATAV1& abd); + + // + // barSetPos and barQueryPos helpers + // + void modifyOverlapBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void modifyNormalBar(RECT& rcDst, const RECT& rcOrg, UINT uEdge, HWND hWnd); + void modifyBarExtent(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void modifyBarBreadth(RECT& rcDst, const RECT& rcOrg, UINT uEdge); + void adjustWorkArea(HMONITOR hMon); + void setWorkArea(LPRECT prcWorkArea); + + // Remove any "dead" appbars + void removeDeadAppBars(); + + // + // AppBar Un/Lock handlers for shared data + // + PAPPBARDATAV1 ABLock(PSHELLAPPBARDATA psad); + void ABUnLock(PAPPBARDATAV1 pabd); + + // + // findBar variants and wrappers + // + BarVector::iterator findBar(HWND hWnd); + BarVector::iterator findBar(HMONITOR hMon, UINT uEdge, LPARAM lParam); + bool isBar(HWND hWnd); + bool getBar(HWND hWnd, BarVector::iterator& itAppBar); + bool getBar(HWND hWnd, AppBar*& pBarRef); + + // + // NIM_* Notification handlers + // + bool addIcon(const NID_XX& nid); // NIM_ADD + bool modifyIcon(const NID_XX& nid); // NIM_MODIFY + bool deleteIcon(const NID_XX& nid); // NIM_DELETE + bool setFocusIcon(const NID_XX& nid); // NIM_SETFOCUS + bool setVersionIcon(const NID_XX& nid); // NIM_SETVERSION + + // + // Send icon notifications on to LiteStep (thus systray modules) + // + bool notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const; + bool extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) const; + + // Remove any "dead" icons + void removeDeadIcons(); + + // + // finds the icon which matches the specified nid + // + IconVector::iterator findIcon(const NID_XX& nid); + + // + // + // + UINT m_uWorkAreaDirty; + RECT m_rWorkAreaDef; // The Working Area without any appbars. + RECT m_rWorkAreaCur; // The Working Area with the appbars. + HWND m_hNotifyWnd; + HWND m_hTrayWnd; + HWND m_hLiteStep; + HINSTANCE m_hInstance; + + SsoVector m_ssoVector; + IconVector m_siVector; + BarVector m_abVector; +}; + +#endif // TRAYSERVICE_H diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index ee8703c..40bba50 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -1,278 +1,278 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2012 LiteStep Development 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. -// -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -#if !defined(LSAPIDEFINES_H) -#define LSAPIDEFINES_H - -/* -* IMPORTANT: -* The exports and definitions included -* with LSAPI_PRIVATE are for INTERNAL USE ONLY! -* -* They MUST NOT be used by any module. -* Their names and/or functionality may be changed at ANY time! -* -*/ - -#include "../utility/common.h" - - -//----------------------------------------------------------------------------- -// MATCH.CPP DEFINES -//----------------------------------------------------------------------------- -#define MATCH_PATTERN 6 /* bad pattern */ -#define MATCH_LITERAL 5 /* match failure on literal match */ -#define MATCH_RANGE 4 /* match failure on [..] construct */ -#define MATCH_ABORT 3 /* premature end of text string */ -#define MATCH_END 2 /* premature end of pattern string */ -#define MATCH_VALID 1 /* valid match */ - -/* pattern defines */ -#define PATTERN_VALID 0 /* valid pattern */ -#define PATTERN_ESC -1 /* literal escape at end of pattern */ -#define PATTERN_RANGE -2 /* malformed range in [..] construct */ -#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */ -#define PATTERN_EMPTY -4 /* [..] contstruct is empty */ - - -//----------------------------------------------------------------------------- -// MESSAGE DEFINES -//----------------------------------------------------------------------------- -#define LM_SHUTDOWN 8889 -#define LM_REPAINT 8890 -#define LM_BRINGTOFRONT 8891 -#define LM_SAVEDATA 8892 -#define LM_RESTOREDATA 8893 -#define LM_POPUP 9182 -#define LM_HIDEPOPUP 9183 -#define LM_FIRSTDESKTOPPAINT 9184 // Deprecated -#define LM_LSSELECT 9185 -#define LM_SETTASKBARONTOP 9186 // Deprecated -#define LM_SAVESYSTRAY 9210 // Deprecated -#define LM_RESTORESYSTRAY 9211 // Deprecated -#define LM_CHECKFORAPPBAR 9212 // Deprecated -#define LM_SENDSYSTRAY 9213 -#define LM_SYSTRAY 9214 -#define LM_SYSTRAYREADY 9215 -#define LM_SYSTRAYINFOEVENT 9216 - -// Shell Hook Messages (obsolete!) -#define LM_SHELLMESSAGE 9219 -#define LM_ACCESSSTATE 9220 -#define LM_ACTIVESHELLWIN LM_ACCESSSTATE + 1 -#define LM_APPCOMMANDX LM_ACCESSSTATE + 2 -#define LM_MINMAXWIN LM_ACCESSSTATE + 3 -#define LM_LANGUAGEX LM_ACCESSSTATE + 4 -#define LM_REDRAWX LM_ACCESSSTATE + 5 -#define LM_TASKMANX LM_ACCESSSTATE + 6 -#define LM_ACTIVEWIN LM_ACCESSSTATE + 7 -#define LM_ADDWINDOW LM_ACCESSSTATE + 8 -#define LM_REMOVEWINDOW LM_ACCESSSTATE + 9 //9229 - -#define LM_RECYCLE 9260 -#define LM_REGISTERMESSAGE 9263 -#define LM_UNREGISTERMESSAGE 9264 -#define LM_GETREVID 9265 -#define LM_UNLOADMODULE 9266 -#define LM_RELOADMODULE 9267 -#define LM_REGISTERHOOKMESSAGE 9268 // Deprecated -#define LM_UNREGISTERHOOKMESSAGE 9269 // Deprecated -#define LM_SHADETOGGLE 9300 -#define LM_REFRESH 9305 - -// Threaded Module Messages -#if defined(LSAPI_PRIVATE) -#define LM_THREAD_BANGCOMMAND 9310 -#define LM_THREADREADY 9311 -#define LM_THREADFINISHED 9312 -#endif - -// VWM Messages -#define LM_VWMUP 9350 -#define LM_VWMDOWN 9351 -#define LM_VWMLEFT 9352 -#define LM_VWMRIGHT 9353 -#define LM_VWMNAV 9354 -#define LM_SWITCHTON 9355 -#define LM_ISSTICKY 9356 -#define LM_STICK 9357 -#define LM_UNSTICK 9358 -#define LM_LISTDESKTOPS 9359 -#define LM_DESKTOPINFO 9360 -#define LM_GETDESKTOPOF 9361 - -// Core Messages -#if defined(LSAPI_PRIVATE) -#define LM_GETLSOBJECT 9400 // Deprecated -#define LM_WINDOWLIST 9401 // Deprecated -#define LM_DATASTORE 9410 // Deprecated -#define LM_MESSAGEMANAGER 9411 // Deprecated -#define LM_BANGCOMMAND 9420 -#define LM_ENUMREVIDS 9430 -#define LM_ENUMMODULES 9431 -#define LM_ENUMPERFORMANCE 9432 -#endif - - -#define LM_SHELLHOOK 9500 // not an actual message - -// shell hook messages -#define LM_WINDOWCREATED (LM_SHELLHOOK + HSHELL_WINDOWCREATED) -#define LM_WINDOWDESTROYED (LM_SHELLHOOK + HSHELL_WINDOWDESTROYED) -#define LM_ACTIVATESHELLWINDOW (LM_SHELLHOOK + HSHELL_ACTIVATESHELLWINDOW) -#define LM_WINDOWACTIVATED (LM_SHELLHOOK + HSHELL_WINDOWACTIVATED) -#define LM_GETMINRECT (LM_SHELLHOOK + HSHELL_GETMINRECT) -#define LM_REDRAW (LM_SHELLHOOK + HSHELL_REDRAW) -#define LM_TASKMAN (LM_SHELLHOOK + HSHELL_TASKMAN) -#define LM_LANGUAGE (LM_SHELLHOOK + HSHELL_LANGUAGE) -#define LM_ACCESSIBILITYSTATE (LM_SHELLHOOK + HSHELL_ACCESSIBILITYSTATE) -#define LM_APPCOMMAND (LM_SHELLHOOK + HSHELL_APPCOMMAND) -#define LM_WINDOWREPLACED (LM_SHELLHOOK + HSHELL_WINDOWREPLACED) -#define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) -#define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) - - -//----------------------------------------------------------------------------- -// CONSTANT DEFINES -//----------------------------------------------------------------------------- -#define MAX_BANGCOMMAND 64 -#define MAX_BANGARGS 256 -#define MAX_RCCOMMAND 64 -#define MAX_LINE_LENGTH 4096 -#define MAX_PATH_LENGTH 1024 - -#define WHITESPACEW L" \t\n\r" -#define WHITESPACEA " \t\n\r" - -#define RESERVEDCHARSW L"\"\'[];$" -#define RESERVEDCHARSA "\"\'[];$" - -#if defined(_UNICODE) -#define WHITESPACE WHITESPACEW -#define RESERVEDCHARS RESERVEDCHARSW -#else -#define WHITESPACE WHITESPACEA -#define RESERVEDCHARS RESERVEDCHARSA -#endif - -#define HIDEmagicDWord 0x59474541 -#define magicDWord 0x49474541 - - -//----------------------------------------------------------------------------- -// MODULE ENTRY POINTS DEFINES -//----------------------------------------------------------------------------- -typedef int (__cdecl* initModuleExProc)(HWND, HINSTANCE, LPCSTR); -typedef void (__cdecl* quitModuleProc)(HINSTANCE); - - -//----------------------------------------------------------------------------- -// BANG COMMAND DEFINES -//----------------------------------------------------------------------------- -typedef void (__cdecl *BangCommand)(HWND hSender, LPCSTR pszArgs); -typedef void (__cdecl *BangCommandEx) \ - (HWND hSender, LPCSTR pszCommand, LPCSTR pszArgs); - -typedef struct _LMBANGCOMMANDA -{ - UINT cbSize; - HWND hWnd; - CHAR szCommand[MAX_BANGCOMMAND]; - CHAR szArgs[MAX_BANGARGS]; - // -} LMBANGCOMMANDA, *PLMBANGCOMMANDA; - -typedef struct _LMBANGCOMMANDW -{ - UINT cbSize; - HWND hWnd; - WCHAR wzCommand[MAX_BANGCOMMAND]; - WCHAR wzArgs[MAX_BANGARGS]; - // -} LMBANGCOMMANDW, *PLMBANGCOMMANDW; - -#if defined(_UNICODE) -#define LMBANGCOMMAND LMBANGCOMMANDW -#define PLMBANGCOMMAND PLMBANGCOMMANDW -#else // _UNICODE -#define LMBANGCOMMAND LMBANGCOMMANDA -#define PLMBANGCOMMAND PLMBANGCOMMANDA -#endif // _UNICODE - -//----------------------------------------------------------------------------- -// VWM DEFINES -//----------------------------------------------------------------------------- -typedef struct LSDESKTOPINFO -{ - int size; - char name[32]; - HICON icon; - BOOL isCurrent; - int number; - // -} LSDESKTOPINFO; - - -//----------------------------------------------------------------------------- -// LM_RECYCLE DEFINES -//----------------------------------------------------------------------------- -#define LR_RECYCLE 0 -#define LR_LOGOFF 1 -#define LR_QUIT 2 -#define LR_MSSHUTDOWN 3 - - -//----------------------------------------------------------------------------- -// LM_UN/RELOADMODULE DEFINES -//----------------------------------------------------------------------------- -#define LMM_PATH 0x0000 -#define LMM_HINSTANCE 0x1000 - - -//----------------------------------------------------------------------------- -// LSLOG LOG LEVEL CONSTANTS -//----------------------------------------------------------------------------- -#define LOG_ERROR 1 -#define LOG_WARNING 2 -#define LOG_NOTICE 3 -#define LOG_DEBUG 4 - - -//----------------------------------------------------------------------------- -// ENUMLSDATA DEFINES -//----------------------------------------------------------------------------- -#define ELD_BANGS 1 -#define ELD_MODULES 2 -#define ELD_REVIDS 3 -#define ELD_BANGS_V2 4 -#define ELD_PERFORMANCE 5 - -// ELD_MODULES: possible dwFlags values -#define LS_MODULE_THREADED 0x0001 -// LS_MODULE_NOTPUMPED 0x0002 no longer used - -typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); -typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); - -#endif // LSAPIDEFINES_H +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(LSAPIDEFINES_H) +#define LSAPIDEFINES_H + +/* +* IMPORTANT: +* The exports and definitions included +* with LSAPI_PRIVATE are for INTERNAL USE ONLY! +* +* They MUST NOT be used by any module. +* Their names and/or functionality may be changed at ANY time! +* +*/ + +#include "../utility/common.h" + + +//----------------------------------------------------------------------------- +// MATCH.CPP DEFINES +//----------------------------------------------------------------------------- +#define MATCH_PATTERN 6 /* bad pattern */ +#define MATCH_LITERAL 5 /* match failure on literal match */ +#define MATCH_RANGE 4 /* match failure on [..] construct */ +#define MATCH_ABORT 3 /* premature end of text string */ +#define MATCH_END 2 /* premature end of pattern string */ +#define MATCH_VALID 1 /* valid match */ + +/* pattern defines */ +#define PATTERN_VALID 0 /* valid pattern */ +#define PATTERN_ESC -1 /* literal escape at end of pattern */ +#define PATTERN_RANGE -2 /* malformed range in [..] construct */ +#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */ +#define PATTERN_EMPTY -4 /* [..] contstruct is empty */ + + +//----------------------------------------------------------------------------- +// MESSAGE DEFINES +//----------------------------------------------------------------------------- +#define LM_SHUTDOWN 8889 +#define LM_REPAINT 8890 +#define LM_BRINGTOFRONT 8891 +#define LM_SAVEDATA 8892 +#define LM_RESTOREDATA 8893 +#define LM_POPUP 9182 +#define LM_HIDEPOPUP 9183 +#define LM_FIRSTDESKTOPPAINT 9184 // Deprecated +#define LM_LSSELECT 9185 +#define LM_SETTASKBARONTOP 9186 // Deprecated +#define LM_SAVESYSTRAY 9210 // Deprecated +#define LM_RESTORESYSTRAY 9211 // Deprecated +#define LM_CHECKFORAPPBAR 9212 // Deprecated +#define LM_SENDSYSTRAY 9213 +#define LM_SYSTRAY 9214 +#define LM_SYSTRAYREADY 9215 +#define LM_SYSTRAYINFOEVENT 9216 + +// Shell Hook Messages (obsolete!) +#define LM_SHELLMESSAGE 9219 +#define LM_ACCESSSTATE 9220 +#define LM_ACTIVESHELLWIN LM_ACCESSSTATE + 1 +#define LM_APPCOMMANDX LM_ACCESSSTATE + 2 +#define LM_MINMAXWIN LM_ACCESSSTATE + 3 +#define LM_LANGUAGEX LM_ACCESSSTATE + 4 +#define LM_REDRAWX LM_ACCESSSTATE + 5 +#define LM_TASKMANX LM_ACCESSSTATE + 6 +#define LM_ACTIVEWIN LM_ACCESSSTATE + 7 +#define LM_ADDWINDOW LM_ACCESSSTATE + 8 +#define LM_REMOVEWINDOW LM_ACCESSSTATE + 9 //9229 + +#define LM_RECYCLE 9260 +#define LM_REGISTERMESSAGE 9263 +#define LM_UNREGISTERMESSAGE 9264 +#define LM_GETREVID 9265 +#define LM_UNLOADMODULE 9266 +#define LM_RELOADMODULE 9267 +#define LM_REGISTERHOOKMESSAGE 9268 // Deprecated +#define LM_UNREGISTERHOOKMESSAGE 9269 // Deprecated +#define LM_SHADETOGGLE 9300 +#define LM_REFRESH 9305 + +// Threaded Module Messages +#if defined(LSAPI_PRIVATE) +#define LM_THREAD_BANGCOMMAND 9310 +#define LM_THREADREADY 9311 +#define LM_THREADFINISHED 9312 +#endif + +// VWM Messages +#define LM_VWMUP 9350 +#define LM_VWMDOWN 9351 +#define LM_VWMLEFT 9352 +#define LM_VWMRIGHT 9353 +#define LM_VWMNAV 9354 +#define LM_SWITCHTON 9355 +#define LM_ISSTICKY 9356 +#define LM_STICK 9357 +#define LM_UNSTICK 9358 +#define LM_LISTDESKTOPS 9359 +#define LM_DESKTOPINFO 9360 +#define LM_GETDESKTOPOF 9361 + +// Core Messages +#if defined(LSAPI_PRIVATE) +#define LM_GETLSOBJECT 9400 // Deprecated +#define LM_WINDOWLIST 9401 // Deprecated +#define LM_DATASTORE 9410 // Deprecated +#define LM_MESSAGEMANAGER 9411 // Deprecated +#define LM_BANGCOMMAND 9420 +#define LM_ENUMREVIDS 9430 +#define LM_ENUMMODULES 9431 +#define LM_ENUMPERFORMANCE 9432 +#endif + + +#define LM_SHELLHOOK 9500 // not an actual message + +// shell hook messages +#define LM_WINDOWCREATED (LM_SHELLHOOK + HSHELL_WINDOWCREATED) +#define LM_WINDOWDESTROYED (LM_SHELLHOOK + HSHELL_WINDOWDESTROYED) +#define LM_ACTIVATESHELLWINDOW (LM_SHELLHOOK + HSHELL_ACTIVATESHELLWINDOW) +#define LM_WINDOWACTIVATED (LM_SHELLHOOK + HSHELL_WINDOWACTIVATED) +#define LM_GETMINRECT (LM_SHELLHOOK + HSHELL_GETMINRECT) +#define LM_REDRAW (LM_SHELLHOOK + HSHELL_REDRAW) +#define LM_TASKMAN (LM_SHELLHOOK + HSHELL_TASKMAN) +#define LM_LANGUAGE (LM_SHELLHOOK + HSHELL_LANGUAGE) +#define LM_ACCESSIBILITYSTATE (LM_SHELLHOOK + HSHELL_ACCESSIBILITYSTATE) +#define LM_APPCOMMAND (LM_SHELLHOOK + HSHELL_APPCOMMAND) +#define LM_WINDOWREPLACED (LM_SHELLHOOK + HSHELL_WINDOWREPLACED) +#define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) +#define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) + + +//----------------------------------------------------------------------------- +// CONSTANT DEFINES +//----------------------------------------------------------------------------- +#define MAX_BANGCOMMAND 64 +#define MAX_BANGARGS 256 +#define MAX_RCCOMMAND 64 +#define MAX_LINE_LENGTH 4096 +#define MAX_PATH_LENGTH 1024 + +#define WHITESPACEW L" \t\n\r" +#define WHITESPACEA " \t\n\r" + +#define RESERVEDCHARSW L"\"\'[];$" +#define RESERVEDCHARSA "\"\'[];$" + +#if defined(_UNICODE) +#define WHITESPACE WHITESPACEW +#define RESERVEDCHARS RESERVEDCHARSW +#else +#define WHITESPACE WHITESPACEA +#define RESERVEDCHARS RESERVEDCHARSA +#endif + +#define HIDEmagicDWord 0x59474541 +#define magicDWord 0x49474541 + + +//----------------------------------------------------------------------------- +// MODULE ENTRY POINTS DEFINES +//----------------------------------------------------------------------------- +typedef int (__cdecl* initModuleExProc)(HWND, HINSTANCE, LPCSTR); +typedef void (__cdecl* quitModuleProc)(HINSTANCE); + + +//----------------------------------------------------------------------------- +// BANG COMMAND DEFINES +//----------------------------------------------------------------------------- +typedef void (__cdecl *BangCommand)(HWND hSender, LPCSTR pszArgs); +typedef void (__cdecl *BangCommandEx) \ + (HWND hSender, LPCSTR pszCommand, LPCSTR pszArgs); + +typedef struct _LMBANGCOMMANDA +{ + UINT cbSize; + HWND hWnd; + CHAR szCommand[MAX_BANGCOMMAND]; + CHAR szArgs[MAX_BANGARGS]; + // +} LMBANGCOMMANDA, *PLMBANGCOMMANDA; + +typedef struct _LMBANGCOMMANDW +{ + UINT cbSize; + HWND hWnd; + WCHAR wzCommand[MAX_BANGCOMMAND]; + WCHAR wzArgs[MAX_BANGARGS]; + // +} LMBANGCOMMANDW, *PLMBANGCOMMANDW; + +#if defined(_UNICODE) +#define LMBANGCOMMAND LMBANGCOMMANDW +#define PLMBANGCOMMAND PLMBANGCOMMANDW +#else // _UNICODE +#define LMBANGCOMMAND LMBANGCOMMANDA +#define PLMBANGCOMMAND PLMBANGCOMMANDA +#endif // _UNICODE + +//----------------------------------------------------------------------------- +// VWM DEFINES +//----------------------------------------------------------------------------- +typedef struct LSDESKTOPINFO +{ + int size; + char name[32]; + HICON icon; + BOOL isCurrent; + int number; + // +} LSDESKTOPINFO; + + +//----------------------------------------------------------------------------- +// LM_RECYCLE DEFINES +//----------------------------------------------------------------------------- +#define LR_RECYCLE 0 +#define LR_LOGOFF 1 +#define LR_QUIT 2 +#define LR_MSSHUTDOWN 3 + + +//----------------------------------------------------------------------------- +// LM_UN/RELOADMODULE DEFINES +//----------------------------------------------------------------------------- +#define LMM_PATH 0x0000 +#define LMM_HINSTANCE 0x1000 + + +//----------------------------------------------------------------------------- +// LSLOG LOG LEVEL CONSTANTS +//----------------------------------------------------------------------------- +#define LOG_ERROR 1 +#define LOG_WARNING 2 +#define LOG_NOTICE 3 +#define LOG_DEBUG 4 + + +//----------------------------------------------------------------------------- +// ENUMLSDATA DEFINES +//----------------------------------------------------------------------------- +#define ELD_BANGS 1 +#define ELD_MODULES 2 +#define ELD_REVIDS 3 +#define ELD_BANGS_V2 4 +#define ELD_PERFORMANCE 5 + +// ELD_MODULES: possible dwFlags values +#define LS_MODULE_THREADED 0x0001 +// LS_MODULE_NOTPUMPED 0x0002 no longer used + +typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); + +#endif // LSAPIDEFINES_H From a7014d2a35e8d234c2f471bc6af6c6e97fcbceda Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 17:16:49 -0700 Subject: [PATCH 19/50] Updated the manual --- docs/manual.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/manual.txt b/docs/manual.txt index aab52bb..d3260ef 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -907,7 +907,9 @@ Contents: Win2000 Win2003 Win2008 + Win2012 Win7 + Win8 Win95 Win98 WinME @@ -1208,6 +1210,7 @@ ENDIF The Current Team: ----------------- - Alexander Vermaat (Acidfire) + - Erik Welander (alur) - Chris Rempel (jugg) - Simon (ilmcuts) - Tobbe Lundberg (Tobbe) From e1cc719f9ecd8f0d877523058848edaeb9803598 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 6 Aug 2012 22:03:36 -0700 Subject: [PATCH 20/50] Some updates on Shell_NotifyIconGetRect handling. --- litestep/TrayService.cpp | 40 ++++++++++++++++++++++++++++++---------- litestep/TrayService.h | 2 +- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 5d05511..64ecfa2 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -651,30 +651,50 @@ HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) return E_NOTIMPL; } + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // // TrayInfoEvent // // Handles tray info events // -LRESULT TrayService::TrayInfoEvent(DWORD /* cbData */, LPVOID lpData) // size, data +LRESULT TrayService::TrayInfoEvent(DWORD /*cbData*/, LPVOID lpData) // size, data { LRESULT lr = 0; LPNOTIFYICONIDENTIFIER_MSGV1 s = (LPNOTIFYICONIDENTIFIER_MSGV1)lpData; - // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. + // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. - if (s->dwMessage == 2) // Icon size? - { - return MAKELONG(16,16); - } + TRACE("dwMessage(%u) sent to TrayInfoEvent (HWND: %x) (dwMagic: %x) (cbSize: %x) (dwPadding: %x) (uID: 0x%x) %d %x %x", + s->dwMessage, s->hWnd, s->dwMagic, s->cbSize, s->dwPadding, s->uID, sizeof(NOTIFYICONIDENTIFIER_MSGV1)); - POINT p; - GetCursorPos(&p); + // Calling Shell_NotifyIconGetRect will cause two successive calls to this function. The first + // (dwMessage 2) should return the top left coordinate of the specified icon. The 2nd should + // return the width and height of the icon. - if (s->dwMessage == 1) // Icon position + switch (s->dwMessage) { - return MAKELPARAM(p.x, p.y); + case 1: + { + // Icon position + POINT p; + GetCursorPos(&p); + lr = MAKELPARAM(p.x, p.y); + } + break; + + case 2: + { + // Width, Height + lr = MAKELPARAM(16, 16); + } + break; + + default: + { + TRACE("Unknown dwMessage(%u) sent to TrayInfoEvent", s->dwMessage); + } + break; } return lr; diff --git a/litestep/TrayService.h b/litestep/TrayService.h index 0b6bb09..cf8df67 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -47,7 +47,7 @@ typedef struct _NOTIFYICONIDENTIFIER_MSGV1 DWORD dwMessage; DWORD cbSize; DWORD dwPadding; - HWND hWnd; + HWND32 hWnd; UINT uID; GUID guidItem; } NOTIFYICONIDENTIFIER_MSGV1, *LPNOTIFYICONIDENTIFIER_MSGV1; From 5a815fb08925fb7ba1a2f5adcdf96bab71a3ddf1 Mon Sep 17 00:00:00 2001 From: alur Date: Wed, 8 Aug 2012 02:15:18 -0700 Subject: [PATCH 21/50] Really fixed 64bit appbars. --- litestep/TrayAppBar.h | 5 +++-- litestep/TrayService.cpp | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/litestep/TrayAppBar.h b/litestep/TrayAppBar.h index 6376229..ca0759e 100644 --- a/litestep/TrayAppBar.h +++ b/litestep/TrayAppBar.h @@ -33,6 +33,7 @@ // Maintains 32bit handles on 64bit builds typedef DWORD HANDLE32; typedef DWORD HWND32; +typedef LONG LPARAM32; typedef struct _APPBARDATAV1 { @@ -41,7 +42,7 @@ typedef struct _APPBARDATAV1 UINT uCallbackMessage; UINT uEdge; RECT rc; - LPARAM lParam; + LPARAM32 lParam; } APPBARDATAV1, *PAPPBARDATAV1; typedef struct _APPBARDATAV2 @@ -51,7 +52,7 @@ typedef struct _APPBARDATAV2 UINT uCallbackMessage; UINT uEdge; RECT rc; - LPARAM lParam; + LPARAM32 lParam; DWORD dw64BitAlign; } APPBARDATAV2, *PAPPBARDATAV2; diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 64ecfa2..3facccc 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -665,8 +665,8 @@ LRESULT TrayService::TrayInfoEvent(DWORD /*cbData*/, LPVOID lpData) // size, dat // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. - TRACE("dwMessage(%u) sent to TrayInfoEvent (HWND: %x) (dwMagic: %x) (cbSize: %x) (dwPadding: %x) (uID: 0x%x) %d %x %x", - s->dwMessage, s->hWnd, s->dwMagic, s->cbSize, s->dwPadding, s->uID, sizeof(NOTIFYICONIDENTIFIER_MSGV1)); + TRACE("dwMessage(%u) sent to TrayInfoEvent (HWND: %x) (dwMagic: %x) (cbSize: %x) (dwPadding: %x) (uID: 0x%x)", + s->dwMessage, s->hWnd, s->dwMagic, s->cbSize, s->dwPadding, s->uID); // Calling Shell_NotifyIconGetRect will cause two successive calls to this function. The first // (dwMessage 2) should return the top left coordinate of the specified icon. The 2nd should @@ -679,7 +679,7 @@ LRESULT TrayService::TrayInfoEvent(DWORD /*cbData*/, LPVOID lpData) // size, dat // Icon position POINT p; GetCursorPos(&p); - lr = MAKELPARAM(p.x, p.y); + lr = MAKELPARAM(p.x, p.y); } break; @@ -717,7 +717,7 @@ LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) { - TRACE("PAPPBARMSGDATAV3 - Invalid ABD size: %u", pamd->abd.cbSize); + TRACE("APPBARMSGDATAV3 - Invalid ABD size: %u. Expected: %u", pamd->abd.cbSize, sizeof(APPBARDATAV2)); break; } @@ -737,7 +737,7 @@ LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) if (sizeof(APPBARDATAV2) != pamd->abd.cbSize) { - TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u", pamd->abd.cbSize); + TRACE("APPBARMSGDATAV2 - Invalid ABD size: %u. Expected: %u", pamd->abd.cbSize, sizeof(APPBARDATAV2)); break; } @@ -757,7 +757,7 @@ LRESULT TrayService::HandleAppBarCopydata(DWORD cbData, LPVOID lpData) if (sizeof(APPBARDATAV1) != pamd->abd.cbSize) { - TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u", pamd->abd.cbSize); + TRACE("APPBARMSGDATAV1 - Invalid ABD size: %u. Expected: %u", pamd->abd.cbSize, sizeof(APPBARDATAV1)); break; } From 3dc3fdb7d5fed146510f5ff1d271fe2f77cad70b Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 10 Aug 2012 18:35:48 -0700 Subject: [PATCH 22/50] Added LM_SYSTRAYINFOEVENT message --- litestep/TrayService.cpp | 44 +++++++++++----------------------------- litestep/TrayService.h | 10 +++++++++ lsapi/lsapidefines.h | 8 ++++++++ 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 3facccc..17f5a06 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -662,41 +662,21 @@ LRESULT TrayService::TrayInfoEvent(DWORD /*cbData*/, LPVOID lpData) // size, dat { LRESULT lr = 0; LPNOTIFYICONIDENTIFIER_MSGV1 s = (LPNOTIFYICONIDENTIFIER_MSGV1)lpData; - - // TODO::Send LM_SYSTRAYINFOEVENT to any registered listener instead. - - TRACE("dwMessage(%u) sent to TrayInfoEvent (HWND: %x) (dwMagic: %x) (cbSize: %x) (dwPadding: %x) (uID: 0x%x)", - s->dwMessage, s->hWnd, s->dwMagic, s->cbSize, s->dwPadding, s->uID); + SYSTRAYINFOEVENT sEvent; // Calling Shell_NotifyIconGetRect will cause two successive calls to this function. The first - // (dwMessage 2) should return the top left coordinate of the specified icon. The 2nd should + // (dwMessage 1) should return the top left coordinate of the specified icon. The 2nd should // return the width and height of the icon. - - switch (s->dwMessage) - { - case 1: - { - // Icon position - POINT p; - GetCursorPos(&p); - lr = MAKELPARAM(p.x, p.y); - } - break; - - case 2: - { - // Width, Height - lr = MAKELPARAM(16, 16); - } - break; - - default: - { - TRACE("Unknown dwMessage(%u) sent to TrayInfoEvent", s->dwMessage); - } - break; - } - + + // Let registered listeners handle this. + sEvent.cbSize = sizeof(SYSTRAYINFOEVENT); + sEvent.dwEvent = s->dwMessage; + sEvent.guidItem = s->guidItem; + sEvent.hWnd = (HWND)s->hWnd; + sEvent.uID = s->uID; + + SendMessage(m_hLiteStep, LM_SYSTRAYINFOEVENT, (WPARAM)&sEvent, (LPARAM)&lr); + return lr; } diff --git a/litestep/TrayService.h b/litestep/TrayService.h index cf8df67..f2d711c 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -52,6 +52,16 @@ typedef struct _NOTIFYICONIDENTIFIER_MSGV1 GUID guidItem; } NOTIFYICONIDENTIFIER_MSGV1, *LPNOTIFYICONIDENTIFIER_MSGV1; +// Used for LM_SYSTRAYINFOEVENT +typedef struct _SYSTRAYINFOEVENT +{ + DWORD cbSize; + DWORD dwEvent; + HWND hWnd; + UINT uID; + GUID guidItem; +} SYSTRAYINFOEVENT, *LPSYSTRAYINFOEVENT; + // data sent by shell via Shell_NotifyIcon typedef struct _SHELLTRAYDATA { diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index 40bba50..b816fc5 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -217,6 +217,14 @@ typedef struct _LMBANGCOMMANDW #define PLMBANGCOMMAND PLMBANGCOMMANDA #endif // _UNICODE + +//----------------------------------------------------------------------------- +// LM_SYSTRAYINFOEVENT DEFINES +//----------------------------------------------------------------------------- +#define TRAYEVENT_GETICONPOS 1 +#define TRAYEVENT_GETICONSIZE 2 + + //----------------------------------------------------------------------------- // VWM DEFINES //----------------------------------------------------------------------------- From 2636147317000fbece2899e6c636994f1c116764 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 10 Aug 2012 19:30:34 -0700 Subject: [PATCH 23/50] Fixed missing copy of guidItem. --- litestep/TrayNotifyIcon.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index 5460469..0b31c82 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -69,6 +69,7 @@ NotifyIcon::NotifyIcon(const NID_XX& nidSource) ,m_uSharedID(0) { m_szTip[0] = 0; + ZeroMemory(&m_guidItem, sizeof(GUID)); Update(nidSource); s_icVtr.push_back(this); @@ -128,19 +129,19 @@ void NotifyIcon::copy_guid(PCNID_XX pnidSource) { if ((pnidSource->uFlags & NIF_GUID) == NIF_GUID) { - switch (pnidSource->cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - m_guidItem = ((NID_6W*)pnidSource)->guidItem; - break; - - case NID_6A_SIZE: - m_guidItem = ((NID_6A*)pnidSource)->guidItem; - break; - - default: - break; + switch (pnidSource->cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + m_guidItem = ((NID_6W*)pnidSource)->guidItem; + break; + + case NID_6A_SIZE: + m_guidItem = ((NID_6A*)pnidSource)->guidItem; + break; + + default: + break; } } } @@ -344,6 +345,7 @@ void NotifyIcon::CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const plsnid->cbSize = sizeof(LSNOTIFYICONDATA); plsnid->hWnd = m_hWnd; plsnid->uID = m_uID; + plsnid->guidItem = m_guidItem; plsnid->uFlags = 0; if (NIF_MESSAGE & m_uFlags & uFlagMask) From 5341ce30f75e7ae0486028e1150e720510dbe986 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 10 Aug 2012 20:11:52 -0700 Subject: [PATCH 24/50] Cleanup --- litestep/TrayNotifyIcon.h | 3 ++- litestep/TrayService.cpp | 1 + lsapi/aboutbox.cpp | 7 +++++-- lsapi/lsapidefines.h | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index 1516882..532defa 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -58,7 +58,8 @@ typedef struct DWORD dwInfoFlags; /* arbitrary & volatile */ // new in XP: - GUID guidItem; /* ???? */ + GUID guidItem; /* persistent & non volatile */ + /**/ } LSNOTIFYICONDATA, *PLSNOTIFYICONDATA; typedef const LSNOTIFYICONDATA * PCLSNOTIFYICONDATA; diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 17f5a06..033420b 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -459,6 +459,7 @@ LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, } } break; + case SH_TRAYINFO_DATA: { lResult = pTrayService->TrayInfoEvent(pcds->cbData, pcds->lpData); diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 848f250..af4eca4 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -913,7 +913,10 @@ static int GetClientWidth(HWND hWnd) // FormatBytes // Formats a byte count into a string suitable for display to the user // -static LPCSTR units[] = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; +// Note: Max value of stBytes is 16 EB, so no need to be concerned of +// overrunning units[] index. +// +static LPCSTR units[] = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB" }; static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer) { @@ -926,7 +929,7 @@ static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer) ++uUnit; } - if (uUnit == 3) + if (uUnit >= 3) { StringCchPrintf( pszBuffer, cchBuffer, diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index b816fc5..039b7d2 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -271,7 +271,7 @@ typedef struct LSDESKTOPINFO #define ELD_MODULES 2 #define ELD_REVIDS 3 #define ELD_BANGS_V2 4 -#define ELD_PERFORMANCE 5 +#define ELD_PERFORMANCE 5 // ELD_MODULES: possible dwFlags values #define LS_MODULE_THREADED 0x0001 From bc60f75320909c4a11a35a1faef5bc07f2f50386 Mon Sep 17 00:00:00 2001 From: alur Date: Fri, 10 Aug 2012 20:48:13 -0700 Subject: [PATCH 25/50] Added handling of hBalloonIcon. --- litestep/TrayNotifyIcon.cpp | 49 +++++++++++++++++++++++++++++++++++++ litestep/TrayNotifyIcon.h | 6 ++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index 0b31c82..a1d6604 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -95,6 +95,31 @@ NotifyIcon::~NotifyIcon() void NotifyIcon::Update(const NID_XX& nidSource) { + + // Check the size of nidSource if we are debuging. +#ifdef _DEBUG + switch (nidSource.cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_6A_SIZE: + case NID_5W_SIZE: + case NID_5A_SIZE: + case NID_4W_SIZE: + case NID_4A_SIZE: + { + // Do nothing + } + break; + + default: + { + TRACE("NotifyIcon::Update - Unknown cbSize: %u", nidSource.cbSize); + } + break; + } +#endif + // // Copy persistent values only // @@ -196,6 +221,29 @@ void NotifyIcon::copy_icon(PCNID_XX pnidSource) m_uFlags |= NIF_ICON; } } + + switch (pnidSource->cbSize) + { + case NID_7W_SIZE: + { + HICON hBalloon = (HICON)((NID_7W*)pnidSource)->hBalloonIcon; + + if (m_hOriginalBalloonIcon != hBalloon) + { + // Not sure why the original icon is copied, but I set it up this way + // anyway. + m_hOriginalBalloonIcon = hBalloon; + m_hBalloonIcon = hBalloon; + } + } + break; + + default: + { + // Do nothing + } + break; + } } void NotifyIcon::copy_tip(PCNID_XX pnidSource) @@ -347,6 +395,7 @@ void NotifyIcon::CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const plsnid->uID = m_uID; plsnid->guidItem = m_guidItem; plsnid->uFlags = 0; + plsnid->hBalloonIcon = m_hBalloonIcon; if (NIF_MESSAGE & m_uFlags & uFlagMask) { diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index 532defa..c028657 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -60,6 +60,8 @@ typedef struct // new in XP: GUID guidItem; /* persistent & non volatile */ + // new in Vista + HICON hBalloonIcon; /* arbitrary & volatile */ /**/ } LSNOTIFYICONDATA, *PLSNOTIFYICONDATA; typedef const LSNOTIFYICONDATA * PCLSNOTIFYICONDATA; @@ -313,7 +315,7 @@ class NotifyIcon // Preserved Notify Icon Data members const HWND m_hWnd; /* persistent & non volatile */ const UINT m_uID; /* persistent & non volatile */ - GUID m_guidItem; /* ? & ? */ + GUID m_guidItem; /* persistent & non volatile */ UINT m_uFlags; /* persistent & volatile */ UINT m_uCallbackMessage; /* persistent & volatile */ @@ -321,9 +323,11 @@ class NotifyIcon CHAR m_szTip[TRAY_MAX_TIP_LENGTH]; /* persistent & volatile */ DWORD m_dwState; /* persistent & volatile */ + HICON m_hBalloonIcon; /* persistent & volatile */ // Internal tracking HANDLE m_hOriginalIcon; + HANDLE m_hOriginalBalloonIcon; HANDLE m_hSharedWnd; UINT m_uSharedID; From 22072599637b27219ae2cdfb94fced00cfe33cff Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 21 Aug 2012 14:44:16 -0700 Subject: [PATCH 26/50] Added fileExists function --- docs/manual.txt | 3 +++ lsapi/MathParser.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/docs/manual.txt b/docs/manual.txt index d3260ef..848b156 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -590,6 +590,9 @@ Contents: endsWith(string, string) Returns true if the second argument, converted to a string, is a suffix of the first argument, converted to a string. + + fileExists(string) + Returns true if the argument is a path to an existing file or directory. floor(number) Returns the floor (greatest lesser integer) of the argument, converted diff --git a/lsapi/MathParser.cpp b/lsapi/MathParser.cpp index 6f57d23..37ea681 100644 --- a/lsapi/MathParser.cpp +++ b/lsapi/MathParser.cpp @@ -105,6 +105,7 @@ static MathValue Math_boolean(const MathValueList& argList); static MathValue Math_ceil(const MathValueList& argList); static MathValue Math_contains(const MathValueList& argList); static MathValue Math_endsWith(const MathValueList& argList); +static MathValue Math_fileExists(const MathValueList& argList); static MathValue Math_floor(const MathValueList& argList); static MathValue Math_if(const MathValueList& argList); static MathValue Math_integer(const MathValueList& argList); @@ -130,6 +131,7 @@ struct FunctionTable { "ceil", Math_ceil, 1 }, { "contains", Math_contains, 2 }, { "endsWith", Math_endsWith, 2 }, + { "fileExists", Math_fileExists, 1 }, { "floor", Math_floor, 1 }, { "if", Math_if, 3 }, { "integer", Math_integer, 1 }, @@ -727,6 +729,13 @@ MathValue Math_endsWith(const MathValueList& argList) } +// File Exists +MathValue Math_fileExists(const MathValueList& argList) +{ + return GetFileAttributes(argList[0].ToString().c_str()) != INVALID_FILE_ATTRIBUTES; +} + + // Floor (round down) MathValue Math_floor(const MathValueList& argList) { From 4fa90af9dc4b1249d72147f1058d2671c9b1b2be Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 21 Aug 2012 15:05:34 -0700 Subject: [PATCH 27/50] Fixed enum order and added missing break; --- lsapi/aboutbox.cpp | 2 +- lsapi/lsapi.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index af4eca4..d8871ea 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -64,9 +64,9 @@ enum ,ABOUT_DEVTEAM ,ABOUT_LICENSE ,ABOUT_MODULES + ,ABOUT_PERFORMANCE ,ABOUT_REVIDS ,ABOUT_SYSINFO - ,ABOUT_PERFORMANCE }; struct AboutOptions diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index f8c9d36..1c1d96d 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -720,6 +720,7 @@ HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) hr = (HRESULT)SendMessage(GetLitestepWnd(), LM_ENUMPERFORMANCE, (WPARAM)pfnCallback, lParam); } + break; default: { From 69be5533eea1d6dbdd1a02ecbd5fbbee3a2a0e68 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 21 Aug 2012 15:26:57 -0700 Subject: [PATCH 28/50] Tabs -> Spaces --- litestep/Module.h | 4 ++-- litestep/ModuleManager.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/litestep/Module.h b/litestep/Module.h index 15c0866..3d62d93 100644 --- a/litestep/Module.h +++ b/litestep/Module.h @@ -61,7 +61,7 @@ class Module DWORD m_dwFlags; /** The amount of time it took to load the module */ - DWORD m_dwLoadTime; + DWORD m_dwLoadTime; /** * Event that is triggered when a threaded module completes initialization @@ -192,7 +192,7 @@ class Module /** * Returns how long this module took to load. */ - DWORD GetLoadTime() const + DWORD GetLoadTime() const { return m_dwLoadTime; } diff --git a/litestep/ModuleManager.cpp b/litestep/ModuleManager.cpp index a835699..874363f 100644 --- a/litestep/ModuleManager.cpp +++ b/litestep/ModuleManager.cpp @@ -434,4 +434,4 @@ HRESULT ModuleManager::EnumPerformance(LSENUMPERFORMANCEPROC pfnCallback, LPARAM } return hr; -} \ No newline at end of file +} From ef006f8716db1a0ff2929406558c359efb44c5d6 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 21 Aug 2012 22:21:37 -0700 Subject: [PATCH 29/50] Manual update --- docs/manual.txt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/docs/manual.txt b/docs/manual.txt index 848b156..75cd918 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1,8 +1,8 @@ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - LiteStep 0.24.8 + LiteStep 0.25.0 Release Notes - Copyright (c) 2009 - LiteStep Development Team + Copyright (c) 2012 - LiteStep Development Team =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Contents: @@ -186,7 +186,7 @@ Contents: line that starts with "shell=" in the "[boot]" section of the "system.ini" file, "shell=explorer.exe". Save the file and reboot your system. - 2. Win2K/XP + 2. Win2K/XP/Vista/7/8 - Note: If you are NOT an administrator, you will most likely NOT be able to set LiteStep as your shell. The only exception to this is if your System @@ -299,13 +299,6 @@ Contents: handles $evars$ and all other configuration. Manages !bang commands, includes core !bangs. - - hook.dll The system shell hook used by some legacy LiteStep modules - for receiving global system messages. - - LiteStep also depends on "libpng13.dll" and "zlib1.dll" for Portable Network - Graphics (PNG) image support. Those two files must exist in the same directory - as "litestep.exe" or in the system path. - LiteStep uses a text configuration file named "step.rc" which must exist in the same directory as "litestep.exe". @@ -1326,7 +1319,7 @@ ENDIF A) Documentation License Notice ------------------------------- - Copyright (c) 2005-2009 LiteStep Development Team + Copyright (c) 2005-2012 LiteStep Development Team Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version @@ -1340,7 +1333,7 @@ ENDIF LiteStep is a replacement shell for the standard Windows® Explorer shell. Copyright (C) 1997-1998 Francis Gastellu - Copyright (C) 1998-2009 LiteStep Development Team + Copyright (C) 1998-2012 LiteStep Development 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 From cf850fd51296c5eb7fdc2b84953fb914a740a482 Mon Sep 17 00:00:00 2001 From: Christian Ratzenhofer Date: Sun, 16 Sep 2012 03:49:14 +0200 Subject: [PATCH 30/50] Added VC10 x64 targets, modified VC10 output paths --- litestep/litestep_vc10.vcxproj | 103 +++++++++++++++++++++++++++++++-- litestep_vc10.sln | 16 ++++- lsapi/lsapi_vc10.vcxproj | 103 +++++++++++++++++++++++++++++++-- utility/utility_vc10.vcxproj | 86 +++++++++++++++++++++++++-- 4 files changed, 295 insertions(+), 13 deletions(-) diff --git a/litestep/litestep_vc10.vcxproj b/litestep/litestep_vc10.vcxproj index d7bc274..3191fa6 100644 --- a/litestep/litestep_vc10.vcxproj +++ b/litestep/litestep_vc10.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + litestep @@ -22,10 +30,19 @@ MultiByte true + + Application + MultiByte + true + Application MultiByte + + Application + MultiByte + @@ -33,19 +50,33 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10\ - Debug_VC10\ + ../Debug_VC10_32\ + ../Debug_VC10_64\ + Debug_VC10_32\ + Debug_VC10_64\ true - ../Release_VC10\ - Release_VC10\ + true + ../Release_VC10_32\ + ../Release_VC10_64\ + Release_VC10_32\ + Release_VC10_64\ false + false @@ -75,6 +106,32 @@ MachineX86 + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + + MaxSpeed @@ -114,6 +171,44 @@ MachineX86 + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + NotSet + false + true + true + + + Level4 + false + + + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + + diff --git a/litestep_vc10.sln b/litestep_vc10.sln index a8a65be..1f8581b 100644 --- a/litestep_vc10.sln +++ b/litestep_vc10.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 +# Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc10.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc10.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" @@ -9,21 +9,35 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/lsapi/lsapi_vc10.vcxproj b/lsapi/lsapi_vc10.vcxproj index 7ba5729..a9b2ffe 100644 --- a/lsapi/lsapi_vc10.vcxproj +++ b/lsapi/lsapi_vc10.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + lsapi @@ -22,10 +30,19 @@ MultiByte true + + DynamicLibrary + MultiByte + true + DynamicLibrary MultiByte + + DynamicLibrary + MultiByte + @@ -33,19 +50,33 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10\ - Debug_VC10\ + ../Debug_VC10_32\ + ../Debug_VC10_64\ + Debug_VC10_32\ + Debug_VC10_64\ true - ../Release_VC10\ - Release_VC10\ + true + ../Release_VC10_32\ + ../Release_VC10_64\ + Release_VC10_32\ + Release_VC10_64\ false + false @@ -76,6 +107,33 @@ MachineX86 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + + MaxSpeed @@ -112,6 +170,41 @@ MachineX86 + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + + @@ -122,7 +215,9 @@ $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj diff --git a/utility/utility_vc10.vcxproj b/utility/utility_vc10.vcxproj index b94f21c..fb9a84a 100644 --- a/utility/utility_vc10.vcxproj +++ b/utility/utility_vc10.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + utility @@ -22,10 +30,19 @@ MultiByte true + + StaticLibrary + MultiByte + true + StaticLibrary MultiByte + + StaticLibrary + MultiByte + @@ -33,17 +50,29 @@ + + + + + + + + <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10\ - Debug_VC10\ - ../Release_VC10\ - Release_VC10\ + ../Debug_VC10_32\ + ../Debug_VC10_64\ + Debug_VC10_32\ + Debug_VC10_64\ + ../Release_VC10_32\ + ../Release_VC10_64\ + Release_VC10_32\ + Release_VC10_64\ @@ -67,6 +96,27 @@ $(OutDir)utility.lib + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + + + $(OutDir)utility.lib + + /wd4201 %(AdditionalOptions) @@ -95,6 +145,34 @@ $(OutDir)utility.lib + + + /wd4201 %(AdditionalOptions) + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + + + $(OutDir)utility.lib + + From 8b97972ce605770015118b1123d4df847402df3f Mon Sep 17 00:00:00 2001 From: alur Date: Tue, 2 Oct 2012 12:38:05 -0700 Subject: [PATCH 31/50] Added 2008 solution and project files. --- litestep/litestep_vc9.vcproj | 349 ++++++++++++++++++++++++++++++ litestep_vc9.sln | 38 ++++ lsapi/lsapi_vc9.vcproj | 399 +++++++++++++++++++++++++++++++++++ utility/utility_vc9.vcproj | 245 +++++++++++++++++++++ 4 files changed, 1031 insertions(+) create mode 100644 litestep/litestep_vc9.vcproj create mode 100644 litestep_vc9.sln create mode 100644 lsapi/lsapi_vc9.vcproj create mode 100644 utility/utility_vc9.vcproj diff --git a/litestep/litestep_vc9.vcproj b/litestep/litestep_vc9.vcproj new file mode 100644 index 0000000..b5c7aa9 --- /dev/null +++ b/litestep/litestep_vc9.vcproj @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/litestep_vc9.sln b/litestep_vc9.sln new file mode 100644 index 0000000..0d61350 --- /dev/null +++ b/litestep_vc9.sln @@ -0,0 +1,38 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc9.vcproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" + ProjectSection(ProjectDependencies) = postProject + {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} = {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc9.vcproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc9.vcproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" + ProjectSection(ProjectDependencies) = postProject + {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/lsapi/lsapi_vc9.vcproj b/lsapi/lsapi_vc9.vcproj new file mode 100644 index 0000000..6b0a537 --- /dev/null +++ b/lsapi/lsapi_vc9.vcproj @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utility/utility_vc9.vcproj b/utility/utility_vc9.vcproj new file mode 100644 index 0000000..8eb1854 --- /dev/null +++ b/utility/utility_vc9.vcproj @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 72a661c3ef09143dbfe97a90ddef54d05130d978 Mon Sep 17 00:00:00 2001 From: alur Date: Tue, 2 Oct 2012 12:47:30 -0700 Subject: [PATCH 32/50] Added .gitignore. --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf0bf4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +Release_* +Debug_* +*/Debug_* +*/Release_* +*.user +*.opensdf +*.sdf +*.suo +*.ncb From b6e5d1be0bb60c6e0a739612409c4e989f3550f5 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 7 Oct 2012 19:50:27 -0700 Subject: [PATCH 33/50] Now using high resolution timers to measure loading time, if available. --- litestep/Module.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/litestep/Module.cpp b/litestep/Module.cpp index 0bd42a3..d31aac1 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -175,7 +175,13 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) { ASSERT(NULL == m_hInstance); - DWORD dwStartTime = GetTickCount(); + DWORD dwStartTime = 0; + __int64 iStartTime, iEndTime, iFrequency; + + if (QueryPerformanceCounter((LARGE_INTEGER*)&iStartTime) == FALSE) + { + dwStartTime = GetTickCount(); + } // delaying the LoadLibrary call until this point is necessary to make // grdtransparent work (it hooks LoadLibrary) @@ -207,7 +213,15 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) CallInit(); } - m_dwLoadTime = GetTickCount() - dwStartTime; + if (QueryPerformanceCounter((LARGE_INTEGER*)&iEndTime) == FALSE || + QueryPerformanceFrequency((LARGE_INTEGER*)&iFrequency) == FALSE) + { + m_dwLoadTime = GetTickCount() - dwStartTime; + } + else + { + m_dwLoadTime = (DWORD)((iEndTime - iStartTime)*1000/iFrequency); + } return true; } From 81723feb33f04ffa487a58025001e35dbdc1c480 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 7 Oct 2012 23:17:12 -0700 Subject: [PATCH 34/50] Now storing the version of icons, which fixes menu positioning after a recycle. --- litestep/TrayNotifyIcon.cpp | 25 +++++++++++++++++++++++++ litestep/TrayNotifyIcon.h | 8 ++++++++ litestep/TrayService.cpp | 2 ++ 3 files changed, 35 insertions(+) diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index a1d6604..ea9d351 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -67,6 +67,7 @@ NotifyIcon::NotifyIcon(const NID_XX& nidSource) ,m_hOriginalIcon(NULL) ,m_hSharedWnd(NULL) ,m_uSharedID(0) + ,m_uVersion(0) { m_szTip[0] = 0; ZeroMemory(&m_guidItem, sizeof(GUID)); @@ -138,6 +139,9 @@ void NotifyIcon::Update(const NID_XX& nidSource) // tool tip string copy_tip(&nidSource); + + // version + copy_version(&nidSource); } @@ -150,6 +154,26 @@ void NotifyIcon::copy_message(PCNID_XX pnidSource) } } +void NotifyIcon::copy_version(PCNID_XX pnidSource) +{ + switch (pnidSource->cbSize) + { + case NID_7W_SIZE: + case NID_6W_SIZE: + case NID_5W_SIZE: + m_uVersion = ((NID_5W*)pnidSource)->uVersion; + break; + + case NID_6A_SIZE: + case NID_5A_SIZE: + m_uVersion = ((NID_5A*)pnidSource)->uVersion; + break; + + default: + break; + } +} + void NotifyIcon::copy_guid(PCNID_XX pnidSource) { if ((pnidSource->uFlags & NIF_GUID) == NIF_GUID) @@ -396,6 +420,7 @@ void NotifyIcon::CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const plsnid->guidItem = m_guidItem; plsnid->uFlags = 0; plsnid->hBalloonIcon = m_hBalloonIcon; + plsnid->uVersion = m_uVersion; if (NIF_MESSAGE & m_uFlags & uFlagMask) { diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index c028657..fba82a0 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -300,6 +300,11 @@ class NotifyIcon { CopyLSNID(plsnid, (UINT)-1); } + + inline void SetVersion(UINT uVersion) + { + this->m_uVersion = uVersion; + } void CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const; @@ -309,8 +314,10 @@ class NotifyIcon void copy_icon(PCNID_XX pnidSource); void copy_tip(PCNID_XX pnidSource); void copy_state(PCNID_XX pnidSource); + void copy_version(PCNID_XX pnidSource); void update_state(DWORD dwState, DWORD dwMask); + void set_version(UINT uVersion); // Preserved Notify Icon Data members const HWND m_hWnd; /* persistent & non volatile */ @@ -324,6 +331,7 @@ class NotifyIcon DWORD m_dwState; /* persistent & volatile */ HICON m_hBalloonIcon; /* persistent & volatile */ + UINT m_uVersion; /* persistent & volatile */ // Internal tracking HANDLE m_hOriginalIcon; diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 033420b..48d46aa 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -2254,11 +2254,13 @@ bool TrayService::setVersionIcon(const NID_XX& nid) case NID_6W_SIZE: case NID_5W_SIZE: lsnid.uVersion = ((NID_5W&)nid).uVersion; + (*it)->SetVersion(((NID_5W&)nid).uVersion); break; case NID_6A_SIZE: case NID_5A_SIZE: lsnid.uVersion = ((NID_5A&)nid).uVersion; + (*it)->SetVersion(((NID_5W&)nid).uVersion); break; default: From a884ecb493760f688d8d0dde4845298b7e731994 Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 8 Oct 2012 04:23:47 -0700 Subject: [PATCH 35/50] Added x and y coordinates to !Run as well as LSRunX and LSRunY. --- docs/manual.txt | 23 +++++++++++++++++++++-- lsapi/bangs.cpp | 24 ++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/docs/manual.txt b/docs/manual.txt index 75cd918..effa330 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -852,6 +852,22 @@ Contents: Usage: ThemeName "Elite-h/\x" + LSRunX + --------- + Sets the default X coordinate of the Windows Run dialog box, when displayed + using !Run. + + Usage: + LSRunX 5 + + LSRunY + --------- + Sets the default Y coordinate of the Windows Run dialog box, when displayed + using !Run. + + Usage: + LSRunY 5 + LSLogLevel ---------- (Deprecated) @@ -1049,10 +1065,13 @@ Contents: !Run ---- - Displays the Windows Run dialog box. + Displays the Windows Run dialog box. If both an x and a y coordinate is + specified, the dialog box will appear to the bottom right of (x,y). If no + coordinates are given, the dialog box will appear at the location indicated + by LSRunX and LSRunY. Usage: - !Run + !Run {x-coordinate} {y-coordinate} !ShowModules ------------ diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index 44be2c3..5e2ec25 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -296,16 +296,32 @@ static void BangRestoreWindows(HWND /* hCaller */, LPCSTR /* pszArgs */) // // BangRun(HWND hCaller, LPCSTR pszArgs) // -static void BangRun(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) { - typedef VOID (WINAPI* RunDlgType)(HWND,HICON,LPCSTR,LPCSTR,LPCSTR,UINT); + typedef VOID (WINAPI* RunDlgType)(HWND,HICON,LPCWSTR,LPCWSTR,LPCWSTR,UINT); + + char szX[MAX_LINE_LENGTH] = { 0 }; + char szY[MAX_LINE_LENGTH] = { 0 }; + LPSTR aszTokens[] = { szX, szY }; + int nTokenCount = CommandTokenize(pszArgs, aszTokens, 2, NULL); + int nX = nTokenCount == 2 ? atoi(szX) : GetRCInt("LSRunX", 0); + int nY = nTokenCount == 2 ? atoi(szY) : GetRCInt("LSRunY", 0); + RunDlgType RunDlg = (RunDlgType)GetProcAddress( GetModuleHandle("SHELL32.DLL"), (LPCSTR)((long)0x003D)); - + if (RunDlg) { - RunDlg(NULL, NULL, NULL, NULL, NULL, 0); + HWND hParent = CreateWindowEx(WS_EX_TOOLWINDOW, "Static", "", + WS_POPUP, nX, nY, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); + + // RunDlg(parent, icon, ?, ?, Description, ?); + RunDlg(hParent, NULL, NULL, NULL, NULL, 0); + + if (hParent) { + DestroyWindow(hParent); + } } } From 538cecfee5f50af46f5c7bb005aa0b232f8ddc0f Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 8 Oct 2012 21:00:03 -0700 Subject: [PATCH 36/50] Fixed issues with tray icons. --- litestep/TrayNotifyIcon.cpp | 33 ++++++++------------------------- litestep/TrayNotifyIcon.h | 11 ++++++++++- litestep/TrayService.cpp | 23 ++++++++++++++++++++++- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index ea9d351..0b91d3a 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -139,9 +139,6 @@ void NotifyIcon::Update(const NID_XX& nidSource) // tool tip string copy_tip(&nidSource); - - // version - copy_version(&nidSource); } @@ -154,26 +151,6 @@ void NotifyIcon::copy_message(PCNID_XX pnidSource) } } -void NotifyIcon::copy_version(PCNID_XX pnidSource) -{ - switch (pnidSource->cbSize) - { - case NID_7W_SIZE: - case NID_6W_SIZE: - case NID_5W_SIZE: - m_uVersion = ((NID_5W*)pnidSource)->uVersion; - break; - - case NID_6A_SIZE: - case NID_5A_SIZE: - m_uVersion = ((NID_5A*)pnidSource)->uVersion; - break; - - default: - break; - } -} - void NotifyIcon::copy_guid(PCNID_XX pnidSource) { if ((pnidSource->uFlags & NIF_GUID) == NIF_GUID) @@ -183,10 +160,12 @@ void NotifyIcon::copy_guid(PCNID_XX pnidSource) case NID_7W_SIZE: case NID_6W_SIZE: m_guidItem = ((NID_6W*)pnidSource)->guidItem; + m_uFlags |= NIF_GUID; break; case NID_6A_SIZE: m_guidItem = ((NID_6A*)pnidSource)->guidItem; + m_uFlags |= NIF_GUID; break; default: @@ -417,10 +396,14 @@ void NotifyIcon::CopyLSNID(LSNOTIFYICONDATA * plsnid, UINT uFlagMask) const plsnid->cbSize = sizeof(LSNOTIFYICONDATA); plsnid->hWnd = m_hWnd; plsnid->uID = m_uID; - plsnid->guidItem = m_guidItem; plsnid->uFlags = 0; plsnid->hBalloonIcon = m_hBalloonIcon; - plsnid->uVersion = m_uVersion; + + if (NIF_GUID & m_uFlags & uFlagMask) + { + plsnid->guidItem = m_guidItem; + plsnid->uFlags |= NIF_GUID; + } if (NIF_MESSAGE & m_uFlags & uFlagMask) { diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index fba82a0..be54ad2 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -281,6 +281,11 @@ class NotifyIcon return NIF_ICON == (NIF_ICON & m_uFlags); } + inline bool HasGUID() const + { + return NIF_GUID == (NIF_GUID & m_uFlags); + } + inline HWND GetHwnd() const { return m_hWnd; @@ -295,6 +300,11 @@ class NotifyIcon { return m_guidItem; } + + inline UINT GetVersion() const + { + return m_uVersion; + } inline void CopyLSNID(LSNOTIFYICONDATA * plsnid) const { @@ -314,7 +324,6 @@ class NotifyIcon void copy_icon(PCNID_XX pnidSource); void copy_tip(PCNID_XX pnidSource); void copy_state(PCNID_XX pnidSource); - void copy_version(PCNID_XX pnidSource); void update_state(DWORD dwState, DWORD dwMask); void set_version(UINT uVersion); diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 48d46aa..2fe11cf 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -1913,6 +1913,12 @@ HWND TrayService::SendSystemTray() (*it)->CopyLSNID(&lsnid); notify(NIM_ADD, &lsnid); + + if ((*it)->GetVersion() != 0) + { + lsnid.uVersion = (*it)->GetVersion(); + notify(NIM_SETVERSION, &lsnid); + } } } @@ -2154,6 +2160,11 @@ bool TrayService::modifyIcon(const NID_XX& nid) ,pni->GetuID() ,0 }; + if ((nid.uFlags & NIF_GUID) == NIF_GUID) + { + lsnid.guidItem = (*it)->GetGUID(); + lsnid.uFlags |= NIF_GUID; + } // This icon is no longer visible, remove notify(NIM_DELETE, &lsnid); @@ -2186,6 +2197,11 @@ bool TrayService::deleteIcon(const NID_XX& nid) ,(*it)->GetuID() ,0 }; + if ((nid.uFlags & NIF_GUID) == NIF_GUID) + { + lsnid.guidItem = (*it)->GetGUID(); + lsnid.uFlags |= NIF_GUID; + } notify(NIM_DELETE, &lsnid); @@ -2219,6 +2235,11 @@ bool TrayService::setFocusIcon(const NID_XX& nid) ,(*it)->GetuID() ,0 }; + if ((nid.uFlags & NIF_GUID) == NIF_GUID) + { + lsnid.guidItem = (*it)->GetGUID(); + lsnid.uFlags |= NIF_GUID; + } bReturn = notify(NIM_SETFOCUS, &lsnid); } @@ -2260,7 +2281,7 @@ bool TrayService::setVersionIcon(const NID_XX& nid) case NID_6A_SIZE: case NID_5A_SIZE: lsnid.uVersion = ((NID_5A&)nid).uVersion; - (*it)->SetVersion(((NID_5W&)nid).uVersion); + (*it)->SetVersion(((NID_5A&)nid).uVersion); break; default: From 4fce186884fc40ce0e766e8815ba5314a929e1a8 Mon Sep 17 00:00:00 2001 From: alur Date: Sat, 20 Oct 2012 03:49:11 -0700 Subject: [PATCH 37/50] Experimental LSSetAsShell replacement code. --- litestep/ExplorerService.cpp | 113 ++++++++++++++++++++++++++++++++++ litestep/ExplorerService.h | 48 +++++++++++++++ litestep/ShellDesktopTray.cpp | 103 +++++++++++++++++++++++++++++++ litestep/ShellDesktopTray.h | 63 +++++++++++++++++++ litestep/litestep.cpp | 50 +++++++-------- litestep/litestep.h | 4 +- 6 files changed, 352 insertions(+), 29 deletions(-) create mode 100644 litestep/ExplorerService.cpp create mode 100644 litestep/ExplorerService.h create mode 100644 litestep/ShellDesktopTray.cpp create mode 100644 litestep/ShellDesktopTray.h diff --git a/litestep/ExplorerService.cpp b/litestep/ExplorerService.cpp new file mode 100644 index 0000000..cdcedbd --- /dev/null +++ b/litestep/ExplorerService.cpp @@ -0,0 +1,113 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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 "../utility/debug.hpp" +#include "ExplorerService.h" +#include "ShellDesktopTray.h" + + +DWORD WINAPI ExplorerThread(LPVOID); + + +ExplorerService::ExplorerService() : + m_dwThreadID(0), + m_hExplorerThread(NULL) +{ +} + + +ExplorerService::~ExplorerService() +{ +} + + +HRESULT ExplorerService::Stop() +{ + if (m_dwThreadID) + { + PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); + } + + if (m_hExplorerThread) + { + if (WaitForSingleObject(m_hExplorerThread, 1000) != WAIT_OBJECT_0) + { + TerminateThread(m_hExplorerThread, 0); + } + + CloseHandle(m_hExplorerThread); + m_hExplorerThread = NULL; + } + + return S_OK; +} + + +HRESULT ExplorerService::Start() +{ + CreateThread(NULL, 0, ExplorerThread, NULL, 0, &m_dwThreadID); + return S_OK; +} + + +DWORD WINAPI ExplorerThread(LPVOID) +{ + typedef void *(WINAPI *SHCREATEDESKTOP)(void *); + typedef bool (WINAPI *SHDESKTOPMESSAGELOOP)(void *); + + TShellDesktopTray *pExplorerTray = NULL; + IShellDesktopTray *pTray = NULL; + SHCREATEDESKTOP fnSHCreateDesktop = NULL; + SHDESKTOPMESSAGELOOP fnSHDesktopMessageLoop = NULL; + HANDLE hDesktop = NULL; + DWORD dwReturn = 0; + + fnSHCreateDesktop = (SHCREATEDESKTOP)GetProcAddress( + GetModuleHandle(_T("SHELL32.DLL")), (LPCSTR)0xC8); + fnSHDesktopMessageLoop = (SHDESKTOPMESSAGELOOP)GetProcAddress( + GetModuleHandle(_T("SHELL32.DLL")), (LPCSTR)0xC9); + + if (fnSHCreateDesktop && fnSHDesktopMessageLoop) + { + pExplorerTray = new TShellDesktopTray(); + pExplorerTray->QueryInterface(IID_IShellDesktopTray, + reinterpret_cast(&pTray)); + + if ((hDesktop = fnSHCreateDesktop(pTray)) != NULL) + { + ShowWindow(FindWindow(_T("Progman"), NULL), SW_HIDE); + fnSHDesktopMessageLoop(hDesktop); + } + else + { + dwReturn = 1; + } + + pTray->Release(); + pExplorerTray->Release(); + } + else + { + dwReturn = 1; + } + + return dwReturn; +} diff --git a/litestep/ExplorerService.h b/litestep/ExplorerService.h new file mode 100644 index 0000000..177ff5f --- /dev/null +++ b/litestep/ExplorerService.h @@ -0,0 +1,48 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(EXPLORERSERVICE_H) +#define EXPLORERSERVICE_H + +#include "ExplorerService.h" +#include "../utility/common.h" +#include "../utility/IService.h" + + +class ExplorerService : public IService +{ +public: + ~ExplorerService(); + ExplorerService(); + + // + // IService methods + // + virtual HRESULT Start(); + virtual HRESULT Stop(); + +private: + DWORD m_dwThreadID; + HANDLE m_hExplorerThread; +}; + + +#endif // EXPLORERSERVICE_H diff --git a/litestep/ShellDesktopTray.cpp b/litestep/ShellDesktopTray.cpp new file mode 100644 index 0000000..9e18575 --- /dev/null +++ b/litestep/ShellDesktopTray.cpp @@ -0,0 +1,103 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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 "../utility/common.h" +#include "ShellDesktopTray.h" + + +TShellDesktopTray::TShellDesktopTray() : + m_uRefCount(0), + m_hDesktopWnd(NULL) +{ +} + + +TShellDesktopTray::~TShellDesktopTray() +{ +} + + +HRESULT TShellDesktopTray::QueryInterface(REFIID riid, LPVOID *ppvObj) +{ + if (!ppvObj) + { + return E_POINTER; + } + + if (riid == IID_IUnknown || riid == IID_IShellDesktopTray) + { + *ppvObj = this; + } + else + { + *ppvObj = NULL; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + + +ULONG TShellDesktopTray::AddRef() +{ + ++m_uRefCount; + + return m_uRefCount; +} + + +ULONG TShellDesktopTray::Release() +{ + if (m_uRefCount > 0) + { + --m_uRefCount; + } + + return m_uRefCount; +} + + +ULONG TShellDesktopTray::GetState() +{ + return 2; +} + + +HRESULT TShellDesktopTray::GetTrayWindow(HWND *hTrayWnd) +{ + // Prevent Explorer from closing the tray window when shutting down + *hTrayWnd = NULL; + return S_OK; +} + + +HRESULT TShellDesktopTray::RegisterDesktopWindow(HWND hDesktopWindow) +{ + m_hDesktopWnd = hDesktopWindow; + return S_OK; +} + + +HRESULT TShellDesktopTray::SetVar(int, ULONG) +{ + return S_OK; +} diff --git a/litestep/ShellDesktopTray.h b/litestep/ShellDesktopTray.h new file mode 100644 index 0000000..a540c35 --- /dev/null +++ b/litestep/ShellDesktopTray.h @@ -0,0 +1,63 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2012 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(SHELLDESKTOPTRAY_H) +#define SHELLDESKTOPTRAY_H + +#include + + +const IID IID_IShellDesktopTray = {0x213E2DF9,0x9A14,0x4328,{0x99,0xB1,0x69,0x61,0xF9,0x14,0x3C,0xE9}}; + + +class IShellDesktopTray : public IUnknown +{ +public: + virtual __declspec(nothrow) ULONG GetState(void) = 0; + virtual __declspec(nothrow) HRESULT GetTrayWindow(HWND *phWnd) = 0; + virtual __declspec(nothrow) HRESULT RegisterDesktopWindow(HWND hDesktopWindow) = 0; + virtual __declspec(nothrow) HRESULT SetVar(int, ULONG) = 0; +}; + + +class TShellDesktopTray : public IShellDesktopTray +{ +public: + TShellDesktopTray(); + ~TShellDesktopTray(); + + // IUnknown + HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj); + ULONG __stdcall AddRef(); + ULONG __stdcall Release(); + + // IShellDesktopTray + ULONG __stdcall GetState(); + HRESULT __stdcall GetTrayWindow(HWND *phWnd); + HRESULT __stdcall RegisterDesktopWindow(HWND hDesktopWindow); + HRESULT __stdcall SetVar(int p1, ULONG p2); + +private: + ULONG m_uRefCount; + HWND m_hDesktopWnd; +}; + +#endif // SHELLDESKTOPTRAY_H diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index a2a1ebc..ca86a13 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -26,6 +26,7 @@ #include "DDEStub.h" #include "RecoveryMenu.h" #include "TrayService.h" +#include "ExplorerService.h" // Managers #include "MessageManager.h" @@ -355,10 +356,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) if (SUCCEEDED(hr)) { - bool bSetAsShell = - (!bUnderExplorer && GetRCBool("LSSetAsShell", TRUE)); - - hr = CreateMainWindow(bSetAsShell); + hr = CreateMainWindow(); } // @@ -366,7 +364,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) // if (SUCCEEDED(hr)) { - hr = _InitServices(); + hr = _InitServices(GetRCBool("LSSetAsShell", TRUE) && !bUnderExplorer); if (SUCCEEDED(hr)) { @@ -486,7 +484,7 @@ int CLiteStep::Run() // // CreateMainWindow // -HRESULT CLiteStep::CreateMainWindow(bool bSetAsShell) +HRESULT CLiteStep::CreateMainWindow() { HRESULT hr = E_FAIL; @@ -526,25 +524,6 @@ HRESULT CLiteStep::CreateMainWindow(bool bSetAsShell) _RegisterShellNotifications(m_hMainWindow); - // Set Shell Window - if (bSetAsShell) - { - typedef BOOL (WINAPI* SETSHELLWINDOWPROC)(HWND); - - SETSHELLWINDOWPROC fnSetShellWindow = - (SETSHELLWINDOWPROC)GetProcAddress( - GetModuleHandle(_T("USER32.DLL")), "SetShellWindow"); - - if (fnSetShellWindow) - { - fnSetShellWindow(m_hMainWindow); - } - else - { - TRACE("SetShellWindow() not found"); - } - } - hr = S_OK; } else @@ -1115,7 +1094,7 @@ LRESULT CLiteStep::_HandleSessionChange(DWORD dwCode, DWORD /* dwSession */) // // _InitServies() // -HRESULT CLiteStep::_InitServices() +HRESULT CLiteStep::_InitServices(bool bSetAsShell) { IService* pService = NULL; @@ -1158,7 +1137,24 @@ HRESULT CLiteStep::_InitServices() return E_OUTOFMEMORY; } } - + + // + // Explorer Service + // + if (bSetAsShell) + { + pService = new ExplorerService(); + + if (pService) + { + m_Services.push_back(pService); + } + else + { + return E_OUTOFMEMORY; + } + } + return S_OK; } diff --git a/litestep/litestep.h b/litestep/litestep.h index 878f278..8f57e91 100644 --- a/litestep/litestep.h +++ b/litestep/litestep.h @@ -81,7 +81,7 @@ class CLiteStep: public ILiteStep private: void MessageHandler(MSG &message); - HRESULT CreateMainWindow(bool bSetAsShell); + HRESULT CreateMainWindow(); HRESULT DestroyMainWindow(); void _RegisterShellNotifications(HWND hWnd); @@ -143,7 +143,7 @@ class CLiteStep: public ILiteStep TrayService* m_pTrayService; // = NULL; std::vector m_Services; - HRESULT _InitServices(); + HRESULT _InitServices(bool bSetAsShell); HRESULT _StartServices(); HRESULT _StopServices(); void _CleanupServices(); From 764099dd5a237139edf629385f8b2621ca329198 Mon Sep 17 00:00:00 2001 From: alur Date: Tue, 23 Oct 2012 01:38:23 -0700 Subject: [PATCH 38/50] Fixed 32bit compilation errors. --- litestep/ShellDesktopTray.h | 22 +++++++++++----------- litestep/litestep_vc11.vcxproj | 6 +++++- lsapi/lsapi_vc11.vcxproj | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/litestep/ShellDesktopTray.h b/litestep/ShellDesktopTray.h index a540c35..962918d 100644 --- a/litestep/ShellDesktopTray.h +++ b/litestep/ShellDesktopTray.h @@ -31,10 +31,10 @@ const IID IID_IShellDesktopTray = {0x213E2DF9,0x9A14,0x4328,{0x99,0xB1,0x69,0x61 class IShellDesktopTray : public IUnknown { public: - virtual __declspec(nothrow) ULONG GetState(void) = 0; - virtual __declspec(nothrow) HRESULT GetTrayWindow(HWND *phWnd) = 0; - virtual __declspec(nothrow) HRESULT RegisterDesktopWindow(HWND hDesktopWindow) = 0; - virtual __declspec(nothrow) HRESULT SetVar(int, ULONG) = 0; + virtual __declspec(nothrow) ULONG STDMETHODCALLTYPE GetState(void) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE GetTrayWindow(HWND *phWnd) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(HWND hDesktopWindow) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE SetVar(int, ULONG) = 0; }; @@ -45,15 +45,15 @@ class TShellDesktopTray : public IShellDesktopTray ~TShellDesktopTray(); // IUnknown - HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj); - ULONG __stdcall AddRef(); - ULONG __stdcall Release(); + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppvObj); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); // IShellDesktopTray - ULONG __stdcall GetState(); - HRESULT __stdcall GetTrayWindow(HWND *phWnd); - HRESULT __stdcall RegisterDesktopWindow(HWND hDesktopWindow); - HRESULT __stdcall SetVar(int p1, ULONG p2); + ULONG STDMETHODCALLTYPE GetState(); + HRESULT STDMETHODCALLTYPE GetTrayWindow(HWND *phWnd); + HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(HWND hDesktopWindow); + HRESULT STDMETHODCALLTYPE SetVar(int p1, ULONG p2); private: ULONG m_uRefCount; diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 6889077..ca46098 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -80,7 +80,7 @@ false - ../Debug_VC11_64\ + C:\LiteStep64\debug Debug_VC11_64\ @@ -228,11 +228,13 @@ + + @@ -244,11 +246,13 @@ + + diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 7760c3d..ac1b52d 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -80,7 +80,7 @@ false - ../Debug_VC11_64\ + C:\LiteStep64\debug Debug_VC11_64\ From 35b6bd538e15258466578f59db2dc87b427f2f82 Mon Sep 17 00:00:00 2001 From: alur Date: Tue, 23 Oct 2012 09:59:27 -0700 Subject: [PATCH 39/50] Fixed 32bit compilation errors. --- litestep/ShellDesktopTray.h | 22 +++++++++++----------- litestep/litestep_vc11.vcxproj | 6 +----- lsapi/lsapi_vc11.vcxproj | 2 +- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/litestep/ShellDesktopTray.h b/litestep/ShellDesktopTray.h index 962918d..a540c35 100644 --- a/litestep/ShellDesktopTray.h +++ b/litestep/ShellDesktopTray.h @@ -31,10 +31,10 @@ const IID IID_IShellDesktopTray = {0x213E2DF9,0x9A14,0x4328,{0x99,0xB1,0x69,0x61 class IShellDesktopTray : public IUnknown { public: - virtual __declspec(nothrow) ULONG STDMETHODCALLTYPE GetState(void) = 0; - virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE GetTrayWindow(HWND *phWnd) = 0; - virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(HWND hDesktopWindow) = 0; - virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE SetVar(int, ULONG) = 0; + virtual __declspec(nothrow) ULONG GetState(void) = 0; + virtual __declspec(nothrow) HRESULT GetTrayWindow(HWND *phWnd) = 0; + virtual __declspec(nothrow) HRESULT RegisterDesktopWindow(HWND hDesktopWindow) = 0; + virtual __declspec(nothrow) HRESULT SetVar(int, ULONG) = 0; }; @@ -45,15 +45,15 @@ class TShellDesktopTray : public IShellDesktopTray ~TShellDesktopTray(); // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppvObj); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); + HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj); + ULONG __stdcall AddRef(); + ULONG __stdcall Release(); // IShellDesktopTray - ULONG STDMETHODCALLTYPE GetState(); - HRESULT STDMETHODCALLTYPE GetTrayWindow(HWND *phWnd); - HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(HWND hDesktopWindow); - HRESULT STDMETHODCALLTYPE SetVar(int p1, ULONG p2); + ULONG __stdcall GetState(); + HRESULT __stdcall GetTrayWindow(HWND *phWnd); + HRESULT __stdcall RegisterDesktopWindow(HWND hDesktopWindow); + HRESULT __stdcall SetVar(int p1, ULONG p2); private: ULONG m_uRefCount; diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index ca46098..6889077 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -80,7 +80,7 @@ false - C:\LiteStep64\debug + ../Debug_VC11_64\ Debug_VC11_64\ @@ -228,13 +228,11 @@ - - @@ -246,13 +244,11 @@ - - diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index ac1b52d..7760c3d 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -80,7 +80,7 @@ false - C:\LiteStep64\debug + ../Debug_VC11_64\ Debug_VC11_64\ From 55766a3f73994fa2907a587be703c26f5de768b0 Mon Sep 17 00:00:00 2001 From: alur Date: Tue, 23 Oct 2012 10:04:02 -0700 Subject: [PATCH 40/50] Added missing files to project. --- litestep/litestep_vc11.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 6889077..141ffb4 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -228,11 +228,13 @@ + + @@ -244,11 +246,13 @@ + + From 144ae78a4fdbd6886b664510a236478d8c14b362 Mon Sep 17 00:00:00 2001 From: alur Date: Sat, 22 Jun 2013 12:10:18 -0700 Subject: [PATCH 41/50] Added LSCloseExplorer (useful for development) --- docs/manual.txt | 12 ++++++++--- litestep/litestep.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/docs/manual.txt b/docs/manual.txt index effa330..e504bc6 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -2,7 +2,7 @@ LiteStep 0.25.0 Release Notes - Copyright (c) 2012 - LiteStep Development Team + Copyright (c) 2013 - LiteStep Development Team =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Contents: @@ -781,14 +781,20 @@ Contents: Usage: LSAutoHideModules TRUE + + LSCloseExplorer + -------------------------- + If explorer is running as shell when LiteStep launches, LiteStep will attempt + to close it. + + Usage: + LSCloseExplorer TRUE LSNoShellWarning -------------------------- Disables the warning issued when loading LiteStep if another shell is already running. Do not use this setting unless you know what you are doing! - Note: LiteStep must be restarted for this setting to take affect. - Usage: LSNoShellWarning TRUE diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index ca86a13..b76c11f 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -42,6 +42,7 @@ #include #include #include +#include // namespace stuff @@ -324,6 +325,53 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) // // Check for another shell // + if (FindWindow("Shell_TrayWnd", NULL) != NULL) + { + if (GetRCBool("LSCloseExplorer", TRUE)) + { + HWND hTrayWindow = FindWindow("Shell_TrayWnd", NULL); + + // Determine the name of the current Shell + DWORD dwProcessID; + GetWindowThreadProcessId(hTrayWindow, &dwProcessID); + HANDLE hShellProc = OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, + FALSE, + dwProcessID + ); + + if (hShellProc != NULL) + { + char szProcessPath[MAX_PATH]; + GetModuleFileNameEx(hShellProc, NULL, szProcessPath, _countof(szProcessPath)); + LPCSTR pszPathName = PathFindFileName(szProcessPath); + + if (strcmp(pszPathName, "explorer.exe") == 0) + { + if (IsVistaOrAbove()) + { + PostMessage(hTrayWindow, 0x5B4, 0, 0); + } + else if (IsOS(OS_XPORGREATER)) + { + HWND hProgman = FindWindow(_T("Progman"), NULL); + PostMessage(hProgman, WM_QUIT, 0, TRUE); + PostMessage(hTrayWindow, WM_QUIT, 0, 0); + } + else + { + // Not supported + } + + // Wait for the process to exit + WaitForSingleObject(hShellProc, 3000); // Wait for at most 3 seconds. + } + + CloseHandle(hShellProc); + } + } + } + if (FindWindow("Shell_TrayWnd", NULL) != NULL) { if (GetRCBool("LSNoShellWarning", FALSE)) From 61152ad104ded123ad5a3546a1b714d3c12fd8fe Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 23 Jun 2013 12:47:25 -0700 Subject: [PATCH 42/50] Updated dates. --- litestep/DDEService.cpp | 2 +- litestep/DDEService.h | 2 +- litestep/DDEStub.cpp | 2 +- litestep/DDEStub.h | 2 +- litestep/DDEWorker.cpp | 2 +- litestep/DDEWorker.h | 2 +- litestep/DataStore.cpp | 2 +- litestep/DataStore.h | 2 +- litestep/ExplorerService.cpp | 2 +- litestep/ExplorerService.h | 2 +- litestep/MessageManager.cpp | 2 +- litestep/MessageManager.h | 2 +- litestep/Module.cpp | 2 +- litestep/Module.h | 2 +- litestep/ModuleManager.cpp | 2 +- litestep/ModuleManager.h | 2 +- litestep/RecoveryMenu.cpp | 2 +- litestep/RecoveryMenu.h | 2 +- litestep/ShellDesktopTray.cpp | 2 +- litestep/ShellDesktopTray.h | 2 +- litestep/StartupRunner.cpp | 2 +- litestep/StartupRunner.h | 2 +- litestep/TrayAppBar.h | 2 +- litestep/TrayNotifyIcon.cpp | 2 +- litestep/TrayNotifyIcon.h | 2 +- litestep/TrayService.cpp | 2 +- litestep/TrayService.h | 2 +- litestep/WinMain.cpp | 2 +- litestep/buildoptions.h | 2 +- litestep/litestep.cpp | 4 ++-- litestep/litestep.h | 2 +- lsapi/BangCommand.cpp | 2 +- lsapi/BangCommand.h | 2 +- lsapi/BangManager.cpp | 2 +- lsapi/BangManager.h | 2 +- lsapi/MathEvaluate.cpp | 2 +- lsapi/MathEvaluate.h | 2 +- lsapi/MathException.h | 2 +- lsapi/MathParser.cpp | 2 +- lsapi/MathParser.h | 2 +- lsapi/MathScanner.cpp | 2 +- lsapi/MathScanner.h | 2 +- lsapi/MathToken.cpp | 2 +- lsapi/MathToken.h | 2 +- lsapi/MathValue.cpp | 2 +- lsapi/MathValue.h | 2 +- lsapi/SettingsDefines.h | 2 +- lsapi/SettingsFileParser.cpp | 2 +- lsapi/SettingsFileParser.h | 2 +- lsapi/SettingsIterator.cpp | 2 +- lsapi/SettingsIterator.h | 2 +- lsapi/SettingsManager.h | 2 +- lsapi/ThreadedBangCommand.h | 2 +- lsapi/aboutbox.cpp | 2 +- lsapi/graphics.cpp | 2 +- lsapi/lsapi.cpp | 2 +- lsapi/lsapi.h | 2 +- lsapi/lsapiInit.cpp | 2 +- lsapi/lsapiInit.h | 2 +- lsapi/lsapidefines.h | 2 +- lsapi/match.cpp | 2 +- lsapi/picopng.cpp | 2 +- lsapi/picopng.h | 2 +- lsapi/png_support.cpp | 2 +- lsapi/png_support.h | 2 +- lsapi/settings.cpp | 2 +- lsapi/settingsmanager.cpp | 2 +- lsapi/stubs.cpp | 2 +- utility/Base.h | 2 +- utility/ILiteStep.h | 2 +- utility/IManager.h | 2 +- utility/IService.h | 2 +- utility/common.h | 2 +- utility/core.hpp | 2 +- utility/criticalsection.h | 2 +- utility/debug.cpp | 2 +- utility/debug.hpp | 2 +- utility/fixup.h | 2 +- utility/macros.h | 2 +- utility/shellhlp.cpp | 2 +- utility/shellhlp.h | 2 +- utility/stringutility.h | 2 +- 82 files changed, 83 insertions(+), 83 deletions(-) diff --git a/litestep/DDEService.cpp b/litestep/DDEService.cpp index 664f2dc..d458728 100644 --- a/litestep/DDEService.cpp +++ b/litestep/DDEService.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEService.h b/litestep/DDEService.h index 1b2d88c..e75f1a5 100644 --- a/litestep/DDEService.h +++ b/litestep/DDEService.h @@ -3,7 +3,7 @@ // This is a part of the Litestep Shell source code. // // Copyright (C) 1998 (e) -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEStub.cpp b/litestep/DDEStub.cpp index e0a23fb..b4b875c 100644 --- a/litestep/DDEStub.cpp +++ b/litestep/DDEStub.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEStub.h b/litestep/DDEStub.h index 6ab0836..9492ea0 100644 --- a/litestep/DDEStub.h +++ b/litestep/DDEStub.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEWorker.cpp b/litestep/DDEWorker.cpp index d609715..2e2f898 100644 --- a/litestep/DDEWorker.cpp +++ b/litestep/DDEWorker.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DDEWorker.h b/litestep/DDEWorker.h index bdf0df2..21923e1 100644 --- a/litestep/DDEWorker.h +++ b/litestep/DDEWorker.h @@ -3,7 +3,7 @@ // This is a part of the Litestep Shell source code. // // Copyright (C) 1998 (e) -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DataStore.cpp b/litestep/DataStore.cpp index e7f5670..018083f 100644 --- a/litestep/DataStore.cpp +++ b/litestep/DataStore.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/DataStore.h b/litestep/DataStore.h index feaa747..55fdb94 100644 --- a/litestep/DataStore.h +++ b/litestep/DataStore.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ExplorerService.cpp b/litestep/ExplorerService.cpp index cdcedbd..c874b17 100644 --- a/litestep/ExplorerService.cpp +++ b/litestep/ExplorerService.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ExplorerService.h b/litestep/ExplorerService.h index 177ff5f..bba2eb3 100644 --- a/litestep/ExplorerService.h +++ b/litestep/ExplorerService.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/MessageManager.cpp b/litestep/MessageManager.cpp index 03a541f..b0fc523 100644 --- a/litestep/MessageManager.cpp +++ b/litestep/MessageManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/MessageManager.h b/litestep/MessageManager.h index 9848331..45bb219 100644 --- a/litestep/MessageManager.h +++ b/litestep/MessageManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/Module.cpp b/litestep/Module.cpp index d31aac1..dad1d59 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/Module.h b/litestep/Module.h index 3d62d93..7de83f8 100644 --- a/litestep/Module.h +++ b/litestep/Module.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ModuleManager.cpp b/litestep/ModuleManager.cpp index 874363f..08b04a8 100644 --- a/litestep/ModuleManager.cpp +++ b/litestep/ModuleManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ModuleManager.h b/litestep/ModuleManager.h index 1c2345c..4d80634 100644 --- a/litestep/ModuleManager.h +++ b/litestep/ModuleManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/RecoveryMenu.cpp b/litestep/RecoveryMenu.cpp index c8a9667..ba2ffd4 100644 --- a/litestep/RecoveryMenu.cpp +++ b/litestep/RecoveryMenu.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/RecoveryMenu.h b/litestep/RecoveryMenu.h index 9b2262e..6ea1be6 100644 --- a/litestep/RecoveryMenu.h +++ b/litestep/RecoveryMenu.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ShellDesktopTray.cpp b/litestep/ShellDesktopTray.cpp index 9e18575..b1b609d 100644 --- a/litestep/ShellDesktopTray.cpp +++ b/litestep/ShellDesktopTray.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/ShellDesktopTray.h b/litestep/ShellDesktopTray.h index a540c35..3765f1b 100644 --- a/litestep/ShellDesktopTray.h +++ b/litestep/ShellDesktopTray.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/StartupRunner.cpp b/litestep/StartupRunner.cpp index b5d94c2..925802c 100644 --- a/litestep/StartupRunner.cpp +++ b/litestep/StartupRunner.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/StartupRunner.h b/litestep/StartupRunner.h index 2f7275e..697a571 100644 --- a/litestep/StartupRunner.h +++ b/litestep/StartupRunner.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayAppBar.h b/litestep/TrayAppBar.h index ca0759e..3c18a85 100644 --- a/litestep/TrayAppBar.h +++ b/litestep/TrayAppBar.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index 0b91d3a..5c4b50a 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index be54ad2..eb111f8 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 2fe11cf..7ce77ef 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/TrayService.h b/litestep/TrayService.h index f2d711c..9ab91bf 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/WinMain.cpp b/litestep/WinMain.cpp index f922c41..aea5db0 100644 --- a/litestep/WinMain.cpp +++ b/litestep/WinMain.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/buildoptions.h b/litestep/buildoptions.h index 780f632..4597474 100644 --- a/litestep/buildoptions.h +++ b/litestep/buildoptions.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index b76c11f..e04af58 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -354,7 +354,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) } else if (IsOS(OS_XPORGREATER)) { - HWND hProgman = FindWindow(_T("Progman"), NULL); + HWND hProgman = FindWindow("Progman", NULL); PostMessage(hProgman, WM_QUIT, 0, TRUE); PostMessage(hTrayWindow, WM_QUIT, 0, 0); } diff --git a/litestep/litestep.h b/litestep/litestep.h index 8f57e91..6416b32 100644 --- a/litestep/litestep.h +++ b/litestep/litestep.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangCommand.cpp b/lsapi/BangCommand.cpp index 0a60ad0..ffb0ee7 100644 --- a/lsapi/BangCommand.cpp +++ b/lsapi/BangCommand.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangCommand.h b/lsapi/BangCommand.h index 2e088ad..e9f480d 100644 --- a/lsapi/BangCommand.h +++ b/lsapi/BangCommand.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangManager.cpp b/lsapi/BangManager.cpp index 1a736ae..29f68c0 100644 --- a/lsapi/BangManager.cpp +++ b/lsapi/BangManager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/BangManager.h b/lsapi/BangManager.h index c2241eb..83965d9 100644 --- a/lsapi/BangManager.h +++ b/lsapi/BangManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathEvaluate.cpp b/lsapi/MathEvaluate.cpp index 711042c..a4983bc 100644 --- a/lsapi/MathEvaluate.cpp +++ b/lsapi/MathEvaluate.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathEvaluate.h b/lsapi/MathEvaluate.h index 7f9ab0c..4c16630 100644 --- a/lsapi/MathEvaluate.h +++ b/lsapi/MathEvaluate.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathException.h b/lsapi/MathException.h index f27adb8..cd35b89 100644 --- a/lsapi/MathException.h +++ b/lsapi/MathException.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathParser.cpp b/lsapi/MathParser.cpp index 37ea681..c92b486 100644 --- a/lsapi/MathParser.cpp +++ b/lsapi/MathParser.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathParser.h b/lsapi/MathParser.h index b1c8823..f3c92be 100644 --- a/lsapi/MathParser.h +++ b/lsapi/MathParser.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathScanner.cpp b/lsapi/MathScanner.cpp index 081b979..1474cd3 100644 --- a/lsapi/MathScanner.cpp +++ b/lsapi/MathScanner.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathScanner.h b/lsapi/MathScanner.h index 7f9d8d6..9e2fe3e 100644 --- a/lsapi/MathScanner.h +++ b/lsapi/MathScanner.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathToken.cpp b/lsapi/MathToken.cpp index 211a0ae..7bd9aac 100644 --- a/lsapi/MathToken.cpp +++ b/lsapi/MathToken.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathToken.h b/lsapi/MathToken.h index be23bd4..1cb0722 100644 --- a/lsapi/MathToken.h +++ b/lsapi/MathToken.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathValue.cpp b/lsapi/MathValue.cpp index 31c5d0c..6f68947 100644 --- a/lsapi/MathValue.cpp +++ b/lsapi/MathValue.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/MathValue.h b/lsapi/MathValue.h index 5f33fad..50225da 100644 --- a/lsapi/MathValue.h +++ b/lsapi/MathValue.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsDefines.h b/lsapi/SettingsDefines.h index b5bde51..23a607e 100644 --- a/lsapi/SettingsDefines.h +++ b/lsapi/SettingsDefines.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsFileParser.cpp b/lsapi/SettingsFileParser.cpp index fb4f54c..e6a655a 100644 --- a/lsapi/SettingsFileParser.cpp +++ b/lsapi/SettingsFileParser.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsFileParser.h b/lsapi/SettingsFileParser.h index 8b35696..d0f3e69 100644 --- a/lsapi/SettingsFileParser.h +++ b/lsapi/SettingsFileParser.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsIterator.cpp b/lsapi/SettingsIterator.cpp index af7f20c..14b0423 100644 --- a/lsapi/SettingsIterator.cpp +++ b/lsapi/SettingsIterator.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsIterator.h b/lsapi/SettingsIterator.h index 0fb2e5d..e86c4a6 100644 --- a/lsapi/SettingsIterator.h +++ b/lsapi/SettingsIterator.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/SettingsManager.h b/lsapi/SettingsManager.h index 50a04c0..8aa3bf7 100644 --- a/lsapi/SettingsManager.h +++ b/lsapi/SettingsManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/ThreadedBangCommand.h b/lsapi/ThreadedBangCommand.h index f2a8cae..1e1d775 100644 --- a/lsapi/ThreadedBangCommand.h +++ b/lsapi/ThreadedBangCommand.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index d8871ea..2e3f8bf 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/graphics.cpp b/lsapi/graphics.cpp index 5f82c2a..eef2b5c 100644 --- a/lsapi/graphics.cpp +++ b/lsapi/graphics.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index 1c1d96d..e0469fe 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapi.h b/lsapi/lsapi.h index d268d80..6785f92 100644 --- a/lsapi/lsapi.h +++ b/lsapi/lsapi.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index 54cc6be..e53f34d 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapiInit.h b/lsapi/lsapiInit.h index 6d6fde3..02f0199 100644 --- a/lsapi/lsapiInit.h +++ b/lsapi/lsapiInit.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index 039b7d2..d953e47 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/match.cpp b/lsapi/match.cpp index 7e18d5b..b7b1e1c 100644 --- a/lsapi/match.cpp +++ b/lsapi/match.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/picopng.cpp b/lsapi/picopng.cpp index f233d21..32e8953 100644 --- a/lsapi/picopng.cpp +++ b/lsapi/picopng.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/picopng.h b/lsapi/picopng.h index c6f4000..59cdde8 100644 --- a/lsapi/picopng.h +++ b/lsapi/picopng.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/png_support.cpp b/lsapi/png_support.cpp index 09a59b8..53867e2 100644 --- a/lsapi/png_support.cpp +++ b/lsapi/png_support.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/png_support.h b/lsapi/png_support.h index d2e0ae2..8fe2a40 100644 --- a/lsapi/png_support.h +++ b/lsapi/png_support.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/settings.cpp b/lsapi/settings.cpp index a3ddbab..c955504 100644 --- a/lsapi/settings.cpp +++ b/lsapi/settings.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/settingsmanager.cpp b/lsapi/settingsmanager.cpp index a72f2a9..dd23037 100644 --- a/lsapi/settingsmanager.cpp +++ b/lsapi/settingsmanager.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/lsapi/stubs.cpp b/lsapi/stubs.cpp index 8d5e851..837d8b6 100644 --- a/lsapi/stubs.cpp +++ b/lsapi/stubs.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/Base.h b/utility/Base.h index 4b8a252..02e7818 100644 --- a/utility/Base.h +++ b/utility/Base.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/ILiteStep.h b/utility/ILiteStep.h index 24275fb..d7678e8 100644 --- a/utility/ILiteStep.h +++ b/utility/ILiteStep.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/IManager.h b/utility/IManager.h index 4b67028..2515855 100644 --- a/utility/IManager.h +++ b/utility/IManager.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/IService.h b/utility/IService.h index 0918858..03d0152 100644 --- a/utility/IService.h +++ b/utility/IService.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/common.h b/utility/common.h index 62941f1..97399df 100644 --- a/utility/common.h +++ b/utility/common.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/core.hpp b/utility/core.hpp index 7f48a09..e3c0110 100644 --- a/utility/core.hpp +++ b/utility/core.hpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/criticalsection.h b/utility/criticalsection.h index 7af0c88..423f914 100644 --- a/utility/criticalsection.h +++ b/utility/criticalsection.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/debug.cpp b/utility/debug.cpp index c947f3e..4543214 100644 --- a/utility/debug.cpp +++ b/utility/debug.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/debug.hpp b/utility/debug.hpp index a8d73aa..931d1c2 100644 --- a/utility/debug.hpp +++ b/utility/debug.hpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/fixup.h b/utility/fixup.h index 77b82f3..b1f1e60 100644 --- a/utility/fixup.h +++ b/utility/fixup.h @@ -2,7 +2,7 @@ // // This is a part of the LiteStep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/macros.h b/utility/macros.h index 0605b60..ea32e4a 100644 --- a/utility/macros.h +++ b/utility/macros.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index 65b7afb..f232ff3 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/shellhlp.h b/utility/shellhlp.h index a2d1622..4aaec21 100644 --- a/utility/shellhlp.h +++ b/utility/shellhlp.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/utility/stringutility.h b/utility/stringutility.h index 8af822d..1008d5e 100644 --- a/utility/stringutility.h +++ b/utility/stringutility.h @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License From 459f88a87173783ac45ff7c7860d726e9d93e007 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 23 Jun 2013 12:48:13 -0700 Subject: [PATCH 43/50] Subclassed the !Run dialog to let it execute bang commands. --- lsapi/bangs.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index 5e2ec25..b921ed0 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -2,7 +2,7 @@ // // This is a part of the Litestep Shell source code. // -// Copyright (C) 1997-2012 LiteStep Development Team +// Copyright (C) 1997-2013 LiteStep Development Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -315,11 +315,54 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) { HWND hParent = CreateWindowEx(WS_EX_TOOLWINDOW, "Static", "", WS_POPUP, nX, nY, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); + SetWindowLongPtr(hParent, GWLP_USERDATA, 0); + SetWindowLongPtr(hParent, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT + { + if (message == WM_TIMER) + { + HWND hDialog = GetWindow(window, GW_ENABLEDPOPUP); + if (hDialog != nullptr) + { + KillTimer(window, 1); + + if (GetWindowLongPtr(window, GWLP_USERDATA) == 0) + { + SetWindowLongPtr(hDialog, GWLP_USERDATA, GetWindowLongPtr(hDialog, GWLP_WNDPROC)); + SetWindowLongPtr(hDialog, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT + { + if (message == WM_COMMAND && LOWORD(wParam) == 1 && HIWORD(wParam) == 0) + { + // Pressed OK, handle it ourselves and forward a cancel instead. + HWND hEditBox = GetDlgItem(window, 0x300A); + if (hEditBox != nullptr) + { + int textLength = GetWindowTextLength(hEditBox) + 1; + LPSTR text = (LPSTR)malloc(textLength*sizeof(char)); + GetWindowText(hEditBox, text, textLength); + + // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. + if (text[0] == '!') { + LSExecute(nullptr, text, SW_SHOWNORMAL); + wParam = MAKEWPARAM(2, 0); // Click on cancel + } + free(text); + } + } + return WNDPROC(GetWindowLongPtr(window, GWLP_USERDATA))(window, message, wParam, lParam); + }); + SetWindowLongPtr(window, GWLP_USERDATA, 1); + } + } + } + return DefWindowProc(window, message, wParam, lParam); + }); + SetTimer(hParent, 1, 10, nullptr); // RunDlg(parent, icon, ?, ?, Description, ?); RunDlg(hParent, NULL, NULL, NULL, NULL, 0); - if (hParent) { + if (hParent) + { DestroyWindow(hParent); } } From 4edd83d07d0fbe24ff2d0484f28294f0c2e1b6ad Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 23 Jun 2013 14:27:26 -0700 Subject: [PATCH 44/50] Fixed formatting. --- lsapi/bangs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index b921ed0..f003cff 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -341,7 +341,8 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) GetWindowText(hEditBox, text, textLength); // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. - if (text[0] == '!') { + if (text[0] == '!') + { LSExecute(nullptr, text, SW_SHOWNORMAL); wParam = MAKEWPARAM(2, 0); // Click on cancel } From bf733991249c1102e53ce62375196305c0d3a9a5 Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 23 Jun 2013 15:16:40 -0700 Subject: [PATCH 45/50] Fixed some dates I missed the first time around. --- litestep/litestep.rc | 2 +- lsapi/aboutbox.cpp | 2 +- lsapi/lsapi.rc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/litestep/litestep.rc b/litestep/litestep.rc index 735253d..fe2d043 100644 --- a/litestep/litestep.rc +++ b/litestep/litestep.rc @@ -150,7 +150,7 @@ BEGIN VALUE "FileDescription", "LiteStep" VALUE "FileVersion", "0.25.0 Alpha" VALUE "InternalName", "LiteStep Core" - VALUE "LegalCopyright", "Copyright © 1997 - 2012" + VALUE "LegalCopyright", "Copyright © 1997 - 2013" VALUE "OriginalFilename", "litestep.exe" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 2e3f8bf..1b82540 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -116,7 +116,7 @@ static const CHAR g_szLicense[] = \ "LiteStep is a replacement shell for the standard Windows® Explorer shell.\r\n" "\r\n" "Copyright (C) 1997-1998 Francis Gastellu\r\n" - "Copyright (C) 1998-2012 LiteStep Development Team\r\n" + "Copyright (C) 1998-2013 LiteStep Development Team\r\n" "\r\n" "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 " diff --git a/lsapi/lsapi.rc b/lsapi/lsapi.rc index bb1ea41..ce02146 100644 --- a/lsapi/lsapi.rc +++ b/lsapi/lsapi.rc @@ -48,7 +48,7 @@ BEGIN VALUE "FileDescription", "LiteStep Module API" VALUE "FileVersion", "0.25.0 Alpha" VALUE "InternalName", "LiteStep API" - VALUE "LegalCopyright", "Copyright © 1997 - 2012" + VALUE "LegalCopyright", "Copyright © 1997 - 2013" VALUE "OriginalFilename", "lsapi.dll" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" From 1d6e9ce6a95afe4797c829d659aa2442f4728d2a Mon Sep 17 00:00:00 2001 From: alur Date: Sun, 23 Jun 2013 17:03:46 -0700 Subject: [PATCH 46/50] Cleaned up a little and documented the RunDlg call. --- lsapi/bangs.cpp | 75 +++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index f003cff..aecb1f8 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -298,7 +298,14 @@ static void BangRestoreWindows(HWND /* hCaller */, LPCSTR /* pszArgs */) // static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) { - typedef VOID (WINAPI* RunDlgType)(HWND,HICON,LPCWSTR,LPCWSTR,LPCWSTR,UINT); + // Flags + // 1 -- Removes the browse button. + // 2 -- No default text. + // 4 -- Calculates the working directory from the filename. + // 8 -- Hides the label to the left of the box. + // 32 -- Removes the Separate Memory Space check box (Windows NT only) + typedef VOID (WINAPI* RunDlgType)(HWND hwndOwner, HICON hIcon, LPCWSTR pwszDirectory, + LPCWSTR pwszTitle, LPCWSTR pwszDescription, UINT uFlags); char szX[MAX_LINE_LENGTH] = { 0 }; char szY[MAX_LINE_LENGTH] = { 0 }; @@ -315,51 +322,53 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) { HWND hParent = CreateWindowEx(WS_EX_TOOLWINDOW, "Static", "", WS_POPUP, nX, nY, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); - SetWindowLongPtr(hParent, GWLP_USERDATA, 0); - SetWindowLongPtr(hParent, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT + if (hParent) { - if (message == WM_TIMER) + SetWindowLongPtr(hParent, GWLP_USERDATA, 0); + SetWindowLongPtr(hParent, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT { - HWND hDialog = GetWindow(window, GW_ENABLEDPOPUP); - if (hDialog != nullptr) + if (message == WM_TIMER) { - KillTimer(window, 1); - - if (GetWindowLongPtr(window, GWLP_USERDATA) == 0) + HWND hDialog = GetWindow(window, GW_ENABLEDPOPUP); + if (hDialog != nullptr) { - SetWindowLongPtr(hDialog, GWLP_USERDATA, GetWindowLongPtr(hDialog, GWLP_WNDPROC)); - SetWindowLongPtr(hDialog, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT + KillTimer(window, 1); + + if (GetWindowLongPtr(window, GWLP_USERDATA) == 0) { - if (message == WM_COMMAND && LOWORD(wParam) == 1 && HIWORD(wParam) == 0) + SetWindowLongPtr(hDialog, GWLP_USERDATA, GetWindowLongPtr(hDialog, GWLP_WNDPROC)); + SetWindowLongPtr(hDialog, GWLP_WNDPROC, (LONG_PTR)(WNDPROC) [] (HWND window, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT { - // Pressed OK, handle it ourselves and forward a cancel instead. - HWND hEditBox = GetDlgItem(window, 0x300A); - if (hEditBox != nullptr) + if (message == WM_COMMAND && LOWORD(wParam) == 1 && HIWORD(wParam) == 0) { - int textLength = GetWindowTextLength(hEditBox) + 1; - LPSTR text = (LPSTR)malloc(textLength*sizeof(char)); - GetWindowText(hEditBox, text, textLength); - - // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. - if (text[0] == '!') + // Pressed OK, handle it ourselves and forward a cancel instead. + HWND hEditBox = GetDlgItem(window, 0x300A); + if (hEditBox != nullptr) { - LSExecute(nullptr, text, SW_SHOWNORMAL); - wParam = MAKEWPARAM(2, 0); // Click on cancel + int nTextLength = GetWindowTextLength(hEditBox) + 1; + LPSTR pszText = (LPSTR)malloc(nTextLength*sizeof(char)); + GetWindowText(hEditBox, pszText, nTextLength); + + // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. + if (pszText[0] == '!') + { + LSExecute(nullptr, pszText, SW_SHOWNORMAL); + wParam = MAKEWPARAM(2, 0); // Click on cancel + } + free(pszText); } - free(text); } - } - return WNDPROC(GetWindowLongPtr(window, GWLP_USERDATA))(window, message, wParam, lParam); - }); - SetWindowLongPtr(window, GWLP_USERDATA, 1); + return WNDPROC(GetWindowLongPtr(window, GWLP_USERDATA))(window, message, wParam, lParam); + }); + SetWindowLongPtr(window, GWLP_USERDATA, 1); + } } } - } - return DefWindowProc(window, message, wParam, lParam); - }); - SetTimer(hParent, 1, 10, nullptr); + return DefWindowProc(window, message, wParam, lParam); + }); + SetTimer(hParent, 1, 10, nullptr); + } - // RunDlg(parent, icon, ?, ?, Description, ?); RunDlg(hParent, NULL, NULL, NULL, NULL, 0); if (hParent) From f73da16033486424a6d21bc4aa2f772bca54a8ac Mon Sep 17 00:00:00 2001 From: alur Date: Mon, 24 Jun 2013 11:56:56 -0700 Subject: [PATCH 47/50] Fixed issue where explorer.EXE is started with a different capitalization. (such as on startup). --- litestep/litestep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index e04af58..e822eb9 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -346,7 +346,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) GetModuleFileNameEx(hShellProc, NULL, szProcessPath, _countof(szProcessPath)); LPCSTR pszPathName = PathFindFileName(szProcessPath); - if (strcmp(pszPathName, "explorer.exe") == 0) + if (_stricmp(pszPathName, "explorer.exe") == 0) { if (IsVistaOrAbove()) { From bf65daa683e2242b2bf5f61c3c1ec06bfd041485 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Sat, 3 Aug 2013 19:24:38 -0700 Subject: [PATCH 48/50] Update from CVS. --- Makefile | 1 + docs/0.24.7/changes.txt | 125 ++ docs/0.24.7/license.txt | 662 ++++++++++ docs/build.txt | 2 +- docs/{build_vc10.txt => build_vc11.txt} | 105 +- docs/changes.txt | 403 ++++-- docs/license.txt | 2 +- docs/manual.txt | 47 +- litestep/DDEService.cpp | 7 + litestep/DDEService.h | 5 +- litestep/DDEStub.cpp | 10 + litestep/DDEStub.h | 5 +- litestep/DDEWorker.cpp | 133 +- litestep/DDEWorker.h | 10 +- litestep/ExplorerService.cpp | 55 +- litestep/ExplorerService.h | 10 +- litestep/FullscreenMonitor.cpp | 380 ++++++ litestep/FullscreenMonitor.h | 65 + litestep/Module.cpp | 181 ++- litestep/Module.h | 25 +- litestep/ModuleManager.cpp | 50 +- litestep/ModuleManager.h | 26 +- litestep/RecoveryMenu.cpp | 46 +- litestep/RecoveryMenu.h | 5 +- litestep/ShellDesktopTray.cpp | 14 +- litestep/ShellDesktopTray.h | 24 +- litestep/StartupRunner.cpp | 74 +- litestep/StartupRunner.h | 3 +- litestep/TaskbarListHandler.cpp | 323 +++++ litestep/TaskbarListHandler.h | 47 + litestep/TrayNotifyIcon.cpp | 34 +- litestep/TrayNotifyIcon.h | 62 +- litestep/TrayService.cpp | 69 +- litestep/TrayService.h | 7 +- litestep/WinMain.cpp | 114 +- litestep/buildoptions.h | 8 +- litestep/litestep.cpp | 562 ++++----- litestep/litestep.h | 20 +- litestep/litestep.rc | 36 +- litestep/litestep_vc11.vcxproj | 564 ++++----- ...tep_vc10.vcxproj => litestep_vc12.vcxproj} | 546 +++++---- litestep/litestep_vc71.vcproj | 253 ---- litestep/litestep_vc8.vcproj | 350 ------ litestep/litestep_vc9.vcproj | 349 ------ litestep/resource.h | 6 +- litestep_vc11.sln | 90 +- litestep_vc10.sln => litestep_vc12.sln | 90 +- litestep_vc71.sln | 40 - litestep_vc8.sln | 38 - litestep_vc9.sln | 38 - lsapi/BangCommand.cpp | 66 +- lsapi/BangCommand.h | 42 +- lsapi/BangManager.cpp | 20 +- lsapi/BangManager.h | 18 +- lsapi/MathEvaluate.cpp | 18 +- lsapi/MathEvaluate.h | 6 +- lsapi/MathException.h | 11 +- lsapi/MathParser.cpp | 116 +- lsapi/MathParser.h | 6 +- lsapi/MathScanner.cpp | 150 +-- lsapi/MathScanner.h | 16 +- lsapi/MathToken.cpp | 70 +- lsapi/MathToken.h | 10 +- lsapi/MathValue.cpp | 52 +- lsapi/MathValue.h | 20 +- lsapi/SettingsDefines.h | 6 +- lsapi/SettingsFileParser.cpp | 305 +++-- lsapi/SettingsFileParser.h | 60 +- lsapi/SettingsIterator.cpp | 62 +- lsapi/SettingsIterator.h | 24 +- lsapi/SettingsManager.h | 119 +- lsapi/ThreadedBangCommand.h | 18 +- lsapi/aboutbox.cpp | 276 ++--- lsapi/bangs.cpp | 302 ++--- lsapi/graphics.cpp | 151 ++- lsapi/lsapi.cpp | 818 ++++++++++--- lsapi/lsapi.h | 127 +- lsapi/lsapi.rc | 6 +- lsapi/lsapiInit.cpp | 207 ++-- lsapi/lsapiInit.h | 10 +- lsapi/lsapi_vc11.vcxproj | 562 ++++----- ...{lsapi_vc10.vcxproj => lsapi_vc12.vcxproj} | 548 +++++---- lsapi/lsapi_vc71.vcproj | 277 ----- lsapi/lsapi_vc8.vcproj | 400 ------ lsapi/lsapi_vc9.vcproj | 399 ------ lsapi/lsapidefines.h | 80 +- lsapi/match.cpp | 370 +++++- lsapi/picopng.cpp | 1086 ++++++++--------- lsapi/png_support.cpp | 10 +- lsapi/png_support.h | 2 +- lsapi/settings.cpp | 335 ++++- lsapi/settingsmanager.cpp | 361 +++--- lsapi/stubs.cpp | 204 +++- utility/IService.h | 1 + utility/common.h | 5 +- utility/debug.cpp | 10 +- utility/macros.h | 18 +- utility/shellhlp.cpp | 361 ++++-- utility/shellhlp.h | 55 +- utility/stringutility.cpp | 55 + utility/stringutility.h | 21 +- utility/utility_vc11.vcxproj | 423 +++---- ...lity_vc10.vcxproj => utility_vc12.vcxproj} | 409 ++++--- utility/utility_vc71.vcproj | 172 --- utility/utility_vc8.vcproj | 244 ---- utility/utility_vc9.vcproj | 245 ---- 106 files changed, 8598 insertions(+), 7288 deletions(-) create mode 100644 docs/0.24.7/changes.txt create mode 100644 docs/0.24.7/license.txt rename docs/{build_vc10.txt => build_vc11.txt} (76%) create mode 100644 litestep/FullscreenMonitor.cpp create mode 100644 litestep/FullscreenMonitor.h create mode 100644 litestep/TaskbarListHandler.cpp create mode 100644 litestep/TaskbarListHandler.h rename litestep/{litestep_vc10.vcxproj => litestep_vc12.vcxproj} (83%) delete mode 100644 litestep/litestep_vc71.vcproj delete mode 100644 litestep/litestep_vc8.vcproj delete mode 100644 litestep/litestep_vc9.vcproj rename litestep_vc10.sln => litestep_vc12.sln (88%) delete mode 100644 litestep_vc71.sln delete mode 100644 litestep_vc8.sln delete mode 100644 litestep_vc9.sln rename lsapi/{lsapi_vc10.vcxproj => lsapi_vc12.vcxproj} (85%) delete mode 100644 lsapi/lsapi_vc71.vcproj delete mode 100644 lsapi/lsapi_vc8.vcproj delete mode 100644 lsapi/lsapi_vc9.vcproj create mode 100644 utility/stringutility.cpp rename utility/{utility_vc10.vcxproj => utility_vc12.vcxproj} (79%) delete mode 100644 utility/utility_vc71.vcproj delete mode 100644 utility/utility_vc8.vcproj delete mode 100644 utility/utility_vc9.vcproj diff --git a/Makefile b/Makefile index 5d12001..41668cd 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,7 @@ EXEOBJS = \ litestep\$(OUTPUT)\DDEService.o \ litestep\$(OUTPUT)\DDEStub.o \ litestep\$(OUTPUT)\DDEWorker.o \ + litestep\$(OUTPUT)\FullscreenMonitor.o \ litestep\$(OUTPUT)\litestep.o \ litestep\$(OUTPUT)\MessageManager.o \ litestep\$(OUTPUT)\Module.o \ diff --git a/docs/0.24.7/changes.txt b/docs/0.24.7/changes.txt new file mode 100644 index 0000000..65845e7 --- /dev/null +++ b/docs/0.24.7/changes.txt @@ -0,0 +1,125 @@ +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + LiteStep 0.24.7 + Changelog +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + +-- NOTE ------------------------------------------------------------------------ + + The 0.24.7 code is based on the 2002-01-03 pre-0.24.6 source. Some of the + functionality that was added to the 0.24.6 branch after this date (mostly Indie + LS changes) was reimplemented in 0.24.7. See below for a list of these + functions and for what is missing. + + +-- CHANGES SINCE 0.24.6 -------------------------------------------------------- + + - Removed all COM. + + - Cleaned up the code... this includes numerous fixes, formatting, and source + beautifications. + + - Massive improvements in StartupRunner and TrayService. Visible items are: + * On NT systems, LiteStep detects if startup items have been run before or + not. This is the same method that Explorer uses to detect if it should + rerun startup items in the event that the shell crashes. Thus the + -nostartup switch is obsolete on NT systems. + * Added command line switch -startup to force running of the startup items. + * StartupRunner now has RunOnceEx support. + * TrayService rewrite enables support for the language indicator icon + (but not on WinXP) and fixes many other problematic icons. + + - Fixed XP logon delay + + - Merged LiteMAN functionallity (i.e. DDE) into the LiteStep core. It is now + called DDEService and loaded by default. Liteman.dll should no longer be + loaded. + + - Added "LSUseSystemDDE". This loads the Windows DDE server instead of the + DDEService. This may result in slightly larger memory usage but "proper" DDE + support. LSUseSystemDDE takes effect on startup only, not on !recycle. + Requires shdocvw.dll from IE. + + - Added !HideModules and !ShowModules to hide or show all module windows. + !ToggleModules is also available. + + - If "LSAutoHideModules" is specified LS tries to automatically hide all module + windows if a full-screen app is detected. Once the full-screen app exits the + modules are redisplayed. + + - LCOpen uses a separate SettingsMap for each file opened with LCOpen. This is + the thread-safe approach but makes it impossible for modules to use the + GetRC* APIs to retrieve settings from those files. For example this affects + Rabidvwm which can no longer read its settings directly from .box files. Put + the settings into step.rc instead or "include" the .box file(s) as a + workaround. + + - Added inform-sega's ShellExecute fix for .lnk files. This enables LSExecute() + to execute .lnk files. + + - Removed support for PixmapPath (use LSImageFolder instead), ThemeFile, + LSThemeFile, and LSColorBGR. + + - Modules are loaded and unloaded asynchronously (at the same time) if + threaded. This should lead to faster start and recycle times if threading is + used. Specify a threaded module by: LoadModule threaded + + - All MessageBoxes (including !alert and !confirm) should now always have focus + and appear ontop of the active window. + + - The Recovery Menu cannot be closed permanently with ALT-F4 any more. + + - Improved handling of exceptions in threaded modules. + + - Improved handling of exceptions during !bang execution. + + - Optimized BitmapToRegion, LoadLSImage, LoadLSIcon, BitmapFromIcon. + + - Added new step.rc setting "LSDisableTrayService". Setting this value disables + the core's system tray support. + + - LM_UN/RELOADMODULE can now un/reload modules by using the HINSTANCE of the + module as the wParam. Set the lParam to LMM_HINSTANCE in that case. + !Reloadmodule and !unloadmodule take advantage of this and should thus no + longer crash even if a module tries to un-/reload itself. + + - Removed -install and -uninstall. + + - Removed !ToggleWharf and !Popup from the core. + + - Added EnumLSData export to lsapi. This gives modules like lscp a consistent + interface to poll core data. + + - etc. etc. + + +-- INDIE LS CHANGES ADDED TO 0.24.7 -------------------------------------------- + + - GetRCCoordinate and ParseCoordinate added to lsapi for reading coordinates + with negative and centered support. + + - Some typos in the string tables were corrected. + + - $windir$ is guaranteed to end with a backslash ('\'). + + - Math evaluation in VarExpansion (can be disabled at compiletime). + + - Stubs in lsapi for the logging APIs (minimal logging support can be enabled + at compiletime) and for the Get-/SetVariable APIs. + + - Addition of $WinXP$, $compiledate$, and $quicklaunch$. + + - Removal of !ToggleWharf and !Popup from lsapi. + + - c0atzin's RegisterShellHook() fix for Win9x. + + +-- INDIE LS CHANGES NOT ADDED TO 0.24.7 ---------------------------------------- + + - All changes made to the recovery menu and the aboutbox. + + - !setvar, !emptytrashbin + + - system color / font variables, OS-* variables. + + - LSCP (including !lscp). This will have to be rewritten to work. diff --git a/docs/0.24.7/license.txt b/docs/0.24.7/license.txt new file mode 100644 index 0000000..8e69c14 --- /dev/null +++ b/docs/0.24.7/license.txt @@ -0,0 +1,662 @@ +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + LiteStep 0.24.7 + Applicable Licenses +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +1) LiteStep Program License (GNU GENERAL PUBLIC LICENSE Version 2) +2) LiteStep Documentation License (GNU FREE DOCUMENTATION LICENSE Version 1.2) + + +-- LITESTEP PROGRAM LICENSE ---------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + +-- LITESTEP DOCUMENTATION LICENSE ---------------------------------------------- + + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. diff --git a/docs/build.txt b/docs/build.txt index 908ad43..da48f50 100644 --- a/docs/build.txt +++ b/docs/build.txt @@ -8,7 +8,7 @@ For build instructions, please review - - build_vc10.txt (official supported method) + - build_vc11.txt (official supported method) - build_mingw.txt The LiteStep source is segmented into separate code modules. The source folder diff --git a/docs/build_vc10.txt b/docs/build_vc11.txt similarity index 76% rename from docs/build_vc10.txt rename to docs/build_vc11.txt index 43de8e5..d0c582c 100644 --- a/docs/build_vc10.txt +++ b/docs/build_vc11.txt @@ -1,52 +1,53 @@ -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - LiteStep 0.25.0 - Visual Studio 2010 Developer Information -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - --- BUILD REQUIREMENTS ---------------------------------------------------------- - - - Visual C++ 2010 (Express) - - Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO & Web Setup) - - This is the configuration used during 0.25.0 development, it is quite possible - that other versions of the above packages can be used, but there's no - guarantee. - - --- BUILD SETUP ----------------------------------------------------------------- - - A. Install VC++ 2010 Express & The Platform SDK - ----------------------------------------------- - - 1. If you don't have the build requirements installed, download them. Install - Visual C++ 2010 Express. Restart when asked and then install the SDK which - should register automatically with VC++. - - 2. It is helpful to select "Expert Settings" in VC++ 2010 Express. See - Tools –> Settings –> Expert Settings. - --- BUILDING LITESTEP ----------------------------------------------------------- - - A. Deploy source code - ---------------------- - - 1. Create a build directory for the source code (eg. C:\src\LiteStep). - - 2. Extract the source code into the build directory. So that the build - directory has the following structure: - - \LiteStep - \litestep - \lsapi - \utility - - B. Compile - ---------- - - 1. Open "litestep_vc10.sln" in VC++ 2010. - - 2. Build either a debug or release build. - - 3. The output binaries will be off of the LiteStep source directory in - Release_VC10 or Debug_VC10 folders depending on the build type. +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + LiteStep 0.25.0 + Visual Studio 2012 Developer Information +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + +-- BUILD REQUIREMENTS ---------------------------------------------------------- + + - Visual C++ 2012 (Express) + - Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO & Web Setup) + + This is the configuration used during 0.25.0 development, it is quite possible + that other versions of the above packages can be used, but there's no + guarantee. + + +-- BUILD SETUP ----------------------------------------------------------------- + + A. Install VC++ 2012 Express & The Platform SDK + ----------------------------------------------- + + 1. If you don't have the build requirements installed, download them. Install + Visual C++ 2012 Express. Restart when asked and then install the SDK which + should register automatically with VC++. + + 2. It is helpful to select "Expert Settings" in VC++ 2012 Express. See + Tools –> Settings –> Expert Settings. + +-- BUILDING LITESTEP ----------------------------------------------------------- + + A. Deploy source code + ---------------------- + + 1. Create a build directory for the source code (eg. C:\src\LiteStep). + + 2. Extract the source code into the build directory. So that the build + directory has the following structure: + + \LiteStep + \litestep + \lsapi + \utility + + B. Compile + ---------- + + 1. Open "litestep_vc11.sln" in VC++ 2012. + + 2. Build either a debug or release build. + + 3. The output binaries will be off of the LiteStep source directory in the + Release_VC11_32, Release_VC11_64, Debug_VC11_32, or Debug_VC11_64 folder + depending on the build type. diff --git a/docs/changes.txt b/docs/changes.txt index 65845e7..8e25a9e 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -1,125 +1,282 @@ -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - LiteStep 0.24.7 - Changelog -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - --- NOTE ------------------------------------------------------------------------ - - The 0.24.7 code is based on the 2002-01-03 pre-0.24.6 source. Some of the - functionality that was added to the 0.24.6 branch after this date (mostly Indie - LS changes) was reimplemented in 0.24.7. See below for a list of these - functions and for what is missing. - - --- CHANGES SINCE 0.24.6 -------------------------------------------------------- - - - Removed all COM. - - - Cleaned up the code... this includes numerous fixes, formatting, and source - beautifications. - - - Massive improvements in StartupRunner and TrayService. Visible items are: - * On NT systems, LiteStep detects if startup items have been run before or - not. This is the same method that Explorer uses to detect if it should - rerun startup items in the event that the shell crashes. Thus the - -nostartup switch is obsolete on NT systems. - * Added command line switch -startup to force running of the startup items. - * StartupRunner now has RunOnceEx support. - * TrayService rewrite enables support for the language indicator icon - (but not on WinXP) and fixes many other problematic icons. - - - Fixed XP logon delay - - - Merged LiteMAN functionallity (i.e. DDE) into the LiteStep core. It is now - called DDEService and loaded by default. Liteman.dll should no longer be - loaded. - - - Added "LSUseSystemDDE". This loads the Windows DDE server instead of the - DDEService. This may result in slightly larger memory usage but "proper" DDE - support. LSUseSystemDDE takes effect on startup only, not on !recycle. - Requires shdocvw.dll from IE. - - - Added !HideModules and !ShowModules to hide or show all module windows. - !ToggleModules is also available. - - - If "LSAutoHideModules" is specified LS tries to automatically hide all module - windows if a full-screen app is detected. Once the full-screen app exits the - modules are redisplayed. - - - LCOpen uses a separate SettingsMap for each file opened with LCOpen. This is - the thread-safe approach but makes it impossible for modules to use the - GetRC* APIs to retrieve settings from those files. For example this affects - Rabidvwm which can no longer read its settings directly from .box files. Put - the settings into step.rc instead or "include" the .box file(s) as a - workaround. - - - Added inform-sega's ShellExecute fix for .lnk files. This enables LSExecute() - to execute .lnk files. - - - Removed support for PixmapPath (use LSImageFolder instead), ThemeFile, - LSThemeFile, and LSColorBGR. +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + LiteStep 0.25.0 Alpha + Experimental Build 2013-08-03 +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +This build requires the Visual C++ 2012 Redistributable Package +http://www.microsoft.com/en-us/download/details.aspx?id=30679 + + +-- PREFACE -------------------------------------------------------------------- + +After the release of 0.24.8, we're focussing on the next release, 0.25.0. +This build is the current state of that code. + + - WARNING - + This is experimental (alpha) code and will have bugs! If you don't know how + to edit step.rc files manually or you don't know how to recover if the shell + crashes, then do not try this build. + + +-- DEVELOPMENT TEAM ----------------------------------------------------------- + + - CONTACT - + Email: devteam at lsdev.org + Website: http://www.lsdev.org/ + IRC: #lsdev on irc.freenode.net + + - TEAM - + Active: Acidfire, alur, ilmcuts, jugg, Tobbe + Inactive: Maduin, Rabidcow, Xjill + + +-- CHANGE HIGHLIGHTS ---------------------------------------------------------- + + 1) Support for running on Vista, 7, 8, Server 2008/2012, and 64-Bit variants + 2) No longer attempt to silently swallow module crashes + 3) Improvements in full screen application detection on multi-monitor setups + 4) Huge improvements in AppBar support, in particular on multi-monitor setups + 5) Attempt to launch Explorer as shell in Safe Mode + 6) Added "-explorer" command line switch to launch Explorer as shell + 7) Switched from libpng to picoPNG, removing libpng13 and zlib1 dependencies + 8) Fixed lack of screen lock/unlock sound on XP and up + 9) Decided on official "LiteStep" spelling + 10) Support for ITaskbarList* interfaces + 11) Support for unicode modules + + +-- CHANGES BY DATE ------------------------------------------------------------ + +The following lists the changes between nightly builds. +See the next section for a cumulative changelog since 0.24.8. + - [2013-08-03] - + - Fixed crash with recursive includes. + - Fixed LiteStep not loading on Windows XP. + - Support for unicode modules. + - Added GetRCFloat and GetRCDouble. + + - [2013-08-01] - + - Modified the .RC prefix syntax, added special handling of keys starting + with *, and made -, as a key, refer to the current prefix. + - The core will now send LM_FULLSCREENACTIVATED and LM_FULLSCREENDEACTIVATED + to modules that have registered for those messages. + - Fixed some startup apps would not run with UAC on. + - Enabled the IncludeFolder directive by default. + - Added support for all ITaskbarList* interfaces. The core will now send + LM_TASK_SETPROGRESSSTATE, LM_TASK_SETPROGRESSVALUE, LM_TASK_MARKASACTIVE, + LM_TASK_REGISTERTAB, LM_TASK_UNREGISTERTAB, LM_TASK_SETACTIVETAB, + LM_TASK_SETTABORDER, LM_TASK_SETTABPROPERTIES, LM_TASK_SETOVERLAYICON, + LM_TASK_SETOVERLAYICONDESC, LM_TASK_SETTHUMBNAILTOOLTIP, + LM_TASK_SETTHUMBNAILCLIP, LM_TASK_ADDBUTTONS, LM_TASK_UPDATEBUTTONS, and + LM_TASK_SETIMAGELIST. All taskbar modules should register for and handle + these messages. + - Added "About LiteStep" and "Start Explorer as shell" to the recovery menu. + + - [2013-07-24] - + - Fixed crash on !Recycle introduced in the 2013-07-21 build when + LSAutoHideModules was disabled initially. + + - [2013-07-21] - + - Modified the .RC file syntax to allow for settings prefixes. This change + is backwards compatible. + - Added detection of Windows 8.1 and Server 2012 R2. + - LSAutoHideModules is now more reliable, and will hide modules on a + monitor as long as there is a fullscreen window on that monitor. + - Added more details to the error message that is shown when a module fails + to load. + + - [2013-06-27] - + - The !Run dialog now supports !Bang commands. + - Added LSCloseExplorer, which will gracefully close the currently running + shell when LiteStep launches. + - Added LSRunX and LSRunY to position the !Run dialog. + - Fixed left click menu positioning for tray icons (also requires tray + module updates). + - Tray modules now need to register for and handle LM_SYSTRAYINFOEVENT. + - Added a fileExists() function. + - Added a performance page to !about, showing module load times. + - Added new enumeration type ELD_PERFORMANCE to EnumLSData + - !about's system information page will now show > 4GB of memory correctly. + - !about's system information page now supports Windows 8 and Windows Server + 2012. + - Various 64bit compilation fixes. + + - [2009-04-04] - + - Added $Win64$ to identify Windows x64 + - Added support for exiting LiteStep by holding CTRL+SHIFT+ALT and + canceling out of the Windows Shutdown dialog. + - Added multi-monitor support to AppBar implementation. + - Fixed LiteStep not running 64-Bit regkeys + - Fixed AppBar support on Windows 7 + - Fixed AppBar implementation not returning tray screen edge + - Fixed reentrant crashes in AppBar implementation + - Removed Win95 multimon compat functions + - Lots of small crash and correctness fixes + - Fixed MinGW builds + - Huge code format update + + - [2009-02-10] - + - Fixed fullscreen app detection + - Supports hiding modules only on the monitor the FS window is on + - Added support for handling more than one fullscreen window + - Fixed !about "System Information" to show memory amounts >2GB + - Also shows partial memory amounts + - Fixed !about not using default shell dialog font + - Fixed Unicode tooltips and balloon tips not always showing up + - Fixed picoPNG code mirroring images + - Switched from libpng to picoPNG, which is included in lsapi.dll. + - Removes libpng13.dll and zlib1.dll dependency + - Fixed LiteStep playing a default system sound if the sound was disabled + - Tweaked module loading error boxes + - Fixed module path getting cut off in the titles, now uses filename only + - Changed icon from warning icon to error icon + - Fixed minor potential crash bug + - Lots of internal code structure changes and code correctness fixes + - Removed VC6 as a supported compiler/development environment + - Added lots of debug TRACEs + - Removed comctl32 V6 manifest + - Replaced with custom activation context management + - (Hopefully) fixes module redraw issues + + - [2009-01-11] - + - Fixed dialogs showing generic icon in taskbar and ALT-TAB + - These dialogs now use the LiteStep icon + - Affects dialogs such as !about, !alert, or !confirm + - Added question mark icon to !confirm + - Added tooltips to AboutBox to show full text if otherwise cut off + - Added full row selection to AboutBox + - Fixed Windows Home Server detection + - Fixed LiteStep quitting too early if an app blocks shutdown + + - [2009-01-10] - + - Fixed LS skipping startup folders + - Added "module" column to !about bangs + - Fixed copyright date in !about license + - Removed lsapi.dll from !about revision IDs + - Added new enumeration type ELD_BANGS_V2 to EnumLSData + - Added missing changelog entries + - Added note about %LiteStepDir% + - Added note about fixed !shutdown bug (Vista) + - Added note about fixed tray tooltips (Vista) + - Added note about changed behavior with custom config files + +For earlier changes see the cumulative changelog below + + +-- CHANGES SINCE 0.24.8 ------------------------------------------------------- + +This is a list of selected changes since the (projected) 0.24.8 final build: + + - ADDED - + - Added playing of appropriate system sounds on screen lock/unlock + - Added $WinVista$, $Win2008$, $Win7$, $Win2008R2$, $Win8$, $Win2012$, + $Win2012R2$, and $Win81$. + - Added $Win64$ to identify Windows x64 + - In safe mode, LiteStep attempts to launch Explorer as shell + - If it fails, LiteStep launches as shell but skips running startup apps + - Added "-explorer" command line switch to launch Explorer in shell mode + - Added environment variable %LiteStepDir% + - Applications started by LS (directly or indirectly) will receive this + - Does NOT end with a backslash (unlike $LiteStepDir$) in order to be + consistent with other %variables% (like %windir%). + - Added "Module" column to !about "Bang Commands" + - Added new enumeration type ELD_BANGS_V2 to EnumLSData + - Added question mark icon to !confirm + - Added tooltips to AboutBox to show full text if otherwise cut off + - Added full row selection to AboutBox + - Added support for exiting LiteStep by holding CTRL+SHIFT+ALT and + canceling out of the Windows Shutdown dialog. + - Added multi-monitor support to AppBar implementation. + - New .RC construct, { }, allowing for the specification of settings + prefixes. Allows for tidier configs. + - Added a performance page to !about, showing module load times. + - Added a fileExists() function. + - Support for version 4 tray icons on Windows 7 and Windows 8. Tray modules + now need to handle LM_SYSTRAYINFOEVENT in order to support this. + - The !Run dialog will now execute !Bang commands. + - LSRunX and LSRunY settings to position the !Run dialog. + - LSCloseExplorer, a setting which causes the explorer shell to gracefully + terminate if it is running as shell when litestep starts. + - IncludeFolder directive, to include every .RC file in a folder. + - Added Added "About LiteStep" and "Start Explorer as shell" to the recovery + menu. + - Support for unicode modules. + - Added GetRCFloat and GetRCDouble. + + + - VISTA & WIN7 & 64-BIT SUPPORT - + - Running on Windows Vista, Windows 7, Windows 8 and 64-Bit Windows now + supported + - Fixed startup folder items running twice on Windows Vista + - Fixed startup detection on Vista + - Added playing of logon sound + - Fixed logon screen delay + - Fixed wallpaper not appearing + - Fixed loading of SSOs on Vista + - Enables the new Alt-Tab replacement + - Fixes lots of system tray icons (network, volume control, ...) + - Fixed tray icon tooltips not showing up + - Multiple fixes in AppBar support + - Including crash fixes and multi-monitor fixes + - Fixed LiteStep only launching 32-Bit versions of applications + - Modules must use LSExecute(Ex) instead of ShellExecute + to take advantage of this + - Fixed $quicklaunch$ not picking up folder path customization + - Fixed OS detection for !about and OS variables such as $WinVista$ + - Fixed !shutdown crashing LiteStep on Vista + - Fixed LiteStep not running 64-Bit regkeys + + + - FIXED - + - Fixed "LiteStep" spelling in a lot of places (see below) + - Fixed inconsistencies in error message handling + - Several robustness and correctness improvements + - Includes fixing several potential crash bugs + - Fixed dialogs showing generic icon in taskbar and ALT-TAB + - These dialogs now use the LiteStep icon + - Affects dialogs such as !about, !alert, or !confirm + - Fixed LiteStep returning an incorrect return value for SHLoadInProc + - Fixed !about not using default shell dialog font + - Fixed Unicode tooltips and balloon tips not always showing up + - Tweaked module loading error boxes + - Fixed module path getting cut off in the titles, now uses filename only + - Changed icon from warning icon to error icon + - Improved LSAutoHideModules's behavior. It is now more accurate and + responsive. It will also keep modules on a monitor hidden as long as there + is a fullscreen window on that monitor. + - !about's system information page will now show > 4GB of memory correctly + - Added support for all ITaskbarList* interfaces. + - Fixed crash with recursive includes. + + + - REMOVED/CHANGED - + - The official spelling is now "LiteStep". There used to be a mix of + "Litestep" and "LiteStep". + - No more attempts to silently swallow exceptions (crashes) from modules. + Instead, LiteStep will just crash outright. Trying to continue leaves + LiteStep in a state which is prone to crash in a non-reproducible way. + - Streamlined error messages during LiteStep startup (core only). Removed + specialized error boxes e.g. from TrayService. + - Error message boxes are now consistenly "topmost". They no longer set + themselves as foreground window. + - Removed hook.dll (was never used) + - If a custom configuration file path is passed on the command line and the + file does not exist, LiteStep now shows a "file not found" error message + instead of falling back to the standard step.rc. + - Removed lsapi.dll from !about "Revision IDs" + - Switched from libpng to picoPNG, which is included in lsapi.dll. + - Removes libpng13.dll and zlib1.dll dependencies + - Removed Win95 multimon compat functions + - Added more details to the error message that is shown when a module fails + to load. - - Modules are loaded and unloaded asynchronously (at the same time) if - threaded. This should lead to faster start and recycle times if threading is - used. Specify a threaded module by: LoadModule threaded - - - All MessageBoxes (including !alert and !confirm) should now always have focus - and appear ontop of the active window. - - - The Recovery Menu cannot be closed permanently with ALT-F4 any more. - - - Improved handling of exceptions in threaded modules. - - - Improved handling of exceptions during !bang execution. - - - Optimized BitmapToRegion, LoadLSImage, LoadLSIcon, BitmapFromIcon. - - - Added new step.rc setting "LSDisableTrayService". Setting this value disables - the core's system tray support. - - - LM_UN/RELOADMODULE can now un/reload modules by using the HINSTANCE of the - module as the wParam. Set the lParam to LMM_HINSTANCE in that case. - !Reloadmodule and !unloadmodule take advantage of this and should thus no - longer crash even if a module tries to un-/reload itself. - - - Removed -install and -uninstall. - - - Removed !ToggleWharf and !Popup from the core. - - - Added EnumLSData export to lsapi. This gives modules like lscp a consistent - interface to poll core data. - - - etc. etc. - - --- INDIE LS CHANGES ADDED TO 0.24.7 -------------------------------------------- - - - GetRCCoordinate and ParseCoordinate added to lsapi for reading coordinates - with negative and centered support. - - - Some typos in the string tables were corrected. - - - $windir$ is guaranteed to end with a backslash ('\'). - - - Math evaluation in VarExpansion (can be disabled at compiletime). - - - Stubs in lsapi for the logging APIs (minimal logging support can be enabled - at compiletime) and for the Get-/SetVariable APIs. - - - Addition of $WinXP$, $compiledate$, and $quicklaunch$. - - - Removal of !ToggleWharf and !Popup from lsapi. - - c0atzin's RegisterShellHook() fix for Win9x. - - --- INDIE LS CHANGES NOT ADDED TO 0.24.7 ---------------------------------------- - - - All changes made to the recovery menu and the aboutbox. - - - !setvar, !emptytrashbin - - - system color / font variables, OS-* variables. - - - LSCP (including !lscp). This will have to be rewritten to work. + - INTERNAL - + - Lots of code consistency and correctness improvements + - Huge code format update + - Several small improvements in code structure + - Removed lots of unused code + - Several small fixes to support compiling as a 64-Bit application + - Several improvements for debug builds (e.g. thread names) + - Removed VC6 as a supported compiler/development environment + - Added lots of debug TRACEs diff --git a/docs/license.txt b/docs/license.txt index 8e69c14..13a0d9d 100644 --- a/docs/license.txt +++ b/docs/license.txt @@ -1,5 +1,5 @@ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - LiteStep 0.24.7 + LiteStep 0.25.0 Applicable Licenses =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- diff --git a/docs/manual.txt b/docs/manual.txt index e504bc6..693a4e9 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -280,7 +280,8 @@ Contents: key combination: CTRL+ALT+F1 that is, press and hold the CTRL key and the ALT key then depress the F1 key and release all three. A popup menu will appear at your mouse cursor location. This menu can be used recover from a broken - configuration. + configuration. Note that launching Explorer might not always work if there is + already an Explorer file manager window open. A) LiteStep Structure --------------------- @@ -368,7 +369,7 @@ Contents: way use the reserved characters of the step.rc parsers except in the special case of * character. The following characters are reserved: - ! $ & * ( ) - + = [ ] ; " ' < > , / + ! $ & * ( ) - + = [ ] ; " ' < > , / { } Furthermore it is recommended that you do not use @, #, or | (vertical bar), because these characters may become reserved in the future. @@ -384,7 +385,7 @@ Contents: 1. Step.rc File Parser - - The step.rc File Parser uses these reserved characters: ;[]"' + - The step.rc File Parser uses these reserved characters: ;[]"'{} ; Used at the beginning of a textual line to delineate a comment. Comments are lines that are ignored by the Directive Parser. A comment @@ -403,7 +404,28 @@ Contents: ElseIf Else Endif - + + - Surrounding Statements within curly braces as shown below like will cause + any command within the braces to have the specified prefix prefixed to it. + Within prefix braces, the key - is evaluated to just the prefix. + Keys starting with a * are treated specially, and the begining * is put at + the begining of the final key name. + + This: + + Prefix + { + - Value + Key Value + *Event Value + } + + Is equivalent to this: + + Prefix Value + PrefixKey Value + *PrefixEvent Value + 2. Step.rc Directive Parser - The step.rc Directive Parser uses these reserved characters: *$[]"' @@ -781,20 +803,14 @@ Contents: Usage: LSAutoHideModules TRUE - - LSCloseExplorer - -------------------------- - If explorer is running as shell when LiteStep launches, LiteStep will attempt - to close it. - - Usage: - LSCloseExplorer TRUE LSNoShellWarning -------------------------- Disables the warning issued when loading LiteStep if another shell is already running. Do not use this setting unless you know what you are doing! + Note: LiteStep must be restarted for this setting to take affect. + Usage: LSNoShellWarning TRUE @@ -925,9 +941,12 @@ Contents: Win2000 Win2003 Win2008 + Win2008R2 Win2012 + Win2012R2 Win7 Win8 + Win81 Win95 Win98 WinME @@ -1344,7 +1363,7 @@ ENDIF A) Documentation License Notice ------------------------------- - Copyright (c) 2005-2012 LiteStep Development Team + Copyright (c) 2005-2013 LiteStep Development Team Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version @@ -1358,7 +1377,7 @@ ENDIF LiteStep is a replacement shell for the standard Windows® Explorer shell. Copyright (C) 1997-1998 Francis Gastellu - Copyright (C) 1998-2012 LiteStep Development Team + Copyright (C) 1998-2013 LiteStep Development 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 diff --git a/litestep/DDEService.cpp b/litestep/DDEService.cpp index d458728..f3ddc16 100644 --- a/litestep/DDEService.cpp +++ b/litestep/DDEService.cpp @@ -121,6 +121,13 @@ HRESULT DDEService::Stop() return hr; } + +HRESULT DDEService::Recycle() +{ + return S_OK; +} + + bool DDEService::_DoStart() { bool bReturn = false; diff --git a/litestep/DDEService.h b/litestep/DDEService.h index e75f1a5..418b3cf 100644 --- a/litestep/DDEService.h +++ b/litestep/DDEService.h @@ -32,8 +32,9 @@ class DDEService: public IService DDEService(); ~DDEService(); - HRESULT Start(); - HRESULT Stop(); + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; static HDDEDATA CALLBACK DdeCallback( UINT wType, UINT wFmt, HCONV hConv, HSZ hszTopic, diff --git a/litestep/DDEStub.cpp b/litestep/DDEStub.cpp index b4b875c..9498c5b 100644 --- a/litestep/DDEStub.cpp +++ b/litestep/DDEStub.cpp @@ -24,16 +24,19 @@ HMODULE DDEStub::m_hShDocVw = NULL; DDEStub::ShellDDEFunc DDEStub::m_pShellDDEInit = NULL; + DDEStub::DDEStub() { // do nothing } + DDEStub::~DDEStub() { // do nothing } + HRESULT DDEStub::Start() { HRESULT hr = S_FALSE; @@ -68,6 +71,7 @@ HRESULT DDEStub::Start() return hr; } + HRESULT DDEStub::Stop() { if (m_pShellDDEInit) @@ -82,3 +86,9 @@ HRESULT DDEStub::Stop() return S_OK; } + + +HRESULT DDEStub::Recycle() +{ + return S_OK; +} diff --git a/litestep/DDEStub.h b/litestep/DDEStub.h index 9492ea0..9763016 100644 --- a/litestep/DDEStub.h +++ b/litestep/DDEStub.h @@ -30,8 +30,9 @@ class DDEStub: public IService DDEStub(); ~DDEStub(); - HRESULT Start(); - HRESULT Stop(); + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; private: typedef void (WINAPI* ShellDDEFunc)(BOOL); diff --git a/litestep/DDEWorker.cpp b/litestep/DDEWorker.cpp index 2e2f898..c0a3a12 100644 --- a/litestep/DDEWorker.cpp +++ b/litestep/DDEWorker.cpp @@ -47,35 +47,35 @@ DDEWorker::~DDEWorker() // Handle incoming DDE requests and pass to relevant functions -BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) +BOOL DDEWorker::ParseRequest(LPCTSTR pszRequest) { // 10 is the maximum number of parameters passed in AddItem PROGMAN DDE call #define DDE_ADDITEM_PARAM_COUNT (10) - LPSTR pszParamList[DDE_ADDITEM_PARAM_COUNT]; - LPSTR pszTmp; - LPSTR pszWorkRequest; + LPTSTR pszParamList[DDE_ADDITEM_PARAM_COUNT]; + LPTSTR pszTmp; + LPTSTR pszWorkRequest; BOOL bReturn = FALSE; DWORD dwRequest = _MatchRequest(pszRequest); if (dwRequest) { - size_t stLength = strlen(pszRequest) + 1; - pszWorkRequest = new char[stLength]; + size_t stLength = _tcslen(pszRequest) + 1; + pszWorkRequest = new TCHAR[stLength]; StringCchCopy(pszWorkRequest, stLength, pszRequest); pszWorkRequest[stLength - 3] = '\0'; - pszWorkRequest = strchr(pszWorkRequest, '('); + pszWorkRequest = _tcschr(pszWorkRequest, '('); ++pszWorkRequest; pszParamList[0] = pszWorkRequest; int nCurIndex = 1; - pszTmp = strchr(pszWorkRequest, ','); // find a delimiter + pszTmp = _tcschr(pszWorkRequest, ','); // find a delimiter while (NULL != pszTmp) { *(pszTmp++) = '\0'; // null terminate and cut. pszParamList[nCurIndex++] = pszTmp; // put it in the pointer list - pszTmp = strchr(pszTmp, ','); // get the next onf + pszTmp = _tcschr(pszTmp, ','); // get the next onf } // Set initial state of the group to act on: @@ -88,12 +88,12 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) // DDE call: e.g. ExploreFolder(idlist[,object]) case DDE_REQUEST_EXPLOREFOLDER: { - char szParam[MAX_PATH]; + TCHAR szParam[MAX_PATH]; StringCchPrintf(szParam, MAX_PATH, - "/e,/idlist,%s", pszParamList[1]); + _T("/e,/idlist,%ls"), pszParamList[1]); - bReturn = ((LSShellExecute(NULL, "open", "explorer.exe", + bReturn = ((LSShellExecute(NULL, _T("open"), _T("explorer.exe"), szParam, NULL, SW_SHOW) > HINSTANCE(32)) ? TRUE : FALSE); } break; @@ -101,12 +101,12 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) // DDE call: e.g. ViewFolder(idlist[,object]) case DDE_REQUEST_VIEWFOLDER: { - char szParam[MAX_PATH]; + TCHAR szParam[MAX_PATH]; StringCchPrintf(szParam, MAX_PATH, - "/idlist,%s", pszParamList[1]); + _T("/idlist,%ls"), pszParamList[1]); - bReturn = ((LSShellExecute(NULL, "open", "explorer.exe", + bReturn = ((LSShellExecute(NULL, _T("open"), _T("explorer.exe"), szParam, NULL, SW_SHOW) > HINSTANCE(32)) ? TRUE : FALSE); // Will return too soon if we don't sleep here... funky @@ -134,7 +134,7 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) { if (2 == nCurIndex) // second parameter forces common/private { - bCommon = atoi(pszParamList[1]); + bCommon = _ttoi(pszParamList[1]); } bReturn = _CreateGroup(pszParamList[0], bCommon); } @@ -145,7 +145,7 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) { if (2 == nCurIndex) // second parameter forces common/private { - bCommon = atoi(pszParamList[1]); + bCommon = _ttoi(pszParamList[1]); } bReturn = _DeleteGroup(pszParamList[0], bCommon); } @@ -158,9 +158,9 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) { if (3 == nCurIndex) // third parameter forces common/private { - bCommon = atoi(pszParamList[2]); + bCommon = _ttoi(pszParamList[2]); } - int nShow = atoi(pszParamList[1]); + int nShow = _ttoi(pszParamList[1]); bReturn = _ShowGroup(pszParamList[0], nShow, bCommon); } } @@ -181,10 +181,10 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) { BOOL bMinimize = FALSE; WORD dwHotKey = 0; - LPCSTR pszDefDir = NULL; + LPCTSTR pszDefDir = NULL; int nIconIndex = 0; - LPCSTR pszIconPath = NULL; - LPCSTR pszDescription = NULL; + LPCTSTR pszIconPath = NULL; + LPCTSTR pszDescription = NULL; // fall through each case switch (nCurIndex) @@ -192,11 +192,11 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) case 10: // SeparateMemSpace ignored for now case 9: { // Minimize - bMinimize = (BOOL)atoi(pszParamList[8]); + bMinimize = (BOOL)_ttoi(pszParamList[8]); } case 8: { // HotKey - dwHotKey = (WORD)atoi(pszParamList[7]); + dwHotKey = (WORD)_ttoi(pszParamList[7]); } case 7: { // DefDir @@ -206,7 +206,7 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) case 5: case 4: { // IconIndex - nIconIndex = atoi(pszParamList[3]); + nIconIndex = _ttoi(pszParamList[3]); } case 3: { // IconPath @@ -243,7 +243,7 @@ BOOL DDEWorker::ParseRequest(LPCSTR pszRequest) // List the program groups BOOL DDEWorker::ListGroups(LPVOID& pGroupList, UINT& ulSize) { - char szPath[MAX_PATH]; + wchar_t szPath[MAX_PATH]; pGroupList = NULL; ulSize = 0; LPSTR pszTemp = NULL; @@ -252,7 +252,7 @@ BOOL DDEWorker::ListGroups(LPVOID& pGroupList, UINT& ulSize) // Get user specific folders if (GetShellFolderPath(CSIDL_PROGRAMS, szPath, MAX_PATH)) { - PathAppend(szPath, "*.*"); + PathAppend(szPath, _T("*.*")); HANDLE hHeap = GetProcessHeap(); if (hHeap) @@ -262,7 +262,7 @@ BOOL DDEWorker::ListGroups(LPVOID& pGroupList, UINT& ulSize) // Get common folders if (GetShellFolderPath(CSIDL_COMMON_PROGRAMS, szPath, MAX_PATH)) { - PathAppend(szPath, "*.*"); + PathAppend(szPath, _T("*.*")); if (_ListGroupsHelper(hHeap, szPath, pGroupList, ulSize)) { @@ -287,43 +287,43 @@ BOOL DDEWorker::ListGroups(LPVOID& pGroupList, UINT& ulSize) } -DWORD DDEWorker::_MatchRequest(LPCSTR pszCommand) +DWORD DDEWorker::_MatchRequest(LPCTSTR pszCommand) { DWORD dwReturn = DDE_REQUEST_NONE; - if (strstr(pszCommand, "[ExploreFolder(") == pszCommand) + if (_tcsstr(pszCommand, L"[ExploreFolder(") == pszCommand) { dwReturn = DDE_REQUEST_EXPLOREFOLDER; } - else if (strstr(pszCommand, "[ViewFolder(") == pszCommand) + else if (_tcsstr(pszCommand, L"[ViewFolder(") == pszCommand) { dwReturn = DDE_REQUEST_VIEWFOLDER; } - else if (strstr(pszCommand, "[FindFolder(") == pszCommand) + else if (_tcsstr(pszCommand, L"[FindFolder(") == pszCommand) { dwReturn = DDE_REQUEST_FINDFOLDER; } - else if (strstr(pszCommand, "[OpenFindFile(") == pszCommand) + else if (_tcsstr(pszCommand, L"[OpenFindFile(") == pszCommand) { dwReturn = DDE_REQUEST_OPENFINDFILE; } - else if (strstr(pszCommand, "[CreateGroup(") == pszCommand) + else if (_tcsstr(pszCommand, L"[CreateGroup(") == pszCommand) { dwReturn = DDE_REQUEST_CREATEGROUP; } - else if (strstr(pszCommand, "[DeleteGroup(") == pszCommand) + else if (_tcsstr(pszCommand, L"[DeleteGroup(") == pszCommand) { dwReturn = DDE_REQUEST_DELETEGROUP; } - else if (strstr(pszCommand, "[ShowGroup(") == pszCommand) + else if (_tcsstr(pszCommand, L"[ShowGroup(") == pszCommand) { dwReturn = DDE_REQUEST_SHOWGROUP; } - else if (strstr(pszCommand, "[AddItem(") == pszCommand) + else if (_tcsstr(pszCommand, L"[AddItem(") == pszCommand) { dwReturn = DDE_REQUEST_ADDITEM; } - else if (strstr(pszCommand, "[DeleteItem(") == pszCommand) + else if (_tcsstr(pszCommand, L"[DeleteItem(") == pszCommand) { dwReturn = DDE_REQUEST_DELETEITEM; } @@ -332,7 +332,7 @@ DWORD DDEWorker::_MatchRequest(LPCSTR pszCommand) } -BOOL DDEWorker::_FindFiles(LPSTR pszPath, BOOL bFindFolder) +BOOL DDEWorker::_FindFiles(LPTSTR pszPath, BOOL bFindFolder) { BOOL bReturn = FALSE; @@ -359,21 +359,21 @@ BOOL DDEWorker::_FindFiles(LPSTR pszPath, BOOL bFindFolder) BOOL DDEWorker::_ShowGroup(LPCTSTR strGroupName, int nShow, BOOL bCommon) { - char szFullPath[MAX_PATH]; - char szPath[MAX_PATH]; + TCHAR szFullPath[MAX_PATH]; + TCHAR szPath[MAX_PATH]; BOOL bReturn = FALSE; // Get the program group path if (GetShellFolderPath(bCommon ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, szPath, MAX_PATH)) { - StringCchPrintf(szFullPath, MAX_PATH, "%s\\%s\\", szPath, strGroupName); + StringCchPrintf(szFullPath, MAX_PATH, _T("%ls\\%ls\\"), szPath, strGroupName); PathQuoteSpaces(szFullPath); if (PathIsDirectory(szFullPath)) { // open it up! - LSShellExecute(NULL, "open", szFullPath, NULL, NULL, nShow); + LSShellExecute(NULL, _T("open"), szFullPath, NULL, NULL, nShow); // set our current group to this one, as per Progman DDE StringCchCopy(m_szCurrentGroup, MAX_PATH, szFullPath); @@ -388,15 +388,15 @@ BOOL DDEWorker::_ShowGroup(LPCTSTR strGroupName, int nShow, BOOL bCommon) // Create the program group BOOL DDEWorker::_CreateGroup(LPCTSTR strGroupName, BOOL bCommon) { - char szPath[MAX_PATH]; - char szFullPath[MAX_PATH]; + TCHAR szPath[MAX_PATH]; + TCHAR szFullPath[MAX_PATH]; BOOL bReturn = FALSE; // Get the program group path if (GetShellFolderPath(bCommon ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, szPath, MAX_PATH)) { - StringCchPrintf(szFullPath, MAX_PATH, "%s\\%s", szPath, strGroupName); + StringCchPrintf(szFullPath, MAX_PATH, _T("%ls\\%ls"), szPath, strGroupName); PathQuoteSpaces(szFullPath); // standard create directory call @@ -428,8 +428,8 @@ BOOL DDEWorker::_CreateGroup(LPCTSTR strGroupName, BOOL bCommon) // Remove the group BOOL DDEWorker::_DeleteGroup(LPCTSTR strGroupName, BOOL bCommon) { - char szTemp[MAX_PATH]; - char szPath[MAX_PATH]; + TCHAR szTemp[MAX_PATH]; + TCHAR szPath[MAX_PATH]; HANDLE hFind; WIN32_FIND_DATA FindData; BOOL bFindFile = TRUE; @@ -440,12 +440,12 @@ BOOL DDEWorker::_DeleteGroup(LPCTSTR strGroupName, BOOL bCommon) szPath, MAX_PATH)) { // Append \*.* for FindFirstFile - StringCchCopy(szTemp, MAX_PATH, "\\"); + StringCchCopy(szTemp, MAX_PATH, _T("\\")); StringCchCat(szTemp, MAX_PATH, strGroupName); StringCchCat(szPath, MAX_PATH, szTemp); StringCchCopy(szTemp, MAX_PATH, szPath); - StringCchCat(szTemp, MAX_PATH, "\\*.*"); + StringCchCat(szTemp, MAX_PATH,_T( "\\*.*")); // Use FindFirstFile to list dir. contents hFind = FindFirstFile(szTemp, &FindData); @@ -471,7 +471,7 @@ BOOL DDEWorker::_DeleteGroup(LPCTSTR strGroupName, BOOL bCommon) // helper function to do allocation for the list of program groups BOOL DDEWorker::_ListGroupsHelper( - HANDLE hHeap, char* szPath, LPVOID& pGroupList, UINT& ulSize) + HANDLE hHeap, LPTSTR szPath, LPVOID& pGroupList, UINT& ulSize) { HANDLE hFind; WIN32_FIND_DATA FindData; @@ -499,7 +499,7 @@ BOOL DDEWorker::_ListGroupsHelper( if (*(FindData.cFileName) != '.' && (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { - ULONG uLen = (ULONG)strlen(FindData.cFileName); + ULONG uLen = (ULONG)_tcslen(FindData.cFileName); pszTemp = (char*) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pGroupList, ulSize + uLen + 2); @@ -533,12 +533,12 @@ BOOL DDEWorker::_ListGroupsHelper( // kill an item BOOL DDEWorker::_DeleteItem(LPCTSTR strItem) { - char szPath[MAX_PATH]; + TCHAR szPath[MAX_PATH]; BOOL bReturn = FALSE; if (m_szCurrentGroup[0]) { - StringCchPrintf(szPath, MAX_PATH, "%s\\%s", m_szCurrentGroup, strItem); + StringCchPrintf(szPath, MAX_PATH, _T("%ls\\%ls"), m_szCurrentGroup, strItem); bReturn = DeleteFile(szPath); } @@ -550,7 +550,7 @@ BOOL DDEWorker::_AddItem( LPCTSTR strCmdLine, LPCTSTR strDescription, LPCTSTR strIconPath, int nIconIndex, LPCTSTR strDefDir, WORD dwHotKey, BOOL bMinimize) { - char szPath[MAX_PATH]; + TCHAR szPath[MAX_PATH]; HRESULT hr; IShellLink* pShellLink; IPersistFile* pPersistFile; @@ -559,20 +559,20 @@ BOOL DDEWorker::_AddItem( // check that we've set a current group via showgroup or creategroup if (m_szCurrentGroup[0]) { - char szDesc[MAX_PATH]; - char szArgs[MAX_PATH]; - char szCmd[MAX_PATH]; + TCHAR szDesc[MAX_PATH]; + TCHAR szArgs[MAX_PATH]; + TCHAR szCmd[MAX_PATH]; - PathQuoteSpaces((char*)strCmdLine); + PathQuoteSpaces((LPTSTR)strCmdLine); LPCTSTR strArgs = PathGetArgs(strCmdLine); if (strArgs) { StringCchCopy(szArgs, MAX_PATH, strArgs); - PathRemoveArgs((char*)strCmdLine); + PathRemoveArgs((LPTSTR)strCmdLine); } - PathUnquoteSpaces((char*) strCmdLine); + PathUnquoteSpaces((LPTSTR) strCmdLine); StringCchCopy(szCmd, MAX_PATH, strCmdLine); if (strDescription) @@ -582,12 +582,12 @@ BOOL DDEWorker::_AddItem( } else { - PathUnquoteSpaces((char*) strDescription); + PathUnquoteSpaces((LPTSTR) strDescription); StringCchCopy(szDesc, MAX_PATH, strDescription); } StringCchPrintf(szPath, MAX_PATH, - "%s\\%s.lnk", m_szCurrentGroup, szDesc); + _T("%ls\\%ls.lnk"), m_szCurrentGroup, szDesc); hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) & pShellLink); @@ -612,13 +612,8 @@ BOOL DDEWorker::_AddItem( if (SUCCEEDED(hr)) { - WCHAR wsz[MAX_PATH]; - - // Ensure that the string is ANSI. - MultiByteToWideChar(CP_ACP, 0, szPath, -1, wsz, MAX_PATH); - // Save the link by calling IPersistFile::Save. - hr = pPersistFile->Save(wsz, TRUE); + hr = pPersistFile->Save(szPath, TRUE); if (SUCCEEDED(hr)) { SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, m_szCurrentGroup, 0); diff --git a/litestep/DDEWorker.h b/litestep/DDEWorker.h index 21923e1..8a44b7b 100644 --- a/litestep/DDEWorker.h +++ b/litestep/DDEWorker.h @@ -43,11 +43,11 @@ class DDEWorker DDEWorker(); ~DDEWorker(); - BOOL ParseRequest(LPCSTR pszRequest); + BOOL ParseRequest(LPCTSTR pszRequest); BOOL ListGroups(LPVOID& pGroupList, UINT& ulSize); private: - BOOL _FindFiles(LPSTR pszPath, BOOL bFindFolder); + BOOL _FindFiles(LPTSTR pszPath, BOOL bFindFolder); BOOL _ShowGroup(LPCTSTR strGroupName, int nShow, BOOL bCommon); BOOL _CreateGroup(LPCTSTR strGroupName, BOOL bCommon); BOOL _DeleteGroup(LPCTSTR strGroupName, BOOL bCommon); @@ -56,10 +56,10 @@ class DDEWorker LPCTSTR strCmdLine, LPCTSTR pszDescription, LPCTSTR pszIconPath, int nIconIndex, LPCTSTR pszDefDir, WORD dwHotKey, BOOL bMinimize); BOOL _ListGroupsHelper( - HANDLE hHeap, char* szPath, LPVOID& pGroupList, UINT& ulSize); - DWORD _MatchRequest(LPCSTR pszCommand); + HANDLE hHeap, wchar_t* szPath, LPVOID& pGroupList, UINT& ulSize); + DWORD _MatchRequest(LPCTSTR pszCommand); - char m_szCurrentGroup[MAX_PATH]; + TCHAR m_szCurrentGroup[MAX_PATH]; BOOL m_bIsUserAnAdmin; }; diff --git a/litestep/ExplorerService.cpp b/litestep/ExplorerService.cpp index c874b17..88d34e9 100644 --- a/litestep/ExplorerService.cpp +++ b/litestep/ExplorerService.cpp @@ -24,26 +24,34 @@ #include "ShellDesktopTray.h" -DWORD WINAPI ExplorerThread(LPVOID); - - +// +// ExplorerService +// ExplorerService::ExplorerService() : m_dwThreadID(0), - m_hExplorerThread(NULL) + m_hExplorerThread(nullptr) { } +// +// ~ExplorerService +// ExplorerService::~ExplorerService() { } +// +// IService::Stop +// HRESULT ExplorerService::Stop() { if (m_dwThreadID) { - PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); + HWND hProgman = FindWindow(_T("Progman"), NULL); + SendMessage(hProgman, 0x44D, 0, 0); + PostMessage(hProgman, WM_QUIT, 0, 1); } if (m_hExplorerThread) @@ -53,31 +61,49 @@ HRESULT ExplorerService::Stop() TerminateThread(m_hExplorerThread, 0); } + TRACE("%p", GetShellWindow()); + CloseHandle(m_hExplorerThread); - m_hExplorerThread = NULL; + m_hExplorerThread = nullptr; } return S_OK; } +// +// IService::Start +// HRESULT ExplorerService::Start() { - CreateThread(NULL, 0, ExplorerThread, NULL, 0, &m_dwThreadID); + m_hExplorerThread = CreateThread(NULL, 0, ExplorerThread, NULL, 0, &m_dwThreadID); + Sleep(1000); + return S_OK; +} + + +// +// IService::Recycle +// +HRESULT ExplorerService::Recycle() +{ return S_OK; } -DWORD WINAPI ExplorerThread(LPVOID) +// +// ExplorerThread +// +DWORD WINAPI ExplorerService::ExplorerThread(LPVOID) { typedef void *(WINAPI *SHCREATEDESKTOP)(void *); typedef bool (WINAPI *SHDESKTOPMESSAGELOOP)(void *); - TShellDesktopTray *pExplorerTray = NULL; - IShellDesktopTray *pTray = NULL; - SHCREATEDESKTOP fnSHCreateDesktop = NULL; - SHDESKTOPMESSAGELOOP fnSHDesktopMessageLoop = NULL; - HANDLE hDesktop = NULL; + TShellDesktopTray *pExplorerTray = nullptr; + IShellDesktopTray *pTray = nullptr; + SHCREATEDESKTOP fnSHCreateDesktop = nullptr; + SHDESKTOPMESSAGELOOP fnSHDesktopMessageLoop = nullptr; + HANDLE hDesktop = nullptr; DWORD dwReturn = 0; fnSHCreateDesktop = (SHCREATEDESKTOP)GetProcAddress( @@ -91,9 +117,8 @@ DWORD WINAPI ExplorerThread(LPVOID) pExplorerTray->QueryInterface(IID_IShellDesktopTray, reinterpret_cast(&pTray)); - if ((hDesktop = fnSHCreateDesktop(pTray)) != NULL) + if ((hDesktop = fnSHCreateDesktop(pTray)) != nullptr) { - ShowWindow(FindWindow(_T("Progman"), NULL), SW_HIDE); fnSHDesktopMessageLoop(hDesktop); } else diff --git a/litestep/ExplorerService.h b/litestep/ExplorerService.h index bba2eb3..25a0209 100644 --- a/litestep/ExplorerService.h +++ b/litestep/ExplorerService.h @@ -25,6 +25,7 @@ #include "ExplorerService.h" #include "../utility/common.h" #include "../utility/IService.h" +#include class ExplorerService : public IService @@ -36,8 +37,13 @@ class ExplorerService : public IService // // IService methods // - virtual HRESULT Start(); - virtual HRESULT Stop(); +public: + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; + +private: + static DWORD WINAPI ExplorerThread(LPVOID); private: DWORD m_dwThreadID; diff --git a/litestep/FullscreenMonitor.cpp b/litestep/FullscreenMonitor.cpp new file mode 100644 index 0000000..7ad4f00 --- /dev/null +++ b/litestep/FullscreenMonitor.cpp @@ -0,0 +1,380 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2013 LiteStep Development 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 "FullscreenMonitor.h" +#include "../lsapi/lsapi.h" +#include "../utility/debug.hpp" + + +// +// FullscreenMonitor +// +FullscreenMonitor::FullscreenMonitor() : + m_workerSleepDuration(100) +{ + m_bReHide = false; +} + + +// +// ~FullscreenMonitor +// +FullscreenMonitor::~FullscreenMonitor() +{ +} + + +// +// _FullScreenGetMonitorHelper +// +HMONITOR FullscreenMonitor::_FullScreenGetMonitorHelper(HWND hWnd) +{ + if (!IsWindow(hWnd) || !IsWindowVisible(hWnd) || IsIconic(hWnd)) + { + return nullptr; + } + + HMONITOR hMonFS = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL); + + if (nullptr == hMonFS) + { + return nullptr; + } + + RECT rScreen = { 0 }; + + if (nullptr != hMonFS) + { + MONITORINFO miFS; + miFS.cbSize = sizeof(MONITORINFO); + + if (GetMonitorInfo(hMonFS, &miFS)) + { + VERIFY(CopyRect(&rScreen, &miFS.rcMonitor)); + } + else + { + rScreen.left = 0; + rScreen.top = 0; + rScreen.right = GetSystemMetrics(SM_CXSCREEN); + rScreen.bottom = GetSystemMetrics(SM_CYSCREEN); + + hMonFS = MonitorFromRect(&rScreen, MONITOR_DEFAULTTOPRIMARY); + } + } + + RECT rWnd; + VERIFY(GetClientRect(hWnd, &rWnd)); + + LONG width = rWnd.right - rWnd.left; + LONG height = rWnd.bottom - rWnd.top; + + POINT pt = { rWnd.left, rWnd.top }; + VERIFY(ClientToScreen(hWnd, &pt)); + + rWnd.left = pt.x; + rWnd.top = pt.y; + rWnd.right = pt.x + width; + rWnd.bottom = pt.y + height; + + // If the client area is the size of the screen, then consider it to be + // a full screen window. + if (EqualRect(&rScreen, &rWnd)) + { + return hMonFS; + } + + DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE); + + // Check Window Rect if WS_CAPTION or WS_THICKFRAME is part of the style. + // As long as at least one of them is not set, then we can check if the + // window is full screen or not: http://support.microsoft.com/kb/q179363/ + if (WS_CAPTION != (WS_CAPTION & dwStyle) || + WS_THICKFRAME != (WS_THICKFRAME & dwStyle)) + { + VERIFY(GetWindowRect(hWnd, &rWnd)); + + if (EqualRect(&rScreen, &rWnd)) + { + return hMonFS; + } + } + + return nullptr; +} + + +// +// _EnumThreadFSWnd +// +BOOL CALLBACK FullscreenMonitor::_EnumThreadFSWnd(HWND hWnd, LPARAM lParam) +{ + HMONITOR hMonFS = _FullScreenGetMonitorHelper(hWnd); + + if (nullptr != hMonFS) + { + *(HMONITOR*)lParam = hMonFS; + return FALSE; + } + + return TRUE; +} + + +// +// IsFullscreenWindow +// +HMONITOR FullscreenMonitor::IsFullscreenWindow(HWND hWnd) +{ + if (!IsWindow(hWnd)) + { + return nullptr; + } + + HMONITOR hMonFS = nullptr; + EnumThreadWindows(GetWindowThreadProcessId(hWnd, nullptr), _EnumThreadFSWnd, (LPARAM)&hMonFS); + + return hMonFS; +} + + +// +// ShowModules +// +void FullscreenMonitor::ShowModules(HMONITOR hMonitor) +{ + if (m_bAutoHideModules) + { + ParseBangCommandW((HWND)hMonitor, L"!ShowModules", nullptr); + } + PostMessage(GetLitestepWnd(), LM_FULLSCREENDEACTIVATED, (WPARAM) hMonitor, 0); +} + + +// +// HideModules +// +void FullscreenMonitor::HideModules(HMONITOR hMonitor, HWND hWnd) +{ + if (m_bAutoHideModules) + { + ParseBangCommandW((HWND)hMonitor, L"!HideModules", nullptr); + } + PostMessage(GetLitestepWnd(), LM_FULLSCREENACTIVATED, (WPARAM) hMonitor, (LPARAM) hWnd); +} + + +// +// ThreadProc +// +void FullscreenMonitor::ThreadProc() +{ + // + struct FSWindow { + FSWindow(HWND hWnd, HMONITOR hMonitor) { + this->hWnd = hWnd; + this->hMonitor = hMonitor; + } + HWND hWnd; + HMONITOR hMonitor; + }; + + // List of all currently living known fullscreen windows + std::list fullscreenWindows; + + // The monitors which currently have modules hidden + std::unordered_multiset hiddenMonitors; + + DWORD dwLiteStepProcID; + GetWindowThreadProcessId(GetLitestepWnd(), &dwLiteStepProcID); + + // On startup, find any existing fullscreen windows. + EnumDesktopWindows(nullptr, [] (HWND hWnd, LPARAM lParam) -> BOOL + { + HMONITOR hMonitor = IsFullscreenWindow(hWnd); + std::list *fullscreenWindows = (std::list*)lParam; + if (hMonitor) + { + // And add it to the list of fullscreen windows. + fullscreenWindows->push_back(FSWindow(hWnd, hMonitor)); + } + return TRUE; + }, (LPARAM)&fullscreenWindows); + + // Hide modules on any monitor we found + for (FSWindow window : fullscreenWindows) + { + hiddenMonitors.insert(window.hMonitor); + if (hiddenMonitors.count(window.hMonitor) == 1) + { + HideModules(window.hMonitor, window.hWnd); + } + } + + // Main Loop + while (m_bRun.load()) + { + HWND hwndForeGround = GetForegroundWindow(); + bool bCheckedForeGround = false; + + // Re-Hide modules on all monitors + if (m_bReHide.load()) + { + hiddenMonitors.clear(); + for (FSWindow window : fullscreenWindows) + { + hiddenMonitors.insert(window.hMonitor); + if (hiddenMonitors.count(window.hMonitor) == 1) + { + HideModules(window.hMonitor, window.hWnd); + } + } + } + + // Verify that all currently known fullscreen windows are still fullscreen. + std::list::iterator iter = fullscreenWindows.begin(); + while (iter != fullscreenWindows.end()) + { + HMONITOR hNewMonitor = IsFullscreenWindow(iter->hWnd); + + // If we already checked the foreground window, don't bother doing it again. + if (iter->hWnd == hwndForeGround) + { + bCheckedForeGround = true; + } + + // + if (hNewMonitor != iter->hMonitor) + { + hiddenMonitors.erase(iter->hMonitor); + + // If there are no fullscreen windows left on the monitor, show the modules + if (hiddenMonitors.count(iter->hMonitor) == 0) + { + ShowModules(iter->hMonitor); + } + + // Check if the window moved to another monitor (and stayed fullscreen) + if (hNewMonitor) + { + iter->hMonitor = hNewMonitor; + hiddenMonitors.insert(hNewMonitor); + if (hiddenMonitors.count(hNewMonitor) == 1) + { + HideModules(hNewMonitor, iter->hWnd); + } + } + else + { + iter = fullscreenWindows.erase(iter); + continue; + } + } + + ++iter; + } + + // Check if the currently active window is a fullscreen window. + if (!bCheckedForeGround) + { + // If the currently active window belongs to litestep, show all modules. + DWORD dwProcID; + GetWindowThreadProcessId(hwndForeGround, &dwProcID); + if (dwProcID == dwLiteStepProcID) + { + if (!hiddenMonitors.empty()) + { + for (HMONITOR hMonitor : hiddenMonitors) + { + ShowModules(hMonitor); + } + hiddenMonitors.clear(); + fullscreenWindows.clear(); + } + } + else + { + HMONITOR hMonitor = IsFullscreenWindow(hwndForeGround); + if (hMonitor) + { + // Add the window to the list of known foreground windows. + fullscreenWindows.push_back(FSWindow(hwndForeGround, hMonitor)); + hiddenMonitors.insert(hMonitor); + + // If we didn't know about any fullscreen windows on this monitor before, hide the modules on it. + if (hiddenMonitors.count(hMonitor) == 1) + { + HideModules(hMonitor, hwndForeGround); + } + } + } + } + + // Avoid using excesive amounts of CPU time + std::this_thread::sleep_for(m_workerSleepDuration); + } +} + + +// +// IService::Start +// +HRESULT FullscreenMonitor::Start() +{ + m_bAutoHideModules = GetRCBoolW(L"LSAutoHideModules", TRUE) != FALSE; + m_bRun.store(true); + m_fullscreenMonitorThread = std::thread(std::bind(&FullscreenMonitor::ThreadProc, this)); + + return S_OK; +} + + +// +// IService::Stop +// +HRESULT FullscreenMonitor::Stop() +{ + m_bRun.store(false); + m_fullscreenMonitorThread.join(); + + return S_OK; +} + + +// +// IService::Recycle +// +HRESULT FullscreenMonitor::Recycle() +{ + bool bAlreadyHidden = m_bAutoHideModules; + m_bAutoHideModules = GetRCBoolW(L"LSAutoHideModules", TRUE) != FALSE; + + // We need to show the modules that were hidden before + if (bAlreadyHidden && !m_bAutoHideModules) + { + // TODO::We could possibly just show the modules on monitors with fullscreen windows. + ParseBangCommandW(nullptr, L"!ShowModules", nullptr); + } + + m_bReHide.store(true); + + return S_OK; +} diff --git a/litestep/FullscreenMonitor.h b/litestep/FullscreenMonitor.h new file mode 100644 index 0000000..6cd0f02 --- /dev/null +++ b/litestep/FullscreenMonitor.h @@ -0,0 +1,65 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(FULLSCREENMONITOR_H) +#define FULLSCREENMONITOR_H + +#include "../utility/IService.h" +#include +#include +#include +#include + +class FullscreenMonitor: public IService +{ +public: + FullscreenMonitor(); + ~FullscreenMonitor(); + + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; + +private: + static HMONITOR _FullScreenGetMonitorHelper(HWND hWnd); + static BOOL CALLBACK _EnumThreadFSWnd(HWND hWnd, LPARAM lParam); + static HMONITOR IsFullscreenWindow(HWND hwnd); + void ThreadProc(); + void ShowModules(HMONITOR hMonitor); + void HideModules(HMONITOR hMonitor, HWND hWnd); + + // LS thread only +private: + std::thread m_fullscreenMonitorThread; + + // Shared +private: + std::atomic m_bRun; + std::atomic m_bReHide; + std::atomic m_bAutoHideModules; + + // Worker thread only +private: + std::chrono::milliseconds m_workerSleepDuration; +}; + +#endif // FULLSCREENMONITOR_H diff --git a/litestep/Module.cpp b/litestep/Module.cpp index dad1d59..397300f 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -23,21 +23,47 @@ #include "../lsapi/ThreadedBangCommand.h" #include "../utility/macros.h" #include "../utility/core.hpp" +#include "../utility/stringutility.h" #include -Module::Module(const std::string& sLocation, DWORD dwFlags) +Module::Module(const std::wstring& sLocation, DWORD dwFlags) { - m_hInstance = NULL; - m_hThread = NULL; - m_pInitEx = NULL; - m_hInitEvent = NULL; - m_hInitCopyEvent = NULL; - m_pQuit = NULL; + m_hInstance = nullptr; + m_hThread = nullptr; + m_pInit = nullptr; + m_hInitEvent = nullptr; + m_hInitCopyEvent = nullptr; + m_pQuit = nullptr; m_dwFlags = dwFlags; m_dwLoadTime = 0; - m_tzLocation = sLocation; + m_wzLocation = sLocation; +} + + +static WORD GetModuleArchitecture(LPCWSTR wzModuleName) +{ + WORD wRet = 0; + HANDLE hFile = CreateFileW(wzModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + HANDLE hFileMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hFileMapping != nullptr) + { + LPVOID lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); + if (lpFileBase != nullptr) + { + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpFileBase; + PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((LPBYTE)pDosHeader + pDosHeader->e_lfanew); + wRet = pNTHeader->OptionalHeader.Magic; + UnmapViewOfFile(lpFileBase); + } + CloseHandle(hFileMapping); + } + CloseHandle(hFile); + } + return wRet; } @@ -54,21 +80,32 @@ bool Module::_LoadDll() // disabled them via SetErrorMode. We force their display here. // First, make Windows display all errors UINT uOldMode = SetErrorMode(0); - - m_hInstance = LoadLibrary(m_tzLocation.c_str()); - - // Second, restore the old state - SetErrorMode(uOldMode); - - if (m_hInstance) + + if ((m_hInstance = LoadLibraryW(m_wzLocation.c_str())) != nullptr) { - m_pInitEx = (initModuleExProc)GetProcAddress( - m_hInstance, "initModuleEx"); - - if (!m_pInitEx) // Might be a BC module, check for underscore + m_pInit = (initModuleProc)GetProcAddress( + m_hInstance, "initModuleW"); + + if (m_pInit != nullptr) // Might be a legacy module, check for initModuleEx { - m_pInitEx = (initModuleExProc)GetProcAddress( - m_hInstance, "_initModuleEx"); + initModuleProcA pInit = (initModuleProcA)GetProcAddress( + m_hInstance, "initModuleEx"); + + if (!pInit) // Might be a BC module, check for underscore + { + pInit = (initModuleProcA)GetProcAddress( + m_hInstance, "_initModuleEx"); + } + + if (pInit) + { + m_pInit = [pInit] (HWND hWnd, HINSTANCE hInst, LPCWSTR pwzPath) -> int { + char szPath[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, pwzPath, -1, + szPath, sizeof(szPath), "", nullptr); + return pInit(hWnd, hInst, szPath); + }; + } } m_pQuit = (quitModuleProc)GetProcAddress( @@ -80,52 +117,84 @@ bool Module::_LoadDll() m_hInstance, "_quitModule"); } - if (!m_pInitEx) + if (!m_pInit) { - RESOURCE_STR(NULL, IDS_INITMODULEEXNOTFOUND_ERROR, - "Error: Could not find initModuleEx().\n" - "\n" - "Please confirm that the dll is a LiteStep module,\n" - "and check with the author for updates."); + RESOURCE_STR(nullptr, IDS_INITMODULEEXNOTFOUND_ERROR, + L"Error: Could not find initModule().\n" + L"\n" + L"Please confirm that the dll is a LiteStep module,\n" + L"and check with the author for updates."); } else if (!m_pQuit) { - RESOURCE_STR(NULL, IDS_QUITMODULENOTFOUND_ERROR, - "Error: Could not find quitModule().\n" - "\n" - "Please confirm that the dll is a LiteStep module."); + RESOURCE_STR(nullptr, IDS_QUITMODULENOTFOUND_ERROR, + L"Error: Could not find quitModule().\n" + L"\n" + L"Please confirm that the dll is a LiteStep module."); } else { bReturn = true; } } - else if (PathFileExists(m_tzLocation.c_str())) - { - RESOURCE_STR(NULL, IDS_MODULEDEPENDENCY_ERROR, - "Error: Could not load module.\n" - "\n" - "This is likely a case of a missing C Run-Time Library" - "or other dependency."); - } else { - RESOURCE_STR(NULL, IDS_MODULENOTFOUND_ERROR, - "Error: Could not locate module.\n" - "\n" - "Please check your configuration."); + HRESULT hrError = HrGetLastError(); + +#if defined(_WIN64) + if (GetModuleArchitecture(m_wzLocation.c_str()) == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + RESOURCE_STR(nullptr, IDS_MODULEWRONGARCH64_ERROR, + L"Error: Could not load module.\n" + L"\n" + L"The module seems to compiled for 32-bit LiteStep. This is a 64-bit version of LiteStep, which can only load 64-bit modules."); + } +#else + if (GetModuleArchitecture(m_wzLocation.c_str()) == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + RESOURCE_STR(nullptr, IDS_MODULEWRONGARCH32_ERROR, + L"Error: Could not load module.\n" + L"\n" + L"The module seems to compiled for 64-bit LiteStep. This is a 32-bit version of LiteStep, which can only load 32-bit modules."); + } +#endif + else if (PathFileExistsW(m_wzLocation.c_str())) + { + RESOURCE_STR(nullptr, IDS_MODULEDEPENDENCY_ERROR, + L"Error: Could not load module.\n" + L"\n" + L"This is likely a case of a missing C Run-Time Library" + L"or other dependency." + L"\n" + L"Error Information:" + L"\n"); + + size_t nLen = 0; + StringCchLengthW(resourceTextBuffer, _countof(resourceTextBuffer), &nLen); + DescriptionFromHR(hrError, resourceTextBuffer + nLen, _countof(resourceTextBuffer) - nLen); + } + else + { + RESOURCE_STR(nullptr, IDS_MODULENOTFOUND_ERROR, + L"Error: Could not locate module.\n" + L"\n" + L"Please check your configuration."); + } } + + // Second, restore the old state + SetErrorMode(uOldMode); if (!bReturn) { - LPCTSTR pszFileName = PathFindFileName(m_tzLocation.c_str()); + LPCWSTR pwzFileName = PathFindFileNameW(m_wzLocation.c_str()); - RESOURCE_MSGBOX_F(pszFileName, MB_ICONERROR); + RESOURCE_MSGBOX_F(pwzFileName, MB_ICONERROR); if (m_hInstance) { FreeLibrary(m_hInstance); - m_hInstance = NULL; + m_hInstance = nullptr; } } } @@ -171,7 +240,7 @@ Module::~Module() } -bool Module::Init(HWND hMainWindow, const std::string& sAppPath) +bool Module::Init(HWND hMainWindow, const std::wstring& sAppPath) { ASSERT(NULL == m_hInstance); @@ -187,21 +256,21 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) // grdtransparent work (it hooks LoadLibrary) if (_LoadDll()) { - ASSERT(NULL != m_pInitEx); - ASSERT(NULL != m_pQuit); + ASSERT(nullptr != m_pInit); + ASSERT(nullptr != m_pQuit); m_hMainWindow = hMainWindow; - m_tzAppPath = sAppPath; + m_wzAppPath = sAppPath; if (m_dwFlags & LS_MODULE_THREADED) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; + sa.lpSecurityDescriptor = nullptr; sa.bInheritHandle = FALSE; - m_hInitCopyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + m_hInitCopyEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_hInitEvent = m_hInitCopyEvent; // using _beginthreadex instead of CreateThread because modules // might use CRT functions @@ -232,8 +301,8 @@ bool Module::Init(HWND hMainWindow, const std::string& sAppPath) int Module::CallInit() { - ASSERT(m_pInitEx != NULL); - return m_pInitEx(m_hMainWindow, m_hInstance, m_tzAppPath.c_str()); + ASSERT(m_pInit != nullptr); + return m_pInit(m_hMainWindow, m_hInstance, m_wzAppPath.c_str()); } @@ -265,8 +334,8 @@ UINT __stdcall Module::ThreadProc(void* dllModPtr) Module* dllMod = (Module*)dllModPtr; #if defined(MSVC_DEBUG) - LPCTSTR pszFileName = PathFindFileName(dllMod->m_tzLocation.c_str()); - DbgSetCurrentThreadName(pszFileName); + LPCTSTR pszFileName = PathFindFileName(dllMod->m_wzLocation.c_str()); + DbgSetCurrentThreadName(WCSTOMBS(pszFileName)); #endif dllMod->CallInit(); diff --git a/litestep/Module.h b/litestep/Module.h index 7de83f8..65c22ee 100644 --- a/litestep/Module.h +++ b/litestep/Module.h @@ -25,6 +25,7 @@ #include "../lsapi/lsapidefines.h" #include "../utility/common.h" #include +#include /** @@ -46,13 +47,13 @@ class Module DWORD m_dwThreadID; /** Path to module's DLL */ - std::basic_string m_tzLocation; + std::basic_string m_wzLocation; /** Path to LiteStep's root directory */ - std::basic_string m_tzAppPath; + std::basic_string m_wzAppPath; /** Pointer to initModuleEx function */ - initModuleExProc m_pInitEx; + std::function m_pInit; /** Pointer to quitModule function */ quitModuleProc m_pQuit; @@ -76,7 +77,7 @@ class Module * @param sLocation path to the module's DLL * @param dwFlags set of flags that control how the module is loaded */ - Module(const std::string& sLocation, DWORD dwFlags); + Module(const std::wstring& sLocation, DWORD dwFlags); /** * Destructor. @@ -94,7 +95,7 @@ class Module * @param sAppPath path to LiteStep's root directory * @return true if successful or false otherwise */ - bool Init(HWND hMainWindow, const std::string& sAppPath); + bool Init(HWND hMainWindow, const std::wstring& sAppPath); /** * Shuts down the module and unloads it. If the module was loaded in its @@ -145,7 +146,7 @@ class Module HANDLE TakeThread() { HANDLE hTemp = m_hThread; - m_hThread = NULL; + m_hThread = nullptr; return hTemp; } @@ -168,7 +169,7 @@ class Module HANDLE TakeInitEvent() { HANDLE hTemp = m_hInitEvent; - m_hInitEvent = NULL; + m_hInitEvent = nullptr; return hTemp; } @@ -176,9 +177,9 @@ class Module /** * Returns the path to this module's DLL. */ - LPCTSTR GetLocation() const + LPCWSTR GetLocation() const { - return m_tzLocation.c_str(); + return m_wzLocation.c_str(); } /** @@ -200,7 +201,7 @@ class Module /** * Returns a pointer to this module's quitModule function. */ - quitModuleProc GetQuit() const + decltype(m_pQuit) GetQuit() const { return m_pQuit; } @@ -208,9 +209,9 @@ class Module /** * Returns a pointer to this module's initModuleEx function. */ - initModuleExProc GetInitEx() const + decltype(m_pInit) GetInit() const { - return m_pInitEx; + return m_pInit; } private: diff --git a/litestep/ModuleManager.cpp b/litestep/ModuleManager.cpp index 08b04a8..e2c1513 100644 --- a/litestep/ModuleManager.cpp +++ b/litestep/ModuleManager.cpp @@ -49,13 +49,13 @@ HRESULT ModuleManager::Start(ILiteStep *pILiteStep) m_pILiteStep = pILiteStep; m_pILiteStep->AddRef(); - char szAppPath[MAX_PATH] = { 0 }; + wchar_t wzAppPath[MAX_PATH] = { 0 }; m_hLiteStep = GetLitestepWnd(); - if (m_hLiteStep && LSGetLitestepPath(szAppPath, MAX_PATH)) + if (m_hLiteStep && LSGetLitestepPathW(wzAppPath, MAX_PATH)) { - m_sAppPath = szAppPath; + m_sAppPath = wzAppPath; _LoadModules(); @@ -112,9 +112,9 @@ UINT ModuleManager::_LoadModules() ASSERT(m_ModuleQueue.empty()); UINT uReturn = 0; - char szLine[MAX_LINE_LENGTH]; + wchar_t wzLine[MAX_LINE_LENGTH]; - LPVOID f = LCOpen(NULL); + LPVOID f = LCOpenW(nullptr); if (f) { @@ -127,20 +127,20 @@ UINT ModuleManager::_LoadModules() #elif defined(LS_COMPAT_LCREADNEXTCONFIG) while (LCReadNextCommand(f, szLine, MAX_LINE_LENGTH)) #else - while (LCReadNextConfig(f, "LoadModule", szLine, MAX_LINE_LENGTH)) + while (LCReadNextConfigW(f, L"LoadModule", wzLine, MAX_LINE_LENGTH)) #endif { - char szCommand[MAX_RCCOMMAND] = { 0 }; - char szToken1[MAX_LINE_LENGTH] = { 0 }; - char szToken2[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzCommand[MAX_RCCOMMAND] = { 0 }; + wchar_t wzToken1[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzToken2[MAX_LINE_LENGTH] = { 0 }; // first buffer takes the "LoadModule" token - LPSTR lpszBuffers[] = { szCommand, szToken1, szToken2 }; + LPWSTR lpwzBuffers[] = { wzCommand, wzToken1, wzToken2 }; - if (LCTokenize(szLine, lpszBuffers, 3, NULL) >= 2) + if (LCTokenizeW(wzLine, lpwzBuffers, 3, nullptr) >= 2) { #if defined(LS_COMPAT_LCREADNEXTCONFIG) - if (_stricmp(szCommand, "LoadModule")) + if (_wcsicmp(wzCommand, L"LoadModule")) { continue; } @@ -148,12 +148,12 @@ UINT ModuleManager::_LoadModules() DWORD dwFlags = 0; - if (_stricmp(szToken2, "threaded") == 0) + if (_wcsicmp(wzToken2, L"threaded") == 0) { dwFlags |= LS_MODULE_THREADED; } - Module* pModule = _MakeModule(szToken1, dwFlags); + Module* pModule = _MakeModule(wzToken1, dwFlags); if (pModule) { @@ -171,11 +171,11 @@ UINT ModuleManager::_LoadModules() } -BOOL ModuleManager::LoadModule(LPCSTR pszLocation, DWORD dwFlags) +BOOL ModuleManager::LoadModule(LPCWSTR pwzLocation, DWORD dwFlags) { BOOL bReturn = FALSE; - Module* pModule = _MakeModule(pszLocation, dwFlags); + Module* pModule = _MakeModule(pwzLocation, dwFlags); if (pModule) { @@ -187,9 +187,9 @@ BOOL ModuleManager::LoadModule(LPCSTR pszLocation, DWORD dwFlags) } -Module* ModuleManager::_MakeModule(LPCSTR pszLocation, DWORD dwFlags) +Module* ModuleManager::_MakeModule(LPCWSTR pwzLocation, DWORD dwFlags) { - return new Module(pszLocation, dwFlags); + return new Module(pwzLocation, dwFlags); } @@ -324,11 +324,11 @@ BOOL ModuleManager::QuitModule(HINSTANCE hModule) } -BOOL ModuleManager::QuitModule(LPCSTR pszLocation) +BOOL ModuleManager::QuitModule(LPCWSTR pwzLocation) { BOOL bReturn = FALSE; - ModuleQueue::iterator iter = _FindModule(pszLocation); + ModuleQueue::iterator iter = _FindModule(pwzLocation); if (iter != m_ModuleQueue.end() && *iter) { @@ -347,7 +347,7 @@ BOOL ModuleManager::ReloadModule(HINSTANCE hModule) if (iter != m_ModuleQueue.end()) { - std::string sLocation = (*iter)->GetLocation(); + std::wstring sLocation = (*iter)->GetLocation(); DWORD dwFlags = (*iter)->GetFlags(); QuitModule(hModule); @@ -358,10 +358,10 @@ BOOL ModuleManager::ReloadModule(HINSTANCE hModule) } -ModuleQueue::iterator ModuleManager::_FindModule(LPCSTR pszLocation) +ModuleQueue::iterator ModuleManager::_FindModule(LPCWSTR pwzLocation) { return std::find_if(m_ModuleQueue.begin(), m_ModuleQueue.end(), - IsLocationEqual(pszLocation)); + IsLocationEqual(pwzLocation)); } @@ -399,7 +399,7 @@ void ModuleManager::_WaitForModules(const HANDLE* pHandles, size_t stCount) cons } -HRESULT ModuleManager::EnumModules(LSENUMMODULESPROC pfnCallback, LPARAM lParam) const +HRESULT ModuleManager::EnumModules(LSENUMMODULESPROCW pfnCallback, LPARAM lParam) const { HRESULT hr = S_OK; @@ -418,7 +418,7 @@ HRESULT ModuleManager::EnumModules(LSENUMMODULESPROC pfnCallback, LPARAM lParam) } -HRESULT ModuleManager::EnumPerformance(LSENUMPERFORMANCEPROC pfnCallback, LPARAM lParam) const +HRESULT ModuleManager::EnumPerformance(LSENUMPERFORMANCEPROCW pfnCallback, LPARAM lParam) const { HRESULT hr = S_OK; diff --git a/litestep/ModuleManager.h b/litestep/ModuleManager.h index 4d80634..2b6bafc 100644 --- a/litestep/ModuleManager.h +++ b/litestep/ModuleManager.h @@ -81,12 +81,12 @@ class ModuleManager: public IManager /** * Loads a module. * - * @param pszLocation path to the module's DLL + * @param pwzLocation path to the module's DLL * @param dwFlags set of flags that control how the module is loaded * @return TRUE if successful or FALSE if an * error occurs */ - BOOL LoadModule(LPCSTR pszLocation, DWORD dwFlags); + BOOL LoadModule(LPCWSTR pwzLocation, DWORD dwFlags); /** * Unloads a module given its instance handle. @@ -100,11 +100,11 @@ class ModuleManager: public IManager /** * Unloads a module given the path to its DLL. * - * @param pszLocation path to the module's DLL + * @param pwzLocation path to the module's DLL * @return TRUE if successful or FALSE if an * error occurs */ - BOOL QuitModule(LPCSTR pszLocation); + BOOL QuitModule(LPCWSTR pwzLocation); /** * Reloads a module given its instance handle @@ -127,7 +127,7 @@ class ModuleManager: public IManager * S_FALSE if the callback function returned * FALSE, or an error code */ - HRESULT EnumModules(LSENUMMODULESPROC pfnCallback, LPARAM lParam) const; + HRESULT EnumModules(LSENUMMODULESPROCW pfnCallback, LPARAM lParam) const; /** * Enumerates performance statistics for loaded modules. Calls the callback @@ -141,7 +141,7 @@ class ModuleManager: public IManager * S_FALSE if the callback function returned * FALSE, or an error code */ - HRESULT EnumPerformance(LSENUMPERFORMANCEPROC pfnCallback, LPARAM lParam) const; + HRESULT EnumPerformance(LSENUMPERFORMANCEPROCW pfnCallback, LPARAM lParam) const; private: /** @@ -169,7 +169,7 @@ class ModuleManager: public IManager * * @return iterator that points to the module or the end of the list */ - ModuleQueue::iterator _FindModule(LPCSTR pszLocation); + ModuleQueue::iterator _FindModule(LPCWSTR pwzLocation); /** * Finds a module in the loaded module list based on its instance handle. @@ -181,11 +181,11 @@ class ModuleManager: public IManager /** * Allocates a module object. * - * @param pszLocation path to the module's DLL + * @param pwzLocation path to the module's DLL * @param dwFlags set of flags that control how the module is loaded * @return pointer to the module object */ - Module* _MakeModule(LPCSTR pszLocation, DWORD dwFlags); + Module* _MakeModule(LPCWSTR pwzLocation, DWORD dwFlags); /** * Waits for an array of events to all be set while remaining responsive @@ -206,7 +206,7 @@ class ModuleManager: public IManager HWND m_hLiteStep; /** Path to LiteStep's root directory */ - std::string m_sAppPath; + std::wstring m_sAppPath; /** * Predicate used by _FindModule to locate a loaded module @@ -217,7 +217,7 @@ class ModuleManager: public IManager /** * Constructor. */ - IsLocationEqual(LPCSTR pszLocation) : m_pszLocation(pszLocation) + IsLocationEqual(LPCWSTR pwzLocation) : m_pwzLocation(pwzLocation) { // do nothing } @@ -228,12 +228,12 @@ class ModuleManager: public IManager */ bool operator() (const Module* pModule) const { - return (_stricmp(m_pszLocation, pModule->GetLocation()) == 0); + return (_wcsicmp(m_pwzLocation, pModule->GetLocation()) == 0); } private: /** Path to match */ - LPCSTR m_pszLocation; + LPCWSTR m_pwzLocation; }; /** diff --git a/litestep/RecoveryMenu.cpp b/litestep/RecoveryMenu.cpp index ba2ffd4..1eb45bb 100644 --- a/litestep/RecoveryMenu.cpp +++ b/litestep/RecoveryMenu.cpp @@ -37,6 +37,8 @@ #define ID_TERMINATE 3 #define ID_RUN 4 #define ID_SHUTDOWN 5 +#define ID_EXPLORER 6 +#define ID_ABOUT 7 const TCHAR szRecoveryMenuWndClass[] = _T("RecoveryMenuWndClass"); @@ -49,17 +51,19 @@ struct MenuCommands { int nStringID; int nCommandID; - LPCSTR pszDefText; + LPCTSTR pszDefText; } rgMenuCommands[] = \ { - { IDS_LITESTEP_RECYCLELS, ID_RECYCLE, "Re&cycle LiteStep" } - ,{ IDS_LITESTEP_QUITLS, ID_QUIT, "&Quit LiteStep" } - ,{ IDS_LITESTEP_TERMINATELS, ID_TERMINATE, "Forcibly &Terminate LiteStep" } - ,{ 0, -1, "" } - ,{ IDS_LITESTEP_RUN, ID_RUN, "&Run..." } - ,{ 0, -1, "" } - ,{ IDS_LITESTEP_SHUTDOWNWIN, ID_SHUTDOWN, "Sh&utdown Windows..." } + { IDS_LITESTEP_RECYCLELS, ID_RECYCLE, _T("Re&cycle LiteStep") } + ,{ IDS_LITESTEP_QUITLS, ID_QUIT, _T("&Quit LiteStep") } + ,{ IDS_LITESTEP_TERMINATELS, ID_TERMINATE, _T("Forcibly &Terminate LiteStep") } + ,{ IDS_LITESTEP_ABOUTLS, ID_ABOUT, _T("&About LiteStep") } + ,{ 0, -1, _T("") } + ,{ IDS_LITESTEP_RUN, ID_RUN, _T("&Run...") } + ,{ IDS_LITESTEP_EXPLORER, ID_EXPLORER, _T("&Start Explorer as shell") } + ,{ 0, -1, _T("") } + ,{ IDS_LITESTEP_SHUTDOWNWIN, ID_SHUTDOWN, _T("Sh&utdown Windows...") } }; @@ -140,6 +144,16 @@ HRESULT RecoveryMenu::Stop() } +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Recycle +// +HRESULT RecoveryMenu::Recycle() +{ + return S_OK; +} + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // ThreadThunk @@ -290,8 +304,8 @@ int RecoveryMenu::ShowMenu(HWND hWnd) const { if (rgMenuCommands[i].nStringID) { - char szBuffer[MAX_PATH] = { 0 }; - GetResStr(m_hInstance, + TCHAR szBuffer[MAX_PATH] = { 0 }; + GetResStrW(m_hInstance, rgMenuCommands[i].nStringID, szBuffer, MAX_PATH, rgMenuCommands[i].pszDefText); @@ -344,6 +358,18 @@ void RecoveryMenu::HandleMenuCommand(int nCommand) const PostMessage(GetLitestepWnd(), LM_RECYCLE, LR_QUIT, 0); } break; + + case ID_ABOUT: + { + LSExecuteW(nullptr, L"!about", SW_SHOW); + } + break; + + case ID_EXPLORER: + { + PostMessage(GetLitestepWnd(), LM_RECYCLE, LR_EXPLORER, 0); + } + break; case ID_TERMINATE: { diff --git a/litestep/RecoveryMenu.h b/litestep/RecoveryMenu.h index 6ea1be6..81300d7 100644 --- a/litestep/RecoveryMenu.h +++ b/litestep/RecoveryMenu.h @@ -45,8 +45,9 @@ class RecoveryMenu : public IService // // IService methods // - HRESULT Start(); - HRESULT Stop(); + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; private: static DWORD WINAPI ThreadThunk(LPVOID pParam); diff --git a/litestep/ShellDesktopTray.cpp b/litestep/ShellDesktopTray.cpp index b1b609d..a494976 100644 --- a/litestep/ShellDesktopTray.cpp +++ b/litestep/ShellDesktopTray.cpp @@ -21,11 +21,12 @@ //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "../utility/common.h" #include "ShellDesktopTray.h" +#include "../lsapi/lsapi.h" TShellDesktopTray::TShellDesktopTray() : m_uRefCount(0), - m_hDesktopWnd(NULL) + m_hDesktopWnd(nullptr) { } @@ -37,7 +38,7 @@ TShellDesktopTray::~TShellDesktopTray() HRESULT TShellDesktopTray::QueryInterface(REFIID riid, LPVOID *ppvObj) { - if (!ppvObj) + if (ppvObj == nullptr) { return E_POINTER; } @@ -48,7 +49,7 @@ HRESULT TShellDesktopTray::QueryInterface(REFIID riid, LPVOID *ppvObj) } else { - *ppvObj = NULL; + *ppvObj = nullptr; return E_NOINTERFACE; } @@ -84,8 +85,7 @@ ULONG TShellDesktopTray::GetState() HRESULT TShellDesktopTray::GetTrayWindow(HWND *hTrayWnd) { - // Prevent Explorer from closing the tray window when shutting down - *hTrayWnd = NULL; + *hTrayWnd = GetLitestepWnd(); return S_OK; } @@ -93,6 +93,10 @@ HRESULT TShellDesktopTray::GetTrayWindow(HWND *hTrayWnd) HRESULT TShellDesktopTray::RegisterDesktopWindow(HWND hDesktopWindow) { m_hDesktopWnd = hDesktopWindow; + + // This is called with Progman. + ShowWindow(m_hDesktopWnd, SW_HIDE); + return S_OK; } diff --git a/litestep/ShellDesktopTray.h b/litestep/ShellDesktopTray.h index 3765f1b..b02408d 100644 --- a/litestep/ShellDesktopTray.h +++ b/litestep/ShellDesktopTray.h @@ -31,29 +31,29 @@ const IID IID_IShellDesktopTray = {0x213E2DF9,0x9A14,0x4328,{0x99,0xB1,0x69,0x61 class IShellDesktopTray : public IUnknown { public: - virtual __declspec(nothrow) ULONG GetState(void) = 0; - virtual __declspec(nothrow) HRESULT GetTrayWindow(HWND *phWnd) = 0; - virtual __declspec(nothrow) HRESULT RegisterDesktopWindow(HWND hDesktopWindow) = 0; - virtual __declspec(nothrow) HRESULT SetVar(int, ULONG) = 0; + virtual __declspec(nothrow) ULONG STDMETHODCALLTYPE GetState(void) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE GetTrayWindow(HWND *phWnd) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(HWND hDesktopWindow) = 0; + virtual __declspec(nothrow) HRESULT STDMETHODCALLTYPE SetVar(int, ULONG) = 0; }; class TShellDesktopTray : public IShellDesktopTray { public: - TShellDesktopTray(); + explicit TShellDesktopTray(); ~TShellDesktopTray(); // IUnknown - HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj); - ULONG __stdcall AddRef(); - ULONG __stdcall Release(); + HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj) override; + ULONG __stdcall AddRef() override; + ULONG __stdcall Release() override; // IShellDesktopTray - ULONG __stdcall GetState(); - HRESULT __stdcall GetTrayWindow(HWND *phWnd); - HRESULT __stdcall RegisterDesktopWindow(HWND hDesktopWindow); - HRESULT __stdcall SetVar(int p1, ULONG p2); + ULONG __stdcall GetState() override; + HRESULT __stdcall GetTrayWindow(HWND *phWnd) override; + HRESULT __stdcall RegisterDesktopWindow(HWND hDesktopWindow) override; + HRESULT __stdcall SetVar(int p1, ULONG p2) override; private: ULONG m_uRefCount; diff --git a/litestep/StartupRunner.cpp b/litestep/StartupRunner.cpp index 925802c..86ed8fb 100644 --- a/litestep/StartupRunner.cpp +++ b/litestep/StartupRunner.cpp @@ -205,7 +205,7 @@ void StartupRunner::_RunShellFolderContents(int nFolder) if (!LSShellExecuteEx(&seiCommand)) { - TRACE("StartupRunner failed to launch '%s'", + TRACE("StartupRunner failed to launch '%ls'", findData.cFileName); } } @@ -478,26 +478,49 @@ void StartupRunner::_SpawnProcess(LPTSTR ptzCommandLine, DWORD dwFlags) // Note that 'App.exe' may contain spaces too // // CreateProcess handles 1 and 2, ShellExecuteEx handles 1 and 3. - // So if the first token doesn't contain path characters (':' or '\') - // ShellExecuteEx is used. That's really ugly but it *should* work. + // + // ShellExecuteEx works with UAC. CreateProcess does not. + // Therefore, we have to attempt to emulate CreateProcess's path parsing + // when we detect case 2. // TCHAR tzToken[MAX_LINE_LENGTH] = { 0 }; - LPCTSTR ptzArgs = NULL; - - GetToken(ptzCommandLine, tzToken, &ptzArgs, FALSE); - - HANDLE hProcess = NULL; + LPTSTR ptzArgs = nullptr; + + GetTokenW(ptzCommandLine, tzToken, const_cast(&ptzArgs), FALSE); - if (strchr(tzToken, _T('\\')) || strchr(tzToken, _T(':'))) + HANDLE hProcess = nullptr; + + // If the first character is a quote, assume that the first token is the complete path. + // If the first token does not contain a \ or the first token does not contain a :, assume it's a relative path. + if (*_tcsspnp(ptzCommandLine, _T(" \t")) == _T('"') || !_tcschr(tzToken, _T('\\')) || !_tcschr(tzToken, _T(':'))) { - hProcess = _CreateProcess(ptzCommandLine); + hProcess = _ShellExecuteEx(tzToken, ptzArgs); } else { - hProcess = _ShellExecuteEx(tzToken, ptzArgs); + // This is an approximation of how CreateProcess determines which file to launch. + ptzArgs = ptzCommandLine; + do + { + ptzArgs = _tcschr(ptzArgs, _T(' ')); + if (ptzArgs != nullptr) + { + *ptzArgs++ = _T('\0'); + } + if (PathFileExists(ptzCommandLine) && PathIsDirectory(ptzCommandLine) == FALSE) + { + hProcess = _ShellExecuteEx(ptzCommandLine, ptzArgs); + break; + } + if (ptzArgs != nullptr) + { + *(ptzArgs-1) = _T(' '); + } + + } while (ptzArgs != nullptr); } - if (hProcess != NULL) + if (hProcess != nullptr) { if (dwFlags & ERK_WAITFOR_QUIT) { @@ -510,31 +533,14 @@ void StartupRunner::_SpawnProcess(LPTSTR ptzCommandLine, DWORD dwFlags) CloseHandle(hProcess); } +#ifdef _DEBUG else { - TRACE("StartupRunner failed to launch '%s'", ptzCommandLine); - } -} - - -HANDLE StartupRunner::_CreateProcess(LPTSTR ptzCommandLine) -{ - HANDLE hReturn = NULL; - - STARTUPINFO suInfo = { 0 }; - PROCESS_INFORMATION procInfo = { 0 }; - - suInfo.cb = sizeof(suInfo); - - if (CreateProcess(NULL, ptzCommandLine, NULL, NULL, FALSE, - CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, - NULL, NULL, &suInfo, &procInfo)) - { - CloseHandle(procInfo.hThread); - hReturn = procInfo.hProcess; + TCHAR tzError[4096]; + DescriptionFromHR(HrGetLastError(), tzError, _countof(tzError)); + TRACE("StartupRunner failed to launch '%ls', %ls", ptzCommandLine, tzError); } - - return hReturn; +#endif } diff --git a/litestep/StartupRunner.h b/litestep/StartupRunner.h index 697a571..bb5e3ed 100644 --- a/litestep/StartupRunner.h +++ b/litestep/StartupRunner.h @@ -33,7 +33,7 @@ class StartupRunner static void Run(BOOL bForce); static bool IsFirstRunThisSession(LPCTSTR pszSubkey); -private: +public: static DWORD WINAPI _ThreadProc(LPVOID lpData); static HKEY _CreateSessionInfoKey(); static void _RunRegKeys(HKEY hkParent, LPCTSTR ptzSubKey, DWORD dwFlags); @@ -42,7 +42,6 @@ class StartupRunner static void _RunStartupMenu(); static void _RunShellFolderContents(int nFolder); static void _SpawnProcess(LPTSTR ptzCommandLine, DWORD dwFlags); - static HANDLE _CreateProcess(LPTSTR ptzCommandLine); static HANDLE _ShellExecuteEx(LPCTSTR ptzExecutable, LPCTSTR ptzArgs); }; diff --git a/litestep/TaskbarListHandler.cpp b/litestep/TaskbarListHandler.cpp new file mode 100644 index 0000000..421a917 --- /dev/null +++ b/litestep/TaskbarListHandler.cpp @@ -0,0 +1,323 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2013 LiteStep Development 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 "../utility/common.h" +#include "../utility/debug.hpp" +#include "../utility/shellhlp.h" +#include "TaskbarListHandler.h" + + +// +// TaskbarListHandler +// +TaskbarListHandler::TaskbarListHandler() : + m_hWndTaskband(nullptr), + m_aWndClass(0), + m_hLiteStep(nullptr), + m_hInstance(nullptr), + WM_ShellHook(0), + m_dwLiteStepProc(0) +{ +} + + +// +// Start +// +HRESULT TaskbarListHandler::Start(HWND hWndTray) { + HRESULT hr = E_FAIL; + + m_hLiteStep = GetLitestepWnd(); + GetWindowThreadProcessId(m_hLiteStep, &m_dwLiteStepProc); + m_hInstance = GetModuleHandle(NULL); + + WNDCLASSEX wndClass; + ZeroMemory(&wndClass, sizeof(WNDCLASSEX)); + wndClass.cbSize = sizeof(WNDCLASSEX); + wndClass.cbWndExtra = sizeof(TaskbarListHandler*); + wndClass.lpszClassName = _T("taskbandHWNDClass"); + wndClass.lpfnWndProc = &TaskbarListHandler::WindowProcedureInit; + wndClass.hInstance = m_hInstance; + wndClass.style = CS_NOCLOSE; + + m_aWndClass = RegisterClassEx(&wndClass); + if (m_aWndClass == 0) + { + hr = HrGetLastError(); + } + else + { + m_hWndTaskband = CreateWindowEx(WS_EX_TOOLWINDOW, (LPCTSTR)m_aWndClass, _T("taskbandHWND"), WS_CHILD, 0, 0, 100, 100, hWndTray, nullptr, m_hInstance, this); + if (m_hWndTaskband == nullptr) + { + hr = HrGetLastError(); + } + else + { + WM_ShellHook = RegisterWindowMessage(_T("SHELLHOOK")); + SetProp(hWndTray, _T("TaskbandHWND"), m_hWndTaskband); + hr = S_OK; + } + } + + return hr; +} + + +// +// Stop +// +HRESULT TaskbarListHandler::Stop() { + if (m_hWndTaskband != nullptr) { + DestroyWindow(m_hWndTaskband); + } + + if (m_aWndClass != 0) { + UnregisterClass((LPCTSTR)m_aWndClass, m_hInstance); + } + + return S_OK; +} + + +// +// HandleMessage +// +LRESULT WINAPI TaskbarListHandler::HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + DbgTraceWindowMessage("ITaskbarList", uMsg, wParam, lParam); + switch (uMsg) + { + // Sent by ITaskbarList::ActivateTab and ITaskbarList::SetActiveAlt + // ActivateTab will send WM_ShellHook(4, hwnd) immediately after this message. + case WM_USER + 50: + { + // wParam = 0, lParam = hWnd + SendMessage(m_hLiteStep, LM_TASK_MARKASACTIVE, lParam, 0); + } + return 0; + + // Sent by ITaskbarList2::MarkFullscreenWindow + case WM_USER + 60: + { + // wParam = 1 to mark as fullscreen, 0 to remove marking + // lParam = hWnd + + // TODO::This should be sent to the fullscreen monitor + } + return 0; + + // Sent by ITaskbarList3::SetProgressValue + case WM_USER + 64: + { + // wParam = hwnd + // lParam = progress, 0 = 0%, 0xFFFE = 100% + SendMessage(m_hLiteStep, LM_TASK_SETPROGRESSVALUE, wParam, lParam); + } + return 0; + + // Sent by ITaskbarList3::SetProgressState + case WM_USER + 65: + { + // wParam = hwnd + // lParam = tbpFlags + SendMessage(m_hLiteStep, LM_TASK_SETPROGRESSSTATE, wParam, lParam); + } + return 0; + + // Sent by ITaskbarList3::RegisterTab + case WM_USER + 67: + { + // wParam = hwndTab + // lParam = hwndMDI + SendMessage(m_hLiteStep, LM_TASK_REGISTERTAB, wParam, lParam); + } + return 0; + + // Sent by ITaskbarList3::UnregisterTab + case WM_USER + 68: + { + // wParam = hwndTab + // lParam = 0 + SendMessage(m_hLiteStep, LM_TASK_UNREGISTERTAB, wParam, 0); + } + return 0; + + // Sent by ITaskbarList3::SetTabOrder + case WM_USER + 71: + { + // wParam = hwndTab + // lParam = hwndInsertBefore + SendMessage(m_hLiteStep, LM_TASK_SETTABORDER, wParam, lParam); + } + return 0; + + // Sent by ITaskbarList3::SetTabActive + case WM_USER + 72: + { + // wParam = hwndTab + // lParam = 0 ??? + SendMessage(m_hLiteStep, LM_TASK_SETACTIVETAB, wParam, lParam); + } + return 0; + + // Mysterious message, sent by control panel windows + case WM_USER + 75: + { + // wParam = hwnd of the control panel + // lParam = 0 ? + + } + return 0; + + // Sent by ITaskbarList3::ThumbBarAddButtons + case WM_USER + 76: + { + // wParam = hwnd + // lParam = SHSharedAlloc(cButtons, pButton) (first 4 bytes is cButtons) + LPUINT pData = (LPUINT)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + THUMBBUTTONLIST thumbList; + thumbList.cButtons = pData[0]; + thumbList.pButton = (THUMBBUTTON*)&pData[1]; + SendMessage(m_hLiteStep, LM_TASK_THUMBBARADDBUTTONS, wParam, (LPARAM)&thumbList); + SHUnlockShared(pData); + } + return 0; + + // Sent by ITaskbarList3::ThumbBarUpdateButtons + case WM_USER + 77: + { + // wParam = hwnd + // lParam = SHSharedAlloc(cButtons, pButton) (first 4 bytes is cButtons) + LPUINT pData = (LPUINT)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + THUMBBUTTONLIST thumbList; + thumbList.cButtons = pData[0]; + thumbList.pButton = (THUMBBUTTON*)&pData[1]; + SendMessage(m_hLiteStep, LM_TASK_THUMBBARUPDATEBUTTONS, wParam, (LPARAM)&thumbList); + SHUnlockShared(pData); + } + return 0; + + // Sent by ITaskbarList3::ThumbBarSetImageList + case WM_USER + 78: + { + // wParam = hwnd + // lParam = SHSharedAlloc(himl) + HIMAGELIST hImageList = (HIMAGELIST)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + SendMessage(m_hLiteStep, LM_TASK_THUMBBARSETIMAGELIST, wParam, (LPARAM)hImageList); + if (hImageList) { + SHUnlockShared(hImageList); + } + } + return 0; + + // Sent by ITaskbarList3::SetOverlayIcon + case WM_USER + 79: + { + // wParam = hwnd + // lParam = hicon + SendMessage(m_hLiteStep, LM_TASK_SETOVERLAYICON, wParam, lParam); + } + return 0; + + // Sent by ITaskbarList3::SetThumbnailTooltip + case WM_USER + 80: + { + // wParam = hwnd + // lParam = SHSharedAlloc(pszTip) + LPWSTR pwzTip = (LPWSTR)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + SendMessage(m_hLiteStep, LM_TASK_SETTHUMBNAILTOOLTIP, wParam, (LPARAM)pwzTip); + if (pwzTip) { + SHUnlockShared(pwzTip); + } + } + return 0; + + // Sent by ITaskbarList3::SetThumbnailClip + case WM_USER + 81: + { + // wParam = hwnd + // lParam = SHSharedAlloc(prcClip) + LPRECT prcClip = (LPRECT)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + SendMessage(m_hLiteStep, LM_TASK_SETTHUMBNAILCLIP, wParam, (LPARAM)prcClip); + if (prcClip) { + SHUnlockShared(prcClip); + } + } + return 0; + + // Sent by ITaskbarList3::SetOverlayIcon + case WM_USER + 85: + { + // wParam = hwnd + // lParam = SHSharedAlloc(pszDescription) + LPWSTR pwzDescription = (LPWSTR)SHLockShared((HANDLE)lParam, m_dwLiteStepProc); + SendMessage(m_hLiteStep, LM_TASK_SETOVERLAYICONDESC, wParam, (LPARAM)pwzDescription); + if (pwzDescription) { + SHUnlockShared(pwzDescription); + } + } + return 0; + + // Sent by ITaskbarList4::SetTabProperties + case WM_USER + 87: + { + // wParam = hwndTab + // lParam = stpFlags + SendMessage(m_hLiteStep, LM_TASK_SETTABPROPERTIES, wParam, lParam); + } + return 0; + + default: + { + // AddTab, DeleteTab, and ActivateTab will send WM_ShellHook + // TODO::We should consider distinguishing between these and actual WM_SHELLHOOK messages + // we may wish to remember that a certain window has been "marked" as deleted, so that we + // don't accidentally recreate it (when activated, or on recycles). + if (uMsg == WM_ShellHook) + { + return SendMessage(m_hLiteStep, uMsg, wParam, lParam); + } + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + +// +// WindowProcedure +// +LRESULT WINAPI TaskbarListHandler::WindowProcedure(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { + return ((TaskbarListHandler *)GetWindowLongPtr(window, 0))->HandleMessage(window, msg, wParam, lParam); +} + + +// +// WindowProcedureInit +// +LRESULT WINAPI TaskbarListHandler::WindowProcedureInit(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { + if (msg == WM_CREATE) { + SetWindowLongPtr(window, 0, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams); + SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)&TaskbarListHandler::WindowProcedure); + return WindowProcedure(window, msg, wParam, lParam); + } + return DefWindowProc(window, msg, wParam, lParam); +} diff --git a/litestep/TaskbarListHandler.h b/litestep/TaskbarListHandler.h new file mode 100644 index 0000000..fc86c6f --- /dev/null +++ b/litestep/TaskbarListHandler.h @@ -0,0 +1,47 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(TASKBARLISTHANDLER_H) +#define TASKBARLISTHANDLER_H + +class TaskbarListHandler { +public: + explicit TaskbarListHandler(); + + HRESULT Start(HWND hWndTray); + HRESULT Stop(); + +private: + HWND m_hWndTaskband; + ATOM m_aWndClass; + + HWND m_hLiteStep; + DWORD m_dwLiteStepProc; + HINSTANCE m_hInstance; + UINT WM_ShellHook; + + + LRESULT WINAPI HandleMessage(HWND window, UINT msg, WPARAM wParam, LPARAM lParam); + static LRESULT WINAPI WindowProcedure(HWND window, UINT msg, WPARAM wParam, LPARAM lParam); + static LRESULT WINAPI WindowProcedureInit(HWND window, UINT msg, WPARAM wParam, LPARAM lParam); +}; + +#endif // TASKBARLISTHANDLER_H diff --git a/litestep/TrayNotifyIcon.cpp b/litestep/TrayNotifyIcon.cpp index 5c4b50a..713bc5c 100644 --- a/litestep/TrayNotifyIcon.cpp +++ b/litestep/TrayNotifyIcon.cpp @@ -260,15 +260,10 @@ void NotifyIcon::copy_tip(PCNID_XX pnidSource) case NID_5W_SIZE: { LPCWSTR pwzSrc = ((NID_5W*)(pnidSource))->szTip; + + HRESULT hr = StringCchCopy(m_szTip, _countof(m_szTip), pwzSrc); - WCHAR szTemp[128]; - memcpy(szTemp, pwzSrc, sizeof(WCHAR)*128); - szTemp[127] = 0; - - int nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - m_szTip, TRAY_MAX_TIP_LENGTH, NULL, NULL); - - if (!nReturn) + if (FAILED(hr)) { m_szTip[0] = 0; } @@ -279,14 +274,9 @@ void NotifyIcon::copy_tip(PCNID_XX pnidSource) { LPCWSTR pwzSrc = ((NID_4W*)(pnidSource))->szTip; - WCHAR szTemp[64]; - memcpy(szTemp, pwzSrc, sizeof(WCHAR)*64); - szTemp[63] = 0; + HRESULT hr = StringCchCopy(m_szTip, _countof(m_szTip), pwzSrc); - int nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - m_szTip, TRAY_MAX_TIP_LENGTH, NULL, NULL); - - if (!nReturn) + if (FAILED(hr)) { m_szTip[0] = 0; } @@ -297,10 +287,11 @@ void NotifyIcon::copy_tip(PCNID_XX pnidSource) case NID_5A_SIZE: { LPCSTR pwzSrc = ((NID_5A*)(pnidSource))->szTip; + + int nReturn = MultiByteToWideChar(CP_ACP, 0, + pwzSrc, -1, m_szTip, _countof(m_szTip)); - HRESULT hr = StringCchCopy(m_szTip, 128, pwzSrc); - - if (FAILED(hr)) + if (nReturn == 0) { m_szTip[0] = 0; } @@ -311,9 +302,10 @@ void NotifyIcon::copy_tip(PCNID_XX pnidSource) { LPCSTR pwzSrc = ((NID_4A*)(pnidSource))->szTip; - HRESULT hr = StringCchCopy(m_szTip, 64, pwzSrc); - - if (FAILED(hr)) + int nReturn = MultiByteToWideChar(CP_ACP, 0, + pwzSrc, -1, m_szTip, _countof(m_szTip)); + + if (nReturn == 0) { m_szTip[0] = 0; } diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index eb111f8..2c27a79 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -35,8 +35,63 @@ // NOTE: Currently, the dwState/Mask members are never passed on to the // systray modules. dwState/Mask are handled internally to this tray service. // -typedef struct +typedef struct LSNOTIFYICONDATA +{ + DWORD cbSize; /* arbitrary & volatile */ + HWND hWnd; /* persistent & non volatile */ + UINT uID; /* persistent & non volatile */ + UINT uFlags; /* persistent & volatile */ + UINT uCallbackMessage; /* persistent & volatile */ + HICON hIcon; /* persistent & volatile */ + WCHAR szTip[TRAY_MAX_TIP_LENGTH]; /* persistent & volatile */ + + // new in 2K: + DWORD dwState; /* persistent & volatile */ + DWORD dwStateMask; /* arbitrary & volatile */ + WCHAR szInfo[TRAY_MAX_INFO_LENGTH]; /* arbitrary & volatile */ + union + { + UINT uTimeout; /* arbitrary & volatile */ + UINT uVersion; /* arbitrary & volatile */ + } DUMMYUNIONNAME; + WCHAR szInfoTitle[TRAY_MAX_INFOTITLE_LENGTH];/* arbitrary & volatile */ + DWORD dwInfoFlags; /* arbitrary & volatile */ + + // new in XP: + GUID guidItem; /* persistent & non volatile */ + + // new in Vista + HICON hBalloonIcon; /* arbitrary & volatile */ + /**/ +} *PLSNOTIFYICONDATA; +typedef const LSNOTIFYICONDATA * PCLSNOTIFYICONDATA; + +// +// Sent to legacy modules +// +typedef struct LSNOTIFYICONDATAA { + LSNOTIFYICONDATAA(PCLSNOTIFYICONDATA nid) { + this->cbSize = sizeof(this); + this->hWnd = nid->hWnd; + this->uID = nid->uID; + this->uFlags = nid->uFlags; + this->uCallbackMessage = nid->uCallbackMessage; + this->hIcon = nid->hIcon; + WideCharToMultiByte(CP_ACP, 0, nid->szTip, _countof(nid->szTip), + this->szTip, sizeof(this->szTip), "?", nullptr); + this->dwState = nid->dwState; + this->dwStateMask = nid->dwStateMask; + WideCharToMultiByte(CP_ACP, 0, nid->szInfo, _countof(nid->szInfo), + this->szInfo, sizeof(this->szInfo), "?", nullptr); + this->uVersion = nid->uVersion; + WideCharToMultiByte(CP_ACP, 0, nid->szInfoTitle, _countof(nid->szInfoTitle), + this->szInfoTitle, sizeof(this->szInfoTitle), "?", nullptr); + this->dwInfoFlags = nid->dwInfoFlags; + this->guidItem = nid->guidItem; + this->hBalloonIcon = nid->hBalloonIcon; + } + DWORD cbSize; /* arbitrary & volatile */ HWND hWnd; /* persistent & non volatile */ UINT uID; /* persistent & non volatile */ @@ -63,8 +118,7 @@ typedef struct // new in Vista HICON hBalloonIcon; /* arbitrary & volatile */ /**/ -} LSNOTIFYICONDATA, *PLSNOTIFYICONDATA; -typedef const LSNOTIFYICONDATA * PCLSNOTIFYICONDATA; +} *PLSNOTIFYICONDATAA; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -336,7 +390,7 @@ class NotifyIcon UINT m_uFlags; /* persistent & volatile */ UINT m_uCallbackMessage; /* persistent & volatile */ HICON m_hIcon; /* persistent & volatile */ - CHAR m_szTip[TRAY_MAX_TIP_LENGTH]; /* persistent & volatile */ + WCHAR m_szTip[TRAY_MAX_TIP_LENGTH]; /* persistent & volatile */ DWORD m_dwState; /* persistent & volatile */ HICON m_hBalloonIcon; /* persistent & volatile */ diff --git a/litestep/TrayService.cpp b/litestep/TrayService.cpp index 7ce77ef..50221fe 100644 --- a/litestep/TrayService.cpp +++ b/litestep/TrayService.cpp @@ -116,6 +116,9 @@ HRESULT TrayService::Start() // tell apps to reregister their icons SendNotifyMessage(HWND_BROADCAST, RegisterWindowMessage(_T("TaskbarCreated")), 0, 0); + + // tell ITaskbarList which window to communicate with + m_taskbarListHandler.Start(m_hTrayWnd); if (IsVistaOrAbove()) { @@ -144,6 +147,7 @@ HRESULT TrayService::Stop() HRESULT hr = S_OK; unloadShellServiceObjects(); + m_taskbarListHandler.Stop(); destroyWindows(); while (!m_siVector.empty()) @@ -170,6 +174,16 @@ HRESULT TrayService::Stop() } +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// +// Recycle() +// +HRESULT TrayService::Recycle() +{ + return S_OK; +} + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- // // createWindows @@ -282,10 +296,10 @@ void TrayService::destroyWindows() HRESULT TrayService::loadShellServiceObject(REFCLSID rclsid) { #if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; + WCHAR szBuffer[MAX_PATH] = { 0 }; CLSIDToString(rclsid, szBuffer, COUNTOF(szBuffer)); - TRACE("loadShellServiceObject(\"%s\")", szBuffer); + TRACE("loadShellServiceObject(\"%ls\")", szBuffer); #endif // The SSO might have a custom manifest. @@ -544,7 +558,7 @@ LRESULT CALLBACK TrayService::WindowTrayProc(HWND hWnd, UINT uMsg, case WM_SETTINGCHANGE: { - TRACE("WM_SETTINGCHANGE(%.4X, \"%s\")", + TRACE("WM_SETTINGCHANGE(%.4X, \"%ls\")", wParam, (LPCTSTR)lParam); if (SPI_SETWORKAREA == wParam) @@ -624,20 +638,20 @@ LRESULT CALLBACK TrayService::WindowNotifyProc(HWND hWnd, UINT uMsg, WPARAM wPar HRESULT TrayService::HandleLoadInProc(REFCLSID clsid, DWORD dwMessage) { #if defined(TRACE_ENABLED) - CHAR szBuffer[MAX_PATH] = { 0 }; + WCHAR szBuffer[MAX_PATH] = { 0 }; CLSIDToString(clsid, szBuffer, COUNTOF(szBuffer)); if (dwMessage == 1) { - TRACE("SHLoadInProc(\"%s\")", szBuffer); + TRACE("SHLoadInProc(\"%ls\")", szBuffer); } else if (dwMessage == 2) { - TRACE("SHEnableServiceObject(\"%s\", FALSE)", szBuffer); + TRACE("SHEnableServiceObject(\"%ls\", FALSE)", szBuffer); } else if (dwMessage == 3) { - TRACE("SHEnableServiceObject(\"%s\", TRUE)", szBuffer); + TRACE("SHEnableServiceObject(\"%ls\", TRUE)", szBuffer); } else { @@ -1887,8 +1901,10 @@ BOOL TrayService::HandleNotification(PSHELLTRAYDATA pstd) // bool TrayService::notify(DWORD dwMessage, PCLSNOTIFYICONDATA pclsnid) const { - return 0 != SendMessage(m_hLiteStep, LM_SYSTRAY, - dwMessage, (LPARAM)pclsnid); + LSNOTIFYICONDATAA lsnidA(pclsnid); + return 0 != (SendMessage(m_hLiteStep, LM_SYSTRAYW, + dwMessage, (LPARAM)pclsnid) | SendMessage(m_hLiteStep, LM_SYSTRAYA, + dwMessage, (LPARAM)&lsnidA)); } @@ -1972,25 +1988,16 @@ bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) cons { NID_5W* pnid = (NID_5W*)&nid; - int nReturn; - WCHAR szTemp[256]; - - memcpy(szTemp, pnid->szInfo, sizeof(WCHAR)*256); - szTemp[255] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfo, TRAY_MAX_INFO_LENGTH, NULL, NULL); - - if (!nReturn) + HRESULT hr; + + hr = StringCchCopy(lsnid.szInfo, _countof(lsnid.szInfo), pnid->szInfo); + if (FAILED(hr)) { lsnid.szInfo[0] = 0; } - memcpy(szTemp, pnid->szInfoTitle, sizeof(WCHAR)*64); - szTemp[63] = 0; - nReturn = WideCharToMultiByte(CP_ACP, 0, szTemp, -1, - lsnid.szInfoTitle, TRAY_MAX_INFOTITLE_LENGTH, NULL, NULL); - - if (!nReturn) + hr = StringCchCopy(lsnid.szInfoTitle, _countof(lsnid.szInfoTitle), pnid->szInfoTitle); + if (FAILED(hr)) { lsnid.szInfoTitle[0] = 0; } @@ -2005,20 +2012,18 @@ bool TrayService::extendNIDCopy(LSNOTIFYICONDATA& lsnid, const NID_XX& nid) cons { NID_5A* pnid = (NID_5A*)&nid; - HRESULT hr; - - hr = StringCchCopy(lsnid.szInfo, - TRAY_MAX_INFO_LENGTH, pnid->szInfo); + int nResult = MultiByteToWideChar(CP_ACP, 0, pnid->szInfo, + sizeof(pnid->szInfo), lsnid.szInfo, _countof(lsnid.szInfo)); - if (FAILED(hr)) + if (nResult == 0) { lsnid.szInfo[0] = 0; } - hr = StringCchCopy(lsnid.szInfoTitle, - TRAY_MAX_INFOTITLE_LENGTH, pnid->szInfoTitle); + nResult = MultiByteToWideChar(CP_ACP, 0, pnid->szInfoTitle, + sizeof(pnid->szInfoTitle), lsnid.szInfoTitle, _countof(lsnid.szInfoTitle)); - if (FAILED(hr)) + if (nResult == 0) { lsnid.szInfoTitle[0] = 0; } diff --git a/litestep/TrayService.h b/litestep/TrayService.h index 9ab91bf..32ce74c 100644 --- a/litestep/TrayService.h +++ b/litestep/TrayService.h @@ -24,6 +24,7 @@ #include "TrayNotifyIcon.h" #include "TrayAppBar.h" +#include "TaskbarListHandler.h" #include "../utility/common.h" #include "../utility/IService.h" #include @@ -122,8 +123,9 @@ class TrayService : public IService // // IService methods // - virtual HRESULT Start(); - virtual HRESULT Stop(); + virtual HRESULT Start() override; + virtual HRESULT Stop() override; + virtual HRESULT Recycle() override; // resend all icon data HWND SendSystemTray(); @@ -239,6 +241,7 @@ class TrayService : public IService SsoVector m_ssoVector; IconVector m_siVector; BarVector m_abVector; + TaskbarListHandler m_taskbarListHandler; }; #endif // TRAYSERVICE_H diff --git a/litestep/WinMain.cpp b/litestep/WinMain.cpp index aea5db0..63f56b4 100644 --- a/litestep/WinMain.cpp +++ b/litestep/WinMain.cpp @@ -62,22 +62,22 @@ WORD ParseCommandLine(LPCTSTR pszCommandLine, LPTSTR pszFile, DWORD cchFile) // By default, run LiteStep and startup apps WORD wStartFlags = LSF_RUN_LITESTEP | LSF_RUN_STARTUPAPPS; - char szToken[MAX_LINE_LENGTH] = { 0 }; - LPCSTR pszNextToken = pszCommandLine; + TCHAR szToken[MAX_LINE_LENGTH] = { 0 }; + LPCTSTR pszNextToken = pszCommandLine; - while (GetToken(pszNextToken, szToken, &pszNextToken, FALSE)) + while (GetTokenW(pszNextToken, szToken, &pszNextToken, FALSE)) { if (szToken[0] == '-') { - if (!_stricmp(szToken, "-nostartup")) + if (!_tcsicmp(szToken, _T("-nostartup"))) { wStartFlags &= ~LSF_RUN_STARTUPAPPS; } - else if (!_stricmp(szToken, "-startup")) + else if (!_tcsicmp(szToken, _T("-startup"))) { wStartFlags |= LSF_FORCE_STARTUPAPPS; } - else if (!_stricmp(szToken, "-explorer")) + else if (!_tcsicmp(szToken, _T("-explorer"))) { wStartFlags &= ~LSF_RUN_LITESTEP; wStartFlags |= LSF_RUN_EXPLORER; @@ -120,17 +120,17 @@ bool SendCommandLineBang(LPCTSTR pszCommand, LPCTSTR pszArgs) bangCommand.hWnd = NULL; HRESULT hr = StringCchCopy( - bangCommand.szCommand, MAX_BANGCOMMAND, pszCommand); + bangCommand.wzCommand, MAX_BANGCOMMAND, pszCommand); if (SUCCEEDED(hr)) { if (pszArgs) { - hr = StringCchCopy(bangCommand.szArgs, MAX_BANGARGS, pszArgs); + hr = StringCchCopy(bangCommand.wzArgs, MAX_BANGARGS, pszArgs); } else { - bangCommand.szArgs[0] = '\0'; + bangCommand.wzArgs[0] = '\0'; } } @@ -143,7 +143,7 @@ bool SendCommandLineBang(LPCTSTR pszCommand, LPCTSTR pszArgs) COPYDATASTRUCT cds = { 0 }; cds.cbData = sizeof(LMBANGCOMMAND); - cds.dwData = LM_BANGCOMMAND; + cds.dwData = LM_BANGCOMMANDW; cds.lpData = &bangCommand; if (SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cds)) @@ -276,60 +276,70 @@ int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE, LPTSTR lpCmdLine, int) wStartFlags |= LSF_RUN_EXPLORER; wStartFlags &= ~LSF_RUN_STARTUPAPPS; } - - if (wStartFlags & LSF_RUN_EXPLORER) - { - // - // Mode 2: (Try to) start Explorer - // - if (StartExplorerShell(EXPLORER_WAIT_TIMEOUT)) - { - // Explorer started as shell, no need try LiteStep as well - wStartFlags &= ~LSF_RUN_LITESTEP; - } - else - { - wStartFlags &= ~LSF_RUN_EXPLORER; - } - } - - if (wStartFlags & LSF_RUN_LITESTEP) + + do { - HANDLE hMutex = NULL; - - if (IsOtherInstanceRunning(&hMutex)) + if (wStartFlags & LSF_RUN_EXPLORER) { // - // Mode 3a: Other LiteStep instance already running + // Mode 2: (Try to) start Explorer // - RESOURCE_STR(hInst, IDS_LITESTEP_ERROR1, - "A previous instance of LiteStep was detected.\n" - "Are you sure you want to continue?"); - - // Can show a MessageBox here since the other instance - // should have closed the welcome screen already - INT idConfirm = RESOURCE_MSGBOX_F( - "LiteStep", MB_ICONINFORMATION | MB_YESNO | MB_DEFBUTTON2); - - if (idConfirm == IDNO) + if (StartExplorerShell(EXPLORER_WAIT_TIMEOUT)) { + // Explorer started as shell, no need try LiteStep as well wStartFlags &= ~LSF_RUN_LITESTEP; } + else + { + wStartFlags &= ~LSF_RUN_EXPLORER; + } } - + if (wStartFlags & LSF_RUN_LITESTEP) { - // - // Mode 3b: Start the shell! - // - nReturn = StartLitestep(hInst, wStartFlags, szAltConfigFile); - } + HANDLE hMutex = NULL; - if (hMutex) - { - CloseHandle(hMutex); + if (IsOtherInstanceRunning(&hMutex)) + { + // + // Mode 3a: Other LiteStep instance already running + // + RESOURCE_STR(hInst, IDS_LITESTEP_ERROR1, + L"A previous instance of LiteStep was detected.\n" + L"Are you sure you want to continue?"); + + // Can show a MessageBox here since the other instance + // should have closed the welcome screen already + INT idConfirm = RESOURCE_MSGBOX_F( + L"LiteStep", MB_ICONINFORMATION | MB_YESNO | MB_DEFBUTTON2); + + if (idConfirm == IDNO) + { + wStartFlags &= ~LSF_RUN_LITESTEP; + } + } + + if (wStartFlags & LSF_RUN_LITESTEP) + { + // + // Mode 3b: Start the shell! + // + nReturn = StartLitestep(hInst, wStartFlags, szAltConfigFile); + } + + if (hMutex) + { + CloseHandle(hMutex); + } + + if (nReturn == LRV_EXPLORER_START) + { + // User wants Explorer as shell anyway + wStartFlags |= LSF_RUN_EXPLORER; + } } - } + + } while (nReturn == LRV_EXPLORER_START && (wStartFlags & LSF_RUN_LITESTEP)); } return nReturn; diff --git a/litestep/buildoptions.h b/litestep/buildoptions.h index 4597474..a4b17f0 100644 --- a/litestep/buildoptions.h +++ b/litestep/buildoptions.h @@ -51,13 +51,17 @@ // Adds support for IncludeFolder Directive (all .rc files in specified folder // will be included - order not guaranteed). This was added by the LDE(X) team. // Thanks Phil! -// 0.25.0 default: DISABLED -//#define LS_CUSTOM_INCLUDEFOLDER +// 0.25.0 default: ENABLED +#define LS_CUSTOM_INCLUDEFOLDER // Makes lsapi use picoPNG instead of zlib+libpng // 0.25.0 default: ENABLED #define LS_USE_PICOPNG +// Makes LiteStep run Explorer's window procedure when set as shell. +// 0.25.0 default: ENABLED +//#define LS_USE_EXPLORER_SERVICE + // Makes LCReadNextConfig conform to pre 0.24.7 API // 0.25.0 default: DISABLED //#define LS_COMPAT_LCREADNEXTCONFIG diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index e822eb9..12c7dcb 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -27,6 +27,7 @@ #include "RecoveryMenu.h" #include "TrayService.h" #include "ExplorerService.h" +#include "FullscreenMonitor.h" // Managers #include "MessageManager.h" @@ -150,7 +151,7 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) if (FAILED(GetAppPath(szAppPath, COUNTOF(szAppPath)))) { // something really crappy is going on. - return -1; + return LRV_NO_APP_PATH; } if (wStartFlags & LSF_ALTERNATE_CONFIG) @@ -159,7 +160,7 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) } else { - PathCombine(szRcPath, szAppPath, "step.rc"); + PathCombine(szRcPath, szAppPath, L"step.rc"); } if (IsVistaOrAbove()) @@ -193,12 +194,12 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) { RESOURCE_STREX( hInst, IDS_LITESTEP_ERROR2, resourceTextBuffer, MAX_LINE_LENGTH, - "Unable to find the file \"%s\".\n" - "Please verify the location of the file, and try again.", szRcPath); + L"Unable to find the file \"%ls\".\n" + L"Please verify the location of the file, and try again.", szRcPath); - RESOURCE_MSGBOX_F("LiteStep", MB_ICONERROR); + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); - return 2; + return LRV_NO_STEP; } // Initialize the LSAPI. Note: The LSAPI controls the bang and settings @@ -206,16 +207,16 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) if (!LSAPIInitialize(szAppPath, szRcPath)) { RESOURCE_MSGBOX(hInst, IDS_LSAPI_INIT_ERROR, - "Failed to initialize the LiteStep API.", "LiteStep"); + L"Failed to initialize the LiteStep API.", L"LiteStep"); - return 3; + return LRV_LSAPI_FAIL; } // All child processes get this variable VERIFY(SetEnvironmentVariable(_T("LitestepDir"), szAppPath)); int nReturn = 0; - + CLiteStep liteStep; HRESULT hr = liteStep.Start(hInst, wStartFlags); @@ -232,11 +233,11 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) { RESOURCE_STREX(hInst, IDS_LITESTEP_INIT_ERROR, resourceTextBuffer, MAX_LINE_LENGTH, - "Failed to initialize LiteStep.\n" - "Please contact the LiteStep Development Team.\n\n" - "Error code: 0x%.8X", hr); + L"Failed to initialize LiteStep.\n" + L"Please contact the LiteStep Development Team.\n\n" + L"Error code: 0x%.8X", hr); - RESOURCE_MSGBOX_F("LiteStep", MB_ICONERROR); + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); } if (FAILED(hr)) @@ -252,20 +253,19 @@ int StartLitestep(HINSTANCE hInst, WORD wStartFlags, LPCTSTR pszAltConfigFile) // CLiteStep() // CLiteStep::CLiteStep() -: m_pRecoveryMenu(NULL), - m_pRegisterShellHook(NULL), - m_hWtsDll(NULL) +: m_pRecoveryMenu(nullptr), + m_pRegisterShellHook(nullptr), + m_hWtsDll(nullptr) { - m_hInstance = NULL; - m_bAutoHideModules = false; - m_hFullScreenMonitor = NULL; - m_hMainWindow = NULL; + m_hInstance = nullptr; + m_hMainWindow = nullptr; WM_ShellHook = 0; - m_pModuleManager = NULL; - m_pDataStoreManager = NULL; - m_pMessageManager = NULL; + m_pModuleManager = nullptr; + m_pDataStoreManager = nullptr; + m_pMessageManager = nullptr; m_bSignalExit = false; - m_pTrayService = NULL; + m_pTrayService = nullptr; + m_pFullscreenMonitor = nullptr; m_BlockRecycle = 0; } @@ -312,41 +312,39 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) // Order of precedence: 1) shift key, 2) command line flags, 3) step.rc if ((GetAsyncKeyState(VK_SHIFT) & 0x8000) || - (GetRCBool("LSNoStartup", TRUE) && + (GetRCBoolW(L"LSNoStartup", TRUE) && !(wStartFlags & LSF_FORCE_STARTUPAPPS))) { wStartFlags &= ~LSF_RUN_STARTUPAPPS; } - m_bAutoHideModules = GetRCBool("LSAutoHideModules", TRUE) ? true : false; - bool bUnderExplorer = false; // // Check for another shell // - if (FindWindow("Shell_TrayWnd", NULL) != NULL) + if (FindWindow(L"Shell_TrayWnd", NULL) != NULL) { - if (GetRCBool("LSCloseExplorer", TRUE)) + if (GetRCBoolW(L"LSCloseExplorer", TRUE)) { - HWND hTrayWindow = FindWindow("Shell_TrayWnd", NULL); + HWND hTrayWindow = FindWindow(L"Shell_TrayWnd", NULL); // Determine the name of the current Shell DWORD dwProcessID; GetWindowThreadProcessId(hTrayWindow, &dwProcessID); HANDLE hShellProc = OpenProcess( - PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, + PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, dwProcessID ); if (hShellProc != NULL) { - char szProcessPath[MAX_PATH]; - GetModuleFileNameEx(hShellProc, NULL, szProcessPath, _countof(szProcessPath)); - LPCSTR pszPathName = PathFindFileName(szProcessPath); + TCHAR szProcessPath[MAX_PATH]; + LSGetProcessImageFileName(hShellProc, szProcessPath, _countof(szProcessPath)); + LPCTSTR pszPathName = PathFindFileName(szProcessPath); - if (_stricmp(pszPathName, "explorer.exe") == 0) + if (_tcsicmp(pszPathName, _T("explorer.exe")) == 0) { if (IsVistaOrAbove()) { @@ -354,7 +352,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) } else if (IsOS(OS_XPORGREATER)) { - HWND hProgman = FindWindow("Progman", NULL); + HWND hProgman = FindWindow(_T("Progman"), NULL); PostMessage(hProgman, WM_QUIT, 0, TRUE); PostMessage(hTrayWindow, WM_QUIT, 0, 0); } @@ -364,7 +362,14 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) } // Wait for the process to exit - WaitForSingleObject(hShellProc, 3000); // Wait for at most 3 seconds. + if (WaitForSingleObject(hShellProc, 3000) != WAIT_OBJECT_0) // Wait for at most 3 seconds. + { + // At this point, forcibly terminate the proc + TerminateProcess(hShellProc, 0); + + // Wait another 3 seconds, max + WaitForSingleObject(hShellProc, 3000); + } } CloseHandle(hShellProc); @@ -372,25 +377,25 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) } } - if (FindWindow("Shell_TrayWnd", NULL) != NULL) + if (FindWindow(L"Shell_TrayWnd", NULL) != NULL) { - if (GetRCBool("LSNoShellWarning", FALSE)) + if (GetRCBoolW(L"LSNoShellWarning", FALSE)) { RESOURCE_STR(hInstance, IDS_LITESTEP_ERROR3, - "LiteStep is not able to load as the system shell.\n" - "Another shell is already active.\n" - "\n" - "Continuing to load LiteStep will disable specific system\n" - "shell functions of LiteStep and some features will not\n" - "function properly such as icon notifications (systray),\n" - "the desktop and some task managers.\n" - "\n" - "To disable this message, place 'LSNoShellWarning' in\n" - "your step.rc.\n" - "\n" - "Continue to load LiteStep?\n"); + L"LiteStep is not able to load as the system shell.\n" + L"Another shell is already active.\n" + L"\n" + L"Continuing to load LiteStep will disable specific system\n" + L"shell functions of LiteStep and some features will not\n" + L"function properly such as icon notifications (systray),\n" + L"the desktop and some task managers.\n" + L"\n" + L"To disable this message, place 'LSNoShellWarning' in\n" + L"your step.rc.\n" + L"\n" + L"Continue to load LiteStep?\n"); - RESOURCE_TITLE(hInstance, IDS_LITESTEP_TITLE_WARNING, "Warning"); + RESOURCE_TITLE(hInstance, IDS_LITESTEP_TITLE_WARNING, L"Warning"); if (RESOURCE_MSGBOX_F( resourceTitleBuffer, MB_YESNO | MB_ICONEXCLAMATION) == IDNO) @@ -403,7 +408,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) } if (SUCCEEDED(hr)) - { + { hr = CreateMainWindow(); } @@ -412,7 +417,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) // if (SUCCEEDED(hr)) { - hr = _InitServices(GetRCBool("LSSetAsShell", TRUE) && !bUnderExplorer); + hr = _InitServices(!bUnderExplorer && GetRCBoolW(L"LSSetAsShell", TRUE)); if (SUCCEEDED(hr)) { @@ -443,7 +448,7 @@ HRESULT CLiteStep::Start(HINSTANCE hInstance, WORD wStartFlags) if (IsVistaOrAbove() && StartupRunner::IsFirstRunThisSession( _T("LogonSoundHasBeenPlayed"))) { - LSPlaySystemSound(_T("WindowsLogon")); + LSPlaySystemSound(L"WindowsLogon"); } // Undocumented call: Shell Loading Finished @@ -516,7 +521,7 @@ int CLiteStep::Run() } } - TRACE("Left main message loop. Last message: 0x%.4X (%u, %u)", + TRACE("Left main message loop. Last message: 0x%.4X (%p, %p)", message.message, message.wParam, message.lParam); if (message.message == WM_QUIT) @@ -686,7 +691,7 @@ void CLiteStep::_RegisterShellNotifications(HWND hWnd) // // Register for shell hook notifications // - WM_ShellHook = RegisterWindowMessage("SHELLHOOK"); + WM_ShellHook = RegisterWindowMessage(L"SHELLHOOK"); m_pRegisterShellHook = (RSHPROC)GetProcAddress( GetModuleHandle(_T("SHELL32.DLL")), (LPCSTR)((long)0x00B5)); @@ -808,7 +813,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l case LM_SHUTDOWN: case SC_CLOSE: { - ParseBangCommand(hWnd, "!ShutDown", NULL); + ParseBangCommandW(hWnd, L"!ShutDown", NULL); } break; @@ -821,15 +826,6 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } break; - case WM_TIMER: - { - if (LT_RUDEAPP == wParam) - { - KillTimer(hWnd, wParam); - HMONITOR hMonFS = _FullScreenGetMonitor(GetForegroundWindow()); - _FullScreenHandler(hMonFS); - } - } break; case LM_SYSTRAYREADY: @@ -889,7 +885,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l if (m_pMessageManager) { - hr = _EnumRevIDs((LSENUMREVIDSPROC)wParam, lParam); + hr = _EnumRevIDs((LSENUMREVIDSPROCW)wParam, lParam); } return hr; @@ -902,7 +898,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l if (m_pModuleManager) { - hr = m_pModuleManager->EnumModules((LSENUMMODULESPROC)wParam, + hr = m_pModuleManager->EnumModules((LSENUMMODULESPROCW)wParam, lParam); } @@ -916,7 +912,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l if (m_pModuleManager) { - hr = m_pModuleManager->EnumPerformance((LSENUMPERFORMANCEPROC)wParam, + hr = m_pModuleManager->EnumPerformance((LSENUMPERFORMANCEPROCW)wParam, lParam); } @@ -948,6 +944,12 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l PostQuitMessage(0); } break; + + case LR_EXPLORER: + { + PostQuitMessage(4); + } + break; default: // wParam == LR_MSSHUTDOWN { @@ -958,7 +960,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } break; - case LM_RELOADMODULE: + case LM_RELOADMODULEA: { if (m_pModuleManager) { @@ -972,17 +974,42 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l { LPCSTR pszPath = (LPCSTR)wParam; - if (pszPath != NULL) + if (pszPath != nullptr) + { + std::unique_ptr wzPath(WCSFromMBS(pszPath)); + m_pModuleManager->QuitModule(wzPath.get()); + m_pModuleManager->LoadModule(wzPath.get(), (DWORD)lParam); + } + } + } + } + break; + + case LM_RELOADMODULEW: + { + if (m_pModuleManager) + { + if (lParam & LMM_HINSTANCE) + { + // not sure if this feature is needed... if a module + // wants to reload it shouldn't need the core to do that + m_pModuleManager->ReloadModule((HINSTANCE)wParam); + } + else // (lParam & LMM_PATH) + { + LPCWSTR pwzPath = (LPCWSTR)wParam; + + if (pwzPath != nullptr) { - m_pModuleManager->QuitModule(pszPath); - m_pModuleManager->LoadModule(pszPath, (DWORD)lParam); + m_pModuleManager->QuitModule(pwzPath); + m_pModuleManager->LoadModule(pwzPath, (DWORD)lParam); } } } } break; - case LM_UNLOADMODULE: + case LM_UNLOADMODULEA: { if (m_pModuleManager) { @@ -994,39 +1021,82 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l { LPCSTR pszPath = (LPCSTR)wParam; - if (pszPath != NULL) + if (pszPath != nullptr) + { + m_pModuleManager->QuitModule(MBSTOWCS(pszPath)); + } + } + } + } + break; + + case LM_UNLOADMODULEW: + { + if (m_pModuleManager) + { + if (lParam & LMM_HINSTANCE) + { + m_pModuleManager->QuitModule((HINSTANCE)wParam); + } + else // (lParam & LMM_PATH) + { + LPCWSTR pwzPath = (LPCWSTR)wParam; + + if (pwzPath != nullptr) { - m_pModuleManager->QuitModule(pszPath); + m_pModuleManager->QuitModule(pwzPath); } } } } break; - case LM_BANGCOMMAND: + case LM_BANGCOMMANDA: { - PLMBANGCOMMAND plmbc = (PLMBANGCOMMAND)lParam; + PLMBANGCOMMANDA plmbc = (PLMBANGCOMMANDA)lParam; - if (plmbc != NULL) + if (plmbc != nullptr) { - if (plmbc->cbSize == sizeof(LMBANGCOMMAND)) + if (plmbc->cbSize == sizeof(LMBANGCOMMANDA)) { - lReturn = ParseBangCommand(plmbc->hWnd, + lReturn = ParseBangCommandA(plmbc->hWnd, plmbc->szCommand, plmbc->szArgs); } } } break; + case LM_BANGCOMMANDW: + { + PLMBANGCOMMANDW plmbc = (PLMBANGCOMMANDW)lParam; + + if (plmbc != nullptr) + { + if (plmbc->cbSize == sizeof(LMBANGCOMMANDW)) + { + lReturn = ParseBangCommandW(plmbc->hWnd, + plmbc->wzCommand, plmbc->wzArgs); + } + } + } + break; + case WM_COPYDATA: { PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam; switch (pcds->dwData) { - case LM_BANGCOMMAND: + case LM_BANGCOMMANDA: + { + lReturn = SendMessage(hWnd, LM_BANGCOMMANDA, + 0, (LPARAM)pcds->lpData); + } + break; + + case LM_BANGCOMMANDW: { - lReturn = SendMessage(hWnd, LM_BANGCOMMAND, + lReturn = SendMessage(hWnd, LM_BANGCOMMANDW, 0, (LPARAM)pcds->lpData); } break; @@ -1074,7 +1144,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l // Convert to an LM_SHELLHOOK message uMsg = LM_SHELLHOOK + wHookCode; - + if (uMsg == LM_APPCOMMAND) { wParam = NULL; @@ -1093,7 +1163,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l lParam = (LPARAM)wExtraBits; } } - + // WM_APP, LM_XYZ, and registered messages are all >= WM_USER if (uMsg >= WM_USER) { @@ -1105,13 +1175,7 @@ LRESULT CLiteStep::InternalWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l break; } } - - // Handle shell hook messages *after* relaying them to modules. - // A module may show or hide some parts of its UI in response to - // those messages, thus undoing any auto-hide done here. - _HandleShellHooks(uMsg, wParam, lParam); - - lReturn = DefWindowProc (hWnd, uMsg, wParam, lParam); + lReturn = DefWindowProc(hWnd, uMsg, wParam, lParam); } break; } @@ -1128,11 +1192,11 @@ LRESULT CLiteStep::_HandleSessionChange(DWORD dwCode, DWORD /* dwSession */) { if (dwCode == WTS_SESSION_LOCK) { - LSPlaySystemSound(_T("WindowsLogoff")); + LSPlaySystemSound(L"WindowsLogoff"); } else if (dwCode == WTS_SESSION_UNLOCK) { - LSPlaySystemSound(_T("WindowsLogon")); + LSPlaySystemSound(L"WindowsLogon"); } return 0; @@ -1144,20 +1208,20 @@ LRESULT CLiteStep::_HandleSessionChange(DWORD dwCode, DWORD /* dwSession */) // HRESULT CLiteStep::_InitServices(bool bSetAsShell) { - IService* pService = NULL; + IService* pService = nullptr; // // DDE Service // - if (GetRCBool("LSUseSystemDDE", TRUE)) + if (GetRCBoolW(L"LSUseSystemDDE", TRUE)) { // M$ DDE - pService = new DDEStub(); + pService = new (std::nothrow) DDEStub(); } else { // liteman - pService = new DDEService(); + pService = new (std::nothrow) DDEService(); } if (pService) @@ -1168,13 +1232,13 @@ HRESULT CLiteStep::_InitServices(bool bSetAsShell) { return E_OUTOFMEMORY; } - + // // Tray Service // - if (GetRCBool("LSDisableTrayService", FALSE)) + if (GetRCBoolW(L"LSDisableTrayService", FALSE)) { - m_pTrayService = new TrayService(); + m_pTrayService = new (std::nothrow) TrayService(); if (m_pTrayService) { @@ -1187,11 +1251,12 @@ HRESULT CLiteStep::_InitServices(bool bSetAsShell) } // - // Explorer Service + // Explorer service // if (bSetAsShell) { - pService = new ExplorerService(); +#if defined(LS_USE_EXPLORER_SERVICE) + pService = new (std::nothrow) ExplorerService(); if (pService) { @@ -1201,8 +1266,26 @@ HRESULT CLiteStep::_InitServices(bool bSetAsShell) { return E_OUTOFMEMORY; } +#else + _SetShellWindow(m_hMainWindow); +#endif } + // + // FullscreenMonitor service + // + m_pFullscreenMonitor = new (std::nothrow) FullscreenMonitor(); + + if (m_pFullscreenMonitor) + { + m_Services.push_back(m_pFullscreenMonitor); + } + else + { + return E_OUTOFMEMORY; + } + + return S_OK; } @@ -1266,7 +1349,7 @@ HRESULT CLiteStep::_InitManagers() HRESULT CLiteStep::_StartManagers() { HRESULT hr = S_OK; - + // Load modules m_pModuleManager->Start(this); @@ -1289,7 +1372,7 @@ HRESULT CLiteStep::_StopManagers() // Clean up as modules might not have m_pMessageManager->ClearMessages(); - + // Note: // - The DataStore manager is persistent. // - The Message manager can not be "stopped", just cleared. @@ -1337,23 +1420,22 @@ void CLiteStep::_Recycle() { return; } - _StopManagers(); if (GetAsyncKeyState(VK_SHIFT) & 0x8000) { RESOURCE_MSGBOX(m_hInstance, IDS_LITESTEP_ERROR6, - "Recycle has been paused, click OK to continue.", - "LiteStep"); + L"Recycle has been paused, click OK to continue.", + L"LiteStep"); } // Re-initialize the bang and settings manager in LSAPI LSAPIReloadBangs(); LSAPIReloadSettings(); - - /* Read in our locally affected settings */ - m_bAutoHideModules = GetRCBool("LSAutoHideModules", TRUE) ? true : false; - + + // Call service's Recycle function + for_each(m_Services.begin(), m_Services.end(), mem_fun(&IService::Recycle)); + _StartManagers(); } @@ -1361,256 +1443,76 @@ void CLiteStep::_Recycle() // // _EnumRevIDs // -HRESULT CLiteStep::_EnumRevIDs(LSENUMREVIDSPROC pfnCallback, LPARAM lParam) const +HRESULT CLiteStep::_EnumRevIDs(LSENUMREVIDSPROCW pfnCallback, LPARAM lParam) const { HRESULT hr = E_FAIL; - MessageManager::windowSetT setWindows; + MessageManager::windowSetT setWindowsW, setWindowsA; - if (m_pMessageManager->GetWindowsForMessage(LM_GETREVID, setWindows)) + if (m_pMessageManager->GetWindowsForMessage(LM_GETREVIDA, setWindowsA) || + m_pMessageManager->GetWindowsForMessage(LM_GETREVIDW, setWindowsW)) { hr = S_OK; - for (MessageManager::windowSetT::iterator iter = setWindows.begin(); - iter != setWindows.end(); ++iter) + for (MessageManager::windowSetT::iterator iter = setWindowsW.begin(); + iter != setWindowsW.end(); ++iter) { // Using MAX_LINE_LENGTH to be on the safe side. Modules // should assume a length of 64 or so. - char szBuffer[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzBuffer[MAX_LINE_LENGTH] = { 0 }; - if (SendMessage(*iter, LM_GETREVID, 0, (LPARAM)&szBuffer) > 0) + if (SendMessage(*iter, LM_GETREVIDW, 0, (LPARAM)&wzBuffer) > 0) { - if (!pfnCallback(szBuffer, lParam)) + if (!pfnCallback(wzBuffer, lParam)) { hr = S_FALSE; break; } } } - } - - return hr; -} -// -// _FullScreenGetMonitorHelper -// -HMONITOR CLiteStep::_FullScreenGetMonitorHelper(HWND hWnd) -{ - if (!IsWindow(hWnd) || !IsWindowVisible(hWnd) || IsIconic(hWnd)) - { - return NULL; - } - - HMONITOR hMonFS = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL); - - if (NULL == hMonFS) - { - return NULL; - } - - RECT rScreen = { 0 }; - - if (NULL != hMonFS) - { - MONITORINFO miFS; - miFS.cbSize = sizeof(MONITORINFO); - - if (GetMonitorInfo(hMonFS, &miFS)) - { - VERIFY(CopyRect(&rScreen, &miFS.rcMonitor)); - } - else + for (MessageManager::windowSetT::iterator iter = setWindowsA.begin(); + iter != setWindowsA.end(); ++iter) { - rScreen.left = 0; - rScreen.top = 0; - rScreen.right = GetSystemMetrics(SM_CXSCREEN); - rScreen.bottom = GetSystemMetrics(SM_CYSCREEN); + // Using MAX_LINE_LENGTH to be on the safe side. Modules + // should assume a length of 64 or so. + char szBuffer[MAX_LINE_LENGTH] = { 0 }; - hMonFS = MonitorFromRect(&rScreen, MONITOR_DEFAULTTOPRIMARY); - } - } - - RECT rWnd; - VERIFY(GetClientRect(hWnd, &rWnd)); - - LONG width = rWnd.right - rWnd.left; - LONG height = rWnd.bottom - rWnd.top; - - POINT pt = { rWnd.left, rWnd.top }; - VERIFY(ClientToScreen(hWnd, &pt)); - - rWnd.left = pt.x; - rWnd.top = pt.y; - rWnd.right = pt.x + width; - rWnd.bottom = pt.y + height; - - // If the client area is the size of the screen, then consider it to be - // a full screen window. - if (EqualRect(&rScreen, &rWnd)) - { - return hMonFS; - } - - DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE); - - // Check Window Rect if WS_CAPTION or WS_THICKFRAME is part of the style. - // As long as at least one of them is not set, then we can check if the - // window is full screen or not: http://support.microsoft.com/kb/q179363/ - if (WS_CAPTION != (WS_CAPTION & dwStyle) || - WS_THICKFRAME != (WS_THICKFRAME & dwStyle)) - { - VERIFY(GetWindowRect(hWnd, &rWnd)); - - if (EqualRect(&rScreen, &rWnd)) - { - return hMonFS; + if (SendMessage(*iter, LM_GETREVIDA, 0, (LPARAM)&szBuffer) > 0) + { + if (!pfnCallback(MBSTOWCS(szBuffer), lParam)) + { + hr = S_FALSE; + break; + } + } } } - return NULL; + return hr; } -// -// _EnumThreadFSWnd -// -BOOL CALLBACK CLiteStep::_EnumThreadFSWnd(HWND hWnd, LPARAM lParam) -{ - HMONITOR hMonFS = _FullScreenGetMonitorHelper(hWnd); - - if (NULL != hMonFS) - { - *(HMONITOR*)lParam = hMonFS; - return FALSE; - } - - return TRUE; -} // -// _FullScreenGetMonitor +// _SetShellWindow // -HMONITOR CLiteStep::_FullScreenGetMonitor(HWND hWnd) const -{ - if (!IsWindow(hWnd)) - { - return NULL; - } - - DWORD dwProcessID; - DWORD dwThreadID = GetWindowThreadProcessId(hWnd, &dwProcessID); - - DWORD dwLSProcessID; - GetWindowThreadProcessId(GetLitestepWnd(), &dwLSProcessID); - - HMONITOR hMonFS = NULL; - - if (dwProcessID != dwLSProcessID) - { - EnumThreadWindows(dwThreadID, _EnumThreadFSWnd, (LPARAM)&hMonFS); - } +BOOL CLiteStep::_SetShellWindow(HWND hWnd) { + typedef BOOL (WINAPI* SETSHELLWINDOWPROC)(HWND); + + SETSHELLWINDOWPROC fnSetShellWindow = + (SETSHELLWINDOWPROC)GetProcAddress( + GetModuleHandle(_T("USER32.DLL")), "SetShellWindow"); - return hMonFS; -} + BOOL bRet = FALSE; -// -// _FullScreenHandler -// -void CLiteStep::_FullScreenHandler(HMONITOR hMonFullScreen) -{ - if (m_hFullScreenMonitor == hMonFullScreen) + if (fnSetShellWindow) { - return; - } - - m_hFullScreenMonitor = hMonFullScreen; - - if (m_pTrayService) - { - m_pTrayService->NotifyRudeApp(m_hFullScreenMonitor); + bRet = fnSetShellWindow(hWnd); } - - if (m_bAutoHideModules) + else { - if (NULL != m_hFullScreenMonitor) - { - // Must first show all modules on all monitors - ParseBangCommand(NULL, "!ShowModules", NULL); - // Pass m_hFullScreenMonitor, so that !HideModules can support only - // hiding modules on the same monitor as the full screen app. - ParseBangCommand((HWND)m_hFullScreenMonitor, "!HideModules", NULL); - } - else - { - ParseBangCommand(NULL, "!ShowModules", NULL); - } + TRACE("SetShellWindow() not found"); } -} -// -// _HandleShellHooks -// -void CLiteStep::_HandleShellHooks(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) - { - case LM_WINDOWACTIVATED: - { - // - // Note: The ShellHook will always set the HighBit when there - // is any full screen app on the desktop, even if it does not - // have focus. Because of this, we have no easy way to tell - // if the currently activated app is full screen or not. - // - // This is worked around by checking the window's actual size - // against the screen size. The correct behavior for this is - // to hide when a full screen app is active, and to show when - // a non full screen app is active. - // - KillTimer(m_hMainWindow, LT_RUDEAPP); - - if (0 != (0x8000 & lParam)) // rudeapp bit - { - // If the rudeapp bit is set then check to see if we have an - // active full screen app and handle it. - HMONITOR hMonFS = _FullScreenGetMonitor((HWND)wParam); - _FullScreenHandler(hMonFS); - - // If we have been told there is a rudeapp, but we did not - // detect one, then wait a second, and check the window in the - // foreground at that time. - if (NULL == m_hFullScreenMonitor) - { - SetTimer(m_hMainWindow, LT_RUDEAPP, 1000, NULL); - } - } - else if (NULL != m_hFullScreenMonitor) - { - // If we have previously detected a full screen app and the - // rudeapp bit is no longer set then remove the handler. - _FullScreenHandler(NULL); - } - } - break; - - case LM_WINDOWDESTROYED: - { - // If we have previously detected a full screen app then remove the - // handler if it was just destroyed. - if (NULL != m_hFullScreenMonitor) - { - if (NULL == _FullScreenGetMonitor(GetForegroundWindow())) - { - _FullScreenHandler(NULL); - } - } - } - break; - - default: - { - // do nothing - } - break; - } -} + return bRet; +} \ No newline at end of file diff --git a/litestep/litestep.h b/litestep/litestep.h index 6416b32..335b5ec 100644 --- a/litestep/litestep.h +++ b/litestep/litestep.h @@ -31,6 +31,7 @@ // forward declarations class IService; class TrayService; +class FullscreenMonitor; class DataStore; class MessageManager; class ModuleManager; @@ -42,11 +43,9 @@ class ModuleManager; #define RSH_PROGMAN 2 #define RSH_TASKMAN 3 -#define LT_RUDEAPP 0xBEAF - // Program Options -const char szMainWindowClass[] = "TApplication"; -const char szMainWindowTitle[] = "LiteStep"; +const TCHAR szMainWindowClass[] = _T("TApplication"); +const TCHAR szMainWindowTitle[] = _T("LiteStep"); #define GWL_CLASSPOINTER 0 @@ -91,7 +90,8 @@ class CLiteStep: public ILiteStep LRESULT _HandleSessionChange(DWORD dwCode, DWORD dwSession); void _Recycle(); - HRESULT _EnumRevIDs(LSENUMREVIDSPROC pfnCallback, LPARAM lParam) const; + HRESULT _EnumRevIDs(LSENUMREVIDSPROCW pfnCallback, LPARAM lParam) const; + static BOOL _SetShellWindow(HWND hWnd); // Application instance HINSTANCE m_hInstance; @@ -100,15 +100,6 @@ class CLiteStep: public ILiteStep // This is a special service that is not kept in the services array IService* m_pRecoveryMenu; - // LSAutoHideModules helpers - bool m_bAutoHideModules; - HMONITOR m_hFullScreenMonitor; // = NULL; - static HMONITOR _FullScreenGetMonitorHelper(HWND hWnd); - static BOOL CALLBACK _EnumThreadFSWnd(HWND hWnd, LPARAM lParam); - HMONITOR _FullScreenGetMonitor(HWND hWnd) const; - void _FullScreenHandler(HMONITOR hMonFullScreen); - void _HandleShellHooks(UINT uMsg, WPARAM wParam, LPARAM lParam); - // Windows HWND m_hMainWindow; // = NULL; @@ -141,6 +132,7 @@ class CLiteStep: public ILiteStep // Service Related // TrayService* m_pTrayService; // = NULL; + FullscreenMonitor* m_pFullscreenMonitor; // = nullptr; std::vector m_Services; HRESULT _InitServices(bool bSetAsShell); diff --git a/litestep/litestep.rc b/litestep/litestep.rc index fe2d043..1723c1c 100644 --- a/litestep/litestep.rc +++ b/litestep/litestep.rc @@ -7,7 +7,7 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "windows.h" +#include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -80,7 +80,7 @@ END 2 TEXTINCLUDE BEGIN - "#include ""windows.h""\r\n" + "#include ""afxres.h""\r\n" "\0" END @@ -154,7 +154,7 @@ BEGIN VALUE "OriginalFilename", "litestep.exe" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" - VALUE "SpecialBuild", "alur's windows 8/x64 branch" + VALUE "SpecialBuild", "CVS HEAD Test Release" END END BLOCK "VarFileInfo" @@ -210,6 +210,8 @@ BEGIN IDS_LITESTEP_RUN "&Run..." IDS_LITESTEP_SHUTDOWNWIN "Sh&utdown Windows..." IDS_MODULEQUIT_ERROR "Exception while quitting module." + IDS_LITESTEP_ABOUTLS "&About LiteStep" + IDS_LITESTEP_EXPLORER "&Start Explorer as shell" END STRINGTABLE @@ -227,11 +229,15 @@ BEGIN "Exception during bang command execution.\nPlease contact the module author.\n\nBang parameters: %s" IDS_LITESTEP_REGISTERCLASS_ERROR "Error registering window class." IDS_MODULEDEPENDENCY_ERROR - "Error: Could not load module.\nThis is likely a case of a missing C Run-Time Library or other dependency." + "Error: Could not load module.\nThis is likely a case of a missing C Run-Time Library or other dependency.\nError Information:\n" IDS_RECURSIVEVAR "Error: Variable ""%s"" is defined recursively." + IDS_RECURSIVEINCLUDE "Error: Reursive include detected!\n%s" IDS_MATHEXCEPTION "Error in Expression:\n %s\n\nDescription:\n %s" IDS_LSAPI_INIT_ERROR "Failed to initialize the LiteStep API." IDS_LITESTEP_INIT_ERROR "Failed to initialize LiteStep.\nPlease contact the LiteStep development team.\n\nError code: 0x%.8X" + + IDS_MODULEWRONGARCH32_ERROR "Error: Could not load module.\n\nThe module seems to compiled for 64-bit LiteStep. This is a 32-bit version of LiteStep, which can only load 32-bit modules." + IDS_MODULEWRONGARCH64_ERROR "Error: Could not load module.\n\nThe module seems to compiled for 32-bit LiteStep. This is a 64-bit version of LiteStep, which can only load 64-bit modules." END #endif // English (U.S.) resources @@ -342,6 +348,28 @@ BEGIN IDS_LITESTEP_SHUTDOWNWIN "&Stäng av..." END +STRINGTABLE +BEGIN + IDS_MODULENOTFOUND_ERROR + "Fel: Modulen kunde inte hittas.\Kontrollera dina inställningar." + IDS_INITMODULEEXNOTFOUND_ERROR + "Fel: Kunde inte hitta initModuleEx() i modulen.\n\Kontrollera att DLL filen är en LiteStep modul." + IDS_QUITMODULENOTFOUND_ERROR + "Fel: Kunde inte hitta ().\n\nPlease conirm that the dll is a LiteStep module." + IDS_MODULEINITEXCEPTION_ERROR + "Ett fel inträffade under modul initialiseringen.\n\nKontakta modulens skapare." + IDS_LITESTEP_CREATEWINDOW_ERROR "Misslyckades med att skapa fönstret." + IDS_LITESTEP_BANGEXCEPTION + "Ett fel inträffade under exekvering av ett bang kommando.\nKontakta modulens skapare.\n\nBang parameterar: %s" + IDS_LITESTEP_REGISTERCLASS_ERROR "Misslyckades med att registrera fönter klassen." + IDS_MODULEDEPENDENCY_ERROR + "Fel: Kunde inte ladda modulen.\nTroligen saknas ett exekveringsbibliotek.\n\n" + IDS_RECURSIVEVAR "Fel: Variabeln ""%s"" är rekursivt definierad." + IDS_MATHEXCEPTION "Fel i uttrycket:\n %s\n\nDescription:\n %s" + IDS_LSAPI_INIT_ERROR "Initaliseringen av LiteStep's API misslyckades." + IDS_LITESTEP_INIT_ERROR "Initaliseringen av LiteStep misslyckades.\n\nFel kod: 0x%.8X" +END + #endif // Swedish resources ///////////////////////////////////////////////////////////////////////////// diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 141ffb4..578bb6f 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -1,280 +1,286 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - litestep - {994556EE-2F21-4811-A85D-6925F7F84B0D} - litestep - Win32Proj - $(VCTargetsPath11) - - - - Application - MultiByte - true - v110 - - - Application - MultiByte - true - v110 - - - Application - MultiByte - v110 - - - Application - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11_32\ - Debug_VC11_32\ - true - true - ../Release_VC11_32\ - Release_VC11_32\ - false - false - - - ../Debug_VC11_64\ - Debug_VC11_64\ - - - ../Release_VC11_64\ - Release_VC11_64\ - - - - Disabled - WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)litestep.exe - true - true - true - $(OutDir)litestep.pdb - Windows - MachineX86 - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)litestep.exe - true - true - true - $(OutDir)litestep.pdb - Windows - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - Default - false - MultiThreadedDLL - true - StreamingSIMDExtensions2 - false - true - true - - - Level4 - false - - - Default - true - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - NotSet - $(OutDir)litestep.exe - true - true - false - Windows - true - true - MachineX86 - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - Default - false - MultiThreadedDLL - true - NotSet - false - true - true - - - Level4 - false - - - Default - true - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - NotSet - $(OutDir)litestep.exe - true - true - false - Windows - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2feca0a4-cb2f-44ca-97ab-de78ebbdecfa} - - - {2213036f-018c-416a-8a6a-7934c936cffc} - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + litestep + {994556EE-2F21-4811-A85D-6925F7F84B0D} + litestep + Win32Proj + $(VCTargetsPath11) + + + + Application + Unicode + true + v110_xp + + + Application + Unicode + true + v110_xp + + + Application + Unicode + v110_xp + + + Application + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11_32\ + Debug_VC11_32\ + true + true + ../Release_VC11_32\ + Release_VC11_32\ + false + false + + + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + MachineX86 + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + + + + + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + StreamingSIMDExtensions2 + false + true + true + + + Level4 + false + + + Default + true + true + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + NotSet + false + true + true + + + Level4 + false + + + Default + true + true + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2feca0a4-cb2f-44ca-97ab-de78ebbdecfa} + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + \ No newline at end of file diff --git a/litestep/litestep_vc10.vcxproj b/litestep/litestep_vc12.vcxproj similarity index 83% rename from litestep/litestep_vc10.vcxproj rename to litestep/litestep_vc12.vcxproj index 3191fa6..278db9d 100644 --- a/litestep/litestep_vc10.vcxproj +++ b/litestep/litestep_vc12.vcxproj @@ -1,262 +1,286 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - litestep - {994556EE-2F21-4811-A85D-6925F7F84B0D} - litestep - Win32Proj - - - - Application - MultiByte - true - - - Application - MultiByte - true - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10_32\ - ../Debug_VC10_64\ - Debug_VC10_32\ - Debug_VC10_64\ - true - true - ../Release_VC10_32\ - ../Release_VC10_64\ - Release_VC10_32\ - Release_VC10_64\ - false - false - - - - Disabled - WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)litestep.exe - true - true - true - $(OutDir)litestep.pdb - Windows - MachineX86 - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)litestep.exe - true - true - true - $(OutDir)litestep.pdb - Windows - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - Default - false - MultiThreadedDLL - true - NotSet - false - true - true - - - Level4 - false - - - Default - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - NotSet - $(OutDir)litestep.exe - true - true - false - Windows - true - true - MachineX86 - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - Default - false - MultiThreadedDLL - true - NotSet - false - true - true - - - Level4 - false - - - Default - true - - - ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - NotSet - $(OutDir)litestep.exe - true - true - false - Windows - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2feca0a4-cb2f-44ca-97ab-de78ebbdecfa} - - - {2213036f-018c-416a-8a6a-7934c936cffc} - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + litestep + {994556EE-2F21-4811-A85D-6925F7F84B0D} + litestep + Win32Proj + $(VCTargetsPath11) + + + + Application + Unicode + true + v120_xp + + + Application + Unicode + true + v120_xp + + + Application + Unicode + v120_xp + + + Application + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC12_32\ + Debug_VC12_32\ + true + true + ../Release_VC12_32\ + Release_VC12_32\ + false + false + + + ../Debug_VC12_64\ + Debug_VC12_64\ + + + ../Release_VC12_64\ + Release_VC12_64\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + MachineX86 + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)litestep.exe + true + true + true + $(OutDir)litestep.pdb + Windows + + + + + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + StreamingSIMDExtensions2 + false + true + true + + + Level4 + false + + + Default + true + true + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;LSAPI_PRIVATE;%(PreprocessorDefinitions) + true + Default + false + MultiThreadedDLL + true + NotSet + false + true + true + + + Level4 + false + + + Default + true + true + true + + + ole32.lib;uuid.lib;shlwapi.lib;advapi32.lib;gdi32.lib;shell32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + NotSet + $(OutDir)litestep.exe + true + true + false + Windows + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2feca0a4-cb2f-44ca-97ab-de78ebbdecfa} + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + \ No newline at end of file diff --git a/litestep/litestep_vc71.vcproj b/litestep/litestep_vc71.vcproj deleted file mode 100644 index 82ea56d..0000000 --- a/litestep/litestep_vc71.vcproj +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/litestep/litestep_vc8.vcproj b/litestep/litestep_vc8.vcproj deleted file mode 100644 index fe1c797..0000000 --- a/litestep/litestep_vc8.vcproj +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/litestep/litestep_vc9.vcproj b/litestep/litestep_vc9.vcproj deleted file mode 100644 index b5c7aa9..0000000 --- a/litestep/litestep_vc9.vcproj +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/litestep/resource.h b/litestep/resource.h index 91daa8b..22dae6f 100644 --- a/litestep/resource.h +++ b/litestep/resource.h @@ -29,6 +29,11 @@ #define IDS_MATHEXCEPTION 25 #define IDS_LSAPI_INIT_ERROR 26 #define IDS_LITESTEP_INIT_ERROR 27 +#define IDS_MODULEWRONGARCH32_ERROR 28 +#define IDS_MODULEWRONGARCH64_ERROR 29 +#define IDS_LITESTEP_ABOUTLS 30 +#define IDS_LITESTEP_EXPLORER 31 +#define IDS_RECURSIVEINCLUDE 32 #define IDI_LS 101 #define IDB_LS 102 #define IDD_ABOUTBOX 103 @@ -40,7 +45,6 @@ #define IDC_LISTVIEW 1006 #define IDC_THEME_INFO 1007 #define IDC_EDIT 1008 -#define IDC_STATIC -1 // Next default values for new objects // diff --git a/litestep_vc11.sln b/litestep_vc11.sln index 7f5091f..4ff40cc 100644 --- a/litestep_vc11.sln +++ b/litestep_vc11.sln @@ -1,45 +1,45 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc11.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc11.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc11.vcxproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc11.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc11.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc11.vcxproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/litestep_vc10.sln b/litestep_vc12.sln similarity index 88% rename from litestep_vc10.sln rename to litestep_vc12.sln index 1f8581b..2155462 100644 --- a/litestep_vc10.sln +++ b/litestep_vc12.sln @@ -1,45 +1,45 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc10.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc10.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc10.vcxproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc12.vcxproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc12.vcxproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc12.vcxproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.ActiveCfg = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|x64.Build.0 = Debug|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.ActiveCfg = Release|x64 + {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|x64.Build.0 = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.ActiveCfg = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|x64.Build.0 = Debug|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.ActiveCfg = Release|x64 + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|x64.Build.0 = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.ActiveCfg = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|x64.Build.0 = Debug|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.ActiveCfg = Release|x64 + {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/litestep_vc71.sln b/litestep_vc71.sln deleted file mode 100644 index bf7dcef..0000000 --- a/litestep_vc71.sln +++ /dev/null @@ -1,40 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc71.vcproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} = {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc71.vcproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc71.vcproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release.Build.0 = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug.ActiveCfg = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug.Build.0 = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release.ActiveCfg = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release.Build.0 = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug.ActiveCfg = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug.Build.0 = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release.ActiveCfg = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/litestep_vc8.sln b/litestep_vc8.sln deleted file mode 100644 index 59bc607..0000000 --- a/litestep_vc8.sln +++ /dev/null @@ -1,38 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc8.vcproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} = {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc8.vcproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc8.vcproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/litestep_vc9.sln b/litestep_vc9.sln deleted file mode 100644 index 0d61350..0000000 --- a/litestep_vc9.sln +++ /dev/null @@ -1,38 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "litestep", "litestep\litestep_vc9.vcproj", "{994556EE-2F21-4811-A85D-6925F7F84B0D}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} = {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utility", "utility\utility_vc9.vcproj", "{2213036F-018C-416A-8A6A-7934C936CFFC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsapi", "lsapi\lsapi_vc9.vcproj", "{2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}" - ProjectSection(ProjectDependencies) = postProject - {2213036F-018C-416A-8A6A-7934C936CFFC} = {2213036F-018C-416A-8A6A-7934C936CFFC} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Debug|Win32.Build.0 = Debug|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.ActiveCfg = Release|Win32 - {994556EE-2F21-4811-A85D-6925F7F84B0D}.Release|Win32.Build.0 = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.ActiveCfg = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Debug|Win32.Build.0 = Debug|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.ActiveCfg = Release|Win32 - {2213036F-018C-416A-8A6A-7934C936CFFC}.Release|Win32.Build.0 = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Debug|Win32.Build.0 = Debug|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.ActiveCfg = Release|Win32 - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/lsapi/BangCommand.cpp b/lsapi/BangCommand.cpp index ffb0ee7..3500d5f 100644 --- a/lsapi/BangCommand.cpp +++ b/lsapi/BangCommand.cpp @@ -21,22 +21,52 @@ //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "BangCommand.h" #include "ThreadedBangCommand.h" +#include +#include "../utility/stringutility.h" -Bang::Bang(DWORD dwThread, BangCommand pfnBang, LPCSTR pszCommand) : - m_szCommand(pszCommand) +Bang::Bang(DWORD dwThread, BangCommandW pfnBang, LPCWSTR pwzCommand) : + m_sCommand(pwzCommand) { m_bEX = false; m_bBang = pfnBang; + m_pAddress = pfnBang; m_dwThreadID = dwThread; } -Bang::Bang(DWORD dwThread, BangCommandEx pfnBang, LPCSTR pszCommand) : - m_szCommand(pszCommand) +Bang::Bang(DWORD dwThread, BangCommandA pfnBang, LPCWSTR pwzCommand) : + m_sCommand(pwzCommand) +{ + m_bEX = false; + m_bBang = [pfnBang] (HWND hOwner, LPCWSTR pwzArgs) -> void { + pfnBang(hOwner, std::unique_ptr(MBSFromWCS(pwzArgs)).get()); + }; + m_pAddress = pfnBang; + m_dwThreadID = dwThread; +} + + +Bang::Bang(DWORD dwThread, BangCommandExW pfnBang, LPCWSTR pwzCommand) : + m_sCommand(pwzCommand) { m_bEX = true; m_bBangEX = pfnBang; + m_pAddress = pfnBang; + m_dwThreadID = dwThread; +} + + +Bang::Bang(DWORD dwThread, BangCommandExA pfnBang, LPCWSTR pwzCommand) : + m_sCommand(pwzCommand) +{ + m_bEX = true; + m_bBangEX = [pfnBang] (HWND hOwner, LPCWSTR pwzCommand, LPCWSTR pwzArgs) -> void { + pfnBang(hOwner, + std::unique_ptr(MBSFromWCS(pwzCommand)).get(), + std::unique_ptr(MBSFromWCS(pwzArgs)).get()); + };; + m_pAddress = pfnBang; m_dwThreadID = dwThread; } @@ -47,19 +77,19 @@ Bang::~Bang() } -void Bang::Execute(HWND hCaller, LPCSTR pszParams) +void Bang::Execute(HWND hCaller, LPCWSTR pwzParams) { DWORD dwThreadID = GetCurrentThreadId(); if (dwThreadID != m_dwThreadID) { ThreadedBangCommand * pInfo = new ThreadedBangCommand(hCaller, - m_szCommand.c_str(), pszParams); + m_sCommand.c_str(), pwzParams); - if (pInfo != NULL) + if (pInfo != nullptr) { // target thread releases pInfo - PostThreadMessage(m_dwThreadID, LM_THREAD_BANGCOMMAND, + PostThreadMessageW(m_dwThreadID, LM_THREAD_BANGCOMMAND, (WPARAM)pInfo, 0); } } @@ -67,11 +97,11 @@ void Bang::Execute(HWND hCaller, LPCSTR pszParams) { if (m_bEX) { - m_bBangEX(hCaller, m_szCommand.c_str(), pszParams); + m_bBangEX(hCaller, m_sCommand.c_str(), pwzParams); } else { - m_bBang(hCaller, pszParams); + m_bBang(hCaller, pwzParams); } } } @@ -79,18 +109,8 @@ void Bang::Execute(HWND hCaller, LPCSTR pszParams) HINSTANCE Bang::GetModule() const { - HINSTANCE hModule = NULL; - LPVOID pAddress = NULL; - - if (m_bEX) - { - pAddress = (LPVOID)m_bBangEX; - } - else - { - pAddress = (LPVOID)m_bBang; - } - + HINSTANCE hModule = nullptr; + // // Given the BangProc's address, VirtualQuery can // figure out the module's HMODULE @@ -98,7 +118,7 @@ HINSTANCE Bang::GetModule() const MEMORY_BASIC_INFORMATION mbi = { 0 }; size_t cbBuffer = sizeof(mbi); - if (VirtualQuery(pAddress, &mbi, cbBuffer) == cbBuffer) + if (VirtualQuery(m_pAddress, &mbi, cbBuffer) == cbBuffer) { hModule = (HINSTANCE)mbi.AllocationBase; } diff --git a/lsapi/BangCommand.h b/lsapi/BangCommand.h index e9f480d..c7c9c35 100644 --- a/lsapi/BangCommand.h +++ b/lsapi/BangCommand.h @@ -25,6 +25,7 @@ #include "../utility/base.h" #include "lsapidefines.h" #include +#include /** @@ -38,10 +39,19 @@ class Bang : public CountedBase * * @param dwThread thread that owns this bang command * @param pfnBang callback function - * @param pszCommand bang command name + * @param pwzCommand bang command name */ - Bang(DWORD dwThread, BangCommand pfnBang, LPCSTR pszCommand); - + Bang(DWORD dwThread, BangCommandA pfnBang, LPCWSTR pwzCommand); + + /** + * Constructs a bang command. + * + * @param dwThread thread that owns this bang command + * @param pfnBang callback function + * @param pwzCommand bang command name + */ + Bang(DWORD dwThread, BangCommandW pfnBang, LPCWSTR pwzCommand); + /** * Constructs a bang command whose callback function takes the bang * command name as a parameter. @@ -51,7 +61,18 @@ class Bang : public CountedBase * name as a parameter * @param pszCommand bang command name */ - Bang(DWORD dwThread, BangCommandEx pfnBang, LPCSTR pszCommand); + Bang(DWORD dwThread, BangCommandExA pfnBang, LPCWSTR pwzCommand); + + /** + * Constructs a bang command whose callback function takes the bang + * command name as a parameter. + * + * @param dwThread thread that owns this bang command + * @param pfnBang callback function which takes the bang command + * name as a parameter + * @param pwzCommand bang command name + */ + Bang(DWORD dwThread, BangCommandExW pfnBang, LPCWSTR pwzCommand); /** * Destructor. @@ -65,9 +86,9 @@ class Bang : public CountedBase * * @param hCaller window handle belonging to caller. The bang * typically uses this as an owner for dialog boxes. - * @param pszParams parameters for the bang command + * @param pwzParams parameters for the bang command */ - void Execute(HWND hCaller, LPCSTR pszParams); + void Execute(HWND hCaller, LPCWSTR pwzParams); HINSTANCE GetModule() const; @@ -80,15 +101,18 @@ class Bang : public CountedBase * function */ bool m_bEX; + + /** The address of the callback function, inside the module */ + LPVOID m_pAddress; /** Callback function */ - BangCommand m_bBang; + std::function m_bBang; /** Callback function that takes the bang command name as a parameter */ - BangCommandEx m_bBangEX; + std::function m_bBangEX; /** Name of this bang command */ - std::string m_szCommand; + std::wstring m_sCommand; }; #endif // BANGCOMMAND_H diff --git a/lsapi/BangManager.cpp b/lsapi/BangManager.cpp index 29f68c0..354c198 100644 --- a/lsapi/BangManager.cpp +++ b/lsapi/BangManager.cpp @@ -36,11 +36,11 @@ BangManager::~BangManager() // Add a bang command to the manager -BOOL BangManager::AddBangCommand(LPCSTR pszName, Bang *pbbBang) +BOOL BangManager::AddBangCommand(LPCWSTR pwzName, Bang *pbbBang) { Lock lock(m_cs); - BangMap::iterator iter = bang_map.find(pszName); + BangMap::iterator iter = bang_map.find(pwzName); if (iter != bang_map.end()) { @@ -48,7 +48,7 @@ BOOL BangManager::AddBangCommand(LPCSTR pszName, Bang *pbbBang) bang_map.erase(iter); } - bang_map.insert(BangMap::value_type(pszName, pbbBang)); + bang_map.insert(BangMap::value_type(pwzName, pbbBang)); pbbBang->AddRef(); return TRUE; @@ -56,13 +56,13 @@ BOOL BangManager::AddBangCommand(LPCSTR pszName, Bang *pbbBang) // Remove a bang command from the manager -BOOL BangManager::RemoveBangCommand(LPCSTR pszName) +BOOL BangManager::RemoveBangCommand(LPCWSTR pwzName) { Lock lock(m_cs); BOOL bReturn = FALSE; - ASSERT(pszName != NULL); - BangMap::iterator iter = bang_map.find(pszName); + ASSERT(pwzName != nullptr); + BangMap::iterator iter = bang_map.find(pwzName); if (iter != bang_map.end()) { @@ -77,10 +77,10 @@ BOOL BangManager::RemoveBangCommand(LPCSTR pszName) // Execute named bang command, passing params, getting result -BOOL BangManager::ExecuteBangCommand(LPCSTR pszName, HWND hCaller, LPCSTR pszParams) +BOOL BangManager::ExecuteBangCommand(LPCWSTR pszName, HWND hCaller, LPCWSTR pwzParams) { BOOL bReturn = FALSE; - Bang* pToExec = NULL; + Bang* pToExec = nullptr; // Acquiring lock manually to allow manual release below m_cs.Acquire(); @@ -99,7 +99,7 @@ BOOL BangManager::ExecuteBangCommand(LPCSTR pszName, HWND hCaller, LPCSTR pszPar if (pToExec) { - pToExec->Execute(hCaller, pszParams); + pToExec->Execute(hCaller, pwzParams); pToExec->Release(); bReturn = TRUE; @@ -125,7 +125,7 @@ void BangManager::ClearBangCommands() } -HRESULT BangManager::EnumBangs(LSENUMBANGSV2PROC pfnCallback, LPARAM lParam) const +HRESULT BangManager::EnumBangs(LSENUMBANGSV2PROCW pfnCallback, LPARAM lParam) const { Lock lock(m_cs); diff --git a/lsapi/BangManager.h b/lsapi/BangManager.h index 83965d9..d970c42 100644 --- a/lsapi/BangManager.h +++ b/lsapi/BangManager.h @@ -36,7 +36,7 @@ class BangManager { private: /** Maps bang command names to Bang objects. */ - typedef std::map BangMap; + typedef std::map BangMap; /** List of bang commands indexed by name */ BangMap bang_map; @@ -58,21 +58,21 @@ class BangManager /** * Adds a bang command to the list. * - * @param pszName bang command name + * @param pwzName bang command name * @param pbbBang Bang object that implements the bang command * @return TRUE if the operation succeeds or * FALSE otherwise */ - BOOL AddBangCommand(LPCSTR pszName, Bang *pbbBang); + BOOL AddBangCommand(LPCWSTR pszName, Bang *pbbBang); /** * Removes a bang command from the list. * - * @param pszName bang command name + * @param pwzName bang command name * @return TRUE if the operation succeeds or * FALSE otherwise */ - BOOL RemoveBangCommand(LPCSTR pszName); + BOOL RemoveBangCommand(LPCWSTR pwzName); /** * Removes all bang commands from the list. @@ -82,13 +82,13 @@ class BangManager /** * Executes a bang command with the specified parameters. * - * @param pszName bang command name + * @param pwzName bang command name * @param hCaller handle to owner window - * @param pszParams command-line arguments + * @param pwzParams command-line arguments * @return TRUE if the operation succeeds or * FALSE otherwise */ - BOOL ExecuteBangCommand(LPCSTR pszName, HWND hCaller, LPCSTR pszParams); + BOOL ExecuteBangCommand(LPCWSTR pwzName, HWND hCaller, LPCWSTR pwzParams); /** * Calls a callback function once for each bang command in the list. @@ -100,7 +100,7 @@ class BangManager * S_FALSE if the callback function returned * FALSE, or an error code */ - HRESULT EnumBangs(LSENUMBANGSV2PROC pfnCallback, LPARAM lParam) const; + HRESULT EnumBangs(LSENUMBANGSV2PROCW pfnCallback, LPARAM lParam) const; }; #endif // BANGMANAGER_H diff --git a/lsapi/MathEvaluate.cpp b/lsapi/MathEvaluate.cpp index a4983bc..47a0353 100644 --- a/lsapi/MathEvaluate.cpp +++ b/lsapi/MathEvaluate.cpp @@ -27,7 +27,7 @@ using namespace std; -bool MathEvaluateBool(const SettingsMap& context, const string& expression, +bool MathEvaluateBool(const SettingsMap& context, const wstring& expression, bool& result, unsigned int flags) { try @@ -41,10 +41,10 @@ bool MathEvaluateBool(const SettingsMap& context, const string& expression, RESOURCE_STREX( GetModuleHandle(NULL), IDS_MATHEXCEPTION, resourceTextBuffer, MAX_LINE_LENGTH, - "Error in Expression:\n %s\n\nDescription:\n %s", - expression.c_str(), e.what()); + L"Error in Expression:\n %ls\n\nDescription:\n %ls", + expression.c_str(), e.GetException()); - RESOURCE_MSGBOX_F("LiteStep", MB_ICONERROR); + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); return false; } @@ -53,8 +53,8 @@ bool MathEvaluateBool(const SettingsMap& context, const string& expression, } -bool MathEvaluateString(const SettingsMap& context, const string& expression, - string& result, const StringSet& recursiveVarSet, unsigned int flags) +bool MathEvaluateString(const SettingsMap& context, const wstring& expression, + wstring& result, const StringSet& recursiveVarSet, unsigned int flags) { try { @@ -74,10 +74,10 @@ bool MathEvaluateString(const SettingsMap& context, const string& expression, RESOURCE_STREX( GetModuleHandle(NULL), IDS_MATHEXCEPTION, resourceTextBuffer, MAX_LINE_LENGTH, - "Error in Expression:\n %s\n\nDescription:\n %s", - expression.c_str(), e.what()); + L"Error in Expression:\n %s\n\nDescription:\n %s", + expression.c_str(), e.GetException()); - RESOURCE_MSGBOX_F("LiteStep", MB_ICONERROR); + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); return false; } diff --git a/lsapi/MathEvaluate.h b/lsapi/MathEvaluate.h index 4c16630..e9900af 100644 --- a/lsapi/MathEvaluate.h +++ b/lsapi/MathEvaluate.h @@ -49,7 +49,7 @@ enum * false if an error occured */ bool MathEvaluateBool(const SettingsMap& context, - const std::string& expression, + const std::wstring& expression, bool& result, unsigned int flags = 0); @@ -66,8 +66,8 @@ bool MathEvaluateBool(const SettingsMap& context, * false if an error occured */ bool MathEvaluateString(const SettingsMap& context, - const std::string& expression, - std::string& result, + const std::wstring& expression, + std::wstring& result, const StringSet& recursiveVarSet, unsigned int flags = 0); diff --git a/lsapi/MathException.h b/lsapi/MathException.h index cd35b89..3a4a5a1 100644 --- a/lsapi/MathException.h +++ b/lsapi/MathException.h @@ -36,10 +36,17 @@ class MathException : public std::runtime_error /** * Constructs a MathException with the specified message. */ - MathException(const std::string& message) throw() : std::runtime_error(message) + MathException(const std::wstring& message) throw() : std::runtime_error(std::string(message.begin(), message.end())) { - // do nothing + this->sMessage = message; } + + const std::wstring & GetException() const + { + return sMessage; + } + + std::wstring sMessage; }; diff --git a/lsapi/MathParser.cpp b/lsapi/MathParser.cpp index c92b486..4f7a5be 100644 --- a/lsapi/MathParser.cpp +++ b/lsapi/MathParser.cpp @@ -124,34 +124,34 @@ static MathValue Math_upperCase(const MathValueList& argList); // Mapping of names to predefined functions struct FunctionTable { - const char *name; MathFunction function; unsigned int numArgs; + const wchar_t *name; MathFunction function; unsigned int numArgs; } gFunctions[] = { - { "abs", Math_abs, 1 }, - { "boolean", Math_boolean, 1 }, - { "ceil", Math_ceil, 1 }, - { "contains", Math_contains, 2 }, - { "endsWith", Math_endsWith, 2 }, - { "fileExists", Math_fileExists, 1 }, - { "floor", Math_floor, 1 }, - { "if", Math_if, 3 }, - { "integer", Math_integer, 1 }, - { "length", Math_length, 1 }, - { "lowerCase", Math_lowerCase, 1 }, - { "max", Math_max, 2 }, - { "min", Math_min, 2 }, - { "number", Math_number, 1 }, - { "pow", Math_pow, 2 }, - { "round", Math_round, 1 }, - { "startsWith", Math_startsWith, 2 }, - { "string", Math_string, 1 }, - { "sqrt", Math_sqrt, 1 }, - { "upperCase", Math_upperCase, 1 } + { L"abs", Math_abs, 1 }, + { L"boolean", Math_boolean, 1 }, + { L"ceil", Math_ceil, 1 }, + { L"contains", Math_contains, 2 }, + { L"endsWith", Math_endsWith, 2 }, + { L"fileExists", Math_fileExists, 1 }, + { L"floor", Math_floor, 1 }, + { L"if", Math_if, 3 }, + { L"integer", Math_integer, 1 }, + { L"length", Math_length, 1 }, + { L"lowerCase", Math_lowerCase, 1 }, + { L"max", Math_max, 2 }, + { L"min", Math_min, 2 }, + { L"number", Math_number, 1 }, + { L"pow", Math_pow, 2 }, + { L"round", Math_round, 1 }, + { L"startsWith", Math_startsWith, 2 }, + { L"string", Math_string, 1 }, + { L"sqrt", Math_sqrt, 1 }, + { L"upperCase", Math_upperCase, 1 } }; const int gNumFunctions = sizeof(gFunctions) / sizeof(gFunctions[0]); -MathParser::MathParser(const SettingsMap& context, const string& expression, const StringSet& recursiveVarSet, unsigned int flags) : +MathParser::MathParser(const SettingsMap& context, const wstring& expression, const StringSet& recursiveVarSet, unsigned int flags) : mContext(context), mScanner(expression), mRecursiveVarSet(recursiveVarSet), mFlags(flags) { // Fill the token buffer @@ -168,19 +168,19 @@ MathValue MathParser::Evaluate() } -MathValue MathParser::CallFunction(const string& name, const MathValueList& argList) const +MathValue MathParser::CallFunction(const wstring& name, const MathValueList& argList) const { for (int i = 0; i < gNumFunctions; ++i) { - if (_stricmp(name.c_str(), gFunctions[i].name) == 0) + if (_wcsicmp(name.c_str(), gFunctions[i].name) == 0) { if (argList.size() != gFunctions[i].numArgs) { // Incorrect number of arguments - ostringstream message; + wostringstream message; - message << "Error: Function " << name << " requires "; - message << gFunctions[i].numArgs << " argument(s)."; + message << L"Error: Function " << name << L" requires "; + message << gFunctions[i].numArgs << L" argument(s)."; throw MathException(message.str()); } @@ -191,21 +191,21 @@ MathValue MathParser::CallFunction(const string& name, const MathValueList& argL } // No such function - throw MathException("Error: " + name + " is not a function"); + throw MathException(L"Error: " + name + L" is not a function"); } -MathValue MathParser::GetVariable(const string& name) const +MathValue MathParser::GetVariable(const wstring& name) const { // Check for recursive variable definitions if (mRecursiveVarSet.count(name) > 0) { // While there may be a localized version of this particular // exception string, none of the other exception strings are localized. - ostringstream message; + wostringstream message; - message << "Error: Variable \"" << name; - message << "\" is defined recursively."; + message << L"Error: Variable \"" << name.c_str(); + message << L"\" is defined recursively."; throw MathException(message.str()); } @@ -223,25 +223,25 @@ MathValue MathParser::GetVariable(const string& name) const newRecursiveVarSet.insert(name); // Expand variable references - char value[MAX_LINE_LENGTH]; + wchar_t value[MAX_LINE_LENGTH]; g_LSAPIManager.GetSettingsManager()->VarExpansionEx( value, (*it).second.c_str(), MAX_LINE_LENGTH, newRecursiveVarSet); - if (_stricmp(value, "false") == 0 || - _stricmp(value, "off") == 0 || - _stricmp(value, "no") == 0) + if (_wcsicmp(value, L"false") == 0 || + _wcsicmp(value, L"off") == 0 || + _wcsicmp(value, L"no") == 0) { // False return false; } - else if (_stricmp(value, "true") == 0 || - _stricmp(value, "on") == 0 || - _stricmp(value, "yes") == 0) + else if (_wcsicmp(value, L"true") == 0 || + _wcsicmp(value, L"on") == 0 || + _wcsicmp(value, L"yes") == 0) { // True return true; } - else if (strlen(value) == 0) + else if (wcslen(value) == 0) { // Unfortunately, VarExpansionEx has no "failure" case, therefore, // an empty value may be from an undefined or recursive variable. @@ -261,8 +261,8 @@ MathValue MathParser::GetVariable(const string& name) const if (value[0] == '\"' || value[0] == '\'') { // If the value is quoted, remove the quotes - char unquoted[MAX_LINE_LENGTH]; - GetToken(value, unquoted, NULL, FALSE); + wchar_t unquoted[MAX_LINE_LENGTH]; + GetTokenW(value, unquoted, NULL, FALSE); StringCchCopy(value, MAX_LINE_LENGTH, unquoted); } @@ -290,7 +290,7 @@ MathValue MathParser::ParsePrimaryExpression() mLookahead[1].GetType() == TT_LPAREN) { // Function Call - string name; + wstring name; MathValueList argList; // Get name @@ -310,13 +310,13 @@ MathValue MathParser::ParsePrimaryExpression() else if (mLookahead[0].GetType() == TT_ID) { // Identifier - string name = mLookahead[0].GetValue(); + wstring name = mLookahead[0].GetValue(); MathValue value = GetVariable(name); if ((mFlags & MATH_EXCEPTION_ON_UNDEFINED) && value.IsUndefined()) { // Reference to undefined variable - ostringstream message; + wostringstream message; message << "Error: Variable " << name << " is not defined."; throw MathException(message.str()); } @@ -376,16 +376,16 @@ MathValue MathParser::ParsePrimaryExpression() // Defined Match(TT_DEFINED); Match(TT_LPAREN); - string name = mLookahead[0].GetValue(); + wstring name = mLookahead[0].GetValue(); Match(TT_ID); Match(TT_RPAREN); return !GetVariable(name).IsUndefined(); } - ostringstream message; + wostringstream message; - message << "Syntax Error: Expected identifier, literal, or subexpression,"; - message << " but found " << mLookahead[0].GetTypeName(); + message << L"Syntax Error: Expected identifier, literal, or subexpression,"; + message << L" but found " << mLookahead[0].GetTypeName(); throw MathException(message.str()); } @@ -653,11 +653,11 @@ void MathParser::Match(int type) { if (mLookahead[0].GetType() != type) { - ostringstream message; + wostringstream message; - message << "Syntax Error: Expected "; + message << L"Syntax Error: Expected "; message << MathToken(type).GetTypeName(); - message << ", but found " << mLookahead[0].GetTypeName(); + message << L", but found " << mLookahead[0].GetTypeName(); throw MathException(message.str()); } @@ -716,8 +716,8 @@ MathValue Math_contains(const MathValueList& argList) // Ends with a substring MathValue Math_endsWith(const MathValueList& argList) { - string toSearch = argList[0].ToString(); - string toFind = argList[1].ToString(); + wstring toSearch = argList[0].ToString(); + wstring toFind = argList[1].ToString(); if (toFind.empty()) { @@ -767,7 +767,7 @@ MathValue Math_length(const MathValueList& argList) // Convert string to lower case MathValue Math_lowerCase(const MathValueList& argList) { - string str = argList[0].ToString(); + wstring str = argList[0].ToString(); transform(str.begin(), str.end(), str.begin(), ::tolower); return str; } @@ -828,8 +828,8 @@ MathValue Math_round(const MathValueList& argList) // Starts with a substring MathValue Math_startsWith(const MathValueList& argList) { - string toSearch = argList[0].ToString(); - string toFind = argList[1].ToString(); + wstring toSearch = argList[0].ToString(); + wstring toFind = argList[1].ToString(); if (toFind.empty()) { @@ -858,7 +858,7 @@ MathValue Math_sqrt(const MathValueList& argList) // Convert string to upper case MathValue Math_upperCase(const MathValueList& argList) { - string str = argList[0].ToString(); + wstring str = argList[0].ToString(); transform(str.begin(), str.end(), str.begin(), ::toupper); return str; } diff --git a/lsapi/MathParser.h b/lsapi/MathParser.h index f3c92be..971c9ff 100644 --- a/lsapi/MathParser.h +++ b/lsapi/MathParser.h @@ -43,7 +43,7 @@ class MathParser /** * Constructor. */ - MathParser(const SettingsMap& context, const std::string& expression, + MathParser(const SettingsMap& context, const std::wstring& expression, const StringSet& recursiveVarSet, unsigned int flags = 0); /** @@ -55,12 +55,12 @@ class MathParser /** * Calls a function with the specified arguments and returns the result. */ - MathValue CallFunction(const std::string& name, const MathValueList& argList) const; + MathValue CallFunction(const std::wstring& name, const MathValueList& argList) const; /** * Returns the value of a variable. */ - MathValue GetVariable(const std::string& name) const; + MathValue GetVariable(const std::wstring& name) const; private: /** diff --git a/lsapi/MathScanner.cpp b/lsapi/MathScanner.cpp index 1474cd3..0f5cdc6 100644 --- a/lsapi/MathScanner.cpp +++ b/lsapi/MathScanner.cpp @@ -28,18 +28,18 @@ using namespace std; // Reserved words -struct ReservedWordTable { const char *str; int type; } gReservedWords[] = \ +struct ReservedWordTable { const wchar_t *str; int type; } gReservedWords[] = \ { - { "false", TT_FALSE }, - { "true", TT_TRUE }, - { "infinity", TT_INFINITY }, - { "nan", TT_NAN }, - { "defined", TT_DEFINED }, - { "div", TT_DIV }, - { "mod", TT_MOD }, - { "and", TT_AND }, - { "or", TT_OR }, - { "not", TT_NOT } + { L"false", TT_FALSE }, + { L"true", TT_TRUE }, + { L"infinity", TT_INFINITY }, + { L"nan", TT_NAN }, + { L"defined", TT_DEFINED }, + { L"div", TT_DIV }, + { L"mod", TT_MOD }, + { L"and", TT_AND }, + { L"or", TT_OR }, + { L"not", TT_NOT } }; const int gNumReservedWords = sizeof(gReservedWords) / sizeof(gReservedWords[0]); @@ -48,29 +48,29 @@ const int gNumReservedWords = sizeof(gReservedWords) / sizeof(gReservedWords[0]) // Operators and punctuation // Checked in this order so for example "<=" must precede "<". Must have enough // lookahead to recognize the longest symbol. -struct SymbolTable { const char *str; int length; int type; } gSymbols[] = \ +struct SymbolTable { const wchar_t *str; int length; int type; } gSymbols[] = \ { - { "(", 1, TT_LPAREN }, - { ")", 1, TT_RPAREN }, - { ",", 1, TT_COMMA }, - { "+", 1, TT_PLUS }, - { "-", 1, TT_MINUS }, - { "*", 1, TT_STAR }, - { "/", 1, TT_SLASH }, - { "&", 1, TT_AMPERSAND }, - { "=", 1, TT_EQUAL }, - { ">=", 2, TT_GREATEREQ }, - { ">", 1, TT_GREATER }, - { "<>", 2, TT_NOTEQUAL }, - { "<=", 2, TT_LESSEQ }, - { "<", 1, TT_LESS }, - { "!=", 2, TT_NOTEQUAL } + { L"(", 1, TT_LPAREN }, + { L")", 1, TT_RPAREN }, + { L",", 1, TT_COMMA }, + { L"+", 1, TT_PLUS }, + { L"-", 1, TT_MINUS }, + { L"*", 1, TT_STAR }, + { L"/", 1, TT_SLASH }, + { L"&", 1, TT_AMPERSAND }, + { L"=", 1, TT_EQUAL }, + { L">=", 2, TT_GREATEREQ }, + { L">", 1, TT_GREATER }, + { L"<>", 2, TT_NOTEQUAL }, + { L"<=", 2, TT_LESSEQ }, + { L"<", 1, TT_LESS }, + { L"!=", 2, TT_NOTEQUAL } }; const int gNumSymbols = sizeof(gSymbols) / sizeof(gSymbols[0]); -MathScanner::MathScanner(const string& expression) : +MathScanner::MathScanner(const wstring& expression) : mStream(expression) { // Fill the lookahead buffer @@ -83,7 +83,7 @@ MathToken MathScanner::NextToken() // Skip past whitespace SkipSpace(); - if (mLookahead[0] < 0) + if (mLookahead[0] == WEOF) { // End of input return MathToken(TT_END); @@ -98,7 +98,7 @@ MathToken MathScanner::NextToken() // Numeric literal return ScanNumber(); } - else if (mLookahead[0] == '\"' || mLookahead[0] == '\'') + else if (mLookahead[0] == L'\"' || mLookahead[0] == L'\'') { // String literal return ScanString(); @@ -126,15 +126,15 @@ MathToken MathScanner::NextToken() } // Error - throw MathException("Illegal character"); + throw MathException(L"Illegal character"); } -MathToken MathScanner::CheckReservedWord(const string& identifier) +MathToken MathScanner::CheckReservedWord(const wstring& identifier) { for (int i = 0; i < gNumReservedWords; ++i) { - if (_stricmp(identifier.c_str(), gReservedWords[i].str) == 0) + if (_wcsicmp(identifier.c_str(), gReservedWords[i].str) == 0) { // It's a reserved word return MathToken(gReservedWords[i].type); @@ -157,7 +157,7 @@ void MathScanner::Next(int count) if (!mStream.get(mLookahead[LOOKAHEAD - 1])) { - mLookahead[LOOKAHEAD - 1] = EOF; + mLookahead[LOOKAHEAD - 1] = WEOF; } } } @@ -165,7 +165,7 @@ void MathScanner::Next(int count) MathToken MathScanner::ScanIdentifier() { - ostringstream value; + wostringstream value; while (IsNameChar(mLookahead[0])) { @@ -179,7 +179,7 @@ MathToken MathScanner::ScanIdentifier() MathToken MathScanner::ScanNumber() { - ostringstream value; + wostringstream value; while (IsDigit(mLookahead[0])) { @@ -187,7 +187,7 @@ MathToken MathScanner::ScanNumber() Next(); } - if (mLookahead[0] == '.') + if (mLookahead[0] == L'.') { value.put(mLookahead[0]); Next(); @@ -205,33 +205,33 @@ MathToken MathScanner::ScanNumber() MathToken MathScanner::ScanString() { - ostringstream value; - char quote = mLookahead[0]; + wostringstream value; + wchar_t quote = mLookahead[0]; Next(); - while (mLookahead[0] != EOF && mLookahead[0] != quote) + while (mLookahead[0] != WEOF && mLookahead[0] != quote) { - if (mLookahead[0] == '\\') + if (mLookahead[0] == L'\\') { // Escape sequence Next(); switch (mLookahead[0]) { - case '\\': - value.put('\\'); + case L'\\': + value.put(L'\\'); break; - case '\"': - value.put('\"'); + case L'\"': + value.put(L'\"'); break; - case '\'': - value.put('\''); + case L'\'': + value.put(L'\''); break; default: - throw MathException("Illegal string escape sequence"); + throw MathException(L"Illegal string escape sequence"); } } else @@ -243,9 +243,9 @@ MathToken MathScanner::ScanString() Next(); } - if (mLookahead[0] == EOF) + if (mLookahead[0] == WEOF) { - throw MathException("Unterminated string literal"); + throw MathException(L"Unterminated string literal"); } Next(); @@ -262,48 +262,48 @@ void MathScanner::SkipSpace() } -bool MathScanner::IsDigit(char ch) +bool MathScanner::IsDigit(wchar_t ch) { - return (ch >= '0' && ch <= '9'); + return (ch >= L'0' && ch <= L'9'); } -bool MathScanner::IsFirstNameChar(char ch) +bool MathScanner::IsFirstNameChar(wchar_t ch) { return !IsDigit(ch) && IsNameChar(ch); } -bool MathScanner::IsNameChar(char ch) +bool MathScanner::IsNameChar(wchar_t ch) { - if (ch < 0 || IsSpace(ch)) + if (ch == WEOF || IsSpace(ch)) { return false; } switch (ch) { - case '!': + case L'!': // case '@': Will be reserved in 0.25 // case '#': Will be reserved in 0.25 - case '$': - case '&': - case '*': - case '(': - case ')': - case '-': - case '+': - case '=': - case '[': - case ']': + case L'$': + case L'&': + case L'*': + case L'(': + case L')': + case L'-': + case L'+': + case L'=': + case L'[': + case L']': // case '|': Will be reserved in 0.25 - case ';': - case '"': - case '\'': - case '<': - case '>': - case ',': - case '/': + case L';': + case L'"': + case L'\'': + case L'<': + case L'>': + case L',': + case L'/': return false; } @@ -311,7 +311,7 @@ bool MathScanner::IsNameChar(char ch) } -bool MathScanner::IsSpace(char ch) +bool MathScanner::IsSpace(wchar_t ch) { - return (ch == ' ' || ch == '\t'); // More than this? + return (ch == L' ' || ch == L'\t'); // More than this? } diff --git a/lsapi/MathScanner.h b/lsapi/MathScanner.h index 9e2fe3e..76781f6 100644 --- a/lsapi/MathScanner.h +++ b/lsapi/MathScanner.h @@ -36,7 +36,7 @@ class MathScanner /** * Constructs a MathScanner that reads from the specified string. */ - MathScanner(const std::string& expression); + MathScanner(const std::wstring& expression); /** * Extracts the next token from the input and returns it. @@ -48,7 +48,7 @@ class MathScanner * Returns a token for the specified identifier, first checking to see if * its a reserved word. */ - MathToken CheckReservedWord(const std::string& identifier); + MathToken CheckReservedWord(const std::wstring& identifier); /** * Read the next count characters from the input. @@ -79,33 +79,33 @@ class MathScanner /** * Returns true if a character is a digit. */ - static bool IsDigit(char ch); + static bool IsDigit(wchar_t ch); /** * Returns true if a character can appear as the first character in an * identifier (name). */ - static bool IsFirstNameChar(char ch); + static bool IsFirstNameChar(wchar_t ch); /** * Returns true if a character can appear in an identifier (name). */ - static bool IsNameChar(char ch); + static bool IsNameChar(wchar_t ch); /** * Returns true if a character is a space character. */ - static bool IsSpace(char ch); + static bool IsSpace(wchar_t ch); private: /** Number of characters of lookahead */ enum { LOOKAHEAD = 2 }; /** Character buffer */ - char mLookahead[LOOKAHEAD]; + wchar_t mLookahead[LOOKAHEAD]; /** Input stream */ - std::istringstream mStream; + std::wistringstream mStream; }; diff --git a/lsapi/MathToken.cpp b/lsapi/MathToken.cpp index 7bd9aac..40282ac 100644 --- a/lsapi/MathToken.cpp +++ b/lsapi/MathToken.cpp @@ -25,37 +25,37 @@ using namespace std; // Mapping of token types to names -struct TokenTypeTable { int type; const char *name; } gTokenTypes[] = \ +struct TokenTypeTable { int type; const wchar_t *name; } gTokenTypes[] = \ { - { TT_INVALID, "INVALID" }, - { TT_ID, "ID" }, - { TT_FALSE, "FALSE" }, - { TT_TRUE, "TRUE" }, - { TT_NUMBER, "NUMBER" }, - { TT_INFINITY, "INFINITY" }, - { TT_NAN, "NAN" }, - { TT_STRING, "STRING" }, - { TT_LPAREN, "LPAREN" }, - { TT_RPAREN, "RPAREN" }, - { TT_DEFINED, "DEFINED" }, - { TT_COMMA, "COMMA" }, - { TT_PLUS, "PLUS" }, - { TT_MINUS, "MINUS" }, - { TT_STAR, "STAR" }, - { TT_SLASH, "SLASH" }, - { TT_DIV, "DIV" }, - { TT_MOD, "MOD" }, - { TT_AMPERSAND, "AMPERSAND" }, - { TT_AND, "AND" }, - { TT_OR, "OR" }, - { TT_NOT, "NOT" }, - { TT_EQUAL, "EQUAL" }, - { TT_GREATER, "GREATER" }, - { TT_GREATEREQ, "GREATEREQ" }, - { TT_LESS, "LESS" }, - { TT_LESSEQ, "LESSEQ" }, - { TT_NOTEQUAL, "NOTEQUAL" }, - { TT_END, "END" } + { TT_INVALID, L"INVALID" }, + { TT_ID, L"ID" }, + { TT_FALSE, L"FALSE" }, + { TT_TRUE, L"TRUE" }, + { TT_NUMBER, L"NUMBER" }, + { TT_INFINITY, L"INFINITY" }, + { TT_NAN, L"NAN" }, + { TT_STRING, L"STRING" }, + { TT_LPAREN, L"LPAREN" }, + { TT_RPAREN, L"RPAREN" }, + { TT_DEFINED, L"DEFINED" }, + { TT_COMMA, L"COMMA" }, + { TT_PLUS, L"PLUS" }, + { TT_MINUS, L"MINUS" }, + { TT_STAR, L"STAR" }, + { TT_SLASH, L"SLASH" }, + { TT_DIV, L"DIV" }, + { TT_MOD, L"MOD" }, + { TT_AMPERSAND, L"AMPERSAND" }, + { TT_AND, L"AND" }, + { TT_OR, L"OR" }, + { TT_NOT, L"NOT" }, + { TT_EQUAL, L"EQUAL" }, + { TT_GREATER, L"GREATER" }, + { TT_GREATEREQ, L"GREATEREQ" }, + { TT_LESS, L"LESS" }, + { TT_LESSEQ, L"LESSEQ" }, + { TT_NOTEQUAL, L"NOTEQUAL" }, + { TT_END, L"END" } }; const int gNumTokenTypes = sizeof(gTokenTypes) / sizeof(gTokenTypes[0]); @@ -75,24 +75,24 @@ MathToken::MathToken(int type) : } -MathToken::MathToken(int type, const string& value) : +MathToken::MathToken(int type, const wstring& value) : mType(type), mValue(value) { // do nothing } -string MathToken::GetTypeName() const +wstring MathToken::GetTypeName() const { for (int i = 0; i < gNumTokenTypes; ++i) { if (gTokenTypes[i].type == mType) { - return string(gTokenTypes[i].name); + return wstring(gTokenTypes[i].name); } } - return string(); + return wstring(); } @@ -102,7 +102,7 @@ void MathToken::SetType(int type) } -void MathToken::SetValue(const string& value) +void MathToken::SetValue(const wstring& value) { mValue = value; } diff --git a/lsapi/MathToken.h b/lsapi/MathToken.h index 1cb0722..0d7a40e 100644 --- a/lsapi/MathToken.h +++ b/lsapi/MathToken.h @@ -81,7 +81,7 @@ class MathToken /** * Constructs a token with the specified type and lexical value. */ - MathToken(int type, const std::string& value); + MathToken(int type, const std::wstring& value); /** * Returns the type of this token. @@ -94,7 +94,7 @@ class MathToken /** * Returns a string description of this token's type. */ - std::string GetTypeName() const; + std::wstring GetTypeName() const; /** * Sets the type of this token. @@ -104,7 +104,7 @@ class MathToken /** * Returns the lexical value of this token. */ - std::string GetValue() const + std::wstring GetValue() const { return mValue; } @@ -112,14 +112,14 @@ class MathToken /** * Sets the lexical value of this token. */ - void SetValue(const std::string& value); + void SetValue(const std::wstring& value); private: /** Token type */ int mType; /** Lexical value */ - std::string mValue; + std::wstring mValue; }; diff --git a/lsapi/MathValue.cpp b/lsapi/MathValue.cpp index 6f68947..446be12 100644 --- a/lsapi/MathValue.cpp +++ b/lsapi/MathValue.cpp @@ -58,14 +58,14 @@ MathValue::MathValue(double value) : } -MathValue::MathValue(const string& value) : +MathValue::MathValue(const wstring& value) : mType(STRING), mString(value) { // do nothing } -MathValue::MathValue(const char *value) : +MathValue::MathValue(const wchar_t *value) : mType(STRING), mString(value) { // do nothing @@ -99,7 +99,7 @@ MathValue& MathValue::operator=(double value) } -MathValue& MathValue::operator=(const string& value) +MathValue& MathValue::operator=(const wstring& value) { mType = STRING; mString = value; @@ -108,7 +108,7 @@ MathValue& MathValue::operator=(const string& value) } -MathValue& MathValue::operator=(const char *value) +MathValue& MathValue::operator=(const wchar_t *value) { mType = STRING; mString = value; @@ -117,26 +117,26 @@ MathValue& MathValue::operator=(const char *value) } -string MathValue::GetTypeName() const +wstring MathValue::GetTypeName() const { switch (mType) { case UNDEFINED: - return "undefined"; + return L"undefined"; case BOOLEAN: - return "boolean"; + return L"boolean"; case NUMBER: - return "number"; + return L"number"; case STRING: - return "string"; + return L"string"; } // Should never happen ASSERT(false); - return string(); + return wstring(); } @@ -154,7 +154,7 @@ bool MathValue::ToBoolean() const return (mNumber != 0.0 && !_isnan(mNumber)); case STRING: - return (!mString.empty() && _stricmp(mString.c_str(), "false") != 0); + return (!mString.empty() && _wcsicmp(mString.c_str(), L"false") != 0); } // Should never happen @@ -193,15 +193,15 @@ double MathValue::ToNumber() const } -string MathValue::ToString() const +wstring MathValue::ToString() const { switch (mType) { case UNDEFINED: - return "undefined"; + return L"undefined"; case BOOLEAN: - return mBoolean ? "true" : "false"; + return mBoolean ? L"true" : L"false"; case NUMBER: return MathNumberToString(mNumber); @@ -212,11 +212,11 @@ string MathValue::ToString() const // Should never happen ASSERT(false); - return string(); + return wstring(); } -string MathValue::ToCompatibleString() const +wstring MathValue::ToCompatibleString() const { // To keep compatible with 0.24.x math evaluations, we must // return an integer formatted string for all number type @@ -224,7 +224,7 @@ string MathValue::ToCompatibleString() const // to returning it as a string. if (NUMBER == mType) { - ostringstream stream; + wostringstream stream; stream << ToInteger(); @@ -515,12 +515,12 @@ MathValue MathIntDivide(const MathValue& a, const MathValue& b) } -string MathNumberToString(double number) +wstring MathNumberToString(double number) { if (_finite(number)) { // Number - ostringstream stream; + wostringstream stream; stream.precision(numeric_limits::digits10 + 1); stream << number; @@ -530,24 +530,24 @@ string MathNumberToString(double number) else if (number == numeric_limits::infinity()) { // Positive infinity - return "Infinity"; + return L"Infinity"; } else if (number == -numeric_limits::infinity()) { // Negative infinity - return "-Infinity"; + return L"-Infinity"; } else { // Not a Number (NaN) - return "NaN"; + return L"NaN"; } } -double MathStringToNumber(const string& str) +double MathStringToNumber(const wstring& str) { - istringstream stream(str); + wistringstream stream(str); double number; if (stream >> number) @@ -555,12 +555,12 @@ double MathStringToNumber(const string& str) // Number return number; } - else if (_stricmp(str.c_str(), "Infinity") == 0) + else if (_wcsicmp(str.c_str(), L"Infinity") == 0) { // Positive infinity return numeric_limits::infinity(); } - else if (_stricmp(str.c_str(), "-Infinity") == 0) + else if (_wcsicmp(str.c_str(), L"-Infinity") == 0) { // Negative infinity return -numeric_limits::infinity(); diff --git a/lsapi/MathValue.h b/lsapi/MathValue.h index 50225da..266f032 100644 --- a/lsapi/MathValue.h +++ b/lsapi/MathValue.h @@ -66,12 +66,12 @@ class MathValue /** * Constructs a string value. */ - MathValue(const std::string& value); + MathValue(const std::wstring& value); /** * Constructs a string value. */ - MathValue(const char *value); + MathValue(const wchar_t *value); /** * Assigns a Boolean to this value. @@ -91,17 +91,17 @@ class MathValue /** * Assigns a string to this value. */ - MathValue& operator=(const std::string& value); + MathValue& operator=(const std::wstring& value); /** * Assigns a string to this value. */ - MathValue& operator=(const char *value); + MathValue& operator=(const wchar_t *value); /** * Returns a string description of this value's type. */ - std::string GetTypeName() const; + std::wstring GetTypeName() const; /** * Returns true if this value is undefined. @@ -153,13 +153,13 @@ class MathValue /** * Converts this value to a string. */ - std::string ToString() const; + std::wstring ToString() const; /** * Converts this value to a string using integer representation * for any NUMBER type. */ - std::string ToCompatibleString() const; + std::wstring ToCompatibleString() const; /** Operators */ friend MathValue operator+ (const MathValue& a, const MathValue& b); @@ -190,7 +190,7 @@ class MathValue double mNumber; /** String value */ - std::string mString; + std::wstring mString; }; @@ -201,10 +201,10 @@ MathValue MathConcatenate(const MathValue& a, const MathValue& b); MathValue MathIntDivide(const MathValue& a, const MathValue& b); /** Convert a number to a string. */ -std::string MathNumberToString(double number); +std::wstring MathNumberToString(double number); /** Convert a string to a number. */ -double MathStringToNumber(const std::string& str); +double MathStringToNumber(const std::wstring& str); #endif // MATHVALUE_H diff --git a/lsapi/SettingsDefines.h b/lsapi/SettingsDefines.h index 23a607e..91c210f 100644 --- a/lsapi/SettingsDefines.h +++ b/lsapi/SettingsDefines.h @@ -29,13 +29,13 @@ /** Maps setting names to values */ -typedef std::multimap SettingsMap; +typedef std::multimap SettingsMap; /** Maps setting names to iterators */ -typedef std::map IteratorMap; +typedef std::map IteratorMap; /** Set of strings with case-insensitive ordering. */ -typedef std::set StringSet; +typedef std::set StringSet; #endif // SETTINGSDEFINES_H_ diff --git a/lsapi/SettingsFileParser.cpp b/lsapi/SettingsFileParser.cpp index e6a655a..d2c784f 100644 --- a/lsapi/SettingsFileParser.cpp +++ b/lsapi/SettingsFileParser.cpp @@ -22,6 +22,9 @@ #include "SettingsFileParser.h" #include "MathEvaluate.h" #include "../utility/core.hpp" +#include "../utility/macros.h" +#include +#include //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -29,7 +32,18 @@ // FileParser constructor // FileParser::FileParser(SettingsMap* pSettingsMap) : - m_pSettingsMap(pSettingsMap), m_phFile(NULL) + m_pSettingsMap(pSettingsMap), m_phFile(NULL), m_trail(m_baseTrail) +{ + ASSERT(NULL != m_pSettingsMap); +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// FileParser constructor +// +FileParser::FileParser(SettingsMap* pSettingsMap, std::list &trail) : + m_pSettingsMap(pSettingsMap), m_phFile(NULL), m_trail(trail) { ASSERT(NULL != m_pSettingsMap); } @@ -51,33 +65,67 @@ FileParser::~FileParser() // void FileParser::ParseFile(LPCTSTR ptzFileName) { - ASSERT(NULL == m_phFile); - ASSERT(NULL != ptzFileName); + ASSERT(nullptr == m_phFile); + ASSERT(nullptr != ptzFileName); TCHAR tzExpandedPath[MAX_PATH_LENGTH]; - VarExpansionEx(tzExpandedPath, ptzFileName, MAX_PATH_LENGTH); + VarExpansionExW(tzExpandedPath, ptzFileName, MAX_PATH_LENGTH); PathUnquoteSpaces(tzExpandedPath); DWORD dwLen = GetFullPathName( - tzExpandedPath, MAX_PATH_LENGTH, m_tzFullPath, NULL); + tzExpandedPath, MAX_PATH_LENGTH, m_tzFullPath, nullptr); if (0 == dwLen || dwLen > MAX_PATH_LENGTH) { - TRACE("Error: Can not get full path for \"%s\"", tzExpandedPath); + TRACE("Error: Can not get full path for \"%ls\"", tzExpandedPath); + return; + } + + std::list::iterator check = std::find(m_trail.begin(), m_trail.end(), TrailItem(0, m_tzFullPath)); + if (check != m_trail.end()) + { + TCHAR trail[MAX_LINE_LENGTH]; + TCHAR line[MAX_LINE_LENGTH]; + + *trail = _T('\0'); + *line = _T('\0'); + for (; check != m_trail.end(); ++check) + { + StringCchCat(trail, _countof(trail), _T("\"")); + StringCchCat(trail, _countof(trail), check->ptzPath); + StringCchCat(trail, _countof(trail), _T("\"")); + StringCchCat(trail, _countof(trail), line); + StringCchPrintf(line, _countof(line), _T(" on line %d"), check->uLine); + StringCchCat(trail, _countof(trail), _T("\nIncludes ")); + } + StringCchCat(trail, _countof(trail), _T("\"")); + StringCchCat(trail, _countof(trail), m_tzFullPath); + StringCchCat(trail, _countof(trail), _T("\"")); + StringCchCat(trail, _countof(trail), line); + + RESOURCE_STREX( + GetModuleHandle(NULL), IDS_RECURSIVEINCLUDE, + resourceTextBuffer, MAX_LINE_LENGTH, + L"Error: Reursive include detected!\n %ls.", + trail); + + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); + return; } - m_phFile = _tfopen(m_tzFullPath, _T("r")); + _tfopen_s(&m_phFile, m_tzFullPath, _T("r")); - if (NULL == m_phFile) + if (nullptr == m_phFile) { - TRACE("Error: Can not open file \"%s\" (Defined as \"%s\").", + TRACE("Error: Can not open file \"%ls\" (Defined as \"%ls\").", m_tzFullPath, ptzFileName); return; } - TRACE("Parsing \"%s\"", m_tzFullPath); + TRACE("Parsing \"%ls\"", m_tzFullPath); + m_trail.push_back(TrailItem(0, m_tzFullPath)); fseek(m_phFile, 0, SEEK_SET); @@ -86,15 +134,17 @@ void FileParser::ParseFile(LPCTSTR ptzFileName) m_uLineNumber = 0; + _ReadNextLine(m_tzReadAhead); while (_ReadLineFromFile(tzKey, tzValue)) { _ProcessLine(tzKey, tzValue); } fclose(m_phFile); - m_phFile = NULL; + m_phFile = nullptr; + m_trail.pop_back(); - TRACE("Finished Parsing \"%s\"", m_tzFullPath); + TRACE("Finished Parsing \"%ls\"", m_tzFullPath); } @@ -102,17 +152,18 @@ void FileParser::ParseFile(LPCTSTR ptzFileName) // // _ReadLineFromFile // -// ptzName must be MAX_RCCOMMAND size -// ptzValue must be MAX_LINE_LENGTH size (or NULL) +// ptzBuffer must be MAX_LINE_LENGTH size // -bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) +bool FileParser::_ReadNextLine(LPTSTR ptzBuffer) { - ASSERT(NULL != m_phFile); - ASSERT(NULL != ptzName); - + ASSERT(nullptr != m_phFile); + ASSERT(nullptr != ptzBuffer); + TCHAR tzBuffer[MAX_LINE_LENGTH]; bool bReturn = false; - + + ptzBuffer[0] = _T('\0'); + while (!feof(m_phFile) && !bReturn) { if (!_fgetts(tzBuffer, MAX_LINE_LENGTH, m_phFile)) @@ -122,14 +173,14 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) } ++m_uLineNumber; - + LPTSTR ptzCurrent = tzBuffer; - + // Jump over any initial whitespace ptzCurrent += _tcsspn(ptzCurrent, WHITESPACE); // Ignore empty lines, and comments - if (ptzCurrent[0] && ptzCurrent[0] != _T(';')) + if (ptzCurrent[0] != '\0' && ptzCurrent[0] != _T(';')) { // End on first reserved character or whitespace size_t stEndConfig = _tcscspn(ptzCurrent, WHITESPACE RESERVEDCHARS); @@ -138,14 +189,92 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) // then the line has an invalid format. Ignore it. if (_tcschr(WHITESPACE _T(";"), ptzCurrent[stEndConfig]) == NULL) { - TRACE("Syntax Error (%s, %d): Invalid line format", + TRACE("Syntax Error (%ls, %d): Invalid line format", m_tzFullPath, m_uLineNumber); continue; } - + + StringCchCopy(ptzBuffer, MAX_LINE_LENGTH, ptzCurrent); + bReturn = true; + } + } + + return bReturn; +} + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// _ReadLineFromFile +// +// ptzName must be MAX_RCCOMMAND size +// ptzValue must be MAX_LINE_LENGTH size (or NULL) +// +bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) +{ + ASSERT(NULL != m_phFile); + ASSERT(NULL != ptzName); + + bool bReturn = false; + + if (m_tzReadAhead[0] == '}') + { + if (m_stPrefixes.empty()) + { + TRACE("Syntax Error (%ls, %d): Unexpected }", + m_tzFullPath, m_uLineNumber); + } + else + { + m_stPrefixes.pop(); + } + + // Skip this line + _ReadNextLine(m_tzReadAhead); + bReturn = _ReadLineFromFile(ptzName, ptzValue); + } + else if (m_tzReadAhead[0] != _T('\0')) + { + LPTSTR ptzCurrent = m_tzReadAhead; + + // End on first reserved character or whitespace + size_t stEndConfig = _tcscspn(ptzCurrent, WHITESPACE RESERVEDCHARS); + + if (stEndConfig != 0) + { + ptzName[0] = _T('\0'); + + // Apply any prefix, as necesary + if (!m_stPrefixes.empty()) + { + // If the key starts with a *, put that * at the begining + if (*ptzCurrent == _T('*')) + { + StringCchCat(ptzName, MAX_RCCOMMAND, _T("*")); + ++ptzCurrent; + --stEndConfig; + } + + // Don't apply prefixes to special keywords + if (!( _tcsnicmp(ptzCurrent, _T("if"), stEndConfig) == 0 + || _tcsnicmp(ptzCurrent, _T("else"), stEndConfig) == 0 + || _tcsnicmp(ptzCurrent, _T("elseif"), stEndConfig) == 0 + || _tcsnicmp(ptzCurrent, _T("endif"), stEndConfig) == 0 + )) + { + StringCchCat(ptzName, MAX_RCCOMMAND, m_stPrefixes.top().tzString); + } + + // If the keyname is simply -, ignore it. + if (_tcsnicmp(ptzCurrent, _T("-"), stEndConfig) == 0) + { + ++ptzCurrent; + stEndConfig = 0; + } + } + // Copy directive name to ptzName. - if (stEndConfig && SUCCEEDED(StringCchCopyN( - ptzName, MAX_RCCOMMAND, ptzCurrent, stEndConfig))) + if (SUCCEEDED(StringCchCatN(ptzName, MAX_RCCOMMAND, ptzCurrent, stEndConfig))) { // If ptzValue is NULL, then the caller doesn't want the value, // however, we still will return TRUE. If the caller does want @@ -166,6 +295,19 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) } bReturn = true; + + // Reads the next line + if (_ReadNextLine(m_tzReadAhead)) + { + if (m_tzReadAhead[0] == '{') + { + m_stPrefixes.push(TCStack(ptzName)); + + // Skip these 2 lines. + _ReadNextLine(m_tzReadAhead); + bReturn = _ReadLineFromFile(ptzName, ptzValue); + } + } } } } @@ -190,7 +332,7 @@ void FileParser::_StripString(LPTSTR ptzString) while (*ptzCurrent != _T('\0')) { - if (strchr(WHITESPACE, *ptzCurrent) == NULL) + if (wcschr(WHITESPACE, *ptzCurrent) == NULL) { if (ptzStart == NULL) { @@ -246,7 +388,7 @@ void FileParser::_StripString(LPTSTR ptzString) if (ptzLast != NULL) { - while (ptzLast > ptzString && strchr(WHITESPACE, *(ptzLast-1))) + while (ptzLast > ptzString && wcschr(WHITESPACE, *(ptzLast-1))) { --ptzLast; } @@ -256,7 +398,7 @@ void FileParser::_StripString(LPTSTR ptzString) if (ptzStart != NULL && ptzStart != ptzString) { - StringCchCopy(ptzString, strlen(ptzString) + 1, ptzStart); + StringCchCopy(ptzString, wcslen(ptzString) + 1, ptzStart); } } @@ -270,7 +412,7 @@ void FileParser::_ProcessLine(LPCTSTR ptzName, LPCTSTR ptzValue) ASSERT(NULL != m_pSettingsMap); ASSERT(NULL != ptzName); ASSERT(NULL != ptzValue); - if (_stricmp(ptzName, _T("if")) == 0) + if (_wcsicmp(ptzName, _T("if")) == 0) { _ProcessIf(ptzValue); } @@ -278,45 +420,46 @@ void FileParser::_ProcessLine(LPCTSTR ptzName, LPCTSTR ptzValue) // In a release build ignore dangling elseif/else/endif. // Too much overhead just for error handling else if ( - (_stricmp(ptzName, "else") == 0) - || (_stricmp(ptzName, "elseif") == 0) - || (_stricmp(ptzName, "endif") == 0) + (_wcsicmp(ptzName, L"else") == 0) + || (_wcsicmp(ptzName, L"elseif") == 0) + || (_wcsicmp(ptzName, L"endif") == 0) ) { - TRACE("Error: Dangling pre-processor directive (%s, line %d): \"%s\"", + TRACE("Error: Dangling pre-processor directive (%ls, line %d): \"%ls\"", m_tzFullPath, m_uLineNumber, ptzName); } #endif - else if (_stricmp(ptzName, "include") == 0) + else if (_wcsicmp(ptzName, L"include") == 0) { TCHAR tzPath[MAX_PATH_LENGTH] = { 0 }; - if (!GetToken(ptzValue, tzPath, NULL, FALSE)) + if (!GetTokenW(ptzValue, tzPath, NULL, FALSE)) { - TRACE("Syntax Error (%s, %d): Empty \"Include\" directive", + TRACE("Syntax Error (%ls, %d): Empty \"Include\" directive", m_tzFullPath, m_uLineNumber); return; } - TRACE("Include (%s, line %d): \"%s\"", + TRACE("Include (%ls, line %d): \"%ls\"", m_tzFullPath, m_uLineNumber, tzPath); - FileParser fpParser(m_pSettingsMap); + m_trail.back().uLine = m_uLineNumber; + FileParser fpParser(m_pSettingsMap, m_trail); fpParser.ParseFile(tzPath); } #if defined(LS_CUSTOM_INCLUDEFOLDER) - else if (_stricmp(ptzName, _T("includefolder")) == 0) + else if (_wcsicmp(ptzName, _T("includefolder")) == 0) { TCHAR tzPath[MAX_PATH_LENGTH]; // path+pattern TCHAR tzFilter[MAX_PATH_LENGTH]; // path only // expands string in ptzValue to tzPath // buffer size defined by MAX_PATH_LENGTH - VarExpansionEx(tzPath, ptzValue, MAX_PATH_LENGTH); + VarExpansionExW(tzPath, ptzValue, MAX_PATH_LENGTH); PathUnquoteSpaces(tzPath); // strips quotation marks from string - TRACE("Searching IncludeFolder (%s, line %d): \"%s\"", + TRACE("Searching IncludeFolder (%ls, line %d): \"%ls\"", m_tzFullPath, m_uLineNumber, tzPath); // Hard-coded filter for *.rc files to limit search operation. @@ -329,11 +472,17 @@ void FileParser::_ProcessLine(LPCTSTR ptzName, LPCTSTR ptzValue) // Looking in tzFilter for data :) HANDLE hSearch = FindFirstFile(tzFilter, &findData); + + // List of found files + std::vector foundFiles; + + // + auto fileComparer = [] (const std::wstring s1, const std::wstring s2) -> bool { + return (_wcsicmp(s1.c_str(), s2.c_str()) > 0); + }; if (INVALID_HANDLE_VALUE != hSearch) { - BOOL FoundNextFile; - do { // stripping out directories, system and hidden files as @@ -345,27 +494,35 @@ void FileParser::_ProcessLine(LPCTSTR ptzName, LPCTSTR ptzValue) if (0 == (dwAttrib & findData.dwFileAttributes)) { - // Processing the valid cFileName data now. - TCHAR tzFile[MAX_PATH_LENGTH]; - - // adding (like above) filename to tzPath to set tzFile - // for opening. - if (tzFile == PathCombine(tzFile, tzPath, findData.cFileName)) - { - TRACE("Found and including: \"%s\"", tzFile); - - FileParser fpParser(m_pSettingsMap); - fpParser.ParseFile(tzFile); - } + foundFiles.push_back(findData.cFileName); + std::push_heap(foundFiles.begin(), foundFiles.end(), fileComparer); } - - FoundNextFile = FindNextFile(hSearch, &findData); - } while (FoundNextFile); + } while (FindNextFile(hSearch, &findData) != FALSE); FindClose(hSearch); } + + while (!foundFiles.empty()) + { + // Processing the valid cFileName data now. + TCHAR tzFile[MAX_PATH_LENGTH]; + + // adding (like above) filename to tzPath to set tzFile + // for opening. + m_trail.back().uLine = m_uLineNumber; + if (tzFile == PathCombine(tzFile, tzPath, foundFiles.begin()->c_str())) + { + TRACE("Found and including: \"%ls\"", tzFile); + + FileParser fpParser(m_pSettingsMap, m_trail); + fpParser.ParseFile(tzFile); + } + + std::pop_heap(foundFiles.begin(), foundFiles.end(), fileComparer); + foundFiles.pop_back(); + } - TRACE("Done searching IncludeFolder (%s, line %d): \"%s\"", + TRACE("Done searching IncludeFolder (%ls, line %d): \"%ls\"", m_tzFullPath, m_uLineNumber, tzPath); } #endif // LS_CUSTOM_INCLUDEFOLDER @@ -389,7 +546,7 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) if (!MathEvaluateBool(*m_pSettingsMap, ptzExpression, result)) { - TRACE("Error parsing expression \"%s\" (%s, line %d)", + TRACE("Error parsing expression \"%ls\" (%ls, line %d)", ptzExpression, m_tzFullPath, m_uLineNumber); // Invalid syntax, so quit processing entire conditional block @@ -397,7 +554,7 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) return; } - TRACE("Expression (%s, line %d): \"%s\" evaluated to %s", + TRACE("Expression (%ls, line %d): \"%ls\" evaluated to %ls", m_tzFullPath, m_uLineNumber, ptzExpression, result ? "TRUE" : "FALSE"); @@ -410,14 +567,14 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) // an ElseIf. Else, or EndIf while (_ReadLineFromFile(tzName, tzValue)) { - if ((_stricmp(tzName, _T("else")) == 0) || - (_stricmp(tzName, _T("elseif")) == 0)) + if ((_tcsicmp(tzName, _T("else")) == 0) || + (_tcsicmp(tzName, _T("elseif")) == 0)) { // After an ElseIf or Else, skip all lines until EndIf _SkipIf(); break; } - else if (_stricmp(tzName, _T("endif")) == 0) + else if (_tcsicmp(tzName, _T("endif")) == 0) { // We're done break; @@ -435,27 +592,27 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) // ElseIf, Else, or EndIf while (_ReadLineFromFile(tzName, tzValue)) { - if (_stricmp(tzName, _T("if")) == 0) + if (_tcsicmp(tzName, _T("if")) == 0) { // Nested Ifs are a special case _SkipIf(); } - else if (_stricmp(tzName, _T("elseif")) == 0) + else if (_tcsicmp(tzName, _T("elseif")) == 0) { // Handle ElseIfs by recursively calling ProcessIf _ProcessIf(tzValue); break; } - else if (_stricmp(tzName, _T("else")) == 0) + else if (_tcsicmp(tzName, _T("else")) == 0) { // Since the If expression was false, when we see Else we // start processing lines until EndIf while (_ReadLineFromFile(tzName, tzValue)) { - if (_stricmp(tzName, "elseif") == 0) + if (_tcsicmp(tzName, _T("elseif")) == 0) { // Error: ElseIf after Else - TRACE("Syntax Error (%s, %d): " + TRACE("Syntax Error (%ls, %d): " "\"ElseIf\" directive after \"Else\"", m_tzFullPath, m_uLineNumber); @@ -463,7 +620,7 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) _SkipIf(); break; } - else if (_stricmp(tzName, _T("endif")) == 0) + else if (_tcsicmp(tzName, _T("endif")) == 0) { // We're done break; @@ -477,7 +634,7 @@ void FileParser::_ProcessIf(LPCTSTR ptzExpression) // We're done break; } - else if (_stricmp(tzName, _T("endif")) == 0) + else if (_tcsicmp(tzName, _T("endif")) == 0) { // We're done break; @@ -497,11 +654,11 @@ void FileParser::_SkipIf() while (_ReadLineFromFile(tzName, NULL)) { - if (_stricmp(tzName, _T("if")) == 0) + if (_tcsicmp(tzName, _T("if")) == 0) { _SkipIf(); } - else if (_stricmp(tzName, _T("endif")) == 0) + else if (_tcsicmp(tzName, _T("endif")) == 0) { break; } diff --git a/lsapi/SettingsFileParser.h b/lsapi/SettingsFileParser.h index d0f3e69..9c33a0f 100644 --- a/lsapi/SettingsFileParser.h +++ b/lsapi/SettingsFileParser.h @@ -24,6 +24,9 @@ #include "settingsdefines.h" #include "lsapidefines.h" +#include +#include +#include /** @@ -43,7 +46,37 @@ class FileParser //: boost::noncopyable * Destructor. */ ~FileParser(); - + +private: + /** Item used to check for recursive includes. */ + struct TrailItem { + TrailItem(UINT uLine, LPCTSTR ptzPath) { + this->uLine = uLine; + this->ptzPath = ptzPath; + } + bool operator==(const TrailItem & item) { + return _tcsicmp(item.ptzPath, this->ptzPath) == 0; + } + UINT uLine; + LPCTSTR ptzPath; + }; + +private: + /** + * Constructor. + * + * @param pSettingsMap SettingsMap to receive settings from files + */ + FileParser(SettingsMap* pSettingsMap, std::list &trail); + +private: + /** + * Not implemented. + */ + FileParser(const FileParser &); + FileParser& operator=(const FileParser&); + +public: /** * Parses a configuration file. Settings read from the file are added to * the SettingsMap object passed in to the FileParser constructor. @@ -55,6 +88,12 @@ class FileParser //: boost::noncopyable private: /** Settings map to receive settings read from file */ SettingsMap* m_pSettingsMap; + + /** Reference to the current trail of included files */ + std::list &m_trail; + + /** Where the trail is actually stored, in the top-level parser */ + std::list m_baseTrail; /** Handle to current file */ FILE* m_phFile; @@ -65,6 +104,25 @@ class FileParser //: boost::noncopyable /** Full path to configuration file */ TCHAR m_tzFullPath[MAX_PATH_LENGTH]; + /** Contains an RC key */ + struct TCStack { + TCStack(LPCTSTR ptzString) { + StringCchCopy(this->tzString, _countof(this->tzString), ptzString); + } + TCHAR tzString[MAX_RCCOMMAND]; + }; + + /** Stack of prefixes. */ + std::stack m_stPrefixes; + + /** The next line to be parsed by _ReadLineFromFile */ + TCHAR m_tzReadAhead[MAX_LINE_LENGTH]; + + /** + * Reads the next line from the current file. + */ + bool _ReadNextLine(LPTSTR ptzBuffer); + /** * Reads the next line from current file. The line is split into a setting * name and a setting value and the value is stripped of extraneous space diff --git a/lsapi/SettingsIterator.cpp b/lsapi/SettingsIterator.cpp index 14b0423..3d7172d 100644 --- a/lsapi/SettingsIterator.cpp +++ b/lsapi/SettingsIterator.cpp @@ -24,41 +24,41 @@ #include "../utility/core.hpp" #include -using std::string; +using std::wstring; -SettingsIterator::SettingsIterator(SettingsMap* pSettingsMap, const string& szPath) +SettingsIterator::SettingsIterator(SettingsMap* pSettingsMap, const wstring& sPath) { if (pSettingsMap) { m_pSettingsMap = pSettingsMap; m_pFileIterator = m_pSettingsMap->begin(); - if (szPath.length()) + if (sPath.length()) { - m_Path = szPath; + m_sPath = sPath; } } } -BOOL SettingsIterator::ReadNextLine(LPSTR pszValue, size_t cchValue) +BOOL SettingsIterator::ReadNextLine(LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; - if (pszValue != NULL && cchValue > 0) + if (pwzValue != nullptr && cchValue > 0) { if (m_pFileIterator != m_pSettingsMap->end()) { - StringCchCopy(pszValue, cchValue, m_pFileIterator->first.c_str()); - StringCchCat(pszValue, cchValue, " "); - StringCchCat(pszValue, cchValue, m_pFileIterator->second.c_str()); + StringCchCopyW(pwzValue, cchValue, m_pFileIterator->first.c_str()); + StringCchCatW(pwzValue, cchValue, L" "); + StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.c_str()); ++m_pFileIterator; bReturn = TRUE; } else { - pszValue[0] = '\0'; + pwzValue[0] = L'\0'; } } @@ -66,7 +66,7 @@ BOOL SettingsIterator::ReadNextLine(LPSTR pszValue, size_t cchValue) } -BOOL SettingsIterator::ReadNextCommand(LPSTR pszValue, size_t cchValue) +BOOL SettingsIterator::ReadNextCommand(LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; @@ -74,9 +74,9 @@ BOOL SettingsIterator::ReadNextCommand(LPSTR pszValue, size_t cchValue) { if (!ispunct(*(m_pFileIterator->first.c_str()))) { - StringCchCopy(pszValue, cchValue, m_pFileIterator->first.c_str()); - StringCchCat(pszValue, cchValue, " "); - StringCchCat(pszValue, cchValue, m_pFileIterator->second.c_str()); + StringCchCopyW(pwzValue, cchValue, m_pFileIterator->first.c_str()); + StringCchCatW(pwzValue, cchValue, L" "); + StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.c_str()); bReturn = TRUE; } @@ -87,45 +87,45 @@ BOOL SettingsIterator::ReadNextCommand(LPSTR pszValue, size_t cchValue) } -BOOL SettingsIterator::ReadNextConfig(LPCSTR pszConfig, LPSTR pszValue, size_t cchValue) +BOOL SettingsIterator::ReadNextConfig(LPCWSTR pwzConfig, LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; - if (pszValue != NULL && cchValue > 0 && pszConfig != NULL) + if (pwzValue != nullptr && cchValue > 0 && pwzConfig != nullptr) { SettingsMap::iterator itSettings; - pszValue[0] = '\0'; + pwzValue[0] = L'\0'; #if defined(LS_COMPAT_LCREADNEXTCONFIG) string sConfig; - if('*' != *pszConfig) + if(L'*' != *pwzConfig) { - sConfig = "*"; - sConfig += pszConfig; + sConfig = L"*"; + sConfig += pwzConfig; } else { - sConfig = pszConfig; + sConfig = pwzConfig; } - pszConfig = sConfig.c_str(); + pwzConfig = sConfig.c_str(); #endif // defined(LS_COMPAT_LCREADNEXTCONFIG) // Has ReadNextConfig been used before for pszConfig? - IteratorMap::iterator it = m_Iterators.find(pszConfig); + IteratorMap::iterator it = m_Iterators.find(pwzConfig); if (it == m_Iterators.end()) { // No, so find the first item with a key of pszConfig - itSettings = m_pSettingsMap->lower_bound(pszConfig); + itSettings = m_pSettingsMap->lower_bound(pwzConfig); - if (_stricmp(itSettings->first.c_str(), pszConfig) == 0) + if (_wcsicmp(itSettings->first.c_str(), pwzConfig) == 0) { // Save the iterator for future use and return the value it = (m_Iterators.insert( - IteratorMap::value_type(pszConfig, itSettings) + IteratorMap::value_type(pwzConfig, itSettings) )).first; bReturn = TRUE; @@ -134,14 +134,14 @@ BOOL SettingsIterator::ReadNextConfig(LPCSTR pszConfig, LPSTR pszValue, size_t c else { // Yes so find the last item with a matching key - itSettings = m_pSettingsMap->upper_bound(pszConfig); + itSettings = m_pSettingsMap->upper_bound(pwzConfig); // Loop until we either find an item with a matching key or the // last matching item do { ++it->second; - } while ((_stricmp(pszConfig, it->first.c_str()) != 0) && + } while ((_wcsicmp(pwzConfig, it->first.c_str()) != 0) && (it->second != itSettings)); // If we found a valid item, return it @@ -153,9 +153,9 @@ BOOL SettingsIterator::ReadNextConfig(LPCSTR pszConfig, LPSTR pszValue, size_t c if (bReturn) { - StringCchCopy(pszValue, cchValue, it->second->first.c_str()); - StringCchCat(pszValue, cchValue, " "); - StringCchCat(pszValue, cchValue, it->second->second.c_str()); + StringCchCopyW(pwzValue, cchValue, it->second->first.c_str()); + StringCchCatW(pwzValue, cchValue, L" "); + StringCchCatW(pwzValue, cchValue, it->second->second.c_str()); } } diff --git a/lsapi/SettingsIterator.h b/lsapi/SettingsIterator.h index e86c4a6..754b2fa 100644 --- a/lsapi/SettingsIterator.h +++ b/lsapi/SettingsIterator.h @@ -37,48 +37,48 @@ class SettingsIterator * with the given file. * * @param pSettingsMap SettingsMap to iterate over - * @param szPath Path to configuration file + * @param sPath Path to configuration file */ - SettingsIterator(SettingsMap* pSettingsMap, const std::string& szPath); + SettingsIterator(SettingsMap* pSettingsMap, const std::wstring& sPath); /** * Retrieve the next value. * - * @param pszValue buffer to receive value + * @param pwzValue buffer to receive value * @param cchValue size of buffer * @return TRUE if operation succeeded or FALSE * if there are no more values to retrieve */ - BOOL ReadNextLine(LPSTR pszValue, size_t cchValue); + BOOL ReadNextLine(LPWSTR pwzValue, size_t cchValue); /** * Retrieve the next value that does not start with an '*'. * - * @param pszValue buffer to receive value + * @param pwzValue buffer to receive value * @param cchValue size of buffer * @return TRUE if operation succeeded or FALSE * if there are no more values to retrieve */ - BOOL ReadNextCommand(LPSTR pszValue, size_t cchValue); + BOOL ReadNextCommand(LPWSTR pwzValue, size_t cchValue); /** * Retrieve the next value with the specified setting name that starts * with an '*'. * - * @param pszConfig setting name - * @param pszValue buffer to receive value + * @param pwzConfig setting name + * @param pwzValue buffer to receive value * @param cchValue size of buffer * @return TRUE if operation succeeded or FALSE * if there are no more values to retrieve */ - BOOL ReadNextConfig(LPCSTR pszConfig, LPSTR pszValue, size_t cchValue); + BOOL ReadNextConfig(LPCWSTR pwzConfig, LPWSTR pszValue, size_t cchValue); /** * Returns path to configuration file. */ - std::string getPath() + std::wstring getPath() { - return m_Path; + return m_sPath; } private: @@ -92,7 +92,7 @@ class SettingsIterator IteratorMap m_Iterators; /** Path to configuration file */ - std::string m_Path; + std::wstring m_sPath; }; diff --git a/lsapi/SettingsManager.h b/lsapi/SettingsManager.h index 8aa3bf7..dcc2979 100644 --- a/lsapi/SettingsManager.h +++ b/lsapi/SettingsManager.h @@ -48,7 +48,7 @@ struct FileInfo typedef std::set IteratorSet; /** Maps file names to FileInfo structures. */ -typedef std::map FileMap; +typedef std::map FileMap; /** @@ -79,12 +79,12 @@ class SettingsManager /** * Searches for a global setting by name. * - * @param pszName setting name + * @param pwzName setting name * @param it iterator to be set to point to setting * @return TRUE if the setting exists or FALSE * otherwise */ - BOOL _FindLine(LPCSTR pszName, SettingsMap::iterator &it); + BOOL _FindLine(LPCWSTR pwzName, SettingsMap::iterator &it); public: /** @@ -100,109 +100,140 @@ class SettingsManager /** * Parses a configuration file and adds its contents to the global settings. * - * @param pszFileName path to configuration file + * @param pwzFileName path to configuration file */ - void ParseFile(LPCSTR pszFileName); + void ParseFile(LPCWSTR pwzFileName); /** * Retrieves a Boolean value from the global settings. Returns * fIfFound if the setting exists and !fIfFound * if it does not. * - * @param pszKeyName setting name + * @param pwzKeyName setting name * @param fIfFound value to return if setting is found * @return setting value */ - BOOL GetRCBool(LPCSTR pszKeyName, BOOL fIfFound); + BOOL GetRCBool(LPCWSTR pwzKeyName, BOOL fIfFound); /** * Retrieves a Boolean value from the global settings. Returns * fDefault if the setting does not exist. * - * @param pszKeyName setting name + * @param pwzKeyName setting name * @param fDefault default value * @return setting value */ - BOOL GetRCBoolDef(LPCSTR pszKeyName, BOOL fDefault); + BOOL GetRCBoolDef(LPCWSTR pszKeyName, BOOL fDefault); /** * Retrieves a color value from the global settings. Returns * crDefault if the setting does not exist. * - * @param pszKeyName setting name + * @param pwzKeyName setting name * @param crDefault default value * @return setting value */ - COLORREF GetRCColor(LPCSTR pszKeyName, COLORREF crDefault); + COLORREF GetRCColor(LPCWSTR pszKeyName, COLORREF crDefault); + + /** + * Retrieves an integer value from the global settings. Returns + * nDefault if the setting does not exist. + * + * @param pwzKeyName setting name + * @param nDefault default value + * @return setting value + */ + __int64 GetRCInt64(LPCWSTR pwzKeyName, __int64 nDefault); /** * Retrieves an integer value from the global settings. Returns * nDefault if the setting does not exist. * - * @param pszKeyName setting name + * @param pwzKeyName setting name * @param nDefault default value * @return setting value */ - int GetRCInt(LPCSTR pszKeyName, int nDefault); + int GetRCInt(LPCWSTR pwzKeyName, int nDefault); + + /** + * Retrieves a floating point value from the global settings. Returns + * fDefault if the setting does not exist. + * + * @param pwzKeyName setting name + * @param fDefault default value + * @return setting value + */ + float GetRCFloat (LPCWSTR pwzKeyName, float fDefault); + + /** + * Retrieves a double-precision floating point value from the + * global settings. Return dDefault if the setting + * does not exist. + * + * @param pwzKeyName setting name + * @param dDefault default value + * @return setting value + */ + double GetRCDouble(LPCWSTR pwzKeyName, double dDefault); /** * Retrieves a raw string value from the global settings. If setting does * not exist, copies pszDefault into the buffer and returns - * FALSE. pszDefault may be NULL in + * FALSE. pszDefault may be nullptr in * which case nothing is copied into the buffer. * * GetRCLine does not parse the string value like * GetRCString does. Its purpose is for retreiving command * lines for applications and bang commands. * - * @param pszKeyName setting name - * @param pszBuffer buffer to receive value + * @param pwzKeyName setting name + * @param pwzBuffer buffer to receive value * @param cchBufferLen size of buffer - * @param pszDefault default value + * @param pwzDefault default value * @return TRUE if setting exists or FALSE * otherwise */ - BOOL GetRCLine(LPCSTR pszKeyName, LPSTR pszBuffer, int cchBufferLen, LPCSTR pszDefault); + BOOL GetRCLine(LPCWSTR pwzKeyName, LPWSTR pwzBuffer, int cchBufferLen, LPCWSTR pwzDefault); /** * Retreives a string value from the global settings. If the setting does - * not exist, copies pszDefault into the buffer and returns - * FALSE. pszDefault may be NULL in + * not exist, copies pwzDefault into the buffer and returns + * FALSE. pwzDefault may be nullptr in * which case nothing is copied into the buffer. * * The raw setting value is parsed and the first space-delimited token or * quoted string is the value returned. * - * @param pszKeyName setting name - * @param pszBuffer buffer to receive value - * @param pszDefault default value + * @param pwzKeyName setting name + * @param pwzBuffer buffer to receive value + * @param pwzDefault default value * @param cchBufferLen size of buffer * @return TRUE if setting exists or FALSE * otherwise */ - BOOL GetRCString(LPCSTR pszKeyName, LPSTR pszBuffer, LPCSTR pszDefault, int cchBufferLen); + BOOL GetRCString(LPCWSTR pwzKeyName, LPWSTR pwzBuffer, LPCWSTR pwzDefault, int cchBufferLen); /** * Retrieves a string value from the global settings. Returns * FALSE if the setting does not exist. Performs the same * operation as {@link #GetRCString}. * - * @param pszKeyName setting name - * @param pszBuffer buffer to receive value + * @param pwzKeyName setting name + * @param pwzBuffer buffer to receive value * @param cchBufferLen size of buffer * @return TRUE if setting exists or FALSE * otherwise */ - BOOL GetVariable(LPCSTR pszKeyName, LPSTR pszBuffer, DWORD cchBufferLen); + BOOL GetVariable(LPCWSTR pwzKeyName, LPWSTR pwzBuffer, DWORD cchBufferLen); /** * Assigns a new value to a global setting. If the setting already exists * its previous value is overwritten, otherwise a new setting is created. * - * @param pszKeyName setting name - * @param pszValue new setting value + * @param pwzKeyName setting name + * @param pwzValue new setting value */ - void SetVariable(LPCSTR pszKeyName, LPCSTR pszValue); + void SetVariable(LPCWSTR pwzKeyName, LPCWSTR pwzValue); /** * Opens a configuration file for sequential access to its contents. The @@ -219,7 +250,7 @@ class SettingsManager * access global settings * @return file handle or NULL if the file could not be opened */ - LPVOID LCOpen(LPCSTR pszPath); + LPVOID LCOpen(LPCWSTR pwzPath); /** * Closes a configuration file opened with {@link #LCOpen}. @@ -239,14 +270,14 @@ class SettingsManager * retrieve all the lines that begin with the specified setting name. * * @param pFile file handle returned by LCOpen - * @param pszConfig setting name - * @param pszBuffer buffer to receive line + * @param pwzConfig setting name + * @param pwzBuffer buffer to receive line * @param cchBufferLen size of buffer * @return TRUE if the line was retrieved or * FALSE if there are no more lines or an error * occurred */ - BOOL LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszBuffer, size_t cchBufferLen); + BOOL LCReadNextConfig(LPVOID pFile, LPCWSTR pwzConfig, LPWSTR pwzBuffer, size_t cchBufferLen); /** * Retrieves the next none config line (one that does not start with a '*' @@ -257,13 +288,13 @@ class SettingsManager * retrieve all non config lines in the file. * * @param pFile file handle returned by LCOpen - * @param pszBuffer buffer to receive line + * @param pwzBuffer buffer to receive line * @param cchBufferLen size of buffer * @return TRUE if the line was retrieved or * FALSE if there are no more lines or an error * occurred */ - BOOL LCReadNextCommand(LPVOID pFile, LPSTR pszBuffer, size_t cchBufferLen); + BOOL LCReadNextCommand(LPVOID pFile, LPWSTR pwzBuffer, size_t cchBufferLen); /** * Retrieves the next line from a configuration file. The entire line @@ -273,36 +304,36 @@ class SettingsManager * retrieve all the lines in the file. * * @param pFile file handle returned by LCOpen - * @param pszBuffer buffer to receive line + * @param pwzBuffer buffer to receive line * @param cchBufferLen size of buffer * @return TRUE if the line was retrieved or * FALSE if there are no more lines or an error * occurred */ - BOOL LCReadNextLine(LPVOID pFile, LPSTR pszBuffer, size_t cchBufferLen); + BOOL LCReadNextLine(LPVOID pFile, LPWSTR pszBuffer, size_t cchBufferLen); /** * Expands variable references. The template string is copied into the * buffer with all variable references ($var$) replaced by the * value of the variable. * - * @param pszBuffer buffer to received the expanded string - * @param pszTemplate string to be expanded + * @param pwzBuffer buffer to received the expanded string + * @param pwzTemplate string to be expanded * @param cchBufferLen size of the buffer */ - void VarExpansionEx(LPSTR pszBuffer, LPCSTR pszTemplate, size_t cchBufferLen); + void VarExpansionEx(LPWSTR pszBuffer, LPCWSTR pszTemplate, size_t cchBufferLen); /** * Expands variable references. The template string is copied into the * buffer with all variable references ($var$) replaced by the * value of the variable. * - * @param pszBuffer buffer to received the expanded string - * @param pszTemplate string to be expanded + * @param pwzBuffer buffer to received the expanded string + * @param pwzTemplate string to be expanded * @param cchBufferLen size of the buffer * @param recursiveVarSet recursive variable set */ - void VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t stLength, const StringSet& recursiveVarSet); + void VarExpansionEx(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate, size_t stLength, const StringSet& recursiveVarSet); }; #endif // SETTINGSMANAGER_H diff --git a/lsapi/ThreadedBangCommand.h b/lsapi/ThreadedBangCommand.h index 1e1d775..25fe27f 100644 --- a/lsapi/ThreadedBangCommand.h +++ b/lsapi/ThreadedBangCommand.h @@ -29,21 +29,21 @@ class ThreadedBangCommand : public CountedBase { public: - ThreadedBangCommand(HWND hCaller, LPCSTR pszName, LPCSTR pszParams) + ThreadedBangCommand(HWND hCaller, LPCWSTR pwzName, LPCWSTR pwzParams) :m_hCaller(hCaller) { - ASSERT(NULL != pszName); + ASSERT(NULL != pwzName); // pszName is guaranteed to be non-NULL - StringCchCopy(m_szName, MAX_BANGCOMMAND, pszName); + StringCchCopyW(m_wzName, MAX_BANGCOMMAND, pwzName); - if (pszParams) + if (pwzParams) { - StringCchCopy(m_szParams, MAX_BANGARGS, pszParams); + StringCchCopyW(m_wzParams, MAX_BANGARGS, pwzParams); } else { - m_szParams[0] = '\0'; + m_wzParams[0] = L'\0'; } } @@ -52,12 +52,12 @@ class ThreadedBangCommand : public CountedBase // Cannot use ParseBangCommand here because that would expand variables // again - and some themes rely on the fact that they are expanded only // once. Besides, it would create inconsistent behavior. - InternalExecuteBangCommand(m_hCaller, m_szName, m_szParams); + InternalExecuteBangCommand(m_hCaller, m_wzName, m_wzParams); } private: - char m_szName[MAX_BANGCOMMAND]; - char m_szParams[MAX_BANGARGS]; + wchar_t m_wzName[MAX_BANGCOMMAND]; + wchar_t m_wzParams[MAX_BANGARGS]; HWND m_hCaller; }; diff --git a/lsapi/aboutbox.cpp b/lsapi/aboutbox.cpp index 1b82540..4b8eda7 100644 --- a/lsapi/aboutbox.cpp +++ b/lsapi/aboutbox.cpp @@ -24,6 +24,7 @@ #include #include #include +#include //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -48,9 +49,9 @@ static void AboutSysInfo(HWND hListView); static void AboutPerformance(HWND hListView); // Utility -static HFONT CreateSimpleFont(LPCSTR pszName, int nSizeInPoints, bool bBold); +static HFONT CreateSimpleFont(LPCWSTR pszName, int nSizeInPoints, bool bBold); static int GetClientWidth(HWND hWnd); -static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer); +static void FormatBytes(DWORDLONG stBytes, LPWSTR pszBuffer, size_t cchBuffer); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -71,18 +72,18 @@ enum struct AboutOptions { - const char* option; + const wchar_t *option; AboutFunction function; } static const g_aboutOptions[] = \ { - { "Bang Commands", AboutBangs } - ,{ "Development Team", AboutDevTeam } - ,{ "License", AboutLicense } - ,{ "Loaded Modules", AboutModules } - ,{ "Performance", AboutPerformance } - ,{ "Revision IDs", AboutRevIDs } - ,{ "System Information", AboutSysInfo } + { L"Bang Commands", AboutBangs } + ,{ L"Development Team", AboutDevTeam } + ,{ L"License", AboutLicense } + ,{ L"Loaded Modules", AboutModules } + ,{ L"Performance", AboutPerformance } + ,{ L"Revision IDs", AboutRevIDs } + ,{ L"System Information", AboutSysInfo } }; @@ -92,19 +93,19 @@ static const g_aboutOptions[] = \ // struct TheDevTeam { - const char *nick; - const char *realName; + const wchar_t *nick; + const wchar_t *realName; } static const g_theDevTeam[] = \ { - { "Acidfire", "Alexander Vermaat" } - ,{ "alur", "Erik Welander" } - ,{ "ilmcuts", "Simon" } - ,{ "jugg", "Chris Rempel" } - ,{ "Maduin", "Kevin Schaffer" } - ,{ "RabidCow", "Joshua Seagoe" } - ,{ "Tobbe", "Tobbe Lundberg" } - ,{ "Xjill", "Vidar T. Fauske" } + { L"Acidfire", L"Alexander Vermaat" } + ,{ L"alur", L"Erik Welander" } + ,{ L"ilmcuts", L"Simon" } + ,{ L"jugg", L"Chris Rempel" } + ,{ L"Maduin", L"Kevin Schaffer" } + ,{ L"RabidCow", L"Joshua Seagoe" } + ,{ L"Tobbe", L"Tobbe Lundberg" } + ,{ L"Xjill", L"Vidar T. Fauske" } }; @@ -112,27 +113,27 @@ static const g_theDevTeam[] = \ // // LiteStep License Notice // -static const CHAR g_szLicense[] = \ - "LiteStep is a replacement shell for the standard Windows® Explorer shell.\r\n" - "\r\n" - "Copyright (C) 1997-1998 Francis Gastellu\r\n" - "Copyright (C) 1998-2013 LiteStep Development Team\r\n" - "\r\n" - "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.\r\n" - "\r\n" - "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.\r\n" - "\r\n" - "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., 51 " - "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r\n" - "\r\n" - "http://www.lsdev.org/"; +static const WCHAR g_wzLicense[] = \ + L"LiteStep is a replacement shell for the standard Windows® Explorer shell.\r\n" + L"\r\n" + L"Copyright (C) 1997-1998 Francis Gastellu\r\n" + L"Copyright (C) 1998-2013 LiteStep Development Team\r\n" + L"\r\n" + L"This program is free software; you can redistribute it and/or modify it " + L"under the terms of the GNU General Public License as published by the Free " + L"Software Foundation; either version 2 of the License, or (at your option) " + L"any later version.\r\n" + L"\r\n" + L"This program is distributed in the hope that it will be useful, but WITHOUT " + L"ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or " + L"FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for " + L"more details.\r\n" + L"\r\n" + L"You should have received a copy of the GNU General Public License along with " + L"this program; if not, write to the Free Software Foundation, Inc., 51 " + L"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r\n" + L"\r\n" + L"http://www.lsdev.org/"; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -146,7 +147,7 @@ struct CallbackInfo }; // Global handle to the running AboutBox instance (if any) -static HWND g_hAboutbox = NULL; +static HWND g_hAboutbox = nullptr; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -196,23 +197,23 @@ static BOOL OnInitDialog(HWND hwndDialog, HWND hwndFocus, LPARAM lParam) // HWND hwndTitle = GetDlgItem(hwndDialog, IDC_TITLE); - HFONT hTitleFont = CreateSimpleFont("Verdana", 14, false); + HFONT hTitleFont = CreateSimpleFont(L"Verdana", 14, false); SetWindowFont(hwndTitle, hTitleFont, FALSE); - Static_SetText(hwndTitle, "LiteStep 0.25.0 Alpha"); + SetWindowTextW(hwndTitle, L"LiteStep 0.25.0 Alpha"); // // Initialize theme info // - char themeAuthor[16] = { 0 }; - char themeName[21] = { 0 }; - char themeOut[MAX_LINE_LENGTH] = { 0 }; + wchar_t themeAuthor[16] = { 0 }; + wchar_t themeName[21] = { 0 }; + wchar_t themeOut[MAX_LINE_LENGTH] = { 0 }; - GetRCString("ThemeAuthor", themeAuthor, "(unknown)", COUNTOF(themeAuthor)); - GetRCString("ThemeName", themeName, "(unknown", COUNTOF(themeName)); + GetRCStringW(L"ThemeAuthor", themeAuthor, L"(unknown)", COUNTOF(themeAuthor)); + GetRCStringW(L"ThemeName", themeName, L"(unknown)", COUNTOF(themeName)); - if (SUCCEEDED(StringCchPrintf(themeOut, COUNTOF(themeOut), - "Theme: %s by %s", themeName, themeAuthor))) + if (SUCCEEDED(StringCchPrintfW(themeOut, COUNTOF(themeOut), + L"Theme: %ls by %ls", themeName, themeAuthor))) { SetDlgItemText(hwndDialog, IDC_THEME_INFO, themeOut); } @@ -220,14 +221,14 @@ static BOOL OnInitDialog(HWND hwndDialog, HWND hwndFocus, LPARAM lParam) // // Initialize compile time // - char compileTime[42] = { 0 }; - LSGetVariableEx("CompileDate", compileTime, 42); + wchar_t compileTime[42] = { 0 }; + LSGetVariableExW(L"CompileDate", compileTime, 42); SetDlgItemText(hwndDialog, IDC_COMPILETIME, compileTime); // // Initialize edit control (license notice) // - SetDlgItemText(hwndDialog, IDC_EDIT, g_szLicense); + SetDlgItemTextW(hwndDialog, IDC_EDIT, g_wzLicense); // // Initialize ComboBox @@ -381,7 +382,7 @@ static INT_PTR OnCommand( DWORD dwStart = 0; SendMessage(hwndCtl, EM_GETSEL, (WPARAM)&dwStart, 0); - Edit_SetText(hwndCtl, g_szLicense); + SetWindowTextW(hwndCtl, g_wzLicense); Edit_SetSel(hwndCtl, dwStart-1, dwStart-1); bHandled = TRUE; @@ -419,19 +420,19 @@ DWORD WINAPI AboutBoxThread(LPVOID /* lpParameter */) // Used by AboutBangs // static BOOL CALLBACK BangCallback( - HMODULE hModule, LPCSTR pszName, LPARAM lParam) + HMODULE hModule, LPCWSTR pszName, LPARAM lParam) { CallbackInfo* pCi = (CallbackInfo*)lParam; LVITEM itemInfo; itemInfo.mask = LVIF_TEXT; itemInfo.iItem = pCi->nItem; - itemInfo.pszText = (char*)pszName; + itemInfo.pszText = (wchar_t*)pszName; itemInfo.iSubItem = 0; ListView_InsertItem(pCi->hListView, &itemInfo); - CHAR szModule[MAX_PATH] = { 0 }; + wchar_t szModule[MAX_PATH] = { 0 }; if (LSGetModuleFileName(hModule, szModule, COUNTOF(szModule))) { @@ -451,11 +452,11 @@ static BOOL CALLBACK BangCallback( static void AboutBangs(HWND hListView) { LVCOLUMN columnInfo; - char text[32]; + wchar_t text[32]; int width = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); - strcpy(text, "Bang Command"); + StringCchCopy(text, _countof(text), L"Bang Command"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = width / 2; @@ -464,7 +465,7 @@ static void AboutBangs(HWND hListView) ListView_InsertColumn(hListView, 0, &columnInfo); - strcpy(text, "Module"); + StringCchCopy(text, _countof(text), L"Module"); columnInfo.cx = width - columnInfo.cx; columnInfo.pszText = text; columnInfo.iSubItem = 1; @@ -474,7 +475,7 @@ static void AboutBangs(HWND hListView) CallbackInfo ci = { 0 }; ci.hListView = hListView; - EnumLSData(ELD_BANGS_V2, (FARPROC)BangCallback, (LPARAM)&ci); + EnumLSDataW(ELD_BANGS_V2, (FARPROC)BangCallback, (LPARAM)&ci); } @@ -486,9 +487,9 @@ static void AboutDevTeam(HWND hListView) { LVCOLUMN columnInfo; int width = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); - char text[32]; + wchar_t text[32]; - strcpy(text, "Nick"); + StringCchCopy(text, _countof(text), L"Nick"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = width / 3; @@ -497,7 +498,7 @@ static void AboutDevTeam(HWND hListView) ListView_InsertColumn(hListView, 0, &columnInfo); - strcpy(text, "Real Name"); + StringCchCopy(text, _countof(text), L"Real Name"); columnInfo.cx = (2 * width) / 3; columnInfo.pszText = text; columnInfo.iSubItem = 1; @@ -510,11 +511,11 @@ static void AboutDevTeam(HWND hListView) itemInfo.mask = LVIF_TEXT; itemInfo.iItem = i; - itemInfo.pszText = (char*)g_theDevTeam[i].nick; + itemInfo.pszText = (wchar_t*)g_theDevTeam[i].nick; itemInfo.iSubItem = 0; ListView_InsertItem(hListView, &itemInfo); - ListView_SetItemText(hListView, i, 1, (char*)g_theDevTeam[i].realName); + ListView_SetItemText(hListView, i, 1, (wchar_t*)g_theDevTeam[i].realName); } } @@ -535,14 +536,14 @@ static void AboutLicense(HWND /* hEdit */) // ModulesCallback // Used by AboutModules // -static BOOL CALLBACK ModulesCallback(LPCSTR pszPath, DWORD /* dwFlags */, LPARAM lParam) +static BOOL CALLBACK ModulesCallback(LPCWSTR pszPath, DWORD /* dwFlags */, LPARAM lParam) { CallbackInfo* pCi = (CallbackInfo*)lParam; LVITEM itemInfo; itemInfo.mask = LVIF_TEXT; itemInfo.iItem = pCi->nItem++; - itemInfo.pszText = (char*)pszPath; + itemInfo.pszText = (wchar_t*)pszPath; itemInfo.iSubItem = 0; ListView_InsertItem(pCi->hListView, &itemInfo); @@ -558,9 +559,9 @@ static BOOL CALLBACK ModulesCallback(LPCSTR pszPath, DWORD /* dwFlags */, LPARAM static void AboutModules(HWND hListView) { LVCOLUMN columnInfo; - char text[32]; + wchar_t text[32]; - strcpy(text, "Module"); + StringCchCopy(text, _countof(text), L"Module"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); @@ -572,7 +573,7 @@ static void AboutModules(HWND hListView) CallbackInfo ci = { 0 }; ci.hListView = hListView; - EnumLSData(ELD_MODULES, (FARPROC)ModulesCallback, (LPARAM)&ci); + EnumLSDataW(ELD_MODULES, (FARPROC)ModulesCallback, (LPARAM)&ci); } @@ -581,12 +582,12 @@ static void AboutModules(HWND hListView) // PerformanceCallback // Used by AboutPerformance // -static BOOL CALLBACK PerformanceCallback(LPCSTR pszPath, DWORD dwLoadTime, LPARAM lParam) +static BOOL CALLBACK PerformanceCallback(LPCWSTR pszPath, DWORD dwLoadTime, LPARAM lParam) { CallbackInfo* pCi = (CallbackInfo*)lParam; - CHAR szModule[MAX_PATH] = { 0 }; - strcpy(szModule, pszPath); + wchar_t szModule[MAX_PATH] = { 0 }; + StringCchCopy(szModule, _countof(szModule), pszPath); PathStripPath(szModule); LVITEM itemInfo; @@ -597,7 +598,7 @@ static BOOL CALLBACK PerformanceCallback(LPCSTR pszPath, DWORD dwLoadTime, LPARA ListView_InsertItem(pCi->hListView, &itemInfo); - sprintf(szModule, "%dms", dwLoadTime); + StringCchPrintf(szModule, _countof(szModule), L"%dms", dwLoadTime); ListView_SetItemText(pCi->hListView, pCi->nItem, 1, szModule); ++pCi->nItem; @@ -612,11 +613,11 @@ static BOOL CALLBACK PerformanceCallback(LPCSTR pszPath, DWORD dwLoadTime, LPARA static void AboutPerformance(HWND hListView) { LVCOLUMN columnInfo; - char text[32]; + wchar_t text[32]; int width = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); - strcpy(text, "Module"); + StringCchCopy(text, _countof(text), L"Module"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = width / 2; @@ -625,7 +626,7 @@ static void AboutPerformance(HWND hListView) ListView_InsertColumn(hListView, 0, &columnInfo); - strcpy(text, "Load Time"); + StringCchCopy(text, _countof(text), L"Load Time"); columnInfo.cx = width - columnInfo.cx; columnInfo.pszText = text; columnInfo.iSubItem = 1; @@ -635,7 +636,7 @@ static void AboutPerformance(HWND hListView) CallbackInfo ci = { 0 }; ci.hListView = hListView; - EnumLSData(ELD_PERFORMANCE, (FARPROC)PerformanceCallback, (LPARAM)&ci); + EnumLSDataW(ELD_PERFORMANCE, (FARPROC)PerformanceCallback, (LPARAM)&ci); } @@ -644,14 +645,14 @@ static void AboutPerformance(HWND hListView) // RevIDCallback // Used by AboutRevIDs // -static BOOL CALLBACK RevIDCallback(LPCSTR pszRevID, LPARAM lParam) +static BOOL CALLBACK RevIDCallback(LPCWSTR pszRevID, LPARAM lParam) { CallbackInfo* pCi = (CallbackInfo*)lParam; LVITEM itemInfo; itemInfo.mask = LVIF_TEXT; itemInfo.iItem = pCi->nItem++; - itemInfo.pszText = (char*)pszRevID; + itemInfo.pszText = (wchar_t*)pszRevID; itemInfo.iSubItem = 0; ListView_InsertItem(pCi->hListView, &itemInfo); @@ -667,9 +668,9 @@ static BOOL CALLBACK RevIDCallback(LPCSTR pszRevID, LPARAM lParam) static void AboutRevIDs(HWND hListView) { LVCOLUMN columnInfo; - char text[32]; + wchar_t text[32]; - strcpy(text, "Revision ID"); + StringCchCopy(text, _countof(text), L"Revision ID"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); @@ -682,7 +683,7 @@ static void AboutRevIDs(HWND hListView) ci.hListView = hListView; ci.nItem = 0; - EnumLSData(ELD_REVIDS, (FARPROC)RevIDCallback, (LPARAM)&ci); + EnumLSDataW(ELD_REVIDS, (FARPROC)RevIDCallback, (LPARAM)&ci); } @@ -691,50 +692,53 @@ static void AboutRevIDs(HWND hListView) // GetWinVerString // Helper for AboutSysInfo // -static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) +static HRESULT GetWinVerString(LPWSTR pwzVersion, DWORD cchVersion) { - ASSERT(pszVersion != NULL); + ASSERT(pwzVersion != nullptr); UINT uVersion = GetWindowsVersion(); - LPCSTR pszTemp = NULL; + LPCWSTR pwzTemp = nullptr; switch (uVersion) { - case WINVER_WIN95: pszTemp = _T("Windows 95"); break; - case WINVER_WIN98: pszTemp = _T("Windows 98"); break; - case WINVER_WINME: pszTemp = _T("Windows ME"); break; - case WINVER_WINNT4: pszTemp = _T("Windows NT 4.0"); break; - case WINVER_WIN2000: pszTemp = _T("Windows 2000"); break; - case WINVER_WINXP: pszTemp = _T("Windows XP"); break; - case WINVER_VISTA: pszTemp = _T("Windows Vista"); break; - case WINVER_WIN7: pszTemp = _T("Windows 7"); break; - case WINVER_WIN8: pszTemp = _T("Windows 8"); break; + case WINVER_WIN95: pwzTemp = L"Windows 95"; break; + case WINVER_WIN98: pwzTemp = L"Windows 98"; break; + case WINVER_WINME: pwzTemp = L"Windows ME"; break; + case WINVER_WINNT4: pwzTemp = L"Windows NT 4.0"; break; + case WINVER_WIN2000: pwzTemp = L"Windows 2000"; break; + case WINVER_WINXP: pwzTemp = L"Windows XP"; break; + case WINVER_VISTA: pwzTemp = L"Windows Vista"; break; + case WINVER_WIN7: pwzTemp = L"Windows 7"; break; + case WINVER_WIN8: pwzTemp = L"Windows 8"; break; + case WINVER_WIN81: pwzTemp = L"Windows 8.1"; break; case WINVER_WIN2003: if (GetSystemMetrics(SM_SERVERR2)) { - pszTemp = _T("Windows Server 2003 R2"); + pwzTemp = L"Windows Server 2003 R2"; } else { - pszTemp = _T("Windows Server 2003"); + pwzTemp = L"Windows Server 2003"; } break; - case WINVER_WHS: pszTemp = _T("Windows Home Server"); break; - case WINVER_WIN2008: pszTemp = _T("Windows Server 2008"); break; - case WINVER_WIN2012: pszTemp = _T("Windows Server 2012"); break; - default: pszTemp = _T(""); break; + case WINVER_WHS: pwzTemp = L"Windows Home Server"; break; + case WINVER_WIN2008: pwzTemp = L"Windows Server 2008"; break; + case WINVER_WIN2008R2: pwzTemp = L"Windows Server 2008 R2"; break; + case WINVER_WIN2012: pwzTemp = L"Windows Server 2012"; break; + case WINVER_WIN2012R2: pwzTemp = L"Windows Server 2012 R2"; break; + default: pwzTemp = L""; break; } - HRESULT hr = StringCchCopy(pszVersion, cchVersion, pszTemp); + HRESULT hr = StringCchCopyW(pwzVersion, cchVersion, pwzTemp); if (SUCCEEDED(hr)) { -#if !defined(WIN64) +#if !defined(_WIN64) if (IsOS(OS_WOW6432)) #endif { - StringCchCat(pszVersion, cchVersion, _T(" (64-Bit)")); + StringCchCatW(pwzVersion, cchVersion, L" (64-Bit)"); } } @@ -748,15 +752,15 @@ static HRESULT GetWinVerString(LPTSTR pszVersion, DWORD cchVersion) // static void AboutSysInfo(HWND hListView) { - LVCOLUMN columnInfo; - LVITEM itemInfo; + LVCOLUMNW columnInfo; + LVITEMW itemInfo; int i = 0; - char buffer[MAX_PATH]; - char text[32]; + wchar_t buffer[MAX_PATH]; + wchar_t text[32]; int width = GetClientWidth(hListView) - GetSystemMetrics(SM_CXVSCROLL); - strcpy(text, "Name"); + StringCchCopyW(text, _countof(text), L"Name"); columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; columnInfo.fmt = LVCFMT_LEFT; columnInfo.cx = width / 3 + width / 8; @@ -768,7 +772,7 @@ static void AboutSysInfo(HWND hListView) /* Using this odd size, keeps the columns aligned with * the other list views, and also gives the text a little * more room to keep from being truncated. */ - strcpy(text, "Value"); + StringCchCopyW(text, _countof(text), L"Value"); columnInfo.cx = (2 * width) / 3 - width / 8; columnInfo.pszText = text; columnInfo.iSubItem = 1; @@ -776,7 +780,7 @@ static void AboutSysInfo(HWND hListView) ListView_InsertColumn(hListView, 1, &columnInfo); // operating system and version - strcpy(text, "Operating System"); + StringCchCopyW(text, _countof(text), L"Operating System"); itemInfo.mask = LVIF_TEXT; itemInfo.iItem = i; itemInfo.pszText = text; @@ -794,7 +798,7 @@ static void AboutSysInfo(HWND hListView) typedef BOOL (WINAPI *GMSExFunctionType)(LPMEMORYSTATUSEX); GMSExFunctionType fpGlobalMemoryStatusEx = (GMSExFunctionType)GetProcAddress( - GetModuleHandle("KERNEL32.DLL"), "GlobalMemoryStatusEx"); + GetModuleHandleW(L"KERNEL32.DLL"), "GlobalMemoryStatusEx"); if (fpGlobalMemoryStatusEx) { @@ -821,16 +825,16 @@ static void AboutSysInfo(HWND hListView) dwAvailPageFile = (DWORDLONG)ms.dwAvailPageFile; } - strcpy(text, "Memory Load"); + StringCchCopyW(text, _countof(text), L"Memory Load"); itemInfo.iItem = i; itemInfo.pszText = text; ListView_InsertItem(hListView, &itemInfo); - StringCchPrintf(buffer, MAX_PATH, "%d%%", dwMemoryLoad); + StringCchPrintfW(buffer, MAX_PATH, L"%d%%", dwMemoryLoad); ListView_SetItemText(hListView, i++, 1, buffer); - strcpy(text, "Physical Memory Total"); + StringCchCopyW(text, _countof(text), L"Physical Memory Total"); itemInfo.iItem = i; itemInfo.pszText = text; @@ -839,7 +843,7 @@ static void AboutSysInfo(HWND hListView) FormatBytes(dwTotalPhys, buffer, 64); ListView_SetItemText(hListView, i++, 1, buffer); - strcpy(text, "Physical Memory Available"); + StringCchCopyW(text, _countof(text), L"Physical Memory Available"); itemInfo.iItem = i; itemInfo.pszText = text; @@ -848,7 +852,7 @@ static void AboutSysInfo(HWND hListView) FormatBytes(dwAvailPhys, buffer, 64); ListView_SetItemText(hListView, i++, 1, buffer); - strcpy(text, "Swap Space Total"); + StringCchCopyW(text, _countof(text), L"Swap Space Total"); itemInfo.iItem = i; itemInfo.pszText = text; @@ -857,7 +861,7 @@ static void AboutSysInfo(HWND hListView) FormatBytes(dwTotalPageFile, buffer, 64); ListView_SetItemText(hListView, i++, 1, buffer); - strcpy(text, "Swap Space Available"); + StringCchCopyW(text, _countof(text), L"Swap Space Available"); itemInfo.iItem = i; itemInfo.pszText = text; @@ -873,25 +877,25 @@ static void AboutSysInfo(HWND hListView) // CreateSimpleFont // Simplified version of CreateFont // -static HFONT CreateSimpleFont(LPCSTR pszName, int nSizeInPoints, bool bBold) +static HFONT CreateSimpleFont(LPCWSTR pwzName, int nSizeInPoints, bool bBold) { - ASSERT(NULL != pszName); ASSERT(nSizeInPoints > 0); + ASSERT(nullptr != pwzName); ASSERT(nSizeInPoints > 0); // convert size from points to pixels - HDC hDC = GetDC(NULL); + HDC hDC = GetDC(nullptr); int sizeInPixels = -MulDiv(nSizeInPoints, GetDeviceCaps(hDC, LOGPIXELSY), 72); - ReleaseDC(NULL, hDC); + ReleaseDC(nullptr, hDC); // fill in LOGFONT structure - LOGFONT lf = { 0 }; + LOGFONTW lf = { 0 }; lf.lfHeight = sizeInPixels; lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; - StringCchCopy(lf.lfFaceName, LF_FACESIZE, pszName); + StringCchCopyW(lf.lfFaceName, LF_FACESIZE, pwzName); // create it - return CreateFontIndirect(&lf); + return CreateFontIndirectW(&lf); } @@ -916,11 +920,11 @@ static int GetClientWidth(HWND hWnd) // Note: Max value of stBytes is 16 EB, so no need to be concerned of // overrunning units[] index. // -static LPCSTR units[] = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB" }; +static LPCWSTR units[] = { L"bytes", L"KB", L"MB", L"GB", L"TB", L"PB", L"EB" }; -static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer) +static void FormatBytes(DWORDLONG stBytes, LPWSTR pwzBuffer, size_t cchBuffer) { - double dValue = (double)stBytes; + long double dValue = (long double) stBytes; unsigned int uUnit = 0; while ((dValue >= 1024) && (uUnit < COUNTOF(units) - 1)) @@ -931,16 +935,16 @@ static void FormatBytes(DWORDLONG stBytes, LPSTR pszBuffer, size_t cchBuffer) if (uUnit >= 3) { - StringCchPrintf( - pszBuffer, cchBuffer, - "%.2f %s", + StringCchPrintfW( + pwzBuffer, cchBuffer, + L"%.2Lf %ls", dValue, units[uUnit]); } else { - StringCchPrintf( - pszBuffer, cchBuffer, - "%d %s", + StringCchPrintfW( + pwzBuffer, cchBuffer, + L"%d %ls", (int)floor(dValue + 0.5), units[uUnit]); } } diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index aecb1f8..8087221 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -24,156 +24,156 @@ extern DWORD WINAPI AboutBoxThread(LPVOID); -static void BangAbout(HWND hCaller, LPCSTR pszArgs); -static void BangAlert(HWND hCaller, LPCSTR pszArgs); -static void BangCascadeWindows(HWND hCaller, LPCSTR pszArgs); -static void BangConfirm(HWND hCaller, LPCSTR pszArgs); -static void BangExecute(HWND hCaller, LPCSTR pszArgs); -static void BangHideModules (HWND hCaller, LPCSTR pszArgs); -static void BangLogoff(HWND hCaller, LPCSTR pszArgs); -static void BangMinimizeWindows(HWND hCaller, LPCSTR pszArgs); -static void BangQuit(HWND caller, LPCSTR param); -static void BangRecycle (HWND hCaller, LPCSTR pszArgs); -static void BangRefresh(HWND hCaller, LPCSTR pszArgs); -static void BangReload(HWND hCaller, LPCSTR pszArgs); -static void BangReloadModule (HWND hCaller, LPCSTR pszArgs); -static void BangRestoreWindows(HWND hCaller, LPCSTR pszArgs); -static void BangRun (HWND hCaller, LPCSTR pszArgs); -static void BangShowModules (HWND hCaller, LPCSTR pszArgs); -static void BangShutdown(HWND hCaller, LPCSTR pszArgs); -static void BangSwitchUser(HWND hCaller, LPCSTR pszArgs); -static void BangTileWindowsH(HWND hCaller, LPCSTR pszArgs); -static void BangTileWindowsV(HWND hCaller, LPCSTR pszArgs); -static void BangToggleModules (HWND hCaller, LPCSTR pszArgs); -static void BangUnloadModule (HWND hCaller, LPCSTR pszArgs); +static void BangAbout(HWND hCaller, LPCWSTR pwzArgs); +static void BangAlert(HWND hCaller, LPCWSTR pwzArgs); +static void BangCascadeWindows(HWND hCaller, LPCWSTR pwzArgs); +static void BangConfirm(HWND hCaller, LPCWSTR pwzArgs); +static void BangExecute(HWND hCaller, LPCWSTR pwzArgs); +static void BangHideModules (HWND hCaller, LPCWSTR pwzArgs); +static void BangLogoff(HWND hCaller, LPCWSTR pwzArgs); +static void BangMinimizeWindows(HWND hCaller, LPCWSTR pwzArgs); +static void BangQuit(HWND hCaller, LPCWSTR param); +static void BangRecycle (HWND hCaller, LPCWSTR pwzArgs); +static void BangRefresh(HWND hCaller, LPCWSTR pwzArgs); +static void BangReload(HWND hCaller, LPCWSTR pwzArgs); +static void BangReloadModule (HWND hCaller, LPCWSTR pwzArgs); +static void BangRestoreWindows(HWND hCaller, LPCWSTR pwzArgs); +static void BangRun (HWND hCaller, LPCWSTR pwzArgs); +static void BangShowModules (HWND hCaller, LPCWSTR pwzArgs); +static void BangShutdown(HWND hCaller, LPCWSTR pwzArgs); +static void BangSwitchUser(HWND hCaller, LPCWSTR pwzArgs); +static void BangTileWindowsH(HWND hCaller, LPCWSTR pwzArgs); +static void BangTileWindowsV(HWND hCaller, LPCWSTR pwzArgs); +static void BangToggleModules (HWND hCaller, LPCWSTR pwzArgs); +static void BangUnloadModule (HWND hCaller, LPCWSTR pwzArgs); void SetupBangs(void) { - AddBangCommand("!About", BangAbout); - AddBangCommand("!Alert", BangAlert); - AddBangCommand("!CascadeWindows", BangCascadeWindows); - AddBangCommand("!Confirm", BangConfirm); - AddBangCommand("!Execute", BangExecute); - AddBangCommand("!HideModules", BangHideModules); - AddBangCommand("!Logoff", BangLogoff); - AddBangCommand("!MinimizeWindows", BangMinimizeWindows); - AddBangCommand("!Quit", BangQuit); - AddBangCommand("!Recycle", BangRecycle); - AddBangCommand("!Refresh", BangRefresh); - AddBangCommand("!Reload", BangReload); - AddBangCommand("!ReloadModule", BangReloadModule); - AddBangCommand("!RestoreWindows", BangRestoreWindows); - AddBangCommand("!Run", BangRun); - AddBangCommand("!ShowModules", BangShowModules); - AddBangCommand("!Shutdown", BangShutdown); - AddBangCommand("!SwitchUser", BangSwitchUser); - AddBangCommand("!TileWindowsH", BangTileWindowsH); - AddBangCommand("!TileWindowsV", BangTileWindowsV); - AddBangCommand("!ToggleModules", BangToggleModules); - AddBangCommand("!UnloadModule", BangUnloadModule); + AddBangCommandW(L"!About", BangAbout); + AddBangCommandW(L"!Alert", BangAlert); + AddBangCommandW(L"!CascadeWindows", BangCascadeWindows); + AddBangCommandW(L"!Confirm", BangConfirm); + AddBangCommandW(L"!Execute", BangExecute); + AddBangCommandW(L"!HideModules", BangHideModules); + AddBangCommandW(L"!Logoff", BangLogoff); + AddBangCommandW(L"!MinimizeWindows", BangMinimizeWindows); + AddBangCommandW(L"!Quit", BangQuit); + AddBangCommandW(L"!Recycle", BangRecycle); + AddBangCommandW(L"!Refresh", BangRefresh); + AddBangCommandW(L"!Reload", BangReload); + AddBangCommandW(L"!ReloadModule", BangReloadModule); + AddBangCommandW(L"!RestoreWindows", BangRestoreWindows); + AddBangCommandW(L"!Run", BangRun); + AddBangCommandW(L"!ShowModules", BangShowModules); + AddBangCommandW(L"!Shutdown", BangShutdown); + AddBangCommandW(L"!SwitchUser", BangSwitchUser); + AddBangCommandW(L"!TileWindowsH", BangTileWindowsH); + AddBangCommandW(L"!TileWindowsV", BangTileWindowsV); + AddBangCommandW(L"!ToggleModules", BangToggleModules); + AddBangCommandW(L"!UnloadModule", BangUnloadModule); } // -// BangAbout(HWND hCaller, LPCSTR pszArgs) +// BangAbout(HWND hCaller, LPCWSTR pwzArgs) // -static void BangAbout(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangAbout(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { CloseHandle(LSCreateThread("AboutBox Thread", AboutBoxThread, NULL, NULL)); } // -// BangAlert(HWND hCaller, LPCSTR pszArgs) +// BangAlert(HWND hCaller, LPCWSTR pwzArgs) // -static void BangAlert(HWND hCaller, LPCSTR pszArgs) +static void BangAlert(HWND hCaller, LPCWSTR pwzArgs) { - char szMessage[MAX_LINE_LENGTH] = { 0 }; - char szTitle[MAX_LINE_LENGTH] = { 0 }; - LPSTR aszTokens[] = { szMessage, szTitle }; + wchar_t wzMessage[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzTitle[MAX_LINE_LENGTH] = { 0 }; + LPWSTR awzTokens[] = { wzMessage, wzTitle }; - int nTokenCount = LCTokenize(pszArgs, aszTokens, 2, 0); + int nTokenCount = LCTokenizeW(pwzArgs, awzTokens, 2, 0); if (nTokenCount >= 1) { if (nTokenCount == 1) { - StringCchCopy(szTitle, MAX_PATH, "LiteStep !Alert"); + StringCchCopyW(wzTitle, MAX_PATH, L"LiteStep !Alert"); } - MessageBox(hCaller, szMessage, szTitle, MB_OK | MB_TOPMOST); + MessageBoxW(hCaller, wzMessage, wzTitle, MB_OK | MB_TOPMOST); } } // -// BangCascadeWindows(HWND hCaller, LPCSTR pszArgs) +// BangCascadeWindows(HWND hCaller, LPCWSTR pwzArgs) // -static void BangCascadeWindows(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangCascadeWindows(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL); } // -// BangConfirm(HWND hCaller, LPCSTR pszArgs) +// BangConfirm(HWND hCaller, LPCWSTR pwzArgs) // -static void BangConfirm(HWND hCaller, LPCSTR pszArgs) +static void BangConfirm(HWND hCaller, LPCWSTR pwzArgs) { - char szFirst[MAX_LINE_LENGTH] = { 0 }; - char szSecond[MAX_LINE_LENGTH] = { 0 }; - char szThird[MAX_LINE_LENGTH] = { 0 }; - char szFourth[MAX_LINE_LENGTH] = { 0 }; - LPSTR aszTokens[] = { szFirst, szSecond, szThird, szFourth }; + wchar_t wzFirst[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzSecond[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzThird[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzFourth[MAX_LINE_LENGTH] = { 0 }; + LPWSTR awzTokens[] = { wzFirst, wzSecond, wzThird, wzFourth }; - int nTokenCount = CommandTokenize(pszArgs, aszTokens, 4, 0); + int nTokenCount = CommandTokenizeW(pwzArgs, awzTokens, 4, 0); if (nTokenCount >= 3) { if (nTokenCount == 3) { - StringCchCopy(szFourth, MAX_LINE_LENGTH, "LiteStep !Confirm"); + StringCchCopyW(wzFourth, MAX_LINE_LENGTH, L"LiteStep !Confirm"); } - LPCSTR pszTitle = (nTokenCount == 3) ? szFourth : szSecond; + LPCWSTR pwzTitle = (nTokenCount == 3) ? wzFourth : wzSecond; - INT idConfirm = MessageBox(hCaller, - szFirst, pszTitle, MB_YESNO | MB_ICONQUESTION | MB_TOPMOST); + INT idConfirm = MessageBoxW(hCaller, + wzFirst, pwzTitle, MB_YESNO | MB_ICONQUESTION | MB_TOPMOST); if (idConfirm == IDYES) { - LSExecute(hCaller, - (nTokenCount == 3) ? szSecond : szThird, SW_SHOWNORMAL); + LSExecuteW(hCaller, + (nTokenCount == 3) ? wzSecond : wzThird, SW_SHOWNORMAL); } else { - LSExecute(hCaller, - (nTokenCount == 3) ? szThird : szFourth, SW_SHOWNORMAL); + LSExecuteW(hCaller, + (nTokenCount == 3) ? wzThird : wzFourth, SW_SHOWNORMAL); } } } // -// BangExecute(HWND hCaller, LPCSTR pszArgs) +// BangExecute(HWND hCaller, LPCWSTR pwzArgs) // -static void BangExecute(HWND hCaller, LPCSTR pszArgs) +static void BangExecute(HWND hCaller, LPCWSTR pwzArgs) { - LPCSTR pszNextToken = pszArgs; - char szCommand[MAX_LINE_LENGTH]; + LPCWSTR pszNextToken = pwzArgs; + wchar_t wzCommand[MAX_LINE_LENGTH]; - while (GetToken(pszNextToken, szCommand, &pszNextToken, TRUE)) + while (GetTokenW(pszNextToken, wzCommand, &pszNextToken, TRUE)) { - LSExecute(hCaller, szCommand, SW_SHOWDEFAULT); + LSExecuteW(hCaller, wzCommand, SW_SHOWDEFAULT); } } // -// BangLogoff(HWND hCaller, LPCSTR pszArgs) +// BangLogoff(HWND hCaller, LPCWSTR pwzArgs) // -static void BangLogoff(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangLogoff(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { HWND hLiteStep = GetLitestepWnd(); @@ -206,18 +206,18 @@ BOOL CALLBACK WindowsEnumProc(HWND hWnd, LPARAM lParam) // -// BangMinimizeWindows(HWND hCaller, LPCSTR pszArgs) +// BangMinimizeWindows(HWND hCaller, LPCWSTR pwzArgs) // -static void BangMinimizeWindows(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangMinimizeWindows(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { EnumWindows(WindowsEnumProc, (LPARAM)SW_MINIMIZE); } // -// BangQuit(HWND hCaller, LPCSTR pszArgs) +// BangQuit(HWND hCaller, LPCWSTR pwzArgs) // -static void BangQuit(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangQuit(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { HWND hLiteStep = GetLitestepWnd(); @@ -229,9 +229,9 @@ static void BangQuit(HWND /* hCaller */, LPCSTR /* pszArgs */) // -// BangRecycle(HWND hCaller, LPCSTR pszArgs) +// BangRecycle(HWND hCaller, LPCSTR pwzArgs) // -static void BangRecycle(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangRecycle(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { HWND hLiteStep = GetLitestepWnd(); @@ -243,13 +243,13 @@ static void BangRecycle(HWND /* hCaller */, LPCSTR /* pszArgs */) // -// BangRefresh(HWND hCaller, LPCSTR pszArgs) +// BangRefresh(HWND hCaller, LPCWSTR pwzArgs) // -static void BangRefresh(HWND hCaller, LPCSTR pszArgs) +static void BangRefresh(HWND hCaller, LPCWSTR pwzArgs) { HWND hLiteStep = GetLitestepWnd(); - BangReload(hCaller, pszArgs); + BangReload(hCaller, pwzArgs); if (hLiteStep) { @@ -258,45 +258,45 @@ static void BangRefresh(HWND hCaller, LPCSTR pszArgs) } -static void BangReload(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangReload(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { LSAPIReloadSettings(); } // -// BangReloadModule(HWND hCaller, LPCSTR pszArgs) +// BangReloadModule(HWND hCaller, LPCWSTR pwzArgs) // -static void BangReloadModule(HWND /* hCaller */, LPCSTR pszArgs) +static void BangReloadModule(HWND /* hCaller */, LPCWSTR pwzArgs) { HWND hLiteStep = GetLitestepWnd(); if (hLiteStep) { - LPCSTR pszNextToken = pszArgs; - char szModuleString[MAX_LINE_LENGTH] = { 0 }; + LPCWSTR pwzNextToken = pwzArgs; + wchar_t wzModuleString[MAX_LINE_LENGTH] = { 0 }; - while (GetToken(pszNextToken, szModuleString, &pszNextToken, TRUE)) + while (GetTokenW(pwzNextToken, wzModuleString, &pwzNextToken, TRUE)) { - SendMessage(hLiteStep, LM_RELOADMODULE, (WPARAM)szModuleString, 0); + SendMessage(hLiteStep, LM_RELOADMODULEW, (WPARAM)wzModuleString, 0); } } } // -// BangRestoreWindows(HWND hCaller, LPCSTR pszArgs) +// BangRestoreWindows(HWND hCaller, LPCWSTR pszArgs) // -static void BangRestoreWindows(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangRestoreWindows(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { EnumWindows(WindowsEnumProc, (LPARAM)SW_RESTORE); } // -// BangRun(HWND hCaller, LPCSTR pszArgs) +// BangRun(HWND hCaller, LPCWSTR pszArgs) // -static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) +static void BangRun(HWND /* hCaller */, LPCWSTR pwzArgs) { // Flags // 1 -- Removes the browse button. @@ -307,20 +307,20 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) typedef VOID (WINAPI* RunDlgType)(HWND hwndOwner, HICON hIcon, LPCWSTR pwszDirectory, LPCWSTR pwszTitle, LPCWSTR pwszDescription, UINT uFlags); - char szX[MAX_LINE_LENGTH] = { 0 }; - char szY[MAX_LINE_LENGTH] = { 0 }; - LPSTR aszTokens[] = { szX, szY }; + wchar_t wzX[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzY[MAX_LINE_LENGTH] = { 0 }; + LPWSTR aszTokens[] = { wzX, wzY }; - int nTokenCount = CommandTokenize(pszArgs, aszTokens, 2, NULL); - int nX = nTokenCount == 2 ? atoi(szX) : GetRCInt("LSRunX", 0); - int nY = nTokenCount == 2 ? atoi(szY) : GetRCInt("LSRunY", 0); + int nTokenCount = CommandTokenizeW(pwzArgs, aszTokens, 2, NULL); + int nX = nTokenCount == 2 ? _wtoi(wzX) : GetRCIntW(L"LSRunX", 0); + int nY = nTokenCount == 2 ? _wtoi(wzY) : GetRCIntW(L"LSRunY", 0); RunDlgType RunDlg = (RunDlgType)GetProcAddress( - GetModuleHandle("SHELL32.DLL"), (LPCSTR)((long)0x003D)); + GetModuleHandleW(L"SHELL32.DLL"), (LPCSTR)((long)0x003D)); if (RunDlg) { - HWND hParent = CreateWindowEx(WS_EX_TOOLWINDOW, "Static", "", + HWND hParent = CreateWindowExW(WS_EX_TOOLWINDOW, L"Static", L"", WS_POPUP, nX, nY, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); if (hParent) { @@ -345,17 +345,17 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) HWND hEditBox = GetDlgItem(window, 0x300A); if (hEditBox != nullptr) { - int nTextLength = GetWindowTextLength(hEditBox) + 1; - LPSTR pszText = (LPSTR)malloc(nTextLength*sizeof(char)); - GetWindowText(hEditBox, pszText, nTextLength); + int nTextLength = GetWindowTextLengthW(hEditBox) + 1; + LPWSTR pwzText = (LPWSTR)malloc(nTextLength*sizeof(wchar_t)); + GetWindowTextW(hEditBox, pwzText, nTextLength); // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. - if (pszText[0] == '!') + if (pwzText[0] == L'!') { - LSExecute(nullptr, pszText, SW_SHOWNORMAL); + LSExecuteW(nullptr, pwzText, SW_SHOWNORMAL); wParam = MAKEWPARAM(2, 0); // Click on cancel } - free(pszText); + free(pwzText); } } return WNDPROC(GetWindowLongPtr(window, GWLP_USERDATA))(window, message, wParam, lParam); @@ -380,9 +380,9 @@ static void BangRun(HWND /* hCaller */, LPCSTR pszArgs) // -// BangShutdown(HWND hCaller, LPCSTR pszArgs) +// BangShutdown(HWND hCaller, LPCWSTR pszArgs) // -static void BangShutdown(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangShutdown(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { HWND hLiteStep = GetLitestepWnd(); @@ -394,14 +394,14 @@ static void BangShutdown(HWND /* hCaller */, LPCSTR /* pszArgs */) // -// BangSwitchUser(HWND hCaller, LPCSTR pszArgs) +// BangSwitchUser(HWND hCaller, LPCWSTR pszArgs) // -static void BangSwitchUser(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangSwitchUser(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { typedef BOOL (WINAPI* LockWorkStationType)(VOID); LockWorkStationType LockWorkStation = (LockWorkStationType)GetProcAddress( - GetModuleHandle("USER32.DLL"), "LockWorkStation"); + GetModuleHandleW(L"USER32.DLL"), "LockWorkStation"); if (LockWorkStation) { @@ -411,38 +411,38 @@ static void BangSwitchUser(HWND /* hCaller */, LPCSTR /* pszArgs */) // -// BangTileWindowsH(HWND hCaller, LPCSTR pszArgs) +// BangTileWindowsH(HWND hCaller, LPCWSTR pszArgs) // -static void BangTileWindowsH(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangTileWindowsH(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL); } // -// BangTileWindowsV(HWND hCaller, LPCSTR pszArgs) +// BangTileWindowsV(HWND hCaller, LPCWSTR pszArgs) // -static void BangTileWindowsV(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangTileWindowsV(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL); } // -// BangUnloadModule(HWND hCaller, LPCSTR pszArgs) +// BangUnloadModule(HWND hCaller, LPCWSTR pszArgs) // -static void BangUnloadModule(HWND /* hCaller */, LPCSTR pszArgs) +static void BangUnloadModule(HWND /* hCaller */, LPCWSTR pwzArgs) { HWND hLiteStep = GetLitestepWnd(); if (hLiteStep) { - LPCSTR pszNextToken = pszArgs; - char szPath[MAX_LINE_LENGTH] = { 0 }; + LPCWSTR pwzNextToken = pwzArgs; + wchar_t wzPath[MAX_LINE_LENGTH] = { 0 }; - while (GetToken(pszNextToken, szPath, &pszNextToken, TRUE)) + while (GetTokenW(pwzNextToken, wzPath, &pwzNextToken, TRUE)) { - SendMessage(hLiteStep, LM_UNLOADMODULE, (WPARAM)szPath, 0); + SendMessage(hLiteStep, LM_UNLOADMODULEW, (WPARAM)wzPath, 0); } } } @@ -487,15 +487,19 @@ static void EMPHandler(HWND hWnd, PEMPCONFIG pEMPCfg) else if ((lUserData == HIDEmagicDWord) && (pEMPCfg->uMode == EMP_SHOW || pEMPCfg->uMode == EMP_TOGGLE)) { - SetWindowLongPtr(hWnd, GWLP_USERDATA, magicDWord); - pEMPCfg->hDwp = DeferWindowPos( - pEMPCfg->hDwp - ,hWnd - ,NULL - ,0 ,0 - ,0 ,0 - ,SWP_SHOWWINDOW | DEFAULT_FLAGS - ); + if (NULL == pEMPCfg->hMon || MonitorFromWindow( + hWnd, MONITOR_DEFAULTTONULL) == pEMPCfg->hMon) + { + SetWindowLongPtr(hWnd, GWLP_USERDATA, magicDWord); + pEMPCfg->hDwp = DeferWindowPos( + pEMPCfg->hDwp + ,hWnd + ,NULL + ,0 ,0 + ,0 ,0 + ,SWP_SHOWWINDOW | DEFAULT_FLAGS + ); + } } } } @@ -514,7 +518,7 @@ static BOOL CALLBACK EnumModulesProc(HWND hWnd, LPARAM lParam) // // BangHideModules(HWND hCaller, LPCSTR pszArgs) // -static void BangHideModules(HWND hCaller, LPCSTR /* pszArgs */) +static void BangHideModules(HWND hCaller, LPCWSTR /* pwzArgs */) { EMPCONFIG EMPCfg = { 0 }; @@ -538,12 +542,24 @@ static void BangHideModules(HWND hCaller, LPCSTR /* pszArgs */) // -// BangShowModules(HWND hCaller, LPCSTR pszArgs) +// BangShowModules(HWND hCaller, LPCWSTR pszArgs) // -static void BangShowModules(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangShowModules(HWND hCaller, LPCWSTR /* pwzArgs */) { EMPCONFIG EMPCfg = { 0 }; + // A hack to support showing modules on a specific monitor. + if (NULL != hCaller && !IsWindow(hCaller)) + { + // Check to see if this is a valid monitor handle + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + if (GetMonitorInfo((HMONITOR)hCaller, &mi)) + { + EMPCfg.hMon = (HMONITOR)hCaller; + } + } + EMPCfg.uMode = EMP_SHOW; EMPCfg.hDwp = BeginDeferWindowPos(10); EnumWindows(EnumModulesProc, (LPARAM)&EMPCfg); @@ -552,9 +568,9 @@ static void BangShowModules(HWND /* hCaller */, LPCSTR /* pszArgs */) // -// BangToggleModules(HWND hCaller, LPCSTR pszArgs) +// BangToggleModules(HWND hCaller, LPCWSTR pszArgs) // -static void BangToggleModules(HWND /* hCaller */, LPCSTR /* pszArgs */) +static void BangToggleModules(HWND /* hCaller */, LPCWSTR /* pwzArgs */) { EMPCONFIG EMPCfg = { 0 }; diff --git a/lsapi/graphics.cpp b/lsapi/graphics.cpp index eef2b5c..995237c 100644 --- a/lsapi/graphics.cpp +++ b/lsapi/graphics.cpp @@ -22,6 +22,7 @@ #include "png_support.h" #include "../utility/core.hpp" #include +#include "../utility/stringutility.h" static void TransparentBltLSWorker( @@ -234,28 +235,28 @@ HRGN BitmapToRegion( // -// HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) +// HBITMAP LoadLSImageW(LPCWSTR pwzImage, LPCWSTR pwzFile) // // Takes strings of the form: // File.bmp // .extract // .extract=file.exe[,3] -HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) +HBITMAP LoadLSImageW(LPCWSTR pwzImage, LPCWSTR pwzFile) { HBITMAP hbmReturn = NULL; - if (pszImage != NULL) + if (pwzImage != NULL) { - if (_stricmp(pszImage, ".none") != 0) + if (_wcsicmp(pwzImage, L".none") != 0) { - char szImage[MAX_PATH]; - StringCchCopy(szImage, MAX_PATH, pszImage); + wchar_t wzImage[MAX_PATH]; + StringCchCopyW(wzImage, _countof(wzImage), pwzImage); // Bitmap merging by Thedd // Thedd - pic1.bmp|pic2.bmp merges the images. Works recursively, // so pic1.bmp|.extract=whatever.dll,3|pic2.bmp also works etc... // bitmap merging by grd - LPSTR pszSecondImage = strchr(szImage, '|'); + LPWSTR pszSecondImage = wcschr(wzImage, L'|'); if (pszSecondImage) { HDC hdcFirst, hdcSecond, hdcResult; @@ -273,8 +274,8 @@ HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) ++pszSecondImage; // load the two bitmaps - hbmFirst = LoadLSImage(szImage, pszFile); - hbmSecond = LoadLSImage(pszSecondImage, pszFile); + hbmFirst = LoadLSImageW(wzImage, pwzFile); + hbmSecond = LoadLSImageW(pszSecondImage, pwzFile); // if the second one is NULL, then there's no merging to do and if (hbmSecond != NULL) @@ -352,11 +353,11 @@ HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) } else { - if (!_strnicmp(szImage, ".extract", 8 /*strlen(".extract")*/)) + if (!_wcsnicmp(wzImage, L".extract", 8 /*wcslen(L".extract")*/)) { HICON hIcon = NULL; - hIcon = LoadLSIcon(szImage, pszFile); + hIcon = LoadLSIconW(wzImage, pwzFile); if (hIcon) { @@ -368,20 +369,20 @@ HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) { // Append the image name to the LiteStep image path and // attempt to load the image. - char szExpandedImage[MAX_PATH]; + wchar_t wzExpandedImage[MAX_PATH]; - VarExpansionEx(szExpandedImage, szImage, MAX_PATH); - LSGetImagePath(szImage, MAX_PATH); - PathAppend(szImage, szExpandedImage); + VarExpansionExW(wzExpandedImage, wzImage, _countof(wzExpandedImage)); + LSGetImagePathW(wzImage, _countof(wzImage)); + PathAppendW(wzImage, wzExpandedImage); - if (PathMatchSpec(szImage, "*.png")) + if (PathMatchSpecW(wzImage, L"*.png")) { - hbmReturn = LoadFromPNG(szImage); + hbmReturn = LoadFromPNG(wzImage); } else { - hbmReturn = (HBITMAP)LoadImage( - NULL, szImage, IMAGE_BITMAP, 0, 0, + hbmReturn = (HBITMAP)LoadImageW( + NULL, wzImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE); } @@ -389,14 +390,14 @@ HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) // and try loading it if (hbmReturn == NULL) { - if (PathMatchSpec(szExpandedImage, "*.png")) + if (PathMatchSpecW(wzExpandedImage, L"*.png")) { - hbmReturn = LoadFromPNG(szExpandedImage); + hbmReturn = LoadFromPNG(wzExpandedImage); } else { - hbmReturn = (HBITMAP)LoadImage( - NULL, szExpandedImage, IMAGE_BITMAP, 0, 0, + hbmReturn = (HBITMAP)LoadImageW( + NULL, wzExpandedImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_LOADFROMFILE); } } @@ -409,6 +410,18 @@ HBITMAP LoadLSImage(LPCSTR pszImage, LPCSTR pszFile) } +// +// LoadLSImageA +// +HBITMAP LoadLSImageA(LPCSTR pszImage, LPCSTR pszFile) +{ + return LoadLSImageW( + std::unique_ptr(WCSFromMBS(pszImage)).get(), + std::unique_ptr(WCSFromMBS(pszFile)).get() + ); +} + + // // BitmapFromIcon(HICON hIcon) // @@ -440,7 +453,7 @@ HBITMAP BitmapFromIcon(HICON hIcon) // -// LoadLSIcon(LPCSTR pszIconPath, LPCSTR pszFile) +// LoadLSIconW(LPCWSTR pwzIconPath, LPCWSTR pwzFile) // // Takes strings of the form: // File.ico @@ -448,17 +461,17 @@ HBITMAP BitmapFromIcon(HICON hIcon) // c:\path\ <- icon extraction for path out of desktop.ini // .extract // .extract=file.exe[,3] ... and returns an icon -HICON LoadLSIcon(LPCSTR pszIconPath, LPCSTR pszFile) +HICON LoadLSIconW(LPCWSTR pwzIconPath, LPCWSTR pwzFile) { HICON hIcon = NULL; - if (pszIconPath != NULL) + if (pwzIconPath != NULL) { - if (_stricmp(pszIconPath, ".none") != 0) + if (_wcsicmp(pwzIconPath, L".none") != 0) { - char szIconPath[MAX_PATH]; - char szIconLSImagePath[MAX_PATH]; - LPSTR pszIconFile = (LPSTR)pszIconPath; + wchar_t wzIconPath[MAX_PATH]; + wchar_t wzIconLSImagePath[MAX_PATH]; + LPWSTR pwzIconFile = (LPWSTR)pwzIconPath; int nIcon = 0; // here comes a large block which does nothing but turning it into @@ -467,61 +480,61 @@ HICON LoadLSIcon(LPCSTR pszIconPath, LPCSTR pszFile) // if .extract but nothing else is there... // then take the file specified as an icon (could probably be done // earlier, but anyhow) - if (_stricmp(pszIconPath, ".extract") == 0) + if (_wcsicmp(pwzIconPath, L".extract") == 0) { - pszIconFile = (LPSTR)pszFile; + pwzIconFile = (LPWSTR)pwzFile; } - else if (_strnicmp(pszIconPath, ".extract=", 9) == 0) + else if (_wcsnicmp(pwzIconPath, L".extract=", 9) == 0) { // remove ".extract=" (as we won't use it anyway) - pszIconFile = (LPSTR)pszIconPath + 9; + pwzIconFile = (LPWSTR)pwzIconPath + 9; } - VarExpansionEx(szIconPath, pszIconFile, MAX_PATH); + VarExpansionExW(wzIconPath, pwzIconFile, _countof(wzIconPath)); - if (PathIsRelative(szIconPath)) + if (PathIsRelativeW(wzIconPath)) { - LSGetImagePath(szIconLSImagePath, MAX_PATH); - PathAppend(szIconLSImagePath, szIconPath); - pszIconFile = szIconLSImagePath; + LSGetImagePathW(wzIconLSImagePath, _countof(wzIconLSImagePath)); + PathAppendW(wzIconLSImagePath, wzIconPath); + pwzIconFile = wzIconLSImagePath; } else { - pszIconFile = szIconPath; + pwzIconFile = wzIconPath; } // large block ends here, now time to separate path and index (if we // have an index) - nIcon = PathParseIconLocation(pszIconFile); + nIcon = PathParseIconLocationW(pwzIconFile); // now we have the two vars we would like, and the loading can begin // well not really, if it's a path, where we're going to get the // icon form desktop.ini there is just a little bit more we have to // do before we can start loading - if (PathIsDirectory(pszIconFile)) + if (PathIsDirectoryW(pwzIconFile)) { - char szTemp[MAX_PATH]; + wchar_t wzTemp[MAX_PATH]; - PathAppend(pszIconFile, "desktop.ini"); - nIcon = GetPrivateProfileInt(".ShellClassInfo", "IconIndex", - 0, pszIconFile); + PathAppendW(pwzIconFile, L"desktop.ini"); + nIcon = GetPrivateProfileIntW(L".ShellClassInfo", L"IconIndex", + 0, pwzIconFile); - GetPrivateProfileString(".ShellClassInfo", "IconFile", - "", szTemp, MAX_PATH, pszIconFile); - StringCchCopy(pszIconFile, MAX_PATH, szTemp); + GetPrivateProfileStringW(L".ShellClassInfo", L"IconFile", + L"", wzTemp, _countof(wzTemp), pwzIconFile); + StringCchCopyW(pwzIconFile, MAX_PATH, wzTemp); } // okay, now it's really time to load the icon... if it's an .ico // file we want to do an LoadImage() thing, otherwise it's // extracticon so lets find out the extension - if (PathMatchSpec(pszIconFile, "*.ico")) + if (PathMatchSpecW(pwzIconFile, L"*.ico")) { - hIcon = (HICON)LoadImage( - NULL, pszIconFile, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + hIcon = (HICON)LoadImageW( + NULL, pwzIconFile, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); } else { - hIcon = ExtractIcon(GetModuleHandle(NULL), pszIconFile, nIcon); + hIcon = ExtractIconW(GetModuleHandle(NULL), pwzIconFile, nIcon); if (hIcon == (HICON)1) { @@ -535,6 +548,18 @@ HICON LoadLSIcon(LPCSTR pszIconPath, LPCSTR pszFile) } +// +// LoadLSIconA +// +HICON LoadLSIconA(LPCSTR pszIconPath, LPCSTR pszFile) +{ + return LoadLSIconW( + std::unique_ptr(WCSFromMBS(pszIconPath)).get(), + std::unique_ptr(WCSFromMBS(pszFile)).get() + ); +} + + // // GetLSBitmapSize(HBITMAP hBitmap, LPINT nWidth, LPINT nHeight) // @@ -544,13 +569,25 @@ void GetLSBitmapSize(HBITMAP hBitmap, LPINT nWidth, LPINT nHeight) if (!GetObject(hBitmap, sizeof(hbmBitmap), (LPSTR) & hbmBitmap)) { - *nWidth = 0; - *nHeight = 0; + if (nWidth) + { + *nWidth = 0; + } + if (nHeight) + { + *nHeight = 0; + } } else { - *nWidth = hbmBitmap.bmWidth; - *nHeight = hbmBitmap.bmHeight; + if (nWidth) + { + *nWidth = hbmBitmap.bmWidth; + } + if (nHeight) + { + *nHeight = hbmBitmap.bmHeight; + } } } diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index e0469fe..bcc3785 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -27,7 +27,7 @@ static int _Tokenize(LPCSTR pszString, LPSTR* lpszBuffers, DWORD dwNumBuffers, LPSTR pszExtraParameters, BOOL bUseBrackets); -BOOL LSAPIInitialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) +BOOL LSAPIInitialize(LPCWSTR pszLitestepPath, LPCWSTR pszRcPath) { try { @@ -41,6 +41,7 @@ BOOL LSAPIInitialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) return g_LSAPIManager.IsInitialized() ? TRUE : FALSE; } + void LSAPIReloadBangs(VOID) { try @@ -53,6 +54,7 @@ void LSAPIReloadBangs(VOID) } } + void LSAPIReloadSettings(VOID) { try @@ -65,27 +67,28 @@ void LSAPIReloadSettings(VOID) } } + void LSAPISetLitestepWindow(HWND hLitestepWnd) { g_LSAPIManager.SetLitestepWindow(hLitestepWnd); } -template -BOOL AddBangCommandWorker(LPCSTR pszCommand, T pfnBangCommand) +template +static BOOL AddBangCommandWorker(LPCWSTR pwzCommand, BangType pfnBangCommand) { BOOL bReturn = FALSE; - if (pszCommand != NULL && pfnBangCommand != NULL) + if (pwzCommand != nullptr && pfnBangCommand != nullptr) { DWORD dwCurrentThreadID = GetCurrentThreadId(); - Bang* pBang = new Bang(dwCurrentThreadID, pfnBangCommand, pszCommand); + Bang* pBang = new Bang(dwCurrentThreadID, pfnBangCommand, pwzCommand); - if (pBang != NULL) + if (pBang != nullptr) { //bBang->AddRef(); - g_LSAPIManager.GetBangManager()->AddBangCommand(pszCommand, pBang); + g_LSAPIManager.GetBangManager()->AddBangCommand(pwzCommand, pBang); pBang->Release(); bReturn = TRUE; } @@ -96,34 +99,72 @@ BOOL AddBangCommandWorker(LPCSTR pszCommand, T pfnBangCommand) // -// AddBangCommand +// AddBangCommandW +// +BOOL AddBangCommandW(LPCWSTR pwzCommand, BangCommandW pfnBangCommand) +{ + return AddBangCommandWorker(pwzCommand, pfnBangCommand); +} + + +// +// AddBangCommandA +// +BOOL AddBangCommandA(LPCSTR pszCommand, BangCommandA pfnBangCommand) +{ + return AddBangCommandWorker(std::unique_ptr(WCSFromMBS(pszCommand)).get(), + pfnBangCommand); +} + + +// +// AddBangCommandExW // -BOOL AddBangCommand(LPCSTR pszCommand, BangCommand pfnBangCommand) +BOOL AddBangCommandExW(LPCWSTR pwzCommand, BangCommandExW pfnBangCommand) { - return AddBangCommandWorker(pszCommand, pfnBangCommand); + return AddBangCommandWorker(pwzCommand, pfnBangCommand); } // -// AddBangCommandEx +// AddBangCommandExA // -BOOL AddBangCommandEx(LPCSTR pszCommand, BangCommandEx pfnBangCommand) +BOOL AddBangCommandExA(LPCSTR pszCommand, BangCommandExA pfnBangCommand) { - return AddBangCommandWorker(pszCommand, pfnBangCommand); + return AddBangCommandWorker(std::unique_ptr(WCSFromMBS(pszCommand)).get(), + pfnBangCommand); } // -// RemoveBangCommand(LPCSTR pszCommand) +// RemoveBangCommandW(LPCWSTR pwzCommand) // -BOOL RemoveBangCommand(LPCSTR pszCommand) +BOOL RemoveBangCommandW(LPCWSTR pwzCommand) { BOOL bResult = FALSE; - if (pszCommand != NULL) + if (pwzCommand != nullptr) { bResult = \ - g_LSAPIManager.GetBangManager()->RemoveBangCommand(pszCommand); + g_LSAPIManager.GetBangManager()->RemoveBangCommand(pwzCommand); + } + + return bResult; +} + + +// +// RemoveBangCommandA(LPCSTR pszCommand) +// +BOOL RemoveBangCommandA(LPCSTR pszCommand) +{ + BOOL bResult = FALSE; + + if (pszCommand != nullptr) + { + bResult = g_LSAPIManager.GetBangManager()->RemoveBangCommand( + std::unique_ptr(WCSFromMBS(pszCommand)).get() + ); } return bResult; @@ -134,33 +175,33 @@ BOOL RemoveBangCommand(LPCSTR pszCommand) // InternalExecuteBangCommand // (Just like ParseBangCommand but without the variable expansion) // -BOOL InternalExecuteBangCommand(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs) +BOOL InternalExecuteBangCommand(HWND hCaller, LPCWSTR pwzCommand, LPCWSTR pwzArgs) { return g_LSAPIManager.GetBangManager()-> - ExecuteBangCommand(pszCommand, hCaller, pszArgs); + ExecuteBangCommand(pwzCommand, hCaller, pwzArgs); } // -// ParseBangCommand +// ParseBangCommandW // -BOOL ParseBangCommand(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs) +BOOL ParseBangCommandW(HWND hCaller, LPCWSTR pwzCommand, LPCWSTR pwzArgs) { - TRACE("ParseBangCommand(%.8X, \"%s\", \"%s\");", - hCaller, pszCommand, pszArgs); + TRACE("ParseBangCommand(%p, \"%ls\", \"%ls\");", + hCaller, pwzCommand, pwzArgs); - char szExpandedArgs[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpandedArgs[MAX_LINE_LENGTH] = { 0 }; BOOL bReturn = FALSE; - if (pszCommand != NULL) + if (pwzCommand != nullptr) { - if (pszArgs != NULL) + if (pwzArgs != nullptr) { - VarExpansionEx(szExpandedArgs, pszArgs, MAX_LINE_LENGTH); + VarExpansionExW(wzExpandedArgs, pwzArgs, MAX_LINE_LENGTH); } bReturn = \ - InternalExecuteBangCommand(hCaller, pszCommand, szExpandedArgs); + InternalExecuteBangCommand(hCaller, pwzCommand, wzExpandedArgs); } return bReturn; @@ -168,67 +209,106 @@ BOOL ParseBangCommand(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs) // -// CommandParse +// ParseBangCommandA +// +BOOL ParseBangCommandA(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs) +{ + return ParseBangCommandW(hCaller, + std::unique_ptr(WCSFromMBS(pszCommand)).get(), + std::unique_ptr(WCSFromMBS(pszArgs)).get()); +} + + +// +// CommandParseW +// +void CommandParseW(LPCWSTR pwzCommand, LPWSTR pwzOutCommand, LPWSTR pwzOutArgs, size_t cchOutCommand, size_t cchOutArgs) +{ + wchar_t wzCommand[MAX_LINE_LENGTH]; + wchar_t wzTempCommand[MAX_LINE_LENGTH]; + LPCWSTR pwzTempArgs = nullptr; + + if (pwzCommand != nullptr) + { + if (pwzOutCommand != nullptr && cchOutCommand > 0) + { + VarExpansionExW(wzCommand, pwzCommand, MAX_LINE_LENGTH); + + GetTokenW(wzCommand, wzTempCommand, &pwzTempArgs, TRUE); + + StringCchCopyW(pwzOutCommand, cchOutCommand, wzTempCommand); + } + + if (pwzOutArgs != nullptr && cchOutArgs > 0) + { + StringCchCopyW(pwzOutArgs, cchOutArgs, pwzTempArgs); + } + } +} + + +// +// CommandParseA // -void CommandParse(LPCSTR pszCommand, LPSTR pszOutCommand, LPSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs) +void CommandParseA(LPCSTR pszCommand, LPSTR pszOutCommand, LPSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs) { char szCommand[MAX_LINE_LENGTH]; char szTempCommand[MAX_LINE_LENGTH]; - LPCSTR pszTempArgs = NULL; + LPCSTR pszTempArgs = nullptr; - if (pszCommand != NULL) + if (pszCommand != nullptr) { - if (pszOutCommand != NULL && cchOutCommand > 0) + if (pszOutCommand != nullptr && cchOutCommand > 0) { - VarExpansionEx(szCommand, pszCommand, MAX_LINE_LENGTH); + VarExpansionExA(szCommand, pszCommand, MAX_LINE_LENGTH); - GetToken(szCommand, szTempCommand, &pszTempArgs, TRUE); + GetTokenA(szCommand, szTempCommand, &pszTempArgs, TRUE); - StringCchCopy(pszOutCommand, cchOutCommand, szTempCommand); + StringCchCopyA(pszOutCommand, cchOutCommand, szTempCommand); } - if (pszOutArgs != NULL && cchOutArgs > 0) + if (pszOutArgs != nullptr && cchOutArgs > 0) { - StringCchCopy(pszOutArgs, cchOutArgs, pszTempArgs); + StringCchCopyA(pszOutArgs, cchOutArgs, pszTempArgs); } } } // -// LSExecuteEx +// LSExecuteExW // -HINSTANCE LSExecuteEx(HWND hOwner, LPCSTR pszOperation, LPCSTR pszCommand, LPCSTR pszArgs, LPCSTR pszDirectory, int nShowCmd) +HINSTANCE LSExecuteExW(HWND hOwner, LPCWSTR pwzOperation, LPCWSTR pwzCommand, LPCWSTR pwzArgs, LPCWSTR pwzDirectory, int nShowCmd) { HINSTANCE hReturn = HINSTANCE(32); - if (pszCommand != NULL) + if (pwzCommand != nullptr) { - if (pszCommand[0] == '!') + if (pwzCommand[0] == L'!') { - hReturn = ParseBangCommand(hOwner, pszCommand, pszArgs) ? + hReturn = ParseBangCommandW(hOwner, pwzCommand, pwzArgs) ? HINSTANCE(33) : HINSTANCE(32); } else { - TRACE("LSExecuteEx(%.8X, \"%s\", \"%s\", \"%s\", \"%s\", %d);", - hOwner, pszOperation, pszCommand, pszArgs,pszDirectory, + TRACE("LSExecuteEx(%p, \"%ls\", \"%ls\", \"%ls\", \"%ls\", %d);", + hOwner, pwzOperation, pwzCommand, pwzArgs, pwzDirectory, nShowCmd); - if (PathIsDirectory(pszCommand)) + if (PathIsDirectoryW(pwzCommand)) { - hReturn = LSShellExecute(hOwner, pszOperation, pszCommand, - pszArgs, NULL, nShowCmd ? nShowCmd : SW_SHOWNORMAL); + hReturn = LSShellExecute(hOwner, pwzOperation, pwzCommand, + pwzArgs, NULL, nShowCmd ? nShowCmd : SW_SHOWNORMAL); } else { - SHELLEXECUTEINFO seiCommand = { 0 }; - seiCommand.cbSize = sizeof(SHELLEXECUTEINFO); + SHELLEXECUTEINFOW seiCommand = { 0 }; + seiCommand.cbSize = sizeof(SHELLEXECUTEINFOW); seiCommand.hwnd = hOwner; - seiCommand.lpVerb = pszOperation; - seiCommand.lpFile = pszCommand; - seiCommand.lpParameters = pszArgs; - seiCommand.lpDirectory = pszDirectory; + seiCommand.lpVerb = pwzOperation; + seiCommand.lpFile = pwzCommand; + seiCommand.lpParameters = pwzArgs; + seiCommand.lpDirectory = pwzDirectory; seiCommand.nShow = nShowCmd; seiCommand.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI; @@ -244,41 +324,56 @@ HINSTANCE LSExecuteEx(HWND hOwner, LPCSTR pszOperation, LPCSTR pszCommand, LPCST // -// LSExecute +// LSExecuteExA // -HINSTANCE LSExecute(HWND hOwner, LPCSTR pszCommand, int nShowCmd) +HINSTANCE LSExecuteExA(HWND hOwner, LPCSTR pszOperation, LPCSTR pszCommand, LPCSTR pszArgs, LPCSTR pszDirectory, int nShowCmd) { - char szCommand[MAX_LINE_LENGTH]; - char szExpandedCommand[MAX_LINE_LENGTH]; - LPCSTR pszArgs; + return LSExecuteExW( + hOwner, + std::unique_ptr(WCSFromMBS(pszOperation)).get(), + std::unique_ptr(WCSFromMBS(pszCommand)).get(), + std::unique_ptr(WCSFromMBS(pszArgs)).get(), + std::unique_ptr(WCSFromMBS(pszDirectory)).get(), + nShowCmd); +} + + +// +// LSExecuteW +// +HINSTANCE LSExecuteW(HWND hOwner, LPCWSTR pwzCommand, int nShowCmd) +{ + wchar_t wzCommand[MAX_LINE_LENGTH]; + wchar_t wzExpandedCommand[MAX_LINE_LENGTH]; + LPCWSTR pwzArgs; HINSTANCE hResult = HINSTANCE(32); - if (pszCommand != NULL) + if (pwzCommand != nullptr) { - VarExpansionEx(szExpandedCommand, pszCommand, MAX_LINE_LENGTH); + VarExpansionExW(wzExpandedCommand, pwzCommand, MAX_LINE_LENGTH); - if (GetToken(szExpandedCommand, szCommand, &pszArgs, TRUE)) + if (GetTokenW(wzExpandedCommand, wzCommand, &pwzArgs, TRUE)) { - if (pszArgs > (szExpandedCommand + strlen(szExpandedCommand))) + if (pwzArgs > (wzExpandedCommand + wcslen(wzExpandedCommand))) { - pszArgs = NULL; + pwzArgs = nullptr; } - if (szCommand[0] == '!') + if (wzCommand[0] == L'!') { - hResult = LSExecuteEx(hOwner, NULL, - szCommand, pszArgs, NULL, 0); + hResult = LSExecuteExW(hOwner, nullptr, + wzCommand, pwzArgs, nullptr, 0); } else { - char szDir[_MAX_DIR]; - char szFullDir[_MAX_DIR + _MAX_DRIVE]; + wchar_t wzDir[_MAX_DIR]; + wchar_t wzFullDir[_MAX_DIR + _MAX_DRIVE]; - _splitpath(szCommand, szFullDir, szDir, NULL, NULL); - StringCchCat(szFullDir, _MAX_DIR + _MAX_DRIVE, szDir); + _wsplitpath_s(wzCommand, wzFullDir, _countof(wzFullDir), wzDir, _countof(wzDir), nullptr, 0, nullptr, 0); + StringCchCatW(wzFullDir, _MAX_DIR + _MAX_DRIVE, wzDir); - hResult = LSExecuteEx(hOwner, NULL, szCommand, pszArgs, - szFullDir, nShowCmd ? nShowCmd : SW_SHOWNORMAL); + hResult = LSExecuteExW(hOwner, NULL, wzCommand, pwzArgs, + wzFullDir, nShowCmd ? nShowCmd : SW_SHOWNORMAL); } } } @@ -286,6 +381,16 @@ HINSTANCE LSExecute(HWND hOwner, LPCSTR pszCommand, int nShowCmd) return hResult; } + +// +// LSExecuteA +// +HINSTANCE LSExecuteA(HWND hOwner, LPCSTR pszCommand, int nShowCmd) +{ + return LSExecuteW(hOwner, std::unique_ptr(WCSFromMBS(pszCommand)).get(), nShowCmd); +} + + // // SetDesktopArea // @@ -299,7 +404,7 @@ void SetDesktopArea(int left, int top, int right, int bottom) // -// GetLitestepWnd +// GetLitestepWnd // HWND GetLitestepWnd() { @@ -308,9 +413,9 @@ HWND GetLitestepWnd() // -// void GetResStr +// GetResStrW // -void GetResStr(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText) +void GetResStrW(HINSTANCE hInstance, UINT uIDText, LPWSTR pszText, size_t cchText, LPCWSTR pszDefText) { if (pszText != NULL && cchText > 0) { @@ -323,16 +428,31 @@ void GetResStr(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, // -// GetResStrEx +// GetResStrA // -void GetResStrEx(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText, ...) +void GetResStrA(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText) { - char szFormat[MAX_LINE_LENGTH]; + if (pszText != nullptr && cchText > 0) + { + if (LoadStringA(hInstance, uIDText, pszText, (int)cchText) == 0) + { + StringCchCopyA(pszText, cchText, pszDefText); + } + } +} + + +// +// GetResStrExW +// +void GetResStrExW(HINSTANCE hInstance, UINT uIDText, LPWSTR pszText, size_t cchText, LPCWSTR pszDefText, ...) +{ + wchar_t szFormat[MAX_LINE_LENGTH]; va_list vargs; if (pszText != NULL && cchText > 0) { - GetResStr(hInstance, uIDText, szFormat, MAX_LINE_LENGTH, pszDefText); + GetResStrW(hInstance, uIDText, szFormat, MAX_LINE_LENGTH, pszDefText); va_start(vargs, pszDefText); StringCchVPrintf(pszText, cchText, szFormat, vargs); @@ -342,16 +462,55 @@ void GetResStrEx(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchTex // -// LSGetLitestepPath +// GetResStrExA +// +void GetResStrExA(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText, ...) +{ + char szFormat[MAX_LINE_LENGTH]; + va_list vargs; + + if (pszText != NULL && cchText > 0) + { + GetResStrA(hInstance, uIDText, szFormat, MAX_LINE_LENGTH, pszDefText); + + va_start(vargs, pszDefText); + StringCchVPrintfA(pszText, cchText, szFormat, vargs); + va_end(vargs); + } +} + + +// +// LSGetLitestepPathW +// +BOOL WINAPI LSGetLitestepPathW(LPWSTR pwzPath, size_t cchPath) +{ + BOOL bReturn = FALSE; + + if (pwzPath != nullptr && cchPath > 0) + { + // Default to user defined variable + if (GetRCStringW(L"litestepdir", pwzPath, nullptr, (int)cchPath)) + { + bReturn = TRUE; + } + } + + return bReturn; +} + + +// +// LSGetLitestepPathA // -BOOL WINAPI LSGetLitestepPath(LPSTR pszPath, size_t cchPath) +BOOL WINAPI LSGetLitestepPathA(LPSTR pszPath, size_t cchPath) { BOOL bReturn = FALSE; - if (pszPath != NULL && cchPath > 0) + if (pszPath != nullptr && cchPath > 0) { // Default to user defined variable - if (GetRCString("litestepdir", pszPath, NULL, (int)cchPath)) + if (GetRCStringA("litestepdir", pszPath, nullptr, (int)cchPath)) { bReturn = TRUE; } @@ -362,23 +521,50 @@ BOOL WINAPI LSGetLitestepPath(LPSTR pszPath, size_t cchPath) // -// LSGetImagePath +// LSGetImagePathW +// +BOOL WINAPI LSGetImagePathW(LPWSTR pwzPath, size_t cchPath) +{ + BOOL bReturn = FALSE; + + if (pwzPath != nullptr && cchPath > 0) + { + if (GetRCStringW(L"LSImageFolder", pwzPath, nullptr, (int)cchPath)) + { + bReturn = SUCCEEDED(PathAddBackslashEx(pwzPath, cchPath)); + } + else + { + if (LSGetLitestepPathW(pwzPath, cchPath)) + { + StringCchCat(pwzPath, cchPath, L"images\\"); + bReturn = TRUE; + } + } + } + + return bReturn; +} + + +// +// LSGetImagePathA // -BOOL WINAPI LSGetImagePath(LPSTR pszPath, size_t cchPath) +BOOL WINAPI LSGetImagePathA(LPSTR pszPath, size_t cchPath) { BOOL bReturn = FALSE; - if (pszPath != NULL && cchPath > 0) + if (pszPath != nullptr && cchPath > 0) { - if (GetRCString("LSImageFolder", pszPath, NULL, (int)cchPath)) + if (GetRCStringA("LSImageFolder", pszPath, nullptr, (int)cchPath)) { - bReturn = SUCCEEDED(PathAddBackslashEx(pszPath, cchPath)); + bReturn = SUCCEEDED(PathAddBackslashExA(pszPath, cchPath)); } else { - if (LSGetLitestepPath(pszPath, cchPath)) + if (LSGetLitestepPathA(pszPath, cchPath)) { - StringCchCat(pszPath, cchPath, "images\\"); + StringCchCatA(pszPath, cchPath, "images\\"); bReturn = TRUE; } } @@ -388,6 +574,67 @@ BOOL WINAPI LSGetImagePath(LPSTR pszPath, size_t cchPath) } +// +// _Tokenize +// (local helper function) +// +static int _Tokenize(LPCWSTR pwzString, LPWSTR* lpwzBuffers, DWORD dwNumBuffers, LPWSTR pwzExtraParameters, BOOL bUseBrackets) +{ + wchar_t wzBuffer[MAX_LINE_LENGTH]; + LPCWSTR pwzNextToken; + DWORD dwTokens = 0; + + if (pwzString != nullptr) + { + pwzNextToken = pwzString; + + if ((lpwzBuffers != nullptr) && (dwNumBuffers > 0)) + { + for (; pwzNextToken && dwTokens < dwNumBuffers; ++dwTokens) + { + GetTokenW(pwzNextToken, wzBuffer, &pwzNextToken, bUseBrackets); + + if (lpwzBuffers[dwTokens] != nullptr) + { + StringCchCopyW(lpwzBuffers[dwTokens], + wcslen(wzBuffer) + 1, wzBuffer); + } + } + + for (DWORD dwClear = dwTokens; dwClear < dwNumBuffers; ++dwClear) + { + if (lpwzBuffers[dwClear] != nullptr) + { + lpwzBuffers[dwClear][0] = L'\0'; + } + } + + if (pwzExtraParameters != nullptr) + { + if (pwzNextToken) + { + StringCchCopyW(pwzExtraParameters, + wcslen(pwzNextToken) + 1, pwzNextToken); + } + else + { + pwzExtraParameters[0] = L'\0'; + } + } + } + else + { + while (GetTokenW(pwzNextToken, nullptr, &pwzNextToken, bUseBrackets)) + { + ++dwTokens; + } + } + } + + return dwTokens; +} + + // // _Tokenize // (local helper function) @@ -398,36 +645,36 @@ static int _Tokenize(LPCSTR pszString, LPSTR* lpszBuffers, DWORD dwNumBuffers, L LPCSTR pszNextToken; DWORD dwTokens = 0; - if (pszString != NULL) + if (pszString != nullptr) { pszNextToken = pszString; - if ((lpszBuffers != NULL) && (dwNumBuffers > 0)) + if ((lpszBuffers != nullptr) && (dwNumBuffers > 0)) { for (; pszNextToken && dwTokens < dwNumBuffers; ++dwTokens) { - GetToken(pszNextToken, szBuffer, &pszNextToken, bUseBrackets); + GetTokenA(pszNextToken, szBuffer, &pszNextToken, bUseBrackets); - if (lpszBuffers[dwTokens] != NULL) + if (lpszBuffers[dwTokens] != nullptr) { - StringCchCopy(lpszBuffers[dwTokens], + StringCchCopyA(lpszBuffers[dwTokens], strlen(szBuffer) + 1, szBuffer); } } for (DWORD dwClear = dwTokens; dwClear < dwNumBuffers; ++dwClear) { - if (lpszBuffers[dwClear] != NULL) + if (lpszBuffers[dwClear] != nullptr) { lpszBuffers[dwClear][0] = '\0'; } } - if (pszExtraParameters != NULL) + if (pszExtraParameters != nullptr) { if (pszNextToken) { - StringCchCopy(pszExtraParameters, + StringCchCopyA(pszExtraParameters, strlen(pszNextToken) + 1, pszNextToken); } else @@ -438,7 +685,7 @@ static int _Tokenize(LPCSTR pszString, LPSTR* lpszBuffers, DWORD dwNumBuffers, L } else { - while (GetToken(pszNextToken, NULL, &pszNextToken, bUseBrackets)) + while (GetTokenA(pszNextToken, nullptr, &pszNextToken, bUseBrackets)) { ++dwTokens; } @@ -450,24 +697,159 @@ static int _Tokenize(LPCSTR pszString, LPSTR* lpszBuffers, DWORD dwNumBuffers, L // -// LCTokenize +// LCTokenizeW +// +int LCTokenizeW(LPCWSTR pwzString, LPWSTR *lpwzBuffers, DWORD dwNumBuffers, LPWSTR pwzExtraParameters) +{ + return _Tokenize(pwzString, + lpwzBuffers, dwNumBuffers, + pwzExtraParameters, + FALSE); +} + +// +// LCTokenizeW // -int LCTokenize(LPCSTR szString, LPSTR *lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters) +int LCTokenizeA(LPCSTR pszString, LPSTR *lpszBuffers, DWORD dwNumBuffers, LPSTR pszExtraParameters) { - return _Tokenize(szString, + return _Tokenize(pszString, lpszBuffers, dwNumBuffers, - szExtraParameters, + pszExtraParameters, FALSE); } +// +// GetTokenW +// +BOOL GetTokenW(LPCWSTR pszString, LPWSTR pszToken, LPCWSTR* pszNextToken, BOOL bUseBrackets) +{ + LPCWSTR pszCurrent = pszString; + LPCWSTR pszStartMarker = nullptr; + int iBracketLevel = 0; + WCHAR cQuote = L'\0'; + bool bIsToken = false; + bool bAppendNextToken = false; + + if (pszString) + { + if (pszToken) + { + pszToken[0] = '\0'; + } + + if (pszNextToken) + { + *pszNextToken = nullptr; + } + + pszCurrent += wcsspn(pszCurrent, WHITESPACEW); + + for (; *pszCurrent; ++pszCurrent) + { + if (iswspace((wint_t)*pszCurrent) && !cQuote) + { + break; + } + + if (bUseBrackets && wcschr(L"[]", *pszCurrent) && + (!wcschr(L"\'\"", cQuote) || !cQuote)) + { + if (*pszCurrent == L'[') + { + if (bIsToken && !cQuote) + { + break; + } + + ++iBracketLevel; + cQuote = L'['; + + if (iBracketLevel == 1) + { + continue; + } + } + else + { + --iBracketLevel; + + if (iBracketLevel <= 0) + { + break; + } + } + } + + if (wcschr(L"\'\"", *pszCurrent) && (cQuote != L'[')) + { + if (!cQuote) + { + if (bIsToken) + { + bAppendNextToken = true; + break; + } + + cQuote = *pszCurrent; + continue; + } + else if (*pszCurrent == cQuote) + { + break; + } + } + + if (!bIsToken) + { + bIsToken = true; + pszStartMarker = pszCurrent; + } + } + + if (pszStartMarker && pszToken) + { + wcsncpy(pszToken, pszStartMarker, pszCurrent - pszStartMarker); + pszToken[pszCurrent - pszStartMarker] = L'\0'; + } + + if (!bAppendNextToken && *pszCurrent) + { + ++pszCurrent; + } + + pszCurrent += wcsspn(pszCurrent, WHITESPACEW); + + if (*pszCurrent && pszNextToken) + { + *pszNextToken = pszCurrent; + } + + if (bAppendNextToken && *pszCurrent) + { + LPWSTR pszNewToken = pszToken; + + if (pszNewToken) + { + pszNewToken += wcslen(pszToken); + } + + GetTokenW(pszCurrent, pszNewToken, pszNextToken, bUseBrackets); + } + + return pszStartMarker != nullptr; + } + + return FALSE; +} + // -// GetToken +// GetTokenA // -BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseBrackets) +BOOL GetTokenA(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseBrackets) { LPCSTR pszCurrent = pszString; - LPCSTR pszStartMarker = NULL; + LPCSTR pszStartMarker = nullptr; int iBracketLevel = 0; CHAR cQuote = '\0'; bool bIsToken = false; @@ -482,10 +864,10 @@ BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseB if (pszNextToken) { - *pszNextToken = NULL; + *pszNextToken = nullptr; } - pszCurrent += strspn(pszCurrent, WHITESPACE); + pszCurrent += strspn(pszCurrent, WHITESPACEA); for (; *pszCurrent; ++pszCurrent) { @@ -551,6 +933,7 @@ BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseB if (pszStartMarker && pszToken) { + //StringCchCopyNA(pszToken, cchToken, pszStartMarker, pszCurrent - pszStartMarker); strncpy(pszToken, pszStartMarker, pszCurrent - pszStartMarker); pszToken[pszCurrent - pszStartMarker] = '\0'; } @@ -560,7 +943,7 @@ BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseB ++pszCurrent; } - pszCurrent += strspn(pszCurrent, WHITESPACE); + pszCurrent += strspn(pszCurrent, WHITESPACEA); if (*pszCurrent && pszNextToken) { @@ -576,10 +959,10 @@ BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseB pszNewToken += strlen(pszToken); } - GetToken(pszCurrent, pszNewToken, pszNextToken, bUseBrackets); + GetTokenA(pszCurrent, pszNewToken, pszNextToken, bUseBrackets); } - return pszStartMarker != NULL; + return pszStartMarker != nullptr; } return FALSE; @@ -589,79 +972,134 @@ BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR* pszNextToken, BOOL bUseB // // CommandTokenize // -int CommandTokenize(LPCSTR szString, LPSTR *lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters) +int CommandTokenizeW(LPCWSTR pwzString, LPWSTR *lpwzBuffers, DWORD dwNumBuffers, LPWSTR pwzExtraParameters) +{ + return _Tokenize(pwzString, + lpwzBuffers, dwNumBuffers, + pwzExtraParameters, + TRUE); +} + + +// +// CommandTokenize +// +int CommandTokenizeA(LPCSTR pszString, LPSTR *lpszBuffers, DWORD dwNumBuffers, LPSTR pszExtraParameters) { - return _Tokenize(szString, + return _Tokenize(pszString, lpszBuffers, dwNumBuffers, - szExtraParameters, + pszExtraParameters, TRUE); } // -// VarExpansion +// VarExpansionW // -void VarExpansion(LPSTR pszExpandedString, LPCSTR pszTemplate) +void VarExpansionW(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate) { - if (pszExpandedString != NULL && pszTemplate != NULL) + if (pwzExpandedString != nullptr && pwzTemplate != nullptr) + { + wchar_t wzTempBuffer[MAX_LINE_LENGTH]; + + VarExpansionExW(wzTempBuffer, pwzTemplate, MAX_LINE_LENGTH); + + // bad mojo, but its a limitation of this old API + StringCchCopyW(pwzExpandedString, + wcslen(wzTempBuffer) + 1, wzTempBuffer); + } +} + + +// +// VarExpansionA +// +void VarExpansionA(LPSTR pszExpandedString, LPCSTR pszTemplate) +{ + if (pszExpandedString != nullptr && pszTemplate != nullptr) { char szTempBuffer[MAX_LINE_LENGTH]; - VarExpansionEx(szTempBuffer, pszTemplate, MAX_LINE_LENGTH); + VarExpansionExA(szTempBuffer, pszTemplate, MAX_LINE_LENGTH); // bad mojo, but its a limitation of this old API - StringCchCopy(pszExpandedString, + StringCchCopyA(pszExpandedString, strlen(szTempBuffer) + 1, szTempBuffer); } } // -// VarExpansionEx +// VarExpansionExW +// +void VarExpansionExW(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate, size_t cchExpandedString) +{ + if (pwzExpandedString != nullptr && + cchExpandedString > 0 && + pwzTemplate != nullptr) + { + if (g_LSAPIManager.IsInitialized()) + { + g_LSAPIManager.GetSettingsManager()->VarExpansionEx( + pwzExpandedString, pwzTemplate, cchExpandedString); + } + else + { + StringCchCopyW(pwzExpandedString, cchExpandedString, pwzTemplate); + } + } +} + + +// +// VarExpansionExA // -void VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpandedString) +void VarExpansionExA(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpandedString) { - if (pszExpandedString != NULL && + if (pszExpandedString != nullptr && cchExpandedString > 0 && - pszTemplate != NULL) + pszTemplate != nullptr) { if (g_LSAPIManager.IsInitialized()) { + std::unique_ptr temp(new wchar_t[cchExpandedString]); g_LSAPIManager.GetSettingsManager()->VarExpansionEx( - pszExpandedString, pszTemplate, cchExpandedString); + temp.get(), MBSTOWCS(pszTemplate), cchExpandedString); + WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchExpandedString, + pszExpandedString, (int)cchExpandedString, "?", nullptr); } else { - StringCchCopy(pszExpandedString, cchExpandedString, pszTemplate); + StringCchCopyA(pszExpandedString, cchExpandedString, pszTemplate); } } } // -// ENUMBANG_DATA +// ENUM_DATA // Helper struct for EnumBangsThunk // -struct ENUMBANG_DATA +typedef struct ENUM_DATA { - LSENUMBANGSPROC fnCallback; + FARPROC fnCallback; LPARAM lParam; -}; +} *LPENUM_DATA; // // EnumBangsThunk // An ELD_BANGS_V2 thunk that translates to an ELD_BANGS-style callback // -static BOOL CALLBACK EnumBangsThunk(HINSTANCE, LPCSTR pszBang, LPARAM lParam) +static BOOL CALLBACK EnumBangsThunk(HINSTANCE, LPCWSTR pwzBang, LPARAM lParam) { - ENUMBANG_DATA* pData = (ENUMBANG_DATA*)lParam; - return pData->fnCallback(pszBang, pData->lParam); + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMBANGSPROCW(pData->fnCallback)(pwzBang, pData->lParam); } // -// EnumLSData +// EnumLSDataW // // Return values: // E_INVALIDARG - Invalid value for uInfo @@ -671,7 +1109,7 @@ static BOOL CALLBACK EnumBangsThunk(HINSTANCE, LPCSTR pszBang, LPARAM lParam) // S_OK - Enumeration successful, callback always returned TRUE // S_FALSE - Enumeration successful, but cancelled by callback // -HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) +HRESULT EnumLSDataW(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) { HRESULT hr = E_INVALIDARG; @@ -685,11 +1123,11 @@ HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) // Call EnumLSData recursively and let a small thunk handle // the translation from ELD_BANGS_V2 to ELD_BANGS // - ENUMBANG_DATA data = { 0 }; - data.fnCallback = (LSENUMBANGSPROC)pfnCallback; + ENUM_DATA data = { 0 }; + data.fnCallback = pfnCallback; data.lParam = lParam; - hr = EnumLSData(ELD_BANGS_V2, + hr = EnumLSDataW(ELD_BANGS_V2, (FARPROC)EnumBangsThunk, (LPARAM)&data); } break; @@ -697,7 +1135,7 @@ HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) case ELD_BANGS_V2: { hr = g_LSAPIManager.GetBangManager()-> - EnumBangs((LSENUMBANGSV2PROC)pfnCallback, lParam); + EnumBangs((LSENUMBANGSV2PROCW)pfnCallback, lParam); } break; @@ -736,3 +1174,105 @@ HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) return hr; } + + +// +// ANSII wrappers +// +static BOOL CALLBACK EnumLSDataBangsANSIIWrapper(LPCWSTR pwzBang, LPARAM lParam) +{ + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMBANGSPROCA(pData->fnCallback)(std::unique_ptr(MBSFromWCS(pwzBang)).get(), pData->lParam); +} +static BOOL CALLBACK EnumLSDataBangsV2ANSIIWrapper(HINSTANCE hInst, LPCWSTR pwzBang, LPARAM lParam) +{ + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMBANGSV2PROCA(pData->fnCallback)(hInst, std::unique_ptr(MBSFromWCS(pwzBang)).get(), pData->lParam); +} +static BOOL CALLBACK EnumLSDataRevIDsANSIIWrapper(LPCWSTR pwzRevID, LPARAM lParam) +{ + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMREVIDSPROCA(pData->fnCallback)(std::unique_ptr(MBSFromWCS(pwzRevID)).get(), pData->lParam); + +} +static BOOL CALLBACK EnumLSDataModulesANSIIWrapper(LPCWSTR pwzModule, DWORD fdwFlags, LPARAM lParam) +{ + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMMODULESPROCA(pData->fnCallback)(std::unique_ptr(MBSFromWCS(pwzModule)).get(), fdwFlags, pData->lParam); + +} +static BOOL CALLBACK EnumLSDataPerformanceANSIIWrapper(LPCWSTR pwzModule, DWORD dwLoadTime, LPARAM lParam) +{ + LPENUM_DATA pData = (LPENUM_DATA)lParam; + return LSENUMPERFORMANCEPROCA(pData->fnCallback)(std::unique_ptr(MBSFromWCS(pwzModule)).get(), dwLoadTime, pData->lParam); +} + + +// +// EnumLSDataA +// +// Return values: +// E_INVALIDARG - Invalid value for uInfo +// E_POINTER - Invalid callback +// E_FAIL - Unspecified error +// E_UNEXPECTED - Callback crashed or other catastrophic failure +// S_OK - Enumeration successful, callback always returned TRUE +// S_FALSE - Enumeration successful, but cancelled by callback +// +HRESULT EnumLSDataA(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) +{ + HRESULT hr = E_INVALIDARG; + + if (nullptr != pfnCallback) + { + ENUM_DATA data; + data.lParam = lParam; + data.fnCallback = pfnCallback; + + pfnCallback = nullptr; + + switch (uInfo) + { + case ELD_BANGS: + { + pfnCallback = FARPROC(EnumLSDataBangsANSIIWrapper); + } + break; + + case ELD_BANGS_V2: + { + pfnCallback = FARPROC(EnumLSDataBangsV2ANSIIWrapper); + } + break; + + case ELD_REVIDS: + { + pfnCallback = FARPROC(EnumLSDataRevIDsANSIIWrapper); + } + break; + + case ELD_MODULES: + { + pfnCallback = FARPROC(EnumLSDataModulesANSIIWrapper); + } + break; + + case ELD_PERFORMANCE: + { + pfnCallback = FARPROC(EnumLSDataPerformanceANSIIWrapper); + } + break; + } + + if (nullptr != pfnCallback) + { + hr = EnumLSDataW(uInfo, pfnCallback, (LPARAM)&data); + } + } + else + { + hr = E_POINTER; + } + + return hr; +} \ No newline at end of file diff --git a/lsapi/lsapi.h b/lsapi/lsapi.h index 6785f92..b36856b 100644 --- a/lsapi/lsapi.h +++ b/lsapi/lsapi.h @@ -48,59 +48,99 @@ extern "C" { #endif // __cplusplus - LSAPI LPVOID LCOpen(LPCSTR szPath); + LSAPI LPVOID LCOpenA(LPCSTR szPath); + LSAPI LPVOID LCOpenW(LPCWSTR wzPath); LSAPI BOOL LCClose(LPVOID pFile); - LSAPI BOOL LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cchValue); - LSAPI BOOL LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue); - LSAPI BOOL LCReadNextLine(LPVOID pFile, LPSTR pszValue, size_t cchValue); - LSAPI int LCTokenize (LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters); - - LSAPI int GetRCInt(LPCSTR lpKeyName, int nDefault); - LSAPI BOOL GetRCString(LPCSTR lpKeyName, LPSTR value, LPCSTR defStr, int maxLen); - LSAPI BOOL GetRCBool(LPCSTR lpKeyName, BOOL ifFound); - LSAPI BOOL GetRCBoolDef(LPCSTR lpKeyName, BOOL bDefault); - LSAPI BOOL GetRCLine(LPCSTR, LPSTR, UINT, LPCSTR); - LSAPI COLORREF GetRCColor(LPCSTR lpKeyName, COLORREF colDef); - - LSAPI BOOL LSGetVariable(LPCSTR pszKeyName, LPSTR pszValue); - LSAPI BOOL LSGetVariableEx(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength); - LSAPI void LSSetVariable(LPCSTR pszKeyName, LPCSTR pszValue); - - LSAPI BOOL AddBangCommand(LPCSTR pszCommand, BangCommand pfnBangCommand); - LSAPI BOOL AddBangCommandEx(LPCSTR pszCommand, BangCommandEx pfnBangCommand); - LSAPI BOOL RemoveBangCommand(LPCSTR pszCommand); - LSAPI BOOL ParseBangCommand (HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs); + LSAPI BOOL LCReadNextCommandA(LPVOID pFile, LPSTR pszValue, size_t cchValue); + LSAPI BOOL LCReadNextCommandW(LPVOID pFile, LPWSTR pwzValue, size_t cchValue); + LSAPI BOOL LCReadNextConfigA(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue); + LSAPI BOOL LCReadNextConfigW(LPVOID pFile, LPCWSTR pwzConfig, LPWSTR pwzValue, size_t cchValue); + LSAPI BOOL LCReadNextLineA(LPVOID pFile, LPSTR pszValue, size_t cchValue); + LSAPI BOOL LCReadNextLineW(LPVOID pFile, LPWSTR pwzValue, size_t cchValue); + LSAPI int LCTokenizeA(LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters); + LSAPI int LCTokenizeW(LPCWSTR wzString, LPWSTR * lpwzBuffers, DWORD dwNumBuffers, LPWSTR wzExtraParameters); + + LSAPI int GetRCIntA(LPCSTR lpKeyName, int nDefault); + LSAPI int GetRCIntW(LPCWSTR lpKeyName, int nDefault); + LSAPI __int64 GetRCInt64A(LPCSTR lpKeyName, __int64 nDefault); + LSAPI __int64 GetRCInt64W(LPCWSTR lpKeyName, __int64 nDefault); + LSAPI float GetRCFloatA(LPCSTR lpKeyName, float fDefault); + LSAPI float GetRCFloatW(LPCWSTR lpKeyName, float fDefault); + LSAPI double GetRCDoubleA(LPCSTR lpKeyName, double dDefault); + LSAPI double GetRCDoubleW(LPCWSTR lpKeyName, double dDefault); + LSAPI BOOL GetRCStringA(LPCSTR lpKeyName, LPSTR value, LPCSTR defStr, int maxLen); + LSAPI BOOL GetRCStringW(LPCWSTR lpKeyName, LPWSTR value, LPCWSTR defStr, int maxLen); + LSAPI BOOL GetRCBoolA(LPCSTR lpKeyName, BOOL ifFound); + LSAPI BOOL GetRCBoolW(LPCWSTR lpKeyName, BOOL ifFound); + LSAPI BOOL GetRCBoolDefA(LPCSTR lpKeyName, BOOL bDefault); + LSAPI BOOL GetRCBoolDefW(LPCWSTR lpKeyName, BOOL bDefault); + LSAPI BOOL GetRCLineA(LPCSTR lpKeyName, LPSTR value, UINT maxLen, LPCSTR defStr); + LSAPI BOOL GetRCLineW(LPCWSTR lpKeyName, LPWSTR value, UINT maxLen, LPCWSTR defStr); + LSAPI COLORREF GetRCColorA(LPCSTR lpKeyName, COLORREF colDef); + LSAPI COLORREF GetRCColorW(LPCWSTR lpKeyName, COLORREF colDef); + + LSAPI BOOL LSGetVariableA(LPCSTR pszKeyName, LPSTR pszValue); + LSAPI BOOL LSGetVariableW(LPCWSTR pwzKeyName, LPWSTR pwzValue); + LSAPI BOOL LSGetVariableExA(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength); + LSAPI BOOL LSGetVariableExW(LPCWSTR pwzKeyName, LPWSTR pwzValue, DWORD dwLength); + LSAPI void LSSetVariableA(LPCSTR pszKeyName, LPCSTR pszValue); + LSAPI void LSSetVariableW(LPCWSTR pwzKeyName, LPCWSTR pwzValue); + + LSAPI BOOL AddBangCommandA(LPCSTR pszCommand, BangCommandA pfnBangCommand); + LSAPI BOOL AddBangCommandW(LPCWSTR pwzCommand, BangCommandW pfnBangCommand); + LSAPI BOOL AddBangCommandExA(LPCSTR pszCommand, BangCommandExA pfnBangCommand); + LSAPI BOOL AddBangCommandExW(LPCWSTR pwzCommand, BangCommandExW pfnBangCommand); + LSAPI BOOL RemoveBangCommandA(LPCSTR pszCommand); + LSAPI BOOL RemoveBangCommandW(LPCWSTR pwzCommand); + LSAPI BOOL ParseBangCommandA(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs); + LSAPI BOOL ParseBangCommandW(HWND hCaller, LPCWSTR pwzCommand, LPCWSTR pwzArgs); LSAPI HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance, int xoffset, int yoffset); LSAPI HBITMAP BitmapFromIcon (HICON hIcon); - LSAPI HBITMAP LoadLSImage(LPCSTR szFile, LPCSTR szImage); - LSAPI HICON LoadLSIcon (LPCSTR szImage, LPCSTR szFile); + LSAPI HBITMAP LoadLSImageA(LPCSTR pszFile, LPCSTR pszImage); + LSAPI HBITMAP LoadLSImageW(LPCWSTR pwzFile, LPCWSTR pwzImage); + LSAPI HICON LoadLSIconA(LPCSTR pszImage, LPCSTR pszFile); + LSAPI HICON LoadLSIconW(LPCWSTR pwzImage, LPCWSTR pwzFile); LSAPI void GetLSBitmapSize(HBITMAP hBitmap, LPINT nWidth, LPINT nHeight); - LSAPI void TransparentBltLS (HDC dc, int nXDest, int nYDest, int nWidth, int nHeight, HDC tempDC, int nXSrc, int nYSrc, COLORREF colorTransparent); + LSAPI void TransparentBltLS(HDC dc, int nXDest, int nYDest, int nWidth, int nHeight, HDC tempDC, int nXSrc, int nYSrc, COLORREF colorTransparent); - LSAPI int CommandTokenize (LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters); - LSAPI void CommandParse(LPCSTR pszCommand, LPSTR pszOutCommand, LPSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs); + LSAPI int CommandTokenizeA(LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters); + LSAPI int CommandTokenizeW(LPCWSTR szString, LPWSTR * lpszBuffers, DWORD dwNumBuffers, LPWSTR szExtraParameters); + LSAPI void CommandParseA(LPCSTR pszCommand, LPSTR pszOutCommand, LPSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs); + LSAPI void CommandParseW(LPCWSTR pszCommand, LPWSTR pszOutCommand, LPWSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs); - LSAPI HINSTANCE LSExecute(HWND Owner, LPCSTR szCommand, int nShowCmd); - LSAPI HINSTANCE LSExecuteEx(HWND Owner, LPCSTR szOperation, LPCSTR szCommand, LPCSTR szArgs, LPCSTR szDirectory, int nShowCmd); + LSAPI HINSTANCE LSExecuteA(HWND Owner, LPCSTR szCommand, int nShowCmd); + LSAPI HINSTANCE LSExecuteW(HWND Owner, LPCWSTR wzCommand, int nShowCmd); + LSAPI HINSTANCE LSExecuteExA(HWND Owner, LPCSTR szOperation, LPCSTR szCommand, LPCSTR szArgs, LPCSTR szDirectory, int nShowCmd); + LSAPI HINSTANCE LSExecuteExW(HWND Owner, LPCWSTR wzOperation, LPCWSTR wzCommand, LPCWSTR wzArgs, LPCWSTR wzDirectory, int nShowCmd); LSAPI HWND GetLitestepWnd(void); - LSAPI BOOL WINAPI LSGetLitestepPath(LPSTR pszPath, size_t cchPath); - LSAPI BOOL WINAPI LSGetImagePath(LPSTR pszPath, size_t cchPath); - - LSAPI void VarExpansion(LPSTR pszExpandedString, LPCSTR pszTemplate); - LSAPI void VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpandedString); - - LSAPI BOOL GetToken(LPCSTR szString, LPSTR szToken, LPCSTR * szNextToken, BOOL useBrackets); + LSAPI BOOL WINAPI LSGetLitestepPathA(LPSTR pszPath, size_t cchPath); + LSAPI BOOL WINAPI LSGetLitestepPathW(LPWSTR pwzPath, size_t cchPath); + LSAPI BOOL WINAPI LSGetImagePathA(LPSTR pszPath, size_t cchPath); + LSAPI BOOL WINAPI LSGetImagePathW(LPWSTR pwzPath, size_t cchPath); + + LSAPI void VarExpansionA(LPSTR pszExpandedString, LPCSTR pszTemplate); + LSAPI void VarExpansionW(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate); + LSAPI void VarExpansionExA(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpandedString); + LSAPI void VarExpansionExW(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate, size_t cchExpandedString); + + LSAPI BOOL GetTokenA(LPCSTR pszString, LPSTR pszToken, LPCSTR * pszNextToken, BOOL useBrackets); + LSAPI BOOL GetTokenW(LPCWSTR pwzString, LPWSTR pwzToken, LPCWSTR * pwzNextToken, BOOL useBrackets); LSAPI void Frame3D(HDC dc, RECT rect, COLORREF TopColor, COLORREF BottomColor, int Width); LSAPI void SetDesktopArea(int left, int top, int right, int bottom); - LSAPI BOOL match(LPCSTR pattern, LPCSTR text); - LSAPI int matche(LPCSTR pattern, LPCSTR text); - LSAPI BOOL is_valid_pattern(LPCSTR p, LPINT error_type); + LSAPI BOOL matchA(LPCSTR pattern, LPCSTR text); + LSAPI BOOL matchW(LPCWSTR pattern, LPCWSTR text); + LSAPI int matcheA(LPCSTR pattern, LPCSTR text); + LSAPI int matcheW(LPCWSTR pattern, LPCWSTR text); + LSAPI BOOL is_valid_patternA(LPCSTR p, LPINT error_type); + LSAPI BOOL is_valid_patternW(LPCWSTR p, LPINT error_type); - LSAPI void GetResStr(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText); - LSAPI void GetResStrEx(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText, ...); + LSAPI void GetResStrA(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText); + LSAPI void GetResStrW(HINSTANCE hInstance, UINT uIDText, LPWSTR pwzText, size_t cchText, LPCWSTR pwzDefText); + LSAPI void GetResStrExA(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText, ...); + LSAPI void GetResStrExW(HINSTANCE hInstance, UINT uIDText, LPWSTR pwzText, size_t cchText, LPCWSTR pwzDefText, ...); LSAPI int LSGetSystemMetrics(int); LSAPI HMONITOR LSMonitorFromWindow(HWND, DWORD); @@ -115,14 +155,15 @@ extern "C" LSAPI int GetRCCoordinate(LPCSTR pszKeyName, int nDefault, int nMaxVal); LSAPI int ParseCoordinate(LPCSTR szString, int nDefault, int nMaxVal); - LSAPI HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam); + LSAPI HRESULT EnumLSDataA(UINT uInfo, FARPROC pfnCallback, LPARAM lParam); + LSAPI HRESULT EnumLSDataW(UINT uInfo, FARPROC pfnCallback, LPARAM lParam); #if defined(LSAPI_PRIVATE) - LSAPI BOOL LSAPIInitialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath); + LSAPI BOOL LSAPIInitialize(LPCWSTR pwzLitestepPath, LPCWSTR pwzRcPath); LSAPI void LSAPIReloadBangs(void); LSAPI void LSAPIReloadSettings(void); LSAPI void LSAPISetLitestepWindow(HWND hLitestepWnd); - LSAPI BOOL InternalExecuteBangCommand(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs); + LSAPI BOOL InternalExecuteBangCommand(HWND hCaller, LPCWSTR pszCommand, LPCWSTR pwzArgs); #endif /* LSAPI_PRIVATE */ #if defined(__cplusplus) diff --git a/lsapi/lsapi.rc b/lsapi/lsapi.rc index ce02146..8fd41f7 100644 --- a/lsapi/lsapi.rc +++ b/lsapi/lsapi.rc @@ -7,7 +7,7 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "windows.h" +#include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -52,7 +52,7 @@ BEGIN VALUE "OriginalFilename", "lsapi.dll" VALUE "ProductName", "LiteStep" VALUE "ProductVersion", "0.25.0 Alpha" - VALUE "SpecialBuild", "alur's windows 8/x64 branch" + VALUE "SpecialBuild", "CVS HEAD Test Release" END END BLOCK "VarFileInfo" @@ -75,7 +75,7 @@ END 2 TEXTINCLUDE BEGIN - "#include ""windows.h""\r\n" + "#include ""afxres.h""\r\n" "\0" END diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index e53f34d..d47e104 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -23,6 +23,7 @@ #include "lsapi.h" #include "../utility/core.hpp" #include +#include LSAPIInit g_LSAPIManager; @@ -35,10 +36,11 @@ LSAPIInit::LSAPIInit() { m_dwMainThreadID = GetCurrentThreadId(); - m_szLitestepPath[0] = '\0'; - m_szRcPath[0] = '\0'; + m_wzLitestepPath[0] = L'\0'; + m_wzRcPath[0] = L'\0'; } + LSAPIInit::~LSAPIInit() { m_bIsInitialized = false; @@ -46,7 +48,8 @@ LSAPIInit::~LSAPIInit() delete m_smSettingsManager; } -void LSAPIInit::Initialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) + +void LSAPIInit::Initialize(LPCWSTR pwzLitestepPath, LPCWSTR pwzRcPath) { try { @@ -63,12 +66,12 @@ void LSAPIInit::Initialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) } // Copy over the strings - if (FAILED(StringCchCopy(m_szLitestepPath, MAX_PATH, pszLitestepPath))) + if (FAILED(StringCchCopyW(m_wzLitestepPath, MAX_PATH, pwzLitestepPath))) { throw LSAPIException(LSAPI_ERROR_GENERAL); } - if (FAILED(StringCchCopy(m_szRcPath, MAX_PATH, pszRcPath))) + if (FAILED(StringCchCopyW(m_wzRcPath, MAX_PATH, pwzRcPath))) { throw LSAPIException(LSAPI_ERROR_GENERAL); } @@ -97,7 +100,7 @@ void LSAPIInit::Initialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) setLitestepVars(); // Load the default RC config file - m_smSettingsManager->ParseFile(m_szRcPath); + m_smSettingsManager->ParseFile(m_wzRcPath); // Add our internal bang commands to the Bang Manager. SetupBangs(); @@ -109,15 +112,16 @@ void LSAPIInit::Initialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath) m_bIsInitialized = false; delete m_smSettingsManager; - m_smSettingsManager = NULL; + m_smSettingsManager = nullptr; delete m_bmBangManager; - m_bmBangManager = NULL; + m_bmBangManager = nullptr; } throw; //rethrow } } + void LSAPIInit::ReloadBangs() { if (!IsInitialized()) @@ -129,6 +133,7 @@ void LSAPIInit::ReloadBangs() SetupBangs(); } + void LSAPIInit::ReloadSettings() { if (!IsInitialized()) @@ -154,73 +159,74 @@ void LSAPIInit::ReloadSettings() setLitestepVars(); // Reload the default RC config file - m_smSettingsManager->ParseFile(m_szRcPath); + m_smSettingsManager->ParseFile(m_wzRcPath); } + void LSAPIInit::setLitestepVars() { - char szTemp[MAX_PATH]; + wchar_t wzTemp[MAX_PATH]; DWORD dwLength = MAX_PATH; // just using a shorter name, no real reason to re-assign. SettingsManager *pSM = m_smSettingsManager; // Set the variable "litestepdir" since it was never set - if (SUCCEEDED(StringCchCopy(szTemp, MAX_PATH, m_szLitestepPath))) + if (SUCCEEDED(StringCchCopyW(wzTemp, MAX_PATH, m_wzLitestepPath))) { - PathAddBackslashEx(szTemp, MAX_PATH); - PathQuoteSpaces(szTemp); - pSM->SetVariable("litestepdir", szTemp); + PathAddBackslashEx(wzTemp, MAX_PATH); + PathQuoteSpacesW(wzTemp); + pSM->SetVariable(L"litestepdir", wzTemp); } - if (GetWindowsDirectory(szTemp, MAX_PATH)) + if (GetWindowsDirectoryW(wzTemp, MAX_PATH)) { - PathAddBackslashEx(szTemp, MAX_PATH); - pSM->SetVariable("windir", szTemp); + PathAddBackslashEx(wzTemp, MAX_PATH); + pSM->SetVariable(L"windir", wzTemp); } - if (GetUserName(szTemp, &dwLength)) + if (GetUserNameW(wzTemp, &dwLength)) { - PathQuoteSpaces(szTemp); - pSM->SetVariable("username", szTemp); + PathQuoteSpacesW(wzTemp); + pSM->SetVariable(L"username", wzTemp); } - pSM->SetVariable("bitbucket", "::{645FF040-5081-101B-9F08-00AA002F954E}"); - pSM->SetVariable("documents", "::{450D8FBA-AD25-11D0-98A8-0800361B1103}"); - pSM->SetVariable("drives", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"); - pSM->SetVariable("network", "::{208D2C60-3AEA-1069-A2D7-08002B30309D}"); - pSM->SetVariable("controls", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"); - pSM->SetVariable("dialup", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{992CFFA0-F557-101A-88EC-00DD010CCC48}"); - pSM->SetVariable("networkanddialup", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}"); - pSM->SetVariable("printers", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"); - pSM->SetVariable("scheduled", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}"); - pSM->SetVariable("admintools", "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}"); + pSM->SetVariable(L"bitbucket", L"::{645FF040-5081-101B-9F08-00AA002F954E}"); + pSM->SetVariable(L"documents", L"::{450D8FBA-AD25-11D0-98A8-0800361B1103}"); + pSM->SetVariable(L"drives", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"); + pSM->SetVariable(L"network", L"::{208D2C60-3AEA-1069-A2D7-08002B30309D}"); + pSM->SetVariable(L"controls", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"); + pSM->SetVariable(L"dialup", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{992CFFA0-F557-101A-88EC-00DD010CCC48}"); + pSM->SetVariable(L"networkanddialup", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}"); + pSM->SetVariable(L"printers", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"); + pSM->SetVariable(L"scheduled", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}"); + pSM->SetVariable(L"admintools", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11d2-A40B-0C5020524153}"); - setShellFolderVariable("quicklaunch", LS_CSIDL_QUICKLAUNCH); - setShellFolderVariable("commondesktopdir", CSIDL_COMMON_DESKTOPDIRECTORY); - setShellFolderVariable("commonfavorites", CSIDL_COMMON_FAVORITES); - setShellFolderVariable("commonprograms", CSIDL_COMMON_PROGRAMS); - setShellFolderVariable("commonstartmenu", CSIDL_COMMON_STARTMENU); - setShellFolderVariable("commonstartup", CSIDL_COMMON_STARTUP); - setShellFolderVariable("cookies", CSIDL_COOKIES); - setShellFolderVariable("desktop", CSIDL_DESKTOP); - setShellFolderVariable("desktopdir", CSIDL_DESKTOPDIRECTORY); - setShellFolderVariable("favorites", CSIDL_FAVORITES); - setShellFolderVariable("fonts", CSIDL_FONTS); - setShellFolderVariable("history", CSIDL_HISTORY); - setShellFolderVariable("internet", CSIDL_INTERNET); - setShellFolderVariable("internetcache", CSIDL_INTERNET_CACHE); - setShellFolderVariable("nethood", CSIDL_NETHOOD); - setShellFolderVariable("documentsdir", CSIDL_PERSONAL); - setShellFolderVariable("printhood", CSIDL_PRINTHOOD); - setShellFolderVariable("programs", CSIDL_PROGRAMS); - setShellFolderVariable("recent", CSIDL_RECENT); - setShellFolderVariable("sendto", CSIDL_SENDTO); - setShellFolderVariable("startmenu", CSIDL_STARTMENU); - setShellFolderVariable("startup", CSIDL_STARTUP); - setShellFolderVariable("templates", CSIDL_TEMPLATES); - setShellFolderVariable("commonadmintoolsdir", CSIDL_COMMON_ADMINTOOLS); - setShellFolderVariable("admintoolsdir", CSIDL_ADMINTOOLS); + setShellFolderVariable(L"quicklaunch", LS_CSIDL_QUICKLAUNCH); + setShellFolderVariable(L"commondesktopdir", CSIDL_COMMON_DESKTOPDIRECTORY); + setShellFolderVariable(L"commonfavorites", CSIDL_COMMON_FAVORITES); + setShellFolderVariable(L"commonprograms", CSIDL_COMMON_PROGRAMS); + setShellFolderVariable(L"commonstartmenu", CSIDL_COMMON_STARTMENU); + setShellFolderVariable(L"commonstartup", CSIDL_COMMON_STARTUP); + setShellFolderVariable(L"cookies", CSIDL_COOKIES); + setShellFolderVariable(L"desktop", CSIDL_DESKTOP); + setShellFolderVariable(L"desktopdir", CSIDL_DESKTOPDIRECTORY); + setShellFolderVariable(L"favorites", CSIDL_FAVORITES); + setShellFolderVariable(L"fonts", CSIDL_FONTS); + setShellFolderVariable(L"history", CSIDL_HISTORY); + setShellFolderVariable(L"internet", CSIDL_INTERNET); + setShellFolderVariable(L"internetcache", CSIDL_INTERNET_CACHE); + setShellFolderVariable(L"nethood", CSIDL_NETHOOD); + setShellFolderVariable(L"documentsdir", CSIDL_PERSONAL); + setShellFolderVariable(L"printhood", CSIDL_PRINTHOOD); + setShellFolderVariable(L"programs", CSIDL_PROGRAMS); + setShellFolderVariable(L"recent", CSIDL_RECENT); + setShellFolderVariable(L"sendto", CSIDL_SENDTO); + setShellFolderVariable(L"startmenu", CSIDL_STARTMENU); + setShellFolderVariable(L"startup", CSIDL_STARTUP); + setShellFolderVariable(L"templates", CSIDL_TEMPLATES); + setShellFolderVariable(L"commonadmintoolsdir", CSIDL_COMMON_ADMINTOOLS); + setShellFolderVariable(L"admintoolsdir", CSIDL_ADMINTOOLS); // // Set version identification variables @@ -228,25 +234,28 @@ void LSAPIInit::setLitestepVars() struct VersionToVariable { UINT uVersion; - LPCTSTR pszVariable; + LPCWSTR pszVariable; } versions[] = \ { - { WINVER_WIN95, _T("Win95") }, - { WINVER_WIN98, _T("Win98") }, - { WINVER_WINME, _T("WinME") }, + { WINVER_WIN95, L"Win95" }, + { WINVER_WIN98, L"Win98" }, + { WINVER_WINME, L"WinME" }, - { WINVER_WINNT4, _T("WinNT4") }, - { WINVER_WIN2000, _T("Win2000") }, - { WINVER_WINXP, _T("WinXP") }, - { WINVER_VISTA, _T("WinVista") }, - { WINVER_WIN7, _T("Win7") }, - { WINVER_WIN8, _T("Win8") }, + { WINVER_WINNT4, L"WinNT4" }, + { WINVER_WIN2000, L"Win2000" }, + { WINVER_WINXP, L"WinXP" }, + { WINVER_VISTA, L"WinVista" }, + { WINVER_WIN7, L"Win7" }, + { WINVER_WIN8, L"Win8" }, + { WINVER_WIN81, L"Win81" }, - { WINVER_WIN2003, _T("Win2003") }, - { WINVER_WHS, _T("Win2003") }, // WHS is Win2003 in disguise - { WINVER_WIN2008, _T("Win2008") }, - { WINVER_WIN2012, _T("Win2012") } + { WINVER_WIN2003, L"Win2003" }, + { WINVER_WHS, L"Win2003" }, // WHS is Win2003 in disguise + { WINVER_WIN2008, L"Win2008" }, + { WINVER_WIN2008R2, L"Win2008R2" }, + { WINVER_WIN2012, L"Win2012" }, + { WINVER_WIN2012R2, L"Win2012R2" } }; UINT uVersion = GetWindowsVersion(); @@ -255,76 +264,78 @@ void LSAPIInit::setLitestepVars() { if (versions[idx].uVersion == uVersion) { - pSM->SetVariable(versions[idx].pszVariable, "true"); + pSM->SetVariable(versions[idx].pszVariable, L"true"); } else { - pSM->SetVariable(versions[idx].pszVariable, "false"); + pSM->SetVariable(versions[idx].pszVariable, L"false"); } } if (IsOS(OS_NT)) { - pSM->SetVariable("Win9x", "false"); - pSM->SetVariable("WinNT", "true"); + pSM->SetVariable(L"Win9x", L"false"); + pSM->SetVariable(L"WinNT", L"true"); } else { - pSM->SetVariable("Win9x", "true"); - pSM->SetVariable("WinNT", "false"); + pSM->SetVariable(L"Win9x", L"true"); + pSM->SetVariable(L"WinNT", L"false"); } #if defined(_WIN64) - pSM->SetVariable("Win64", "true"); + pSM->SetVariable(L"Win64", L"true"); #else if (IsOS(OS_WOW6432)) { - pSM->SetVariable("Win64", "true"); + pSM->SetVariable(L"Win64", L"true"); } else { - pSM->SetVariable("Win64", "false"); + pSM->SetVariable(L"Win64", L"false"); } #endif // screen resolution - StringCchPrintf(szTemp, MAX_PATH, "%d", GetSystemMetrics(SM_CXSCREEN)); - pSM->SetVariable("ResolutionX", szTemp); + StringCchPrintfW(wzTemp, MAX_PATH, L"%d", GetSystemMetrics(SM_CXSCREEN)); + pSM->SetVariable(L"ResolutionX", wzTemp); - StringCchPrintf(szTemp, MAX_PATH, "%d", GetSystemMetrics(SM_CYSCREEN)); - pSM->SetVariable("ResolutionY", szTemp); + StringCchPrintfW(wzTemp, MAX_PATH, L"%d", GetSystemMetrics(SM_CYSCREEN)); + pSM->SetVariable(L"ResolutionY", wzTemp); // build date/time from PE headers - getCompileTime(szTemp, MAX_PATH); - pSM->SetVariable("CompileDate", szTemp); + getCompileTime(wzTemp, MAX_PATH); + pSM->SetVariable(L"CompileDate", wzTemp); #if defined(LS_CUSTOM_INCLUDEFOLDER) - pSM->SetVariable("IncludeFolder", "1"); + pSM->SetVariable(L"IncludeFolder", L"1"); #endif // LS_CUSTOM_INCLUDEFOLDER } -bool LSAPIInit::setShellFolderVariable(LPCSTR pszVariable, int nFolder) + +bool LSAPIInit::setShellFolderVariable(LPCWSTR pwzVariable, int nFolder) { bool bSuccess = false; - char szPath[MAX_PATH] = { 0 }; + wchar_t wzPath[MAX_PATH] = { 0 }; - if (GetShellFolderPath(nFolder, szPath, MAX_PATH)) + if (GetShellFolderPath(nFolder, wzPath, MAX_PATH)) { - PathAddBackslashEx(szPath, MAX_PATH); - PathQuoteSpaces(szPath); + PathAddBackslashEx(wzPath, MAX_PATH); + PathQuoteSpacesW(wzPath); - m_smSettingsManager->SetVariable(pszVariable, szPath); + m_smSettingsManager->SetVariable(pwzVariable, wzPath); bSuccess = true; } return bSuccess; } + // Gets the compiletime/date from the PE header // #define MakePtr(cast, ptr, addValue) \ (cast)((DWORD_PTR)(ptr) + (DWORD_PTR)(addValue)) -void LSAPIInit::getCompileTime(LPSTR pszValue, size_t cchValue) +void LSAPIInit::getCompileTime(LPWSTR pwzValue, size_t cchValue) { IMAGE_DOS_HEADER* dosheader; IMAGE_NT_HEADERS* ntheader; @@ -349,16 +360,16 @@ void LSAPIInit::getCompileTime(LPSTR pszValue, size_t cchValue) lsapitime = (time_t)(ntheader->FileHeader.TimeDateStamp); compiletime = std::max(lsexetime, lsapitime); - tm* timeStruct = gmtime(&compiletime); + tm timeStruct; - if (timeStruct) + if (gmtime_s(&timeStruct, &compiletime) == 0) { - _tcsftime(pszValue, cchValue, - _T("\"Compiled on %b %d %Y at %H:%M:%S UTC\""), timeStruct); + wcsftime(pwzValue, cchValue, + L"\"Compiled on %b %d %Y at %H:%M:%S UTC\"", &timeStruct); } else { - StringCchPrintf(pszValue, cchValue, - "\"Compiled at an unknown time\""); + StringCchPrintfW(pwzValue, cchValue, + L"\"Compiled at an unknown time\""); } } diff --git a/lsapi/lsapiInit.h b/lsapi/lsapiInit.h index 02f0199..dd721e0 100644 --- a/lsapi/lsapiInit.h +++ b/lsapi/lsapiInit.h @@ -57,9 +57,9 @@ class LSAPIException class LSAPIInit { private: - bool setShellFolderVariable(LPCSTR pszVariable, int nFolder); + bool setShellFolderVariable(LPCWSTR pwzVariable, int nFolder); void setLitestepVars(); - void getCompileTime(LPSTR pszValue, size_t cchValue); + void getCompileTime(LPWSTR pwzValue, size_t cchValue); public: LSAPIInit(); @@ -95,7 +95,7 @@ class LSAPIInit return m_dwMainThreadID; } - void Initialize(LPCSTR pszLitestepPath, LPCSTR pszRcPath); + void Initialize(LPCWSTR pszLitestepPath, LPCWSTR pszRcPath); bool IsInitialized() const { @@ -117,8 +117,8 @@ class LSAPIInit SettingsManager* m_smSettingsManager; HWND m_hLitestepWnd; - char m_szLitestepPath[MAX_PATH]; - char m_szRcPath[MAX_PATH]; + wchar_t m_wzLitestepPath[MAX_PATH]; + wchar_t m_wzRcPath[MAX_PATH]; bool m_bIsInitialized; }; diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 7760c3d..ae05807 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -1,281 +1,283 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - lsapi - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} - lsapi - Win32Proj - $(VCTargetsPath11) - - - - DynamicLibrary - MultiByte - true - v110 - - - DynamicLibrary - MultiByte - true - v110 - - - DynamicLibrary - MultiByte - v110 - - - DynamicLibrary - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11_32\ - Debug_VC11_32\ - true - true - ../Release_VC11_32\ - Release_VC11_32\ - false - false - - - ../Debug_VC11_64\ - Debug_VC11_64\ - - - ../Release_VC11_64\ - Release_VC11_64\ - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - true - $(OutDir)lsapi.pdb - Windows - $(OutDir)lsapi.lib - MachineX86 - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - true - $(OutDir)lsapi.pdb - Windows - $(OutDir)lsapi.lib - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - StreamingSIMDExtensions2 - true - true - - - Level4 - false - - - Default - true - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - false - Windows - true - true - $(OutDir)lsapi.lib - MachineX86 - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - false - Windows - true - true - $(OutDir)lsapi.lib - - - - - - - - - - - - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2213036f-018c-416a-8a6a-7934c936cffc} - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + lsapi + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} + lsapi + Win32Proj + $(VCTargetsPath11) + + + + DynamicLibrary + Unicode + true + v110_xp + + + DynamicLibrary + Unicode + true + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11_32\ + Debug_VC11_32\ + true + true + ../Release_VC11_32\ + Release_VC11_32\ + false + false + + + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + MachineX86 + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + + + + + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions2 + true + true + + + Level4 + false + + + Default + true + true + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + true + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + \ No newline at end of file diff --git a/lsapi/lsapi_vc10.vcxproj b/lsapi/lsapi_vc12.vcxproj similarity index 85% rename from lsapi/lsapi_vc10.vcxproj rename to lsapi/lsapi_vc12.vcxproj index a9b2ffe..f614071 100644 --- a/lsapi/lsapi_vc10.vcxproj +++ b/lsapi/lsapi_vc12.vcxproj @@ -1,267 +1,283 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - lsapi - {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} - lsapi - Win32Proj - - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10_32\ - ../Debug_VC10_64\ - Debug_VC10_32\ - Debug_VC10_64\ - true - true - ../Release_VC10_32\ - ../Release_VC10_64\ - Release_VC10_32\ - Release_VC10_64\ - false - false - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - true - $(OutDir)lsapi.pdb - Windows - $(OutDir)lsapi.lib - MachineX86 - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - true - $(OutDir)lsapi.pdb - Windows - $(OutDir)lsapi.lib - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - false - Windows - true - true - $(OutDir)lsapi.lib - MachineX86 - - - - - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - - - advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) - $(OutDir)lsapi.dll - true - true - false - Windows - true - true - $(OutDir)lsapi.lib - - - - - - - - - - - - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - $(IntDir)%(Filename)1.obj - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2213036f-018c-416a-8a6a-7934c936cffc} - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + lsapi + {2FECA0A4-CB2F-44CA-97AB-DE78EBBDECFA} + lsapi + Win32Proj + $(VCTargetsPath11) + + + + DynamicLibrary + Unicode + true + v120_xp + + + DynamicLibrary + Unicode + true + v120_xp + + + DynamicLibrary + Unicode + v120_xp + + + DynamicLibrary + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC12_32\ + Debug_VC12_32\ + true + true + ../Release_VC12_32\ + Release_VC12_32\ + false + false + + + ../Debug_VC12_64\ + Debug_VC12_64\ + + + ../Release_VC12_64\ + Release_VC12_64\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + MachineX86 + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + true + $(OutDir)lsapi.pdb + Windows + $(OutDir)lsapi.lib + + + + + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions2 + true + true + + + Level4 + false + + + Default + true + true + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + MachineX86 + + + + + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;LSAPI_INTERNAL;LSAPI_PRIVATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + true + true + + + advapi32.lib;ole32.lib;shlwapi.lib;shell32.lib;gdi32.lib;user32.lib;msvcrt.lib;msvcprt.lib;%(AdditionalDependencies) + $(OutDir)lsapi.dll + true + true + false + Windows + true + true + $(OutDir)lsapi.lib + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2213036f-018c-416a-8a6a-7934c936cffc} + + + + + \ No newline at end of file diff --git a/lsapi/lsapi_vc71.vcproj b/lsapi/lsapi_vc71.vcproj deleted file mode 100644 index 9c029e0..0000000 --- a/lsapi/lsapi_vc71.vcproj +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lsapi/lsapi_vc8.vcproj b/lsapi/lsapi_vc8.vcproj deleted file mode 100644 index 5630ee7..0000000 --- a/lsapi/lsapi_vc8.vcproj +++ /dev/null @@ -1,400 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lsapi/lsapi_vc9.vcproj b/lsapi/lsapi_vc9.vcproj deleted file mode 100644 index 6b0a537..0000000 --- a/lsapi/lsapi_vc9.vcproj +++ /dev/null @@ -1,399 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lsapi/lsapidefines.h b/lsapi/lsapidefines.h index d953e47..233017b 100644 --- a/lsapi/lsapidefines.h +++ b/lsapi/lsapidefines.h @@ -33,6 +33,7 @@ */ #include "../utility/common.h" +#include //----------------------------------------------------------------------------- @@ -70,7 +71,7 @@ #define LM_RESTORESYSTRAY 9211 // Deprecated #define LM_CHECKFORAPPBAR 9212 // Deprecated #define LM_SENDSYSTRAY 9213 -#define LM_SYSTRAY 9214 +#define LM_SYSTRAYA 9214 #define LM_SYSTRAYREADY 9215 #define LM_SYSTRAYINFOEVENT 9216 @@ -90,9 +91,9 @@ #define LM_RECYCLE 9260 #define LM_REGISTERMESSAGE 9263 #define LM_UNREGISTERMESSAGE 9264 -#define LM_GETREVID 9265 -#define LM_UNLOADMODULE 9266 -#define LM_RELOADMODULE 9267 +#define LM_GETREVIDA 9265 +#define LM_UNLOADMODULEA 9266 +#define LM_RELOADMODULEA 9267 #define LM_REGISTERHOOKMESSAGE 9268 // Deprecated #define LM_UNREGISTERHOOKMESSAGE 9269 // Deprecated #define LM_SHADETOGGLE 9300 @@ -125,7 +126,7 @@ #define LM_WINDOWLIST 9401 // Deprecated #define LM_DATASTORE 9410 // Deprecated #define LM_MESSAGEMANAGER 9411 // Deprecated -#define LM_BANGCOMMAND 9420 +#define LM_BANGCOMMANDA 9420 #define LM_ENUMREVIDS 9430 #define LM_ENUMMODULES 9431 #define LM_ENUMPERFORMANCE 9432 @@ -149,6 +150,49 @@ #define LM_WINDOWREPLACING (LM_SHELLHOOK + HSHELL_WINDOWREPLACING) #define LM_MONITORCHANGED (LM_SHELLHOOK + HSHELL_MONITORCHANGED) +// FullscreenMonitor events +#define LM_FULLSCREENACTIVATED 32768 +#define LM_FULLSCREENDEACTIVATED 32769 + +// ITaskbarList* messages +#define LM_TASK_SETPROGRESSSTATE 33024 +#define LM_TASK_SETPROGRESSVALUE 33025 +#define LM_TASK_MARKASACTIVE 33026 +#define LM_TASK_REGISTERTAB 33027 +#define LM_TASK_UNREGISTERTAB 33028 +#define LM_TASK_SETACTIVETAB 33029 +#define LM_TASK_SETTABORDER 33030 +#define LM_TASK_SETTABPROPERTIES 33031 +#define LM_TASK_SETOVERLAYICON 33032 +#define LM_TASK_SETOVERLAYICONDESC 33033 +#define LM_TASK_SETTHUMBNAILTOOLTIP 33034 +#define LM_TASK_SETTHUMBNAILCLIP 33035 +#define LM_TASK_THUMBBARADDBUTTONS 33036 +#define LM_TASK_THUMBBARUPDATEBUTTONS 33037 +#define LM_TASK_THUMBBARSETIMAGELIST 33038 + +// +#define LM_UNLOADMODULEW 33281 +#define LM_RELOADMODULEW 33282 +#define LM_GETREVIDW 33283 +#define LM_BANGCOMMANDW 33284 +#define LM_SYSTRAYW 33285 + + +//----------------------------------------------------------------------------- +// ITaskbarList DEFINES +//----------------------------------------------------------------------------- + +// Min and max progress values sent by LM_TASKSETPROGRESSVALUE +#define TASKSETPROGRESSVALUE_MIN 0 +#define TASKSETPROGRESSVALUE_MAX 0xFFFE + +// Sent by LM_TASKADDBUTTONS and LM_TASKUPDATEBUTTONS +typedef struct THUMBBUTTONLIST { + UINT cButtons; + LPTHUMBBUTTON pButton; +} *LPTHUMBBUTTONLIST; + //----------------------------------------------------------------------------- // CONSTANT DEFINES @@ -180,16 +224,20 @@ //----------------------------------------------------------------------------- // MODULE ENTRY POINTS DEFINES //----------------------------------------------------------------------------- -typedef int (__cdecl* initModuleExProc)(HWND, HINSTANCE, LPCSTR); +typedef int (__cdecl* initModuleProc)(HWND, HINSTANCE, LPCWSTR); +typedef int (__cdecl* initModuleProcA)(HWND, HINSTANCE, LPCSTR); typedef void (__cdecl* quitModuleProc)(HINSTANCE); //----------------------------------------------------------------------------- // BANG COMMAND DEFINES //----------------------------------------------------------------------------- -typedef void (__cdecl *BangCommand)(HWND hSender, LPCSTR pszArgs); -typedef void (__cdecl *BangCommandEx) \ +typedef void (__cdecl *BangCommandA)(HWND hSender, LPCSTR pszArgs); +typedef void (__cdecl *BangCommandW)(HWND hSender, LPCWSTR pszArgs); +typedef void (__cdecl *BangCommandExA) \ (HWND hSender, LPCSTR pszCommand, LPCSTR pszArgs); +typedef void (__cdecl *BangCommandExW) \ + (HWND hSender, LPCWSTR pszCommand, LPCWSTR pszArgs); typedef struct _LMBANGCOMMANDA { @@ -246,6 +294,7 @@ typedef struct LSDESKTOPINFO #define LR_LOGOFF 1 #define LR_QUIT 2 #define LR_MSSHUTDOWN 3 +#define LR_EXPLORER 4 //----------------------------------------------------------------------------- @@ -277,10 +326,15 @@ typedef struct LSDESKTOPINFO #define LS_MODULE_THREADED 0x0001 // LS_MODULE_NOTPUMPED 0x0002 no longer used -typedef BOOL (CALLBACK* LSENUMBANGSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMBANGSV2PROC)(HINSTANCE, LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMREVIDSPROC)(LPCSTR, LPARAM); -typedef BOOL (CALLBACK* LSENUMMODULESPROC)(LPCSTR, DWORD, LPARAM); -typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROC)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSPROCA)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSPROCW)(LPCWSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSV2PROCA)(HINSTANCE, LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMBANGSV2PROCW)(HINSTANCE, LPCWSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMREVIDSPROCA)(LPCSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMREVIDSPROCW)(LPCWSTR, LPARAM); +typedef BOOL (CALLBACK* LSENUMMODULESPROCA)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMMODULESPROCW)(LPCWSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROCA)(LPCSTR, DWORD, LPARAM); +typedef BOOL (CALLBACK* LSENUMPERFORMANCEPROCW)(LPCWSTR, DWORD, LPARAM); #endif // LSAPIDEFINES_H diff --git a/lsapi/match.cpp b/lsapi/match.cpp index b7b1e1c..da48e6d 100644 --- a/lsapi/match.cpp +++ b/lsapi/match.cpp @@ -39,7 +39,8 @@ #include "lsapi.h" #include -static int matche_after_star (LPCSTR pattern, LPCSTR text); +static int matche_after_starA(LPCSTR pattern, LPCSTR text); +static int matche_after_starW(LPCWSTR pattern, LPCWSTR text); /*----------------------------------------------------------------------------- * @@ -58,7 +59,7 @@ static int matche_after_star (LPCSTR pattern, LPCSTR text); * -----------------------------------------------------------------------------*/ -BOOL is_valid_pattern(LPCSTR p, LPINT error_type) +BOOL is_valid_patternA(LPCSTR p, LPINT error_type) { // init error_type *error_type = PATTERN_VALID; @@ -158,6 +159,106 @@ BOOL is_valid_pattern(LPCSTR p, LPINT error_type) return TRUE; } +BOOL is_valid_patternW(LPCWSTR p, LPINT error_type) +{ + // init error_type + *error_type = PATTERN_VALID; + + // loop through pattern to EOS + while (*p) + { + // determine pattern type + switch (*p) + { + // check literal escape, it cannot be at end of pattern + case L'\\': + if (!*++p) + { + *error_type = PATTERN_ESC; + return FALSE; + } + ++p; + break; + + // the [..] construct must be well formed + case L'[': + ++p; + + // if the next character is ']' then bad pattern + if (*p == L']') + { + *error_type = PATTERN_EMPTY; + return FALSE; + } + + // if end of pattern here then bad pattern + if (!*p) + { + *error_type = PATTERN_CLOSE; + return FALSE; + } + + // loop to end of [..] construct + while (*p != L']') + { + // check for literal escape + if (*p++ == L'\\') + { + // if end of pattern here then bad pattern + if (!*p++) + { + *error_type = PATTERN_ESC; + return FALSE; + } + } + + // if end of pattern here then bad pattern + if (!*p) + { + *error_type = PATTERN_CLOSE; + return FALSE; + } + + // if this a range + if (*p == L'-') + { + // we must have an end of range + if (!*++p || *p == L']') + { + *error_type = PATTERN_RANGE; + return FALSE; + } + else + { + // check for literal escape + if (*p == L'\\') + { + ++p; + } + + // if end of pattern here then bad pattern + if (!*p++) + { + *error_type = PATTERN_ESC; + return FALSE; + } + } + } + } + break; + + // all other characters are valid pattern elements + case L'*': + case L'?': + default: + ++p; // "normal" character + break; + } + } + + return TRUE; +} + /*----------------------------------------------------------------------------- * @@ -192,7 +293,7 @@ BOOL is_valid_pattern(LPCSTR p, LPINT error_type) * -----------------------------------------------------------------------------*/ -int matche(LPCSTR p, LPCSTR t) +int matcheA(LPCSTR p, LPCSTR t) { char range_start, range_end; // start and end in range @@ -217,7 +318,7 @@ int matche(LPCSTR p, LPCSTR t) // multiple any character match case '*': - return matche_after_star(p, t); + return matche_after_starA(p, t); // [..] construct, single member/exclusion character match case '[': @@ -379,13 +480,199 @@ int matche(LPCSTR p, LPCSTR t) return MATCH_VALID; } +int matcheW(LPCWSTR p, LPCWSTR t) +{ + wchar_t range_start, range_end; // start and end in range + + BOOL invert; // is this [..] or [!..] + BOOL member_match; // have I matched the [..] construct? + BOOL loop; // should I terminate? + + for (; *p; ++p, ++t) + { + // if this is the end of the text then this is the end of the match + if (!*t) + { + return (*p == L'*' && !*++p) ? MATCH_VALID : MATCH_ABORT; + } + + // determine and react to pattern type + switch (*p) + { + // single any character match + case L'?': + break; + + // multiple any character match + case L'*': + return matche_after_starW(p, t); + + // [..] construct, single member/exclusion character match + case L'[': + // move to beginning of range + ++p; + + // check if this is a member match or exclusion match + invert = FALSE; + if (*p == L'!' || *p == L'^') + { + invert = TRUE; + ++p; + } + + // if closing bracket here or at range start then we have a + // malformed pattern + if (*p == L']') + { + return MATCH_PATTERN; + } + + member_match = FALSE; + loop = TRUE; + + while (loop) + { + // if end of construct then loop is done + if (*p == L']') + { + loop = FALSE; + continue; + } + + // matching a '!', '^', '-', '\' or a ']' + if (*p == L'\\') + { + range_start = range_end = *++p; + } + else + { + range_start = range_end = *p; + } + + // if end of pattern then bad pattern (Missing ']') + if (!*p) + { + return MATCH_PATTERN; + } + + // check for range bar + if (*++p == L'-') + { + // get the range end + range_end = *++p; + + // if end of pattern or construct then bad pattern + if (!range_end || range_end == L']') + { + return MATCH_PATTERN; + } + + // special character range end + if (range_end == L'\\') + { + range_end = *++p; + + // if end of text then we have a bad pattern + if (!range_end) + { + return MATCH_PATTERN; + } + } + + // move just beyond this range + ++p; + } + + // if the text character is in range then match found. + // Make sure the range letters have the proper relationship + // to one another before comparison + if (range_start < range_end) + { + if (*t >= range_start && *t <= range_end) + { + member_match = TRUE; + loop = FALSE; + } + } + else + { + if (*t >= range_end && *t <= range_start) + { + member_match = TRUE; + loop = FALSE; + } + } + } + + // if there was a match in an exclusion set then no match + // if there was no match in a member set then no match + if ((invert && member_match) || !(invert || member_match)) + { + return MATCH_RANGE; + } + + // if this is not an exclusion then skip the rest of the [...] + // construct that already matched. + if (member_match) + { + while (*p != L']') + { + // bad pattern (Missing ']') + if (!*p) + { + return MATCH_PATTERN; + } + + // skip exact match + if (*p++ == L'\\') + { + // if end of text then we have a bad pattern + if (!*p++) + { + return MATCH_PATTERN; + } + } + } + } + break; + + // next character is quoted and must match exactly + case L'\\': + // move pattern pointer to quoted char and fall through + ++p; + + // if end of text then we have a bad pattern + if (!*p) + { + return MATCH_PATTERN; + } + + // FALL THROUGH + + // must match this character exactly + default: + if (toupper(*p) != toupper(*t)) + { + return MATCH_LITERAL; + } + } + } + + // if end of text not reached then the pattern fails + if (*t) + { + return MATCH_END; + } + + return MATCH_VALID; +} /*----------------------------------------------------------------------------- * * recursively call matche() with final segment of PATTERN and of TEXT. * -----------------------------------------------------------------------------*/ -static int matche_after_star (LPCSTR p, LPCSTR t) +static int matche_after_starA(LPCSTR p, LPCSTR t) { int match = 0; char nextp; @@ -432,7 +719,70 @@ static int matche_after_star (LPCSTR p, LPCSTR t) // text pointer as we go here if (toupper(nextp) == toupper(*t) || *p == '[') { - match = matche(p, t); + match = matcheA(p, t); + } + + // if the end of text is reached then no match + if (!*t++) + { + match = MATCH_ABORT; + } + } while (match != MATCH_VALID && + match != MATCH_ABORT && + match != MATCH_PATTERN); + + // return result + return match; +} + +static int matche_after_starW(LPCWSTR p, LPCWSTR t) +{ + int match = 0; + wchar_t nextp; + + // pass over existing ? and * in pattern + while (*p == L'?' || *p == L'*') + { + // take one char for each ? + if (*p++ == L'?') + { + // if end of text then no match + if (!*t++) + { + return MATCH_ABORT; + } + } + } + + // if end of pattern we have matched regardless of text left + if (!*p) + { + return MATCH_VALID; + } + + // get the next character to match which must be a literal or '[' + nextp = *p; + if (nextp == L'\\') + { + nextp = p[1]; + + // if end of text then we have a bad pattern + if (!nextp) + { + return MATCH_PATTERN; + } + } + + // Continue until we run out of text or definite result seen + do + { + // a precondition for matching is that the next character + // in the pattern match the next character in the text or that + // the next pattern char is the beginning of a range. Increment + // text pointer as we go here + if (toupper(nextp) == toupper(*t) || *p == L'[') + { + match = matcheW(p, t); } // if the end of text is reached then no match @@ -454,7 +804,11 @@ static int matche_after_star (LPCSTR p, LPCSTR t) * match() is a shell to matche() to return only BOOL values. * -----------------------------------------------------------------------------*/ -BOOL match(LPCSTR p, LPCSTR t) +BOOL matchA(LPCSTR p, LPCSTR t) +{ + return (matcheA(p, t) == MATCH_VALID) ? TRUE : FALSE; +} +BOOL matchW(LPCWSTR p, LPCWSTR t) { - return (matche(p, t) == MATCH_VALID) ? TRUE : FALSE; + return (matcheW(p, t) == MATCH_VALID) ? TRUE : FALSE; } diff --git a/lsapi/picopng.cpp b/lsapi/picopng.cpp index 32e8953..7bd940c 100644 --- a/lsapi/picopng.cpp +++ b/lsapi/picopng.cpp @@ -1,543 +1,543 @@ -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// This is a part of the Litestep Shell source code. -// -// Copyright (C) 1997-2013 LiteStep Development 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 "../litestep/buildoptions.h" - -#if defined(LS_USE_PICOPNG) - -#include - -// These were moved outside of "decodePNG()" for VC7.1/8 compiler support -static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; -static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; -static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; -static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; -static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths - -//int decodePNG(std::vector& out_image_32bit, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) -int decodePNG(std::vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) -{ - // picoPNG version 20101224 - // Copyright (c) 2005-2010 Lode Vandevenne - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for - // programs that need only 1 .cpp file. Since it's a single function, it's very limited, - // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or - // with no color conversion at all. For anything more complex, another tiny library - // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. - // Apologies for the compact code style, it's to make this tiny. - - struct Zlib //nested functions for zlib decompression - { - static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} - static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) - { - unsigned long result = 0; - for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; - return result; - } - struct HuffmanTree - { - int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) - { //make tree given the lengths - unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; - std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); - for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length - for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; - for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes - tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet - for(unsigned long n = 0; n < numcodes; n++) //the codes - for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code - { - unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; - if(treepos > numcodes - 2) return 55; - if(tree2d[2 * treepos + bit] == 32767) //not yet filled in - { - if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit - else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes - } - else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value - } - return 0; - } - int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const - { //Decodes a symbol from the tree - unsigned long numcodes = (unsigned long)tree2d.size() / 2; - if(treepos >= numcodes) return 11; //error: you appeared outside the codetree - result = tree2d[2 * treepos + bit]; - decoded = (result < numcodes); - treepos = decoded ? 0 : result - numcodes; - return 0; - } - std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. - }; - struct Inflator - { - int error; - void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) - { - size_t bp = 0, pos = 0; //bit pointer and byte pointer - error = 0; - unsigned long BFINAL = 0; - while(!BFINAL && !error) - { - if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory - BFINAL = readBitFromStream(bp, &in[inpos]); - unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); - if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE - else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); - else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); - } - if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that - } - void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree - { - std::vector bitlen(288, 8), bitlenD(32, 5);; - for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; - for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; - tree.makeFromLengths(bitlen, 15); - treeD.makeFromLengths(bitlenD, 15); - } - HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes - unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) - { //decode a single symbol from given list of bits with given code tree. return value is the symbol - bool decoded; unsigned long ct; - for(size_t treepos = 0;;) - { - if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode - error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened - if(decoded) return ct; - } - } - void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) - { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree - std::vector bitlen(288, 0), bitlenD(32, 0); - if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory - size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 - size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 - size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 - std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree - for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; - error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; - size_t i = 0, replength; - while(i < HLIT + HDIST) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; - if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code - else if(code == 16) //repeat previous - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 2); - unsigned long value; //set value to the previous code - if((i - 1) < HLIT) value = bitlen[i - 1]; - else value = bitlenD[i - HLIT - 1]; - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; - } - } - else if(code == 17) //repeat "0" 3-10 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 3 + readBitsFromStream(bp, in, 3); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else if(code == 18) //repeat "0" 11-138 times - { - if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory - replength = 11 + readBitsFromStream(bp, in, 7); - for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths - { - if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes - if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; - } - } - else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. - } - if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 - error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done - error = treeD.makeFromLengths(bitlenD, 15); if(error) return; - } - void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) - { - if(btype == 1) { generateFixedTrees(codetree, codetreeD); } - else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } - for(;;) - { - unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; - if(code == 256) return; //end code - else if(code <= 255) //literal symbol - { - if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room - out[pos++] = (unsigned char)(code); - } - else if(code >= 257 && code <= 285) //length code - { - size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - length += readBitsFromStream(bp, in, numextrabits); - unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; - if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) - unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; - if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory - dist += readBitsFromStream(bp, in, numextrabitsD); - size_t start = pos, back = start - dist; //backwards - if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room - for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } - } - } - } - void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) - { - while((bp & 0x7) != 0) bp++; //go to first boundary of byte - size_t p = bp / 8; - if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory - unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; - if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN - if(pos + LEN >= out.size()) out.resize(pos + LEN); - if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer - for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data - bp = p * 8; - } - }; - int decompress(std::vector& out, const std::vector& in) //returns error value - { - Inflator inflator; - if(in.size() < 2) { return 53; } //error, size of zlib data too small - if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way - unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; - if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec - if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." - inflator.inflate(out, in, 2); - return inflator.error; //note: adler32 checksum was skipped and ignored - } - }; - struct PNG //nested functions for PNG decoding - { - struct Info - { - unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; - bool key_defined; //is a transparent color key given? - std::vector palette; - } info; - int error; - void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) - { - error = 0; - if(size == 0 || in == 0) { error = 48; return; } //the given data is empty - readPngHeader(&in[0], size); if(error) return; - size_t pos = 33; //first byte of the first chunk after the header - std::vector idat; //the data from idat chunks - bool IEND = false, known_type = true; - info.key_defined = false; - while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer - { - if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk - size_t chunkLength = read32bitInt(&in[pos]); pos += 4; - if(chunkLength > 2147483647) { error = 63; return; } - if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk - if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data - { - idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); - pos += (4 + chunkLength); - } - else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } - else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) - { - pos += 4; //go after the 4 letters - info.palette.resize(4 * (chunkLength / 3)); - if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big - for(size_t i = 0; i < info.palette.size(); i += 4) - { - for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB - info.palette[i + 3] = 255; //alpha - } - } - else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) - { - pos += 4; //go after the 4 letters - if(info.colorType == 3) - { - if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries - for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; - } - else if(info.colorType == 0) - { - if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image - info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else if(info.colorType == 2) - { - if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image - info.key_defined = 1; - info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; - info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; - } - else { error = 42; return; } //error: tRNS chunk not allowed for other color models - } - else //it's not an implemented chunk type, so ignore it: skip over the data - { - if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) - pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk - known_type = false; - } - pos += 4; //step over CRC (which is ignored) - } - unsigned long bpp = getBpp(info); - std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled - Zlib zlib; //decompress with the Zlib decompressor - error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error - size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; - out.resize(outlength); //time to fill the out buffer - unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization - if(info.interlaceMethod == 0) //no interlace, just filter - { - size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte - if(bpp >= 8) //byte per byte - for(unsigned long y = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - linestart += (1 + linelength); //go to start of next scanline - } - else //less than 8 bits per pixel, so fill it up bit per bit - { - std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 - for(size_t y = 0, obp = 0; y < info.height; y++) - { - unsigned long filterType = scanlines[linestart]; - const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; - unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; - for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); - linestart += (1 + linelength); //go to start of next scanline - } - } - } - else //interlaceMethod is 1 (Adam7) - { - size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; - size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; - size_t passstart[7] = {0}; - size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes - for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); - std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline - for(int i = 0; i < 7; i++) - adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); - } - if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed - { - std::vector data = out; - error = convert(out, &data[0], info, info.width, info.height); - } - } - void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info - { - if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header - if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature - if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! - info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); - info.bitDepth = in[24]; info.colorType = in[25]; - info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification - info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification - info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification - error = checkColorValidity(info.colorType, info.bitDepth); - } - void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) - { - switch(filterType) - { - case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; - case 1: - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth]) & 0xFF; - break; - case 2: - if(precon) for(size_t i = 0; i < length; i++) recon[i] = (scanline[i] + precon[i]) & 0xFF; - else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; - break; - case 3: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + precon[i] / 2) & 0xFF; - for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2)) & 0xFF; - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth] / 2) & 0xFF; - } - break; - case 4: - if(precon) - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + paethPredictor(0, precon[i], 0)) & 0xFF; - for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])) & 0xFF; - } - else - { - for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; - for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)) & 0xFF; - } - break; - default: error = 36; return; //error: unexisting filter type given - } - } - void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) - { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. - if(passw == 0) return; - size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); - for(unsigned long y = 0; y < passh; y++) - { - unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; - unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; - if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel - out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; - else for(size_t i = 0; i < passw; i++) - { - size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; - for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); - } - unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" - } - } - static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} - static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) - { - unsigned long result = 0; - for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); - return result; - } - void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } - unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } - int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code - { - if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } - else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } - else return 31; //unexisting color type - } - unsigned long getBpp(const Info& info) - { - if(info.colorType == 2) return (3 * info.bitDepth); - else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; - else return info.bitDepth; - } - int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) - { //converts from any color type to 32-bit. return value = LodePNG error code - size_t numpixels = w * h, bp = 0; - out.resize(numpixels * 4); - unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization - if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; - out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; - out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) - for(size_t i = 0; i < numpixels; i++) - { - if(4U * in[i] >= infoIn.palette.size()) return 46; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; - out_[4 * i + 3] = in[2 * i + 1]; - } - else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha - else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; - out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color - for(size_t i = 0; i < numpixels; i++) - { - for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; - out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha - for(size_t i = 0; i < numpixels; i++) - { - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte - out_[4 * i + 3] = in[4 * i + 2]; - } - else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha - else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 - out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); - out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; - } - else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette - for(size_t i = 0; i < numpixels; i++) - { - unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); - if(4 * value >= infoIn.palette.size()) return 47; - for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette - } - return 0; - } - unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 - { - short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); - return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); - } - }; - PNG decoder; decoder.decode(out_image, in_png, in_size, true); - image_width = decoder.info.width; image_height = decoder.info.height; - return decoder.error; -} - -#endif // LS_USE_PICOPNG +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2013 LiteStep Development 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 "../litestep/buildoptions.h" + +#if defined(LS_USE_PICOPNG) + +#include + +// These were moved outside of "decodePNG()" for VC7.1/8 compiler support +static const unsigned long LENBASE[29] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258}; +static const unsigned long LENEXTRA[29] = {0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; +static const unsigned long DISTBASE[30] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; +static const unsigned long DISTEXTRA[30] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; +static const unsigned long CLCL[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; //code length code lengths + +//int decodePNG(std::vector& out_image_32bit, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) +int decodePNG(std::vector& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, unsigned long in_size) +{ + // picoPNG version 20101224 + // Copyright (c) 2005-2010 Lode Vandevenne + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // picoPNG is a PNG decoder in one C++ function of around 500 lines. Use picoPNG for + // programs that need only 1 .cpp file. Since it's a single function, it's very limited, + // it can convert a PNG to raw pixel data either converted to 32-bit RGBA color or + // with no color conversion at all. For anything more complex, another tiny library + // is available: LodePNG (lodepng.c(pp)), which is a single source and header file. + // Apologies for the compact code style, it's to make this tiny. + + struct Zlib //nested functions for zlib decompression + { + static unsigned long readBitFromStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++; return result;} + static unsigned long readBitsFromStream(size_t& bitp, const unsigned char* bits, size_t nbits) + { + unsigned long result = 0; + for(size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i; + return result; + } + struct HuffmanTree + { + int makeFromLengths(const std::vector& bitlen, unsigned long maxbitlen) + { //make tree given the lengths + unsigned long numcodes = (unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0; + std::vector tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0); + for(unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++; //count number of instances of each code length + for(unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1; + for(unsigned long n = 0; n < numcodes; n++) if(bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++; //generate all the codes + tree2d.clear(); tree2d.resize(numcodes * 2, 32767); //32767 here means the tree2d isn't filled there yet + for(unsigned long n = 0; n < numcodes; n++) //the codes + for(unsigned long i = 0; i < bitlen[n]; i++) //the bits for this code + { + unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1; + if(treepos > numcodes - 2) return 55; + if(tree2d[2 * treepos + bit] == 32767) //not yet filled in + { + if(i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; } //last bit + else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; } //addresses are encoded as values > numcodes + } + else treepos = tree2d[2 * treepos + bit] - numcodes; //subtract numcodes from address to get address value + } + return 0; + } + int decode(bool& decoded, unsigned long& result, size_t& treepos, unsigned long bit) const + { //Decodes a symbol from the tree + unsigned long numcodes = (unsigned long)tree2d.size() / 2; + if(treepos >= numcodes) return 11; //error: you appeared outside the codetree + result = tree2d[2 * treepos + bit]; + decoded = (result < numcodes); + treepos = decoded ? 0 : result - numcodes; + return 0; + } + std::vector tree2d; //2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all nodes and leaves of the tree. + }; + struct Inflator + { + int error; + void inflate(std::vector& out, const std::vector& in, size_t inpos = 0) + { + size_t bp = 0, pos = 0; //bit pointer and byte pointer + error = 0; + unsigned long BFINAL = 0; + while(!BFINAL && !error) + { + if(bp >> 3 >= in.size()) { error = 52; return; } //error, bit pointer will jump past memory + BFINAL = readBitFromStream(bp, &in[inpos]); + unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]); + if(BTYPE == 3) { error = 20; return; } //error: invalid BTYPE + else if(BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size()); + else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE); + } + if(!error) out.resize(pos); //Only now we know the true size of out, resize it to that + } + void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) //get the tree of a deflated block with fixed tree + { + std::vector bitlen(288, 8), bitlenD(32, 5);; + for(size_t i = 144; i <= 255; i++) bitlen[i] = 9; + for(size_t i = 256; i <= 279; i++) bitlen[i] = 7; + tree.makeFromLengths(bitlen, 15); + treeD.makeFromLengths(bitlenD, 15); + } + HuffmanTree codetree, codetreeD, codelengthcodetree; //the code tree for Huffman codes, dist codes, and code length codes + unsigned long huffmanDecodeSymbol(const unsigned char* in, size_t& bp, const HuffmanTree& codetree, size_t inlength) + { //decode a single symbol from given list of bits with given code tree. return value is the symbol + bool decoded; unsigned long ct; + for(size_t treepos = 0;;) + { + if((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10; return 0; } //error: end reached without endcode + error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in)); if(error) return 0; //stop, an error happened + if(decoded) return ct; + } + } + void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD, const unsigned char* in, size_t& bp, size_t inlength) + { //get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree + std::vector bitlen(288, 0), bitlenD(32, 0); + if(bp >> 3 >= inlength - 2) { error = 49; return; } //the bit pointer is or will go past the memory + size_t HLIT = readBitsFromStream(bp, in, 5) + 257; //number of literal/length codes + 257 + size_t HDIST = readBitsFromStream(bp, in, 5) + 1; //number of dist codes + 1 + size_t HCLEN = readBitsFromStream(bp, in, 4) + 4; //number of code length codes + 4 + std::vector codelengthcode(19); //lengths of tree to decode the lengths of the dynamic tree + for(size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0; + error = codelengthcodetree.makeFromLengths(codelengthcode, 7); if(error) return; + size_t i = 0, replength; + while(i < HLIT + HDIST) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength); if(error) return; + if(code <= 15) { if(i < HLIT) bitlen[i++] = code; else bitlenD[i++ - HLIT] = code; } //a length code + else if(code == 16) //repeat previous + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 2); + unsigned long value; //set value to the previous code + if((i - 1) < HLIT) value = bitlen[i - 1]; + else value = bitlenD[i - HLIT - 1]; + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 13; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = value; else bitlenD[i++ - HLIT] = value; + } + } + else if(code == 17) //repeat "0" 3-10 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 3 + readBitsFromStream(bp, in, 3); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 14; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else if(code == 18) //repeat "0" 11-138 times + { + if(bp >> 3 >= inlength) { error = 50; return; } //error, bit pointer jumps past memory + replength = 11 + readBitsFromStream(bp, in, 7); + for(size_t n = 0; n < replength; n++) //repeat this value in the next lengths + { + if(i >= HLIT + HDIST) { error = 15; return; } //error: i is larger than the amount of codes + if(i < HLIT) bitlen[i++] = 0; else bitlenD[i++ - HLIT] = 0; + } + } + else { error = 16; return; } //error: somehow an unexisting code appeared. This can never happen. + } + if(bitlen[256] == 0) { error = 64; return; } //the length of the end code 256 must be larger than 0 + error = tree.makeFromLengths(bitlen, 15); if(error) return; //now we've finally got HLIT and HDIST, so generate the code trees, and the function is done + error = treeD.makeFromLengths(bitlenD, 15); if(error) return; + } + void inflateHuffmanBlock(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength, unsigned long btype) + { + if(btype == 1) { generateFixedTrees(codetree, codetreeD); } + else if(btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength); if(error) return; } + for(;;) + { + unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength); if(error) return; + if(code == 256) return; //end code + else if(code <= 255) //literal symbol + { + if(pos >= out.size()) out.resize((pos + 1) * 2); //reserve more room + out[pos++] = (unsigned char)(code); + } + else if(code >= 257 && code <= 285) //length code + { + size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + length += readBitsFromStream(bp, in, numextrabits); + unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength); if(error) return; + if(codeD > 29) { error = 18; return; } //error: invalid dist code (30-31 are never used) + unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD]; + if((bp >> 3) >= inlength) { error = 51; return; } //error, bit pointer will jump past memory + dist += readBitsFromStream(bp, in, numextrabitsD); + size_t start = pos, back = start - dist; //backwards + if(pos + length >= out.size()) out.resize((pos + length) * 2); //reserve more room + for(size_t i = 0; i < length; i++) { out[pos++] = out[back++]; if(back >= start) back = start - dist; } + } + } + } + void inflateNoCompression(std::vector& out, const unsigned char* in, size_t& bp, size_t& pos, size_t inlength) + { + while((bp & 0x7) != 0) bp++; //go to first boundary of byte + size_t p = bp / 8; + if(p >= inlength - 4) { error = 52; return; } //error, bit pointer will jump past memory + unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4; + if(LEN + NLEN != 65535) { error = 21; return; } //error: NLEN is not one's complement of LEN + if(pos + LEN >= out.size()) out.resize(pos + LEN); + if(p + LEN > inlength) { error = 23; return; } //error: reading outside of in buffer + for(unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++]; //read LEN bytes of literal data + bp = p * 8; + } + }; + int decompress(std::vector& out, const std::vector& in) //returns error value + { + Inflator inflator; + if(in.size() < 2) { return 53; } //error, size of zlib data too small + if((in[0] * 256 + in[1]) % 31 != 0) { return 24; } //error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way + unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1; + if(CM != 8 || CINFO > 7) { return 25; } //error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec + if(FDICT != 0) { return 26; } //error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary." + inflator.inflate(out, in, 2); + return inflator.error; //note: adler32 checksum was skipped and ignored + } + }; + struct PNG //nested functions for PNG decoding + { + struct Info + { + unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b; + bool key_defined; //is a transparent color key given? + std::vector palette; + } info; + int error; + void decode(std::vector& out, const unsigned char* in, size_t size, bool convert_to_rgba32) + { + error = 0; + if(size == 0 || in == 0) { error = 48; return; } //the given data is empty + readPngHeader(&in[0], size); if(error) return; + size_t pos = 33; //first byte of the first chunk after the header + std::vector idat; //the data from idat chunks + bool IEND = false, known_type = true; + info.key_defined = false; + while(!IEND) //loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer + { + if(pos + 8 >= size) { error = 30; return; } //error: size of the in buffer too small to contain next chunk + size_t chunkLength = read32bitInt(&in[pos]); pos += 4; + if(chunkLength > 2147483647) { error = 63; return; } + if(pos + chunkLength >= size) { error = 35; return; } //error: size of the in buffer too small to contain next chunk + if(in[pos + 0] == 'I' && in[pos + 1] == 'D' && in[pos + 2] == 'A' && in[pos + 3] == 'T') //IDAT chunk, containing compressed image data + { + idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]); + pos += (4 + chunkLength); + } + else if(in[pos + 0] == 'I' && in[pos + 1] == 'E' && in[pos + 2] == 'N' && in[pos + 3] == 'D') { pos += 4; IEND = true; } + else if(in[pos + 0] == 'P' && in[pos + 1] == 'L' && in[pos + 2] == 'T' && in[pos + 3] == 'E') //palette chunk (PLTE) + { + pos += 4; //go after the 4 letters + info.palette.resize(4 * (chunkLength / 3)); + if(info.palette.size() > (4 * 256)) { error = 38; return; } //error: palette too big + for(size_t i = 0; i < info.palette.size(); i += 4) + { + for(size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++]; //RGB + info.palette[i + 3] = 255; //alpha + } + } + else if(in[pos + 0] == 't' && in[pos + 1] == 'R' && in[pos + 2] == 'N' && in[pos + 3] == 'S') //palette transparency chunk (tRNS) + { + pos += 4; //go after the 4 letters + if(info.colorType == 3) + { + if(4 * chunkLength > info.palette.size()) { error = 39; return; } //error: more alpha values given than there are palette entries + for(size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++]; + } + else if(info.colorType == 0) + { + if(chunkLength != 2) { error = 40; return; } //error: this chunk must be 2 bytes for greyscale image + info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else if(info.colorType == 2) + { + if(chunkLength != 6) { error = 41; return; } //error: this chunk must be 6 bytes for RGB image + info.key_defined = 1; + info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2; + info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2; + } + else { error = 42; return; } //error: tRNS chunk not allowed for other color models + } + else //it's not an implemented chunk type, so ignore it: skip over the data + { + if(!(in[pos + 0] & 32)) { error = 69; return; } //error: unknown critical chunk (5th bit of first byte of chunk type is 0) + pos += (chunkLength + 4); //skip 4 letters and uninterpreted data of unimplemented chunk + known_type = false; + } + pos += 4; //step over CRC (which is ignored) + } + unsigned long bpp = getBpp(info); + std::vector scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height); //now the out buffer will be filled + Zlib zlib; //decompress with the Zlib decompressor + error = zlib.decompress(scanlines, idat); if(error) return; //stop if the zlib decompressor returned an error + size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8; + out.resize(outlength); //time to fill the out buffer + unsigned char* out_ = outlength ? &out[0] : 0; //use a regular pointer to the std::vector for faster code if compiled without optimization + if(info.interlaceMethod == 0) //no interlace, just filter + { + size_t linestart = 0, linelength = (info.width * bpp + 7) / 8; //length in bytes of a scanline, excluding the filtertype byte + if(bpp >= 8) //byte per byte + for(unsigned long y = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + linestart += (1 + linelength); //go to start of next scanline + } + else //less than 8 bits per pixel, so fill it up bit per bit + { + std::vector templine((info.width * bpp + 7) >> 3); //only used if bpp < 8 + for(size_t y = 0, obp = 0; y < info.height; y++) + { + unsigned long filterType = scanlines[linestart]; + const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth]; + unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength); if(error) return; + for(size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0])); + linestart += (1 + linelength); //go to start of next scanline + } + } + } + else //interlaceMethod is 1 (Adam7) + { + size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 }; + size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 }; + size_t passstart[7] = {0}; + size_t pattern[28] = {0,4,0,2,0,1,0,0,0,4,0,2,0,1,8,8,4,4,2,2,1,8,8,8,4,4,2,2}; //values for the adam7 passes + for(int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8); + std::vector scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8); //"old" and "new" scanline + for(int i = 0; i < 7; i++) + adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp); + } + if(convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) //conversion needed + { + std::vector data = out; + error = convert(out, &data[0], info, info.width, info.height); + } + } + void readPngHeader(const unsigned char* in, size_t inlength) //read the information from the header and store it in the Info + { + if(inlength < 29) { error = 27; return; } //error: the data length is smaller than the length of the header + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { error = 28; return; } //no PNG signature + if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { error = 29; return; } //error: it doesn't start with a IHDR chunk! + info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]); + info.bitDepth = in[24]; info.colorType = in[25]; + info.compressionMethod = in[26]; if(in[26] != 0) { error = 32; return; } //error: only compression method 0 is allowed in the specification + info.filterMethod = in[27]; if(in[27] != 0) { error = 33; return; } //error: only filter method 0 is allowed in the specification + info.interlaceMethod = in[28]; if(in[28] > 1) { error = 34; return; } //error: only interlace methods 0 and 1 exist in the specification + error = checkColorValidity(info.colorType, info.bitDepth); + } + void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned long filterType, size_t length) + { + switch(filterType) + { + case 0: for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; break; + case 1: + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth]) & 0xFF; + break; + case 2: + if(precon) for(size_t i = 0; i < length; i++) recon[i] = (scanline[i] + precon[i]) & 0xFF; + else for(size_t i = 0; i < length; i++) recon[i] = scanline[i]; + break; + case 3: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + precon[i] / 2) & 0xFF; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2)) & 0xFF; + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + recon[i - bytewidth] / 2) & 0xFF; + } + break; + case 4: + if(precon) + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = (scanline[i] + paethPredictor(0, precon[i], 0)) & 0xFF; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])) & 0xFF; + } + else + { + for(size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i]; + for(size_t i = bytewidth; i < length; i++) recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)) & 0xFF; + } + break; + default: error = 36; return; //error: unexisting filter type given + } + } + void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp) + { //filter and reposition the pixels into the output when the image is Adam7 interlaced. This function can only do it after the full image is already decoded. The out buffer must have the correct allocated memory size already. + if(passw == 0) return; + size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8); + for(unsigned long y = 0; y < passh; y++) + { + unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo; + unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8); if(error) return; + if(bpp >= 8) for(size_t i = 0; i < passw; i++) for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel + out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b]; + else for(size_t i = 0; i < passw; i++) + { + size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp; + for(size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0])); + } + unsigned char* temp = linen; linen = lineo; lineo = temp; //swap the two buffer pointers "line old" and "line new" + } + } + static unsigned long readBitFromReversedStream(size_t& bitp, const unsigned char* bits) { unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++; return result;} + static unsigned long readBitsFromReversedStream(size_t& bitp, const unsigned char* bits, unsigned long nbits) + { + unsigned long result = 0; + for(size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i); + return result; + } + void setBitOfReversedStream(size_t& bitp, unsigned char* bits, unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; } + unsigned long read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } + int checkColorValidity(unsigned long colorType, unsigned long bd) //return type is a LodePNG error code + { + if((colorType == 2 || colorType == 4 || colorType == 6)) { if(!(bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 0) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; else return 0; } + else if(colorType == 3) { if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; else return 0; } + else return 31; //unexisting color type + } + unsigned long getBpp(const Info& info) + { + if(info.colorType == 2) return (3 * info.bitDepth); + else if(info.colorType >= 4) return (info.colorType - 2) * info.bitDepth; + else return info.bitDepth; + } + int convert(std::vector& out, const unsigned char* in, Info& infoIn, unsigned long w, unsigned long h) + { //converts from any color type to 32-bit. return value = LodePNG error code + size_t numpixels = w * h, bp = 0; + out.resize(numpixels * 4); + unsigned char* out_ = out.empty() ? 0 : &out[0]; //faster if compiled without optimization + if(infoIn.bitDepth == 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i]; + out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c]; + out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 3) //indexed color (palette) + for(size_t i = 0; i < numpixels; i++) + { + if(4U * in[i] >= infoIn.palette.size()) return 46; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c]; //get rgb colors from the palette + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0]; + out_[4 * i + 3] = in[2 * i + 1]; + } + else if(infoIn.bitDepth == 8 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c]; //RGB with alpha + else if(infoIn.bitDepth == 16 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i]; + out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 2) //RGB color + for(size_t i = 0; i < numpixels; i++) + { + for(size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c]; + out_[4 * i + 3] = (infoIn.key_defined && 256U*in[6*i+0]+in[6*i+1] == infoIn.key_r && 256U*in[6*i+2]+in[6*i+3] == infoIn.key_g && 256U*in[6*i+4]+in[6*i+5] == infoIn.key_b) ? 0 : 255; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 4) //greyscale with alpha + for(size_t i = 0; i < numpixels; i++) + { + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i]; //most significant byte + out_[4 * i + 3] = in[4 * i + 2]; + } + else if(infoIn.bitDepth == 16 && infoIn.colorType == 6) for(size_t i = 0; i < numpixels; i++) for(size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c]; //RGB with alpha + else if(infoIn.bitDepth < 8 && infoIn.colorType == 0) //greyscale + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1); //scale value from 0 to 255 + out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (unsigned char)(value); + out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255; + } + else if(infoIn.bitDepth < 8 && infoIn.colorType == 3) //palette + for(size_t i = 0; i < numpixels; i++) + { + unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth); + if(4 * value >= infoIn.palette.size()) return 47; + for(size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c]; //get rgb colors from the palette + } + return 0; + } + unsigned char paethPredictor(short a, short b, short c) //Paeth predicter, used by PNG filter type 4 + { + short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p); + return (unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c); + } + }; + PNG decoder; decoder.decode(out_image, in_png, in_size, true); + image_width = decoder.info.width; image_height = decoder.info.height; + return decoder.error; +} + +#endif // LS_USE_PICOPNG diff --git a/lsapi/png_support.cpp b/lsapi/png_support.cpp index 53867e2..59491dd 100644 --- a/lsapi/png_support.cpp +++ b/lsapi/png_support.cpp @@ -29,7 +29,7 @@ #include //designed for loading files from hard disk in an std::vector -void loadFile(std::vector& buffer, const std::string& filename) +void loadFile(std::vector& buffer, const std::wstring& filename) { std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate); @@ -61,9 +61,9 @@ void loadFile(std::vector& buffer, const std::string& filename) } } -HBITMAP LoadFromPNG(LPCSTR pszFilename) +HBITMAP LoadFromPNG(LPCWSTR pwzFilename) { - if (pszFilename == NULL) + if (pwzFilename == NULL) { return NULL; } @@ -71,7 +71,7 @@ HBITMAP LoadFromPNG(LPCSTR pszFilename) //load and decode std::vector buffer, image, palette; - loadFile(buffer, pszFilename); + loadFile(buffer, pwzFilename); if (buffer.empty()) { @@ -176,7 +176,7 @@ void ls_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) // passing a FILE* into libpng, isn't reliable because it crashes if libpng was // compiled with a different CRT than lsapi.dll // -HBITMAP LoadFromPNG(LPCSTR pszFilename) +HBITMAP LoadFromPNG(LPCWSTR pwzFilename) { HBITMAP hDibSection = NULL; diff --git a/lsapi/png_support.h b/lsapi/png_support.h index 8fe2a40..ecaf1fc 100644 --- a/lsapi/png_support.h +++ b/lsapi/png_support.h @@ -24,6 +24,6 @@ #include "../utility/common.h" -HBITMAP LoadFromPNG(LPCSTR pszFilename); +HBITMAP LoadFromPNG(LPCWSTR pwzFilename); #endif // PNG_SUPPORT_H diff --git a/lsapi/settings.cpp b/lsapi/settings.cpp index c955504..3fbeac3 100644 --- a/lsapi/settings.cpp +++ b/lsapi/settings.cpp @@ -22,30 +22,36 @@ #include "settingsmanager.h" #include "lsapiInit.h" #include "../utility/core.hpp" +#include "../utility/stringutility.h" -LPVOID LCOpen(LPCSTR pszPath) +LPVOID LCOpenW(LPCWSTR pwzPath) { - LPVOID pFile = NULL; + LPVOID pFile = nullptr; if (g_LSAPIManager.IsInitialized()) { - if (pszPath) + if (pwzPath) { - if (pszPath[0] != '\0') + if (pwzPath[0] != L'\0') { - pFile = g_LSAPIManager.GetSettingsManager()->LCOpen(pszPath); + pFile = g_LSAPIManager.GetSettingsManager()->LCOpen(pwzPath); } } - if (pFile == NULL) + if (pFile == nullptr) { - pFile = g_LSAPIManager.GetSettingsManager()->LCOpen(NULL); + pFile = g_LSAPIManager.GetSettingsManager()->LCOpen(nullptr); } } return pFile; } +LPVOID LCOpenA(LPCSTR pszPath) +{ + return LCOpenW(std::unique_ptr(WCSFromMBS(pszPath)).get()); +} + BOOL LCClose(LPVOID pFile) { @@ -53,7 +59,7 @@ BOOL LCClose(LPVOID pFile) if (g_LSAPIManager.IsInitialized()) { - if (pFile != NULL) + if (pFile != nullptr) { bReturn = g_LSAPIManager.GetSettingsManager()->LCClose(pFile); } @@ -63,16 +69,35 @@ BOOL LCClose(LPVOID pFile) } -BOOL LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cchValue) +BOOL LCReadNextCommandW(LPVOID pFile, LPWSTR pwzValue, size_t cchValue) +{ + BOOL bReturn = FALSE; + + if (g_LSAPIManager.IsInitialized()) + { + if (pFile != nullptr && pwzValue != nullptr && cchValue > 0) + { + bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextCommand( + pFile, pwzValue, cchValue); + } + } + + return bReturn; +} + + +BOOL LCReadNextCommandA(LPVOID pFile, LPSTR pszValue, size_t cchValue) { BOOL bReturn = FALSE; if (g_LSAPIManager.IsInitialized()) { - if (pFile != NULL && pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pszValue != nullptr && cchValue > 0) { + std::unique_ptr temp(new wchar_t[cchValue]); bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextCommand( - pFile, pszValue, cchValue); + pFile, temp.get(), cchValue); + WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); } } @@ -80,17 +105,54 @@ BOOL LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cchValue) } -BOOL LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue) +BOOL LCReadNextConfigW(LPVOID pFile, LPCWSTR pwzConfig, LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; if (g_LSAPIManager.IsInitialized()) { - if (pFile != NULL && pszConfig != NULL && - pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pwzConfig != nullptr && + pwzValue != nullptr && cchValue > 0) { bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextConfig( - pFile, pszConfig, pszValue, cchValue); + pFile, pwzConfig, pwzValue, cchValue); + } + } + + return bReturn; +} + + +BOOL LCReadNextConfigA(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue) +{ + BOOL bReturn = FALSE; + + if (g_LSAPIManager.IsInitialized()) + { + if (pFile != nullptr && pszConfig != nullptr && + pszValue != nullptr && cchValue > 0) + { + std::unique_ptr temp(new wchar_t[cchValue]); + bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextConfig( + pFile, MBSTOWCS(pszConfig), temp.get(), cchValue); + WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); + } + } + + return bReturn; +} + + +BOOL LCReadNextLineW(LPVOID pFile, LPWSTR pwzValue, size_t cchValue) +{ + BOOL bReturn = FALSE; + + if (g_LSAPIManager.IsInitialized()) + { + if (pFile != nullptr && pwzValue != nullptr && cchValue > 0) + { + bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextLine( + pFile, pwzValue, cchValue); } } @@ -98,102 +160,242 @@ BOOL LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cch } -BOOL LCReadNextLine(LPVOID pFile, LPSTR pszValue, size_t cchValue) +BOOL LCReadNextLineA(LPVOID pFile, LPSTR pszValue, size_t cchValue) { BOOL bReturn = FALSE; if (g_LSAPIManager.IsInitialized()) { - if (pFile != NULL && pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pszValue != nullptr && cchValue > 0) { + std::unique_ptr value(new wchar_t[cchValue]); bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextLine( - pFile, pszValue, cchValue); + pFile, value.get(), cchValue); + WideCharToMultiByte(CP_ACP, 0, value.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); } } return bReturn; } -int GetRCInt(LPCSTR szKeyName, int nDefault) + +__int64 GetRCInt64W(LPCWSTR pwzKeyName, __int64 nDefault) +{ + if (g_LSAPIManager.IsInitialized()) + { + return g_LSAPIManager.GetSettingsManager()->GetRCInt64( + pwzKeyName, nDefault); + } + + return nDefault; +} + + +__int64 GetRCInt64A(LPCSTR pszKeyName, __int64 nDefault) +{ + return GetRCInt64W(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), nDefault); +} + + +int GetRCIntW(LPCWSTR pwzKeyName, int nDefault) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCInt( - szKeyName, nDefault); + pwzKeyName, nDefault); } return nDefault; } -BOOL GetRCBool(LPCSTR szKeyName, BOOL ifFound) +int GetRCIntA(LPCSTR pszKeyName, int nDefault) +{ + return GetRCIntW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), nDefault); +} + + +float GetRCFloatW(LPCWSTR pwzKeyName, float fDefault) +{ + if (g_LSAPIManager.IsInitialized()) + { + return g_LSAPIManager.GetSettingsManager()->GetRCFloat( + pwzKeyName, fDefault); + } + + return fDefault; +} + + +float GetRCFloatA(LPCSTR pszKeyName, float fDefault) +{ + return GetRCFloatW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), fDefault); +} + + +double GetRCDoubleW(LPCWSTR pwzKeyName, double dDefault) +{ + if (g_LSAPIManager.IsInitialized()) + { + return g_LSAPIManager.GetSettingsManager()->GetRCDouble( + pwzKeyName, dDefault); + } + + return dDefault; +} + + +double GetRCDoubleA(LPCSTR pszKeyName, double dDefault) +{ + return GetRCDoubleW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), dDefault); +} + + +BOOL GetRCBoolW(LPCWSTR pwzKeyName, BOOL ifFound) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCBool( - szKeyName, ifFound); + pwzKeyName, ifFound); } return !ifFound; } -BOOL GetRCBoolDef(LPCSTR szKeyName, BOOL bDefault) +BOOL GetRCBoolA(LPCSTR pszKeyName, BOOL ifFound) +{ + return GetRCBoolW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), ifFound); +} + + +BOOL GetRCBoolDefW(LPCWSTR pwzKeyName, BOOL bDefault) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCBoolDef( - szKeyName, bDefault); + pwzKeyName, bDefault); } return bDefault; } -BOOL GetRCString(LPCSTR szKeyName, LPSTR szValue, LPCSTR defStr, int maxLen) +BOOL GetRCBoolDefA(LPCSTR pszKeyName, BOOL bDefault) +{ + return GetRCBoolDefW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), bDefault); +} + + +BOOL GetRCStringW(LPCWSTR pwzKeyName, LPWSTR pwzValue, LPCWSTR pwzDefStr, int maxLen) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCString( - szKeyName, szValue, defStr, maxLen); + pwzKeyName, pwzValue, pwzDefStr, maxLen); } - else if (szValue && defStr) + else if (pwzValue && pwzDefStr) { - StringCchCopy(szValue, maxLen, defStr); + StringCchCopyW(pwzValue, maxLen, pwzDefStr); } return FALSE; } -COLORREF GetRCColor(LPCSTR szKeyName, COLORREF colDef) +BOOL GetRCStringA(LPCSTR pszKeyName, LPSTR pszValue, LPCSTR pszDefStr, int maxLen) +{ + if (g_LSAPIManager.IsInitialized()) + { + std::unique_ptr tempValue(new wchar_t[maxLen]); + std::unique_ptr key (WCSFromMBS(pszKeyName)); + std::unique_ptr def (WCSFromMBS(pszDefStr)); + + *tempValue = L'\0'; + + BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetRCString( + key.get(), tempValue.get(), def.get(), maxLen); + + if (pszValue) + { + WideCharToMultiByte(CP_ACP, 0, tempValue.get(), maxLen, pszValue, maxLen, "?", nullptr); + } + + return bRet; + } + else if (pszValue && pszDefStr) + { + StringCchCopyA(pszValue, maxLen, pszDefStr); + } + + return FALSE; +} + + +COLORREF GetRCColorW(LPCWSTR pwzKeyName, COLORREF colDef) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCColor( - szKeyName, colDef); + pwzKeyName, colDef); } return colDef; } -BOOL GetRCLine(LPCSTR szKeyName, LPSTR szBuffer, UINT nBufLen, LPCSTR szDefault) +COLORREF GetRCColorA(LPCSTR pszKeyName, COLORREF colDef) +{ + return GetRCColorW(std::unique_ptr(WCSFromMBS(pszKeyName)).get(), colDef); +} + + +BOOL GetRCLineW(LPCWSTR pwzKeyName, LPWSTR pwzBuffer, UINT nBufLen, LPCWSTR pwzDefault) { if (g_LSAPIManager.IsInitialized()) { return g_LSAPIManager.GetSettingsManager()->GetRCLine( - szKeyName, szBuffer, nBufLen, szDefault); + pwzKeyName, pwzBuffer, nBufLen, pwzDefault); } - else if (szBuffer && szDefault) + else if (pwzBuffer && pwzDefault) { - StringCchCopy(szBuffer, nBufLen, szDefault); + StringCchCopyW(pwzBuffer, nBufLen, pwzDefault); } return FALSE; } -BOOL LSGetVariableEx(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) + +BOOL GetRCLineA(LPCSTR pszKeyName, LPSTR pszBuffer, UINT nBufLen, LPCSTR pszDefault) +{ + if (g_LSAPIManager.IsInitialized()) + { + std::unique_ptr tempValue(new wchar_t[nBufLen]); + std::unique_ptr key (WCSFromMBS(pszKeyName)); + std::unique_ptr def (WCSFromMBS(pszDefault)); + + *tempValue = L'\0'; + + BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetRCLine( + key.get(), tempValue.get(), nBufLen, def.get()); + + if (pszBuffer) + { + WideCharToMultiByte(CP_ACP, 0, tempValue.get(), nBufLen, pszBuffer, nBufLen, "?", nullptr); + } + + return bRet; + } + else if (pszBuffer && pszDefault) + { + StringCchCopyA(pszBuffer, nBufLen, pszDefault); + } + + return FALSE; +} + + +BOOL LSGetVariableExW(LPCWSTR pszKeyName, LPWSTR pszValue, DWORD dwLength) { if (g_LSAPIManager.IsInitialized()) { @@ -204,14 +406,33 @@ BOOL LSGetVariableEx(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) return FALSE; } -BOOL LSGetVariable(LPCSTR pszKeyName, LPSTR pszValue) + +BOOL LSGetVariableExA(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) +{ + if (g_LSAPIManager.IsInitialized()) + { + std::unique_ptr temp(new wchar_t[dwLength]); + + BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetVariable( + MBSTOWCS(pszKeyName), temp.get(), dwLength); + + WideCharToMultiByte(CP_ACP, 0, temp.get(), dwLength, pszValue, dwLength, "?", nullptr); + + return bRet; + } + + return FALSE; +} + + +BOOL LSGetVariableW(LPCWSTR pszKeyName, LPWSTR pszValue) { BOOL bReturn = FALSE; - char szTempValue[MAX_LINE_LENGTH]; + wchar_t szTempValue[MAX_LINE_LENGTH]; if (pszValue) { - pszValue[0] = '\0'; + pszValue[0] = L'\0'; } if (g_LSAPIManager.IsInitialized()) @@ -221,7 +442,32 @@ BOOL LSGetVariable(LPCSTR pszKeyName, LPSTR pszValue) if (bReturn && pszValue) { - StringCchCopy(pszValue, strlen(szTempValue) + 1, szTempValue); + StringCchCopy(pszValue, wcslen(szTempValue) + 1, szTempValue); + } + } + + return bReturn; +} + + +BOOL LSGetVariableA(LPCSTR pszKeyName, LPSTR pszValue) +{ + BOOL bReturn = FALSE; + wchar_t szTempValue[MAX_LINE_LENGTH]; + + if (pszValue) + { + pszValue[0] = L'\0'; + } + + if (g_LSAPIManager.IsInitialized()) + { + bReturn = g_LSAPIManager.GetSettingsManager()->GetVariable( + MBSTOWCS(pszKeyName), szTempValue, MAX_LINE_LENGTH); + + if (bReturn && pszValue) + { + StringCchCopyA(pszValue, _countof(szTempValue), WCSTOMBS(szTempValue)); } } @@ -229,10 +475,19 @@ BOOL LSGetVariable(LPCSTR pszKeyName, LPSTR pszValue) } -void LSSetVariable(LPCSTR pszKeyName, LPCSTR pszValue) +void LSSetVariableW(LPCWSTR pszKeyName, LPCWSTR pszValue) { if (g_LSAPIManager.IsInitialized()) { g_LSAPIManager.GetSettingsManager()->SetVariable(pszKeyName, pszValue); } } + + +void LSSetVariableA(LPCSTR pszKeyName, LPCSTR pszValue) +{ + LSSetVariableW( + std::unique_ptr(WCSFromMBS(pszKeyName)).get(), + std::unique_ptr(WCSFromMBS(pszValue)).get() + ); +} diff --git a/lsapi/settingsmanager.cpp b/lsapi/settingsmanager.cpp index dd23037..df7e620 100644 --- a/lsapi/settingsmanager.cpp +++ b/lsapi/settingsmanager.cpp @@ -59,24 +59,24 @@ SettingsManager::~SettingsManager() } -void SettingsManager::ParseFile(LPCSTR pszFileName) +void SettingsManager::ParseFile(LPCWSTR pwzFileName) { - TRACE("Loading config file \"%s\"", pszFileName); + TRACE("Loading config file \"%ls\"", pwzFileName); FileParser fpParser(&m_SettingsMap); - fpParser.ParseFile(pszFileName); + fpParser.ParseFile(pwzFileName); } -BOOL SettingsManager::_FindLine(LPCSTR pszName, SettingsMap::iterator &it) +BOOL SettingsManager::_FindLine(LPCWSTR pwzName, SettingsMap::iterator &it) { - ASSERT(NULL != pszName); + ASSERT(NULL != pwzName); BOOL bReturn = FALSE; // first appearance of a setting takes effect - it = m_SettingsMap.lower_bound(pszName); + it = m_SettingsMap.lower_bound(pwzName); - if (it != m_SettingsMap.end() && _stricmp(pszName, it->first.c_str()) == 0) + if (it != m_SettingsMap.end() && _wcsicmp(pwzName, it->first.c_str()) == 0) { bReturn = TRUE; } @@ -85,35 +85,35 @@ BOOL SettingsManager::_FindLine(LPCSTR pszName, SettingsMap::iterator &it) } -BOOL SettingsManager::GetRCString(LPCSTR pszKeyName, LPSTR pszValue, LPCSTR pszDefStr, int nMaxLen) +BOOL SettingsManager::GetRCString(LPCWSTR pwzKeyName, LPWSTR pwzValue, LPCWSTR pwzDefStr, int nMaxLen) { SettingsMap::iterator it; BOOL bReturn = FALSE; - if (pszValue) + if (pwzValue) { - pszValue[0] = '\0'; + pwzValue[0] = L'\0'; } - if (pszKeyName) + if (pwzKeyName) { - if (_FindLine(pszKeyName, it)) + if (_FindLine(pwzKeyName, it)) { bReturn = TRUE; - if (pszValue) + if (pwzValue) { - char szToken[MAX_LINE_LENGTH] = { 0 }; - GetToken(it->second.c_str(), szToken, NULL, FALSE); + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + GetTokenW(it->second.c_str(), wzToken, NULL, FALSE); StringSet recursiveVarSet; - recursiveVarSet.insert(pszKeyName); - VarExpansionEx(pszValue, szToken, nMaxLen, recursiveVarSet); + recursiveVarSet.insert(pwzKeyName); + VarExpansionEx(pwzValue, wzToken, nMaxLen, recursiveVarSet); } } - else if (pszDefStr && pszValue) + else if (pwzDefStr && pwzValue) { - StringCchCopy(pszValue, nMaxLen, pszDefStr); + StringCchCopyW(pwzValue, nMaxLen, pwzDefStr); // for compatibility reasons GetRCString and GetRCLine return FALSE // if the default value is returned. @@ -125,34 +125,34 @@ BOOL SettingsManager::GetRCString(LPCSTR pszKeyName, LPSTR pszValue, LPCSTR pszD } -BOOL SettingsManager::GetRCLine(LPCSTR pszKeyName, LPSTR pszValue, int nMaxLen, LPCSTR pszDefStr) +BOOL SettingsManager::GetRCLine(LPCWSTR pwzKeyName, LPWSTR pwzValue, int nMaxLen, LPCWSTR pwzDefStr) { SettingsMap::iterator it; BOOL bReturn = FALSE; - if (pszValue) + if (pwzValue) { - pszValue[0] = '\0'; + pwzValue[0] = L'\0'; } - if (pszKeyName) + if (pwzKeyName) { - if (_FindLine(pszKeyName, it)) + if (_FindLine(pwzKeyName, it)) { bReturn = TRUE; - if (pszValue) + if (pwzValue) { // for compatibility reasons GetRCLine expands $evars$ StringSet recursiveVarSet; - recursiveVarSet.insert(pszKeyName); - VarExpansionEx(pszValue, it->second.c_str(), + recursiveVarSet.insert(pwzKeyName); + VarExpansionEx(pwzValue, it->second.c_str(), nMaxLen, recursiveVarSet); } } - else if (pszDefStr && pszValue) + else if (pwzDefStr && pwzValue) { - StringCchCopy(pszValue, nMaxLen, pszDefStr); + StringCchCopyW(pwzValue, nMaxLen, pwzDefStr); // for compatibility reasons GetRCString and GetRCLine // return FALSE if the default value is returned. @@ -164,25 +164,25 @@ BOOL SettingsManager::GetRCLine(LPCSTR pszKeyName, LPSTR pszValue, int nMaxLen, } -BOOL SettingsManager::GetRCBool(LPCSTR pszKeyName, BOOL bIfFound) +BOOL SettingsManager::GetRCBool(LPCWSTR pwzKeyName, BOOL bIfFound) { SettingsMap::iterator it; - if (pszKeyName && _FindLine(pszKeyName, it)) + if (pwzKeyName && _FindLine(pwzKeyName, it)) { - char szExpanded[MAX_LINE_LENGTH] = { 0 }; - char szToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; StringSet recursiveVarSet; - recursiveVarSet.insert(pszKeyName); - VarExpansionEx(szExpanded, it->second.c_str(), + recursiveVarSet.insert(pwzKeyName); + VarExpansionEx(wzExpanded, it->second.c_str(), MAX_LINE_LENGTH, recursiveVarSet); - if (GetToken(szExpanded, szToken, NULL, FALSE)) + if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) { - if (_stricmp(szToken, "off") && - _stricmp(szToken, "false") && - _stricmp(szToken, "no")) + if (_wcsicmp(wzToken, L"off") && + _wcsicmp(wzToken, L"false") && + _wcsicmp(wzToken, L"no")) { return bIfFound; } @@ -197,25 +197,25 @@ BOOL SettingsManager::GetRCBool(LPCSTR pszKeyName, BOOL bIfFound) } -BOOL SettingsManager::GetRCBoolDef(LPCSTR pszKeyName, BOOL bDefault) +BOOL SettingsManager::GetRCBoolDef(LPCWSTR pwzKeyName, BOOL bDefault) { SettingsMap::iterator it; - if (pszKeyName && _FindLine(pszKeyName, it)) + if (pwzKeyName && _FindLine(pwzKeyName, it)) { - char szToken[MAX_LINE_LENGTH] = { 0 }; - char szExpanded[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; StringSet recursiveVarSet; - recursiveVarSet.insert(pszKeyName); - VarExpansionEx(szExpanded, it->second.c_str(), + recursiveVarSet.insert(pwzKeyName); + VarExpansionEx(wzExpanded, it->second.c_str(), MAX_LINE_LENGTH, recursiveVarSet); - if (GetToken(szExpanded, szToken, NULL, FALSE)) + if (GetTokenW(wzExpanded, wzToken, NULL, FALSE)) { - if ((_stricmp(szToken, "off") == 0) || - (_stricmp(szToken, "false") == 0) || - (_stricmp(szToken, "no") == 0)) + if ((_wcsicmp(wzToken, L"off") == 0) || + (_wcsicmp(wzToken, L"false") == 0) || + (_wcsicmp(wzToken, L"no") == 0)) { return FALSE; } @@ -228,24 +228,49 @@ BOOL SettingsManager::GetRCBoolDef(LPCSTR pszKeyName, BOOL bDefault) } -int SettingsManager::GetRCInt(LPCSTR pszKeyName, int nDefault) +__int64 SettingsManager::GetRCInt64(LPCWSTR pszKeyName, __int64 nDefault) +{ + SettingsMap::iterator it; + __int64 nValue = nDefault; + + if (pszKeyName && _FindLine(pszKeyName, it)) + { + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; + + StringSet recursiveVarSet; + recursiveVarSet.insert(pszKeyName); + VarExpansionEx(wzExpanded, it->second.c_str(), + MAX_LINE_LENGTH, recursiveVarSet); + + if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) + { + nValue = _wcstoi64(wzToken, nullptr, 0); + } + } + + return nValue; +} + + +int SettingsManager::GetRCInt(LPCWSTR pszKeyName, int nDefault) { SettingsMap::iterator it; int nValue = nDefault; if (pszKeyName && _FindLine(pszKeyName, it)) { - char szToken[MAX_LINE_LENGTH] = { 0 }; - char szExpanded[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(szExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.c_str(), MAX_LINE_LENGTH, recursiveVarSet); - if (GetToken(szExpanded, szToken, NULL, FALSE)) + if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) { - nValue = strtol(szToken, NULL, 0); + nValue = wcstol(wzToken, nullptr, 0); } } @@ -253,40 +278,90 @@ int SettingsManager::GetRCInt(LPCSTR pszKeyName, int nDefault) } -COLORREF SettingsManager::GetRCColor(LPCSTR pszKeyName, COLORREF crDefault) +float SettingsManager::GetRCFloat(LPCWSTR pszKeyName, float fDefault) +{ + SettingsMap::iterator it; + float fValue = fDefault; + + if (pszKeyName && _FindLine(pszKeyName, it)) + { + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; + + StringSet recursiveVarSet; + recursiveVarSet.insert(pszKeyName); + VarExpansionEx(wzExpanded, it->second.c_str(), + MAX_LINE_LENGTH, recursiveVarSet); + + if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) + { + fValue = (float)wcstod(wzToken, nullptr); + } + } + + return fValue; +} + + +double SettingsManager::GetRCDouble(LPCWSTR pszKeyName, double dDefault) +{ + SettingsMap::iterator it; + double dValue = dDefault; + + if (pszKeyName && _FindLine(pszKeyName, it)) + { + wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; + wchar_t wzExpanded[MAX_LINE_LENGTH] = { 0 }; + + StringSet recursiveVarSet; + recursiveVarSet.insert(pszKeyName); + VarExpansionEx(wzExpanded, it->second.c_str(), + MAX_LINE_LENGTH, recursiveVarSet); + + if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) + { + dValue = wcstod(wzToken, nullptr); + } + } + + return dValue; +} + + +COLORREF SettingsManager::GetRCColor(LPCWSTR pszKeyName, COLORREF crDefault) { COLORREF crReturn = crDefault; SettingsMap::iterator it; if (pszKeyName && _FindLine(pszKeyName, it)) { - char szBuffer[MAX_LINE_LENGTH]; - char szFirst[MAX_LINE_LENGTH]; - char szSecond[MAX_LINE_LENGTH]; - char szThird[MAX_LINE_LENGTH]; + wchar_t wzBuffer[MAX_LINE_LENGTH]; + wchar_t wzFirst[MAX_LINE_LENGTH]; + wchar_t wzSecond[MAX_LINE_LENGTH]; + wchar_t wzThird[MAX_LINE_LENGTH]; - LPSTR lpszTokens[3] = { szFirst, szSecond, szThird }; + LPWSTR lpwzTokens[3] = { wzFirst, wzSecond, wzThird }; StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(szBuffer, it->second.c_str(), + VarExpansionEx(wzBuffer, it->second.c_str(), MAX_LINE_LENGTH, recursiveVarSet); - int nCount = LCTokenize(szBuffer, lpszTokens, 3, NULL); + int nCount = LCTokenizeW(wzBuffer, lpwzTokens, 3, nullptr); if (nCount >= 3) { int nRed, nGreen, nBlue; - nRed = strtol(szFirst, NULL, 10); - nGreen = strtol(szSecond, NULL, 10); - nBlue = strtol(szThird, NULL, 10); + nRed = wcstol(wzFirst, nullptr, 10); + nGreen = wcstol(wzSecond, nullptr, 10); + nBlue = wcstol(wzThird, nullptr, 10); crReturn = RGB(nRed, nGreen, nBlue); } else if (nCount >= 1) { - crReturn = strtol(szFirst, NULL, 16); + crReturn = wcstol(wzFirst, nullptr, 16); // convert from BGR to RGB crReturn = RGB(GetBValue(crReturn), GetGValue(crReturn), GetRValue(crReturn)); @@ -297,7 +372,7 @@ COLORREF SettingsManager::GetRCColor(LPCSTR pszKeyName, COLORREF crDefault) } -BOOL SettingsManager::GetVariable(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) +BOOL SettingsManager::GetVariable(LPCWSTR pszKeyName, LPWSTR pszValue, DWORD dwLength) { // using GetRCString instead of GetRCLine here, again for compatibility // reasons. As a side effect this strips any "" quotes around the @@ -306,7 +381,7 @@ BOOL SettingsManager::GetVariable(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLen } -void SettingsManager::SetVariable(LPCSTR pszKeyName, LPCSTR pszValue) +void SettingsManager::SetVariable(LPCWSTR pszKeyName, LPCWSTR pszValue) { if ((pszKeyName) && (pszValue)) { @@ -324,30 +399,30 @@ void SettingsManager::SetVariable(LPCSTR pszKeyName, LPCSTR pszValue) } -void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t stLength) +void SettingsManager::VarExpansionEx(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate, size_t stLength) { StringSet recursiveVarSet; - VarExpansionEx(pszExpandedString, pszTemplate, stLength, recursiveVarSet); + VarExpansionEx(pwzExpandedString, pwzTemplate, stLength, recursiveVarSet); } -void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t stLength, const StringSet& recursiveVarSet) +void SettingsManager::VarExpansionEx(LPWSTR pwzExpandedString, LPCWSTR pwzTemplate, size_t stLength, const StringSet& recursiveVarSet) { - char szTempExpandedString[MAX_LINE_LENGTH] = { 0 }; - LPSTR pszTempExpandedString = szTempExpandedString; + wchar_t wzTempExpandedString[MAX_LINE_LENGTH] = { 0 }; + LPWSTR pwzTempExpandedString = wzTempExpandedString; // available working length in szTempExpandedString DWORD cchTempExpanded = MAX_LINE_LENGTH; - if ((pszTemplate != NULL) && (pszExpandedString != NULL) && + if ((pwzTemplate != nullptr) && (pwzExpandedString != nullptr) && (cchTempExpanded > 0)) { - while ((*pszTemplate != '\0') && (cchTempExpanded > 0)) + while ((*pwzTemplate != L'\0') && (cchTempExpanded > 0)) { - if (*pszTemplate != '$') + if (*pwzTemplate != L'$') { - *pszTempExpandedString = *pszTemplate; - ++pszTemplate; - ++pszTempExpandedString; + *pwzTempExpandedString = *pwzTemplate; + ++pwzTemplate; + ++pwzTempExpandedString; --cchTempExpanded; } else @@ -355,22 +430,22 @@ void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate // // This is a variable so we need to find the end of it: // - ++pszTemplate; + ++pwzTemplate; - LPCSTR pszVariable = pszTemplate; + LPCWSTR pwzVariable = pwzTemplate; - while ((*pszTemplate != '$') && (*pszTemplate != '\0')) + while ((*pwzTemplate != L'$') && (*pwzTemplate != L'\0')) { - ++pszTemplate; + ++pwzTemplate; } bool bSucceeded = false; - if (*pszTemplate == '\0') + if (*pwzTemplate == L'\0') { - bSucceeded = SUCCEEDED(StringCchCopyN( - pszTempExpandedString, (size_t)cchTempExpanded, - pszVariable, pszTemplate - pszVariable)); + bSucceeded = SUCCEEDED(StringCchCopyNW( + pwzTempExpandedString, (size_t)cchTempExpanded, + pwzVariable, pwzTemplate - pwzVariable)); } else { @@ -378,24 +453,24 @@ void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate // We've found the end of the variable so copy it // someplace usefull: // - char szVariable[MAX_LINE_LENGTH]; + wchar_t wzVariable[MAX_LINE_LENGTH]; - if (SUCCEEDED(StringCchCopyN(szVariable, MAX_LINE_LENGTH, - pszVariable, pszTemplate - pszVariable)) && - (szVariable[0] != '\0')) + if (SUCCEEDED(StringCchCopyNW(wzVariable, MAX_LINE_LENGTH, + pwzVariable, pwzTemplate - pwzVariable)) && + (wzVariable[0] != L'\0')) { // Check for recursive variable definitions - if (recursiveVarSet.count(szVariable) > 0) + if (recursiveVarSet.count(wzVariable) > 0) { RESOURCE_STREX( GetModuleHandle(NULL), IDS_RECURSIVEVAR, resourceTextBuffer, MAX_LINE_LENGTH, - "Error: Variable \"%s\" is defined recursively.", - szVariable); + L"Error: Variable \"%ls\" is defined recursively.", + wzVariable); - RESOURCE_MSGBOX_F("LiteStep", MB_ICONERROR); + RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); - pszExpandedString[0] = '\0'; + pwzExpandedString[0] = L'\0'; return; } @@ -403,36 +478,36 @@ void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate // Get the value, if we can. // SettingsMap::iterator it; - if (_FindLine(szVariable, it)) + if (_FindLine(wzVariable, it)) { StringSet newRecursiveVarSet(recursiveVarSet); - newRecursiveVarSet.insert(szVariable); + newRecursiveVarSet.insert(wzVariable); // FIXME: Should we not call GetToken here?! - TCHAR szTemp[MAX_LINE_LENGTH]; - GetToken(it->second.c_str(), szTemp, NULL, FALSE); + WCHAR wzTemp[MAX_LINE_LENGTH]; + GetTokenW(it->second.c_str(), wzTemp, NULL, FALSE); - VarExpansionEx(pszTempExpandedString, szTemp, + VarExpansionEx(pwzTempExpandedString, wzTemp, (size_t)cchTempExpanded, newRecursiveVarSet); bSucceeded = true; } - else if (GetEnvironmentVariable(szVariable, - pszTempExpandedString, cchTempExpanded)) + else if (GetEnvironmentVariableW(wzVariable, + pwzTempExpandedString, cchTempExpanded)) { bSucceeded = true; } #if defined(LS_COMPAT_MATH) else { - std::string result; + std::wstring result; - if (MathEvaluateString(m_SettingsMap, szVariable, + if (MathEvaluateString(m_SettingsMap, wzVariable, result, recursiveVarSet, MATH_EXCEPTION_ON_UNDEFINED | MATH_VALUE_TO_COMPATIBLE_STRING)) { - StringCchCopy(pszTempExpandedString, + StringCchCopyW(pwzTempExpandedString, (size_t)cchTempExpanded, result.c_str()); bSucceeded = true; } @@ -447,37 +522,37 @@ void SettingsManager::VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate // if (bSucceeded) { - size_t stTempLen = strlen(pszTempExpandedString); + size_t stTempLen = wcslen(pwzTempExpandedString); // safe operation and cast because // stTempLen < cchTempExpanded cchTempExpanded -= (DWORD)stTempLen; - pszTempExpandedString += stTempLen; + pwzTempExpandedString += stTempLen; } // // Move to the next character if we didn't run out of space: // - if (*pszTemplate != '\0') + if (*pwzTemplate != L'\0') { - ++pszTemplate; + ++pwzTemplate; } } } - *pszTempExpandedString = '\0'; - StringCchCopy(pszExpandedString, stLength, szTempExpandedString); + *pwzTempExpandedString = L'\0'; + StringCchCopyW(pwzExpandedString, stLength, wzTempExpandedString); } } -LPVOID SettingsManager::LCOpen(LPCSTR pszPath) +LPVOID SettingsManager::LCOpen(LPCWSTR pwzPath) { - LPVOID pFile = NULL; + LPVOID pFile = nullptr; - if (pszPath == NULL) + if (pwzPath == nullptr) { - SettingsIterator* psiNew = new SettingsIterator(&m_SettingsMap, "\0"); + SettingsIterator* psiNew = new SettingsIterator(&m_SettingsMap, L"\0"); if (psiNew) { @@ -487,14 +562,14 @@ LPVOID SettingsManager::LCOpen(LPCSTR pszPath) } else { - char szPath[MAX_PATH] = { 0 }; - VarExpansionEx(szPath, pszPath, MAX_PATH); + wchar_t wzPath[MAX_PATH] = { 0 }; + VarExpansionEx(wzPath, pwzPath, MAX_PATH); Lock lock(m_CritSection); - FileMap::iterator it = m_FileMap.find(szPath); + FileMap::iterator it = m_FileMap.find(wzPath); - if (it == m_FileMap.end() && PathFileExists(szPath)) + if (it == m_FileMap.end() && PathFileExistsW(wzPath)) { FileInfo* pFileInfo = new FileInfo; @@ -503,14 +578,14 @@ LPVOID SettingsManager::LCOpen(LPCSTR pszPath) pFileInfo->m_pSettingsMap = new SettingsMap; pFileInfo->m_Count = 1; - TRACE("Loading config file \"%s\"", szPath); + TRACE("Loading config file \"%ls\"", wzPath); FileParser fpParser(pFileInfo->m_pSettingsMap); - fpParser.ParseFile(szPath); + fpParser.ParseFile(wzPath); - m_FileMap.insert(FileMap::value_type(szPath, pFileInfo)); + m_FileMap.insert(FileMap::value_type(wzPath, pFileInfo)); - it = m_FileMap.find(szPath); + it = m_FileMap.find(wzPath); ASSERT(it != m_FileMap.end()); } } @@ -518,7 +593,7 @@ LPVOID SettingsManager::LCOpen(LPCSTR pszPath) if (it != m_FileMap.end()) { SettingsIterator * psiNew = - new SettingsIterator(it->second->m_pSettingsMap, szPath); + new SettingsIterator(it->second->m_pSettingsMap, wzPath); if (psiNew) { @@ -573,23 +648,23 @@ BOOL SettingsManager::LCClose(LPVOID pFile) } -BOOL SettingsManager::LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue) +BOOL SettingsManager::LCReadNextConfig(LPVOID pFile, LPCWSTR pwzConfig, LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; - char szTempValue[MAX_LINE_LENGTH]; + wchar_t wzTempValue[MAX_LINE_LENGTH]; - if (pFile != NULL && pszConfig != NULL && - pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pwzConfig != nullptr && + pwzValue != nullptr && cchValue > 0) { IteratorSet::iterator it = m_Iterators.find((SettingsIterator*)pFile); if (it != m_Iterators.end()) { - bReturn = (*it)->ReadNextConfig(pszConfig, - szTempValue, MAX_LINE_LENGTH); + bReturn = (*it)->ReadNextConfig(pwzConfig, + wzTempValue, MAX_LINE_LENGTH); if (bReturn) { - VarExpansionEx(pszValue, szTempValue, cchValue); + VarExpansionEx(pwzValue, wzTempValue, cchValue); } } } @@ -598,22 +673,22 @@ BOOL SettingsManager::LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR psz } -BOOL SettingsManager::LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cchValue) +BOOL SettingsManager::LCReadNextCommand(LPVOID pFile, LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; - char szTempValue[MAX_LINE_LENGTH]; + wchar_t wzTempValue[MAX_LINE_LENGTH]; - if (pFile != NULL && pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pwzValue != nullptr && cchValue > 0) { IteratorSet::iterator it = m_Iterators.find((SettingsIterator*)pFile); if (it != m_Iterators.end()) { - bReturn = (*it)->ReadNextCommand(szTempValue, MAX_LINE_LENGTH); + bReturn = (*it)->ReadNextCommand(wzTempValue, MAX_LINE_LENGTH); if (bReturn) { - VarExpansionEx(pszValue, szTempValue, cchValue); + VarExpansionEx(pwzValue, wzTempValue, cchValue); } } } @@ -622,22 +697,22 @@ BOOL SettingsManager::LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cch } -BOOL SettingsManager::LCReadNextLine(LPVOID pFile, LPSTR pszValue, size_t cchValue) +BOOL SettingsManager::LCReadNextLine(LPVOID pFile, LPWSTR pwzValue, size_t cchValue) { BOOL bReturn = FALSE; - char szTempValue[MAX_LINE_LENGTH]; + wchar_t wzTempValue[MAX_LINE_LENGTH]; - if (pFile != NULL && pszValue != NULL && cchValue > 0) + if (pFile != nullptr && pwzValue != nullptr && cchValue > 0) { IteratorSet::iterator it = m_Iterators.find((SettingsIterator*)pFile); if (it != m_Iterators.end()) { - bReturn = (*it)->ReadNextLine(szTempValue, MAX_LINE_LENGTH); + bReturn = (*it)->ReadNextLine(wzTempValue, MAX_LINE_LENGTH); if (bReturn) { - VarExpansionEx(pszValue, szTempValue, cchValue); + VarExpansionEx(pwzValue, wzTempValue, cchValue); } } } diff --git a/lsapi/stubs.cpp b/lsapi/stubs.cpp index 837d8b6..b7366f0 100644 --- a/lsapi/stubs.cpp +++ b/lsapi/stubs.cpp @@ -25,9 +25,9 @@ BOOL WINAPI LSLog(int nLevel, LPCSTR pszModule, LPCSTR pszMessage) { #if defined(LS_COMPAT_LOGGING) - char szLogFile[MAX_PATH] = { 0 }; + wchar_t wzLogFile[MAX_PATH] = { 0 }; - int nLogLevel = GetRCInt("LSLogLevel", 2); + int nLogLevel = GetRCIntW(L"LSLogLevel", 2); // Should this message be logged? if (!pszModule || !pszMessage || @@ -37,13 +37,13 @@ BOOL WINAPI LSLog(int nLevel, LPCSTR pszModule, LPCSTR pszMessage) } // Has a log file been assigned? - if (!GetRCString("LSLogFile", szLogFile, NULL, MAX_PATH)) + if (!GetRCStringW(L"LSLogFile", wzLogFile, NULL, MAX_PATH)) { return FALSE; } // If so, open it - HANDLE hLogFile = CreateFile(szLogFile, + HANDLE hLogFile = CreateFile(wzLogFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, @@ -67,11 +67,11 @@ BOOL WINAPI LSLog(int nLevel, LPCSTR pszModule, LPCSTR pszMessage) // Add timestamp and module name to message LPCSTR rszLevel[4] = { "Error", "Warning", "Notice", "Debug" }; - TCHAR szLine[MAX_LINE_LENGTH] = { 0 }; + CHAR szLine[MAX_LINE_LENGTH] = { 0 }; size_t cbLine = sizeof(szLine); size_t cbRemaining = 0; - if (SUCCEEDED(StringCbPrintfEx(szLine, cbLine, NULL, &cbRemaining, + if (SUCCEEDED(StringCbPrintfExA(szLine, cbLine, NULL, &cbRemaining, STRSAFE_IGNORE_NULLS, "%02d-%02d-%04d %02d:%02d:%02d - %s - %s: %s\r\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, rszLevel[nLevel-1], pszModule, pszMessage))) @@ -105,7 +105,7 @@ BOOL WINAPIV LSLogPrintf(int nLevel, LPCSTR pszModule, LPCSTR pszFormat, ...) va_list argList; va_start(argList, pszFormat); - if (SUCCEEDED(StringCchVPrintf(szMessage, MAX_LINE_LENGTH, + if (SUCCEEDED(StringCchVPrintfA(szMessage, MAX_LINE_LENGTH, pszFormat, argList))) { bReturn = LSLog(nLevel, pszModule, szMessage); @@ -123,7 +123,7 @@ int GetRCCoordinate(LPCSTR pszKeyName, int nDefault, int nMaxVal) { char strVal[MAX_LINE_LENGTH]; - if (!GetRCString(pszKeyName, strVal, NULL, MAX_LINE_LENGTH)) + if (!GetRCStringA(pszKeyName, strVal, NULL, MAX_LINE_LENGTH)) { return nDefault; } @@ -258,3 +258,191 @@ BOOL LSEnumDisplayDevices( { return EnumDisplayDevicesA(lpDevice, iDevNum, lpDisplayDevice, dwFlags); } + +extern "C" +{ + LSAPI LPVOID LCOpen(LPCSTR szPath) + { + return LCOpenA(szPath); + } + + LSAPI BOOL LCReadNextCommand(LPVOID pFile, LPSTR pszValue, size_t cchValue) + { + return LCReadNextCommandA(pFile, pszValue, cchValue); + } + + LSAPI BOOL LCReadNextConfig(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cchValue) + { + return LCReadNextConfigA(pFile, pszConfig, pszValue, cchValue); + } + + LSAPI BOOL LCReadNextLine(LPVOID pFile, LPSTR pszValue, size_t cchValue) + { + return LCReadNextLineA(pFile, pszValue, cchValue); + } + + LSAPI int LCTokenize(LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters) + { + return LCTokenizeA(szString, lpszBuffers, dwNumBuffers, szExtraParameters); + } + + LSAPI int GetRCInt(LPCSTR lpKeyName, int nDefault) + { + return GetRCIntA(lpKeyName, nDefault); + } + + LSAPI BOOL GetRCString(LPCSTR lpKeyName, LPSTR value, LPCSTR defStr, int maxLen) + { + return GetRCStringA(lpKeyName, value, defStr, maxLen); + } + + LSAPI BOOL GetRCBool(LPCSTR lpKeyName, BOOL ifFound) + { + return GetRCBoolA(lpKeyName, ifFound); + } + + LSAPI BOOL GetRCBoolDef(LPCSTR lpKeyName, BOOL bDefault) + { + return GetRCBoolDefA(lpKeyName, bDefault); + } + + LSAPI BOOL GetRCLine(LPCSTR lpKeyName, LPSTR value, UINT maxLen, LPCSTR defStr) + { + return GetRCLineA(lpKeyName, value, maxLen, defStr); + } + + LSAPI COLORREF GetRCColor(LPCSTR lpKeyName, COLORREF colDef) + { + return GetRCColorA(lpKeyName, colDef); + } + + LSAPI BOOL LSGetVariable(LPCSTR pszKeyName, LPSTR pszValue) + { + return LSGetVariableA(pszKeyName, pszValue); + } + + LSAPI BOOL LSGetVariableEx(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) + { + return LSGetVariableExA(pszKeyName, pszValue, dwLength); + } + + LSAPI void LSSetVariable(LPCSTR pszKeyName, LPCSTR pszValue) + { + return LSSetVariableA(pszKeyName, pszValue); + } + + LSAPI BOOL AddBangCommand(LPCSTR pszCommand, BangCommandA pfnBangCommand) + { + return AddBangCommandA(pszCommand, pfnBangCommand); + } + + LSAPI BOOL AddBangCommandEx(LPCSTR pszCommand, BangCommandExA pfnBangCommand) + { + return AddBangCommandExA(pszCommand, pfnBangCommand); + } + + LSAPI BOOL RemoveBangCommand(LPCSTR pszCommand) + { + return RemoveBangCommandA(pszCommand); + } + + LSAPI BOOL ParseBangCommand(HWND hCaller, LPCSTR pszCommand, LPCSTR pszArgs) + { + return ParseBangCommandA(hCaller, pszCommand, pszArgs); + } + + LSAPI HBITMAP LoadLSImage(LPCSTR pszFile, LPCSTR pszImage) + { + return LoadLSImageA(pszFile, pszImage); + } + + LSAPI HICON LoadLSIcon(LPCSTR pszImage, LPCSTR pszFile) + { + return LoadLSIconA(pszImage, pszFile); + } + + LSAPI int CommandTokenize(LPCSTR szString, LPSTR * lpszBuffers, DWORD dwNumBuffers, LPSTR szExtraParameters) + { + return CommandTokenizeA(szString, lpszBuffers, dwNumBuffers, szExtraParameters); + } + + LSAPI void CommandParse(LPCSTR pszCommand, LPSTR pszOutCommand, LPSTR pszOutArgs, size_t cchOutCommand, size_t cchOutArgs) + { + return CommandParseA(pszCommand, pszOutCommand, pszOutArgs, cchOutCommand, cchOutArgs); + } + + LSAPI HINSTANCE LSExecute(HWND Owner, LPCSTR szCommand, int nShowCmd) + { + return LSExecuteA(Owner, szCommand, nShowCmd); + } + + LSAPI HINSTANCE LSExecuteEx(HWND Owner, LPCSTR szOperation, LPCSTR szCommand, LPCSTR szArgs, LPCSTR szDirectory, int nShowCmd) + { + return LSExecuteExA(Owner, szOperation, szCommand, szArgs, szDirectory, nShowCmd); + } + + LSAPI BOOL WINAPI LSGetLitestepPath(LPSTR pszPath, size_t cchPath) + { + return LSGetLitestepPathA(pszPath, cchPath); + } + + LSAPI BOOL WINAPI LSGetImagePath(LPSTR pszPath, size_t cchPath) + { + return LSGetImagePathA(pszPath, cchPath); + } + + LSAPI void VarExpansion(LPSTR pszExpandedString, LPCSTR pszTemplate) + { + return VarExpansionA(pszExpandedString, pszTemplate); + } + + LSAPI void VarExpansionEx(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpandedString) + { + return VarExpansionExA(pszExpandedString, pszTemplate, cchExpandedString); + } + + LSAPI BOOL GetToken(LPCSTR pszString, LPSTR pszToken, LPCSTR * pszNextToken, BOOL useBrackets) + { + return GetTokenA(pszString, pszToken, pszNextToken, useBrackets); + } + + LSAPI BOOL match(LPCSTR pattern, LPCSTR text) + { + return matchA(pattern, text); + } + + LSAPI int matche(LPCSTR pattern, LPCSTR text) + { + return matcheA(pattern, text); + } + + LSAPI BOOL is_valid_pattern(LPCSTR p, LPINT error_type) + { + return is_valid_patternA(p, error_type); + } + + LSAPI void GetResStr(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText) + { + return GetResStrA(hInstance, uIDText, pszText, cchText, pszDefText); + } + + LSAPI void GetResStrEx(HINSTANCE hInstance, UINT uIDText, LPSTR pszText, size_t cchText, LPCSTR pszDefText, ...) + { + char szFormat[MAX_LINE_LENGTH]; + va_list vargs; + + if (pszText != NULL && cchText > 0) + { + GetResStrA(hInstance, uIDText, szFormat, MAX_LINE_LENGTH, pszDefText); + + va_start(vargs, pszDefText); + StringCchVPrintfA(pszText, cchText, szFormat, vargs); + va_end(vargs); + } + } + + LSAPI HRESULT EnumLSData(UINT uInfo, FARPROC pfnCallback, LPARAM lParam) + { + return EnumLSDataA(uInfo, pfnCallback, lParam); + } +} diff --git a/utility/IService.h b/utility/IService.h index 03d0152..5a0515f 100644 --- a/utility/IService.h +++ b/utility/IService.h @@ -27,6 +27,7 @@ class IService : public CountedBase { public: + virtual HRESULT Recycle() = 0; virtual HRESULT Start() = 0; virtual HRESULT Stop() = 0; }; diff --git a/utility/common.h b/utility/common.h index 97399df..a9d3e64 100644 --- a/utility/common.h +++ b/utility/common.h @@ -29,8 +29,9 @@ #else -# define _WIN32_WINNT 0x0602 -# define _WIN32_IE 0x0603 +# define _WIN32_WINNT 0x0603 +# define WINVER 0x0603 +# define _WIN32_IE 0x0A00 # define WIN32_LEAN_AND_MEAN diff --git a/utility/debug.cpp b/utility/debug.cpp index 4543214..b5493f2 100644 --- a/utility/debug.cpp +++ b/utility/debug.cpp @@ -60,17 +60,17 @@ void DbgTraceWindowMessage(const char* pszPrefix, unsigned int uMsg, { if (uMsg < WM_USER) { - TRACE("[%s] WM_%.4X(%.8X, %.8X)", + TRACE("[%ls] WM_%.4X(%p, %p)", pszPrefix, uMsg, wParam, lParam); } else if (uMsg >= WM_USER && uMsg <= (WM_APP-1)) { - TRACE("[%s] WM_USER+%u(%.8X, %.8X)", + TRACE("[%ls] WM_USER+%u(%p, %p)", pszPrefix, uMsg-WM_USER, wParam, lParam); } else if (uMsg >= WM_APP && uMsg <= (MAXINTATOM-1)) { - TRACE("[%s] WM_APP+%u(%.8X, %.8X)", + TRACE("[%ls] WM_APP+%u(%p, %p)", pszPrefix, uMsg-WM_APP, wParam, lParam); } else if (uMsg >= MAXINTATOM) @@ -82,12 +82,12 @@ void DbgTraceWindowMessage(const char* pszPrefix, unsigned int uMsg, if (GetClipboardFormatName( uMsg, szMsgName, COUNTOF(szMsgName)) > 0) { - TRACE("[%s] WM_'%s'(%.8X, %.8X)", + TRACE("[%ls] WM_'%ls'(%p, %p)", pszPrefix, szMsgName, wParam, lParam); } else { - TRACE("[%s] WM_%.8X(%.8X, %.8X)", + TRACE("[%ls] WM_%.8X(%p, %p)", pszPrefix, uMsg, wParam, lParam); } } diff --git a/utility/macros.h b/utility/macros.h index ea32e4a..dfe49b1 100644 --- a/utility/macros.h +++ b/utility/macros.h @@ -31,38 +31,38 @@ #if !defined(LSRESOURCEBUFFER) #define LSRESOURCEBUFFER -static char resourceTextBuffer[MAX_LINE_LENGTH + 1] = { 0 }; -static char resourceTitleBuffer[MAX_LINE_LENGTH + 1] = { 0 }; +static wchar_t resourceTextBuffer[MAX_LINE_LENGTH + 1] = { 0 }; +static wchar_t resourceTitleBuffer[MAX_LINE_LENGTH + 1] = { 0 }; #endif // LSRESOURCEBUFFER #define RESOURCE_MSGBOX_F(title, extra_flags) \ - MessageBox(NULL, resourceTextBuffer, title, \ + MessageBoxW(nullptr, resourceTextBuffer, title, \ MB_TOPMOST | extra_flags) #define RESOURCE_MSGBOX(instance, id, deftext, title) \ - GetResStr( (instance), (id) \ + GetResStrW( (instance), (id) \ ,resourceTextBuffer, MAX_LINE_LENGTH \ ,deftext); \ RESOURCE_MSGBOX_F(title, MB_OK | MB_ICONEXCLAMATION) #define RESOURCE_MSGBOX_T(instance, id, deftext, titleid, deftitle) \ - GetResStr( (instance), (id) \ + GetResStrW( (instance), (id) \ ,resourceTextBuffer, MAX_LINE_LENGTH \ ,deftext ); \ - GetResStr( (instance), (titleid) \ + GetResStrW( (instance), (titleid) \ ,resourceTitleBuffer, MAX_LINE_LENGTH \ ,deftitle ); \ RESOURCE_MSGBOX_F(resourceTitleBuffer, MB_OK | MB_ICONEXCLAMATION) #define RESOURCE_STR(instance, id, deftext) \ - GetResStr( (instance), (id) \ + GetResStrW( (instance), (id) \ ,resourceTextBuffer, MAX_LINE_LENGTH \ ,deftext ) -#define RESOURCE_STREX GetResStrEx +#define RESOURCE_STREX GetResStrExW #define RESOURCE_TITLE(instance, id, deftext) \ - GetResStr( (instance), (id) \ + GetResStrW( (instance), (id) \ ,resourceTitleBuffer, MAX_LINE_LENGTH \ ,deftext ) diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index f232ff3..347d214 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -220,6 +220,74 @@ HRESULT PathAddBackslashEx(LPTSTR ptzPath, size_t cchPath) } +// +// PathAddBackslashEx +// +// Checked version of PathAddBackslash which also handles quoted paths +// +// Return values: S_OK - backslash appended +// S_FALSE - path already ended with a backslash +// E_OUTOFMEMORY - buffer too small +// E_FAIL - other failure (invalid input string) +// +HRESULT PathAddBackslashExA(LPSTR pszPath, size_t cchPath) +{ + ASSERT(cchPath <= STRSAFE_MAX_CCH); + ASSERT(nullptr != pszPath); ASSERT(0 != cchPath); + + HRESULT hr = E_FAIL; + size_t cchCurrentLength = 0; + + if (SUCCEEDED(StringCchLengthA(pszPath, cchPath, &cchCurrentLength))) + { + bool bHasQuote = false; + LPSTR ptzEnd = pszPath + cchCurrentLength; + + if ((ptzEnd > pszPath) && (*(ptzEnd-1) == _T('\"'))) + { + --ptzEnd; + bHasQuote = true; + } + + if (ptzEnd > pszPath) + { + if (*(ptzEnd-1) != _T('\\')) + { + if (cchPath - cchCurrentLength > 1) + { + if (bHasQuote) + { + *(ptzEnd+1) = *ptzEnd; + } + + *ptzEnd = _T('\\'); + + if (bHasQuote) + { + ++ptzEnd; + } + + ASSERT((size_t)(ptzEnd - pszPath) < cchPath); + *(ptzEnd+1) = _T('\0'); + + hr = S_OK; + } + else + { + hr = E_OUTOFMEMORY; + } + } + else + { + hr = S_FALSE; + } + } + } + + return hr; +} + + // // GetSystemString // @@ -298,7 +366,7 @@ bool LSGetModuleFileName(HINSTANCE hInst, LPTSTR pszBuffer, DWORD cchBuffer) // GetModuleFileName doesn't null-terminate the buffer if it is too // small. Make sure that even in this error case the buffer is properly // terminated - some people don't check return values. - pszBuffer[cchBuffer-1] = '\0'; + pszBuffer[cchBuffer-1] = L'\0'; } else if (cchCopied > 0 && cchCopied < cchBuffer) { @@ -309,6 +377,66 @@ bool LSGetModuleFileName(HINSTANCE hInst, LPTSTR pszBuffer, DWORD cchBuffer) } +// +// LSGetModuleFileNameEx +// +// Wrapper around GetModuleFileNameEx, dealing with that it moved from +// psapi to Kernel32 with Windows 7. +// +DWORD LSGetModuleFileNameEx(HANDLE hProcess, HMODULE hModule, LPTSTR pszBuffer, DWORD cchBuffer) +{ + typedef DWORD(WINAPI * GetModuleProc)(HANDLE hProcess, HMODULE hModule, LPTSTR pszBuffer, DWORD cchBuffer); + static GetModuleProc proc = nullptr; + + if (proc == nullptr) + { + proc = (GetModuleProc)GetProcAddress(GetModuleHandle(_T("Kernel32.dll")), "K32GetModuleFileNameExW"); + if (proc == nullptr) + { + // Try pre Windows 7 + proc = (GetModuleProc)GetProcAddress(LoadLibrary(_T("Psapi.dll")), "GetModuleFileNameExW"); + } + } + + if (proc) + { + return proc(hProcess, hModule, pszBuffer, cchBuffer); + } + + return 0; +} + + +// +// LSGetProcessImageFileName +// +// Wrapper around GetProcessImageFileName, dealing with that it moved from +// psapi to Kernel32 with Windows 7. +// +DWORD LSGetProcessImageFileName(HANDLE hProcess, LPTSTR pszBuffer, DWORD cchBuffer) +{ + typedef DWORD(WINAPI * GetImageNameProc)(HANDLE hProcess, LPTSTR pszBuffer, DWORD cchBuffer); + static GetImageNameProc proc = nullptr; + + if (proc == nullptr) + { + proc = (GetImageNameProc)GetProcAddress(GetModuleHandle(_T("Kernel32.dll")), "K32GetProcessImageFileNameW"); + if (proc == nullptr) + { + // Try pre Windows 7 + proc = (GetImageNameProc)GetProcAddress(LoadLibrary(_T("Psapi.dll")), "GetProcessImageFileNameW"); + } + } + + if (proc) + { + return proc(hProcess, pszBuffer, cchBuffer); + } + + return 0; +} + + // // TryAllowSetForegroundWindow // Calls AllowSetForegroundWindow on platforms that support it @@ -353,20 +481,15 @@ HRESULT TryAllowSetForegroundWindow(HWND hWnd) // bool IsVistaOrAbove() { - bool bVistaOrAbove = false; - - OSVERSIONINFO ovi = { 0 }; + OSVERSIONINFOEX ovi = { 0 }; ovi.dwOSVersionInfoSize = sizeof(ovi); - - VERIFY(GetVersionEx(&ovi)); - - if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && - ovi.dwMajorVersion >= 6) - { - bVistaOrAbove = true; - } - - return bVistaOrAbove; + ovi.dwMajorVersion = 6; + ovi.dwPlatformId = VER_PLATFORM_WIN32_NT; + + ULONGLONG uConditionMask = 0; + uConditionMask = VerSetConditionMask(uConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + uConditionMask = VerSetConditionMask(uConditionMask, VER_PLATFORMID, VER_EQUAL); + return VerifyVersionInfo(&ovi, VER_MAJORVERSION | VER_PLATFORMID, uConditionMask) != FALSE; } @@ -376,7 +499,7 @@ bool IsVistaOrAbove() void LSShutdownDialog(HWND hWnd) { FARPROC fnProc = GetProcAddress( - GetModuleHandle("SHELL32.DLL"), (LPCSTR)((long)0x003C)); + GetModuleHandleW(L"SHELL32.DLL"), (LPCSTR)((long)0x003C)); if (fnProc) { @@ -405,7 +528,7 @@ void LSShutdownDialog(HWND hWnd) (GetAsyncKeyState(VK_CONTROL) & 0x8000) && (GetAsyncKeyState(VK_MENU) & 0x8000)) { - PostQuitMessage(1); + PostQuitMessage(LRV_SHUTDOWN_DLG); } } } @@ -415,7 +538,7 @@ void LSShutdownDialog(HWND hWnd) // LSPlaySystemSound // Wrapper around PlaySound to play system event sounds // -BOOL LSPlaySystemSound(LPCTSTR pszSoundAlias) +BOOL LSPlaySystemSound(LPCWSTR pwzSoundAlias) { BOOL bResult = FALSE; @@ -424,15 +547,10 @@ BOOL LSPlaySystemSound(LPCTSTR pszSoundAlias) if (hWinMM) { - typedef BOOL (WINAPI* PlaySoundProc)(LPCTSTR, HMODULE, DWORD); + typedef BOOL (WINAPI* PlaySoundProc)(LPCWSTR, HMODULE, DWORD); -#if defined(UNICODE) PlaySoundProc fnPlaySound = (PlaySoundProc) GetProcAddress(hWinMM, "PlaySoundW"); -#else - PlaySoundProc fnPlaySound = (PlaySoundProc) - GetProcAddress(hWinMM, "PlaySoundA"); -#endif if (fnPlaySound) { @@ -449,7 +567,7 @@ BOOL LSPlaySystemSound(LPCTSTR pszSoundAlias) dwFlags |= SND_SYSTEM; } - bResult = fnPlaySound(pszSoundAlias, NULL, dwFlags); + bResult = fnPlaySound(pwzSoundAlias, NULL, dwFlags); } VERIFY(FreeLibrary(hWinMM)); @@ -540,12 +658,12 @@ HANDLE LSCreateThread(LPCSTR pszName, LPTHREAD_START_ROUTINE fnStartAddres, // GetVersionMetric // Helper for GetWindowsVersion // -enum WINVER_METRIC +enum class WINVER_METRIC { - WVM_ANY, - WVM_SERVER, - WVM_WORKSTATION, - WVM_HOMESERVER + ANY, + SERVER, + WORKSTATION, + HOMESERVER }; @@ -553,35 +671,64 @@ BOOL GetVersionMetric(WINVER_METRIC metric) { // NB: OSVERSIONINFOEX is not supported on very early platforms but // those don't require such a "metric" - OSVERSIONINFOEX ovi = { 0 }; + OSVERSIONINFOEXW ovi = { 0 }; ovi.dwOSVersionInfoSize = sizeof(ovi); - - if (GetVersionEx((LPOSVERSIONINFO)&ovi)) + + ULONGLONG dwlConditionMask = 0; + + switch (metric) { - switch (metric) - { - case WVM_ANY: + case WINVER_METRIC::ANY: return TRUE; - case WVM_SERVER: - return (ovi.wProductType != VER_NT_WORKSTATION); + case WINVER_METRIC::SERVER: + ovi.wProductType = VER_NT_WORKSTATION; + dwlConditionMask = VerSetConditionMask(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL); + return VerifyVersionInfoW(&ovi, VER_PRODUCT_TYPE, dwlConditionMask) == FALSE; - case WVM_WORKSTATION: - return (ovi.wProductType == VER_NT_WORKSTATION); + case WINVER_METRIC::WORKSTATION: + ovi.wProductType = VER_NT_WORKSTATION; + dwlConditionMask = VerSetConditionMask(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL); + return VerifyVersionInfoW(&ovi, VER_PRODUCT_TYPE, dwlConditionMask) != FALSE; - case WVM_HOMESERVER: - return (ovi.wSuiteMask == VER_SUITE_WH_SERVER); + case WINVER_METRIC::HOMESERVER: + ovi.wSuiteMask = VER_SUITE_WH_SERVER; + dwlConditionMask = VerSetConditionMask(dwlConditionMask, VER_SUITENAME, VER_EQUAL); + return VerifyVersionInfoW(&ovi, VER_SUITENAME, dwlConditionMask) != FALSE; default: ASSERT(false); break; - } } return FALSE; } +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// IsWindowsVersionOrGreater +// +// Taken from VersionHelpers.h +// +bool IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) +{ + OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; + DWORDLONG const dwlConditionMask = VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask( + 0, VER_MAJORVERSION, VER_GREATER_EQUAL), + VER_MINORVERSION, VER_GREATER_EQUAL), + VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + + osvi.dwMajorVersion = wMajorVersion; + osvi.dwMinorVersion = wMinorVersion; + osvi.wServicePackMajor = wServicePackMajor; + + return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; +} + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // GetWindowsVersion @@ -589,62 +736,45 @@ BOOL GetVersionMetric(WINVER_METRIC metric) UINT GetWindowsVersion() { UINT uVersion = WINVER_UNKNOWN; - - OSVERSIONINFO ovi = { 0 }; - ovi.dwOSVersionInfoSize = sizeof(ovi); - GetVersionEx(&ovi); - - if (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + + struct VerStringTable { - if (ovi.dwMinorVersion >= 90) - { - uVersion = WINVER_WIN95; - } - else if (ovi.dwMinorVersion >= 10) - { - uVersion = WINVER_WIN98; - } - else - { - uVersion = WINVER_WINME; - } + WORD dwMajor; + WORD dwMinor; + WINVER_METRIC metric; + UINT uVersion; } - else + versions[] = \ { - struct VerStringTable - { - DWORD dwMajor; - DWORD dwMinor; - WINVER_METRIC metric; - UINT uVersion; - } - versions[] = \ - { - { 4, 0, WVM_ANY, WINVER_WINNT4 }, - { 5, 0, WVM_ANY, WINVER_WIN2000 }, - { 5, 1, WVM_ANY, WINVER_WINXP }, // 32-Bit + { 6, 3, WINVER_METRIC::SERVER, WINVER_WIN2012R2 }, + { 6, 3, WINVER_METRIC::WORKSTATION, WINVER_WIN81 }, + + { 6, 2, WINVER_METRIC::SERVER, WINVER_WIN2012 }, + { 6, 2, WINVER_METRIC::WORKSTATION, WINVER_WIN8 }, - // WVM_HOMESERVER should also match WVM_SERVER, so list it first - { 5, 2, WVM_HOMESERVER, WINVER_WHS }, - { 5, 2, WVM_SERVER, WINVER_WIN2003 }, - { 5, 2, WVM_WORKSTATION, WINVER_WINXP }, // 64-Bit + { 6, 1, WINVER_METRIC::SERVER, WINVER_WIN2008R2 }, + { 6, 1, WINVER_METRIC::WORKSTATION, WINVER_WIN7 }, + + { 6, 0, WINVER_METRIC::SERVER, WINVER_WIN2008 }, + { 6, 0, WINVER_METRIC::WORKSTATION, WINVER_VISTA }, - { 6, 0, WVM_WORKSTATION, WINVER_VISTA }, - { 6, 0, WVM_SERVER, WINVER_WIN2008 }, - { 6, 1, WVM_ANY, WINVER_WIN7 }, - { 6, 2, WVM_SERVER, WINVER_WIN2012 }, - { 6, 2, WVM_ANY, WINVER_WIN8 } - }; + // WVM_HOMESERVER should also match WVM_SERVER, so list it first + { 5, 2, WINVER_METRIC::HOMESERVER, WINVER_WHS }, + { 5, 2, WINVER_METRIC::SERVER, WINVER_WIN2003 }, + { 5, 2, WINVER_METRIC::WORKSTATION, WINVER_WINXP }, // 64-Bit + + { 5, 1, WINVER_METRIC::ANY, WINVER_WINXP }, // 32-Bit + { 5, 0, WINVER_METRIC::ANY, WINVER_WIN2000 }, + { 4, 0, WINVER_METRIC::ANY, WINVER_WINNT4 } + }; - for (size_t idx = 0; idx < COUNTOF(versions); ++idx) + for (VerStringTable &version : versions) + { + if (IsWindowsVersionOrGreater(version.dwMajor, version.dwMinor, 0) && + GetVersionMetric(version.metric)) { - if (versions[idx].dwMajor == ovi.dwMajorVersion && - versions[idx].dwMinor == ovi.dwMinorVersion && - GetVersionMetric(versions[idx].metric)) - { - uVersion = versions[idx].uVersion; - break; - } + uVersion = version.uVersion; + break; } } @@ -658,6 +788,7 @@ UINT GetWindowsVersion() // BOOL LSDisableWow64FsRedirection(PVOID* ppvOldValue) { +#ifndef _WIN64 typedef BOOL (WINAPI* Wow64DisableWow64FsRedirectionProc)(PVOID*); HMODULE hKernel32 = GetModuleHandle(_T("kernel32.dll")); @@ -674,6 +805,10 @@ BOOL LSDisableWow64FsRedirection(PVOID* ppvOldValue) } return bResult; +#else + UNREFERENCED_PARAMETER(ppvOldValue); + return TRUE; +#endif } @@ -683,6 +818,7 @@ BOOL LSDisableWow64FsRedirection(PVOID* ppvOldValue) // BOOL LSRevertWow64FsRedirection(PVOID pvOldValue) { +#ifndef _WIN64 typedef BOOL (WINAPI* Wow64RevertWow64FsRedirectionProc)(PVOID); HMODULE hKernel32 = GetModuleHandle(_T("kernel32.dll")); @@ -699,6 +835,10 @@ BOOL LSRevertWow64FsRedirection(PVOID pvOldValue) } return bResult; +#else + UNREFERENCED_PARAMETER(pvOldValue); + return TRUE; +#endif } @@ -706,12 +846,12 @@ BOOL LSRevertWow64FsRedirection(PVOID pvOldValue) // // LSShellExecuteEx // -BOOL LSShellExecuteEx(LPSHELLEXECUTEINFO lpExecInfo) +BOOL LSShellExecuteEx(LPSHELLEXECUTEINFOW lpExecInfo) { - PVOID pvOldValue = NULL; + PVOID pvOldValue = nullptr; LSDisableWow64FsRedirection(&pvOldValue); - BOOL bReturn = ShellExecuteEx(lpExecInfo); + BOOL bReturn = ShellExecuteExW(lpExecInfo); LSRevertWow64FsRedirection(pvOldValue); return bReturn; @@ -722,13 +862,13 @@ BOOL LSShellExecuteEx(LPSHELLEXECUTEINFO lpExecInfo) // // LSShellExecuteA // -HINSTANCE LSShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, - LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShow) +HINSTANCE LSShellExecute(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, + LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShow) { - PVOID pvOldValue = NULL; + PVOID pvOldValue = nullptr; LSDisableWow64FsRedirection(&pvOldValue); - - HINSTANCE hinstResult = ShellExecute( + + HINSTANCE hinstResult = ShellExecuteW( hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShow); LSRevertWow64FsRedirection(pvOldValue); @@ -801,7 +941,7 @@ HANDLE LSActivateActCtxForClsid(REFCLSID rclsid, PULONG_PTR pulCookie) TCHAR szSubkey[MAX_PATH] = { 0 }; HRESULT hr = StringCchPrintf(szSubkey, COUNTOF(szSubkey), - _T("CLSID\\%s\\InProcServer32"), szCLSID); + _T("CLSID\\%ls\\InProcServer32"), szCLSID); if (SUCCEEDED(hr)) { @@ -854,3 +994,24 @@ void LSDeactivateActCtx(HANDLE hActCtx, ULONG_PTR* pulCookie) } } } + + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// DescriptionFromHR +// Retrives a description of a HRESULT error code. +// +HRESULT DescriptionFromHR(HRESULT hr, LPWSTR buf, size_t cchBuf) { + if (FACILITY_WINDOWS == HRESULT_FACILITY(hr)) + { + hr = HRESULT_CODE(hr); + } + + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, DWORD(cchBuf), nullptr) == 0) + { + return StringCchPrintfW(buf, cchBuf, L"Unknown error, 0x%.8X", hr); + } + + return S_OK; +} diff --git a/utility/shellhlp.h b/utility/shellhlp.h index 4aaec21..06c957f 100644 --- a/utility/shellhlp.h +++ b/utility/shellhlp.h @@ -38,12 +38,16 @@ bool GetShellFolderPath(int nFolder, LPTSTR ptzPath, size_t cchPath); bool GetSystemString(DWORD dwCode, LPTSTR ptzBuffer, DWORD cchBuffer); HRESULT PathAddBackslashEx(LPTSTR ptzPath, size_t cchPath); +HRESULT PathAddBackslashExA(LPSTR pszPath, size_t cchPath); HRESULT CLSIDToString(REFCLSID rclsid, LPTSTR ptzBuffer, size_t cchBuffer); bool LSGetModuleFileName(HINSTANCE hInst, LPTSTR pszBuffer, DWORD cchBuffer); +DWORD LSGetModuleFileNameEx(HANDLE hProcess, HMODULE hModule, + LPTSTR pszBuffer, DWORD cchBuffer); +DWORD LSGetProcessImageFileName(HANDLE hProcess, LPTSTR pszBuffer, DWORD cchBuffer); HRESULT TryAllowSetForegroundWindow(HWND hWnd); bool IsVistaOrAbove(); void LSShutdownDialog(HWND hWnd); -BOOL LSPlaySystemSound(LPCTSTR pszSoundAlias); +BOOL LSPlaySystemSound(LPCWSTR pwzSoundAlias); HANDLE LSCreateThread(LPCSTR pszName, LPTHREAD_START_ROUTINE fnStartAddres, LPVOID lpParameter, LPDWORD pdwThreadId); @@ -55,9 +59,9 @@ HANDLE LSCreateThread(LPCSTR pszName, LPTHREAD_START_ROUTINE fnStartAddres, BOOL LSDisableWow64FsRedirection(PVOID* ppvOldValue); BOOL LSRevertWow64FsRedirection(PVOID pvOldValue); -BOOL LSShellExecuteEx(LPSHELLEXECUTEINFO lpExecInfo); -HINSTANCE LSShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, - LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShow); +BOOL LSShellExecuteEx(LPSHELLEXECUTEINFOW lpExecInfo); +HINSTANCE LSShellExecute(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, + LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShow); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -69,6 +73,18 @@ HANDLE LSActivateActCtxForClsid(REFCLSID rclsid, PULONG_PTR pulCookie); void LSDeactivateActCtx(HANDLE hActCtx, ULONG_PTR* pulCookie); +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// LiteStep Return Values (LRV) +// +#define LRV_NO_APP_PATH -1 +#define LRV_OK 0 // is also S_OK from WinError +#define LRV_SHUTDOWN_DLG 1 +#define LRV_NO_STEP 2 +#define LRV_LSAPI_FAIL 3 +#define LRV_EXPLORER_START 4 + + //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // // Windows Versions @@ -78,23 +94,26 @@ UINT GetWindowsVersion(); #define WINVER_UNKNOWN (UINT)-1 // Win9x -#define WINVER_WIN95 1 -#define WINVER_WIN98 2 -#define WINVER_WINME 3 +#define WINVER_WIN95 1 +#define WINVER_WIN98 2 +#define WINVER_WINME 3 // Windows NT Workstation -#define WINVER_WINNT4 4 -#define WINVER_WIN2000 5 -#define WINVER_WINXP 6 -#define WINVER_VISTA 7 -#define WINVER_WIN7 8 -#define WINVER_WIN8 9 +#define WINVER_WINNT4 4 +#define WINVER_WIN2000 5 +#define WINVER_WINXP 6 +#define WINVER_VISTA 7 +#define WINVER_WIN7 8 +#define WINVER_WIN8 9 +#define WINVER_WIN81 10 // Windows NT Server -#define WINVER_WIN2003 10 -#define WINVER_WHS 11 -#define WINVER_WIN2008 12 -#define WINVER_WIN2012 13 +#define WINVER_WIN2003 11 +#define WINVER_WHS 12 +#define WINVER_WIN2008 13 +#define WINVER_WIN2008R2 14 +#define WINVER_WIN2012 15 +#define WINVER_WIN2012R2 16 //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -107,4 +126,6 @@ inline HRESULT HrGetLastError() return HRESULT_FROM_WIN32(GetLastError()); } +HRESULT DescriptionFromHR(HRESULT hr, LPWSTR buf, size_t cchBuf); + #endif // SHELLHLP_H diff --git a/utility/stringutility.cpp b/utility/stringutility.cpp new file mode 100644 index 0000000..22eca9b --- /dev/null +++ b/utility/stringutility.cpp @@ -0,0 +1,55 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1997-2013 LiteStep Development 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 "stringutility.h" +#include "common.h" + + +// +// WCSFromMBS +// +wchar_t *WCSFromMBS(const char *pszMBS) +{ + if (pszMBS != nullptr) + { + size_t nLen = strlen(pszMBS) + 1; + wchar_t *pwzWCS = new wchar_t[nLen]; + MultiByteToWideChar(CP_ACP, 0, pszMBS, -1, pwzWCS, (int)nLen); + return pwzWCS; + } + return nullptr; +} + + +// +// MBSFromWCS +// +char *MBSFromWCS(const wchar_t *pwzWCS) +{ + if (nullptr != pwzWCS) + { + size_t nLen = wcslen(pwzWCS) + 1; + char *pszMBS = new char[nLen]; + WideCharToMultiByte(CP_ACP, 0, pwzWCS, -1, pszMBS, (int)nLen, "?", nullptr); + return pszMBS; + } + return nullptr; +} diff --git a/utility/stringutility.h b/utility/stringutility.h index 1008d5e..1bac6bd 100644 --- a/utility/stringutility.h +++ b/utility/stringutility.h @@ -23,7 +23,9 @@ #define STRINGUTILITY_H #include -#include // for _stricmp/strcmp +#include // for _wcsicmp/wcscmp +#include + // // stringicmp @@ -32,9 +34,9 @@ // struct stringicmp { - bool operator()(const std::string &s1, const std::string &s2) const + bool operator()(const std::wstring &s1, const std::wstring &s2) const { - return (_stricmp(s1.c_str(), s2.c_str()) < 0); + return (_wcsicmp(s1.c_str(), s2.c_str()) < 0); } }; @@ -46,11 +48,20 @@ struct stringicmp // struct stringcmp { - bool operator()(const std::string &s1, const std::string &s2) const + bool operator()(const std::wstring &s1, const std::wstring &s2) const { - return (strcmp(s1.c_str(), s2.c_str()) < 0); + return (wcscmp(s1.c_str(), s2.c_str()) < 0); } }; +// +// Quick conversion +// +wchar_t *WCSFromMBS(const char *pszMBS); +char *MBSFromWCS(const wchar_t *pwzWCS); + +#define WCSTOMBS(str) std::unique_ptr(MBSFromWCS(str)).get() +#define MBSTOWCS(str) std::unique_ptr(WCSFromMBS(str)).get() + #endif // STRINGUTILITY_H diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index 911e2e1..6936f89 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -1,211 +1,214 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - utility - {2213036F-018C-416A-8A6A-7934C936CFFC} - utility - Win32Proj - $(VCTargetsPath11) - - - - StaticLibrary - MultiByte - true - v110 - - - StaticLibrary - MultiByte - true - v110 - - - StaticLibrary - MultiByte - v110 - - - StaticLibrary - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC11_32\ - Debug_VC11_32\ - ../Release_VC11_32\ - Release_VC11_32\ - - - ../Debug_VC11_64\ - Debug_VC11_64\ - - - ../Release_VC11_64\ - Release_VC11_64\ - - - - /wd4201 %(AdditionalOptions) - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - true - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - false - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - true - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - StreamingSIMDExtensions2 - true - true - - - Level4 - false - - - Default - true - true - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - true - - - $(OutDir)utility.lib - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + utility + {2213036F-018C-416A-8A6A-7934C936CFFC} + utility + Win32Proj + $(VCTargetsPath11) + + + + StaticLibrary + Unicode + true + v110_xp + + + StaticLibrary + Unicode + true + v110_xp + + + StaticLibrary + Unicode + v110_xp + + + StaticLibrary + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC11_32\ + Debug_VC11_32\ + ../Release_VC11_32\ + Release_VC11_32\ + + + ../Debug_VC11_64\ + Debug_VC11_64\ + + + ../Release_VC11_64\ + Release_VC11_64\ + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions2 + true + true + + + Level4 + false + + + Default + true + true + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + MaxSpeed + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + true + true + + + $(OutDir)utility.lib + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utility/utility_vc10.vcxproj b/utility/utility_vc12.vcxproj similarity index 79% rename from utility/utility_vc10.vcxproj rename to utility/utility_vc12.vcxproj index fb9a84a..b60dd80 100644 --- a/utility/utility_vc10.vcxproj +++ b/utility/utility_vc12.vcxproj @@ -1,197 +1,214 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - utility - {2213036F-018C-416A-8A6A-7934C936CFFC} - utility - Win32Proj - - - - StaticLibrary - MultiByte - true - - - StaticLibrary - MultiByte - true - - - StaticLibrary - MultiByte - - - StaticLibrary - MultiByte - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ../Debug_VC10_32\ - ../Debug_VC10_64\ - Debug_VC10_32\ - Debug_VC10_64\ - ../Release_VC10_32\ - ../Release_VC10_64\ - Release_VC10_32\ - Release_VC10_64\ - - - - /wd4201 %(AdditionalOptions) - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - EditAndContinue - Default - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - EnableFastChecks - true - MultiThreadedDebugDLL - true - true - - - Level4 - false - ProgramDatabase - Default - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - - - $(OutDir)utility.lib - - - - - /wd4201 %(AdditionalOptions) - MaxSpeed - AnySuitable - Speed - true - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;%(PreprocessorDefinitions) - true - MultiThreadedDLL - true - NotSet - true - true - - - Level4 - false - - - Default - true - - - $(OutDir)utility.lib - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + utility + {2213036F-018C-416A-8A6A-7934C936CFFC} + utility + Win32Proj + $(VCTargetsPath11) + + + + StaticLibrary + Unicode + true + v120_xp + + + StaticLibrary + Unicode + true + v120_xp + + + StaticLibrary + Unicode + v120_xp + + + StaticLibrary + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ../Debug_VC12_32\ + Debug_VC12_32\ + ../Release_VC12_32\ + Release_VC12_32\ + + + ../Debug_VC12_64\ + Debug_VC12_64\ + + + ../Release_VC12_64\ + Release_VC12_64\ + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + true + MultiThreadedDebugDLL + true + true + + + Level4 + false + ProgramDatabase + Default + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions2 + true + true + + + Level4 + false + + + Default + true + true + true + + + $(OutDir)utility.lib + + + + + /wd4201 %(AdditionalOptions) + Full + AnySuitable + Speed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + NotSet + true + true + + + Level4 + false + + + Default + true + true + true + + + $(OutDir)utility.lib + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/utility/utility_vc71.vcproj b/utility/utility_vc71.vcproj deleted file mode 100644 index f80495c..0000000 --- a/utility/utility_vc71.vcproj +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utility/utility_vc8.vcproj b/utility/utility_vc8.vcproj deleted file mode 100644 index a07989e..0000000 --- a/utility/utility_vc8.vcproj +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utility/utility_vc9.vcproj b/utility/utility_vc9.vcproj deleted file mode 100644 index 8eb1854..0000000 --- a/utility/utility_vc9.vcproj +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 6e038b7cf3b2d8e2ea858d43532eade6f612f837 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 6 Aug 2013 14:00:10 -0700 Subject: [PATCH 49/50] Sync from CVS --- docs/changes.txt | 13 +- litestep/COMFactory.cpp | 166 +++++++ litestep/COMFactory.h | 56 +++ litestep/COMService.cpp | 117 +++++ litestep/COMService.h | 53 ++ litestep/DesktopWallpaper.cpp | 642 +++++++++++++++++++++++++ litestep/DesktopWallpaper.h | 87 ++++ litestep/FullscreenMonitor.cpp | 5 + litestep/IDesktopWallpaper.h | 84 ++++ litestep/IDesktopWallpaperPrivate.h | 45 ++ litestep/Module.cpp | 27 +- litestep/TrayNotifyIcon.h | 6 +- litestep/litestep.cpp | 21 +- litestep/litestep_vc11.vcxproj | 13 +- litestep/litestep_vc12.vcxproj | 8 + litestep/litestep_vc12.vcxproj.filters | 110 +++++ lsapi/lsapi.cpp | 2 +- lsapi/lsapi_vc11.vcxproj | 6 +- lsapi/settings.cpp | 18 +- utility/shellhlp.cpp | 30 ++ utility/shellhlp.h | 1 + utility/utility_vc11.vcxproj | 6 +- 22 files changed, 1486 insertions(+), 30 deletions(-) create mode 100644 litestep/COMFactory.cpp create mode 100644 litestep/COMFactory.h create mode 100644 litestep/COMService.cpp create mode 100644 litestep/COMService.h create mode 100644 litestep/DesktopWallpaper.cpp create mode 100644 litestep/DesktopWallpaper.h create mode 100644 litestep/IDesktopWallpaper.h create mode 100644 litestep/IDesktopWallpaperPrivate.h create mode 100644 litestep/litestep_vc12.vcxproj.filters diff --git a/docs/changes.txt b/docs/changes.txt index 8e25a9e..9dd238b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -1,6 +1,6 @@ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= LiteStep 0.25.0 Alpha - Experimental Build 2013-08-03 + Experimental Build 2013-08-04 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= This build requires the Visual C++ 2012 Redistributable Package @@ -49,6 +49,17 @@ This build is the current state of that code. The following lists the changes between nightly builds. See the next section for a cumulative changelog since 0.24.8. + - [2013-08-??] - + - Added GetRCInt64. + - Fixed Right Click -> Set as desktop background on Windows 8. + - Fixed the color and appearance dialog on Windows 8. + - Fixed the desktop background dialog on Windows 8. + + - [2013-08-04] - + - Fixed the A versions of GetRCString, Line, and so on writing to the entire + buffer, causing crashes in modules which do not specify their buffer sizes + correctly. + - [2013-08-03] - - Fixed crash with recursive includes. - Fixed LiteStep not loading on Windows XP. diff --git a/litestep/COMFactory.cpp b/litestep/COMFactory.cpp new file mode 100644 index 0000000..a803015 --- /dev/null +++ b/litestep/COMFactory.cpp @@ -0,0 +1,166 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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 "../utility/common.h" +#include "../utility/debug.hpp" +#include "../utility/shellhlp.h" +#include "COMFactory.h" +#include "DesktopWallpaper.h" +#include + + +// +// COMFactory +// +COMFactory::COMFactory() +{ + m_uRefCount = 1; +} + + +// +// ~COMFactory +// +COMFactory::~COMFactory() +{ +} + + +// +// IUnknown::AddRef +// Increments the reference count for an interface on an object. +// +ULONG COMFactory::AddRef() +{ + return InterlockedIncrement(&m_uRefCount); +} + + +// +// IUnknown::Release +// Decrements the reference count for an interface on an object. +// +ULONG COMFactory::Release() +{ + if (InterlockedDecrement(&m_uRefCount) == 0) + { + delete this; + return 0; + } + + return m_uRefCount; +} + + +// +// IUnknown::QueryInterface +// Retrieves pointers to the supported interfaces on an object. +// +HRESULT COMFactory::QueryInterface(REFIID riid, void **ppvObject) +{ + if (ppvObject == nullptr) + { + return E_POINTER; + } + + if (riid == IID_IUnknown) + { + *ppvObject = (IUnknown*)this; + } + else if (riid == IID_IClassFactory) + { + *ppvObject = (IClassFactory*)this; + } + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + + +// +// IClassFactory::CreateInstance +// Creates an instance of the specified objet +// +HRESULT COMFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) +{ + if (ppvObject == nullptr) + { + return E_POINTER; + } + + // TODO::Aggregate? + if (pUnkOuter != nullptr) + { + return CLASS_E_NOAGGREGATION; + } + + if (riid == IID_IUnknown) + { + *ppvObject = (IUnknown*)(new DesktopWallpaper()); + } + else if (riid == IID_IDesktopWallpaper) + { + *ppvObject = (IDesktopWallpaper*)(new DesktopWallpaper()); + } + else if (riid == IID_IDesktopWallpaperPrivate) + { + *ppvObject = (IDesktopWallpaperPrivate*)(new DesktopWallpaper()); + } + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + // We failed to create the object. + if (*ppvObject == nullptr) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + + +// +// IClassFactory::LockServer +// +// +HRESULT COMFactory::LockServer(BOOL) +{ + return E_NOTIMPL; +} + + +// +// IClassFactory::IsLocked +// +// +bool COMFactory::IsLocked() +{ + return false; +} diff --git a/litestep/COMFactory.h b/litestep/COMFactory.h new file mode 100644 index 0000000..07fdf56 --- /dev/null +++ b/litestep/COMFactory.h @@ -0,0 +1,56 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(COMFACTORY_H) +#define COMFACTORY_H + +#include "../utility/common.h" +#include + +class COMFactory : public IClassFactory +{ + // Constructor +public: + COMFactory(); + + // Destructor +private: + virtual ~COMFactory(); + +public: + // IUnknown + ULONG STDMETHODCALLTYPE AddRef(); + STDMETHOD(QueryInterface) (REFIID, void**); + ULONG STDMETHODCALLTYPE Release(); + + // IClassFactory + STDMETHOD(CreateInstance) (IUnknown*, REFIID, void**); + STDMETHOD(LockServer) (BOOL); + + // Utility + bool IsLocked(); + +private: + ULONG m_uRefCount; +}; + +#endif // COMFACTORY_H diff --git a/litestep/COMService.cpp b/litestep/COMService.cpp new file mode 100644 index 0000000..7486657 --- /dev/null +++ b/litestep/COMService.cpp @@ -0,0 +1,117 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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 "COMService.h" +#include "../utility/common.h" +#include +#include "IDesktopWallpaper.h" +#include "COMFactory.h" +#include "../utility/debug.hpp" + + +// +// COMService +// +COMService::COMService() +{ +} + + +// +// ~COMService +// +COMService::~COMService() +{ +} + + +// +// ThreadProc +// Protects COM objects from actions of modules (CoUninitialize...) +// +void COMService::ThreadProc() +{ + m_dwThreadID = GetCurrentThreadId(); + +#if defined(_DEBUG) + DbgSetCurrentThreadName("LS COM Service"); +#endif + + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + COMFactory *pFactory = new COMFactory(); + + // C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD + const GUID CLSID_DesktopWallpaper = { 0xC2CF3110, 0x460E, 0x4FC1, { 0xB9, 0xD0, 0x8A, 0x1C, 0x0C, 0x9C, 0xC4, 0xBD } }; + + DWORD dwFactoryCookie; + CoRegisterClassObject(CLSID_DesktopWallpaper, pFactory, + CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwFactoryCookie); + + MSG msg; + while (GetMessage(&msg, nullptr, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + CoRevokeClassObject(dwFactoryCookie); + + pFactory->Release(); + + CoUninitialize(); +} + + +// +// IService::Start +// +HRESULT COMService::Start() +{ + m_COMThread = std::thread(std::bind(&COMService::ThreadProc, this)); + + return S_OK; +} + + +// +// IService::Start +// +HRESULT COMService::Stop() +{ + // Switch to this if we ever drop XP support, using m_dwThreadID leads to a possible race condition + //PostThreadMessage(GetThreadId(m_COMThread.native_handle()), WM_QUIT, 0, 0); + PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); + + m_COMThread.join(); + + return S_OK; +} + + +// +// IService::Start +// +HRESULT COMService::Recycle() +{ + return S_OK; +} diff --git a/litestep/COMService.h b/litestep/COMService.h new file mode 100644 index 0000000..1378c54 --- /dev/null +++ b/litestep/COMService.h @@ -0,0 +1,53 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(COMSERVICE_H) +#define COMSERVICE_H + +#include "../utility/IService.h" +#include "COMFactory.h" +#include + +class COMService : public IService +{ +public: + COMService(); + ~COMService(); + + // IService +public: + HRESULT Start() override; + HRESULT Stop() override; + HRESULT Recycle() override; + +private: + void ThreadProc(); + +private: + // COM worker thread + std::thread m_COMThread; + + // Necesary since XP does not support GetThreadId + DWORD m_dwThreadID; +}; + +#endif // COMSERVICE_H diff --git a/litestep/DesktopWallpaper.cpp b/litestep/DesktopWallpaper.cpp new file mode 100644 index 0000000..e75d9d4 --- /dev/null +++ b/litestep/DesktopWallpaper.cpp @@ -0,0 +1,642 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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 "../utility/common.h" +#include "DesktopWallpaper.h" +#include +#include "../utility/shellhlp.h" + + +// +// DesktopWallpaper +// +DesktopWallpaper::DesktopWallpaper() +{ + m_uRefCount = 1; + EnumDisplayMonitors(nullptr, nullptr, [] (HMONITOR hMonitor, HDC, LPRECT rect, LPARAM lParam) -> BOOL + { + DesktopWallpaper* self = (DesktopWallpaper*)lParam; + + MONITORINFOEXW monitorInfoEx; + ZeroMemory(&monitorInfoEx, sizeof(MONITORINFOEXW)); + monitorInfoEx.cbSize = sizeof(MONITORINFOEXW); + GetMonitorInfoW(hMonitor, &monitorInfoEx); + + MonitorData data; + data.rRect = *rect; + data.uNumber = UINT(self->m_vMonitors.size() + 1); + StringCchCopyW(data.wzDeviceString, _countof(data.wzDeviceString), monitorInfoEx.szDevice); + + self->m_vMonitors.push_back(data); + + return TRUE; + + }, (LPARAM)this); +} + + +// +// ~DesktopWallpaper +// +DesktopWallpaper::~DesktopWallpaper() +{ +} + + +// +// IUnknown::AddRef +// Increments the reference count for an interface on an object. +// +ULONG DesktopWallpaper::AddRef() +{ + return InterlockedIncrement(&m_uRefCount); +} + + +// +// IUnknown::Release +// Decrements the reference count for an interface on an object. +// +ULONG DesktopWallpaper::Release() +{ + if (InterlockedDecrement(&m_uRefCount) == 0) + { + delete this; + return 0; + } + + return m_uRefCount; +} + + +// +// IUnknown::QueryInterface +// Retrieves pointers to the supported interfaces on an object. +// +HRESULT DesktopWallpaper::QueryInterface(REFIID riid, void **ppvObject) +{ + if (ppvObject == nullptr) + { + return E_POINTER; + } + + if (riid == IID_IUnknown) + { + *ppvObject = (IUnknown*)this; + } + else if (riid == IID_IDesktopWallpaper) + { + *ppvObject = (IDesktopWallpaper*)this; + } + else if (riid == IID_IDesktopWallpaperPrivate) + { + *ppvObject = (IDesktopWallpaperPrivate*)this; + } + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + + +// +// IDesktopWallpaper::SetWallpaper +// Sets the desktop wallpaper for the specified monitor. +// +HRESULT DesktopWallpaper::SetWallpaper(LPCWSTR pwzMonitorID, LPCWSTR pwzWallpaper) +{ + if (pwzWallpaper == nullptr) + { + return E_INVALIDARG; + } + + if (!PathFileExistsW(pwzWallpaper)) + { + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } + + // TODO::Handle the case where this is not null + if (pwzMonitorID != nullptr) + { + // Find the monitor and apply the wallpaper to only that monitor + } + else + { + SHSetValue(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"Wallpaper", REG_SZ, + pwzWallpaper, (DWORD)wcslen(pwzWallpaper)*sizeof(pwzWallpaper[0])); + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0); + } + + return S_OK; +} + + +// +// IDesktopWallpaper::GetWallpaper +// Retrives the current wallpaper at the specified monitor +// +HRESULT DesktopWallpaper::GetWallpaper(LPCWSTR pwzMonitorID, LPWSTR* ppwzWallpaper) +{ + if (ppwzWallpaper == nullptr) + { + return E_POINTER; + } + + // TODO::Handle the case where this is not null + if (pwzMonitorID != nullptr) + { + } + else + { + // If we are displaying wallpapers per-monitor, or a slideshow is running... + + *ppwzWallpaper = (LPWSTR)CoTaskMemAlloc(MAX_PATH*sizeof(WCHAR)); + DWORD dwType = REG_SZ; + DWORD dwSize = MAX_PATH*sizeof(WCHAR); + SHGetValue(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"Wallpaper", &dwType, *ppwzWallpaper, &dwSize); + } + return S_OK; +} + + +// +// IDesktopWallpaper::GetMonitorDevicePathAt +// Retrives a string which uniquely identifies the specified monitor. +// +HRESULT DesktopWallpaper::GetMonitorDevicePathAt(UINT uMonitorIndex, LPWSTR* ppwzMonitorID) +{ + if (ppwzMonitorID == nullptr) + { + return E_POINTER; + } + + if (uMonitorIndex >= m_vMonitors.size()) + { + return E_INVALIDARG; + } + + SHStrDupW(m_vMonitors[uMonitorIndex].wzDeviceString, ppwzMonitorID); + + return S_OK; +} + + +// +// IDesktopWallpaper::GetMonitorDevicePathCount +// Retrives the number of monitors. +// +HRESULT DesktopWallpaper::GetMonitorDevicePathCount(LPUINT puCount) +{ + if (puCount == nullptr) + { + return E_POINTER; + } + + *puCount = UINT(m_vMonitors.size()); + + return S_OK; +} + + +// +// IDesktopWallpaper::GetMonitorRECT +// Retrives the rectangle of a particular monitor. +// +HRESULT DesktopWallpaper::GetMonitorRECT(LPCWSTR pwzMonitorID, tagRECT* pDisplayRect) +{ + if (pDisplayRect == nullptr) + { + return E_POINTER; + } + + if (pwzMonitorID == nullptr) + { + // This is what explorer returns in this case. + return 0x800706F4; + } + + for (MonitorData &monitor : m_vMonitors) + { + if (_wcsicmp(monitor.wzDeviceString, pwzMonitorID) == 0) + { + *pDisplayRect = monitor.rRect; + return S_OK; + } + } + + return E_INVALIDARG; +} + + +// +// IDesktopWallpaper::SetBackgroundColor +// Sets the desktop background color. +// +HRESULT DesktopWallpaper::SetBackgroundColor(ULONG uColor) +{ + WCHAR wzColor[64]; + StringCchPrintfW(wzColor, _countof(wzColor), L"%d %d %d", uColor & 0xFF, (uColor >> 8) & 0xFF, (uColor >> 16) & 0xFF); + SHSetValue(HKEY_CURRENT_USER, L"Control Panel\\Colors", L"Background", REG_SZ, + wzColor, (DWORD)wcslen(wzColor)*sizeof(wzColor[0])); + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0); + + return S_OK; +} + + +// +// IDesktopWallpaper::GetBackgroundColor +// Retrives the desktop background color. +// +HRESULT DesktopWallpaper::GetBackgroundColor(PULONG puColor) +{ + if (puColor == nullptr) + { + return E_POINTER; + } + + // Get the current color from the registry + WCHAR wzColor[64]; + DWORD dwType = REG_SZ; + DWORD dwSize = sizeof(wzColor); + SHGetValue(HKEY_CURRENT_USER, L"Control Panel\\Colors", L"Background", &dwType, wzColor, &dwSize); + + // Parse the registry value + ULONG uRed, uGreen, uBlue; + LPWSTR pEndPtr; + uRed = wcstoul(wzColor, &pEndPtr, 10); + uGreen = wcstoul(pEndPtr, &pEndPtr, 10); + uBlue = wcstoul(pEndPtr, &pEndPtr, 10); + + // Return the color :) + *puColor = (uBlue << 16) | (uGreen << 8) | uRed; + return S_OK; +} + + +// +// IDesktopWallpaper::SetPosition +// Sets the wallpapers style and tiling options. +// +HRESULT DesktopWallpaper::SetPosition(DESKTOP_WALLPAPER_POSITION position) +{ + LPCWSTR pwzStyle = L"0"; + LPCWSTR pwzTile = L"0"; + + switch (position) + { + case DWPOS_CENTER: + { + } + break; + + case DWPOS_FILL: + { + pwzStyle = L"10"; + } + break; + + case DWPOS_FIT: + { + pwzStyle = L"6"; + } + break; + + case DWPOS_SPAN: + { + pwzStyle = L"22"; + } + break; + + case DWPOS_STRETCH: + { + pwzStyle = L"2"; + } + break; + + case DWPOS_TILE: + { + pwzTile = L"1"; + } + break; + + default: + { + } + return E_INVALIDARG; + } + + SHSetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"WallpaperStyle", REG_SZ, + pwzStyle, (DWORD)wcslen(pwzStyle)*sizeof(pwzStyle[0])); + SHSetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"TileWallpaper", REG_SZ, + pwzTile, (DWORD)wcslen(pwzTile)*sizeof(pwzTile[0])); + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDESKWALLPAPER, 0); + + return S_OK; +} + + +// +// IDesktopWallpaper::GetPosition +// Gets the current wallpaper style and tiling mode. +// +HRESULT DesktopWallpaper::GetPosition(DESKTOP_WALLPAPER_POSITION* pPosition) +{ + if (pPosition == nullptr) + { + return E_POINTER; + } + + WCHAR wzStyle[64], wzTiling[64]; + DWORD dwType = REG_SZ; + DWORD dwSize = sizeof(wzStyle); + SHGetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"WallpaperStyle", &dwType, wzStyle, &dwSize); + SHGetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"TileWallpaper", &dwType, wzTiling, &dwSize); + + if (*wzTiling == L'\1') + { + *pPosition = DWPOS_TILE; + } + else if (_wcsicmp(wzStyle, L"0") == 0) + { + *pPosition = DWPOS_CENTER; + } + else if (_wcsicmp(wzStyle, L"2") == 0) + { + *pPosition = DWPOS_STRETCH; + } + else if (_wcsicmp(wzStyle, L"6") == 0) + { + *pPosition = DWPOS_FIT; + } + else if (_wcsicmp(wzStyle, L"10") == 0) + { + *pPosition = DWPOS_FILL; + } + else if (_wcsicmp(wzStyle, L"22") == 0) + { + *pPosition = DWPOS_SPAN; + } + else + { + *pPosition = DWPOS_CENTER; + } + + return S_OK; +} + + +// +// IDesktopWallpaper::SetSlideshow +// +// +HRESULT DesktopWallpaper::SetSlideshow(IShellItemArray* pItems) +{ + return S_OK; +} + + +// +// IDesktopWallpaper::GetSlideshow +// +// +HRESULT DesktopWallpaper::GetSlideshow(IShellItemArray** ppItems) +{ + if (ppItems == nullptr) + { + return E_POINTER; + } + + DWORD dwType = REG_SZ; + DWORD dwSize = MAX_PATH*sizeof(WCHAR); + WCHAR wallpaper[MAX_PATH]; + SHGetValue(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"Wallpaper", &dwType, wallpaper, &dwSize); + + HRESULT hr; + + IShellFolder *pRootFolder = nullptr; + hr = SHGetDesktopFolder(&pRootFolder); + + LPITEMIDLIST idList = nullptr; + if (SUCCEEDED(hr)) + { + hr = pRootFolder->ParseDisplayName(nullptr, nullptr, wallpaper, nullptr, &idList, NULL); + } + + if (SUCCEEDED(hr)) + { + hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)&idList, ppItems); + } + + if (idList) + { + CoTaskMemFree(idList); + } + if (pRootFolder) + { + pRootFolder->Release(); + } + + // S_FALSE means that the slideshow is currently disabled + return S_FALSE; +} + + +// +// IDesktopWallpaper::SetSlideshowOptions +// +// +HRESULT DesktopWallpaper::SetSlideshowOptions(DESKTOP_SLIDESHOW_OPTIONS options, UINT uSlideshowTick) +{ + return S_OK; +} + + +// +// IDesktopWallpaper::GetSlideshowOptions +// +// +HRESULT DesktopWallpaper::GetSlideshowOptions(DESKTOP_SLIDESHOW_OPTIONS *pOptions, LPUINT puSlideshowTick) +{ + if (pOptions == nullptr || puSlideshowTick == nullptr) + { + return E_POINTER; + } + + *pOptions = DESKTOP_SLIDESHOW_OPTIONS(0); + return S_OK; +} + + +// +// IDesktopWallpaper::AdvanceSlideshow +// +// +HRESULT DesktopWallpaper::AdvanceSlideshow(LPCWSTR pwzMonitorID, DESKTOP_SLIDESHOW_DIRECTION direction) +{ + return S_OK; +} + + +// +// IDesktopWallpaper::GetStatus +// +// +HRESULT DesktopWallpaper::GetStatus(DESKTOP_SLIDESHOW_STATE* pState) +{ + if (pState == nullptr) + { + return E_POINTER; + } + + *pState = DESKTOP_SLIDESHOW_STATE::DSS_ENABLED; + return S_OK; +} + + +// +// IDesktopWallpaper::Enable +// +// +HRESULT DesktopWallpaper::Enable(BOOL /* bEnable */) +{ + return S_OK; +} + + +// +// IDesktopWallpaperPrivate::?? +// Never seen anything call this. +// Experiments with explorer, makes this seem like an alias of SetWallpaper +// +HRESULT DesktopWallpaper::SetWallpaper2(LPCWSTR pwzMonitor, LPCWSTR pwzWallpaper) +{ + return SetWallpaper(pwzMonitor, pwzWallpaper); +} + + +// +// IDesktopWallpaperPrivate::?? +// Likes to give me E_PENDING. Does not care about parameters, not sure it actually +// takes any. +// +HRESULT DesktopWallpaper::PrivateB(LPVOID) +{ + return E_NOTIMPL; +} + + +// +// IDesktopWallpaperPrivate::?? +// Called by the Color and Appearance dialog when you select the automatic +// DWM color +// +HRESULT DesktopWallpaper::GetWallpaperColor(PULONG puColor) +{ + // TODO::We may need to actually compute the DWM colorization here... + if (puColor == nullptr) + { + return E_POINTER; + } + + DWORD dwColor; + DWORD dwType = REG_DWORD; + DWORD dwSize = sizeof(dwColor); + SHGetValueW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", L"ImageColor", &dwType, &dwColor, &dwSize); + *puColor = dwColor; + + return S_OK; +} + + +// +// IDesktopWallpaperPrivate::?? +// Seems to set the 2nd parameter to the monitor "#" +// +HRESULT DesktopWallpaper::GetMonitorNumber(LPCWSTR pwzMonitorID, LPUINT puMonitorNumber) +{ + if (puMonitorNumber == nullptr) + { + return E_POINTER; + } + + if (pwzMonitorID == nullptr) + { + // This is what explorer returns in this case. + return 0x800706F4; + } + + for (MonitorData &monitor : m_vMonitors) + { + if (_wcsicmp(monitor.wzDeviceString, pwzMonitorID) == 0) + { + *puMonitorNumber = monitor.uNumber; + return S_OK; + } + } + + return E_INVALIDARG; +} + + +// +// IDesktopWallpaperPrivate::?? +// ??? +// +HRESULT DesktopWallpaper::PrivateE(LPVOID) +{ + return E_NOTIMPL; +} + + +// +// IDesktopWallpaperPrivate::?? +// ??? +// +HRESULT DesktopWallpaper::PrivateF(LPVOID) +{ + return E_NOTIMPL; +} + + +// +// IDesktopWallpaperPrivate::?? +// ??? +// +HRESULT DesktopWallpaper::PrivateG(LPVOID) +{ + return E_NOTIMPL; +} + + +// +// IDesktopWallpaperPrivate::?? +// ??? +// +HRESULT DesktopWallpaper::PrivateH(LPVOID) +{ + return E_NOTIMPL; +} diff --git a/litestep/DesktopWallpaper.h b/litestep/DesktopWallpaper.h new file mode 100644 index 0000000..dfc2af2 --- /dev/null +++ b/litestep/DesktopWallpaper.h @@ -0,0 +1,87 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(DESKTOPWALLPAPER_H) +#define DESKTOPWALLPAPER_H + +#include "IDesktopWallpaper.h" +#include "IDesktopWallpaperPrivate.h" +#include + +class DesktopWallpaper : public IDesktopWallpaperPrivate +{ +public: + DesktopWallpaper(); + +private: + virtual ~DesktopWallpaper(); + + // IUnknown Implementation +public: + ULONG STDMETHODCALLTYPE AddRef(); + STDMETHOD(QueryInterface) (REFIID, void**); + ULONG STDMETHODCALLTYPE Release(); + + // IDesktopWallpaper Implementation +public: + STDMETHOD(SetWallpaper) (LPCWSTR, LPCWSTR); + STDMETHOD(GetWallpaper) (LPCWSTR, LPWSTR*); + STDMETHOD(GetMonitorDevicePathAt) (UINT, LPWSTR*); + STDMETHOD(GetMonitorDevicePathCount) (LPUINT); + STDMETHOD(GetMonitorRECT) (LPCWSTR, tagRECT*); + STDMETHOD(SetBackgroundColor) (ULONG); + STDMETHOD(GetBackgroundColor) (PULONG); + STDMETHOD(SetPosition) (DESKTOP_WALLPAPER_POSITION); + STDMETHOD(GetPosition) (DESKTOP_WALLPAPER_POSITION*); + STDMETHOD(SetSlideshow) (IShellItemArray*); + STDMETHOD(GetSlideshow) (IShellItemArray**); + STDMETHOD(SetSlideshowOptions) (DESKTOP_SLIDESHOW_OPTIONS, UINT); + STDMETHOD(GetSlideshowOptions) (DESKTOP_SLIDESHOW_OPTIONS*, LPUINT); + STDMETHOD(AdvanceSlideshow) (LPCWSTR, DESKTOP_SLIDESHOW_DIRECTION); + STDMETHOD(GetStatus) (DESKTOP_SLIDESHOW_STATE*); + STDMETHOD(Enable) (BOOL); + + // IDesktopWallpaperPrivate Implementation +public: + STDMETHOD(SetWallpaper2) (LPCWSTR, LPCWSTR); + STDMETHOD(PrivateB) (LPVOID); + STDMETHOD(GetWallpaperColor) (PULONG); + STDMETHOD(GetMonitorNumber) (LPCWSTR, LPUINT); + STDMETHOD(PrivateE) (LPVOID); + STDMETHOD(PrivateF) (LPVOID); + STDMETHOD(PrivateG) (LPVOID); + STDMETHOD(PrivateH) (LPVOID); + +private: + struct MonitorData + { + RECT rRect; + WCHAR wzDeviceString[MAX_PATH]; + UINT uNumber; + }; + +private: + ULONG m_uRefCount; + std::vector m_vMonitors; +}; + +#endif // DESKTOPWALLPAPER_H diff --git a/litestep/FullscreenMonitor.cpp b/litestep/FullscreenMonitor.cpp index 7ad4f00..6c91802 100644 --- a/litestep/FullscreenMonitor.cpp +++ b/litestep/FullscreenMonitor.cpp @@ -187,6 +187,11 @@ void FullscreenMonitor::HideModules(HMONITOR hMonitor, HWND hWnd) // void FullscreenMonitor::ThreadProc() { + +#if defined(_DEBUG) + DbgSetCurrentThreadName("LS FullscreenMonitor Service"); +#endif + // struct FSWindow { FSWindow(HWND hWnd, HMONITOR hMonitor) { diff --git a/litestep/IDesktopWallpaper.h b/litestep/IDesktopWallpaper.h new file mode 100644 index 0000000..f227cf4 --- /dev/null +++ b/litestep/IDesktopWallpaper.h @@ -0,0 +1,84 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(IDESKTOPWALLPAPER_H) +#define IDESKTOPWALLPAPER_H + +// +// This is backport of the IDesktopWallpaper class, and related types, since +// they do not exist in the XP toolkit (and LS will not run on XP if compiled +// with the post-XP toolkit). +// + +#include + +enum DESKTOP_SLIDESHOW_DIRECTION +{ + DSD_FORWARD = 0, + DSD_BACKWARD = 1 +}; + +enum DESKTOP_WALLPAPER_POSITION +{ + DWPOS_CENTER = 0, + DWPOS_TILE = 1, + DWPOS_STRETCH = 2, + DWPOS_FIT = 3, + DWPOS_FILL = 4, + DWPOS_SPAN = 5 +}; + +enum DESKTOP_SLIDESHOW_OPTIONS +{ + DSO_SHUFFLEIMAGES = 0x1 +}; + +enum DESKTOP_SLIDESHOW_STATE +{ + DSS_ENABLED = 0x1, + DSS_SLIDESHOW = 0x2, + DSS_DISABLED_BY_REMOTE_SESSION = 0x4 +}; + +const GUID IID_IDesktopWallpaper = { 0xb92b56a9, 0x8b55, 0x4e14, { 0x9a, 0x89, 0x01, 0x99, 0xbb, 0xb6, 0xf9, 0x3b} }; + +class IDesktopWallpaper : public IUnknown +{ + STDMETHOD(SetWallpaper) (LPCWSTR, LPCWSTR) = 0; + STDMETHOD(GetWallpaper) (LPCWSTR, LPWSTR*) = 0; + STDMETHOD(GetMonitorDevicePathAt) (unsigned int, LPWSTR*) = 0; + STDMETHOD(GetMonitorDevicePathCount) (unsigned int*) = 0; + STDMETHOD(GetMonitorRECT) (LPCWSTR, tagRECT*) = 0; + STDMETHOD(SetBackgroundColor) (unsigned long) = 0; + STDMETHOD(GetBackgroundColor) (unsigned long*) = 0; + STDMETHOD(SetPosition) (DESKTOP_WALLPAPER_POSITION) = 0; + STDMETHOD(GetPosition) (DESKTOP_WALLPAPER_POSITION*) = 0; + STDMETHOD(SetSlideshow) (IShellItemArray*) = 0; + STDMETHOD(GetSlideshow) (IShellItemArray**) = 0; + STDMETHOD(SetSlideshowOptions) (DESKTOP_SLIDESHOW_OPTIONS, unsigned int) = 0; + STDMETHOD(GetSlideshowOptions) (DESKTOP_SLIDESHOW_OPTIONS*, unsigned int*) = 0; + STDMETHOD(AdvanceSlideshow) (LPCWSTR, DESKTOP_SLIDESHOW_DIRECTION) = 0; + STDMETHOD(GetStatus) (DESKTOP_SLIDESHOW_STATE*) = 0; + STDMETHOD(Enable) (BOOL) = 0; +}; + +#endif // IDESKTOPWALLPAPER_H diff --git a/litestep/IDesktopWallpaperPrivate.h b/litestep/IDesktopWallpaperPrivate.h new file mode 100644 index 0000000..cf267ec --- /dev/null +++ b/litestep/IDesktopWallpaperPrivate.h @@ -0,0 +1,45 @@ +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// This is a part of the Litestep Shell source code. +// +// Copyright (C) 1998 (e) +// Copyright (C) 1997-2013 LiteStep Development 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. +// +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#if !defined(IDESKTOPWALLPAPERPRIVATE_H) +#define IDESKTOPWALLPAPERPRIVATE_H + +// +// The functions listed here, and their functionality are guesses, which were +// obtained by examining how explorer handles these calls. +// + +const GUID IID_IDesktopWallpaperPrivate = { 0xC182461F, 0xDFAC, 0x4375, { 0xAB, 0x6E, 0x4C, 0xC4, 0x5A, 0xA7, 0xF9, 0xCC } }; +class IDesktopWallpaperPrivate : public IDesktopWallpaper +{ +public: + STDMETHOD(SetWallpaper2) (LPCWSTR, LPCWSTR) = 0; + STDMETHOD(PrivateB) (LPVOID) = 0; + STDMETHOD(GetWallpaperColor) (PULONG) = 0; + STDMETHOD(GetMonitorNumber) (LPCWSTR, LPUINT) = 0; + STDMETHOD(PrivateE) (LPVOID) = 0; + STDMETHOD(PrivateF) (LPVOID) = 0; + STDMETHOD(PrivateG) (LPVOID) = 0; + STDMETHOD(PrivateH) (LPVOID) = 0; +}; + +#endif // IDESKTOPWALLPAPERPRIVATE_H diff --git a/litestep/Module.cpp b/litestep/Module.cpp index 397300f..7df1898 100644 --- a/litestep/Module.cpp +++ b/litestep/Module.cpp @@ -67,6 +67,23 @@ static WORD GetModuleArchitecture(LPCWSTR wzModuleName) } +// +// This is a workaround because Microsofts std::function implementation is bugged +// +template +void AssignToFunction(std::function &func, T* value) +{ + if (value == nullptr) + { + func = nullptr; + } + else + { + func = value; + } +} + + bool Module::_LoadDll() { bool bReturn = false; @@ -83,10 +100,10 @@ bool Module::_LoadDll() if ((m_hInstance = LoadLibraryW(m_wzLocation.c_str())) != nullptr) { - m_pInit = (initModuleProc)GetProcAddress( - m_hInstance, "initModuleW"); + AssignToFunction(m_pInit, (initModuleProc) GetProcAddress( + m_hInstance, "initModuleW")); - if (m_pInit != nullptr) // Might be a legacy module, check for initModuleEx + if (!m_pInit) // Might be a legacy module, check for initModuleEx { initModuleProcA pInit = (initModuleProcA)GetProcAddress( m_hInstance, "initModuleEx"); @@ -117,7 +134,7 @@ bool Module::_LoadDll() m_hInstance, "_quitModule"); } - if (!m_pInit) + if (m_pInit == nullptr) { RESOURCE_STR(nullptr, IDS_INITMODULEEXNOTFOUND_ERROR, L"Error: Could not find initModule().\n" @@ -125,7 +142,7 @@ bool Module::_LoadDll() L"Please confirm that the dll is a LiteStep module,\n" L"and check with the author for updates."); } - else if (!m_pQuit) + else if (m_pQuit == nullptr) { RESOURCE_STR(nullptr, IDS_QUITMODULENOTFOUND_ERROR, L"Error: Could not find quitModule().\n" diff --git a/litestep/TrayNotifyIcon.h b/litestep/TrayNotifyIcon.h index 2c27a79..dc90ea4 100644 --- a/litestep/TrayNotifyIcon.h +++ b/litestep/TrayNotifyIcon.h @@ -78,14 +78,14 @@ typedef struct LSNOTIFYICONDATAA this->uFlags = nid->uFlags; this->uCallbackMessage = nid->uCallbackMessage; this->hIcon = nid->hIcon; - WideCharToMultiByte(CP_ACP, 0, nid->szTip, _countof(nid->szTip), + WideCharToMultiByte(CP_ACP, 0, nid->szTip, -1, this->szTip, sizeof(this->szTip), "?", nullptr); this->dwState = nid->dwState; this->dwStateMask = nid->dwStateMask; - WideCharToMultiByte(CP_ACP, 0, nid->szInfo, _countof(nid->szInfo), + WideCharToMultiByte(CP_ACP, 0, nid->szInfo, -1, this->szInfo, sizeof(this->szInfo), "?", nullptr); this->uVersion = nid->uVersion; - WideCharToMultiByte(CP_ACP, 0, nid->szInfoTitle, _countof(nid->szInfoTitle), + WideCharToMultiByte(CP_ACP, 0, nid->szInfoTitle, -1, this->szInfoTitle, sizeof(this->szInfoTitle), "?", nullptr); this->dwInfoFlags = nid->dwInfoFlags; this->guidItem = nid->guidItem; diff --git a/litestep/litestep.cpp b/litestep/litestep.cpp index 12c7dcb..b9c34b2 100644 --- a/litestep/litestep.cpp +++ b/litestep/litestep.cpp @@ -28,6 +28,7 @@ #include "TrayService.h" #include "ExplorerService.h" #include "FullscreenMonitor.h" +#include "COMService.h" // Managers #include "MessageManager.h" @@ -1271,6 +1272,20 @@ HRESULT CLiteStep::_InitServices(bool bSetAsShell) #endif } + // + // COM Service + // + pService = new (std::nothrow) COMService(); + + if (pService) + { + m_Services.push_back(pService); + } + else + { + return E_OUTOFMEMORY; + } + // // FullscreenMonitor service // @@ -1449,8 +1464,10 @@ HRESULT CLiteStep::_EnumRevIDs(LSENUMREVIDSPROCW pfnCallback, LPARAM lParam) con MessageManager::windowSetT setWindowsW, setWindowsA; - if (m_pMessageManager->GetWindowsForMessage(LM_GETREVIDA, setWindowsA) || - m_pMessageManager->GetWindowsForMessage(LM_GETREVIDW, setWindowsW)) + m_pMessageManager->GetWindowsForMessage(LM_GETREVIDA, setWindowsA); + m_pMessageManager->GetWindowsForMessage(LM_GETREVIDW, setWindowsW); + + if (!setWindowsA.empty() || !setWindowsW.empty()) { hr = S_OK; diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 578bb6f..70ae57a 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -36,17 +36,17 @@ Application Unicode true - v110_xp + v110 Application Unicode - v110_xp + v110 Application Unicode - v110_xp + v110 @@ -226,10 +226,13 @@ + + + @@ -246,12 +249,16 @@ + + + + diff --git a/litestep/litestep_vc12.vcxproj b/litestep/litestep_vc12.vcxproj index 278db9d..8a8fc6f 100644 --- a/litestep/litestep_vc12.vcxproj +++ b/litestep/litestep_vc12.vcxproj @@ -226,10 +226,13 @@ + + + @@ -246,12 +249,16 @@ + + + + @@ -260,6 +267,7 @@ + diff --git a/litestep/litestep_vc12.vcxproj.filters b/litestep/litestep_vc12.vcxproj.filters new file mode 100644 index 0000000..5359183 --- /dev/null +++ b/litestep/litestep_vc12.vcxproj.filters @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + Services + + + Services + + + Services + + + Services + + + Services + + + Services + + + + Services + + + Services + + + COMServiceObjects + + + COMServiceObjects + + + + + + + + + + + + + + + + Services + + + Services + + + Services + + + Services + + + Services + + + Services + + + + Services + + + Services + + + COMServiceObjects + + + COMServiceObjects + + + COMServiceObjects + + + COMServiceObjects + + + + + + + + + + + + {2cbbf3c2-b15e-4920-ba91-b93559d1958f} + + + {a8ad4190-dfef-43c4-9d03-705df38c7a43} + + + \ No newline at end of file diff --git a/lsapi/lsapi.cpp b/lsapi/lsapi.cpp index bcc3785..8ecc869 100644 --- a/lsapi/lsapi.cpp +++ b/lsapi/lsapi.cpp @@ -1065,7 +1065,7 @@ void VarExpansionExA(LPSTR pszExpandedString, LPCSTR pszTemplate, size_t cchExpa std::unique_ptr temp(new wchar_t[cchExpandedString]); g_LSAPIManager.GetSettingsManager()->VarExpansionEx( temp.get(), MBSTOWCS(pszTemplate), cchExpandedString); - WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchExpandedString, + WideCharToMultiByte(CP_ACP, 0, temp.get(), -1, pszExpandedString, (int)cchExpandedString, "?", nullptr); } else diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index ae05807..354eef6 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -36,17 +36,17 @@ DynamicLibrary Unicode true - v110_xp + v110 DynamicLibrary Unicode - v110_xp + v110 DynamicLibrary Unicode - v110_xp + v110 diff --git a/lsapi/settings.cpp b/lsapi/settings.cpp index 3fbeac3..065b907 100644 --- a/lsapi/settings.cpp +++ b/lsapi/settings.cpp @@ -97,7 +97,7 @@ BOOL LCReadNextCommandA(LPVOID pFile, LPSTR pszValue, size_t cchValue) std::unique_ptr temp(new wchar_t[cchValue]); bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextCommand( pFile, temp.get(), cchValue); - WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, temp.get(), -1, pszValue, (int)cchValue, "?", nullptr); } } @@ -135,7 +135,7 @@ BOOL LCReadNextConfigA(LPVOID pFile, LPCSTR pszConfig, LPSTR pszValue, size_t cc std::unique_ptr temp(new wchar_t[cchValue]); bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextConfig( pFile, MBSTOWCS(pszConfig), temp.get(), cchValue); - WideCharToMultiByte(CP_ACP, 0, temp.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, temp.get(), -1, pszValue, (int)cchValue, "?", nullptr); } } @@ -171,7 +171,7 @@ BOOL LCReadNextLineA(LPVOID pFile, LPSTR pszValue, size_t cchValue) std::unique_ptr value(new wchar_t[cchValue]); bReturn = g_LSAPIManager.GetSettingsManager()->LCReadNextLine( pFile, value.get(), cchValue); - WideCharToMultiByte(CP_ACP, 0, value.get(), (int)cchValue, pszValue, (int)cchValue, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, value.get(), -1, pszValue, (int)cchValue, "?", nullptr); } } @@ -311,14 +311,14 @@ BOOL GetRCStringA(LPCSTR pszKeyName, LPSTR pszValue, LPCSTR pszDefStr, int maxLe std::unique_ptr key (WCSFromMBS(pszKeyName)); std::unique_ptr def (WCSFromMBS(pszDefStr)); - *tempValue = L'\0'; + *tempValue = '\0'; BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetRCString( key.get(), tempValue.get(), def.get(), maxLen); if (pszValue) { - WideCharToMultiByte(CP_ACP, 0, tempValue.get(), maxLen, pszValue, maxLen, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, tempValue.get(), -1, pszValue, maxLen, "?", nullptr); } return bRet; @@ -374,14 +374,14 @@ BOOL GetRCLineA(LPCSTR pszKeyName, LPSTR pszBuffer, UINT nBufLen, LPCSTR pszDefa std::unique_ptr key (WCSFromMBS(pszKeyName)); std::unique_ptr def (WCSFromMBS(pszDefault)); - *tempValue = L'\0'; + *tempValue = '\0'; BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetRCLine( key.get(), tempValue.get(), nBufLen, def.get()); if (pszBuffer) { - WideCharToMultiByte(CP_ACP, 0, tempValue.get(), nBufLen, pszBuffer, nBufLen, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, tempValue.get(), -1, pszBuffer, nBufLen, "?", nullptr); } return bRet; @@ -416,7 +416,7 @@ BOOL LSGetVariableExA(LPCSTR pszKeyName, LPSTR pszValue, DWORD dwLength) BOOL bRet = g_LSAPIManager.GetSettingsManager()->GetVariable( MBSTOWCS(pszKeyName), temp.get(), dwLength); - WideCharToMultiByte(CP_ACP, 0, temp.get(), dwLength, pszValue, dwLength, "?", nullptr); + WideCharToMultiByte(CP_ACP, 0, temp.get(), -1, pszValue, dwLength, "?", nullptr); return bRet; } @@ -457,7 +457,7 @@ BOOL LSGetVariableA(LPCSTR pszKeyName, LPSTR pszValue) if (pszValue) { - pszValue[0] = L'\0'; + pszValue[0] = '\0'; } if (g_LSAPIManager.IsInitialized()) diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index 347d214..e25c137 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -346,6 +346,36 @@ HRESULT CLSIDToString(REFCLSID rclsid, LPTSTR ptzBuffer, size_t cchBuffer) } +// +// Attempts to parse a string into a GUID. +// Mostly for debugging purposes. +// +BOOL LSGUIDFromString(LPCTSTR guidString, LPGUID guid) +{ + typedef BOOL (WINAPI* PROCTYPE)(LPCTSTR, LPGUID); + static PROCTYPE proc = nullptr; + + if (proc == nullptr) + { + proc = (PROCTYPE)GetProcAddress(GetModuleHandle(_T("Shell32.dll")), +#if defined(_UNICODE) + (LPCSTR)704 +#else + (LPCSTR)703 +#endif + ); + } + + if (proc) + { + return proc(guidString, guid); + } + + return FALSE; +} + + + // // LSGetModuleFileName // diff --git a/utility/shellhlp.h b/utility/shellhlp.h index 06c957f..c02a7ff 100644 --- a/utility/shellhlp.h +++ b/utility/shellhlp.h @@ -50,6 +50,7 @@ void LSShutdownDialog(HWND hWnd); BOOL LSPlaySystemSound(LPCWSTR pwzSoundAlias); HANDLE LSCreateThread(LPCSTR pszName, LPTHREAD_START_ROUTINE fnStartAddres, LPVOID lpParameter, LPDWORD pdwThreadId); +BOOL LSGUIDFromString(LPCTSTR ptzGUIDString, LPGUID pGUID); //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index 6936f89..516680d 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -36,17 +36,17 @@ StaticLibrary Unicode true - v110_xp + v110 StaticLibrary Unicode - v110_xp + v110 StaticLibrary Unicode - v110_xp + v110 From a8096e24d3d4527d7be98e66a1a7c2a81faeffe0 Mon Sep 17 00:00:00 2001 From: Erik Welander Date: Tue, 6 Aug 2013 23:56:47 -0700 Subject: [PATCH 50/50] Update from CVS. --- docs/changes.txt | 18 +++++- docs/manual.txt | 41 ++++++++++++- litestep/DesktopWallpaper.cpp | 28 ++++++++- litestep/litestep.rc | 34 +++++------ litestep/litestep_vc11.vcxproj | 6 +- lsapi/MathEvaluate.cpp | 6 +- lsapi/MathParser.cpp | 106 ++++++++++++++++++++++++++------- lsapi/SettingsDefines.h | 14 ++++- lsapi/SettingsFileParser.cpp | 49 +++++++++++++-- lsapi/SettingsFileParser.h | 4 +- lsapi/SettingsIterator.cpp | 6 +- lsapi/SettingsManager.h | 3 +- lsapi/bangs.cpp | 5 +- lsapi/lsapiInit.cpp | 5 ++ lsapi/lsapi_vc11.vcxproj | 6 +- lsapi/settingsmanager.cpp | 50 ++++++++++------ utility/shellhlp.cpp | 1 - utility/utility_vc11.vcxproj | 6 +- 18 files changed, 297 insertions(+), 91 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 9dd238b..0380707 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -53,7 +53,14 @@ See the next section for a cumulative changelog since 0.24.8. - Added GetRCInt64. - Fixed Right Click -> Set as desktop background on Windows 8. - Fixed the color and appearance dialog on Windows 8. - - Fixed the desktop background dialog on Windows 8. + - Fixed the desktop background dialog on Windows 8. Per-monitor wallpaper, + and slideshows are not working yet. + - Added $dollar$, $at$, $nl$, and $cr$. Allowing you to insert literal $, + newlines, carriage returns, and @'s in strings. + - Added pathDirPart(), pathDrivePart(), pathFilePart(), pathFileNamePart(), + and pathExtPart() functions. + - Extended the prefix RC syntax by adding @ as a special character in the + value, refering to the current prefix. - [2013-08-04] - - Fixed the A versions of GetRCString, Line, and so on writing to the entire @@ -183,6 +190,8 @@ This is a list of selected changes since the (projected) 0.24.8 final build: - Added $WinVista$, $Win2008$, $Win7$, $Win2008R2$, $Win8$, $Win2012$, $Win2012R2$, and $Win81$. - Added $Win64$ to identify Windows x64 + - Added $Dollar$, $At$, $NL$, and $CR$ to allow for insertion of literal $, + @, newline, and carriage return symbols. - In safe mode, LiteStep attempts to launch Explorer as shell - If it fails, LiteStep launches as shell but skips running startup apps - Added "-explorer" command line switch to launch Explorer in shell mode @@ -201,7 +210,8 @@ This is a list of selected changes since the (projected) 0.24.8 final build: - New .RC construct, { }, allowing for the specification of settings prefixes. Allows for tidier configs. - Added a performance page to !about, showing module load times. - - Added a fileExists() function. + - Added fileExists(), pathDirPart(), pathDrivePart(), pathFilePart(), + pathFileNamePart(), and pathExtPart() functions. - Support for version 4 tray icons on Windows 7 and Windows 8. Tray modules now need to handle LM_SYSTRAYINFOEVENT in order to support this. - The !Run dialog will now execute !Bang commands. @@ -212,7 +222,9 @@ This is a list of selected changes since the (projected) 0.24.8 final build: - Added Added "About LiteStep" and "Start Explorer as shell" to the recovery menu. - Support for unicode modules. - - Added GetRCFloat and GetRCDouble. + - Added GetRCFloat, GetRCDouble, and GetRCInt64. + - Extended the prefix RC syntax by adding @ as a special character in the + value, refering to the current prefix. - VISTA & WIN7 & 64-BIT SUPPORT - diff --git a/docs/manual.txt b/docs/manual.txt index 693a4e9..28adb7c 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -409,12 +409,19 @@ Contents: any command within the braces to have the specified prefix prefixed to it. Within prefix braces, the key - is evaluated to just the prefix. Keys starting with a * are treated specially, and the begining * is put at - the begining of the final key name. + the begining of the final key name. Inside the curly braces, @ is treated + as a special character in values, and is replaced by the prefix. Several + @'s in a row walks up the prefix stack. - This: + Using an example, this: Prefix { + Prefix2 + { + SomeKey @@ + SomeOtherKey @ + } - Value Key Value *Event Value @@ -422,6 +429,8 @@ Contents: Is equivalent to this: + PrefixPrefix2SomeKey Prefix + PrefixPrefix2SomeOtherKey PrefixPrefix2 Prefix Value PrefixKey Value *PrefixEvent Value @@ -640,6 +649,26 @@ Contents: 1 and false maps to 0. A string is parsed as a numeric literal; if parsing fails, the string is mapped to NaN. + pathDirPart(string) + Returns the directory part of the string. For example, + pathDirPart('c:\\test\\somefile.txt') will return c:\test\ + + pathDrivePart(string) + Returns the drive part of the string. For example, + pathDrivePart('c:\\test\\somefile.txt') will return c:\ + + pathExtPart(string) + Returns the extension part of the string. For example, + pathExtPart('c:\\test\\somefile.txt') will return + + pathFilePart(string) + Returns the file part of the string. For example, + pathFilePart('c:\\test\\somefile.txt') will return somefile.txt + + pathFileNamePart(string) + Returns the file name part of the string. For example, + pathFileNamePart('c:\\test\\somefile.txt') will return somefile + pow(number, number) Returns the first argument, converted to a number, raised to the power of the second argument, converted to a number. @@ -933,7 +962,7 @@ Contents: WinDir 2. Conditional Expansions - + Win64 Win9X WinNT @@ -973,6 +1002,12 @@ Contents: NetworkAndDialup Printers Scheduled + + 5. Character Literal Expansions + Dollar - Evaluates to $ + At - Evaluates to @ + NL - Evaluates to a newline character + CR - Evaluate to a carriage return character F) !Bang Commands ----------------- diff --git a/litestep/DesktopWallpaper.cpp b/litestep/DesktopWallpaper.cpp index e75d9d4..898a0ea 100644 --- a/litestep/DesktopWallpaper.cpp +++ b/litestep/DesktopWallpaper.cpp @@ -26,6 +26,32 @@ #include "../utility/shellhlp.h" +// +// Wrapper around SHCreateShellItemArrayFromIDLists. +// Until we drop XP support. +// +HRESULT LSCreateShellItemArrayFromIDLists(UINT cidl, PCIDLIST_ABSOLUTE_ARRAY rgpidl, + IShellItemArray **ppsiItemArray) +{ + typedef HRESULT (WINAPI* PROCTYPE)(UINT cidl, PCIDLIST_ABSOLUTE_ARRAY rgpidl, + IShellItemArray **ppsiItemArray); + static PROCTYPE proc = nullptr; + + if (proc == nullptr) + { + proc = (PROCTYPE)GetProcAddress(GetModuleHandle(_T("Shell32.dll")), + "SHCreateShellItemArrayFromIDLists"); + } + + if (proc == nullptr) + { + return E_FAIL; + } + + return proc(cidl, rgpidl, ppsiItemArray); +} + + // // DesktopWallpaper // @@ -448,7 +474,7 @@ HRESULT DesktopWallpaper::GetSlideshow(IShellItemArray** ppItems) if (SUCCEEDED(hr)) { - hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)&idList, ppItems); + hr = LSCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)&idList, ppItems); } if (idList) diff --git a/litestep/litestep.rc b/litestep/litestep.rc index 1723c1c..59185d0 100644 --- a/litestep/litestep.rc +++ b/litestep/litestep.rc @@ -31,12 +31,12 @@ BEGIN IDS_LITESTEP_TITLE_WARNING "Warnung" IDS_LITESTEP_TITLE_ERROR "Fehler" IDS_LITESTEP_ERROR1 "Eine vorherige Instanz von LiteStep gefunden.\nSind Sie sicher, daß Sie weitermachen wollen?" - IDS_LITESTEP_ERROR2 "Konnte die Datei ""%s"" nicht finden.\nBitte stellen Sie sicher, daß der Pfad korrekt ist und die Datei existiert." + IDS_LITESTEP_ERROR2 "Konnte die Datei ""%ls"" nicht finden.\nBitte stellen Sie sicher, daß der Pfad korrekt ist und die Datei existiert." IDS_LITESTEP_ERROR3 "LiteStep kann nicht als die System-Shell geladen werden,\nda bereits eine andere Shell aktiv ist.\n\nFalls Sie mit dem Laden LiteSteps fortfahren, werden einige\nFunktionen deaktiviert, und einige Features werden nicht\nordnungsgemäß funktionieren, wie z.B. der System-Tray, der\nDesktop und einige Task-Manager.\n\nUm diesen Hinweis abzuschalten, fügen Sie 'LSNoShellWarning'\nin Ihre step.rc ein.\n\nSoll mit dem Laden LiteSteps fortgefahren werden?" IDS_LITESTEP_ERROR4 "Fehler beim Registrieren der LiteStep-Hauptfensterklasse." IDS_LITESTEP_ERROR5 "Fehler beim Erzeugen des LiteStep-Hauptfensters." IDS_LITESTEP_ERROR6 "Recycle wurde pausiert. Drücken Sie OK, um weiterzumachen." - IDS_LITESTEP_ERROR7 "Konnte %s nicht laden." + IDS_LITESTEP_ERROR7 "Konnte %ls nicht laden." IDS_LITESTEP_RECYCLELS "LiteStep &recyclen" IDS_LITESTEP_QUITLS "LiteStep be&enden" IDS_LITESTEP_TERMINATELS "LiteStep ab&brechen" @@ -198,12 +198,12 @@ BEGIN IDS_LITESTEP_TITLE_WARNING "Warning" IDS_LITESTEP_TITLE_ERROR "Error" IDS_LITESTEP_ERROR1 "A previous instance of LiteStep was detected.\nAre you sure you want to continue?" - IDS_LITESTEP_ERROR2 "Unable to find the file ""%s"".\nPlease verify the location of the file." + IDS_LITESTEP_ERROR2 "Unable to find the file ""%ls"".\nPlease verify the location of the file." IDS_LITESTEP_ERROR3 "LiteStep is not able to load as the system shell.\nAnother shell is already active.\n\nContinuing to load LiteStep will disable specific system\nshell functions of LiteStep and some features will not\nfunction properly such as icon notifications (systray),\nthe desktop and some task managers.\n\nTo disable this message, place 'LSNoShellWarning' in\nyour step.rc.\n\nContinue to load LiteStep?" IDS_LITESTEP_ERROR4 "Error registering main LiteStep window class." IDS_LITESTEP_ERROR5 "Error creating LiteStep main application window." IDS_LITESTEP_ERROR6 "Recycle has been paused, click OK to continue." - IDS_LITESTEP_ERROR7 "Unable to load %s." + IDS_LITESTEP_ERROR7 "Unable to load %ls." IDS_LITESTEP_RECYCLELS "Re&cycle LiteStep" IDS_LITESTEP_QUITLS "&Quit LiteStep" IDS_LITESTEP_TERMINATELS "Forcibly &Terminate LiteStep" @@ -226,13 +226,13 @@ BEGIN "Error: Exception during module initialization.\n\nPlease contact the module writer." IDS_LITESTEP_CREATEWINDOW_ERROR "Unable to create window." IDS_LITESTEP_BANGEXCEPTION - "Exception during bang command execution.\nPlease contact the module author.\n\nBang parameters: %s" + "Exception during bang command execution.\nPlease contact the module author.\n\nBang parameters: %ls" IDS_LITESTEP_REGISTERCLASS_ERROR "Error registering window class." IDS_MODULEDEPENDENCY_ERROR "Error: Could not load module.\nThis is likely a case of a missing C Run-Time Library or other dependency.\nError Information:\n" - IDS_RECURSIVEVAR "Error: Variable ""%s"" is defined recursively." - IDS_RECURSIVEINCLUDE "Error: Reursive include detected!\n%s" - IDS_MATHEXCEPTION "Error in Expression:\n %s\n\nDescription:\n %s" + IDS_RECURSIVEVAR "Error: Variable ""%ls"" is defined recursively." + IDS_RECURSIVEINCLUDE "Error: Reursive include detected!\n%ls" + IDS_MATHEXCEPTION "Error in Expression:\n %ls\n\nDescription:\n %ls" IDS_LSAPI_INIT_ERROR "Failed to initialize the LiteStep API." IDS_LITESTEP_INIT_ERROR "Failed to initialize LiteStep.\nPlease contact the LiteStep development team.\n\nError code: 0x%.8X" @@ -263,12 +263,12 @@ BEGIN IDS_LITESTEP_TITLE_WARNING "Avertissement" IDS_LITESTEP_TITLE_ERROR "Erreur" IDS_LITESTEP_ERROR1 "Une instance de LiteStep existe déjà.\nVoulez-vous vraiment continuer?" - IDS_LITESTEP_ERROR2 "Impossible de trouver le fichier ""%s"".\nVeuillez vérifier\nl'emplacement du fichier." + IDS_LITESTEP_ERROR2 "Impossible de trouver le fichier ""%ls"".\nVeuillez vérifier\nl'emplacement du fichier." IDS_LITESTEP_ERROR3 "Vous utilisez présentement un autre Shell que LiteStep.\nBien que le Shell LiteStep ait la capacité de fonctionner\nen mode ""application standard"", nous ne conseillons pas\nce mode pour les utilisateurs inexpérimentés.\n\nSi vous continuez, quelques fonctionnalités de LiteStep,\ndont la zone d'icônes de notification, le bureau et la\nbarre des tâches, ne pourront pas fonctionner normalement.\n\nPour désactiver ce message, ajoutez \\'LSNoShellWarning\\'\ndans votre fichier step.rc.\n\nVoulez-vous continuer en mode application?" IDS_LITESTEP_ERROR4 "Erreur d'enregistrement de la window class principale de LiteStep." IDS_LITESTEP_ERROR5 "Erreur de création de la fenêtre principale d'application de LiteStep" IDS_LITESTEP_ERROR6 "Recycler est en pause, cliquez OK pour poursuivre." - IDS_LITESTEP_ERROR7 "%s n'a pu être chargé(e)." + IDS_LITESTEP_ERROR7 "%ls n'a pu être chargé(e)." IDS_LITESTEP_RECYCLELS "&Recycler LiteStep" IDS_LITESTEP_QUITLS "&Quitter LiteStep" IDS_LITESTEP_TERMINATELS "&Forcer l'arrêt de LiteStep" @@ -299,12 +299,12 @@ BEGIN IDS_LITESTEP_TITLE_WARNING "Waarschuwing." IDS_LITESTEP_TITLE_ERROR "Fout" IDS_LITESTEP_ERROR1 "Er is een andere instantie van LiteStep gedetecteerd.\nWeet u zeker dat u door wilt gaan?" - IDS_LITESTEP_ERROR2 "Het bestand ""%s"".\nVerifieer de locatie van het bestand en probeer opnieuw." + IDS_LITESTEP_ERROR2 "Het bestand ""%ls"".\nVerifieer de locatie van het bestand en probeer opnieuw." IDS_LITESTEP_ERROR3 "Op dit moment gebruikt u een andere grafische interface (gui).\nHoewel LiteStep bovenop de huidige GUI kan draaien, adviseren\nwe dat niet voor onervaren gebruikers.\n\nAls u doorgaat, zullen sommige van LiteStep's functies\nniet naar behoren werken zoals de taakbalk, het bureaublad\nen andere functies\n\nOm dit bericht voortaan niet meer te laten zien, plaatst\nu 'LSNoShellWarning' in uw step.rc.\n\nLiteStep toch starten?" IDS_LITESTEP_ERROR4 "Fout bij het registreren van de main LiteStep Window Class." IDS_LITESTEP_ERROR5 "Error creating LiteStep main application window." IDS_LITESTEP_ERROR6 "Recycle is gepauzeerd, klik op OK om door te gaan." - IDS_LITESTEP_ERROR7 "Unable to load %s." + IDS_LITESTEP_ERROR7 "Unable to load %ls." IDS_LITESTEP_RECYCLELS "&Hernieuw LiteStep" IDS_LITESTEP_QUITLS "&Stop LiteStep" IDS_LITESTEP_TERMINATELS "Forcibly &Terminate LiteStep" @@ -335,12 +335,12 @@ BEGIN IDS_LITESTEP_TITLE_WARNING "Varning" IDS_LITESTEP_TITLE_ERROR "Fel" IDS_LITESTEP_ERROR1 "En tidigare instans av LiteStep upptäcktes.\nÄr du säker på att du vill fortsätta?" - IDS_LITESTEP_ERROR2 "Kunde inte hitta filen ""%s"".\nKontrollera att filen existerar och försök igen." + IDS_LITESTEP_ERROR2 "Kunde inte hitta filen ""%ls"".\nKontrollera att filen existerar och försök igen." IDS_LITESTEP_ERROR3 "LiteStep kan inte starta som systemets skal.\nEtt annat skal körs redan.\n\nOm du väljer att fortsätta kommer vissa funktioner\ni LiteStep inte att fungera som det är tänkt, till\nexempel meddelandefältet, skrivbordet och vissa\naktivitetshanterare.\n\nFör att inaktivera detta meddelande, skriv\n'LSNoShellWarning' i din step.rc\n\nVill du fortfarande starta LiteStep?" IDS_LITESTEP_ERROR4 "Ett fel uppstod när klassen för huvudfönstret skulle registreras.Error registering main LiteStep window class." IDS_LITESTEP_ERROR5 "Kunde inte skapa huvudfönstret." IDS_LITESTEP_ERROR6 "Återvinning av inställningarna har pausats. Tryck på OK för att fortsätta." - IDS_LITESTEP_ERROR7 "Kunde inte ladda %s." + IDS_LITESTEP_ERROR7 "Kunde inte ladda %ls." IDS_LITESTEP_RECYCLELS "&Återvinn inställningar" IDS_LITESTEP_QUITLS "&Avsluta" IDS_LITESTEP_TERMINATELS "Avsluta med &våld." @@ -360,12 +360,12 @@ BEGIN "Ett fel inträffade under modul initialiseringen.\n\nKontakta modulens skapare." IDS_LITESTEP_CREATEWINDOW_ERROR "Misslyckades med att skapa fönstret." IDS_LITESTEP_BANGEXCEPTION - "Ett fel inträffade under exekvering av ett bang kommando.\nKontakta modulens skapare.\n\nBang parameterar: %s" + "Ett fel inträffade under exekvering av ett bang kommando.\nKontakta modulens skapare.\n\nBang parameterar: %ls" IDS_LITESTEP_REGISTERCLASS_ERROR "Misslyckades med att registrera fönter klassen." IDS_MODULEDEPENDENCY_ERROR "Fel: Kunde inte ladda modulen.\nTroligen saknas ett exekveringsbibliotek.\n\n" - IDS_RECURSIVEVAR "Fel: Variabeln ""%s"" är rekursivt definierad." - IDS_MATHEXCEPTION "Fel i uttrycket:\n %s\n\nDescription:\n %s" + IDS_RECURSIVEVAR "Fel: Variabeln ""%ls"" är rekursivt definierad." + IDS_MATHEXCEPTION "Fel i uttrycket:\n %ls\n\nDescription:\n %s" IDS_LSAPI_INIT_ERROR "Initaliseringen av LiteStep's API misslyckades." IDS_LITESTEP_INIT_ERROR "Initaliseringen av LiteStep misslyckades.\n\nFel kod: 0x%.8X" END diff --git a/litestep/litestep_vc11.vcxproj b/litestep/litestep_vc11.vcxproj index 70ae57a..04bc05b 100644 --- a/litestep/litestep_vc11.vcxproj +++ b/litestep/litestep_vc11.vcxproj @@ -36,17 +36,17 @@ Application Unicode true - v110 + v110_xp Application Unicode - v110 + v110_xp Application Unicode - v110 + v110_xp diff --git a/lsapi/MathEvaluate.cpp b/lsapi/MathEvaluate.cpp index 47a0353..ece9e71 100644 --- a/lsapi/MathEvaluate.cpp +++ b/lsapi/MathEvaluate.cpp @@ -42,7 +42,7 @@ bool MathEvaluateBool(const SettingsMap& context, const wstring& expression, GetModuleHandle(NULL), IDS_MATHEXCEPTION, resourceTextBuffer, MAX_LINE_LENGTH, L"Error in Expression:\n %ls\n\nDescription:\n %ls", - expression.c_str(), e.GetException()); + expression.c_str(), e.GetException().c_str()); RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); @@ -74,8 +74,8 @@ bool MathEvaluateString(const SettingsMap& context, const wstring& expression, RESOURCE_STREX( GetModuleHandle(NULL), IDS_MATHEXCEPTION, resourceTextBuffer, MAX_LINE_LENGTH, - L"Error in Expression:\n %s\n\nDescription:\n %s", - expression.c_str(), e.GetException()); + L"Error in Expression:\n %ls\n\nDescription:\n %ls", + expression.c_str(), e.GetException().c_str()); RESOURCE_MSGBOX_F(L"LiteStep", MB_ICONERROR); diff --git a/lsapi/MathParser.cpp b/lsapi/MathParser.cpp index 4f7a5be..399d0dc 100644 --- a/lsapi/MathParser.cpp +++ b/lsapi/MathParser.cpp @@ -114,6 +114,11 @@ static MathValue Math_lowerCase(const MathValueList& argList); static MathValue Math_max(const MathValueList& argList); static MathValue Math_min(const MathValueList& argList); static MathValue Math_number(const MathValueList& argList); +static MathValue Math_pathDirPart(const MathValueList& argList); +static MathValue Math_pathDrivePart(const MathValueList& argList); +static MathValue Math_pathExtPart(const MathValueList& argList); +static MathValue Math_pathFilePart(const MathValueList& argList); +static MathValue Math_pathFileNamePart(const MathValueList& argList); static MathValue Math_pow(const MathValueList& argList); static MathValue Math_round(const MathValueList& argList); static MathValue Math_startsWith(const MathValueList& argList); @@ -126,26 +131,31 @@ struct FunctionTable { const wchar_t *name; MathFunction function; unsigned int numArgs; } gFunctions[] = { - { L"abs", Math_abs, 1 }, - { L"boolean", Math_boolean, 1 }, - { L"ceil", Math_ceil, 1 }, - { L"contains", Math_contains, 2 }, - { L"endsWith", Math_endsWith, 2 }, - { L"fileExists", Math_fileExists, 1 }, - { L"floor", Math_floor, 1 }, - { L"if", Math_if, 3 }, - { L"integer", Math_integer, 1 }, - { L"length", Math_length, 1 }, - { L"lowerCase", Math_lowerCase, 1 }, - { L"max", Math_max, 2 }, - { L"min", Math_min, 2 }, - { L"number", Math_number, 1 }, - { L"pow", Math_pow, 2 }, - { L"round", Math_round, 1 }, - { L"startsWith", Math_startsWith, 2 }, - { L"string", Math_string, 1 }, - { L"sqrt", Math_sqrt, 1 }, - { L"upperCase", Math_upperCase, 1 } + { L"abs", Math_abs, 1 }, + { L"boolean", Math_boolean, 1 }, + { L"ceil", Math_ceil, 1 }, + { L"contains", Math_contains, 2 }, + { L"endsWith", Math_endsWith, 2 }, + { L"fileExists", Math_fileExists, 1 }, + { L"floor", Math_floor, 1 }, + { L"if", Math_if, 3 }, + { L"integer", Math_integer, 1 }, + { L"length", Math_length, 1 }, + { L"lowerCase", Math_lowerCase, 1 }, + { L"max", Math_max, 2 }, + { L"min", Math_min, 2 }, + { L"number", Math_number, 1 }, + { L"pathDirPart", Math_pathDirPart, 1 }, + { L"pathDrivePart", Math_pathDrivePart, 1 }, + { L"pathExtPart", Math_pathExtPart, 1 }, + { L"pathFilePart", Math_pathFilePart, 1 }, + { L"pathFileNamePart", Math_pathFileNamePart, 1 }, + { L"pow", Math_pow, 2 }, + { L"round", Math_round, 1 }, + { L"startsWith", Math_startsWith, 2 }, + { L"string", Math_string, 1 }, + { L"sqrt", Math_sqrt, 1 }, + { L"upperCase", Math_upperCase, 1 } }; const int gNumFunctions = sizeof(gFunctions) / sizeof(gFunctions[0]); @@ -225,7 +235,7 @@ MathValue MathParser::GetVariable(const wstring& name) const // Expand variable references wchar_t value[MAX_LINE_LENGTH]; g_LSAPIManager.GetSettingsManager()->VarExpansionEx( - value, (*it).second.c_str(), MAX_LINE_LENGTH, newRecursiveVarSet); + value, (*it).second.sValue.c_str(), MAX_LINE_LENGTH, newRecursiveVarSet); if (_wcsicmp(value, L"false") == 0 || _wcsicmp(value, L"off") == 0 || @@ -810,6 +820,60 @@ MathValue Math_number(const MathValueList& argList) } +// Path directory part +MathValue Math_pathDirPart(const MathValueList& argList) +{ + WCHAR wzPath[MAX_PATH]; + + StringCchCopy(wzPath, _countof(wzPath), argList[0].ToString().c_str()); + *(LPTSTR)PathFindFileName(wzPath) = _T('\0'); + + return wzPath; +} + + +// Path drive part +MathValue Math_pathDrivePart(const MathValueList& argList) +{ + WCHAR wzDrive[MAX_PATH]; + + StringCchCopy(wzDrive, _countof(wzDrive), argList[0].ToString().c_str()); + + return PathStripToRoot(wzDrive) != FALSE ? wzDrive : _T(""); +} + + +// Path extension part +MathValue Math_pathExtPart(const MathValueList& argList) +{ + WCHAR wzPath[MAX_PATH]; + + StringCchCopy(wzPath, _countof(wzPath), argList[0].ToString().c_str()); + + LPCTSTR ptzExtension = PathFindExtension(wzPath); + return *ptzExtension == _T('\0') ? ptzExtension : ptzExtension + 1; +} + + +// Path file part +MathValue Math_pathFilePart(const MathValueList& argList) +{ + return PathFindFileName(argList[0].ToString().c_str()); +} + + +// Path filename part +MathValue Math_pathFileNamePart(const MathValueList& argList) +{ + WCHAR wzPath[MAX_PATH]; + + StringCchCopy(wzPath, _countof(wzPath), argList[0].ToString().c_str()); + *(LPTSTR)PathFindExtension(wzPath) = _T('\0'); + + return PathFindFileName(wzPath); +} + + // Power MathValue Math_pow(const MathValueList& argList) { diff --git a/lsapi/SettingsDefines.h b/lsapi/SettingsDefines.h index 91c210f..16c5042 100644 --- a/lsapi/SettingsDefines.h +++ b/lsapi/SettingsDefines.h @@ -27,9 +27,21 @@ #include #include +/** */ +struct SettingValue +{ + SettingValue(std::wstring sValue, bool bTerminal) + { + this->sValue = sValue; + this->bTerminal = bTerminal; + } + + std::wstring sValue; + bool bTerminal; +}; /** Maps setting names to values */ -typedef std::multimap SettingsMap; +typedef std::multimap SettingsMap; /** Maps setting names to iterators */ typedef std::map IteratorMap; diff --git a/lsapi/SettingsFileParser.cpp b/lsapi/SettingsFileParser.cpp index d2c784f..206539f 100644 --- a/lsapi/SettingsFileParser.cpp +++ b/lsapi/SettingsFileParser.cpp @@ -226,7 +226,7 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) } else { - m_stPrefixes.pop(); + m_stPrefixes.pop_front(); } // Skip this line @@ -262,7 +262,7 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) || _tcsnicmp(ptzCurrent, _T("endif"), stEndConfig) == 0 )) { - StringCchCat(ptzName, MAX_RCCOMMAND, m_stPrefixes.top().tzString); + StringCchCat(ptzName, MAX_RCCOMMAND, m_stPrefixes.front().tzString); } // If the keyname is simply -, ignore it. @@ -290,8 +290,45 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) // Removing trailing whitespace and comments _StripString(ptzValueStart); - - StringCchCopy(ptzValue, MAX_LINE_LENGTH, ptzValueStart); + + DWORD cchRemaining = MAX_LINE_LENGTH; + + // If we have prefixes, check if the string contains any @'s + if (!m_stPrefixes.empty()) + { + LPTSTR ptzAtSearch; + while ((ptzAtSearch = _tcschr(ptzValueStart, _T('@'))) != nullptr) + { + // Copy this part of the value over. + DWORD nSize = (DWORD)(ptzAtSearch - ptzValueStart); + StringCchCopyN(ptzValue, cchRemaining, ptzValueStart, nSize); + cchRemaining -= nSize; + ptzValue += nSize; + + // Figure out how many levels up to go + auto prefix = m_stPrefixes.begin(); + for (; *(ptzAtSearch + 1) == _T('@'); ++ptzAtSearch) + { + if (prefix != m_stPrefixes.end()) + { + ++prefix; + } + } + + // Copy over the prefix. + if (prefix != m_stPrefixes.end()) + { + StringCchCopy(ptzValue, cchRemaining, prefix->tzString); + nSize = (DWORD)_tcslen(prefix->tzString); + ptzValue += nSize; + cchRemaining -= nSize; + } + + // Move our pointer past the @'s + ptzValueStart = ++ptzAtSearch; + } + } + StringCchCopy(ptzValue, cchRemaining, ptzValueStart); } bReturn = true; @@ -301,7 +338,7 @@ bool FileParser::_ReadLineFromFile(LPTSTR ptzName, LPTSTR ptzValue) { if (m_tzReadAhead[0] == '{') { - m_stPrefixes.push(TCStack(ptzName)); + m_stPrefixes.push_front(TCStack(ptzName)); // Skip these 2 lines. _ReadNextLine(m_tzReadAhead); @@ -528,7 +565,7 @@ void FileParser::_ProcessLine(LPCTSTR ptzName, LPCTSTR ptzValue) #endif // LS_CUSTOM_INCLUDEFOLDER else { - m_pSettingsMap->insert(SettingsMap::value_type(ptzName, ptzValue)); + m_pSettingsMap->insert(SettingsMap::value_type(ptzName, SettingValue(ptzValue, false))); } } diff --git a/lsapi/SettingsFileParser.h b/lsapi/SettingsFileParser.h index 9c33a0f..49f6494 100644 --- a/lsapi/SettingsFileParser.h +++ b/lsapi/SettingsFileParser.h @@ -24,7 +24,7 @@ #include "settingsdefines.h" #include "lsapidefines.h" -#include +#include #include #include @@ -113,7 +113,7 @@ class FileParser //: boost::noncopyable }; /** Stack of prefixes. */ - std::stack m_stPrefixes; + std::deque m_stPrefixes; /** The next line to be parsed by _ReadLineFromFile */ TCHAR m_tzReadAhead[MAX_LINE_LENGTH]; diff --git a/lsapi/SettingsIterator.cpp b/lsapi/SettingsIterator.cpp index 3d7172d..7c2b040 100644 --- a/lsapi/SettingsIterator.cpp +++ b/lsapi/SettingsIterator.cpp @@ -52,7 +52,7 @@ BOOL SettingsIterator::ReadNextLine(LPWSTR pwzValue, size_t cchValue) { StringCchCopyW(pwzValue, cchValue, m_pFileIterator->first.c_str()); StringCchCatW(pwzValue, cchValue, L" "); - StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.c_str()); + StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.sValue.c_str()); ++m_pFileIterator; bReturn = TRUE; } @@ -76,7 +76,7 @@ BOOL SettingsIterator::ReadNextCommand(LPWSTR pwzValue, size_t cchValue) { StringCchCopyW(pwzValue, cchValue, m_pFileIterator->first.c_str()); StringCchCatW(pwzValue, cchValue, L" "); - StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.c_str()); + StringCchCatW(pwzValue, cchValue, m_pFileIterator->second.sValue.c_str()); bReturn = TRUE; } @@ -155,7 +155,7 @@ BOOL SettingsIterator::ReadNextConfig(LPCWSTR pwzConfig, LPWSTR pwzValue, size_t { StringCchCopyW(pwzValue, cchValue, it->second->first.c_str()); StringCchCatW(pwzValue, cchValue, L" "); - StringCchCatW(pwzValue, cchValue, it->second->second.c_str()); + StringCchCatW(pwzValue, cchValue, it->second->second.sValue.c_str()); } } diff --git a/lsapi/SettingsManager.h b/lsapi/SettingsManager.h index dcc2979..72994ef 100644 --- a/lsapi/SettingsManager.h +++ b/lsapi/SettingsManager.h @@ -232,8 +232,9 @@ class SettingsManager * * @param pwzKeyName setting name * @param pwzValue new setting value + * @param bTerminal whether or not this is a terminal value */ - void SetVariable(LPCWSTR pwzKeyName, LPCWSTR pwzValue); + void SetVariable(LPCWSTR pwzKeyName, LPCWSTR pwzValue, bool bTerminal = false); /** * Opens a configuration file for sequential access to its contents. The diff --git a/lsapi/bangs.cpp b/lsapi/bangs.cpp index 8087221..231bce7 100644 --- a/lsapi/bangs.cpp +++ b/lsapi/bangs.cpp @@ -352,7 +352,10 @@ static void BangRun(HWND /* hCaller */, LPCWSTR pwzArgs) // Only handle bang commands ourselfs, as anything else will prevent the RunMRU from populating properly. if (pwzText[0] == L'!') { - LSExecuteW(nullptr, pwzText, SW_SHOWNORMAL); + WCHAR wzCommand[MAX_BANGCOMMAND]; + LPCWSTR pwzArgs = nullptr; + GetTokenW(pwzText, wzCommand, &pwzArgs, TRUE); + LSExecuteExW(nullptr, nullptr, wzCommand, pwzArgs, nullptr, 0); wParam = MAKEWPARAM(2, 0); // Click on cancel } free(pwzText); diff --git a/lsapi/lsapiInit.cpp b/lsapi/lsapiInit.cpp index d47e104..cfc6ab4 100644 --- a/lsapi/lsapiInit.cpp +++ b/lsapi/lsapiInit.cpp @@ -190,6 +190,11 @@ void LSAPIInit::setLitestepVars() PathQuoteSpacesW(wzTemp); pSM->SetVariable(L"username", wzTemp); } + + pSM->SetVariable(L"nl", L"\n", true); + pSM->SetVariable(L"cr", L"\r", true); + pSM->SetVariable(L"dollar", L"$", true); + pSM->SetVariable(L"at", L"@", true); pSM->SetVariable(L"bitbucket", L"::{645FF040-5081-101B-9F08-00AA002F954E}"); pSM->SetVariable(L"documents", L"::{450D8FBA-AD25-11D0-98A8-0800361B1103}"); diff --git a/lsapi/lsapi_vc11.vcxproj b/lsapi/lsapi_vc11.vcxproj index 354eef6..ae05807 100644 --- a/lsapi/lsapi_vc11.vcxproj +++ b/lsapi/lsapi_vc11.vcxproj @@ -36,17 +36,17 @@ DynamicLibrary Unicode true - v110 + v110_xp DynamicLibrary Unicode - v110 + v110_xp DynamicLibrary Unicode - v110 + v110_xp diff --git a/lsapi/settingsmanager.cpp b/lsapi/settingsmanager.cpp index df7e620..66b6d21 100644 --- a/lsapi/settingsmanager.cpp +++ b/lsapi/settingsmanager.cpp @@ -104,7 +104,7 @@ BOOL SettingsManager::GetRCString(LPCWSTR pwzKeyName, LPWSTR pwzValue, LPCWSTR p if (pwzValue) { wchar_t wzToken[MAX_LINE_LENGTH] = { 0 }; - GetTokenW(it->second.c_str(), wzToken, NULL, FALSE); + GetTokenW(it->second.sValue.c_str(), wzToken, NULL, FALSE); StringSet recursiveVarSet; recursiveVarSet.insert(pwzKeyName); @@ -146,7 +146,7 @@ BOOL SettingsManager::GetRCLine(LPCWSTR pwzKeyName, LPWSTR pwzValue, int nMaxLen // for compatibility reasons GetRCLine expands $evars$ StringSet recursiveVarSet; recursiveVarSet.insert(pwzKeyName); - VarExpansionEx(pwzValue, it->second.c_str(), + VarExpansionEx(pwzValue, it->second.sValue.c_str(), nMaxLen, recursiveVarSet); } } @@ -175,7 +175,7 @@ BOOL SettingsManager::GetRCBool(LPCWSTR pwzKeyName, BOOL bIfFound) StringSet recursiveVarSet; recursiveVarSet.insert(pwzKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) @@ -208,7 +208,7 @@ BOOL SettingsManager::GetRCBoolDef(LPCWSTR pwzKeyName, BOOL bDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pwzKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, NULL, FALSE)) @@ -240,7 +240,7 @@ __int64 SettingsManager::GetRCInt64(LPCWSTR pszKeyName, __int64 nDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) @@ -265,7 +265,7 @@ int SettingsManager::GetRCInt(LPCWSTR pszKeyName, int nDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) @@ -290,7 +290,7 @@ float SettingsManager::GetRCFloat(LPCWSTR pszKeyName, float fDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) @@ -315,7 +315,7 @@ double SettingsManager::GetRCDouble(LPCWSTR pszKeyName, double dDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(wzExpanded, it->second.c_str(), + VarExpansionEx(wzExpanded, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); if (GetTokenW(wzExpanded, wzToken, nullptr, FALSE)) @@ -344,7 +344,7 @@ COLORREF SettingsManager::GetRCColor(LPCWSTR pszKeyName, COLORREF crDefault) StringSet recursiveVarSet; recursiveVarSet.insert(pszKeyName); - VarExpansionEx(wzBuffer, it->second.c_str(), + VarExpansionEx(wzBuffer, it->second.sValue.c_str(), MAX_LINE_LENGTH, recursiveVarSet); int nCount = LCTokenizeW(wzBuffer, lpwzTokens, 3, nullptr); @@ -381,19 +381,20 @@ BOOL SettingsManager::GetVariable(LPCWSTR pszKeyName, LPWSTR pszValue, DWORD dwL } -void SettingsManager::SetVariable(LPCWSTR pszKeyName, LPCWSTR pszValue) +void SettingsManager::SetVariable(LPCWSTR pszKeyName, LPCWSTR pszValue, bool bTerminal) { - if ((pszKeyName) && (pszValue)) + if (pszKeyName && pszValue) { // in order for LSSetVariable to work evars must be redefinable SettingsMap::iterator it; if (_FindLine(pszKeyName, it)) { - it->second.assign(pszValue); + it->second.sValue.assign(pszValue); + it->second.bTerminal = bTerminal; } else { - m_SettingsMap.insert(SettingsMap::value_type(pszKeyName, pszValue)); + m_SettingsMap.insert(SettingsMap::value_type(pszKeyName, SettingValue(pszValue, bTerminal))); } } } @@ -483,12 +484,23 @@ void SettingsManager::VarExpansionEx(LPWSTR pwzExpandedString, LPCWSTR pwzTempla StringSet newRecursiveVarSet(recursiveVarSet); newRecursiveVarSet.insert(wzVariable); - // FIXME: Should we not call GetToken here?! - WCHAR wzTemp[MAX_LINE_LENGTH]; - GetTokenW(it->second.c_str(), wzTemp, NULL, FALSE); - - VarExpansionEx(pwzTempExpandedString, wzTemp, - (size_t)cchTempExpanded, newRecursiveVarSet); + // Don't call GetTokenW on terminals, because we don't want to strip + // Whitespace (in particular, for $nl$ and $cr$). + // Ok, since we define all terminals internally. + if (it->second.bTerminal) + { + StringCchCopyW(pwzTempExpandedString, (size_t)cchTempExpanded, + it->second.sValue.c_str()); + } + else + { + // FIXME: Should we not call GetToken here?! + WCHAR wzTemp[MAX_LINE_LENGTH]; + GetTokenW(it->second.sValue.c_str(), wzTemp, NULL, FALSE); + + VarExpansionEx(pwzTempExpandedString, wzTemp, + (size_t)cchTempExpanded, newRecursiveVarSet); + } bSucceeded = true; } diff --git a/utility/shellhlp.cpp b/utility/shellhlp.cpp index e25c137..26c707b 100644 --- a/utility/shellhlp.cpp +++ b/utility/shellhlp.cpp @@ -375,7 +375,6 @@ BOOL LSGUIDFromString(LPCTSTR guidString, LPGUID guid) } - // // LSGetModuleFileName // diff --git a/utility/utility_vc11.vcxproj b/utility/utility_vc11.vcxproj index 516680d..6936f89 100644 --- a/utility/utility_vc11.vcxproj +++ b/utility/utility_vc11.vcxproj @@ -36,17 +36,17 @@ StaticLibrary Unicode true - v110 + v110_xp StaticLibrary Unicode - v110 + v110_xp StaticLibrary Unicode - v110 + v110_xp