/*
 * TAPI32 Assisted Telephony
 *
 * Copyright 1999  Andreas Mohr
 * Copyright 2011  André Hentschel
 *
 * 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 <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winreg.h"
#include "objbase.h"
#include "tapi.h"
#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(tapi);

/***********************************************************************
 *      tapiGetLocationInfoW (TAPI32.@)
 */
DWORD WINAPI tapiGetLocationInfoW(LPWSTR countrycode, LPWSTR citycode)
{
    HKEY hkey, hsubkey;
    DWORD currid;
    DWORD valsize;
    DWORD type;
    DWORD bufsize;
    BYTE buf[200];
    WCHAR szlockey[20];

    static const WCHAR currentidW[] = {'C','u','r','r','e','n','t','I','D',0};
    static const WCHAR locationW[]  = {'L','o','c','a','t','i','o','n','%','u',0};
    static const WCHAR areacodeW[]  = {'A','r','e','a','C','o','d','e',0};
    static const WCHAR countryW[]   = {'C','o','u','n','t','r','y',0};
    static const WCHAR fmtW[]       = {'%','u',0};

    static const WCHAR locations_keyW[] =
        {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
         'W','i','n','d','o','w','s','\\',
         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
         'T','e','l','e','p','h','o','n','y','\\','L','o','c','a','t','i','o','n','s',0};

    if(RegOpenKeyW(HKEY_LOCAL_MACHINE, locations_keyW, &hkey) == ERROR_SUCCESS) {
        valsize = sizeof( DWORD);
        if(!RegQueryValueExW(hkey, currentidW, 0, &type, (LPBYTE) &currid, &valsize) &&
           type == REG_DWORD) {
            /* find a subkey called Location1, Location2... */
            sprintfW( szlockey, locationW, currid);
            if( !RegOpenKeyW( hkey, szlockey, &hsubkey)) {
                if( citycode) {
                    bufsize=sizeof(buf);
                    if( !RegQueryValueExW( hsubkey, areacodeW, 0, &type, buf, &bufsize) &&
                        type == REG_SZ) {
                        lstrcpynW( citycode, (WCHAR *) buf, 8);
                    } else 
                        citycode[0] = '\0';
                }
                if( countrycode) {
                    bufsize=sizeof(buf);
                    if( !RegQueryValueExW( hsubkey, countryW, 0, &type, buf, &bufsize) &&
                        type == REG_DWORD)
                        snprintfW( countrycode, 8, fmtW, *(LPDWORD) buf );
                    else
                        countrycode[0] = '\0';
                }
                TRACE("(%p \"%s\", %p \"%s\"): success.\n", countrycode, debugstr_w(countrycode),
                      citycode, debugstr_w(citycode));
                RegCloseKey( hkey);
                RegCloseKey( hsubkey);
                return 0; /* SUCCESS */
            }
        }
        RegCloseKey( hkey);
    }
    WARN("(%p, %p): failed (no telephony registry entries?).\n", countrycode, citycode);
    return TAPIERR_REQUESTFAILED;
}


/***********************************************************************
 *      tapiGetLocationInfoA (TAPI32.@)
 */
DWORD WINAPI tapiGetLocationInfoA(LPSTR countrycode, LPSTR citycode)
{
    DWORD ret, len;
    LPWSTR country, city;

    len = MultiByteToWideChar( CP_ACP, 0, countrycode, -1, NULL, 0 );
    country = HeapAlloc( GetProcessHeap(), 0, len );
    MultiByteToWideChar( CP_ACP, 0, countrycode, -1, country, len );

    len = MultiByteToWideChar( CP_ACP, 0, citycode, -1, NULL, 0 );
    city = HeapAlloc( GetProcessHeap(), 0, len );
    MultiByteToWideChar( CP_ACP, 0, citycode, -1, city, len );

    ret = tapiGetLocationInfoW(country, city);

    HeapFree( GetProcessHeap(), 0, city );
    HeapFree( GetProcessHeap(), 0, country );
    return ret;
}

/***********************************************************************
 *		tapiRequestMakeCall (TAPI32.@)
 */
DWORD WINAPI tapiRequestMakeCallA(LPCSTR lpszDestAddress, LPCSTR lpszAppName,
                                 LPCSTR lpszCalledParty, LPCSTR lpszComment)
{
    FIXME("(%s, %s, %s, %s): stub.\n", lpszDestAddress, lpszAppName, lpszCalledParty, lpszComment);
    return 0;
}
