Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / netapi32 / netapi32.c
1 /*
2  * Copyright 2001 Mike McCormack
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20
21 #include <string.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/debug.h"
31 #include "winerror.h"
32 #include "nb30.h"
33
34 #ifdef HAVE_SYS_FILE_H
35 # include <sys/file.h>
36 #endif
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40 #ifdef HAVE_SYS_SOCKET_H
41 # include <sys/socket.h>
42 #endif
43 #ifdef HAVE_SYS_SOCKIO_H
44 # include <sys/sockio.h>
45 #endif
46 #ifdef HAVE_NET_IF_H
47 # include <net/if.h>
48 #endif
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
51 #endif
52
53 #ifdef HAVE_SOCKADDR_SA_LEN
54 #  ifndef max
55 #   define max(a,b) ((a) > (b) ? (a) : (b))
56 #  endif
57 #  define ifreq_size(i) max(sizeof(struct ifreq),\
58 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
59 # else
60 #  define ifreq_size(i) sizeof(struct ifreq)
61 # endif /* defined(HAVE_SOCKADDR_SA_LEN) */
62
63 WINE_DEFAULT_DEBUG_CHANNEL(netbios);
64
65 HMODULE NETAPI32_hModule = 0;
66
67 struct NetBiosAdapter
68 {
69     int valid;
70     unsigned char address[6];
71 };
72
73 static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA];
74
75 # ifdef SIOCGIFHWADDR
76 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
77 {
78     if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0)
79         return -1;
80     memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6);
81     return 0;
82 }
83 # else
84 #  ifdef SIOCGENADDR
85 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
86 {
87     if (ioctl(sd, SIOCGENADDR, ifr) < 0)
88         return -1;
89     memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
90     return 0;
91 }
92 #   else
93 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
94 {
95     return -1;
96 }
97 #  endif /* SIOCGENADDR */
98 # endif /* SIOCGIFHWADDR */
99
100 static UCHAR NETBIOS_Enum(PNCB ncb)
101 {
102 #ifdef HAVE_NET_IF_H
103     int             sd;
104     struct ifreq    ifr, *ifrp;
105     struct ifconf   ifc;
106     unsigned char   buf[1024];
107     int             i, ofs;
108 #endif
109     LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
110
111     TRACE("NCBENUM\n");
112
113     lanas->length = 0;
114
115 #ifdef HAVE_NET_IF_H
116     /* BSD 4.4 defines the size of an ifreq to be
117      * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
118      * However, under earlier systems, sa_len isn't present, so
119      *  the size is just sizeof(struct ifreq)
120      */
121
122     sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
123     if (sd < 0)
124         return NRC_OPENERROR;
125
126     memset(buf, 0, sizeof(buf));
127     ifc.ifc_len = sizeof(buf);
128     ifc.ifc_buf = buf;
129     /* get the ifconf interface */
130     if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
131     {
132         close(sd);
133         return NRC_OPENERROR;
134     }
135
136     /* loop through the interfaces, looking for a valid one */
137     /* n = ifc.ifc_len; */
138     ofs = 0;
139     for (i = 0; i < ifc.ifc_len; i++)
140     {
141         unsigned char *a = NETBIOS_Adapter[i].address;
142
143         ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
144         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
145
146         /* try to get the address for this interface */
147         if(get_hw_address(sd, &ifr, a)==0)
148         {
149             /* make sure it's not blank */
150             /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
151                 continue; */
152
153             TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i,
154                         a[0],a[1],a[2],a[3],a[4],a[5]);
155
156             NETBIOS_Adapter[i].valid = TRUE;
157             lanas->lana[lanas->length] = i;
158             lanas->length++;
159         }
160         ofs += ifreq_size(ifr);
161     }
162     close(sd);
163 #endif /* HAVE_NET_IF_H */
164     return NRC_GOODRET;
165 }
166
167
168 static UCHAR NETBIOS_Astat(PNCB ncb)
169 {
170     struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
171     PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
172
173     TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
174
175     if(!nad->valid)
176         return NRC_INVADDRESS;
177
178     memset(astat, 0, sizeof astat);
179     memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address);
180
181     return NRC_GOODRET;
182 }
183
184 BOOL WINAPI
185 NETAPI32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
186 {
187     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
188
189     switch (fdwReason) {
190         case DLL_PROCESS_ATTACH:
191             NETAPI32_hModule = hinstDLL;
192             break;
193         case DLL_PROCESS_DETACH:
194             break;
195     }
196
197     return TRUE;
198 }
199
200 BOOL WINAPI Netbios(PNCB pncb)
201 {
202     UCHAR ret = NRC_ILLCMD;
203
204     TRACE("ncb = %p\n",pncb);
205
206     if(!pncb)
207         return NRC_INVADDRESS;
208
209     switch(pncb->ncb_command&0x7f)
210     {
211     case NCBRESET:
212         FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
213         if( (pncb->ncb_lana_num < MAX_LANA ) &&
214              NETBIOS_Adapter[pncb->ncb_lana_num].valid)
215             ret = NRC_GOODRET;
216         else
217             ret = NRC_ILLCMD; /* NetBIOS emulator not found */
218         break;
219
220     case NCBADDNAME:
221         FIXME("NCBADDNAME\n");
222         break;
223
224     case NCBADDGRNAME:
225         FIXME("NCBADDGRNAME\n");
226         break;
227
228     case NCBDELNAME:
229         FIXME("NCBDELNAME\n");
230         break;
231
232     case NCBSEND:
233         FIXME("NCBSEND\n");
234         break;
235
236     case NCBRECV:
237         FIXME("NCBRECV\n");
238         break;
239
240     case NCBHANGUP:
241         FIXME("NCBHANGUP\n");
242         break;
243
244     case NCBCANCEL:
245         FIXME("NCBCANCEL\n");
246         break;
247
248     case NCBLISTEN:
249         FIXME("NCBLISTEN\n");
250         break;
251
252     case NCBASTAT:
253         ret = NETBIOS_Astat(pncb);
254         break;
255
256     case NCBENUM:
257         ret = NETBIOS_Enum(pncb);
258         break;
259
260     default:
261         FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);
262
263         ret = NRC_ILLCMD; /* NetBIOS emulator not found */
264     }
265     pncb->ncb_retcode = ret;
266     return ret;
267 }
268