/* - - - WABImprt.c - Contains code for importing another WAB into the currently opened WAB * * */ #include "_apipch.h" /* - - PromptForWABFile * * Shows the OpenFileName dialog to prompt for the WAB file to import * :Cache the last imported WAB file in the registry * * bOpen - if TRUE, calls GetOpenFileName; if false, calls GetSaveFileName */ BOOL PromptForWABFile(HWND hWnd, LPTSTR pszFile, DWORD cchSizeFile, BOOL bOpen) { OPENFILENAME ofn; LPTSTR lpFilter = FormatAllocFilter(idsWABImportString, TEXT("*.WAB"),0,NULL,0,NULL); TCHAR szFileName[MAX_PATH + 1] = TEXT(""); TCHAR szTitle[MAX_PATH] = TEXT(""); BOOL bRet = FALSE; LoadString( hinstMapiX, bOpen ? idsSelectWABToImport : idsSelectWABToExport, szTitle, ARRAYSIZE(szTitle)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.hInstance = hinstMapiX; ofn.lpstrFilter = lpFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = ARRAYSIZE(szFileName); ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = szTitle; ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = TEXT("wab"); ofn.lCustData = 0; ofn.lpfnHook = NULL; ofn.lpTemplateName = NULL; if(bOpen) bRet = GetOpenFileName(&ofn); else bRet = GetSaveFileName(&ofn); if(bRet) StrCpyN(pszFile, szFileName, cchSizeFile); LocalFreeAndNull(&lpFilter); return bRet; } /* - MapOldNamedPropsToNewNamedProps - * Takes all the props from the wab being imported and finds or creates appropriate * named props from the store being imported into * *lpulOldNP and *lpulNewNP are LocalAlloced and should be freed by caller typedef struct _NamedProp { ULONG ulPropTag; // Contains the proptag for this named prop LPTSTR lpsz; // Contains the string for this named prop } NAMED_PROP, * LPNAMED_PROP; typedef struct _tagGuidNamedProps { LPGUID lpGUID; // Application GUID for which these named props are ULONG cValues; // Number of entries in the lpmn array LPNAMED_PROP lpnm; // Array of Named Props for this Guid. } GUID_NAMED_PROPS, * LPGUID_NAMED_PROPS; */ HRESULT MapOldNamedPropsToNewNamedProps(HANDLE hPropertyStore, LPADRBOOK lpAdrBook, ULONG * lpulPropCount, LPULONG * lppulOldNP, LPULONG * lppulNewNP) { ULONG ulcGUIDCount = 0,i=0,j=0,ulCount=0; LPGUID_NAMED_PROPS lpgnp = NULL; HRESULT hr = S_OK; LPULONG lpulOldNP = NULL, lpulNewNP = NULL; ULONG ulcOldNPCount = 0; LPSPropTagArray lpta = NULL; LPMAPINAMEID * lppPropNames = NULL; SCODE sc ; if(HR_FAILED(hr = GetNamedPropsFromPropStore(hPropertyStore, &ulcGUIDCount, &lpgnp))) goto exit; if(ulcGUIDCount) { for(i=0;ilpguid = lpgnp[i].lpGUID; lppPropNames[ulCount]->ulKind = MNID_STRING; { int nSize = lstrlen(lpgnp[i].lpnm[j].lpsz); if(!nSize) continue; else { nSize++; if(sc = MAPIAllocateMore(sizeof(WCHAR)*nSize, lppPropNames, &(lppPropNames[ulCount]->Kind.lpwstrName))) { hr = ResultFromScode(sc); goto exit; } } StrCpyN(lppPropNames[ulCount]->Kind.lpwstrName,lpgnp[i].lpnm[j].lpsz, nSize); ulCount++; } } } // [PaulHi] 3/25/99 Use the actual count of the lppPropNames array, or we will walk off // into unknown memory and crash. ulcOldNPCount = ulCount; hr = lpAdrBook->lpVtbl->GetIDsFromNames(lpAdrBook, ulcOldNPCount, lppPropNames, MAPI_CREATE, &lpta); if(HR_FAILED(hr)) goto exit; // Note that of the tags that are returned, we don't know the tag type .. this we will have // to infer based on the original tags when we see them being used ulCount = 0; for(i=0;iaulPropTag[ulCount]; } } } *lppulNewNP = lpulNewNP; *lppulOldNP = lpulOldNP; *lpulPropCount = ulcOldNPCount; hr = S_OK; exit: if(lpta) MAPIFreeBuffer(lpta); if(lppPropNames) MAPIFreeBuffer(lppPropNames); if(HR_FAILED(hr)) { LocalFreeAndNull(&lpulNewNP); LocalFreeAndNull(&lpulOldNP); } FreeGuidnamedprops(ulcGUIDCount, lpgnp); return hr; } /*************************************************************************** ****************************************************************************/ void ChangeOldNamedPropsToNewNamedProps(ULONG ulcProps, LPSPropValue lpProps, ULONG ulcNPCount, ULONG * lpulOldNP, ULONG *lpulNewNP) { ULONG i,j; for(i=0;i= 0x8000) //this is a named prop { ULONG ulType = PROP_TYPE(lpProps[i].ulPropTag); for(j=0;jcb != SIZEOF_WAB_ENTRYID) { // perhaps this is a Folder EID in it's formal proper form .. // We should try to reduce it to a DWORD... // this may be a WAB container .. reset the entryid to a WAB entryid if(WAB_CONTAINER == IsWABEntryID(lpsbTemp->cb, (LPENTRYID)lpsbTemp->lpb, NULL,NULL,NULL,NULL,NULL)) { SBinary sbEID = {0}; IsWABEntryID(lpsbTemp->cb, (LPENTRYID)lpsbTemp->lpb, (LPVOID*)&sbEID.lpb,(LPVOID*)&sbEID.cb,NULL,NULL,NULL); if(sbEID.cb == SIZEOF_WAB_ENTRYID) CopyMemory(&dwTemp, sbEID.lpb, min(sbEID.cb, sizeof(dwTemp))); else return; } } else CopyMemory(&dwTemp, lpsbOld->lpb, min(lpsbOld->cb, sizeof(dwTemp))); dwTemp = 0xFFFFFFFF - dwTemp; SetSBinary(lpsbTemp, lpsbOld->cb, (LPBYTE)&dwTemp); } /* - GetNewEID - * Finds a new entryid or a temp entryid for a given old entryid * When bTemp is true, only looks in the temp entryid column */ LPSBinary GetNewEID(LPSBinary lpsbOldEID, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp) { DWORD dw = 0; while(lppsbEIDs[eidOld][dw].cb && dw < dwCount) { if( lppsbEIDs[eidOld][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp !memcmp(lppsbEIDs[eidOld][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb)) { if(bTemp) return lpsbOldEID; if(lppsbEIDs[eidNew][dw].cb) return &(lppsbEIDs[eidNew][dw]); else if(lppsbEIDs[eidTemp][dw].cb) return &(lppsbEIDs[eidTemp][dw]); else return lpsbOldEID; } else if( lppsbEIDs[eidTemp][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp !memcmp(lppsbEIDs[eidTemp][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb)) { if(lppsbEIDs[eidNew][dw].cb) return &(lppsbEIDs[eidNew][dw]); else return lpsbOldEID; } dw++; } // if we reached here, then we haven't cached an appropriate temp or new eid for the current one // so add the current one to this table if(dwcb, lpsbOldEID->lpb); SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID); return(&(lppsbEIDs[eidTemp][dw])); } return lpsbOldEID; } /* - SetNewEID - * */ void SetNewEID(LPSBinary lpsbOldEID, LPSBinary lpsbNewEID, DWORD dwCount, LPSBinary * lppsbEIDs) { DWORD dw = 0; while(lppsbEIDs[eidOld][dw].cb && dw < dwCount) { if( lppsbEIDs[eidOld][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp !memcmp(lppsbEIDs[eidOld][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb)) { SetSBinary(&(lppsbEIDs[eidNew][dw]), lpsbNewEID->cb, lpsbNewEID->lpb); if(!lppsbEIDs[eidTemp][dw].cb) SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID); return; } dw++; } if(dwcb, lpsbOldEID->lpb); SetSBinary(&lppsbEIDs[eidNew][dw], lpsbNewEID->cb, lpsbNewEID->lpb); SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID); } } /* - - Replace EID * */ void ReplaceEID(LPSBinary lpsb, LPSPropValue lpProps, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp) { LPSBinary lpsbOldEID = lpsb; LPSBinary lpsbNewEID = GetNewEID(lpsbOldEID, dwCount, lppsbEIDs, bTemp); if(lpsbOldEID == lpsbNewEID) return; if(lpsbOldEID->cb != lpsbNewEID->cb) { if(!bTemp) { // this is a prop array read from a WAB file using readrecord LocalFree(lpsbOldEID->lpb); lpsbOldEID->lpb = LocalAlloc(LMEM_ZEROINIT, lpsbNewEID->cb); } else { // this was called from GetProps and is a MAPI Array lpsbOldEID->lpb = NULL; MAPIAllocateMore(lpsbNewEID->cb, lpProps, (LPVOID *) (&(lpsbOldEID->lpb))); } } if(lpsbOldEID->lpb) { lpsbOldEID->cb = lpsbNewEID->cb; CopyMemory(lpsbOldEID->lpb, lpsbNewEID->lpb, lpsbNewEID->cb); } } /* - UpdateEntryIDReferences - * Updates entryids in the given prop array * * The first time the function is called, btemp is FALSE and we replace all EIDs in the * array with temp or new eids * The second time this function is called, bTemp is TRUE and we replace all temp EIDS in * the array with the new EIDs * */ void UpdateEntryIDReferences(ULONG ulcProps, LPSPropValue lpProps, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp) { ULONG i, j, k, l; ULONG ulEntryIDTags[] = { PR_WAB_DL_ENTRIES, PR_WAB_FOLDER_PARENT, PR_WAB_FOLDER_PARENT_OLDPROP, PR_WAB_USER_SUBFOLDERS, }; DWORD dwEntryIDTagCount = 4; //keep in sync with above array for(i=0;i IAddrBook object ulFlags = 0 or MAPI_DIALOG - MAPI_DIALOG means show msgs and progress bar lpszFileName - file name to open, if 0 prompts with GetOpenFileName dialog Returns : HRESULT Comment : ***************************************************************************/ HRESULT HrImportWABFile(HWND hWnd, LPADRBOOK lpAdrBook, ULONG ulFlags, LPTSTR lpszFileName) { LPIAB lpIAB = (LPIAB) lpAdrBook; BOOL bFoldersImported = FALSE; HRESULT hr = E_FAIL; HRESULT hrDeferred = S_OK; TCHAR szWABFile[MAX_PATH+1] = TEXT(""); TCHAR szFile[MAX_PATH+1] = TEXT(""), szPath[MAX_PATH] = TEXT(""); HANDLE hPropertyStore = NULL; DWORD dwWABEntryCount = 0; LPSBinary * lppsbWABEIDs = NULL; ULONG ulcNPCount = 0; LPULONG lpulOldNP = NULL,lpulNewNP = NULL; ULONG i,j,k,n; BOOL bShowUI = (hWnd && (ulFlags & MAPI_DIALOG)); ULONG rgObj[] = { MAPI_MAILUSER, MAPI_DISTLIST, MAPI_ABCONT }; #ifdef IMPORT_FOLDERS #define ulrgObjMax 3 #else #define ulrgObjMax 2 #endif SBinary sbPAB = {0}; SPropertyRestriction PropRes = {0}; //HCURSOR hOldCur = NULL; SPropValue sp = {0}; ULONG ulcOldProps = 0; LPSPropValue lpOldProps = NULL; LPMAPIPROP lpObject = NULL; ULONG ulEIDCount = 0; LPSBinary rgsbEntryIDs = NULL; TCHAR szBuf[MAX_UI_STR]; LPPTGDATA lpPTGData=GetThreadStoragePointer(); if(lpszFileName && lstrlen(lpszFileName)) StrCpyN(szWABFile, lpszFileName, ARRAYSIZE(szWABFile)); else if (!PromptForWABFile(hWnd, szWABFile, ARRAYSIZE(szWABFile), TRUE)) { hr = MAPI_E_USER_CANCEL; goto exit; } //hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT)); // when importing old format files, there is always a possibility that the file data may get // munged when opening the file .. // therefore, before we attempt to import it, we will try to make a copy of the file if(GetFileAttributes(szWABFile) == 0xFFFFFFFF) goto exit; if (!GetTempPath(ARRAYSIZE(szPath), szPath)) goto exit; if(!GetTempFileName(szPath, TEXT("WAB"), 0, szFile)) goto exit; if(!CopyFile(szWABFile, szFile, FALSE)) goto exit; if(GetFileAttributes(szFile) == 0xFFFFFFFF) goto exit; // First let's open this file hr = OpenPropertyStore(szFile, AB_OPEN_EXISTING | AB_DONT_RESTORE | AB_IGNORE_OUTLOOK, hWnd, &hPropertyStore); if(HR_FAILED(hr) || (!hPropertyStore)) { //if(bShowUI) // ShowMessageBoxParam(hWnd, IDE_VCARD_IMPORT_FILE_ERROR, MB_ICONEXCLAMATION, szFile); goto exit; } // get a count of how many entries exist in this new .wab file if(!(dwWABEntryCount = GetWABFileEntryCount(hPropertyStore))) { hr = S_OK; goto exit; } if(bShowUI) { EnableWindow(hWnd, FALSE); CreateShowAbortDialog(hWnd, idsImporting, IDI_ICON_IMPORT, dwWABEntryCount*2 + 1, 0); } if(lppsbWABEIDs = LocalAlloc(LMEM_ZEROINIT, sizeof(LPSBinary) * eidMax)) { for(i=0;ilpVtbl->GetPAB(lpAdrBook, &sbPAB.cb, (LPENTRYID *)&sbPAB.lpb))) goto exit; for(n=0;nlpVtbl->SetProps(lpObject, ulcOldProps, lpOldProps, NULL))) { hrDeferred = hr; hr = S_OK; goto endofthisloop; } // SaveChanges if(HR_FAILED(hr = lpObject->lpVtbl->SaveChanges(lpObject, KEEP_OPEN_READONLY))) { hrDeferred = hr; hr = S_OK; goto endofthisloop; } // By now the object has a new or existin EID .. if so, use this EID { ULONG ulcNewProps = 0; LPSPropValue lpNewProps = NULL; if(HR_FAILED(hr = lpObject->lpVtbl->GetProps(lpObject, NULL, MAPI_UNICODE, &ulcNewProps, &lpNewProps))) { hrDeferred = hr; hr = S_OK; goto endofthisloop; } for(j=0;jlpVtbl->Release(lpObject); lpObject = NULL; } //for i.. FreeEntryIDs(NULL, ulEIDCount, rgsbEntryIDs); rgsbEntryIDs = NULL; ulEIDCount = 0; } // for n.. if(bShowUI) SetPrintDialogMsg(idsImportProcessing, 0, szEmpty); // Now that we have opened all the entries, we need to reopen the new entries in the new WAB and // reset any temp entryids we might have put in them for(n=0;nlpVtbl->OpenEntry(lpAdrBook, lppsbWABEIDs[eidNew][n].cb, (LPENTRYID) lppsbWABEIDs[eidNew][n].lpb, NULL, MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN *)&lpObject))) { hrDeferred = hr; hr = S_OK; continue; } if(ulObjType == MAPI_ABCONT) goto endloop; if(HR_FAILED(hr = lpObject->lpVtbl->GetProps(lpObject, NULL, MAPI_UNICODE, &ulcOldProps, &lpOldProps))) { hrDeferred = hr; hr = S_OK; goto endloop; } // open the record and reset any temp eids in it UpdateEntryIDReferences(ulcOldProps, lpOldProps, dwWABEntryCount, lppsbWABEIDs, TRUE); // SaveChanges if(HR_FAILED(hr = lpObject->lpVtbl->SaveChanges(lpObject, KEEP_OPEN_READONLY))) { hrDeferred = hr; hr = S_OK; } endloop: if(lpOldProps) { MAPIFreeBuffer(lpOldProps); ulcOldProps = 0; lpOldProps = NULL; } if(lpObject) { lpObject->lpVtbl->Release(lpObject); lpObject = NULL; } } // for n... hr = S_OK; exit: if(lstrlen(szFile)) DeleteFile(szFile); if(sbPAB.lpb) MAPIFreeBuffer(sbPAB.lpb); if(ulcOldProps && lpOldProps) LocalFreePropArray(NULL, ulcOldProps, &lpOldProps); if(lpObject) lpObject->lpVtbl->Release(lpObject); if(lppsbWABEIDs) { for(i=0;i