Files
Open-Shell-Menu/ClassicStartSrc/ClassicStartMenu/ClassicStartMenu.cpp
Xenhat 0adcd693e4 Some branding and licensing work (#22)
* Fix stdafx include

* Fix basic handling of "Games" folder on Windows10 RS4 (#10)
This does the following:
- Sets the default state to hidden
- Skips the Games folder when searching

This does not:
- Hide the dead menu entry.

I do not currently know how to actively change the user preference setting to forcefully hide it.

* Add basic Visual Studio gitignore

* Add specific entries to gitignore

* Do not set default menu to Win7 on RS4 (#10)

* Rename "PC Settings" to "Settings" (#12)

* Create distinction between modern and legacy settings in search results

* Add more build artifacts to gitignore

* Add default paths for toolset and build all languages

* Fix several memsize, memtype and nullpointer issues

* create trunk branch containing all changes

* set fallback and next version to 4.3.2, set resource fallback value to allow loading in IDE

* add generated en-US.dll to gitignore

* Don't echo script contents, add disabled "git clean -dfx" to build fresh

* Initial re-branding work (#21)

* Create copy of __MakeFinal to build all languages (Use this file when releasing new versions)

* Move the registry key IvoSoft->Passionate-Coder (#21)

* Change company/mfg name IvoSoft->Passionate-Coder (#21)

* Update some leftover copyright dates (#21)

* Fix accidental copy-paste breaking MakeFinal scripts

* Fix invalid company name for Wix and change registry keys to match the new string (#21)

* Update more copyright and legal text (#21)

* Update RTF files format (Wordpad generated those) (#21)

* update license text in RTF files (#21)
We lost the blue link text in the installer page. Will have to manually re-color all the links later.
2018-06-25 01:42:52 -04:00

698 lines
21 KiB
C++

// Classic Shell (c) 2009-2017, Ivo Beltchev
// Classic Start (c) 2017-2018, The Passionate-Coder Team
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
#include <stdafx.h>
#include <dbghelp.h>
#include <wuapi.h>
#include "StringUtils.h"
#include "ResourceHelper.h"
#include "TrackResources.h"
#include "ComHelper.h"
#include "Settings.h"
#include "psapi.h"
#include "ClassicStartMenuDLL\ClassicStartMenuDLL.h"
#include "ClassicStartMenuDLL\SettingsUI.h"
#include "ClassicStartMenuDLL\resource.h"
#include "ClassicStartMenuDLL\LogManager.h"
static HHOOK g_StartHook;
static void UnhookStartMenu( void )
{
if (g_StartHook)
UnhookWindowsHookEx(g_StartHook);
g_StartHook=NULL;
}
enum THookMode
{
HOOK_NONE, // don't hook Explorer, running as a separate exe
HOOK_NORMAL, // hook Explorer normally, no retry
HOOK_STARTUP, // retry to hook Explorer
HOOK_STARTUP2, // retry to hook Explorer (for secondary desktops)
};
static bool HookStartMenu( THookMode mode, HWND &menu )
{
HMODULE hHookModule=GetModuleHandle(L"ClassicStartMenuDLL.dll");
// find the Progman window and the start button
DllLogToFile(STARTUP_LOG,L"StartMenu: hooking Explorer");
HWND progWin=NULL;
bool bFindAppManager=(mode==HOOK_STARTUP && GetWinVersion()>=WIN_VER_WIN8 && GetWinVersion()<=WIN_VER_WIN81);
for (int i=0;i<120;i++) // retry for 1 minute
{
if (bFindAppManager)
bFindAppManager=!FindWindow(L"ApplicationManager_DesktopShellWindow",NULL);
if (!bFindAppManager)
{
progWin=FindWindowEx(NULL,NULL,L"Progman",NULL);
if (progWin) break;
if (mode!=HOOK_STARTUP && mode!=HOOK_STARTUP2) return true; // the Progman window may not be created yet (if Explorer is currently restarting)
}
DllLogToFile(STARTUP_LOG,L"StartMenu: can't find Progman, retrying");
Sleep(500);
}
if (!progWin)
return true;
DWORD process=0;
DWORD thread=GetWindowThreadProcessId(progWin,&process);
HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,process);
if (hProcess)
{
bool success=false;
wchar_t path[MAX_PATH];
if (GetModuleFileNameEx(hProcess,NULL,path,_countof(path)))
{
if (_wcsicmp(PathFindFileName(path),L"explorer.exe")==0)
success=true;
else
DllLogToFile(STARTUP_LOG,L"StartMenu: found wrong process %s",path);
}
else
DllLogToFile(STARTUP_LOG,L"StartMenu: failed to get process name");
CloseHandle(hProcess);
if (!success)
return false;
}
else
DllLogToFile(STARTUP_LOG,L"StartMenu: failed to open process %d",process);
for (int i=0;i<10;i++) // retry for 5 sec
{
if (FindTaskBar(process)) break;
if (mode!=HOOK_STARTUP && mode!=HOOK_STARTUP2) return false; // the taskbar may not be created yet (if Explorer is currently restarting)
DllLogToFile(STARTUP_LOG,L"StartMenu: can't find taskbar, retrying");
Sleep(500);
}
if (mode==HOOK_NONE)
{
menu=ToggleStartMenu(-1,false);
return true;
}
// install hooks in the explorer process
thread=GetWindowThreadProcessId(g_TaskBar,NULL);
g_StartHook=SetWindowsHookEx(WH_GETMESSAGE,HookInject,hHookModule,thread);
if (!g_StartHook)
{
int err=GetLastError();
DllLogToFile(STARTUP_LOG,L"StartMenu: hook failed: 0x%08X",err);
}
PostMessage(g_TaskBar,WM_NULL,0,0); // make sure there is one message in the queue
return true;
}
static UINT g_TaskbarCreatedMsg; // the "TaskbarCreated" message
// CStartHookWindow is a hidden window that waits for the "TaskbarCreated" message and rehooks the explorer process
// Also when the start menu wants to shut down it sends WM_CLOSE to this window, which unhooks explorer and exits
const int WM_OPEN=WM_USER+10;
const int TIMER_HOOK=1;
class CStartHookWindow: public CWindowImpl<CStartHookWindow>
{
public:
DECLARE_WND_CLASS(L"ClassicStartMenu.CStartHookWindow")
BEGIN_MSG_MAP( CStartHookWindow )
MESSAGE_HANDLER( WM_OPEN, OnOpen )
MESSAGE_HANDLER( WM_CLOSE, OnClose )
MESSAGE_HANDLER( WM_CLEAR, OnClear )
MESSAGE_HANDLER( WM_TIMER, OnTimer )
MESSAGE_HANDLER( g_TaskbarCreatedMsg, OnTaskbarCreated )
END_MSG_MAP()
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 OnOpen( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnTaskbarCreated( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
};
LRESULT CStartHookWindow::OnOpen( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (g_TaskBar) ::PostMessage(g_TaskBar,RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"),wParam,lParam);
return 0;
}
LRESULT CStartHookWindow::OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
UnhookStartMenu();
Sleep(100);
PostQuitMessage(0);
return 0;
}
LRESULT CStartHookWindow::OnClear( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
UnhookStartMenu();
return 0;
}
LRESULT CStartHookWindow::OnTaskbarCreated( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
DllLogToFile(STARTUP_LOG,L"StartMenu: Taskbar Created");
SetTimer(TIMER_HOOK,100);
return 0;
}
LRESULT CStartHookWindow::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (wParam==TIMER_HOOK)
{
UnhookStartMenu();
HWND menu;
HookStartMenu(HOOK_NORMAL,menu);
if (g_StartHook)
KillTimer(TIMER_HOOK);
}
return 0;
}
enum
{
CMD_NONE=-1,
CMD_TOGGLE_NEW=-2,
};
static const GUID IID_IWpnTileSink={0xe716b283,0x6be7,0x4e6f,{0xa8,0x8f,0x1c,0xde,0x47,0xd5,0xe3,0x55}};
interface IWpnTileSink : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE TileSessionUpdated(unsigned long,void const *,unsigned long) = 0;
virtual HRESULT STDMETHODCALLTYPE TileSessionNotificationCleared(unsigned long,void const *,unsigned long) = 0;
virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated(unsigned long,int) = 0;
virtual HRESULT STDMETHODCALLTYPE TileRequestNotificationCompleted(void const * ptr64,unsigned long) = 0;
virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated2(unsigned long,int) = 0;
};
class CWpnTileSink : public IWpnTileSink
{
// from IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject );
virtual ULONG STDMETHODCALLTYPE AddRef( void ) { return 1; }
virtual ULONG STDMETHODCALLTYPE Release( void ) { return 1; }
virtual HRESULT STDMETHODCALLTYPE TileSessionUpdated(unsigned long a,void const *b,unsigned long c)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE TileSessionNotificationCleared(unsigned long a,void const *b,unsigned long c)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated(unsigned long a,int b)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE TileRequestNotificationCompleted(void const * a,unsigned long b)
{
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE TileSessionImageDownloadUpdated2(unsigned long a,int b)
{
return S_OK;
}
};
HRESULT STDMETHODCALLTYPE CWpnTileSink::QueryInterface( REFIID riid, void **ppvObject )
{
*ppvObject=NULL;
if (riid==IID_IUnknown || riid==IID_IWpnTileSink)
{
*ppvObject=this;
return S_OK;
}
return E_NOINTERFACE;
}
MIDL_INTERFACE("0e467ac1-65f2-48d6-8bf2-375430548a87")
IWpnPresentationEndpoint : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE TileCreateSession( unsigned long * ) = 0;
virtual HRESULT STDMETHODCALLTYPE TileCloseSession( unsigned long ) = 0;
virtual HRESULT STDMETHODCALLTYPE TileUpdateSession( unsigned long,const void *,unsigned long ) = 0; // (1, str, 1)
virtual HRESULT STDMETHODCALLTYPE TileRequestNotification( const void *, unsigned long ) = 0; // (str, 1)*/
};
const CLSID CLSID_WpnPlatform={0x0c9281f9, 0x6da1, 0x4006, {0x87, 0x29, 0xde, 0x6e, 0x6b, 0x61, 0x58, 0x1c}};
MIDL_INTERFACE("9fa045cb-b9b3-47ba-842f-e2ab458f2b0c")
IWpnPlatform : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE CreateAppEndpoint( struct IWpnAppEndpoint **ppEndpoint ) = 0;
virtual HRESULT STDMETHODCALLTYPE CreatePresentationEndpoint(struct IWpnPresentationEndpoint ** ppEndpoint ) = 0;
/* virtual HRESULT STDMETHODCALLTYPE CreateRegistrationEndpoint(struct IWpnRegistrationEndpoint * ptr64 * ptr64) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateSettingsEndpoint(struct IWpnSettingsEndpoint * ptr64 * ptr64) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateIdleTaskEndpoint(struct IWpnIdleTaskEndpoint * ptr64 * ptr64) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateTestEndpoint(struct IWpnTestEndpoint * ptr64 * ptr64) = 0;*/
};
//const wchar_t *g_AppId=L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail";
//const wchar_t *g_AppId=L"Microsoft.BingNews_8wekyb3d8bbwe!AppexNews";
//const wchar_t *g_AppId=L"Microsoft.WindowsStore_8wekyb3d8bbwe!App";
//const wchar_t *g_AppId=L"Microsoft.BingWeather_8wekyb3d8bbwe!App";
const wchar_t *g_AppId=L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar";
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow )
{
/* CoInitialize(NULL);
{
CComPtr<IWpnPlatform> pWpnPlatform;
HRESULT hr=pWpnPlatform.CoCreateInstance(CLSID_WpnPlatform);
CComPtr<IWpnPresentationEndpoint> pUnknown;
hr=pWpnPlatform->CreatePresentationEndpoint(&pUnknown);
CWpnTileSink sink;
DWORD cookie;
CComQIPtr<IConnectionPoint> pConnectionPoint=pUnknown;
hr=pConnectionPoint->Advise(&sink,&cookie);
CComPtr<IWpnPresentationEndpoint> pWpnPresentationEndpoint=pUnknown;
DWORD session;
hr=pWpnPresentationEndpoint->TileCreateSession(&session);
struct
{
const wchar_t *appid;
void *ptr1;
void *ptr2;
__int64 idx;
} request={g_AppId,0,0,1};
hr=pWpnPresentationEndpoint->TileRequestNotification(&request,1);
MSG msg;
while(true)
{
struct
{
const wchar_t *appid;
__int64 idx;
} updateData={g_AppId,1};
hr=pWpnPresentationEndpoint->TileUpdateSession(session,&updateData,1);
while (PeekMessage(&msg,0,0,0,PM_REMOVE))
// while (GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(100);
}
int q=0;
}
CoUninitialize();
return 0;*/
/* DWORD count;
pStore->GetCount(&count);
for (DWORD i=0;i<count;i++)
{
PROPERTYKEY key;
if (SUCCEEDED(pStore->GetAt(i,&key)))
{
CComString pPropName;
PSGetNameFromPropertyKey(key,&pPropName);
PROPVARIANT val;
PropVariantInit(&val);
pStore->GetValue(key,&val);
PropVariantClear(&val);
}
}*/
DllLogToFile(STARTUP_LOG,L"StartMenu: start '%s'",lpstrCmdLine);
DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll"));
if (wcsstr(lpstrCmdLine,L"-startup") || (wcsstr(lpstrCmdLine,L"-autorun") && HIWORD(winVer)<WIN_VER_WIN8))
{
WaitDllInitThread();
if (!DllGetSettingBool(L"AutoStart"))
{
DllLogToFile(STARTUP_LOG,L"StartMenu: quit - no AutoStart");
return 0;
}
#ifdef BUILD_BETA
if (GetKeyState(VK_SHIFT)<0)
return 0;
#endif
int sleep=DllGetSettingInt(L"AutoStartDelay");
if (sleep>0)
Sleep(sleep);
}
else if (wcsstr(lpstrCmdLine,L"-autorun")) // on Win8+
{
WaitDllInitThread();
CRegKey regKey;
if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\PassionateCoder\\ClassicStart",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS)
{
DWORD ver1;
if (regKey.QueryDWORDValue(L"WinVersion",ver1)==ERROR_SUCCESS)
{
if (ver1<winVer)
{
// this is an upgrade
MessageBox(NULL,DllLoadStringEx(IDS_UPGRADE_WIN),DllLoadStringEx(IDS_APP_TITLE),MB_OK);
#ifdef _WIN64
wchar_t path[_MAX_PATH]=L"%windir%\\System32\\StartMenuHelper64.dll";
#else
wchar_t path[_MAX_PATH]=L"%windir%\\System32\\StartMenuHelper32.dll";
#endif
DoEnvironmentSubst(path,_countof(path));
if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES)
{
GetModuleFileName(NULL,path,_countof(path));
CoInitialize(NULL);
ShellExecute(NULL,L"runas",path,L"-upgrade",NULL,SW_SHOWNORMAL);
CoUninitialize();
}
}
}
}
if (!DllGetSettingBool(L"AutoStart"))
{
DllLogToFile(STARTUP_LOG,L"StartMenu: quit - no AutoStart");
return 0;
}
int sleep=DllGetSettingInt(L"AutoStartDelay");
if (sleep>0)
Sleep(sleep);
}
if (wcsstr(lpstrCmdLine,L"-upgrade"))
{
WaitDllInitThread();
CRegKey regKey;
DWORD error=regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\PassionateCoder\\ClassicStart",KEY_WRITE|KEY_WOW64_64KEY);
const wchar_t *nl=error==ERROR_SUCCESS?L"\r\n\r\n":L"\r\n";
if (error==ERROR_SUCCESS)
{
regKey.SetDWORDValue(L"WinVersion",winVer);
// run regsvr32 StartMenuHelper
#ifdef _WIN64
wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper64.dll\"";
#else
wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper32.dll\"";
#endif
DoEnvironmentSubst(cmdLine,_countof(cmdLine));
wchar_t exe[_MAX_PATH]=L"%windir%\\System32\\regsvr32.exe";
DoEnvironmentSubst(exe,_countof(exe));
STARTUPINFO startupInfo={sizeof(startupInfo)};
PROCESS_INFORMATION processInfo;
memset(&processInfo,0,sizeof(processInfo));
if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo))
{
CloseHandle(processInfo.hThread);
WaitForSingleObject(processInfo.hProcess,INFINITE);
GetExitCodeProcess(processInfo.hProcess,&error);
CloseHandle(processInfo.hProcess);
}
else
error=GetLastError();
}
if (error)
{
wchar_t msg[1024];
int len=Sprintf(msg,_countof(msg),L"%s%s",DllLoadStringEx(IDS_UPGRADE_ERROR),nl);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,error,0,msg+len,_countof(msg)-len,NULL);
MessageBox(NULL,msg,DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONERROR);
}
else
{
MessageBox(NULL,DllLoadStringEx(IDS_UPGRADE_SUCCESS),DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONINFORMATION);
}
return error;
}
const wchar_t *pCmd=wcsstr(lpstrCmdLine,L"-cmd ");
if (pCmd)
{
WaitDllInitThread();
CoInitialize(NULL);
wchar_t command[100];
GetToken(pCmd+5,command,_countof(command),L" ");
if (DllExecuteNamedCommand(command))
{
MSG msg;
while (PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CoUninitialize();
return 0;
}
#ifndef _WIN64
const wchar_t *pSaveAdmx=wcsstr(lpstrCmdLine,L"-saveadmx ");
if (pSaveAdmx)
{
WaitDllInitThread();
wchar_t language[100];
GetToken(pSaveAdmx+10,language,_countof(language),L" ");
HMODULE dll=NULL;
if (language[0])
{
wchar_t path[_MAX_PATH];
GetCurrentDirectory(_countof(path),path);
PathAppend(path,language);
PathAddExtension(path,L".dll");
dll=LoadLibraryEx(path,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE);
}
DllLoadTranslationResources(dll,NULL);
if (!DllSaveAdmx(COMPONENT_MENU,"ClassicStartMenu.admx","ClassicStartMenu.adml","ClassicStartMenuADMX.txt"))
return 1;
if (!DllSaveAdmx(COMPONENT_SHARED,"ClassicStart.admx","ClassicStart.adml","ClassicStartADMX.txt"))
return 1;
return 0;
}
#endif
wchar_t path[_MAX_PATH];
GetModuleFileName(NULL,path,_countof(path));
*PathFindFileName(path)=0;
SetCurrentDirectory(path);
const wchar_t *pRunAs=wcsstr(lpstrCmdLine,L"-runas");
if (pRunAs)
{
pRunAs+=7;
CoInitialize(NULL);
wchar_t exe[_MAX_PATH];
const wchar_t *args=NULL;
CComString strExe, strArgs;
if (SUCCEEDED(SHEvaluateSystemCommandTemplate(pRunAs,&strExe,NULL,&strArgs)))
{
args=strArgs;
Strcpy(exe,_countof(exe),strExe);
}
else
{
args=SeparateArguments(pRunAs,exe);
}
SHELLEXECUTEINFO execute={sizeof(execute),SEE_MASK_DOENVSUBST|SEE_MASK_FLAG_LOG_USAGE};
execute.lpFile=exe;
execute.lpParameters=args;
execute.nShow=SW_SHOWNORMAL;
ShellExecuteEx(&execute);
CoUninitialize();
return 0;
}
WaitDllInitThread();
int open=CMD_NONE;
if (wcsstr(lpstrCmdLine,L"-togglenew")!=NULL) open=CMD_TOGGLE_NEW;
else if (wcsstr(lpstrCmdLine,L"-toggle")!=NULL) open=MSG_TOGGLE;
else if (wcsstr(lpstrCmdLine,L"-open")!=NULL) open=MSG_OPEN;
else if (wcsstr(lpstrCmdLine,L"-settings")!=NULL) open=MSG_SETTINGS;
else if (wcsstr(lpstrCmdLine,L"-exit")!=NULL) open=MSG_EXIT;
{
const wchar_t *pXml=wcsstr(lpstrCmdLine,L"-xml ");
if (pXml)
{
wchar_t xml[_MAX_PATH];
GetToken(pXml+5,xml,_countof(xml),L" ");
CoInitialize(NULL);
bool res=DllImportSettingsXml(xml);
CoUninitialize();
if (res)
open=MSG_RELOADSETTINGS;
else
return 1;
}
}
{
const wchar_t *pBackup=wcsstr(lpstrCmdLine,L"-backup ");
if (pBackup)
{
wchar_t xml[_MAX_PATH];
GetToken(pBackup+8,xml,_countof(xml),L" ");
CoInitialize(NULL);
bool res=DllExportSettingsXml(xml);
CoUninitialize();
return res?0:1;
}
}
const wchar_t *pNoHook=wcsstr(lpstrCmdLine,L"-nohook");
bool bHookExplorer=!pNoHook;
if (pNoHook)
{
pNoHook+=7;
if (*pNoHook=='1') MiniDumpType=MiniDumpNormal;
if (*pNoHook=='2') MiniDumpType=MiniDumpWithDataSegs;
if (*pNoHook=='3') MiniDumpType=MiniDumpWithFullMemory;
}
if (!bHookExplorer)
SetUnhandledExceptionFilter(TopLevelFilter);
#ifndef BUILD_SETUP
if (wcsstr(lpstrCmdLine,L"-testsettings")!=NULL || GetKeyState(VK_SHIFT)<0)
{
CoInitialize(NULL);
InitManagers(true);
EditSettings(true,0);
CloseManagers(true);
CoUninitialize();
#ifdef TRACK_GDI_RESOURCES
DllDumpResourceLeaks();
#endif
return 0;
}
#endif
// prevent multiple instances from running on the same desktop
// the assumption is that multiple desktops for the same user will have different name (but may repeat across users)
wchar_t userName[256];
DWORD len=_countof(userName);
GetUserName(userName,&len);
len=0;
HANDLE desktop=GetThreadDesktop(GetCurrentThreadId());
GetUserObjectInformation(desktop,UOI_NAME,NULL,0,&len);
wchar_t *deskName=(wchar_t*)malloc(len);
GetUserObjectInformation(desktop,UOI_NAME,deskName,len,&len);
bool bDefaultDesktop=(_wcsicmp(deskName,L"Default")==0);
wchar_t mutexName[1024];
Sprintf(mutexName,_countof(mutexName),L"ClassicStartMenu.Mutex.%s.%s",userName,deskName);
free(deskName);
if (open==CMD_NONE)
DllLogToFile(STARTUP_LOG,L"StartMenu: mutex %s",mutexName);
HWND progWin=FindWindowEx(NULL,NULL,L"Progman",NULL);
DWORD process;
if (progWin)
GetWindowThreadProcessId(progWin,&process);
HANDLE hMutex=NULL;
if (bHookExplorer)
{
hMutex=CreateMutex(NULL,TRUE,mutexName);
if (GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED)
{
if (open==MSG_TOGGLE || open==CMD_TOGGLE_NEW)
{
if (progWin)
{
AllowSetForegroundWindow(process);
HWND taskBar=FindTaskBar(process);
if (taskBar)
PostMessage(taskBar,RegisterWindowMessage(L"ClassicStartMenu.StartMenuMsg"),(open==CMD_TOGGLE_NEW)?MSG_TOGGLENEW:MSG_TOGGLE,0);
else
PostMessage(progWin,WM_SYSCOMMAND,SC_TASKLIST,(open==CMD_TOGGLE_NEW)?'WSMK':'CSM');
}
}
else if (open!=CMD_NONE)
{
AllowSetForegroundWindow(process);
HWND hwnd=FindWindow(L"ClassicStartMenu.CStartHookWindow",L"StartHookWindow");
if (hwnd) PostMessage(hwnd,WM_OPEN,open,0);
}
if (open==MSG_EXIT && hMutex && WaitForSingleObject(hMutex,2000)==WAIT_OBJECT_0)
ReleaseMutex(hMutex);
if (open==CMD_NONE)
DllLogToFile(STARTUP_LOG,L"StartMenu: exit (mutex exists)");
return 0;
}
}
if (open!=CMD_NONE && open!=MSG_OPEN && open!=MSG_SETTINGS)
{
if (hMutex) ReleaseMutex(hMutex);
return 0;
}
OleInitialize(NULL);
if (!bHookExplorer)
{
DllUpdateSettings();
InitManagers(true);
}
CStartHookWindow window;
window.Create(NULL,NULL,L"StartHookWindow",WS_POPUP);
g_TaskbarCreatedMsg=RegisterWindowMessage(L"TaskbarCreated");
typedef BOOL (WINAPI *tChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct );
HMODULE hUser32=GetModuleHandle(L"user32.dll");
tChangeWindowMessageFilterEx ChangeWindowMessageFilterEx=(tChangeWindowMessageFilterEx)GetProcAddress(hUser32,"ChangeWindowMessageFilterEx");
if (ChangeWindowMessageFilterEx)
{
ChangeWindowMessageFilterEx(window,g_TaskbarCreatedMsg,MSGFLT_ADD,NULL);
ChangeWindowMessageFilterEx(window,WM_CLEAR,MSGFLT_ADD,NULL);
ChangeWindowMessageFilterEx(window,WM_OPEN,MSGFLT_ADD,NULL);
ChangeWindowMessageFilterEx(window,WM_CLOSE,MSGFLT_ADD,NULL);
}
else
{
ChangeWindowMessageFilter(g_TaskbarCreatedMsg,MSGFLT_ADD);
ChangeWindowMessageFilter(WM_CLEAR,MSGFLT_ADD);
ChangeWindowMessageFilter(WM_OPEN,MSGFLT_ADD);
ChangeWindowMessageFilter(WM_CLOSE,MSGFLT_ADD);
}
MSG msg;
HWND menu=NULL;
if (HookStartMenu(bHookExplorer?(bDefaultDesktop?HOOK_STARTUP:HOOK_STARTUP2):HOOK_NONE,menu))
{
if (bHookExplorer && open>=0)
window.PostMessage(WM_OPEN,open,MSG_OPEN);
DllLogToFile(STARTUP_LOG,L"StartMenu: start message loop");
while ((bHookExplorer || IsWindow(menu)) && GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DllLogToFile(STARTUP_LOG,L"StartMenu: end message loop");
window.DestroyWindow();
if (!bHookExplorer)
{
CloseManagers(true);
}
OleUninitialize();
if (hMutex) ReleaseMutex(hMutex);
#ifdef TRACK_GDI_RESOURCES
DllDumpResourceLeaks();
#endif
return 0;
}