Rebrand to Open-Shell (#36) (#58)

* Rebrand to Open-Shell

* Slight installer branding improvement
This commit is contained in:
Xenhat
2018-08-05 15:22:10 -04:00
committed by GitHub
parent 4637019a0f
commit f4dd56155b
1115 changed files with 3124 additions and 3140 deletions

29
Src/Lib/Assert.cpp Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

72
Src/Lib/DownloadHelper.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

197
Src/Lib/Settings.h Normal file
View 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 &regSettings, CRegKey &regSettingsUser, CRegKey &regPolicy, CRegKey &regPolicyUser );
private:
bool ReadValue( CRegKey &regKey, 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 &regSettings, CRegKey &regSettingsUser, CRegKey &regPolicy, CRegKey &regPolicyUser );
// 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
View 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>> &macros )
{
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
View 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>> &macros );
// 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

File diff suppressed because it is too large Load Diff

389
Src/Lib/SettingsUIHelper.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
Src/Lib/flags24.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

152
Src/Lib/resource.h Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB