/*
 *	TYPELIB 16bit part.
 *
 * Copyright 1997 Marcus Meissner
 * Copyright 1999 Rein Klazes
 * Copyright 2000 Francois Jacques
 * Copyright 2001 Huw D M Davies 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>

#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "wine/winbase16.h"
#include "winreg.h"
#include "winuser.h"
#include "objbase.h"
#include "oleauto.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

/*************************************************************************
 * TYPELIB {TYPELIB}
 *
 * This dll is the 16 bit version of the Typelib API, part the original
 * implementation of Ole automation. It and its companion ole2disp.dll were
 * superseded by oleaut32.dll which provides 32 bit implementations of these
 * functions and greatly extends the OLE API.
 *
 * Winelib developers cannot use these functions directly, they are implemented
 * solely for backwards compatibility with existing legacy applications.
 *
 * SEE ALSO
 *  oleaut32(), ole2disp().
 */

/****************************************************************************
 *		QueryPathOfRegTypeLib	[TYPELIB.14]
 *
 * Get the registry key of a registered type library.
 *
 * RETURNS
 *  Success: S_OK. path is updated with the key name
 *  Failure: E_FAIL, if guid was not found in the registry
 *
 * NOTES
 *  The key takes the form "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
 */
HRESULT WINAPI
QueryPathOfRegTypeLib16(
	REFGUID guid,	/* [in] Guid to get the key name for */
	WORD wMaj,	/* [in] Major version */
	WORD wMin,	/* [in] Minor version */
	LCID lcid,	/* [in] Locale Id */
	SEGPTR *path)	/* [out] Destination for the registry key name */
{
	char	xguid[80];
	char	typelibkey[100],pathname[260];
	LONG	plen;
        char   *ret;

	TRACE("\n");

	if (HIWORD(guid)) {
            sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%x\\win16",
                     guid->Data1, guid->Data2, guid->Data3,
                     guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
                     guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
                     wMaj,wMin,lcid);
	} else {
		sprintf(xguid,"<guid 0x%08x>",(DWORD)guid);
		FIXME("(%s,%d,%d,0x%04x,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,lcid,path);
		return E_FAIL;
	}
	plen = sizeof(pathname);
	if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
		/* try again without lang specific id */
		if (SUBLANGID(lcid))
			return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
		FIXME("key %s not found\n",typelibkey);
		return E_FAIL;
	}
        ret = HeapAlloc( GetProcessHeap(), 0, strlen(pathname) + 1 );
        if (!ret) return E_FAIL;
        strcpy( ret, pathname );
	*path = MapLS(ret);
	return S_OK;
}

/******************************************************************************
 * LoadTypeLib [TYPELIB.3]
 *
 * Load and register a type library.
 *
 * RETURNS
 *  Success: S_OK. pptLib contains the type libraries ITypeLib interface.
 *  Failure: An HRESULT error code.
 *
 * NOTES
 *  Both parameters are FAR pointers.
 */
HRESULT WINAPI LoadTypeLib16(
    LPSTR szFile, /* [in] Name of file to load from */
    ITypeLib** pptLib) /* [out] Destination for loaded ITypeLib interface */
{
    FIXME("(%s,%p): stub\n",debugstr_a(szFile),pptLib);

    if (pptLib!=0)
      *pptLib=0;

    return E_FAIL;
}

/***********************************************************************
 *              LHashValOfNameSys  (TYPELIB.4)
 */
ULONG WINAPI LHashValOfNameSys16( SYSKIND skind, LCID lcid, LPCSTR lpStr)
{
    return LHashValOfNameSysA( skind, lcid, lpStr );
}

/****************************************************************************
 *	OaBuildVersion				(TYPELIB.15)
 *
 * Get the Ole Automation build version.
 *
 * PARAMS
 *  None
 *
 * RETURNS
 *  The build version.
 *
 * NOTES
 *  Known typelib.dll versions:
 *| OLE Ver.  Comments                   Date    Build Ver.
 *| --------  -------------------------  ----    ---------
 *| OLE 2.01  Call not available         1993     N/A
 *| OLE 2.02                             1993-94  02 3002
 *| OLE 2.03                                      23 730
 *| OLE 2.03                                      03 3025
 *| OLE 2.03  W98 SE orig. file !!       1993-95  10 3024
 *| OLE 2.1   NT                         1993-95  ?? ???
 *| OLE 2.3.1 W95                                 23 700
 *| OLE2 4.0  NT4SP6                     1993-98  40 4277
 *| OLE 2.1   W2K                        2000     10 3029
 *| OLE 2.1   WXP                        2002     10 3029
 *| OLE 2.1   Vista                      2007     10 3029
 */
DWORD WINAPI OaBuildVersion16(void)
{
    /* FIXME: I'd like to return the highest currently known version value
     * in case the user didn't force a --winver, but I don't know how
     * to retrieve the "versionForced" info from misc/version.c :(
     * (this would be useful in other places, too) */
    FIXME("If you get version error messages, please report them\n");
    switch(GetVersion() & 0x8000ffff)  /* mask off build number */
    {
    case 0x80000a03:  /* WIN31 */
		return MAKELONG(3027, 3); /* WfW 3.11 */
    case 0x80000004:  /* WIN95 */
		return MAKELONG(700, 23); /* Win95A */
    case 0x80000a04:  /* WIN98 */
		return MAKELONG(3024, 10); /* W98 SE */
    case 0x00000004:  /* NT4 */
		return MAKELONG(4277, 40); /* NT4 SP6 */
    case 0x00000005:  /* W2K */
		return MAKELONG(3029, 10); /* W2K SP4 */
    case 0x00000105:  /* WXP */
		return MAKELONG(3029, 10); /* WXP SP2 */
    case 0x00000006:  /* Vista */
		return MAKELONG(3029, 10); /* Vista */
    default:
	FIXME("Version value not known yet. Please investigate it!\n");
		return 0;
    }
}
