This works like a charm for SQL Server 6.5, I can't vouch for others...

BOOL EnsureDSNExists(LPCSTR szDSN, 
                     BOOL bIsSystemDSN,
                     LPCSTR szDriverName,
                     LPCSTR szServer,
                     LPCSTR szDatabase,
                     LPCSTR szNetLibrary,
                     LPCSTR szAddress)
{
        char dsn[SQL_MAX_DSN_LENGTH+1];
        char desc[256];
        short len,desclen;
        BOOL result=FALSE;
        HENV hEnv;
        RETCODE ret;

        ret = SQLAllocEnv(&hEnv);
        if (ret == SQL_ERROR)
                return FALSE;

        // search for existing DSN
        ret = SQLDataSources(hEnv, SQL_FETCH_FIRST, (BYTE *)dsn, SQL_MAX_DSN_LENGTH, &len, (BYTE *)desc, 255, &desclen);
        while (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
        {
                if (!strcmp(dsn,szDSN))
                {
                        result=TRUE;
                        break;
                }
                ret = SQLDataSources(hEnv, SQL_FETCH_NEXT, (BYTE *)dsn, SQL_MAX_DSN_LENGTH, &len, (BYTE *)desc, 255, &desclen);
        }
        
        if (!result)
        {
                // if we got here, the DSN doesn't exist
                char buf[2048];
                sprintf(buf,"SERVER=%s%c"  
                                   "DSN=%s%c"  
                                   "DATABASE=%s%c"
                                   "NETWORK=%s%c"
                                   "ADDRESS=%s%c",
                                   szServer,'\0',
                                   szDSN,'\0',
                                   szDatabase,'\0',
                                   szNetLibrary,'\0',
                                   szAddress,'\0');
                result = ::SQLConfigDataSource(NULL, bIsSystemDSN? ODBC_ADD_SYS_DSN:ODBC_ADD_DSN, szDriverName, buf);
        }
        SQLFreeEnv(hEnv);
        return result;
}