|
|
|
|
|
|
||
|
/****************************************************************************/ /**
**/ /** Copyright
(c) 2005 Diodia Software (http://www.diodia.com/) **/ /**
**/ /** Use in any
form with or without modification for commercial and non- **/ /** commercial
purposes is permitted. **/ /**
**/ /****************************************************************************/ #include "stdafx.h"
#include "ThreadObject.h" #include "Helper.h" #include "RegistryNotifyC.h"
/****************************************************************************/ /* /* DESCRIPTION : Registry notify timer data. /* /****************************************************************************/ struct RegistryNotifyTimerDataC { RegistryNotifyTimerDataC() { RegistryNotify = NULL; TimerId = 0; };
RegistryNotifyC *RegistryNotify; UINT TimerId; };
ThreadObjectT<RegistryNotifyTimerDataC> TimerData;
/****************************************************************************/ /* /* DESCRIPTION : RegistryNotifyC factory. /* /* RETURN VALUE: - /* /****************************************************************************/ RegistryNotifyI *RegistryNotifyCreate() { return new RegistryNotifyC; }
/****************************************************************************/ /* /* DESCRIPTION : RegistryNotifyC constructor. /* /* RETURN VALUE: - /* /****************************************************************************/ RegistryNotifyC::RegistryNotifyC() { mNextId = 0;
mUpdate = CreateEvent(NULL, FALSE, FALSE, NULL); mTerminate = CreateEvent(NULL, FALSE, FALSE, NULL); mMutex = CreateMutex(NULL, FALSE, NULL);
if (mUpdate && mTerminate && mMutex) { mThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) _ThreadProc, (LPVOID) this, 0, &mThreadId); } else { mThread = NULL; mThreadId = 0; } }
/****************************************************************************/ /* /* DESCRIPTION : RegistryNotifyC destructor. /* /* RETURN VALUE: - /* /****************************************************************************/ RegistryNotifyC::~RegistryNotifyC() { StopTimer();
if (mThread) { SetEvent(mTerminate); WaitForSingleObject(mThread, INFINITE); }
if (mTerminate) CloseHandle(mTerminate); if (mMutex) CloseHandle(mMutex); if (mUpdate) CloseHandle(mUpdate);
for (RegHandlerListC::iterator Idx = mHandlers.begin();
Idx != mHandlers.end();
Idx++) {
delete *Idx; } }
/****************************************************************************/ /* /* DESCRIPTION : Add handler. /* /* RETURN VALUE: None /* /****************************************************************************/ int RegistryNotifyC::AddHandler(HKEY MainKey, const char *SubKey, const char *Name, RegistryNotifyHandlerI *Handler) { OneRegHandlerC *OneRegHandler;
if (!mMutex) return 0;
WaitForSingleObject(mMutex, INFINITE); SetEvent(mUpdate);
StartTimer();
OneRegHandler = new OneRegHandlerC(MainKey, SubKey, Name, Handler);
OneRegHandler->mId = ++mNextId; mHandlers.push_back(OneRegHandler);
ReleaseMutex(mMutex);
return OneRegHandler->mId; }
/****************************************************************************/ /* /* DESCRIPTION : Remove handler. /* /* RETURN VALUE: None /* /****************************************************************************/ void RegistryNotifyC::RemoveHandler(int Id) { if (!mMutex) return;
WaitForSingleObject(mMutex, INFINITE); SetEvent(mUpdate);
for (RegHandlerListC::iterator Idx = mHandlers.begin(); Idx != mHandlers.end(); Idx++) { if ((*Idx)->mId == Id) {
delete *Idx;
mHandlers.erase(Idx); break; } }
if (mHandlers.size() == 0) StopTimer();
ReleaseMutex(mMutex); }
/****************************************************************************/ /* /* DESCRIPTION : Monitor registry. /* /* RETURN VALUE: S_OK /* /****************************************************************************/ DWORD WINAPI RegistryNotifyC::_ThreadProc(RegistryNotifyC *RegistryNotify) { RegistryNotify->ThreadProc(); return S_OK; }
/****************************************************************************/ /* /* DESCRIPTION : Monitor registry. /* /* RETURN VALUE: None /* /****************************************************************************/ void RegistryNotifyC::ThreadProc() { RegHandlerListC::iterator Idx; HANDLE *Handles; DWORD Size; DWORD Res;
while (true) { WaitForSingleObject(mMutex, INFINITE);
Handles = (HANDLE *) malloc((2 + mHandlers.size()) * sizeof(HANDLE));
Handles[0]
= mTerminate;
Handles[1] = mUpdate;
Size = 2;
for (Idx = mHandlers.begin();
Idx != mHandlers.end(); Idx++) { Handles[Size++] = (*Idx)->mNotifyEvent; }
ReleaseMutex(mMutex);
Res = WaitForMultipleObjects(Size, Handles, FALSE, INFINITE); if (Res < WAIT_OBJECT_0 || Res >= WAIT_OBJECT_0 + Size) { free(Handles); return; }
if (Res == WAIT_OBJECT_0) { /* terminate */ free(Handles); return; }
for (Idx = mHandlers.begin(); Idx != mHandlers.end(); Idx++) { if (WaitForSingleObject((*Idx)->mNotifyEvent, 0) == WAIT_OBJECT_0) { (*Idx)->Reset(); (*Idx)->CheckValue(); } }
free(Handles); } }
/****************************************************************************/ /* /* DESCRIPTION : Handle registry events. /* /* RETURN VALUE: None /* /****************************************************************************/ void RegistryNotifyC::HandleEvents() { RegHandlerListC::iterator Idx;
for (Idx = mHandlers.begin(); Idx != mHandlers.end(); Idx++) { if ((*Idx)->mChanged) { (*Idx)->mHandler->RegistryChanged((*Idx)->mMainKey, (*Idx)->mSubKey.c_str()); (*Idx)->mChanged = false; } } }
/****************************************************************************/ /* /* DESCRIPTION : Registry notify timer. /* /* RETURN VALUE: None /* /****************************************************************************/ void CALLBACK RegistryNotifyC::_RegistryNotifyTimer(HWND hWnd, UINT Msg, UINT EventId, DWORD Time) { TimerData.Find()->RegistryNotify->HandleEvents(); }
/****************************************************************************/ /* /* DESCRIPTION : Start registry notify timer. /* /* RETURN VALUE: None /* /****************************************************************************/ void RegistryNotifyC::StartTimer() { if (TimerData.Find()->TimerId == 0) { TimerData.Find()->RegistryNotify = this; TimerData.Find()->TimerId = (UINT) SetTimer(NULL, 0, 1000, _RegistryNotifyTimer); } }
/****************************************************************************/ /* /* DESCRIPTION : Stop registry notify timer. /* /* RETURN VALUE: None /* /****************************************************************************/ void RegistryNotifyC::StopTimer() { if (TimerData.Find()->TimerId != 0) { KillTimer(NULL, TimerData.Find()->TimerId); TimerData.Find()->RegistryNotify = NULL; TimerData.Find()->TimerId = 0; } }
/****************************************************************************/ /* /* DESCRIPTION : OneRegHandlerC constructor. /* /* RETURN VALUE: - /* /****************************************************************************/ OneRegHandlerC::OneRegHandlerC(HKEY MainKey, const char *SubKey, const char *Name, RegistryNotifyHandlerI *Handler) { LONG Res;
mMainKey = MainKey; mSubKey = SubKey; if (Name) mName = Name; mValue = NULL; mSize = 0; mHandler = Handler; mNotifyEvent = NULL; mKey = NULL; mChanged = false;
Res = RegOpenKeyEx(mMainKey, mSubKey.c_str(), 0, KEY_NOTIFY, &mKey); if (Res != ERROR_SUCCESS) return;
mNotifyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!mNotifyEvent) { RegCloseKey(mKey); mKey = NULL; return; }
RegNotifyChangeKeyValue(mKey, TRUE, REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY, mNotifyEvent, TRUE);
mSize = RegistryReadBinary(mMainKey, mSubKey.c_str(), mName.c_str(), &mValue); }
/****************************************************************************/ /* /* DESCRIPTION : OneRegHandlerC destructor. /* /* RETURN VALUE: - /* /****************************************************************************/ OneRegHandlerC::~OneRegHandlerC() { if (mNotifyEvent) CloseHandle(mNotifyEvent); if (mKey) RegCloseKey(mKey); if (mValue) free(mValue); }
/****************************************************************************/ /* /* DESCRIPTION : Check if value has changed. /* /* RETURN VALUE: - /* /****************************************************************************/ void OneRegHandlerC::CheckValue() { char *Value; int Size;
if (mName.empty()) { mChanged = true; return; }
Size = RegistryReadBinary(mMainKey, mSubKey.c_str(), mName.c_str(), &Value); if (Size != mSize || (Size > 0 && memcmp(Value, mValue, Size))) { free(mValue); mValue = Value; mSize = Size; mChanged = true; return; }
if (Value) free(Value); }
/****************************************************************************/ /* /* DESCRIPTION : Reset handler. /* /* RETURN VALUE: - /* /****************************************************************************/ void OneRegHandlerC::Reset() { LONG Res;
if (mKey) { RegCloseKey(mKey); mKey = NULL; }
Res = RegOpenKeyEx(mMainKey, mSubKey.c_str(), 0, KEY_NOTIFY, &mKey); if (Res != ERROR_SUCCESS) return;
RegNotifyChangeKeyValue(mKey, TRUE, REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY, mNotifyEvent, TRUE);
ResetEvent(mNotifyEvent); } |
Source Files Commands.cpp Context.cpp CreatePath.cpp DateParser.cpp DlgEditFeedC.cpp DlgManageFeedsC.cpp Hook.cpp Iso8601.cpp MsXmlMisc.cpp MsXmlSelect.cpp RegistryNotify.cpp RegistryUtil.cpp RSS.cpp RSS.def RSS.idl RssAction.cpp RssDownloader.cpp RssFeed.cpp RssHelpers.cpp RssInit.cpp RssItem.cpp RssMultiFeed.cpp RssTimer.cpp RssXml.cpp StdAfx.cpp Header Files Commands.h ContextC.h DateParser.h DlgEditFeedC.h DlgManageFeedsC.h Helper.h HookC.h RegistryNotify.h RegistryNotifyC.h Resource.h RssDownloaderC.h RssFeedC.h RssHelpers.h RssItemC.h RssMultiFeedC.h StdAfx.h ThreadObject.h XmlHelpers.h Resource Files about.htm DiodiaLogoSmall.gif logo.bmp manifest.xml read.bmp RSS.rc RSS.rgs ToolBandLayout.xml |
|
|
© 2002-2008 Diodia Software |
||