From 49566229022ee6e96eac0888f9c0501fcd92033b Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Tue, 3 Jul 2012 17:21:34 +0000 Subject: AutoShutdown: renamed to .cpp git-svn-id: http://svn.miranda-ng.org/main/trunk@736 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/AutoShutdown/cpuusage.c | 257 -------------- plugins/AutoShutdown/cpuusage.cpp | 257 ++++++++++++++ plugins/AutoShutdown/frame.c | 644 ----------------------------------- plugins/AutoShutdown/frame.cpp | 644 +++++++++++++++++++++++++++++++++++ plugins/AutoShutdown/main.c | 192 ----------- plugins/AutoShutdown/main.cpp | 192 +++++++++++ plugins/AutoShutdown/options.c | 189 ---------- plugins/AutoShutdown/options.cpp | 189 ++++++++++ plugins/AutoShutdown/settingsdlg.c | 512 ---------------------------- plugins/AutoShutdown/settingsdlg.cpp | 512 ++++++++++++++++++++++++++++ plugins/AutoShutdown/shutdownsvc.c | 624 --------------------------------- plugins/AutoShutdown/shutdownsvc.cpp | 624 +++++++++++++++++++++++++++++++++ plugins/AutoShutdown/utils.c | 458 ------------------------- plugins/AutoShutdown/utils.cpp | 458 +++++++++++++++++++++++++ plugins/AutoShutdown/watcher.c | 408 ---------------------- plugins/AutoShutdown/watcher.cpp | 408 ++++++++++++++++++++++ 16 files changed, 3284 insertions(+), 3284 deletions(-) delete mode 100644 plugins/AutoShutdown/cpuusage.c create mode 100644 plugins/AutoShutdown/cpuusage.cpp delete mode 100644 plugins/AutoShutdown/frame.c create mode 100644 plugins/AutoShutdown/frame.cpp delete mode 100644 plugins/AutoShutdown/main.c create mode 100644 plugins/AutoShutdown/main.cpp delete mode 100644 plugins/AutoShutdown/options.c create mode 100644 plugins/AutoShutdown/options.cpp delete mode 100644 plugins/AutoShutdown/settingsdlg.c create mode 100644 plugins/AutoShutdown/settingsdlg.cpp delete mode 100644 plugins/AutoShutdown/shutdownsvc.c create mode 100644 plugins/AutoShutdown/shutdownsvc.cpp delete mode 100644 plugins/AutoShutdown/utils.c create mode 100644 plugins/AutoShutdown/utils.cpp delete mode 100644 plugins/AutoShutdown/watcher.c create mode 100644 plugins/AutoShutdown/watcher.cpp (limited to 'plugins/AutoShutdown') diff --git a/plugins/AutoShutdown/cpuusage.c b/plugins/AutoShutdown/cpuusage.c deleted file mode 100644 index 1270fe02ec..0000000000 --- a/plugins/AutoShutdown/cpuusage.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - -'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; -} - -#if !defined(_UNICODE) -static void Win9x_PerfStatsSwitch(HKEY hKey,char *pszAction,char *pszName) -{ - DWORD dwData,dwSize; - dwSize=sizeof(dwData); - if(!RegOpenKeyExA(hKey,pszAction,0,KEY_QUERY_VALUE,&hKey)) { - /* a simple query does the trick (data and size must not be NULL!) */ - RegQueryValueExA(hKey,pszName,NULL,NULL,(BYTE*)&dwData,&dwSize); - RegCloseKey(hKey); - } -} -#endif - -/************************* 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(); -} - -#if !defined(_UNICODE) -static void Win9x_PollThread(struct CpuUsageThreadParams *param) -{ - HKEY hKeyStats,hKeyData; - DWORD dwBufferSize,dwData; - - if(!RegOpenKeyExA(HKEY_DYN_DATA,"PerfStats",0,KEY_QUERY_VALUE,&hKeyStats)) { - /* start query */ - /* not needed for kernel - * Win9x_PerfStatsSwitch(hKeyStats,"StartSrv","KERNEL"); */ - Win9x_PerfStatsSwitch(hKeyStats,"StartStat","KERNEL\\CPUUsage"); - /* retrieve cpu usage */ - if(!RegOpenKeyExA(hKeyStats,"StatData",0,KEY_QUERY_VALUE,&hKeyData)) { - dwBufferSize=sizeof(dwData); - while(!RegQueryValueExA(hKeyData,"KERNEL\\CPUUsage",NULL,NULL,(BYTE*)&dwData,&dwBufferSize)) { - dwBufferSize=sizeof(dwData); - if(!CallBackAndWait(param,(BYTE)dwData)) break; - } - RegCloseKey(hKeyData); - } - /* stop query */ - Win9x_PerfStatsSwitch(hKeyStats,"StopStat","KERNEL\\CPUUsage"); - /* not needed for kernel - * Win9x_PerfStatsSwitch(hKeyStats,"StopSrv","KERNEL"); */ - RegCloseKey(hKeyStats); - } - /* return error for PollCpuUsage() if never succeeded */ - if(param->hFirstEvent!=NULL) SetEvent(param->hFirstEvent); - mir_free(param); -} -#endif /* !_UNICODE */ - -static void WinNT_PollThread(struct CpuUsageThreadParams *param) -{ - 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; - } - _itow(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;dwCountNumObjectTypes;++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 defined(_UNICODE) - if(mir_forkthread(WinNT_PollThread,param)!=-1) -#else - if(mir_forkthread(IsWinVerNT()?WinNT_PollThread:Win9x_PollThread,param)!=-1) -#endif - WaitForSingleObject(hFirstEvent,INFINITE); /* wait for first success */ - else mir_free(param); /* thread not started */ - CloseHandle(hFirstEvent); - return idThread; -} diff --git a/plugins/AutoShutdown/cpuusage.cpp b/plugins/AutoShutdown/cpuusage.cpp new file mode 100644 index 0000000000..1270fe02ec --- /dev/null +++ b/plugins/AutoShutdown/cpuusage.cpp @@ -0,0 +1,257 @@ +/* + +'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; +} + +#if !defined(_UNICODE) +static void Win9x_PerfStatsSwitch(HKEY hKey,char *pszAction,char *pszName) +{ + DWORD dwData,dwSize; + dwSize=sizeof(dwData); + if(!RegOpenKeyExA(hKey,pszAction,0,KEY_QUERY_VALUE,&hKey)) { + /* a simple query does the trick (data and size must not be NULL!) */ + RegQueryValueExA(hKey,pszName,NULL,NULL,(BYTE*)&dwData,&dwSize); + RegCloseKey(hKey); + } +} +#endif + +/************************* 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(); +} + +#if !defined(_UNICODE) +static void Win9x_PollThread(struct CpuUsageThreadParams *param) +{ + HKEY hKeyStats,hKeyData; + DWORD dwBufferSize,dwData; + + if(!RegOpenKeyExA(HKEY_DYN_DATA,"PerfStats",0,KEY_QUERY_VALUE,&hKeyStats)) { + /* start query */ + /* not needed for kernel + * Win9x_PerfStatsSwitch(hKeyStats,"StartSrv","KERNEL"); */ + Win9x_PerfStatsSwitch(hKeyStats,"StartStat","KERNEL\\CPUUsage"); + /* retrieve cpu usage */ + if(!RegOpenKeyExA(hKeyStats,"StatData",0,KEY_QUERY_VALUE,&hKeyData)) { + dwBufferSize=sizeof(dwData); + while(!RegQueryValueExA(hKeyData,"KERNEL\\CPUUsage",NULL,NULL,(BYTE*)&dwData,&dwBufferSize)) { + dwBufferSize=sizeof(dwData); + if(!CallBackAndWait(param,(BYTE)dwData)) break; + } + RegCloseKey(hKeyData); + } + /* stop query */ + Win9x_PerfStatsSwitch(hKeyStats,"StopStat","KERNEL\\CPUUsage"); + /* not needed for kernel + * Win9x_PerfStatsSwitch(hKeyStats,"StopSrv","KERNEL"); */ + RegCloseKey(hKeyStats); + } + /* return error for PollCpuUsage() if never succeeded */ + if(param->hFirstEvent!=NULL) SetEvent(param->hFirstEvent); + mir_free(param); +} +#endif /* !_UNICODE */ + +static void WinNT_PollThread(struct CpuUsageThreadParams *param) +{ + 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; + } + _itow(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;dwCountNumObjectTypes;++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 defined(_UNICODE) + if(mir_forkthread(WinNT_PollThread,param)!=-1) +#else + if(mir_forkthread(IsWinVerNT()?WinNT_PollThread:Win9x_PollThread,param)!=-1) +#endif + WaitForSingleObject(hFirstEvent,INFINITE); /* wait for first success */ + else mir_free(param); /* thread not started */ + CloseHandle(hFirstEvent); + return idThread; +} diff --git a/plugins/AutoShutdown/frame.c b/plugins/AutoShutdown/frame.c deleted file mode 100644 index f9266b1906..0000000000 --- a/plugins/AutoShutdown/frame.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - -'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)GetWindowLong(hwndProgress,GWL_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; - HANDLE 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*)GetWindowLong(hwndFrame,GWL_USERDATA); - - switch(msg) { - case WM_NCCREATE: /* init window data */ - dat=(struct CountdownFrameWndData*)mir_calloc(sizeof(*dat)); - SetWindowLong(hwndFrame,GWL_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); - SetWindowLong(dat->hwndProgress,GWL_USERDATA,SetWindowLong(dat->hwndProgress,GWL_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); - SetWindowLong(hwndFrame,GWL_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); - SetWindowLong(dat->hwndProgress,GWL_STYLE,GetWindowLong(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=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)) { - SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)|TTS_NOANIMATE); - SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(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 */ - } - } - SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)&(~TTS_NOANIMATE)); - SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(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) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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/frame.cpp b/plugins/AutoShutdown/frame.cpp new file mode 100644 index 0000000000..f9266b1906 --- /dev/null +++ b/plugins/AutoShutdown/frame.cpp @@ -0,0 +1,644 @@ +/* + +'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)GetWindowLong(hwndProgress,GWL_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; + HANDLE 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*)GetWindowLong(hwndFrame,GWL_USERDATA); + + switch(msg) { + case WM_NCCREATE: /* init window data */ + dat=(struct CountdownFrameWndData*)mir_calloc(sizeof(*dat)); + SetWindowLong(hwndFrame,GWL_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); + SetWindowLong(dat->hwndProgress,GWL_USERDATA,SetWindowLong(dat->hwndProgress,GWL_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); + SetWindowLong(hwndFrame,GWL_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); + SetWindowLong(dat->hwndProgress,GWL_STYLE,GetWindowLong(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=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)) { + SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)|TTS_NOANIMATE); + SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(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 */ + } + } + SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)&(~TTS_NOANIMATE)); + SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(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) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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/main.c b/plugins/AutoShutdown/main.c deleted file mode 100644 index d4f9a63480..0000000000 --- a/plugins/AutoShutdown/main.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - -'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; -PLUGINLINK *pluginLink; -struct MM_INTERFACE mmi; -static HANDLE hHookModulesLoaded; -HANDLE hActiveIcon,hInactiveIcon; - -PLUGININFOEX pluginInfo={ - sizeof(PLUGININFOEX), - "AutoShutdown", - PLUGIN_VERSION, -#if defined(_DEBUG) - "Development build not intended for release. ("__DATE__")", -#else - "Adds the possibility to shutdown the computer when a specified event occurs.", /* autotranslated */ -#endif - "H. Herkenrath", - PLUGIN_EMAIL, /* @ will be set later */ - "© 2004-2007 H. Herkenrath", - PLUGIN_WEBSITE, - UNICODE_AWARE, - 0, -#if defined(_UNICODE) - // {9DE24579-5C5C-49aa-80E8-4D38E4344E63} - {0x9de24579,0x5c5c,0x49aa,{0x80,0xe8,0x4d,0x38,0xe4,0x34,0x4e,0x63}}, -#else - // {7C0DD208-94D8-4283-879A-E6F86135B826} - {0x7c0dd208,0x94d8,0x4283,{0x87,0x9a,0xe6,0xf8,0x61,0x35,0xb8,0x26}} -#endif -}; -static const MUUID interfaces[]={MIID_SHUTDOWN,MIID_LAST}; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,void *pReserved) -{ - UNREFERENCED_PARAMETER(pReserved); - if(fdwReason==DLL_PROCESS_ATTACH) - /* Do not call this function from a DLL that is linked to the static C run-time library (CRT). - * The static CRT requires DLL_THREAD_ATTACH and DLL_THREAD_DETATCH notifications to function properly. */ - DisableThreadLibraryCalls(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) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - if(ServiceExists("DBEditorpp/RegisterSingleModule")) - CallService("DBEditorpp/RegisterSingleModule",(WPARAM)"AutoShutdown",0); - /* merged thundershutdown plugin */ - if(GetModuleHandleA("tshutdown.dll")) { - DBWriteContactSettingByte(NULL,"PluginDisable","tshutdown.dll",1); - DBWriteContactSettingByte(NULL,"AutoShutdown","WeatherShutdown",1); - } - return 0; -} - -#ifdef __cplusplus -extern "C" { -#endif - -__declspec(dllexport) const PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) -{ - if(mirandaVersioncode) { - 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; - UNREFERENCED_PARAMETER(lParam); - 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; - CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); - return 0; -} - -/************************* Trigger ************************************/ - -static int __stdcall ActionProc(DWORD idAction,REPORTINFO *ri,int shutdownType) -{ - UNREFERENCED_PARAMETER(ri); - 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) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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/options.cpp b/plugins/AutoShutdown/options.cpp new file mode 100644 index 0000000000..2026038859 --- /dev/null +++ b/plugins/AutoShutdown/options.cpp @@ -0,0 +1,189 @@ +/* + +'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 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; + UNREFERENCED_PARAMETER(lParam); + 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; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + return 0; +} + +/************************* Trigger ************************************/ + +static int __stdcall ActionProc(DWORD idAction,REPORTINFO *ri,int shutdownType) +{ + UNREFERENCED_PARAMETER(ri); + 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) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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/settingsdlg.c b/plugins/AutoShutdown/settingsdlg.c deleted file mode 100644 index 03f514d61b..0000000000 --- a/plugins/AutoShutdown/settingsdlg.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - -'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;itype==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 BOOL 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;iidFrom) { - 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,×tamp)) - 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 ServiceShowSettingsDialog(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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) -{ - TTBButtonV2 ttbb; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - 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.pszServiceUp=ttbb.pszServiceDown="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=(HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&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=(HANDLE)CallService(MS_CLIST_ADDTRAYMENUITEM,0,(LPARAM)&cmi); - - IcoLib_ReleaseIcon(cmi.hIcon); -} - -static int MenuItemCommand(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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 */ - SkinAddNewHotkey("AutoShutdown_Toggle",Translate("Main"),Translate("Toggle Automatic Shutdown"),'T',HOTKEYF_CONTROL|HOTKEYF_SHIFT,"AutoShutdown/MenuCommand"); - /* 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/settingsdlg.cpp b/plugins/AutoShutdown/settingsdlg.cpp new file mode 100644 index 0000000000..03f514d61b --- /dev/null +++ b/plugins/AutoShutdown/settingsdlg.cpp @@ -0,0 +1,512 @@ +/* + +'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;itype==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 BOOL 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;iidFrom) { + 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,×tamp)) + 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 ServiceShowSettingsDialog(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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) +{ + TTBButtonV2 ttbb; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + 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.pszServiceUp=ttbb.pszServiceDown="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=(HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&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=(HANDLE)CallService(MS_CLIST_ADDTRAYMENUITEM,0,(LPARAM)&cmi); + + IcoLib_ReleaseIcon(cmi.hIcon); +} + +static int MenuItemCommand(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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 */ + SkinAddNewHotkey("AutoShutdown_Toggle",Translate("Main"),Translate("Toggle Automatic Shutdown"),'T',HOTKEYF_CONTROL|HOTKEYF_SHIFT,"AutoShutdown/MenuCommand"); + /* 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/shutdownsvc.c b/plugins/AutoShutdown/shutdownsvc.c deleted file mode 100644 index 2b519cc512..0000000000 --- a/plugins/AutoShutdown/shutdownsvc.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - -'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); -#if defined(_UNICODE) - *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessageW"); -#else - *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessageA"); - if(!pfnBroadcastSystemMessage) /* Win95 has undecorated API */ - *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessage"); -#endif - 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; -} - -#if !defined(_UNICODE) -static void Win9x_TerminateExplorer(void) -{ - HANDLE hProcess; - DWORD idProcess; - if(GetWindowThreadProcessId(GetDesktopWindow(),&idProcess)) { - hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,idProcess); - if(hProcess!=NULL) { - TerminateProcess(hProcess,0); - CloseHandle(hProcess); - } - } -} -#endif - -/************************* 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,(void*)&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,(void*)&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,(void*)szScreenSaveActive,&dwSize); - dwSize=sizeof(szScreenSaverIsSecure); /* in bytes */ - ZeroMemory(&szScreenSaverIsSecure, dwSize); - RegQueryValueEx(hKey,_T("ScreenSaverIsSecure"),0,NULL,(void*)szScreenSaverIsSecure,&dwSize); - dwSize=sizeof(szScrnsaveExe); /* in bytes */ - ZeroMemory(&szScrnsaveExe,dwSize); - RegQueryValueEx(hKey,_T("SCRNSAVE.EXE"),0,NULL,(void*)szScrnsaveExe,&dwSize); - /* set LOGON.SCR data */ - if(!RegSetValueEx(hKey,_T("ScreenSaveActive"),0,REG_SZ,(void*)_T("1"),2) && - !RegSetValueEx(hKey,_T("ScreenSaverIsSecure"),0,REG_SZ,(void*)"1",2) && - !RegSetValueEx(hKey,_T("SCRNSAVE.EXE"),0,REG_SZ,(void*)_T("LOGIN.SCR"),10)) - SendMessage(GetForegroundWindow(),WM_SYSCOMMAND,SC_SCREENSAVE,0); - else dwErrCode=GetLastError(); - /* restore old settings */ - RegSetValueEx(hKey,_T("ScreenSaveActive"),0,REG_SZ,(void*)szScreenSaveActive,(lstrlen(szScreenSaveActive)+1)*sizeof(TCHAR)); - RegSetValueEx(hKey,_T("ScreenSaverIsSecure"),0,REG_SZ,(void*)szScreenSaverIsSecure,(lstrlen(szScreenSaverIsSecure)+1)*sizeof(TCHAR)); - RegSetValueEx(hKey,_T("SCRNSAVE.EXE"),0,REG_SZ,(void*)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*); - #if defined(_UNICODE) - *(PROC*)&pfnRasEnumConnections=GetProcAddress(hRasApiDLL,"RasEnumConnectionsW"); - *(PROC*)&pfnRasHangUp=GetProcAddress(hRasApiDLL,"RasHangUpW"); - *(PROC*)&pfnRasGetConnectStatus=GetProcAddress(hRasApiDLL,"RasGetConnectStatusW"); - #else - *(PROC*)&pfnRasEnumConnections=GetProcAddress(hRasApiDLL,"RasEnumConnectionsA"); - *(PROC*)&pfnRasHangUp=GetProcAddress(hRasApiDLL,"RasHangUpA"); - *(PROC*)&pfnRasGetConnectStatus=GetProcAddress(hRasApiDLL,"RasGetConnectStatusA"); - #endif - 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;dw3000) 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); - #if defined(_UNICODE) - *(PROC*)&pfnInitiateSystemShutdownEx=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownExW"); - *(PROC*)&pfnInitiateSystemShutdown=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownW"); - #else - *(PROC*)&pfnInitiateSystemShutdownEx=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownExA"); - *(PROC*)&pfnInitiateSystemShutdown=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownA"); - #endif - 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 !defined(_UNICODE) - if(shutdownType==SDSDT_LOGOFF && !IsWinVerNT()) Win9x_TerminateExplorer(); - #endif - } - 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 BOOL CALLBACK ShutdownDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam) -{ - BYTE shutdownType=(BYTE)GetWindowLong(hwndDlg,DWL_USER); - WORD countdown=(WORD)GetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_USERDATA); - static BOOL (WINAPI *pfnLockSetForegroundWindow)(UINT); - - switch(msg) { - case WM_INITDIALOG: - hwndShutdownDlg=hwndDlg; - SetWindowLong(hwndDlg,DWL_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); - SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_USERDATA,(LONG)hBoldFont); - } - { WORD countdown=DBGetContactSettingWord(NULL,"AutoShutdown","ConfirmDlgCountdown",SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT); - if(countdown<3) countdown=SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT; - SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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; - SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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); - SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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 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 ServiceIsTypeEnabled(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - return IsShutdownTypeEnabled((BYTE)wParam); /* does shutdownType range check */ -} - -int 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 defined(_UNICODE) - 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; - } - #else - if(lParam&GSTDF_UNICODE) { - static WCHAR szConvBuf[128]; - WCHAR *buf=a2u(pszDesc); - if(buf==NULL) return (int)NULL; - lstrcpynW(szConvBuf,buf,SIZEOF(szConvBuf)); - mir_free(buf); - return (int)szConvBuf; - } - #endif - 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/shutdownsvc.cpp b/plugins/AutoShutdown/shutdownsvc.cpp new file mode 100644 index 0000000000..2b519cc512 --- /dev/null +++ b/plugins/AutoShutdown/shutdownsvc.cpp @@ -0,0 +1,624 @@ +/* + +'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); +#if defined(_UNICODE) + *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessageW"); +#else + *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessageA"); + if(!pfnBroadcastSystemMessage) /* Win95 has undecorated API */ + *(PROC*)&pfnBroadcastSystemMessage=GetProcAddress(GetModuleHandleA("USER32"),"BroadcastSystemMessage"); +#endif + 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; +} + +#if !defined(_UNICODE) +static void Win9x_TerminateExplorer(void) +{ + HANDLE hProcess; + DWORD idProcess; + if(GetWindowThreadProcessId(GetDesktopWindow(),&idProcess)) { + hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,idProcess); + if(hProcess!=NULL) { + TerminateProcess(hProcess,0); + CloseHandle(hProcess); + } + } +} +#endif + +/************************* 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,(void*)&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,(void*)&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,(void*)szScreenSaveActive,&dwSize); + dwSize=sizeof(szScreenSaverIsSecure); /* in bytes */ + ZeroMemory(&szScreenSaverIsSecure, dwSize); + RegQueryValueEx(hKey,_T("ScreenSaverIsSecure"),0,NULL,(void*)szScreenSaverIsSecure,&dwSize); + dwSize=sizeof(szScrnsaveExe); /* in bytes */ + ZeroMemory(&szScrnsaveExe,dwSize); + RegQueryValueEx(hKey,_T("SCRNSAVE.EXE"),0,NULL,(void*)szScrnsaveExe,&dwSize); + /* set LOGON.SCR data */ + if(!RegSetValueEx(hKey,_T("ScreenSaveActive"),0,REG_SZ,(void*)_T("1"),2) && + !RegSetValueEx(hKey,_T("ScreenSaverIsSecure"),0,REG_SZ,(void*)"1",2) && + !RegSetValueEx(hKey,_T("SCRNSAVE.EXE"),0,REG_SZ,(void*)_T("LOGIN.SCR"),10)) + SendMessage(GetForegroundWindow(),WM_SYSCOMMAND,SC_SCREENSAVE,0); + else dwErrCode=GetLastError(); + /* restore old settings */ + RegSetValueEx(hKey,_T("ScreenSaveActive"),0,REG_SZ,(void*)szScreenSaveActive,(lstrlen(szScreenSaveActive)+1)*sizeof(TCHAR)); + RegSetValueEx(hKey,_T("ScreenSaverIsSecure"),0,REG_SZ,(void*)szScreenSaverIsSecure,(lstrlen(szScreenSaverIsSecure)+1)*sizeof(TCHAR)); + RegSetValueEx(hKey,_T("SCRNSAVE.EXE"),0,REG_SZ,(void*)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*); + #if defined(_UNICODE) + *(PROC*)&pfnRasEnumConnections=GetProcAddress(hRasApiDLL,"RasEnumConnectionsW"); + *(PROC*)&pfnRasHangUp=GetProcAddress(hRasApiDLL,"RasHangUpW"); + *(PROC*)&pfnRasGetConnectStatus=GetProcAddress(hRasApiDLL,"RasGetConnectStatusW"); + #else + *(PROC*)&pfnRasEnumConnections=GetProcAddress(hRasApiDLL,"RasEnumConnectionsA"); + *(PROC*)&pfnRasHangUp=GetProcAddress(hRasApiDLL,"RasHangUpA"); + *(PROC*)&pfnRasGetConnectStatus=GetProcAddress(hRasApiDLL,"RasGetConnectStatusA"); + #endif + 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;dw3000) 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); + #if defined(_UNICODE) + *(PROC*)&pfnInitiateSystemShutdownEx=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownExW"); + *(PROC*)&pfnInitiateSystemShutdown=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownW"); + #else + *(PROC*)&pfnInitiateSystemShutdownEx=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownExA"); + *(PROC*)&pfnInitiateSystemShutdown=GetProcAddress(GetModuleHandleA("ADVAPI32"),"InitiateSystemShutdownA"); + #endif + 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 !defined(_UNICODE) + if(shutdownType==SDSDT_LOGOFF && !IsWinVerNT()) Win9x_TerminateExplorer(); + #endif + } + 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 BOOL CALLBACK ShutdownDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + BYTE shutdownType=(BYTE)GetWindowLong(hwndDlg,DWL_USER); + WORD countdown=(WORD)GetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_USERDATA); + static BOOL (WINAPI *pfnLockSetForegroundWindow)(UINT); + + switch(msg) { + case WM_INITDIALOG: + hwndShutdownDlg=hwndDlg; + SetWindowLong(hwndDlg,DWL_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); + SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_USERDATA,(LONG)hBoldFont); + } + { WORD countdown=DBGetContactSettingWord(NULL,"AutoShutdown","ConfirmDlgCountdown",SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT); + if(countdown<3) countdown=SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT; + SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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; + SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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); + SetWindowLong(GetDlgItem(hwndDlg,IDC_TEXT_HEADER),GWL_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 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 ServiceIsTypeEnabled(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + return IsShutdownTypeEnabled((BYTE)wParam); /* does shutdownType range check */ +} + +int 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 defined(_UNICODE) + 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; + } + #else + if(lParam&GSTDF_UNICODE) { + static WCHAR szConvBuf[128]; + WCHAR *buf=a2u(pszDesc); + if(buf==NULL) return (int)NULL; + lstrcpynW(szConvBuf,buf,SIZEOF(szConvBuf)); + mir_free(buf); + return (int)szConvBuf; + } + #endif + 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/utils.c b/plugins/AutoShutdown/utils.c deleted file mode 100644 index b9bbddbc01..0000000000 --- a/plugins/AutoShutdown/utils.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - -'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 -#if !defined(_UNICODE) -WCHAR* a2u(const char *pszAnsi) -{ - int codepage,cch; - WCHAR *psz; - - if(pszAnsi==NULL) return NULL; - codepage=CallService(MS_LANGPACK_GETCODEPAGE,0,0); - cch=MultiByteToWideChar(codepage,0,pszAnsi,-1,NULL,0); - if(!cch) return NULL; - - psz=(WCHAR*)mir_alloc(cch*sizeof(WCHAR)); - if(psz!=NULL && !MultiByteToWideChar(codepage,0,pszAnsi,-1,psz,cch)) { - mir_free(psz); - return NULL; - } - return psz; -} -#endif - -// mir_free() the return value -#if defined(_UNICODE) -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; -} -#endif - -void TrimString(TCHAR *pszStr) -{ - int i; - TCHAR *psz,szChars[]=_T(" \r\n\t"); - for(i=0;ilpszCaption); /* 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; - ts=localtime(×tamp); /* 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); - #if defined(_UNICODE) - static int (WINAPI *pfnGetDurationFormat)(LCID,DWORD,const SYSTEMTIME*,double,WCHAR*,WCHAR*,int); - #endif - /* Init */ - if(!fInited) { - #if defined(_UNICODE) - *(PROC*)&pfnGetDurationFormat=GetProcAddress(GetModuleHandleA("KERNEL32"),"GetDurationFormat"); - if(pfnGetDurationFormat==NULL) { - #endif - HMODULE hShlwDLL=LoadLibraryA("SHLWAPI"); /* all ascii */ - #if defined(_UNICODE) - *(PROC*)&pfnStrFromTimeInterval=GetProcAddress(hShlwDLL,"StrFromTimeIntervalW"); - #else - *(PROC*)&pfnStrFromTimeInterval=GetProcAddress(hShlwDLL,"StrFromTimeIntervalA"); - #endif - #if defined(_UNICODE) - } - #endif - fInited=TRUE; - } - /* WinVista */ - #if defined(_UNICODE) - 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; - } - #endif - /* 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 */ - } - return CallService(MS_FONT_REGISTERT,(WPARAM)&fid,(LPARAM)&fid); -} - -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 */ - return CallService(MS_COLOUR_REGISTERT,(WPARAM)&cid,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 (HANDLE)CallService(MS_SKIN2_ADDICON,0,(LPARAM)&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); - } - } - return CallService(MS_SKIN_ADDNEWSOUND,0,(LPARAM)&ssd); -} - -/* workaround for 'Hotkey Service' plugin because it has needs an event catcher */ -static char szHotkeyService[MAXMODULELABELLENGTH]; -static int moduleId,itemId; -static int HotkeysServiceHotkeyPressed(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - if(((THKSEvent*)wParam)->moduleId==moduleId && ((THKSEvent*)wParam)->itemId==LOWORD(itemId)) - CallService(szHotkeyService,0,0); - return 0; -} - -/* defines for 'Hotkey Manager' */ -#define HK_ACT_OVERWRITE 0 -#define HKF_GLOBAL 0x00000001 -#define HKF_WPARNUM 0x00000008 -#define HKF_HEX 0x00000200 -#define HKF_LCURRENT 0x00001000 -#define HKT_SERVICE 2 -typedef struct { - void *reserved1; - void *reserved2; - int hotkey; - WCHAR* descr; - DWORD flags; - ATOM reserved3; - DWORD _type; - char* service; - WPARAM wparam; - LPARAM lparam; -} HOTKEYREC; -#define MS_HK_ADDHOTKEY "HotKey/AddHotkey" - -int SkinAddNewHotkey(const char *pszDbName,const char *pszSection,const char *pszDescription,UINT vk,UINT hotkeyfModifiers,const char *pszServiceName) -{ - if(ServiceExists(MS_SKIN_ADDHOTKEY)) { /* clist_mw, clist_modern */ - SKINHOTKEYDESCEX shd; - ZeroMemory(&shd,sizeof(shd)); - shd.cbSize=sizeof(shd); - shd.pszName=(char*)pszDbName; - shd.pszDescription=(char*)pszDescription; - shd.pszSection=(char*)pszSection; - shd.pszService=(char*)pszServiceName; - shd.DefHotKey=MAKEWORD(vk,hotkeyfModifiers); - CallService(MS_SKIN_ADDHOTKEY,0,(LPARAM)&shd); - /* no return */ - } - if(ServiceExists(MS_HOTKEYSPLUS_ADDKEY)) /* 'Hotkeys Plus' */ - return CallService(MS_HOTKEYSPLUS_ADDKEY,(WPARAM)pszServiceName,(LPARAM)pszDescription); - if(ServiceExists(HKS_REGISTERFUNCTION)) { /* mHotKey */ - KEYHASH kh; - kh.isShift=(hotkeyfModifiers&HOTKEYF_SHIFT)!=0; - kh.isCtrl=(hotkeyfModifiers&HOTKEYF_CONTROL)!=0; - kh.isAlt=(hotkeyfModifiers&HOTKEYF_ALT)!=0; - kh.vkCode=vk; - return !CallService(HKS_REGISTERFUNCTION,(WPARAM)&kh,(LPARAM)pszServiceName); - } - if(ServiceExists(MS_HK_ADDHOTKEY)) { /* 'Hotkey Manager' */ - HOTKEYREC hkr; - ZeroMemory(&hkr,sizeof(hkr)); - hkr.hotkey=(int)MAKEWORD(vk,hotkeyfModifiers); - #if defined(_UNICODE) - hkr.descr=(WCHAR*)pszDescription; - #else - hkr.descr=(WCHAR*)a2u(pszDescription); - #endif - hkr.flags=HKF_GLOBAL|HKF_WPARNUM|HKF_LCURRENT|HKF_HEX; - hkr._type=HKT_SERVICE; - hkr.service=(char*)pszServiceName; - CallService(MS_HK_ADDHOTKEY,(WPARAM)&hkr,HK_ACT_OVERWRITE); - #if !defined(_UNICODE) - mir_free(hkr.descr); - #endif - return 0; - } - if(ServiceExists(MS_HKS_REGISTER_ITEM)) { /* 'Hotkeys Service' */ - THKSItem item; - ZeroMemory(&item,sizeof(item)); - item.name=(char*)pszSection; - item.itemType=HKS_ITEM_MODULE; - item.owner=LOWORD(CallService(MS_HKS_REGISTER_ITEM,(WPARAM)&item,0)); - item.name=(char*)pszDescription; - item.itemType=HKS_ITEM_ACTION; - item.hotkey.key=(WORD)vk; - item.hotkey.modifiers=MOD_GLOBAL; - if(hotkeyfModifiers&HOTKEYF_ALT) item.hotkey.modifiers|=MOD_ALT; - if(hotkeyfModifiers&HOTKEYF_CONTROL) item.hotkey.modifiers|=MOD_CONTROL; - if(hotkeyfModifiers&HOTKEYF_SHIFT) item.hotkey.modifiers|=MOD_SHIFT; - if(hotkeyfModifiers&HOTKEYF_EXT) item.hotkey.modifiers|=MOD_WIN; - /* no possibility to specify a service to call, - * all processing needs to be done in the plugins */ - moduleId=item.owner; - mir_snprintf(szHotkeyService,sizeof(szHotkeyService),"%s",pszServiceName); // only allows for one hotkey as a whole - HookEvent(ME_HKS_KEY_PRESSED,HotkeysServiceHotkeyPressed); - itemId=CallService(MS_HKS_REGISTER_ITEM,(WPARAM)&item,0); - return HIWORD(itemId); - } - return 1; -} diff --git a/plugins/AutoShutdown/utils.cpp b/plugins/AutoShutdown/utils.cpp new file mode 100644 index 0000000000..b9bbddbc01 --- /dev/null +++ b/plugins/AutoShutdown/utils.cpp @@ -0,0 +1,458 @@ +/* + +'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 +#if !defined(_UNICODE) +WCHAR* a2u(const char *pszAnsi) +{ + int codepage,cch; + WCHAR *psz; + + if(pszAnsi==NULL) return NULL; + codepage=CallService(MS_LANGPACK_GETCODEPAGE,0,0); + cch=MultiByteToWideChar(codepage,0,pszAnsi,-1,NULL,0); + if(!cch) return NULL; + + psz=(WCHAR*)mir_alloc(cch*sizeof(WCHAR)); + if(psz!=NULL && !MultiByteToWideChar(codepage,0,pszAnsi,-1,psz,cch)) { + mir_free(psz); + return NULL; + } + return psz; +} +#endif + +// mir_free() the return value +#if defined(_UNICODE) +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; +} +#endif + +void TrimString(TCHAR *pszStr) +{ + int i; + TCHAR *psz,szChars[]=_T(" \r\n\t"); + for(i=0;ilpszCaption); /* 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; + ts=localtime(×tamp); /* 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); + #if defined(_UNICODE) + static int (WINAPI *pfnGetDurationFormat)(LCID,DWORD,const SYSTEMTIME*,double,WCHAR*,WCHAR*,int); + #endif + /* Init */ + if(!fInited) { + #if defined(_UNICODE) + *(PROC*)&pfnGetDurationFormat=GetProcAddress(GetModuleHandleA("KERNEL32"),"GetDurationFormat"); + if(pfnGetDurationFormat==NULL) { + #endif + HMODULE hShlwDLL=LoadLibraryA("SHLWAPI"); /* all ascii */ + #if defined(_UNICODE) + *(PROC*)&pfnStrFromTimeInterval=GetProcAddress(hShlwDLL,"StrFromTimeIntervalW"); + #else + *(PROC*)&pfnStrFromTimeInterval=GetProcAddress(hShlwDLL,"StrFromTimeIntervalA"); + #endif + #if defined(_UNICODE) + } + #endif + fInited=TRUE; + } + /* WinVista */ + #if defined(_UNICODE) + 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; + } + #endif + /* 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 */ + } + return CallService(MS_FONT_REGISTERT,(WPARAM)&fid,(LPARAM)&fid); +} + +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 */ + return CallService(MS_COLOUR_REGISTERT,(WPARAM)&cid,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 (HANDLE)CallService(MS_SKIN2_ADDICON,0,(LPARAM)&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); + } + } + return CallService(MS_SKIN_ADDNEWSOUND,0,(LPARAM)&ssd); +} + +/* workaround for 'Hotkey Service' plugin because it has needs an event catcher */ +static char szHotkeyService[MAXMODULELABELLENGTH]; +static int moduleId,itemId; +static int HotkeysServiceHotkeyPressed(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + if(((THKSEvent*)wParam)->moduleId==moduleId && ((THKSEvent*)wParam)->itemId==LOWORD(itemId)) + CallService(szHotkeyService,0,0); + return 0; +} + +/* defines for 'Hotkey Manager' */ +#define HK_ACT_OVERWRITE 0 +#define HKF_GLOBAL 0x00000001 +#define HKF_WPARNUM 0x00000008 +#define HKF_HEX 0x00000200 +#define HKF_LCURRENT 0x00001000 +#define HKT_SERVICE 2 +typedef struct { + void *reserved1; + void *reserved2; + int hotkey; + WCHAR* descr; + DWORD flags; + ATOM reserved3; + DWORD _type; + char* service; + WPARAM wparam; + LPARAM lparam; +} HOTKEYREC; +#define MS_HK_ADDHOTKEY "HotKey/AddHotkey" + +int SkinAddNewHotkey(const char *pszDbName,const char *pszSection,const char *pszDescription,UINT vk,UINT hotkeyfModifiers,const char *pszServiceName) +{ + if(ServiceExists(MS_SKIN_ADDHOTKEY)) { /* clist_mw, clist_modern */ + SKINHOTKEYDESCEX shd; + ZeroMemory(&shd,sizeof(shd)); + shd.cbSize=sizeof(shd); + shd.pszName=(char*)pszDbName; + shd.pszDescription=(char*)pszDescription; + shd.pszSection=(char*)pszSection; + shd.pszService=(char*)pszServiceName; + shd.DefHotKey=MAKEWORD(vk,hotkeyfModifiers); + CallService(MS_SKIN_ADDHOTKEY,0,(LPARAM)&shd); + /* no return */ + } + if(ServiceExists(MS_HOTKEYSPLUS_ADDKEY)) /* 'Hotkeys Plus' */ + return CallService(MS_HOTKEYSPLUS_ADDKEY,(WPARAM)pszServiceName,(LPARAM)pszDescription); + if(ServiceExists(HKS_REGISTERFUNCTION)) { /* mHotKey */ + KEYHASH kh; + kh.isShift=(hotkeyfModifiers&HOTKEYF_SHIFT)!=0; + kh.isCtrl=(hotkeyfModifiers&HOTKEYF_CONTROL)!=0; + kh.isAlt=(hotkeyfModifiers&HOTKEYF_ALT)!=0; + kh.vkCode=vk; + return !CallService(HKS_REGISTERFUNCTION,(WPARAM)&kh,(LPARAM)pszServiceName); + } + if(ServiceExists(MS_HK_ADDHOTKEY)) { /* 'Hotkey Manager' */ + HOTKEYREC hkr; + ZeroMemory(&hkr,sizeof(hkr)); + hkr.hotkey=(int)MAKEWORD(vk,hotkeyfModifiers); + #if defined(_UNICODE) + hkr.descr=(WCHAR*)pszDescription; + #else + hkr.descr=(WCHAR*)a2u(pszDescription); + #endif + hkr.flags=HKF_GLOBAL|HKF_WPARNUM|HKF_LCURRENT|HKF_HEX; + hkr._type=HKT_SERVICE; + hkr.service=(char*)pszServiceName; + CallService(MS_HK_ADDHOTKEY,(WPARAM)&hkr,HK_ACT_OVERWRITE); + #if !defined(_UNICODE) + mir_free(hkr.descr); + #endif + return 0; + } + if(ServiceExists(MS_HKS_REGISTER_ITEM)) { /* 'Hotkeys Service' */ + THKSItem item; + ZeroMemory(&item,sizeof(item)); + item.name=(char*)pszSection; + item.itemType=HKS_ITEM_MODULE; + item.owner=LOWORD(CallService(MS_HKS_REGISTER_ITEM,(WPARAM)&item,0)); + item.name=(char*)pszDescription; + item.itemType=HKS_ITEM_ACTION; + item.hotkey.key=(WORD)vk; + item.hotkey.modifiers=MOD_GLOBAL; + if(hotkeyfModifiers&HOTKEYF_ALT) item.hotkey.modifiers|=MOD_ALT; + if(hotkeyfModifiers&HOTKEYF_CONTROL) item.hotkey.modifiers|=MOD_CONTROL; + if(hotkeyfModifiers&HOTKEYF_SHIFT) item.hotkey.modifiers|=MOD_SHIFT; + if(hotkeyfModifiers&HOTKEYF_EXT) item.hotkey.modifiers|=MOD_WIN; + /* no possibility to specify a service to call, + * all processing needs to be done in the plugins */ + moduleId=item.owner; + mir_snprintf(szHotkeyService,sizeof(szHotkeyService),"%s",pszServiceName); // only allows for one hotkey as a whole + HookEvent(ME_HKS_KEY_PRESSED,HotkeysServiceHotkeyPressed); + itemId=CallService(MS_HKS_REGISTER_ITEM,(WPARAM)&item,0); + return HIWORD(itemId); + } + return 1; +} diff --git a/plugins/AutoShutdown/watcher.c b/plugins/AutoShutdown/watcher.c deleted file mode 100644 index 75a2881e98..0000000000 --- a/plugins/AutoShutdown/watcher.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - -'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(HANDLE *phDoneEvent) -{ - 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) -{ -#if defined(_UNICODE) - 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; - } -#else - (*ppBlob)[*pcbBlob]=0; - return (char*)*ppBlob; -#endif -} - -static int MsgEventAdded(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - 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; - UNREFERENCED_PARAMETER(wParam); - if(ack->type==ACKTYPE_FILE) - switch(ack->result) { - case ACKRESULT_DATA: - { int i; - for(i=0;ihProcess) - 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;ihProcess) { - /* 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) -{ - UNREFERENCED_PARAMETER(wParam); - 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) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - if(DBGetContactSettingByte(NULL,"AutoShutdown","HddOverheatShutdown",SETTING_HDDOVERHEATSHUTDOWN_DEFAULT)) - ServiceShutdown(SDSDT_SHUTDOWN,TRUE); - return 0; -} - -/************************* Services ***********************************/ - -int ServiceStartWatcher(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - - /* 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 ServiceStopWatcher(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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 ServiceIsWatcherEnabled(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - return currentWatcherType!=0; -} - -/************************* Misc ***********************************/ - -static int WatcherModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(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/watcher.cpp b/plugins/AutoShutdown/watcher.cpp new file mode 100644 index 0000000000..75a2881e98 --- /dev/null +++ b/plugins/AutoShutdown/watcher.cpp @@ -0,0 +1,408 @@ +/* + +'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(HANDLE *phDoneEvent) +{ + 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) +{ +#if defined(_UNICODE) + 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; + } +#else + (*ppBlob)[*pcbBlob]=0; + return (char*)*ppBlob; +#endif +} + +static int MsgEventAdded(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + 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; + UNREFERENCED_PARAMETER(wParam); + if(ack->type==ACKTYPE_FILE) + switch(ack->result) { + case ACKRESULT_DATA: + { int i; + for(i=0;ihProcess) + 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;ihProcess) { + /* 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) +{ + UNREFERENCED_PARAMETER(wParam); + 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) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + if(DBGetContactSettingByte(NULL,"AutoShutdown","HddOverheatShutdown",SETTING_HDDOVERHEATSHUTDOWN_DEFAULT)) + ServiceShutdown(SDSDT_SHUTDOWN,TRUE); + return 0; +} + +/************************* Services ***********************************/ + +int ServiceStartWatcher(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + + /* 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 ServiceStopWatcher(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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 ServiceIsWatcherEnabled(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + return currentWatcherType!=0; +} + +/************************* Misc ***********************************/ + +static int WatcherModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(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); +} -- cgit v1.2.3