// // MODULE: APGTSHTX.CPP // // PURPOSE: Template file decoder // // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint // // COMPANY: Saltmine Creative, Inc. (206)-633-4743 support@saltmine.com // // AUTHOR: Roman Mach // // ORIGINAL DATE: 8-2-96 // // NOTES: // 1. Based on Print Troubleshooter DLL // // Version Date By Comments //-------------------------------------------------------------------- // V0.1 - RM Original // V0.15 8/15/96 VM New htx format // V0.2 6/4/97 RWM Local Version for Memphis // V0.3 04/09/98 JM/OK+ Local Version for NT5 // #include "stdafx.h" //#include #include #include #include #include #include #include #include #include #include #include "apgts.h" #include "ErrorEnums.h" #include "bnts.h" #include "BackupInfo.h" #include "cachegen.h" #include "apgtsinf.h" #include "apgtscmd.h" #include "apgtshtx.h" #include "TSHOOT.h" #include "chmread.h" // // CHTMLInputTemplate::CHTMLInputTemplate(const TCHAR *filename) { // initialize a few things m_dwErr = 0; m_cur_stack_count=0; m_command_start = NULL; _tcscpy(m_filename,filename); m_cHeaderItems = 0; m_infer = NULL; m_strResPath = _T(""); } // // CHTMLInputTemplate::~CHTMLInputTemplate() { Destroy(); } // // must be locked to use // VOID CHTMLInputTemplate::SetInfer(CInfer *infer, TCHAR *vroot) { m_infer = infer; _tcscpy(m_vroot, vroot); } // // DWORD CHTMLInputTemplate::Initialize(LPCTSTR szResPath, CString strFile) { CHAR *filestr; m_dwErr = 0; m_strResPath = szResPath; m_strFile = strFile; if (strFile.GetLength()) { // m_filename is CHM file path and name // and strFile - file name within CHM if (S_OK != ::ReadChmFile(m_filename, strFile, (void**)&filestr, &m_dwSize)) { m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG;//fix! return m_dwErr; } } else { // m_filename is a free standing file DWORD nBytesRead; HANDLE hFile; BOOL bResult; hFile = CreateFile( m_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { //??? //ReportError(TSERR_RESOURCE); m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG;//fix! return m_dwErr; } m_dwSize = GetFileSize(hFile, NULL); filestr = (CHAR *)malloc(m_dwSize+1); if (!((m_dwSize != 0xFFFFFFFF) && (m_dwSize != 0)) || filestr == NULL) { CloseHandle(hFile); m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG;//fix! return m_dwErr; } bResult = ReadFile(hFile, filestr, m_dwSize, &nBytesRead, NULL); if(!(bResult && nBytesRead == m_dwSize)) { CloseHandle(hFile); free(filestr); m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG;//fix! return m_dwErr; } CloseHandle(hFile); hFile = NULL; } filestr[m_dwSize] = '\0'; #ifdef _UNICODE WCHAR *wfilestr = (WCHAR *)malloc((m_dwSize + 1) * sizeof (WCHAR)); WCHAR *wchopstr = (WCHAR *)malloc((m_dwSize + 1) * sizeof (WCHAR)); MultiByteToWideChar( CP_ACP, 0, filestr, -1, wfilestr, m_dwSize ); MultiByteToWideChar( CP_ACP, 0, filestr, -1, wchopstr, m_dwSize ); m_startstr = wfilestr; m_chopstr = wchopstr; #else m_startstr = filestr; m_chopstr = (CHAR *)malloc(m_dwSize+1); strcpy(m_chopstr, filestr); #endif // get locations of start and end blocks ScanFile(); // copy blocks into ram for speed BuildInMem(); // free memory free(filestr); #ifdef _UNICODE free(wfilestr); #endif free(m_chopstr); return m_dwErr; } // // VOID CHTMLInputTemplate::Destroy() { HTXCommand *command, *nextcommand; // free holders command = m_command_start; nextcommand = command; while (command != NULL) { nextcommand = command->GetNext(); delete command; command = nextcommand; } } // // DWORD CHTMLInputTemplate::Reload() { Destroy(); return Initialize((LPCTSTR) m_strResPath, m_strFile); } // // void CHTMLInputTemplate::ScanFile() { UINT start, end; TCHAR *ptr, *sptr, *eptr, var_name[30]; HTXCommand *tmpCommand, *prevCommand; UINT var_index; sptr = m_chopstr; m_cur_command = new HTXCommand(HTX_TYPESTART,_T("")); end = start = 0; m_cur_command->SetStart(start); m_cur_command->SetEnd(end); m_command_start = m_cur_command; // this is bad: if the user does not terminate each command on a separate line // the file will misbehave, should at least write out a warning or something... sptr = _tcstok(sptr, _T("\r\n")); if (sptr) { do { if ((sptr = _tcsstr(sptr,HTX_COMMAND_START)) != NULL) { if ((ptr = _tcsstr(sptr,HTX_ENDIFSTR))!=NULL) { tmpCommand = new HTXCommand(HTX_TYPEENDIF,HTX_ENDIFSTR); prevCommand = Pop(); if (prevCommand->GetType() != HTX_TYPEIF) { m_dwErr = EV_GTS_ERROR_ITMPL_IFMISTAG; break; } prevCommand->SetEndIf(tmpCommand); } else if ((ptr = _tcsstr(sptr,HTX_ENDFORSTR))!=NULL) { tmpCommand = new HTXCommand(HTX_TYPEENDFOR,HTX_ENDFORSTR); prevCommand = Pop(); if (prevCommand->GetType() != HTX_TYPEFORANY) { m_dwErr = EV_GTS_ERROR_ITMPL_FORMISTAG; break; } prevCommand->SetEndFor(tmpCommand); } else if ((ptr = _tcsstr(sptr,HTX_ELSESTR))!=NULL) { tmpCommand = new HTXCommand(HTX_TYPEELSE,HTX_ELSESTR); prevCommand = Pop(); if (prevCommand->GetType() != HTX_TYPEIF) { m_dwErr = EV_GTS_ERROR_ITMPL_IFMISTAG; break; } prevCommand->SetElse(tmpCommand); Push(prevCommand); } else if ((ptr = _tcsstr(sptr,HTX_IFSTR))!=NULL) { // get the variable ptr = _tcsninc(ptr, _tcslen(HTX_IFSTR)); if( _stscanf(ptr,_T("%s"),var_name) <= 0) m_dwErr = EV_GTS_ERROR_ITMPL_IFMISTAG; if ((var_index = CheckVariable(var_name)) == FALSE ) { m_dwErr = EV_GTS_ERROR_ITMPL_VARIABLE; break; } tmpCommand = new HTXIfCommand(HTX_TYPEIF,HTX_IFSTR,var_index); Push(tmpCommand); } else if ((ptr = _tcsstr(sptr,HTX_FORANYSTR))!=NULL) { // get variable ptr = _tcsninc(ptr, _tcslen(HTX_FORANYSTR)); if( _stscanf(ptr,_T("%s"),var_name) <= 0) m_dwErr = EV_GTS_ERROR_ITMPL_FORMISTAG; if ((var_index = CheckVariable(var_name)) == FALSE ) { m_dwErr = EV_GTS_ERROR_ITMPL_VARIABLE; break; } tmpCommand = new HTXForCommand(HTX_TYPEFORANY,HTX_FORANYSTR, var_index); Push(tmpCommand); } else if ((ptr = _tcsstr(sptr,HTX_DISPLAYSTR))!=NULL) { // get variable ptr = _tcsninc(ptr, _tcslen(HTX_DISPLAYSTR)); if( _stscanf(ptr,_T("%s"),var_name) <= 0) m_dwErr = EV_GTS_ERROR_ITMPL_FORMISTAG; if ((var_index = CheckVariable(var_name)) == FALSE ) { m_dwErr = EV_GTS_ERROR_ITMPL_VARIABLE; break; } tmpCommand = new HTXDisplayCommand(HTX_TYPEDISPLAY,HTX_DISPLAYSTR, var_index); } else if ((ptr = _tcsstr(sptr, HTX_RESOURCESTR)) != NULL) { ptr = _tcsninc(ptr, _tcslen(HTX_RESOURCESTR)); if (_stscanf(ptr, _T("%s"), var_name) <= 0) m_dwErr = EV_GTS_ERROR_ITMPL_FORMISTAG; if ((var_index = CheckVariable(var_name)) == FALSE) { m_dwErr = EV_GTS_ERROR_ITMPL_VARIABLE; break; } m_cHeaderItems++; tmpCommand = new HTXResourceCommand(HTX_TYPERESOURCE, HTX_RESOURCESTR); ((HTXResourceCommand *) tmpCommand)->GetResName(var_name); } else continue; // get the command terminator if ((eptr = _tcsstr(ptr,HTX_COMMAND_END)) == NULL) { m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG; eptr = ptr; // try to recover } eptr = _tcsninc(eptr, _tcslen(HTX_COMMAND_END)); if (tmpCommand == NULL) { m_dwErr = EV_GTS_ERROR_ITMPL_NOMEM; return; } // Add command to command list if (m_command_start == NULL) { m_command_start = tmpCommand; m_cur_command = tmpCommand; } else { m_cur_command->SetNext(tmpCommand); m_cur_command = tmpCommand; } CString strCHM = ::ExtractCHM(m_filename); tmpCommand->GetResource(m_strResPath, strCHM); start = (UINT)(sptr - m_chopstr); // / sizeof (TCHAR); end = (UINT)(eptr - m_chopstr); // / sizeof (TCHAR); tmpCommand->SetStart(start); tmpCommand->SetEnd(end); } } while ((sptr = _tcstok(NULL, _T("\r\n"))) != NULL); } if (m_cur_stack_count > 0) // missing and endfor or an endif m_dwErr = EV_GTS_ERROR_ITMPL_ENDMISTAG; } /* * METHOD: BuildInMem * * PURPOSE: This method will read the HTML between commands (after) and associate * it with the command. As a command is executed the HTML after the * command is printed * */ UINT CHTMLInputTemplate::BuildInMem() { HTXCommand *cur_com, *last_command; if (m_dwErr) return (TRUE); // copy strings from file to // note duplication of effort (before and after strings may be same string) cur_com = m_command_start; last_command = cur_com; while (cur_com != NULL) { if (cur_com->GetNext() == NULL) { if (cur_com->ReadAfterStr(cur_com->GetEnd(), m_dwSize, m_startstr)) return (m_dwErr = EV_GTS_ERROR_ITMPL_NOMEM); } else { if (cur_com->ReadAfterStr(cur_com->GetEnd(), cur_com->GetNext()->GetStart(), m_startstr)) return (m_dwErr = EV_GTS_ERROR_ITMPL_NOMEM); } last_command = cur_com; cur_com = cur_com->GetNext(); } return (FALSE); } // // bool CHTMLInputTemplate::IsFileName(TCHAR *name) { bool bFileName; if (name[0] != _T('$')) bFileName = false; else if (NULL == _tcsstr(name, _T("."))) bFileName = false; else bFileName = true; return bFileName; } /* * METHOD: CheckVariable * * PURPOSE: This routine will check to see if the variable name is a valid one * and if it is will return a UINT that represents that variable. * Integers are used in other routines when refering to a variable (for * speed). * */ UINT CHTMLInputTemplate::CheckVariable(TCHAR *var_name) { if (!_tcsncmp(DATA_PROBLEM_ASK,var_name, _tcslen(var_name))) { return (PROBLEM_ASK_INDEX); } else if (!_tcsncmp(DATA_RECOMMENDATIONS,var_name, _tcslen(var_name))) { return (RECOMMENDATIONS_INDEX); } else if (!_tcsncmp(DATA_QUESTIONS,var_name, _tcslen(var_name))) { return (QUESTIONS_INDEX); } else if (!_tcsncmp(DATA_STATE,var_name, _tcslen(var_name))) { return (STATE_INDEX); } else if (!_tcsncmp(DATA_BACK,var_name, _tcslen(var_name))) { return (BACK_INDEX); } else if (!_tcsncmp(DATA_TROUBLE_SHOOTERS, var_name, _tcslen(var_name))) { return (TROUBLE_SHOOTER_INDEX); } else if (IsFileName(var_name)) { return (RESOURCE_INDEX); } else return (FALSE); } // // UINT CHTMLInputTemplate::GetStatus() { return (m_dwErr); } CHTMLInputTemplate::Push(HTXCommand *command) { if (m_cur_stack_count >9) return(FALSE); m_command_stack[m_cur_stack_count] = command; m_cur_stack_count++; return(TRUE); } HTXCommand *CHTMLInputTemplate::Pop() { if (m_cur_stack_count <= 0) return(NULL); return(m_command_stack[--m_cur_stack_count]); } // // HTXCommand *CHTMLInputTemplate::GetFirstCommand() { return(m_command_start); } /* * ROUTINE: SetType * * PURPOSE: This set the TroubleShooter Type in the template * The type field is printed after the header information * */ void CHTMLInputTemplate::SetType(LPCTSTR type) { _stprintf(m_tstype, _T("%s"),type); } /* * ROUTINE: Print * * PURPOSE: Prints out the Template. This functions executes the * commands in the template and generates the output page. * */ CHTMLInputTemplate::Print(UINT nargs, CString *cstr) { HTXCommand *cur_com; CString strTxt; if (m_dwErr){ strTxt.LoadString(IDS__ER_HTX_PARSE); *cstr += strTxt; return(FALSE); } cur_com = m_command_start; // get the start command cur_com = cur_com->Execute(cstr,m_infer); // This prints the header if (m_cHeaderItems) { // The first command prints script. Don't start the form. int count = m_cHeaderItems; do { cur_com = cur_com->GetNext(); cur_com = cur_com->Execute(cstr, m_infer); count--; } while (count > 0); AfxFormatString1(strTxt, IDS_FORM_START, m_tstype); *cstr += strTxt; cur_com = cur_com->GetNext(); } else { AfxFormatString1(strTxt, IDS_FORM_START, m_tstype); *cstr += strTxt; cur_com = cur_com->GetNext(); } while (cur_com != NULL) { cur_com = cur_com->Execute(cstr, m_infer); cur_com = cur_com->GetNext(); } return(TRUE); } // for testing // void CHTMLInputTemplate::DumpContentsToStdout() { HTXCommand *cur_com; cur_com = GetFirstCommand(); while( cur_com != NULL){ _tprintf(_T("(%d) before: [%s]\n"), cur_com->GetType(), cur_com->GetBeforeStr()); _tprintf(_T("(%d) after: [%s]\n"), cur_com->GetType(), cur_com->GetAfterStr()); _tprintf(_T("\n")); cur_com = cur_com->GetNext(); } }