// MODULE: TSHOOTCTL.CPP // // PURPOSE: Interface for the componet. // // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint // // COMPANY: Saltmine Creative, Inc. (206)-633-4743 support@saltmine.com // // AUTHOR: Roman Mach // // ORIGINAL DATE: 6/4/96 // // NOTES: // 1. Based on Print Troubleshooter DLL. // 2. Richard Meadows wrote the RunQuery, BackUp, Problem Page and // PreLoadURL functions. // // Version Date By Comments //-------------------------------------------------------------------- // V0.1 - RM Original // V0.3 04/09/98 JM/OK+ Local Version for NT5 // #include "stdafx.h" #include "ErrorEnums.h" #include "cathelp.h" #include "TSHOOT.h" #include "time.h" #include "apgts.h" #include "ErrorEnums.h" #include "BasicException.h" #include "apgtsfst.h" #include "ErrorEnums.h" #include "CabUnCompress.h" #include "bnts.h" #include "BackupInfo.h" #include "cachegen.h" #include "apgtsinf.h" #include "apgtscmd.h" #include "apgtshtx.h" #include "apgtscls.h" #include "OcxGlobals.h" class CTSHOOTCtrl; #include "dnldlist.h" #include "download.h" #include "TSHOOTCtl.h" #include "TSHOOTPpg.h" #include "Functions.h" #include "ErrorEnums.h" #include "BasicException.h" #include "HttpQueryException.h" #include #include "LaunchServ.h" #include "LaunchServ_i.c" // >>> test #include "fstream.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CTSHOOTCtrl, COleControl) ///////////////////////////////////////////////////////////////////////////// // Message map BEGIN_MESSAGE_MAP(CTSHOOTCtrl, COleControl) //{{AFX_MSG_MAP(CTSHOOTCtrl) // NOTE - ClassWizard will add and remove message map entries // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG_MAP ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Dispatch map BEGIN_DISPATCH_MAP(CTSHOOTCtrl, COleControl) //{{AFX_DISPATCH_MAP(CTSHOOTCtrl) DISP_PROPERTY_NOTIFY(CTSHOOTCtrl, "DownloadURL", m_downloadURL, OnDownloadURLChanged, VT_BSTR) DISP_PROPERTY_NOTIFY(CTSHOOTCtrl, "DownloadListFilename", m_downloadListFilename, OnDownloadListFilenameChanged, VT_BSTR) DISP_FUNCTION(CTSHOOTCtrl, "RunQuery", RunQuery, VT_BSTR, VTS_VARIANT VTS_VARIANT VTS_I2) DISP_FUNCTION(CTSHOOTCtrl, "SetSniffResult", SetSniffResult, VT_BOOL, VTS_VARIANT VTS_VARIANT) DISP_FUNCTION(CTSHOOTCtrl, "GetExtendedError", GetExtendedError, VT_I4, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "GetCurrentFriendlyDownload", GetCurrentFriendlyDownload, VT_BSTR, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "GetCurrentFileDownload", GetCurrentFileDownload, VT_BSTR, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "DownloadAction", DownloadAction, VT_I4, VTS_I4) DISP_FUNCTION(CTSHOOTCtrl, "BackUp", BackUp, VT_BSTR, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "ProblemPage", ProblemPage, VT_BSTR, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "PreLoadURL", PreLoadURL, VT_BSTR, VTS_BSTR) DISP_FUNCTION(CTSHOOTCtrl, "Restart", Restart, VT_BSTR, VTS_NONE) DISP_FUNCTION(CTSHOOTCtrl, "RunQuery2", RunQuery2, VT_BSTR, VTS_BSTR VTS_BSTR VTS_BSTR) DISP_FUNCTION(CTSHOOTCtrl, "SetPair", SetPair, VT_EMPTY, VTS_BSTR VTS_BSTR) //}}AFX_DISPATCH_MAP DISP_FUNCTION_ID(CTSHOOTCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) END_DISPATCH_MAP() ///////////////////////////////////////////////////////////////////////////// // Event map BEGIN_EVENT_MAP(CTSHOOTCtrl, COleControl) //{{AFX_EVENT_MAP(CTSHOOTCtrl) EVENT_CUSTOM("BindProgress", FireBindProgress, VTS_BSTR VTS_I4 VTS_I4) EVENT_CUSTOM("BindStatus", FireBindStatus, VTS_I4 VTS_I4 VTS_I4 VTS_BOOL) EVENT_CUSTOM("Sniffing", FireSniffing, VTS_BSTR VTS_BSTR VTS_BSTR VTS_BSTR) //}}AFX_EVENT_MAP END_EVENT_MAP() ///////////////////////////////////////////////////////////////////////////// // Property pages // TODO: Add more property pages as needed. Remember to increase the count! BEGIN_PROPPAGEIDS(CTSHOOTCtrl, 1) PROPPAGEID(CTSHOOTPropPage::guid) END_PROPPAGEIDS(CTSHOOTCtrl) ///////////////////////////////////////////////////////////////////////////// // Initialize class factory and guid IMPLEMENT_OLECREATE_EX(CTSHOOTCtrl, "TSHOOT.TSHOOTCtrl.1", 0x4b106874, 0xdd36, 0x11d0, 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff) ///////////////////////////////////////////////////////////////////////////// // Type library ID and version IMPLEMENT_OLETYPELIB(CTSHOOTCtrl, _tlid, _wVerMajor, _wVerMinor) ///////////////////////////////////////////////////////////////////////////// // Interface IDs const IID BASED_CODE IID_DTSHOOT = { 0x4b106872, 0xdd36, 0x11d0, { 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff } }; const IID BASED_CODE IID_DTSHOOTEvents = { 0x4b106873, 0xdd36, 0x11d0, { 0x8b, 0x44, 0, 0xa0, 0x24, 0xdd, 0x9e, 0xff } }; const CATID CATID_SafeForScripting = {0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}}; const CATID CATID_SafeForInitializing = {0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}}; ///////////////////////////////////////////////////////////////////////////// // Control type information static const DWORD BASED_CODE _dwTSHOOTOleMisc = OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST | OLEMISC_INSIDEOUT | OLEMISC_CANTLINKINSIDE | OLEMISC_RECOMPOSEONRESIZE; IMPLEMENT_OLECTLTYPE(CTSHOOTCtrl, IDS_TSHOOT, _dwTSHOOTOleMisc) ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::CTSHOOTCtrlFactory::UpdateRegistry - // Adds or removes system registry entries for CTSHOOTCtrl BOOL CTSHOOTCtrl::CTSHOOTCtrlFactory::UpdateRegistry(BOOL bRegister) { // TODO: Verify that your control follows apartment-model threading rules. // Refer to MFC TechNote 64 for more information. // If your control does not conform to the apartment-model rules, then // you must modify the code below, changing the 6th parameter from // afxRegApartmentThreading to 0. HRESULT hr; BOOL bRes; if (bRegister) { bRes = AfxOleRegisterControlClass( AfxGetInstanceHandle(), m_clsid, m_lpszProgID, IDS_TSHOOT, IDB_TSHOOT, afxRegApartmentThreading, _dwTSHOOTOleMisc, _tlid, _wVerMajor, _wVerMinor); hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable"); ASSERT(SUCCEEDED(hr)); hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data"); ASSERT(SUCCEEDED(hr)); hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting); ASSERT(SUCCEEDED(hr)); hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing); ASSERT(SUCCEEDED(hr)); } else { hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting); ASSERT(SUCCEEDED(hr)); hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing); ASSERT(SUCCEEDED(hr)); bRes = AfxOleUnregisterClass(m_clsid, m_lpszProgID); } return bRes; } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::CTSHOOTCtrl - Constructor CTSHOOTCtrl::CTSHOOTCtrl() { InitializeIIDs(&IID_DTSHOOT, &IID_DTSHOOTEvents); // TODO: Initialize your control's instance data here. m_strCurShooter = _T(""); m_download = NULL; m_bComplete = TRUE; m_dwExtendedErr = LTSC_OK; m_pSniffedContainer = NULL; } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::~CTSHOOTCtrl - Destructor CTSHOOTCtrl::~CTSHOOTCtrl() { // TODO: Cleanup your control's instance data here. } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::OnDraw - Drawing function void CTSHOOTCtrl::OnDraw( CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid) { // TODO: Replace the following code with your own drawing code. pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH))); pdc->Ellipse(rcBounds); } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::DoPropExchange - Persistence support void CTSHOOTCtrl::DoPropExchange(CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::OnResetState - Reset control to default state void CTSHOOTCtrl::OnResetState() { COleControl::OnResetState(); // Resets defaults found in DoPropExchange // TODO: Reset any other control state here. } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl::AboutBox - Display an "About" box to the user void CTSHOOTCtrl::AboutBox() { CDialog dlgAbout(IDD_ABOUTBOX_TSHOOT); dlgAbout.DoModal(); } ///////////////////////////////////////////////////////////////////////////// // CTSHOOTCtrl message handlers bool CTSHOOTCtrl::SetSniffResult(const VARIANT FAR& varNodeName, const VARIANT FAR& varNodeState) { BSTR bstrNodeName = NULL; int iNodeState = 0; short sNodeNameLen = 0; TCHAR* tszNodeName = NULL; bool ret = true; // >>> test #ifdef _DEBUG // AfxDebugBreak(); #endif if (VT_BYREF == (VT_BYREF & varNodeName.vt) && // data type is VT_VARIANT | VT_BYREF VT_VARIANT == (VT_VARIANT & varNodeName.vt) // this means that data in VB script was passed as a variable ) { bstrNodeName = varNodeName.pvarVal->bstrVal; } else { if (VT_BSTR == (VT_BSTR & varNodeName.vt)) // data is of VT_BSTR type // this means that data in VB script was passed as a constant bstrNodeName = varNodeName.bstrVal; else return false; } if (VT_BYREF == (VT_BYREF & varNodeState.vt) && // data type is VT_VARIANT | VT_BYREF VT_VARIANT == (VT_VARIANT & varNodeState.vt) // this means that data in VB script was passed as a variable ) { iNodeState = varNodeState.pvarVal->iVal; } else { if (VT_I2 == (VT_I2 & varNodeState.vt)) // data is of VT_I2 type // this means that data in VB script was passed as a constant iNodeState = varNodeState.iVal; else return false; } sNodeNameLen = (short)::SysStringLen(bstrNodeName); tszNodeName = new TCHAR[sNodeNameLen+1]; tszNodeName[sNodeNameLen] = 0; ::BSTRToTCHAR(tszNodeName, bstrNodeName, sNodeNameLen); // // implement set node state functionality here // if (m_pSniffedContainer) { ret = m_pSniffedContainer->AddNode(tszNodeName, iNodeState); } else { MessageBox(_T("Sniffed data will be lost!")); ret = false; } // delete [] tszNodeName; return ret; } BSTR CTSHOOTCtrl::RunQuery(const VARIANT FAR& varCmds, const VARIANT FAR& varVals, short size) { CString strCmd1; CString strTxt; CString strResult = _T(""); try { HMODULE hModule = AfxGetInstanceHandle(); ASSERT(INVALID_HANDLE_VALUE != hModule); m_httpQuery.Initialize(varCmds, varVals, size); if (m_httpQuery.GetFirstCmd() == C_ASK_LIBRARY) { // Added to support launching by the TS Launcher. // Get an ILaunchTS interface. HRESULT hRes; DWORD dwResult; ILaunchTS *pILaunchTS = NULL; CLSID clsidLaunchTS = CLSID_LaunchTS; IID iidLaunchTS = IID_ILaunchTS; // Get an interface on the launch server hRes = CoCreateInstance(clsidLaunchTS, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER | CLSCTX_INPROC_SERVER, iidLaunchTS, (void **) &pILaunchTS); if (FAILED(hRes)) { m_dwExtendedErr = TSERR_LIB_STATE_INFO; strResult = _T("LaunchServ interface not found."); return strResult.AllocSysString(); } // Get all of the query values. hRes = pILaunchTS->GetShooterStates(&dwResult); if (FAILED(hRes)) { m_dwExtendedErr = dwResult; strResult.Format(_T("GetShooterStates Failed. %ld"), dwResult); pILaunchTS->Release(); return strResult.AllocSysString(); } // Run the query. OLECHAR *poleShooter; hRes = pILaunchTS->GetTroubleShooter(&poleShooter); if (FAILED(hRes)) { m_dwExtendedErr = TSERR_LIB_STATE_INFO; strResult = _T("GetTroubleShooter Failed. "); pILaunchTS->Release(); return strResult.AllocSysString(); } m_strCurShooter = poleShooter; // Ignoring, for now, any other information we may get from the launch server // (e.g. problem node) set up m_httpQuery and other things as if we just had // a request for this troubleshooting belief network. m_httpQuery.SetFirst(CString(C_TYPE), m_strCurShooter); SysFreeString(poleShooter); m_Conf.Initialize(hModule, (LPCTSTR) m_strCurShooter ); // CDBLoadConfiguration m_apgts.Initialize( m_Conf.GetAPI(), // APGTSContext &m_Conf, &m_httpQuery); m_apgts.RemoveSkips(); m_Conf.GetAPI()->api.pAPI->SetHttpQuery(&m_httpQuery); // sniffing m_Conf.GetAPI()->api.pAPI->ReadTheDscModel(); m_pSniffedContainer = m_Conf.GetAPI()->api.pAPI; m_httpQuery.FinishInitFromServ(m_Conf.GetAPI()->api.pAPI, pILaunchTS); FireSniffing(m_httpQuery.GetMachine(), m_httpQuery.GetPNPDevice(), m_httpQuery.GetDeviceInstance(), m_httpQuery.GetGuidClass()); pILaunchTS->Release(); pILaunchTS = NULL; m_httpQuery.SetStackDirection(); m_Conf.SetValues(m_httpQuery); m_apgts.ClearBackup(); m_Conf.GetAPI()->api.pAPI->SetReverse(false); m_apgts.DoContent(&m_httpQuery); // now add sniffed nodes that were automatically traversed // to the stack of navigated nodes - UGLY m_httpQuery.PushNodesLastSniffed(m_Conf.GetAPI()->api.pAPI->GetArrLastSniffed()); // Now that we've done all the processing render the appropriate page. // This is the first page the user sees when launching a torubleshooter. m_apgts.RenderNext(strResult); m_apgts.Empty(); } else if (m_httpQuery.GetFirstCmd() == C_SELECT) { // Unsupported function. // Returns a page that has all of the trouble shooters. try { CFirstPage firstPage; CString str = m_httpQuery.GetTroubleShooter(); firstPage.RenderFirst(strResult, str); // Here I am getting an hit file. } catch(CBasicException *pExc) { m_dwExtendedErr = pExc->m_dwBErr; strResult = _T(""); delete pExc; } } else { // Normal operation. if (m_httpQuery.GetTroubleShooter() != m_strCurShooter) { m_strCurShooter = m_httpQuery.GetTroubleShooter(); m_Conf.Initialize(hModule, (LPCTSTR) m_strCurShooter ); // CDBLoadConfiguration m_apgts.Initialize( m_Conf.GetAPI(), // APGTSContext &m_Conf, &m_httpQuery); m_apgts.RemoveSkips(); m_Conf.GetAPI()->api.pAPI->SetHttpQuery(&m_httpQuery); // sniffing m_Conf.GetAPI()->api.pAPI->ReadTheDscModel(); m_pSniffedContainer = m_Conf.GetAPI()->api.pAPI; FireSniffing(m_httpQuery.GetMachine(), m_httpQuery.GetPNPDevice(), m_httpQuery.GetDeviceInstance(), m_httpQuery.GetGuidClass()); } m_httpQuery.FinishInit(m_Conf.GetAPI()->api.pAPI, varCmds, varVals); m_httpQuery.SetStackDirection(); m_Conf.SetValues(m_httpQuery); m_apgts.ClearBackup(); m_Conf.GetAPI()->api.pAPI->SetReverse(false); m_apgts.DoContent(&m_httpQuery); // now add sniffed nodes that were automatically traversed // to the stack of navigated nodes - UGLY m_httpQuery.PushNodesLastSniffed(m_Conf.GetAPI()->api.pAPI->GetArrLastSniffed()); // >>> test //static int step = 0; //char name[16] = {0}; //sprintf(name, "next_step%d.htm", ++step); //ofstream file(name); m_apgts.RenderNext(strResult); //file << (LPCTSTR)strResult; m_apgts.Empty(); } } catch(COleException *pOExc) { m_dwExtendedErr = (DLSTATTYPES) pOExc->m_sc; pOExc->Delete(); strResult = _T(""); } catch(CBasicException *pExc) { m_dwExtendedErr = pExc->m_dwBErr; delete pExc; strResult = _T(""); } unsigned short pErrorStr[2] = { NULL, NULL }; if (strResult.GetLength() > 0) { return strResult.AllocSysString(); } else { return SysAllocString((unsigned short *) pErrorStr); } } BSTR CTSHOOTCtrl::BackUp() { BCache *pApi = m_Conf.GetAPI()->api.pAPI; CString strResult = _T(""); if (m_httpQuery.BackUp(pApi, &m_apgts)) { m_Conf.GetAPI()->api.pAPI->SetReverse(true); m_apgts.DoContent(&m_httpQuery); m_apgts.RenderNext(strResult); m_apgts.Empty(); } else m_dwExtendedErr = TSERR_AT_START; return strResult.AllocSysString(); } // Starter // Historically (until March '98) this was called when the "Restart button" is pressed. // However, that assumed we would always want to go clear back to the problem page, which // is no longer policy now that the Launcher is introduced. BSTR CTSHOOTCtrl::ProblemPage() { BCache *pApi = m_Conf.GetAPI()->api.pAPI; CString strResult = _T(""); if (m_strCurShooter.GetLength() > 0) { m_httpQuery.RemoveNodes(pApi); m_apgts.DoContent(&m_httpQuery); m_apgts.RenderNext(strResult); m_apgts.Empty(); } else m_dwExtendedErr = TSERR_NOT_STARTED; m_apgts.ResetService(); return strResult.AllocSysString(); } // Called when the "Restart button" is pressed. // If TS Launcher was not involved, go clear back to the problem page. // If TS Launcher is involved, go back to the page we launched to, which may or may not // be the problem page. BSTR CTSHOOTCtrl::Restart() { BCache *pApi = m_Conf.GetAPI()->api.pAPI; CString strResult; // >>> test #ifdef _DEBUG // AfxDebugBreak(); #endif // resniffing m_pSniffedContainer->Flush(); FireSniffing(m_httpQuery.GetMachine(), m_httpQuery.GetPNPDevice(), m_httpQuery.GetDeviceInstance(), m_httpQuery.GetGuidClass()); if (m_strCurShooter.GetLength() > 0) { m_httpQuery.RemoveNodes(pApi); m_httpQuery.RestoreStatesFromServ(); m_apgts.ClearBackup(); m_apgts.DoContent(&m_httpQuery); m_apgts.RenderNext(strResult); m_apgts.Empty(); } else m_dwExtendedErr = TSERR_NOT_STARTED; return strResult.AllocSysString(); } BSTR CTSHOOTCtrl::PreLoadURL(LPCTSTR szRoot) { // SzRoot should look like one of these. // _T("http://www.microsoft.com/isapi/support/apgts/"); // _T("http://localhost/isapi/support/apgts/"); // _T("http://catbert.saltmine.com/scripts/apgts/"); CString strResult; strResult = szRoot; strResult += PRELOAD_LIBRARY + m_strCurShooter + m_httpQuery.GetSubmitString(m_Conf.GetAPI()->api.pAPI); return strResult.AllocSysString(); } const CString CTSHOOTCtrl::GetListPath() { if (!m_downloadURL.GetLength() || !m_downloadListFilename.GetLength()) return _T(""); return m_downloadURL + m_downloadListFilename; } // // Types: // // 0 = Get INI file contents and fill up list // Returns: 0 = ok, other = Error connecting // // 1 = Download and register DSC files based on list // Returns: 0 = ok, other = Error, typically no more data in list // // Notes: // 1. This function starts downloading and calls BindStatus event // as download progresses. // 2. Type 0 must always be called after type 1 is finished to reset // the list otherwise an error is returned // 3. Keep dwActionType and DLITEMTYPES in sync // long CTSHOOTCtrl::DownloadAction(long dwActionType) { DLITEMTYPES dwType; CString sURL; if (!GetListPath().GetLength()) return LTSCERR_NOPATH; if (dwActionType == 0) { dwType = DLITEM_INI; sURL = GetListPath(); // initialize to 'no error' m_dwExtendedErr = LTSC_OK; //m_bComplete = FALSE; } else if (dwActionType == 1) { //if (!m_bComplete) // return LTSCERR_DNLDNOTDONE; dwType = DLITEM_DSC; sURL = m_downloadURL; if (!m_dnldList.FindNextItem()) return LTSC_NOMOREITEMS; sURL += m_dnldList.GetCurrFile(); } else return LTSCERR_UNKNATYPE; if (m_download == NULL) m_download = new CDownload(); if (m_download == NULL) return LTSCERR_NOMEM; HRESULT hr = m_download->DoDownload( this, sURL, dwType); if (FAILED(hr)) return LTSCERR_DNLD; return LTSC_OK; } void CTSHOOTCtrl::OnDownloadListFilenameChanged() { SetModifiedFlag(); } void CTSHOOTCtrl::OnDownloadURLChanged() { SetModifiedFlag(); } BSTR CTSHOOTCtrl::GetCurrentFileDownload() { CString strResult = m_dnldList.GetCurrFile(); return strResult.AllocSysString(); } BSTR CTSHOOTCtrl::GetCurrentFriendlyDownload() { CString strResult = m_dnldList.GetCurrFriendly(); return strResult.AllocSysString(); } long CTSHOOTCtrl::GetExtendedError() { return (m_dwExtendedErr & 0x0000FFFF); } VOID CTSHOOTCtrl::StatusEventHelper(DLITEMTYPES dwItem, DLSTATTYPES dwStat, DWORD dwExtended, BOOL bComplete) { m_bComplete = bComplete; FireBindStatus(dwItem, dwStat, dwExtended, bComplete); } VOID CTSHOOTCtrl::ProgressEventHelper( DLITEMTYPES dwItem, ULONG ulCurr, ULONG ulTotal ) { if (dwItem == DLITEM_INI) FireBindProgress(m_downloadListFilename, ulCurr, ulTotal); else FireBindProgress(m_dnldList.GetCurrFile(), ulCurr, ulTotal); } // Input data is null terminated for both binary and text data to simplify processing // DLSTATTYPES CTSHOOTCtrl::ProcessReceivedData(DLITEMTYPES dwItem, TCHAR *pData, UINT uLen) { DLSTATTYPES dwStat = LTSC_OK; switch(dwItem) { case DLITEM_INI: // processing INI file dwStat = ProcessINI(pData); break; case DLITEM_DSC: // processing DSC file dwStat = ProcessDSC(pData, uLen); break; default: dwStat = LTSCERR_UNSUPP; break; } return dwStat; } // Returns true if we need to update this file // BOOL CTSHOOTCtrl::FileRegCheck(CString &sType, CString &sFilename, CString &sKeyName, DWORD dwCurrVersion) { HKEY hk, hknew; BOOL bStat = FALSE; CString sMainKey; // figure out what our main key is for this file if (sType == TSINI_TYPE_TS) sMainKey = TSREGKEY_TL; else if (sType == TSINI_TYPE_SF) sMainKey = TSREGKEY_SFL; else { m_dwExtendedErr = LTSCERR_BADTYPE; return FALSE; } // first open the main key (try open all access now just in case of permissions problems) if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, sMainKey, 0, KEY_ALL_ACCESS, &hk) == ERROR_SUCCESS) { CString sValueName; CString sValueClass; FILETIME ftLastWriteTime; DWORD count = 0; LONG ldStat = ERROR_SUCCESS; BOOL bFound = FALSE; while (ldStat == ERROR_SUCCESS) { LPTSTR lptname = sValueName.GetBuffer(MAX_PATH + 1); LPTSTR lptclass = sValueClass.GetBuffer(MAX_PATH + 1); DWORD namesize = MAX_PATH; DWORD classsize = MAX_PATH; ldStat = RegEnumKeyEx( hk, count, lptname, &namesize, NULL, lptclass, &classsize, &ftLastWriteTime); sValueName.ReleaseBuffer(); sValueClass.ReleaseBuffer(); if (ldStat != ERROR_SUCCESS) { break; } if (!sValueName.CompareNoCase(sKeyName)) { // open specific troubleshooter key data (read only) if (RegOpenKeyEx( hk, sKeyName, 0, KEY_ALL_ACCESS, &hknew) == ERROR_SUCCESS) { DWORD dwData, dwValue; BYTE szValue[MAXCHAR]; //dwData = REG_DWORD; dwData = REG_SZ; DWORD dwSize = MAXCHAR; if (RegQueryValueEx(hknew, TSLCL_FVERSION, 0, &dwData, szValue, &dwSize) == ERROR_SUCCESS) { dwValue = _ttoi((TCHAR *) szValue); if (dwValue < dwCurrVersion) bStat = TRUE; else { // check if file exists HANDLE hCurrFind; WIN32_FIND_DATA FindCurrData; CString sFullPath; sFullPath = m_sBasePath + _T("\\") + sFilename; hCurrFind = FindFirstFile(sFullPath, &FindCurrData); if (hCurrFind != INVALID_HANDLE_VALUE) { FindClose(hCurrFind); } else bStat = TRUE; } } else m_dwExtendedErr = LTSCERR_KEYQUERY; RegCloseKey(hknew); } else m_dwExtendedErr = LTSCERR_KEYOPEN2; // this is important: set this true to prevent default from trying to download // we wont download if we found the key but can't update bFound = TRUE; break; } count++; } if (!bFound) { bStat = TRUE; } RegCloseKey(hk); } else m_dwExtendedErr = LTSCERR_KEYOPEN; return bStat; } DLSTATTYPES CTSHOOTCtrl::ProcessINI(TCHAR *pData) { BOOL bFoundHeader = FALSE; int dwCount = 0; int dwMaxLines = 10000; DLSTATTYPES dwStat = LTSC_OK; dwStat = GetPathToFiles(); if (dwStat != LTSC_OK) return dwStat; m_dnldList.RemoveAll(); CString sData = pData; int dwFullLen = sData.GetLength(); // just to be safe... while (dwMaxLines--) { CString sFullString = sData.SpanExcluding(_T("\r\n")); int dwPartLen = sFullString.GetLength(); if (!dwPartLen) break; dwFullLen -= dwPartLen; CString sSkipString1 = sData.Right(dwFullLen); CString sSkipString2 = sSkipString1.SpanIncluding(_T("\r\n")); dwFullLen -= sSkipString2.GetLength(); sData = sSkipString1.Right(dwFullLen); sFullString.TrimLeft(); sFullString.TrimRight(); int dwLineLen = sFullString.GetLength(); if (!dwLineLen) continue; if (sFullString[0] == _T(';')) continue; if (sFullString == TSINI_GROUP_STR) { bFoundHeader = TRUE; continue; } else if (sFullString[0] == _T('[')) { bFoundHeader = FALSE; continue; } if (bFoundHeader) { CString sParam[TSINI_LINE_PARAM_COUNT]; int posstart = 0; // now break apart components for (int i=0;i