mirror of
https://github.com/Open-Shell/Open-Shell-Menu.git
synced 2026-04-17 13:23:04 +10:00
* Rebrand to Open-Shell * Slight installer branding improvement
This commit is contained in:
29
Src/Lib/Assert.cpp
Normal file
29
Src/Lib/Assert.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "StringUtils.h"
|
||||
|
||||
static DWORD _stdcall AssertThreadProc( void *param )
|
||||
{
|
||||
return MessageBoxA(NULL,(const char *)param,"Assertion Failed",MB_ABORTRETRYIGNORE|MB_TASKMODAL|MB_ICONERROR);
|
||||
}
|
||||
|
||||
// debug assert
|
||||
bool dbg_assert( const char *exp, const char *file, unsigned line )
|
||||
{
|
||||
char buf[2048];
|
||||
Sprintf(buf,_countof(buf),"Expression: %s\r\nFile: %s\r\nLine: %d\n",exp,file,line);
|
||||
HANDLE h=CreateThread(NULL,0,AssertThreadProc,buf,0,NULL);
|
||||
if (h)
|
||||
{
|
||||
WaitForSingleObject(h,INFINITE);
|
||||
DWORD res=IDRETRY;
|
||||
GetExitCodeThread(h,&res);
|
||||
if (res==IDABORT)
|
||||
TerminateProcess(GetCurrentProcess(),1);
|
||||
return (res==IDIGNORE); // true will continue, false will cause _CrtDbgBreak
|
||||
}
|
||||
return true;
|
||||
}
|
||||
16
Src/Lib/Assert.h
Normal file
16
Src/Lib/Assert.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
bool dbg_assert( const char *exp, const char *file, unsigned line );
|
||||
#define Assert(exp) do { if (!(exp) && !dbg_assert(#exp,__FILE__,__LINE__)) _CrtDbgBreak(); } while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define Assert(exp) ((void)0)
|
||||
|
||||
#endif
|
||||
45
Src/Lib/ComHelper.h
Normal file
45
Src/Lib/ComHelper.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shlobj.h>
|
||||
#include "Assert.h"
|
||||
|
||||
class CAbsolutePidl
|
||||
{
|
||||
public:
|
||||
CAbsolutePidl( void ) { m_Pidl=NULL; }
|
||||
CAbsolutePidl( const CAbsolutePidl &pidl ) { m_Pidl=pidl?ILCloneFull(pidl):NULL; }
|
||||
~CAbsolutePidl( void ) { Clear(); }
|
||||
void operator=( const CAbsolutePidl &pidl ) { Clone(pidl); }
|
||||
|
||||
void Clear( void ) { if (m_Pidl) ILFree(m_Pidl); m_Pidl=NULL; }
|
||||
operator PIDLIST_ABSOLUTE( void ) const { return m_Pidl; }
|
||||
PIDLIST_ABSOLUTE* operator&( void ) { Assert(m_Pidl==NULL); return &m_Pidl; }
|
||||
void Swap( CAbsolutePidl &pidl ) { PIDLIST_ABSOLUTE q=pidl.m_Pidl; pidl.m_Pidl=m_Pidl; m_Pidl=q; }
|
||||
void Attach( PIDLIST_ABSOLUTE pidl ) { Clear(); m_Pidl=pidl; }
|
||||
PIDLIST_ABSOLUTE Detach( void ) { PIDLIST_ABSOLUTE pidl=m_Pidl; m_Pidl=NULL; return pidl; }
|
||||
void Clone( PIDLIST_ABSOLUTE pidl ) { Clear(); m_Pidl=pidl?ILCloneFull(pidl):NULL; }
|
||||
|
||||
private:
|
||||
PIDLIST_ABSOLUTE m_Pidl;
|
||||
};
|
||||
|
||||
class CComString
|
||||
{
|
||||
public:
|
||||
CComString( void ) { m_String=NULL; }
|
||||
~CComString( void ) { Clear(); }
|
||||
|
||||
void Clear( void ) { if (m_String) CoTaskMemFree(m_String); m_String=NULL; }
|
||||
operator const wchar_t*( void ) const { return m_String; }
|
||||
wchar_t** operator&( void ) { Assert(m_String==NULL); return &m_String; }
|
||||
void MakeUpper( void ) { if (m_String) CharUpper(m_String); }
|
||||
|
||||
private:
|
||||
CComString( const CComString &str );
|
||||
void operator=( const CComString &str );
|
||||
wchar_t *m_String;
|
||||
};
|
||||
1145
Src/Lib/DownloadHelper.cpp
Normal file
1145
Src/Lib/DownloadHelper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
72
Src/Lib/DownloadHelper.h
Normal file
72
Src/Lib/DownloadHelper.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
enum TVersionCheck
|
||||
{
|
||||
CHECK_AUTO,
|
||||
CHECK_AUTO_WAIT,
|
||||
CHECK_UPDATE,
|
||||
};
|
||||
|
||||
enum TSettingsComponent;
|
||||
|
||||
struct LanguageVersionData
|
||||
{
|
||||
CString language;
|
||||
CString url;
|
||||
DWORD version;
|
||||
DWORD build;
|
||||
DWORD hash;
|
||||
bool bBasic;
|
||||
WORD languageId;
|
||||
HBITMAP bitmap;
|
||||
|
||||
LanguageVersionData( void ) { bBasic=false; bitmap=NULL; }
|
||||
};
|
||||
|
||||
struct VersionData
|
||||
{
|
||||
bool bValid;
|
||||
DWORD newVersion;
|
||||
DWORD encodedLangVersion;
|
||||
CString downloadUrl;
|
||||
CString downloadSigner;
|
||||
CString news;
|
||||
CString updateLink;
|
||||
CString languageLink;
|
||||
CString altUrl;
|
||||
bool bNewVersion;
|
||||
bool bIgnoreVersion;
|
||||
bool bNewLanguage;
|
||||
bool bIgnoreLanguage;
|
||||
CString newLanguage;
|
||||
std::vector<LanguageVersionData> languages;
|
||||
|
||||
~VersionData( void ) { Clear(); }
|
||||
void Clear( void );
|
||||
void Swap( VersionData &data );
|
||||
|
||||
enum TLoadResult
|
||||
{
|
||||
LOAD_OK,
|
||||
LOAD_ERROR, // the file is missing some data
|
||||
LOAD_BAD_VERSION, // the version is wrong
|
||||
LOAD_BAD_FILE, // the file is corrupted
|
||||
};
|
||||
|
||||
TLoadResult Load( const wchar_t *fname, bool bLoadFlags );
|
||||
private:
|
||||
void operator=( const VersionData& );
|
||||
};
|
||||
|
||||
typedef void (*tNewVersionCallback)( VersionData &data );
|
||||
|
||||
// 0 - fail, 1 - success, 2 - cancel
|
||||
DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionCheck check, tNewVersionCallback callback );
|
||||
DWORD DownloadLanguageDll( HWND owner, TSettingsComponent component, const LanguageVersionData &data, CString &error );
|
||||
DWORD DownloadNewVersion( HWND owner, TSettingsComponent component, const wchar_t *url, const wchar_t *signer, CString &fname, CString &error );
|
||||
29
Src/Lib/FNVHash.cpp
Normal file
29
Src/Lib/FNVHash.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "FNVHash.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
// FNV hash algorithm as described here: http://www.isthe.com/chongo/tech/comp/fnv/index.html
|
||||
|
||||
// Calculate FNV hash for a memory buffer
|
||||
unsigned int CalcFNVHash( const void *buf, int len, unsigned int hash )
|
||||
{
|
||||
for (int i=0;i<len;i++)
|
||||
hash=(hash^((const unsigned char*)buf)[i])*16777619;
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Calculate FNV hash for a string
|
||||
unsigned int CalcFNVHash( const char *text, unsigned int hash )
|
||||
{
|
||||
return CalcFNVHash(text,Strlen(text),hash);
|
||||
}
|
||||
|
||||
// Calculate FNV hash for a wide string
|
||||
unsigned int CalcFNVHash( const wchar_t *text, unsigned int hash )
|
||||
{
|
||||
return CalcFNVHash(text,Strlen(text)*2,hash);
|
||||
}
|
||||
16
Src/Lib/FNVHash.h
Normal file
16
Src/Lib/FNVHash.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
const unsigned int FNV_HASH0=2166136261;
|
||||
|
||||
// Calculate FNV hash for a memory buffer
|
||||
unsigned int CalcFNVHash( const void *buf, int len, unsigned int hash=FNV_HASH0 );
|
||||
|
||||
// Calculate FNV hash for a string
|
||||
unsigned int CalcFNVHash( const char *text, unsigned int hash=FNV_HASH0 );
|
||||
|
||||
// Calculate FNV hash for a wide string
|
||||
unsigned int CalcFNVHash( const wchar_t *text, unsigned int hash=FNV_HASH0 );
|
||||
62
Src/Lib/FileHelper.cpp
Normal file
62
Src/Lib/FileHelper.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "stdafx.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
bool CreateFakeFolder( const wchar_t *source, const wchar_t *fname )
|
||||
{
|
||||
// create directory
|
||||
CreateDirectory(fname,NULL);
|
||||
if (!SetFileAttributes(fname,FILE_ATTRIBUTE_READONLY))
|
||||
return false;
|
||||
|
||||
// create shortcut
|
||||
wchar_t path[_MAX_PATH];
|
||||
Sprintf(path,_countof(path),L"%s\\target.lnk",fname);
|
||||
{
|
||||
CComPtr<IShellLink> pLink;
|
||||
HRESULT hr=pLink.CoCreateInstance(CLSID_ShellLink);
|
||||
if (FAILED(hr)) return false;
|
||||
pLink->SetPath(source);
|
||||
CComQIPtr<IPersistFile> pFile=pLink;
|
||||
if (!pFile) return false;
|
||||
hr=pFile->Save(path,TRUE);
|
||||
if (FAILED(hr)) return false;
|
||||
}
|
||||
|
||||
// create desktop.ini
|
||||
Sprintf(path,_countof(path),L"%s\\desktop.ini",fname);
|
||||
HANDLE f=CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL);
|
||||
if (f==INVALID_HANDLE_VALUE) return false;
|
||||
const char *desktopIni="[.ShellClassInfo]\r\nCLSID2={0AFACED1-E828-11D1-9187-B532F1E9575D}\r\nFlags=2\r\n";
|
||||
DWORD q;
|
||||
WriteFile(f,desktopIni,Strlen(desktopIni),&q,NULL);
|
||||
CloseHandle(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeleteFakeFolder( const wchar_t *fname )
|
||||
{
|
||||
wchar_t path[_MAX_PATH];
|
||||
Sprintf(path,_countof(path),L"%s\\target.lnk",fname);
|
||||
BOOL res;
|
||||
res=SetFileAttributes(path,GetFileAttributes(path)&~FILE_ATTRIBUTE_READONLY);
|
||||
res=DeleteFile(path);
|
||||
Sprintf(path,_countof(path),L"%s\\desktop.ini",fname);
|
||||
res=SetFileAttributes(path,GetFileAttributes(path)&~FILE_ATTRIBUTE_READONLY);
|
||||
res=DeleteFile(path);
|
||||
res=SetFileAttributes(fname,GetFileAttributes(fname)&~FILE_ATTRIBUTE_READONLY);
|
||||
res=RemoveDirectory(fname);
|
||||
}
|
||||
|
||||
bool IsFakeFolder( const wchar_t *fname )
|
||||
{
|
||||
wchar_t path[_MAX_PATH];
|
||||
Sprintf(path,_countof(path),L"%s\\target.lnk",fname);
|
||||
if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
Sprintf(path,_countof(path),L"%s\\desktop.ini",fname);
|
||||
DWORD attrib=GetFileAttributes(path);
|
||||
if (attrib!=INVALID_FILE_ATTRIBUTES && (attrib&FILE_ATTRIBUTE_SYSTEM))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
9
Src/Lib/FileHelper.h
Normal file
9
Src/Lib/FileHelper.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
bool CreateFakeFolder( const wchar_t *source, const wchar_t *fname );
|
||||
void DeleteFakeFolder( const wchar_t *fname );
|
||||
bool IsFakeFolder( const wchar_t *fname );
|
||||
144
Src/Lib/IatHookHelper.cpp
Normal file
144
Src/Lib/IatHookHelper.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "IatHookHelper.h"
|
||||
#include "Assert.h"
|
||||
|
||||
struct ImgDelayDescr
|
||||
{
|
||||
DWORD grAttrs; // attributes
|
||||
DWORD rvaDLLName; // RVA to dll name
|
||||
DWORD rvaHmod; // RVA of module handle
|
||||
DWORD rvaIAT; // RVA of the IAT
|
||||
DWORD rvaINT; // RVA of the INT
|
||||
DWORD rvaBoundIAT; // RVA of the optional bound IAT
|
||||
DWORD rvaUnloadIAT; // RVA of optional copy of original IAT
|
||||
DWORD dwTimeStamp; // 0 if not bound, O.W. date/time stamp of DLL bound to (Old BIND)
|
||||
};
|
||||
|
||||
static void *PtrFromRva( IMAGE_DOS_HEADER *dosHeader, size_t offset )
|
||||
{
|
||||
return (BYTE*)dosHeader+offset;
|
||||
}
|
||||
|
||||
static IatHookData *g_IatHooks;
|
||||
static int g_IatHookCount;
|
||||
|
||||
const int MAX_IAT_HOOKS=4096/sizeof(IatHookData);
|
||||
|
||||
void InitializeIatHooks( void )
|
||||
{
|
||||
Assert(!g_IatHooks);
|
||||
g_IatHooks=(IatHookData*)VirtualAlloc(NULL,4096,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
|
||||
g_IatHookCount=0;
|
||||
}
|
||||
|
||||
void ClearIatHooks( void )
|
||||
{
|
||||
if (!g_IatHooks) return;
|
||||
for (int i=0;i<g_IatHookCount;i++)
|
||||
{
|
||||
if (g_IatHooks[i].jump[0])
|
||||
return; // still used
|
||||
}
|
||||
VirtualFree(g_IatHooks,0,MEM_RELEASE);
|
||||
g_IatHooks=NULL;
|
||||
g_IatHookCount=0;
|
||||
}
|
||||
|
||||
IatHookData *SetIatHook( IMAGE_DOS_HEADER *dosHeader, DWORD iatOffset, DWORD intOfset, const char *targetProc, void *newProc )
|
||||
{
|
||||
IMAGE_THUNK_DATA *thunk=(IMAGE_THUNK_DATA*)PtrFromRva(dosHeader,iatOffset);
|
||||
IMAGE_THUNK_DATA *origThunk=(IMAGE_THUNK_DATA*)PtrFromRva(dosHeader,intOfset);
|
||||
for (;origThunk->u1.Function;origThunk++,thunk++)
|
||||
{
|
||||
if (origThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG)
|
||||
{
|
||||
if (IS_INTRESOURCE(targetProc) && IMAGE_ORDINAL(origThunk->u1.Ordinal)==(uintptr_t)targetProc)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
IMAGE_IMPORT_BY_NAME *import=(IMAGE_IMPORT_BY_NAME*)PtrFromRva(dosHeader,origThunk->u1.AddressOfData);
|
||||
if (!IS_INTRESOURCE(targetProc) && strcmp(targetProc,(char*)import->Name)==0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (origThunk->u1.Function)
|
||||
{
|
||||
IatHookData *hook=g_IatHooks+g_IatHookCount;
|
||||
g_IatHookCount++;
|
||||
hook->jump[0]=hook->jump[1]=0x90; // NOP
|
||||
hook->jump[2]=0xFF; hook->jump[3]=0x25; // JUMP
|
||||
#ifdef _WIN64
|
||||
hook->jumpOffs=0;
|
||||
#else
|
||||
hook->jumpOffs=(DWORD)(hook)+8;
|
||||
#endif
|
||||
hook->newProc=newProc;
|
||||
hook->oldProc=(void*)thunk->u1.Function;
|
||||
hook->thunk=thunk;
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(&thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect);
|
||||
thunk->u1.Function=(DWORD_PTR)hook;
|
||||
VirtualProtect(&thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect);
|
||||
return hook;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IatHookData *SetIatHook( HMODULE hPatchedModule, const char *targetModule, const char *targetProc, void *newProc )
|
||||
{
|
||||
ATLASSERT(g_IatHooks);
|
||||
if (g_IatHookCount>=MAX_IAT_HOOKS) return NULL;
|
||||
IMAGE_DOS_HEADER *dosHeader=(IMAGE_DOS_HEADER*)hPatchedModule;
|
||||
IMAGE_NT_HEADERS *ntHeader=(IMAGE_NT_HEADERS*)PtrFromRva(dosHeader,dosHeader->e_lfanew);
|
||||
if (ntHeader->Signature!=IMAGE_NT_SIGNATURE) return NULL;
|
||||
|
||||
IMAGE_IMPORT_DESCRIPTOR *importDescriptor=(IMAGE_IMPORT_DESCRIPTOR*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||
|
||||
for (;importDescriptor->Characteristics!=0;importDescriptor++)
|
||||
{
|
||||
const char *dllName=(char*)PtrFromRva(dosHeader,importDescriptor->Name);
|
||||
if (_stricmp(dllName,targetModule)!=0) continue;
|
||||
|
||||
if (!importDescriptor->FirstThunk || !importDescriptor->OriginalFirstThunk) break;
|
||||
|
||||
return SetIatHook(dosHeader,importDescriptor->FirstThunk,importDescriptor->OriginalFirstThunk,targetProc,newProc);
|
||||
}
|
||||
|
||||
ImgDelayDescr *delayDescriptor=(ImgDelayDescr*)PtrFromRva(dosHeader,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress);
|
||||
|
||||
for (;delayDescriptor->rvaDLLName!=0;delayDescriptor++)
|
||||
{
|
||||
const char *dllName=(char*)PtrFromRva(dosHeader,delayDescriptor->rvaDLLName);
|
||||
if (_stricmp(dllName,targetModule)!=0) continue;
|
||||
|
||||
if (!delayDescriptor->rvaIAT || !delayDescriptor->rvaINT) break;
|
||||
|
||||
return SetIatHook(dosHeader,delayDescriptor->rvaIAT,delayDescriptor->rvaINT,targetProc,newProc);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ClearIatHook( IatHookData *hook )
|
||||
{
|
||||
if (!hook || !hook->jump[0]) return;
|
||||
if (hook->thunk->u1.Function==(DWORD_PTR)hook)
|
||||
{
|
||||
// the hook was untouched by anybody else
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),PAGE_READWRITE,&oldProtect);
|
||||
void *cex=InterlockedCompareExchangePointer((void**)&hook->thunk->u1.Function,hook->oldProc,hook);
|
||||
VirtualProtect(&hook->thunk->u1.Function,sizeof(void*),oldProtect,&oldProtect);
|
||||
if (cex==hook)
|
||||
{
|
||||
hook->jump[0]=0;
|
||||
return; // successfully replaced the original function
|
||||
}
|
||||
}
|
||||
// failed to replace the original function, leave behind the thunk
|
||||
hook->newProc=hook->oldProc;
|
||||
}
|
||||
19
Src/Lib/IatHookHelper.h
Normal file
19
Src/Lib/IatHookHelper.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
struct IatHookData
|
||||
{
|
||||
unsigned char jump[4]; // jump instruction 0x90, 0x90, 0xFF, 0x25
|
||||
DWORD jumpOffs; // jump instruction offset
|
||||
void *newProc; // the address of the new proc
|
||||
void *oldProc; // the address of the old proc
|
||||
IMAGE_THUNK_DATA *thunk; // the IAT thunk
|
||||
};
|
||||
|
||||
void InitializeIatHooks( void );
|
||||
IatHookData *SetIatHook( HMODULE hPatchedModule, const char *targetModule, const char *targetProc, void *newProc );
|
||||
void ClearIatHook( IatHookData *hook );
|
||||
void ClearIatHooks( void );
|
||||
7
Src/Lib/Instance.cpp
Normal file
7
Src/Lib/Instance.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
|
||||
HINSTANCE g_Instance;
|
||||
601
Src/Lib/LanguageSettingsHelper.cpp
Normal file
601
Src/Lib/LanguageSettingsHelper.cpp
Normal file
@@ -0,0 +1,601 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "resource.h"
|
||||
#include "Settings.h"
|
||||
#include "SettingsUIHelper.h"
|
||||
#include "ResourceHelper.h"
|
||||
#include "ComHelper.h"
|
||||
#include "FNVHash.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Translations.h"
|
||||
#include "DownloadHelper.h"
|
||||
#include <uxtheme.h>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
int g_LanguageIDs[]={
|
||||
0x0401,
|
||||
0x0402,
|
||||
0x0403,
|
||||
0x0405,
|
||||
0x0406,
|
||||
0x0407,
|
||||
0x0408,
|
||||
0x0409,
|
||||
0x0C0A,
|
||||
0x0425,
|
||||
0x0429,
|
||||
0x040B,
|
||||
0x040C,
|
||||
0x0491,
|
||||
0x040D,
|
||||
0x041A,
|
||||
0x040E,
|
||||
0x040F,
|
||||
0x0410,
|
||||
0x0411,
|
||||
0x0412,
|
||||
0x0427,
|
||||
0x0426,
|
||||
0x0414,
|
||||
0x0413,
|
||||
0x0415,
|
||||
0x0416,
|
||||
0x0816,
|
||||
0x0418,
|
||||
0x0419,
|
||||
0x041B,
|
||||
0x0424,
|
||||
0x081A,
|
||||
0x041D,
|
||||
0x041E,
|
||||
0x041F,
|
||||
0x0422,
|
||||
0x0804,
|
||||
0x0C04,
|
||||
0x0404,
|
||||
};
|
||||
|
||||
int g_LanguageIDCount=_countof(g_LanguageIDs);
|
||||
|
||||
class CLanguageSettingsDlg: public CResizeableDlg<CLanguageSettingsDlg>
|
||||
{
|
||||
public:
|
||||
BEGIN_MSG_MAP( CLanguageSettingsDlg )
|
||||
MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog )
|
||||
MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
|
||||
MESSAGE_HANDLER( WM_SIZE, OnSize )
|
||||
COMMAND_ID_HANDLER( IDC_BUTTONCHECK, OnCheckUpdates )
|
||||
NOTIFY_HANDLER( IDC_LISTLANGUAGE, LVN_ITEMCHANGED, OnSelChange )
|
||||
NOTIFY_HANDLER( IDC_LISTLANGUAGE, LVN_ITEMCHANGING, OnSelChanging )
|
||||
NOTIFY_HANDLER( IDC_LISTLANGUAGE, NM_CUSTOMDRAW, OnCustomDraw )
|
||||
NOTIFY_HANDLER( IDC_LINKDOWNLOAD, NM_CLICK, OnDownload )
|
||||
END_MSG_MAP()
|
||||
|
||||
BEGIN_RESIZE_MAP
|
||||
RESIZE_CONTROL(IDC_LISTLANGUAGE,MOVE_SIZE_X|MOVE_SIZE_Y)
|
||||
RESIZE_CONTROL(IDC_BUTTONCHECK,MOVE_MOVE_Y)
|
||||
RESIZE_CONTROL(IDC_LINKDOWNLOAD,MOVE_SIZE_X|MOVE_MOVE_Y)
|
||||
END_RESIZE_MAP
|
||||
|
||||
void SetGroup( CSetting *pGroup );
|
||||
void SetComponent( TSettingsComponent component ) { m_Component=component; }
|
||||
|
||||
protected:
|
||||
// Handler prototypes:
|
||||
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
|
||||
LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnCheckUpdates( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
|
||||
LRESULT OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnDownload( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
|
||||
private:
|
||||
CSetting *m_pSetting;
|
||||
TSettingsComponent m_Component;
|
||||
CWindow m_Tooltip;
|
||||
HIMAGELIST m_ImageList;
|
||||
bool m_bLargeFlags;
|
||||
bool m_bLocked;
|
||||
|
||||
struct LangInfo
|
||||
{
|
||||
CString name;
|
||||
int id;
|
||||
int image;
|
||||
bool operator<( const LangInfo &info ) { return _wcsicmp(name,info.name)<0; }
|
||||
};
|
||||
std::vector<LangInfo> m_LanguageIDs; // the order matches the items in the listbox
|
||||
static VersionData s_VersionData;
|
||||
static void NewVersionCallback( VersionData &data );
|
||||
|
||||
void UpdateFlags( void );
|
||||
void UpdateLink( const wchar_t *language );
|
||||
|
||||
void AddFlag( const wchar_t *langName, int langId, HBITMAP bmp );
|
||||
};
|
||||
|
||||
VersionData CLanguageSettingsDlg::s_VersionData;
|
||||
|
||||
void CLanguageSettingsDlg::AddFlag( const wchar_t *langName, int langId, HBITMAP bmp )
|
||||
{
|
||||
std::vector<LangInfo>::iterator it=m_LanguageIDs.begin()+1;
|
||||
int idx=1;
|
||||
for (;idx<(int)m_LanguageIDs.size();idx++)
|
||||
{
|
||||
if (_wcsicmp(langName,m_LanguageIDs[idx].name)<=0)
|
||||
break;
|
||||
}
|
||||
if (idx==(int)m_LanguageIDs.size() || _wcsicmp(langName,m_LanguageIDs[idx].name)<0)
|
||||
{
|
||||
LangInfo info;
|
||||
info.id=langId;
|
||||
info.image=ImageList_AddMasked(m_ImageList,bmp,0xFF00FF);
|
||||
info.name=langName;
|
||||
m_LanguageIDs.insert(m_LanguageIDs.begin()+idx,info);
|
||||
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
wchar_t name[256];
|
||||
GetLocaleInfo(info.id,LOCALE_SLANGUAGE,name,_countof(name));
|
||||
wchar_t text[256];
|
||||
Sprintf(text,_countof(text),L"%s - %s",info.name,name);
|
||||
LVITEM item={LVIF_IMAGE|LVIF_TEXT};
|
||||
item.iItem=idx;
|
||||
item.iImage=info.image;
|
||||
item.pszText=text;
|
||||
ListView_InsertItem(list,&item);
|
||||
}
|
||||
}
|
||||
|
||||
void CLanguageSettingsDlg::UpdateFlags( void )
|
||||
{
|
||||
// add flags from s_VersionData
|
||||
for (std::vector<LanguageVersionData>::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it)
|
||||
{
|
||||
if (it->bitmap)
|
||||
{
|
||||
BITMAPINFO bi={0};
|
||||
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biWidth=m_bLargeFlags?32:24;
|
||||
bi.bmiHeader.biHeight=m_bLargeFlags?16:11;
|
||||
bi.bmiHeader.biPlanes=1;
|
||||
bi.bmiHeader.biBitCount=32;
|
||||
|
||||
HDC hdc=CreateCompatibleDC(NULL);
|
||||
HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,NULL,NULL,0);
|
||||
HGDIOBJ bmp0=SelectObject(hdc,bmp);
|
||||
HDC hsrc=CreateCompatibleDC(hdc);
|
||||
HGDIOBJ bmp02=SelectObject(hsrc,it->bitmap);
|
||||
SetDCBrushColor(hdc,0xFF00FF);
|
||||
RECT rc={0,0,bi.bmiHeader.biWidth,bi.bmiHeader.biHeight};
|
||||
FillRect(hdc,&rc,(HBRUSH)GetStockObject(DC_BRUSH));
|
||||
if (m_bLargeFlags)
|
||||
BitBlt(hdc,3,0,22,16,hsrc,0,11,SRCCOPY);
|
||||
else
|
||||
BitBlt(hdc,2,0,16,11,hsrc,0,0,SRCCOPY);
|
||||
SelectObject(hsrc,bmp02);
|
||||
DeleteDC(hsrc);
|
||||
SelectObject(hdc,bmp0);
|
||||
DeleteDC(hdc);
|
||||
AddFlag(it->language,it->languageId,bmp);
|
||||
DeleteObject(bmp);
|
||||
}
|
||||
}
|
||||
|
||||
// add flags from dlls
|
||||
for (int pass=0;pass<2;pass++)
|
||||
{
|
||||
wchar_t path[_MAX_PATH];
|
||||
if (pass==0)
|
||||
{
|
||||
GetModuleFileName(g_Instance,path,_countof(path));
|
||||
*PathFindFileName(path)=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Strcpy(path,_countof(path),L"%ALLUSERSPROFILE%\\OpenShell\\Languages");
|
||||
DoEnvironmentSubst(path,_countof(path));
|
||||
}
|
||||
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
|
||||
wchar_t find[_MAX_PATH];
|
||||
Sprintf(find,_countof(find),L"%s\\*.dll",path);
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h=FindFirstFile(find,&data);
|
||||
while (h!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!(data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && wcschr(data.cFileName,'-'))
|
||||
{
|
||||
wchar_t fname[_MAX_PATH];
|
||||
Sprintf(fname,_countof(fname),L"%s\\%s",path,data.cFileName);
|
||||
wchar_t language[_MAX_PATH];
|
||||
Strcpy(language,_countof(language),data.cFileName);
|
||||
PathRemoveExtension(language);
|
||||
|
||||
bool bFound=false;
|
||||
for (std::vector<LangInfo>::const_iterator it=m_LanguageIDs.begin();it!=m_LanguageIDs.end();++it)
|
||||
{
|
||||
if (_wcsicmp(it->name,language)==0)
|
||||
{
|
||||
bFound=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int langId=0;
|
||||
if (!bFound && GetLocaleInfoEx(language,LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER,(LPWSTR)&langId,4))
|
||||
{
|
||||
HINSTANCE hModule=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
if (hModule)
|
||||
{
|
||||
HBITMAP bmp;
|
||||
if (m_bLargeFlags)
|
||||
bmp=(HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(1),IMAGE_BITMAP,32,16,LR_CREATEDIBSECTION);
|
||||
else
|
||||
bmp=(HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(2),IMAGE_BITMAP,24,11,LR_CREATEDIBSECTION);
|
||||
if (bmp)
|
||||
{
|
||||
AddFlag(language,langId,bmp);
|
||||
DeleteObject(bmp);
|
||||
}
|
||||
FreeLibrary(hModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!FindNextFile(h,&data))
|
||||
{
|
||||
FindClose(h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
|
||||
{
|
||||
m_bLocked=false;
|
||||
InitResize();
|
||||
EnableThemeDialogTexture(m_hWnd,ETDT_ENABLETAB);
|
||||
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
if (IsAppThemed())
|
||||
SetWindowTheme(list,L"Explorer",NULL);
|
||||
HBITMAP bmp;
|
||||
HDC hdc=::GetDC(NULL);
|
||||
int dpi=GetDeviceCaps(hdc,LOGPIXELSY);
|
||||
::ReleaseDC(NULL,hdc);
|
||||
m_bLargeFlags=dpi>=144;
|
||||
if (m_bLargeFlags)
|
||||
{
|
||||
m_ImageList=ImageList_Create(32,16,ILC_COLOR24|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,0);
|
||||
bmp=(HBITMAP)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDB_FLAGS24),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ImageList=ImageList_Create(24,11,ILC_COLOR24|ILC_MASK|(IsLanguageRTL()?ILC_MIRROR:0),0,0);
|
||||
bmp=(HBITMAP)LoadImage(_AtlBaseModule.GetResourceInstance(),MAKEINTRESOURCE(IDB_FLAGS),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
|
||||
}
|
||||
ImageList_AddMasked(m_ImageList,bmp,0xFF00FF);
|
||||
DeleteObject(bmp);
|
||||
ListView_SetImageList(list,m_ImageList,LVSIL_SMALL);
|
||||
RECT rc;
|
||||
list.GetWindowRect(&rc);
|
||||
ListView_SetExtendedListViewStyleEx(list,LVS_EX_DOUBLEBUFFER,LVS_EX_DOUBLEBUFFER);
|
||||
LVCOLUMN column={LVCF_WIDTH,0,rc.right-rc.left};
|
||||
ListView_InsertColumn(list,0,&column);
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,L"");
|
||||
|
||||
m_LanguageIDs.resize(_countof(g_LanguageIDs)+1);
|
||||
{
|
||||
wchar_t languages[100]={0};
|
||||
ULONG size=0;
|
||||
ULONG len=_countof(languages);
|
||||
GetUserPreferredUILanguages(MUI_LANGUAGE_ID,&size,languages,&len);
|
||||
wchar_t *end;
|
||||
m_LanguageIDs[0].id=wcstol(languages,&end,16);
|
||||
m_LanguageIDs[0].image=I_IMAGENONE;
|
||||
}
|
||||
|
||||
for (int i=0;i<=(int)_countof(g_LanguageIDs);i++)
|
||||
{
|
||||
if (i>0)
|
||||
{
|
||||
m_LanguageIDs[i].id=g_LanguageIDs[i-1];
|
||||
m_LanguageIDs[i].image=i-1;
|
||||
}
|
||||
wchar_t name[256];
|
||||
GetLocaleInfo(m_LanguageIDs[i].id,LOCALE_SNAME,name,_countof(name));
|
||||
m_LanguageIDs[i].name=name;
|
||||
}
|
||||
|
||||
std::sort(m_LanguageIDs.begin()+1,m_LanguageIDs.end());
|
||||
|
||||
LVITEM item={LVIF_IMAGE|LVIF_TEXT};
|
||||
for (int i=0;i<(int)m_LanguageIDs.size();i++)
|
||||
{
|
||||
wchar_t name[256];
|
||||
GetLocaleInfo(m_LanguageIDs[i].id,LOCALE_SLANGUAGE,name,_countof(name));
|
||||
wchar_t text[256];
|
||||
if (i==0)
|
||||
Sprintf(text,_countof(text),L"%s (%s)",LoadStringEx(IDS_OS_LANGUAGE),m_LanguageIDs[i].name);
|
||||
else
|
||||
Sprintf(text,_countof(text),L"%s - %s",m_LanguageIDs[i].name,name);
|
||||
item.iItem=i;
|
||||
item.iImage=m_LanguageIDs[i].image;
|
||||
item.pszText=text;
|
||||
ListView_InsertItem(list,&item);
|
||||
}
|
||||
|
||||
// parse update.ver in data and add all flags
|
||||
wchar_t path[_MAX_PATH]=L"%ALLUSERSPROFILE%\\OpenShell\\update.ver";
|
||||
DoEnvironmentSubst(path,_countof(path));
|
||||
s_VersionData.bValid=(s_VersionData.Load(path,true)==VersionData::LOAD_OK);
|
||||
|
||||
UpdateFlags();
|
||||
|
||||
m_Tooltip.Create(TOOLTIPS_CLASS,m_hWnd,NULL,NULL,WS_POPUP|TTS_NOPREFIX);
|
||||
TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,'CLSH'};
|
||||
tool.uId=(UINT_PTR)list.m_hWnd;
|
||||
tool.lpszText=L"";
|
||||
m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
|
||||
{
|
||||
m_Tooltip.Detach();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
|
||||
{
|
||||
CResizeableDlg<CLanguageSettingsDlg>::OnSize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CLanguageSettingsDlg::NewVersionCallback( VersionData &data )
|
||||
{
|
||||
s_VersionData.Swap(data);
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnCheckUpdates( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
|
||||
{
|
||||
DWORD res=CheckForNewVersion(m_hWnd,m_Component,CHECK_UPDATE,NewVersionCallback);
|
||||
if (res==2) return 0;
|
||||
if (res)
|
||||
{
|
||||
UpdateFlags();
|
||||
CString language=GetSettingString(L"Language");
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
for (int idx=0;idx<(int)m_LanguageIDs.size();idx++)
|
||||
{
|
||||
const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L"";
|
||||
if (_wcsicmp(language,name)==0)
|
||||
{
|
||||
ListView_SetItemState(list,idx,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
|
||||
ListView_EnsureVisible(list,idx,FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UpdateLink(language);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_VersionData.Clear();
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,LoadStringEx(IDS_LANGUAGE_FAIL));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnSelChange( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
|
||||
{
|
||||
// set setting
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
int idx=ListView_GetNextItem(list,-1,LVNI_SELECTED);
|
||||
if (idx<0) return 0;
|
||||
|
||||
const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L"";
|
||||
CSettingsLockWrite lock;
|
||||
CComVariant val(name);
|
||||
if (m_pSetting->value!=val)
|
||||
SetSettingsDirty();
|
||||
m_pSetting->value=val;
|
||||
|
||||
if (_wcsicmp(m_pSetting->value.bstrVal,m_pSetting->defValue.bstrVal)==0)
|
||||
m_pSetting->flags|=CSetting::FLAG_DEFAULT;
|
||||
else
|
||||
m_pSetting->flags&=~CSetting::FLAG_DEFAULT;
|
||||
UpdateLink(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnSelChanging( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
|
||||
{
|
||||
return m_bLocked?TRUE:FALSE;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
|
||||
{
|
||||
NMLVCUSTOMDRAW *pDraw=(NMLVCUSTOMDRAW*)pnmh;
|
||||
if (!m_bLocked)
|
||||
{
|
||||
bHandled=FALSE;
|
||||
return 0;
|
||||
}
|
||||
if (pDraw->nmcd.dwDrawStage==CDDS_PREPAINT)
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
if (pDraw->nmcd.dwDrawStage!=CDDS_ITEMPREPAINT)
|
||||
{
|
||||
bHandled=FALSE;
|
||||
return 0;
|
||||
}
|
||||
pDraw->clrTextBk=GetSysColor(COLOR_BTNFACE);
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
static HRESULT CALLBACK TaskDialogCallbackProc( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData )
|
||||
{
|
||||
if (uNotification==TDN_HYPERLINK_CLICKED)
|
||||
{
|
||||
ShellExecute(hwnd,L"open",(const wchar_t*)lParam,NULL,NULL,SW_SHOWNORMAL);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LRESULT CLanguageSettingsDlg::OnDownload( int idCtrl, LPNMHDR pnmh, BOOL& bHandled )
|
||||
{
|
||||
CString language=GetSettingString(L"Language");
|
||||
if (language.IsEmpty())
|
||||
language=m_LanguageIDs[0].name;
|
||||
|
||||
for (std::vector<LanguageVersionData>::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it)
|
||||
{
|
||||
if (_wcsicmp(it->language,language)==0)
|
||||
{
|
||||
CString error;
|
||||
DWORD res=DownloadLanguageDll(m_hWnd,m_Component,*it,error);
|
||||
if (res==2)
|
||||
return 0;
|
||||
if (res)
|
||||
MessageBox(LoadStringEx(it->bBasic?IDS_LANGUAGE_SUCCESS2:IDS_LANGUAGE_SUCCESS),LoadStringEx(IDS_UPDATE_TITLE),MB_OK|(it->bBasic?MB_ICONWARNING:MB_ICONINFORMATION));
|
||||
else
|
||||
{
|
||||
if (!s_VersionData.languageLink.IsEmpty())
|
||||
error+=L" "+LoadStringEx(IDS_DOWNLOAD_TIP)+L"\r\n\r\n"+s_VersionData.languageLink;
|
||||
TASKDIALOGCONFIG task={sizeof(task),m_hWnd,NULL,TDF_ENABLE_HYPERLINKS|TDF_ALLOW_DIALOG_CANCELLATION|TDF_USE_HICON_MAIN,TDCBF_OK_BUTTON};
|
||||
CString title=LoadStringEx(IDS_UPDATE_TITLE);
|
||||
task.pszWindowTitle=title;
|
||||
task.pszContent=error;
|
||||
task.hMainIcon=LoadIcon(NULL,IDI_ERROR);
|
||||
task.pfCallback=TaskDialogCallbackProc;
|
||||
TaskDialogIndirect(&task,NULL,NULL,NULL);
|
||||
}
|
||||
UpdateLink(language);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CLanguageSettingsDlg::SetGroup( CSetting *pGroup )
|
||||
{
|
||||
m_bLocked=false;
|
||||
m_pSetting=pGroup+1;
|
||||
|
||||
const wchar_t *language=L"";
|
||||
if (m_pSetting->value.vt==VT_BSTR && m_pSetting->value.bstrVal)
|
||||
language=m_pSetting->value.bstrVal;
|
||||
int len=Strlen(language);
|
||||
|
||||
CWindow list=GetDlgItem(IDC_LISTLANGUAGE);
|
||||
for (int idx=0;idx<(int)m_LanguageIDs.size();idx++)
|
||||
{
|
||||
const wchar_t *name=idx>0?m_LanguageIDs[idx].name:L"";
|
||||
if (_wcsicmp(language,name)==0)
|
||||
{
|
||||
ListView_SetItemState(list,idx,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
|
||||
ListView_EnsureVisible(list,idx,FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UpdateLink(m_pSetting->value.bstrVal);
|
||||
m_bLocked=m_pSetting->IsLocked();
|
||||
|
||||
TOOLINFO tool={sizeof(tool),0,m_hWnd,'CLSH'};
|
||||
tool.uId=(UINT_PTR)list.m_hWnd;
|
||||
CString str;
|
||||
if (m_bLocked)
|
||||
str=LoadStringEx(IDS_SETTING_LOCKED);
|
||||
tool.lpszText=(LPWSTR)(LPCWSTR)str;
|
||||
m_Tooltip.SendMessage(TTM_UPDATETIPTEXT,0,(LPARAM)&tool);
|
||||
ListView_SetBkColor(list,GetSysColor(m_bLocked?COLOR_BTNFACE:COLOR_WINDOW));
|
||||
}
|
||||
|
||||
void CLanguageSettingsDlg::UpdateLink( const wchar_t *language )
|
||||
{
|
||||
TOOLINFO tool={sizeof(tool),TTF_SUBCLASS|TTF_IDISHWND,m_hWnd,'CLSH'};
|
||||
tool.uId=(UINT_PTR)GetDlgItem(IDC_LINKDOWNLOAD).m_hWnd;
|
||||
m_Tooltip.SendMessage(TTM_DELTOOL,0,(LPARAM)&tool);
|
||||
|
||||
if (!s_VersionData.bValid)
|
||||
{
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,L"");
|
||||
return;
|
||||
}
|
||||
if (!*language)
|
||||
language=m_LanguageIDs[0].name;
|
||||
|
||||
wchar_t text[1024];
|
||||
for (std::vector<LanguageVersionData>::const_iterator it=s_VersionData.languages.begin();it!=s_VersionData.languages.end();++it)
|
||||
{
|
||||
if (_wcsicmp(it->language,language)==0)
|
||||
{
|
||||
DWORD dllVersion=0, dllBuild=0;
|
||||
HINSTANCE resInstance=LoadTranslationDll(language);
|
||||
if (resInstance)
|
||||
{
|
||||
dllVersion=GetVersionEx(resInstance,&dllBuild);
|
||||
FreeLibrary(resInstance);
|
||||
}
|
||||
if (it->version>dllVersion || (it->version==dllVersion && it->build>dllBuild))
|
||||
{
|
||||
Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_DOWNLOAD),language);
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,text);
|
||||
|
||||
tool.lpszText=(LPWSTR)(LPCWSTR)it->url;
|
||||
m_Tooltip.SendMessage(TTM_ADDTOOL,0,(LPARAM)&tool);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_UPDATED),language);
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Sprintf(text,_countof(text),LoadStringEx(IDS_LANGUAGE_MISSING),language);
|
||||
SetDlgItemText(IDC_LINKDOWNLOAD,text);
|
||||
}
|
||||
|
||||
class CLanguageSettingsPanel: public ISettingsPanel
|
||||
{
|
||||
public:
|
||||
CLanguageSettingsPanel( TSettingsComponent component ) { s_Dialog.SetComponent(component); }
|
||||
virtual HWND Create( HWND parent );
|
||||
virtual HWND Activate( CSetting *pGroup, const RECT &rect, bool bReset );
|
||||
virtual bool Validate( HWND parent ) { return true; }
|
||||
|
||||
private:
|
||||
static CLanguageSettingsDlg s_Dialog;
|
||||
};
|
||||
|
||||
CLanguageSettingsDlg CLanguageSettingsPanel::s_Dialog;
|
||||
|
||||
ISettingsPanel *GetLanguageSettings( TSettingsComponent component )
|
||||
{
|
||||
static CLanguageSettingsPanel panel(component);
|
||||
return &panel;
|
||||
}
|
||||
|
||||
HWND CLanguageSettingsPanel::Create( HWND parent )
|
||||
{
|
||||
if (!s_Dialog.m_hWnd)
|
||||
s_Dialog.Create(parent,LoadDialogEx(IDD_LANGUAGE));
|
||||
return s_Dialog.m_hWnd;
|
||||
}
|
||||
|
||||
HWND CLanguageSettingsPanel::Activate( CSetting *pGroup, const RECT &rect, bool bReset )
|
||||
{
|
||||
s_Dialog.SetGroup(pGroup);
|
||||
s_Dialog.SetWindowPos(HWND_TOP,&rect,SWP_SHOWWINDOW);
|
||||
return s_Dialog.m_hWnd;
|
||||
}
|
||||
12
Src/Lib/LanguageSettingsHelper.h
Normal file
12
Src/Lib/LanguageSettingsHelper.h
Normal file
@@ -0,0 +1,12 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
class ISettingsPanel;
|
||||
|
||||
extern int g_LanguageIDs[];
|
||||
extern int g_LanguageIDCount;
|
||||
|
||||
ISettingsPanel *GetLanguageSettings( TSettingsComponent component );
|
||||
330
Src/Lib/Lib.rc
Normal file
330
Src/Lib/Lib.rc
Normal file
@@ -0,0 +1,330 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_SETTINGSTREE DIALOGEX 0, 0, 350, 160
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_SYSMENU
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "",IDC_SETTINGS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,7,336,126
|
||||
LTEXT "The settings that are modified from the default will show in bold\r\nRight-click on a setting for more functions",IDC_STATICTIP,7,135,336,18
|
||||
END
|
||||
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 381, 213
|
||||
STYLE DS_SETFONT | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_CONTROLPARENT
|
||||
CAPTION "Settings"
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
ICON "",IDC_ICONSEARCH,7,9,20,20
|
||||
EDITTEXT IDC_EDITSEARCH,22,7,120,12,ES_AUTOHSCROLL
|
||||
CONTROL "Show all settings",IDC_CHECKALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,154,7,79,12
|
||||
CONTROL "<a>Help...</a>",IDC_LINKHELP,"SysLink",WS_TABSTOP,348,9,26,10,WS_EX_TRANSPARENT
|
||||
CONTROL "",IDC_TABSETTINGS,"SysTabControl32",TCS_MULTILINE | TCS_FOCUSNEVER,7,20,367,169
|
||||
CONTROL "<a>www.classicshell.net</a>",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,195,66,10,WS_EX_TRANSPARENT
|
||||
CONTROL "Name of translator goes <a href=""http://www.yoursite.com"">here</a>",IDC_SYSLINKLOC,
|
||||
"SysLink",NOT WS_VISIBLE | WS_TABSTOP,80,195,111,10
|
||||
PUSHBUTTON "&Backup",IDC_BUTTONBACKUP,200,192,60,14,WS_GROUP
|
||||
DEFPUSHBUTTON "OK",IDOK,267,192,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,324,192,50,14
|
||||
END
|
||||
|
||||
IDD_BROWSEFORICON DIALOGEX 0, 0, 317, 183
|
||||
STYLE DS_SETFONT | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CAPTION "Select Icon"
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "File:",IDC_STATICFILE,7,7,19,14,SS_CENTERIMAGE
|
||||
EDITTEXT IDC_EDITFILE,33,7,260,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "...",IDC_BUTTONBROWSE,294,7,16,14
|
||||
CONTROL "",IDC_LISTICONS,"SysListView32",LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,26,303,132
|
||||
DEFPUSHBUTTON "OK",IDOK,205,162,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,260,162,50,14
|
||||
END
|
||||
|
||||
IDD_LANGUAGE DIALOGEX 0, 0, 316, 144
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "",IDC_LISTLANGUAGE,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,18,302,99
|
||||
LTEXT "Select a language for the user interface:",IDC_STATICHINT,7,7,131,8
|
||||
PUSHBUTTON "&Check for Updates",IDC_BUTTONCHECK,7,123,75,14
|
||||
CONTROL "download link goes here",IDC_LINKDOWNLOAD,"SysLink",WS_TABSTOP,85,126,224,10
|
||||
END
|
||||
|
||||
IDD_CUSTOMTREE DIALOGEX 0, 0, 365, 183
|
||||
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Current toolbar items:",IDC_STATICLEFT,7,7,167,8
|
||||
CONTROL "",IDC_TREEITEMS,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS | TVS_SHOWSELALWAYS | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,16,167,139
|
||||
LTEXT "Available commands:",IDC_STATICRIGHT,193,7,100,8
|
||||
CONTROL "",IDC_TREECOMMANDS,"SysTreeView32",TVS_SHOWSELALWAYS | TVS_INFOTIP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,191,16,167,139
|
||||
LTEXT "<<",IDC_STATICMIDDLE,177,77,11,8
|
||||
LTEXT "Drag items from the right column to the left. Double-click to edit. Right-click for more functions",IDC_STATICHINT,7,159,351,17
|
||||
END
|
||||
|
||||
IDD_PROGRESS DIALOGEX 0, 0, 209, 63
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
|
||||
CAPTION "Dialog"
|
||||
FONT 9, "Segoe UI", 400, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "Cancel",IDCANCEL,152,42,50,14
|
||||
CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,20,195,14
|
||||
LTEXT "Static",IDC_MESSAGE,7,7,195,12
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_SETTINGSTREE, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 343
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 153
|
||||
END
|
||||
|
||||
IDD_SETTINGS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 374
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 206
|
||||
END
|
||||
|
||||
IDD_BROWSEFORICON, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 310
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 176
|
||||
END
|
||||
|
||||
IDD_LANGUAGE, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 309
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 137
|
||||
END
|
||||
|
||||
IDD_CUSTOMTREE, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 358
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 176
|
||||
END
|
||||
|
||||
IDD_PROGRESS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 202
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 56
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICONLOCK ICON "padlock.ico"
|
||||
IDI_ICONPLAY ICON "play.ico"
|
||||
IDI_ICONWARNING ICON "warning.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
IDB_FLAGS BITMAP "flags.bmp"
|
||||
IDB_FLAGS24 BITMAP "flags24.bmp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_TOGGLE_SETTING "Toggle Setting\tSpace"
|
||||
IDS_SELECT_SETTING "Select Setting\tSpace"
|
||||
IDS_DEFAULT_SETTING "Set Default\tCtrl+Space"
|
||||
IDS_PLAY_SETTING "Play Sound\tCtrl+P"
|
||||
IDS_ICON_FILTERS "Icon files (*.ico, *.dll, *.exe)|*.ico;*.dll;*.exe|ICO files (*.ico)|*.ico|DLL files (*.dll)|*.dll|EXE files (*.exe)|*.exe|All Files (*.*)|*.*|"
|
||||
IDS_ICON_TITLE "Select Source File"
|
||||
IDS_WAV_FILTERS "WAV files (*.wav)|*.wav|"
|
||||
IDS_WAV_TITLE "Select Sound File"
|
||||
IDS_SETTING_LOCKED "This setting has been locked by the administrator"
|
||||
IDS_SETTING_LOCKED_GP "This setting has been locked by a group policy"
|
||||
IDS_BASIC_SETTINGS "Basic Settings"
|
||||
IDS_ALWAYS_ON_TOP "&Always on Top"
|
||||
IDS_MENU_EDIT "Edit Item"
|
||||
IDS_MENU_DELETE "Delete Item"
|
||||
IDS_MENU_RENAME "Rename Item"
|
||||
IDS_PICK_LINK_TITLE "Select a file or a folder"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_PICK_LINK_FILE "Select File"
|
||||
IDS_PICK_LINK_FOLDER "Select Folder"
|
||||
IDS_DUPLICATE_ITEM "Item named '%s' already exists."
|
||||
IDS_ERROR_TITLE "Error"
|
||||
IDS_ERROR_SEPARATOR "The item name cannot be '%s'."
|
||||
IDS_ERROR_ASCII "This is an internal name of the item and must contain only English letters and numbers. Use the Text and Tip properties to enter the visible text."
|
||||
IDS_ERROR_EMPTY "The item name cannot be empty."
|
||||
IDS_RESET_TOOLBAR "Reset Toolbar"
|
||||
IDS_RESET_TOOLBAR_WARN "Are you sure you want to reset all toolbar buttons?"
|
||||
IDS_RESET_MENU "Reset Start Menu"
|
||||
IDS_RESET_MENU_WARN "Are you sure you want to reset the whole start menu?"
|
||||
IDS_ADD_TOOLBAR "Add to Toolbar"
|
||||
IDS_ADD_MENU "Add to Menu"
|
||||
IDS_INSERT_MENU "Create sub-menu"
|
||||
IDS_EMPTY_MENU "<empty menu>"
|
||||
IDS_TREE_TOOLBAR "Current toolbar buttons:"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_TREE_MENU "Current menu items:"
|
||||
IDS_XML_FILTERS "XML files (*.xml)|*.xml|"
|
||||
IDS_XML_TITLE_LOAD "Load XML File"
|
||||
IDS_XML_TITLE_SAVE "Save XML File"
|
||||
IDS_RESET_CONFIRM "Are you sure you want to reset all settings?"
|
||||
IDS_RESET_TITLE "Reset All Settings"
|
||||
IDS_TOOLBAR_LOCKED "The toolbar is locked by the administrator"
|
||||
IDS_MENU_LOCKED "The start menu is locked by the administrator"
|
||||
IDS_BACKUP_SAVE "Save to XML File..."
|
||||
IDS_BACKUP_LOAD "Load from XML File..."
|
||||
IDS_BACKUP_RESET "Reset all settings"
|
||||
IDS_ERROR_LOADING_XML "Error loading XML file '%s'."
|
||||
IDS_ERROR_SAVING_XML "Error saving XML file '%s'."
|
||||
IDS_DRAG_DROP_EXP_TIP "Drag buttons from the right column to the left. You can drop on top of a button to create a sub-menu.\nDouble-click in the left column to edit the button. Right-click for more functions."
|
||||
IDS_DRAG_DROP_SM_TIP "Drag menu items from the right column to the left. You can drop on top of a menu item to create a sub-menu.\nDouble-click in the left column to edit the item. Right-click for more functions."
|
||||
IDS_COMMAND_EXP_TIP "Drag the command or double-click on it to add it to the toolbar"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_COMMAND_SM_TIP "Drag the command or double-click on it to add it to the start menu"
|
||||
IDS_COMMAND_FILTERS "Programs (*.exe, *.com, *.pif, *.bat, *.cmd)|*.exe;*.com;*.pif;*.bat;*.cmd|All files (*.*)|*.*|"
|
||||
IDS_OS_LANGUAGE "Current OS language"
|
||||
IDS_BMP_FILTERS "Image files (*.bmp,*.png)|*.bmp;*.png|"
|
||||
IDS_BMP_TITLE "Select Image File"
|
||||
IDS_SEARCH_PROMPT "Search Settings"
|
||||
IDS_SETTING_SEARCH "Search Results"
|
||||
IDS_WEBSITE_TIP "Visit Open-Shell on the web - http://www.classicshell.net"
|
||||
IDS_LOCATE_SETTING "Locate setting"
|
||||
IDS_LANGUAGE_UPDATED "The language %s is up to date."
|
||||
IDS_LANGUAGE_MISSING "Update for language %s is not available."
|
||||
IDS_LANGUAGE_DOWNLOAD "New update for language %s is available. <a>Click here to install it.</a>"
|
||||
IDS_LANGUAGE_SUCCESS "The language file was installed successfully.\nYou need to log off and back on for the update to take effect."
|
||||
IDS_LANGUAGE_SUCCESS2 "The language file was installed successfully.\nYou need to log off and back on for the update to take effect.\n\nNote: This update provides only basic translations. It supports only the main text found in the start menu and in Explorer. The settings will not be translated."
|
||||
IDS_LANGUAGE_FAIL "Failed to check for updates."
|
||||
IDS_INTERNET_FAIL "Failed to connect to the Internet."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_INITIATE_FAIL "Failed to initiate the download."
|
||||
IDS_LANG_DOWNLOAD_FAIL "Failed to download the language file."
|
||||
IDS_LANG_SAVE_FAIL "Failed to save language file '%s'."
|
||||
IDS_UPDATE_TITLE "Open-Shell Update"
|
||||
IDS_INST_DOWNLOAD_FAIL "Failed to download the new version."
|
||||
IDS_INST_SAVE_FAIL "Failed to save file '%s'."
|
||||
IDS_PROGRESS_CONNECT "Connecting..."
|
||||
IDS_PROGRESS_DOWNLOAD "Downloading..."
|
||||
IDS_PROGRESS_VERIFY "Verifying..."
|
||||
IDS_PROGRESS_SAVE "Saving..."
|
||||
IDS_PROGRESS_TITLE_CHECK "Checking for updates"
|
||||
IDS_PROGRESS_TITLE_DOWNLOAD "Downloading update"
|
||||
IDS_DOWNLOAD_TIP "You can try getting the file directly from the website:"
|
||||
IDS_BMP_FILTERS2 "Image files (*.bmp,*.png,*.jpg)|*.bmp;*.png;*.jpg|"
|
||||
IDS_UNSAVED_CHANGES "Do you want to save your changes to the settings?"
|
||||
IDS_UNSAVED_TITLE "Unsaved changes"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_VERSION_URL "http://www.classicshell.net/files/updates/update_"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
193
Src/Lib/Lib.vcxproj
Normal file
193
Src/Lib/Lib.vcxproj
Normal file
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D42FE717-485B-492D-884A-1999F6D51154}</ProjectGuid>
|
||||
<RootNamespace>Lib</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<UseOfAtl>Static</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<UseOfAtl>Static</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<UseOfAtl>Static</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<UseOfAtl>Static</UseOfAtl>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(Configuration)64\</OutDir>
|
||||
<IntDir>$(Configuration)64\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(Configuration)64\</OutDir>
|
||||
<IntDir>$(Configuration)64\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\Setup\OpenShell.ico" />
|
||||
<Image Include="flags.bmp" />
|
||||
<Image Include="flags24.bmp" />
|
||||
<Image Include="padlock.ico" />
|
||||
<Image Include="play.ico" />
|
||||
<Image Include="warning.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Lib.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Assert.h" />
|
||||
<ClInclude Include="ComHelper.h" />
|
||||
<ClInclude Include="DownloadHelper.h" />
|
||||
<ClInclude Include="FileHelper.h" />
|
||||
<ClInclude Include="FNVHash.h" />
|
||||
<ClInclude Include="IatHookHelper.h" />
|
||||
<ClInclude Include="LanguageSettingsHelper.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="ResourceHelper.h" />
|
||||
<ClInclude Include="Settings.h" />
|
||||
<ClInclude Include="SettingsParser.h" />
|
||||
<ClInclude Include="SettingsUIHelper.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="StringSet.h" />
|
||||
<ClInclude Include="StringUtils.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="TrackResources.h" />
|
||||
<ClInclude Include="Translations.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Assert.cpp" />
|
||||
<ClCompile Include="DownloadHelper.cpp" />
|
||||
<ClCompile Include="FileHelper.cpp" />
|
||||
<ClCompile Include="FNVHash.cpp" />
|
||||
<ClCompile Include="IatHookHelper.cpp" />
|
||||
<ClCompile Include="Instance.cpp" />
|
||||
<ClCompile Include="LanguageSettingsHelper.cpp" />
|
||||
<ClCompile Include="ResourceHelper.cpp" />
|
||||
<ClCompile Include="Settings.cpp" />
|
||||
<ClCompile Include="SettingsParser.cpp" />
|
||||
<ClCompile Include="SettingsUIHelper.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringSet.cpp" />
|
||||
<ClCompile Include="StringUtils.cpp" />
|
||||
<ClCompile Include="TrackResources.cpp" />
|
||||
<ClCompile Include="Translations.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
152
Src/Lib/Lib.vcxproj.filters
Normal file
152
Src/Lib/Lib.vcxproj.filters
Normal file
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Strings">
|
||||
<UniqueIdentifier>{2dafcc43-3a9f-4c0e-8d8a-b43c78f07e35}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resources">
|
||||
<UniqueIdentifier>{48a0589e-ec5e-4ded-b507-ca72c33429c7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Settings">
|
||||
<UniqueIdentifier>{402c170e-bb90-4637-85b7-98857963160f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Lib">
|
||||
<UniqueIdentifier>{40e914e4-1c35-4b97-a4f6-15dce5ff5b20}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\Setup\OpenShell.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="flags.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="flags24.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="padlock.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="play.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
<Image Include="warning.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Lib.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Assert.h">
|
||||
<Filter>Strings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FNVHash.h">
|
||||
<Filter>Strings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringSet.h">
|
||||
<Filter>Strings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringUtils.h">
|
||||
<Filter>Strings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ComHelper.h">
|
||||
<Filter>Resources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileHelper.h">
|
||||
<Filter>Resources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IatHookHelper.h">
|
||||
<Filter>Resources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ResourceHelper.h">
|
||||
<Filter>Resources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TrackResources.h">
|
||||
<Filter>Resources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DownloadHelper.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LanguageSettingsHelper.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SettingsParser.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SettingsUIHelper.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Translations.h">
|
||||
<Filter>Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Lib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Lib</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Assert.cpp">
|
||||
<Filter>Strings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FNVHash.cpp">
|
||||
<Filter>Strings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringSet.cpp">
|
||||
<Filter>Strings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringUtils.cpp">
|
||||
<Filter>Strings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileHelper.cpp">
|
||||
<Filter>Resources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IatHookHelper.cpp">
|
||||
<Filter>Resources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Instance.cpp">
|
||||
<Filter>Resources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ResourceHelper.cpp">
|
||||
<Filter>Resources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TrackResources.cpp">
|
||||
<Filter>Resources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DownloadHelper.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LanguageSettingsHelper.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SettingsParser.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SettingsUIHelper.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Translations.cpp">
|
||||
<Filter>Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Lib</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
904
Src/Lib/ResourceHelper.cpp
Normal file
904
Src/Lib/ResourceHelper.cpp
Normal file
@@ -0,0 +1,904 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "StringSet.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Settings.h"
|
||||
#include "Translations.h"
|
||||
#include "ResourceHelper.h"
|
||||
#include "Assert.h"
|
||||
#include <vector>
|
||||
#include <wincodec.h>
|
||||
#include "TrackResources.h"
|
||||
|
||||
static CStringSet g_ResStrings;
|
||||
static std::map<int,std::vector<char> > g_ResDialogs;
|
||||
|
||||
// Loads all strings and dialogs from hLngInstance
|
||||
// pDialogs is a NULL-terminated list of dialog IDs. They are loaded from hLngInstance if possible, otherwise from g_Instance
|
||||
void LoadTranslationResources( HINSTANCE hLngInstance, int *pDialogs )
|
||||
{
|
||||
Assert(g_Instance);
|
||||
DWORD lngVersion=0;
|
||||
if (hLngInstance)
|
||||
{
|
||||
LoadTranslationOverrides(hLngInstance);
|
||||
g_ResStrings.Init(hLngInstance);
|
||||
lngVersion=GetVersionEx(hLngInstance);
|
||||
}
|
||||
if (!pDialogs)
|
||||
return;
|
||||
for (int i=0;pDialogs[i];i+=2)
|
||||
{
|
||||
int dlgId=pDialogs[i];
|
||||
DWORD dlgVersion=pDialogs[i+1];
|
||||
HINSTANCE hInst=hLngInstance;
|
||||
HRSRC hrsrc=NULL;
|
||||
if (hLngInstance && lngVersion>=dlgVersion)
|
||||
hrsrc=FindResource(hInst,MAKEINTRESOURCE(dlgId),RT_DIALOG);
|
||||
if (!hrsrc)
|
||||
{
|
||||
hInst=g_Instance;
|
||||
hrsrc=FindResource(hInst,MAKEINTRESOURCE(dlgId),RT_DIALOG);
|
||||
}
|
||||
if (hrsrc)
|
||||
{
|
||||
HGLOBAL hglb=LoadResource(hInst,hrsrc);
|
||||
if (hglb)
|
||||
{
|
||||
// finally lock the resource
|
||||
LPVOID res=LockResource(hglb);
|
||||
std::vector<char> &dlg=g_ResDialogs[dlgId];
|
||||
dlg.resize(SizeofResource(hInst,hrsrc));
|
||||
if (!dlg.empty())
|
||||
memcpy(&dlg[0],res,dlg.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loads the best DLL for the current language
|
||||
HINSTANCE LoadTranslationDll( const wchar_t *langSetting )
|
||||
{
|
||||
Assert(g_Instance);
|
||||
CString language=langSetting;
|
||||
wchar_t languages[100]={0};
|
||||
if (!language.IsEmpty())
|
||||
{
|
||||
Strcpy(languages,_countof(languages)-1,language);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG size=0;
|
||||
ULONG len=_countof(languages);
|
||||
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len);
|
||||
}
|
||||
|
||||
wchar_t path1[_MAX_PATH];
|
||||
GetModuleFileName(g_Instance,path1,_countof(path1));
|
||||
*PathFindFileName(path1)=0;
|
||||
|
||||
wchar_t path2[_MAX_PATH]=L"%ALLUSERSPROFILE%\\OpenShell\\Languages\\";
|
||||
DoEnvironmentSubst(path2,_countof(path2));
|
||||
|
||||
DWORD curVersion=GetVersionEx(g_Instance);
|
||||
HINSTANCE resInstance=NULL;
|
||||
for (const wchar_t *lang=languages;*lang;lang+=Strlen(lang)+1)
|
||||
{
|
||||
if (_wcsicmp(lang,L"en")==0 || _wcsnicmp(lang,L"en-",3)==0)
|
||||
break; // English
|
||||
wchar_t fname[_MAX_PATH];
|
||||
DWORD ver1=0, ver2=0, build1=0, build2=0;
|
||||
Sprintf(fname,_countof(fname),L"%s%s.dll",path1,lang);
|
||||
HINSTANCE resInstance1=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
if (resInstance1)
|
||||
{
|
||||
ver1=GetVersionEx(resInstance1,&build1);
|
||||
if (ver1<MIN_LANGUAGE_VERSION || ver1>curVersion)
|
||||
{
|
||||
ver1=0;
|
||||
FreeLibrary(resInstance1);
|
||||
resInstance1=NULL;
|
||||
}
|
||||
}
|
||||
Sprintf(fname,_countof(fname),L"%s%s.dll",path2,lang);
|
||||
HINSTANCE resInstance2=LoadLibraryEx(fname,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
if (resInstance2)
|
||||
{
|
||||
ver2=GetVersionEx(resInstance2,&build2);
|
||||
if (ver2<MIN_LANGUAGE_VERSION || ver2>curVersion)
|
||||
{
|
||||
ver2=0;
|
||||
FreeLibrary(resInstance2);
|
||||
resInstance2=NULL;
|
||||
}
|
||||
}
|
||||
if (ver1 || ver2)
|
||||
{
|
||||
if (ver1>ver2 || (ver1==ver2 && build1>build2))
|
||||
{
|
||||
resInstance=resInstance1;
|
||||
if (resInstance2) FreeLibrary(resInstance2);
|
||||
}
|
||||
else
|
||||
{
|
||||
resInstance=resInstance2;
|
||||
if (resInstance1) FreeLibrary(resInstance1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resInstance;
|
||||
}
|
||||
|
||||
// Returns a localized string
|
||||
CString LoadStringEx( int stringID )
|
||||
{
|
||||
CString str=g_ResStrings.GetString(stringID);
|
||||
if (str.IsEmpty())
|
||||
str.LoadString(g_Instance,stringID);
|
||||
return str;
|
||||
}
|
||||
|
||||
CString LoadStringEnglish( int stringID )
|
||||
{
|
||||
CString str;
|
||||
str.LoadString(g_Instance,stringID);
|
||||
return str;
|
||||
}
|
||||
|
||||
// Returns a localized dialog template
|
||||
DLGTEMPLATE *LoadDialogEx( int dlgID )
|
||||
{
|
||||
std::map<int,std::vector<char> >::iterator it=g_ResDialogs.find(dlgID);
|
||||
if (it==g_ResDialogs.end())
|
||||
return NULL;
|
||||
if (it->second.empty())
|
||||
return NULL;
|
||||
return (DLGTEMPLATE*)&it->second[0];
|
||||
}
|
||||
|
||||
// Loads an icon. path can be a path to .ico file, or in the format "module.dll, number"
|
||||
HICON LoadIcon( int iconSize, const wchar_t *path, std::vector<HMODULE> &modules )
|
||||
{
|
||||
wchar_t text[1024];
|
||||
Strcpy(text,_countof(text),path);
|
||||
DoEnvironmentSubst(text,_countof(text));
|
||||
wchar_t *c=wcsrchr(text,',');
|
||||
if (c)
|
||||
{
|
||||
// resource file
|
||||
*c=0;
|
||||
const wchar_t *res=c+1;
|
||||
int idx=_wtol(res);
|
||||
if (idx>0) res=MAKEINTRESOURCE(idx);
|
||||
if (!text[0])
|
||||
return (HICON)LoadImage(_AtlBaseModule.GetResourceInstance(),res,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR);
|
||||
HMODULE hMod=GetModuleHandle(PathFindFileName(text));
|
||||
if (!hMod)
|
||||
{
|
||||
hMod=LoadLibraryEx(text,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
if (!hMod) return NULL;
|
||||
modules.push_back(hMod);
|
||||
}
|
||||
return (HICON)LoadImage(hMod,res,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (HICON)LoadImage(NULL,text,IMAGE_ICON,iconSize,iconSize,LR_DEFAULTCOLOR|LR_LOADFROMFILE);
|
||||
}
|
||||
}
|
||||
|
||||
HICON LoadIcon( int iconSize, PIDLIST_ABSOLUTE pidl )
|
||||
{
|
||||
HICON hIcon=NULL;
|
||||
CComPtr<IShellFolder> pFolder;
|
||||
PCITEMID_CHILD child;
|
||||
if (SUCCEEDED(SHBindToParent(pidl,IID_IShellFolder,(void**)&pFolder,&child)))
|
||||
{
|
||||
bool bLarge=(iconSize>GetSystemMetrics(SM_CXSMICON));
|
||||
LONG lSize;
|
||||
if (bLarge)
|
||||
lSize=MAKELONG(iconSize,GetSystemMetrics(SM_CXSMICON));
|
||||
else
|
||||
lSize=MAKELONG(GetSystemMetrics(SM_CXICON),iconSize);
|
||||
CComPtr<IExtractIcon> pExtract;
|
||||
if (SUCCEEDED(pFolder->GetUIObjectOf(NULL,1,&child,IID_IExtractIcon,NULL,(void**)&pExtract)))
|
||||
{
|
||||
// get the icon location
|
||||
wchar_t location[_MAX_PATH];
|
||||
int index=0;
|
||||
UINT flags=0;
|
||||
if (pExtract->GetIconLocation(0,location,_countof(location),&index,&flags)==S_OK)
|
||||
{
|
||||
if (flags&GIL_NOTFILENAME)
|
||||
{
|
||||
// extract the icon
|
||||
HICON hIcon2=NULL;
|
||||
HRESULT hr=pExtract->Extract(location,index,bLarge?&hIcon:&hIcon2,bLarge?&hIcon2:&hIcon,lSize);
|
||||
if (FAILED(hr))
|
||||
hIcon=hIcon2=NULL;
|
||||
if (hr==S_FALSE)
|
||||
flags=0;
|
||||
if (hIcon2) DestroyIcon(hIcon2); // HACK!!! Even though Extract should support NULL, not all implementations do. For example shfusion.dll crashes
|
||||
}
|
||||
if (!(flags&GIL_NOTFILENAME))
|
||||
{
|
||||
if (ExtractIconEx(location,index==-1?0:index,bLarge?&hIcon:NULL,bLarge?NULL:&hIcon,1)!=1)
|
||||
hIcon=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// try again using the ANSI version
|
||||
CComPtr<IExtractIconA> pExtractA;
|
||||
if (SUCCEEDED(pFolder->GetUIObjectOf(NULL,1,&child,IID_IExtractIconA,NULL,(void**)&pExtractA)))
|
||||
{
|
||||
// get the icon location
|
||||
char location[_MAX_PATH];
|
||||
int index=0;
|
||||
UINT flags=0;
|
||||
if (pExtractA->GetIconLocation(0,location,_countof(location),&index,&flags)==S_OK)
|
||||
{
|
||||
if (flags&GIL_NOTFILENAME)
|
||||
{
|
||||
// extract the icon
|
||||
HICON hIcon2=NULL;
|
||||
HRESULT hr=pExtractA->Extract(location,index,bLarge?&hIcon:&hIcon2,bLarge?&hIcon2:&hIcon,lSize);
|
||||
if (FAILED(hr))
|
||||
hIcon=hIcon2=NULL;
|
||||
if (hr==S_FALSE)
|
||||
flags=0;
|
||||
if (hIcon2) DestroyIcon(hIcon2); // HACK!!! Even though Extract should support NULL, not all implementations do. For example shfusion.dll crashes
|
||||
}
|
||||
if (!(flags&GIL_NOTFILENAME))
|
||||
{
|
||||
if (ExtractIconExA(location,index==-1?0:index,bLarge?&hIcon:NULL,bLarge?NULL:&hIcon,1)!=1)
|
||||
hIcon=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
HICON ShExtractIcon( const wchar_t *path, int index, int iconSize )
|
||||
{
|
||||
HICON hIcon;
|
||||
|
||||
typedef UINT (WINAPI *FSHExtractIconsW)( LPCWSTR pszFileName, int nIconIndex, int cxIcon, int cyIcon, HICON *phIcon, UINT *pIconId, UINT nIcons, UINT flags );
|
||||
static FSHExtractIconsW s_SHExtractIconsW;
|
||||
|
||||
if (!s_SHExtractIconsW)
|
||||
{
|
||||
HMODULE hShell32=GetModuleHandle(L"Shell32.dll");
|
||||
if (hShell32)
|
||||
s_SHExtractIconsW=(FSHExtractIconsW)GetProcAddress(hShell32,"SHExtractIconsW");
|
||||
}
|
||||
|
||||
if (s_SHExtractIconsW)
|
||||
{
|
||||
UINT id;
|
||||
if (!s_SHExtractIconsW(path,index,iconSize,iconSize,&hIcon,&id,1,LR_DEFAULTCOLOR))
|
||||
hIcon=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ExtractIconEx(path,index,&hIcon,NULL,1)!=1)
|
||||
return NULL;
|
||||
}
|
||||
if (hIcon)
|
||||
{
|
||||
AddTrackedIcon(hIcon);
|
||||
}
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
HICON ShExtractIcon( const char *path, int index, int iconSize )
|
||||
{
|
||||
wchar_t pathW[_MAX_PATH];
|
||||
MbsToWcs(pathW,_countof(pathW),path);
|
||||
return ShExtractIcon(pathW,index,iconSize);
|
||||
}
|
||||
|
||||
// Converts an icon to a bitmap. pBits may be NULL. If bDestroyIcon is true, hIcon will be destroyed
|
||||
HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, unsigned int **pBits, bool bDestroyIcon )
|
||||
{
|
||||
BITMAPINFO bi={0};
|
||||
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biWidth=bi.bmiHeader.biHeight=iconSize;
|
||||
bi.bmiHeader.biPlanes=1;
|
||||
bi.bmiHeader.biBitCount=32;
|
||||
RECT rc={0,0,iconSize,iconSize};
|
||||
|
||||
HDC hdc=CreateCompatibleDC(NULL);
|
||||
unsigned int *bits;
|
||||
HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0);
|
||||
HGDIOBJ bmp0=SelectObject(hdc,bmp);
|
||||
FillRect(hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
|
||||
DrawIconEx(hdc,0,0,hIcon,iconSize,iconSize,0,NULL,DI_NORMAL);
|
||||
SelectObject(hdc,bmp0);
|
||||
DeleteDC(hdc);
|
||||
if (bDestroyIcon) DestroyIcon(hIcon);
|
||||
if (pBits) *pBits=bits;
|
||||
return bmp;
|
||||
}
|
||||
|
||||
// Premultiplies a DIB section by the alpha channel and a given color
|
||||
void PremultiplyBitmap( HBITMAP hBitmap, COLORREF rgb )
|
||||
{
|
||||
BITMAP info;
|
||||
GetObject(hBitmap,sizeof(info),&info);
|
||||
int n=info.bmWidth*info.bmHeight;
|
||||
int mr=(rgb)&255;
|
||||
int mg=(rgb>>8)&255;
|
||||
int mb=(rgb>>16)&255;
|
||||
// pre-multiply the alpha
|
||||
for (int i=0;i<n;i++)
|
||||
{
|
||||
unsigned int &pixel=((unsigned int*)info.bmBits)[i];
|
||||
int a=(pixel>>24);
|
||||
int r=(pixel>>16)&255;
|
||||
int g=(pixel>>8)&255;
|
||||
int b=(pixel)&255;
|
||||
r=(r*a*mr)/(255*255);
|
||||
g=(g*a*mg)/(255*255);
|
||||
b=(b*a*mb)/(255*255);
|
||||
pixel=(a<<24)|(r<<16)|(g<<8)|b;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a grayscale version of an icon
|
||||
HICON CreateDisabledIcon( HICON hIcon, int iconSize )
|
||||
{
|
||||
// convert normal icon to grayscale
|
||||
ICONINFO info;
|
||||
GetIconInfo(hIcon,&info);
|
||||
|
||||
unsigned int *bits;
|
||||
HBITMAP bmp=BitmapFromIcon(hIcon,iconSize,&bits,false);
|
||||
|
||||
int n=iconSize*iconSize;
|
||||
for (int i=0;i<n;i++)
|
||||
{
|
||||
unsigned int &pixel=bits[i];
|
||||
int r=(pixel&255);
|
||||
int g=((pixel>>8)&255);
|
||||
int b=((pixel>>16)&255);
|
||||
int l=(77*r+151*g+28*b)/256;
|
||||
pixel=(pixel&0xFF000000)|(l*0x010101);
|
||||
}
|
||||
|
||||
if (info.hbmColor) DeleteObject(info.hbmColor);
|
||||
info.hbmColor=bmp;
|
||||
hIcon=CreateIconIndirect(&info);
|
||||
DeleteObject(bmp);
|
||||
if (info.hbmMask) DeleteObject(info.hbmMask);
|
||||
return hIcon;
|
||||
}
|
||||
|
||||
// Loads an image file into a bitmap and optionally resizes it
|
||||
HBITMAP LoadImageFile( const wchar_t *path, const SIZE *pSize, bool bUseAlpha, bool bPremultiply, std::vector<unsigned int> *pButtonAnim )
|
||||
{
|
||||
HBITMAP srcBmp=NULL;
|
||||
if (_wcsicmp(PathFindExtension(path),L".bmp")==0)
|
||||
{
|
||||
srcBmp=(HBITMAP)LoadImage(NULL,path,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);
|
||||
}
|
||||
if (srcBmp && !pSize)
|
||||
return srcBmp;
|
||||
CComPtr<IWICImagingFactory> pFactory;
|
||||
if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory)))
|
||||
{
|
||||
if (srcBmp) DeleteObject(srcBmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CComPtr<IWICBitmapSource> pBitmap;
|
||||
if (srcBmp)
|
||||
{
|
||||
CComPtr<IWICBitmap> pBitmap2;
|
||||
if (FAILED(pFactory->CreateBitmapFromHBITMAP(srcBmp,NULL,bUseAlpha?WICBitmapUseAlpha:WICBitmapIgnoreAlpha,&pBitmap2)))
|
||||
{
|
||||
DeleteObject(srcBmp);
|
||||
return NULL;
|
||||
}
|
||||
pBitmap=pBitmap2;
|
||||
DeleteObject(srcBmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CComPtr<IWICBitmapDecoder> pDecoder;
|
||||
if (FAILED(pFactory->CreateDecoderFromFilename(path,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder)))
|
||||
return NULL;
|
||||
|
||||
CComPtr<IWICBitmapFrameDecode> pFrame;
|
||||
if (FAILED(pDecoder->GetFrame(0,&pFrame)))
|
||||
return NULL;
|
||||
pBitmap=pFrame;
|
||||
}
|
||||
|
||||
CComPtr<IWICFormatConverter> pConverter;
|
||||
if (FAILED(pFactory->CreateFormatConverter(&pConverter)))
|
||||
return NULL;
|
||||
pConverter->Initialize(pBitmap,bPremultiply?GUID_WICPixelFormat32bppPBGRA:GUID_WICPixelFormat32bppBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut);
|
||||
pBitmap=pConverter;
|
||||
|
||||
int frameCount=1;
|
||||
int Yoffset=0;
|
||||
if (pButtonAnim)
|
||||
{
|
||||
frameCount=3;
|
||||
UINT width=0, height=0;
|
||||
pBitmap->GetSize(&width,&height);
|
||||
if (width>=3)
|
||||
{
|
||||
unsigned int data[3];
|
||||
WICRect rect={0,0,3,1};
|
||||
if (SUCCEEDED(pBitmap->CopyPixels(&rect,12,12,(BYTE*)data)) && (data[0]&0xFFFFFF)==ANIM_BUTTON_TAG1 && (data[1]&0xFFFFFF)==ANIM_BUTTON_TAG2)
|
||||
{
|
||||
Yoffset=(data[2]>>16)&255;
|
||||
if (Yoffset<(int)height)
|
||||
{
|
||||
frameCount=data[2]&255;
|
||||
if (frameCount<1) frameCount=1;
|
||||
if (frameCount>(int)(height-1)) frameCount=height-1;
|
||||
pButtonAnim->resize(Yoffset*width);
|
||||
rect.Width=width;
|
||||
rect.Height=Yoffset;
|
||||
pBitmap->CopyPixels(&rect,width*4,Yoffset*width*4,(BYTE*)&(*pButtonAnim)[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int frameWidthS, frameHeightS;
|
||||
int frameWidthD, frameHeightD;
|
||||
{
|
||||
UINT width=0, height=0;
|
||||
pBitmap->GetSize(&width,&height);
|
||||
frameWidthS=width;
|
||||
frameHeightS=(height-Yoffset)/frameCount;
|
||||
frameWidthD=frameWidthS;
|
||||
frameHeightD=frameHeightS;
|
||||
|
||||
// if cx>0, use as width
|
||||
// if cx<0, use -cx as width limit
|
||||
// if cy==0, scale proportionally
|
||||
if (pSize && pSize->cx && (pSize->cx>0 || -pSize->cx<frameWidthS))
|
||||
{
|
||||
frameWidthD=abs(pSize->cx);
|
||||
if (pSize->cy)
|
||||
frameHeightD=pSize->cy;
|
||||
else
|
||||
frameHeightD=frameWidthD*frameHeightS/frameWidthS;
|
||||
}
|
||||
}
|
||||
|
||||
BITMAPINFO bi={0};
|
||||
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biWidth=frameWidthD;
|
||||
bi.bmiHeader.biHeight=-frameHeightD*frameCount;
|
||||
bi.bmiHeader.biPlanes=1;
|
||||
bi.bmiHeader.biBitCount=32;
|
||||
|
||||
HDC hdc=CreateCompatibleDC(NULL);
|
||||
BYTE *pBits;
|
||||
HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&pBits,NULL,0);
|
||||
DeleteDC(hdc);
|
||||
|
||||
for (int frame=0;frame<frameCount;frame++)
|
||||
{
|
||||
CComPtr<IWICBitmapSource> pFrame=pBitmap;
|
||||
if (frameCount>1)
|
||||
{
|
||||
CComPtr<IWICBitmapClipper> pClipper;
|
||||
if (FAILED(pFactory->CreateBitmapClipper(&pClipper)))
|
||||
{
|
||||
DeleteObject(bmp);
|
||||
bmp=NULL;
|
||||
break;
|
||||
}
|
||||
WICRect rect={0,frameHeightS*frame+Yoffset,frameWidthS,frameHeightS};
|
||||
pClipper->Initialize(pBitmap,&rect);
|
||||
pFrame=pClipper;
|
||||
}
|
||||
if (frameWidthS!=frameWidthD || frameHeightS!=frameHeightD)
|
||||
{
|
||||
CComPtr<IWICBitmapScaler> pScaler;
|
||||
if (FAILED(pFactory->CreateBitmapScaler(&pScaler)))
|
||||
{
|
||||
DeleteObject(bmp);
|
||||
bmp=NULL;
|
||||
break;
|
||||
}
|
||||
pScaler->Initialize(pFrame,frameWidthD,frameHeightD,WICBitmapInterpolationModeFant);
|
||||
pFrame=pScaler;
|
||||
}
|
||||
int stride=frameWidthD*4;
|
||||
int frameSize=frameHeightD*stride;
|
||||
pFrame->CopyPixels(NULL,stride,frameSize,pBits+frameSize*frame);
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
// Loads a bitmap from a IMAGE resource
|
||||
HBITMAP LoadImageResource( HMODULE hModule, const wchar_t *name, bool bTopDown, bool bPremultiply )
|
||||
{
|
||||
CComPtr<IWICImagingFactory> pFactory;
|
||||
if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory)))
|
||||
return NULL;
|
||||
|
||||
CComPtr<IWICBitmapSource> pBitmap;
|
||||
if (hModule)
|
||||
{
|
||||
HRSRC src=FindResource(hModule,name,L"IMAGE");
|
||||
if (!src) return NULL;
|
||||
HGLOBAL hGlobal=LoadResource(hModule,src);
|
||||
if (!hGlobal) return NULL;
|
||||
void *pngData=LockResource(hGlobal);
|
||||
if (!pngData) return NULL;
|
||||
DWORD size=SizeofResource(hModule,src);
|
||||
CComPtr<IStream> pStream;
|
||||
pStream.Attach(SHCreateMemStream((BYTE*)pngData,size));
|
||||
if (!pStream) return NULL;
|
||||
|
||||
CComPtr<IWICBitmapDecoder> pDecoder;
|
||||
if (FAILED(pFactory->CreateDecoderFromStream(pStream,NULL,WICDecodeMetadataCacheOnLoad,&pDecoder)))
|
||||
return NULL;
|
||||
CComPtr<IWICBitmapFrameDecode> pFrame;
|
||||
if (FAILED(pDecoder->GetFrame(0,&pFrame)))
|
||||
return NULL;
|
||||
pBitmap=pFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_wcsicmp(PathFindExtension(name),L".bmp")==0)
|
||||
{
|
||||
HBITMAP bmp=(HBITMAP)LoadImage(NULL,name,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE);
|
||||
if (!bmp)
|
||||
return NULL;
|
||||
CComPtr<IWICBitmap> pBitmap2;
|
||||
if (FAILED(pFactory->CreateBitmapFromHBITMAP(bmp,NULL,WICBitmapUseAlpha,&pBitmap2)))
|
||||
pBitmap2=NULL;
|
||||
DeleteObject(bmp);
|
||||
if (!pBitmap2)
|
||||
return NULL;
|
||||
pBitmap=pBitmap2;
|
||||
}
|
||||
else
|
||||
{
|
||||
CComPtr<IWICBitmapDecoder> pDecoder;
|
||||
if (FAILED(pFactory->CreateDecoderFromFilename(name,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder)))
|
||||
return NULL;
|
||||
CComPtr<IWICBitmapFrameDecode> pFrame;
|
||||
if (FAILED(pDecoder->GetFrame(0,&pFrame)))
|
||||
return NULL;
|
||||
pBitmap=pFrame;
|
||||
}
|
||||
}
|
||||
|
||||
CComPtr<IWICFormatConverter> pConverter;
|
||||
if (FAILED(pFactory->CreateFormatConverter(&pConverter)))
|
||||
return NULL;
|
||||
pConverter->Initialize(pBitmap,bPremultiply?GUID_WICPixelFormat32bppPBGRA:GUID_WICPixelFormat32bppBGRA,WICBitmapDitherTypeNone,NULL,0,WICBitmapPaletteTypeMedianCut);
|
||||
|
||||
UINT width=0, height=0;
|
||||
pConverter->GetSize(&width,&height);
|
||||
|
||||
BITMAPINFO bi={0};
|
||||
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biWidth=width;
|
||||
bi.bmiHeader.biHeight=bTopDown?-(int)height:(int)height;
|
||||
bi.bmiHeader.biPlanes=1;
|
||||
bi.bmiHeader.biBitCount=32;
|
||||
|
||||
HDC hdc=CreateCompatibleDC(NULL);
|
||||
BYTE *bits;
|
||||
HBITMAP bmp=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&bits,NULL,0);
|
||||
DeleteDC(hdc);
|
||||
|
||||
if (bTopDown)
|
||||
{
|
||||
pConverter->CopyPixels(NULL,width*4,width*height*4,bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UINT y=0;y<height;y++)
|
||||
{
|
||||
WICRect rc={0,(INT)y,(INT)width,1};
|
||||
pConverter->CopyPixels(&rc,width*4,width*4,bits+(height-y-1)*width*4);
|
||||
}
|
||||
}
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
// Returns the version of a given module
|
||||
DWORD GetVersionEx( HINSTANCE hInstance, DWORD *pBuild )
|
||||
{
|
||||
// get the DLL version. this is a bit hacky. the standard way is to use GetFileVersionInfo and such API.
|
||||
// but it takes a file name instead of module handle so it will probably load the DLL a second time.
|
||||
// the header of the version resource is a fixed size so we can count on VS_FIXEDFILEINFO to always
|
||||
// be at offset 40
|
||||
HRSRC hResInfo=FindResource(hInstance,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION);
|
||||
if (!hResInfo)
|
||||
return 0;
|
||||
HGLOBAL hRes=LoadResource(hInstance,hResInfo);
|
||||
void *pRes=LockResource(hRes);
|
||||
if (!pRes) return 0;
|
||||
|
||||
VS_FIXEDFILEINFO *pVer=(VS_FIXEDFILEINFO*)((char*)pRes+40);
|
||||
if (pBuild)
|
||||
*pBuild=LOWORD(pVer->dwProductVersionLS);
|
||||
return ((HIWORD(pVer->dwProductVersionMS)&255)<<24)|((LOWORD(pVer->dwProductVersionMS)&255)<<16)|HIWORD(pVer->dwProductVersionLS);
|
||||
}
|
||||
|
||||
// Returns the Windows version - 0x600, 0x601, ...
|
||||
WORD GetWinVersion( void )
|
||||
{
|
||||
static WORD version;
|
||||
if (!version)
|
||||
{
|
||||
#pragma warning(suppress:4996)
|
||||
DWORD ver=GetVersion();
|
||||
version=MAKEWORD(HIBYTE(ver),LOBYTE(ver));
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
static bool IsWin81Update1Helper( void )
|
||||
{
|
||||
DWORD build;
|
||||
DWORD ver=GetVersionEx(GetModuleHandle(L"user32.dll"),&build);
|
||||
return HIWORD(ver)==WIN_VER_WIN81 && build>17000;
|
||||
}
|
||||
|
||||
// Returns true if the version is Win81 Update1 or later
|
||||
bool IsWin81Update1( void )
|
||||
{
|
||||
static bool bIsUpdate1=IsWin81Update1Helper();
|
||||
return bIsUpdate1;
|
||||
}
|
||||
|
||||
static bool IsWin10RS1Helper( void )
|
||||
{
|
||||
DWORD build;
|
||||
DWORD ver=GetVersionEx(GetModuleHandle(L"user32.dll"),&build);
|
||||
return ver>MAKELONG(14000,10<<8);
|
||||
}
|
||||
|
||||
// Returns true if the version is Windows10 RS1 or later
|
||||
bool IsWin10RS1( void )
|
||||
{
|
||||
static bool bIsRS1=IsWin10RS1Helper();
|
||||
return bIsRS1;
|
||||
}
|
||||
|
||||
typedef LONG NTSTATUS, *PNTSTATUS;
|
||||
#define STATUS_SUCCESS (0x00000000)
|
||||
typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
// *DO NOT USE DIRECTLY* : Call GetOSVersion() instead.
|
||||
//
|
||||
// The functions above return a windows version
|
||||
// that is rather not user-readable. This code should give
|
||||
// us a number we can reference with the "public" windows builds
|
||||
// such as what is returned by 'winver.exe'.
|
||||
RTL_OSVERSIONINFOW GetRealOSVersion() {
|
||||
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
|
||||
if (hMod) {
|
||||
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
|
||||
if (fxPtr != nullptr) {
|
||||
RTL_OSVERSIONINFOW rovi = { 0 };
|
||||
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||
if ( STATUS_SUCCESS == fxPtr(&rovi) ) {
|
||||
return rovi;
|
||||
}
|
||||
}
|
||||
}
|
||||
RTL_OSVERSIONINFOW rovi = { 0 };
|
||||
return rovi;
|
||||
}
|
||||
|
||||
static RTL_OSVERSIONINFOW GetOSVersion()
|
||||
{
|
||||
// cache result to avoid calling the dll multiple times.
|
||||
static RTL_OSVERSIONINFOW ver = GetRealOSVersion();
|
||||
return ver;
|
||||
}
|
||||
|
||||
static bool IsWin10RS4Helper( void )
|
||||
{
|
||||
auto version = GetOSVersion();
|
||||
return version.dwMajorVersion > 8 && version.dwBuildNumber > 17131;
|
||||
}
|
||||
|
||||
// Returns true if the version is Windows10 RS4 (Spring Creator Update) or later
|
||||
bool IsWin10RS4( void )
|
||||
{
|
||||
static bool bIsRS4=IsWin10RS4Helper();
|
||||
return bIsRS4;
|
||||
}
|
||||
|
||||
// Wrapper for IShellFolder::ParseDisplayName
|
||||
HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut )
|
||||
{
|
||||
static ITEMIDLIST ilRoot={0};
|
||||
static CComPtr<IShellFolder> pDesktop;
|
||||
if (_wcsicmp(pszName,L"::{Desktop}")==0)
|
||||
{
|
||||
*ppidl=ILCloneFull((PIDLIST_ABSOLUTE)&ilRoot);
|
||||
if (psfgaoOut)
|
||||
{
|
||||
*psfgaoOut=0;
|
||||
if (sfgaoIn&SFGAO_FOLDER)
|
||||
*psfgaoOut|=SFGAO_FOLDER;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppidl=NULL;
|
||||
if (!pDesktop)
|
||||
{
|
||||
HRESULT hr=SHGetDesktopFolder(&pDesktop);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
SFGAOF flags=sfgaoIn;
|
||||
HRESULT hr=pDesktop->ParseDisplayName(NULL,NULL,(wchar_t*)pszName,NULL,(PIDLIST_RELATIVE*)ppidl,psfgaoOut?&flags:NULL);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (psfgaoOut)
|
||||
*psfgaoOut=flags;
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
// Separates the arguments from the program
|
||||
// May return NULL if no arguments are found
|
||||
const wchar_t *SeparateArguments( const wchar_t *command, wchar_t *program )
|
||||
{
|
||||
if (command[0]=='"')
|
||||
{
|
||||
// quoted program - just GetToken will work
|
||||
return GetToken(command,program,_MAX_PATH,L" ");
|
||||
}
|
||||
|
||||
// skip leading spaces
|
||||
while (*command==' ')
|
||||
command++;
|
||||
const wchar_t *args=wcschr(command,' ');
|
||||
if (!args)
|
||||
{
|
||||
// no spaces - the whole thing is a program
|
||||
Strcpy(program,_MAX_PATH,command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len=(int)(args-command);
|
||||
if (len>_MAX_PATH-1) len=_MAX_PATH-1;
|
||||
memcpy(program,command,len*2);
|
||||
program[len]=0;
|
||||
|
||||
const wchar_t *space=command;
|
||||
while (*space)
|
||||
{
|
||||
space=wcschr(space+1,' ');
|
||||
if (!space)
|
||||
space=command+Strlen(command);
|
||||
len=(int)(space-command);
|
||||
if (len>=_MAX_PATH) break;
|
||||
wchar_t prog2[_MAX_PATH];
|
||||
memcpy(prog2,command,len*2);
|
||||
prog2[len]=0;
|
||||
if (len>0 && prog2[len-1]=='\\')
|
||||
prog2[len-1]=0;
|
||||
WIN32_FIND_DATA data;
|
||||
HANDLE h=FindFirstFile(prog2,&data);
|
||||
if (h!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// found a valid file
|
||||
FindClose(h);
|
||||
memcpy(program,command,len*2);
|
||||
program[len]=0;
|
||||
if (*space)
|
||||
args=space+1;
|
||||
else
|
||||
args=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
while (args && *args==' ')
|
||||
args++;
|
||||
return args;
|
||||
}
|
||||
struct CommonEnvVar
|
||||
{
|
||||
const wchar_t *name;
|
||||
wchar_t value[_MAX_PATH];
|
||||
int len;
|
||||
};
|
||||
|
||||
CommonEnvVar g_CommonEnvVars[]={
|
||||
{L"USERPROFILE"},
|
||||
{L"ALLUSERSPROFILE"},
|
||||
{L"SystemRoot"},
|
||||
{L"SystemDrive"},
|
||||
};
|
||||
|
||||
void UnExpandEnvStrings( const wchar_t *src, wchar_t *dst, int size )
|
||||
{
|
||||
static bool bInit=false;
|
||||
if (!bInit)
|
||||
{
|
||||
bInit=true;
|
||||
for (int i=0;i<_countof(g_CommonEnvVars);i++)
|
||||
{
|
||||
int len=GetEnvironmentVariable(g_CommonEnvVars[i].name,g_CommonEnvVars[i].value,_MAX_PATH);
|
||||
if (len<=_MAX_PATH)
|
||||
g_CommonEnvVars[i].len=len;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<_countof(g_CommonEnvVars);i++)
|
||||
{
|
||||
int len=g_CommonEnvVars[i].len;
|
||||
if (_wcsnicmp(src,g_CommonEnvVars[i].value,len)==0)
|
||||
{
|
||||
const wchar_t *name=g_CommonEnvVars[i].name;
|
||||
if (Strlen(src)-len+Strlen(name)+3>size)
|
||||
break; // not enough space
|
||||
Sprintf(dst,size,L"%%%s%%%s",name,src+len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Strcpy(dst,size,src);
|
||||
}
|
||||
|
||||
void StringUpper( CString &str )
|
||||
{
|
||||
int len=str.GetLength();
|
||||
wchar_t *buf=str.GetBuffer(len);
|
||||
CharUpper(buf);
|
||||
str.ReleaseBufferSetLength(len);
|
||||
}
|
||||
|
||||
// Create a font from the user settings
|
||||
HFONT CreateFontSetting( const wchar_t *fontStr, int dpi )
|
||||
{
|
||||
const wchar_t *str=fontStr;
|
||||
if (!*str) return NULL;
|
||||
|
||||
wchar_t name[256];
|
||||
while (*str==' ')
|
||||
str++;
|
||||
str=GetToken(str,name,_countof(name),L",");
|
||||
int len=Strlen(name);
|
||||
while (len>0 && name[len-1]==' ')
|
||||
name[--len]=0;
|
||||
while (*str==' ')
|
||||
str++;
|
||||
wchar_t token[256];
|
||||
str=GetToken(str,token,_countof(token),L",");
|
||||
len=Strlen(token);
|
||||
while (len>0 && token[len-1]==' ')
|
||||
token[--len]=0;
|
||||
int weight=FW_NORMAL;
|
||||
bool bItalic=false;
|
||||
if (_wcsicmp(token,L"bold")==0)
|
||||
weight=FW_BOLD;
|
||||
else if (_wcsicmp(token,L"italic")==0)
|
||||
bItalic=1;
|
||||
else if (_wcsicmp(token,L"bold_italic")==0)
|
||||
weight=FW_BOLD, bItalic=true;
|
||||
str=GetToken(str,token,_countof(token),L", \t");
|
||||
int size=-_wtol(token);
|
||||
return CreateFont(size*dpi/72,0,0,0,weight,bItalic?1:0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,name);
|
||||
}
|
||||
88
Src/Lib/ResourceHelper.h
Normal file
88
Src/Lib/ResourceHelper.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <shobjidl.h>
|
||||
#include <vector>
|
||||
|
||||
// Loads the best DLL for the given language
|
||||
HINSTANCE LoadTranslationDll( const wchar_t *langSetting );
|
||||
|
||||
// Loads all strings and dialogs from hLngInstance
|
||||
// pDialogs is a NULL-terminated list of dialog IDs. They are loaded from hLngInstance if possible, otherwise from g_Instance
|
||||
void LoadTranslationResources( HINSTANCE hLngInstance, int *pDialogs );
|
||||
|
||||
// Returns a localized string
|
||||
CString LoadStringEx( int stringID );
|
||||
CString LoadStringEnglish( int stringID );
|
||||
|
||||
// Returns a localized dialog template
|
||||
DLGTEMPLATE *LoadDialogEx( int dlgID );
|
||||
|
||||
// Loads an icon. path can be a path to .ico file, or in the format "module.dll, number"
|
||||
HICON LoadIcon( int iconSize, const wchar_t *path, std::vector<HMODULE> &modules );
|
||||
|
||||
// Loads the icon for the given pidl (file or folder)
|
||||
HICON LoadIcon( int iconSize, PIDLIST_ABSOLUTE pidl );
|
||||
|
||||
// Extracts icon of a given size from a specified location the way Shell does it
|
||||
HICON ShExtractIcon( const wchar_t *path, int index, int iconSize );
|
||||
HICON ShExtractIcon( const char *path, int index, int iconSize );
|
||||
|
||||
// Converts an icon to a bitmap. pBits may be NULL. If bDestroyIcon is true, hIcon will be destroyed
|
||||
HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, unsigned int **pBits, bool bDestroyIcon );
|
||||
|
||||
// Loads an image file into a bitmap and optionally resizes it
|
||||
HBITMAP LoadImageFile( const wchar_t *path, const SIZE *pSize, bool bUseAlpha, bool bPremultiply, std::vector<unsigned int> *pButtonAnim );
|
||||
|
||||
// Loads a bitmap from a IMAGE resource
|
||||
HBITMAP LoadImageResource( HMODULE hModule, const wchar_t *name, bool bTopDown, bool bPremultiply );
|
||||
|
||||
// Premultiplies a DIB section by the alpha channel and a given color
|
||||
void PremultiplyBitmap( HBITMAP hBitmap, COLORREF rgb );
|
||||
|
||||
// Creates a grayscale version of an icon
|
||||
HICON CreateDisabledIcon( HICON hIcon, int iconSize );
|
||||
|
||||
// Returns the version of a given module
|
||||
DWORD GetVersionEx( HINSTANCE hInstance, DWORD *pBuild=NULL );
|
||||
|
||||
const int WIN_VER_VISTA=0x600;
|
||||
const int WIN_VER_WIN7 =0x601;
|
||||
const int WIN_VER_WIN8 =0x602;
|
||||
const int WIN_VER_WIN81=0x603;
|
||||
const int WIN_VER_WIN10=0xA00;
|
||||
|
||||
// Returns the Windows version - 0x600, 0x601, ...
|
||||
WORD GetWinVersion( void );
|
||||
|
||||
// Returns true if the version is Win81 Update1
|
||||
bool IsWin81Update1( void );
|
||||
|
||||
// Returns true if the version is Windows10 RS1 or later
|
||||
bool IsWin10RS1( void );
|
||||
|
||||
// Returns true if the version is Windows10 RS4 (Spring Creator Update) or later
|
||||
bool IsWin10RS4( void );
|
||||
|
||||
// Wrapper for IShellFolder::ParseDisplayName
|
||||
HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut );
|
||||
|
||||
// Separates the arguments from the program
|
||||
// May return NULL if no arguments are found
|
||||
const wchar_t *SeparateArguments( const wchar_t *command, wchar_t *program );
|
||||
|
||||
// Replaces some common paths with environment variables
|
||||
void UnExpandEnvStrings( const wchar_t *src, wchar_t *dst, int size );
|
||||
|
||||
void StringUpper( CString &str );
|
||||
|
||||
// Create a font from the user settings
|
||||
HFONT CreateFontSetting( const wchar_t *fontStr, int dpi );
|
||||
|
||||
extern HINSTANCE g_Instance;
|
||||
|
||||
const int ANIM_BUTTON_TAG1='ANM';
|
||||
const int ANIM_BUTTON_TAG2='BTN';
|
||||
2844
Src/Lib/Settings.cpp
Normal file
2844
Src/Lib/Settings.cpp
Normal file
File diff suppressed because it is too large
Load Diff
197
Src/Lib/Settings.h
Normal file
197
Src/Lib/Settings.h
Normal file
@@ -0,0 +1,197 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
class ISettingsPanel
|
||||
{
|
||||
public:
|
||||
virtual HWND Create( HWND parent )=0;
|
||||
virtual HWND Activate( struct CSetting *pGroup, const RECT &rect, bool bReset )=0;
|
||||
virtual bool Validate( HWND parent )=0;
|
||||
};
|
||||
|
||||
struct CSetting
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
TYPE_GROUP=-2,
|
||||
TYPE_RADIO=-1,
|
||||
TYPE_BOOL=1,
|
||||
TYPE_INT,
|
||||
TYPE_HOTKEY,
|
||||
TYPE_HOTKEY_ANY,
|
||||
TYPE_COLOR, // requires the high 8 bits of the flags to contain an index into the color palette
|
||||
|
||||
// string types
|
||||
TYPE_STRING,
|
||||
TYPE_ICON,
|
||||
TYPE_BITMAP,
|
||||
TYPE_BITMAP_JPG,
|
||||
TYPE_SOUND,
|
||||
TYPE_FONT,
|
||||
TYPE_MULTISTRING,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// initial settings
|
||||
FLAG_WARM= 0x00001,
|
||||
FLAG_COLD= 0x00002,
|
||||
FLAG_BASIC= 0x00004,
|
||||
FLAG_HIDDEN= 0x00008,
|
||||
FLAG_SHARED= 0x00010,
|
||||
FLAG_NORESET= 0x00020,
|
||||
FLAG_NODEFAULT= 0x00040,
|
||||
FLAG_NOSAVE= 0x00080,
|
||||
FLAG_CALLBACK= 0x00100,
|
||||
|
||||
FLAG_MENU_CLASSIC1= 0x00200,
|
||||
FLAG_MENU_CLASSIC2= 0x00400,
|
||||
FLAG_MENU_CLASSIC_BOTH=FLAG_MENU_CLASSIC1|FLAG_MENU_CLASSIC2,
|
||||
FLAG_MENU_WIN7= 0x00800,
|
||||
FLAG_MENU_MASK=FLAG_MENU_CLASSIC1|FLAG_MENU_CLASSIC2|FLAG_MENU_WIN7,
|
||||
|
||||
// for run-time use only
|
||||
FLAG_DEFAULT= 0x01000,
|
||||
FLAG_FORCED_DEFAULT= 0x02000,
|
||||
FLAG_LOCKED_REG= 0x04000, // locked by HKLM registry setting
|
||||
FLAG_LOCKED_GP= 0x08000, // locked by a group policy
|
||||
FLAG_LOCKED_MASK=FLAG_LOCKED_REG|FLAG_LOCKED_GP,
|
||||
FLAG_WARNING= 0x10000, // show a warning icon
|
||||
// top 8 bits need to stay unused. that's where we store the color index
|
||||
};
|
||||
|
||||
const wchar_t *name;
|
||||
Type type;
|
||||
int nameID, tipID; // resource strings
|
||||
CComVariant defValue; // default value
|
||||
unsigned int flags;
|
||||
const wchar_t *depend;
|
||||
const wchar_t *nest;
|
||||
ISettingsPanel *pPanel; // custom panel for editing this group of settings
|
||||
|
||||
CSetting *pLinkTo; // if this is not NULL, then the value is stored in the linked setting (the default value, radio settings, etc. must match between the two)
|
||||
|
||||
// runtime use only
|
||||
CComVariant value; // current value
|
||||
CComVariant tempValue; // the value is stored here when editing begins and restored if the editing is canceled
|
||||
unsigned int tempFlags;
|
||||
|
||||
bool IsEnabled( void ) const;
|
||||
bool IsDefault( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_DEFAULT)!=0; }
|
||||
bool IsForcedDefault( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_FORCED_DEFAULT)!=0; }
|
||||
bool IsLocked( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_LOCKED_MASK)!=0; }
|
||||
bool IsLockedReg( void ) const { return ((pLinkTo?pLinkTo->flags:flags)&FLAG_LOCKED_REG)!=0; }
|
||||
bool ShouldLoad( bool bShared ) const;
|
||||
bool MatchFilter( const wchar_t *filter ) const;
|
||||
const CComVariant &GetValue( void ) const { return pLinkTo?pLinkTo->value:value; }
|
||||
|
||||
void LoadValue( CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser );
|
||||
|
||||
private:
|
||||
bool ReadValue( CRegKey ®Key, const wchar_t *valName );
|
||||
};
|
||||
|
||||
// Images in the tree image list
|
||||
enum {
|
||||
SETTING_STATE_NONE=1,
|
||||
SETTING_STATE_SETTING=2,
|
||||
SETTING_STATE_CHECKBOX=4,
|
||||
SETTING_STATE_RADIO=8,
|
||||
|
||||
// additional flags
|
||||
SETTING_STATE_DISABLED=1,
|
||||
SETTING_STATE_CHECKED=2,
|
||||
|
||||
SETTING_IMAGE_COLOR=13, // 10 blank images to use for custom colors
|
||||
};
|
||||
|
||||
enum TSettingsComponent
|
||||
{
|
||||
COMPONENT_EXPLORER,
|
||||
COMPONENT_MENU,
|
||||
COMPONENT_IE,
|
||||
COMPONENT_UPDATE,
|
||||
COMPONENT_SHARED,
|
||||
};
|
||||
|
||||
class ICustomSettings
|
||||
{
|
||||
public:
|
||||
virtual int AppendBackupMenu( HMENU menu, int id ) = 0;
|
||||
virtual void ExecuteBackupMenu( int id ) = 0;
|
||||
};
|
||||
|
||||
void InitSettings( CSetting *pSettings, TSettingsComponent component, ICustomSettings *pCustom );
|
||||
void LoadSettings( void );
|
||||
void SaveSettings( void );
|
||||
void UpdateDefaultSettings( void );
|
||||
void EditSettings( const wchar_t *title, bool bModal, int tab );
|
||||
void CloseSettings( void );
|
||||
void SetSettingsDirty( void );
|
||||
void SelectSettingsTab( int tab, bool bAdvanced, const CSetting *pSelect );
|
||||
void UpdateSettings( void ); // implemented by the user
|
||||
void UpgradeSettings( bool bShared ); // implemented by the user (called when converting 3.0 settings to 4.0)
|
||||
void ClosingSettings( HWND hWnd, int flags, int command ); // implemented by the user
|
||||
const wchar_t *GetDocRelativePath( void ); // implemented by the user
|
||||
void SettingChangedCallback( const CSetting *pSetting ); // implemented by the user
|
||||
bool IsSettingsMessage( MSG *msg );
|
||||
bool ImportSettingsXml( const wchar_t *fname );
|
||||
bool ExportSettingsXml( const wchar_t *fname );
|
||||
const CSetting *GetAllSettings( void );
|
||||
void SetSettingsStyle( int style, int mask );
|
||||
void GetSettingsStyle( int &style, int &mask );
|
||||
|
||||
// Finds a setting by name
|
||||
CSetting *FindSetting( const wchar_t *name );
|
||||
// Updates the setting with a new default value and locked flag
|
||||
void UpdateSetting( const wchar_t *name, const CComVariant &defValue, bool bLockedGP );
|
||||
// Updates the setting with a new tooltip and a warning flag
|
||||
void UpdateSettingText( const wchar_t *name, int nameID, int tipID, bool bWarning );
|
||||
|
||||
void HideSetting( const wchar_t *name, bool bHide );
|
||||
void HideSettingGroup( const wchar_t *name, bool bHide );
|
||||
void UpdateGroupText( const wchar_t *name, int nameID );
|
||||
|
||||
bool GetSettingBool( const wchar_t *name );
|
||||
int GetSettingInt( const wchar_t *name );
|
||||
CString GetSettingString( const wchar_t *name );
|
||||
bool IsSettingLocked( const wchar_t *name );
|
||||
bool IsSettingForcedDefault( const wchar_t *name );
|
||||
|
||||
// In some cases the default can change dynamically, so the setting may be out of date. Use bDef to detect if the default value should be used
|
||||
int GetSettingInt( const wchar_t *name, bool &bDef );
|
||||
bool GetSettingBool( const wchar_t *name, bool &bDef );
|
||||
|
||||
struct CSettingsLockRead
|
||||
{
|
||||
CSettingsLockRead( void );
|
||||
~CSettingsLockRead( void );
|
||||
};
|
||||
|
||||
struct CSettingsLockWrite
|
||||
{
|
||||
CSettingsLockWrite( void );
|
||||
~CSettingsLockWrite( void );
|
||||
};
|
||||
|
||||
bool HasHelp( void );
|
||||
void ShowHelp( void );
|
||||
|
||||
#ifndef _WIN64
|
||||
bool SaveAdmx( TSettingsComponent component, const char *admxFile, const char *admlFile, const char *docFile );
|
||||
#endif
|
||||
|
||||
// Opens the registry keys for the settings of the given component
|
||||
// Returns true if the user settings were read from the old HKCU location. That means the settings may need to be upgraded
|
||||
bool OpenSettingsKeys( TSettingsComponent component, CRegKey ®Settings, CRegKey ®SettingsUser, CRegKey ®Policy, CRegKey ®PolicyUser );
|
||||
|
||||
// Get a value from a manually loaded setting
|
||||
bool GetSettingBool( const CSetting &setting );
|
||||
CString GetSettingString( const CSetting &setting );
|
||||
|
||||
// the format for the location is key_name|value_name|file_name
|
||||
void VLogToFile( const wchar_t *location, const wchar_t *message, va_list args );
|
||||
void LogToFile( const wchar_t *location, const wchar_t *message, ... );
|
||||
554
Src/Lib/SettingsParser.cpp
Normal file
554
Src/Lib/SettingsParser.cpp
Normal file
@@ -0,0 +1,554 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "SettingsParser.h"
|
||||
#include "ResourceHelper.h"
|
||||
#include "StringUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
const int MAX_TREE_LEVEL=10;
|
||||
|
||||
// Reads a file into m_Text
|
||||
bool CSettingsParser::LoadText( const wchar_t *fname )
|
||||
{
|
||||
// read settings file into buf
|
||||
FILE *f=NULL;
|
||||
if (_wfopen_s(&f,fname,L"rb")) return false;
|
||||
if (!f) return false;
|
||||
fseek(f,0,SEEK_END);
|
||||
int size=ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
std::vector<unsigned char> buf(size);
|
||||
if (size<4 || fread(&buf[0],1,size,f)!=size)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
LoadText(&buf[0],size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads a text resource into m_Text
|
||||
bool CSettingsParser::LoadText( HMODULE hMod, HRSRC hResInfo )
|
||||
{
|
||||
HGLOBAL hRes=LoadResource(hMod,hResInfo);
|
||||
int size=SizeofResource(hMod,hResInfo);
|
||||
unsigned char *buf=(unsigned char*)LockResource(hRes);
|
||||
if (!buf) return false;
|
||||
LoadText(buf,size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSettingsParser::LoadText( const unsigned char *buf, int size )
|
||||
{
|
||||
// copy buf to text and convert to UTF16
|
||||
if (buf[0]==0xFF && buf[1]==0xFE)
|
||||
{
|
||||
// UTF16
|
||||
int len=(size-2)/2;
|
||||
m_Text.resize(len+1);
|
||||
memcpy(&m_Text[0],&buf[2],size-2);
|
||||
m_Text[len]=0;
|
||||
}
|
||||
else if (buf[0]==0xEF && buf[1]==0xBB && buf[2]==0xBF)
|
||||
{
|
||||
// UTF8
|
||||
int len=MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[3],size-3,NULL,0);
|
||||
m_Text.resize(len+1);
|
||||
MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[3],size-3,&m_Text[0],len);
|
||||
m_Text[len]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ACP
|
||||
int len=MultiByteToWideChar(CP_ACP,0,(const char*)&buf[0],size,NULL,0);
|
||||
m_Text.resize(len+1);
|
||||
MultiByteToWideChar(CP_UTF8,0,(const char*)&buf[0],size,&m_Text[0],len);
|
||||
m_Text[len]=0;
|
||||
}
|
||||
}
|
||||
|
||||
void CSettingsParser::LoadText( const wchar_t *buf, int size )
|
||||
{
|
||||
m_Text.resize(size+1);
|
||||
memcpy(&m_Text[0],buf,size*2);
|
||||
m_Text[size]=0;
|
||||
}
|
||||
|
||||
// Splits m_Text into m_Lines
|
||||
void CSettingsParser::ParseText( void )
|
||||
{
|
||||
if (m_Text.empty()) return;
|
||||
// split into lines
|
||||
wchar_t *str=&m_Text[0];
|
||||
while (*str)
|
||||
{
|
||||
if (*str!=';') // ignore lines starting with ;
|
||||
{
|
||||
// trim leading whitespace
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
m_Lines.push_back(str);
|
||||
}
|
||||
wchar_t *p1=wcschr(str,'\r');
|
||||
wchar_t *p2=wcschr(str,'\n');
|
||||
wchar_t *end=&m_Text[m_Text.size()-1];
|
||||
if (p1) end=p1;
|
||||
if (p2 && p2<end) end=p2;
|
||||
|
||||
wchar_t *next=end;
|
||||
while (*next=='\r' || *next=='\n')
|
||||
next++;
|
||||
|
||||
// trim trailing whitespace
|
||||
while (end>str && (*end==' ' || *end=='\t'))
|
||||
end--;
|
||||
*end=0;
|
||||
str=next;
|
||||
}
|
||||
}
|
||||
|
||||
// Filters the settings that belong to the given language
|
||||
// languages is a 00-terminated list of language names ordered by priority
|
||||
void CSettingsParser::FilterLanguages( const wchar_t *languages )
|
||||
{
|
||||
std::vector<const wchar_t*> lines;
|
||||
lines.swap(m_Lines);
|
||||
for (const wchar_t *lang=languages;*lang;lang+=wcslen(lang)+1)
|
||||
{
|
||||
size_t langLen=wcslen(lang);
|
||||
for (size_t i=0;i<lines.size();i++)
|
||||
{
|
||||
const wchar_t *line=lines[i];
|
||||
if (*line=='[' && _wcsnicmp(line+1,lang,langLen)==0 && line[langLen+1]==']')
|
||||
{
|
||||
for (i++;i<lines.size();i++)
|
||||
{
|
||||
line=lines[i];
|
||||
if (*line=='[') break;
|
||||
m_Lines.push_back(line);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::reverse(m_Lines.begin(),m_Lines.end());
|
||||
}
|
||||
|
||||
// Returns a setting with the given name. If no setting is found, returns def
|
||||
const wchar_t *CSettingsParser::FindSetting( const wchar_t *name, const wchar_t *def )
|
||||
{
|
||||
const wchar_t *str=FindSettingInt(name,wcslen(name));
|
||||
return (str && *str)?str:def;
|
||||
}
|
||||
|
||||
const wchar_t *CSettingsParser::FindSettingDirect( const wchar_t *name )
|
||||
{
|
||||
return FindSettingInt(name,wcslen(name));
|
||||
}
|
||||
|
||||
const wchar_t *CSettingsParser::FindSettingInt( const wchar_t *name, size_t len )
|
||||
{
|
||||
for (std::vector<const wchar_t*>::const_reverse_iterator it=m_Lines.rbegin();it!=m_Lines.rend();++it)
|
||||
{
|
||||
const wchar_t *str=*it;
|
||||
if (_wcsnicmp(name,str,len)==0)
|
||||
{
|
||||
str+=len;
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
if (*str!='=') continue;
|
||||
str++;
|
||||
while (*str==' ' || *str=='\t')
|
||||
str++;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Frees all resources
|
||||
void CSettingsParser::Reset( void )
|
||||
{
|
||||
m_Lines.clear();
|
||||
m_Text.clear();
|
||||
}
|
||||
|
||||
// Parses a tree structure of items. The rootName setting must be a list of item names.
|
||||
void CSettingsParser::ParseTree( const wchar_t *rootName, std::vector<TreeItem> &items )
|
||||
{
|
||||
const wchar_t *str=FindSetting(rootName);
|
||||
if (str)
|
||||
{
|
||||
CString names[MAX_TREE_LEVEL];
|
||||
ParseTreeRec(str,items,names,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeItem last={L"",-1};
|
||||
items.push_back(last);
|
||||
}
|
||||
}
|
||||
|
||||
int CSettingsParser::ParseTreeRec( const wchar_t *str, std::vector<TreeItem> &items, CString *names, int level )
|
||||
{
|
||||
size_t start=items.size();
|
||||
while (*str)
|
||||
{
|
||||
wchar_t token[256];
|
||||
str=GetToken(str,token,_countof(token),L", \t");
|
||||
if (token[0])
|
||||
{
|
||||
//
|
||||
bool bFound=false;
|
||||
for (int i=0;i<level;i++)
|
||||
if (_wcsicmp(token,names[i])==0)
|
||||
{
|
||||
bFound=true;
|
||||
break;
|
||||
}
|
||||
if (!bFound)
|
||||
{
|
||||
TreeItem item={token,-1};
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t end=items.size();
|
||||
if (start==end) return -1;
|
||||
|
||||
TreeItem item={L"",-1};
|
||||
items.push_back(item);
|
||||
|
||||
if (level<MAX_TREE_LEVEL-1)
|
||||
{
|
||||
for (size_t i=start;i<end;i++)
|
||||
{
|
||||
wchar_t buf[266];
|
||||
Sprintf(buf,_countof(buf),L"%s.Items",items[i].name);
|
||||
const wchar_t *str2=FindSetting(buf);
|
||||
if (str2)
|
||||
{
|
||||
names[level]=items[i].name;
|
||||
// these two statements must be on separate lines. otherwise items[i] is evaluated before ParseTreeRec, but
|
||||
// the items vector can be reallocated inside ParseTreeRec, causing the address to be invalidated -> crash!
|
||||
int idx=ParseTreeRec(str2,items,names,level+1);
|
||||
items[i].children=idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (int)start;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CSkinParser::LoadVariation( const wchar_t *fname )
|
||||
{
|
||||
m_VarText.swap(m_Text);
|
||||
bool res=LoadText(fname);
|
||||
if (res)
|
||||
{
|
||||
std::vector<const wchar_t*> lines;
|
||||
lines.swap(m_Lines);
|
||||
lines.push_back(L"[TRUE]");
|
||||
ParseText();
|
||||
m_Lines.insert(m_Lines.begin(),lines.begin(),lines.end());
|
||||
}
|
||||
m_VarText.swap(m_Text);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CSkinParser::LoadVariation( HMODULE hMod, HRSRC hResInfo )
|
||||
{
|
||||
m_VarText.swap(m_Text);
|
||||
bool res=LoadText(hMod,hResInfo);
|
||||
if (res)
|
||||
{
|
||||
std::vector<const wchar_t*> lines;
|
||||
lines.swap(m_Lines);
|
||||
lines.push_back(L"[TRUE]");
|
||||
ParseText();
|
||||
m_Lines.insert(m_Lines.begin(),lines.begin(),lines.end());
|
||||
}
|
||||
m_VarText.swap(m_Text);
|
||||
return res;
|
||||
}
|
||||
|
||||
void CSkinParser::Reset( void )
|
||||
{
|
||||
CSettingsParser::Reset();
|
||||
m_VarText.clear();
|
||||
}
|
||||
|
||||
static const wchar_t *g_OptionNames[SKIN_OPTION_TYPE_COUNT]={
|
||||
L"OPTION ",
|
||||
L"OPTION_NUMBER ",
|
||||
L"OPTION_STRING ",
|
||||
L"OPTION_COLOR ",
|
||||
L"OPTION_IMAGE ",
|
||||
};
|
||||
|
||||
// Parses the option from m_Lines[index]. Returns false if index is out of bounds
|
||||
bool CSkinParser::ParseOption( CString &name, TSkinOptionType &type, CString &label, bool &value, CString &condition, CString &disValue, int index )
|
||||
{
|
||||
if (index<0 || index>=(int)m_Lines.size())
|
||||
return false;
|
||||
name.Empty();
|
||||
wchar_t buf[256];
|
||||
const wchar_t *line=m_Lines[index];
|
||||
if (_wcsnicmp(line,L"OPTION",6)!=0)
|
||||
return true;
|
||||
type=SKIN_OPTION_NONE;
|
||||
for (int i=0;i<SKIN_OPTION_TYPE_COUNT;i++)
|
||||
{
|
||||
int len=Strlen(g_OptionNames[i]);
|
||||
if (_wcsnicmp(line,g_OptionNames[i],len)==0)
|
||||
{
|
||||
type=(TSkinOptionType)i;
|
||||
line+=len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type==SKIN_OPTION_NONE)
|
||||
return true;
|
||||
|
||||
const wchar_t *end=wcschr(line,'=');
|
||||
if (!end) return true;
|
||||
line=GetToken(line,buf,_countof(buf),L" \t=");
|
||||
name=buf;
|
||||
line=GetToken(line,buf,_countof(buf),L",");
|
||||
if (buf[0]=='#')
|
||||
label=LoadStringEx(_wtol(buf+1));
|
||||
else
|
||||
label=buf;
|
||||
if (label.IsEmpty())
|
||||
name.Empty();
|
||||
line=GetToken(line,buf,_countof(buf),L" \t,");
|
||||
value=_wtol(buf)!=0;
|
||||
line=GetToken(line,buf,_countof(buf),L",");
|
||||
condition=buf;
|
||||
line=GetToken(line,buf,_countof(buf),L" \t,");
|
||||
disValue=buf;
|
||||
if (type==SKIN_OPTION_BOOL && name==L"RADIOGROUP")
|
||||
type=SKIN_OPTION_GROUP;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Filters the conditional groups
|
||||
// values/count - list of true options. the rest are assumed to be false
|
||||
void CSkinParser::FilterConditions( const wchar_t **values, int count )
|
||||
{
|
||||
std::vector<const wchar_t*> lines;
|
||||
lines.swap(m_Lines);
|
||||
|
||||
bool bEnable=true;
|
||||
|
||||
for (size_t i=0;i<lines.size();i++)
|
||||
{
|
||||
const wchar_t *line=lines[i];
|
||||
if (*line=='[')
|
||||
{
|
||||
bEnable=false;
|
||||
wchar_t condition[256];
|
||||
const wchar_t *end=wcschr(line,']');
|
||||
if (!end) continue; // not closed
|
||||
int len=(int)(end-line)-1;
|
||||
if (len>_countof(condition)-1)
|
||||
continue; // too long
|
||||
memcpy(condition,line+1,len*2);
|
||||
condition[len]=0;
|
||||
|
||||
// evaluate condition
|
||||
if (EvalCondition(condition,values,count)==1)
|
||||
bEnable=true;
|
||||
continue;
|
||||
}
|
||||
if (bEnable)
|
||||
m_Lines.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Substitutes the provided macro strings
|
||||
void CSkinParser::ApplyMacros( const std::vector<std::pair<CString,CString>> ¯os )
|
||||
{
|
||||
std::vector<CString> names;
|
||||
for (std::vector<std::pair<CString,CString>>::const_iterator it=macros.begin();it!=macros.end();++it)
|
||||
{
|
||||
wchar_t name[256];
|
||||
Sprintf(name,_countof(name),L"@%s@",it->first);
|
||||
names.push_back(name);
|
||||
}
|
||||
|
||||
for (std::vector<const wchar_t*>::iterator it=m_Lines.begin();it!=m_Lines.end();++it)
|
||||
{
|
||||
if (wcschr(*it,'@'))
|
||||
{
|
||||
CString string=*it;
|
||||
for (size_t i=0;i<names.size();i++)
|
||||
string.Replace(names[i],macros[i].second);
|
||||
|
||||
m_ExtraStrings.push_back(string);
|
||||
*it=string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a setting with the given name
|
||||
const wchar_t *CSkinParser::FindSetting( const wchar_t *name )
|
||||
{
|
||||
const wchar_t *str=CSettingsParser::FindSetting(name);
|
||||
if (!str && m_Aliases)
|
||||
{
|
||||
for (int i=0;m_Aliases[i];i+=2)
|
||||
{
|
||||
if (wcscmp(name,m_Aliases[i])==0)
|
||||
return CSettingsParser::FindSetting(m_Aliases[i+1]);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum TType
|
||||
{
|
||||
TYPE_AND,
|
||||
TYPE_OR,
|
||||
TYPE_NOT,
|
||||
TYPE_PAR, // '('
|
||||
};
|
||||
|
||||
static bool ApplyOperator( bool *valStack, int &vsp, TType op )
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case TYPE_AND:
|
||||
if (vsp<2) return false;
|
||||
vsp--;
|
||||
valStack[vsp-1]=valStack[vsp-1] && valStack[vsp];
|
||||
return true;
|
||||
case TYPE_OR:
|
||||
if (vsp<2) return false;
|
||||
vsp--;
|
||||
valStack[vsp-1]=valStack[vsp-1] || valStack[vsp];
|
||||
return true;
|
||||
case TYPE_NOT:
|
||||
if (vsp<1) return false;
|
||||
valStack[vsp-1]=!valStack[vsp-1];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Evaluates a boolean condition. vars/count - a list of variable names that are TRUE. The rest are assumed FALSE
|
||||
// Returns: 0 - false, 1 - true, -1 - error
|
||||
int EvalCondition( const wchar_t *condition, const wchar_t *const *values, int count )
|
||||
{
|
||||
wchar_t token[256];
|
||||
TType opStack[16];
|
||||
int osp=0;
|
||||
bool valStack[16];
|
||||
int vsp=0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// skip leading whitespace
|
||||
while (*condition==' ' || *condition=='\t')
|
||||
condition++;
|
||||
if (!*condition) break;
|
||||
|
||||
if (*condition=='(')
|
||||
{
|
||||
if (osp>=_countof(opStack)) return -1; // too much nesting
|
||||
opStack[osp]=TYPE_PAR;
|
||||
osp++;
|
||||
condition++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*condition==')')
|
||||
{
|
||||
bool found=false;
|
||||
while (osp>0)
|
||||
{
|
||||
osp--;
|
||||
if (opStack[osp]==TYPE_PAR)
|
||||
{
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation
|
||||
}
|
||||
if (!found) return -1; // too many )
|
||||
condition++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// find token
|
||||
const wchar_t *end=condition;
|
||||
while (*end && *end!=' ' && *end!='\t' && *end!='(' && *end!=')')
|
||||
end++;
|
||||
|
||||
int len=(int)(end-condition);
|
||||
if (len>=sizeof(token)) return -1; // too long token
|
||||
memcpy(token,condition,len*2);
|
||||
token[len]=0;
|
||||
condition=end;
|
||||
while (*condition==' ' || *condition=='\t')
|
||||
condition++;
|
||||
|
||||
if (_wcsicmp(token,L"and")==0 || _wcsicmp(token,L"or")==0)
|
||||
{
|
||||
while (osp>0 && opStack[osp-1]!=TYPE_PAR)
|
||||
{
|
||||
osp--;
|
||||
if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation
|
||||
}
|
||||
if (osp>=_countof(opStack)) return -1; // too much nesting
|
||||
opStack[osp]=(token[0]=='a' || token[0]=='A')?TYPE_AND:TYPE_OR;
|
||||
osp++;
|
||||
}
|
||||
else if (_wcsicmp(token,L"not")==0)
|
||||
{
|
||||
while (osp>0 && opStack[osp-1]==TYPE_NOT)
|
||||
{
|
||||
osp--;
|
||||
if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation
|
||||
}
|
||||
if (osp>=_countof(opStack)) return -1; // too much nesting
|
||||
opStack[osp]=TYPE_NOT;
|
||||
osp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vsp>=_countof(valStack)) return -1; // too much nesting
|
||||
bool bValue=false;
|
||||
if (_wcsicmp(token,L"true")==0)
|
||||
bValue=true;
|
||||
else
|
||||
{
|
||||
for (int i=0;i<count;i++)
|
||||
if (_wcsicmp(token,values[i])==0)
|
||||
{
|
||||
bValue=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
valStack[vsp++]=bValue;
|
||||
}
|
||||
}
|
||||
|
||||
while (osp>0)
|
||||
{
|
||||
osp--;
|
||||
if (opStack[osp]==TYPE_PAR) return -1; // unclosed (
|
||||
if (!ApplyOperator(valStack,vsp,opStack[osp])) return -1; // invalid operation
|
||||
}
|
||||
|
||||
if (vsp!=1) return -1; // unbalanced expression
|
||||
return valStack[0]?1:0;
|
||||
}
|
||||
104
Src/Lib/SettingsParser.h
Normal file
104
Src/Lib/SettingsParser.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CSettingsParser
|
||||
{
|
||||
public:
|
||||
// Reads a file into m_Text
|
||||
bool LoadText( const wchar_t *fname );
|
||||
// Reads a text resource into m_Text
|
||||
bool LoadText( HMODULE hMod, HRSRC hResInfo );
|
||||
|
||||
void LoadText( const unsigned char *buf, int size );
|
||||
void LoadText( const wchar_t *buf, int size );
|
||||
|
||||
// Splits m_Text into m_Lines
|
||||
void ParseText( void );
|
||||
|
||||
// Filters the settings that belong to the given language
|
||||
// languages is a 00-terminated list of language names ordered by priority
|
||||
void FilterLanguages( const wchar_t *languages );
|
||||
|
||||
// Returns a setting with the given name. If no setting is found, returns def
|
||||
const wchar_t *FindSetting( const wchar_t *name, const wchar_t *def=NULL );
|
||||
// Returns a setting with the given name, even if the value is blank. If the setting is not found, returns NULL
|
||||
const wchar_t *FindSettingDirect( const wchar_t *name );
|
||||
|
||||
// Frees all resources
|
||||
virtual void Reset( void );
|
||||
|
||||
struct TreeItem
|
||||
{
|
||||
CString name; // empty - last child
|
||||
int children; // index to the first child. -1 - no children
|
||||
};
|
||||
|
||||
// Parses a tree structure of items. The rootName setting must be a list of item names.
|
||||
// Then for each name in the list the function will search for name.Items recursively.
|
||||
// The last child in the list will have an empty name.
|
||||
// Note - the rootName item will not be added to the list
|
||||
void ParseTree( const wchar_t *rootName, std::vector<TreeItem> &items );
|
||||
|
||||
protected:
|
||||
std::vector<wchar_t> m_Text;
|
||||
std::vector<const wchar_t*> m_Lines;
|
||||
|
||||
private:
|
||||
const wchar_t *FindSettingInt( const wchar_t *name, size_t len );
|
||||
|
||||
int ParseTreeRec( const wchar_t *rootName, std::vector<TreeItem> &items, CString *names, int level );
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum TSkinOptionType
|
||||
{
|
||||
SKIN_OPTION_GROUP=-2,
|
||||
SKIN_OPTION_NONE=-1,
|
||||
SKIN_OPTION_BOOL,
|
||||
SKIN_OPTION_NUMBER,
|
||||
SKIN_OPTION_STRING,
|
||||
SKIN_OPTION_COLOR,
|
||||
SKIN_OPTION_IMAGE,
|
||||
|
||||
SKIN_OPTION_TYPE_COUNT
|
||||
};
|
||||
|
||||
class CSkinParser: public CSettingsParser
|
||||
{
|
||||
public:
|
||||
CSkinParser( void ) { m_Aliases=NULL; }
|
||||
bool LoadVariation( const wchar_t *fname );
|
||||
bool LoadVariation( HMODULE hMod, HRSRC hResInfo );
|
||||
void SetAliases( const wchar_t **aliases ) { m_Aliases=aliases; }
|
||||
virtual void Reset( void );
|
||||
|
||||
// Parses the option from m_Lines[index]. Returns false if index is out of bounds
|
||||
bool ParseOption( CString &name, TSkinOptionType &type, CString &label, bool &value, CString &condition, CString &disValue, int index );
|
||||
|
||||
// Filters the conditional groups
|
||||
// values/count - list of true options. the rest are assumed to be false
|
||||
void FilterConditions( const wchar_t **values, int count );
|
||||
|
||||
// Substitutes the provided macro strings
|
||||
void ApplyMacros( const std::vector<std::pair<CString,CString>> ¯os );
|
||||
|
||||
// Returns a setting with the given name
|
||||
const wchar_t *FindSetting( const wchar_t *name );
|
||||
|
||||
protected:
|
||||
std::vector<wchar_t> m_VarText;
|
||||
const wchar_t **m_Aliases;
|
||||
std::vector<CString> m_ExtraStrings;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int EvalCondition( const wchar_t *condition, const wchar_t *const *values, int count );
|
||||
3568
Src/Lib/SettingsUIHelper.cpp
Normal file
3568
Src/Lib/SettingsUIHelper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
389
Src/Lib/SettingsUIHelper.h
Normal file
389
Src/Lib/SettingsUIHelper.h
Normal file
@@ -0,0 +1,389 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SettingsParser.h"
|
||||
#include "resource.h"
|
||||
#include "Assert.h"
|
||||
#include <vector>
|
||||
|
||||
class CCommandsTree;
|
||||
class CSettingsTree;
|
||||
class ISettingsPanel;
|
||||
struct CSetting;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CResizeableDlg - a dialog that rearranges its controls when it gets resized
|
||||
template<class T> class CResizeableDlg: public CDialogImpl<T>
|
||||
{
|
||||
public:
|
||||
CResizeableDlg( void )
|
||||
{
|
||||
m_ClientSize.cx=m_ClientSize.cy=0;
|
||||
m_WindowSize.cx=m_WindowSize.cy=0;
|
||||
m_Flags=0;
|
||||
}
|
||||
|
||||
void Create( HWND hWndParent )
|
||||
{
|
||||
CDialogImpl<T>::Create(hWndParent);
|
||||
}
|
||||
|
||||
void Create( HWND hWndParent, DLGTEMPLATE *pTemplate )
|
||||
{
|
||||
ATLASSUME(m_hWnd == NULL);
|
||||
if (!m_thunk.Init(NULL,NULL))
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
_AtlWinModule.AddCreateWndData(&m_thunk.cd,(CDialogImplBaseT<CWindow>*)this);
|
||||
HWND hWnd=::CreateDialogIndirect(_AtlBaseModule.GetResourceInstance(),pTemplate,hWndParent,T::StartDialogProc);
|
||||
ATLASSUME(m_hWnd==hWnd);
|
||||
}
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
MOVE_LEFT=1,
|
||||
MOVE_LEFT2=2,
|
||||
MOVE_RIGHT=4,
|
||||
MOVE_RIGHT2=8,
|
||||
MOVE_TOP=16,
|
||||
MOVE_TOP2=32,
|
||||
MOVE_BOTTOM=64,
|
||||
MOVE_BOTTOM2=128,
|
||||
|
||||
MOVE_MOVE_X=MOVE_LEFT|MOVE_RIGHT,
|
||||
MOVE_MOVE_Y=MOVE_TOP|MOVE_BOTTOM,
|
||||
MOVE_SIZE_X=MOVE_RIGHT,
|
||||
MOVE_SIZE_Y=MOVE_BOTTOM,
|
||||
MOVE_LEFT_HALF=MOVE_RIGHT2,
|
||||
MOVE_RIGHT_HALF=MOVE_LEFT2|MOVE_RIGHT,
|
||||
MOVE_CENTER=MOVE_LEFT2|MOVE_RIGHT2,
|
||||
MOVE_TOP_HALF=MOVE_BOTTOM2,
|
||||
MOVE_BOTTOM_HALF=MOVE_TOP2|MOVE_BOTTOM,
|
||||
MOVE_VCENTER=MOVE_TOP2|MOVE_BOTTOM2,
|
||||
|
||||
MOVE_HORIZONTAL=1,
|
||||
MOVE_VERTICAL=2,
|
||||
MOVE_GRIPPER=4,
|
||||
MOVE_REINITIALIZE=8, // InitResize is called for a second time to recapture the control sizes
|
||||
|
||||
MOVE_MODAL=MOVE_HORIZONTAL|MOVE_VERTICAL|MOVE_GRIPPER,
|
||||
};
|
||||
|
||||
struct Control
|
||||
{
|
||||
int id;
|
||||
unsigned int flags;
|
||||
HWND hwnd;
|
||||
RECT rect0;
|
||||
};
|
||||
|
||||
void InitResize( int flags=MOVE_HORIZONTAL|MOVE_VERTICAL )
|
||||
{
|
||||
m_Flags=flags;
|
||||
T *pThis=static_cast<T*>(this);
|
||||
|
||||
int count=0;
|
||||
for (const Control *pControl=pThis->GetResizeControls();pControl->id;pControl++)
|
||||
count++;
|
||||
m_Controls.resize(count);
|
||||
if (count>0)
|
||||
memcpy(&m_Controls[0],pThis->GetResizeControls(),count*sizeof(Control));
|
||||
|
||||
RECT rc;
|
||||
pThis->GetClientRect(&rc);
|
||||
if (!(m_Flags&MOVE_REINITIALIZE))
|
||||
{
|
||||
m_Gripper.m_hWnd=NULL;
|
||||
if (m_Flags&MOVE_GRIPPER)
|
||||
m_Gripper.Create(L"SCROLLBAR",pThis->m_hWnd,rc,NULL,WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|SBS_SIZEBOX|SBS_SIZEGRIP|SBS_SIZEBOXBOTTOMRIGHTALIGN);
|
||||
}
|
||||
m_ClientSize.cx=rc.right;
|
||||
m_ClientSize.cy=rc.bottom;
|
||||
pThis->GetWindowRect(&rc);
|
||||
m_WindowSize.cx=rc.right-rc.left;
|
||||
m_WindowSize.cy=rc.bottom-rc.top;
|
||||
for (std::vector<Control>::iterator it=m_Controls.begin();it!=m_Controls.end();++it)
|
||||
{
|
||||
it->hwnd=pThis->GetDlgItem(it->id);
|
||||
Assert(it->hwnd);
|
||||
if (!it->hwnd) continue;
|
||||
::GetWindowRect(it->hwnd,&it->rect0);
|
||||
::MapWindowPoints(NULL,m_hWnd,(POINT*)&it->rect0,2);
|
||||
}
|
||||
}
|
||||
|
||||
void OnSize( void )
|
||||
{
|
||||
T *pThis=static_cast<T*>(this);
|
||||
RECT rc;
|
||||
pThis->GetClientRect(&rc);
|
||||
int dx=rc.right-m_ClientSize.cx;
|
||||
int dy=rc.bottom-m_ClientSize.cy;
|
||||
int dx2=dx/2;
|
||||
int dy2=dy/2;
|
||||
for (std::vector<Control>::iterator it=m_Controls.begin();it!=m_Controls.end();++it)
|
||||
{
|
||||
if (!it->hwnd) continue;
|
||||
int x1=it->rect0.left;
|
||||
int y1=it->rect0.top;
|
||||
int x2=it->rect0.right;
|
||||
int y2=it->rect0.bottom;
|
||||
if (it->flags&MOVE_LEFT) x1+=dx;
|
||||
else if (it->flags&MOVE_LEFT2) x1+=dx2;
|
||||
if (it->flags&MOVE_TOP) y1+=dy;
|
||||
else if (it->flags&MOVE_TOP2) y1+=dy2;
|
||||
if (it->flags&MOVE_RIGHT) x2+=dx;
|
||||
else if (it->flags&MOVE_RIGHT2) x2+=dx2;
|
||||
if (it->flags&MOVE_BOTTOM) y2+=dy;
|
||||
else if (it->flags&MOVE_BOTTOM2) y2+=dy2;
|
||||
::SetWindowPos(it->hwnd,NULL,x1,y1,x2-x1,y2-y1,SWP_NOZORDER|SWP_NOCOPYBITS);
|
||||
}
|
||||
if (m_Gripper.m_hWnd)
|
||||
{
|
||||
RECT rc2;
|
||||
m_Gripper.GetWindowRect(&rc2);
|
||||
int w=rc2.right-rc2.left;
|
||||
int h=rc2.bottom-rc2.top;
|
||||
m_Gripper.SetWindowPos(HWND_BOTTOM,rc.right-w,rc.bottom-h,w,h,0);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT OnGetMinMaxInfo( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
|
||||
{
|
||||
MINMAXINFO *pInfo=(MINMAXINFO*)lParam;
|
||||
pInfo->ptMinTrackSize.x=m_WindowSize.cx;
|
||||
pInfo->ptMinTrackSize.y=m_WindowSize.cy;
|
||||
if (!(m_Flags&MOVE_HORIZONTAL))
|
||||
pInfo->ptMaxTrackSize.x=pInfo->ptMinTrackSize.x;
|
||||
if (!(m_Flags&MOVE_VERTICAL))
|
||||
pInfo->ptMaxTrackSize.y=pInfo->ptMinTrackSize.y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GetStoreRect( RECT &rc )
|
||||
{
|
||||
GetWindowRect(&rc);
|
||||
rc.right-=rc.left+m_WindowSize.cx;
|
||||
rc.bottom-=rc.top+m_WindowSize.cy;
|
||||
}
|
||||
|
||||
void GetPlacementRect( RECT &rc )
|
||||
{
|
||||
WINDOWPLACEMENT placement;
|
||||
GetWindowPlacement(&placement);
|
||||
rc=placement.rcNormalPosition;
|
||||
rc.right-=rc.left+m_WindowSize.cx;
|
||||
rc.bottom-=rc.top+m_WindowSize.cy;
|
||||
}
|
||||
|
||||
void SetStoreRect( const RECT &rc )
|
||||
{
|
||||
SetWindowPos(NULL,rc.left,rc.top,m_WindowSize.cx+rc.right,m_WindowSize.cy+rc.bottom,SWP_NOZORDER|SWP_NOCOPYBITS);
|
||||
SendMessage(DM_REPOSITION);
|
||||
}
|
||||
|
||||
private:
|
||||
SIZE m_ClientSize;
|
||||
SIZE m_WindowSize;
|
||||
int m_Flags;
|
||||
CWindow m_Gripper;
|
||||
std::vector<Control> m_Controls;
|
||||
};
|
||||
|
||||
#define BEGIN_RESIZE_MAP const Control *GetResizeControls( void ) { static Control controls[]={
|
||||
#define RESIZE_CONTROL(id,flags) {id,flags},
|
||||
#define END_RESIZE_MAP {0,0}}; return controls; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CStdCommand
|
||||
{
|
||||
const wchar_t *name; // NULL for the terminator item, empty for custom item
|
||||
int displayNameId; // always valid
|
||||
int tipID;
|
||||
const wchar_t *itemName; // NULL for separators
|
||||
const wchar_t *label;
|
||||
const wchar_t *tip;
|
||||
const wchar_t *icon; // NULL for separators, "none" - force no icon, "" for default icon
|
||||
const KNOWNFOLDERID *knownFolder;
|
||||
unsigned int settings;
|
||||
const wchar_t *iconD;
|
||||
|
||||
bool IsSeparator( void ) const { return !itemName; }
|
||||
bool IsCustom( void ) const { return !*name; }
|
||||
bool IsStyle( int style, int mask ) const { return (settings&mask)==0 || (settings&style); }
|
||||
};
|
||||
|
||||
struct CTreeItem
|
||||
{
|
||||
CString name;
|
||||
CString command;
|
||||
CString link;
|
||||
CString label;
|
||||
CString tip;
|
||||
CString icon;
|
||||
CString iconD;
|
||||
unsigned int settings;
|
||||
const CStdCommand *pStdCommand; // always valid
|
||||
|
||||
CTreeItem( void ) { settings=0; pStdCommand=NULL; }
|
||||
void SetCommand( CString command, const CStdCommand *pStdCommands, int style, int mask );
|
||||
unsigned int GetIconKey( void ) const;
|
||||
HICON LoadIcon( bool bSmall, std::vector<HMODULE> &modules ) const;
|
||||
unsigned int GetIconDKey( unsigned int iconKey ) const;
|
||||
HICON LoadIconD( HICON hIcon, std::vector<HMODULE> &modules ) const; // always large
|
||||
CString GetDisplayName( bool bTitle ) const;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const HICON HICON_NONE=(HICON)-1;
|
||||
|
||||
class CCustomTreeDlg: public CResizeableDlg<CCustomTreeDlg>
|
||||
{
|
||||
public:
|
||||
CCustomTreeDlg( bool bMenu, const CStdCommand *pStdCommands, int style, int mask );
|
||||
~CCustomTreeDlg( void );
|
||||
|
||||
BEGIN_MSG_MAP( CCustomTreeDlg )
|
||||
MESSAGE_HANDLER( WM_INITDIALOG, OnInitDialog )
|
||||
MESSAGE_HANDLER( WM_SIZE, OnSize )
|
||||
MESSAGE_HANDLER( WM_CONTEXTMENU, OnContextMenu )
|
||||
|
||||
NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_GETINFOTIP, OnGetInfoTip )
|
||||
NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_BEGINDRAG, OnBeginDrag )
|
||||
NOTIFY_HANDLER( IDC_TREECOMMANDS, NM_DBLCLK, OnAddItem )
|
||||
NOTIFY_HANDLER( IDC_TREECOMMANDS, TVN_KEYDOWN, OnAddItem )
|
||||
NOTIFY_HANDLER( IDC_TREEITEMS, TVN_GETINFOTIP, OnGetInfoTip )
|
||||
NOTIFY_HANDLER( IDC_TREEITEMS, NM_DBLCLK, OnEditItem )
|
||||
NOTIFY_HANDLER( IDC_TREEITEMS, TVN_KEYDOWN, OnEditItem )
|
||||
NOTIFY_HANDLER( IDC_TREEITEMS, NM_CUSTOMDRAW, OnCustomDraw )
|
||||
REFLECT_NOTIFICATIONS()
|
||||
END_MSG_MAP()
|
||||
|
||||
BEGIN_RESIZE_MAP
|
||||
RESIZE_CONTROL(IDC_TREEITEMS,MOVE_LEFT_HALF|MOVE_SIZE_Y)
|
||||
RESIZE_CONTROL(IDC_STATICMIDDLE,MOVE_CENTER|MOVE_VCENTER)
|
||||
RESIZE_CONTROL(IDC_STATICRIGHT,MOVE_CENTER)
|
||||
RESIZE_CONTROL(IDC_TREECOMMANDS,MOVE_RIGHT_HALF|MOVE_SIZE_Y)
|
||||
RESIZE_CONTROL(IDC_STATICHINT,MOVE_SIZE_X|MOVE_MOVE_Y)
|
||||
END_RESIZE_MAP
|
||||
|
||||
void SetGroup( CSetting *pGroup, bool bReset );
|
||||
void SerializeData( void );
|
||||
|
||||
protected:
|
||||
// Handler prototypes:
|
||||
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
|
||||
LRESULT OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnContextMenu( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnGetInfoTip( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnBeginDrag( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnAddItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnEditItem( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
LRESULT OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled );
|
||||
|
||||
virtual void InitItems( void ) {}
|
||||
virtual void ItemsChanged( void ) {}
|
||||
virtual void ParseTreeItemExtra( CTreeItem *pItem, CSettingsParser &parser ) {}
|
||||
virtual void SerializeItemExtra( CTreeItem *pItem, std::vector<wchar_t> &stringBuilder ) {}
|
||||
virtual bool EditItem( CTreeItem *pItem, HWND tree, HTREEITEM hItem, std::vector<HMODULE> &modules );
|
||||
void AddItem( HTREEITEM hCommand );
|
||||
|
||||
HTREEITEM GetRoot( void );
|
||||
HTREEITEM GetChild( HTREEITEM hParent );
|
||||
HTREEITEM GetNext( HTREEITEM hItem );
|
||||
CTreeItem *GetItem( HTREEITEM hItem );
|
||||
|
||||
static void AppendString( std::vector<wchar_t> &stringBuilder, const wchar_t *text );
|
||||
|
||||
int m_Style, m_StyleMask;
|
||||
|
||||
private:
|
||||
CSettingsTree &m_Tree;
|
||||
CCommandsTree &m_CommandsTree;
|
||||
const CStdCommand *m_pStdCommands;
|
||||
CSetting *m_pSetting;
|
||||
bool m_bMenu;
|
||||
|
||||
const CStdCommand *FindStdCommand( const wchar_t *name );
|
||||
|
||||
void EditItemInternal( CTreeItem *pItem, HTREEITEM hItem );
|
||||
int ParseTreeItem( CTreeItem *pItem, CSettingsParser &parser );
|
||||
void SerializeItem( HTREEITEM hItem, std::vector<wchar_t> &stringBuilder );
|
||||
void CreateTreeItems( CSettingsParser &parser, HTREEITEM hParent, const CSettingsParser::TreeItem *pItems, int index );
|
||||
};
|
||||
|
||||
class CEditCustomItemDlg: public CResizeableDlg<CEditCustomItemDlg>
|
||||
{
|
||||
public:
|
||||
CEditCustomItemDlg( CTreeItem *pItem, std::vector<HMODULE> &modules ): m_Modules(modules) { m_pItem=pItem; }
|
||||
virtual ~CEditCustomItemDlg( void );
|
||||
void SetEnableParent( HWND parent ) { m_EnableParent=parent; }
|
||||
bool GetResult( void ) { return m_bResult; }
|
||||
|
||||
BEGIN_MSG_MAP( CEditCustomItemDlg )
|
||||
MESSAGE_HANDLER( WM_SIZE, OnSize )
|
||||
MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo )
|
||||
END_MSG_MAP()
|
||||
|
||||
virtual BEGIN_RESIZE_MAP
|
||||
END_RESIZE_MAP
|
||||
|
||||
bool Run( HWND parent, int dlgID );
|
||||
|
||||
protected:
|
||||
CTreeItem *m_pItem;
|
||||
|
||||
// Handler prototypes:
|
||||
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
|
||||
LRESULT OnSize( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
|
||||
LRESULT OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
|
||||
LRESULT OnOK( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
|
||||
LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
|
||||
|
||||
void InitDialog( CWindow commandCombo, const CStdCommand *pStdcommands, int style, int mask, CWindow linkCombo, const KNOWNFOLDERID *const *pCommonLinks );
|
||||
void UpdateIcons( int iconID, int iconDID );
|
||||
CString GetComboText( WORD wNotifyCode, WORD wID );
|
||||
|
||||
private:
|
||||
std::vector<HMODULE> &m_Modules;
|
||||
HWND m_EnableParent;
|
||||
bool m_bResult;
|
||||
HICON m_hIcon;
|
||||
unsigned int m_IconKey;
|
||||
HICON m_hIconD;
|
||||
unsigned int m_IconDKey;
|
||||
CTreeItem m_StoredItem;
|
||||
|
||||
void StorePlacement( void );
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ISettingsPanel *GetDefaultSettings( const CString *filter, const CSetting *pSelect );
|
||||
HIMAGELIST GetSettingsImageList( HWND tree );
|
||||
bool BrowseForIcon( HWND hWndParent, wchar_t *path, int &id );
|
||||
bool BrowseForBitmap( HWND hWndParent, wchar_t *path, bool bAllowJpeg );
|
||||
bool BrowseForSound( HWND hWndParent, wchar_t *path );
|
||||
const wchar_t *GetSettingsRegPath( void );
|
||||
|
||||
// Special GUID for the real desktop
|
||||
extern const GUID FOLDERID_DesktopRoot;
|
||||
|
||||
bool BrowseCommandHelper( HWND parent, wchar_t *text );
|
||||
bool BrowseLinkHelper( HWND parent, wchar_t *text );
|
||||
bool BrowseIconHelper( HWND parent, wchar_t *text );
|
||||
75
Src/Lib/StringSet.cpp
Normal file
75
Src/Lib/StringSet.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "StringSet.h"
|
||||
|
||||
static CString CreateString( const WORD *data )
|
||||
{
|
||||
int len=*data;
|
||||
data++;
|
||||
if (len==0) return NULL;
|
||||
|
||||
CString str;
|
||||
wchar_t *ptr=str.GetBuffer(len);
|
||||
if (ptr)
|
||||
{
|
||||
memcpy(ptr,data,len*2);
|
||||
ptr[len]=0;
|
||||
str.ReleaseBufferSetLength(len);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
BOOL CALLBACK CStringSet::EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam )
|
||||
{
|
||||
CStringSet *set=(CStringSet*)lParam;
|
||||
// find resource
|
||||
HRSRC hr=FindResource(hModule,lpszName,RT_STRING);
|
||||
if (!hr) return TRUE;
|
||||
|
||||
HGLOBAL hg=LoadResource(hModule,hr);
|
||||
if (hg)
|
||||
{
|
||||
const WORD *res=(WORD*)LockResource(hg);
|
||||
if (res)
|
||||
{
|
||||
for (int i=0;i<16;i++)
|
||||
{
|
||||
int id=(((int)(intptr_t)lpszName)<<4)+i-16;
|
||||
|
||||
CString str=CreateString(res);
|
||||
if (!str.IsEmpty())
|
||||
(*set)[id]=str;
|
||||
res+=(*res)+1;
|
||||
}
|
||||
UnlockResource(hg);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Initializes the string database
|
||||
void CStringSet::Init( HINSTANCE hInstance )
|
||||
{
|
||||
clear();
|
||||
m_hInstance=hInstance;
|
||||
if (hInstance)
|
||||
EnumResourceNames(hInstance,RT_STRING,EnumResNameProc,(LONG_PTR)this);
|
||||
}
|
||||
|
||||
// Returns a string by ID (returns "" if the string is missing)
|
||||
CString CStringSet::GetString( UINT uID )
|
||||
{
|
||||
// search in the database
|
||||
const_iterator it=find(uID);
|
||||
|
||||
if (it!=end())
|
||||
{
|
||||
if (it->second)
|
||||
return it->second;
|
||||
}
|
||||
return CString();
|
||||
}
|
||||
23
Src/Lib/StringSet.h
Normal file
23
Src/Lib/StringSet.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
class CStringSet: public std::map<int,CString>
|
||||
{
|
||||
public:
|
||||
CStringSet( void ) { m_hInstance=NULL; }
|
||||
// Initializes the string database
|
||||
void Init( HINSTANCE hInstance );
|
||||
|
||||
// Returns a string by ID (returns "" if the string is missing)
|
||||
CString GetString( UINT uID );
|
||||
|
||||
private:
|
||||
HINSTANCE m_hInstance;
|
||||
|
||||
static BOOL CALLBACK CStringSet::EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam );
|
||||
};
|
||||
484
Src/Lib/StringUtils.cpp
Normal file
484
Src/Lib/StringUtils.cpp
Normal file
@@ -0,0 +1,484 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
// StringUtils is also available under the CPOL license as part of the FormatString article
|
||||
// on CodeProject: http://www.codeproject.com/KB/string/FormatString.aspx
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "StringUtils.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef STR_USE_WIN32_CONV
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef STR_USE_WIN32_DBCS
|
||||
static int g_MaxCharSize=0;
|
||||
#endif
|
||||
|
||||
// Returns 1 if the ANSI code page is single-byte, or 2 if it is double-byte (DBCS)
|
||||
int GetMaxCharSize( void )
|
||||
{
|
||||
#ifdef STR_USE_WIN32_DBCS
|
||||
if (!g_MaxCharSize)
|
||||
{
|
||||
CPINFO info;
|
||||
if (GetCPInfo(CP_ACP,&info))
|
||||
g_MaxCharSize=info.MaxCharSize;
|
||||
}
|
||||
return g_MaxCharSize;
|
||||
#else
|
||||
return MB_CUR_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Copies src to dst. size is the size of dst in bytes, including the terminating 0.
|
||||
// Returns the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int Strcpy( char *dst, int size, const char *src )
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
char *dst0=dst;
|
||||
if (GetMaxCharSize()==1)
|
||||
{
|
||||
// SBCS version
|
||||
while (size>1)
|
||||
{
|
||||
if (*src==0) break;
|
||||
*dst++=*src++;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DBCS version
|
||||
while (size>1)
|
||||
{
|
||||
if (*src==0) break;
|
||||
#ifdef STR_USE_WIN32_DBCS
|
||||
if (IsDBCSLeadByte((BYTE)*src))
|
||||
{
|
||||
#else
|
||||
if (isleadbyte((unsigned char)*src))
|
||||
{
|
||||
#endif
|
||||
if (size==2) break;
|
||||
if (src[1]==0) break;
|
||||
*dst++=*src++;
|
||||
*dst++=*src++;
|
||||
size-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst++=*src++;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dst=0;
|
||||
return (int)(dst-dst0);
|
||||
}
|
||||
|
||||
int Strcpy( wchar_t *dst, int size, const wchar_t *src )
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
int len=Strlen(src);
|
||||
if (len>size-1)
|
||||
len=size-1;
|
||||
if (len>0 && src[len]>=0xDC00 && src[len]<=0xDFFF) // check for trailing surrogate
|
||||
len--;
|
||||
memcpy(dst,src,len*sizeof(wchar_t));
|
||||
dst[len]=0;
|
||||
return len;
|
||||
}
|
||||
|
||||
// Copies src to dst. size is the size of dst in characters, including the terminating 0.
|
||||
// Copies up to len characters and always appends terminating 0.
|
||||
int Strncpy( char *dst, int size, const char *src, int len )
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
char *dst0=dst;
|
||||
const char *end=src+len;
|
||||
if (GetMaxCharSize()==1)
|
||||
{
|
||||
// SBCS version
|
||||
while (size>1)
|
||||
{
|
||||
if (src==end) break;
|
||||
*dst++=*src++;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// DBCS version
|
||||
while (size>1)
|
||||
{
|
||||
if (src==end) break;
|
||||
#ifdef STR_USE_WIN32_DBCS
|
||||
if (IsDBCSLeadByte((BYTE)*src))
|
||||
{
|
||||
#else
|
||||
if (isleadbyte((unsigned char)*src))
|
||||
{
|
||||
#endif
|
||||
if (size==2) break;
|
||||
if (src+1==end) break;
|
||||
*dst++=*src++;
|
||||
*dst++=*src++;
|
||||
size-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst++=*src++;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*dst=0;
|
||||
return (int)(dst-dst0);
|
||||
}
|
||||
|
||||
int Strncpy( wchar_t *dst, int size, const wchar_t *src, int len )
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
if (len>size-1)
|
||||
len=size-1;
|
||||
if (len>0 && src[len]>=0xDC00 && src[len]<=0xDFFF) // check for trailing surrogate
|
||||
len--;
|
||||
memcpy(dst,src,len*sizeof(wchar_t));
|
||||
dst[len]=0;
|
||||
return len;
|
||||
}
|
||||
|
||||
// Appends src to dst. size is the size of dst in bytes, including the terminating 0.
|
||||
// Returns the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1-strlen(dst). If size>=strlen(dst), returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int Strcat( char *dst, int size, const char *src )
|
||||
{
|
||||
assert(dst);
|
||||
int len=Strlen(dst);
|
||||
assert(len<size);
|
||||
return Strcpy(dst+len,size-len,src);
|
||||
}
|
||||
|
||||
int Strcat( wchar_t *dst, int size, const wchar_t *src )
|
||||
{
|
||||
assert(dst);
|
||||
int len=Strlen(dst);
|
||||
assert(len<size);
|
||||
return Strcpy(dst+len,size-len,src);
|
||||
}
|
||||
|
||||
// Writes formatted string to dst. size is the size of dst in characters, including the terminating 0.
|
||||
// Returns the number of characters written, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int Sprintf( char *dst, int size, const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
int len=Vsprintf(dst,size,format,args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Sprintf( wchar_t *dst, int size, const wchar_t *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
int len=Vsprintf(dst,size,format,args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Vsprintf( char *dst, int size, const char *format, va_list args )
|
||||
{
|
||||
assert(dst);
|
||||
assert(format);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
int len=_vsnprintf_s(dst,size,size-1,format,args);
|
||||
#else
|
||||
int len=_vsnprintf(dst,size-1,format,args);
|
||||
#endif
|
||||
if (len<0)
|
||||
len=size-1;
|
||||
dst[len]=0;
|
||||
return len;
|
||||
}
|
||||
|
||||
int Vsprintf( wchar_t *dst, int size, const wchar_t *format, va_list args )
|
||||
{
|
||||
assert(dst);
|
||||
assert(format);
|
||||
assert(size>0);
|
||||
if (size<=0) return 0;
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
int len=_vsnwprintf_s(dst,size,size-1,format,args);
|
||||
#else
|
||||
int len=_vsnwprintf(dst,size-1,format,args);
|
||||
#endif
|
||||
if (len<0)
|
||||
len=size-1;
|
||||
dst[len]=0;
|
||||
return len;
|
||||
}
|
||||
|
||||
// Outputs a formatted debug string
|
||||
void Trace( const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
char buf[1024];
|
||||
Vsprintf(buf,_countof(buf)-2,format,args);
|
||||
Strcat(buf,_countof(buf),"\r\n");
|
||||
OutputDebugStringA(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Trace( const wchar_t *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
wchar_t buf[1024];
|
||||
Vsprintf(buf,_countof(buf)-2,format,args);
|
||||
Strcat(buf,_countof(buf),L"\r\n");
|
||||
OutputDebugStringW(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Convert between multi-byte and wide characters. size is the size of dst in characters, including the
|
||||
// terminating 0.
|
||||
// Return the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
|
||||
#ifdef STR_USE_WIN32_CONV
|
||||
int MbsToWcs( wchar_t *dst, int size, const char *src, int codePage )
|
||||
{
|
||||
if (!dst)
|
||||
return MultiByteToWideChar(codePage,0,src,Strlen(src),NULL,0);
|
||||
|
||||
assert(size);
|
||||
if (size==0) return 0;
|
||||
if (size==1)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
int len=Strlen(src);
|
||||
dst[size-2]=0;
|
||||
int res=MultiByteToWideChar(codePage,0,src,len,dst,size-1);
|
||||
if (res)
|
||||
{
|
||||
// the result fits
|
||||
dst[res]=0;
|
||||
return res;
|
||||
}
|
||||
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
|
||||
{ // some unknown error
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dst[size-2]) // could not fit a surrogate pair
|
||||
return size-2;
|
||||
dst[size-1]=0;
|
||||
return size-1;
|
||||
}
|
||||
|
||||
int WcsToMbs( char *dst, int size, const wchar_t *src, int codePage )
|
||||
{
|
||||
if (!dst)
|
||||
return WideCharToMultiByte(codePage,0,src,Strlen(src),NULL,0,NULL,NULL);
|
||||
|
||||
assert(size);
|
||||
if (size==0) return 0;
|
||||
if (size==1)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
int len=Strlen(src);
|
||||
int l=size;
|
||||
if (l>10) l=10;
|
||||
memset(dst+size-l,0,l); // fill the end with zeros (up to 10 bytes)
|
||||
int res=WideCharToMultiByte(codePage,0,src,len,dst,size-1,NULL,NULL);
|
||||
if (res)
|
||||
{
|
||||
// the result fits
|
||||
dst[res]=0;
|
||||
return res;
|
||||
}
|
||||
if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER) // some unknown error
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// find the last non-zero to return the correct length
|
||||
for (len=size-1;len>0;len--)
|
||||
if (dst[len-1])
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int MbsToWcs( wchar_t *dst, int size, const char *src )
|
||||
{
|
||||
if (!dst)
|
||||
{
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
size_t res;
|
||||
if (mbstowcs_s(&res,NULL,0,src,0)!=0)
|
||||
return 0;
|
||||
return (int)res-1;
|
||||
#else
|
||||
int res=(int)mbstowcs(NULL,src,0);
|
||||
if (res<0) return 0;
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(size);
|
||||
if (size==0) return 0;
|
||||
if (size==1)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
size_t res;
|
||||
mbstowcs_s(&res,dst,size,src,_TRUNCATE);
|
||||
return (int)res-1;
|
||||
#else
|
||||
int res=(int)mbstowcs(dst,src,size-1);
|
||||
if (res<0)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
if (res==size-1)
|
||||
dst[res]=0;
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
int WcsToMbs( char *dst, int size, const wchar_t *src )
|
||||
{
|
||||
if (!dst)
|
||||
{
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
size_t res;
|
||||
if (wcstombs_s(&res,NULL,0,src,0)!=0)
|
||||
return 0;
|
||||
return (int)res-1;
|
||||
#else
|
||||
int res=(int)wcstombs(NULL,src,0);
|
||||
if (res<0) return 0;
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(size);
|
||||
if (size==0) return 0;
|
||||
if (size==1)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _MSC_VER>=1400 // VC8.0
|
||||
size_t res;
|
||||
if (wcstombs_s(&res,dst,size,src,_TRUNCATE)!=0)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
return (int)res-1;
|
||||
#else
|
||||
int res=(int)wcstombs(dst,src,size-1);
|
||||
if (res<0)
|
||||
{
|
||||
dst[0]=0;
|
||||
return 0;
|
||||
}
|
||||
if (res==size-1)
|
||||
dst[res]=0;
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *GetToken( const char *text, char *token, int size, const char *separators )
|
||||
{
|
||||
while (*text && strchr(separators,*text))
|
||||
text++;
|
||||
const char *c1=text,*c2;
|
||||
if (text[0]=='\"')
|
||||
{
|
||||
c1++;
|
||||
c2=strchr(c1,'\"');
|
||||
}
|
||||
else
|
||||
{
|
||||
c2=c1;
|
||||
while (*c2!=0 && !strchr(separators,*c2))
|
||||
c2++;
|
||||
}
|
||||
if (!c2) c2=text+strlen(text);
|
||||
int l=(int)(c2-c1);
|
||||
if (l>size-1) l=size-1;
|
||||
memcpy(token,c1,l);
|
||||
token[l]=0;
|
||||
|
||||
if (*c2) return c2+1;
|
||||
else return c2;
|
||||
}
|
||||
|
||||
const wchar_t *GetToken( const wchar_t *text, wchar_t *token, int size, const wchar_t *separators )
|
||||
{
|
||||
while (*text && wcschr(separators,*text))
|
||||
text++;
|
||||
const wchar_t *c1=text,*c2;
|
||||
if (text[0]=='\"')
|
||||
{
|
||||
c1++;
|
||||
c2=wcschr(c1,'\"');
|
||||
}
|
||||
else
|
||||
{
|
||||
c2=c1;
|
||||
while (*c2!=0 && !wcschr(separators,*c2))
|
||||
c2++;
|
||||
}
|
||||
if (!c2) c2=text+wcslen(text);
|
||||
int l=(int)(c2-c1);
|
||||
if (l>size-1) l=size-1;
|
||||
memcpy(token,c1,l*2);
|
||||
token[l]=0;
|
||||
|
||||
if (*c2) return c2+1;
|
||||
else return c2;
|
||||
}
|
||||
113
Src/Lib/StringUtils.h
Normal file
113
Src/Lib/StringUtils.h
Normal file
@@ -0,0 +1,113 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
// StringUtils is also available under the CPOL license as part of the FormatString article
|
||||
// on CodeProject: http://www.codeproject.com/KB/string/FormatString.aspx
|
||||
|
||||
#ifndef _STRINGUTILS_H
|
||||
#define _STRINGUTILS_H
|
||||
|
||||
// StringUtils provides secure implementations of common string functions.
|
||||
// All strings are guaranteed to be zero-terminated and to not contain partial
|
||||
// double-byte characters or partial surrogate pairs.
|
||||
// It also provides char and wchar_t overrides of the same functions.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Configuration of the string functions
|
||||
|
||||
// If defined, enables the use of WideCharToMultiByte and MultiByteToWideChar
|
||||
// If not defined, wcstombs and mbstowcs are used instead. they always use the default code page
|
||||
// and don't support surrogate pairs
|
||||
#define STR_USE_WIN32_CONV
|
||||
|
||||
// If defined, enables the use of Windows localization functions - GetNumberFormat, GetTimeFormat, etc
|
||||
// If not defined, then the numbers, currency, time and date use fixed formats
|
||||
#define STR_USE_WIN32_NLS
|
||||
|
||||
// If defined, enables support for SYSTEMTIME, FILETIME and DATE
|
||||
// If not defined, only time_t is supported as a time format
|
||||
#define STR_USE_WIN32_TIME
|
||||
|
||||
// If defined, enables the use of IsDBCSLeadByte to support DBCS code pages
|
||||
// If not defined, isleadbyte is used instead
|
||||
#define STR_USE_WIN32_DBCS
|
||||
|
||||
// enables support for STL strings and streams
|
||||
//#define STR_USE_STL
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef STR_USE_STL
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
// _countof: compute the number of elements in a statically-allocated array
|
||||
// VS2005 supports this, but earlier versions do not
|
||||
#ifndef _countof
|
||||
#define _countof(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
// Returns 1 if the ANSI code page is single-byte, or 2 if it is double-byte (DBCS)
|
||||
int GetMaxCharSize( void );
|
||||
|
||||
// Returns the length of a string
|
||||
inline int Strlen( const char *str ) { return (int)strlen(str); }
|
||||
inline int Strlen( const wchar_t *str ) { return (int)wcslen(str); }
|
||||
|
||||
// Copies src to dst. size is the size of dst in characters, including the terminating 0.
|
||||
// Returns the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int Strcpy( char *dst, int size, const char *src );
|
||||
int Strcpy( wchar_t *dst, int size, const wchar_t *src );
|
||||
|
||||
// Copies src to dst. size is the size of dst in characters, including the terminating 0.
|
||||
// Copies up to len characters and always appends terminating 0.
|
||||
int Strncpy( char *dst, int size, const char *src, int len );
|
||||
int Strncpy( wchar_t *dst, int size, const wchar_t *src, int len );
|
||||
|
||||
// Appends src to dst. size is the size of dst in bytes, including the terminating 0.
|
||||
// Returns the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1-strlen(dst). If size>=strlen(dst), returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int Strcat( char *dst, int size, const char *src );
|
||||
int Strcat( wchar_t *dst, int size, const wchar_t *src );
|
||||
|
||||
// Writes formatted string to dst. size is the size of dst in characters, including the terminating 0.
|
||||
// Returns the number of characters written, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
int _cdecl Sprintf( char *dst, int size, const char *format, ... );
|
||||
int _cdecl Sprintf( wchar_t *dst, int size, const wchar_t *format, ... );
|
||||
int _cdecl Vsprintf( char *dst, int size, const char *format, va_list args );
|
||||
int _cdecl Vsprintf( wchar_t *dst, int size, const wchar_t *format, va_list args );
|
||||
|
||||
// Outputs a formatted debug string
|
||||
void Trace( const char *format, ... );
|
||||
void Trace( const wchar_t *format, ... );
|
||||
|
||||
// Converts between multi-byte and wide characters. size is the size of dst in characters, including the
|
||||
// terminating 0.
|
||||
// Returns the number of characters copied, excluding the terminating 0.
|
||||
// The return value is <=size-1. If size is 0, returns 0 and does nothing.
|
||||
// The result in dst is always 0 terminated.
|
||||
// If dst is NULL the size is ignored and the function just returns the number of characters (not counting the 0)
|
||||
#ifdef STR_USE_WIN32_CONV
|
||||
int MbsToWcs( wchar_t *dst, int size, const char *src, int codePage=CP_ACP );
|
||||
int WcsToMbs( char *dst, int size, const wchar_t *src, int codePage=CP_ACP );
|
||||
#else
|
||||
int MbsToWcs( wchar_t *dst, int size, const char *src );
|
||||
int WcsToMbs( char *dst, int size, const wchar_t *src );
|
||||
#endif
|
||||
|
||||
const char *GetToken( const char *text, char *token, int size, const char *separators );
|
||||
const wchar_t *GetToken( const wchar_t *text, wchar_t *token, int size, const wchar_t *separators );
|
||||
|
||||
#endif
|
||||
227
Src/Lib/TrackResources.cpp
Normal file
227
Src/Lib/TrackResources.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include <stdafx.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "StringUtils.h"
|
||||
#include "ResourceHelper.h"
|
||||
#include "Assert.h"
|
||||
|
||||
typedef std::pair<const char*,int> TrackedResource;
|
||||
typedef std::map<HGDIOBJ,TrackedResource> TrackedResourceMap;
|
||||
|
||||
static TrackedResourceMap g_TrackedGdiResources;
|
||||
static TrackedResourceMap g_TrackedUserResources;
|
||||
|
||||
HDC TrackCreateCompatibleDC( HDC hdc, const char *file, int line )
|
||||
{
|
||||
HDC res=CreateCompatibleDC(hdc);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HFONT TrackCreateFont( int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCWSTR pszFaceName, const char *file, int line )
|
||||
{
|
||||
HFONT res=CreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HFONT TrackCreateFontIndirect( const LOGFONT *lplf, const char *file, int line )
|
||||
{
|
||||
HFONT res=CreateFontIndirect(lplf);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HANDLE TrackLoadImage( HINSTANCE hInst, LPCWSTR name, UINT type, int cx, int cy, UINT fuLoad, const char *file, int line )
|
||||
{
|
||||
HANDLE res=LoadImage(hInst,name,type,cx,cy,fuLoad);
|
||||
if (type==IMAGE_BITMAP)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
else
|
||||
g_TrackedUserResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HBITMAP TrackCreateDIBSection( HDC hdc, CONST BITMAPINFO *lpbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset, const char *file, int line )
|
||||
{
|
||||
HBITMAP res=CreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HBITMAP TrackCreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits, const char *file, int line )
|
||||
{
|
||||
HBITMAP res=CreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
HBITMAP TrackCreateCompatibleBitmap( HDC hdc, int cx, int cy, const char *file, int line )
|
||||
{
|
||||
HBITMAP res=CreateCompatibleBitmap(hdc,cx,cy);
|
||||
if (res)
|
||||
g_TrackedGdiResources[res]=TrackedResource(file,line);
|
||||
return res;
|
||||
}
|
||||
|
||||
void TrackAddTrackedObject( HGDIOBJ obj, const char *file, int line )
|
||||
{
|
||||
if (obj)
|
||||
g_TrackedGdiResources[obj]=TrackedResource(file,line);
|
||||
}
|
||||
|
||||
void TrackAddTrackedIcon( HICON hIcon, const char *file, int line )
|
||||
{
|
||||
if (hIcon)
|
||||
g_TrackedUserResources[hIcon]=TrackedResource(file,line);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL TrackDeleteDC( HDC hdc )
|
||||
{
|
||||
Assert(hdc);
|
||||
if (g_TrackedGdiResources.find(hdc)!=g_TrackedGdiResources.end())
|
||||
g_TrackedGdiResources.erase(hdc);
|
||||
else
|
||||
Assert(0);
|
||||
return DeleteDC(hdc);
|
||||
}
|
||||
|
||||
BOOL TrackDeleteObject( HGDIOBJ obj )
|
||||
{
|
||||
Assert(obj);
|
||||
if (g_TrackedGdiResources.find(obj)!=g_TrackedGdiResources.end())
|
||||
g_TrackedGdiResources.erase(obj);
|
||||
else
|
||||
Assert(0);
|
||||
return DeleteObject(obj);
|
||||
}
|
||||
|
||||
BOOL TrackDestroyIcon( HICON hIcon )
|
||||
{
|
||||
Assert(hIcon);
|
||||
if (g_TrackedUserResources.find(hIcon)!=g_TrackedUserResources.end())
|
||||
g_TrackedUserResources.erase(hIcon);
|
||||
else
|
||||
Assert(0);
|
||||
return DestroyIcon(hIcon);
|
||||
}
|
||||
|
||||
|
||||
static void DumpBitmapLeaks( const std::vector<HBITMAP> &bitmaps )
|
||||
{
|
||||
int index=0;
|
||||
for (std::vector<HBITMAP>::const_iterator it=bitmaps.begin();it!=bitmaps.end();++it)
|
||||
{
|
||||
BITMAP info;
|
||||
GetObject(*it,sizeof(info),&info);
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct GdiTableCell
|
||||
{
|
||||
void *pKernel;
|
||||
unsigned short nProcess;
|
||||
unsigned short nCount;
|
||||
unsigned short nUpper;
|
||||
unsigned short nType;
|
||||
void *pUser;
|
||||
};
|
||||
|
||||
static const GdiTableCell *GetGdiTable( void )
|
||||
{
|
||||
HMODULE gdi32=GetModuleHandle(L"gdi32.dll");
|
||||
FARPROC GdiQueryTable=GetProcAddress(gdi32,"GdiQueryTable");
|
||||
if (GdiQueryTable)
|
||||
{
|
||||
// GdiQueryTable();
|
||||
if (GetWinVersion()>=WIN_VER_WIN8)
|
||||
return *(GdiTableCell**)((char*)GdiQueryTable+0x6b1b0);
|
||||
else
|
||||
return *(GdiTableCell**)((char*)GdiQueryTable+0x29db0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DumpResourceLeaks( void )
|
||||
{
|
||||
GdiFlush();
|
||||
Trace("GDI objects %d",GetGuiResources(GetCurrentProcess(),GR_GDIOBJECTS));
|
||||
Trace("USER objects %d",GetGuiResources(GetCurrentProcess(),GR_USEROBJECTS));
|
||||
const GdiTableCell *cells=GetGdiTable();
|
||||
if (!cells) return;
|
||||
|
||||
int counts[16]={0};
|
||||
unsigned short pid=(unsigned short)GetCurrentProcessId();
|
||||
int n=65536;
|
||||
std::vector<HBITMAP> bitmaps;
|
||||
for (int i=0;i<n;i++)
|
||||
{
|
||||
if (cells[i].pKernel && cells[i].nProcess==pid)
|
||||
{
|
||||
HGDIOBJ handle=(HGDIOBJ)(intptr_t)((cells[i].nUpper<<16)|i);
|
||||
const TrackedResource *res=NULL;
|
||||
TrackedResourceMap::const_iterator it=g_TrackedGdiResources.find(handle);
|
||||
if (it!=g_TrackedGdiResources.end())
|
||||
res=&it->second;
|
||||
DWORD type=GetObjectType(handle);
|
||||
if (!(type&~15))
|
||||
counts[type]++;
|
||||
switch (type)
|
||||
{
|
||||
case OBJ_BITMAP:
|
||||
{
|
||||
BITMAP info;
|
||||
GetObject(handle,sizeof(info),&info);
|
||||
bitmaps.push_back((HBITMAP)handle);
|
||||
}
|
||||
break;
|
||||
case OBJ_BRUSH:
|
||||
{
|
||||
LOGBRUSH info;
|
||||
GetObject(handle,sizeof(info),&info);
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
case OBJ_DC:
|
||||
{
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
case OBJ_FONT:
|
||||
{
|
||||
LOGFONT info;
|
||||
GetObject(handle,sizeof(info),&info);
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
case OBJ_PEN:
|
||||
{
|
||||
LOGPEN info;
|
||||
GetObject(handle,sizeof(info),&info);
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
case OBJ_REGION:
|
||||
{
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
case OBJ_MEMDC:
|
||||
{
|
||||
int q=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DumpBitmapLeaks(bitmaps);
|
||||
}
|
||||
51
Src/Lib/TrackResources.h
Normal file
51
Src/Lib/TrackResources.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
//#define TRACK_GDI_RESOURCES
|
||||
#ifndef _DEBUG
|
||||
#undef TRACK_GDI_RESOURCES
|
||||
#endif
|
||||
|
||||
#ifdef TRACK_GDI_RESOURCES
|
||||
|
||||
#undef CreateFont
|
||||
#undef CreateFontIndirect
|
||||
#undef LoadImage
|
||||
|
||||
#define CreateCompatibleDC(hdc) TrackCreateCompatibleDC(hdc,__FILE__,__LINE__)
|
||||
#define CreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName) TrackCreateFont(cHeight,cWidth,cEscapement,cOrientation,cWeight,bItalic,bUnderline,bStrikeOut,iCharSet,iOutPrecision,iClipPrecision,iQuality,iPitchAndFamily,pszFaceName,__FILE__,__LINE__)
|
||||
#define CreateFontIndirect(lplf) TrackCreateFontIndirect(lplf,__FILE__,__LINE__)
|
||||
#define LoadImage(hInst,name,type,cx,cy,fuLoad) TrackLoadImage(hInst,name,type,cx,cy,fuLoad,__FILE__,__LINE__)
|
||||
#define CreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset) TrackCreateDIBSection(hdc,lpbmi,usage,ppvBits,hSection,offset,__FILE__,__LINE__)
|
||||
#define CreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits) TrackCreateBitmap(nWidth,nHeight,nPlanes,nBitCount,lpBits,__FILE__,__LINE__)
|
||||
#define CreateCompatibleBitmap(hdc,cx,cy) TrackCreateCompatibleBitmap(hdc,cx,cy,__FILE__,__LINE__)
|
||||
#define AddTrackedObject(obj) TrackAddTrackedObject(obj,__FILE__,__LINE__)
|
||||
#define AddTrackedIcon(hIcon) TrackAddTrackedIcon(hIcon,__FILE__,__LINE__)
|
||||
|
||||
#define DeleteDC(hdc) TrackDeleteDC(hdc)
|
||||
#define DeleteObject(obj) TrackDeleteObject(obj)
|
||||
#define DestroyIcon(hIcon) TrackDestroyIcon(hIcon)
|
||||
|
||||
HDC TrackCreateCompatibleDC( HDC hdc, const char *file, int line );
|
||||
HFONT TrackCreateFont( int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, DWORD bItalic, DWORD bUnderline, DWORD bStrikeOut, DWORD iCharSet, DWORD iOutPrecision, DWORD iClipPrecision, DWORD iQuality, DWORD iPitchAndFamily, LPCWSTR pszFaceName, const char *file, int line );
|
||||
HFONT TrackCreateFontIndirect( const LOGFONT *lplf, const char *file, int line );
|
||||
HANDLE TrackLoadImage( HINSTANCE hInst, LPCWSTR name, UINT type, int cx, int cy, UINT fuLoad, const char *file, int line );
|
||||
HBITMAP TrackCreateDIBSection( HDC hdc, CONST BITMAPINFO *lpbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset, const char *file, int line );
|
||||
HBITMAP TrackCreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits, const char *file, int line );
|
||||
HBITMAP TrackCreateCompatibleBitmap( HDC hdc, int cx, int cy, const char *file, int line );
|
||||
void TrackAddTrackedObject( HGDIOBJ obj, const char *file, int line );
|
||||
void TrackAddTrackedIcon( HICON hIcon, const char *file, int line );
|
||||
|
||||
BOOL TrackDeleteDC( HDC hdc );
|
||||
BOOL TrackDeleteObject( HGDIOBJ obj );
|
||||
BOOL TrackDestroyIcon( HICON hIcon );
|
||||
|
||||
void DumpResourceLeaks( void );
|
||||
|
||||
#else
|
||||
#define AddTrackedObject(obj)
|
||||
#define AddTrackedIcon(hIcon)
|
||||
#endif
|
||||
83
Src/Lib/Translations.cpp
Normal file
83
Src/Lib/Translations.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "SettingsParser.h"
|
||||
|
||||
static CSettingsParser g_Translations;
|
||||
static CSettingsParser g_TranslationOverrides;
|
||||
static bool g_bRTL;
|
||||
|
||||
// Parses the settings from an ini file. Supports UTF16, UTF8 or ANSI files
|
||||
// Use forceLang for force a specific language
|
||||
void ParseTranslations( const wchar_t *fname, const wchar_t *forceLang )
|
||||
{
|
||||
g_Translations.Reset();
|
||||
|
||||
if (fname)
|
||||
{
|
||||
if (!g_Translations.LoadText(fname)) return;
|
||||
g_Translations.ParseText();
|
||||
}
|
||||
|
||||
wchar_t languages[100]={0};
|
||||
if (forceLang && *forceLang)
|
||||
{
|
||||
int len=(int)wcslen(forceLang);
|
||||
if (len>50) len=50;
|
||||
memcpy(languages,forceLang,len*2);
|
||||
memcpy(languages+len+1,L"default\0en-US\0",30);
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG size=0;
|
||||
ULONG len=_countof(languages);
|
||||
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,&size,languages,&len);
|
||||
if (len>50) len=50;
|
||||
if (len<1) len=1;
|
||||
memcpy(languages+len-1,L"default\0en-US\0",30);
|
||||
}
|
||||
|
||||
g_Translations.FilterLanguages(languages);
|
||||
|
||||
// Checks for right-to-left languages
|
||||
g_bRTL=false;
|
||||
LOCALESIGNATURE localesig;
|
||||
LANGID language=GetUserDefaultUILanguage();
|
||||
if (forceLang && *forceLang)
|
||||
{
|
||||
if (GetLocaleInfoEx(forceLang,LOCALE_FONTSIGNATURE,(LPWSTR)&localesig,(sizeof(localesig)/sizeof(wchar_t))) && (localesig.lsUsb[3]&0x08000000))
|
||||
g_bRTL=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetLocaleInfoW(language,LOCALE_FONTSIGNATURE,(LPWSTR)&localesig,(sizeof(localesig)/sizeof(wchar_t))) && (localesig.lsUsb[3]&0x08000000))
|
||||
g_bRTL=true;
|
||||
}
|
||||
}
|
||||
|
||||
// Loads text overrides from the given module. They must be in a "L10N" resource with ID=1
|
||||
void LoadTranslationOverrides( HMODULE hModule )
|
||||
{
|
||||
HRSRC hResInfo=FindResource(hModule,MAKEINTRESOURCE(1),L"L10N");
|
||||
if (hResInfo)
|
||||
{
|
||||
g_TranslationOverrides.LoadText(hModule,hResInfo);
|
||||
g_TranslationOverrides.ParseText();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a setting with the given name. If no setting is found, returns def
|
||||
const wchar_t *FindTranslation( const wchar_t *name, const wchar_t *def )
|
||||
{
|
||||
const wchar_t *str=g_TranslationOverrides.FindSetting(name);
|
||||
if (str) return str;
|
||||
return g_Translations.FindSetting(name,def);
|
||||
}
|
||||
|
||||
// Checks for right-to-left languages
|
||||
bool IsLanguageRTL( void )
|
||||
{
|
||||
return g_bRTL;
|
||||
}
|
||||
21
Src/Lib/Translations.h
Normal file
21
Src/Lib/Translations.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Classic Shell (c) 2009-2017, Ivo Beltchev
|
||||
// Open-Shell (c) 2017-2018, The Open-Shell Team
|
||||
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
|
||||
|
||||
#pragma once
|
||||
|
||||
// Parses the settings from an ini file. Supports UTF16, UTF8 or ANSI files
|
||||
// Use forceLang for force a specific language
|
||||
void ParseTranslations( const wchar_t *fname, const wchar_t *forceLang );
|
||||
|
||||
// Loads text overrides from the given module. They must be in a "L10N" resource with ID=1
|
||||
void LoadTranslationOverrides( HMODULE hModule );
|
||||
|
||||
// Returns a setting with the given name. If no setting is found, returns def
|
||||
const wchar_t *FindTranslation( const wchar_t *name, const wchar_t *def );
|
||||
|
||||
// Checks for right-to-left languages
|
||||
bool IsLanguageRTL( void );
|
||||
|
||||
// Language DLLs between this version and the current version are acceptable
|
||||
const int MIN_LANGUAGE_VERSION=0x03090005;
|
||||
BIN
Src/Lib/flags.bmp
Normal file
BIN
Src/Lib/flags.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
Src/Lib/flags24.bmp
Normal file
BIN
Src/Lib/flags24.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
Src/Lib/padlock.ico
Normal file
BIN
Src/Lib/padlock.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Src/Lib/play.ico
Normal file
BIN
Src/Lib/play.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 190 B |
152
Src/Lib/resource.h
Normal file
152
Src/Lib/resource.h
Normal file
@@ -0,0 +1,152 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Lib.rc
|
||||
//
|
||||
#define IDS_VERSION_URL 100
|
||||
#define IDB_FLAGS 109
|
||||
#define IDB_FLAGS24 108
|
||||
#define IDC_STATICICON 209
|
||||
#define IDC_SETTINGS 236
|
||||
#define IDC_TREEITEMS 238
|
||||
#define IDC_COMBOCOMMAND 239
|
||||
#define IDC_EDITLABEL 240
|
||||
#define IDC_EDITTIP 241
|
||||
#define IDC_BUTTONLINK 242
|
||||
#define IDC_EDITLINK 244
|
||||
#define IDC_EDITICON 245
|
||||
#define IDC_BUTTONICON 246
|
||||
#define IDC_EDITICOND 247
|
||||
#define IDC_BUTTONICOND 248
|
||||
#define IDC_TABSETTINGS 250
|
||||
#define IDC_STATICCOMMAND 251
|
||||
#define IDC_STATICLINK 252
|
||||
#define IDC_STATICTEXT 253
|
||||
#define IDC_STATICINFOTIP 254
|
||||
#define IDC_STATICICOND 255
|
||||
#define IDC_ICONN 256
|
||||
#define IDC_ICOND 257
|
||||
#define IDC_COMBOLINK 258
|
||||
#define IDC_STATICHINT 259
|
||||
#define IDI_ICONLOCK 1000
|
||||
#define IDI_ICONWARNING 1001
|
||||
#define IDC_EDITFILE 1001
|
||||
#define IDI_ICONPLAY 1002
|
||||
#define IDC_BUTTONBROWSE 1002
|
||||
#define IDC_LISTICONS 1003
|
||||
#define IDC_LISTLANGUAGE 1004
|
||||
#define IDC_STATICTIP 1005
|
||||
#define IDC_TREE1 1006
|
||||
#define IDC_TREECOMMANDS 1006
|
||||
#define IDC_STATICLEFT 1007
|
||||
#define IDC_STATICRIGHT 1008
|
||||
#define IDC_STATICMIDDLE 1009
|
||||
#define IDC_LINKHELP 1010
|
||||
#define IDC_BUTTONBACKUP 1011
|
||||
#define IDC_STATICFILE 1013
|
||||
#define IDC_LINKWEB 1014
|
||||
#define IDC_EDITSEARCH 1025
|
||||
#define IDC_SYSLINKLOC 1026
|
||||
#define IDC_ICONSEARCH 1027
|
||||
#define IDC_CHECKALL 1031
|
||||
#define IDC_BUTTONCHECK 1032
|
||||
#define IDC_LINKDOWNLOAD 1035
|
||||
#define IDC_PROGRESS 1036
|
||||
#define IDC_MESSAGE 1037
|
||||
#define IDD_SETTINGS 4000
|
||||
#define IDS_TOGGLE_SETTING 4000
|
||||
#define IDD_SETTINGSTREE 4001
|
||||
#define IDS_SELECT_SETTING 4001
|
||||
#define IDD_BROWSEFORICON 4002
|
||||
#define IDS_DEFAULT_SETTING 4002
|
||||
#define IDD_LANGUAGE 4003
|
||||
#define IDS_PLAY_SETTING 4003
|
||||
#define IDD_CUSTOMTREE 4004
|
||||
#define IDS_ICON_FILTERS 4004
|
||||
#define IDD_PROGRESS 4005
|
||||
#define IDS_ICON_TITLE 4005
|
||||
#define IDS_WAV_FILTERS 4006
|
||||
#define IDS_WAV_TITLE 4007
|
||||
#define IDS_SETTING_LOCKED 4008
|
||||
#define IDS_SETTING_LOCKED_GP 4009
|
||||
#define IDS_BASIC_SETTINGS 4010
|
||||
#define IDS_ALWAYS_ON_TOP 4011
|
||||
#define IDS_MENU_EDIT 4012
|
||||
#define IDS_MENU_DELETE 4013
|
||||
#define IDS_MENU_RENAME 4014
|
||||
#define IDS_PICK_LINK_TITLE 4015
|
||||
#define IDS_PICK_LINK_FILE 4016
|
||||
#define IDS_PICK_LINK_FOLDER 4017
|
||||
#define IDS_DUPLICATE_ITEM 4018
|
||||
#define IDS_ERROR_TITLE 4019
|
||||
#define IDS_ERROR_SEPARATOR 4020
|
||||
#define IDS_ERROR_ASCII 4021
|
||||
#define IDS_ERROR_EMPTY 4022
|
||||
#define IDS_RESET_TOOLBAR 4023
|
||||
#define IDS_RESET_TOOLBAR_WARN 4024
|
||||
#define IDS_RESET_MENU 4025
|
||||
#define IDS_RESET_MENU_WARN 4026
|
||||
#define IDS_ADD_TOOLBAR 4027
|
||||
#define IDS_ADD_MENU 4028
|
||||
#define IDS_INSERT_MENU 4029
|
||||
#define IDS_EMPTY_MENU 4030
|
||||
#define IDS_TREE_TOOLBAR 4031
|
||||
#define IDS_TREE_MENU 4032
|
||||
#define IDS_XML_FILTERS 4033
|
||||
#define IDS_XML_TITLE_LOAD 4034
|
||||
#define IDS_XML_TITLE_SAVE 4035
|
||||
#define IDS_RESET_CONFIRM 4036
|
||||
#define IDS_RESET_TITLE 4037
|
||||
#define IDS_TOOLBAR_LOCKED 4038
|
||||
#define IDS_MENU_LOCKED 4039
|
||||
#define IDS_BACKUP_SAVE 4040
|
||||
#define IDS_BACKUP_LOAD 4041
|
||||
#define IDS_BACKUP_RESET 4042
|
||||
#define IDS_ERROR_LOADING_XML 4043
|
||||
#define IDS_ERROR_SAVING_XML 4044
|
||||
#define IDS_DRAG_DROP_EXP_TIP 4045
|
||||
#define IDS_DRAG_DROP_SM_TIP 4046
|
||||
#define IDS_COMMAND_EXP_TIP 4047
|
||||
#define IDS_STRING4048 4048
|
||||
#define IDS_COMMAND_SM_TIP 4048
|
||||
#define IDS_COMMAND_FILTERS 4049
|
||||
#define IDS_OS_LANGUAGE 4050
|
||||
#define IDS_BMP_FILTERS 4051
|
||||
#define IDS_BMP_TITLE 4052
|
||||
#define IDS_SEARCH_PROMPT 4053
|
||||
#define IDS_SETTING_SEARCH 4054
|
||||
#define IDS_WEBSITE_TIP 4055
|
||||
#define IDS_LOCATE_SETTING 4056
|
||||
#define IDS_LANGUAGE_UPDATED 4057
|
||||
#define IDS_LANGUAGE_MISSING 4058
|
||||
#define IDS_LANGUAGE_DOWNLOAD 4059
|
||||
#define IDS_LANGUAGE_SUCCESS 4060
|
||||
#define IDS_LANGUAGE_SUCCESS2 4061
|
||||
#define IDS_LANGUAGE_FAIL 4062
|
||||
#define IDS_INTERNET_FAIL 4063
|
||||
#define IDS_INITIATE_FAIL 4064
|
||||
#define IDS_LANG_DOWNLOAD_FAIL 4065
|
||||
#define IDS_LANG_SAVE_FAIL 4066
|
||||
#define IDS_UPDATE_TITLE 4067
|
||||
#define IDS_INST_DOWNLOAD_FAIL 4068
|
||||
#define IDS_INST_SAVE_FAIL 4069
|
||||
#define IDS_PROGRESS_CONNECT 4070
|
||||
#define IDS_PROGRESS_DOWNLOAD 4071
|
||||
#define IDS_PROGRESS_VERIFY 4072
|
||||
#define IDS_PROGRESS_SAVE 4073
|
||||
#define IDS_PROGRESS_TITLE_CHECK 4074
|
||||
#define IDS_PROGRESS_TITLE_DOWNLOAD 4075
|
||||
#define IDS_DOWNLOAD_TIP 4076
|
||||
#define IDS_BMP_FILTERS2 4077
|
||||
#define IDS_UNSAVED_CHANGES 4078
|
||||
#define IDS_UNSAVED_TITLE 4079
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 111
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1038
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
5
Src/Lib/stdafx.cpp
Normal file
5
Src/Lib/stdafx.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// StartMenuDLL.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
22
Src/Lib/stdafx.h
Normal file
22
Src/Lib/stdafx.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define STRICT_TYPED_ITEMIDS
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <shlobj.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <atltypes.h>
|
||||
#include <atlstr.h>
|
||||
#include <atlwin.h>
|
||||
24
Src/Lib/targetver.h
Normal file
24
Src/Lib/targetver.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
// The following macros define the minimum required platform. The minimum required platform
|
||||
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
|
||||
// your application. The macros work by enabling all features available on platform versions up to and
|
||||
// including the version specified.
|
||||
|
||||
// Modify the following defines if you have to target a platform prior to the ones specified below.
|
||||
// Refer to MSDN for the latest info on corresponding values for different platforms.
|
||||
#ifndef WINVER // Specifies that the minimum required platform is Windows 7.
|
||||
#define WINVER 0x0602 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 7.
|
||||
#define _WIN32_WINNT 0x0602 // Change this to the appropriate value to target other versions of Windows.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
|
||||
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
|
||||
#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
|
||||
#endif
|
||||
BIN
Src/Lib/warning.ico
Normal file
BIN
Src/Lib/warning.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user