diff --git a/configure b/configure index 69857a79496..aeed119f38d 100755 --- a/configure +++ b/configure @@ -7081,6 +7081,7 @@ dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvideo/Makefile +dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile @@ -7340,6 +7341,7 @@ dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvideo/Makefile +dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile diff --git a/configure.in b/configure.in index 69697eb157e..17c48dfcc16 100644 --- a/configure.in +++ b/configure.in @@ -1247,6 +1247,7 @@ dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvideo/Makefile +dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile diff --git a/dlls/Makefile.in b/dlls/Makefile.in index 8845ab371a1..b6927d4f152 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -44,6 +44,7 @@ SUBDIRS = \ msrle32 \ msvcrt \ msvideo \ + netapi32 \ ntdll \ odbc32 \ ole32 \ @@ -148,6 +149,7 @@ all: \ libmsvcrt.$(LIBEXT) \ libmsvfw32.$(LIBEXT) \ libmsvideo.$(LIBEXT) \ + libnetapi32.$(LIBEXT) \ libntdll.$(LIBEXT) \ libodbc32.$(LIBEXT) \ libole2.$(LIBEXT) \ @@ -336,6 +338,9 @@ libmsvcrt.$(LIBEXT): msvcrt/libmsvcrt.$(LIBEXT) libmsvfw32.$(LIBEXT) libmsvideo.$(LIBEXT): msvideo/libmsvfw32.$(LIBEXT) $(RM) $@ && $(LN_S) msvideo/libmsvfw32.$(LIBEXT) $@ +libnetapi32.$(LIBEXT): netapi32/libnetapi32.$(LIBEXT) + $(RM) $@ && $(LN_S) netapi32/libnetapi32.$(LIBEXT) $@ + libntdll.$(LIBEXT): ntdll/libntdll.$(LIBEXT) $(RM) $@ && $(LN_S) ntdll/libntdll.$(LIBEXT) $@ @@ -569,6 +574,10 @@ msvideo/libmsvfw32.$(LIBEXT): dummy libwinmm.$(LIBEXT) libcomctl32.$(LIBEXT) \ libntdll.$(LIBEXT) @cd msvideo && $(MAKE) libmsvfw32.$(LIBEXT) +netapi32/libnetapi32.$(LIBEXT): dummy libuser32.$(LIBEXT) libadvapi32.$(LIBEXT) \ + libkernel32.$(LIBEXT) libntdll.$(LIBEXT) + @cd netapi32 && $(MAKE) libnetapi32.$(LIBEXT) + ntdll/libntdll.$(LIBEXT): dummy @cd ntdll && $(MAKE) libntdll.$(LIBEXT) diff --git a/dlls/netapi32/.cvsignore b/dlls/netapi32/.cvsignore new file mode 100644 index 00000000000..199fc7cb4e1 --- /dev/null +++ b/dlls/netapi32/.cvsignore @@ -0,0 +1,2 @@ +Makefile +netapi32.spec.c diff --git a/dlls/netapi32/Makefile.in b/dlls/netapi32/Makefile.in new file mode 100644 index 00000000000..650e6193625 --- /dev/null +++ b/dlls/netapi32/Makefile.in @@ -0,0 +1,14 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = netapi32 + +LDDLLFLAGS = @LDDLLFLAGS@ +SYMBOLFILE = $(MODULE).tmp.o + +C_SRCS = netapi32.c + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c new file mode 100644 index 00000000000..0d74c1ca8b5 --- /dev/null +++ b/dlls/netapi32/netapi32.c @@ -0,0 +1,250 @@ +/* + * Copyright 2001 Mike McCormack + */ + +#include +#include +#include +#include + +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" +#include "debugtools.h" +#include "winerror.h" +#include "nb30.h" + +#ifdef HAVE_SYS_FILE_H +# include +#endif +#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H +# include +#endif +#ifdef HAVE_NET_IF_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#ifdef HAVE_SOCKADDR_SA_LEN +# ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +# endif +# define ifreq_size(i) max(sizeof(struct ifreq),\ +sizeof((i).ifr_name)+(i).ifr_addr.sa_len) +# else +# define ifreq_size(i) sizeof(struct ifreq) +# endif /* defined(HAVE_SOCKADDR_SA_LEN) */ + +DEFAULT_DEBUG_CHANNEL(netbios); + +HMODULE NETAPI32_hModule = 0; + +struct NetBiosAdapter +{ + int valid; + unsigned char address[6]; +}; + +static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA]; + +# ifdef SIOCGIFHWADDR +int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address) +{ + if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0) + return -1; + memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6); + return 0; +} +# else +# ifdef SIOCGENADDR +int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address) +{ + if (ioctl(sd, SIOCGENADDR, ifr) < 0) + return -1; + memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6); + return 0; +} +# else +int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address) +{ + return -1; +} +# endif /* SIOCGENADDR */ +# endif /* SIOCGIFHWADDR */ + +static UCHAR NETBIOS_Enum(PNCB ncb) +{ +#ifdef HAVE_NET_IF_H + int sd; + struct ifreq ifr, *ifrp; + struct ifconf ifc; + unsigned char buf[1024]; + int i, ofs; +#endif + LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer; + + TRACE("NCBENUM\n"); + + lanas->length = 0; + +#ifdef HAVE_NET_IF_H + /* BSD 4.4 defines the size of an ifreq to be + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len + * However, under earlier systems, sa_len isn't present, so + * the size is just sizeof(struct ifreq) + */ + + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) + return NRC_OPENERROR; + + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + /* get the ifconf interface */ + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) + { + close(sd); + return NRC_OPENERROR; + } + + /* loop through the interfaces, looking for a valid one */ + /* n = ifc.ifc_len; */ + ofs = 0; + for (i = 0; i < ifc.ifc_len; i++) + { + unsigned char *a = NETBIOS_Adapter[i].address; + + ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs); + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); + + /* try to get the address for this interface */ + if(get_hw_address(sd, &ifr, a)==0) + { + /* make sure it's not blank */ + /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + continue; */ + + TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i, + a[0],a[1],a[2],a[3],a[4],a[5]); + + NETBIOS_Adapter[i].valid = TRUE; + lanas->lana[lanas->length] = i; + lanas->length++; + } + ofs += ifreq_size(ifr); + } + close(sd); +#endif /* HAVE_NET_IF_H */ + return NRC_GOODRET; +} + + +static UCHAR NETBIOS_Astat(PNCB ncb) +{ + struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num]; + PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer; + + TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num); + + if(!nad->valid) + return NRC_INVADDRESS; + + memset(astat, 0, sizeof astat); + memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address); + + return NRC_GOODRET; +} + +BOOL WINAPI +NETAPI32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("%x,%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 ) && + NETBIOS_Adapter[pncb->ncb_lana_num].valid) + ret = NRC_GOODRET; + 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; +} + diff --git a/dlls/netapi32/netapi32.spec b/dlls/netapi32/netapi32.spec new file mode 100644 index 00000000000..077211cdc72 --- /dev/null +++ b/dlls/netapi32/netapi32.spec @@ -0,0 +1,13 @@ +name netapi32 +type win32 +init NETAPI32_LibMain + +#import user32.dll +#import advapi32.dll +#import kernel32.dll +import ntdll.dll + +debug_channels (netbios) + +1 stdcall Netbios(ptr) Netbios + diff --git a/include/Makefile.in b/include/Makefile.in index a3fde3208be..fbe99f7c23c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -74,6 +74,7 @@ INSTALLED_INCLUDES = \ msvcrt/time.h \ msvcrt/wchar.h \ msvcrt/wctype.h \ + nb30.h \ nspapi.h \ ntsecapi.h \ oaidl.h \ diff --git a/include/nb30.h b/include/nb30.h new file mode 100644 index 00000000000..ae1350b03a1 --- /dev/null +++ b/include/nb30.h @@ -0,0 +1,95 @@ +#ifndef NCB_INCLUDED +#define NCB_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#define NCBNAMSZ 16 +#define MAX_LANA 0xfe + +#define NCBRESET 0x32 +#define NCBADDNAME 0x30 +#define NCBADDGRNAME 0x36 +#define NCBDELNAME 0x31 +#define NCBSEND 0x14 +#define NCBRECV 0x15 +#define NCBHANGUP 0x12 +#define NCBCANCEL 0x35 +#define NCBLISTEN 0x11 +#define NCBCALL 0x10 +#define NCBASTAT 0x33 +#define NCBENUM 0x37 + +#include "pshpack1.h" + +typedef struct _NCB +{ + UCHAR ncb_command; + UCHAR ncb_retcode; + UCHAR ncb_lsn; + UCHAR ncb_num; + PUCHAR ncb_buffer; + WORD ncb_length; + UCHAR ncb_callname[NCBNAMSZ]; + UCHAR ncb_name[NCBNAMSZ]; + UCHAR ncb_rto; + UCHAR ncb_sto; + VOID (*ncb_post)(struct _NCB *); + UCHAR ncb_lana_num; + UCHAR ncb_cmd_cplt; + UCHAR ncb_reserved[10]; + HANDLE ncb_event; +} NCB, *PNCB; + +typedef struct _ADAPTER_STATUS +{ + UCHAR adapter_address[6]; + UCHAR rev_major; + UCHAR reserved0; + UCHAR adapter_type; + UCHAR rev_minor; + WORD duration; + WORD frmr_recv; + WORD frmr_xmit; + WORD iframe_recv_error; + WORD xmit_aborts; + WORD xmit_success; + WORD recv_success; + WORD iframe_xmit_error; + WORD recv_buffer_unavail; + WORD t1_timeouts; + WORD ti_timeouts; + DWORD reserved1; + WORD free_ncbs; + WORD max_cfg_ncbs; + WORD max_ncbs; + WORD xmit_buf_unavail; + WORD max_dgram_size; + WORD pending_sess; + WORD max_cfg_sess; + WORD max_sess; + WORD max_sess_pktsize; + WORD name_count; +} ADAPTER_STATUS, *PADAPTER_STATUS; + +typedef struct _LANA_ENUM +{ + UCHAR length; + UCHAR lana[MAX_LANA+1]; +} LANA_ENUM, *PLANA_ENUM; + +#define NRC_GOODRET 0x00 +#define NRC_BUFLEN 0x01 +#define NRC_ILLCMD 0x03 +#define NRC_CMDTMO 0x05 +#define NRC_INCOMP 0x06 +#define NRC_INVADDRESS 0x39 +#define NRC_PENDING 0xff +#define NRC_OPENERROR 0x3f + +#ifdef __cplusplus +} +#endif + +#endif /* NCB_INCLUDED */