Click here to Skip to main content
15,896,207 members
Articles / Desktop Programming / WTL

RSS Reader Plug-in for Internet Explorer

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
16 Jul 2007CPOL4 min read 317.7K   1.3K   32  
This is a toolbar for the Internet Explorer which shows information from RSS taken from the Internet.
// MainFrm.h : interface of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////

#pragma once
#include <vld.h>
#include <vector>
#include <string>
#include <atlmisc.h>
#include <wininet.h>
#include <iphlpapi.h>

#include "AmHttpSocket.h"

#pragma comment(lib,"WS2_32.Lib")


#define RRP_RSSFETCH WM_USER + 10
#define RRP_FETCHCOMPLETE WM_USER + 11
#define RRP_REFRESH WM_USER + 12
#define RRP_REMOVE WM_USER + 13
#define RRP_TOOLBAR_REG WM_USER + 14
#define RRP_TOOLBAR_UNREG WM_USER + 15
#define RRP_FETCHER_PROCESS_BUSY WM_USER + 16
#define RRP_FETCHER_PROCESS_FREE WM_USER + 17
#define RRP_CLEAN WM_USER + 18


#include "ras.h"
#define RASCN_Connection        0x00000001
DWORD (WINAPI *RasNotify)(HRASCONN, HANDLE, DWORD);


using namespace std;




//Structures used in message exchange
typedef struct RssInfo {
	UINT message;
	string localName;
	string remoteName;
	FILETIME systemTime;
}RssInfo;



typedef struct TRssInfo {
	UINT message;
	char localName[50];//cant be more than 10 actually
	char remoteName[1024];//I've heard this is the URL limit
	HWND toolbarHandle;
}TRssInfo;



class CMainFrame : public CFrameWindowImpl<CMainFrame>,
				   public CMessageFilter,
				   public CIdleHandler
{
public:
	DECLARE_FRAME_WND_CLASS("RRPRssFetcherWindowClass", IDR_MAINFRAME)

	virtual BOOL PreTranslateMessage(MSG* pMsg)	{
		return CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg);
	}

	virtual BOOL OnIdle()	{
		return FALSE;
	}

	CMainFrame() {
		retryCount = 0;
		oneMinCount = 0;
		::GetSystemTimeAsFileTime(&startTime);
	}
	~CMainFrame() {
//		rssDir.~basic_string();
	}

	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_COPYDATA, OnWmCopy)
		MESSAGE_HANDLER(WM_CLOSE, OnClose)
		MESSAGE_HANDLER(WM_TIMER, OnTimer)
		MESSAGE_HANDLER(RRP_TOOLBAR_REG,OnToolbarReg)
		MESSAGE_HANDLER(RRP_TOOLBAR_UNREG,OnToolbarUnReg)
		MESSAGE_HANDLER(RRP_CLEAN,OnClean)
		MESSAGE_HANDLER(RRP_RSSFETCH,OnRssFetchRequest)
		MESSAGE_HANDLER(RRP_REMOVE ,OnRssRemove)
		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	LRESULT	OnToolbarReg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
//		::MessageBox(NULL,"Toolbar Reg","Message",MB_ICONHAND);
		referenceCount++;
		return 0;
	}
	
	
	LRESULT	OnToolbarUnReg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
//		::MessageBox(NULL,"Toolbar UnReg","Message",MB_ICONHAND);
		referenceCount--;
		if(referenceCount <= 0)
			PostMessage(WM_CLOSE);
		return 0;
	}

	LRESULT	OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) {
		if(wParam == 2) {
			if(referenceCount <= 0)
				PostMessage(WM_CLOSE);
			oneMinCount++;
			if(oneMinCount%12 == 0) {
				::PostMessage(m_toolbarHandle,RRP_FETCHER_PROCESS_FREE,0,0);
				retryCount = 0;
			}
			return 0;
		}
		::GetSystemTimeAsFileTime(&startTime);
		return 0;
	}

	LRESULT	OnClean(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
		int n = rssInfoVector.size();
		for(int i = 0;i<n;i++) {
//			if(rssInfoVector[i]) {
			if(true) {
				rssInfoVector[i].systemTime.dwHighDateTime = 0;
				rssInfoVector[i].systemTime.dwLowDateTime = 0;
			}
		}
		return 0;
	}


	UINT ConnNotification(HWND toolbarHandle) {
	  SECURITY_ATTRIBUTES SecAtt;
      SecAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
	  SecAtt.lpSecurityDescriptor = NULL;
	  SecAtt.bInheritHandle = FALSE;
	  HANDLE hActive = CreateEvent(&SecAtt, TRUE, FALSE, "Connect");
	  HANDLE hInst = LoadLibrary("rasapi32.dll");
 	  RasNotify = (DWORD (WINAPI *)(HRASCONN, HANDLE, DWORD)) GetProcAddress ((HMODULE) hInst, "RasConnectionNotificationA");
	  DWORD ret = ::RasNotify((HRASCONN)INVALID_HANDLE_VALUE, hActive, RASCN_Connection);
	  if(ret == 0) 
	      WaitForSingleObject(hActive, INFINITE);
	  ::FreeLibrary((HMODULE)hInst);
	  return 0;
	}



	
	//Invoked when the rss fetch request comes
	LRESULT	OnRssFetchRequest(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) { 
		RssInfo *obj = reinterpret_cast<RssInfo *>(lParam);
		HWND toolbarHandle = reinterpret_cast<HWND>(wParam);

		::PostMessage(toolbarHandle,RRP_FETCHER_PROCESS_BUSY,0,0);

		char *receivedData = httpRequest.GetPage(obj->remoteName.c_str());
		if(!receivedData) {
			delete obj;
			::PostMessage(toolbarHandle,RRP_FETCHER_PROCESS_FREE,0,0);
			return 0;
		}
		//Checkinng if the downloaded file is the xml file
		if(strstr(receivedData,"<?xml") != receivedData) {
//			delete receivedData;
			delete obj;
			::PostMessage(toolbarHandle,RRP_FETCHER_PROCESS_FREE,0,0);
			return 0;
		}

		if(strcmp(receivedData,"Error") == 0) {
	//		delete receivedData;
			delete obj;
			::PostMessage(toolbarHandle,RRP_FETCHER_PROCESS_FREE,0,0);
			return 0;
		}
		//Creating the file name
		string dir = getInstallationDirectory();
		string myFile = dir;
		myFile +=  "\\rss\\";
		myFile += obj->localName;
		FILE *fp = fopen(myFile.c_str(),"w");
		fprintf(fp,"%s",receivedData);
		fclose(fp);

		//RRP_FETCHCOMPLETE also tells that process is free now!!
		::PostMessage(toolbarHandle,RRP_FETCHCOMPLETE,0,0);
		bool found = false;
		int n = rssInfoVector.size();
		for(int i = 0;i<n;i++) {
//			if(rssInfoVector[i]) {
			if(true) {
				if(rssInfoVector[i].remoteName.compare(obj->remoteName)) {
					found = true;
					GetSystemTimeAsFileTime(&(rssInfoVector[i].systemTime));
				}
			}
		}
		
		if(found == false) {
			RssInfo tobj;
			tobj.localName = obj->localName;
			tobj.remoteName = obj->remoteName;
			tobj.systemTime = obj->systemTime;
			GetSystemTimeAsFileTime(&(tobj.systemTime));
			rssInfoVector.push_back(tobj);
		}
		delete obj;
		return 0;
	}

	//Invoked when rss remove request comes
	LRESULT	OnRssRemove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) { 
/*		int n = rssInfoVector.size();
		RssInfo *obj = reinterpret_cast<RssInfo*>(lParam);
		for(int i=0;i<n;i++)
			if(rssInfoVector[i].remoteName.compare(obj->remoteName)) {
				rssInfoVector.erase(i);
				break;
			}*/
		return 0;
	}


	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
		init();
		referenceCount = 0;
//		rssInfoVector = std::vector<RssInfo*>();
		SetTimer(1,1000*60*10);
		SetTimer(2,5000);
//		request = Request();
//		register object for message filtering and idle updates
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		return 0;
	}

	//De-Multiplexing messages
	//Need to see if the files are really present on the disk or not
	LRESULT OnWmCopy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) {
		COPYDATASTRUCT *cds = reinterpret_cast<COPYDATASTRUCT *>(lParam);
		RssInfo *obj;
//		rssInfo->toolbarHandle;		
		if(cds->cbData = sizeof(TRssInfo)) {
			TRssInfo *rssInfo = reinterpret_cast<TRssInfo *>(cds->lpData);
			int n = rssInfoVector.size();
			bool loaded = false;
			for(int i = 0;i<n;i++) {
//				if(rssInfoVector[i]) {
				if(true) {
					if(rssInfoVector[i].remoteName.compare(rssInfo->remoteName) == 0) {
						if(rssInfoVector[i].systemTime.dwHighDateTime > startTime.dwHighDateTime) {
							loaded = true;
							break;
						}
						else
							if((rssInfoVector[i].systemTime.dwHighDateTime == startTime.dwHighDateTime) &&
								(rssInfoVector[i].systemTime.dwLowDateTime > startTime.dwLowDateTime)) {
									loaded = true;
									break;
							}
					}
				}
			}
			if(loaded) {
				::PostMessage(rssInfo->toolbarHandle,RRP_FETCHCOMPLETE,0,0);
				return 0;
			}
			switch(rssInfo->message) {
				case RRP_RSSFETCH: 
					if(prevRomoteFilename.compare(rssInfo->remoteName) == 0)
						retryCount++;
					//If the retry request comes for the same file 
					//more than 5 times It means that Probably internet connection
					//is not there,so send FREE messaged after 1 min
					if(retryCount >= 5) {
						m_toolbarHandle = rssInfo->toolbarHandle;
						::PostMessage(rssInfo->toolbarHandle,RRP_FETCHER_PROCESS_BUSY,0,0);
						return 0;
					}
					prevRomoteFilename = rssInfo->remoteName;
					obj =  getRssInfo(rssInfo->localName,rssInfo->remoteName);
					PostMessage(RRP_RSSFETCH,reinterpret_cast<WPARAM>(rssInfo->toolbarHandle),(LPARAM)obj);
					break;
				case RRP_REMOVE: 
					obj =  getRssInfo(rssInfo->localName,rssInfo->remoteName);
					PostMessage(RRP_RSSFETCH,reinterpret_cast<WPARAM>(rssInfo->toolbarHandle),(LPARAM)obj);
					break;
			}
		}
		
		return 0;
	}

	LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) {
		if(referenceCount <= 0) {
			DestroyWindow();

		}
		return 0;
	}

	RssInfo * getRssInfo(char *localName,char *remoteName) {
		RssInfo *rssInfo = new RssInfo();
		ZeroMemory(rssInfo,sizeof(RssInfo));
		rssInfo->localName = localName;
		rssInfo->remoteName = remoteName;
		return rssInfo;
	}

	string getInstallationDirectory() {
		return rssDir;
	}

	void init() {
		CRegKey currentVersionRegEntry;
		TCHAR programFilesAddress[2048];
		currentVersionRegEntry.Create(HKEY_LOCAL_MACHINE, 
			_T("Software\\Microsoft\\Windows\\CurrentVersion"));
		DWORD length= 2048;
		if(ERROR_SUCCESS ==
			currentVersionRegEntry.QueryValue(programFilesAddress, _T("ProgramFilesDir"),&length)) { 
				rssDir = programFilesAddress;
				rssDir += _T("\\RssReader for IE");
		}
		else {
		//C:\\Program Files is taken as default
			rssDir = _T("C:\\Program Files\\RssReader for IE");
		}
//		rssDir = rssDirectory;
	}

private:
		int referenceCount;
		std::vector<RssInfo> rssInfoVector;
		string rssDir;
		string prevRomoteFilename;
		int retryCount;
		ULONG oneMinCount;
		HWND m_toolbarHandle ;
		FILETIME CMainFrame::startTime;
		//File Time is much easier to handle
		CAmHttpSocket httpRequest;
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
Quote : "Life is all about solving problems and enjoying their solutions !! "

Comments and Discussions