乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      如何抓住狡猾的狐貍?(復(fù)合文檔)

       king9413 2013-08-15

      環(huán)境:Windows 98SE/2000,VC++ 6.0,F(xiàn)oxmail 4.1 簡(jiǎn)體中文版

      摘要

      本文旨在介紹 Foxmail 的賬號(hào)存儲(chǔ)機(jī)制,并基于此編寫一個(gè)輔助工具 SmartFox ,實(shí)現(xiàn)閃存“隨身郵”功能。 

      問(wèn)題的出現(xiàn)與分析

      最近我買了一支愛(ài)國(guó)者的經(jīng)典型“迷你王”閃存,自己安裝了 Foxmail ,并在閃存上創(chuàng)建了兩個(gè)賬號(hào)以收發(fā)郵件。但當(dāng)我在另一臺(tái) PC 上使用 Foxmail 時(shí),它卻提示沒(méi)有可用的賬號(hào)。這是怎么回事呢?原來(lái), Foxmail 在創(chuàng)建賬號(hào)時(shí),會(huì)將這個(gè)賬號(hào)所在目錄完整的路徑名記錄下來(lái)。由于閃存在不同的 PC 上獲得的盤符不一定相同,這樣在閃存的盤符改變后, Foxmail 便因無(wú)法定位該目錄而發(fā)生錯(cuò)誤。

      開(kāi)始時(shí),我編輯了一個(gè)批處理文件 Foxmail.BAT 用以啟動(dòng) Foxmail 。其思路是將閃存的根目錄重定向?yàn)?Z: 盤,每次將閃存的當(dāng)前盤符作為參數(shù)傳遞給這個(gè)批處理文件即可。為此我不得不將之前創(chuàng)建的賬號(hào)刪除,在命令行提示符下啟動(dòng)批處理命令,然后在 Z: 盤下創(chuàng)建賬號(hào)。這樣不是太麻煩了嗎?是的!我也曾嘗試過(guò)利用中間文件自動(dòng)進(jìn)行參數(shù)傳遞,但是由于 DOS 的不可重入性而不能保證每次都成功運(yùn)行。因此我開(kāi)始剖析 Foxmail 的賬號(hào)存儲(chǔ)機(jī)制。 

      Foxmail 的賬號(hào)存儲(chǔ)機(jī)制

      Foxmail 將每個(gè)賬號(hào)的最基本信息(賬號(hào)名稱、存儲(chǔ)目錄)存放在安裝目錄下的文件Accounts.CFG 中。在每個(gè)賬號(hào)的目錄中則利用文件 Account.STG 存儲(chǔ)該賬號(hào)的其他信息。

      Accounts.CFG 是一個(gè)復(fù)合文檔,它包括一個(gè) Ver30 存儲(chǔ)( Storage )。在 Ver30 存儲(chǔ)下有一個(gè)accounts.cfg 流( Stream )。你可以使用 Visual Studio 6.0 提供的 DocFile 閱讀器打開(kāi)它。關(guān)于存儲(chǔ)和流的更多知識(shí),請(qǐng)參閱 MSDN: [Platform SDK] Structured Storage 。

      經(jīng)過(guò)分析,我得到了 Foxmail 的賬號(hào)存儲(chǔ)機(jī)制。如下即為 accounts.cfg 流的 C 語(yǔ)言描述結(jié)構(gòu)(表中均為十六進(jìn)制):

      偏移地址

      變量名

      描述

      00000000

      BYTE Reserved [40];

      文件頭。在 00000007 處存儲(chǔ)了曾創(chuàng)建賬號(hào)的個(gè)數(shù)。

      00000040

      DWORD cAccount;

      現(xiàn)有的賬號(hào)數(shù)。

      第一個(gè)賬號(hào)信息塊( AIB , Account Information Block )的開(kāi)始。

      00000044

      DWORD idxAccount;

      該賬號(hào)的順序編號(hào)。


      DWORD lenACTName;

      賬號(hào)名字符串的長(zhǎng)度。


      String strACTName [lenACTName];

      賬號(hào)名字符串。


      DWORD lenACTPath;

      賬號(hào)所在目錄的字符串長(zhǎng)度。


      String strACTPath [lenACTPath];

      賬號(hào)所在目錄的全路徑名。


      BYTE Reserved [18];

      0x18 個(gè) 00 (可能用以存儲(chǔ)密碼)。

      下一個(gè) AIB

      注意:所有的字符串長(zhǎng)度均不包括結(jié)尾符在內(nèi)。

      編程實(shí)現(xiàn)

      現(xiàn)在我們就可以開(kāi)始編寫 Foxmail 的輔助工具 SmartFox 了。 重要約定:

      1.所有賬號(hào)的目錄均在閃存上!

      2.SmartFox 在 Foxmail 安裝目錄下工作!

      程序的流程:獲得閃存的當(dāng)前盤符,打開(kāi) accounts.cfg 流,修改所有賬號(hào)的目錄盤符為閃存當(dāng)前盤符,啟動(dòng) Foxmail 。我認(rèn)為沒(méi)有必要在 Foxmail 退出后恢復(fù) accounts.cfg 的內(nèi)容,你認(rèn)為呢?

      SmartFox 是一個(gè)利用 MFC 實(shí)現(xiàn)的基于對(duì)話框的應(yīng)用程序,靜態(tài)鏈接 MFC 的動(dòng)態(tài)鏈接庫(kù)。

      運(yùn)行界面如下,單擊左鍵啟動(dòng) Foxmail ,單擊右鍵退出。

      (一)對(duì)程序中使用的 API 的介紹,更詳細(xì)的內(nèi)容請(qǐng)參見(jiàn) MSDN :

      1. 獲得當(dāng)前目錄的全路徑名 (Win API)

      1.DWORD GetCurrentDirectory(
      2.  DWORD nBufferLength,  // 保存目錄名的緩沖區(qū)大小
      3.  LPTSTR lpBuffer       // 指向緩沖區(qū)的指針
      4.);

      2. 打開(kāi)一個(gè)復(fù)合文檔 (Win API)

      1.HRESULT StgOpenStorage(
      2.  const WCHAR *pwcsName,    //復(fù)合文檔的文件名
      3.  IStorage *pstgPriority,   //先前已打開(kāi)的根存儲(chǔ)的指針
      4.  DWORD grfMode,            //訪問(wèn)模式
      5.  SNB snbExclude,           //指向一個(gè)SNB結(jié)構(gòu)的指針,以確定哪些元素將被排除訪問(wèn)
      6.  DWORD reserved,           //保留
      7.  IStorage **ppstgOpen      //接受返回的IStorage接口指針
      8.);

      3. 打開(kāi)一個(gè)子存儲(chǔ)或流 (IStorage API)

      1.HRESULT OpenStorage(
      2.  const WCHAR *pwcsName,   //要打開(kāi)的存儲(chǔ)的名字
      3.  IStorage *pstgPriority,  //該參數(shù)一定為NULL值
      4.  DWORD grfMode,           //訪問(wèn)模式
      5.  SNB snbExclude,          //該參數(shù)一定為NULL值
      6.  DWORD reserved,          //保留
      7.  IStorage **ppstg         //接受返回的IStorage接口指針
      8.);

      OpenStream 的參數(shù)與 OpenStorage 的差不多,只是返回的是一個(gè) IStream 指針。

      4. 取得流的大小,移動(dòng)流的讀寫指針,從流讀寫數(shù)據(jù) (IStream API)

      01.HRESULT Stat(
      02.  STATSTG *pstatstg,  //指向一個(gè)STATSTG結(jié)構(gòu)的指針,STATSTG的cb域即為流的大小。
      03.  DWORD grfStatFlag   //決定是否要在STATSTG中返回某些值的標(biāo)志
      04.);
      05. 
      06. 
      07.HRESULT Seek(
      08.  LARGE_INTEGER dlibMove,          //相對(duì)于dwOrigin的偏址
      09.  DWORD dwOrigin,                  //起始位置
      10.  ULARGE_INTEGER *plibNewPosition  //接受指向新位置的指針
      11.);
      12. 
      13. 
      14.HRESULT Read(
      15.  void *pv,  //指向數(shù)據(jù)緩沖區(qū)的指針
      16.  ULONG cb,  //要讀的字節(jié)數(shù)
      17.  ULONG *pcbRead //實(shí)際讀出的字節(jié)數(shù)
      18.);Write 的參數(shù)與 Read 的一樣。

      5. 加載外部程序 (Win API)

      01.HINSTANCE ShellExecute(
      02.    HWND hwnd,  //父窗口句柄
      03.    LPCTSTR lpVerb, //要執(zhí)行的動(dòng)作:edit,explore,find,open,print,properties
      04.    LPCTSTR lpFile,     //文件名
      05.    LPCTSTR lpParameters,   //傳遞的命令行參數(shù)
      06.    LPCTSTR lpDirectory,        //缺省工作目錄
      07.    INT nShowCmd    //窗口的顯示模式
      08.);
      09. 
      10.UINT WinExec(
      11.  LPCSTR lpCmdLine,  // 命令的字符串
      12.  UINT uCmdShow      //窗口的顯示模式
      13.);

      6. 此外,我在程序中使用了 COM 庫(kù)的缺省 IMalloc 接口管理緩沖區(qū)

      1.HRESULT CoGetMalloc(      //這是一個(gè)Win API
      2.  DWORD dwMemContext,  //決定該內(nèi)存塊是否被共享的標(biāo)志
      3.  LPMALLOC * ppMalloc  //接受返回的內(nèi)存分配器的IMalloc接口指針
      4.);

      IMalloc::Alloc() ,IMalloc::Free() 的使用與 C 語(yǔ)言中的 alloc() 和 free() 類似,在此不再贅述。

      (二)實(shí)現(xiàn)步驟:

      在 StdAfx.h 中加入以下的頭文件:objidl.h ,afxole.h ,afxpriv.h ,afxtempl.h

      1.在 CSmartFoxApp::InitInstance() 中加入: ::CoInitialize(NULL);

      2.為 CSmartFoxDlg 添加如下數(shù)據(jù)成員:

      1.IStorage * m_pRootStg; // 根存儲(chǔ)的接口指針
      2.IStorage * m_pVer30Stg; //Ver30 存儲(chǔ)的接口指針
      3.IStream * m_pStream; //accounts.cfg 流的接口指針
      4.char * m_pBuffer; // 用以讀寫 accounts.cfg 流的緩沖區(qū)指針
      5.char m_Driver; // 閃存的當(dāng)前盤符
      6.CArray  m_aryPosition; // 保存流中賬號(hào)目錄所在偏移地址的數(shù)組   

      3.利用 Class Wizard 為 CSmartFoxDlg 添加或修改下列函數(shù):

      001.BOOL CSmartFoxDlg::OnInitDialog()
      002.    {
      003.    CDialog::OnInitDialog();
      004.    SetIcon(m_hIcon, TRUE);         // Set big icon
      005.    SetIcon(m_hIcon, FALSE);        // Set small icon
      006.    try
      007.        {
      008.        m_Driver = GetDriver();
      009.        m_pStream = GetIStream();
      010.        m_pBuffer = GetBuffer(m_pStream);
      011.        GetAccountInfo(m_pStream, m_pBuffer);
      012.        }
      013.    catch (char * sMsg)
      014.        {
      015.        AfxMessageBox(sMsg,MB_OK,NULL);
      016.        ClearUp();
      017.        }
      018.    return TRUE;  // return TRUE  unless you set the focus to a control
      019.    }
      020. 
      021.void CSmartFoxDlg::OnClickEmail()
      022.{
      023.    ShellExecute(this->m_hWnd,
      024.               "open",
      025.               "mailto: korby@sohu.com?subject=Re: 關(guān)于SmartFox的意見(jiàn)",  
      026.               NULL,
      027.               NULL,
      028.               SW_SHOWNORMAL);
      029.    ClearUp();
      030.}
      031. 
      032.void CSmartFoxDlg::OnLButtonDown(UINT nFlags, CPoint point)
      033.    {
      034.    // I will modify the driver letter of accounts here, and startup FoxMail.
      035.    try
      036.        {
      037.        ModifyAccountDriver(m_pStream, m_pBuffer);
      038.        ClearUp();
      039.        if (WinExec("FoxMail.EXE", SW_SHOWNORMAL) < 31) throw "加載FoxMail.EXE失敗";
      040.        }
      041.    catch (char * sMsg)
      042.        {
      043.        AfxMessageBox(sMsg,MB_OK,NULL);
      044.        }
      045.    }
      046. 
      047.void CSmartFoxDlg::OnRButtonDown(UINT nFlags, CPoint point)
      048.{
      049.    // If I don''''t do this, the message will be transferred to window behind.
      050.    SetCapture();
      051.}
      052. 
      053.void CSmartFoxDlg::OnRButtonUp(UINT nFlags, CPoint point)
      054.{
      055.    ::ReleaseCapture();
      056.    ClearUp();
      058. 
      059.void CSmartFoxDlg::ClearUp()
      060.    {
      061.    if (m_pRootStg  != NULL) m_pRootStg->Release();
      062.    if (m_pVer30Stg != NULL) m_pVer30Stg->Release();
      063.    if (m_pStream   != NULL) m_pStream->Release();
      064.    if (m_pBuffer   != NULL)
      065.        {
      066.        IMalloc *  pMalloc;
      067.        ::CoGetMalloc(MEMCTX_TASK, &pMalloc);
      068.        pMalloc->Free(m_pBuffer);
      069.        pMalloc->Release();
      070.        }
      071.    ::CoUninitialize();
      072.    OnCancel();
      073.    }
      074. 
      075.// All codes below find out driver letter and directories of each account.
      076.char CSmartFoxDlg::GetDriver()
      077.    {
      078.    char sCurDir[256];
      079.    int ret = ::GetCurrentDirectory(256, sCurDir);
      080.    if (ret == NULL) throw  "取當(dāng)前驅(qū)動(dòng)器盤符時(shí)失敗";
      081.    else  return sCurDir[0];
      082.    }
      083. 
      084.IStream * CSmartFoxDlg::GetIStream()
      085.    {
      086.    USES_CONVERSION;
      087.    // Get interface Storage pointer of Accounts.CFG
      088.    IStream *  pStream;
      089.    HRESULT    hr;
      090.    hr = ::StgOpenStorage(T2COLE("Accounts.CFG"),
      091.                 NULL,
      092.                 STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
      093.                 NULL,
      094.                 0,
      095.                 &m_pRootStg);
      096.    if (hr != S_OK) throw "打開(kāi)Accounts.CFG文件時(shí)失敗";
      097.     
      098.    hr = m_pRootStg->OpenStorage(T2COLE("Ver30"),
      099.                    NULL,
      100.                    STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
      101.                    NULL,
      102.                    0,
      103.                    &m_pVer30Stg);
      104.    if (hr != S_OK) throw "打開(kāi)Ver30存儲(chǔ)時(shí)失敗";
      105.     
      106.    hr = m_pVer30Stg->OpenStream(T2COLE("accounts.cfg"),
      107.                    NULL,
      108.                    STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
      109.                    NULL,
      110.                    &pStream);
      111.    if (hr != S_OK) throw "打開(kāi)accounts.cfg流時(shí)失敗";
      112.     
      113.    return pStream;
      114.    }
      115. 
      116.char * CSmartFoxDlg::GetBuffer(IStream * pStream)
      117.    {
      118.    STATSTG    StatStg;
      119.    IMalloc *  pMalloc;
      120.    char *     pBuffer;
      121.    HRESULT    hr;
      122.     
      123.    hr = pStream->Stat(&StatStg, NULL);
      124.    if (hr != S_OK) throw "讀取accounts.cfg流的大小時(shí)失敗";
      125.     
      126.    hr = ::CoGetMalloc(MEMCTX_TASK, &pMalloc);
      127.    if (hr != S_OK) throw "獲取COM庫(kù)的IMalloc接口指針時(shí)失敗";
      128.     
      129.    pBuffer = (char *)pMalloc->Alloc(ULONG(StatStg.cbSize.QuadPart));
      130.    if (pBuffer == NULL) throw "申請(qǐng)緩沖區(qū)時(shí)失敗";
      131.             
      132.    pMalloc->Release();
      133.    return pBuffer;
      134.    }
      135. 
      136.void CSmartFoxDlg::GetAccountInfo(IStream * pStream, char * pBuffer)
      137.    {
      138.    // I will find out names and directories of each account.
      139.    STATSTG    StatStg;
      140.    ULONG      cbReaded;
      141.    HRESULT    hr;
      142.     
      143.    char *     p = pBuffer;
      144.    DWORD      cAccount;
      145.    DWORD      len;
      146.    CString    name;    // Gets the name of account.
      147.    CString    path;    // Gets the path of account.
      148.     
      149.    CString    strEdit; //Displays text in edit control.
      150.    CEdit *    pEdit = (CEdit *) GetDlgItem(IDC_EDIT);
      151.    strEdit.Format("閃存當(dāng)前為%c:盤, 現(xiàn)存賬號(hào)及其目錄: \r\n", m_Driver);
      152.     
      153.    hr = pStream->Stat(&StatStg, NULL);
      154.    if (hr != S_OK) throw "讀取accounts.cfg流的大小時(shí)失敗";
      155.     
      156.    hr = pStream->Read(pBuffer, ULONG(StatStg.cbSize.QuadPart), &cbReaded);
      157.    if (hr != S_OK) throw "讀取accounts.cfg流的內(nèi)容時(shí)失敗";
      158.     
      159.    p += 0x40;
      160.    cAccount = (*p);    //Count of accounts.
      161.    p += 0x4;
      162. 
      163.    for (DWORD i = 1; i <= cAccount; i++)
      164.        {
      165.        // Value of (*p) is index of account.
      166.        if (DWORD(*p) != i) throw "accounts.cfg流損壞";
      167.        p += 0x4;   //Skips the index number.
      168.        len = DWORD(*p);    //Gets length of name.
      169.        p += 0x4;   //Skips the length number. The string does not include NULL.
      170.         
      171.        name.Empty();
      172.        path.Empty();
      173.         
      174.        for (DWORD n = 0; n < len; n++, p++) name += char (*p); // Gets account name.
      175.         
      176.        len = DWORD(*p); // Gets length of directory.
      177.        p += 4; // Skips the length number.
      178.                 
      179.        m_aryPosition.Add(p-pBuffer);  //Stores offset into array.
      180.         
      181.        for (n = 0; n< len; n++, p++) path += char (*p); //Gets account path.
      182. 
      183.        strEdit += name+"\t"+path+"\r\n";
      184.         
      185.        p += 0x18; //Skips 0x18 Nulls.
      186.        }
      187.    pEdit->SetWindowText(strEdit);
      188.    }
      189. 
      190.void CSmartFoxDlg::ModifyAccountDriver(IStream *pStream, char * pBuffer)
      191.    {
      192.    STATSTG    StatStg;
      193.    ULONG      cbWrited;
      194.    HRESULT    hr;
      195. 
      196.    LARGE_INTEGER  MovOffset;
      197.    ULARGE_INTEGER NewPosition;
      198.     
      199.    char *     p;
      200. 
      201.    for (int i = 0; i< m_aryPosition.GetSize(); i++)
      202.        {
      203.        p = pBuffer + m_aryPosition.GetAt(i);
      204.        (*p) = m_Driver;
      205.        }
      206. 
      207.    hr = pStream->Stat(&StatStg, NULL);
      208.    if (hr != S_OK) throw "讀取accounts.cfg流的大小時(shí)失敗";
      209. 
      210.    MovOffset.QuadPart = 0;
      211.    hr = pStream->Seek(MovOffset, 0, &NewPosition);
      212.    if (hr != S_OK) throw "移動(dòng)accounts.cfg流的讀寫指針時(shí)失敗";
      213.     
      214.    pStream->Write(pBuffer, ULONG(StatStg.cbSize.QuadPart), &cbWrited);
      215.    if (hr != S_OK) throw "向accounts.cfg流寫入數(shù)據(jù)時(shí)失敗";
      216.    }

      編譯鏈接生成 SmartFox.EXE 后,將其拷貝到 Foxmail 在閃存上的安裝目錄。利用 SmartFox.EXE 運(yùn)行 Foxmail 就可以實(shí)現(xiàn)“隨身郵”的功能了!

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多