|
|
// --------------------------------------------------------------------------------
// Utility.cpp
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "migrate.h"
#include "migerror.h"
#include "utility.h"
#include "resource.h"
#include <shared.h>
extern BOOL g_fQuiet;
/*
* CenterDialog * * Purpose: * This function centers a dialog with respect to its parent * dialog. * * Parameters: * hwndDlg hwnd of the dialog to center */ VOID CenterDialog(HWND hwndDlg) { HWND hwndOwner; RECT rc; RECT rcDlg; RECT rcOwner; RECT rcWork; INT x; INT y; INT nAdjust;
// Get the working area rectangle
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
// Get the owner window and dialog box rectangles.
// The window rect of the destop window is in trouble on multimonitored
// macs. GetWindow only gets the main screen.
if (hwndOwner = GetParent(hwndDlg)) GetWindowRect(hwndOwner, &rcOwner); else rcOwner = rcWork;
GetWindowRect(hwndDlg, &rcDlg); rc = rcOwner;
// Offset the owner and dialog box rectangles so that
// right and bottom values represent the width and
// height, and then offset the owner again to discard
// space taken up by the dialog box.
OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); OffsetRect(&rc, -rc.left, -rc.top); OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
// The new position is the sum of half the remaining
// space and the owner's original position.
// But not less than Zero - jefbai
x= rcOwner.left + (rc.right / 2); y= rcOwner.top + (rc.bottom / 2);
// Make sure the dialog doesn't go off the right edge of the screen
nAdjust = rcWork.right - (x + rcDlg.right); if (nAdjust < 0) x += nAdjust;
//$ Raid 5128: Make sure the left edge is visible
if (x < rcWork.left) x = rcWork.left;
// Make sure the dialog doesn't go off the bottom edge of the screen
nAdjust = rcWork.bottom - (y + rcDlg.bottom); if (nAdjust < 0) y += nAdjust;
//$ Raid 5128: Make sure the top edge is visible
if (y < rcWork.top) y = rcWork.top; SetWindowPos(hwndDlg, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); }
// --------------------------------------------------------------------------------
// CommifyString
// --------------------------------------------------------------------------------
#define WHOLENUM_LEN 30
#define LODWORD(_qw) (DWORD)(_qw)
const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB, IDS_ORDERPB, IDS_ORDEREB};
// takes a DWORD add commas etc to it and puts the result in the buffer
LPSTR CommifyString(DWORD dw, LPSTR pszResult, UINT cchBuf) { char szTemp[30]; char szSep[5]; NUMBERFMT nfmt;
nfmt.NumDigits = 0; nfmt.LeadingZero = 0; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep)); nfmt.Grouping = atoi(szSep); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep)); nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep; nfmt.NegativeOrder = 0;
wnsprintf(szTemp, ARRAYSIZE(szTemp), TEXT("%lu"), dw);
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt,pszResult, ARRAYSIZE(szTemp)) == 0) StrCpyN(pszResult, szTemp, cchBuf);
return pszResult; }
// --------------------------------------------------------------------------------
// MapDataDirToAcctId
// --------------------------------------------------------------------------------
HRESULT MapDataDirToAcctId(DWORD dwServer, LPCSTR pszSubDir, LPSTR pszAcctId, int cchAcctId) { // Locals
LPACCOUNTINFO pAccount; DWORD i;
// Trace
TraceCall("MapDataDirToAcctId");
// Set Account Id
for (i=0; i<g_AcctTable.cAccounts; i++) { // Redability
pAccount = &g_AcctTable.prgAccount[i];
// Looking for News Servers
if (ISFLAGSET(pAccount->dwServer, dwServer)) { // Same Sub directory
if (lstrcmpi(pAccount->szDataDir, pszSubDir) == 0) { // Set Account Id
StrCpyN(pszAcctId, pAccount->szAcctId, cchAcctId);
// Done
return(S_OK); } } }
// Done
return(E_FAIL); }
// --------------------------------------------------------------------------------
// EnumerateStoreFiles
// --------------------------------------------------------------------------------
HRESULT EnumerateStoreFiles(LPCSTR pszPath, DIRTYPE tyDir, LPCSTR pszSubDir, LPENUMFILEINFO pEnumInfo, LPFILEINFO *ppHead) { // Locals
HRESULT hr=S_OK; CHAR szFullPath[MAX_PATH + MAX_PATH]; CHAR szSearch[MAX_PATH + MAX_PATH]; WIN32_FIND_DATA fd; HANDLE hFind=INVALID_HANDLE_VALUE; DWORD i; LPACCOUNTINFO pAccount; LPFILEINFO pNew=NULL;
// Trace
TraceCall("EnumerateStoreFiles");
// Invalid Args
Assert(pszPath && pEnumInfo && pEnumInfo->pszExt && pEnumInfo->pszExt[0] == '.' && ppHead);
// Build Base Path
if (pszSubDir) wnsprintf(szFullPath, ARRAYSIZE(szFullPath), "%s\\%s", pszPath, pszSubDir); else StrCpyN(szFullPath, pszPath, ARRAYSIZE(szFullPath));
// Do we have a sub dir
wnsprintf(szSearch, ARRAYSIZE(szSearch), "%s\\*.*", szFullPath);
// 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 (ISFLAGSET(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) { // Not . and not ..
if (lstrcmpi(fd.cFileName, ".") != 0 && lstrcmpi(fd.cFileName, "..") != 0) { // Default Dirtype
DIRTYPE tyDirNew=tyDir;
// Decide new dir type
if (lstrcmpi(fd.cFileName, "mail") == 0) tyDirNew = DIR_IS_LOCAL; else if (lstrcmpi(fd.cFileName, "news") == 0) tyDirNew = DIR_IS_NEWS; else if (lstrcmpi(fd.cFileName, "imap") == 0) tyDirNew = DIR_IS_IMAP;
// Recursive...
IF_FAILEXIT(hr = EnumerateStoreFiles(szFullPath, tyDirNew, fd.cFileName, pEnumInfo, ppHead)); } }
// Otherwise... don't enumerate any files in the root directory...
else if (DIR_IS_ROOT != tyDir) { // Locals
BOOL fIsFile=FALSE; CHAR szPath[_MAX_PATH]; CHAR szDrive[_MAX_DRIVE]; CHAR szDir[_MAX_DIR]; CHAR szFile[_MAX_FNAME]; CHAR szExt[_MAX_EXT];
// Split the Path
_splitpath(fd.cFileName, szDrive, szDir, szFile, szExt); // Extension I'm looking for ?
if ('\0' != *szExt) { // Ext1
if (lstrcmpi(pEnumInfo->pszExt, szExt) == 0) fIsFile = TRUE;
// FoldFile
if (pEnumInfo->pszFoldFile && lstrcmpi(pEnumInfo->pszFoldFile, fd.cFileName) == 0) fIsFile = TRUE;
// UidlFile
if (pEnumInfo->pszUidlFile && lstrcmpi(pEnumInfo->pszUidlFile, fd.cFileName) == 0) fIsFile = TRUE;
// SubList
if (pEnumInfo->pszSubList && lstrcmpi(pEnumInfo->pszSubList, fd.cFileName) == 0) fIsFile = TRUE;
// GrpList
if (pEnumInfo->pszGrpList && lstrcmpi(pEnumInfo->pszGrpList, fd.cFileName) == 0) fIsFile = TRUE; }
// If Not is file, and caller wants to look for v1 news and I'm in the news directory
if (FALSE == fIsFile && TRUE == pEnumInfo->fFindV1News && DIR_IS_NEWS == tyDir) { // If this is a .dat file or a .sub file
if (lstrcmpi(szExt, ".dat") == 0) fIsFile = TRUE;
// .sub file
else if (lstrcmpi(szExt, ".sub") == 0) fIsFile = TRUE; }
// Is File
if (fIsFile) { // Allocate a FileInfo
IF_NULLEXIT(pNew = (LPFILEINFO)g_pMalloc->Alloc(sizeof(FILEINFO)));
// Zero alloc
ZeroMemory(pNew, sizeof(FILEINFO));
// Determine File Type
if (DIR_IS_LOCAL == tyDir) { // Default file type
pNew->tyFile = FILE_IS_LOCAL_MESSAGES;
// Set Server Type
pNew->dwServer = SRV_POP3;
// Set Account Id
StrCpyN(pNew->szAcctId, "LocalStore", ARRAYSIZE(pNew->szAcctId));
// Folders
if (pEnumInfo->pszFoldFile && lstrcmpi(pEnumInfo->pszFoldFile, fd.cFileName) == 0) pNew->tyFile = FILE_IS_LOCAL_FOLDERS;
// pop3uidl
else if (pEnumInfo->pszUidlFile && lstrcmpi(pEnumInfo->pszUidlFile, fd.cFileName) == 0) pNew->tyFile = FILE_IS_POP3UIDL; } // News
else if (DIR_IS_NEWS == tyDir) { // Default file type
pNew->tyFile = FILE_IS_NEWS_MESSAGES;
// Set Server Type
pNew->dwServer = SRV_NNTP;
// Map to An Account Id
MapDataDirToAcctId(SRV_NNTP, pszSubDir, pNew->szAcctId, ARRAYSIZE(pNew->szAcctId));
// sublist.dat
if (pEnumInfo->pszSubList && lstrcmpi(pEnumInfo->pszSubList, fd.cFileName) == 0) pNew->tyFile = FILE_IS_NEWS_SUBLIST;
// grplist.dat
else if (pEnumInfo->pszGrpList && lstrcmpi(pEnumInfo->pszGrpList, fd.cFileName) == 0) pNew->tyFile = FILE_IS_NEWS_GRPLIST;
// If this is a .dat file or a .sub file
else if (pEnumInfo->fFindV1News) { // Group List
if (lstrcmpi(szExt, ".dat") == 0) pNew->tyFile = FILE_IS_NEWS_GRPLIST; // .sub file
else if (lstrcmpi(szExt, ".sub") == 0) pNew->tyFile = FILE_IS_NEWS_SUBLIST;
// Try to find the Account (szFile should equal the server name)
for (DWORD i=0; i<g_AcctTable.cAccounts; i++) { // Is this the Account
if (lstrcmpi(g_AcctTable.prgAccount[i].szServer, szFile) == 0) { StrCpyN(pNew->szAcctId, g_AcctTable.prgAccount[i].szAcctId, ARRAYSIZE(pNew->szAcctId)); break; } } } }
// IMAP
else if (DIR_IS_IMAP == tyDir) { // Default file type
pNew->tyFile = FILE_IS_IMAP_MESSAGES;
// Set Server Type
pNew->dwServer = SRV_IMAP;
// Map to An Account Id
MapDataDirToAcctId(SRV_IMAP, pszSubDir, pNew->szAcctId, ARRAYSIZE(pNew->szAcctId));
// Folders
if (pEnumInfo->pszFoldFile && lstrcmpi(pEnumInfo->pszFoldFile, fd.cFileName) == 0) pNew->tyFile = FILE_IS_IMAP_FOLDERS; }
// Format the filename
wnsprintf(pNew->szFilePath, ARRAYSIZE(pNew->szFilePath), "%s\\%s", szFullPath, fd.cFileName);
// Trace This
TraceInfo(_MSG("MigFile: %s", pNew->szFilePath));
// Link It In
pNew->pNext = (*ppHead);
// Set ppHead
*ppHead = pNew;
// Don't Free pNew
pNew = NULL; } }
// Find the Next File
if (!FindNextFile(hFind, &fd)) break; }
exit: // Cleanup
SafeMemFree(pNew); if (hFind) FindClose(hFind);
// Done
return hr; }
// --------------------------------------------------------------------------------
// FreeFileList
// --------------------------------------------------------------------------------
HRESULT FreeFileList(LPFILEINFO *ppHead) { // Locals
LPFILEINFO pCurrent=(*ppHead); LPFILEINFO pNext;
// Loop
while (pCurrent) { // Save Next
pNext = pCurrent->pNext;
// Free Current
g_pMalloc->Free(pCurrent);
// Goto Next
pCurrent = pNext; }
// Done
return S_OK; }
// --------------------------------------------------------------------------------
// MigrageDlgProc
// --------------------------------------------------------------------------------
INT_PTR CALLBACK MigrageDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Trace
TraceCall("MigrageDlgProc");
// Handle Message
switch (uMsg) { case WM_INITDIALOG: return TRUE; }
// Done
return 0; }
// --------------------------------------------------------------------------------
// InitializeCounters
// --------------------------------------------------------------------------------
void InitializeCounters(LPMEMORYFILE pFile, LPFILEINFO pInfo, LPDWORD pcMax, LPDWORD pcbNeeded, BOOL fInflate) { // Increment pcMax
(*pcMax) += pFile->cbSize;
// Save Size
pInfo->cbFile = pFile->cbSize;
// Set Progress Max
pInfo->cProgMax = pFile->cbSize;
// Set cProgInc
pInfo->cProgInc = pInfo->cRecords > 0 ? (pFile->cbSize / pInfo->cRecords) : pFile->cbSize;
// Increment pcbNeeded
(*pcbNeeded) += pInfo->cbFile;
// Assume the file will be 8% bigger
if (fInflate) (*pcbNeeded) += ((pInfo->cbFile * 8) / 100); }
// --------------------------------------------------------------------------------
// IncrementProgress
// --------------------------------------------------------------------------------
void IncrementProgress(LPPROGRESSINFO pProgress, LPFILEINFO pInfo) { // Locals
MSG msg; ULARGE_INTEGER uliCurrent; ULARGE_INTEGER uliMax;
// Trace
TraceCall("IncrementProgress");
// Increment
pProgress->cCurrent += pInfo->cProgInc;
// Increment per-file progress
pInfo->cProgCur += pInfo->cProgInc;
// If cur is now larget than max ?
if (pProgress->cCurrent > pProgress->cMax) pProgress->cCurrent = pProgress->cMax;
// Set 64
uliCurrent.QuadPart = pProgress->cCurrent; uliMax.QuadPart = pProgress->cMax;
// Compute percent
DWORD cPercent = (DWORD)((uliCurrent.QuadPart) * 100 / uliMax.QuadPart);
// Change
if (cPercent != pProgress->cPercent) { // Locals
CHAR szRes[50]; CHAR szProgress[50];
// Save It
pProgress->cPercent = cPercent;
// Load the String
LoadString(g_hInst, IDS_COMPLETE, szRes, ARRAYSIZE(szRes));
// Update status
if(!g_fQuiet) SendMessage(GetDlgItem(pProgress->hwndProgress, IDC_PROGRESS), PBM_SETPOS, pProgress->cPercent, 0);
// Format
wnsprintf(szProgress, ARRAYSIZE(szProgress), szRes, cPercent);
// Update Description...
if(!g_fQuiet) SetDlgItemText(pProgress->hwndProgress, IDS_STATUS, szProgress); }
// Pump messages until current cycle is complete
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (!IsDialogMessage(pProgress->hwndProgress, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } }
// --------------------------------------------------------------------------------
// SetProgressFile
// --------------------------------------------------------------------------------
void SetProgressFile(LPPROGRESSINFO pProgress, LPFILEINFO pInfo) { // Locals
CHAR szRes[255]; CHAR szMsg[255 + MAX_PATH + MAX_PATH]; CHAR szScratch[50];
// Load String
LoadString(g_hInst, IDS_MIGRATING, szRes, ARRAYSIZE(szRes));
// Format the String
wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, pInfo->szFilePath, StrFormatByteSize64A(pInfo->cbFile, szScratch, ARRAYSIZE(szScratch)));
// Update Description...
if(!g_fQuiet) SetDlgItemText(pProgress->hwndProgress, IDS_DESCRIPT, szMsg); }
// --------------------------------------------------------------------------------
// WriteMigrationLogFile
// --------------------------------------------------------------------------------
HRESULT WriteMigrationLogFile(HRESULT hrMigrate, DWORD dwLastError, LPCSTR pszStoreRoot, LPCSTR pszMigrate, LPCSTR pszCmdLine, LPFILEINFO pHeadFile) { // Locals
HRESULT hr=S_OK; HANDLE hFile=NULL; DWORD cbFile; CHAR szWrite[2024]; DWORD cbWrote; CHAR szLogFile[MAX_PATH]; SYSTEMTIME st; LPFILEINFO pCurrent;
// Trace
TraceCall("WriteMigrationLogFile");
// Invalid Args
Assert(pszStoreRoot && pszCmdLine);
// File name too long....
wnsprintf(szLogFile, ARRAYSIZE(szLogFile), "%s\\%s.log", pszStoreRoot, pszMigrate);
// Open the File
hFile = CreateFile(szLogFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
// Failure
if (INVALID_HANDLE_VALUE == hFile) { hFile = NULL; hr = TraceResult(E_FAIL); goto exit; }
// Get the Size
cbFile = ::GetFileSize(hFile, NULL); if (0xFFFFFFFF == cbFile) { hr = TraceResult(MIGRATE_E_CANTGETFILESIZE); goto exit; }
// If file is getting kind of large
if (cbFile >= 102400) { // Seek to the end of the file...
if (0xffffffff == SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) { hr = TraceResult(MIGRATE_E_CANTSETFILEPOINTER); goto exit; }
// Set End Of File
if (0 == SetEndOfFile(hFile)) { hr = TraceResult(MIGRATE_E_CANTSETENDOFFILE); goto exit; } }
// Seek to the end of the file...
if (0xffffffff == SetFilePointer(hFile, 0, NULL, FILE_END)) { hr = TraceResult(MIGRATE_E_CANTSETFILEPOINTER); goto exit; }
// add a new line
if (!WriteFile(hFile, pszCmdLine, lstrlen(pszCmdLine), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; }
// add a new line
if (!WriteFile(hFile, "\r\n", lstrlen("\r\n"), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; }
// Write the Date
GetLocalTime(&st);
// Build the string
wnsprintf(szWrite, ARRAYSIZE(szWrite), "Date: %.2d/%.2d/%.4d %.2d:%.2d:%.2d\r\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);
// add a new line
if (!WriteFile(hFile, szWrite, lstrlen(szWrite), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; }
// Set Text
wnsprintf(szWrite, ARRAYSIZE(szWrite), "Store Root: %s\r\nGlobal Migrate Result: HRESULT = 0x%08X, GetLastError() = %d\r\n\r\n", pszStoreRoot, hrMigrate, dwLastError);
// Write Store Root
if (!WriteFile(hFile, szWrite, lstrlen(szWrite), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; }
// Loop through the files
for (pCurrent=pHeadFile; pCurrent!=NULL; pCurrent=pCurrent->pNext) { // Format the string
wnsprintf(szWrite, ARRAYSIZE(szWrite), "cbFile: %012d, cRecords: %08d, fMigrate: %d, hrMigrate: 0x%08X, GetLastError(): %05d, File: %s\r\n", pCurrent->cbFile, pCurrent->cRecords, pCurrent->fMigrate, pCurrent->hrMigrate, pCurrent->dwLastError, pCurrent->szFilePath);
// Write Store Root
if (!WriteFile(hFile, szWrite, lstrlen(szWrite), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; } }
// Write Store Root
if (!WriteFile(hFile, "\r\n\r\n", lstrlen("\r\n\r\n"), &cbWrote, NULL)) { hr = TraceResult(MIGRATE_E_WRITEFILE); goto exit; }
exit: // Close the file
if (hFile) CloseHandle(hFile);
// Done
return hr; }
// --------------------------------------------------------------------------------
// BlobReadData
// --------------------------------------------------------------------------------
HRESULT BlobReadData(LPBYTE lpbBlob, ULONG cbBlob, ULONG *pib, LPBYTE lpbData, ULONG cbData) { // Check Parameters
AssertSz(lpbBlob && cbBlob > 0 && pib && cbData > 0 && lpbData, "Bad Parameter"); AssertReadWritePtr(lpbBlob, cbData); AssertReadWritePtr(lpbData, cbData); AssertSz(*pib + cbData <= cbBlob, "Blob overflow");
// Copy Data Data
CopyMemory (lpbData, lpbBlob + (*pib), cbData); *pib += cbData;
// Done
return S_OK; }
// --------------------------------------------------------------------------------
// ReplaceExtension
// --------------------------------------------------------------------------------
void ReplaceExtension(LPCSTR pszFilePath, LPCSTR pszExtNew, LPSTR pszFilePathNew, int cchFilePathNew) { // Locals
CHAR szPath[_MAX_PATH]; CHAR szDrive[_MAX_DRIVE]; CHAR szDir[_MAX_DIR]; CHAR szFile[_MAX_FNAME]; CHAR szExt[_MAX_EXT];
// Trace
TraceCall("ReplaceExtension");
// Split the Path
_splitpath(pszFilePath, szDrive, szDir, szFile, szExt);
// Build New File Path
wnsprintf(pszFilePathNew, cchFilePathNew, "%s%s%s%s", szDrive, szDir, szFile, pszExtNew);
// Done
return; }
// --------------------------------------------------------------------------------
// GetAvailableDiskSpace
// --------------------------------------------------------------------------------
HRESULT GetAvailableDiskSpace(LPCSTR pszFilePath, DWORDLONG *pdwlFree) { // Locals
HRESULT hr=S_OK; CHAR szDrive[5]; DWORD dwSectorsPerCluster; DWORD dwBytesPerSector; DWORD dwNumberOfFreeClusters; DWORD dwTotalNumberOfClusters;
// Trace
TraceCall("GetAvailableDiskSpace");
// Invalid Args
Assert(pszFilePath && pszFilePath[1] == ':' && pdwlFree);
// Split the path
szDrive[0] = *pszFilePath; szDrive[1] = ':'; szDrive[2] = '\\'; szDrive[3] = '\0'; // Get free disk space - if it fails, lets pray we have enought disk space
if (!GetDiskFreeSpace(szDrive, &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters)) { hr = TraceResult(E_FAIL); goto exit; }
// Return Amount of Free Disk Space
*pdwlFree = (dwNumberOfFreeClusters * (dwSectorsPerCluster * dwBytesPerSector));
exit: // Done
return hr; }
// --------------------------------------------------------------------------------
// MyWriteFile
// --------------------------------------------------------------------------------
HRESULT MyWriteFile(HANDLE hFile, DWORD faAddress, LPVOID pData, DWORD cbData) { // Locals
DWORD cbWrote;
// Trace
TraceCall("MyWriteFile");
// Seek to the end of the file...
if (0xffffffff == SetFilePointer(hFile, faAddress, NULL, FILE_BEGIN)) return TraceResult(MIGRATE_E_CANTSETFILEPOINTER);
// Write file
if (0 == WriteFile(hFile, pData, cbData, &cbWrote, NULL)) return TraceResult(MIGRATE_E_WRITEFILE);
// Done
return S_OK; }
// --------------------------------------------------------------------------------
// MigrateMessageBox
// --------------------------------------------------------------------------------
UINT MigrateMessageBox(LPCSTR pszMsg, UINT uType) { // Locals
CHAR szTitle[100];
// Load title
LoadString(g_hInst, IDS_TITLE, szTitle, ARRAYSIZE(szTitle));
// MessageBox
return MessageBox(NULL, pszMsg, szTitle, uType); }
// --------------------------------------------------------------------------------
// CreateAccountDirectory
// --------------------------------------------------------------------------------
HRESULT CreateAccountDirectory(LPCSTR pszStoreRoot, LPCSTR pszBase, DWORD iAccount, LPSTR pszPath, int cchPath) { // Locals
HRESULT hr=S_OK; CHAR szDir[MAX_PATH + MAX_PATH];
// Trace
TraceCall("CreateAccountDirectory");
// Loop
while(1) { // Format the path
wnsprintf(pszPath, cchPath, "Acct%04d", iAccount);
// Format the Path
wnsprintf(szDir, ARRAYSIZE(szDir), "%s\\%s\\%s", pszStoreRoot, pszBase, pszPath);
// Create the Directory
if (CreateDirectory(szDir, NULL)) break;
// If not already exists, failure
if (ERROR_ALREADY_EXISTS != GetLastError()) { hr = TraceResult(E_FAIL); goto exit; }
// Try Again
iAccount++; }
exit: // Done
return(hr); }
// --------------------------------------------------------------------------------
// BuildAccountTable
// --------------------------------------------------------------------------------
HRESULT BuildAccountTable(HKEY hkeyBase, LPCSTR pszRegRoot, LPCSTR pszStoreRoot, LPACCOUNTTABLE pTable) { // Locals
HRESULT hr=S_OK; HKEY hkeyRoot=NULL; HKEY hkeyAcct=NULL; DWORD i; DWORD cb; DWORD cAccounts=0; DWORD dwType; LONG lResult; LPACCOUNTINFO pAccount;
// Trace
TraceCall("BuildAccountTable");
// Validate Args
Assert(hkeyBase && pszRegRoot && pTable);
// Initialize
ZeroMemory(pTable, sizeof(ACCOUNTTABLE));
// Open the Root Key
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyBase, pszRegRoot, 0, KEY_ALL_ACCESS, &hkeyRoot)) { hr = TraceResult(E_FAIL); goto exit; }
// Enumerate keys
if (ERROR_SUCCESS != RegQueryInfoKey(hkeyRoot, NULL, NULL, 0, &pTable->cAccounts, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { hr = TraceResult(E_FAIL); goto exit; }
// Allocate the Account Array
IF_NULLEXIT(pTable->prgAccount = (LPACCOUNTINFO)ZeroAllocate(sizeof(ACCOUNTINFO) * pTable->cAccounts));
// Start Enumerating the keys
for (i=0; i<pTable->cAccounts; i++) { // Close Current hkeyAcct
if (hkeyAcct) { RegCloseKey(hkeyAcct); hkeyAcct = NULL; }
// Readability
pAccount = &pTable->prgAccount[cAccounts];
// Set the size of the account id field
cb = sizeof(pAccount->szAcctId);
// Enum the Key Info
lResult = RegEnumKeyEx(hkeyRoot, i, pAccount->szAcctId, &cb, 0, NULL, NULL, NULL);
// No more items
if (lResult == ERROR_NO_MORE_ITEMS) break;
// Error, lets move onto the next account
if (lResult != ERROR_SUCCESS) { Assert(FALSE); continue; }
// Open the Account Key
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyRoot, pAccount->szAcctId, 0, KEY_ALL_ACCESS, &hkeyAcct)) { Assert(FALSE); continue; }
// Set Length of Field
cb = sizeof(pAccount->szAcctName);
// Query the Account Name
if (ERROR_SUCCESS != RegQueryValueEx(hkeyAcct, "Account Name", NULL, &dwType, (LPBYTE)pAccount->szAcctName, &cb)) { Assert(FALSE); continue; }
// Set Length of field
cb = sizeof(pAccount->szServer);
// Try to determine the account type
if (ERROR_SUCCESS == RegQueryValueEx(hkeyAcct, "POP3 Server", NULL, &dwType, (LPBYTE)pAccount->szServer, &cb)) { // Its a pop3 server
pAccount->dwServer = SRV_POP3;
// Set the Directory
wnsprintf(pAccount->szDirectory, ARRAYSIZE(pAccount->szDirectory), "%s\\Mail", pszStoreRoot); }
// Otherwise - NNTP
else if (ERROR_SUCCESS == RegQueryValueEx(hkeyAcct, "NNTP Server", NULL, &dwType, (LPBYTE)pAccount->szServer, &cb)) { // Its an nntp account
pAccount->dwServer = SRV_NNTP;
// Set length of the field
cb = sizeof(pAccount->szDataDir);
// Query the Data Directory
if (ERROR_SUCCESS != RegQueryValueEx(hkeyAcct, "NNTP Data Directory", NULL, &dwType, (LPBYTE)pAccount->szDataDir, &cb)) { // CreateAccountDirectory
if (FAILED(CreateAccountDirectory(pszStoreRoot, "News", i, pAccount->szDataDir, ARRAYSIZE(pAccount->szDataDir)))) continue;
// Set the Data Directory
if (ERROR_SUCCESS != RegSetValueEx(hkeyAcct, "NNTP Data Directory", 0, REG_SZ, (LPBYTE)pAccount->szDataDir, lstrlen(pAccount->szDataDir) + 1)) continue; }
// Format the Directory
wnsprintf(pAccount->szDirectory, ARRAYSIZE(pAccount->szDirectory), "%s\\News\\%s", pszStoreRoot, pAccount->szDataDir); } // Otherwise - IMAP
else if (ERROR_SUCCESS == RegQueryValueEx(hkeyAcct, "IMAP Server", NULL, &dwType, (LPBYTE)pAccount->szServer, &cb)) { // Its an IMAP Server
pAccount->dwServer = SRV_IMAP;
// Set length of the field
cb = sizeof(pAccount->szDataDir);
// Query the Data Directory
if (ERROR_SUCCESS != RegQueryValueEx(hkeyAcct, "IMAP Data Directory", NULL, &dwType, (LPBYTE)pAccount->szDataDir, &cb)) { // CreateAccountDirectory
if (FAILED(CreateAccountDirectory(pszStoreRoot, "IMAP", i, pAccount->szDataDir, ARRAYSIZE(pAccount->szDataDir)))) continue;
// Set the Data Directory
if (ERROR_SUCCESS != RegSetValueEx(hkeyAcct, "IMAP Data Directory", 0, REG_SZ, (LPBYTE)pAccount->szDataDir, lstrlen(pAccount->szDataDir) + 1)) continue; }
// Format the Directory
wnsprintf(pAccount->szDirectory, ARRAYSIZE(pAccount->szDirectory), "%s\\IMAP\\%s", pszStoreRoot, pAccount->szDataDir); }
// Othewise, skip the account
else continue;
// Make sure the directory exists
if (0 == CreateDirectory(pAccount->szDirectory, NULL) && ERROR_ALREADY_EXISTS != GetLastError()) continue;
// Increment Valid Account Count
cAccounts++; }
// Set Actual Number of Accounts
pTable->cAccounts = cAccounts;
exit: // Cleanup
if (hkeyAcct) RegCloseKey(hkeyAcct); if (hkeyRoot) RegCloseKey(hkeyRoot);
// Done
return(hr); }
|