summaryrefslogtreecommitdiff
path: root/plugins/AutoShutdown/src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-05 11:34:19 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-05 11:34:19 +0000
commitf4ca33472b18027cdcf38c2569e1efbb116bd2a1 (patch)
tree56060e4103980528a5cf8c3534514988b1f8798a /plugins/AutoShutdown/src
parent9ee9547340e785ca4eb38294d975d6e1a3a567f2 (diff)
AutoShutdown: folder structure change
git-svn-id: http://svn.miranda-ng.org/main/trunk@767 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AutoShutdown/src')
-rw-r--r--plugins/AutoShutdown/src/common.h85
-rw-r--r--plugins/AutoShutdown/src/cpuusage.cpp210
-rw-r--r--plugins/AutoShutdown/src/cpuusage.h24
-rw-r--r--plugins/AutoShutdown/src/frame.cpp642
-rw-r--r--plugins/AutoShutdown/src/frame.h28
-rw-r--r--plugins/AutoShutdown/src/main.cpp132
-rw-r--r--plugins/AutoShutdown/src/options.cpp185
-rw-r--r--plugins/AutoShutdown/src/options.h24
-rw-r--r--plugins/AutoShutdown/src/resource.h58
-rw-r--r--plugins/AutoShutdown/src/settingsdlg.cpp506
-rw-r--r--plugins/AutoShutdown/src/settingsdlg.h30
-rw-r--r--plugins/AutoShutdown/src/shutdownsvc.cpp576
-rw-r--r--plugins/AutoShutdown/src/shutdownsvc.h29
-rw-r--r--plugins/AutoShutdown/src/utils.cpp342
-rw-r--r--plugins/AutoShutdown/src/utils.h48
-rw-r--r--plugins/AutoShutdown/src/version.h24
-rw-r--r--plugins/AutoShutdown/src/watcher.cpp390
-rw-r--r--plugins/AutoShutdown/src/watcher.h29
18 files changed, 3362 insertions, 0 deletions
diff --git a/plugins/AutoShutdown/src/common.h b/plugins/AutoShutdown/src/common.h
new file mode 100644
index 0000000000..d0ee925bdc
--- /dev/null
+++ b/plugins/AutoShutdown/src/common.h
@@ -0,0 +1,85 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h> /* for mir_sntprintf() */
+#include <time.h> /* for mktime(),time() */
+#include <tchar.h>
+#include <windows.h>
+#include <commctrl.h>
+
+/* WinXP+: shutdown reason codes */
+#if defined(EWX_RESTARTAPPS) /* new MS Platform SDK */
+ #include <reason.h>
+#else
+ #define SHTDN_REASON_MAJOR_OTHER 0x00000000
+ #define SHTDN_REASON_MINOR_OTHER 0x00000000
+ #define SHTDN_REASON_FLAG_PLANNED 0x80000000
+#endif
+
+/* RAS */
+#undef WINVER
+#define WINVER 0x400 /* prevent INVALID_BUFFER error */
+#include <ras.h> /* for RasEnumConnections(), RasHangUp() */
+#include <raserror.h> /* error codes for RAS */
+
+#define MIRANDA_VER 0x0A00
+#include <newpluginapi.h>
+#include <m_utils.h>
+#include <m_database.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_langpack.h>
+#include <m_system.h>
+#include <m_skin.h>
+#include <m_protosvc.h>
+#include <m_protocols.h>
+#include <m_plugins.h>
+#include <m_options.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_idle.h>
+#include <win2k.h>
+#include <m_cluiframes.h>
+#include <m_clistint.h>
+#include <m_fontservice.h>
+#include <m_icolib.h>
+#include <m_clc.h>
+#include <m_genmenu.h>
+#include <m_button.h>
+#include <m_hotkeys.h>
+
+#include <m_weather.h>
+#include <m_hddinfo.h>
+#include <m_toptoolbar.h>
+#include <m_trigger.h>
+#include <m_autoreplacer.h>
+#include <m_magneticwindows.h>
+#include <m_snappingwindows.h>
+#include "m_shutdown.h"
+
+#include "cpuusage.h"
+#include "frame.h"
+#include "options.h"
+#include "settingsdlg.h"
+#include "shutdownsvc.h"
+#include "utils.h"
+#include "watcher.h"
+#include "resource.h"
diff --git a/plugins/AutoShutdown/src/cpuusage.cpp b/plugins/AutoShutdown/src/cpuusage.cpp
new file mode 100644
index 0000000000..d99be4a6fe
--- /dev/null
+++ b/plugins/AutoShutdown/src/cpuusage.cpp
@@ -0,0 +1,210 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/************************* Stat Switch ********************************/
+
+#define Li2Double(x) ((double)((x).HighPart)*4.294967296E9+(double)((x).LowPart))
+
+static BOOL WinNT_PerfStatsSwitch(TCHAR *pszServiceName,BOOL fDisable)
+{
+ HKEY hKeyServices,hKeyService,hKeyPerf;
+ DWORD dwData,dwDataSize;
+ BOOL fSwitched=FALSE;
+ /* Win2000+ */
+ if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("System\\CurrentControlSet\\Services"),0,KEY_QUERY_VALUE|KEY_SET_VALUE,&hKeyServices)) {
+ if(!RegOpenKeyEx(hKeyServices,pszServiceName,0,KEY_QUERY_VALUE|KEY_SET_VALUE,&hKeyService)) {
+ if(!RegOpenKeyEx(hKeyService,_T("Performance"),0,KEY_QUERY_VALUE|KEY_SET_VALUE,&hKeyPerf)) {
+ dwDataSize=sizeof(DWORD);
+ if(!RegQueryValueEx(hKeyPerf,_T("Disable Performance Counters"),NULL,NULL,(BYTE*)&dwData,&dwDataSize))
+ if((dwData!=0)!=fDisable)
+ fSwitched=!RegSetValueEx(hKeyPerf,_T("Disable Performance Counters"),0,REG_DWORD,(BYTE*)&fDisable,dwDataSize);
+ RegCloseKey(hKeyPerf);
+ }
+ RegCloseKey(hKeyService);
+ }
+ RegCloseKey(hKeyServices);
+ }
+ return fSwitched;
+}
+
+/************************* Poll Thread ********************************/
+struct CpuUsageThreadParams {
+ DWORD dwDelayMillis;
+ CPUUSAGEAVAILPROC pfnDataAvailProc;
+ LPARAM lParam;
+ HANDLE hFirstEvent;
+ DWORD *pidThread;
+};
+
+static BOOL CallBackAndWait(struct CpuUsageThreadParams *param,BYTE nCpuUsage)
+{
+ if(param->hFirstEvent!=NULL) {
+ /* return value for PollCpuUsage() */
+ *param->pidThread=GetCurrentThreadId();
+ SetEvent(param->hFirstEvent);
+ param->hFirstEvent=NULL;
+ /* lower priority after first call */
+ SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_IDLE);
+ }
+ if(!param->pfnDataAvailProc(nCpuUsage,param->lParam)) return FALSE;
+ SleepEx(param->dwDelayMillis,TRUE);
+ return !Miranda_Terminated();
+}
+
+static void WinNT_PollThread(void *vparam)
+{
+ CpuUsageThreadParams *param = (CpuUsageThreadParams*)vparam;
+
+ DWORD dwBufferSize=0,dwCount;
+ BYTE *pBuffer=NULL;
+ PERF_DATA_BLOCK *pPerfData=NULL;
+ LONG res,lCount;
+ PERF_OBJECT_TYPE *pPerfObj;
+ PERF_COUNTER_DEFINITION *pPerfCounter;
+ PERF_INSTANCE_DEFINITION *pPerfInstance;
+ PERF_COUNTER_BLOCK *pPerfCounterBlock;
+ DWORD dwObjectId,dwCounterId;
+ WCHAR wszValueName[11],*pwszInstanceName;
+ BYTE nCpuUsage;
+ BOOL fSwitched,fFound,fIsFirst=FALSE;
+ LARGE_INTEGER liPrevCounterValue={0},liCurrentCounterValue={0},liPrevPerfTime100nSec={0};
+
+ /* init */
+ if(IsWinVer2000Plus()) { /* Win2000+: */
+ dwObjectId=238; /*'Processor' object */
+ dwCounterId=6; /* '% processor time' counter */
+ pwszInstanceName=L"_Total"; /* '_Total' instance */
+ } else { /* WinNT4: */
+ dwObjectId=2; /* 'System' object */
+ dwCounterId=240; /* '% Total processor time' counter */
+ pwszInstanceName=NULL;
+ }
+ _itot_s(dwObjectId, wszValueName, 10);
+ fSwitched = WinNT_PerfStatsSwitch(_T("PerfOS"), FALSE);
+
+ /* poll */
+ for(;;) {
+ /* retrieve data for given object */
+ res=RegQueryValueExW(HKEY_PERFORMANCE_DATA,wszValueName,NULL,NULL,(BYTE*)pPerfData,&dwBufferSize);
+ while(!pBuffer || res==ERROR_MORE_DATA) {
+ pBuffer=(BYTE*)mir_realloc(pPerfData,dwBufferSize+=256);
+ if(!pBuffer) break;
+ pPerfData=(PERF_DATA_BLOCK*)pBuffer;
+ res=RegQueryValueExW(HKEY_PERFORMANCE_DATA,wszValueName,NULL,NULL,pBuffer,&dwBufferSize);
+ }
+ if(res!=ERROR_SUCCESS) break;
+
+ /* find object in data */
+ fFound=FALSE;
+ /* first object */
+ pPerfObj=(PERF_OBJECT_TYPE*)((BYTE*)pPerfData+pPerfData->HeaderLength);
+ for(dwCount=0;dwCount<pPerfData->NumObjectTypes;++dwCount) {
+ if(pPerfObj->ObjectNameTitleIndex==dwObjectId) {
+ /* find counter in object data */
+ /* first counter */
+ pPerfCounter=(PERF_COUNTER_DEFINITION*)((BYTE*)pPerfObj+pPerfObj->HeaderLength);
+ for(dwCount=0;dwCount<(pPerfObj->NumCounters);++dwCount) {
+ if(pPerfCounter->CounterNameTitleIndex==dwCounterId) {
+ /* find instance in counter data */
+ if(pPerfObj->NumInstances==PERF_NO_INSTANCES) {
+ pPerfCounterBlock=(PERF_COUNTER_BLOCK*)((BYTE*)pPerfObj+pPerfObj->DefinitionLength);
+ liCurrentCounterValue=*(LARGE_INTEGER*)((BYTE*)pPerfCounterBlock+pPerfCounter->CounterOffset);
+ fFound=TRUE;
+ }
+ else {
+ /* first instance */
+ pPerfInstance=(PERF_INSTANCE_DEFINITION*)((BYTE*)pPerfObj+pPerfObj->DefinitionLength);
+ for(lCount=0;lCount<(pPerfObj->NumInstances);++lCount) {
+ pPerfCounterBlock=(PERF_COUNTER_BLOCK*)((BYTE*)pPerfInstance+pPerfInstance->ByteLength);
+ if(!lstrcmpiW(pwszInstanceName,(WCHAR*)((BYTE*)pPerfInstance+pPerfInstance->NameOffset)) || !pwszInstanceName) {
+ liCurrentCounterValue=*(LARGE_INTEGER*)((BYTE*)pPerfCounterBlock+pPerfCounter->CounterOffset);
+ fFound=TRUE;
+ break;
+ }
+ /* next instance */
+ pPerfInstance=(PPERF_INSTANCE_DEFINITION)((BYTE*)pPerfCounterBlock+pPerfCounterBlock->ByteLength);
+ }
+ }
+ break;
+ }
+ /* next counter */
+ pPerfCounter=(PERF_COUNTER_DEFINITION*)((BYTE*)pPerfCounter+pPerfCounter->ByteLength);
+ }
+ break;
+ }
+ /* next object */
+ pPerfObj=(PERF_OBJECT_TYPE*)((BYTE*)pPerfObj+pPerfObj->TotalByteLength);
+ }
+ if(!fFound) break;
+
+ /* calc val from data, we need two samplings
+ * counter type: PERF_100NSEC_TIMER_INV
+ * calc: time base=100Ns, value=100*(1-(data_diff)/(100NsTime_diff)) */
+ if(!fIsFirst) {
+ nCpuUsage=(BYTE)((1.0-(Li2Double(liCurrentCounterValue)-Li2Double(liPrevCounterValue))/(Li2Double(pPerfData->PerfTime100nSec)-Li2Double(liPrevPerfTime100nSec)))*100.0+0.5);
+ if(!CallBackAndWait(param,nCpuUsage)) break;
+ }
+ else fIsFirst=FALSE;
+ /* store current sampling for next */
+ CopyMemory(&liPrevCounterValue,&liCurrentCounterValue,sizeof(LARGE_INTEGER));
+ CopyMemory(&liPrevPerfTime100nSec,&pPerfData->PerfTime100nSec,sizeof(LARGE_INTEGER));
+ }
+
+ /* uninit */
+ if(pPerfData) mir_free(pPerfData);
+ if(fSwitched) WinNT_PerfStatsSwitch(_T("PerfOS"),TRUE);
+
+ /* return error for PollCpuUsage() if never succeeded */
+ if(param->hFirstEvent!=NULL) SetEvent(param->hFirstEvent);
+ mir_free(param);
+}
+
+/************************* Start Thread *******************************/
+
+// returns poll thread id on success
+DWORD PollCpuUsage(CPUUSAGEAVAILPROC pfnDataAvailProc,LPARAM lParam,DWORD dwDelayMillis)
+{
+ struct CpuUsageThreadParams *param;
+ DWORD idThread=0;
+ HANDLE hFirstEvent;
+
+ /* init params */
+ param=(struct CpuUsageThreadParams*)mir_alloc(sizeof(struct CpuUsageThreadParams));
+ if(param==NULL) return FALSE;
+ param->dwDelayMillis=dwDelayMillis;
+ param->pfnDataAvailProc=pfnDataAvailProc;
+ param->lParam=lParam;
+ param->pidThread=&idThread;
+ param->hFirstEvent=hFirstEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
+ if(hFirstEvent==NULL) {
+ mir_free(param);
+ return 0;
+ }
+ /* start thread */
+ if((int)mir_forkthread(WinNT_PollThread, param) != -1)
+ WaitForSingleObject(hFirstEvent,INFINITE); /* wait for first success */
+ else
+ mir_free(param); /* thread not started */
+ CloseHandle(hFirstEvent);
+ return idThread;
+}
diff --git a/plugins/AutoShutdown/src/cpuusage.h b/plugins/AutoShutdown/src/cpuusage.h
new file mode 100644
index 0000000000..681a2c8213
--- /dev/null
+++ b/plugins/AutoShutdown/src/cpuusage.h
@@ -0,0 +1,24 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Start Thread */
+typedef BOOL (CALLBACK* CPUUSAGEAVAILPROC)(BYTE nCpuUsage,LPARAM lParam);
+DWORD PollCpuUsage(CPUUSAGEAVAILPROC pfnDataAvailProc,LPARAM lParam,DWORD dwDelayMillis);
diff --git a/plugins/AutoShutdown/src/frame.cpp b/plugins/AutoShutdown/src/frame.cpp
new file mode 100644
index 0000000000..425edb3831
--- /dev/null
+++ b/plugins/AutoShutdown/src/frame.cpp
@@ -0,0 +1,642 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Show Frame */
+extern HINSTANCE hInst;
+static HWND hwndCountdownFrame;
+static WORD hFrame;
+/* Misc */
+static HANDLE hHookModulesLoaded;
+
+/************************* Helpers ************************************/
+
+#define FRAMEELEMENT_BAR 1
+#define FRAMEELEMENT_BKGRND 2
+#define FRAMEELEMENT_TEXT 3
+static COLORREF GetDefaultColor(BYTE id)
+{
+ switch(id) {
+ case FRAMEELEMENT_BAR:
+ return RGB(250,0,0); /* same color as used on header icon */
+ case FRAMEELEMENT_BKGRND:
+ return (COLORREF)DBGetContactSettingDword(NULL,"CLC","BkColour",CLCDEFAULT_BKCOLOUR);
+ case FRAMEELEMENT_TEXT:
+ return GetSysColor(COLOR_WINDOWTEXT);
+ }
+ return 0; /* never happens */
+}
+
+static LOGFONT* GetDefaultFont(LOGFONT *lf)
+{
+ NONCLIENTMETRICS ncm;
+ ZeroMemory(&ncm,sizeof(ncm));
+ ncm.cbSize=sizeof(ncm);
+ if(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,ncm.cbSize,&ncm,0)) {
+ *lf=ncm.lfStatusFont;
+ return lf;
+ }
+ return (LOGFONT*)NULL;
+}
+
+static HICON SetFrameTitleIcon(WORD hFrame,HICON hNewIcon)
+{
+ HICON hPrevIcon;
+ hPrevIcon=(HICON)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_ICON,hFrame),0);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_ICON,hFrame),(LPARAM)hNewIcon);
+ if((int)hPrevIcon==-1) return (HICON)NULL;
+ return hPrevIcon;
+}
+
+static LRESULT CALLBACK ProgressBarSubclassProc(HWND hwndProgress,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ return SendMessage(GetParent(hwndProgress),msg,wParam,lParam);
+ }
+ return CallWindowProc((WNDPROC)GetWindowLongPtr(hwndProgress, GWLP_USERDATA), hwndProgress, msg, wParam, lParam);
+}
+
+/************************* Window Class *******************************/
+
+#define COUNTDOWNFRAME_CLASS _T("AutoShutdownCountdown")
+
+/* Data */
+struct CountdownFrameWndData { /* sizeof=57, max cbClsExtra=40 on Win32 */
+ time_t countdown,settingLastTime;
+ HANDLE hHookColorsChanged,hHookFontsChanged,hHookIconsChanged;
+ HWND hwndIcon,hwndProgress,hwndDesc,hwndTime,hwndToolTip;
+ HBRUSH hbrBackground;
+ COLORREF clrBackground,clrText;
+ HFONT hFont;
+ WORD fTimeFlags;
+ BYTE flags;
+};
+
+/* Flags */
+#define FWPDF_PAUSED 0x01
+#define FWPDF_PAUSEDSHOWN 0x02
+#define FWPDF_COUNTDOWNINVALID 0x04
+#define FWPDF_TIMEISCLIPPED 0x08
+
+/* Menu Items */
+#define MENUITEM_STOPCOUNTDOWN 1
+#define MENUITEM_PAUSECOUNTDOWN 2
+
+/* Messages */
+#define M_REFRESH_COLORS (WM_USER+0)
+#define M_REFRESH_ICONS (WM_USER+1)
+#define M_REFRESH_FONTS (WM_USER+2)
+#define M_SET_COUNTDOWN (WM_USER+3)
+#define M_UPDATE_COUNTDOWN (WM_USER+4)
+#define M_CHECK_CLIPPED (WM_USER+5)
+#define M_CLOSE_COUNTDOWN (WM_USER+6)
+#define M_PAUSE_COUNTDOWN (WM_USER+7)
+
+static LRESULT CALLBACK FrameWndProc(HWND hwndFrame,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ struct CountdownFrameWndData *dat=(struct CountdownFrameWndData*)GetWindowLongPtr(hwndFrame, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_NCCREATE: /* init window data */
+ dat=(struct CountdownFrameWndData*)mir_calloc(sizeof(*dat));
+ SetWindowLongPtr(hwndFrame, GWLP_USERDATA, (LONG)dat);
+ if(dat==NULL) return FALSE; /* creation failed */
+ dat->fTimeFlags=*(WORD*)((CREATESTRUCT*)lParam)->lpCreateParams;
+ dat->flags=FWPDF_COUNTDOWNINVALID;
+ break;
+ case WM_CREATE: /* create childs */
+ { CREATESTRUCT *params=(CREATESTRUCT*)lParam;
+ dat->hwndIcon=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ NULL,
+ WS_CHILD|WS_VISIBLE|SS_ICON|SS_CENTERIMAGE|SS_NOTIFY,
+ 3, 0,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ dat->hwndProgress=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ PROGRESS_CLASS,
+ (dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),
+ WS_CHILD|WS_VISIBLE|PBS_SMOOTH,
+ GetSystemMetrics(SM_CXICON)+5,
+ 5, 90,
+ (GetSystemMetrics(SM_CXICON)/2)-5,
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndProgress==NULL) return -1; /* creation failed, calls WM_DESTROY */
+ SendMessage(dat->hwndProgress,PBM_SETSTEP,(WPARAM)1,0);
+ SetWindowLongPtr(dat->hwndProgress, GWLP_USERDATA, SetWindowLongPtr(dat->hwndProgress, GWLP_WNDPROC, (LONG)ProgressBarSubclassProc));
+ dat->hwndDesc=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ (dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),
+ WS_CHILD|WS_VISIBLE|SS_LEFTNOWORDWRAP|SS_NOTIFY,
+ GetSystemMetrics(SM_CXICON)+5,
+ (GetSystemMetrics(SM_CXICON)/2),
+ 75,
+ (GetSystemMetrics(SM_CXICON)/2),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ dat->hwndTime=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ NULL, /* hh:mm:ss */
+ WS_CHILD|WS_VISIBLE|SS_RIGHT|SS_NOTIFY|SS_ENDELLIPSIS,
+ (GetSystemMetrics(SM_CXICON)+80),
+ (GetSystemMetrics(SM_CXICON)/2),
+ 35,
+ (GetSystemMetrics(SM_CXICON)/2),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndTime==NULL) return -1; /* creation failed, calls WM_DESTROY */
+ /* create tooltips */
+ if(IsWinVer98Plus() || IsWinVer2000Plus()) {
+ TTTOOLINFO ti;
+ dat->hwndToolTip=CreateWindowEx(WS_EX_TOPMOST,
+ TOOLTIPS_CLASS,
+ NULL,
+ WS_POPUP|TTS_ALWAYSTIP|TTS_NOPREFIX,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndToolTip!=NULL) {
+ SetWindowPos(dat->hwndToolTip,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize=sizeof(ti);
+ ti.hwnd=hwndFrame;
+ ti.uFlags=TTF_IDISHWND|TTF_SUBCLASS|TTF_TRANSPARENT;
+ ti.lpszText=LPSTR_TEXTCALLBACK; /* commctl 4.70+ */
+ ti.uId=(UINT)dat->hwndTime; /* in-place tooltip */
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ ti.uFlags&=~TTF_TRANSPARENT;
+ ti.uId=(UINT)dat->hwndProgress;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ if(dat->hwndDesc!=NULL) {
+ ti.uId=(UINT)dat->hwndDesc;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ }
+ if(dat->hwndIcon!=NULL) {
+ ti.uId=(UINT)dat->hwndIcon;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ }
+ }
+ }
+ /* init layout */
+ dat->hHookColorsChanged=HookEventMessage(ME_COLOUR_RELOAD,hwndFrame,M_REFRESH_COLORS);
+ dat->hHookFontsChanged=HookEventMessage(ME_FONT_RELOAD,hwndFrame,M_REFRESH_FONTS);
+ dat->hHookIconsChanged=HookEventMessage(ME_SKIN2_ICONSCHANGED,hwndFrame,M_REFRESH_ICONS);
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_FONTS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_ICONS,0,0);
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ if(!SetTimer(hwndFrame,1,1000,NULL)) return -1; /* creation failed, calls WM_DESTROY */
+ return 0;
+ }
+ case WM_DESTROY:
+ { HICON hIcon;
+ if(dat==NULL) return 0;
+ UnhookEvent(dat->hHookColorsChanged);
+ UnhookEvent(dat->hHookFontsChanged);
+ UnhookEvent(dat->hHookIconsChanged);
+ /* other childs are destroyed automatically */
+ if(dat->hwndToolTip!=NULL) DestroyWindow(dat->hwndToolTip);
+ hIcon=(HICON)SendMessage(dat->hwndIcon,STM_SETIMAGE,IMAGE_ICON,(LPARAM)NULL);
+ IcoLib_ReleaseIcon(hIcon); /* does NULL check */
+ break;
+ }
+ case WM_NCDESTROY:
+ if(dat==NULL) return 0;
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ if(dat->hbrBackground!=NULL) DeleteObject(dat->hbrBackground);
+ mir_free(dat);
+ SetWindowLongPtr(hwndFrame, GWLP_USERDATA, (LONG)NULL);
+ break;
+ case WM_SIZE:
+ { RECT rc;
+ LONG width,height;
+ HDWP hdwp;
+ UINT defflg=SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE;
+ SetRect(&rc,0,0,LOWORD(lParam),HIWORD(lParam)); /* width,height */
+ /* workaround: reduce flickering of frame in clist */
+ InvalidateRect(hwndFrame,&rc,FALSE);
+ hdwp=BeginDeferWindowPos(3);
+ /* progress */
+ width=rc.right-GetSystemMetrics(SM_CXICON)-10;
+ height=rc.bottom-(GetSystemMetrics(SM_CYICON)/2)-5;
+ hdwp=DeferWindowPos(hdwp,dat->hwndProgress,NULL,0,0,width,height,SWP_NOMOVE|defflg);
+ /* desc */
+ if(dat->hwndDesc!=NULL) hdwp=DeferWindowPos(hdwp,dat->hwndDesc,NULL,GetSystemMetrics(SM_CXICON)+5,5+height,0,0,SWP_NOSIZE|defflg);
+ /* time */
+ hdwp=DeferWindowPos(hdwp,dat->hwndTime,NULL,GetSystemMetrics(SM_CXICON)+85,5+height,width-80,(GetSystemMetrics(SM_CXICON)/2),defflg);
+ EndDeferWindowPos(hdwp);
+ PostMessage(hwndFrame,M_CHECK_CLIPPED,0,0);
+ return 0;
+ }
+ case M_REFRESH_COLORS:
+ { COLORREF clrBar;
+ if(FontService_GetColor(TranslateT("Automatic Shutdown"),TranslateT("Progress Bar"),&clrBar))
+ clrBar=GetDefaultColor(FRAMEELEMENT_BAR);
+ if(FontService_GetColor(TranslateT("Automatic Shutdown"),TranslateT("Background"),&dat->clrBackground))
+ dat->clrBackground=GetDefaultColor(FRAMEELEMENT_BKGRND);
+ if(dat->hbrBackground!=NULL) DeleteObject(dat->hbrBackground);
+ dat->hbrBackground=CreateSolidBrush(dat->clrBackground);
+ SendMessage(dat->hwndProgress,PBM_SETBARCOLOR,0,(LPARAM)clrBar);
+ SendMessage(dat->hwndProgress,PBM_SETBKCOLOR,0,(LPARAM)dat->clrBackground);
+ InvalidateRect(hwndFrame,NULL,TRUE);
+ return 0;
+ }
+ case M_REFRESH_ICONS:
+ if(dat->hwndIcon!=NULL)
+ IcoLib_ReleaseIcon((HICON)SendMessage(dat->hwndIcon,STM_SETIMAGE,IMAGE_ICON,(LPARAM)IcoLib_GetIcon("AutoShutdown_Header")));
+ if(hFrame) /* refresh frame title icon */
+ IcoLib_ReleaseIcon(SetFrameTitleIcon(hFrame,IcoLib_GetIcon("AutoShutdown_Active")));
+ return 0;
+ case M_REFRESH_FONTS:
+ { LOGFONT lf;
+ if(!FontService_GetFont(TranslateT("Automatic Shutdown"),TranslateT("Countdown on Frame"),&dat->clrText,&lf)) {
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ dat->hFont=CreateFontIndirect(&lf);
+ }
+ else {
+ dat->clrText=GetDefaultColor(FRAMEELEMENT_TEXT);
+ if(GetDefaultFont(&lf)!=NULL) {
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ dat->hFont=CreateFontIndirect(&lf);
+ }
+ }
+ if(dat->hwndDesc!=NULL)
+ SendMessage(dat->hwndDesc,WM_SETFONT,(WPARAM)dat->hFont,FALSE);
+ SendMessage(dat->hwndTime,WM_SETFONT,(WPARAM)dat->hFont,FALSE);
+ InvalidateRect(hwndFrame,NULL,FALSE);
+ return 0;
+ }
+ case WM_SYSCOLORCHANGE:
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ break;
+ case WM_SETTINGCHANGE: /* colors depend on windows settings */
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_FONTS,0,0);
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ RedrawWindow(hwndFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ break;
+ case WM_TIMECHANGE: /* windows system clock changed */
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ PostMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ break;
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORSTATIC:
+ SetTextColor((HDC)wParam,dat->clrText);
+ SetBkColor((HDC)wParam,dat->clrBackground);
+ return (BOOL)dat->hbrBackground;
+ case WM_ERASEBKGND:
+ { RECT rc;
+ if(dat->hbrBackground!=NULL && GetClientRect(hwndFrame,&rc)) {
+ FillRect((HDC)wParam,&rc,dat->hbrBackground);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ case M_SET_COUNTDOWN:
+ if(dat->fTimeFlags&SDWTF_ST_TIME) {
+ dat->settingLastTime=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","TimeStamp",SETTING_TIMESTAMP_DEFAULT);
+ dat->countdown=time(NULL);
+ if(dat->settingLastTime>dat->countdown) dat->countdown=dat->settingLastTime-dat->countdown;
+ else dat->countdown=0;
+ }
+ else if(dat->flags&FWPDF_COUNTDOWNINVALID) {
+ dat->countdown=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","Countdown",SETTING_COUNTDOWN_DEFAULT);
+ dat->countdown*=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","CountdownUnit",SETTING_COUNTDOWNUNIT_DEFAULT);
+ }
+ dat->flags&=~FWPDF_COUNTDOWNINVALID;
+ /* commctl 4.70+, Win95: 1-100 will work fine (wrap around) */
+ SendMessage(dat->hwndProgress,PBM_SETRANGE32,(WPARAM)0,(LPARAM)dat->countdown);
+ return 0;
+ case WM_TIMER:
+ if(dat==NULL) return 0;
+ if(dat->countdown!=0 && !(dat->flags&FWPDF_COUNTDOWNINVALID) && !(dat->flags&FWPDF_PAUSED)) {
+ dat->countdown--;
+ PostMessage(dat->hwndProgress,PBM_STEPIT,0,0);
+ }
+ if(IsWindowVisible(hwndFrame)) PostMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ if(dat->countdown==0) {
+ SendMessage(hwndFrame,M_CLOSE_COUNTDOWN,0,0);
+ ServiceShutdown(0,TRUE);
+ ServiceStopWatcher(0,0);
+ }
+ return 0;
+ case WM_SHOWWINDOW:
+ /* the text is kept unchanged while hidden */
+ if((BOOL)wParam) SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ break;
+ case M_UPDATE_COUNTDOWN:
+ if(dat->flags&FWPDF_PAUSED && !(dat->flags&FWPDF_PAUSEDSHOWN)) {
+ SetWindowText(dat->hwndTime,TranslateT("Paused"));
+ dat->flags|=FWPDF_PAUSEDSHOWN;
+ }
+ else {
+ TCHAR szOutput[256];
+ if(dat->fTimeFlags&SDWTF_ST_TIME)
+ GetFormatedDateTime(szOutput,SIZEOF(szOutput),dat->settingLastTime,TRUE);
+ else GetFormatedCountdown(szOutput,SIZEOF(szOutput),dat->countdown);
+ SetWindowText(dat->hwndTime,szOutput);
+ PostMessage(hwndFrame,M_CHECK_CLIPPED,0,0);
+ /* update tooltip text (if shown) */
+ if(dat->hwndToolTip!=NULL && !(dat->flags&FWPDF_PAUSED)) {
+ TTTOOLINFO ti;
+ ti.cbSize=sizeof(ti);
+ if(SendMessage(dat->hwndToolTip,TTM_GETCURRENTTOOL,0,(LPARAM)&ti) && (HWND)ti.uId!=dat->hwndIcon)
+ SendMessage(dat->hwndToolTip,TTM_UPDATE,0,0);
+ } else dat->flags&=~FWPDF_PAUSEDSHOWN;
+ }
+ return 0;
+ case M_CLOSE_COUNTDOWN:
+ KillTimer(hwndFrame,1);
+ dat->countdown=0;
+ dat->flags&=~FWPDF_PAUSED;
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ dat->flags|=FWPDF_COUNTDOWNINVALID;
+ /* step up to upper range */
+ SendMessage(dat->hwndProgress,PBM_SETPOS,SendMessage(dat->hwndProgress,PBM_GETRANGE,FALSE,0),0);
+ SetWindowLongPtr(dat->hwndProgress, GWL_STYLE, GetWindowLongPtr(dat->hwndProgress, GWL_STYLE) | PBM_SETMARQUEE);
+ SendMessage(dat->hwndProgress,PBM_SETMARQUEE,TRUE,10); /* marquee for rest of time */
+ return 0;
+ case M_PAUSE_COUNTDOWN:
+ if(dat->flags&FWPDF_PAUSED) {
+ /* unpause */
+ dat->flags&=~(FWPDF_PAUSED|FWPDF_PAUSEDSHOWN);
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ SendMessage(dat->hwndProgress,PBM_SETSTATE,PBST_NORMAL,0); /* WinVista+ */
+ }
+ else {
+ /* pause */
+ dat->flags|=FWPDF_PAUSED;
+ SendMessage(dat->hwndProgress,PBM_SETSTATE,PBST_PAUSED,0); /* WinVista+ */
+ }
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ return 0;
+ case WM_CONTEXTMENU:
+ { HMENU hContextMenu;
+ POINT pt;
+ if(dat->flags&FWPDF_COUNTDOWNINVALID) return 0;
+ POINTSTOPOINT(pt,MAKEPOINTS(lParam));
+ if(pt.x==-1 && pt.y==-1) { /* invoked by keyboard */
+ RECT rc;
+ /* position in middle above rect */
+ if(!GetWindowRect(hwndFrame, &rc)) return 0;
+ pt.x=rc.left+((int)(rc.right-rc.left)/2);
+ pt.y=rc.top+((int)(rc.bottom-rc.top)/2);
+ }
+ hContextMenu=CreatePopupMenu();
+ if(hContextMenu!=NULL) {
+ AppendMenu(hContextMenu,MF_STRING,MENUITEM_PAUSECOUNTDOWN,(dat->flags&FWPDF_PAUSED)?TranslateT("&Unpause Countdown"):TranslateT("&Pause Countdown"));
+ SetMenuDefaultItem(hContextMenu,MENUITEM_PAUSECOUNTDOWN,FALSE);
+ AppendMenu(hContextMenu,MF_STRING,MENUITEM_STOPCOUNTDOWN,TranslateT("&Cancel Countdown"));
+ TrackPopupMenuEx(hContextMenu,TPM_LEFTALIGN|TPM_TOPALIGN|TPM_HORPOSANIMATION|TPM_VERPOSANIMATION|TPM_RIGHTBUTTON,pt.x,pt.y,hwndFrame,NULL);
+ DestroyMenu(hContextMenu);
+ }
+ return 0;
+ }
+ case WM_LBUTTONDBLCLK:
+ if(!(dat->flags&FWPDF_COUNTDOWNINVALID))
+ SendMessage(hwndFrame,M_PAUSE_COUNTDOWN,0,0);
+ return 0;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case MENUITEM_STOPCOUNTDOWN:
+ /* close only countdown window when other watcher types running */
+ if(dat->fTimeFlags&~(SDWTF_SPECIFICTIME|SDWTF_ST_MASK))
+ CloseCountdownFrame(); /* something else is running */
+ else ServiceStopWatcher(0,0); /* calls CloseCountdownFrame() */
+ return 0;
+ case MENUITEM_PAUSECOUNTDOWN:
+ SendMessage(hwndFrame,M_PAUSE_COUNTDOWN,0,0);
+ return 0;
+ }
+ break;
+ case M_CHECK_CLIPPED: /* for in-place tooltip on dat->hwndTime */
+ { RECT rc;
+ HDC hdc;
+ SIZE size;
+ HFONT hFontPrev=NULL;
+ TCHAR szOutput[256];
+ dat->flags&=~FWPDF_TIMEISCLIPPED;
+ if(GetWindowText(dat->hwndTime,szOutput,SIZEOF(szOutput)-1))
+ if(GetClientRect(dat->hwndTime,&rc)) {
+ hdc=GetDC(dat->hwndTime);
+ if(hdc!=NULL) {
+ if(dat->hFont!=NULL)
+ hFontPrev = (HFONT)SelectObject(hdc,dat->hFont);
+ if(GetTextExtentPoint32(hdc,szOutput,lstrlen(szOutput),&size))
+ if(size.cx>=(rc.right-rc.left))
+ dat->flags&=FWPDF_TIMEISCLIPPED;
+ if(dat->hFont!=NULL)
+ SelectObject(hdc,hFontPrev);
+ ReleaseDC(dat->hwndTime,hdc);
+ }
+ }
+ return 0;
+ }
+ case WM_NOTIFY:
+ if(((NMHDR*)lParam)->hwndFrom==dat->hwndToolTip)
+ switch(((NMHDR*)lParam)->code) {
+ case TTN_SHOW: /* 'in-place' tooltip on dat->hwndTime */
+ if(dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam==dat->hwndTime && IsWinVer2000Plus()) {
+ RECT rc;
+ if(GetWindowRect(dat->hwndTime,&rc)) {
+ SetWindowLongPtr(dat->hwndToolTip, GWL_STYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_STYLE) | TTS_NOANIMATE);
+ SetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE) | WS_EX_TRANSPARENT);
+ SendMessage(dat->hwndToolTip,TTM_ADJUSTRECT,TRUE,(LPARAM)&rc);
+ SetWindowPos(dat->hwndToolTip,NULL,rc.left,rc.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+ return TRUE; /* self-defined position */
+ }
+ }
+ SetWindowLongPtr(dat->hwndToolTip, GWL_STYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_STYLE) & (~TTS_NOANIMATE));
+ SetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE) & (~WS_EX_TRANSPARENT));
+ return 0;
+ case TTN_POP:
+ /* workaround #5: frame does not get redrawn after
+ * in-place tooltip hidden on dat->hwndTime */
+ RedrawWindow(hwndCountdownFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ return 0;
+ case TTN_NEEDTEXT:
+ { NMTTDISPINFO *ttdi=(NMTTDISPINFO*)lParam;
+ if(dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam==dat->hwndTime) {
+ if(GetWindowText(dat->hwndTime,ttdi->szText,SIZEOF(ttdi->szText)-1))
+ ttdi->lpszText=ttdi->szText;
+ }
+ else if((HWND)wParam==dat->hwndIcon)
+ ttdi->lpszText=TranslateT("Automatic Shutdown");
+ else {
+ TCHAR szTime[SIZEOF(ttdi->szText)];
+ if(dat->fTimeFlags&SDWTF_ST_TIME)
+ GetFormatedDateTime(szTime,SIZEOF(szTime),dat->settingLastTime,FALSE);
+ else GetFormatedCountdown(szTime,SIZEOF(szTime),dat->countdown);
+ mir_sntprintf(ttdi->szText,SIZEOF(ttdi->szText),_T("%s %s"),(dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),szTime);
+ ttdi->lpszText=ttdi->szText;
+ }
+ return 0;
+ }
+ }
+ break;
+ }
+ return DefWindowProc(hwndFrame,msg,wParam,lParam);
+}
+
+/************************* Show Frame *********************************/
+
+void ShowCountdownFrame(WORD fTimeFlags)
+{
+ hwndCountdownFrame=CreateWindowEx(WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT,
+ COUNTDOWNFRAME_CLASS,
+ NULL,
+ WS_CHILD|WS_TABSTOP,
+ 0, 0,
+ GetSystemMetrics(SM_CXICON)+103,
+ GetSystemMetrics(SM_CYICON)+2,
+ (HWND)CallService(MS_CLUI_GETHWND,0,0),
+ NULL,
+ hInst,
+ &fTimeFlags);
+ if(hwndCountdownFrame==NULL) return;
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ CLISTFrame clf;
+ ZeroMemory(&clf,sizeof(clf));
+ clf.cbSize=sizeof(clf);
+ clf.hIcon=IcoLib_GetIcon("AutoShutdown_Active"); /* CListFrames does not make a copy */
+ clf.align=alBottom;
+ clf.height=GetSystemMetrics(SM_CYICON);
+ clf.Flags=F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_SKINNED;
+ clf.name=Translate("AutoShutdown");
+ clf.TBname=Translate("Automatic Shutdown");
+ clf.hWnd=hwndCountdownFrame;
+ hFrame=(WORD)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&clf,0);
+ if(hFrame) {
+ ShowWindow(hwndCountdownFrame,SW_SHOW);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,hFrame),(LPARAM)clf.name);
+ /* HACKS TO FIX CLUI FRAMES:
+ * *** why is CLUIFrames is horribly buggy??! *** date: sept 2005, nothing changed until sept 2006
+ * workaround #1: MS_CLIST_FRAMES_REMOVEFRAME does not finish with destroy cycle (clist_modern, clist_nicer crashes) */
+ SendMessage((HWND)CallService(MS_CLUI_GETHWND,0,0),WM_SIZE,0,0);
+ /* workaround #2: drawing glitch after adding a frame (frame positioned wrongly when hidden) */
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,hFrame,FU_FMPOS|FU_FMREDRAW);
+ /* workaround #3: MS_CLIST_FRAMES_SETFRAMEOPTIONS does cause redrawing problems */
+ if(!(CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),0)&F_VISIBLE))
+ CallService(MS_CLIST_FRAMES_SHFRAME,hFrame,0);
+ /* workaround #4: MS_CLIST_FRAMES_SHFRAME does cause redrawing problems when frame was hidden */
+ RedrawWindow(hwndCountdownFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ /* workaround #5: for in-place tooltip TTN_POP
+ * workaround #6 and #7: see CloseCountdownFrame() */
+ }
+ }
+}
+
+void CloseCountdownFrame(void)
+{
+ if(hwndCountdownFrame!=NULL) {
+ SendMessage(hwndCountdownFrame,M_CLOSE_COUNTDOWN,0,0);
+ if(hFrame) {
+ IcoLib_ReleaseIcon(SetFrameTitleIcon(hFrame,NULL));
+ /* HACKS TO FIX CLUIFrames:
+ * workaround #6: MS_CLIST_FRAMES_REMOVEFRAME does not finish with
+ * destroy cycle (clist_modern, clist_nicer crashes) */
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),(LPARAM)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),0)&(~F_VISIBLE));
+ #if !defined(_DEBUG)
+ /* workaround #7: MS_CLIST_FRAMES_REMOVEFRAME crashes after two calls
+ * clist_nicer crashes after some calls (bug in it) */
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME,hFrame,0);
+ #endif
+ }
+ else DestroyWindow(hwndCountdownFrame);
+ hwndCountdownFrame=NULL;
+ hFrame=0;
+ }
+
+}
+
+/************************* Misc ***************************************/
+
+static int FrameModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ LOGFONT lf;
+ COLORREF clr;
+ HMODULE hUxThemeDLL;
+ BOOL (WINAPI *pfnIsThemeActive)(VOID);
+ /* built-in font module is not available before this hook */
+ clr=GetDefaultColor(FRAMEELEMENT_TEXT);
+ FontService_RegisterFont("AutoShutdown","CountdownFont",TranslateT("Automatic Shutdown"),TranslateT("Countdown on Frame"),0,FALSE,GetDefaultFont(&lf),clr);
+ clr=GetDefaultColor(FRAMEELEMENT_BKGRND);
+ FontService_RegisterColor("AutoShutdown","BkgColor",TranslateT("Automatic Shutdown"),TranslateT("Background"),clr);
+ /* progressbar color can only be changed in windows classic theme */
+ /* FIXME: should be registered/unregistered on WM_THEMECHANGED/ME_OPT_INITIALISE msg,
+ * currently not possible as no such font service exists */
+ hUxThemeDLL=LoadLibraryA("UXTHEME"); /* all ascii */
+ *(PROC*)&pfnIsThemeActive=(hUxThemeDLL!=NULL)?GetProcAddress(hUxThemeDLL,"IsThemeActive"):NULL;
+ if(pfnIsThemeActive==NULL || !pfnIsThemeActive()) {
+ /* progressbar color can only be changed with classic theme */
+ clr=GetDefaultColor(FRAMEELEMENT_BAR);
+ FontService_RegisterColor("AutoShutdown","ProgressColor",TranslateT("Automatic Shutdown"),TranslateT("Progress Bar"),clr);
+ }
+ if(hUxThemeDLL!=NULL) FreeLibrary(hUxThemeDLL);
+ }
+ return 0;
+}
+
+int InitFrame(void)
+{
+ WNDCLASSEX wcx;
+ ZeroMemory(&wcx,sizeof(wcx));
+ wcx.cbSize =sizeof(wcx);
+ wcx.style =CS_DBLCLKS|CS_PARENTDC;
+ wcx.lpfnWndProc =FrameWndProc;
+ wcx.hInstance =hInst;
+ wcx.hCursor =(HCURSOR)LoadImage(NULL,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
+ wcx.lpszClassName =COUNTDOWNFRAME_CLASS;
+ if(!RegisterClassEx(&wcx)) return 1;
+
+ hwndCountdownFrame=NULL;
+ hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,FrameModulesLoaded);
+ return 0;
+}
+
+void UninitFrame(void)
+{
+ /* frame closed by UninitWatcher() */
+ UnregisterClass(COUNTDOWNFRAME_CLASS,hInst); /* fails if window still exists */
+ UnhookEvent(hHookModulesLoaded);
+}
diff --git a/plugins/AutoShutdown/src/frame.h b/plugins/AutoShutdown/src/frame.h
new file mode 100644
index 0000000000..1b0bffdafd
--- /dev/null
+++ b/plugins/AutoShutdown/src/frame.h
@@ -0,0 +1,28 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Show Frame */
+void ShowCountdownFrame(WORD fTimeFlags);
+void CloseCountdownFrame(void);
+
+/* Misc */
+int InitFrame(void);
+void UninitFrame(void); \ No newline at end of file
diff --git a/plugins/AutoShutdown/src/main.cpp b/plugins/AutoShutdown/src/main.cpp
new file mode 100644
index 0000000000..31b4bbb7d7
--- /dev/null
+++ b/plugins/AutoShutdown/src/main.cpp
@@ -0,0 +1,132 @@
+/*
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+#include "version.h"
+
+HINSTANCE hInst;
+static HANDLE hHookModulesLoaded;
+HANDLE hActiveIcon,hInactiveIcon;
+int hLangpack;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "AutoShutdown",
+ PLUGIN_VERSION,
+ "Adds the possibility to shutdown the computer when a specified event occurs.", /* autotranslated */
+ "H. Herkenrath",
+ "hrathh@users.sourceforge.net", /* @ will be set later */
+ "© 2004-2007 H. Herkenrath",
+ "http://addons.miranda-im.org/details.php?action=viewfile&id=3056",
+ UNICODE_AWARE,
+ // {9DE24579-5C5C-49aa-80E8-4D38E4344E63}
+ {0x9de24579,0x5c5c,0x49aa,{0x80,0xe8,0x4d,0x38,0xe4,0x34,0x4e,0x63}},
+};
+
+static const MUUID interfaces[]={MIID_SHUTDOWN,MIID_LAST};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, VOID *pReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+static void InstallFile(const TCHAR *pszFileName,const TCHAR *pszDestSubDir)
+{
+ TCHAR szFileFrom[MAX_PATH+1],szFileTo[MAX_PATH+1],*p;
+ HANDLE hFile;
+
+ if(!GetModuleFileName(hInst,szFileFrom,SIZEOF(szFileFrom)-lstrlen(pszFileName)))
+ return;
+ p=_tcsrchr(szFileFrom,_T('\\'));
+ if(p!=NULL) *(++p)=0;
+ lstrcat(szFileFrom,pszFileName); /* buffer safe */
+
+ hFile=CreateFile(szFileFrom,0,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
+ if(hFile==INVALID_HANDLE_VALUE) return;
+ CloseHandle(hFile);
+
+ if(!GetModuleFileName(NULL,szFileTo,SIZEOF(szFileTo)-lstrlen(pszDestSubDir)-lstrlen(pszFileName)))
+ return;
+ p=_tcsrchr(szFileTo,_T('\\'));
+ if(p!=NULL) *(++p)=0;
+ lstrcat(szFileTo,pszDestSubDir); /* buffer safe */
+ CreateDirectory(szFileTo,NULL);
+ lstrcat(szFileTo,pszFileName); /* buffer safe */
+
+ if(!MoveFile(szFileFrom,szFileTo) && GetLastError()==ERROR_ALREADY_EXISTS) {
+ DeleteFile(szFileTo);
+ MoveFile(szFileFrom,szFileTo);
+ }
+}
+
+static int ShutdownModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ if(ServiceExists("DBEditorpp/RegisterSingleModule"))
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)"AutoShutdown",0);
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+ mir_getLP(&pluginInfo);
+ INITCOMMONCONTROLSEX icc;
+ icc.dwSize=sizeof(icc);
+ icc.dwICC=ICC_DATE_CLASSES|ICC_UPDOWN_CLASS|ICC_PROGRESS_CLASS;
+ if(!InitCommonControlsEx(&icc)) return 1;
+
+ if(InitFrame()) return 1; /* before icons */
+
+ /* shared */
+ IcoLib_AddIconRes("AutoShutdown_Header",TranslateT("Automatic Shutdown"),TranslateT("Header"),hInst,IDI_HEADER,TRUE);
+ hActiveIcon=IcoLib_AddIconRes("AutoShutdown_Active",TranslateT("Automatic Shutdown"),TranslateT("Active"),hInst,IDI_ACTIVE,FALSE);
+ hInactiveIcon=IcoLib_AddIconRes("AutoShutdown_Inactive",TranslateT("Automatic Shutdown"),TranslateT("Inactive"),hInst,IDI_INACTIVE,FALSE);
+
+ InitShutdownSvc();
+ InitWatcher(); /* before InitSettingsDlg() */
+ InitSettingsDlg();
+ InitOptions();
+
+ hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ShutdownModulesLoaded);
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnhookEvent(hHookModulesLoaded);
+
+ UninitOptions();
+ UninitSettingsDlg(); /* before UninitWatcher() */
+ UninitWatcher(); /* before UninitFrame() */
+ UninitFrame();
+ UninitShutdownSvc();
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/AutoShutdown/src/options.cpp b/plugins/AutoShutdown/src/options.cpp
new file mode 100644
index 0000000000..c173a169a9
--- /dev/null
+++ b/plugins/AutoShutdown/src/options.cpp
@@ -0,0 +1,185 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Option Page */
+static HANDLE hHookOptInit;
+extern HINSTANCE hInst;
+/* Trigger */
+static HANDLE hHookModulesLoaded;
+
+/************************* Option Page ********************************/
+
+#define M_ENABLE_SUBCTLS (WM_APP+111)
+
+static INT_PTR CALLBACK ShutdownOptDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ { WORD setting=DBGetContactSettingWord(NULL,"AutoShutdown","ConfirmDlgCountdown",SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT);
+ if(setting<3) setting=SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT;
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CONFIRMDLGCOUNTDOWN,UDM_SETRANGE,0,MAKELPARAM(999,3));
+ SendDlgItemMessage(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN,EM_SETLIMITTEXT,3,0);
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CONFIRMDLGCOUNTDOWN,UDM_SETPOS,0,MAKELPARAM(setting,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN,setting,FALSE);
+ }
+ CheckDlgButton(hwndDlg,IDC_CHECK_SMARTOFFLINECHECK,DBGetContactSettingByte(NULL,"AutoShutdown","SmartOfflineCheck",SETTING_SMARTOFFLINECHECK_DEFAULT)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_REMEMBERONRESTART,DBGetContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",SETTING_REMEMBERONRESTART_DEFAULT)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_SHOWCONFIRMDLG,DBGetContactSettingByte(NULL,"AutoShutdown","ShowConfirmDlg",SETTING_SHOWCONFIRMDLG_DEFAULT)!=0);
+ { BOOL enabled=ServiceIsTypeEnabled(SDSDT_SHUTDOWN,0);
+ if(enabled) {
+ if(ServiceExists(MS_SYSINFO_HDDTEMP)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_HDDOVERHEAT),TRUE);
+ CheckDlgButton(hwndDlg,IDC_CHECK_HDDOVERHEAT,DBGetContactSettingByte(NULL,"AutoShutdown","HddOverheatShutdown",SETTING_HDDOVERHEATSHUTDOWN_DEFAULT)!=0);
+ }
+ if(ServiceExists(MS_WEATHER_UPDATE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_WEATHER),TRUE);
+ CheckDlgButton(hwndDlg,IDC_CHECK_WEATHER,DBGetContactSettingByte(NULL,"AutoShutdown","WeatherShutdown",SETTING_WEATHERSHUTDOWN_DEFAULT)!=0);
+ }
+ }
+ }
+ SendMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ return TRUE; /* default focus */
+ case M_ENABLE_SUBCTLS:
+ { BOOL checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWCONFIRMDLG)!=0;
+ if(checked!=IsWindowEnabled(GetDlgItem(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN))) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SPIN_CONFIRMDLGCOUNTDOWN),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT_COUNTDOWNSTARTS),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT_SECONDS),checked);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_EDIT_CONFIRMDLGCOUNTDOWN:
+ if(HIWORD(wParam)==EN_KILLFOCUS)
+ if((int)GetDlgItemInt(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN,NULL,TRUE)<3) {
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CONFIRMDLGCOUNTDOWN,UDM_SETPOS,0,MAKELPARAM(3,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN,3,FALSE);
+ }
+ if(HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())
+ return TRUE; /* no apply */
+ break;
+ }
+ PostMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ PostMessage(GetParent(hwndDlg),PSM_CHANGED,0,0); /* enable apply */
+ return FALSE;
+ case WM_NOTIFY:
+ switch(((NMHDR*)lParam)->code) {
+ case PSN_APPLY:
+ DBWriteContactSettingByte(NULL,"AutoShutdown","ShowConfirmDlg",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWCONFIRMDLG)!=0));
+ DBWriteContactSettingWord(NULL,"AutoShutdown","ConfirmDlgCountdown",(WORD)GetDlgItemInt(hwndDlg,IDC_EDIT_CONFIRMDLGCOUNTDOWN,NULL,FALSE));
+ DBWriteContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_REMEMBERONRESTART)!=0));
+ DBWriteContactSettingByte(NULL,"AutoShutdown","SmartOfflineCheck",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SMARTOFFLINECHECK)!=0));
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECK_WEATHER)))
+ DBWriteContactSettingByte(NULL,"AutoShutdown","WeatherShutdown",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_WEATHER)!=0));
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECK_HDDOVERHEAT)))
+ DBWriteContactSettingByte(NULL,"AutoShutdown","HddOverheatShutdown",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_HDDOVERHEAT)!=0));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int ShutdownOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.hInstance=hInst;
+ odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPT_SHUTDOWN);
+ odp.position=900000002;
+ odp.ptszGroup=_T("Events"); /* autotranslated */
+ odp.ptszTitle=_T("Automatic Shutdown"); /* autotranslated */
+ odp.ptszTab=_T("Automatic Shutdown"); /* autotranslated, can be made a tab */
+ odp.flags=ODPF_BOLDGROUPS|ODPF_EXPERTONLY|ODPF_TCHAR;
+ odp.pfnDlgProc = ShutdownOptDlgProc;
+ Options_AddPage(wParam, &odp);
+ return 0;
+}
+
+/************************* Trigger ************************************/
+
+static int __stdcall ActionProc(DWORD idAction,REPORTINFO *ri,int shutdownType)
+{
+ if(idAction&ACT_PERFORM) ServiceShutdown(shutdownType,TRUE);
+ return 0;
+}
+#define ActionProcJmp(shutdownType) { return ActionProc(id,ri,shutdownType); }
+
+static int CloseActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_CLOSEMIRANDA)
+static int SetOfflineActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_SETMIRANDAOFFLINE)
+static int LogoffActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_LOGOFF)
+static int RebootActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_REBOOT)
+static int ShutdownActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_SHUTDOWN)
+static int StandbyActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_STANDBY)
+static int HibernateActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_HIBERNATE)
+static int LockActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_LOCKWORKSTATION)
+static int HangupActionProc(DWORD id,REPORTINFO *ri) ActionProcJmp(SDSDT_CLOSERASCONNECTIONS)
+
+static int TriggerRegisterActions(WPARAM wParam,LPARAM lParam)
+{
+ /* new trigger API (0.2.0.69+) */
+ if(ServiceExists(MS_TRIGGER_REGISTERCONDITION)) {
+ ACTIONREGISTER ar;
+ BYTE shutdownType;
+ char *pszDesc,szName[138];
+ ACTIONFUNCTION actionFunctions[SDSDT_MAX]={CloseActionProc,SetOfflineActionProc,LogoffActionProc,
+ RebootActionProc,ShutdownActionProc,StandbyActionProc,
+ HibernateActionProc,LockActionProc,HangupActionProc};
+ ZeroMemory(&ar,sizeof(ar));
+ ar.cbSize=sizeof(ar);
+ ar.flags=ARF_TCHAR|ARF_FUNCTION;
+ ar.pszName=szName;
+ for(shutdownType=1;shutdownType<=SDSDT_MAX;++shutdownType)
+ if(ServiceIsTypeEnabled(shutdownType,0)) {
+ pszDesc=(char*)ServiceGetTypeDescription(shutdownType,GSTDF_UNTRANSLATED);
+ if(pszDesc!=NULL) {
+ mir_snprintf(szName,sizeof(szName),"Shutdown: %s",pszDesc); /* autotranslated */
+ ar.actionFunction=actionFunctions[shutdownType-1];
+ CallService(MS_TRIGGER_REGISTERACTION,0,(LPARAM)&ar);
+ }
+ }
+ }
+ return 0;
+}
+
+/************************* Misc ***************************************/
+
+void InitOptions(void)
+{
+ /* Option Page */
+ hHookOptInit=HookEvent(ME_OPT_INITIALISE,ShutdownOptInit);
+ /* Trigger */
+ hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,TriggerRegisterActions);
+}
+
+void UninitOptions(void)
+{
+ /* Option Page */
+ UnhookEvent(hHookOptInit);
+ /* Trigger */
+ UnhookEvent(hHookModulesLoaded);
+}
diff --git a/plugins/AutoShutdown/src/options.h b/plugins/AutoShutdown/src/options.h
new file mode 100644
index 0000000000..8b8e63f04f
--- /dev/null
+++ b/plugins/AutoShutdown/src/options.h
@@ -0,0 +1,24 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Misc */
+void InitOptions(void);
+void UninitOptions(void);
diff --git a/plugins/AutoShutdown/src/resource.h b/plugins/AutoShutdown/src/resource.h
new file mode 100644
index 0000000000..4d8370f00a
--- /dev/null
+++ b/plugins/AutoShutdown/src/resource.h
@@ -0,0 +1,58 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDI_ACTIVE 101
+#define IDI_INACTIVE 102
+#define IDI_HEADER 103
+#define IDD_SETTINGS 104
+#define IDD_SHUTDOWNNOW 105
+#define IDD_OPT_SHUTDOWN 106
+#define IDC_ICON_HEADER 1001
+#define IDC_TEXT_HEADER 1002
+#define IDC_TEXT_HEADERDESC 1003
+#define IDC_RECT_HEADER 1004
+#define IDC_RADIO_STTIME 1005
+#define IDC_RADIO_STCOUNTDOWN 1006
+#define IDC_CHECK_SPECIFICTIME 1007
+#define IDC_TIME_TIMESTAMP 1008
+#define IDC_DATE_TIMESTAMP 1009
+#define IDC_EDIT_COUNTDOWN 1010
+#define IDC_SPIN_COUNTDOWN 1011
+#define IDC_COMBO_COUNTDOWNUNIT 1012
+#define IDC_COMBO_SHUTDOWNTYPE 1013
+#define IDC_TEXT_SHUTDOWNTYPE 1014
+#define IDC_TEXT_SECONDS 1015
+#define IDC_CHECK_FILETRANSFER 1016
+#define IDC_CHECK_IDLE 1017
+#define IDC_URL_IDLE 1018
+#define IDC_CHECK_MESSAGE 1019
+#define IDC_EDIT_MESSAGE 1020
+#define IDC_CHECK_STATUS 1021
+#define IDC_CHECK_CPUUSAGE 1022
+#define IDC_TEXT_CURRENTCPU 1023
+#define IDC_EDIT_CPUUSAGE 1024
+#define IDC_SPIN_CPUUSAGE 1025
+#define IDC_TEXT_PERCENT 1026
+#define IDC_BUTTON_SHUTDOWNNOW 1027
+#define IDC_TEXT_UNSAVEDWARNING 1028
+#define IDC_CHECK_SHOWCONFIRMDLG 1029
+#define IDC_TEXT_COUNTDOWNSTARTS 1030
+#define IDC_EDIT_CONFIRMDLGCOUNTDOWN 1031
+#define IDC_SPIN_CONFIRMDLGCOUNTDOWN 1032
+#define IDC_CHECK_REMEMBERONRESTART 1033
+#define IDC_CHECK_SMARTOFFLINECHECK 1034
+#define IDC_CHECK_WEATHER 1035
+#define IDC_CHECK_HDDOVERHEAT 1036
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1037
+#define _APS_NEXT_SYMED_VALUE 2001
+#endif
+#endif
diff --git a/plugins/AutoShutdown/src/settingsdlg.cpp b/plugins/AutoShutdown/src/settingsdlg.cpp
new file mode 100644
index 0000000000..2871c65e33
--- /dev/null
+++ b/plugins/AutoShutdown/src/settingsdlg.cpp
@@ -0,0 +1,506 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Menu Item */
+static HANDLE hServiceMenuCommand;
+/* Toolbar Button */
+static HANDLE hHookToolbarLoaded;
+/* Services */
+static HANDLE hServiceShowDlg;
+static HWND hwndSettingsDlg;
+extern HINSTANCE hInst;
+
+/************************* Dialog *************************************/
+
+static void EnableDlgItem(HWND hwndDlg,int idCtrl,BOOL fEnable)
+{
+ hwndDlg=GetDlgItem(hwndDlg,idCtrl);
+ if(hwndDlg!=NULL && IsWindowEnabled(hwndDlg)!=fEnable)
+ EnableWindow(hwndDlg,fEnable);
+}
+
+static BOOL CALLBACK DisplayCpuUsageProc(BYTE nCpuUsage,LPARAM lParam)
+{
+ TCHAR str[64];
+ /* dialog closed? */
+ if(!IsWindow((HWND)lParam)) return FALSE; /* stop poll thread */
+ mir_sntprintf(str,SIZEOF(str),TranslateT("(current: %u%%)"),nCpuUsage);
+ SetWindowText((HWND)lParam,str);
+ return TRUE;
+}
+
+static BOOL AnyProtoHasCaps(DWORD caps1)
+{
+ int nProtoCount,i;
+ PROTOCOLDESCRIPTOR **protos;
+ if(!CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&nProtoCount,(LPARAM)&protos))
+ for(i=0;i<nProtoCount;++i)
+ if(protos[i]->type==PROTOTYPE_PROTOCOL)
+ if(CallProtoService(protos[i]->szName,PS_GETCAPS,(WPARAM)PFLAGNUM_1,0)&caps1)
+ return TRUE; /* CALLSERVICE_NOTFOUND also handled gracefully */
+ return FALSE;
+}
+
+#define M_ENABLE_SUBCTLS (WM_APP+111)
+#define M_UPDATE_SHUTDOWNDESC (WM_APP+112)
+#define M_CHECK_DATETIME (WM_APP+113)
+static INT_PTR CALLBACK SettingsDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ { LCID locale;
+ hwndSettingsDlg=hwndDlg;
+ TranslateDialogDefault(hwndDlg);
+ locale=CallService(MS_LANGPACK_GETLOCALE,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_ICON_HEADER,STM_SETIMAGE,IMAGE_ICON,(LPARAM)IcoLib_GetIcon("AutoShutdown_Header"));
+ { HFONT hBoldFont;
+ LOGFONT lf;
+ if(GetObject((HFONT)SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_GETFONT,0,0),sizeof(lf),&lf)) {
+ lf.lfWeight=FW_BOLD;
+ hBoldFont=CreateFontIndirect(&lf);
+ } else hBoldFont=NULL;
+ SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_SETFONT,(WPARAM)hBoldFont,FALSE);
+ }
+ /* read-in watcher flags */
+ { WORD watcherType;
+ watcherType=DBGetContactSettingWord(NULL,"AutoShutdown","WatcherFlags",SETTING_WATCHERFLAGS_DEFAULT);
+ CheckRadioButton(hwndDlg,IDC_RADIO_STTIME,IDC_RADIO_STCOUNTDOWN,(watcherType&SDWTF_ST_TIME)?IDC_RADIO_STTIME:IDC_RADIO_STCOUNTDOWN);
+ CheckDlgButton(hwndDlg,IDC_CHECK_SPECIFICTIME,(watcherType&SDWTF_SPECIFICTIME)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_MESSAGE,(watcherType&SDWTF_MESSAGE)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_FILETRANSFER,(watcherType&SDWTF_FILETRANSFER)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_IDLE,(watcherType&SDWTF_IDLE)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_STATUS,(watcherType&SDWTF_STATUS)!=0);
+ CheckDlgButton(hwndDlg,IDC_CHECK_CPUUSAGE,(watcherType&SDWTF_CPUUSAGE)!=0);
+ }
+ /* read-in countdown val */
+ { SYSTEMTIME st;
+ if(!TimeStampToSystemTime((time_t)DBGetContactSettingDword(NULL,"AutoShutdown","TimeStamp",SETTING_TIMESTAMP_DEFAULT),&st))
+ GetLocalTime(&st);
+ DateTime_SetSystemtime(GetDlgItem(hwndDlg,IDC_TIME_TIMESTAMP),GDT_VALID,&st);
+ DateTime_SetSystemtime(GetDlgItem(hwndDlg,IDC_DATE_TIMESTAMP),GDT_VALID,&st);
+ SendMessage(hwndDlg,M_CHECK_DATETIME,0,0);
+ }
+ { DWORD setting;
+ setting=DBGetContactSettingDword(NULL,"AutoShutdown","Countdown",SETTING_COUNTDOWN_DEFAULT);
+ if(setting<1) setting=SETTING_COUNTDOWN_DEFAULT;
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_COUNTDOWN,UDM_SETRANGE,0,MAKELPARAM(UD_MAXVAL,1));
+ SendDlgItemMessage(hwndDlg,IDC_EDIT_COUNTDOWN,EM_SETLIMITTEXT,(WPARAM)10,0);
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_COUNTDOWN,UDM_SETPOS,0,MAKELPARAM(setting,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_COUNTDOWN,setting,FALSE);
+ }
+ { HWND hwndCombo;
+ DWORD lastUnit;
+ int i,index;
+ const DWORD unitValues[]={1,60,60*60,60*60*24,60*60*24*7,60*60*24*31};
+ const TCHAR *unitNames[]={_T("Second(s)"),_T("Minute(s)"),_T("Hour(s)"),
+ _T("Day(s)"),_T("Week(s)"),_T("Month(s)")};
+ hwndCombo=GetDlgItem(hwndDlg,IDC_COMBO_COUNTDOWNUNIT);
+ lastUnit=DBGetContactSettingDword(NULL,"AutoShutdown","CountdownUnit",SETTING_COUNTDOWNUNIT_DEFAULT);
+ SendMessage(hwndCombo,CB_SETLOCALE,(WPARAM)locale,0); /* sort order */
+ SendMessage(hwndCombo,CB_INITSTORAGE,SIZEOF(unitNames),SIZEOF(unitNames)*16); /* approx. */
+ for(i=0;i<SIZEOF(unitNames);++i) {
+ index=SendMessage(hwndCombo,CB_ADDSTRING,0,(LPARAM)TranslateTS(unitNames[i]));
+ if(index!=LB_ERR) {
+ SendMessage(hwndCombo,CB_SETITEMDATA,index,(LPARAM)unitValues[i]);
+ if(i==0 || unitValues[i]==lastUnit) SendMessage(hwndCombo,CB_SETCURSEL,index,0);
+ }
+ }
+ }
+ { DBVARIANT dbv;
+ if(!DBGetContactSettingTString(NULL,"AutoShutdown","Message",&dbv)) {
+ SetDlgItemText(hwndDlg,IDC_EDIT_MESSAGE,dbv.ptszVal);
+ mir_free(dbv.ptszVal);
+ }
+ if(ServiceExists(MS_AUTOREPLACER_ADDWINHANDLE))
+ CallService(MS_AUTOREPLACER_ADDWINHANDLE,0,(LPARAM)GetDlgItem(hwndDlg,IDC_EDIT_MESSAGE));
+ }
+ /* cpuusage threshold */
+ { BYTE setting;
+ setting=DBGetContactSettingRangedByte(NULL,"AutoShutdown","CpuUsageThreshold",SETTING_CPUUSAGETHRESHOLD_DEFAULT,1,100);
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CPUUSAGE,UDM_SETRANGE,0,MAKELPARAM(100,1));
+ SendDlgItemMessage(hwndDlg,IDC_EDIT_CPUUSAGE,EM_SETLIMITTEXT,(WPARAM)3,0);
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CPUUSAGE,UDM_SETPOS,0,MAKELPARAM(setting,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_CPUUSAGE,setting,FALSE);
+ }
+ /* shutdown types */
+ { HWND hwndCombo;
+ BYTE lastShutdownType;
+ BYTE shutdownType;
+ int index;
+ TCHAR *pszText;
+ hwndCombo=GetDlgItem(hwndDlg,IDC_COMBO_SHUTDOWNTYPE);
+ lastShutdownType=DBGetContactSettingByte(NULL,"AutoShutdown","ShutdownType",SETTING_SHUTDOWNTYPE_DEFAULT);
+ SendMessage(hwndCombo,CB_SETLOCALE,(WPARAM)locale,0); /* sort order */
+ SendMessage(hwndCombo,CB_SETEXTENDEDUI,TRUE,0);
+ SendMessage(hwndCombo,CB_INITSTORAGE,SDSDT_MAX,SDSDT_MAX*32);
+ for(shutdownType=1;shutdownType<=SDSDT_MAX;++shutdownType)
+ if(ServiceIsTypeEnabled(shutdownType,0)) {
+ pszText=(TCHAR*)ServiceGetTypeDescription(shutdownType,GSTDF_TCHAR); /* never fails */
+ index=SendMessage(hwndCombo,CB_ADDSTRING,0,(LPARAM)pszText);
+ if(index!=LB_ERR) {
+ SendMessage(hwndCombo,CB_SETITEMDATA,index,(LPARAM)shutdownType);
+ if(shutdownType==1 || shutdownType==lastShutdownType) SendMessage(hwndCombo,CB_SETCURSEL,(WPARAM)index,0);
+ }
+ }
+ SendMessage(hwndDlg,M_UPDATE_SHUTDOWNDESC,0,(LPARAM)hwndCombo);
+ }
+ /* check if proto is installed that supports instant messages and check if a message dialog plugin is installed */
+ if(!AnyProtoHasCaps(PF1_IMRECV) || !ServiceExists(MS_MSG_SENDMESSAGE)) { /* no srmessage present? */
+ CheckDlgButton(hwndDlg,IDC_CHECK_MESSAGE,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT_MESSAGE),FALSE);
+ }
+ /* check if proto is installed that supports file transfers and check if a file transfer dialog is available */
+ if((!AnyProtoHasCaps(PF1_FILESEND) && !AnyProtoHasCaps(PF1_FILERECV)) || !ServiceExists(MS_FILE_SENDFILE)) { /* no srfile present? */
+ CheckDlgButton(hwndDlg,IDC_CHECK_FILETRANSFER,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_FILETRANSFER),FALSE);
+ }
+ /* check if cpu usage can be detected */
+ if(!PollCpuUsage(DisplayCpuUsageProc,(LPARAM)GetDlgItem(hwndDlg,IDC_TEXT_CURRENTCPU),1800)) {
+ CheckDlgButton(hwndDlg,IDC_CHECK_CPUUSAGE,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_CPUUSAGE),FALSE);
+ }
+ SendMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ MagneticWindows_AddWindow(hwndDlg);
+ Utils_RestoreWindowPositionNoSize(hwndDlg,NULL,"AutoShutdown","SettingsDlg_");
+ return TRUE; /* default focus */
+ }
+ case WM_DESTROY:
+ { HICON hIcon;
+ HFONT hFont;
+ if(ServiceExists(MS_AUTOREPLACER_ADDWINHANDLE))
+ CallService(MS_AUTOREPLACER_REMWINHANDLE,0,(LPARAM)GetDlgItem(hwndDlg,IDC_EDIT_MESSAGE));
+ Utils_SaveWindowPosition(hwndDlg,NULL,"AutoShutdown","SettingsDlg_");
+ MagneticWindows_RemoveWindow(hwndDlg);
+ hIcon=(HICON)SendDlgItemMessage(hwndDlg,IDC_ICON_HEADER,STM_SETIMAGE,IMAGE_ICON,(LPARAM)NULL);
+ IcoLib_ReleaseIcon(hIcon); /* does NULL check */
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_SETFONT,(WPARAM)NULL,FALSE); /* no return value */
+ if(hFont!=NULL) DeleteObject(hFont);
+ hwndSettingsDlg=NULL;
+ return TRUE;
+ }
+ case WM_CTLCOLORSTATIC:
+ switch(GetDlgCtrlID((HWND)lParam)) {
+ case IDC_ICON_HEADER:
+ SetBkMode((HDC)wParam,TRANSPARENT);
+ case IDC_RECT_HEADER:
+ /* need to set COLOR_WINDOW manually for Win9x */
+ SetBkColor((HDC)wParam,GetSysColor(COLOR_WINDOW));
+ return (BOOL)GetSysColorBrush(COLOR_WINDOW);
+ case IDC_TEXT_HEADER:
+ case IDC_TEXT_HEADERDESC:
+ SetBkMode((HDC)wParam,TRANSPARENT);
+ return (BOOL)GetStockObject(NULL_BRUSH);
+ }
+ break;
+ case M_ENABLE_SUBCTLS:
+ { BOOL checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_MESSAGE)!=0;
+ EnableDlgItem(hwndDlg,IDC_EDIT_MESSAGE,checked);
+ checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_SPECIFICTIME)!=0;
+ EnableDlgItem(hwndDlg,IDC_RADIO_STTIME,checked);
+ EnableDlgItem(hwndDlg,IDC_RADIO_STCOUNTDOWN,checked);
+ checked=(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SPECIFICTIME) && IsDlgButtonChecked(hwndDlg,IDC_RADIO_STTIME));
+ EnableDlgItem(hwndDlg,IDC_TIME_TIMESTAMP,checked);
+ EnableDlgItem(hwndDlg,IDC_DATE_TIMESTAMP,checked);
+ checked=(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SPECIFICTIME) && IsDlgButtonChecked(hwndDlg,IDC_RADIO_STCOUNTDOWN));
+ EnableDlgItem(hwndDlg,IDC_EDIT_COUNTDOWN,checked);
+ EnableDlgItem(hwndDlg,IDC_SPIN_COUNTDOWN,checked);
+ EnableDlgItem(hwndDlg,IDC_COMBO_COUNTDOWNUNIT,checked);
+ checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_IDLE)!=0;
+ EnableDlgItem(hwndDlg,IDC_URL_IDLE,checked);
+ checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_CPUUSAGE)!=0;
+ EnableDlgItem(hwndDlg,IDC_EDIT_CPUUSAGE,checked);
+ EnableDlgItem(hwndDlg,IDC_SPIN_CPUUSAGE,checked);
+ EnableDlgItem(hwndDlg,IDC_TEXT_PERCENT,checked);
+ EnableDlgItem(hwndDlg,IDC_TEXT_CURRENTCPU,checked);
+ checked=(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SPECIFICTIME) || IsDlgButtonChecked(hwndDlg,IDC_CHECK_MESSAGE) ||
+ IsDlgButtonChecked(hwndDlg,IDC_CHECK_IDLE) || IsDlgButtonChecked(hwndDlg,IDC_CHECK_STATUS) ||
+ IsDlgButtonChecked(hwndDlg,IDC_CHECK_FILETRANSFER) || IsDlgButtonChecked(hwndDlg,IDC_CHECK_CPUUSAGE));
+ EnableDlgItem(hwndDlg,IDOK,checked);
+ }
+ return TRUE;
+ case M_UPDATE_SHUTDOWNDESC: /* lParam=(LPARAM)(HWND)hwndCombo */
+ { BYTE shutdownType;
+ shutdownType=(BYTE)SendMessage((HWND)lParam,CB_GETITEMDATA,SendMessage((HWND)lParam,CB_GETCURSEL,0,0),0);
+ SetDlgItemText(hwndDlg,IDC_TEXT_SHUTDOWNTYPE,(TCHAR*)ServiceGetTypeDescription(shutdownType,GSTDF_LONGDESC|GSTDF_TCHAR));
+ return TRUE;
+ }
+ case WM_TIMECHANGE: /* system time changed */
+ SendMessage(hwndDlg,M_CHECK_DATETIME,0,0);
+ return TRUE;
+ case M_CHECK_DATETIME:
+ { SYSTEMTIME st,stBuf;
+ time_t timestamp;
+ DateTime_GetSystemtime(GetDlgItem(hwndDlg,IDC_DATE_TIMESTAMP),&stBuf);
+ DateTime_GetSystemtime(GetDlgItem(hwndDlg,IDC_TIME_TIMESTAMP),&st);
+ st.wDay=stBuf.wDay;
+ st.wDayOfWeek=stBuf.wDayOfWeek;
+ st.wMonth=stBuf.wMonth;
+ st.wYear=stBuf.wYear;
+ GetLocalTime(&stBuf);
+ if(SystemTimeToTimeStamp(&st,&timestamp)) {
+ /* set to current date if earlier */
+ if(timestamp<time(NULL)) {
+ st.wDay=stBuf.wDay;
+ st.wDayOfWeek=stBuf.wDayOfWeek;
+ st.wMonth=stBuf.wMonth;
+ st.wYear=stBuf.wYear;
+ if(SystemTimeToTimeStamp(&st,&timestamp)) {
+ /* step one day up if still earlier */
+ if(timestamp<time(NULL)) {
+ timestamp+=24*60*60;
+ TimeStampToSystemTime(timestamp,&st);
+ }
+ }
+ }
+ }
+ DateTime_SetRange(GetDlgItem(hwndDlg,IDC_DATE_TIMESTAMP),GDTR_MIN,&stBuf);
+ DateTime_SetRange(GetDlgItem(hwndDlg,IDC_TIME_TIMESTAMP),GDTR_MIN,&stBuf);
+ DateTime_SetSystemtime(GetDlgItem(hwndDlg,IDC_DATE_TIMESTAMP),GDT_VALID,&st);
+ DateTime_SetSystemtime(GetDlgItem(hwndDlg,IDC_TIME_TIMESTAMP),GDT_VALID,&st);
+ return TRUE;
+ }
+ case WM_NOTIFY:
+ switch(((NMHDR*)lParam)->idFrom) {
+ case IDC_TIME_TIMESTAMP:
+ case IDC_DATE_TIMESTAMP:
+ switch(((NMHDR*)lParam)->code) {
+ case DTN_CLOSEUP:
+ case NM_KILLFOCUS:
+ PostMessage(hwndDlg,M_CHECK_DATETIME,0,0);
+ return TRUE;
+ }
+ }
+ break;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_CHECK_MESSAGE:
+ case IDC_CHECK_FILETRANSFER:
+ case IDC_CHECK_IDLE:
+ case IDC_CHECK_CPUUSAGE:
+ case IDC_CHECK_STATUS:
+ case IDC_CHECK_SPECIFICTIME:
+ case IDC_RADIO_STTIME:
+ case IDC_RADIO_STCOUNTDOWN:
+ SendMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ return TRUE;
+ case IDC_EDIT_COUNTDOWN:
+ if(HIWORD(wParam)==EN_KILLFOCUS) {
+ if((int)GetDlgItemInt(hwndDlg,IDC_EDIT_COUNTDOWN,NULL,TRUE)<1) {
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_COUNTDOWN,UDM_SETPOS,0,MAKELPARAM(1,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_COUNTDOWN,1,FALSE);
+ }
+ return TRUE;
+ }
+ break;
+ case IDC_EDIT_CPUUSAGE:
+ if(HIWORD(wParam)==EN_KILLFOCUS) {
+ WORD val;
+ val=(WORD)GetDlgItemInt(hwndDlg,IDC_EDIT_CPUUSAGE,NULL,FALSE);
+ if(val<1) val=1;
+ else if(val>100) val=100;
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_CPUUSAGE,UDM_SETPOS,0,MAKELPARAM(val,0));
+ SetDlgItemInt(hwndDlg,IDC_EDIT_CPUUSAGE,val,FALSE);
+ return TRUE;
+ }
+ break;
+ case IDC_URL_IDLE:
+ { OPENOPTIONSDIALOG ood;
+ ood.cbSize=sizeof(ood);
+ ood.pszGroup="Status"; /* autotranslated */
+ ood.pszPage="Idle"; /* autotranslated */
+ ood.pszTab=NULL;
+ CallService(MS_OPT_OPENOPTIONS,0,(LPARAM)&ood);
+ return TRUE;
+ }
+ case IDC_COMBO_SHUTDOWNTYPE:
+ if(HIWORD(wParam)==CBN_SELCHANGE)
+ SendMessage(hwndDlg,M_UPDATE_SHUTDOWNDESC,0,lParam);
+ return TRUE;
+ case IDOK: /* save settings and start watcher */
+ ShowWindow(hwndDlg,SW_HIDE);
+ /* message text */
+ { HWND hwndEdit=GetDlgItem(hwndDlg,IDC_EDIT_MESSAGE);
+ int len=GetWindowTextLength(hwndEdit)+1;
+ TCHAR *pszText=(TCHAR*)mir_alloc(len*sizeof(TCHAR));
+ if(pszText!=NULL && GetWindowText(hwndEdit,pszText,len+1)) {
+ TrimString(pszText);
+ DBWriteContactSettingTString(NULL,"AutoShutdown","Message",pszText);
+ }
+ mir_free(pszText); /* does NULL check */
+ }
+ /* timestamp */
+ { SYSTEMTIME st;
+ time_t timestamp;
+ DateTime_GetSystemtime(GetDlgItem(hwndDlg,IDC_TIME_TIMESTAMP),&st); /* time gets synchronized */
+ if(!SystemTimeToTimeStamp(&st,&timestamp))
+ timestamp=time(NULL);
+ DBWriteContactSettingDword(NULL,"AutoShutdown","TimeStamp",(DWORD)timestamp);
+ }
+ /* shutdown type */
+ { int index;
+ index=SendDlgItemMessage(hwndDlg,IDC_COMBO_SHUTDOWNTYPE,CB_GETCURSEL,0,0);
+ if(index!=LB_ERR) DBWriteContactSettingByte(NULL,"AutoShutdown","ShutdownType",(BYTE)SendDlgItemMessage(hwndDlg,IDC_COMBO_SHUTDOWNTYPE,CB_GETITEMDATA,(WPARAM)index,0));
+ index=SendDlgItemMessage(hwndDlg,IDC_COMBO_COUNTDOWNUNIT,CB_GETCURSEL,0,0);
+ if(index!=LB_ERR) DBWriteContactSettingDword(NULL,"AutoShutdown","CountdownUnit",(DWORD)SendDlgItemMessage(hwndDlg,IDC_COMBO_COUNTDOWNUNIT,CB_GETITEMDATA,(WPARAM)index,0));
+ DBWriteContactSettingDword(NULL,"AutoShutdown","Countdown",(DWORD)GetDlgItemInt(hwndDlg,IDC_EDIT_COUNTDOWN,NULL,FALSE));
+ DBWriteContactSettingByte(NULL,"AutoShutdown","CpuUsageThreshold",(BYTE)GetDlgItemInt(hwndDlg,IDC_EDIT_CPUUSAGE,NULL,FALSE));
+ }
+ /* watcher type */
+ { WORD watcherType;
+ watcherType=(WORD)(IsDlgButtonChecked(hwndDlg,IDC_RADIO_STTIME)?SDWTF_ST_TIME:SDWTF_ST_COUNTDOWN);
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SPECIFICTIME)) watcherType|=SDWTF_SPECIFICTIME;
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_MESSAGE)) watcherType|=SDWTF_MESSAGE;
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_FILETRANSFER)) watcherType|=SDWTF_FILETRANSFER;
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_IDLE)) watcherType|=SDWTF_IDLE;
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_STATUS)) watcherType|=SDWTF_STATUS;
+ if(IsDlgButtonChecked(hwndDlg,IDC_CHECK_CPUUSAGE)) watcherType|=SDWTF_CPUUSAGE;
+ DBWriteContactSettingWord(NULL,"AutoShutdown","WatcherFlags",watcherType);
+ ServiceStartWatcher(0,watcherType);
+ }
+ /* fall through */
+ case IDCANCEL: /* WM_CLOSE */
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ break;
+ }
+ CallSnappingWindowProc(hwndDlg,msg,wParam,lParam); /* Snapping Windows plugin */
+ return FALSE;
+}
+
+/************************* Services ***********************************/
+
+static INT_PTR ServiceShowSettingsDialog(WPARAM wParam,LPARAM lParam)
+{
+ if(hwndSettingsDlg!=NULL) { /* already opened, bring to front */
+ SetForegroundWindow(hwndSettingsDlg);
+ return 0;
+ }
+ return (CreateDialog(hInst, MAKEINTRESOURCE(IDD_SETTINGS), NULL, SettingsDlgProc) == NULL);
+}
+
+/************************* Toolbar ************************************/
+
+static WORD hToolbarButton;
+
+static int ToolbarLoaded(WPARAM wParam,LPARAM lParam)
+{
+ TTBButton ttbb;
+
+ ZeroMemory(&ttbb,sizeof(ttbb));
+ ttbb.cbSize=sizeof(ttbb);
+ /* toptoolbar offers icolib support */
+ ttbb.hIconUp=(HICON)LoadImage(hInst,MAKEINTRESOURCE(IDI_ACTIVE),IMAGE_ICON,0,0,0);
+ ttbb.hIconDn=(HICON)LoadImage(hInst,MAKEINTRESOURCE(IDI_INACTIVE),IMAGE_ICON,0,0,0);
+ ttbb.pszService="AutoShutdown/MenuCommand";
+ ttbb.dwFlags=TTBBF_VISIBLE|TTBBF_SHOWTOOLTIP;
+ ttbb.name=Translate("Start/Stop automatic shutdown");
+
+ hToolbarButton=(WORD)CallService(MS_TTB_ADDBUTTON,(WPARAM)&ttbb,0);
+ if(ttbb.hIconUp!=NULL) DestroyIcon(ttbb.hIconUp);
+ if(ttbb.hIconDn!=NULL) DestroyIcon(ttbb.hIconDn);
+ return 0;
+}
+
+void SetShutdownToolbarButton(BOOL fActive)
+{
+ if(hToolbarButton) {
+ CallService(MS_TTB_SETBUTTONSTATE,hToolbarButton,fActive?TTBST_PUSHED:TTBST_RELEASED);
+ CallService(MS_TTB_SETBUTTONOPTIONS,MAKEWPARAM(TTBO_TIPNAME,hToolbarButton),(LPARAM)(fActive?Translate("Sdop automatic shutdown"):Translate("Start automatic shutdown")));
+ }
+}
+
+/************************* Menu Item **********************************/
+
+static HANDLE hMainMenuItem,hTrayMenuItem;
+extern HANDLE hActiveIcon,hInactiveIcon;
+
+void SetShutdownMenuItem(BOOL fActive)
+{
+ CLISTMENUITEM cmi;
+ ZeroMemory(&cmi,sizeof(cmi));
+ cmi.cbSize=sizeof(cmi);
+
+ /* main menu */
+ cmi.position=2001090000;
+ cmi.icolibItem=fActive?hActiveIcon:hInactiveIcon;
+ cmi.ptszName=fActive?_T("Stop automatic &shutdown"):_T("Automatic &shutdown..."); /* autotranslated */
+ cmi.pszService="AutoShutdown/MenuCommand";
+ cmi.flags=CMIF_TCHAR|CMIF_ICONFROMICOLIB;
+ if(hMainMenuItem!=NULL) {
+ cmi.flags|=CMIM_NAME|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hMainMenuItem,(LPARAM)&cmi);
+ }
+ else hMainMenuItem = Menu_AddMainMenuItem(&cmi);
+
+ /* tray menu */
+ cmi.position=899999;
+ if(hTrayMenuItem!=NULL) {
+ cmi.flags|=CMIM_NAME|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hTrayMenuItem,(LPARAM)&cmi);
+ }
+ else hTrayMenuItem = Menu_AddTrayMenuItem(&cmi);
+
+ IcoLib_ReleaseIcon(cmi.hIcon);
+}
+
+static INT_PTR MenuItemCommand(WPARAM wParam,LPARAM lParam)
+{
+ /* toggle between StopWatcher and ShowSettingsDdialog */
+ if(ServiceIsWatcherEnabled(0,0))
+ ServiceStopWatcher(0,0);
+ else
+ ServiceShowSettingsDialog(0,0);
+ return 0;
+}
+
+/************************* Misc ***************************************/
+
+void InitSettingsDlg(void)
+{
+ /* Menu Item */
+ hServiceMenuCommand = CreateServiceFunction("AutoShutdown/MenuCommand", MenuItemCommand);
+ hMainMenuItem=hTrayMenuItem=NULL;
+ SetShutdownMenuItem(FALSE);
+ /* Toolbar Item */
+ hToolbarButton=0;
+ hHookToolbarLoaded=HookEvent(ME_TTB_MODULELOADED,ToolbarLoaded); /* no service to check for */
+ /* Hotkey */
+ AddHotkey();
+ /* Services */
+ hwndSettingsDlg=NULL;
+ hServiceShowDlg = CreateServiceFunction(MS_AUTOSHUTDOWN_SHOWSETTINGSDIALOG, ServiceShowSettingsDialog);
+}
+
+void UninitSettingsDlg(void)
+{
+ /* Toolbar Item */
+ UnhookEvent(hHookToolbarLoaded);
+ /* Menu Item */
+ DestroyServiceFunction(hServiceMenuCommand);
+ /* Services */
+ DestroyServiceFunction(hServiceShowDlg);
+}
+
diff --git a/plugins/AutoShutdown/src/settingsdlg.h b/plugins/AutoShutdown/src/settingsdlg.h
new file mode 100644
index 0000000000..2f7bf8ea84
--- /dev/null
+++ b/plugins/AutoShutdown/src/settingsdlg.h
@@ -0,0 +1,30 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Menu Item */
+void SetShutdownMenuItem(BOOL fActive);
+
+/* Toolbar Button */
+void SetShutdownToolbarButton(BOOL fActive);
+
+/* Misc */
+void InitSettingsDlg(void);
+void UninitSettingsDlg(void);
diff --git a/plugins/AutoShutdown/src/shutdownsvc.cpp b/plugins/AutoShutdown/src/shutdownsvc.cpp
new file mode 100644
index 0000000000..57c12c65a2
--- /dev/null
+++ b/plugins/AutoShutdown/src/shutdownsvc.cpp
@@ -0,0 +1,576 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Shutdown Dialog */
+static HWND hwndShutdownDlg;
+extern HINSTANCE hInst;
+/* Services */
+static HANDLE hEventOkToShutdown,hEventShutdown;
+static HANDLE hServiceShutdown,hServiceIsTypeEnabled,hServiceGetTypeDesc;
+
+/************************* Utils **************************************/
+
+static BOOL WinNT_SetPrivilege(TCHAR *pszPrivName,BOOL bEnable)
+{
+ BOOL bReturn=FALSE;
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tkp;
+ /* get a token for this process */
+ if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) {
+ tkp.PrivilegeCount=1; /* one privilege is to set */
+ /* get the LUID for the shutdown privilege */
+ if(LookupPrivilegeValue(NULL,pszPrivName,&tkp.Privileges[0].Luid)) {
+ tkp.Privileges[0].Attributes=bEnable?SE_PRIVILEGE_ENABLED:0;
+ /* get the shutdown privilege for this process */
+ bReturn=AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
+ }
+ CloseHandle(hToken);
+ }
+ return bReturn;
+}
+
+static void BroadcastEndSession(DWORD dwRecipients,LPARAM lParam)
+{
+ LONG (WINAPI *pfnBroadcastSystemMessage)(DWORD,DWORD*,UINT,WPARAM,LPARAM);
+ *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessageW");
+ if(pfnBroadcastSystemMessage)
+ pfnBroadcastSystemMessage(BSF_FORCEIFHUNG,&dwRecipients,WM_ENDSESSION,TRUE,lParam);
+}
+
+static BOOL WinNT_IsWorkStationLocked(void)
+{
+ HDESK hDesk;
+ TCHAR szName[8];
+ DWORD cbName;
+ BOOL bLocked;
+ hDesk=OpenInputDesktop(0,FALSE,DESKTOP_READOBJECTS);
+ if(hDesk==NULL) return TRUE;
+ bLocked=(!GetUserObjectInformation(hDesk,UOI_NAME,szName,SIZEOF(szName),&cbName) || lstrcmpi(szName,_T("default"))!=0);
+ CloseDesktop(hDesk);
+ return bLocked;
+}
+
+/************************* Workers ************************************/
+static BOOL IsShutdownTypeEnabled(BYTE shutdownType)
+{
+ BOOL bReturn=FALSE;
+ switch(shutdownType) {
+ case SDSDT_HIBERNATE:
+ case SDSDT_STANDBY:
+ { HMODULE hPowerDLL=LoadLibraryA("POWRPROF"); /* all ascii */
+ if(hPowerDLL!=NULL) {
+ BOOLEAN (STDAPICALLTYPE *pfnIsPwrModeAllowed)(void);
+ *(PROC*)&pfnIsPwrModeAllowed=GetProcAddress(hPowerDLL,(shutdownType==SDSDT_HIBERNATE)?"IsPwrHibernateAllowed":"IsPwrSuspendAllowed");
+ if(pfnIsPwrModeAllowed) bReturn=pfnIsPwrModeAllowed()!=0;
+ FreeLibrary(hPowerDLL);
+ }
+ }
+ /* test privilege */
+ if(bReturn && IsWinVerNT()) {
+ bReturn=WinNT_SetPrivilege(SE_SHUTDOWN_NAME,TRUE);
+ if(bReturn) WinNT_SetPrivilege(SE_SHUTDOWN_NAME,FALSE);
+ }
+ break;
+ case SDSDT_LOGOFF:
+ { HKEY hKey;
+ DWORD dwSetting,dwSize;
+ /* NoLogOff is BINARY on Win9x/ME and DWORD on Win2000+ */
+ bReturn=TRUE;
+ if(RegOpenKeyEx(HKEY_CURRENT_USER,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"),0,KEY_QUERY_VALUE,&hKey)==ERROR_SUCCESS) {
+ dwSize=sizeof(dwSetting);
+ if(RegQueryValueEx(hKey, _T("NoLogOff"), 0, NULL, (LPBYTE)&dwSetting, &dwSize) == ERROR_SUCCESS)
+ if(dwSetting) bReturn=FALSE;
+ RegCloseKey(hKey);
+ }
+ }
+ break;
+ case SDSDT_LOCKWORKSTATION:
+ { void (WINAPI *pfnLockWorkStation)(void);
+ *(PROC*)&pfnLockWorkStation=GetProcAddress(GetModuleHandleA("USER32"),"LockWorkStation");
+ if(pfnLockWorkStation) {
+ HKEY hKey;
+ DWORD dwSize,dwSetting;
+ /* DisableLockWorkstation is DWORD on Win2000+ */
+ bReturn=TRUE;
+ if(RegOpenKeyEx(HKEY_CURRENT_USER,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"),0,KEY_QUERY_VALUE,&hKey)==ERROR_SUCCESS) {
+ dwSize=sizeof(dwSetting);
+ if(!RegQueryValueEx(hKey, _T("DisableLockWorkstation"), 0, NULL, (LPBYTE)&dwSetting, &dwSize))
+ if(dwSetting) bReturn=FALSE;
+ RegCloseKey(hKey);
+ }
+ }
+ else if(IsWinVerNT()) /* for WinNT4 */
+ bReturn=SearchPath(NULL,_T("LOGIN.SCR"),NULL,0,NULL,NULL)!=0;
+ }
+ break;
+ case SDSDT_CLOSERASCONNECTIONS:
+ /* check if RAS installed/available */
+ bReturn=SearchPath(NULL,_T("RASAPI32"),_T(".DLL"),0,NULL,NULL)!=0;
+ break;
+ case SDSDT_SETMIRANDAOFFLINE:
+ case SDSDT_CLOSEMIRANDA:
+ bReturn=TRUE; /* always possible */
+ break;
+ case SDSDT_REBOOT:
+ case SDSDT_SHUTDOWN:
+ /* test privileges */
+ if(IsWinVerNT()) {
+ bReturn=WinNT_SetPrivilege(SE_SHUTDOWN_NAME,TRUE);
+ if(bReturn) WinNT_SetPrivilege(SE_SHUTDOWN_NAME,FALSE);
+ }
+ else bReturn=TRUE;
+ break;
+ }
+ return bReturn;
+}
+
+static DWORD ShutdownNow(BYTE shutdownType)
+{
+ DWORD dwErrCode=ERROR_SUCCESS;
+ switch(shutdownType) {
+ case SDSDT_CLOSEMIRANDA:
+ if(!Miranda_Terminated()) {
+ /* waiting for short until ready (but not too long...) */
+ DWORD dwLastTickCount=GetTickCount();
+ while(!CallService(MS_SYSTEM_OKTOEXIT,0,0)) {
+ /* infinite loop protection (max 5 sec) */
+ if(GetTickCount()-dwLastTickCount>=5000) { /* wraparound works */
+ OutputDebugStringA("Timeout (5 sec)\n"); /* tell others, all ascii */
+ break;
+ }
+ SleepEx(1000,TRUE);
+ if(Miranda_Terminated()) break; /* someone else did it */
+ OutputDebugStringA("Not ready to exit. Waiting...\n"); /* tell others, all ascii */
+ }
+ /* shutdown service must be called from main thread anyway */
+ if(!DestroyWindow((HWND)CallService(MS_CLUI_GETHWND,0,0)))
+ dwErrCode=GetLastError();
+ }
+ break;
+ case SDSDT_SETMIRANDAOFFLINE:
+ /* set global status mode to offline (is remembered by Miranda on exit) */
+ CallService(MS_CLIST_SETSTATUSMODE,(WPARAM)ID_STATUS_OFFLINE,(LPARAM)NULL);
+ break;
+ case SDSDT_STANDBY:
+ case SDSDT_HIBERNATE:
+ WinNT_SetPrivilege(SE_SHUTDOWN_NAME,TRUE);
+ if(!SetSystemPowerState(shutdownType==SDSDT_STANDBY,TRUE))
+ dwErrCode=GetLastError();
+ WinNT_SetPrivilege(SE_SHUTDOWN_NAME,FALSE);
+ break;
+ case SDSDT_LOCKWORKSTATION:
+ { BOOL (WINAPI *pfnLockWorkStation)(void);
+ *(PROC*)&pfnLockWorkStation=GetProcAddress(GetModuleHandleA("USER32"),"LockWorkStation");
+ if(pfnLockWorkStation!=NULL) /* Win2000+ */
+ if(!pfnLockWorkStation() && !WinNT_IsWorkStationLocked())
+ dwErrCode=GetLastError();
+ else if(IsWinVerNT()) { /* WinNT4 */
+ HKEY hKey;
+ /* start LOGON.SCR screensaver (locks workstation on NT4) */
+ if(!SearchPath(NULL,_T("LOGIN.SCR"),NULL,0,NULL,NULL)) {
+ if(RegCreateKeyEx(HKEY_CURRENT_USER,_T("Control Panel\\Desktop"),0,NULL,REG_OPTION_VOLATILE,KEY_QUERY_VALUE|KEY_SET_VALUE,NULL,&hKey,NULL)==ERROR_SUCCESS) {
+ TCHAR szScreenSaveActive[2],szScreenSaverIsSecure[2],szScrnsaveExe[MAX_PATH];
+ DWORD dwSize;
+ /* save old settings */
+ dwSize=sizeof(szScreenSaveActive); /* in bytes */
+ ZeroMemory(&szScreenSaveActive,dwSize);
+ RegQueryValueEx(hKey, _T("ScreenSaveActive"), 0, NULL, (LPBYTE)szScreenSaveActive, &dwSize);
+ dwSize=sizeof(szScreenSaverIsSecure); /* in bytes */
+ ZeroMemory(&szScreenSaverIsSecure, dwSize);
+ RegQueryValueEx(hKey, _T("ScreenSaverIsSecure"), 0, NULL, (LPBYTE)szScreenSaverIsSecure, &dwSize);
+ dwSize=sizeof(szScrnsaveExe); /* in bytes */
+ ZeroMemory(&szScrnsaveExe, dwSize);
+ RegQueryValueEx(hKey, _T("SCRNSAVE.EXE"), 0, NULL, (LPBYTE)szScrnsaveExe, &dwSize);
+ /* set LOGON.SCR data */
+ if(!RegSetValueEx(hKey, _T("ScreenSaveActive"), 0, REG_SZ, (LPBYTE)_T("1"), 2) &&
+ !RegSetValueEx(hKey, _T("ScreenSaverIsSecure"), 0, REG_SZ, (LPBYTE)"1", 2) &&
+ !RegSetValueEx(hKey, _T("SCRNSAVE.EXE"), 0, REG_SZ, (LPBYTE)_T("LOGIN.SCR"), 10))
+ SendMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
+ else dwErrCode=GetLastError();
+ /* restore old settings */
+ RegSetValueEx(hKey, _T("ScreenSaveActive"), 0, REG_SZ, (BYTE*)szScreenSaveActive, (lstrlen(szScreenSaveActive)+1)*sizeof(TCHAR));
+ RegSetValueEx(hKey, _T("ScreenSaverIsSecure"), 0, REG_SZ, (BYTE*)szScreenSaverIsSecure, (lstrlen(szScreenSaverIsSecure)+1)*sizeof(TCHAR));
+ RegSetValueEx(hKey, _T("SCRNSAVE.EXE"), 0, REG_SZ, (BYTE*)szScrnsaveExe, (lstrlen(szScrnsaveExe)+1)*sizeof(TCHAR));
+ RegCloseKey(hKey);
+ } else dwErrCode=GetLastError();
+ } else dwErrCode=GetLastError();
+ } else dwErrCode=GetLastError();
+ }
+ break;
+ case SDSDT_CLOSERASCONNECTIONS:
+ ShutdownNow(SDSDT_SETMIRANDAOFFLINE); /* set Miranda offline */
+ /* hang up all ras connections */
+ { HMODULE hRasApiDLL=LoadLibrary(_T("RASAPI32")); /* all ascii */
+ if(hRasApiDLL!=NULL) {
+ DWORD (APIENTRY *pfnRasEnumConnections)(RASCONN*,DWORD*,DWORD*);
+ DWORD (APIENTRY *pfnRasHangUp)(HRASCONN);
+ DWORD (APIENTRY *pfnRasGetConnectStatus)(HRASCONN,RASCONNSTATUS*);
+ *(PROC*)&pfnRasEnumConnections=GetProcAddress(hRasApiDLL,"RasEnumConnectionsW");
+ *(PROC*)&pfnRasHangUp=GetProcAddress(hRasApiDLL,"RasHangUpW");
+ *(PROC*)&pfnRasGetConnectStatus=GetProcAddress(hRasApiDLL,"RasGetConnectStatusW");
+ if(pfnRasEnumConnections && pfnRasGetConnectStatus && pfnRasHangUp) {
+ RASCONN *paConn;
+ RASCONN *paConnBuf;
+ DWORD dwConnSize,dwConnItems,dwRetries;
+ RASCONNSTATUS rcs;
+ DWORD dw,dwLastTickCount;
+
+ dwConnSize=sizeof(RASCONN);
+ dwConnItems=0;
+ paConn=(RASCONN*)mir_alloc(dwConnSize);
+ dwErrCode=ERROR_NOT_ENOUGH_MEMORY;
+ if(paConn!=NULL)
+ for(dwRetries=5;dwRetries!=0;dwRetries--) { /* prevent infinite loop (rare) */
+ ZeroMemory(paConn,dwConnSize);
+ paConn[0].dwSize=sizeof(RASCONN);
+ dwErrCode=pfnRasEnumConnections(paConn,&dwConnSize,&dwConnItems);
+ if(dwErrCode!=ERROR_BUFFER_TOO_SMALL) break;
+ paConnBuf=(RASCONN*)mir_realloc(paConn,dwConnSize);
+ if(paConnBuf!=NULL) {
+ mir_free(paConn);
+ paConn=NULL;
+ dwErrCode=ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ paConn=paConnBuf;
+ }
+ if(dwErrCode==ERROR_SUCCESS || dwErrCode==ERROR_BUFFER_TOO_SMALL) {
+ for(dw=0;dw<dwConnItems;++dw) {
+ if(dwErrCode) {
+ if(pfnRasHangUp(paConn[dw].hrasconn))
+ paConn[dw].hrasconn=NULL; /* do not wait for on error */
+ } else {
+ dwErrCode=pfnRasHangUp(paConn[dw].hrasconn);
+ if(!dwErrCode) paConn[dw].hrasconn=NULL; /* do not wait for on error */
+ }
+ }
+ /* RAS does not allow to quit directly after HangUp (see docs) */
+ dwLastTickCount=GetTickCount();
+ ZeroMemory(&rcs,sizeof(RASCONNSTATUS));
+ rcs.dwSize=sizeof(RASCONNSTATUS);
+ for(dw=0;dw<dwConnItems;++dw)
+ if(paConn[dw].hrasconn!=NULL)
+ while(pfnRasGetConnectStatus(paConn[dw].hrasconn, &rcs)!=ERROR_INVALID_HANDLE) {
+ Sleep(0); /* give rest of time silce to other threads with equal priority */
+ /* infinite loop protection (3000ms defined in docs) */
+ dwRetries=GetTickCount();
+ if(dwRetries-dwLastTickCount>3000) break; /* wraparound works */
+ }
+ }
+ mir_free(paConn); /* does NULL check */
+ } else dwErrCode=GetLastError();
+ FreeLibrary(hRasApiDLL);
+ } else dwErrCode=GetLastError();
+ }
+ /* set Miranda to offline again, to remain offline with reconnection plugins */
+ ShutdownNow(SDSDT_SETMIRANDAOFFLINE);
+ break;
+ case SDSDT_REBOOT:
+ case SDSDT_SHUTDOWN:
+ if(GetSystemMetrics(SM_SHUTTINGDOWN)) { /* Win2000+, 0 on error */
+ dwErrCode=ERROR_SHUTDOWN_IN_PROGRESS;
+ break;
+ }
+ /* WinNT4/2000/XP */
+ { BOOL (WINAPI *pfnInitiateSystemShutdownEx)(const TCHAR*,const TCHAR*,DWORD,BOOL,BOOL,DWORD);
+ BOOL (WINAPI *pfnInitiateSystemShutdown)(const TCHAR*,const TCHAR*,DWORD,BOOL,BOOL);
+ *(PROC*)&pfnInitiateSystemShutdownEx=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownExW");
+ *(PROC*)&pfnInitiateSystemShutdown=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownW");
+ if(pfnInitiateSystemShutdownEx!=NULL || pfnInitiateSystemShutdown!=NULL) {
+ WinNT_SetPrivilege(SE_SHUTDOWN_NAME,TRUE);
+
+ /* does not send out WM_ENDSESSION messages, so we do it manually to
+ * give the applications the chance to save their data */
+ WinNT_SetPrivilege(SE_TCB_NAME,TRUE); /* for BSM_ALLDESKTOPS */
+ BroadcastEndSession(BSM_APPLICATIONS|BSM_ALLDESKTOPS,ENDSESSION_CLOSEAPP); /* app should close itself */
+ WinNT_SetPrivilege(SE_TCB_NAME,FALSE);
+
+ if(pfnInitiateSystemShutdownEx!=NULL) {
+ if(!pfnInitiateSystemShutdownEx(NULL,TranslateT("AutoShutdown"),0,TRUE,shutdownType==SDSDT_REBOOT,SHTDN_REASON_MAJOR_OTHER|SHTDN_REASON_MINOR_OTHER|SHTDN_REASON_FLAG_PLANNED))
+ dwErrCode=GetLastError();
+ } else if(!pfnInitiateSystemShutdown(NULL,TranslateT("AutoShutdown"),0,TRUE,shutdownType==SDSDT_REBOOT))
+ dwErrCode=GetLastError();
+
+ /* cleanly close Miranda */
+ if(!dwErrCode) ShutdownNow(SDSDT_CLOSEMIRANDA);
+ break;
+ }
+ }
+ /* fall through for Win9x */
+ case SDSDT_LOGOFF:
+ { UINT flags;
+ switch(shutdownType) {
+ case SDSDT_LOGOFF: flags=EWX_LOGOFF; break;
+ case SDSDT_REBOOT: flags=EWX_REBOOT; break;
+ default: flags=EWX_SHUTDOWN|EWX_POWEROFF;
+ }
+ if(shutdownType==SDSDT_LOGOFF && IsWinVer2000Plus() && !WinNT_IsWorkStationLocked())
+ flags|=EWX_FORCEIFHUNG; /* only considered for WM_ENDSESSION messages */
+ else flags|=EWX_FORCE; /* must be used when workstation locked */
+
+ if(flags&EWX_FORCE) {
+ /* EWX_FORCE does not send out WM_ENDSESSION messages, so we do it
+ * manually to give the applications the chance to save their data */
+ BroadcastEndSession(BSM_APPLICATIONS,(shutdownType==SDSDT_LOGOFF)?ENDSESSION_LOGOFF:0);
+
+ /* Windows Me/98/95 (msdn): Because of the design of the shell,
+ * calling ExitWindowsEx with EWX_FORCE fails to completely log off
+ * the user (the system terminates the applications and displays the
+ * Enter Windows Password dialog box, however, the user's desktop remains.)
+ * To log off the user forcibly, terminate the Explorer process before calling
+ * ExitWindowsEx with EWX_LOGOFF and EWX_FORCE. */
+ }
+ if(!ExitWindowsEx(flags,SHTDN_REASON_MAJOR_OTHER|SHTDN_REASON_MINOR_OTHER|SHTDN_REASON_FLAG_PLANNED))
+ dwErrCode=GetLastError();
+ /* cleanly close Miranda */
+ if(!dwErrCode) ShutdownNow(SDSDT_CLOSEMIRANDA);
+ }
+ break;
+ }
+ return dwErrCode;
+}
+
+/************************* Shutdown Dialog ****************************/
+
+#define M_START_SHUTDOWN (WM_APP+111)
+#define M_UPDATE_COUNTDOWN (WM_APP+112)
+static INT_PTR CALLBACK ShutdownDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ BYTE shutdownType=(BYTE)GetWindowLongPtr(hwndDlg, DWLP_USER);
+ WORD countdown=(WORD)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA);
+ static BOOL (WINAPI *pfnLockSetForegroundWindow)(UINT);
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ hwndShutdownDlg=hwndDlg;
+ SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG)lParam);
+ TranslateDialogDefault(hwndDlg);
+
+ if(lParam==SDSDT_SHUTDOWN || lParam==SDSDT_REBOOT || lParam==SDSDT_LOGOFF)
+ ShowWindow(GetDlgItem(hwndDlg,IDC_TEXT_UNSAVEDWARNING),SW_SHOW);
+ SendDlgItemMessage(hwndDlg,IDC_ICON_HEADER,STM_SETIMAGE,IMAGE_ICON,(LPARAM)IcoLib_GetIcon("AutoShutdown_Header"));
+ { HFONT hBoldFont;
+ LOGFONT lf;
+ if(GetObject((HFONT)SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_GETFONT,0,0),sizeof(lf),&lf)) {
+ lf.lfWeight=FW_BOLD;
+ hBoldFont=CreateFontIndirect(&lf);
+ }
+ else hBoldFont=NULL;
+ SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_SETFONT,(WPARAM)hBoldFont,FALSE);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, (LONG)hBoldFont);
+ }
+ { WORD countdown=DBGetContactSettingWord(NULL,"AutoShutdown","ConfirmDlgCountdown",SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT);
+ if(countdown<3) countdown=SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT;
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, countdown);
+ SendMessage(hwndDlg,M_UPDATE_COUNTDOWN,0,countdown);
+ }
+ SkinPlaySound("AutoShutdown_Countdown");
+ if(!SetTimer(hwndDlg,1,1000,NULL)) PostMessage(hwndDlg,M_START_SHUTDOWN,0,0);
+ Utils_RestoreWindowPositionNoSize(hwndDlg,NULL,"AutoShutdown","ConfirmDlg_");
+
+ /* disallow foreground window changes (WinMe/2000+) */
+ SetForegroundWindow(hwndDlg);
+ *(PROC*)&pfnLockSetForegroundWindow=GetProcAddress(GetModuleHandleA("USER32"),"LockSetForegroundWindow");
+ if(pfnLockSetForegroundWindow!=NULL)
+ pfnLockSetForegroundWindow(LSFW_LOCK);
+
+ SendMessage(hwndDlg,WM_NEXTDLGCTL,(WPARAM)GetDlgItem(hwndDlg,IDCANCEL),TRUE);
+ return FALSE; /* focus set on cancel */
+ case WM_DESTROY:
+ { HFONT hFont;
+ HICON hIcon;
+ hwndShutdownDlg=NULL;
+ ShowWindow(hwndDlg,SW_HIDE);
+ /* reallow foreground window changes (WinMe/2000+) */
+ if(pfnLockSetForegroundWindow) pfnLockSetForegroundWindow(LSFW_UNLOCK);
+ Utils_SaveWindowPosition(hwndDlg,NULL,"AutoShutdown","ConfirmDlg_");
+ hIcon=(HICON)SendDlgItemMessage(hwndDlg,IDC_ICON_HEADER,STM_SETIMAGE,IMAGE_ICON,(LPARAM)NULL);
+ IcoLib_ReleaseIcon(hIcon); /* does NULL check */
+ hFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_GETFONT,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_TEXT_HEADER,WM_SETFONT,(WPARAM)NULL,FALSE); /* no return value */
+ if(hFont!=NULL) DeleteObject(hFont);
+ return TRUE;
+ }
+ case M_START_SHUTDOWN:
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_BUTTON_SHUTDOWNNOW))) {
+ DWORD dwErrCode;
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_SHUTDOWNNOW),FALSE);
+ ShowWindow(hwndDlg,SW_HIDE); /* get rid of the dialog immediately */
+ dwErrCode=ShutdownNow(shutdownType);
+ if(dwErrCode!=ERROR_SUCCESS) {
+ char *pszErr;
+ pszErr=GetWinErrorDescription(dwErrCode);
+ ShowInfoMessage(NIIF_ERROR,Translate("Automatic Shutdown Error"),Translate("The shutdown process failed!\nReason: %s"),(pszErr!=NULL)?pszErr:Translate("Unknown"));
+ if(pszErr!=NULL) LocalFree(pszErr);
+ }
+ DestroyWindow(hwndDlg);
+ }
+ return TRUE;
+ case WM_TIMER:
+ if(countdown) {
+ --countdown;
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, countdown);
+ if(countdown==27 || countdown==24 || countdown==21 || countdown==19 ||
+ countdown==17 || countdown==15 || countdown==13 || countdown==11 ||
+ countdown<=10)
+ SkinPlaySound("AutoShutdown_Countdown");
+ }
+ else KillTimer(hwndDlg,wParam); /* countdown finished */
+ PostMessage(hwndDlg,M_UPDATE_COUNTDOWN,0,countdown);
+ return TRUE;
+ case M_UPDATE_COUNTDOWN: /* lParam=(WORD)countdown */
+ { TCHAR szText[256];
+ TCHAR *desc[]={_T("Miranda IM is going to be automatically closed in %u second(s)."),
+ _T("All Miranda IM protocols are going to be set to offline in %u second(s)."),
+ _T("You will be logged off automatically in %u second(s)."),
+ _T("The computer will automatically be restarted in %u second(s)."),
+ _T("The computer will automatically be set to standby mode in %u second(s)."),
+ _T("The computer will automatically be set to hibernate mode in %u second(s)."),
+ _T("The workstation will automatically get locked in %u second(s)."),
+ _T("All dialup connections will be closed in %u second(s)."),
+ _T("The computer will automatically be shut down in %u second(s).")};
+ mir_sntprintf(szText,SIZEOF(szText),TranslateTS(desc[shutdownType-1]),lParam);
+ SetDlgItemText(hwndDlg,IDC_TEXT_HEADER,szText);
+ /* countdown finished */
+ if(!lParam) PostMessage(hwndDlg,M_START_SHUTDOWN,0,0);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_BUTTON_SHUTDOWNNOW:
+ KillTimer(hwndDlg,1);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, 0);
+ SendMessage(hwndDlg,M_UPDATE_COUNTDOWN,0,(LONG)0);
+ PostMessage(hwndDlg,M_START_SHUTDOWN,0,0);
+ return TRUE;
+ case IDCANCEL: /* WM_CLOSE */
+ if(countdown) {
+ KillTimer(hwndDlg,1);
+ DestroyWindow(hwndDlg);
+ }
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+/************************* Services ***********************************/
+
+INT_PTR ServiceShutdown(WPARAM wParam,LPARAM lParam)
+{
+ /* passing 0 as wParam is only to be used internally, undocumented */
+ if(!wParam) wParam=DBGetContactSettingByte(NULL,"AutoShutdown","ShutdownType",SETTING_SHUTDOWNTYPE_DEFAULT);
+ if(!IsShutdownTypeEnabled((BYTE)wParam)) return 1; /* does shutdownType range check */
+ if((BOOL)lParam && hwndShutdownDlg!=NULL) return 2;
+
+ /* ask others if allowed */
+ if(NotifyEventHooks(hEventOkToShutdown,wParam,lParam)) {
+ OutputDebugStringA("automatic shutdown denied by event hook\n"); /* all ascii */
+ return 3;
+ }
+ /* tell others */
+ NotifyEventHooks(hEventShutdown,wParam,lParam);
+ /* show dialog */
+ if(lParam && DBGetContactSettingByte(NULL,"AutoShutdown","ShowConfirmDlg",SETTING_SHOWCONFIRMDLG_DEFAULT))
+ if(CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SHUTDOWNNOW), NULL, ShutdownDlgProc, (LPARAM)(BYTE)wParam) != NULL)
+ return 0;
+ /* show error */
+ { DWORD dwErrCode;
+ dwErrCode=ShutdownNow((BYTE)wParam);
+ if(dwErrCode!=ERROR_SUCCESS) {
+ char *pszErr;
+ pszErr=GetWinErrorDescription(dwErrCode);
+ ShowInfoMessage(NIIF_ERROR,Translate("Automatic Shutdown Error"),Translate("Inititiating the shutdown process failed!\nReason: %s"),(pszErr!=NULL)?pszErr:Translate("Unknown"));
+ if(pszErr!=NULL) LocalFree(pszErr);
+ return 4;
+ }
+ }
+ return 0;
+}
+
+INT_PTR ServiceIsTypeEnabled(WPARAM wParam,LPARAM lParam)
+{
+ return IsShutdownTypeEnabled((BYTE)wParam); /* does shutdownType range check */
+}
+
+INT_PTR ServiceGetTypeDescription(WPARAM wParam,LPARAM lParam)
+{
+ TCHAR *pszDesc;
+ const TCHAR *apszShort[]={_T("Close Miranda IM"),_T("Set Miranda IM offline"),_T("Log off user"),
+ _T("Restart computer"),_T("Shutdown computer"),_T("Standby mode"),_T("Hibernate mode"),
+ _T("Lock workstation"),_T("Hang up dialup connections"),_T("Close Miranda IM"),
+ _T("Set Miranda IM offline"),_T("Log off user"),_T("Restart computer"),_T("Shutdown computer"),
+ _T("Standby mode"),_T("Hibernate mode"),_T("Lock workstation"),_T("Hang up dialup connections")};
+ const TCHAR *apszLong[]={_T("Sets all Miranda IM protocols to offline and closes Miranda IM."),
+ _T("Sets all Miranda IM protocols to offline."),
+ _T("Logs the current Windows user off so that another user can log in."),
+ _T("Shuts down Windows and then restarts Windows."),
+ _T("Closes all running programs and shuts down Windows to a point at which it is safe to turn off the power."),
+ _T("Saves the current Windows session in memory and sets the system to suspend mode."),
+ _T("Saves the current Windows session on harddisc, so that the power can be turned off."),
+ _T("Locks the computer. To unlock the computer, you must log in."),
+ _T("Sets all protocols to offline and closes all RAS connections.")};
+ /* shutdownType range check */
+ if(!wParam || (BYTE)wParam>SDSDT_MAX) return (int)NULL;
+ /* select description */
+ pszDesc=(TCHAR*)((lParam&GSTDF_LONGDESC)?apszLong:apszShort)[wParam-1];
+ if(!(lParam&GSTDF_UNTRANSLATED)) pszDesc=TranslateTS(pszDesc);
+ /* convert as needed */
+ if(!(lParam&GSTDF_UNICODE)) {
+ static char szConvBuf[128];
+ char *buf=u2a(pszDesc);
+ if(buf==NULL) return (int)NULL;
+ lstrcpynA(szConvBuf,buf,sizeof(szConvBuf));
+ mir_free(buf);
+ return (int)szConvBuf;
+ }
+ return (int)pszDesc;
+}
+
+/************************* Misc ***************************************/
+
+void InitShutdownSvc(void)
+{
+ /* Shutdown Dialog */
+ hwndShutdownDlg=NULL;
+ SkinAddNewSoundBundled("AutoShutdown_Countdown",Translate("Alerts"),Translate("Automatic Shutdown Countdown"),"Sounds\\","countdown.wav");
+ /* Services */
+ hEventOkToShutdown=CreateHookableEvent(ME_AUTOSHUTDOWN_OKTOSHUTDOWN);
+ hEventShutdown=CreateHookableEvent(ME_AUTOSHUTDOWN_SHUTDOWN);
+ hServiceShutdown = CreateServiceFunction(MS_AUTOSHUTDOWN_SHUTDOWN, ServiceShutdown);
+ hServiceIsTypeEnabled = CreateServiceFunction(MS_AUTOSHUTDOWN_ISTYPEENABLED, ServiceIsTypeEnabled);
+ hServiceGetTypeDesc = CreateServiceFunction(MS_AUTOSHUTDOWN_GETTYPEDESCRIPTION, ServiceGetTypeDescription);
+}
+
+void UninitShutdownSvc(void)
+{
+ /* Shutdown Dialog */
+ if(hwndShutdownDlg!=NULL) DestroyWindow(hwndShutdownDlg);
+ /* Services */
+ DestroyServiceFunction(hServiceShutdown);
+ DestroyServiceFunction(hServiceIsTypeEnabled);
+ DestroyServiceFunction(hServiceGetTypeDesc);
+ DestroyHookableEvent(hEventOkToShutdown);
+ DestroyHookableEvent(hEventShutdown);
+}
diff --git a/plugins/AutoShutdown/src/shutdownsvc.h b/plugins/AutoShutdown/src/shutdownsvc.h
new file mode 100644
index 0000000000..639d02a7fa
--- /dev/null
+++ b/plugins/AutoShutdown/src/shutdownsvc.h
@@ -0,0 +1,29 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Services */
+INT_PTR ServiceShutdown(WPARAM wParam,LPARAM lParam);
+INT_PTR ServiceIsTypeEnabled(WPARAM wParam,LPARAM lParam);
+INT_PTR ServiceGetTypeDescription(WPARAM wParam,LPARAM lParam);
+
+/* Misc */
+void InitShutdownSvc(void);
+void UninitShutdownSvc(void);
diff --git a/plugins/AutoShutdown/src/utils.cpp b/plugins/AutoShutdown/src/utils.cpp
new file mode 100644
index 0000000000..c0128f80d6
--- /dev/null
+++ b/plugins/AutoShutdown/src/utils.cpp
@@ -0,0 +1,342 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/************************* String *********************************/
+
+// mir_free() the return value
+char* u2a(const WCHAR *pszUnicode)
+{
+ int codepage,cch;
+ char *psz;
+ DWORD flags;
+
+ if(pszUnicode==NULL) return NULL;
+ codepage=CallService(MS_LANGPACK_GETCODEPAGE,0,0);
+ /* without WC_COMPOSITECHECK some characters might get out strange (see MS blog) */
+ cch=WideCharToMultiByte(codepage,flags=WC_COMPOSITECHECK,pszUnicode,-1,NULL,0,NULL,NULL);
+ if(!cch) cch=WideCharToMultiByte(codepage,flags=0,pszUnicode,-1,NULL,0,NULL,NULL);
+ if(!cch) return NULL;
+
+ psz=(char*)mir_alloc(cch);
+ if(psz!=NULL && !WideCharToMultiByte(codepage,flags,pszUnicode,-1,psz,cch,NULL,NULL)){
+ mir_free(psz);
+ return NULL;
+ }
+ return psz;
+}
+
+void TrimString(TCHAR *pszStr)
+{
+ int i;
+ TCHAR *psz,szChars[]=_T(" \r\n\t");
+ for(i=0;i<SIZEOF(szChars);++i) {
+ /* trim end */
+ psz=&pszStr[lstrlen(pszStr)-1];
+ while(pszStr[0] && *psz==szChars[i]) {
+ *psz=0;
+ psz=CharPrev(pszStr,psz);
+ }
+ /* trim beginning */
+ for(psz=pszStr;(*psz && *psz==szChars[i]);psz=CharNext(psz));
+ MoveMemory(pszStr,psz,(lstrlen(psz)+1)*sizeof(TCHAR));
+ }
+}
+
+/************************* Error Output ***************************/
+
+static void MessageBoxIndirectFree(void *param)
+{
+ MSGBOXPARAMSA *mbp = (MSGBOXPARAMSA*)param;
+ MessageBoxIndirectA(mbp);
+ mir_free((char*)mbp->lpszCaption); /* does NULL check */
+ mir_free((char*)mbp->lpszText); /* does NULL check */
+ mir_free(mbp);
+}
+
+void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...)
+{
+ char szText[256]; /* max for systray */
+ MSGBOXPARAMSA *mbp;
+
+ va_list va;
+ va_start(va,pszTextFmt);
+ mir_vsnprintf(szText,SIZEOF(szText),pszTextFmt,va);
+ va_end(va);
+
+ if(ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) {
+ MIRANDASYSTRAYNOTIFY msn;
+ msn.cbSize=sizeof(msn);
+ msn.szProto=NULL;
+ msn.szInfoTitle=(char*)pszTitle;
+ msn.szInfo=(char*)szText;
+ msn.uTimeout=30000; /* max timeout */
+ msn.dwInfoFlags=flags;
+ if(!CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY,0,(LPARAM)&msn))
+ return; /* success */
+ }
+
+ mbp=(MSGBOXPARAMSA*)mir_calloc(sizeof(*mbp));
+ if(mbp==NULL) return;
+ mbp->cbSize=sizeof(*mbp);
+ mbp->lpszCaption=mir_strdup(pszTitle);
+ mbp->lpszText=mir_strdup(szText);
+ mbp->dwStyle=MB_OK|MB_SETFOREGROUND|MB_TASKMODAL;
+ mbp->dwLanguageId=LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0));
+ switch(flags&NIIF_ICON_MASK) {
+ case NIIF_INFO: mbp->dwStyle|=MB_ICONINFORMATION; break;
+ case NIIF_WARNING: mbp->dwStyle|=MB_ICONWARNING; break;
+ case NIIF_ERROR: mbp->dwStyle|=MB_ICONERROR;
+ }
+ mir_forkthread(MessageBoxIndirectFree, mbp);
+}
+
+// LocalFree() the return value
+char* GetWinErrorDescription(DWORD dwLastError)
+{
+ char *buf=NULL;
+ DWORD flags=FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM;
+ if(!FormatMessageA(flags,NULL,dwLastError,LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0)),(char*)&buf,0,NULL))
+ if(GetLastError()==ERROR_RESOURCE_LANG_NOT_FOUND)
+ FormatMessageA(flags,NULL,dwLastError,0,(char*)&buf,0,NULL);
+ return buf;
+}
+
+/************************* Time ***********************************/
+
+BOOL SystemTimeToTimeStamp(SYSTEMTIME *st,time_t *timestamp)
+{
+ struct tm ts;
+ ts.tm_isdst=-1; /* daylight saving time (-1=compute) */
+ ts.tm_sec=st->wSecond; /* 0-59 */
+ ts.tm_min=st->wMinute; /* 0-59 */
+ ts.tm_hour=st->wHour; /* 0-23 */
+ ts.tm_mday=st->wDay; /* 1-31 */
+ ts.tm_wday=st->wDayOfWeek; /* 0-6 (Sun-Sat) */
+ ts.tm_mon=st->wMonth-1; /* 0-11 (Jan-Dec) */
+ ts.tm_year=st->wYear-1900; /* current year minus 1900 */
+ ts.tm_yday=0; /* 0-365 (Jan1=0) */
+ *timestamp=mktime(&ts);
+ return (*timestamp!=-1);
+}
+
+BOOL TimeStampToSystemTime(time_t timestamp,SYSTEMTIME *st)
+{
+ struct tm *ts = {0};
+ localtime_s(ts, &timestamp); /* statically alloced, local time correction */
+ if(ts==NULL) return FALSE;
+ st->wMilliseconds=0; /* 0-999 (not given in tm) */
+ st->wSecond=(WORD)ts->tm_sec; /* 0-59 */
+ st->wMinute=(WORD)ts->tm_min; /* 0-59 */
+ st->wHour=(WORD)ts->tm_hour; /* 0-23 */
+ st->wDay=(WORD)ts->tm_mday; /* 1-31 */
+ st->wDayOfWeek=(WORD)ts->tm_wday; /* 0-6 (Sun-Sat) */
+ st->wMonth=(WORD)(ts->tm_mon+1); /* 1-12 (Jan-Dec) */
+ st->wYear=(WORD)(ts->tm_year+1900); /* 1601-30827 */
+ return TRUE;
+}
+
+BOOL GetFormatedCountdown(TCHAR *pszOut,int nSize,time_t countdown)
+{
+ static BOOL fInited=FALSE;
+ static int (WINAPI *pfnStrFromTimeInterval)(TCHAR*,UINT,DWORD,int);
+ static int (WINAPI *pfnGetDurationFormat)(LCID,DWORD,const SYSTEMTIME*,double,WCHAR*,WCHAR*,int);
+ /* Init */
+ if(!fInited) {
+ *(PROC*)&pfnGetDurationFormat=GetProcAddress(GetModuleHandleA("KERNEL32"),"GetDurationFormat");
+ if(pfnGetDurationFormat==NULL) {
+ HMODULE hShlwDLL=LoadLibraryA("SHLWAPI"); /* all ascii */
+ *(PROC*)&pfnStrFromTimeInterval=GetProcAddress(hShlwDLL,"StrFromTimeIntervalW");
+ }
+ fInited=TRUE;
+ }
+ /* WinVista */
+ if(pfnGetDurationFormat!=NULL) {
+ SYSTEMTIME st;
+ LCID locale;
+ locale=(LCID)CallService(MS_LANGPACK_GETLOCALE,0,0);
+ if(TimeStampToSystemTime(countdown,&st))
+ if(pfnGetDurationFormat(locale,0,&st,0,NULL,pszOut,nSize))
+ return TRUE;
+ return FALSE;
+ }
+ /* Win9x/NT/XP */
+ if(pfnStrFromTimeInterval!=NULL)
+ return pfnStrFromTimeInterval(pszOut,nSize,(countdown>(MAXDWORD/1000))?MAXDWORD:(countdown*1000),10)!=0;
+ return FALSE;
+}
+
+BOOL GetFormatedDateTime(TCHAR *pszOut,int nSize,time_t timestamp,BOOL fShowDateEvenToday)
+{
+ SYSTEMTIME st,stNow;
+ LCID locale;
+ locale=(LCID)CallService(MS_LANGPACK_GETLOCALE,0,0);
+ GetLocalTime(&stNow);
+ TimeStampToSystemTime(timestamp,&st);
+ /* today: no need to show the date */
+ if(!fShowDateEvenToday && st.wDay==stNow.wDay && st.wMonth==stNow.wMonth && st.wYear==stNow.wYear)
+ return GetTimeFormat(locale,((st.wSecond==0)?TIME_NOSECONDS:0)|TIME_FORCE24HOURFORMAT,&st,NULL,pszOut,nSize)!=0;
+ /* show both date and time */
+ { TCHAR szDate[128],szTime[128];
+ if(!GetTimeFormat(locale,((st.wSecond==0)?TIME_NOSECONDS:0)|TIME_FORCE24HOURFORMAT,&st,NULL,szTime,SIZEOF(szTime)))
+ return FALSE;
+ if(!GetDateFormat(locale,DATE_SHORTDATE,&st,NULL,szDate,SIZEOF(szDate)))
+ return FALSE;
+ mir_sntprintf(pszOut,nSize,_T("%s %s"),szTime,szDate);
+ return TRUE;
+ }
+}
+
+/************************* Fonts & Colors *************************/
+
+int FontService_RegisterFont(const char *pszDbModule,const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDescription,int position,BOOL bAllowEffects,LOGFONT *plfDefault,COLORREF clrDefault)
+{
+ FontIDT fid;
+ ZeroMemory(&fid,sizeof(fid));
+ fid.cbSize=sizeof(fid);
+ lstrcpynA(fid.dbSettingsGroup,pszDbModule,sizeof(fid.dbSettingsGroup)); /* buffer safe */
+ lstrcpynA(fid.prefix,pszDbName,sizeof(fid.prefix)); /* buffer safe */
+ lstrcpyn(fid.group,pszSection,SIZEOF(fid.group)); /* buffer safe */
+ lstrcpyn(fid.name,pszDescription,SIZEOF(fid.name)); /* buffer safe */
+ fid.flags=FIDF_ALLOWREREGISTER;
+ if(bAllowEffects) fid.flags|=FIDF_ALLOWEFFECTS;
+ fid.order=position;
+ if(plfDefault!=NULL) {
+ fid.flags|=FIDF_DEFAULTVALID;
+ fid.deffontsettings.colour=clrDefault;
+ fid.deffontsettings.size=(char)plfDefault->lfHeight;
+ if(plfDefault->lfItalic) fid.deffontsettings.style|=DBFONTF_ITALIC;
+ if(plfDefault->lfWeight!=FW_NORMAL) fid.deffontsettings.style|=DBFONTF_BOLD;
+ if(plfDefault->lfUnderline) fid.deffontsettings.style|=DBFONTF_UNDERLINE;
+ if(plfDefault->lfStrikeOut) fid.deffontsettings.style|=DBFONTF_STRIKEOUT;
+ fid.deffontsettings.charset=plfDefault->lfCharSet;
+ lstrcpyn(fid.deffontsettings.szFace,plfDefault->lfFaceName,SIZEOF(fid.deffontsettings.szFace)); /* buffer safe */
+ }
+ FontRegisterT(&fid);
+ return 0;
+}
+
+int FontService_GetFont(const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF *pclr,LOGFONT *plf)
+{
+ FontIDT fid;
+ fid.cbSize=sizeof(fid);
+ lstrcpyn(fid.group,pszSection,SIZEOF(fid.group)); /* buffer sfae */
+ lstrcpyn(fid.name,pszDescription,SIZEOF(fid.name)); /* buffer safe */
+ *pclr=(COLORREF)CallService(MS_FONT_GETT,(WPARAM)&fid,(LPARAM)plf); /* uses fallback font on error */
+ return (int)*pclr==-1;
+}
+
+int FontService_RegisterColor(const char *pszDbModule,const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF clrDefault)
+{
+ ColourIDT cid;
+ ZeroMemory(&cid,sizeof(cid));
+ cid.cbSize=sizeof(cid);
+ cid.defcolour=clrDefault;
+ lstrcpynA(cid.dbSettingsGroup,pszDbModule,sizeof(cid.dbSettingsGroup)); /* buffer safe */
+ lstrcpynA(cid.setting,pszDbName,sizeof(cid.setting)); /* buffer safe */
+ lstrcpyn(cid.group,pszSection,SIZEOF(cid.group)); /* buffer safe */
+ lstrcpyn(cid.name,pszDescription,SIZEOF(cid.name)); /* buffer safe */
+ ColourRegisterT(&cid);
+ return 0;
+}
+
+int FontService_GetColor(const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF *pclr)
+{
+ ColourIDT cid;
+ ZeroMemory(&cid,sizeof(cid));
+ cid.cbSize=sizeof(cid);
+ lstrcpyn(cid.group,pszSection,sizeof(cid.group)); /* buffer safe */
+ lstrcpyn(cid.name,pszDescription,sizeof(cid.name)); /* buffer safe */
+ *pclr=(COLORREF)CallService(MS_COLOUR_GETT,(WPARAM)&cid,0);
+ return (int)*pclr==-1;
+}
+
+/************************* Skin ***********************************/
+
+HANDLE IcoLib_AddIconRes(const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDesc,HINSTANCE hInst,WORD idRes,BOOL fLarge)
+{
+ SKINICONDESC sid;
+ TCHAR szFileName[MAX_PATH];
+ sid.cbSize=sizeof(SKINICONDESC);
+ sid.pszName=(char*)pszDbName;
+ sid.ptszSection=(TCHAR*)pszSection;
+ sid.ptszDescription=(TCHAR*)pszDesc;
+ sid.ptszDefaultFile=szFileName;
+ sid.iDefaultIndex=-idRes;
+ sid.cx=GetSystemMetrics(fLarge?SM_CXICON:SM_CXSMICON);
+ sid.cy=GetSystemMetrics(fLarge?SM_CYICON:SM_CYSMICON);
+ sid.hDefaultIcon=NULL;
+ sid.flags=SIDF_SORTED|SIDF_ALL_TCHAR;
+ if(!GetModuleFileName(hInst,szFileName,SIZEOF(szFileName)))
+ return NULL;
+ return Skin_AddIcon(&sid);
+}
+
+HICON IcoLib_GetIcon(const char *pszDbName)
+{
+ return (HICON)CallService(MS_SKIN2_GETICON,0,(LPARAM)pszDbName);
+}
+
+int IcoLib_ReleaseIcon(HICON hIcon)
+{
+ return CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0);
+}
+
+int SkinAddNewSoundBundled(const char *pszDbName,const char *pszSection,const char *pszDesc,const char *pszSubDir,const char *pszDefaultFile)
+{
+ SKINSOUNDDESCEX ssd;
+ char szFile[MAX_PATH],*p;
+ HANDLE hFile;
+
+ ssd.cbSize=sizeof(ssd);
+ ssd.pszName=pszDbName;
+ ssd.pszSection=pszSection;
+ ssd.pszDescription=pszDesc;
+ ssd.pszDefaultFile=NULL;
+ if(GetModuleFileNameA(NULL,szFile,SIZEOF(szFile)-lstrlenA(pszSubDir)-lstrlenA(pszDefaultFile))) {
+ p=strrchr(szFile,'\\');
+ if(p!=NULL) *(++p)=0;
+ lstrcatA(lstrcatA(szFile,pszSubDir),pszDefaultFile); /* buffer safe */
+ /* check if sound file exist */
+ hFile=CreateFileA(szFile,0,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
+ if(hFile!=INVALID_HANDLE_VALUE) {
+ ssd.pszDefaultFile=szFile; /* MS_UTILS_PATHTORELATIVET called automatically */
+ CloseHandle(hFile);
+ }
+ }
+ Skin_AddSound(&ssd);
+ return 0;
+}
+
+void AddHotkey()
+{
+ HOTKEYDESC hkd = {0};
+ hkd.cbSize = sizeof(hkd);
+ hkd.dwFlags = HKD_TCHAR;
+ hkd.pszName = "AutoShutdown_Toggle";
+ hkd.ptszDescription = _T("Toggle Automatic Shutdown");
+ hkd.ptszSection = _T("Main");
+ hkd.pszService = "AutoShutdown/MenuCommand";
+ hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL|HOTKEYF_SHIFT, 'T') | HKF_MIRANDA_LOCAL;
+ hkd.lParam = FALSE;
+ Hotkey_Register(&hkd);
+}
diff --git a/plugins/AutoShutdown/src/utils.h b/plugins/AutoShutdown/src/utils.h
new file mode 100644
index 0000000000..d70dd980d7
--- /dev/null
+++ b/plugins/AutoShutdown/src/utils.h
@@ -0,0 +1,48 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* String */
+WCHAR *a2u(const char *pszAnsi);
+char *u2a(const WCHAR *pszUnicode);
+void TrimString(TCHAR *pszStr);
+
+/* Error Output */
+void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...);
+char* GetWinErrorDescription(DWORD dwLastError);
+
+/* Time */
+BOOL SystemTimeToTimeStamp(SYSTEMTIME *st,time_t *timestamp);
+BOOL TimeStampToSystemTime(time_t timestamp,SYSTEMTIME *st);
+BOOL GetFormatedCountdown(TCHAR *pszOut,int nSize,time_t countdown);
+BOOL GetFormatedDateTime(TCHAR *pszOut,int nSize,time_t timestamp,BOOL fShowDateEvenToday);
+
+/* Fonts & Colors */
+int FontService_RegisterFont(const char *pszDbModule,const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDescription,int position,BOOL bAllowEffects,LOGFONT *plfDefault,COLORREF clrDefault);
+int FontService_GetFont(const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF *pclr,LOGFONT *plf);
+int FontService_RegisterColor(const char *pszDbModule,const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF clrDefault);
+int FontService_GetColor(const TCHAR *pszSection,const TCHAR *pszDescription,COLORREF *pclr);
+
+/* Skin */
+HANDLE IcoLib_AddIconRes(const char *pszDbName,const TCHAR *pszSection,const TCHAR *pszDesc,HINSTANCE hInst,WORD idRes,BOOL fLarge);
+HICON IcoLib_GetIcon(const char *pszDbName);
+int IcoLib_ReleaseIcon(HICON hIcon);
+int SkinAddNewSoundBundled(const char *pszDbName,const char *pszSection,const char *pszDesc,const char *pszSubDir,const char *pszDefaultFile);
+void AddHotkey();
diff --git a/plugins/AutoShutdown/src/version.h b/plugins/AutoShutdown/src/version.h
new file mode 100644
index 0000000000..70dd82fe01
--- /dev/null
+++ b/plugins/AutoShutdown/src/version.h
@@ -0,0 +1,24 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(1,4,0,2)
+#define FILE_VERSION 1,4,0,2
+#define FILE_VERSION_STR "1.4.0.2"
diff --git a/plugins/AutoShutdown/src/watcher.cpp b/plugins/AutoShutdown/src/watcher.cpp
new file mode 100644
index 0000000000..3121248cba
--- /dev/null
+++ b/plugins/AutoShutdown/src/watcher.cpp
@@ -0,0 +1,390 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Msg Shutdown */
+static HANDLE hHookEventAdded;
+/* Transfer Shutdown */
+static HANDLE hHookProtoAck;
+/* Idle Shutdown */
+static HANDLE hHookIdleChanged;
+/* Status Shutdown */
+static HANDLE hHookSettingChanged;
+/* Weather Shutdown */
+static HANDLE hHookWeatherUpdated;
+/* Overheat Shutdown */
+static HANDLE hHookHddOverheat;
+/* Services */
+static HANDLE hServiceStartWatcher,hServiceStopWatcher,hServiceIsEnabled;
+static HANDLE hEventWatcherChanged;
+/* Misc */
+static HANDLE hHookModulesLoaded;
+
+/************************* Shared *************************************/
+
+static WORD currentWatcherType;
+
+static void __stdcall MainThreadMapping(void *param)
+{
+ HANDLE *phDoneEvent = (HANDLE*)param;
+ ServiceShutdown(0,TRUE); /* ensure main thread (for cpu usage shutdown) */
+ ServiceStopWatcher(0,0);
+ if(*phDoneEvent!=NULL) SetEvent(*phDoneEvent);
+}
+
+static void __inline ShutdownAndStopWatcher(void)
+{
+ HANDLE hDoneEvent;
+ hDoneEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
+ if(CallFunctionAsync(MainThreadMapping, &hDoneEvent))
+ if(hDoneEvent!=NULL) WaitForSingleObject(hDoneEvent,INFINITE);
+ if(hDoneEvent!=NULL) CloseHandle(hDoneEvent);
+}
+
+/************************* Msg Shutdown *******************************/
+
+// ppBlob might get reallocated, must have been allocated using mir_alloc()
+static TCHAR* GetMessageText(BYTE **ppBlob,DWORD *pcbBlob)
+{
+ DWORD cb;
+ (*ppBlob)[*pcbBlob]=0;
+ cb=lstrlenA((char*)*ppBlob);
+ /* use Unicode data if present */
+ if(*pcbBlob>(cb+3)) {
+ (*ppBlob)[*pcbBlob-1]=0;
+ return (WCHAR*)&(*ppBlob)[cb];
+ }
+ /* no Unicode data present, convert from ANSI */
+ { int len;
+ BYTE *buf;
+ len=MultiByteToWideChar(CP_ACP,0,(char*)*ppBlob,-1,NULL,0);
+ if(!len) return NULL;
+ buf=(BYTE*)mir_realloc(*ppBlob,(*pcbBlob)+(len*sizeof(WCHAR)));
+ if(buf==NULL) return NULL;
+ *pcbBlob+=len*sizeof(WCHAR);
+ *ppBlob=buf;
+ buf=&(*ppBlob)[cb];
+ MultiByteToWideChar(CP_ACP,0,(char*)*ppBlob,-1,(WCHAR*)buf,len);
+ ((WCHAR*)buf)[len-1]=0;
+ return (WCHAR*)buf;
+ }
+}
+
+static int MsgEventAdded(WPARAM wParam,LPARAM lParam)
+{
+ if(currentWatcherType&SDWTF_MESSAGE) {
+ DBEVENTINFO dbe;
+ dbe.cbSize=sizeof(dbe);
+ dbe.cbBlob=(DWORD)CallService(MS_DB_EVENT_GETBLOBSIZE,(WPARAM)lParam,0);
+ dbe.pBlob=(BYTE*)mir_alloc(dbe.cbBlob+2); /* ensure term zero */
+ if(dbe.pBlob==NULL) return 0;
+ if(!CallService(MS_DB_EVENT_GET,(WPARAM)lParam,(LPARAM)&dbe))
+ if(dbe.eventType==EVENTTYPE_MESSAGE && !(dbe.flags&DBEF_SENT)) {
+ DBVARIANT dbv;
+ TCHAR *pszMsg;
+ if(!DBGetContactSettingTString(NULL,"AutoShutdown","Message",&dbv)) {
+ TrimString(dbv.ptszVal);
+ pszMsg=GetMessageText(&dbe.pBlob,&dbe.cbBlob);
+ if(pszMsg!=NULL && _tcsstr(pszMsg,dbv.ptszVal)!=NULL)
+ ShutdownAndStopWatcher(); /* msg with specified text recvd */
+ mir_free(dbv.ptszVal); /* does NULL check */
+ }
+ }
+ mir_free(dbe.pBlob);
+ }
+ return 0;
+}
+
+/************************* Transfer Shutdown **************************/
+
+static HANDLE *transfers;
+static int nTransfersCount;
+
+static int ProtoAck(WPARAM wParam,LPARAM lParam)
+{
+ ACKDATA *ack=(ACKDATA*)lParam;
+ if(ack->type==ACKTYPE_FILE)
+ switch(ack->result) {
+ case ACKRESULT_DATA:
+ { int i;
+ for(i=0;i<nTransfersCount;++i)
+ if(transfers[i]==ack->hProcess)
+ break; /* already in list */
+ /* insert into list */
+ { HANDLE *buf=(HANDLE*)mir_realloc(transfers,(nTransfersCount+1)*sizeof(HANDLE)); if(buf!=NULL) {
+ transfers=buf;
+ transfers[nTransfersCount]=ack->hProcess;
+ ++nTransfersCount;
+ }
+ }
+ break;
+ }
+ case ACKRESULT_SUCCESS:
+ case ACKRESULT_FAILED:
+ case ACKRESULT_DENIED:
+ { int i;
+ for(i=0;i<nTransfersCount;++i)
+ if(transfers[i]==ack->hProcess) {
+ /* remove from list */
+ HANDLE *buf;
+ if(i<(nTransfersCount-1))
+ MoveMemory(&transfers[i],&transfers[i+1],(nTransfersCount-i-1)*sizeof(HANDLE));
+ --nTransfersCount;
+ buf=(HANDLE*)mir_realloc(transfers,nTransfersCount*sizeof(HANDLE));
+ if(buf!=NULL) transfers=buf;
+ else if(!nTransfersCount) transfers=NULL;
+ /* stop watcher */
+ if(!nTransfersCount && (currentWatcherType&SDWTF_FILETRANSFER))
+ ShutdownAndStopWatcher();
+ break;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+/************************* Idle Shutdown ******************************/
+
+static int IdleChanged(WPARAM wParam,LPARAM lParam)
+{
+ if(currentWatcherType&SDWTF_IDLE && lParam&IDF_ISIDLE)
+ ShutdownAndStopWatcher();
+ return 0;
+}
+
+/************************* Status Shutdown ****************************/
+
+static BOOL CheckAllContactsOffline(void)
+{
+ BOOL fSmartCheck,fAllOffline=TRUE; /* tentatively */
+ HANDLE hContact;
+ char *pszProto;
+ fSmartCheck=DBGetContactSettingByte(NULL,"AutoShutdown","SmartOfflineCheck",SETTING_SMARTOFFLINECHECK_DEFAULT);
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact!=NULL) {
+ pszProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ if(pszProto!=NULL && CallProtoService(pszProto,PS_GETSTATUS,0,0)!=ID_STATUS_OFFLINE)
+ if(DBGetContactSettingByte(hContact,pszProto,"ChatRoom",0)) continue;
+ if(DBGetContactSettingWord(hContact,pszProto,"Status",0)!=ID_STATUS_OFFLINE) {
+ if(fSmartCheck) {
+ if(DBGetContactSettingByte(hContact,"CList","Hidden",0)) continue;
+ if(DBGetContactSettingByte(hContact,"CList","NotOnList",0)) continue;
+ }
+ fAllOffline=FALSE;
+ break;
+ }
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+ return fAllOffline;
+}
+
+static int StatusSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ if(currentWatcherType&SDWTF_STATUS) {
+ DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam;
+ if((HANDLE)wParam!=NULL && dbcws->value.wVal==ID_STATUS_OFFLINE && !lstrcmpA(dbcws->szSetting,"Status")) {
+ char *pszProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ if(pszProto!=NULL && !lstrcmpA(dbcws->szModule,pszProto))
+ if(CheckAllContactsOffline())
+ ShutdownAndStopWatcher();
+ }
+ }
+ return 0;
+}
+
+/************************* Cpu Shutdown *******************************/
+
+static DWORD idCpuUsageThread;
+
+static BOOL CALLBACK CpuUsageWatcherProc(BYTE nCpuUsage,LPARAM lParam)
+{
+ static BYTE nTimesBelow=0; /* only one watcher thread */
+ /* terminated? */
+ if(idCpuUsageThread!=GetCurrentThreadId()) {
+ nTimesBelow=0;
+ return FALSE; /* stop poll thread */
+ }
+ /* ignore random peaks */
+ if(nCpuUsage<(BYTE)lParam) ++nTimesBelow;
+ else nTimesBelow=0;
+ if(nTimesBelow==3) {
+ nTimesBelow=0;
+ ShutdownAndStopWatcher();
+ return FALSE; /* stop poll thread */
+ }
+ return TRUE;
+}
+
+/************************* Weather Shutdown ***************************/
+
+static int WeatherUpdated(WPARAM wParam,LPARAM lParam)
+{
+ char *pszProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ if((BOOL)lParam && pszProto!=NULL && CallProtoService(pszProto,PS_GETSTATUS,0,0)==THUNDER)
+ if(DBGetContactSettingByte(NULL,"AutoShutdown","WeatherShutdown",SETTING_WEATHERSHUTDOWN_DEFAULT))
+ ServiceShutdown(SDSDT_SHUTDOWN,TRUE);
+ return 0;
+}
+
+/************************* Overheat Shutdown **************************/
+
+static int HddOverheat(WPARAM wParam,LPARAM lParam)
+{
+ if(DBGetContactSettingByte(NULL,"AutoShutdown","HddOverheatShutdown",SETTING_HDDOVERHEATSHUTDOWN_DEFAULT))
+ ServiceShutdown(SDSDT_SHUTDOWN,TRUE);
+ return 0;
+}
+
+/************************* Services ***********************************/
+
+INT_PTR ServiceStartWatcher(WPARAM wParam,LPARAM lParam)
+{
+ /* passing watcherType as lParam is only to be used internally, undocumented */
+ if(lParam==0) lParam=(LPARAM)DBGetContactSettingWord(NULL,"AutoShutdown","WatcherFlags",0);
+
+ if(!(lParam&SDWTF_MASK)) return 1; /* invalid flags or empty? */
+ if(lParam&SDWTF_SPECIFICTIME && !(lParam&SDWTF_ST_MASK)) return 2; /* no specific time choice? */
+ if(currentWatcherType==(WORD)lParam) return 3;
+
+ if(currentWatcherType!=0) {
+ /* Time Shutdown */
+ CloseCountdownFrame(); /* fails if not opened */
+ /* Cpu Shutdown */
+ idCpuUsageThread=0;
+ }
+ SetShutdownMenuItem(TRUE);
+ SetShutdownToolbarButton(TRUE);
+ currentWatcherType=(WORD)lParam;
+ NotifyEventHooks(hEventWatcherChanged,TRUE,0);
+
+ /* Time Shutdown */
+ if(currentWatcherType&SDWTF_SPECIFICTIME)
+ ShowCountdownFrame(currentWatcherType); /* after modules loaded */
+ /* Cpu Shutdown */
+ if(currentWatcherType&SDWTF_CPUUSAGE)
+ idCpuUsageThread=PollCpuUsage(CpuUsageWatcherProc,(LPARAM)DBGetContactSettingRangedByte(NULL,"AutoShutdown","CpuUsageThreshold",SETTING_CPUUSAGETHRESHOLD_DEFAULT,1,100),1500);
+ /* Transfer Shutdown */
+ if(currentWatcherType&SDWTF_FILETRANSFER && !nTransfersCount)
+ ShutdownAndStopWatcher();
+ /* Status Shutdown */
+ if(currentWatcherType&SDWTF_STATUS && CheckAllContactsOffline())
+ ShutdownAndStopWatcher();
+ return 0;
+}
+
+INT_PTR ServiceStopWatcher(WPARAM wParam,LPARAM lParam)
+{
+ if(currentWatcherType==0) return 1;
+
+ /* Time Shutdown */
+ if(currentWatcherType&SDWTF_SPECIFICTIME)
+ CloseCountdownFrame();
+ /* Cpu Shutdown */
+ idCpuUsageThread=0;
+
+ currentWatcherType=0;
+ SetShutdownMenuItem(FALSE);
+ SetShutdownToolbarButton(FALSE);
+ NotifyEventHooks(hEventWatcherChanged,FALSE,0);
+ return 0;
+}
+
+INT_PTR ServiceIsWatcherEnabled(WPARAM wParam,LPARAM lParam)
+{
+ return currentWatcherType!=0;
+}
+
+/************************* Misc ***********************************/
+
+static int WatcherModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ /* Weather Shutdown */
+ if(ServiceExists(MS_WEATHER_UPDATE))
+ hHookWeatherUpdated=HookEvent(ME_WEATHER_UPDATED,WeatherUpdated);
+ /* Overheat Shutdown */
+ if(ServiceExists(MS_SYSINFO_HDDTEMP))
+ hHookHddOverheat=HookEvent(ME_SYSINFO_HDDOVERHEAT,HddOverheat);
+
+ /* restore watcher if it was running on last exit */
+ if(DBGetContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",0)==SDROR_RUNNING) {
+ DBWriteContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",1);
+ ServiceStartWatcher(0,0); /* after modules loaded */
+ }
+ return 0;
+}
+
+void InitWatcher(void)
+{
+ /* Shared */
+ currentWatcherType=0;
+ /* Message Shutdown */
+ hHookEventAdded=HookEvent(ME_DB_EVENT_ADDED,MsgEventAdded);
+ /* Status Shutdown*/
+ hHookSettingChanged=HookEvent(ME_DB_CONTACT_SETTINGCHANGED,StatusSettingChanged);
+ /* Idle Shutdown */
+ hHookIdleChanged=HookEvent(ME_IDLE_CHANGED,IdleChanged);
+ /* Transfer Shutdown */
+ transfers=NULL;
+ nTransfersCount=0;
+ hHookProtoAck=HookEvent(ME_PROTO_ACK,ProtoAck);
+ /* Weather Shutdown */
+ hHookWeatherUpdated=NULL;
+ /* Overheat Shutdown */
+ hHookHddOverheat=NULL;
+ /* Services */
+ hEventWatcherChanged=CreateHookableEvent(ME_AUTOSHUTDOWN_WATCHERCHANGED);
+ hServiceStartWatcher = CreateServiceFunction(MS_AUTOSHUTDOWN_STARTWATCHER, ServiceStartWatcher);
+ hServiceStopWatcher = CreateServiceFunction(MS_AUTOSHUTDOWN_STOPWATCHER, ServiceStopWatcher);
+ hServiceIsEnabled = CreateServiceFunction(MS_AUTOSHUTDOWN_ISWATCHERENABLED, ServiceIsWatcherEnabled);
+ /* Misc */
+ hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,WatcherModulesLoaded);
+}
+
+void UninitWatcher(void)
+{
+ /* remember watcher if running */
+ if(!ServiceStopWatcher(0,0))
+ if(DBGetContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",SETTING_REMEMBERONRESTART_DEFAULT))
+ DBWriteContactSettingByte(NULL,"AutoShutdown","RememberOnRestart",SDROR_RUNNING);
+
+ /* Message Shutdown */
+ UnhookEvent(hHookEventAdded);
+ /* Status Shutdown*/
+ UnhookEvent(hHookSettingChanged);
+ /* Idle Shutdown */
+ UnhookEvent(hHookIdleChanged);
+ /* Transfer Shutdown */
+ UnhookEvent(hHookProtoAck);
+ mir_free(transfers); /* does NULL check */
+ /* Weather Shutdown */
+ UnhookEvent(hHookWeatherUpdated); /* does NULL check */
+ /* Overheat Shutdown */
+ UnhookEvent(hHookHddOverheat); /* does NULL check */
+ /* Services */
+ DestroyServiceFunction(hServiceStartWatcher);
+ DestroyServiceFunction(hServiceStopWatcher);
+ DestroyServiceFunction(hServiceIsEnabled);
+ DestroyHookableEvent(hEventWatcherChanged);
+ /* Misc */
+ UnhookEvent(hHookModulesLoaded);
+}
diff --git a/plugins/AutoShutdown/src/watcher.h b/plugins/AutoShutdown/src/watcher.h
new file mode 100644
index 0000000000..962378b811
--- /dev/null
+++ b/plugins/AutoShutdown/src/watcher.h
@@ -0,0 +1,29 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Services */
+INT_PTR ServiceStartWatcher(WPARAM wParam,LPARAM lParam);
+INT_PTR ServiceStopWatcher(WPARAM wParam,LPARAM lParam);
+INT_PTR ServiceIsWatcherEnabled(WPARAM wParam,LPARAM lParam);
+
+/* Misc */
+void InitWatcher(void);
+void UninitWatcher(void);