Fixed a race condition on RPC worker thread creation, and a typo.
[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 #ifdef HAVE_UNISTD_H
25 # include <unistd.h>
26 #endif
27
28 #include "winbase.h"
29 #include "winreg.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "wine/debug.h"
33 #include "winerror.h"
34 #include "nb30.h"
35
36 #ifdef HAVE_SYS_FILE_H
37 # include <sys/file.h>
38 #endif
39 #ifdef HAVE_SYS_IOCTL_H
40 # include <sys/ioctl.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKET_H
43 # include <sys/socket.h>
44 #endif
45 #ifdef HAVE_SYS_SOCKIO_H
46 # include <sys/sockio.h>
47 #endif
48 #ifdef HAVE_NET_IF_H
49 # include <net/if.h>
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif
54
55 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
56 #  ifndef max
57 #   define max(a,b) ((a) > (b) ? (a) : (b))
58 #  endif
59 #  define ifreq_size(i) max(sizeof(struct ifreq),\
60 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
61 # else
62 #  define ifreq_size(i) sizeof(struct ifreq)
63 # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
64
65 WINE_DEFAULT_DEBUG_CHANNEL(netbios);
66
67 HMODULE NETAPI32_hModule = 0;
68
69 struct NetBiosAdapter
70 {
71     int valid;
72     unsigned char address[6];
73 };
74
75 static struct NetBiosAdapter NETBIOS_Adapter[MAX_LANA];
76
77 # ifdef SIOCGIFHWADDR
78 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
79 {
80     if (ioctl(sd, SIOCGIFHWADDR, ifr) < 0)
81         return -1;
82     memcpy(address, (unsigned char *)&ifr->ifr_hwaddr.sa_data, 6);
83     return 0;
84 }
85 # else
86 #  ifdef SIOCGENADDR
87 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
88 {
89     if (ioctl(sd, SIOCGENADDR, ifr) < 0)
90         return -1;
91     memcpy(address, (unsigned char *) ifr->ifr_enaddr, 6);
92     return 0;
93 }
94 #   else
95 int get_hw_address(int sd, struct ifreq *ifr, unsigned char *address)
96 {
97     return -1;
98 }
99 #  endif /* SIOCGENADDR */
100 # endif /* SIOCGIFHWADDR */
101
102 int enum_hw(void)
103 {
104     int ret = 0;
105 #ifdef HAVE_NET_IF_H
106     int             sd;
107     struct ifreq    ifr, *ifrp;
108     struct ifconf   ifc;
109     unsigned char   buf[1024];
110     int             i, ofs;
111     /* BSD 4.4 defines the size of an ifreq to be
112      * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
113      * However, under earlier systems, sa_len isn't present, so
114      *  the size is just sizeof(struct ifreq)
115      */
116
117     sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
118     if (sd < 0)
119         return NRC_OPENERROR;
120
121     memset(buf, 0, sizeof(buf));
122     ifc.ifc_len = sizeof(buf);
123     ifc.ifc_buf = buf;
124     /* get the ifconf interface */
125     if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
126     {
127         close(sd);
128         return NRC_OPENERROR;
129     }
130
131     /* loop through the interfaces, looking for a valid one */
132     /* n = ifc.ifc_len; */
133     ofs = 0;
134     for (i = 0; i < ifc.ifc_len; i++)
135     {
136         unsigned char *a = NETBIOS_Adapter[i].address;
137
138         ifrp = (struct ifreq *)((char *)ifc.ifc_buf+ofs);
139         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
140
141         /* try to get the address for this interface */
142         if(get_hw_address(sd, &ifr, a)==0)
143         {
144             /* make sure it's not blank */
145             /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
146                 continue; */
147
148             TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i,
149                         a[0],a[1],a[2],a[3],a[4],a[5]);
150
151             NETBIOS_Adapter[i].valid = TRUE;
152
153             ret++;
154         }
155         ofs += ifreq_size(ifr);
156     }
157     close(sd);
158     TRACE("found %d adapters\n",ret);
159 #endif /* HAVE_NET_IF_H */
160     return ret;
161 }
162
163 void wprint_mac(WCHAR* buffer, int index)
164 {
165   int i;
166   unsigned char  val;
167   for (i = 0; i<6; i++)
168     {
169       val = NETBIOS_Adapter[index].address[i];
170       if ((val >>4) >9)
171         buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
172       else
173         buffer[2*i] = (WCHAR)((val >>4) + '0');
174       if ((val & 0xf ) >9)
175         buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
176       else
177         buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
178     }
179   buffer[12]=(WCHAR)0;
180       
181 }
182 static UCHAR NETBIOS_Enum(PNCB ncb)
183 {
184     int             i;
185     LANA_ENUM *lanas = (PLANA_ENUM) ncb->ncb_buffer;
186
187     TRACE("NCBENUM\n");
188
189     lanas->length = 0;
190     for (i = 0; i < enum_hw(); i++)
191     {
192          lanas->lana[lanas->length] = i;
193          lanas->length++;
194     }
195     return NRC_GOODRET;
196 }
197
198
199 static UCHAR NETBIOS_Astat(PNCB ncb)
200 {
201     struct NetBiosAdapter *nad = &NETBIOS_Adapter[ncb->ncb_lana_num];
202     PADAPTER_STATUS astat = (PADAPTER_STATUS) ncb->ncb_buffer;
203
204     TRACE("NCBASTAT (Adapter %d)\n", ncb->ncb_lana_num);
205
206     if(!nad->valid)
207         return NRC_INVADDRESS;
208
209     memset(astat, 0, sizeof astat);
210     memcpy(astat->adapter_address, nad->address, sizeof astat->adapter_address);
211
212     return NRC_GOODRET;
213 }
214
215 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
216 {
217     TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
218
219     switch (fdwReason) {
220         case DLL_PROCESS_ATTACH:
221             NETAPI32_hModule = hinstDLL;
222             break;
223         case DLL_PROCESS_DETACH:
224             break;
225     }
226
227     return TRUE;
228 }
229
230 BOOL WINAPI Netbios(PNCB pncb)
231 {
232     UCHAR ret = NRC_ILLCMD;
233
234     TRACE("ncb = %p\n",pncb);
235
236     if(!pncb)
237         return NRC_INVADDRESS;
238
239     switch(pncb->ncb_command&0x7f)
240     {
241     case NCBRESET:
242         FIXME("NCBRESET adapter %d\n",pncb->ncb_lana_num);
243         if( (pncb->ncb_lana_num < MAX_LANA ) &&
244              NETBIOS_Adapter[pncb->ncb_lana_num].valid)
245             ret = NRC_GOODRET;
246         else
247             ret = NRC_ILLCMD; /* NetBIOS emulator not found */
248         break;
249
250     case NCBADDNAME:
251         FIXME("NCBADDNAME\n");
252         break;
253
254     case NCBADDGRNAME:
255         FIXME("NCBADDGRNAME\n");
256         break;
257
258     case NCBDELNAME:
259         FIXME("NCBDELNAME\n");
260         break;
261
262     case NCBSEND:
263         FIXME("NCBSEND\n");
264         break;
265
266     case NCBRECV:
267         FIXME("NCBRECV\n");
268         break;
269
270     case NCBHANGUP:
271         FIXME("NCBHANGUP\n");
272         break;
273
274     case NCBCANCEL:
275         FIXME("NCBCANCEL\n");
276         break;
277
278     case NCBLISTEN:
279         FIXME("NCBLISTEN\n");
280         break;
281
282     case NCBASTAT:
283         ret = NETBIOS_Astat(pncb);
284         break;
285
286     case NCBENUM:
287         ret = NETBIOS_Enum(pncb);
288         break;
289
290     default:
291         FIXME("(%p): command code %02x\n", pncb, pncb->ncb_command);
292
293         ret = NRC_ILLCMD; /* NetBIOS emulator not found */
294     }
295     pncb->ncb_retcode = ret;
296     return ret;
297 }