Back to index

lightning-sunbird  0.9+nobinonly
IEPatcherDlg.cpp
Go to the documentation of this file.
00001 // IEPatcherDlg.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "IEPatcher.h"
00006 #include "IEPatcherDlg.h"
00007 #include "ScanForFilesDlg.h"
00008 #include "ScannerThread.h"
00009 #include "DlgProxy.h"
00010 
00011 #include <sys/types.h> 
00012 #include <sys/stat.h>
00013 
00014 #ifdef _DEBUG
00015 #define new DEBUG_NEW
00016 #undef THIS_FILE
00017 static char THIS_FILE[] = __FILE__;
00018 #endif
00019 
00020 const CLSID CLSID_WebBrowser_V1 = { 0xEAB22AC3, 0x30C1, 0x11CF, { 0xA7, 0xEB, 0x00, 0x00, 0xC0, 0x5B, 0xAE, 0x0B } };
00021 const CLSID CLSID_WebBrowser = { 0x8856F961, 0x340A, 0x11D0, { 0xA9, 0x6B, 0x00, 0xC0, 0x4F, 0xD7, 0x05, 0xA2 } };
00022 const CLSID CLSID_InternetExplorer = { 0x0002DF01, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
00023 const CLSID CLSID_MozillaBrowser = {0x1339B54C,0x3453,0x11D2,{0x93,0xB9,0x00,0x00,0x00,0x00,0x00,0x00}};
00024 const IID IID_IWebBrowser = { 0xEAB22AC1, 0x30C1, 0x11CF, { 0xA7, 0xEB, 0x00, 0x00, 0xC0, 0x5B, 0xAE, 0x0B } };
00025 const IID IID_IWebBrowser2 = { 0xD30C1661, 0xCDAF, 0x11d0, { 0x8A, 0x3E, 0x00, 0xC0, 0x4F, 0xC9, 0xE2, 0x6E } };
00026 const IID IID_IWebBrowserApp = { 0x0002DF05, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
00027 
00028 
00029 #define ITEM_PATCHSTATUS 1
00030 
00031 #define IMG_DOESNTCONTAINIE 0
00032 #define IMG_CONTAINSIE             1
00033 #define IMG_CONTAINSMOZILLA 2
00034 #define IMG_UNKNOWNSTATUS   3
00035 
00037 // CIEPatcherDlg dialog
00038 
00039 IMPLEMENT_DYNAMIC(CIEPatcherDlg, CDialog);
00040 
00041 CIEPatcherDlg::CIEPatcherDlg(CWnd* pParent /*=NULL*/)
00042        : CDialog(CIEPatcherDlg::IDD, pParent)
00043 {
00044        //{{AFX_DATA_INIT(CIEPatcherDlg)
00045        //}}AFX_DATA_INIT
00046        // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
00047        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
00048        m_pAutoProxy = NULL;
00049 }
00050 
00051 
00052 CIEPatcherDlg::~CIEPatcherDlg()
00053 {
00054        // If there is an automation proxy for this dialog, set
00055        //  its back pointer to this dialog to NULL, so it knows
00056        //  the dialog has been deleted.
00057        if (m_pAutoProxy != NULL)
00058               m_pAutoProxy->m_pDialog = NULL;
00059 }
00060 
00061 
00062 void CIEPatcherDlg::DoDataExchange(CDataExchange* pDX)
00063 {
00064        CDialog::DoDataExchange(pDX);
00065        //{{AFX_DATA_MAP(CIEPatcherDlg)
00066        DDX_Control(pDX, IDC_PATCH, m_btnPatch);
00067        DDX_Control(pDX, IDC_FILELIST, m_cFileList);
00068        //}}AFX_DATA_MAP
00069 }
00070 
00071 
00072 BEGIN_MESSAGE_MAP(CIEPatcherDlg, CDialog)
00073        //{{AFX_MSG_MAP(CIEPatcherDlg)
00074        ON_WM_PAINT()
00075        ON_WM_QUERYDRAGICON()
00076        ON_WM_CLOSE()
00077        ON_BN_CLICKED(IDC_SCAN, OnScan)
00078        ON_NOTIFY(NM_CLICK, IDC_FILELIST, OnClickFilelist)
00079        ON_BN_CLICKED(IDC_PATCH, OnPatch)
00080        //}}AFX_MSG_MAP
00081        ON_MESSAGE(WM_UPDATEFILESTATUS, OnUpdateFileStatus)
00082 END_MESSAGE_MAP()
00083 
00084 
00086 // CIEPatcherDlg message handlers
00087 
00088 BOOL CIEPatcherDlg::OnInitDialog()
00089 {
00090        CDialog::OnInitDialog();
00091 
00092        // Start the scanner thread
00093        AfxBeginThread(RUNTIME_CLASS(CScannerThread), 0);
00094 
00095        // Set the icon for this dialog.  The framework does this automatically
00096        //  when the application's main window is not a dialog
00097        SetIcon(m_hIcon, TRUE);                   // Set big icon
00098        SetIcon(m_hIcon, FALSE);           // Set small icon
00099 
00100        // Add icons to image list
00101        m_cImageList.Create(16, 16, ILC_MASK, 0, 5);
00102        m_cImageList.Add(AfxGetApp()->LoadIcon(IDI_DOESNTCONTAINIE));
00103        m_cImageList.Add(AfxGetApp()->LoadIcon(IDI_CONTAINSIE));
00104        m_cImageList.Add(AfxGetApp()->LoadIcon(IDI_CONTAINSMOZILLA));
00105        m_cImageList.Add(AfxGetApp()->LoadIcon(IDI_UNKNOWNSTATUS));
00106 
00107        // Associate image list with file list
00108        m_cFileList.SetImageList(&m_cImageList, LVSIL_SMALL);
00109 
00110        struct ColumnData
00111        {
00112               TCHAR *sColumnTitle;
00113               int nPercentageWidth;
00114               int nFormat;
00115        };
00116 
00117        ColumnData aColData[] =
00118        {
00119               { _T("File"),               70, LVCFMT_LEFT },
00120               { _T("Patch Status"),       30, LVCFMT_LEFT }
00121        };
00122 
00123        // Get the size of the file list control and neatly
00124        // divide it into columns
00125 
00126        CRect rcFileList;
00127        m_cFileList.GetClientRect(&rcFileList);
00128 
00129        int nColTotal = sizeof(aColData) / sizeof(aColData[0]);
00130        int nWidthRemaining = rcFileList.Width();
00131        
00132        for (int nCol = 0; nCol < nColTotal; nCol++)
00133        {
00134               ColumnData *pData = &aColData[nCol];
00135 
00136               int nColWidth = (rcFileList.Width() * pData->nPercentageWidth) / 100;
00137               if (nCol == nColTotal - 1)
00138               {
00139                      nColWidth = nWidthRemaining;
00140               }
00141               else if (nColWidth > nWidthRemaining)
00142               {
00143                      nColWidth = nWidthRemaining;
00144               }
00145 
00146               m_cFileList.InsertColumn(nCol, pData->sColumnTitle, pData->nFormat, nColWidth);
00147 
00148               nWidthRemaining -= nColWidth;
00149               if (nColWidth <= 0)
00150               {
00151                      break;
00152               }
00153        }
00154 
00155        return TRUE;  // return TRUE  unless you set the focus to a control
00156 }
00157 
00158 
00159 // If you add a minimize button to your dialog, you will need the code below
00160 //  to draw the icon.  For MFC applications using the document/view model,
00161 //  this is automatically done for you by the framework.
00162 
00163 void CIEPatcherDlg::OnPaint() 
00164 {
00165        if (IsIconic())
00166        {
00167               CPaintDC dc(this); // device context for painting
00168 
00169               SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
00170 
00171               // Center icon in client rectangle
00172               int cxIcon = GetSystemMetrics(SM_CXICON);
00173               int cyIcon = GetSystemMetrics(SM_CYICON);
00174               CRect rect;
00175               GetClientRect(&rect);
00176               int x = (rect.Width() - cxIcon + 1) / 2;
00177               int y = (rect.Height() - cyIcon + 1) / 2;
00178 
00179               // Draw the icon
00180               dc.DrawIcon(x, y, m_hIcon);
00181        }
00182        else
00183        {
00184               CDialog::OnPaint();
00185        }
00186 }
00187 
00188 
00189 // The system calls this to obtain the cursor to display while the user drags
00190 //  the minimized window.
00191 HCURSOR CIEPatcherDlg::OnQueryDragIcon()
00192 {
00193        return (HCURSOR) m_hIcon;
00194 }
00195 
00196 
00197 // Automation servers should not exit when a user closes the UI
00198 //  if a controller still holds on to one of its objects.  These
00199 //  message handlers make sure that if the proxy is still in use,
00200 //  then the UI is hidden but the dialog remains around if it
00201 //  is dismissed.
00202 
00203 void CIEPatcherDlg::OnClose() 
00204 {
00205        if (CanExit())
00206               CDialog::OnClose();
00207 }
00208 
00209 
00210 LONG CIEPatcherDlg::OnUpdateFileStatus(WPARAM wParam, LPARAM lParam)
00211 {
00212        PatchStatus ps = (PatchStatus) wParam;
00213        TCHAR *pszFile = (TCHAR *) lParam;
00214        UpdateFileStatus(pszFile, ps);
00215        return 0;
00216 }
00217 
00218 
00219 void CIEPatcherDlg::OnScan() 
00220 {
00221        CScanForFilesDlg dlg;
00222        
00223        if (dlg.DoModal() == IDOK)
00224        {
00225               CWaitCursor wc;
00226 
00227               CFileFind op;
00228               if (op.FindFile(dlg.m_sFilePattern))
00229               {
00230                      op.FindNextFile();
00231                      do {
00232                             if (!op.IsDirectory())
00233                             {
00234                                    AddFileToList(op.GetFilePath());
00235                             }
00236                      } while (op.FindNextFile());
00237                      op.Close();
00238               }
00239        }
00240 }
00241 
00242 
00243 void CIEPatcherDlg::OnPatch() 
00244 {
00245        int nItem = -1;
00246        do {
00247               nItem = m_cFileList.GetNextItem(nItem, LVNI_ALL | LVNI_SELECTED);
00248               if (nItem != -1)
00249               {
00250                      m_cQueuedFileDataList[nItem]->ps = psPatchPending;
00251                      UpdateFileStatus(nItem, m_cQueuedFileDataList[nItem]->sFileName, m_cQueuedFileDataList[nItem]->ps);
00252               }
00253        } while (nItem != -1);
00254 }
00255 
00256 
00257 void CIEPatcherDlg::OnClickFilelist(NMHDR* pNMHDR, LRESULT* pResult) 
00258 {
00259        // Check if files are selected     
00260 
00261        *pResult = 0;
00262 }
00263 
00264 
00266 
00267 
00268 BOOL CIEPatcherDlg::CanExit()
00269 {
00270        // If the proxy object is still around, then the automation
00271        //  controller is still holding on to this application.  Leave
00272        //  the dialog around, but hide its UI.
00273        if (m_pAutoProxy != NULL)
00274        {
00275               ShowWindow(SW_HIDE);
00276               return FALSE;
00277        }
00278 
00279        return TRUE;
00280 }
00281 
00282 
00283 PatchStatus CIEPatcherDlg::ScanFile(const CString &sFileName)
00284 {
00285        char *pszBuffer = NULL;
00286        long nBufferSize = 0;
00287        if (!ReadFileToBuffer(sFileName, &pszBuffer, &nBufferSize))
00288        {
00289               return psFileError;
00290        }
00291 
00292        PatchStatus ps = ScanBuffer(pszBuffer, nBufferSize, FALSE);
00293        delete []pszBuffer;
00294        return ps;
00295 }
00296 
00297 
00298 BOOL CIEPatcherDlg::WriteBufferToFile(const CString &sFileName, char *pszBuffer, long nBufferSize)
00299 {
00300        CString sMessage;
00301        sMessage.Format("Saving patched file \"%s\"", sFileName);
00302        TraceProgress(sMessage);
00303 
00304        FILE *fDest = fopen(sFileName, "wb");
00305        if (fDest == NULL)
00306        {
00307               TraceProgress("Error: Could not open destination file");
00308               return FALSE;
00309        }
00310 
00311        fwrite(pszBuffer, 1, nBufferSize, fDest);
00312        fclose(fDest);
00313        TraceProgress("File saved");
00314 
00315        return TRUE;
00316 }
00317 
00318 
00319 BOOL CIEPatcherDlg::ReadFileToBuffer(const CString &sFileName, char **ppszBuffer, long *pnBufferSize)
00320 {
00321        CString sProcessing;
00322        sProcessing.Format("Processing file \"%s\"", sFileName);
00323        TraceProgress(sProcessing);
00324 
00325        // Allocate a memory buffer to slurp up the whole file
00326        struct _stat srcStat;
00327        _stat(sFileName, &srcStat);
00328 
00329        char *pszBuffer = new char[srcStat.st_size / sizeof(char)];
00330        if (pszBuffer == NULL)
00331        {
00332               TraceProgress("Error: Could not allocate buffer for file");
00333               return FALSE;
00334        }
00335        FILE *fSrc = fopen(sFileName, "rb");
00336        if (fSrc == NULL)
00337        {
00338               TraceProgress("Error: Could not open file");
00339               delete []pszBuffer;
00340               return FALSE;
00341        }
00342        size_t sizeSrc = srcStat.st_size;
00343        size_t sizeRead = 0;
00344 
00345        // Dumb but effective
00346        sizeRead = fread(pszBuffer, 1, sizeSrc, fSrc);
00347        fclose(fSrc);
00348 
00349        if (sizeRead != sizeSrc)
00350        {
00351               TraceProgress("Error: Could not read all of file");
00352               delete []pszBuffer;
00353               return FALSE;
00354        }
00355 
00356        *ppszBuffer = pszBuffer;
00357        *pnBufferSize = sizeRead;
00358 
00359        return TRUE;
00360 }
00361 
00362 
00363 PatchStatus CIEPatcherDlg::ScanBuffer(char *pszBuffer, long nBufferSize, BOOL bApplyPatch)
00364 {
00365        if (nBufferSize < sizeof(CLSID))
00366        {
00367               return psNotPatchable;
00368        }
00369               
00370        TraceProgress("Scanning for IE...");
00371 
00372        BOOL bPatchApplied = FALSE;
00373        PatchStatus ps = psUnknownStatus;
00374 
00375        // Scan through buffer, one byte at a time doing a memcmp
00376        for (size_t i = 0; i < nBufferSize - sizeof(CLSID); i++)
00377        {
00378               if (memcmp(&pszBuffer[i], &CLSID_MozillaBrowser, sizeof(CLSID)) == 0)
00379               {
00380                      TraceProgress("Found CLSID_MozillaBrowser");
00381                      if (ps == psUnknownStatus)
00382                      {
00383                             ps = psAlreadyPatched;
00384                      }
00385               }
00386               else if (memcmp(&pszBuffer[i], &CLSID_WebBrowser_V1, sizeof(CLSID)) == 0)
00387               {
00388                      TraceProgress("Found CLSID_WebBrowser_V1");
00389                      if (ps == psUnknownStatus)
00390                      {
00391                             ps = psPatchable;
00392                      }
00393                      if (bApplyPatch)
00394                      {
00395                             TraceProgress("Patching with CLSID_MozillaBrowser");
00396                             memcpy(&pszBuffer[i], &CLSID_MozillaBrowser, sizeof(CLSID));
00397                             bPatchApplied = TRUE;
00398                      }
00399               }
00400               else if (memcmp(&pszBuffer[i], &CLSID_WebBrowser, sizeof(CLSID)) == 0)
00401               {
00402                      TraceProgress("Found CLSID_WebBrowser");
00403                      if (ps == psUnknownStatus)
00404                      {
00405                             ps = psPatchable;
00406                      }
00407                      if (bApplyPatch)
00408                      {
00409                             TraceProgress("Patching with CLSID_MozillaBrowser");
00410                             memcpy(&pszBuffer[i], &CLSID_MozillaBrowser, sizeof(CLSID));
00411                             TraceProgress("Patching with CLSID_MozillaBrowser");
00412                             bPatchApplied = TRUE;
00413                      }
00414               }
00415               else if (memcmp(&pszBuffer[i], &IID_IWebBrowser, sizeof(CLSID)) == 0)
00416               {
00417                      TraceProgress("Found IID_IWebBrowser");
00418                      if (ps == psUnknownStatus)
00419                      {
00420                             ps = psPatchable;
00421                      }
00422               }
00423               else if (memcmp(&pszBuffer[i], &CLSID_InternetExplorer, sizeof(CLSID)) == 0)
00424               {
00425                      TraceProgress("Warning: Found CLSID_InternetExplorer, patching might not work");
00426                      if (ps == psUnknownStatus)
00427                      {
00428                             ps = psMayBePatchable;
00429                      }
00430               }
00431               else if (memcmp(&pszBuffer[i], &IID_IWebBrowser2, sizeof(CLSID)) == 0)
00432               {
00433                      TraceProgress("Found IID_IWebBrowser2");
00434                      if (ps == psUnknownStatus)
00435                      {
00436                             ps = psPatchable;
00437                      }
00438               }
00439               else if (memcmp(&pszBuffer[i], &IID_IWebBrowserApp, sizeof(CLSID)) == 0)
00440               {
00441                      TraceProgress("Found IID_IWebBrowserApp");
00442                      if (ps == psUnknownStatus)
00443                      {
00444                             ps = psPatchable;
00445                      }
00446               }
00447        }
00448 
00449        if (ps == psUnknownStatus)
00450        {
00451               ps = psNotPatchable;
00452        }
00453        if (bApplyPatch)
00454        {
00455               ps = (bPatchApplied) ? psAlreadyPatched : psNotPatchable;
00456        }
00457 
00458        TraceProgress("Scan completed");
00459 
00460        return ps;
00461 }
00462 
00463 
00464 BOOL CIEPatcherDlg::PatchFile(const CString & sFileFrom, const CString & sFileTo, PatchStatus *pPatchStatus)
00465 {
00466        if (sFileTo.IsEmpty())
00467        {
00468               return FALSE;
00469        }
00470        if (sFileTo == sFileFrom)
00471        {
00472               TraceProgress("Warning: Patching disabled for safety reasons, source and destination names must differ");
00473               return FALSE;
00474        }
00475        
00476        char *pszBuffer = NULL;
00477        long nBufferSize = 0;
00478 
00479        if (!ReadFileToBuffer(sFileFrom, &pszBuffer, &nBufferSize))
00480        {
00481               return FALSE;
00482        }
00483 
00484        // Scan and patch the buffer
00485        *pPatchStatus = ScanBuffer(pszBuffer, nBufferSize, TRUE);
00486        if (*pPatchStatus == psNotPatchable)
00487        {
00488               TraceProgress("Error: Nothing was found to patch");
00489        }
00490        else
00491        {
00492               // Write out the patch file
00493               WriteBufferToFile(sFileTo, pszBuffer, nBufferSize);
00494        }
00495 
00496        delete []pszBuffer;
00497        return FALSE;
00498 }
00499 
00500 
00501 void CIEPatcherDlg::TraceProgress(const CString &sProgress)
00502 {
00503        // TODO
00504 }
00505 
00506 
00507 void CIEPatcherDlg::AddFileToList(const CString & sFile)
00508 {
00509        CSingleLock sl(&m_csQueuedFileDataList, TRUE);
00510 
00511        int nIndex = m_cFileList.GetItemCount();
00512        m_cFileList.InsertItem(nIndex, sFile, IMG_UNKNOWNSTATUS);
00513 
00514        QueuedFileData *pData = new QueuedFileData;
00515        pData->ps = psUnknownStatus;
00516        pData->sFileName = sFile;
00517        pData->sPatchedFileName = sFile;
00518        m_cQueuedFileDataList.Add(pData);
00519 
00520        UpdateFileStatus(nIndex, pData->ps);
00521 }
00522 
00523 
00524 void CIEPatcherDlg::UpdateFileStatus(int nFileIndex, const CString &sFile, PatchStatus ps)
00525 {
00526        CString sStatus;
00527        int nIconStatus = -1;
00528 
00529        switch (ps)
00530        {
00531        case psFileError:
00532               sStatus = _T("File error");
00533               break;
00534 
00535        case psNotPatchable:
00536               sStatus = _T("Nothing to patch");
00537               nIconStatus = IMG_DOESNTCONTAINIE;
00538               break;
00539 
00540        case psPatchable:
00541               sStatus = _T("Patchable");
00542               nIconStatus = IMG_CONTAINSIE;
00543               break;
00544 
00545        case psMayBePatchable:
00546               sStatus = _T("Maybe patchable");
00547               nIconStatus = IMG_CONTAINSIE;
00548               break;
00549 
00550        case psAlreadyPatched:
00551               sStatus = _T("Already patched");
00552               nIconStatus = IMG_CONTAINSMOZILLA;
00553               break;
00554 
00555        case psUnknownStatus:
00556               sStatus = _T("Status pending");
00557               nIconStatus = IMG_UNKNOWNSTATUS;
00558               break;
00559 
00560        case psPatchPending:
00561               sStatus = _T("Patch pending");
00562               break;
00563 
00564        default:
00565               sStatus = _T("*** ERROR ***");
00566               break;
00567        }
00568 
00569        if (nIconStatus != -1)
00570        {
00571               m_cFileList.SetItem(nFileIndex, -1, LVIF_IMAGE, NULL, nIconStatus, 0, 0, 0);
00572        }
00573        m_cFileList.SetItemText(nFileIndex, ITEM_PATCHSTATUS, sStatus);
00574 }
00575 
00576 
00577 void CIEPatcherDlg::UpdateFileStatus(const CString &sFile, PatchStatus ps)
00578 {
00579        CSingleLock sl(&m_csQueuedFileDataList, TRUE);
00580 
00581        for (int n = 0; n < m_cQueuedFileDataList.GetSize(); n++)
00582        {
00583               if (m_cQueuedFileDataList[n]->sFileName == sFile)
00584               {
00585                      UpdateFileStatus(n, sFile, ps);
00586                      m_cQueuedFileDataList[n]->ps = ps;
00587                      return;
00588               }
00589        }
00590 }
00591 
00592 
00593 BOOL CIEPatcherDlg::GetPendingFileToScan(CString & sFileToScan)
00594 {
00595        CSingleLock sl(&m_csQueuedFileDataList, TRUE);
00596 
00597        for (int n = 0; n < m_cQueuedFileDataList.GetSize(); n++)
00598        {
00599               if (m_cQueuedFileDataList[n]->ps == psUnknownStatus)
00600               {
00601                      sFileToScan = m_cQueuedFileDataList[n]->sFileName;
00602                      return TRUE;
00603               }
00604        }
00605        return FALSE;
00606 }
00607 
00608 
00609 BOOL CIEPatcherDlg::GetPendingFileToPatch(CString & sFileToPatch)
00610 {
00611        CSingleLock sl(&m_csQueuedFileDataList, TRUE);
00612 
00613        for (int n = 0; n < m_cQueuedFileDataList.GetSize(); n++)
00614        {
00615               if (m_cQueuedFileDataList[n]->ps == psPatchPending)
00616               {
00617                      sFileToPatch = m_cQueuedFileDataList[n]->sFileName;
00618                      return TRUE;
00619               }
00620        }
00621        return FALSE;
00622 }