mirror of
https://github.com/Open-Shell/Open-Shell-Menu.git
synced 2026-04-11 17:37:22 +10:00
Some icons (modern settings, jump-list tasks) are monochrome, basically they are defined just by alpha channel. Thus they can be displayed in any color (white is default). Since these icons are white by default, they look nice on dark backgrounds. But they are not very visible on light backgrounds. Thus the idea is to 'colorize' such icon using color of corresponding text item. That way they will always have proper color. Fixes #466.
483 lines
16 KiB
C++
483 lines
16 KiB
C++
// 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 "ComHelper.h"
|
|
#include <map>
|
|
#include <set>
|
|
#include <list>
|
|
#include <vector>
|
|
|
|
interface IImageList2;
|
|
interface IWICImagingFactory;
|
|
|
|
// CItemManager - global cache for item information
|
|
|
|
class CItemManager;
|
|
extern CItemManager g_ItemManager;
|
|
|
|
class CItemManager
|
|
{
|
|
public:
|
|
CItemManager( void );
|
|
~CItemManager( void );
|
|
|
|
static int SMALL_ICON_SIZE;
|
|
static int LARGE_ICON_SIZE;
|
|
static int EXTRA_LARGE_ICON_SIZE;
|
|
|
|
// Initializes the manager. Called from DllMain
|
|
void Init( void );
|
|
void Close( void );
|
|
void ResetTempIcons( void );
|
|
void LoadCacheFile( void );
|
|
void SaveCacheFile( void );
|
|
void ClearCache( void );
|
|
|
|
static int GetDPI( bool bOverride ) { return (bOverride && s_DPIOverride)?s_DPIOverride:s_DPI; }
|
|
static bool GetDPIOverride( void ) { return s_DPIOverride!=0; }
|
|
|
|
enum TIconSizeType
|
|
{
|
|
ICON_SIZE_TYPE_SMALL,
|
|
ICON_SIZE_TYPE_LARGE,
|
|
ICON_SIZE_TYPE_EXTRA_LARGE,
|
|
ICON_SIZE_TYPE_SMALL_METRO,
|
|
ICON_SIZE_TYPE_LARGE_METRO,
|
|
ICON_SIZE_TYPE_EXTRA_LARGE_METRO,
|
|
|
|
ICON_SIZE_COUNT
|
|
};
|
|
|
|
struct IconInfo
|
|
{
|
|
TIconSizeType sizeType;
|
|
bool bTemp; // the icon will be destroyed when the menu closes
|
|
bool bMetro; // this is a Metro icon. it may depend on the system color
|
|
FILETIME timestamp;
|
|
HBITMAP bitmap; // bitmaps are guaranteed to be valid on the main thread (if the handle is read atomically)
|
|
|
|
void SetPath( const wchar_t *path );
|
|
const CString &GetPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ICONS)); return PATH; }
|
|
|
|
private:
|
|
CString PATH; // metro icon paths start with # and are not saved to cache file
|
|
|
|
friend class CItemManager;
|
|
};
|
|
|
|
enum
|
|
{
|
|
INFO_LINK=1, // bLink, appid, bNoPin, bNoNew, targetPidl, targetPath, arguments
|
|
INFO_METRO=2, // bLink, bMetroLink, bMetroApp, appid, metroName, package, packagePath, iconPath, color
|
|
INFO_LINK_APPID=4, // the appid is validated by the app resolver (for jumplists and UserAssist items). Can only be used from the main thread
|
|
|
|
INFO_SMALL_ICON=16,
|
|
INFO_LARGE_ICON=32,
|
|
INFO_EXTRA_LARGE_ICON=64,
|
|
|
|
INFO_NO_PATH=8192, // don't trust the parsing name
|
|
INFO_VALIDATE_FILE=16384, // if the path doesn't exist returns NULL
|
|
INFO_REFRESH_NOW=32768,
|
|
INFO_STARTSCREEN_ICON=65536,
|
|
|
|
INFO_DATA=INFO_LINK|INFO_METRO|INFO_LINK_APPID,
|
|
INFO_ICON=INFO_SMALL_ICON|INFO_LARGE_ICON|INFO_EXTRA_LARGE_ICON,
|
|
};
|
|
|
|
enum TLocation
|
|
{
|
|
LOCATION_UNKNOWN,
|
|
LOCATION_START_MENU,
|
|
LOCATION_GAMES,
|
|
LOCATION_DESKTOP,
|
|
LOCATION_TASKBAR,
|
|
LOCATION_METRO,
|
|
};
|
|
|
|
struct ItemInfo
|
|
{
|
|
ItemInfo( void )
|
|
{
|
|
smallIcon=largeIcon=extraLargeIcon=NULL;
|
|
validFlags=refreshFlags=0;
|
|
bIconOnly=bTemp=bLink=bExplicitAppId=bNoPin=bNoNew=bMetroLink=bMetroApp=bProtectedLink=false;
|
|
writestamp.dwHighDateTime=writestamp.dwLowDateTime=0;
|
|
createstamp.dwHighDateTime=createstamp.dwLowDateTime=0;
|
|
location=LOCATION_UNKNOWN;
|
|
}
|
|
|
|
// PATH never changes after the item is created. it can be accessed without a lock
|
|
CString PATH;
|
|
|
|
// these are replaced atomically with pointers that are always valid
|
|
const IconInfo *smallIcon;
|
|
const IconInfo *largeIcon;
|
|
const IconInfo *extraLargeIcon;
|
|
|
|
const CAbsolutePidl &GetPidl( void ) const { Assert(GetCurrentThreadId()==g_ItemManager.m_MainThreadId || RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return pidl; }
|
|
bool IsLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bLink; }
|
|
bool IsMetroLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bMetroLink; }
|
|
bool IsMetroApp( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bMetroApp; }
|
|
bool IsProtectedLink( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bProtectedLink; }
|
|
bool IsNoPin( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bNoPin; }
|
|
bool IsNoNew( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bNoNew; }
|
|
bool IsExplicitAppId( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return bExplicitAppId; }
|
|
const CString &GetPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return path; }
|
|
const CString &GetAppid( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return appid; }
|
|
const CString &GetTargetPATH( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return targetPATH; }
|
|
const CAbsolutePidl &GetTargetPidl( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return targetPidl; }
|
|
const CString &GetMetroName( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return metroName; }
|
|
const CString &GetIconPath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return iconPath; }
|
|
const CString &GetPackagePath( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return packagePath; }
|
|
TLocation GetLocation( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return location; }
|
|
|
|
private:
|
|
CAbsolutePidl pidl;
|
|
CAbsolutePidl newPidl;
|
|
FILETIME writestamp; // valid only for items with paths. the rest are assumed to never change
|
|
FILETIME createstamp; // valid only for items with paths. the rest are assumed to never change
|
|
bool bIconOnly;
|
|
bool bTemp; // the item and its icon will be destroyed when the menu closes (only allowed for small-icon items)
|
|
bool bLink;
|
|
bool bMetroLink;
|
|
bool bMetroApp;
|
|
bool bProtectedLink; // Metro link in the common Programs folder
|
|
bool bNoPin; // the link shouldn't be pinned
|
|
bool bNoNew; // the link shouldn't be new
|
|
bool bExplicitAppId;
|
|
CString path; // only for a file
|
|
CString packagePath; // only for a metro app
|
|
TLocation location;
|
|
|
|
int validFlags;
|
|
int refreshFlags; // 0 if not in the queue, the item can't be deleted if this is !=0
|
|
|
|
CAbsolutePidl targetPidl;
|
|
CString targetPATH;
|
|
CString appid;
|
|
CString metroName;
|
|
CString iconPath;
|
|
DWORD iconColor;
|
|
|
|
int iconIndex; // used only if bIconOnly
|
|
|
|
const CAbsolutePidl &GetLatestPidl( void ) const { Assert(RWLock::ThreadHasReadLock(RWLOCK_ITEMS)); return newPidl?newPidl:pidl; }
|
|
|
|
friend class CItemManager;
|
|
};
|
|
|
|
const ItemInfo *GetItemInfo( IShellItem *pItem, PIDLIST_ABSOLUTE pidl, int refreshFlags, TLocation location=LOCATION_UNKNOWN );
|
|
const ItemInfo *GetItemInfo( CString path, int refreshFlags, TLocation location=LOCATION_UNKNOWN );
|
|
const ItemInfo *GetCustomIcon( const wchar_t *location, int index, TIconSizeType iconSizeType, bool bTemp );
|
|
const ItemInfo *GetCustomIcon( const wchar_t *path, TIconSizeType iconSizeType );
|
|
const ItemInfo* GetLinkIcon(IShellLink* link, TIconSizeType iconSizeType);
|
|
const ItemInfo *GetMetroAppInfo10( const wchar_t *appid );
|
|
void UpdateItemInfo( const ItemInfo *pInfo, int refreshFlags, bool bHasWriteLock=false );
|
|
void WaitForShortcuts( const POINT &balloonPos );
|
|
bool IsTaskbarPinned( const wchar_t *appid );
|
|
void UpdateNewPrograms( const POINT &balloonPos );
|
|
bool IsNewProgram( PIDLIST_ABSOLUTE pidl, bool bFolder, bool bMetroApp );
|
|
bool HasNewPrograms( bool bReal ) { return m_bHasNewPrograms[bReal?0:1]; }
|
|
bool HasNewApps( bool bReal ) { return m_bHasNewApps[bReal?0:1]; }
|
|
void RefreshInfos( void );
|
|
|
|
void RemoveNewItem( PIDLIST_ABSOLUTE pItem1, PIDLIST_ABSOLUTE pItem2, bool bFolder );
|
|
void RemoveNewItems( bool bPrograms, bool bMetro );
|
|
void SaveOldItems( void );
|
|
|
|
enum TRWLock
|
|
{
|
|
RWLOCK_ITEMS,
|
|
RWLOCK_ICONS,
|
|
RWLOCK_COUNT,
|
|
};
|
|
|
|
class RWLock
|
|
{
|
|
public:
|
|
RWLock( CItemManager *pThis, bool bWrite, TRWLock index )
|
|
{
|
|
if (index==RWLOCK_COUNT)
|
|
{
|
|
m_pLock=NULL;
|
|
return;
|
|
}
|
|
#ifdef _DEBUG
|
|
m_pState=&g_LockState[index];
|
|
Assert(*m_pState==0);
|
|
#endif
|
|
m_pLock=&pThis->m_RWLocks[index];
|
|
m_bWrite=bWrite;
|
|
if (bWrite)
|
|
AcquireSRWLockExclusive(m_pLock);
|
|
else
|
|
AcquireSRWLockShared(m_pLock);
|
|
#ifdef _DEBUG
|
|
*m_pState=bWrite?2:1;
|
|
#endif
|
|
}
|
|
|
|
~RWLock( void )
|
|
{
|
|
if (!m_pLock) return;
|
|
#ifdef _DEBUG
|
|
Assert(*m_pState==(m_bWrite?2:1));
|
|
*m_pState=0;
|
|
#endif
|
|
if (m_bWrite)
|
|
ReleaseSRWLockExclusive(m_pLock);
|
|
else
|
|
ReleaseSRWLockShared(m_pLock);
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
static bool ThreadHasReadLock( TRWLock index ) { return g_LockState[index]!=0; }
|
|
static bool ThreadHasWriteLock( TRWLock index ) { return g_LockState[index]==2; }
|
|
#endif
|
|
|
|
private:
|
|
SRWLOCK *m_pLock;
|
|
bool m_bWrite;
|
|
|
|
#ifdef _DEBUG
|
|
int *m_pState;
|
|
static _declspec(thread) int g_LockState[RWLOCK_COUNT]; // 0 - none, 1 - read, 2 - write
|
|
#endif
|
|
};
|
|
|
|
private:
|
|
static int s_DPI;
|
|
static int s_DPIOverride;
|
|
|
|
enum TLock
|
|
{
|
|
LOCK_CLEANUP,
|
|
LOCK_COUNT,
|
|
};
|
|
|
|
SRWLOCK m_RWLocks[RWLOCK_COUNT];
|
|
CRITICAL_SECTION m_CriticalSections[LOCK_COUNT];
|
|
DWORD m_CriticalSectionOwners[LOCK_COUNT];
|
|
HANDLE m_StartEvent; // start the refresh thread
|
|
HANDLE m_WorkEvent; // kicks off the refresh thread
|
|
HANDLE m_ExitEvent; // exit all threads
|
|
HANDLE m_DoneEvent; // done preloading start menu items
|
|
HANDLE m_PreloadItemsThread;
|
|
HANDLE m_RefreshInfoThread;
|
|
HANDLE m_SaveCacheThread;
|
|
DWORD m_MainThreadId, m_PreloadItemsThreadId, m_RefreshInfoThreadId;
|
|
|
|
// per-thread info used to load icons
|
|
struct LoadIconData
|
|
{
|
|
int m_IconSizes[ICON_SIZE_COUNT];
|
|
HIMAGELIST m_TempLists[ICON_SIZE_COUNT];
|
|
CComPtr<IImageList2> m_pTempLists[ICON_SIZE_COUNT];
|
|
CComPtr<IWICImagingFactory> m_pFactory;
|
|
|
|
void Init( void );
|
|
void Close( void );
|
|
};
|
|
|
|
LoadIconData m_LoadIconData[3]; // one for each thread (main, preload, refresh)
|
|
LoadIconData &GetLoadIconData( void );
|
|
|
|
class Lock
|
|
{
|
|
public:
|
|
Lock( CItemManager *pThis, TLock index )
|
|
{
|
|
m_pSection=&pThis->m_CriticalSections[index];
|
|
EnterCriticalSection(m_pSection);
|
|
m_pOwner=&pThis->m_CriticalSectionOwners[index];
|
|
if (!*m_pOwner)
|
|
*m_pOwner=GetCurrentThreadId();
|
|
else
|
|
m_pOwner=NULL;
|
|
}
|
|
|
|
~Lock( void )
|
|
{
|
|
if (m_pOwner) *m_pOwner=0;
|
|
LeaveCriticalSection(m_pSection);
|
|
}
|
|
|
|
private:
|
|
CRITICAL_SECTION *m_pSection;
|
|
DWORD *m_pOwner;
|
|
};
|
|
|
|
bool ThreadHasLock( TLock index ) { return m_CriticalSectionOwners[index]==GetCurrentThreadId(); }
|
|
|
|
// requires LOCK_ITEMS to be held
|
|
void QueueItemInfo( ItemInfo *pInfo, int refreshFlags );
|
|
// doesn't require a lock
|
|
void RefreshItemInfo( ItemInfo *pInfo, int refreshFlags, IShellItem *pItem, bool bHasWriteLock );
|
|
|
|
void FindInCache( unsigned int hash, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon );
|
|
void StoreInCache( unsigned int hash, const wchar_t *path, HBITMAP hSmallBitmap, HBITMAP hLargeBitmap, HBITMAP hExtraLargeBitmap, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp, bool bMetro );
|
|
void LoadShellIcon( IShellItem *pItem, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor );
|
|
void LoadMetroIcon( IShellItem *pItem, int &refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, const DWORD *pMetroColor );
|
|
void LoadCustomIcon( const wchar_t *iconPath, int iconIndex, int refreshFlags, const IconInfo *&smallIcon, const IconInfo *&largeIcon, const IconInfo *&extraLargeIcon, bool bTemp );
|
|
HICON LoadShellIcon( int index, int iconSize );
|
|
HICON LoadShellIcon( int iconSize, IExtractIcon *pExtractW, const wchar_t *location, IExtractIconA *pExtractA, const char *locationA, int index );
|
|
HBITMAP BitmapFromIcon( HICON hIcon, int iconSize, bool bDestroyIcon=true );
|
|
|
|
bool m_bInitialized;
|
|
|
|
// sizes for all shell image lists <size, list>
|
|
std::vector<std::pair<int,int>> m_ListSizes;
|
|
|
|
// the key is a hash of the path or the pidl
|
|
std::multimap<unsigned int,ItemInfo> m_ItemInfos;
|
|
|
|
// the key is a hash of the uppercase appid (win10 only)
|
|
std::map<unsigned int,const ItemInfo*> m_MetroItemInfos10;
|
|
// hashes of appids that are for sure not valid
|
|
std::set<unsigned int> m_BlackListInfos10;
|
|
|
|
// the key is a hash of the location and index
|
|
std::multimap<unsigned int,IconInfo> m_IconInfos;
|
|
|
|
// bitmaps that were replaced but may still be used by the main thread
|
|
std::vector<HBITMAP> m_OldBitmaps;
|
|
|
|
const IconInfo *m_DefaultSmallIcon;
|
|
const IconInfo *m_DefaultLargeIcon;
|
|
const IconInfo *m_DefaultExtraLargeIcon;
|
|
|
|
// list of items to process in background
|
|
std::list<ItemInfo*> m_ItemQueue;
|
|
std::list<ItemInfo*> m_ItemQueueLow; // lower priority
|
|
|
|
std::vector<const ItemInfo*> m_NewPrograms;
|
|
std::vector<const ItemInfo*> m_NewProgramRoots;
|
|
unsigned int m_TransientHash;
|
|
bool m_bHasNewPrograms[2]; // 0 - for real, 1 - filtered
|
|
bool m_bHasNewApps[2]; // 0 - for real, 1 - filtered
|
|
|
|
bool m_bPreloadIcons;
|
|
bool m_bPreloadFavorites;
|
|
enum TLoadingStage
|
|
{
|
|
LOAD_STOPPED, // the loading threads are not running
|
|
LOAD_STOPPING, // the loading threads are stopping
|
|
LOAD_LOADING, // the loading threads are running
|
|
};
|
|
volatile TLoadingStage m_LoadingStage;
|
|
int m_LastCacheSave;
|
|
COLORREF m_OldSysAccentColor;
|
|
bool m_bOldInvertIcons;
|
|
|
|
void LoadFolderItems( IShellItem *pFolder, int refreshFlags, int levels, TLocation location );
|
|
void LoadMetroItems( int refreshFlags );
|
|
void PreloadItemsThread( void );
|
|
void CreateDefaultIcons( void );
|
|
static DWORD CALLBACK StaticPreloadItemsThread( void *param );
|
|
void RefreshInfoThread( void );
|
|
static DWORD CALLBACK StaticRefreshInfoThread( void *param );
|
|
static DWORD CALLBACK SaveCacheFileThread( void *param );
|
|
|
|
// all paths are in caps and end with \
|
|
CString m_RootStartMenu1;
|
|
CString m_RootStartMenu2;
|
|
CString m_RootStartMenu3;
|
|
CString m_RootCommonPrograms;
|
|
CString m_RootGames;
|
|
CString m_RootDesktop;
|
|
CString m_RootTaskbar;
|
|
CString m_RootMetro;
|
|
// can be called from any thread
|
|
TLocation DetermineLocation( const wchar_t *PATH );
|
|
|
|
struct ModuleInfo
|
|
{
|
|
CString PATH;
|
|
FILETIME timestamp;
|
|
};
|
|
static bool CompareModuleTimeStamp( const CString &PATH, const FILETIME ×tamp, std::vector<ModuleInfo> &modules );
|
|
|
|
struct KnownPathGuid
|
|
{
|
|
CComString path;
|
|
CComString guid;
|
|
int pathLen;
|
|
};
|
|
|
|
struct OldItemInfo
|
|
{
|
|
unsigned int hash;
|
|
FILETIME timestamp;
|
|
|
|
bool operator<( const OldItemInfo &x ) const { return hash<x.hash; }
|
|
};
|
|
|
|
std::vector<OldItemInfo> m_OldItemInfos;
|
|
|
|
void LoadOldItems( void );
|
|
bool IsPathUsed( CRegKey ®Key, const wchar_t *path, const FILETIME &createstamp, const KnownPathGuid *knownPaths, int knownPathsCount, bool bMetroApp );
|
|
void AddOldItems( const std::vector<unsigned> &hashes );
|
|
};
|
|
|
|
CString GetPropertyStoreString( IPropertyStore *pStore, REFPROPERTYKEY key );
|
|
|
|
class CShellItemEnumerator
|
|
{
|
|
public:
|
|
CShellItemEnumerator( IShellItem *pFolder );
|
|
bool IsValid( void ) const;
|
|
bool GetNext( CComPtr<IShellItem> &pChild, CAbsolutePidl &childPidl );
|
|
|
|
private:
|
|
CComPtr<IEnumIDList> m_pEnumPidls;
|
|
CComPtr<IEnumShellItems> m_pEnumItems;
|
|
CAbsolutePidl m_Root;
|
|
};
|
|
|
|
struct UserAssistData
|
|
{
|
|
int pad1;
|
|
int count;
|
|
int pad2[2];
|
|
float history[10];
|
|
int last;
|
|
FILETIME timestamp;
|
|
int pad3;
|
|
};
|
|
|
|
void EncodeUserAssistPath( wchar_t *path );
|
|
void EncodeRot13( wchar_t *text );
|
|
|
|
enum TNetworkType
|
|
{
|
|
NETWORK_NONE,
|
|
NETWORK_SERVER, // \\server
|
|
NETWORK_SHARE, // \\server\share
|
|
NETWORK_DRIVE, // Q:
|
|
NETWORK_FOLDER, // either \\server\share\folder or Q:\folder
|
|
NETWORK_FILE, // something with extension
|
|
};
|
|
|
|
HRESULT MenuParseDisplayName( const wchar_t *path, PIDLIST_ABSOLUTE *pPidl, SFGAOF *pFlags, TNetworkType *pNetworkType );
|
|
const wchar_t *GetDefaultNetworkIcon( TNetworkType networkType );
|
|
bool MenuGetFileTimestamp( const wchar_t *path, FILETIME *pWriteTime, FILETIME *pCreateTime );
|
|
STDAPI ShGetKnownFolderPath( REFKNOWNFOLDERID rfid, PWSTR *pPath );
|
|
STDAPI ShGetKnownFolderIDList(REFKNOWNFOLDERID rfid, PIDLIST_ABSOLUTE *pPidl );
|
|
STDAPI ShGetKnownFolderItem(REFKNOWNFOLDERID rfid, IShellItem **ppItem );
|
|
HBITMAP ColorizeMonochromeImage(HBITMAP bitmap, DWORD color);
|
|
|
|
#define TASKBAR_PINNED_ROOT L"%APPDATA%\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar"
|
|
#define START_MENU_PINNED_ROOT L"%APPDATA%\\OpenShell\\Pinned"
|
|
#define STARTSCREEN_COMMAND L"startscreen.lnk"
|
|
#define USERASSIST_LINKS_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count"
|
|
#define USERASSIST_APPIDS_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\Count"
|
|
|
|
|
|
//#define STARTSCREEN_WIN7
|
|
#ifdef BUILD_SETUP
|
|
#undef STARTSCREEN_WIN7
|
|
#endif
|