//+---------------------------------------------------------------------------- // // File: CChimeTask.cpp // // Module: ChimeTask.dll // // Synopsis: Framework task implementation for chime. CChimeTask class definition. // // Copyright (c) Microsoft Corporation. All rights reserved. // // //+---------------------------------------------------------------------------- #include #include #include #include "..\sasamplemsgdll\sampleresource.h" //resource dll header file containing msg desc. #include "appliancetask_i.c" #include "appsrvcs_i.c" #include "taskctx_i.c" const WCHAR RESOURCE_DLL_NAME []=L"sampleresource.dll"; const WCHAR SZ_CHIMETYPE [] =L"ChimeType"; const DWORD DW_FREQ=1000; // frequency for Beep const DWORD DW_DURATION=100; // duration for Beep const long TIME_TO_LIVE=30000; //duration for visual alert //+---------------------------------------------------------------------------- // // Function: CChimeTask::OnTaskExecute // // Synopsis: Gets the chime type and calls the Chime function // Arguments: pTaskContext - a pair containing the parameters for // the task called. // // Returns: HRESULT // // //+---------------------------------------------------------------------------- STDMETHODIMP CChimeTask::OnTaskExecute(IUnknown *pTaskContext) { TRACE("CChimeTask::OnTaskExecute called"); HRESULT hr=S_OK; CHIME_TYPE nCType=TYPEERROR; ASSERT(pTaskContext); try { do { if (NULL == pTaskContext) { TRACE("ChimeTask::OnTaskExecute got NULL pTaskContext"); hr = E_POINTER; break; } CComPtr pTaskParameters; //Get the task parameters using the task context that got passed in hr = pTaskContext->QueryInterface(IID_ITaskContext, (void **)&pTaskParameters); if (FAILED(hr)) { TRACE1("ChimeTask::OnTaskExecute pTaskContext->Query interface failed",hr); break; } //Find out what the chime type is and call chime function nCType= GetChimeType(pTaskParameters); if(TYPEERROR == nCType) { TRACE("CChimeTask::OnTaskExecute - CChimeTask::Chime got in an unknown chime type"); hr=E_FAIL; break; } hr=Chime(nCType); if (FAILED(hr)) { TRACE1("CChimeTask::OnTaskExecute - CChimeTask::Chime failed - a chime type problem?",hr); break; } } while(false); } catch(...) { TRACE("CChimeTask::OnTaskExecute caught unknown exception"); hr=E_FAIL; } return hr; } //+---------------------------------------------------------------------------- // // Function: CChimeTask::OnTaskComplete // // Synopsis: This is the rollback routine which gets a result for the task. // So, if one of the other task executables failed, this routine // can perform clean up operations. However, not all operations can // be undone. This routine pulls out the actual rollback // task being called by the framework from pTaskContext and routes // the call to the correct routine which implements the rollback. // Each of these routines decides if it can rollback or not. // If the task had succeeded, no action is taken and none of the // rollback routines are called. // // Arguments: pTaskContext - a pair containing the parameters for // the task called. The "MethodName" parameter indicates the actual // task being called // lTaskResult - indicates if the OnTaskExecute()s of each of the // TaskExecutables succeeded. lTaskResult contains a failure code // if even one of the TaskExecutables failed. It contains no // information about which of the TaskExecutables failed. // // Returns: HRESULT // // //+---------------------------------------------------------------------------- STDMETHODIMP CChimeTask::OnTaskComplete(IUnknown *pTaskContext, LONG lTaskResult) { //There is nothing to do or roll back here. //Since framework requires implementation of this function, return S_OK and it's done. return S_OK; } //+---------------------------------------------------------------------------- // // Function: CChimeTask::GetChimeType // // Synopsis: Returns the chime type from context passed in with the pTaskParameter // // Arguments: IN ITaskContext *pTaskParameter // // Returns: CHIME_TYPE // // //+---------------------------------------------------------------------------- CHIME_TYPE CChimeTask::GetChimeType(IN ITaskContext *pTaskParameter) { _bstr_t bstrParamName(SZ_CHIMETYPE); HRESULT hr=S_OK; _variant_t varValue; CHIME_TYPE nCType = TYPEERROR; ASSERT(pTaskParameter); try { do { hr = pTaskParameter->GetParameter(bstrParamName, &varValue); if (FAILED(hr)) { TRACE1(("CChimeTask::GetChimeType GetParameter failed %X"),hr); break; } if (V_VT(&varValue) == VT_BSTR) { TRACE1(("WEB called Chime Task -- Chime Now - Cchimetask::GetChimeType"), V_VT(&varValue)); if (lstrcmp(V_BSTR(&varValue), TEXT("0"))==0) nCType=NONE; else if (lstrcmp(V_BSTR(&varValue), TEXT("1"))==0) nCType=AUDIBLE; else if (lstrcmp(V_BSTR(&varValue), TEXT("2"))==0) nCType=VISUAL; else if (lstrcmp(V_BSTR(&varValue), TEXT("3"))==0) nCType=BOTH; else nCType=TYPEERROR; } else if (V_VT(&varValue) == VT_I4) { TRACE1(("Chime Service called Chime Task- Cchimetask::GetChimeType"), V_VT(&varValue)); if (V_I4(&varValue) == 0) nCType=NONE; else if (V_I4(&varValue)== 1) nCType=AUDIBLE; else if (V_I4(&varValue)== 2) nCType=VISUAL; else if (V_I4(&varValue)== 3) nCType=BOTH; else nCType=TYPEERROR; } else nCType=TYPEERROR; } while(false); } catch(...) { TRACE("CChimeTask::GetChimeType caught unknown exception"); hr=E_FAIL; } if (FAILED(hr)) { nCType= TYPEERROR; } return nCType; } //+---------------------------------------------------------------------------- // // Function: CChimeTask::Chime // // Synopsis: Chimes (audible, visual, both) depending on the chimetype passed in. // // Arguments: IN nCType // // Returns: HRESULT // // //+---------------------------------------------------------------------------- HRESULT CChimeTask::Chime(IN CHIME_TYPE nCType) { HRESULT hrRet=S_OK; switch (nCType) { case TYPEERROR: hrRet=E_FAIL; break; case NONE: break; case AUDIBLE: Beep(DW_FREQ,DW_DURATION); //standard beep from speaker break; case VISUAL: hrRet=RaiseVisualAlert(); break; case BOTH: Beep(DW_FREQ,DW_DURATION); hrRet=RaiseVisualAlert(); break; default: hrRet=E_FAIL; // we should never end up here. break; } return hrRet; } //+---------------------------------------------------------------------------- // // Function: CChimeTask::RaiseVisualAlert() // // Synopsis: Raises visual alerts to be displayed on the web page // // Arguments: void // // Returns: void // // //+---------------------------------------------------------------------------- HRESULT CChimeTask::RaiseVisualAlert() { DWORD dwAlertType = SA_ALERT_TYPE_ATTENTION; DWORD dwAlertId = SA_SAMPLEAPP_CHIME_CHIME_ALERT; // from the resource dll header file _bstr_t bstrAlertLog(RESOURCE_DLL_NAME); _bstr_t bstrAlertSource(L""); _variant_t varReplacementStrings; _variant_t varRawData; LONG lCookie; HRESULT hrRet=S_OK; try { do { CComPtr pAppSrvcs; hrRet = CoCreateInstance(CLSID_ApplianceServices, NULL, CLSCTX_INPROC_SERVER, IID_IApplianceServices, (void**)&pAppSrvcs); if (FAILED(hrRet)) { TRACE1("CChimeTask::RaiseVisualAlert CoCreateInstance returned %X ", hrRet); break; } // Initialize() is called prior to using other component services. Performs // component initialization operations. hrRet = pAppSrvcs->Initialize(); if (FAILED(hrRet)) { TRACE1("CChimeTask::RaiseVisualAlert pAppSrvcs->Initialize() failed %X",hrRet); break; } // Now we are going to add the time info after the "Chime" visual message // Start with getting time SYSTEMTIME LocalTime; GetLocalTime(&LocalTime); WCHAR wszTmpStr[10]={0}; //temp string to be used WCHAR wszHourStr[10]={0}; //string to hold hour info and the final string WCHAR wszMinStr[10]={0}; //string to hold minute info _ultow(LocalTime.wHour, wszTmpStr,10); if (LocalTime.wHour == 0) // add leading 0 if the time is 12:00 AM { wcscat(wszHourStr,L"0"); } wcscat(wszHourStr,wszTmpStr); //form the hour string wszTmpStr[0]='\0'; //reinit temp string _ultow(LocalTime.wMinute, wszTmpStr,10); if (LocalTime.wMinute < 10) // add leading 0 if the Minute is < 10 { wcscat(wszMinStr,L"0"); //form the minute string } wcscat(wszMinStr,wszTmpStr); //combine together wcscat(wszHourStr,L":"); // now add : after hour e.g 2:23 wcscat(wszHourStr,wszMinStr); // combine all to get the final string. // Now we need to set it up so that it can be passed in to the RaiseAlert api // Initalize the varReplacementStrings variant. VariantInit(&varReplacementStrings); // Create the SAFEARRAY. SAFEARRAY *psa; V_ARRAY(&varReplacementStrings) = SafeArrayCreateVector(VT_BSTR, 0, 1); psa=V_ARRAY(&varReplacementStrings); //initialize the psa pointer if (psa == NULL) { TRACE("failed in SafeArrayCreateVector"); break; } // Set the type. V_VT(&varReplacementStrings) = VT_ARRAY | VT_BSTR; // Lock the array data. BSTR *pData; hrRet = SafeArrayAccessData(psa, (void**)&pData); if (FAILED(hrRet)) { TRACE("failed in SafeArrayAccessData"); break; } //pass in the time string we created above into the variant structure pData[0]=SysAllocString(wszHourStr); hrRet = pAppSrvcs->RaiseAlert(dwAlertType, dwAlertId, bstrAlertLog, bstrAlertSource, TIME_TO_LIVE, // 30 seconds, then go away &varReplacementStrings, &varRawData, &lCookie); SafeArrayUnaccessData(psa); if (FAILED(hrRet)) { TRACE1("CChimeTask::RaiseVisualAlert pAppSrvcs->RaiseAlert failed %X",hrRet); break; } } while(false); } catch(...) { TRACE("CChimeTask::RaiseVisualAlert caught unknown exception"); hrRet=E_FAIL; } return hrRet; }