| evgueny az 2005-12-04, 7:02 pm |
| A bit of my code of a homescreen weather plug-in is below.
Problem following: Then I try to load the new forecast, from time to time
phone hangs (switching-off of the battery helps only). And as I have
calculated, lag usually occurs after an output{exit} from a download thread.
Lag occurs only after attempt of loading the forecast and is not regular. If
not to start loading the forecast (in manual or automatically) - all works
wonderfully and does not hang
Also from time to time instead of lag on the screen there is a message
"invalid plugin - please select another.... bla-bla-bla"
I can not understand in what the reason of it about one month: (
#include "sys/xfont.h"
#include "sys/xbitmap.h"
#include "getweather.h"
#include "memplug.h"
#include <atlbase.h>
#include <winuserm.h>
#include "sys/ulog/ulog.h"
#if (DLEVEL > 0)
ULOG ulog("\\Storage\\weatherplugin.log", 1);
#endif
const wchar_t* g_currentpath = L"\\Storage\\Application
Data\\Home\\weather\\";
// Usage:
//
// <plugin clsid="{55EE36E7-7CC3-47e8-85E2-1D8644280EAA}">
// </plugin>
#define IMAGENAME TEXT("weatherplugin.dll")
ULONG g_dwDLLRefCount = 0;
HINSTANCE g_hInstance=NULL;
#define INITGUID
#include "initguid.h"
//{55EE36E7-7CC3-47e8-85E2-1D8644280EAA}
#define CLSIDTEXT__PLUGWEATHER TEXT("55EE36E7-7CC3-47e8-85E2-1D8644280EAA")
DEFINE_GUID(CLSID_PLUGWEATHER, 0x55ee36e7, 0x7cc3, 0x47e8, 0x85, 0xe2, 0x1d,
0x86, 0x44, 0x28, 0xe, 0xaa);
DEFINE_GUID(IID_IHomePlugin, 0x7F0C58E9, 0x4F30, 0x47bb, 0x96, 0x93,
0xd7, 0x78, 0xe9, 0x99, 0xc4, 0x33);
DEFINE_GUID(IID_IHomePluginEnvironment, 0xFF328DC0, 0x22F5, 0x4AC1, 0xA1,
0x03, 0x19, 0xB3, 0x89, 0xC6, 0x33, 0xFA);
DEFINE_GUID(IID_IHomePluginEnvironment2,
0xE01A8A84, 0xDDEF, 0x438e, 0x90,
0x04, 0x3F, 0xB2, 0xA9, 0x08, 0xE4, 0x65);
DEFINE_GUID(IID_IPersistStream, 0x00000109, 0x0000, 0x0000, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
DEFINE_GUID(IID_IPersist, 0x0000010c, 0x0000, 0x0000, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46);
DEFINE_GUID(IID_IObjectWithSite, 0xFC4801A3, 0x2BA9, 0x11CF, 0xA2, 0x29,
0x00, 0xAA, 0x00, 0x3D, 0x73, 0x52);
//#include "home.h"
#include <COGUID.H>
#undef INITGUID
//---------------------------------------------------------------------------------------------------------
#include "connection.h"
#include "resource.h"
enum { connConnecting, connConnected, connDownload, connSuccess, connFailed,
connComplete };
const wchar_t* __fastcall GetStr( const UINT uID )
{
return (const wchar_t*) LoadString(g_hInstance, uID, 0, 0);
}
DWORD WINAPI WeatherUploadThreadProc( LPVOID lpParameter );
bool __fastcall DownloadWeather( WeatherPlugin *Owner, IConnection *con )
{
__TRACEENTER("DownloadWeather()");
bool FSuccess = false;
IXMLDOMDocument *xmldoc;
CoCreateInstance ( CLSID_DOMDocument, NULL,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IXMLDOMDocument,
(void**)&xmldoc );
if (xmldoc==NULL)
{
__TRACE("CoCreateInstance CLSID_DOMDocument failed");
return 0;
}
__TRACE("CoCreateInstance CLSID_DOMDocument");
int partnerid = 1003725713;
const wchar_t *key = L"1729016d019d4a7d";
USTR url = L"http://xoap.weather.com/weather/local/";
url+= Owner->cityId;
url+= L"?cc=*&dayf=2&prod=xoap&par=";
url+= partnerid;
url+= L"&key=";
url+= key;
url+= L"&unit=m";
CComVariant bstrUrl = (wchar_t*)url;
__TRACE("download: "<< (wchar_t*)url );
short state;
xmldoc->put_async( VARIANT_TRUE );
xmldoc->put_validateOnParse( VARIANT_FALSE );
xmldoc->load( bstrUrl, &state);
if (state)
{
__TRACE("downloading");
MSG msg;
long state = READYSTATE_UNINITIALIZED;
Owner->DownloadStatus( connDownload );
DWORD timeout = GetTickCount()+60000;
while ( !Owner->FWeatherUploadTerminate )
{
int dt = timeout - GetTickCount();
__TRACE("downloading timeout: " << dt);
if ( dt <= 0)
{
__TRACE("downloading failed: timeout");
break;
}
if ( con->GetStatus() != CONNMGR_STATUS_CONNECTED )
{
__TRACE("downloading failed: connection was dropped");
break;
}
int process = 25;
__TRACE("process messages: start");
while( P Message(&msg, NULL, 0, 0, PM_REMOVE))
{
__TRACE("message #" << (25-process) << " uid:"<< (HEX)msg.message);
if (msg.message == WM_QUIT) Owner->FWeatherUploadTerminate = 1;
TranslateMessage( &msg );
DispatchMessage(&msg);
if (--process == 0) break;
}
__TRACE("process messages: end");
if (process==25) Sleep(100);
if ( xmldoc->get_readyState( &state )==S_OK)
{
if ( state == READYSTATE_COMPLETE)
{
__TRACE("download complete");
IXMLDOMParseError *xmlerr=0;
long errorcode = 1;
__TRACE("xmldoc->get_parseError()");
xmldoc->get_parseError(&xmlerr);
if (xmlerr)
{
__TRACE("xmlerr->get_errorCode()");
xmlerr->get_errorCode(&errorcode);
xmlerr->Release();
}
if ( errorcode==0 )
{
__TRACE("xml document save");
wchar_t *name = L"\\Storage\\Application
Data\\Home\\weather\\forecast.xml";
CComVariant vname = name;
xmldoc->save( vname );
Owner->DownloadStatus( connSuccess );
FSuccess = true;
__TRACE("xml document succesfully saved");
}
else
__TRACE("xml document parse error. code=" <<(HEX)errorcode );
break;
}
}
else
{
__TRACE("download failed: xmldoc->get_readyState = failed");
break;
}
}
if (FSuccess==false)
{
__TRACE("xml download abort()");
HRESULT hr = xmldoc->abort();
__TRACE("xml download abort code="<<hr);
}
} // if state
xmldoc->Release();
__TRACEEXIT("DownloadWeather()");
return FSuccess;
}
bool __fastcall WeatherUpload( WeatherPlugin *Owner, int connid )
{
__TRACEENTER("WeatherUpload()");
if ( Owner->FWeatherUploadTerminate )
{
__TRACEEXIT("WeatherUpload():: thread terminated");
return false;
}
bool FSuccess = false;
IConnection con;
if ( con.connect(connid) )
{
Owner->DownloadStatus( connConnecting );
__TRACE("connecting");
DWORD timeout = GetTickCount() + 30000;
while( !Owner->FWeatherUploadTerminate )
{
__TRACE("wait connect");
if (GetTickCount()>timeout)
{
__TRACE("connecting failed. timeout");
break;
}
DWORD status = con.GetStatus();
#define break_ifstatus( v ) if ( status == v ) { __TRACE("connecting
failed. status="#v); break; }
//BreakIfStatus( CONNMGR_STATUS_UNKNOWN );
break_ifstatus( CONNMGR_STATUS_DISCONNECTED );
break_ifstatus( CONNMGR_STATUS_CONNECTIONFAILED );
break_ifstatus( CONNMGR_STATUS_CONNECTIONCANCELED );
break_ifstatus( CONNMGR_STATUS_CONNECTIONDISABLED );
break_ifstatus( CONNMGR_STATUS_NOPATHTODESTINATION );
break_ifstatus( CONNMGR_STATUS_WAITINGDISCONNECTION );
if ( con.GetStatus()==CONNMGR_STATUS_CONNECTED)
{
__TRACE("Connected");
Owner->DownloadStatus( connConnected );
FSuccess = DownloadWeather( Owner, &con);
break;
}
Sleep(1000);
}
}
if (FSuccess==false) Owner->DownloadStatus( connFailed );
__TRACEEXIT("WeatherUpload()");
return FSuccess;
};
DWORD WINAPI WeatherUploadThreadProc( LPVOID lpParameter )
{
__TRACEENTER("WeatherUploadThreadProc()");
CoInitializeEx(NULL, COINIT_MULTITHREADED);
WeatherPlugin *Owner = (WeatherPlugin*) lpParameter;
int idInternet=-1;
int idWork =-1;
int id = 0;
wchar_t *name;
IConnection con;
while( (name = con.GetName(id)) )
{
if (wcscmp( name, L"Work") ==0) idWork = id;
if (wcscmp( name, L"The Internet")==0) idInternet = id;
id++;
}
bool download=0;
if (idWork != -1) download = WeatherUpload(Owner,
ork );
if (!download && idInternet != -1) download = WeatherUpload(Owner,
idInternet);
Owner->DownloadStatus( connComplete );
CoUninitialize();
__TRACEEXIT("WeatherUploadThreadProc()");
return 1;
}
WeatherPlugin::WeatherPlugin(): m_cRef(1),
m_ppe(NULL)
{
__TRACEENTER("WeatherPlugin::WeatherPlugin()");
g_hInstance = GetModuleHandle(IMAGENAME);
g_dwDLLRefCount++;
hWeatherUploadThread = NULL;
pstrstatus = NULL;
forecast = new IForecast;
FDownloadStatus = -1;
GetCurrentWeather( forecast );
tinyarrow.importPng("tiny-arrow.png");
__TRACEEXIT("WeatherPlugin::WeatherPlugin()");
}
WeatherPlugin::~WeatherPlugin()
{
__TRACEENTER("WeatherPlugin::~WeatherPlugin()");
FWeatherUploadTerminate = true;
if (hWeatherUploadThread)
{
__TRACE("download thread terminate");
DWORD ExitCode = 0;
DWORD timeout = GetTickCount()+2000;
while( GetTickCount() < timeout )
{
GetExitCodeThread( hWeatherUploadThread, &ExitCode);
if (ExitCode==1) break;
Sleep(10);
}
if (ExitCode!=1)
{ __TRACE("download thread buzzed");
TerminateThread(hWeatherUploadThread, 1);
}
CloseHandle( hWeatherUploadThread );
hWeatherUploadThread = NULL;
}
if(m_ppe)
{
m_ppe->Release();
m_ppe = NULL;
}
if (forecast) delete forecast;
forecast = NULL;
g_dwDLLRefCount--;
__TRACEEXIT("WeatherPlugin::~WeatherPlugin()");
}
void __fastcall WeatherPlugin:: SetUpdateTimer()
{
__TRACEENTER("WeatherPlugin::SetUpdateTimer()");
if (m_ppe && forecast)
{
int t = forecast->GetNearUpdTimeout();
if (t==0) t=10;
__TRACE( "GetNearUpdTimeout T=" << t << " min");
if (t>0) m_ppe->SetSingleShotTimer( m_hPlugin, t*60000 );
}
else __TRACE("m_ppe or pForecast is NULL");
__TRACEEXIT("WeatherPlugin::SetUpdateTimer()");
}
void __fastcall WeatherPlugin:: DownloadStatus( int id )
{
__TRACEENTER("WeatherPlugin::DownloadStatus()");
if (FWeatherUploadTerminate) return;
FDownloadStatus = id;
if (m_ppe) m_ppe->InvalidatePlugin( m_hPlugin, 0);
__TRACEEXIT("WeatherPlugin::DownloadStatus()");
}
void __fastcall WeatherPlugin:: DownloadWeather()
{
__TRACEENTER("WeatherPlugin::DownloadWeather()");
if (hWeatherUploadThread)
{
DWORD ExitCode;
GetExitCodeThread( hWeatherUploadThread, &ExitCode);
if (ExitCode!=1)
{
__TRACEEXIT("WeatherPlugin::DownloadWeather(). download already runned");
return;
}
CloseHandle( hWeatherUploadThread );
hWeatherUploadThread = NULL;
}
FWeatherUploadTerminate = false;
DWORD threadId;
hWeatherUploadThread = CreateThread( 0, 0, WeatherUploadThreadProc, this,
0,
&threadId );
SetThreadPriority( hWeatherUploadThread, THREAD_PRIORITY_BELOW_NORMAL );
__TRACEEXIT("WeatherPlugin:: DownloadWeather()");
}
HRESULT WeatherPlugin::Initialize( HPLUGIN hPlugin, IXMLDOMNode*
pnodeParams, IXMLDOMNode* pnodeDefault )
{
__TRACEENTER("WeatherPlugin::Initialize()");
IXMLDOMNode *pNode;
IXMLDOMNamedNodeMap *pDOMNamedNodeMap;
forecast->updday = 30;
forecast->updnight = 120;
forecast->daybegin = 7;
forecast->dayend = 22;
cityId="RSXX0094";
displayname.free();
if ( pnodeParams->get_attributes(&pDOMNamedNodeMap)==0)
{
CComVariant value;
if ( pDOMNamedNodeMap->getNamedItem( L"day_begin", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
USTR val = value.bstrVal;
forecast->daybegin = val;
}
if ( pDOMNamedNodeMap->getNamedItem( L"day_end", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
USTR val = value.bstrVal;
forecast->dayend = val;
}
if ( forecast->daybegin > 24 ) forecast->daybegin=24;
else if (forecast->daybegin < 0) forecast->daybegin = 0;
if ( forecast->dayend > 24 ) forecast->dayend=24;
else if (forecast->dayend < 0) forecast->dayend = 0;
if ( forecast->daybegin >= forecast->dayend )
{
forecast->daybegin = 7;
forecast->dayend = 22;
}
if ( pDOMNamedNodeMap->getNamedItem( L"upd_day", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
USTR val = value.bstrVal;
forecast->updday = val;
}
if ( pDOMNamedNodeMap->getNamedItem( L"upd_night", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
USTR val = value.bstrVal;
forecast->updnight = val;
}
if (forecast->updday < 0 || forecast->updday > 24*60) forecast->updday
= 30;
if (forecast->updnight < 0 || forecast->updnight > 24*60)
forecast->updnight = 2*60;
if ( pDOMNamedNodeMap->getNamedItem( L"cityname", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
displayname = value.bstrVal;
__TRACE("cityname=" << (wchar_t*)displayname );
}
if ( pDOMNamedNodeMap->getNamedItem( L"cityid", &pNode)==0)
{
value.Clear();
pNode->get_nodeValue( &value );
pNode->Release();
cityId = value.bstrVal;
__TRACE("cityid=" << (wchar_t*)cityId );
}
pDOMNamedNodeMap->Release();
}
__TRACE("daytime [" << forecast->daybegin << "..." << forecast->dayend <<
"]h" );
__TRACE("daytime autoupdate=" << forecast->updday );
__TRACE("nighttime autoupdate=" << forecast->updnight );
m_hPlugin = hPlugin;
__TRACEEXIT("WeatherPlugin::Initialize()" );
return(S_OK);
}
HRESULT WeatherPlugin::GetHeight( int* pdyPlugin )
{
__TRACE("WeatherPlugin::GetHeight()" );
*pdyPlugin = 40;
return S_OK;
}
HRESULT WeatherPlugin::GetSelectability(BOOL* pfSelectable)
{
__TRACE("WeatherPlugin::GetSelectability()" );
HRESULT hr = S_OK;
*pfSelectable = TRUE;
return(hr);
}
int __fastcall GetTextWidth(HDC hdc, wchar_t *str )
{
__TRACEENTER("GetTextWidth()" );
RECT rtext;
rtext.left = rtext.top = rtext.right = rtext.bottom = 0;
DrawText( hdc, str, -1, &rtext, DT_CALCRECT );
__TRACEEXIT("GetTextWidth()" );
return rtext.right;
}
HRESULT WeatherPlugin::OnEvent( PluginEvent* ppe )
{
__TRACEENTER("WeatherPlugin::OnEvent()" );
if (!ppe)
{
__TRACEEXIT("WeatherPlugin::OnEvent(): ppe=NULL" );
return S_OK; // 26.11.2005
}
if (!forecast)
{
__TRACEEXIT("WeatherPlugin::OnEvent(): forecast=NULL" );
return S_OK; // 26.11.2005
}
if (hWeatherUploadThread)
{
__TRACE("Is download thread terminated?" );
DWORD ExitCode;
GetExitCodeThread( hWeatherUploadThread, &ExitCode);
if (ExitCode==1)
{
__TRACE("download thread terminated = yes" );
CloseHandle( hWeatherUploadThread );
hWeatherUploadThread = NULL;
}
else
__TRACE("download thread terminated = no" );
}
if (FDownloadStatus != -1)
{
switch( FDownloadStatus )
{
case connComplete:
__TRACE("connComplete");
SetUpdateTimer();
pstrstatus = NULL;
break;
case connConnecting:
__TRACE("connConnecting");
pstrstatus=GetStr(IDS_CONNECTING);
break;
case connConnected:
__TRACE("connConnected");
pstrstatus=GetStr(IDS_CONNECTED);
break;
case connDownload:
__TRACE("connDownload");
pstrstatus=GetStr(IDS_DOWNLOAD);
break;
case connFailed:
__TRACE("connFailed");
pstrstatus=GetStr(IDS_DOWNLOADERR);
break;
case connSuccess:
__TRACE("connSuccess");
GetCurrentWeather( forecast );
pstrstatus=NULL;
break;
}
}
FDownloadStatus = -1;
HRESULT hr = S_OK;
switch(ppe->idEvent)
{
case PE_KEYDOWN:
__TRACEENTER("PE_KEYDOWN" );
switch( ppe->p.key.wVKey )
{
case VK_TLEFT:
__TRACE("VK_TLEFT" );
forecast->FForecastNext = -1 ;
if (m_ppe) m_ppe->InvalidatePlugin( m_hPlugin, 0);
break;
case VK_TRIGHT:
__TRACE("VK_TRIGHT" );
forecast->FForecastNext = +1 ;
if (m_ppe) m_ppe->InvalidatePlugin( m_hPlugin, 0);
break;
}
__TRACEEXIT("PE_KEYDOWN" );
break;
case PE_TIMER:
{
__TRACEENTER("PE_TIMER" );
int t = forecast->GetNearUpdTimeout();
__TRACE("GetNearUpdTimeout() T="<< t );
if (t>0)
{ if (m_ppe) m_ppe->SetSingleShotTimer( m_hPlugin, t*60000 );
}
else if (t==0) DownloadWeather();
__TRACEEXIT("PE_TIMER" );
break;
}
// our plugin has been selected and clicked
case PE_ACTION:
{
__TRACEENTER("PE_ACTION" );
DownloadWeather();
__TRACEEXIT("PE_ACTION" );
break;
}
// we've recieved a paint message for our plugin, so we need
// to update and draw the memory usage status bar
case PE_PAINT:
{
__TRACEENTER("PE_PAINT" );
forecast->UpdateWeatherIcon();
USTR text;
HDC hdc;
RECT rect,
rpos;
rect = ppe->p.paint.rcDraw;
hdc = ppe->p.paint.hdc;
XFont font(L"tahoma", 12, 400, 0x0 );
font.Select( hdc );
SetBkMode(hdc, TRANSPARENT);
rpos = rect;
rpos.left += 40; rpos.top += 2;
if (forecast->FForecastMode < 5)
{
if (forecast->cc_temp != 0xFFFF)
{
if(forecast->cc_temp > 0) SetTextColor(hdc, 0x2020FF );
else SetTextColor(hdc, 0xFF2020 );
if (forecast->cc_temp > 0) text = L"+";
text += forecast->cc_temp;
text += L"œ";
DrawText( hdc, text, -1, &rpos, DT_SINGLELINE | DT_LEFT | DT_TOP );
rpos.left += GetTextWidth(hdc, text)-1;
}
if (forecast->fc_temp!=0xFFFF)
{
rpos.top += 4;
tinyarrow.Paint( hdc, rpos.left, rpos.top, 0xFF );
rpos.top -= 4; rpos.left += tinyarrow.Width();
if(forecast->fc_temp > 0) SetTextColor(hdc, 0x2020FF );
else SetTextColor(hdc, 0xFF2020 );
if (forecast->fc_temp > 0) text = L"+";
else text.free();
text += forecast->fc_temp;
text += L"œ";
DrawText( hdc, text, -1, &rpos, DT_SINGLELINE | DT_LEFT | DT_TOP );
rpos.left += GetTextWidth(hdc, text)-1;
}
SetTextColor(hdc, 0x000000);
if ( forecast->strForecast.length() )
{
rpos.left += 10;
DrawText(hdc, forecast->strForecast, -1, &rpos, DT_SINGLELINE |
DT_LEFT | DT_TOP );
}
SYSTEMTIME sys;
GetLocalTime(&sys);
if (pstrstatus) text = pstrstatus;
else text.sprintf(L"%d:%02d", sys.wHour, sys.wMinute );
rpos = rect;
rpos.left += 38;
rpos.top += 14;
DrawText( hdc, text, -1, &rpos, DT_SINGLELINE | DT_LEFT | DT_TOP );
USTR day =
text.sprintf(L"%s, %d %s", GetStr(IDS_SUNDAY+sys.wDayOfW ),
sys.wDay,
GetStr(IDS_MONTHS+sys.wMonth-1) );
int W = GetTextWidth(hdc, text );
rpos.left = rpos.right - W - 2;
if (ppe->p.paint.fSelected)
{
font.Restore( hdc );
font.setUnderline(1);
font.Select( hdc );
SetTextColor(hdc, 0x800000);
}
DrawText( hdc, text, -1, &rpos, DT_SINGLELINE | DT_LEFT| DT_TOP );
forecast->forecastIcon[0].Paint( hdc, rect.left+3, rect.top );
forecast->forecastIcon[1].Paint( hdc, rect.left+3, rect.top );
forecast->forecastIcon[2].Paint( hdc, rect.left+3, rect.top );
}
else
{
rpos = rect;
rpos.left += 10;
USTR line1, line2;
switch(forecast->FForecastMode)
{
case 5:
{
if (displayname.length() ) line1 = displayname;
else line1=forecast->strCityName;
int t = forecast->GetNearUpdTimeout();
USTR infomask = GetStr( IDS_FORECASTINFO );
line2.sprintf( infomask, forecast->cc.dt.hour, forecast->cc.dt.minute,
t );
} break;
case 6:
line1="Powered by www.weather.com";
line2="";
break;
case 7:
line1="ZHG WeatherPlugin rev 1.01";
line2="email: eaz@nm.ru";
break;
};
rpos.top += 2;
DrawText( hdc, line1, -1, &rpos, DT_SINGLELINE | DT_LEFT | DT_TOP );
rpos.top += 14;
DrawText( hdc, line2, -1, &rpos, DT_SINGLELINE | DT_LEFT | DT_TOP );
}
font.Restore( hdc );
__TRACEEXIT("PE_PAINT" );
break;
}
case PE_SYSCOLORCHANGE:
break;
case PE_DATACHANGE:
break;
}
__TRACEEXIT("WeatherPlugin::OnEvent()" );
return(hr);
}
HRESULT WeatherPlugin::GetClassID(CLSID* pClassID)
{
__TRACE("WeatherPlugin::GetClassID()" );
*pClassID = CLSID_PLUGWEATHER;
return(S_OK);
}
HRESULT WeatherPlugin::IsDirty(void)
{
__TRACE("WeatherPlugin::IsDirty()" );
return(S_OK);
}
HRESULT WeatherPlugin::Load(IStream* pStm)
{
__TRACEENTER("WeatherPlugin::Load()");
pStm->Read( &m_hPlugin, sizeof m_hPlugin, 0);
DWORD version;
pStm->Read( &version, sizeof(DWORD), 0);
if (version != 0x1002)
{
__TRACEEXIT("WeatherPlugin::Load(); structure invalid version" );
return E_FAIL;
}
UINT L;
pStm->Read( &L, sizeof(UINT), 0);
if (L) pStm->Read( cityId.alloc(L), L*sizeof(wchar_t), 0);
else cityId.free();
pStm->Read( &L, sizeof(UINT), 0);
if (L) pStm->Read( displayname.alloc(L), L*sizeof(wchar_t), 0);
else displayname.free();
pStm->Read( &forecast->daybegin, sizeof(int), 0);
pStm->Read( &forecast->dayend, sizeof(int), 0);
pStm->Read( &forecast->updday, sizeof(int), 0);
pStm->Read( &forecast->updnight, sizeof(int), 0);
SetUpdateTimer();
__TRACEEXIT("WeatherPlugin::Load()" );
return S_OK;
}
HRESULT WeatherPlugin::Save( IStream *pStm, BOOL fClearDirty )
{
__TRACEENTER("WeatherPlugin::Save()" );
pStm->Write( &m_hPlugin, sizeof m_hPlugin, 0);
DWORD version = 0x1002;
pStm->Write( &version, sizeof(DWORD), 0);
UINT L = cityId.length();
pStm->Write( &L, sizeof(UINT), 0);
if (L) pStm->Write( cityId.w_str(), L*sizeof(wchar_t), 0);
L = displayname.length();
pStm->Write( &L, sizeof(UINT), 0);
if (L) pStm->Write( displayname.w_str(), L*sizeof(wchar_t), 0);
pStm->Write( &forecast->daybegin, sizeof(int), 0);
pStm->Write( &forecast->dayend, sizeof(int), 0);
pStm->Write( &forecast->updday, sizeof(int), 0);
pStm->Write( &forecast->updnight, sizeof(int), 0);
__TRACEEXIT("WeatherPlugin::Save()" );
return S_OK;
}
// ****************************************
******************************
// Function Name: GetSizeMax
//
// Purpose: Trivial implementation of IPersistStream's GetSizeMax method
HRESULT WeatherPlugin::GetSizeMax(ULARGE_INTEGER
* pcbSize )
{
__TRACE("WeatherPlugin::GetSizeMax()" );
ULONGLONG* pl = (ULONGLONG*)pcbSize;
*pl = 0;
return(S_OK);
}
HRESULT WeatherPlugin:: SetSite( IUnknown* pSite )
{
__TRACEENTER("WeatherPlugin::SetSite()");
HRESULT hr = S_OK;
if(m_ppe)
{
m_ppe->Release();
m_ppe = NULL;
}
if(pSite)
{
if(FAILED(hr = pSite-> QueryInterface(IID_IHomePluginEnvironmen
t2,
(void**)&m_ppe)))
{
__TRACE("QueryInterface 'IID_IHomePluginEnvironment2'
failed" );
goto Error;
}
}
Error:
__TRACEEXIT("WeatherPlugin::SetSite()");
return(hr);
}
HRESULT WeatherPlugin::GetSite( REFIID riid, void** ppvSite )
{
__TRACEENTER("WeatherPlugin::GetSite()" );
HRESULT hr = S_OK;
if(!m_ppe)
{
__TRACE("failed, m_ppe=NULL" );
hr = E_FAIL;
goto Error;
}
if(FAILED(hr = m_ppe->QueryInterface(riid, ppvSite)))
{
__TRACE("m_ppe->QueryInterface err=" << (HEX)hr );
goto Error;
}
Error:
__TRACEEXIT("WeatherPlugin::GetSite()" );
return(hr);
}
HRESULT WeatherPlugin::QueryInterface( REFIID riid, void** ppObject )
{
__TRACEENTER("WeatherPlugin::QueryInterface()" );
HRESULT hr = S_OK;
if(IID_IUnknown == riid || IID_IObjectWithSite == riid ||
IID_IHomePlugin == riid)
{
*ppObject = (IHomePlugin*)this;
}
else if(IID_IPersist == riid || IID_IPersistStream == riid)
{
*ppObject = (IPersistStream*)this;
}
else
{
__TRACE("QueryInterface() failed: NoInterface" << (HEX)hr );
hr = E_NOINTERFACE;
goto Error;
}
AddRef();
Error:
__TRACEEXIT("WeatherPlugin::QueryInterface()" );
return(hr);
}
//------------------------------------------------------------------------
// ****************************************
********************
//
// Implementation of class PluginFactory
//
// ****************************************
********************
PluginFactory::PluginFactory() :
m_cRef(1)
{
__TRACE("PluginFactory::PluginFactory()" );
}
PluginFactory::~PluginFactory()
{
__TRACE("PluginFactory::~PluginFactory()" );
}
HRESULT PluginFactory::QueryInterface(
REFIID riid,
void** ppObject
)
{
__TRACE("PluginFactory::QueryInterface()" );
HRESULT hr = S_OK;
if(riid == IID_IUnknown || riid == IID_IClassFactory)
{
*ppObject= (IClassFactory*)this;
}
else
{
__TRACE(" failed: E_NOINTERFACE" );
hr = E_NOINTERFACE;
goto Error;
}
AddRef();
Error:
return(hr);
}
HRESULT PluginFactory::CreateInstance( IUnknown *pUnkOuter, REFIID riid,
void** ppObject
)
{
__TRACE("PluginFactory::CreateInstance()" );
HRESULT hr = S_OK;
IUnknown* punk = NULL;
*ppObject = NULL;
if(pUnkOuter != NULL)
{
__TRACE("PluginFactory::CreateInstance() failed: CLASS_E_NOAGGREGATION" );
hr = CLASS_E_NOAGGREGATION;
goto Error;
}
punk = (IUnknown*)(IHomePlugin*) new WeatherPlugin;
if(!punk)
{
__TRACE("PluginFactory::CreateInstance() failed: E_OUTOFMEMORY" );
hr = E_OUTOFMEMORY;
goto Error;
}
if(FAILED(punk->QueryInterface(riid, ppObject)))
{
__TRACE("PluginFactory::CreateInstance() failed: E_NOINTERFACE" );
hr = E_NOINTERFACE;
goto Error;
}
Error:
if(punk)
{
punk->Release();
}
return hr;
}
HRESULT PluginFactory::LockServer( BOOL fLock )
{
__TRACE("PluginFactory::LockServer()" );
if(fLock) g_dwDLLRefCount++;
else g_dwDLLRefCount--;
return(S_OK);
}
// ****************************************
********************
//
// Implementation of standard COM exports
//
// ****************************************
********************
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void** ppObject )
{
__TRACE("DllGetClassObject()" );
HRESULT hr = S_OK;
PluginFactory *pFactory = NULL;
if(rclsid == CLSID_PLUGWEATHER)
{
__TRACE("DllGetClassObject(CLSID_PLUGWEATHER)" );
pFactory = new PluginFactory;
if(!pFactory)
{
__TRACE("DllGetClassObject( CLSID_PLUGWEATHER ) failed:
E_OUTOFMEMORY" );
hr = E_OUTOFMEMORY;
goto Error;
}
if(FAILED(pFactory->QueryInterface(riid, ppObject)))
{
__TRACE("DllGetClassObject( CLSID_PLUGWEATHER ) failed:
E_NOINTERFACE" );
hr = E_NOINTERFACE;
goto Error;
}
}
else
{
__TRACE("DllGetClassObject() failed: CLASS_E_CLASSNOTAVAILABLE" );
hr = CLASS_E_CLASSNOTAVAILABLE;
goto Error;
}
Error:
if(pFactory)
{
pFactory->Release();
}
return(hr);
}
STDAPI DllCanUnloadNow()
{
__TRACE("DllCanUnloadNow()" );
if(g_dwDLLRefCount)
{
__TRACE("- return false. g_dwDLLRefCount=" <<
(long)g_dwDLLRefCount );
return S_FALSE;
}
else
{
__TRACE("- return true");
return S_OK;
}
}
STDAPI DllRegisterServer(void)
{
HRESULT hr = S_OK;
HKEY hKeyCLSID = NULL;
HKEY hKeyInproc32 = NULL;
DWORD dwDisposition;
HMODULE hModule;
TCHAR szName[MAX_PATH+1];
if(ERROR_SUCCESS != RegCreateKeyEx(HKEY_CLASSES_ROOT,
TEXT("CLSID\\{") CLSIDTEXT__PLUGWEATHER TEXT("}"),
NULL, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hKeyCLSID, &dwDisposition))
{
hr = E_FAIL;
goto Error;
}
if(ERROR_SUCCESS != RegSetValueEx(hKeyCLSID, TEXT(""), NULL, REG_SZ,
(BYTE*) TEXT("ZHG WeatherPlugin"), sizeof(TEXT("ZHG WeatherPlugin"))))
{
hr = E_FAIL;
goto Error;
}
if(ERROR_SUCCESS != RegCreateKeyEx(hKeyCLSID, TEXT("InprocServer32"),
NULL, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hKeyInproc32, &dwDisposition))
{
hr = E_FAIL;
goto Error;
}
hModule = GetModuleHandle(IMAGENAME);
if(!hModule)
{
hr = E_FAIL;
goto Error;
}
if(GetModuleFileName(hModule, szName, sizeof(szName))==0)
{
hr = E_FAIL;
goto Error;
}
if(ERROR_SUCCESS != RegSetValueEx(hKeyInproc32, TEXT(""), NULL, REG_SZ,
(BYTE*) szName, sizeof(TCHAR)*(lstrlen(szName)+1)))
{
hr = E_FAIL;
goto Error;
}
Error:
if(hKeyInproc32)
{
RegCloseKey(hKeyInproc32);
}
if(hKeyCLSID)
{
RegCloseKey(hKeyCLSID);
}
return(hr);
}
STDAPI DllUnregisterServer(void)
{
HRESULT hr = S_OK;
if(ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,
TEXT("CLSID\\{") CLSIDTEXT__PLUGWEATHER TEXT("}\\InprocServer32")))
{
hr = E_FAIL;
goto Error;
}
if(ERROR_SUCCESS != RegDeleteKey(HKEY_CLASSES_ROOT,
TEXT("CLSID\\{") CLSIDTEXT__PLUGWEATHER TEXT("}")))
{
hr = E_FAIL;
goto Error;
}
Error:
return(hr);
}
|