예제 #1
0
/* Add Plucker document */
void AddDocument
    (
    DocumentInfo*   docInfo,
    Char*           volumeLabel
    )
    /* THROWS */
{
    MemHandle   handle;
    UInt8*      dataPtr;
    UInt16      infoSize;
    UInt16      dataSize;
    UInt16      dbIndex;

    infoSize = sizeof *docInfo - 2 * sizeof( UInt16) - sizeof( Char* );
    if ( docInfo->location == RAM )
        dataSize = 0;
    else
        dataSize = StrLen( docInfo->filename ) + StrLen( volumeLabel ) + 2;

    dbIndex = dmMaxRecordIndex;
    handle  = NewRecord( plkrDocList, &dbIndex, infoSize + dataSize );
    THROW_IF( handle == NULL, DmGetLastErr() );
    dataPtr = MemHandleLock( handle );
    DmWrite( dataPtr, 0, docInfo, infoSize );
    if ( docInfo->location != RAM ) {
        DmWrite( dataPtr, infoSize, docInfo->filename,
            StrLen( docInfo->filename ) + 1 );
        DmWrite( dataPtr, infoSize + StrLen( docInfo->filename ) + 1,
            volumeLabel, StrLen( volumeLabel ) + 1 );
    }
    MemHandleUnlock( handle );
    CloseRecord( handle, true );
}
예제 #2
0
파일: bookmarks.c 프로젝트: kjk/noah-palm
/* Delete a bookmark for a given word in a bookmark database indicated by sortType */
static Err DeleteBookmarkInDB(AppContext* appContext, BookmarkSortType sortType, char *word)
{
    Err          err;
    UInt16       recsCount, i;
    MemHandle    recHandle;
    char *       wordInRecord;

    err = OpenBookmarksDB(appContext, sortType);
    if ( errNone != err )
        return err;

    recsCount = DmNumRecords(appContext->bookmarksDb);
    for (i = 0; i < recsCount; i++)
    {
        recHandle = DmQueryRecord(appContext->bookmarksDb, i);
        if (!recHandle)
        {
            err = DmGetLastErr();
            goto OnError;
        }

        wordInRecord = (char*)MemHandleLock(recHandle);
        Assert(wordInRecord);
        if (0 == StrCompare(wordInRecord, word))
        {
            MemHandleUnlock(recHandle);
            DmRemoveRecord(appContext->bookmarksDb, i);
            break;
        }
        MemHandleUnlock(recHandle);
    }
OnError:
    CloseBookmarksDB(appContext);
    return err;
}
예제 #3
0
/* Finds and opens database,
 * calls plugin specific code to create new item,
 * then fills in GoTo parameters.
 */
static UInt16
PickBooger(KleenexPtr kleenexP)
{
    DmOpenRef dbR;
    UInt32 creatorID;
    UInt16 cardNo;
    LocalID dbID;
    Boolean closedb = false;
    UInt16 err, index;
    Char name[dmDBNameLength];

    /* Check for the correct version */
    if (!((kleenexP->version) & IBVERSION_PICTURE))
        return (boogerErrorVersionMismatch);

    /* Open the database */
    cardNo = 0;
    if (!(dbID = DmFindDatabase(cardNo, "DiddleIDB")))
        return 1;

    if ((dbR = DmOpenDatabase(cardNo, dbID, dmModeReadWrite))) {
        closedb = true;

    } else if (DmGetLastErr() == dmErrAlreadyOpenForWrites) {
        dbR = NULL;
        while ((dbR = DmNextOpenDatabase(dbR))) {
            DmOpenDatabaseInfo(dbR, &dbID, NULL, NULL, &cardNo, NULL);
            DmDatabaseInfo(cardNo, dbID, name, NULL, NULL, NULL, NULL, NULL,
                           NULL, NULL, NULL, NULL, &creatorID);
            if (!StrCompare(name, "DiddleIDB") && (creatorID == DB_CREATOR))
                break;
        }
        if (!dbR)
            return 1;
    }

    /* Call plugin specific routine to create item in database */
    err = DoTheBoogie(kleenexP, dbR, &index);

    /* Close the database */
    if (closedb)
        DmCloseDatabase(dbR);

    /* Did it work? */
    if (err)
        return (1);

    /* Load the GoTo parameters */
    if (!(kleenexP->booger.cmdPBP = MemPtrNew(sizeof(GoToParamsType))))
        return (1);
    MemSet(kleenexP->booger.cmdPBP, sizeof(GoToParamsType), 0);
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->dbCardNo = cardNo;
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->dbID = dbID;
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->recordNum = index;
    MemPtrSetOwner(kleenexP->booger.cmdPBP, 0);

    return (errNone);
}
예제 #4
0
/* Finds and opens database,
 * calls plugin specific code to create new item,
 * then fills in GoTo parameters.
 */
static UInt16
PickBooger(KleenexPtr kleenexP)
{
    DmOpenRef dbR;
    DmSearchStateType searchstate;
    UInt32 creatorID, dbtype;
    UInt16 cardNo;
    LocalID dbID;
    Boolean closedb = false;
    UInt16 err, index;

    /* Check for the correct version */
    if (!((kleenexP->version) & IBVERSION_ORIG))
        return (boogerErrorVersionMismatch);

    /* Open the database */
    if (DmGetNextDatabaseByTypeCreator(true, &searchstate, DB_TYPE,
                                       DB_CREATOR, true, &cardNo, &dbID))
        return (1);

    if ((dbR = DmOpenDatabase(cardNo, dbID, dmModeReadWrite))) {
        closedb = true;

    } else if (DmGetLastErr() == dmErrAlreadyOpenForWrites) {
        dbR = NULL;
        while ((dbR = DmNextOpenDatabase(dbR))) {
            DmOpenDatabaseInfo(dbR, &dbID, NULL, NULL, &cardNo, NULL);
            DmDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL, NULL,
                           NULL, NULL, NULL, &dbtype, &creatorID);
            if ((dbtype == DB_TYPE) && (creatorID == DB_CREATOR))
                break;
        }
        if (!dbR)
            return (1);
    }

    /* Call plugin specific routine to create item in database */
    err = DoTheBoogie(kleenexP, dbR, &index);

    /* Close the database */
    if (closedb)
        DmCloseDatabase(dbR);

    /* Did it work? */
    if (err)
        return (1);

    /* Load the GoTo parameters */
    if (!(kleenexP->booger.cmdPBP = MemPtrNew(sizeof(GoToParamsType))))
        return (1);
    MemSet(kleenexP->booger.cmdPBP, sizeof(GoToParamsType), 0);
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->dbCardNo = cardNo;
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->dbID = dbID;
    ((GoToParamsType *)(kleenexP->booger.cmdPBP))->recordNum = index;
    MemPtrSetOwner(kleenexP->booger.cmdPBP, 0);

    return (errNone);
}
예제 #5
0
/* DESCRIPTION:  Get the application's database.  Open the database if it
 * exists, create it if neccessary.
 *
 * PARAMETERS:   *dbPP - pointer to a database ref (DmOpenRef) to be set
 *					  mode - how to open the database (dmModeReadWrite)
 *
 * RETURNED:     Err - zero if no error, else the error
 */
static Err getPalmanoDatabase (DmOpenRef *dbPP, UInt16 mode)
{
  Err error = 0;
  DmOpenRef dbP;

  *dbPP = NULL;
  
  // Find the application's data file.  If it doesn't exist create it.
  dbP = DmOpenDatabaseByTypeCreator (sysFileTMidi, pmnoCreatorDB, mode);

  if (!dbP) {
    debugPrintf("getPalmanoDatabase(): Can't open database, code %d\n",
		DmGetLastErr());
    error = DmCreateDatabase (0, "palmano", pmnoCreatorDB, sysFileTMidi, false);

    if (error) {
      debugPrintf("getPalmanoDatabase(): DmCreateDatabase exit code %d\n", error);
      ErrAlert(error);
      return error;
    }
    else
      debugPrintf("getPalmanoDatabase(): create DB ok\n");

    dbP = DmOpenDatabaseByTypeCreator(sysFileTMidi, pmnoCreatorDB, mode);
    if (!dbP) {
      debugPrintf("getPalmanoDatabase(): Can't open database after create, code %d\n",
		  DmGetLastErr());
      ErrAlert(DmGetLastErr());      
      return DmGetLastErr();
    } else
      debugPrintf("getPalmanoDatabase(): second open DB ok\n");


    // Set the backup bit.  This is to aid syncs with non Palm software.
    //    ToDoSetDBBackupBit(dbP);
		
  } else
    debugPrintf("getPalmanoDatabase(): open DB ok\n");


  *dbPP = dbP;
  return 0;
}
예제 #6
0
// Open preferences database and find a record that contains preferences.
// Return errNone if opened succesfully, otherwise an error:
//   psErrNoPrefDatabase - pref database couldn't be found
// devnote: it scans through all records even though we only store preferences
// in one record because I want to be able to use preferences database used
// in earlier versions of Noah Pro/Thes.
Err PrefsStoreReader::ErrOpenPrefsDatabase()
{
    if (_db)
    {
        Assert(_recHandle);
        Assert(_recData);
        return errNone;
    }

    // we already tried to open the database but couldn't, so don't try again
    if (_fDbNotFound)
        return psErrNoPrefDatabase;

    LocalID dbId;
    Err err = ErrFindDatabaseByNameTypeCreator(_dbName, _dbType, _dbCreator, &dbId);
    if (dmErrCantFind==err)
    {
        err = psErrNoPrefDatabase;
        goto ExitAndMarkNotFound;
    }
    if (err)
        goto ExitAndMarkNotFound;
    Assert(0!=dbId);

    _db = DmOpenDatabase(0, dbId, dmModeReadWrite);
    if (!_db)
    {
        err = DmGetLastErr();
        Assert(err);
        goto ExitAndMarkNotFound;
    }

    UInt16 recsCount = DmNumRecords(_db);
    for (UInt16 recNo = 0; recNo < recsCount; recNo++)
    {
        _recHandle = DmQueryRecord(_db, recNo);
        _recData = (unsigned char*)MemHandleLock(_recHandle);
        if ( (MemHandleSize(_recHandle)>=4) && FValidPrefsStoreRecord(_recData) )
        {
            // we found the record with prefernces so remember _recData and _recHandle
            // those must be freed in destructor
            return errNone;
        }
        MemHandleUnlock(_recHandle);
        _recHandle = NULL;
    }

    DmCloseDatabase(_db);
    _db = 0;
    err = psErrNoPrefDatabase;
ExitAndMarkNotFound:
    _fDbNotFound = true;
    return err;
}
예제 #7
0
/************************************************************
 *
 *  FUNCTION: ApptGetRecord
 *
 *  DESCRIPTION: Get a record from a Appointment Database
 *
 *  PARAMETERS: database pointer
 *                  database index
 *                  database record
 *
 *  RETURNS: ##0 if successful, errorcode if not
 *
 *  CREATED: 1/25/95 
 *
 *  BY: Roger Flores
 *
 *************************************************************/
Err ApptGetRecord (DmOpenRef dbP, UInt16 index, ApptDBRecordPtr r,
                   MemHandle * handleP) {
    MemHandle handle;
    ApptPackedDBRecordPtr src;

    handle = DmQueryRecord(dbP, index);
    ErrFatalDisplayIf(DmGetLastErr(), "Error Querying record");

    src = (ApptPackedDBRecordPtr) MemHandleLock (handle);

    if (DmGetLastErr()) {
        *handleP = 0;
        return DmGetLastErr();
    }

    ApptUnpack(src, r);

    *handleP = handle;
    return 0;
}
예제 #8
0
/*
** Map record index to grid coordinates.
*/
static void MapIndexToCoordinates(UInt16* dbI, UInt16* x, UInt16* y) {
  UInt16 pos;

  if (*dbI == noRecordSelected)
    *dbI = d.top_visible_record;

  pos = DmPositionInCategory(d.dbR, *dbI, p.category);
  if (DmGetLastErr() != errNone) abort();

  *y = (pos - d.top_row_pos_in_cat) / recordsPerRow;
  *x = (pos - d.top_row_pos_in_cat) % recordsPerRow;
}
예제 #9
0
/***********************************************************************
 *
 * FUNCTION: ZDicFontInit
 *
 * DESCRIPTION: Initial all font resource
 *
 * PARAMETERS:	nothing
 *
 * RETURN:		errNone if success else fail.
 *
 * REVISION HISTORY:
 *		Name			Date		Description
 *		----			----		-----------
 *		ZhongYuanHuan	14/Aug/04	Initial Revision 
 *				
 ***********************************************************************/
Err ZDicFontInit ( UInt16 refNum, ZDicFontType* fontP, Boolean bUseSysFont )
{
	#pragma unused(refNum)
	
	UInt32  version;	
	Err     err;
	
	MemSet ( fontP, sizeof ( ZDicFontType ), 0 );
	fontP->smallFontID = stdFont;
	fontP->largeFontID = largeFont;
	
	if ( bUseSysFont ) return errNone;
	
	fontP->fontLibP = DmOpenDatabaseByTypeCreator ( ZDicFontTypeID, ZDicFontCreatorID, dmModeReadOnly );
	
	if ( fontP->fontLibP == 0 )
	{
	    err = DmGetLastErr ();
	    return err;
	}
	
	// Load the phonic font resource and assign it a font ID.
	err = FtrGet(sysFtrCreator, sysFtrNumWinVersion, &version);
	if (!err && version >= 4 )
	{
		// the screen is double density so use double density of phonetic font.
		fontP->phonicSmallFontH = DmGetResource('nfnt', PhonicSmallFontHight);
		fontP->phonicLargeFontH = DmGetResource('nfnt', PhonicLargeFontHight);		
	}
		
	if (fontP->phonicSmallFontH == NULL || fontP->phonicLargeFontH == NULL)
	{
		if (fontP->phonicSmallFontH != NULL) DmReleaseResource(fontP->phonicSmallFontH);
		if (fontP->phonicLargeFontH != NULL) DmReleaseResource(fontP->phonicLargeFontH);
		
		// the screen is low desity so use low density of phonetic font.
		fontP->phonicSmallFontH = DmGetResource(fontRscType, PhonicSmallFontLow);
		fontP->phonicLargeFontH = DmGetResource(fontRscType, PhonicLargeFontLow);		
	}
		
	fontP->phonicSmallFontP = (FontType *)MemHandleLock(fontP->phonicSmallFontH);
	fontP->phonicLargeFontP = (FontType *)MemHandleLock(fontP->phonicLargeFontH);
	err = FntDefineFont(kPHONIC_SMALL_FONT_ID, fontP->phonicSmallFontP);
	err = FntDefineFont(kPHONIC_LARGE_FONT_ID, fontP->phonicLargeFontP);
	fontP->smallFontID = kPHONIC_SMALL_FONT_ID;
	fontP->largeFontID = kPHONIC_LARGE_FONT_ID;		

	return errNone;
}
예제 #10
0
/* Rename document name in document list */
void UpdateDocumentName
    (
    UInt16      index,  /* record index */
    const Char* name,   /* new document name */
    const Char* filename  /* new filename */
    )
    /* THROWS */
{
    MemHandle       handle;
    DocumentData*   handlePtr;

    THROW_IF( name == NULL || *name == '\0', errNoDocumentName );

    handle = OpenRecord( plkrDocList, index );
    THROW_IF( handle == NULL, DmGetLastErr() );

    handlePtr = MemHandleLock( handle );
    DmWrite( handlePtr, OFFSETOF( DocumentData, name ),
        name, StrLen( name ) + 1 );
    if ( handlePtr->location != RAM ) {
        DocumentData*   dataPtr;
        UInt16          infoSize;
        UInt16          dataSize;
        Char            volumeLabel[ LABEL_LEN ];
        UInt16          fileLength;
        UInt16          volumeLabelLength;

        fileLength          = StrLen( handlePtr->data ) + 1;
        volumeLabelLength   = StrLen( handlePtr->data + fileLength ) + 1;
        StrNCopy( volumeLabel, handlePtr->data + fileLength,
            volumeLabelLength );

        MemHandleUnlock( handle );

        infoSize = sizeof *dataPtr;
        dataSize = StrLen( filename ) + StrLen( volumeLabel ) + 2;

        handle  = ResizeRecord( plkrDocList, index, infoSize + dataSize );
        dataPtr = MemHandleLock( handle );
        DmWrite( dataPtr, infoSize, filename, StrLen( filename ) + 1 );
        DmWrite( dataPtr, infoSize + StrLen( filename ) + 1, volumeLabel,
            StrLen( volumeLabel ) + 1 );
    }
    MemHandleUnlock( handle );
    CloseRecord( handle, true );
    DmInsertionSort( plkrDocList, CompareDocumentNames, 0 );
}
예제 #11
0
Err getDatabase (DmOpenRef * DBptr, UInt32 type, UInt32 creator, UInt32 mode,
    UInt16 card, char *name, Boolean * created) {
    Err errors;
    *created = false;

    errors = getDatabaseByTypeCreatorName (DBptr, type, creator, mode, name); 

    /* if the database does not exist, make a new one. */
    if (errors) {
        errors = DmCreateDatabase (card, name, creator, type, false);
        if (errors) return errors;
        *created = true;
    	errors = getDatabaseByTypeCreatorName (DBptr, type, creator, mode, name); 
        if (!*DBptr || errors) return DmGetLastErr ();
    }

    return 0; 
}
예제 #12
0
/*
** Move the cursor down, if possible.
**
** The return value indicates whether we need to scroll down.
*/
static Boolean ThumbnailViewMoveCursorDown(void) {
  const UInt16 pos = DmPositionInCategory(d.dbR, p.dbI, p.category);
  if (DmGetLastErr() != errNone) abort();

  /* We're already at the very end. */
  if (pos + 1 == d.records_in_cat)
    return false;
 
  /* Just go to the last visible thumbnail if we can't move downward a full row. */
  if (pos + recordsPerRow >= d.records_in_cat) {
    UInt16 x1, y1; /* dummy coordinates */
    UInt16 dummyIndex = dmMaxRecordIndex;
    Err err = DmSeekRecordInCategory(d.dbR, &dummyIndex, 0, dmSeekBackward, p.category);
    if (err != errNone) abort();

    MapIndexToCoordinates(&dummyIndex, &x1, &y1);

    /* Only move the cursor if we can move to a new row, otherwise do nothing. */
    if (y1 != d.thumbnailY) {
      d.thumbnailY = y1;
      d.thumbnailX = x1;
    }
    
    /* Handle the special case that we need to scroll AND would go past the end. */
    if (d.thumbnailY > numberOfRows - 1) {
      d.thumbnailY = numberOfRows - 1;
      return true;
    }

    return false;
  }

  /* Simply go down a row. */
  if (d.thumbnailY < numberOfRows - 1) {
    ++d.thumbnailY;
    return false;
  }
   
  /* We need to scroll down. */
  return true;
}
예제 #13
0
/*
** Move the cursor left, if possible.
**
** The return value indicates whether we need to scroll up.
*/
static Boolean ThumbnailViewMoveCursorLeft(void) {
  const UInt16 pos = DmPositionInCategory(d.dbR, p.dbI, p.category);
  if (DmGetLastErr() != errNone) abort();

  /* If this is the first record in the category, don't do anything */
  if (pos == 0)
    return false;

  if (d.thumbnailX > 0) {
    --d.thumbnailX;
    return false;
  } else {
    d.thumbnailX = recordsPerRow - 1;
    if (d.thumbnailY > 0) {
      --d.thumbnailY;
      return false;
    } else {
      return true;
    }
  }
}
예제 #14
0
/*
** Move the cursor right, if possible.
**
** The return value indicates whether we need to scroll down.
*/
static Boolean ThumbnailViewMoveCursorRight(void) {
  const UInt16 pos = DmPositionInCategory(d.dbR, p.dbI, p.category);
  if (DmGetLastErr() != errNone) abort();

  /* This is the last record, don't do anything */ 
  if (pos + 1 == d.records_in_cat)
    return false;

  if (d.thumbnailX < recordsPerRow - 1) {
    ++d.thumbnailX;
    return false;
  } else {
    d.thumbnailX = 0;

    if (d.thumbnailY < numberOfRows - 1) {
      ++d.thumbnailY;
      return false;
    } else {
      return true;
    }
  }
}
예제 #15
0
/*
 * initCNLBGlobeParameter
 * 初始化调用CLibGetMatchContactByRecordId()时需提供的预初始化参数。需要由调用者提供
 * 该参数的原因,是CLibGetMatchContactByRecordId()可能被用于循环检索多条记录(比如,
 * 由于查找库未提供获取特定分类下符合拼音关键字要求的通讯录集这种功能,调用者可能自行
 * 通过循环调用CLibGetMatchContactByRecordId()来实现该功能),提供该参数可以节省每次
 * 调用CLibGetMatchContactByRecordId()时,由库函数进行初始化所造成的时间开销和内存碎片
 *
 * 参数:
 *	globe			<->	给予的UInt16指针,用于返回查找库的引用
 *	addressType		->	通讯录的类型,ADDRESS_VERSION_OLD或ADDRESS_VERSION_NEW
 *
 * 返回:
 *	当成功初始化时,返回errNone;否则返回对应的错误代码
 */
Err initCNLBGlobeParameter(CNLBGlobeType **globe, UInt8 addressType)
{	
	//Allocate globe variable
	(*globe) = (CNLBGlobeType *)MemPtrNew(sizeof(CNLBGlobeType));
	if ((*globe) != NULL)
	{
		MemSet((*globe), sizeof(CNLBGlobeType), 0x00);
		
		//Get the PY table
		if (FtrGet(CLibCreatorID, PY_TABLE_FTR_NUMBER, (UInt32 *)&((*globe)->pyTableP)) == errNone)
		{
			//Open Contact database
			if (addressType == ADDRESS_VERSION_NEW)
			{
				(*globe)->addressDbRef = DmOpenDatabaseByTypeCreator('DATA', 'PAdd', dmModeReadOnly);
			}
			else
			{
				(*globe)->addressDbRef = DmOpenDatabaseByTypeCreator('DATA', 'addr', dmModeReadOnly);
			}
			if (DmGetLastErr())
			{
				MemPtrFree((*globe));
				return CNLB_DB_NOT_FOUND_ERROR;
			}
		}
		else
		{
			MemPtrFree((*globe));
			return CNLB_RUNTIME_ERROR;
		}
	}
	else
	{
		return CNLB_RUNTIME_ERROR;
	}
	
	return errNone;
}
예제 #16
0
파일: bookmarks.c 프로젝트: kjk/noah-palm
/* Create a new record recNum in a databse db that contains given word */
static Err WriteWordInRecord(DmOpenRef db, UInt16 recNum, char *word)
{
    int         wordLen;
    MemHandle   recHandle;
    MemPtr      recData;
    Err         err;

    Assert(db);
    Assert(word);

    wordLen = StrLen(word)+1;

    recHandle = DmNewRecord(db, &recNum, wordLen);
    if (!recHandle)
        return DmGetLastErr();

    recData = MemHandleLock(recHandle);
    Assert( recData );

    err = DmWrite(recData, 0, word, wordLen);
    MemHandleUnlock(recHandle);
    DmReleaseRecord(db, recNum, true);
    return err;
}
예제 #17
0
// Save preferences previously set via ErrSet*() calls to a database.
// If something goes wrong, returns an error
// Possible errors:
//   memErrNotEnoughSpace - not enough memory to allocate needed structures
//   errors from Dm*() calls
Err PrefsStoreWriter::ErrSavePreferences()
{
    Err     err = errNone;
    long    blobSize;
    void *  prefsBlob = SerializeItems(_items, _itemsCount, &blobSize);
    if ( NULL == prefsBlob ) 
        return memErrNotEnoughSpace;

    DmOpenRef db = DmOpenDatabaseByTypeCreator(_dbType, _dbCreator, dmModeReadWrite);
    if (!db)
    {
        err = DmCreateDatabase(0, _dbName, _dbCreator, _dbType, false);
        if ( err)
            return err;

        db = DmOpenDatabaseByTypeCreator(_dbType, _dbCreator, dmModeReadWrite);
        if (!db)
            return DmGetLastErr();
    }

    // set backup bit on the database. code adapted from DataStore.cpp
    // DataStore::open()
    if (errNone == err)
    {
        LocalID localId;
        UInt16 cardNo;
        UInt16 attribs;
        err = DmOpenDatabaseInfo(db, &localId, NULL, NULL, &cardNo, NULL);
        if (errNone != err)
            goto Continue;
        err = DmDatabaseInfo(cardNo, localId, NULL, &attribs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        if (errNone != err)
            goto Continue;
        if (0 != attribs & dmHdrAttrBackup)
            goto Continue;
        attribs |= dmHdrAttrBackup;
        err = DmSetDatabaseInfo(cardNo, localId, NULL, &attribs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
Continue:
        err = errNone;
    }

    UInt16    recNo = 0;
    UInt16    recsCount = DmNumRecords(db);
    MemHandle recHandle;
    Boolean   fRecordBusy = false;
    Boolean   fRecFound = false;
    void *    recData;
    long      recSize;
    while (recNo < recsCount)
    {
        recHandle = DmGetRecord(db, recNo);
        fRecordBusy = true;
        recData = MemHandleLock(recHandle);
        recSize = MemHandleSize(recHandle);
        if (IsValidPrefRecord(recData))
        {
            fRecFound = true;
            break;
        }
        MemPtrUnlock(recData);
        DmReleaseRecord(db, recNo, true);
        fRecordBusy = false;
        ++recNo;
    }

    if (fRecFound && blobSize>recSize)
    {
        /* need to resize the record */
        MemPtrUnlock(recData);
        DmReleaseRecord(db,recNo,true);
        fRecordBusy = false;
        recHandle = DmResizeRecord(db, recNo, blobSize);
        if ( NULL == recHandle )
            return DmGetLastErr();
        recData = MemHandleLock(recHandle);
        Assert( MemHandleSize(recHandle) == blobSize );        
    }

    if (!fRecFound)
    {
        recNo = 0;
        recHandle = DmNewRecord(db, &recNo, blobSize);
        if (!recHandle)
        {
            err = DmGetLastErr();
            goto CloseDbExit;
        }
        recData = MemHandleLock(recHandle);
        fRecordBusy = true;
    }

    err = DmWrite(recData, 0, prefsBlob, blobSize);
    MemPtrUnlock(recData);
    if (fRecordBusy)
        DmReleaseRecord(db, recNo, true);
CloseDbExit:
    // if had error before - preserve that error
    // otherwise return error code from DmCloseDatabase()
    if (err)
        DmCloseDatabase(db);
    else
        err = DmCloseDatabase(db);
    new_free( prefsBlob );
    return err;
}