/*
 *	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 "config.h"
#include "wine/port.h"

#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 "winreg.h"
#include "winuser.h"

#include "objbase.h"
#include "ole2disp.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 */
	LPBSTR16 path)	/* [out] Destination for the registry key name */
{
	char	xguid[80];
	char	typelibkey[100],pathname[260];
	LONG	plen;

       	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;
	}
	*path = SysAllocString16(pathname);
	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;
}

/****************************************************************************
 *	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;
    }
}
