/*
 * Copyright 2001 Mike McCormack
 *
 * 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
 */

#include "config.h"

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include "winbase.h"
#include "winreg.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "winerror.h"
#include "nb30.h"
#include "lmcons.h"
#include "iphlpapi.h"

WINE_DEFAULT_DEBUG_CHANNEL(netbios);

HMODULE NETAPI32_hModule = 0;

static UCHAR NETBIOS_Enum(PNCB ncb)
{
    int             i;
    LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
    DWORD apiReturn, size = 0;
    PMIB_IFTABLE table;
    UCHAR ret;
 
    TRACE("NCBENUM\n");
 
    apiReturn = GetIfTable(NULL, &size, FALSE);
    if (apiReturn != NO_ERROR)
      {
        table = (PMIB_IFTABLE)malloc(size);
        if (table)
          {
            apiReturn = GetIfTable(table, &size, FALSE);
            if (apiReturn == NO_ERROR)
              {
                lanas->length = 0;
                for (i = 0; i < table->dwNumEntries && lanas->length < MAX_LANA;
                 i++)
                  {
                    if (table->table[i].dwType != MIB_IF_TYPE_LOOPBACK)
                      {
                        lanas->lana[lanas->length] = table->table[i].dwIndex;
                        lanas->length++;
                      }
                  }
                ret = NRC_GOODRET;
              }
            else
                ret = NRC_SYSTEM;
            free(table);
          }
        else
            ret = NRC_NORESOURCES;
      }
    else
        ret = NRC_SYSTEM;
    return ret;
}


static UCHAR NETBIOS_Astat(PNCB ncb)
{
    PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
    MIB_IFROW row;
  
    TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
  
    memset(astat, 0, sizeof astat);
  
    row.dwIndex = ncb->ncb_lana_num;
    if (GetIfEntry(&row) != NO_ERROR)
        return NRC_INVADDRESS;
    /* doubt anyone cares, but why not.. */
    if (row.dwType == MIB_IF_TYPE_TOKENRING)
        astat->adapter_type = 0xff;
    else
        astat->adapter_type = 0xfe; /* for Ethernet */
    return NRC_GOODRET;
}

BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);

    switch (fdwReason) {
	case DLL_PROCESS_ATTACH:
            NETAPI32_hModule = hinstDLL;
	    break;
	case DLL_PROCESS_DETACH:
	    break;
    }

    return TRUE;
}

BOOL WINAPI Netbios(PNCB pncb)
{
    UCHAR ret = NRC_ILLCMD;

    TRACE("ncb = %p\n",pncb);

    if(!pncb)
        return NRC_INVADDRESS;

    switch(pncb->ncb_command&0x7f)
    {
    case NCBRESET:
        FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
        if(pncb->ncb_lana_num < MAX_LANA )
          {
            MIB_IFROW row;

            row.dwIndex = pncb->ncb_lana_num;
            if (GetIfEntry(&row) != NO_ERROR)
                ret = NRC_GOODRET;
            else
                ret = NRC_ILLCMD; /* NetBIOS emulator not found */
          }
        else
            ret = NRC_ILLCMD; /* NetBIOS emulator not found */
        break;

    case NCBADDNAME:
        FIXME("NCBADDNAME\n");
        break;

    case NCBADDGRNAME:
        FIXME("NCBADDGRNAME\n");
        break;

    case NCBDELNAME:
        FIXME("NCBDELNAME\n");
        break;

    case NCBSEND:
        FIXME("NCBSEND\n");
        break;

    case NCBRECV:
        FIXME("NCBRECV\n");
        break;

    case NCBHANGUP:
        FIXME("NCBHANGUP\n");
        break;

    case NCBCANCEL:
        FIXME("NCBCANCEL\n");
        break;

    case NCBLISTEN:
        FIXME("NCBLISTEN\n");
        break;

    case NCBASTAT:
        ret = NETBIOS_Astat(pncb);
        break;

    case NCBENUM:
        ret = NETBIOS_Enum(pncb);
        break;

    default:
        FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);

        ret = NRC_ILLCMD; /* NetBIOS emulator not found */
    }
    pncb->ncb_retcode = ret;
    return ret;
}

NET_API_STATUS  WINAPI NetServerEnum(
  LPCWSTR servername,
  DWORD level,
  LPBYTE* bufptr,
  DWORD prefmaxlen,
  LPDWORD entriesread,
  LPDWORD totalentries,
  DWORD servertype,
  LPCWSTR domain,
  LPDWORD resume_handle
)
{
    FIXME("Stub (%p, %ld %p %ld %p %p %ld %s %p)\n",servername, level, bufptr,
          prefmaxlen, entriesread, totalentries, servertype, debugstr_w(domain), resume_handle);

    return ERROR_NO_BROWSER_SERVERS_FOUND;
}
