Back to index

lightning-sunbird  0.9+nobinonly
MozABConduitSync.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation
00018  *
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *       Rajiv Dayal <rdayal@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include <windows.h>
00040 #include "syncmgr.h"
00041 #include <tchar.h>
00042 #include <time.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 #include "CondAPI.h"
00047 #include "hslog.h"
00048 #include "MozABConduitSync.h"
00049 #include "MozABConduitRecord.h"
00050 
00051 
00052 #define MAX_PROD_ID_TEXT    255
00053 #define PERSONAL "Personal"
00054 
00055 // Global var
00056 FILE *gFD = NULL; // logging.
00057 
00058 CMozABConduitSync::CMozABConduitSync(CSyncProperties& rProps)
00059 {
00060     m_dbHH = NULL;
00061     m_dbPC = NULL;
00062     m_remoteDB = NULL;
00063     m_TotRemoteDBs = rProps.m_nRemoteCount; // Fixed 3/25/99 KRM
00064     m_ConduitHandle =  (CONDHANDLE)0;
00065     memcpy(&m_rSyncProperties, &rProps, sizeof(m_rSyncProperties));
00066     memset(&m_SystemInfo, 0, sizeof(m_SystemInfo));
00067 
00068     // See if logging is turned on (ie, check env variable "MOZ_CONDUIT_LOG"
00069     // for a logfile like "c:\\temp\\conduitlog.txt").
00070     char *envVar = getenv(ENV_VAR_CONDUTI_LOG);
00071     if(envVar != NULL )
00072       gFD = fopen(envVar, "a+");
00073 }
00074 
00075 CMozABConduitSync::~CMozABConduitSync()
00076 {
00077     long retval;
00078 
00079     if (m_SystemInfo.m_ProductIdText) {
00080         delete m_SystemInfo.m_ProductIdText;
00081            m_SystemInfo.m_ProductIdText = NULL;
00082            m_SystemInfo.m_AllocedLen = 0; 
00083     }
00084     if ((!m_rSyncProperties.m_RemoteDbList) && (m_remoteDB)) {
00085         delete m_remoteDB;
00086         m_remoteDB = NULL;
00087     }
00088     if (m_ConduitHandle) {
00089         retval = SyncUnRegisterConduit(m_ConduitHandle);
00090         m_ConduitHandle = 0;
00091     }
00092 
00093     if (gFD)
00094       fclose(gFD);
00095 }
00096 
00097 long CMozABConduitSync::Perform(void)
00098 {
00099     long retval = 0;
00100 
00101     // Log the start time.
00102     time_t ltime;
00103     time( &ltime );
00104     CONDUIT_LOG1(gFD, "\n------------ START OF PALM SYNC ------------ at %s", ctime(&ltime));
00105 
00106     if (m_rSyncProperties.m_SyncType > eProfileInstall)
00107         return GEN_ERR_BAD_SYNC_TYPE;
00108 
00109     if (m_rSyncProperties.m_SyncType == eDoNothing) {
00110         return 0;
00111     }
00112 
00113     // Obtain System Information
00114     m_SystemInfo.m_ProductIdText = (BYTE*) new char [MAX_PROD_ID_TEXT]; //deleted in d'ctor
00115     if (!m_SystemInfo.m_ProductIdText)
00116         return GEN_ERR_LOW_MEMORY;
00117 
00118     m_SystemInfo.m_AllocedLen = (BYTE) MAX_PROD_ID_TEXT; 
00119     retval = SyncReadSystemInfo(m_SystemInfo);
00120     if (retval)
00121         return retval;
00122 
00123     // Register this conduit with SyncMgr.DLL for communication to HH
00124     retval = SyncRegisterConduit(m_ConduitHandle);
00125     if (retval) {
00126         CONDUIT_LOG0(gFD, "Failed SyncRegisterConduit.\n");
00127         return retval;
00128     }
00129 
00130     for (int iCount=0; iCount < m_TotRemoteDBs && !retval; iCount++) {
00131         retval = GetRemoteDBInfo(iCount);
00132         if (retval) {
00133             retval = 0;
00134             break;
00135         }
00136 
00137         m_dbHH = new MozABHHManager(GENERIC_FLAG_APPINFO_SUPPORTED | GENERIC_FLAG_CATEGORY_SUPPORTED,
00138                     m_remoteDB->m_Name,
00139                     m_remoteDB->m_Creator,
00140                     m_remoteDB->m_DbType,
00141                     m_remoteDB->m_DbFlags,
00142                     0,
00143                                              m_remoteDB->m_CardNum,
00144                     m_rSyncProperties.m_SyncType);
00145         if(!m_dbHH) {
00146             CONDUIT_LOG0(gFD, "Failed dbHH.\n");
00147             return GEN_ERR_LOW_MEMORY;
00148         }
00149 
00150         m_dbPC = new MozABPCManager();
00151         if(!m_dbPC) {
00152             if (m_dbHH)
00153                 delete m_dbHH;
00154             m_dbHH = NULL;
00155             CONDUIT_LOG0(gFD, "Failed dbPC.\n");
00156             return GEN_ERR_LOW_MEMORY;
00157         }
00158 
00159         char conduitName[32];
00160         GetConduitName(conduitName, 32);
00161         LogAddFormattedEntry(slSyncStarted, FALSE, "SYNC %s", conduitName);
00162         CONDUIT_LOG1(gFD, "slSyncStarted. SyncType=%d\n", m_rSyncProperties.m_SyncType);
00163 
00164         switch (m_rSyncProperties.m_SyncType) {
00165             case eFast:
00166                 retval = PerformFastSync();
00167                 if ((retval) && (retval == GEN_ERR_CHANGE_SYNC_MODE)){
00168                     if (m_rSyncProperties.m_SyncType == eHHtoPC)
00169                         retval = CopyHHtoPC();
00170                     else if (m_rSyncProperties.m_SyncType == ePCtoHH)
00171                         retval = CopyPCtoHH();
00172                 }
00173                 break;
00174             case eSlow:
00175                 retval = PerformSlowSync();  
00176                 if ((retval) && (retval == GEN_ERR_CHANGE_SYNC_MODE)){
00177                     if (m_rSyncProperties.m_SyncType == eHHtoPC)
00178                         retval = CopyHHtoPC();
00179                     else if (m_rSyncProperties.m_SyncType == ePCtoHH)
00180                         retval = CopyPCtoHH();
00181                 }
00182                 break;
00183             case eHHtoPC:
00184             case eBackup: 
00185                 retval = CopyHHtoPC();
00186                 break;
00187             case eInstall:
00188             case ePCtoHH:
00189             case eProfileInstall:
00190                 retval = CopyPCtoHH();
00191                 break;
00192             case eDoNothing:
00193                 break;
00194             default:
00195                 retval = GEN_ERR_SYNC_TYPE_NOT_SUPPORTED;
00196                 break;
00197         }
00198 
00199         if (retval) {
00200             LogAddFormattedEntry(slSyncAborted, FALSE, "retval=%d %s\n", retval, conduitName);
00201             CONDUIT_LOG1(gFD, "Sync finished with errors retval=%d\n", retval);
00202         }
00203         else {
00204             LogAddFormattedEntry(slSyncFinished, FALSE, "%s", conduitName);
00205             CONDUIT_LOG0(gFD, "Sync Finished retval=0\n");
00206         }
00207 
00208         // remove the handheld and PC manager
00209         if (m_dbHH)
00210             delete m_dbHH;
00211         m_dbHH = NULL;
00212         if (m_dbPC)
00213             delete m_dbPC;
00214         m_dbPC = NULL;
00215     }
00216 
00217     // Log the end time.
00218     time( &ltime );
00219     CONDUIT_LOG1(gFD, "------------ END OF PALM SYNC -------------- at %s\n", ctime(&ltime));
00220 
00221     // Unregister the conduit
00222     long retval2 = 0;
00223     if (m_ConduitHandle) {
00224         retval2 = SyncUnRegisterConduit(m_ConduitHandle);
00225         m_ConduitHandle = 0;
00226     }
00227 
00228     if (!retval)
00229         return retval2;
00230 
00231     return retval;
00232 }
00233 
00234 long CMozABConduitSync::GetRemoteDBInfo(int iIndex)
00235 {
00236     long retval = 0;
00237     if (m_rSyncProperties.m_RemoteDbList) {
00238         m_remoteDB = m_rSyncProperties.m_RemoteDbList[iIndex];
00239     } else {
00240         if (m_remoteDB)
00241             delete m_remoteDB;
00242 
00243         m_remoteDB = new CDbList; // deleted in d'ctor
00244         if (m_remoteDB) {
00245             m_remoteDB->m_Creator  = m_rSyncProperties.m_Creator; 
00246             m_remoteDB->m_DbFlags  = eRecord; // todo
00247             m_remoteDB->m_DbType   = m_rSyncProperties.m_DbType; 
00248             strncpy(m_remoteDB->m_Name, m_rSyncProperties.m_RemoteName[iIndex], sizeof(m_remoteDB->m_Name)-1);
00249             m_remoteDB->m_Name[sizeof(m_remoteDB->m_Name)-1] = '\0';
00250             m_remoteDB->m_Version   = 0;
00251             m_remoteDB->m_CardNum   = 0;
00252             m_remoteDB->m_ModNumber = 0;
00253             m_remoteDB->m_CreateDate= 0;
00254             m_remoteDB->m_ModDate   = 0;
00255             m_remoteDB->m_BackupDate= 0;
00256         } else {
00257             retval = GEN_ERR_LOW_MEMORY;
00258         }
00259     }
00260     return retval;
00261 }
00262 
00263 BOOL CMozABConduitSync::CategoryNameMatches(CPString &catName, CPString &cutOffMozABName, BOOL isPAB)
00264 {
00265   if (!catName.CompareNoCase(cutOffMozABName.GetBuffer(0)))
00266     return TRUE;
00267   else 
00268     return (isPAB && !catName.CompareNoCase("Personal"));
00269 }
00270 
00271 BOOL CMozABConduitSync::CategoryExists(CPString &mozABName, BOOL isPAB)
00272 {
00273     CPCategory * pCategory = m_dbHH->GetFirstCategory();
00274     // Palm only allows 15 chars for category names.
00275     CPString cutOffName;
00276     if (mozABName.Length() > 15)
00277         cutOffName = mozABName.Left(15);
00278     else
00279         cutOffName = mozABName;
00280     while (pCategory)
00281     {
00282         CPString catName(pCategory->GetName());
00283         if (CategoryNameMatches(catName, cutOffName, isPAB))
00284           return TRUE;
00285         // Process next category
00286         pCategory = m_dbHH->GetNextCategory();
00287     }
00288     return FALSE;
00289 }
00290 
00291 // this is done in separate thread since the main thread in this DLL
00292 // needs to call SyncYieldCycles(1) atleast once every 7 seconds
00293 DWORD WINAPI DoFastSync(LPVOID lpParameter)
00294 {
00295     CONDUIT_LOG0(gFD, "-- SYNC DoFastSync --\n");
00296 
00297     CMozABConduitSync * sync = (CMozABConduitSync * ) lpParameter;
00298     if(!sync || !sync->m_dbHH)
00299         return 0;
00300     
00301     BOOL initialHHSync = (sync->m_rSyncProperties.m_FirstDevice == eHH);
00302     if (initialHHSync) // if HH has been reset, copy everything on pc to hh.
00303       return sync->CopyPCtoHH();
00304 
00305     long retval=0;
00306     BOOL success = FALSE;
00307 
00308     DWORD mozABCount=0;
00309     LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla
00310     CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla
00311     CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla
00312     BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla
00313     BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync?
00314     DWORD mozABIndex;
00315 
00316     retval = sync->m_dbHH->OpenDB(FALSE);
00317     if (!retval)
00318         retval = sync->m_dbHH->LoadCategories();
00319 
00320     CONDUIT_LOG0(gFD, "Getting moz AB List ... ");
00321     if(!retval)
00322         retval = sync->m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList);
00323     CONDUIT_LOG1(gFD, "done getting moz AB List. retval = %d\n", retval);
00324 
00325     if (retval)
00326       return retval;
00327     
00328     // Create an array to help us identify addrbooks that have been deleted on Palm.
00329     DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount);
00330     if (!mozABSeen)
00331       return GEN_ERR_LOW_MEMORY;
00332     else
00333       memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount);
00334 
00335     CONDUIT_LOG1(gFD, "first device = %lx\n", sync->m_rSyncProperties.m_FirstDevice);
00336 
00337     // See if palm sync was performed before.
00338     for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00339       if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
00340       {
00341         neverDidPalmSyncBefore = FALSE;
00342         break;
00343       }
00344     
00345     // Log moz addrbooks.
00346     for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00347     {
00348       CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
00349                    mozABIndex, mozCatIndexList[mozABIndex], ! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag), 
00350                    mozABNameList[mozABIndex]->GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00351     }
00352 
00353     // For each category, try to find the corresponding AB in the moz AB list
00354     // and see if it has been synchronized before and take action accordingly.
00355     CPCategory * pCategory = sync->m_dbHH->GetFirstCategory();
00356     while (pCategory)
00357     {
00358         CPalmRecord ** recordListHH = NULL;
00359         DWORD recordCountHH=0;
00360 
00361         DWORD catID = pCategory->GetID();
00362         DWORD catIndex = pCategory->GetIndex();
00363         DWORD catFlags = pCategory->GetFlags();
00364         CPString catName(pCategory->GetName());
00365 
00366         CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID);
00367         BOOL abRenamed = FALSE;
00368         BOOL foundInABList=FALSE;
00369         for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00370         {
00371             // Palm only allows 15 chars for category names.
00372             CPString cutOffName;
00373             if (mozABNameList[mozABIndex]->Length() > 15)
00374                 cutOffName = mozABNameList[mozABIndex]->Left(15);
00375             else
00376                 cutOffName = *mozABNameList[mozABIndex];
00377 
00378             // if this category has been synchronized before
00379             if(catIndex == mozCatIndexList[mozABIndex]) 
00380             {
00381                 retval = sync->m_dbHH->LoadUpdatedRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00382                 CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' has been synced before\n", catID, catName.GetBuffer(0));
00383                 foundInABList = TRUE;
00384                 mozABSeen[mozABIndex] = TRUE; // mark it seen
00385                 // See if the name has been changed on Palm side. Note that if both
00386                 // Palm category and the corresponding moz addrbook are renamed then 
00387                 // Palm category name takes precedence.
00388                 if (!sync->CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00389                 {
00390                   abRenamed = TRUE;
00391                   CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' was renamed (from '%s') on Palm so do the same on moz\n", 
00392                     catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0));
00393                 }
00394                 break;
00395             }
00396 
00397             // if corresponding category exists but not synchronized before
00398             if(sync->CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00399             {
00400                 retval = sync->m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00401                 CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' has not been synced before\n", catID, catName.GetBuffer(0));
00402                 foundInABList = TRUE;
00403                 mozABSeen[mozABIndex] = TRUE; // mark it seen
00404                 break;
00405             }
00406         } // end of for
00407 
00408         if(!retval && foundInABList)
00409         {
00410           CPalmRecord ** recordListPC=NULL;
00411           DWORD recordCountPC=0;
00412           DWORD newRecAddedCount = 0;
00413           DWORD * newRecIDList=NULL;
00414           CONDUIT_LOG1(gFD, "  Syncing with moz AB with %d modified Palm record(s) ... ", recordCountHH);
00415           retval = sync->m_dbPC->SynchronizePCAB(catIndex, catID, catName,
00416                                                  recordCountHH, recordListHH,
00417                                                  &recordCountPC, &recordListPC);
00418           CONDUIT_LOG1(gFD, "Done syncing AB. retval=%lx.\n", retval);
00419 
00420           // SynchronizePCAB() returns a list of modified moz records so update those on Palm.
00421           if (!retval) {
00422               unsigned long i;
00423               newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD));
00424               if (recordCountPC > 0)
00425                 CONDUIT_LOG1(gFD, "  Updating Palm AB with %d modified moz record(s) ...\n", recordCountPC);
00426               for (i=0; i < recordCountPC; i++) {
00427                   if(!recordListPC[i])
00428                       continue;
00429                   CPalmRecord palmRec = *recordListPC[i];
00430                   palmRec.SetCategory(catIndex);
00431                   if(palmRec.GetAttribs() == ATTR_DELETED)
00432                   {
00433                     CONDUIT_LOG0(gFD, "    - deleting a record\n");
00434                                                        retval = sync->m_dbHH->DeleteARecord(palmRec);
00435                   }
00436                   else if(palmRec.GetAttribs() == ATTR_MODIFIED)
00437                   {
00438                     CONDUIT_LOG0(gFD, "    - modifying a record\n");
00439                                                        retval = sync->m_dbHH->UpdateARecord(palmRec);
00440                   }
00441                   else if(palmRec.GetAttribs() == ATTR_NEW) {
00442                       CONDUIT_LOG0(gFD, "    - adding a record\n");
00443                                                          retval = sync->m_dbHH->AddARecord(palmRec); // should we check existing recs?
00444                       if(!retval && (newRecAddedCount < recordCountPC)) {
00445                           newRecIDList[newRecAddedCount] = palmRec.GetID();
00446                           newRecAddedCount++;
00447                       }
00448                   }
00449                   delete recordListPC[i]; // once done with PC record, delete
00450                                        }
00451               if (recordCountPC > 0)
00452                 CONDUIT_LOG0(gFD, "  Done updating Palm AB.\n");
00453           }
00454           // the MozAB is now synchronized
00455           if(!retval)
00456               mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag;
00457           // delete the PC recordList now that palm is updated
00458           if(recordListPC)
00459               free(recordListPC);  
00460           // notify Mozilla that sync is done so that memory can be freed 
00461           success = retval ? FALSE : TRUE;
00462 
00463           if(newRecAddedCount) {
00464               if(newRecAddedCount != recordCountPC)
00465                   newRecIDList = (DWORD *) realloc(newRecIDList, newRecAddedCount);
00466               retval = sync->m_dbPC->NotifySyncDone(success, catIndex, newRecAddedCount, newRecIDList);
00467           }
00468           else 
00469               retval = sync->m_dbPC->NotifySyncDone(success);
00470 
00471           if(newRecIDList)
00472               free(newRecIDList);
00473 
00474           // See if it was renamed on palm.
00475           if (abRenamed)
00476           {
00477             // We should not rename personal and collected address books here.
00478             if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) &&
00479               mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL))
00480             {
00481               CONDUIT_LOG0(gFD, "  Renaming AB ... ");
00482               retval = sync->m_dbPC->RenamePCAB(catIndex, catName, *mozABUrlList[mozABIndex]);
00483               CONDUIT_LOG1(gFD, "Done renaming AB. retval=%d.\n", retval);
00484             }
00485           }
00486         }
00487         
00488         // If this category can't be found in the moz AB list then two cases here:
00489         //    1. If catFlags is not CAT_DIRTY then this category has been deleted
00490         //       on moz so remove it from palm side.
00491         //    2. else, if we never did palm sync on moz before then it's a new one
00492         //       on palm. So create a new AB in moz with all records in this category
00493         //       (even if it's an empty AB).
00494         if(!retval && !foundInABList) 
00495         {
00496             if (catFlags != CAT_DIRTY && !neverDidPalmSyncBefore && !initialHHSync)
00497             {
00498               BOOL abDeleted = sync->m_dbPC->PCABDeleted(catName);
00499               if (abDeleted)
00500               {
00501                 CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is removed from moz and needs to be removed from palm\n", catID, catName.GetBuffer(0));
00502                 CONDUIT_LOG0(gFD, "  Deleting AB from Palm ... ");
00503                 retval = sync->m_dbHH->DeleteCategory(catIndex, FALSE);
00504                 CONDUIT_LOG1(gFD, "Done deleting AB from Palm. retval=%d.\n", retval);
00505               }
00506             }
00507             else
00508             {
00509               CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is new on palm and needs to be added to moz\n", catID, catName.GetBuffer(0));
00510               retval = sync->m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00511               CONDUIT_LOG1(gFD, "  Creating new moz AB with %d Palm record(s) ... ", recordCountHH);
00512               if(!retval)
00513                 retval = sync->m_dbPC->AddRecords(FALSE, catIndex, catName, recordCountHH, recordListHH);
00514               CONDUIT_LOG1(gFD, "Done creating new moz AB. retval=%d.\n", retval);
00515             }
00516         }
00517 
00518         // delete and free HH records and recordList once synced
00519         if(recordListHH) {
00520             CPalmRecord ** tempRecordListHH = recordListHH;
00521             for(DWORD i=0; i < recordCountHH; i++) 
00522             {
00523                 if(*tempRecordListHH)
00524                     delete *tempRecordListHH;
00525                 tempRecordListHH++;
00526             }
00527             free(recordListHH);
00528         }
00529 
00530         // Process next category
00531         pCategory = sync->m_dbHH->GetNextCategory();
00532     } // end of while
00533 
00534     // Deal with any Moz AB not existing in Palm, ones not sync'ed above,
00535     // and the case where Palm ABs have been deleted.
00536     for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00537     {
00538         if((mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag || neverDidPalmSyncBefore || initialHHSync) && !sync->CategoryExists(*mozABNameList[mozABIndex],  mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00539         {
00540             CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s' doesn't exist on Palm so needs to be added to palm\n",
00541                     mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0));
00542             CPalmRecord ** recordListPC=NULL;
00543             DWORD recordCountPC=0;
00544             DWORD * newRecIDList=NULL;
00545             CPCategory cat;
00546             retval = sync->m_dbPC->LoadAllRecords(*mozABNameList[mozABIndex],
00547                                                                 &recordCountPC, &recordListPC);
00548             if(!retval) 
00549             {
00550                 if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00551                   cat.SetName(mozABNameList[mozABIndex]->GetBuffer(0));
00552                 else
00553                   cat.SetName("Personal");
00554 
00555                 CONDUIT_LOG1(gFD, "  Creating new Palm AB with %d record(s) ... ", recordCountPC);
00556                 retval = sync->m_dbHH->AddCategory(cat);
00557                 CONDUIT_LOG2(gFD, "Done creating new Palm AB, new category index=%d. retval=%d.\n", cat.GetIndex(), retval);
00558                 if(!retval) 
00559                 {
00560                     CONDUIT_LOG1(gFD, "  Adding %d record(s) to new Palm AB ... ", recordCountPC);
00561                     newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD));
00562                     for (unsigned long i=0; i < recordCountPC; i++) 
00563                     {
00564                         if(!recordListPC[i])
00565                             continue;
00566                         CPalmRecord palmRec = *recordListPC[i];
00567                         palmRec.SetCategory(cat.GetIndex());
00568                         retval = sync->m_dbHH->AddARecord(palmRec); // should we check existing recs?
00569                         newRecIDList[i] = palmRec.GetID();
00570                         delete recordListPC[i]; // delete the record now that it is used
00571                     }
00572                     CONDUIT_LOG0(gFD, "Done adding new records to new Palm AB.\n");
00573                 }
00574                 else
00575                   CONDUIT_LOG1(gFD, "Creating new Palm AB failed. retval=%d.\n", retval);
00576             }
00577             else
00578               CONDUIT_LOG1(gFD, "  Loading moz AB records failed so can't create new Palm AB. retval=%d.\n", retval);
00579 
00580 
00581             // the MozAB is now synchronized
00582             if(!retval)
00583               mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag;
00584             // delete the recordList now that palm is updated
00585             if(recordListPC)
00586                 free(recordListPC);  
00587             // notify Mozilla that sync is done so that memory can be freed 
00588             if(!retval)
00589                 success = TRUE;
00590             else
00591             {
00592                 success = FALSE;
00593                 recordCountPC=0;
00594             }
00595             retval = sync->m_dbPC->NotifySyncDone(success, cat.GetIndex(), recordCountPC, newRecIDList);
00596             if(newRecIDList)
00597                 free(newRecIDList);
00598 
00599             // Lastly, update the AB with new category index and mod time.
00600             retval = sync->m_dbPC->UpdatePCABSyncInfo(success ? cat.GetIndex() : -1, *mozABNameList[mozABIndex]);
00601         }
00602         else if (!mozABSeen[mozABIndex] && !neverDidPalmSyncBefore && !initialHHSync)
00603         {
00604           // We should not delete personal and collected address books here. Rather,
00605           // reset the mod time so next time we can sync them back to Palm again.
00606           // Note: make sure the moz addrbook has been synced before to avoid the case
00607           // where early sync failed and we delete this un-synced addrbook by mistake.
00608           if (mozCatIndexList[mozABIndex] > -1 &&
00609               ! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) &&
00610               mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL))
00611           {
00612             CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s' is removed on Palm and needs to be removed from moz\n", 
00613                     mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0));
00614             CONDUIT_LOG0(gFD, "  Deleting AB from moz ... ");
00615             retval = sync->m_dbPC->DeletePCAB(mozCatIndexList[mozABIndex], *mozABNameList[mozABIndex], *mozABUrlList[mozABIndex]);
00616             CONDUIT_LOG1(gFD, "Done deleting AB from moz. retval=%d.\n", retval);
00617           }
00618           else
00619           {
00620             CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s', is removed on Palm but only need to reset sync info on moz\n", 
00621                     mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0));
00622             // Reset category index and mod time.
00623             CONDUIT_LOG0(gFD, "  Resetting AB info on moz ... ");
00624             retval = sync->m_dbPC->UpdatePCABSyncInfo(-1, *mozABNameList[mozABIndex]);
00625             CONDUIT_LOG1(gFD, "  Done resetting AB info on moz. retval=%d.\n", retval);
00626           }
00627         }
00628     } // end of mozAB not existing in Palm for loop
00629 
00630     // Purge deleted Palm record permanently (in case they were logically deleted).
00631     sync->m_dbHH->PurgeDeletedRecs();
00632 
00633     // Free stuff we allocated.
00634     CoTaskMemFree(mozABSeen);
00635     
00636     // update category info in HH
00637     sync->m_dbHH->CompactCategoriesToHH();
00638 
00639     // close the HH DB once synced
00640     retval = sync->m_dbHH->CloseDB(FALSE);
00641 
00642     return retval;
00643 }
00644 
00645 long CMozABConduitSync::PerformFastSync()
00646 {
00647     CONDUIT_LOG0(gFD, "-- SYNC Palm -> PerformFastSync --\n");
00648 
00649     DWORD ThreadId;
00650     DWORD threadExitCode;
00651     HANDLE hThread = CreateThread(NULL, 0, DoFastSync, this, 0, &ThreadId);
00652     while (WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT) {
00653         SyncYieldCycles(1); // every sec call this for feedback & keep Palm connection alive 
00654         continue;
00655     }
00656     
00657     // get and return thread's return code if available
00658     BOOL ret = GetExitCodeThread(hThread, &threadExitCode);
00659     if (!ret)
00660         return GetLastError();
00661     // thread failed
00662     CONDUIT_LOG1(gFD, "GetExitCodeThread failed return code = %d\n", threadExitCode);
00663     return threadExitCode;
00664 }
00665 
00666 
00667 long CMozABConduitSync::PerformSlowSync()
00668 {
00669     // we take care of first time sync in fast sync in an optimized way
00670     return PerformFastSync();
00671 }
00672 
00673 long CMozABConduitSync::CopyHHtoPC()
00674 {
00675     long retval=0;
00676     BOOL success = FALSE;
00677     CONDUIT_LOG0(gFD, "-- SYNC Palm -> Destkop --\n");
00678 
00679     if(!m_dbHH)
00680         return retval;
00681     
00682     DWORD mozABCount=0;
00683     LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla
00684     CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla
00685     CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla
00686     BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla
00687     BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync?
00688     DWORD mozABIndex;
00689 
00690     retval = m_dbHH->OpenDB(FALSE);
00691     if (!retval)
00692         retval = m_dbHH->LoadCategories();
00693 
00694     CONDUIT_LOG0(gFD, "Getting moz AB List ... ");
00695     if(!retval)
00696         retval = m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList);
00697 
00698     CONDUIT_LOG1(gFD, "Done getting moz AB List. retval = %d\n", retval);
00699     if (retval)
00700       return retval;
00701     
00702     // Create an array to help us identify addrbooks that have been deleted on Palm.
00703     DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount);
00704     if (!mozABSeen)
00705       return GEN_ERR_LOW_MEMORY;
00706     else
00707       memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount);
00708 
00709     // See if palm sync was performed before.
00710     for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00711       if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
00712       {
00713         neverDidPalmSyncBefore = FALSE;
00714         break;
00715       }
00716     
00717     // Log moz addrbooks.
00718     for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00719     {
00720       CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
00721                    mozABIndex, mozCatIndexList[mozABIndex], !(mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag), 
00722                    mozABNameList[mozABIndex]->GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00723     }
00724 
00725     // For each category, try to find the corresponding AB in the moz AB list
00726     // and overwrite it with the HH category.
00727     CPCategory * pCategory = m_dbHH->GetFirstCategory();
00728     while (pCategory)
00729     {
00730         CPalmRecord ** recordListHH = NULL;
00731         DWORD recordCountHH=0;
00732 
00733         DWORD catID = pCategory->GetID();
00734         DWORD catIndex = pCategory->GetIndex();
00735         DWORD catFlags = pCategory->GetFlags();
00736         CPString catName(pCategory->GetName());
00737 
00738         CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID);
00739         BOOL abRenamed = FALSE;
00740         BOOL foundInABList=FALSE;
00741         for(mozABIndex = 0; mozABIndex < mozABCount; mozABIndex++)
00742         {
00743             // Palm only allows 15 chars for category names.
00744             CPString cutOffName;
00745             if (mozABNameList[mozABIndex]->Length() > 15)
00746                 cutOffName = mozABNameList[mozABIndex]->Left(15);
00747             else
00748                 cutOffName = *mozABNameList[mozABIndex];
00749 
00750             // if this category has been synchronized before, check if it has been renamed
00751             if(catIndex == mozCatIndexList[mozABIndex]) 
00752             {
00753                   CONDUIT_LOG4(gFD, "Category index = %d, name = '%s' moz ab name = %s has been synced before uri = %s\n", 
00754                     catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00755                 foundInABList = TRUE;
00756                 mozABSeen[mozABIndex] = TRUE; // mark it seen
00757                 // See if the name has been changed on Palm side. Note that if both
00758                 // Palm category and the corresponding moz addrbook are renamed then 
00759                 // Palm category name takes precedence.
00760                 if (!CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00761                 {
00762                   abRenamed = TRUE;
00763                   CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' was renamed (from '%s') on Palm so do the same on moz\n", 
00764                     catID, catName.GetBuffer(0), mozABNameList[mozABIndex]->GetBuffer(0));
00765                 }
00766                 break;
00767             }
00768             // if corresponding category exists 
00769             if (CategoryNameMatches(catName, cutOffName, mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00770             {
00771                 retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00772                 CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' matches moz ab %s\n", catID, catName.GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00773                 foundInABList = TRUE;
00774                 mozABSeen[mozABIndex] = TRUE; // mark it seen
00775                 break;
00776             }
00777             else
00778                 CONDUIT_LOG3(gFD, "Category index = %d, name = '%s' doesn't match moz ab %s\n", catID, catName.GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00779 
00780         } // end of for
00781 
00782         // we've got a matching moz AB. So, just delete all the cards in the Moz AB and copy over all the cards
00783         // in the HH category.
00784         if(!retval && foundInABList)
00785         {
00786           CPalmRecord ** recordListPC=NULL;
00787           DWORD * newRecIDList=NULL;
00788 //          retval = m_dbPC->DeletePCAB(mozCatIndexList[mozABIndex], *mozABNameList[mozABIndex], *mozABUrlList[mozABIndex]);
00789           retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00790           CONDUIT_LOG2(gFD, "  Creating new moz AB %s with %d Palm record(s) ... ", mozABNameList[mozABIndex]->GetBuffer(0), recordCountHH);
00791           if(!retval)
00792             retval = m_dbPC->AddRecords(TRUE, catIndex, *mozABNameList[mozABIndex], recordCountHH, recordListHH);
00793 
00794           CONDUIT_LOG1(gFD, "Done creating new moz AB. retval=%d.\n", retval);
00795           // the MozAB is now synchronized
00796           if(!retval)
00797               mozDirFlagsList[mozABIndex] &= ~kFirstTimeSyncDirFlag;
00798           // delete the PC recordList now that palm is updated
00799           if(recordListPC)
00800               free(recordListPC);  
00801           // notify Mozilla that sync is done so that memory can be freed 
00802           success = retval ? FALSE : TRUE;
00803 
00804           retval = m_dbPC->NotifySyncDone(success);
00805 
00806           if(newRecIDList)
00807               free(newRecIDList);
00808 
00809           // See if it was renamed on palm.
00810           if (abRenamed)
00811           {
00812             // We should not rename personal and collected address books here.
00813             if (! (mozDirFlagsList[mozABIndex] & kIsPabDirFlag) &&
00814               mozABUrlList[mozABIndex]->CompareNoCase(COLLECTED_ADDRBOOK_URL))
00815             {
00816               CONDUIT_LOG0(gFD, "  Renaming AB ... ");
00817               retval = m_dbPC->RenamePCAB(catIndex, catName, *mozABUrlList[mozABIndex]);
00818               CONDUIT_LOG1(gFD, "Done renaming AB. retval=%d.\n", retval);
00819             }
00820           }
00821         }
00822         
00823         // If this category can't be found in the moz AB list, then
00824         // create a new AB in moz with all records in this category
00825         //  (even if it's an empty AB).
00826         if(!retval && !foundInABList) 
00827         {
00828             CONDUIT_LOG2(gFD, "Category index = %d, name = '%s' is new on palm and needs to be added to moz\n", catID, catName.GetBuffer(0));
00829             retval = m_dbHH->LoadAllRecordsInCategory(catIndex, &recordListHH, &recordCountHH);
00830             CONDUIT_LOG2(gFD, "  Creating new moz AB %s with %d Palm record(s) ... ", catName.GetBuffer(0), recordCountHH);
00831             if(!retval)
00832             {
00833               CPString mozABName;
00834 
00835               retval = m_dbPC->AddRecords(FALSE, catIndex, catName, recordCountHH, recordListHH);
00836             }
00837             CONDUIT_LOG2(gFD, "Done creating new moz AB %s - retval=%d.\n", catName.GetBuffer(0), retval);
00838         }
00839 
00840         // delete and free HH records and recordList once synced
00841         if(recordListHH) 
00842         {
00843             CPalmRecord ** tempRecordListHH = recordListHH;
00844             for(DWORD i=0; i < recordCountHH; i++) 
00845             {
00846                 delete *tempRecordListHH;
00847                 tempRecordListHH++;
00848             }
00849             free(recordListHH);
00850         }
00851 
00852         // Process next category
00853         pCategory = m_dbHH->GetNextCategory();
00854     } // end of while
00855 
00856     // Free stuff we allocated.
00857     CoTaskMemFree(mozABSeen);
00858     
00859     // update category info in HH
00860     m_dbHH->CompactCategoriesToHH();
00861 
00862     // close the HH DB once synced
00863     retval = m_dbHH->CloseDB(FALSE);
00864 
00865     return retval;
00866 }
00867 
00868 long CMozABConduitSync::CopyPCtoHH()
00869 {
00870     long retval=0;
00871     BOOL success = FALSE;
00872 
00873     CONDUIT_LOG0(gFD, "-- SYNC Destkop-> Palm --\n");
00874 
00875     if(!m_dbHH)
00876         return retval;
00877     
00878     DWORD mozABCount=0;
00879     LONG * mozCatIndexList = NULL; // freed by MSCOM/Mozilla
00880     CPString ** mozABNameList = NULL; // freed by MSCOM/Mozilla
00881     CPString ** mozABUrlList = NULL; // freed by MSCOM/Mozilla
00882     BOOL * mozDirFlagsList = NULL; // freed by MSCOM/Mozilla
00883     BOOL neverDidPalmSyncBefore = TRUE; // 1st time palm sync?
00884     DWORD mozABIndex;
00885 
00886     retval = m_dbHH->OpenDB(FALSE);
00887     if (!retval)
00888         retval = m_dbHH->LoadCategories();
00889 
00890     CONDUIT_LOG0(gFD, "Getting moz AB List ... ");
00891     if(!retval)
00892         retval = m_dbPC->GetPCABList(&mozABCount, &mozCatIndexList, &mozABNameList, &mozABUrlList, &mozDirFlagsList);
00893 
00894     if (retval)
00895       return retval;
00896     CONDUIT_LOG0(gFD, "Done getting moz AB List. \n");
00897     
00898     // Create an array to help us identify addrbooks that have been deleted on Palm.
00899     DWORD *mozABSeen = (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * mozABCount);
00900     if (!mozABSeen)
00901       return GEN_ERR_LOW_MEMORY;
00902     else
00903       memset(mozABSeen, FALSE, sizeof(DWORD) * mozABCount);
00904 
00905     // See if palm sync was performed before.
00906     for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00907       if (! (mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag))
00908       {
00909         neverDidPalmSyncBefore = FALSE;
00910         break;
00911       }
00912     
00913     // Log moz addrbooks.
00914     for (mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00915     {
00916       CONDUIT_LOG5(gFD, "Moz AB[%d] category index/synced=%d/%d, name= '%s', url= '%s'\n",
00917                    mozABIndex, mozCatIndexList[mozABIndex], !(mozDirFlagsList[mozABIndex] & kFirstTimeSyncDirFlag), 
00918                    mozABNameList[mozABIndex]->GetBuffer(0), mozABUrlList[mozABIndex]->GetBuffer(0));
00919     }
00920 
00921     // For each category, try to find the corresponding AB in the moz AB list
00922     // and see if it has been synchronized before and take action accordingly.
00923     CPCategory * pCategory = m_dbHH->GetFirstCategory();
00924     while (pCategory)
00925     {
00926         CPalmRecord ** recordListHH = NULL;
00927         DWORD recordCountHH=0;
00928 
00929         DWORD catID = pCategory->GetID();
00930         DWORD catIndex = pCategory->GetIndex();
00931         DWORD catFlags = pCategory->GetFlags();
00932         CPString catName(pCategory->GetName());
00933 
00934         CONDUIT_LOG3(gFD, "\nProcessing Palm AB '%s' (catIndex/catId) = (%d/%d)... \n", catName.GetBuffer(0), catIndex, catID);
00935         BOOL abRenamed = FALSE;
00936         BOOL foundInABList=FALSE;
00937 
00938         retval = m_dbHH->DeleteCategory(catIndex, FALSE); // delete the category - we'll recreate from moz ab.
00939 
00940         // Process next category
00941         pCategory = m_dbHH->GetNextCategory();
00942     } // end of while
00943 
00944     // Deal with any Moz AB not existing in Palm, ones not sync'ed above,
00945     // and the case where Palm ABs have been deleted.
00946     for(mozABIndex=0; mozABIndex<mozABCount; mozABIndex++)
00947     {
00948         CONDUIT_LOG3(gFD, "\nMoz AB[%d] category index = %d, name = '%s' doesn't exist on Palm so needs to be added to palm\n",
00949                 mozABIndex, mozCatIndexList[mozABIndex], mozABNameList[mozABIndex]->GetBuffer(0));
00950         CPalmRecord ** recordListPC=NULL;
00951         DWORD recordCountPC=0;
00952         DWORD * newRecIDList=NULL;
00953         CPCategory cat;
00954         retval = m_dbPC->LoadAllRecords(*mozABNameList[mozABIndex],
00955                                                             &recordCountPC, &recordListPC);
00956         if(!retval) 
00957         {
00958             if ((mozDirFlagsList[mozABIndex] & kIsPabDirFlag))
00959               cat.SetName("Personal");
00960             else
00961               cat.SetName(mozABNameList[mozABIndex]->GetBuffer(0));
00962             CONDUIT_LOG1(gFD, "  Creating new Palm AB with %d record(s) ... ", recordCountPC);
00963             retval = m_dbHH->AddCategory(cat);
00964             CONDUIT_LOG2(gFD, "Done creating new Palm AB, new category index=%d. retval=%d.\n", cat.GetIndex(), retval);
00965             if(!retval) {
00966                 CONDUIT_LOG1(gFD, "  Adding %d record(s) to new Palm AB ... ", recordCountPC);
00967                 newRecIDList = (DWORD *) calloc(recordCountPC, sizeof(DWORD));
00968                 for (unsigned long i=0; i < recordCountPC; i++) 
00969                 {
00970                     if(!recordListPC[i])
00971                         continue;
00972                     CPalmRecord palmRec = *recordListPC[i];
00973                     palmRec.SetCategory(cat.GetIndex());
00974                     retval = m_dbHH->AddARecord(palmRec); // should we check existing recs?
00975                     newRecIDList[i] = palmRec.GetID();
00976                     delete recordListPC[i]; // delete the record now that it is used
00977                 }
00978                 CONDUIT_LOG0(gFD, "Done adding new records to new Palm AB.\n");
00979             }
00980             else
00981               CONDUIT_LOG1(gFD, "Creating new Palm AB failed. retval=%d.\n", retval);
00982         }
00983         else
00984           CONDUIT_LOG1(gFD, "  Loading moz AB records failed so can't create new Palm AB. retval=%d.\n", retval);
00985 
00986 
00987         // delete the recordList now that palm is updated
00988         if(recordListPC)
00989             free(recordListPC);  
00990         // notify Mozilla that sync is done so that memory can be freed 
00991         if(!retval)
00992             success = TRUE;
00993         else
00994         {
00995             success = FALSE;
00996             recordCountPC=0;
00997         }
00998         retval = m_dbPC->NotifySyncDone(success, cat.GetIndex(), recordCountPC, newRecIDList);
00999         if(newRecIDList)
01000             free(newRecIDList);
01001 
01002         // Lastly, update the AB with new category index and mod time.
01003         retval = m_dbPC->UpdatePCABSyncInfo(success ? cat.GetIndex() : -1, *mozABNameList[mozABIndex]);
01004     } // end of mozAB not existing in Palm for loop
01005 
01006     // Purge deleted Palm record permanently (in case they were logically deleted).
01007     m_dbHH->PurgeDeletedRecs();
01008 
01009     // Free stuff we allocated.
01010     CoTaskMemFree(mozABSeen);
01011     
01012     // update category info in HH
01013     m_dbHH->CompactCategoriesToHH();
01014 
01015     // close the HH DB once synced
01016     retval = m_dbHH->CloseDB(FALSE);
01017 
01018     return retval;
01019 }
01020