INT21_GetFreeDiskSpace(): The drive parameter is found in the DL
[wine] / dlls / netapi32 / wksta.c
1 /*
2  * Copyright 2002 Andriy Palamarchuk
3  *
4  * netapi32 user functions
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "nb30.h"
26 #include "lmcons.h"
27 #include "lmapibuf.h"
28 #include "lmerr.h"
29 #include "lmwksta.h"
30 #include "iphlpapi.h"
31 #include "winerror.h"
32 #include "ntstatus.h"
33 #include "winreg.h"
34 #include "winternl.h"
35 #include "ntsecapi.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
39
40 /************************************************************
41  *                NETAPI_IsLocalComputer
42  *
43  * Checks whether the server name indicates local machine.
44  */
45 BOOL NETAPI_IsLocalComputer(LPCWSTR ServerName)
46 {
47     if (!ServerName)
48     {
49         return TRUE;
50     }
51     else
52     {
53         DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
54         BOOL Result;
55         LPWSTR buf;
56
57         NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
58         Result = GetComputerNameW(buf,  &dwSize);
59         if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
60             ServerName += 2;
61         Result = Result && !lstrcmpW(ServerName, buf);
62         NetApiBufferFree(buf);
63
64         return Result;
65     }
66 }
67
68 static void wprint_mac(WCHAR* buffer, PIP_ADAPTER_INFO adapter)
69 {
70   if (adapter != NULL)
71     {
72       int i;
73       unsigned char  val;
74
75       for (i = 0; i<max(adapter->AddressLength, 6); i++)
76         {
77           val = adapter->Address[i];
78           if ((val >>4) >9)
79             buffer[2*i] = (WCHAR)((val >>4) + 'A' - 10);
80           else
81             buffer[2*i] = (WCHAR)((val >>4) + '0');
82           if ((val & 0xf ) >9)
83             buffer[2*i+1] = (WCHAR)((val & 0xf) + 'A' - 10);
84           else
85             buffer[2*i+1] = (WCHAR)((val & 0xf) + '0');
86         }
87       buffer[12]=(WCHAR)0;
88     }
89   else
90     buffer[0] = 0;
91 }
92
93 #define TRANSPORT_NAME_HEADER "\\Device\\NetBT_Tcpip_"
94 #define TRANSPORT_NAME_LEN \
95  (sizeof(TRANSPORT_NAME_HEADER) + MAX_ADAPTER_NAME_LENGTH)
96
97 static void wprint_name(WCHAR *buffer, int len, PIP_ADAPTER_INFO adapter)
98 {
99   WCHAR *ptr;
100   const char *name;
101
102   if (!buffer)
103     return;
104   if (!adapter)
105     return;
106
107   for (ptr = buffer, name = TRANSPORT_NAME_HEADER; *name && ptr < buffer + len;
108    ptr++, name++)
109     *ptr = *name;
110   for (name = adapter->AdapterName; name && *name && ptr < buffer + len;
111    ptr++, name++)
112     *ptr = *name;
113   *ptr = '\0';
114 }
115
116 NET_API_STATUS WINAPI 
117 NetWkstaTransportEnum(LPCWSTR ServerName, DWORD level, LPBYTE* pbuf,
118                       DWORD prefmaxlen, LPDWORD read_entries,
119                       LPDWORD total_entries, LPDWORD hresume)
120 {
121   FIXME(":%s, 0x%08lx, %p, 0x%08lx, %p, %p, %p\n", debugstr_w(ServerName), 
122         level, pbuf, prefmaxlen, read_entries, total_entries,hresume);
123   if (!NETAPI_IsLocalComputer(ServerName))
124     {
125       FIXME(":not implemented for non-local computers\n");
126       return ERROR_INVALID_LEVEL;
127     }
128   else
129     {
130       if (hresume && *hresume)
131         {
132           FIXME(":resume handle not implemented\n");
133           return ERROR_INVALID_LEVEL;
134         }
135         
136       switch (level)
137         {
138         case 0: /* transport info */
139           {
140             PWKSTA_TRANSPORT_INFO_0 ti;
141             int i,size_needed,n_adapt;
142             DWORD apiReturn, adaptInfoSize = 0;
143             PIP_ADAPTER_INFO info, ptr;
144             
145             apiReturn = GetAdaptersInfo(NULL, &adaptInfoSize);
146             if (apiReturn == ERROR_NO_DATA)
147               return ERROR_NETWORK_UNREACHABLE;
148             if (!read_entries)
149               return STATUS_ACCESS_VIOLATION;
150             if (!total_entries || !pbuf)
151               return RPC_X_NULL_REF_POINTER;
152
153             info = (PIP_ADAPTER_INFO)malloc(adaptInfoSize);
154             apiReturn = GetAdaptersInfo(info, &adaptInfoSize);
155             if (apiReturn != NO_ERROR)
156               {
157                 free(info);
158                 return apiReturn;
159               }
160
161             for (n_adapt = 0, ptr = info; ptr; ptr = ptr->Next)
162               n_adapt++;
163             size_needed = n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) 
164              + n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
165              + n_adapt * 13 * sizeof (WCHAR);
166             if (prefmaxlen == MAX_PREFERRED_LENGTH)
167               NetApiBufferAllocate( size_needed, (LPVOID *) pbuf);
168             else
169               {
170                 if (size_needed > prefmaxlen)
171                   {
172                     free(info);
173                     return ERROR_MORE_DATA;
174                   }
175                 NetApiBufferAllocate(prefmaxlen,
176                                      (LPVOID *) pbuf);
177               }
178             for (i = 0, ptr = info; ptr; ptr = ptr->Next, i++)
179               {
180                 ti = (PWKSTA_TRANSPORT_INFO_0) 
181                   ((PBYTE) *pbuf + i * sizeof(WKSTA_TRANSPORT_INFO_0));
182                 ti->wkti0_quality_of_service=0;
183                 ti->wkti0_number_of_vcs=0;
184                 ti->wkti0_transport_name= (LPWSTR)
185                   ((PBYTE )*pbuf +
186                    n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0)
187                    + i * TRANSPORT_NAME_LEN * sizeof (WCHAR));
188                 wprint_name(ti->wkti0_transport_name,TRANSPORT_NAME_LEN, ptr);
189                 ti->wkti0_transport_address= (LPWSTR)
190                   ((PBYTE )*pbuf +
191                    n_adapt * sizeof(WKSTA_TRANSPORT_INFO_0) +
192                    n_adapt * TRANSPORT_NAME_LEN * sizeof (WCHAR)
193                    + i * 13 * sizeof (WCHAR));
194                 ti->wkti0_wan_ish=TRUE; /*TCPIP/NETBIOS Protocoll*/
195                 wprint_mac(ti->wkti0_transport_address, ptr);
196                 TRACE("%d of %d:ti at %p transport_address at %p %s\n",i,n_adapt,
197                       ti, ti->wkti0_transport_address, debugstr_w(ti->wkti0_transport_address));
198               }
199             *read_entries = n_adapt;
200             *total_entries = n_adapt;
201             free(info);
202             if(hresume) *hresume= 0;
203             break;
204           }
205         default:
206           ERR("Invalid level %ld is specified\n", level);
207           return ERROR_INVALID_LEVEL;
208         }
209       return NERR_Success;
210     }
211 }
212                                             
213
214 /************************************************************
215  *                NetWkstaUserGetInfo  (NETAPI32.@)
216  */
217 NET_API_STATUS WINAPI NetWkstaUserGetInfo(LPWSTR reserved, DWORD level,
218                                           PBYTE* bufptr)
219 {
220     TRACE("(%s, %ld, %p)\n", debugstr_w(reserved), level, bufptr);
221     switch (level)
222     {
223     case 0:
224     {
225         PWKSTA_USER_INFO_0 ui;
226         DWORD dwSize = UNLEN + 1;
227
228         /* set up buffer */
229         NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_0) + dwSize * sizeof(WCHAR),
230                              (LPVOID *) bufptr);
231
232         ui = (PWKSTA_USER_INFO_0) *bufptr;
233         ui->wkui0_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_0));
234
235         /* get data */
236         if (!GetUserNameW(ui->wkui0_username, &dwSize))
237         {
238             NetApiBufferFree(ui);
239             return ERROR_NOT_ENOUGH_MEMORY;
240         }
241         else
242             NetApiBufferReallocate(
243                 *bufptr, sizeof(WKSTA_USER_INFO_0) +
244                 (lstrlenW(ui->wkui0_username) + 1) * sizeof(WCHAR),
245                 (LPVOID *) bufptr);
246         break;
247     }
248
249     case 1:
250     {
251         PWKSTA_USER_INFO_1 ui;
252         PWKSTA_USER_INFO_0 ui0;
253         DWORD dwSize;
254         LSA_OBJECT_ATTRIBUTES ObjectAttributes;
255         LSA_HANDLE PolicyHandle;
256         PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo;
257         NTSTATUS NtStatus;
258
259         /* sizes of the field buffers in WCHARS */
260         int username_sz, logon_domain_sz, oth_domains_sz, logon_server_sz;
261
262         FIXME("Level 1 processing is partially implemented\n");
263         oth_domains_sz = 1;
264         logon_server_sz = 1;
265
266         /* get some information first to estimate size of the buffer */
267         ui0 = NULL;
268         NetWkstaUserGetInfo(NULL, 0, (PBYTE *) &ui0);
269         username_sz = lstrlenW(ui0->wkui0_username) + 1;
270
271         ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
272         NtStatus = LsaOpenPolicy(NULL, &ObjectAttributes,
273                                  POLICY_VIEW_LOCAL_INFORMATION,
274                                  &PolicyHandle);
275         if (NtStatus != STATUS_SUCCESS)
276         {
277             ERR("LsaOpenPolicyFailed with NT status %lx\n",
278                 LsaNtStatusToWinError(NtStatus));
279             NetApiBufferFree(ui0);
280             return ERROR_NOT_ENOUGH_MEMORY;
281         }
282         LsaQueryInformationPolicy(PolicyHandle, PolicyAccountDomainInformation,
283                                   (PVOID*) &DomainInfo);
284         logon_domain_sz = lstrlenW(DomainInfo->DomainName.Buffer) + 1;
285         LsaClose(PolicyHandle);
286
287         /* set up buffer */
288         NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1) +
289                              (username_sz + logon_domain_sz +
290                               oth_domains_sz + logon_server_sz) * sizeof(WCHAR),
291                              (LPVOID *) bufptr);
292         ui = (WKSTA_USER_INFO_1 *) *bufptr;
293         ui->wkui1_username = (LPWSTR) (*bufptr + sizeof(WKSTA_USER_INFO_1));
294         ui->wkui1_logon_domain = (LPWSTR) (
295             ((PBYTE) ui->wkui1_username) + username_sz * sizeof(WCHAR));
296         ui->wkui1_oth_domains = (LPWSTR) (
297             ((PBYTE) ui->wkui1_logon_domain) +
298             logon_domain_sz * sizeof(WCHAR));
299         ui->wkui1_logon_server = (LPWSTR) (
300             ((PBYTE) ui->wkui1_oth_domains) +
301             oth_domains_sz * sizeof(WCHAR));
302
303         /* get data */
304         dwSize = username_sz;
305         lstrcpyW(ui->wkui1_username, ui0->wkui0_username);
306         NetApiBufferFree(ui0);
307
308         lstrcpynW(ui->wkui1_logon_domain, DomainInfo->DomainName.Buffer,
309                 logon_domain_sz);
310         LsaFreeMemory(DomainInfo);
311
312         /* FIXME. Not implemented. Populated with empty strings */
313         ui->wkui1_oth_domains[0] = 0;
314         ui->wkui1_logon_server[0] = 0;
315         break;
316     }
317     case 1101:
318     {
319         PWKSTA_USER_INFO_1101 ui;
320         DWORD dwSize = 1;
321
322         FIXME("Stub. Level 1101 processing is not implemented\n");
323         /* FIXME see also wkui1_oth_domains for level 1 */
324
325         /* set up buffer */
326         NetApiBufferAllocate(sizeof(WKSTA_USER_INFO_1101) + dwSize * sizeof(WCHAR),
327                              (LPVOID *) bufptr);
328
329         ui = (PWKSTA_USER_INFO_1101) *bufptr;
330         ui->wkui1101_oth_domains = (LPWSTR)(ui + 1);
331
332         /* get data */
333         ui->wkui1101_oth_domains[0] = 0;
334         break;
335     }
336     default:
337         ERR("Invalid level %ld is specified\n", level);
338         return ERROR_INVALID_LEVEL;
339     }
340     return NERR_Success;
341 }
342
343 /************************************************************
344  *                NetpGetComputerName  (NETAPI32.@)
345  */
346 NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer)
347 {
348     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
349
350     TRACE("(%p)\n", Buffer);
351     NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) Buffer);
352     if (GetComputerNameW(*Buffer,  &dwSize))
353     {
354         NetApiBufferReallocate(
355             *Buffer, dwSize * sizeof(WCHAR),
356             (LPVOID *) Buffer);
357         return NERR_Success;
358     }
359     else
360     {
361         NetApiBufferFree(*Buffer);
362         return ERROR_NOT_ENOUGH_MEMORY;
363     }
364 }