//-------------------------------------------------------------------------- // OE4Imp.cpp //-------------------------------------------------------------------------- #include "pch.hxx" #include "oe4imp.h" #include "structs.h" #include "migerror.h" #include #include #include #include "dllmain.h" #include "resource.h" //-------------------------------------------------------------------------- // Constants //-------------------------------------------------------------------------- static const char c_szMail[] = "mail"; static const char c_szFoldersNch[] = "folders.nch"; static const char c_szEmpty[] = ""; // -------------------------------------------------------------------------------- // MSG_xxx flags // -------------------------------------------------------------------------------- #define MSG_DELETED 0x0001 #define MSG_UNREAD 0x0002 #define MSG_SUBMITTED 0x0004 #define MSG_UNSENT 0x0008 #define MSG_RECEIVED 0x0010 #define MSG_NEWSMSG 0x0020 #define MSG_NOSECUI 0x0040 #define MSG_VOICEMAIL 0x0080 #define MSG_REPLIED 0x0100 #define MSG_FORWARDED 0x0200 #define MSG_RCPTSENT 0x0400 #define MSG_FLAGGED 0x0800 #define MSG_LAST 0x0200 #define MSG_EXTERNAL_FLAGS 0x00fe #define MSG_FLAGS 0x000f //-------------------------------------------------------------------------- // COE4Import_CreateInstance //-------------------------------------------------------------------------- COE4Import_CreateInstance(IUnknown *pUnkOuter, IUnknown **ppUnknown) { // Trace TraceCall("COE4Import_CreateInstance"); // Initialize *ppUnknown = NULL; // Create me COE4Import *pNew = new COE4Import(); if (NULL == pNew) return TraceResult(E_OUTOFMEMORY); // Cast to unknown *ppUnknown = SAFECAST(pNew, IMailImport *); // Done return(S_OK); } // -------------------------------------------------------------------------------- // GetRecordBlock // -------------------------------------------------------------------------------- HRESULT GetRecordBlock(LPMEMORYFILE pFile, DWORD faRecord, LPRECORDBLOCKV5B1 *ppRecord, LPBYTE *ppbData, BOOL *pfContinue) { // Locals HRESULT hr=S_OK; // Trace TraceCall("GetRecordBlock"); // Bad Length if (faRecord + sizeof(RECORDBLOCKV5B1) > pFile->cbSize) { *pfContinue = TRUE; hr = TraceResult(MIGRATE_E_OUTOFRANGEADDRESS); goto exit; } // Cast the Record (*ppRecord) = (LPRECORDBLOCKV5B1)((LPBYTE)pFile->pView + faRecord); // Invalid Record Signature if (faRecord != (*ppRecord)->faRecord) { *pfContinue = TRUE; hr = TraceResult(MIGRATE_E_BADRECORDSIGNATURE); goto exit; } // Bad Length if (faRecord + (*ppRecord)->cbRecord > pFile->cbSize) { *pfContinue = TRUE; hr = TraceResult(MIGRATE_E_OUTOFRANGEADDRESS); goto exit; } // Set pbData *ppbData = (LPBYTE)((LPBYTE)(*ppRecord) + sizeof(RECORDBLOCKV5B1)); exit: // Done return hr; } //-------------------------------------------------------------------------- // COE4Import::COE4Import //-------------------------------------------------------------------------- COE4Import::COE4Import(void) { TraceCall("COE4Import::COE4Import"); m_cRef = 1; m_pList = NULL; *m_szDirectory = '\0'; m_cFolders = 0; m_prgFolder = NULL; } //-------------------------------------------------------------------------- // COE4Import::~COE4Import //-------------------------------------------------------------------------- COE4Import::~COE4Import(void) { TraceCall("COE4Import::~COE4Import"); _Cleanup(); } //-------------------------------------------------------------------------- // COE4Import::_FreeFolderList //-------------------------------------------------------------------------- void COE4Import::_Cleanup(void) { _FreeFolderList(m_pList); m_pList = NULL; SafeMemFree(m_prgFolder); m_cFolders = 0; } //-------------------------------------------------------------------------- // COE4Import::_FreeFolderList //-------------------------------------------------------------------------- void COE4Import::_FreeFolderList(IMPFOLDERNODE *pNode) { // Locals IMPFOLDERNODE *pNext; IMPFOLDERNODE *pCurrent=pNode; // Loop while (pCurrent) { // Save next pNext = pCurrent->pnext; // Free Children ? if (pCurrent->pchild) { // Free _FreeFolderList(pCurrent->pchild); } // Free szName g_pMalloc->Free(pCurrent->szName); // Free pCurrent g_pMalloc->Free(pCurrent); // Set Current pCurrent = pNext; } } //-------------------------------------------------------------------------- // COE4Import::QueryInterface //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::QueryInterface(REFIID riid, LPVOID *ppv) { // Locals HRESULT hr=S_OK; // Stack TraceCall("COE4Import::QueryInterface"); // Find IID if (IID_IUnknown == riid) *ppv = (IUnknown *)this; else if (IID_IMailImport == riid) *ppv = (IMailImport *)this; else { *ppv = NULL; hr = TraceResult(E_NOINTERFACE); goto exit; } // AddRef It ((IUnknown *)*ppv)->AddRef(); exit: // Done return(hr); } //-------------------------------------------------------------------------- // COE4Import::AddRef //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COE4Import::AddRef(void) { TraceCall("COE4Import::AddRef"); return InterlockedIncrement(&m_cRef); } //-------------------------------------------------------------------------- // COE4Import::Release //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COE4Import::Release(void) { TraceCall("COE4Import::Release"); LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return (ULONG)cRef; } //-------------------------------------------------------------------------- // COE4Import::InitializeImport //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::InitializeImport(HWND hwnd) { // Let Importer Ask for the Directory return(S_OK); } //-------------------------------------------------------------------------- // COE4Import::GetDirectory //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::GetDirectory(LPSTR pszDir, UINT cch) { // Locals HKEY hKey=NULL; DWORD dwType; DWORD cb=cch; // Try to query the OE4 store root... if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Outlook Express", 0, KEY_READ, &hKey)) { // Try to read the value if (ERROR_SUCCESS == RegQueryValueEx(hKey, "Store Root", NULL, &dwType, (LPBYTE)pszDir, &cb)) goto exit; } if (hKey) { RegCloseKey(hKey); hKey = NULL; } // Try V1 if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Internet Mail and News", 0, KEY_READ, &hKey)) { // Query the Store Root if (ERROR_SUCCESS == RegQueryValueEx(hKey, "Store Root", NULL, &dwType, (LPBYTE)pszDir, &cb)) goto exit; } // Null It Out *pszDir = '\0'; exit: // Close the Key if (hKey) RegCloseKey(hKey); // Done return(S_OK); } //-------------------------------------------------------------------------- // COE4Import::SetDirectory //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::SetDirectory(LPSTR pszDir) { // Trace TraceCall("COE4Import::SetDirectory"); // Save the Directory StrCpyN(m_szDirectory, pszDir, ARRAYSIZE(m_szDirectory)); // Done return(S_OK); } //-------------------------------------------------------------------------- // COE4Import::_EnumerateV1Folders //-------------------------------------------------------------------------- HRESULT COE4Import::_EnumerateV1Folders(void) { // Locals HRESULT hr=S_OK; CHAR szRes[255]; CHAR szMbxPath[MAX_PATH + MAX_PATH]; CHAR szSearch[MAX_PATH + MAX_PATH]; WIN32_FIND_DATA fd; HANDLE hFind=INVALID_HANDLE_VALUE; DWORD cAllocated=0; LPFLDINFO pFolder; DWORD i; MEMORYFILE MbxFile={0}; LPMBXFILEHEADER pMbxHeader; // Trace TraceCall("COE4Import::_EnumerateV1Folders"); // Do we have a sub dir wnsprintf(szSearch, ARRAYSIZE(szSearch), "%s\\*.mbx", m_szDirectory); // Find first file hFind = FindFirstFile(szSearch, &fd); // Did we find something if (INVALID_HANDLE_VALUE == hFind) goto exit; // Loop for ever while(1) { // If this is not a directory if (FALSE == ISFLAGSET(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { // Open the file IF_FAILEXIT(hr = MakeFilePath(m_szDirectory, fd.cFileName, c_szEmpty, szMbxPath, ARRAYSIZE(szMbxPath))); // Open the memory file if (SUCCEEDED(OpenMemoryFile(szMbxPath, &MbxFile))) { // Allocate if (m_cFolders + 1 > cAllocated) { // Reallocate IF_FAILEXIT(hr = HrRealloc((LPVOID *)&m_prgFolder, (cAllocated + 10) * sizeof(FLDINFO))); // Set cAllocated cAllocated += 10; } // Readability pFolder = &m_prgFolder[m_cFolders]; // Zero this node ZeroMemory(pFolder, sizeof(FLDINFO)); // Copy the filename StrCpyN(pFolder->szFile, fd.cFileName, ARRAYSIZE(pFolder->szFile)); // Strip the Extension Off PathRemoveExtensionA(pFolder->szFile); // Copy the folder name StrCpyN(pFolder->szFolder, pFolder->szFile, ARRAYSIZE(pFolder->szFolder)); // Set Special pFolder->tySpecial = (FOLDER_TYPE_NORMAL - 1); // Loop through special folder for (i=FOLDER_TYPE_INBOX; iszFolder, szRes) == 0) { // Copy the Folder Name pFolder->tySpecial = (i - 1); // Done break; } } // Read the Mbx File Header pMbxHeader = (LPMBXFILEHEADER)(MbxFile.pView); // Get the message Count so progress will work nicely pFolder->cMessages = pMbxHeader->cMsg; // Close the memory file CloseMemoryFile(&MbxFile); // Increment m_cFolders m_cFolders++; } } // Find the Next File if (!FindNextFile(hFind, &fd)) break; } exit: // Cleanup if (hFind) FindClose(hFind); CloseMemoryFile(&MbxFile); // Done return(hr); } //-------------------------------------------------------------------------- // COE4Import::EnumerateFolders //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::EnumerateFolders(DWORD_PTR dwCookie, IEnumFOLDERS **ppEnum) { // Locals HRESULT hr=S_OK; DWORD cchDir; MEMORYFILE File={0}; LPTABLEHEADERV5B1 pHeader; LPBYTE pbData; DWORD faRecord; LPFLDINFO pFolder; LPRECORDBLOCKV5B1 pRecord; BOOL fContinue; COE4EnumFolders *pEnum=NULL; CHAR szFilePath[MAX_PATH + MAX_PATH]; IMPFOLDERNODE *pList; IMPFOLDERNODE *pNode=(IMPFOLDERNODE *)dwCookie; // Trace TraceCall("COE4Import::EnumerateFolders"); // Invalid Args Assert(ppEnum); // No folders yet ? if (COOKIE_ROOT == dwCookie) { // Reset... _Cleanup(); // Append \Mail onto m_szDirectory cchDir = lstrlen(m_szDirectory); // Is there enough room if (cchDir + lstrlen(c_szMail) + 2 >= ARRAYSIZE(m_szDirectory)) { hr = TraceResult(E_FAIL); goto exit; } // Need a Wack ? PathAddBackslash(m_szDirectory); // Append \\mail StrCatBuff(m_szDirectory, c_szMail, ARRAYSIZE(m_szDirectory)); // Make Path to folders.nch file IF_FAILEXIT(hr = MakeFilePath(m_szDirectory, c_szFoldersNch, c_szEmpty, szFilePath, ARRAYSIZE(szFilePath))); // If the folders.nch file doesn't exist, just try to enumerate the if (FALSE == PathFileExists(szFilePath)) { // EnumerateV1Folders IF_FAILEXIT(hr = _EnumerateV1Folders()); } // Otherwise, crack the folders.nch file else { // Open the Folders file IF_FAILEXIT(hr = OpenMemoryFile(szFilePath, &File)); // Validate Version pHeader = (LPTABLEHEADERV5B1)File.pView; // Check the Signature... if (File.cbSize < sizeof(TABLEHEADERV5B1) || OBJECTDB_SIGNATURE != pHeader->dwSignature || OBJECTDB_VERSION_PRE_V5 != pHeader->wMajorVersion) { hr = TraceResult(E_FAIL); goto exit; } // Allocate Folder Array IF_NULLEXIT(m_prgFolder = (LPFLDINFO)ZeroAllocate(sizeof(FLDINFO) * pHeader->cRecords)); // Initialize faRecord to start faRecord = pHeader->faFirstRecord; // While we have a record while(faRecord) { // Readability pFolder = &m_prgFolder[m_cFolders]; // Get the Record IF_FAILEXIT(hr = GetRecordBlock(&File, faRecord, &pRecord, &pbData, &fContinue)); // DWORD - hFolder CopyMemory(&pFolder->idFolder, pbData, sizeof(pFolder->idFolder)); pbData += sizeof(pFolder->idFolder); // CHAR(MAX_FOLDER_NAME) - szFolder CopyMemory(pFolder->szFolder, pbData, sizeof(pFolder->szFolder)); pbData += sizeof(pFolder->szFolder); // CHAR(260) - szFile CopyMemory(pFolder->szFile, pbData, sizeof(pFolder->szFile)); pbData += sizeof(pFolder->szFile); // DWORD - idParent CopyMemory(&pFolder->idParent, pbData, sizeof(pFolder->idParent)); pbData += sizeof(pFolder->idParent); // DWORD - idChild CopyMemory(&pFolder->idChild, pbData, sizeof(pFolder->idChild)); pbData += sizeof(pFolder->idChild); // DWORD - idSibling CopyMemory(&pFolder->idSibling, pbData, sizeof(pFolder->idSibling)); pbData += sizeof(pFolder->idSibling); // DWORD - tySpecial CopyMemory(&pFolder->tySpecial, pbData, sizeof(pFolder->tySpecial)); pbData += sizeof(pFolder->tySpecial); // DWORD - cChildren CopyMemory(&pFolder->cChildren, pbData, sizeof(pFolder->cChildren)); pbData += sizeof(pFolder->cChildren); // DWORD - cMessages CopyMemory(&pFolder->cMessages, pbData, sizeof(pFolder->cMessages)); pbData += sizeof(pFolder->cMessages); // DWORD - cUnread CopyMemory(&pFolder->cUnread, pbData, sizeof(pFolder->cUnread)); pbData += sizeof(pFolder->cUnread); // DWORD - cbTotal CopyMemory(&pFolder->cbTotal, pbData, sizeof(pFolder->cbTotal)); pbData += sizeof(pFolder->cbTotal); // DWORD - cbUsed CopyMemory(&pFolder->cbUsed, pbData, sizeof(pFolder->cbUsed)); pbData += sizeof(pFolder->cbUsed); // DWORD - bHierarchy CopyMemory(&pFolder->bHierarchy, pbData, sizeof(pFolder->bHierarchy)); pbData += sizeof(pFolder->bHierarchy); // DWORD - dwImapFlags CopyMemory(&pFolder->dwImapFlags, pbData, sizeof(pFolder->dwImapFlags)); pbData += sizeof(DWORD); // BLOB - bListStamp CopyMemory(&pFolder->bListStamp, pbData, sizeof(pFolder->bListStamp)); pbData += sizeof(BYTE); // DWORD - bReserved[3] pbData += (3 * sizeof(BYTE)); // DWORD - rgbReserved pbData += 40; // Increment Count m_cFolders++; // Goto the Next Record faRecord = pRecord->faNext; } } // Build Import Folder Hierarchy IF_FAILEXIT(hr = _BuildFolderHierarchy(0, 0, NULL, m_cFolders, m_prgFolder)); } // Not Folders ? else if (NULL == m_prgFolder) { hr = TraceResult(E_FAIL); goto exit; } // What should I if (dwCookie == COOKIE_ROOT) pList = m_pList; else pList = pNode->pchild; // Create Folder Enumerator IF_NULLEXIT(pEnum = new COE4EnumFolders(pList)); // Return Enumerator *ppEnum = (IEnumFOLDERS *)pEnum; // Don't Free pEnum = NULL; exit: // Cleanup SafeRelease(pEnum); CloseMemoryFile(&File); // Done return(hr); } //-------------------------------------------------------------------------- // COE4Import::_BuildFolderHierarchy //-------------------------------------------------------------------------- HRESULT COE4Import::_BuildFolderHierarchy(DWORD cDepth, DWORD idParent, IMPFOLDERNODE *pParent, DWORD cFolders, LPFLDINFO prgFolder) { // Locals HRESULT hr=S_OK; DWORD i; IMPFOLDERNODE *pPrevious=NULL; IMPFOLDERNODE *pNode; // Trace TraceCall("COE4Import::_BuildFolderHierarchy"); // Walk through prgFolder and find items with parent of idParent for (i=0; ipparent = pParent; // Set Depth pNode->depth = cDepth; // Copy name IF_NULLEXIT(pNode->szName = PszDupA(prgFolder[i].szFolder)); // Count of Messages pNode->cMsg = prgFolder[i].cMessages; // Set Type pNode->type = (IMPORTFOLDERTYPE)(prgFolder[i].tySpecial + 1); // Set lParam pNode->lparam = i; // Link pNode into List if (pPrevious) pPrevious->pnext = pNode; else if (pParent) pParent->pchild = pNode; else { Assert(NULL == m_pList); m_pList = pNode; } // Set pPrevious pPrevious = pNode; // Has Children ? if (prgFolder[i].cChildren) { // Enumerate Children IF_FAILEXIT(hr = _BuildFolderHierarchy(cDepth + 1, prgFolder[i].idFolder, pNode, cFolders, prgFolder)); } } } exit: // Done return(hr); } //-------------------------------------------------------------------------- // COE4Import::ImportFolder //-------------------------------------------------------------------------- STDMETHODIMP COE4Import::ImportFolder(DWORD_PTR dwCookie, IFolderImport *pImport) { // Locals HRESULT hr=S_OK; CHAR szIdxPath[MAX_PATH + MAX_PATH]; CHAR szMbxPath[MAX_PATH + MAX_PATH]; MEMORYFILE IdxFile={0}; MEMORYFILE MbxFile={0}; LPBYTE pbStream; LPMBXFILEHEADER pMbxHeader; LPIDXFILEHEADER pIdxHeader; DWORD faIdxRead; LPIDXMESSAGEHEADER pIdxMessage; LPMBXMESSAGEHEADER pMbxMessage; DWORD cMessages=0; DWORD dwMsgState; DWORD i; DWORD cb; CByteStream *pStream=NULL; IMPFOLDERNODE *pNode=(IMPFOLDERNODE *)dwCookie; LPFLDINFO pFolder; // Trace TraceCall("COE4Import::ImportFolder"); // Set pFolder pFolder = &m_prgFolder[pNode->lparam]; // .idx path IF_FAILEXIT(hr = MakeFilePath(m_szDirectory, pFolder->szFile, ".idx", szIdxPath, ARRAYSIZE(szIdxPath))); // .mbx path IF_FAILEXIT(hr = MakeFilePath(m_szDirectory, pFolder->szFile, ".mbx", szMbxPath, ARRAYSIZE(szMbxPath))); // Open the memory file IF_FAILEXIT(hr = OpenMemoryFile(szIdxPath, &IdxFile)); // Open the memory file IF_FAILEXIT(hr = OpenMemoryFile(szMbxPath, &MbxFile)); // Read the Mbx File Header pMbxHeader = (LPMBXFILEHEADER)(MbxFile.pView); // Read the Idx File Header pIdxHeader = (LPIDXFILEHEADER)(IdxFile.pView); // Validate the Version of th idx file if (pIdxHeader->ver != CACHEFILE_VER || pIdxHeader->dwMagic != CACHEFILE_MAGIC) { hr = TraceResult(MIGRATE_E_INVALIDIDXHEADER); goto exit; } // Setup faIdxRead faIdxRead = sizeof(IDXFILEHEADER); // Set Message Count pImport->SetMessageCount(pIdxHeader->cMsg); // Prepare to Loop for (i=0; icMsg; i++) { // Done if (faIdxRead >= IdxFile.cbSize) break; // Read an idx message header pIdxMessage = (LPIDXMESSAGEHEADER)((LPBYTE)IdxFile.pView + faIdxRead); // If this message is not marked as deleted... if (ISFLAGSET(pIdxMessage->dwState, MSG_DELETED)) goto NextMessage; // Initialize State dwMsgState = 0; // Fixup the Flags if (ISFLAGSET(pIdxMessage->dwState, MSG_UNREAD)) FLAGSET(dwMsgState, MSG_STATE_UNREAD); if (ISFLAGSET(pIdxMessage->dwState, MSG_UNSENT)) FLAGSET(dwMsgState, MSG_STATE_UNSENT); if (ISFLAGSET(pIdxMessage->dwState, MSG_SUBMITTED)) FLAGSET(dwMsgState, MSG_STATE_SUBMITTED); // Bad if (pIdxMessage->dwOffset > MbxFile.cbSize) goto NextMessage; // Lets read the message header in the mbx file to validate the msgids pMbxMessage = (LPMBXMESSAGEHEADER)((LPBYTE)MbxFile.pView + pIdxMessage->dwOffset); // Validate the Message Ids if (pMbxMessage->msgid != pIdxMessage->msgid) goto NextMessage; // Check for magic if (pMbxMessage->dwMagic != MSGHDR_MAGIC) goto NextMessage; // Get the stream pointer pbStream = (LPBYTE)((LPBYTE)MbxFile.pView + (pIdxMessage->dwOffset + sizeof(MBXMESSAGEHEADER))); // New byte Stream IF_NULLEXIT(pStream = new CByteStream(pbStream, pMbxMessage->dwBodySize)); // Import the message IF_FAILEXIT(hr = pImport->ImportMessage(MSG_TYPE_MAIL, dwMsgState, pStream, NULL, 0)); // Count cMessages++; NextMessage: // Cleanup if (pStream) { pStream->AcquireBytes(&cb, &pbStream, ACQ_DISPLACE); pStream->Release(); pStream = NULL; } // Goto Next Header Assert(pIdxMessage); // Update faIdxRead faIdxRead += pIdxMessage->dwSize; } exit: // Cleanup if (pStream) { pStream->AcquireBytes(&cb, &pbStream, ACQ_DISPLACE); pStream->Release(); pStream = NULL; } CloseMemoryFile(&IdxFile); CloseMemoryFile(&MbxFile); // Done return hr; } //-------------------------------------------------------------------------- // COE4EnumFolders::COE4EnumFolders //-------------------------------------------------------------------------- COE4EnumFolders::COE4EnumFolders(IMPFOLDERNODE *pList) { TraceCall("COE4EnumFolders::COE4EnumFolders"); m_cRef = 1; m_pList = pList; m_pNext = pList; } //-------------------------------------------------------------------------- // COE4EnumFolders::COE4EnumFolders //-------------------------------------------------------------------------- COE4EnumFolders::~COE4EnumFolders(void) { TraceCall("COE4EnumFolders::~COE4EnumFolders"); } //-------------------------------------------------------------------------- // COE4EnumFolders::COE4EnumFolders //-------------------------------------------------------------------------- STDMETHODIMP COE4EnumFolders::QueryInterface(REFIID riid, LPVOID *ppv) { // Locals HRESULT hr=S_OK; // Stack TraceCall("COE4EnumFolders::QueryInterface"); // Find IID if (IID_IUnknown == riid) *ppv = (IUnknown *)this; else if (IID_IEnumFOLDERS == riid) *ppv = (IEnumFOLDERS *)this; else { *ppv = NULL; hr = TraceResult(E_NOINTERFACE); goto exit; } // AddRef It ((IUnknown *)*ppv)->AddRef(); exit: // Done return(hr); } //-------------------------------------------------------------------------- // COE4EnumFolders::AddRef //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COE4EnumFolders::AddRef(void) { TraceCall("COE4EnumFolders::AddRef"); return InterlockedIncrement(&m_cRef); } //-------------------------------------------------------------------------- // COE4EnumFolders::Release //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COE4EnumFolders::Release(void) { TraceCall("COE4EnumFolders::Release"); LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return (ULONG)cRef; } //-------------------------------------------------------------------------- // COE4EnumFolders::Next //-------------------------------------------------------------------------- STDMETHODIMP COE4EnumFolders::Next(IMPORTFOLDER *pFolder) { // Locals HRESULT hr=S_OK; // Trace TraceCall("COE4EnumFolders::Next"); // Invalid Args Assert(pFolder != NULL); // Done if (NULL == m_pNext) return(S_FALSE); // Zero ZeroMemory(pFolder, sizeof(IMPORTFOLDER)); // Store pNext into dwCookie pFolder->dwCookie = (DWORD_PTR)m_pNext; // Copy Folder Name StrCpyN(pFolder->szName, m_pNext->szName, ARRAYSIZE(pFolder->szName)); // Copy Type pFolder->type = m_pNext->type; // Has Sub Folders ? pFolder->fSubFolders = (m_pNext->pchild != NULL); // Goto Next m_pNext = m_pNext->pnext; // Done return(S_OK); } //-------------------------------------------------------------------------- // COE4EnumFolders::Reset //-------------------------------------------------------------------------- STDMETHODIMP COE4EnumFolders::Reset(void) { // Trace TraceCall("COE4EnumFolders::Reset"); // Reset m_pNext = m_pList; // Done return(S_OK); }