RegistryNotify.cpp

/****************************************************************************/

/**                                                                        **/

/** 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