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