/*
 * SetupX .inf file parsing functions
 *
 * Copyright 2000 Andreas Mohr for Codeweavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * FIXME:
 * - return values ???
 * - this should be reimplemented at some point to have its own
 *   file parsing instead of using profile functions,
 *   as some SETUPX exports probably demand that
 *   (IpSaveRestorePosition, IpFindNextMatchLine, ...).
 */

#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "ntddk.h"
#include "wine/winbase16.h"
#include "setupapi.h"
#include "setupx16.h"
#include "setupapi_private.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(setupapi);

#define MAX_HANDLES 16384
#define FIRST_HANDLE 32

static HINF handles[MAX_HANDLES];


static RETERR16 alloc_hinf16( HINF hinf, HINF16 *hinf16 )
{
    int i;
    for (i = 0; i < MAX_HANDLES; i++)
    {
        if (!handles[i])
        {
            handles[i] = hinf;
            *hinf16 = i + FIRST_HANDLE;
            return OK;
        }
    }
    return ERR_IP_OUT_OF_HANDLES;
}

static HINF get_hinf( HINF16 hinf16 )
{
    int idx = hinf16 - FIRST_HANDLE;
    if (idx < 0 || idx >= MAX_HANDLES) return 0;
    return handles[idx];
}


static HINF free_hinf16( HINF16 hinf16 )
{
    HINF ret;
    int idx = hinf16 - FIRST_HANDLE;

    if (idx < 0 || idx >= MAX_HANDLES) return 0;
    ret = handles[idx];
    handles[idx] = 0;
    return ret;
}

/* convert last error code to a RETERR16 value */
static RETERR16 get_last_error(void)
{
    switch(GetLastError())
    {
    case ERROR_EXPECTED_SECTION_NAME:
    case ERROR_BAD_SECTION_NAME_LINE:
    case ERROR_SECTION_NAME_TOO_LONG: return ERR_IP_INVALID_SECT_NAME;
    case ERROR_SECTION_NOT_FOUND: return ERR_IP_SECT_NOT_FOUND;
    case ERROR_LINE_NOT_FOUND: return ERR_IP_LINE_NOT_FOUND;
    default: return IP_ERROR;  /* FIXME */
    }
}


/***********************************************************************
 *		IpOpen (SETUPX.2)
 *
 */
RETERR16 WINAPI IpOpen16( LPCSTR filename, HINF16 *hinf16 )
{
    HINF hinf = SetupOpenInfFileA( filename, NULL, INF_STYLE_WIN4, NULL );
    if (hinf == (HINF)INVALID_HANDLE_VALUE) return get_last_error();
    return alloc_hinf16( hinf, hinf16 );
}


/***********************************************************************
 *		IpClose (SETUPX.4)
 */
RETERR16 WINAPI IpClose16( HINF16 hinf16 )
{
    HINF hinf = free_hinf16( hinf16 );
    if (!hinf) return ERR_IP_INVALID_HINF;
    SetupCloseInfFile( hinf );
    return OK;
}


/***********************************************************************
 *		IpGetProfileString (SETUPX.210)
 */
RETERR16 WINAPI IpGetProfileString16( HINF16 hinf16, LPCSTR section, LPCSTR entry,
                                      LPSTR buffer, WORD buflen )
{
    DWORD required_size;
    HINF hinf = get_hinf( hinf16 );

    if (!hinf) return ERR_IP_INVALID_HINF;
    if (!SetupGetLineTextA( NULL, hinf, section, entry, buffer, buflen, &required_size ))
        return get_last_error();
    TRACE("%p: section %s entry %s ret %s\n",
          hinf, debugstr_a(section), debugstr_a(entry), debugstr_a(buffer) );
    return OK;
}


/***********************************************************************
 *		GenFormStrWithoutPlaceHolders (SETUPX.103)
 *
 * ought to be pretty much implemented, I guess...
 */
void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR dst, LPCSTR src, HINF16 hinf16 )
{
    UNICODE_STRING srcW;
    HINF hinf = get_hinf( hinf16 );

    if (!hinf) return;

    if (!RtlCreateUnicodeStringFromAsciiz( &srcW, src )) return;
    PARSER_string_substA( hinf, srcW.Buffer, dst, MAX_INF_STRING_LENGTH );
    RtlFreeUnicodeString( &srcW );
    TRACE( "%s -> %s\n", debugstr_a(src), debugstr_a(dst) );
}

/***********************************************************************
 *		GenInstall (SETUPX.101)
 *
 * generic installer function for .INF file sections
 *
 * This is not perfect - patch whenever you can !
 *
 * wFlags == GENINSTALL_DO_xxx
 * e.g. NetMeeting:
 * first call GENINSTALL_DO_REGSRCPATH | GENINSTALL_DO_FILES,
 * second call GENINSTALL_DO_LOGCONFIG | CFGAUTO | INI2REG | REG | INI
 */
RETERR16 WINAPI GenInstall16( HINF16 hinf16, LPCSTR section, WORD genflags )
{
    UINT flags = 0;
    HINF hinf = get_hinf( hinf16 );
    RETERR16 ret = OK;
    void *context;

    if (!hinf) return ERR_IP_INVALID_HINF;

    if (genflags & GENINSTALL_DO_FILES) flags |= SPINST_FILES;
    if (genflags & GENINSTALL_DO_INI) flags |= SPINST_INIFILES;
    if (genflags & GENINSTALL_DO_REG) flags |= SPINST_REGISTRY;
    if (genflags & GENINSTALL_DO_INI2REG) flags |= SPINST_INI2REG;
    if (genflags & GENINSTALL_DO_LOGCONFIG) flags |= SPINST_LOGCONFIG;
    if (genflags & (GENINSTALL_DO_REGSRCPATH|GENINSTALL_DO_CFGAUTO|GENINSTALL_DO_PERUSER))
        FIXME( "unsupported flags %x\n", genflags );

    context = SetupInitDefaultQueueCallback( 0 );
    if (!SetupInstallFromInfSectionA( 0, hinf, section, flags, 0, NULL, 0,
                                      SetupDefaultQueueCallbackA, context, 0, 0 ))
        ret = get_last_error();

    SetupTermDefaultQueueCallback( context );
    return ret;
}


WORD InfNumEntries = 0;
INF_FILE *InfList = NULL;
HINF16 IP_curr_handle = 0;


BOOL IP_FindInf(HINF16 hInf, WORD *ret)
{
    WORD n;

    for (n=0; n < InfNumEntries; n++)
	if (InfList[n].hInf == hInf)
	{
	    *ret = n;
	    return TRUE;
	}
    return FALSE;
}
	

LPCSTR IP_GetFileName(HINF16 hInf)
{
    WORD n;
    if (IP_FindInf(hInf, &n))
    {
	return InfList[n].lpInfFileName;
    }
    return NULL;
}


