/* SCCSID: fwk/cssm/dlapi.c, dss_cdsa_fwk, fwk_rel2, dss_971010 1.8 10/10/97 10:42:19 */
/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

/*-----------------------------------------------------------------------
 *      File:   DLAPI.C
 *
 * This file contains the functions that are contained in the DLI portion
 * of the CSSM exported functions.
 */
/*
 * (C) COPYRIGHT International Business Machines Corp. 1996, 1997
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 *
 * Copyright (c) 1995, 1996, 1997 Intel Corporation. All rights reserved.
 *
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 */
/*
 * WARNING: EXPORT RESTRICTED.
 * This software listing contains cryptographic methods and technology.
 * It is export restricted by the Office of Defense Trade Controls, United
 * States Department of State and cannot be downloaded or otherwise
 * exported or re-exported (i) into (or to a national or resident of) Cuba,
 * Iraq, Libya, Yugoslavia, North Korea, Iran, Syria or any other country
 * to which the US has embargoed goods; or (ii) to anyone on the US
 * Treasury Department's list of Specially Designated Nationals or the US
 * Commerce Department's Table of Denial Orders. By downloading or using
 * this product, you are agreeing to the foregoing and you are representing
 * and warranting that you are not located in, under the control of, or a
 * national or resident of any such country or on any such list.
 */

#include "cssm.h"
#include "cssmport.h"
#include "internal.h"
#include "cssmdli.h"
#include "addin.h"

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_Authenticate
 *
 *Description:
 *   Exported function to authenticate DB data source
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   AccessRequest -  indicator of the requested access mode
 *                    for the data store or DL module
 *   UserAuthentication -  credential as required for
 *                         obtaining authorized access
 *
 *Returns:
 *  CSSM_FAIL - unable to authenticate
 *  CSSM_OK - authentication completed
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_Authenticate(
	CSSM_DL_DB_HANDLE DLDBHandle,
    const CSSM_DB_ACCESS_TYPE_PTR AccessRequest,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(
                                           DLDBHandle.DLHandle, CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->Authenticate))
		ret = CallBack->Authenticate (DLDBHandle, AccessRequest,
                                            UserAuthentication);
    else {
		ret = CSSM_FAIL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbOpen
 *
 *Description:
 *   Exported function for DL module to open a database
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DbName - name of database file
 *
 *Returns:
 *  0 - DL unable to open the database
 *  non 0 - handle for the open database file
 *
 *----------------------------------------------------------------*/
CSSM_DB_HANDLE CSSMAPI CSSM_DL_DbOpen(
	CSSM_DL_HANDLE DLDBHandle,
    const char *DbName,
    const CSSM_DB_ACCESS_TYPE_PTR AccessRequest,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication,
    const void *OpenParameters)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_HANDLE DbHandle = 0;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(0);

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(0);
        }
    }


    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbOpen))
		DbHandle = CallBack->DbOpen (DLDBHandle, DbName, AccessRequest,
                                           UserAuthentication, OpenParameters);
    else {
		DbHandle = 0;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			DbHandle = 0;
		}
    }

    return(DbHandle);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbClose
 *
 *Description:
 *   Exported function for DL module to close a previously open
 *   database file
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DBHandle - handle that identifies the database file
 *
 *Returns:
 *  CSSM_FAIL - DL unable to close file
 *  CSSM_OK - DB file is closed
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DbClose (CSSM_DL_DB_HANDLE DLDBHandle)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbClose))
        ret = CallBack->DbClose (DLDBHandle);
    else {
        ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbCreate
 *
 *Description:
 *   Exported function for DL module for creating a database file.
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   CLHandle - handle that identifies CL module
 *   DbName - name of database file
 *
 *Returns:
 *  0 - unable to create database file
 *  non 0 - handle for the database file
 *
 *----------------------------------------------------------------*/
CSSM_DB_HANDLE CSSMAPI CSSM_DL_DbCreate(
	CSSM_DL_HANDLE DLDBHandle,
    const char *DbName,
    const CSSM_DBINFO_PTR DBInfo,
    const CSSM_DB_ACCESS_TYPE_PTR AccessRequest,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication,
    const void *OpenParameters)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_HANDLE DbHandle = 0;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(0);

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(0);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbCreate))
		DbHandle = CallBack->DbCreate (DLDBHandle, DbName, DBInfo,
                                       AccessRequest, UserAuthentication,
                                       OpenParameters);
    else {
		DbHandle = 0;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			DbHandle = 0;
		}
    }

    return(DbHandle);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbDelete
 *
 *Description:
 *   Exported function for DL module to delete a database file.
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DbName - name of database file
 *
 *Returns:
 *  CSSM_FAIL - DL unable to delete database file
 *  CSSM_OK - database file is deleted
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DbDelete(
	CSSM_DL_HANDLE DLDBHandle,
    const char *DbName,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbDelete))
		ret = CallBack->DbDelete (DLDBHandle, DbName, UserAuthentication);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbImport
 *
 *Description:
 *   Exported function for DL module to import a database file
 *   into the DL data storage
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DbDestLogicalName - name associated with new data source
 *   DbSrcFileName - name of external file to load into the data store
 *
 *Returns:
 *  CSSM_FAIL - DL unable to import source file
 *  CSSM_OK - source file is added to the data store
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DbImport(
	CSSM_DL_HANDLE DLDBHandle,
    const char *DbDestinationName,
    const char *DbSourceName,
    const CSSM_DBINFO_PTR DBInfo,
    CSSM_BOOL InfoOnly,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbImport))
		ret = CallBack->DbImport (DLDBHandle, DbDestinationName, DbSourceName,
                                  DBInfo, InfoOnly, UserAuthentication);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbExport
 *
 *Description:
 *   Exported function for DL module to export data store to an
 *   external file
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DbSrcLogicalName - name of data source to export
 *   DbDestFileName - name of external file to store the data store
 *
 *Returns:
 *  CSSM_FAIL - DL unable to export source file
 *  CSSM_OK - data store is saved to the external file
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DbExport(
	CSSM_DL_HANDLE DLDBHandle,
    const char *DbDestinationName,
    const char *DbSourceName,
    CSSM_BOOL InfoOnly,
    const CSSM_USER_AUTHENTICATION_PTR UserAuthentication)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbExport))
		ret = CallBack->DbExport (DLDBHandle, DbSourceName, DbDestinationName,
                                  InfoOnly, UserAuthentication);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbSetRecordParsingFunctions
 *
 *Description:
 *   Exported function for DL module to set parsing functions.
 *
 *Parameters:
 *   DLHandle - handle that identifies DL module
 *   DbName - name of data source
 *   RecordType - type of record for parsing functions
 *   FunctionTable - table of parsing functions
 *
 *Returns:
 *  CSSM_FAIL - DL unable to set parsing functions
 *  CSSM_OK - parsing function set
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DbSetRecordParsingFunctions(
	CSSM_DL_HANDLE DLHandle,
    const char* DbName,
    CSSM_DB_RECORDTYPE RecordType,
    const CSSM_DB_RECORD_PARSING_FNTABLE_PTR FunctionTable)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbSetRecordParsingFunctions))
		ret = CallBack->DbSetRecordParsingFunctions (DLHandle, DbName,
                                            RecordType, FunctionTable);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DbGetRecordParsingFunctions
 *
 *Description:
 *   Exported function to get parsing functions for DL module.
 *
 *Parameters:
 *   DLHandle - handle that identifies DL module
 *   DbName - name of data source
 *   RecordType - type of record for parsing functions
 *
 *Returns:
 *  Non NULL - pointer to table of parsing functions
 *  NULL - unable to get parsing functions
 *
 *----------------------------------------------------------------*/
CSSM_DB_RECORD_PARSING_FNTABLE_PTR CSSMAPI CSSM_DL_DbGetRecordParsingFunctions(
	CSSM_DL_HANDLE DLHandle,
    const char* DbName,
    CSSM_DB_RECORDTYPE RecordType)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_RECORD_PARSING_FNTABLE_PTR ret = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DbGetRecordParsingFunctions))
		ret = CallBack->DbGetRecordParsingFunctions (DLHandle, DbName, RecordType);
    else {
		ret = NULL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			ret = NULL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_GetDbNameFromHandle
 *
 *Description:
 *   Exported function to get DB name for DLDB module.
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *
 *Returns:
 *  Non NULL - pointer to name of DB
 *  NULL - unable to get name
 *
 *----------------------------------------------------------------*/
char * CSSMAPI CSSM_DL_GetDbNameFromHandle (CSSM_DL_DB_HANDLE DLDBHandle)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    char *ret = NULL;
    CSSM_MUTEX retMutex;

	/* clear the error */
    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->GetDbNameFromHandle))
		ret = CallBack->GetDbNameFromHandle(DLDBHandle);
    else {
		ret = NULL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(!cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL)) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			ret = NULL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DataInsert
 *
 *Description:
 *   Exported function to insert data into DLDB module.
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   RecordType - record type to be inserted
 *   Attributes - attributes of record
 *   Data - data to be inserted
 *
 *Returns:
 *  Non NULL - pointer to the inserted record
 *  NULL - unable to insert record
 *
 *----------------------------------------------------------------*/
CSSM_DB_UNIQUE_RECORD_PTR CSSMAPI CSSM_DL_DataInsert(
	CSSM_DL_DB_HANDLE DLDBHandle,
    CSSM_DB_RECORDTYPE RecordType,
    const CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes,
    const CSSM_DATA_PTR Data)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_UNIQUE_RECORD_PTR ret = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DataInsert))
		ret = CallBack->DataInsert (DLDBHandle, RecordType, Attributes,
                                        Data);
    else {
		ret = NULL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			ret = NULL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DataDelete
 *
 *Description:
 *   Exported function to delete data from DLDB module.
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   RecordType - record type to be inserted
 *   UniqueRecordIdentifier - ID of record
 *
 *Returns:
 *  CSSM_OK - data deleted
 *  CSSM_FAIL - unable to delete record
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_DataDelete(
	CSSM_DL_DB_HANDLE DLDBHandle,
    CSSM_DB_RECORDTYPE RecordType,
    const CSSM_DB_UNIQUE_RECORD_PTR UniqueRecordIdentifier)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DataDelete))
		ret = CallBack->DataDelete (DLDBHandle, RecordType,
                                    UniqueRecordIdentifier);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DataGetFirst
 *
 *Description:
 *   Exported function to get first record from DLDB module that
 *   match query
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   Query - query of serach
 *   ResultsHandle (output) - handle that identifies this search
 *   EndOfDataStore (output) - identifies if there are more records
 *   Attributes (output) - attributes of data
 *   Data (output) - object stored in the retrieved record
 *
 *Returns:
 *  NULL - and EndOfDataStore is TRUE, then a normal termination
 *         condition has occurred. If the pointer is NULL and
 *         EndOfDataStore is FALSE, then an error has occurred
 *  Non NULL - pointer a unique record locator and the record
 *
 *----------------------------------------------------------------*/
CSSM_DB_UNIQUE_RECORD_PTR CSSMAPI CSSM_DL_DataGetFirst(
	CSSM_DL_DB_HANDLE DLDBHandle,
    const CSSM_QUERY_PTR Query,
    CSSM_HANDLE_PTR  ResultsHandle,
    CSSM_BOOL  *EndOfDataStore,
    CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes,
    CSSM_DATA_PTR  Data)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_UNIQUE_RECORD_PTR ret = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }

    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DataGetFirst))
		ret = CallBack->DataGetFirst (DLDBHandle, Query, ResultsHandle,
                                      EndOfDataStore, Attributes, Data);
     else {
		ret = NULL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = NULL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_DataGetNext
 *
 *Description:
 *   Exported function to get next record from DLDB module that
 *   match query
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   ResultsHandle - handle that identifies this search
 *   EndOfDataStore (output) - identifies if there are more records
 *   Attributes (output) - attributes of data
 *   Data (output) - object stored in the retrieved record
 *
 *Returns:
 *  NULL - and EndOfDataStore is TRUE, then a normal termination
 *         condition has occurred. If the pointer is NULL and
 *         EndOfDataStore is FALSE, then an error has occurred
 *  Non NULL - pointer a unique record locator and the record
 *
 *----------------------------------------------------------------*/
CSSM_DB_UNIQUE_RECORD_PTR CSSMAPI CSSM_DL_DataGetNext(
	CSSM_DL_DB_HANDLE DLDBHandle,
    CSSM_HANDLE ResultsHandle,
    CSSM_BOOL *EndOfDataStore,
    CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes,
    CSSM_DATA_PTR Data)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_DB_UNIQUE_RECORD_PTR ret = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);


    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DataGetNext))
		ret = CallBack->DataGetNext (DLDBHandle, ResultsHandle,
                                     EndOfDataStore, Attributes, Data);
    else {
		ret = NULL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			ret = NULL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_FreeUniqueRecord
 *
 *Description:
 *   Exported function to free record
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   UniqueRecord - pointer to unique record
 *
 *Returns:
 *  CSSM_FAIL - unable to free record
 *  CSSM_OK - record free
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_FreeUniqueRecord(
	CSSM_DL_DB_HANDLE DLDBHandle,
    CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->FreeUniqueRecord))
		ret = CallBack->FreeUniqueRecord (DLDBHandle, UniqueRecord);
    else {
		ret = CSSM_FAIL;
        CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_AbortQuery
 *
 *Description:
 *   Exported function to abort search
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DLDB data source
 *   ResultsHandle - handle that identifies this search
 *
 *Returns:
 *  CSSM_FAIL - unable to terminate search
 *  CSSM_OK - serch terminated
 *
 *----------------------------------------------------------------*/
CSSM_RETURN CSSMAPI CSSM_DL_AbortQuery(
	CSSM_DL_DB_HANDLE DLDBHandle,
    CSSM_HANDLE ResultsHandle)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    CSSM_RETURN ret = CSSM_FAIL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(ret);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(CSSM_FAIL);
        }
    }

    /* Make sure that function pointer is valid */
    if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->DataAbortQuery))
		ret = CallBack->DataAbortQuery (DLDBHandle, ResultsHandle);
	else {
		ret = CSSM_FAIL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// cssm error is set
			ret = CSSM_FAIL;
		}
    }

    return(ret);
}

/*---------------------------------------------------------------
 *
 *Name: CSSM_DL_PassThrough
 *
 *Description:
 *   Exported function for DL module to allow private functions
 *
 *Parameters:
 *   DLDBHandle - handle that identifies DL module
 *   DBHandle - handle that identifies the database file
 *   PassThroughId - identifier suupiled by the TP module
 *   InputParams - data associated with pass through function
 *
 *Returns:
 *  NULL - unable to complete pass through call
 *  non NULL - result from pass through call
 *
 *----------------------------------------------------------------*/
void * CSSMAPI CSSM_DL_PassThrough(
	CSSM_DL_DB_HANDLE DLDBHandle,
    uint32 PassThroughId,
    const void * InputParams)
{
    CSSM_SPI_DL_FUNCS_PTR CallBack = NULL;
    void * Data = NULL;
    CSSM_MUTEX retMutex;

    /* clear the error */

    CSSM_ClearError ();

    CallBack  = (CSSM_SPI_DL_FUNCS_PTR)cssm_GetAddInCallBackByHandle(DLDBHandle.DLHandle,
                       CSSM_SERVICE_DL);

	if (CallBack == NULL)
		return(NULL);

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_LockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle, CSSM_SERVICE_DL),CSSM_INFINITE_WAIT);
        if(retMutex != CSSM_MUTEX_LOCKED) {
            return(NULL);
        }
    }

    /* Make sure that function pointer is valid */
	if (!cssm_IsBadCodePtr ((CSSM_CALLBACK)CallBack->PassThrough))
		Data = CallBack->PassThrough (DLDBHandle, PassThroughId,
									  InputParams);
	else {
		Data = NULL;
		CSSM_SetError (&cssm_GUID, CSSM_FUNCTION_NOT_IMPLEMENTED);
    }

    if(cssm_CheckThreadSafe (DLDBHandle.DLHandle, CSSM_SERVICE_DL) == CSSM_FALSE) {
        retMutex = cssm_UnlockMutex(cssm_GetMultitaskMutexHandle (DLDBHandle.DLHandle,CSSM_SERVICE_DL));
		if (retMutex != CSSM_MUTEX_UNLOCKED) {
			// panic and dont free
			Data = NULL;
		}
    }

    return(Data);
}
