// Copyright (c) 1996-1997, Microsoft Corp. All rights reserved. #include "header.h" #include "contain.h" #include "cprint.h" #include "secwin.h" #include "web.h" #include "contain.h" #include #include #include "cdlg.h" #include "resource.h" #include "progress.h" #include "cpaldc.h" #include "hha_strtable.h" #include "animate.h" #include // #define INITGUID #include #include BOOL CPrint::OnBeginOrEnd(void) { if (m_fInitializing) { switch (m_action) { case PRINT_CUR_ALL: SetCheck(IDRADIO_PRINT_ALL); break; case PRINT_CUR_HEADING: SetCheck(IDRADIO_PRINT_BOOK); break; default: SetCheck(IDRADIO_PRINT_CURRENT); break; } } else { if (GetCheck(IDRADIO_PRINT_ALL)) m_action = PRINT_CUR_ALL; else if (GetCheck(IDRADIO_PRINT_BOOK)) m_action = PRINT_CUR_HEADING; else m_action = PRINT_CUR_TOPIC; } return TRUE; } void CHHWinType::OnPrint(void) { HWND hWnd; if (m_pCIExpContainer == NULL) { return; } static BOOL fCurrentlyPrinting = FALSE; if (fCurrentlyPrinting) { MsgBox(IDS_PRINTING); return; } CToc* ptoc = reinterpret_cast(m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: This should be a dynamic_cast. However, we are not compiling with RTTI. hWnd = GetFocus(); int action = PRINT_CUR_TOPIC; if (IsExpandedNavPane() && curNavType == HHWIN_NAVTYPE_TOC && ptoc != NULL) { HTREEITEM hitem = TreeView_GetSelection(ptoc->m_hwndTree); if (hitem) { CPrint prt(*this); prt.SetAction(action); if (!prt.DoModal()) { SetFocus(hWnd); return; } action = prt.GetAction(); } } if (action == PRINT_CUR_TOPIC) { m_pCIExpContainer->m_pIE3CmdTarget->Exec(NULL, OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } else { fCurrentlyPrinting = TRUE; PrintTopics(action, ptoc, m_pCIExpContainer->m_pWebBrowserApp, GetHwnd()); fCurrentlyPrinting = FALSE; } SetFocus(hWnd); } void PrintTopics(int action, CToc* ptoc, IWebBrowserAppImpl* pWebApp, HWND hWndHelp /* = NULL */) { ASSERT(pWebApp && pWebApp); if (ptoc == NULL || pWebApp == NULL) return; static BOOL fCurrentlyPrinting = FALSE; if (fCurrentlyPrinting) { MsgBox(IDS_PRINTING); return; } fCurrentlyPrinting = TRUE; CStr cszCurrentUrl; pWebApp->GetLocationURL(&cszCurrentUrl); CPrintHook ph(cszCurrentUrl, ptoc, hWndHelp); ph.BeginPrinting(action); fCurrentlyPrinting = FALSE; } ///////////////////////////////////////////////////////////////////////////// // CPrintHook member functions CPrintHook::CPrintHook(PCSTR pszFirstUrl, CToc* pToc, HWND hWndHelp /* = NULL */) : m_pcp(NULL), m_dwCookie(0), m_ref(0), m_pToc(pToc), m_action(PRINT_CUR_TOPIC), m_hWndHelp(hWndHelp), m_phh(NULL), m_level(0), m_fFirstHeading(TRUE), m_fDestroyHelpWindow(FALSE), m_cszFirstUrl(pszFirstUrl), m_fIsIE3(FALSE), m_cszPrintFile("") { m_phh = pToc->m_phh; } BOOL CPrintHook::CreatePrintWindow(CStr* pcszUrl /* = NULL */) { BOOL bReturn = FALSE; HH_WINTYPE hhWinType; ZERO_STRUCTURE(hhWinType); hhWinType.cbStruct = sizeof(HH_WINTYPE); hhWinType.pszType = txtPrintWindow; hhWinType.pszCaption = GetStringResource(IDS_PRINT_CAPTION); hhWinType.rcWindowPos.left = 0; hhWinType.rcWindowPos.top = 0; hhWinType.rcWindowPos.right = 200; hhWinType.rcWindowPos.bottom = 200; hhWinType.dwStyles = WS_MINIMIZE; hhWinType.fsValidMembers = HHWIN_PARAM_RECT | HHWIN_PARAM_STYLES; xHtmlHelpA(NULL, NULL, HH_SET_WIN_TYPE, (DWORD_PTR) &hhWinType); m_hWndHelp = xHtmlHelpA(NULL, txtPrintWindow, HH_DISPLAY_TOPIC, (DWORD_PTR) (pcszUrl ? pcszUrl->psz : m_cszFirstUrl.psz)); m_fDestroyHelpWindow = TRUE; if (m_hWndHelp != NULL) { StartAnimation(IDS_GATHERING_PRINTS, m_hWndHelp); m_phh = FindWindowIndex(m_hWndHelp); if (!m_fDestroyHelpWindow) m_phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate((pcszUrl ? (PCSTR)*pcszUrl : (PCSTR)m_cszFirstUrl), NULL, NULL, NULL, NULL); // Set up the event sink for the WebBrowser control. LPCONNECTIONPOINTCONTAINER pcpc; HRESULT hr = m_phh->m_pCIExpContainer->m_pWebBrowserApp->m_lpDispatch->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pcpc); if (SUCCEEDED(hr)) { // Try to find the connection point for DIID_DWebBrowserEvents2. // If that fails, try DIID_DWebBrowserEvents. hr = pcpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &m_pcp); if (FAILED(hr)) { m_fIsIE3 = TRUE; hr = pcpc->FindConnectionPoint(DIID_DWebBrowserEvents, &m_pcp); } pcpc->Release(); if (SUCCEEDED(hr)) { hr = m_pcp->Advise((LPUNKNOWN)(LPDISPATCH)this, &m_dwCookie); bReturn = TRUE; } } } return bReturn; } void CPrintHook::DestroyPrintWindow() { // Disconnect the event sink. if (m_pcp != NULL) { #ifdef _DEBUG HRESULT hr = m_pcp->Unadvise(m_dwCookie); ASSERT(SUCCEEDED(hr)); #else m_pcp->Unadvise(m_dwCookie); #endif m_pcp->Release(); m_pcp = NULL; } if (m_hWndHelp != NULL) { if (m_fDestroyHelpWindow) { DestroyWindow(m_hWndHelp); m_hWndHelp = NULL; } } DeleteFile(m_cszPrintFile); } CPrintHook::~CPrintHook() { DestroyPrintWindow(); ASSERT(m_ref == 0); } // Generic OLE method implementations. STDMETHODIMP CPrintHook::QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppvObject) { if (DO_GUIDS_MATCH(riid, IID_IUnknown) || DO_GUIDS_MATCH(riid, IID_IDispatch) || DO_GUIDS_MATCH(riid, DIID_DWebBrowserEvents) || DO_GUIDS_MATCH(riid, DIID_DWebBrowserEvents2)) { *ppvObject = (LPVOID)this; AddRef(); return S_OK; } else { *ppvObject = NULL; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CPrintHook::AddRef(void) { return ++m_ref; } STDMETHODIMP_(ULONG) CPrintHook::Release(void) { return --m_ref; } // IDispatch method implementation. STDMETHODIMP CPrintHook::GetTypeInfoCount( /* [out] */ UINT *pctinfo) { return E_NOTIMPL; } STDMETHODIMP CPrintHook::GetTypeInfo( /* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo **ppTInfo) { // arg checking if (iTInfo != 0) return DISP_E_BADINDEX; if (!ppTInfo) return E_POINTER; *ppTInfo = NULL; return E_NOTIMPL; } STDMETHODIMP CPrintHook::GetIDsOfNames( /* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, /* [in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) { return E_NOTIMPL; } STDMETHODIMP CPrintHook::Invoke( /* [in] */ DISPID dispIdMember, /* [in] */ REFIID riid, /* [in] */ LCID lcid, /* [in] */ WORD wFlags, /* [out][in] */ DISPPARAMS *pdispparams, /* [out] */ VARIANT *pVarResult, /* [out] */ EXCEPINFO *pExcepInfo, /* [out] */ UINT *puArgErr) { if (!DO_GUIDS_MATCH(riid, IID_NULL)) return DISP_E_UNKNOWNINTERFACE; if (!(wFlags & DISPATCH_METHOD)) return E_INVALIDARG; switch (dispIdMember) { case DISPID_BEFORENAVIGATE: DBWIN("DISPID_BEFORENAVIGATE\n"); break; case DISPID_BEFORENAVIGATE2: // ie4 version. char szURL[MAX_URL]; char szTFN[MAX_URL]; char szHeaders[MAX_URL]; WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL); // 27-Sep-1997 [ralphw] IE 4 will send us a script command, followed // by a 1 then the current URL. We don't care about the current URL // in this case, so we nuke it. { PSTR pszCurUrl = StrChr(szURL, 1); if (pszCurUrl) *pszCurUrl = '\0'; } szTFN[0] = 0; if( pdispparams->rgvarg[3].pvarVal->bstrVal ) WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].pvarVal->bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL); szHeaders[0] = 0; if( pdispparams->rgvarg[1].pvarVal->bstrVal ) WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].pvarVal->bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL); // OnBeforeNavigate(szURL, (long)pdispparams->rgvarg[4].pvarVal->lVal, szTFN, // pdispparams->rgvarg[2].pvarVal, szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal ); break; #if 0 case DISPID_STATUSTEXTCHANGE: DBWIN("DISPID_STATUSTEXTCHANGE\n"); break; case DISPID_DOWNLOADBEGIN: DBWIN("DISPID_DOWNLOADBEGIN\n"); break; case DISPID_NEWWINDOW: DBWIN("DISPID_NEWWINDOW\n"); break; case DISPID_WINDOWMOVE: DBWIN("DISPID_WINDOWMOVE\n"); break; case DISPID_WINDOWRESIZE: DBWIN("DISPID_WINDOWRESIZE\n"); break; case DISPID_WINDOWACTIVATE: DBWIN("DISPID_WINDOWACTIVATE\n"); break; case DISPID_PROPERTYCHANGE: DBWIN("DISPID_PROPERTYCHANGE\n"); break; case DISPID_TITLECHANGE: DBWIN("DISPID_TITLECHANGE\n"); break; case DISPID_FRAMEBEFORENAVIGATE: DBWIN("DISPID_FRAMEBEFORENAVIGATE\n"); break; case DISPID_FRAMENAVIGATECOMPLETE: DBWIN("DISPID_FRAMENAVIGATECOMPLETE\n"); break; case DISPID_FRAMENEWWINDOW: DBWIN("DISPID_FRAMENEWWINDOW\n"); break; case DISPID_NAVIGATECOMPLETE: DBWIN("DISPID_NAVIGATECOMPLETE\n"); break; case DISPID_DOWNLOADCOMPLETE: DBWIN("DISPID_DOWNLOADCOMPLETE\n"); break; case DISPID_DOCUMENTCOMPLETE: DBWIN("DISPID_DOCUMENTCOMPLETE\n"); break; #endif case DISPID_PROGRESSCHANGE: ASSERT(pdispparams->cArgs == 2); DBWIN("DISPID_PROGRESSCHANGE\n"); OnProgressChange(V_I4(&(pdispparams->rgvarg[1])), V_I4(&(pdispparams->rgvarg[0]))); #if 1 #ifdef _DEBUG char szDebug[80]; wsprintf(szDebug, "ProgressChange(%li, %li)\n", V_I4(&(pdispparams->rgvarg[1])), V_I4(&(pdispparams->rgvarg[0]))); DBWIN(szDebug); #endif #endif } return S_OK; } void CPrintHook::OnProgressChange(LONG lProgress, LONG lProgressMax) { if (lProgress == -1) { StopAnimation(); // Print the page if it isn't a duplicate. if (m_fIsPrinting) { Print(); DBWIN("Printing"); } } else NextAnimation(); } // This function allows the WebBrowser to handle its queued messages before continuing. BOOL CPrintHook::PumpMessages() { MSG msg; // Handle WebBrowser window messages while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (!m_fIsPrinting) { if (m_phh && m_phh->m_pCIExpContainer && m_phh->m_pCIExpContainer->m_pWebBrowserApp) { m_phh->m_pCIExpContainer->m_pWebBrowserApp->Stop(); } return FALSE; } if(!IsDialogMessage(m_hWndHelp, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return TRUE; } void CPrintHook::BeginPrinting(int action) { m_pos = 1; m_level = 0; m_action = action; m_fIsPrinting = TRUE; m_fFirstHeading = TRUE; SITEMAP_ENTRY* psme = NULL; TV_ITEM tvi; if (m_action == PRINT_CUR_TOPIC || m_action == PRINT_CUR_HEADING) { tvi.hItem = TreeView_GetSelection(m_pToc->m_hwndTree); if (!tvi.hItem) goto ExitBegin; // no current selection if (m_pToc->m_fBinaryTOC == FALSE) { tvi.mask = TVIF_PARAM; if (TreeView_GetItem(m_pToc->m_hwndTree, &tvi)) psme = m_pToc->m_sitemap.GetSiteMapEntry((int)tvi.lParam); if (psme == NULL) goto ExitBegin; m_pos = (int)tvi.lParam; // Because the user may have selected a topic under a heading, but // wants to print all of the topics under that heading, we have to // search upward until we find the heading. if (m_action == PRINT_CUR_HEADING) { if (psme->fTopic || psme->cUrls <= 0) { while (psme != NULL && psme->fTopic && m_pos > 0) { psme = m_pToc->m_sitemap.GetSiteMapEntry(--m_pos); } } } // Set the current level for reference later. If the user just // wants to print the current topic, the level isn't significant. m_level = ((m_action == PRINT_CUR_TOPIC || psme == NULL) ? 0 : psme->level); } } if (m_pToc->m_fBinaryTOC == FALSE) { // If the user isn't printing all topics and psme is NULL, // see if this is just a single topic and, if so, print it. if (m_action != PRINT_CUR_ALL && psme == NULL) { // Get the original sitemap entry. m_pos = (int)tvi.lParam; psme = m_pToc->m_sitemap.GetSiteMapEntry(m_pos); // If there's a URL, print it. if (psme->cUrls > 0) { m_action = PRINT_CUR_TOPIC; } } } if (BuildPrintTable()) { // We sit in this loop while printing because we don't want this // function to return until printing is complete. while (PumpMessages()); DestroyPrintWindow(); } ExitBegin: return; } BOOL CPrintHook::BuildPrintTable() { BOOL bReturn = FALSE; if (!m_fIsPrinting) return bReturn; CTable table; CStr cszCurUrl; if (m_pToc->m_fBinaryTOC) { switch (m_action) { case PRINT_CUR_TOPIC: m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl); table.AddString((PCSTR)cszCurUrl); break; case PRINT_CUR_HEADING: TV_ITEM tvi; tvi.hItem = TreeView_GetSelection(m_pToc->m_hwndTree); if (!tvi.hItem) { m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl); table.AddString((PCSTR)cszCurUrl); } else { tvi.mask = TVIF_PARAM; TreeView_GetItem(m_pToc->m_hwndTree, &tvi); CTreeNode *p = (CTreeNode *)tvi.lParam; CTreeNode *pParent = NULL; if (p->GetType() == TOPIC) { pParent = p->GetParent(); } CHourGlass hour; m_phh->m_phmData->m_pTitleCollection->GetChildURLS((pParent ? pParent: p), &table); if (pParent) delete pParent; } break; case PRINT_CUR_ALL: if (!m_pToc->m_pBinTOCRoot) { m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl); table.AddString((PCSTR)cszCurUrl); } else m_phh->m_phmData->m_pTitleCollection->GetChildURLS(m_pToc->m_pBinTOCRoot, &table); // oh my god they are printing the entire TOC break; } } else { // Get the next sitemap entry. // Print the sitemap entry URL if the its level is greater than // the saved level. If the sitemap entry is a heading at the same // level and contains a URL, proceed as well. for (SITEMAP_ENTRY* psme = m_pToc->m_sitemap.GetSiteMapEntry(m_pos); psme != NULL; psme = m_pToc->m_sitemap.GetSiteMapEntry(++m_pos)) { if ((psme->level > m_level) || (!psme->fTopic && psme->level == m_level && m_fFirstHeading)) { // The top level heading could have a URL, so we // want to print it. However, we don't want to print // any other headings at that level, so set the // m_fFirstHeading flag to FALSE. if (m_action == PRINT_CUR_HEADING && !psme->fTopic && psme->level == m_level) { m_fFirstHeading = FALSE; } if (psme->cUrls > 0) { // Get the URL from the sitemap entry. LPCTSTR pszUrl = (psme->pUrls->urlPrimary ? psme->pUrls->urlPrimary : psme->pUrls->urlSecondary); CStr cszUrl(pszUrl); // Synchronize the TOC if we created the print window. if (m_fDestroyHelpWindow) m_pToc->Synchronize(cszUrl); // Truncate the strings at the # character if there is one. LPTSTR pszFind = StrChr(cszUrl, '#'); if (pszFind != NULL) *pszFind = '\0'; ConvertBackSlashToForwardSlash(cszUrl); if (table.IsStringInTable(cszUrl) == 0) table.AddString((PCSTR)cszUrl); if (m_action == PRINT_CUR_TOPIC) break; } } else break; } } if (m_pToc->m_phhctrl != NULL) { m_pToc->m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl); m_hwndParent = m_pToc->m_phhctrl->m_hwndParent; } else if (m_pToc->m_fBinaryTOC) { cszCurUrl = m_phh->GetToc(); m_hwndParent = m_phh->GetHwnd(); } else { cszCurUrl = m_pToc->m_sitemap.GetSiteMapFile(); if (m_phh) m_hwndParent = m_phh->GetHwnd(); else m_hwndParent = m_hWndHelp; } if (ConstructFile((PCSTR)cszCurUrl, &table, &m_cszPrintFile)) { bReturn = CreatePrintWindow(&m_cszPrintFile); } return bReturn; } static const char txtTmpPrefix[] = "~hh"; static const char txtHtmlExtension[] = ".htm"; static const char txtImg[] = "IMG"; static const char txtSrc[] = "SRC"; static const char txtLink[] = "LINK"; static const char txtHREF[] = "HREF"; static const char txtTagBeginBody[] = "BODY"; static const char txtTagEndBody[] = "/BODY"; static const char txtTagItAll[] = ""; static const char txtTmpPrintStinrg[] = "~hh%X.htm"; static const char txtFrame[] = "FRAME"; static const char txtBeginScript[] = "SCRIPT"; static const char txtEndScript[] = "/SCRIPT"; const int FILE_PAD = 16 * 1024; BOOL CPrintHook::ConstructFile(PCSTR pszCurrentUrl, CTable* pFileTable, CStr* pm_cszPrintFile) { char szTempPath[MAX_PATH]; char szHtmlFile[MAX_PATH]; char szThisURL[MAX_PATH]; char szCurrentUrl[MAX_PATH]; CProgress progress(GetStringResource(IDS_GATHERING_PRINTS), m_hwndParent, pFileTable->CountStrings() / 10, 10); strcpy(szCurrentUrl, pszCurrentUrl); PSTR pszFilePortion = (PSTR) FindFilePortion(szCurrentUrl); ASSERT(pszFilePortion); GetTempPath(sizeof(szHtmlFile), szHtmlFile); AddTrailingBackslash(szHtmlFile); wsprintf(szHtmlFile + strlen(szHtmlFile), txtTmpPrintStinrg, GetTickCount() & 0xFFFF); HFILE hfDst = _lcreat(szHtmlFile, 0); if (hfDst == HFILE_ERROR) { MsgBox(IDS_FILE_ERROR, szHtmlFile, MB_OK); return FALSE; } int endpos = pFileTable->CountStrings(); PSTR pszMem = NULL; CStr cszTmpFile; for (int i = 1; i <= endpos; i++) { BOOL fSeenBody = FALSE; if (pszMem) { GlobalFree((HGLOBAL) pszMem); pszMem = NULL; } progress.Progress(); ASSERT_COMMENT(pFileTable->CountStrings(), "Empty file list"); PSTR pszFile; if (!StrChr(pFileTable->GetPointer(i), CH_COLON)) { if (*pFileTable->GetPointer(i) == '/' || *pFileTable->GetPointer(i) == '\\') { TranslateUrl(szCurrentUrl, pFileTable->GetPointer(i)); } else { strcpy(pszFilePortion, pFileTable->GetPointer(i)); } pszFile = szCurrentUrl; } else { pszFile = pFileTable->GetPointer(i); PSTR psz = stristr(pszFile, txtSysRoot); if (psz) { char szPath[MAX_PATH]; GetRegWindowsDirectory(szPath); strcat(szPath, psz + strlen(txtSysRoot)); cszTmpFile = szPath; pszFile = cszTmpFile.psz; } else if (IsCompiledHtmlFile(pszFile, &cszTmpFile)) { pszFile = cszTmpFile.psz; } } strcpy(szThisURL, pszFile); if (!ConvertToCacheFile(pszFile, szTempPath)) { // AuthorMsg(IDS_CANT_OPEN, pFileTable->GetPointer(i), m_hwndParent, NULL); continue; } int cbMem; UINT cbFile, cbFinalLen; PSTR psz, pszStart , pszTag; if ( IsCompiledURL(szTempPath ) ) { CStr cszCompiledName; PCSTR pszStream = GetCompiledName(szTempPath, &cszCompiledName); if (pszStream == NULL) continue; // BUGBUG: should use existing file system handle if available CFSClient fs; if (!fs.Initialize(cszCompiledName)) { MsgBox(IDS_FILE_ERROR, pFileTable->GetPointer(i), MB_OK); continue; } if (FAILED(fs.OpenStream(pszStream))) { // AuthorMsg(IDS_CANT_OPEN, pFileTable->GetPointer(i), m_hwndParent, NULL); continue; } cbFile = fs.SeekSub(0, SK_END); cbFinalLen = cbFile; fs.SeekSub(0, SK_SET); cbMem = cbFile + FILE_PAD; pszMem = (PSTR) GlobalAlloc(GMEM_FIXED, cbMem); ASSERT(pszMem); if (!pszMem) { GlobalFree((HGLOBAL) pszMem); fs.CloseStream(); continue; } if (FAILED(fs.Read((PBYTE) pszMem, cbFile))) { fs.CloseStream(); continue; } fs.CloseStream(); } else { HANDLE hf = CreateFile(szTempPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hf == INVALID_HANDLE_VALUE) goto BadFile; ASSERT(hf); cbFile = GetFileSize(hf, NULL); cbFinalLen = cbFile; cbMem = cbFile + FILE_PAD; pszMem = (PSTR) GlobalAlloc(GMEM_FIXED, cbMem); ASSERT(pszMem); if (!pszMem) { GlobalFree((HGLOBAL) pszMem); CloseHandle(hf); continue; // next HTML file might be smaller, so try again } DWORD cbRead; if (!ReadFile(hf, pszMem, cbFile, &cbRead, NULL) || cbRead != cbFile) { CloseHandle(hf); continue; } CloseHandle(hf); } pszMem[cbFile] = '\0'; psz = pszMem; pszStart = psz; pszTag = psz; while ((pszTag = StrChr(pszTag, '<'))) { pszTag = FirstNonSpace(pszTag + 1); if (IsSamePrefix(pszTag, txtTagEndBody, sizeof(txtTagEndBody) - 1)) { while (*pszTag != '<') // back up to the angle bracket pszTag--; cbFile = (int)(pszTag - pszStart); break; } else if (IsSamePrefix(pszTag, txtBeginScript, sizeof(txtBeginScript) - 1)) { // skip to end tag while ((pszTag = StrChr(pszTag, '<'))) { pszTag = FirstNonSpace(pszTag + 1); if (IsSamePrefix(pszTag, txtEndScript, sizeof(txtEndScript) - 1)) break; } } else if (IsSamePrefix(pszTag, txtTagBeginBody, sizeof(txtTagBeginBody) - 1)) { // If this isn't the first HTML file, then we ignore everything // up to the body tag if (i > 1 && !fSeenBody) { fSeenBody = TRUE; pszStart = StrChr(pszTag, '>'); if (!pszStart) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } pszStart++; cbFile -= (int)(pszStart - pszMem); } } else if (IsSamePrefix(pszTag, txtImg, sizeof(txtImg) - 1)) { // Change the URL for images to be a full path -- this lets // the browser pull it in without us having to copy it // anywhere. pszTag += sizeof(txtImg) - 1; for(;;) { while (*pszTag != ' ' && *pszTag != '>') { if (*pszTag == CH_QUOTE) { pszTag = StrChr(pszTag + 1, CH_QUOTE); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } } pszTag++; } if (*pszTag == '>') goto NoSrcTag; pszTag++; if (IsSamePrefix(pszTag, txtSrc, sizeof(txtSrc) - 1)) break; pszTag++; } ASSERT(IsSamePrefix(pszTag, txtSrc, sizeof(txtSrc) - 1)); pszTag = StrChr(pszTag, '='); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } pszTag = FirstNonSpace(pszTag + 1); char chSearch; if (*pszTag == CH_QUOTE) { chSearch = CH_QUOTE; pszTag = FirstNonSpace(pszTag + 1); } else chSearch = ' '; PSTR pszBeginUrl = pszTag; pszTag = StrChr(pszTag + 1, chSearch); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } char chSave = *pszTag; *pszTag = '\0'; if (!StrChr(pszBeginUrl, CH_COLON)) { // This makes it relative to the original HTML file, // but not necessarily relative to the current file CStr cszCompiledName; char fname[_MAX_FNAME]=""; int diff=0; PSTR pszBeginFile='\0'; strcpy(szTempPath, szThisURL); if ( IsCompiledURL(szTempPath ) ) { // a compiled URL with an image in it. PCSTR pszStream = GetCompiledName(szTempPath, &cszCompiledName); SplitPath(pszStream, NULL, NULL, fname, NULL); pszBeginFile = stristr(szTempPath, fname); ASSERT( pszBeginFile ); diff = (int)(strlen(szThisURL) - strlen(pszBeginFile)); }else { // non-compiled URL; an html file with and image in it pszBeginFile = strrchr(szTempPath, '/'); ASSERT(pszBeginFile); diff = (int)(pszBeginFile - szTempPath) + 1; } cbFile += diff; cbFinalLen += diff; while (cbFinalLen > (UINT) cbMem) { int StartDiff = (int)(pszStart - pszMem); int TagDiff = (int)(pszTag - pszMem); int BeginDiff = (int)(pszBeginUrl - pszMem); PSTR pszNew = (PSTR) GlobalReAlloc((HGLOBAL) pszMem, cbMem += FILE_PAD, GMEM_MOVEABLE); ASSERT(pszNew); if (!pszNew) { GlobalFree((HGLOBAL) pszMem); MsgBox(IDS_OOM); _lclose(hfDst); DeleteFile(szHtmlFile); if (pszMem) { GlobalFree((HGLOBAL) pszMem); pszMem = NULL; } return FALSE; } pszMem = pszNew; pszStart = pszMem + StartDiff; pszTag = pszMem + TagDiff; pszBeginUrl = pszMem + BeginDiff; } MoveMemory(pszTag + diff, pszTag, cbFinalLen - (pszTag - pszMem) - diff); if ( !IsCompiledURL(szTempPath) ) { strcpy(pszBeginFile, "/"); pszBeginFile ++; // pointing at the NULL } strcpy(pszBeginFile, pszBeginUrl); strcpy( pszBeginUrl, szTempPath); pszTag += diff; *pszTag = chSave; } else *pszTag = chSave; } else if (IsSamePrefix(pszTag, txtLink, sizeof(txtLink) - 1)) { // Change the URL for CSS to be a full path -- this lets // the browser pull it in without us having to copy it // anywhere. pszTag += sizeof(txtImg) - 1; for(;;) { while (*pszTag != ' ' && *pszTag != '>') { if (*pszTag == CH_QUOTE) { pszTag = StrChr(pszTag + 1, CH_QUOTE); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } } pszTag++; } if (*pszTag == '>') goto NoSrcTag; pszTag++; if (IsSamePrefix(pszTag, txtHREF, sizeof(txtHREF) - 1)) break; pszTag++; } ASSERT(IsSamePrefix(pszTag, txtHREF, sizeof(txtHREF) - 1)); pszTag = StrChr(pszTag, '='); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } pszTag = FirstNonSpace(pszTag + 1); char chSearch; if (*pszTag == CH_QUOTE) { chSearch = CH_QUOTE; pszTag = FirstNonSpace(pszTag + 1); } else chSearch = ' '; PSTR pszBeginUrl = pszTag; pszTag = StrChr(pszTag + 1, chSearch); if (!pszTag) { AuthorMsg(IDSHHA_CORRUPTED_HTML, pFileTable->GetPointer(i), m_hwndParent, NULL); goto BadFile; } char chSave = *pszTag; *pszTag = '\0'; char szScratch[MAX_URL]; if (!StrChr(pszBeginUrl, CH_COLON)) { // BUGBUG: This makes it relative to the original HTML file, // but not necessarily relative to the current file strcpy(pszFilePortion, pszBeginUrl); strcpy(szScratch, szCurrentUrl); } else { // qualify .CHM filespec which will look like: MK@MSITStore:foo.chm::/bar.css // CExCollection* pCollection; CExTitle* pTitle; HRESULT hr; if ( (pCollection = GetCurrentCollection(NULL, pszBeginUrl)) ) { if ( SUCCEEDED(hr = pCollection->URL2ExTitle( pszBeginUrl, &pTitle )) && pTitle ) { const char* pszPathName; char* psz; lstrcpy(szScratch, pszBeginUrl); if ( (pszPathName = pTitle->GetPathName()) ) { if ( (psz = StrChr(szScratch, CH_COLON)) ) { ++psz; strcpy(psz, pszPathName); if ( (psz = StrStr(pszBeginUrl, "::")) ) strcat(szScratch, psz); } } } } } int diff = (int)(strlen(szScratch) - strlen(pszBeginUrl)); cbFile += diff; cbFinalLen += diff; while (cbFinalLen >= (UINT) cbMem) { int StartDiff = (int)(pszStart - pszMem); int TagDiff = (int)(pszTag - pszMem); int BeginDiff = (int)(pszBeginUrl - pszMem); PSTR pszNew = (PSTR) GlobalReAlloc((HGLOBAL) pszMem, cbMem += FILE_PAD, GMEM_MOVEABLE); ASSERT(pszNew); if (!pszNew) { GlobalFree((HGLOBAL) pszMem); MsgBox(IDS_OOM); _lclose(hfDst); DeleteFile(szHtmlFile); if (pszMem) { GlobalFree((HGLOBAL) pszMem); pszMem = NULL; } return FALSE; } pszMem = pszNew; pszStart = pszMem + StartDiff; pszTag = pszMem + TagDiff; pszBeginUrl = pszMem + BeginDiff; } MoveMemory(pszTag + diff, pszTag, cbFinalLen - (pszTag - pszMem) - diff); strcpy(pszBeginUrl, szScratch); pszTag += diff; *pszTag = chSave; } else if (IsSamePrefix(pszTag, txtFrame, sizeof(txtFrame) - 1)) { MsgBox(IDS_CANT_PRINT_FRAMESET); _lclose(hfDst); DeleteFile(szHtmlFile); if (pszMem) { GlobalFree((HGLOBAL) pszMem); pszMem = NULL; } return FALSE; } NoSrcTag: pszTag++; // skip over the '<' } if (_lwrite(hfDst, pszStart, cbFile) != cbFile) { MsgBox(IDS_INSUFFICIENT_SPACE, szHtmlFile, MB_OK); _lclose(hfDst); DeleteFile(szHtmlFile); } BadFile: continue; } if (pszMem) { GlobalFree((HGLOBAL) pszMem); pszMem = NULL; } _lclose(hfDst); *pm_cszPrintFile = szHtmlFile; return TRUE; #if 0 BOOL bReturn = (GetSystemDirectory(m_szPrintFile, _MAX_PATH) > 0); if (bReturn) { StrCat(m_szPrintFile, "\\hhtest.htm"); *pm_cszPrintFile = m_szPrintFile; HANDLE hFile = CreateFile(m_szPrintFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { DWORD dwBytesWritten = 0; TCHAR szOpenHTML[] = "\r\n\r\n" \ "

Printing is not currently implemented.

\r\n" \ "

\r\n" \ "Here is the list of files that you asked to print:\r\n" "

\r\n"; WriteFile(hFile, (LPCVOID)szOpenHTML, strlen(szOpenHTML) * sizeof(TCHAR), &dwBytesWritten, NULL); TCHAR szFile[_MAX_PATH], szFileHTML[_MAX_PATH * 2]; pFileTable->SetPosition(); while (pFileTable->GetString(szFile)) { wsprintf(szFileHTML, "%s
\r\n", szFile); WriteFile(hFile, (LPCVOID)szFileHTML, strlen(szFileHTML) * sizeof(TCHAR), &dwBytesWritten, NULL); } TCHAR szCloseHTML[] = "

\r\n" \ "\r\n\r\n"; WriteFile(hFile, (LPCVOID)szCloseHTML, strlen(szCloseHTML) * sizeof(TCHAR), &dwBytesWritten, NULL); CloseHandle(hFile); } else bReturn = FALSE; } return bReturn; #endif } BOOL CPrintHook::TranslateUrl(PSTR pszFullUrl, PSTR pszRelUrl) { BOOL bReturn; URL_COMPONENTS uc; ZERO_STRUCTURE(uc); uc.dwStructSize = sizeof(URL_COMPONENTS); uc.dwSchemeLength = 1; uc.nScheme = INTERNET_SCHEME_DEFAULT ; uc.dwHostNameLength = 1; uc.dwUserNameLength = 1; uc.dwPasswordLength = 1; uc.dwUrlPathLength = 1; uc.dwExtraInfoLength = 1; if ((bReturn = InternetCrackUrl(pszFullUrl, 0, 0, &uc))) { uc.lpszUrlPath = pszRelUrl; uc.dwUrlPathLength = 0; // Make a copy of uc.lpszExtraInfo because it will // be lost when InternetCreateUrl() modifies pszFullUrl. CStr cszExtraInfo(uc.lpszExtraInfo); uc.lpszExtraInfo = (PSTR)cszExtraInfo; uc.dwExtraInfoLength = 0; DWORD dwBufLen = MAX_PATH; bReturn = InternetCreateUrl(&uc, 0, pszFullUrl, &dwBufLen); } return bReturn; } // This function just tells the WebBrowser to print the current page. HRESULT CPrintHook::Print() { // Change the cursor to an hourglass. SetClassLongPtr(m_hWndHelp, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, (LPCTSTR) IDC_WAIT)); HRESULT hr = E_FAIL; HRESULT hrCancelled = (m_fIsIE3 ? 0x80040100 : 0x80040104); LPOLECOMMANDTARGET lpOleCommandTarget = m_phh->m_pCIExpContainer->m_pIE3CmdTarget; ASSERT(lpOleCommandTarget); if (lpOleCommandTarget != NULL) { // Give printing 10 tries and then bail out if it doesn't work. for (USHORT i = 0; i < 10 && FAILED(hr); i++) { if (!PumpMessages()) break; #ifdef _DEBUG try { #endif // Call the Exec() function to print the currently displayed page. if (m_fIsIE3) { hr = lpOleCommandTarget->Exec(NULL,OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER, NULL, NULL); } else { hr = lpOleCommandTarget->Exec(&CGID_MSHTML,IDM_PRINT, MSOCMDEXECOPT_PROMPTUSER, NULL, NULL); } #ifdef _DEBUG TCHAR szDebug[40]; wsprintf(szDebug, "m_pos == %i, hr == %lx", m_pos, hr); DBWIN(szDebug); #endif #ifdef _DEBUG } catch(...) { ASSERT_COMMENT(TRUE, "An exception occurred when printing. " \ "Please send email to randyfe or ralphw."); hr = E_FAIL; } #endif // On IE 4, wait for printing to finish before continuing. if (!m_fIsIE3) { OLECMD olecmd; olecmd.cmdID = IDM_PRINTQUERYJOBSPENDING; do { DBWIN("Waiting for printing to finish..."); olecmd.cmdf = 0; #ifdef _DEBUG try { #else if (m_phh && m_phh->m_pCIExpContainer && m_phh->m_pCIExpContainer->m_pIE3CmdTarget) #endif m_phh->m_pCIExpContainer->m_pIE3CmdTarget->QueryStatus(&CGID_MSHTML, 1, &olecmd, NULL); #ifdef _DEBUG } catch(...) { ASSERT_COMMENT(TRUE, "An exception occurred when waiting for printing to finish. " \ "Please send email to randyfe or ralphw."); break; } #endif PumpMessages(); } while (olecmd.cmdf & OLECMDF_ENABLED); } if (hr == hrCancelled) break; } } m_fIsPrinting = FALSE; // Change the cursor back to an arrow. SetClassLongPtr(m_hWndHelp, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, (LPCTSTR) IDC_ARROW)); #ifdef _DEBUG TCHAR szDebug[50]; wsprintf(szDebug, "Print complete... hr == %lx", hr); DBWIN(szDebug); #endif return hr; } STATIC INT_PTR CALLBACK ProgressDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); const int DEFAULT_WIDTH = 200; const int DEFAULT_HEIGHT = 50; CProgress::CProgress(PCSTR pszCaption, HWND hwndCallersParent, int cSteps, int cHowOften) { cProgress = -1; steps = cSteps; cFrequency = cHowOften; pszTitle = lcStrDup(pszCaption); fWindowCreationFailed = FALSE; hwndProgress = NULL; hwndParent = hwndCallersParent; hwndFrame = NULL; dwStartTime = GetTickCount(); counter = 0; } CProgress::~CProgress() { if (hwndFrame && IsWindow(hwndFrame)) DestroyWindow(hwndFrame); lcFree(pszTitle); } void CProgress::Progress() { if (++counter == cFrequency) { counter = 0; if (hwndProgress) SendMessage(hwndProgress, PBM_STEPIT, 0, 0); else { cProgress++; if (GetTickCount() - dwStartTime >= 1500) CreateTheWindow(); } } } void CProgress::CreateTheWindow(void) { if (fWindowCreationFailed) return; // couldn't create the window if (!hwndParent) { CPalDC dc(SCREEN_IC); rc.left = dc.GetDeviceWidth() - (DEFAULT_WIDTH / 2); rc.top = dc.GetDeviceHeight() - (DEFAULT_HEIGHT / 2); } else { RECT rcParent; GetWindowRect(hwndParent, &rcParent); rc.left = (RECT_WIDTH(rcParent) / 2) - (DEFAULT_WIDTH / 2); rc.top = (RECT_HEIGHT(rcParent) / 2) - (DEFAULT_HEIGHT / 2); } hwndFrame = CreateDialog(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDDLG_PROGRESS), hwndParent, ProgressDialogProc); if (!hwndFrame) { fWindowCreationFailed = TRUE; return; } RECT rcFrame; GetWindowRect(hwndFrame, &rcFrame); MoveWindow(hwndFrame, rcFrame.left, rc.top, RECT_WIDTH(rcFrame), RECT_HEIGHT(rcFrame), FALSE); hwndProgress = GetDlgItem(hwndFrame, ID_PROGRESS); if (steps > 0) { SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, steps)); SendMessage(hwndProgress, PBM_SETSTEP, (WPARAM) 1, 0); } SetWindowText(hwndFrame, pszTitle); while (cProgress-- >= 0) SendMessage(hwndProgress, PBM_STEPIT, 0, 0); ShowWindow(hwndFrame, SW_SHOW); } STATIC INT_PTR CALLBACK ProgressDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_INITDIALOG) return TRUE; else return FALSE; }