Link to ntdll.
[wine] / dlls / netapi32 / access.c
1 /*
2  * Copyright 2002 Andriy Palamarchuk
3  *
4  * netapi32 access 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
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "lmcons.h"
27 #include "lmaccess.h"
28 #include "lmapibuf.h"
29 #include "lmerr.h"
30 #include "netapi32_misc.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
35
36 const WCHAR sAdminUserName[] = {'A','d','m','i','n','i','s','t','r','a','t',
37                                 'o','r',0};
38 const WCHAR sGuestUserName[] = {'G','u','e','s','t',0};
39
40 /************************************************************
41  *                NETAPI_ValidateServername
42  *
43  * Validates server name
44  */
45 NET_API_STATUS NETAPI_ValidateServername(LPCWSTR ServerName)
46 {
47     if (ServerName)
48     {
49         if (ServerName[0] == 0)
50             return ERROR_BAD_NETPATH;
51         else if (
52             ((ServerName[0] == '\\') &&
53              (ServerName[1] != '\\'))
54             ||
55             ((ServerName[0] == '\\') &&
56              (ServerName[1] == '\\') &&
57              (ServerName[2] == 0))
58             )
59             return ERROR_INVALID_NAME;
60     }
61     return NERR_Success;
62 }
63
64 /************************************************************
65  *                NETAPI_IsKnownUser
66  *
67  * Checks whether the user name indicates current user.
68  */
69 BOOL NETAPI_IsKnownUser(LPCWSTR UserName)
70 {
71     DWORD dwSize = UNLEN + 1;
72     BOOL Result;
73     LPWSTR buf;
74
75     if (!lstrcmpW(UserName, sAdminUserName) ||
76         !lstrcmpW(UserName, sGuestUserName))
77         return TRUE;
78     NetApiBufferAllocate(dwSize * sizeof(WCHAR), (LPVOID *) &buf);
79     Result = GetUserNameW(buf, &dwSize);
80
81     Result = Result && !lstrcmpW(UserName, buf);
82     NetApiBufferFree(buf);
83
84     return Result;
85 }
86
87 #define NETAPI_ForceKnownUser(UserName, FailureCode) \
88     if (!NETAPI_IsKnownUser(UserName)) \
89     { \
90         FIXME("Can't find information for user %s\n", \
91               debugstr_w(UserName)); \
92         return FailureCode; \
93     }
94
95 /************************************************************
96  *                NetUserGetInfo  (NETAPI32.@)
97  */
98 NET_API_STATUS WINAPI
99 NetUserGetInfo(LPCWSTR servername, LPCWSTR username, DWORD level,
100                LPBYTE* bufptr)
101 {
102     NET_API_STATUS status;
103     TRACE("(%s, %s, %ld, %p)\n", debugstr_w(servername), debugstr_w(username),
104           level, bufptr);
105     status = NETAPI_ValidateServername(servername);
106     if (status != NERR_Success)
107         return status;
108     NETAPI_ForceLocalComputer(servername, NERR_InvalidComputer);
109     NETAPI_ForceKnownUser(username, NERR_UserNotFound);
110
111     switch (level)
112     {
113     case 0:
114     {
115         PUSER_INFO_0 ui;
116         int name_sz;
117
118         name_sz = lstrlenW(username) + 1;
119
120         /* set up buffer */
121         NetApiBufferAllocate(sizeof(USER_INFO_0) + name_sz * sizeof(WCHAR),
122                              (LPVOID *) bufptr);
123
124         ui = (PUSER_INFO_0) *bufptr;
125         ui->usri0_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_0));
126
127         /* get data */
128         lstrcpyW(ui->usri0_name, username);
129         break;
130     }
131
132     case 10:
133     {
134         PUSER_INFO_10 ui;
135         PUSER_INFO_0 ui0;
136         NET_API_STATUS status;
137         /* sizes of the field buffers in WCHARS */
138         int name_sz, comment_sz, usr_comment_sz, full_name_sz;
139
140         comment_sz = 1;
141         usr_comment_sz = 1;
142         full_name_sz = 1;
143
144         /* get data */
145         status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
146         if (status != NERR_Success)
147         {
148             NetApiBufferFree(ui0);
149             return status;
150         }
151         name_sz = lstrlenW(ui0->usri0_name) + 1;
152
153         /* set up buffer */
154         NetApiBufferAllocate(sizeof(USER_INFO_10) +
155                              (name_sz + comment_sz + usr_comment_sz +
156                               full_name_sz) * sizeof(WCHAR),
157                              (LPVOID *) bufptr);
158         ui = (PUSER_INFO_10) *bufptr;
159         ui->usri10_name = (LPWSTR) (*bufptr + sizeof(USER_INFO_10));
160         ui->usri10_comment = (LPWSTR) (
161             ((PBYTE) ui->usri10_name) + name_sz * sizeof(WCHAR));
162         ui->usri10_usr_comment = (LPWSTR) (
163             ((PBYTE) ui->usri10_comment) + comment_sz * sizeof(WCHAR));
164         ui->usri10_full_name = (LPWSTR) (
165             ((PBYTE) ui->usri10_usr_comment) + usr_comment_sz * sizeof(WCHAR));
166
167         /* set data */
168         lstrcpyW(ui->usri10_name, ui0->usri0_name);
169         NetApiBufferFree(ui0);
170         ui->usri10_comment[0] = 0;
171         ui->usri10_usr_comment[0] = 0;
172         ui->usri10_full_name[0] = 0;
173         break;
174     }
175
176     case 1:
177       {
178         static const WCHAR homedirW[] = {'H','O','M','E',0};
179         PUSER_INFO_1 ui;
180         PUSER_INFO_0 ui0;
181         NET_API_STATUS status;
182         /* sizes of the field buffers in WCHARS */
183         int name_sz, password_sz, home_dir_sz, comment_sz, script_path_sz;
184
185         password_sz = 1; /* not filled out for security reasons for NetUserGetInfo*/
186         comment_sz = 1;
187         script_path_sz = 1;
188
189        /* get data */
190         status = NetUserGetInfo(servername, username, 0, (LPBYTE *) &ui0);
191         if (status != NERR_Success)
192         {
193             NetApiBufferFree(ui0);
194             return status;
195         }
196         name_sz = lstrlenW(ui0->usri0_name) + 1;
197         home_dir_sz = GetEnvironmentVariableW(homedirW, NULL,0);
198         /* set up buffer */
199         NetApiBufferAllocate(sizeof(USER_INFO_1) +
200                              (name_sz + password_sz + home_dir_sz +
201                               comment_sz + script_path_sz) * sizeof(WCHAR),
202                              (LPVOID *) bufptr);
203
204         ui = (PUSER_INFO_1) *bufptr;
205         ui->usri1_name = (LPWSTR) (ui + 1);
206         ui->usri1_password = ui->usri1_name + name_sz;
207         ui->usri1_home_dir = ui->usri1_password + password_sz;
208         ui->usri1_comment = ui->usri1_home_dir + home_dir_sz;
209         ui->usri1_script_path = ui->usri1_comment + comment_sz;
210         /* set data */
211         lstrcpyW(ui->usri1_name, ui0->usri0_name);
212         NetApiBufferFree(ui0);
213         ui->usri1_password[0] = 0;
214         ui->usri1_password_age = 0;
215         ui->usri1_priv = 0;
216         GetEnvironmentVariableW(homedirW, ui->usri1_home_dir,home_dir_sz);
217         ui->usri1_comment[0] = 0;
218         ui->usri1_flags = 0;
219         ui->usri1_script_path[0] = 0;
220         break;
221       }
222     case 2:
223     case 3:
224     case 4:
225     case 11:
226     case 20:
227     case 23:
228     case 1003:
229     case 1005:
230     case 1006:
231     case 1007:
232     case 1008:
233     case 1009:
234     case 1010:
235     case 1011:
236     case 1012:
237     case 1013:
238     case 1014:
239     case 1017:
240     case 1018:
241     case 1020:
242     case 1023:
243     case 1024:
244     case 1025:
245     case 1051:
246     case 1052:
247     case 1053:
248     {
249         FIXME("Level %ld is not implemented\n", level);
250         break;
251     }
252     default:
253         ERR("Invalid level %ld is specified\n", level);
254         return ERROR_INVALID_LEVEL;
255     }
256     return NERR_Success;
257 }
258
259
260
261 /************************************************************
262  *                NetUserEnum  (NETAPI32.@)
263  */
264 NET_API_STATUS WINAPI
265 NetUserEnum(LPCWSTR servername, DWORD level, DWORD filter, LPBYTE* bufptr,
266             DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries,
267             LPDWORD resume_handle)
268 {
269   FIXME("stub!\n");
270   return ERROR_ACCESS_DENIED;
271 }
272
273 /************************************************************
274  *                ACCESS_QueryAdminDisplayInformation
275  *
276  *  Creates a buffer with information for the Admin User
277  */
278 void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
279 {
280     const WCHAR sAdminUserName[] = {
281         'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
282
283     /* sizes of the field buffers in WCHARS */
284     int name_sz, comment_sz, full_name_sz;
285     PNET_DISPLAY_USER usr;
286
287     /* set up buffer */
288     name_sz = lstrlenW(sAdminUserName);
289     comment_sz = 1;
290     full_name_sz = 1;
291     
292     *pdwSize = sizeof(NET_DISPLAY_USER);
293     *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
294     NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
295
296     usr = *buf;
297     usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
298     usr->usri1_comment = (LPWSTR) (
299         ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
300     usr->usri1_full_name = (LPWSTR) (
301         ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
302
303     /* set data */
304     lstrcpyW(usr->usri1_name, sAdminUserName);
305     usr->usri1_comment[0] = 0;
306     usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
307     usr->usri1_full_name[0] = 0;
308     usr->usri1_user_id = 500;
309     usr->usri1_next_index = 0;
310 }
311
312 /************************************************************
313  *                ACCESS_QueryGuestDisplayInformation
314  *
315  *  Creates a buffer with information for the Guest User
316  */
317 void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
318 {
319     const WCHAR sGuestUserName[] = {
320         'G','u','e','s','t',0 };
321
322     /* sizes of the field buffers in WCHARS */
323     int name_sz, comment_sz, full_name_sz;
324     PNET_DISPLAY_USER usr;
325
326     /* set up buffer */
327     name_sz = lstrlenW(sGuestUserName);
328     comment_sz = 1;
329     full_name_sz = 1;
330     
331     *pdwSize = sizeof(NET_DISPLAY_USER);
332     *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
333     NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
334
335     usr = *buf;
336     usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
337     usr->usri1_comment = (LPWSTR) (
338         ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
339     usr->usri1_full_name = (LPWSTR) (
340         ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
341
342     /* set data */
343     lstrcpyW(usr->usri1_name, sGuestUserName);
344     usr->usri1_comment[0] = 0;
345     usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
346         UF_DONT_EXPIRE_PASSWD;
347     usr->usri1_full_name[0] = 0;
348     usr->usri1_user_id = 500;
349     usr->usri1_next_index = 0;
350 }
351
352 /************************************************************
353  *                NetQueryDisplayInformation  (NETAPI32.@)
354  * Copies NET_DISPLAY_USER record.
355  */
356 void ACCESS_CopyDisplayUser(PNET_DISPLAY_USER dest, LPWSTR *dest_buf,
357                             PNET_DISPLAY_USER src)
358 {
359     LPWSTR str = *dest_buf;
360
361     src->usri1_name = str;
362     lstrcpyW(src->usri1_name, dest->usri1_name);
363     str = (LPWSTR) (
364         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
365
366     src->usri1_comment = str;
367     lstrcpyW(src->usri1_comment, dest->usri1_comment);
368     str = (LPWSTR) (
369         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
370
371     src->usri1_flags = dest->usri1_flags;
372
373     src->usri1_full_name = str;
374     lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
375     str = (LPWSTR) (
376         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
377
378     src->usri1_user_id = dest->usri1_user_id;
379     src->usri1_next_index = dest->usri1_next_index;
380     *dest_buf = str;
381 }
382
383 /************************************************************
384  *                NetQueryDisplayInformation  (NETAPI32.@)
385  *
386  * The buffer structure:
387  * - array of fixed size record of the level type
388  * - strings, referenced by the record of the level type
389  */
390 NET_API_STATUS WINAPI
391 NetQueryDisplayInformation(
392     LPWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
393     DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
394     PVOID *SortedBuffer)
395 {
396     TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
397           Level, Index, EntriesRequested, PreferredMaximumLength,
398           ReturnedEntryCount, SortedBuffer);
399     NETAPI_ForceLocalComputer(ServerName, ERROR_ACCESS_DENIED);
400     switch (Level)
401     {
402     case 1:
403     {
404         /* current record */
405         PNET_DISPLAY_USER inf;
406         /* current available strings buffer */
407         LPWSTR str;
408         PNET_DISPLAY_USER admin, guest;
409         DWORD admin_size, guest_size;
410         LPWSTR name = NULL;
411         DWORD dwSize;
412
413         /* sizes of the field buffers in WCHARS */
414         int name_sz, comment_sz, full_name_sz;
415
416         /* number of the records, returned in SortedBuffer
417            3 - for current user, Administrator and Guest users
418          */
419         int records = 3;
420
421         FIXME("Level %ld partially implemented\n", Level);
422         *ReturnedEntryCount = records;
423         comment_sz = 1;
424         full_name_sz = 1;
425
426         /* get data */
427         dwSize = UNLEN + 1;
428         NetApiBufferAllocate(dwSize, (LPVOID *) &name);
429         if (!GetUserNameW(name, &dwSize))
430         {
431             NetApiBufferFree(name);
432             return ERROR_ACCESS_DENIED;
433         }
434         name_sz = dwSize;
435         ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
436         ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
437
438         /* set up buffer */
439         dwSize = sizeof(NET_DISPLAY_USER) * records;
440         dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
441
442         NetApiBufferAllocate(dwSize +
443                              admin_size - sizeof(NET_DISPLAY_USER) +
444                              guest_size - sizeof(NET_DISPLAY_USER),
445                              (LPVOID *) SortedBuffer);
446         inf = (PNET_DISPLAY_USER) *SortedBuffer;
447         str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
448         inf->usri1_name = str;
449         str = (LPWSTR) (
450             ((PBYTE) str) + name_sz * sizeof(WCHAR));
451         inf->usri1_comment = str;
452         str = (LPWSTR) (
453             ((PBYTE) str) + comment_sz * sizeof(WCHAR));
454         inf->usri1_full_name = str;
455         str = (LPWSTR) (
456             ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
457
458         /* set data */
459         lstrcpyW(inf->usri1_name, name);
460         NetApiBufferFree(name);
461         inf->usri1_comment[0] = 0;
462         inf->usri1_flags =
463             UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
464         inf->usri1_full_name[0] = 0;
465         inf->usri1_user_id = 0;
466         inf->usri1_next_index = 0;
467
468         inf++;
469         ACCESS_CopyDisplayUser(admin, &str, inf);
470         NetApiBufferFree(admin);
471
472         inf++;
473         ACCESS_CopyDisplayUser(guest, &str, inf);
474         NetApiBufferFree(guest);
475         break;
476     }
477
478     case 2:
479     case 3:
480     {
481         FIXME("Level %ld is not implemented\n", Level);
482         break;
483     }
484
485     default:
486         ERR("Invalid level %ld is specified\n", Level);
487         return ERROR_INVALID_LEVEL;
488     }
489     return NERR_Success;
490 }
491
492 /************************************************************
493  *                NetGetDCName  (NETAPI32.@)
494  *
495  *  Return the name of the primary domain controller (PDC)
496  */
497
498 NET_API_STATUS WINAPI
499 NetGetDCName(LPWSTR servername, LPWSTR domainname, LPBYTE *bufptr)
500 {
501   FIXME("stub!\n");
502   return NERR_DCNotFound; /* say we can't find a domain controller */  
503 }
504
505
506 /************************************************************
507  *                NetUserModalsGet  (NETAPI32.@)
508  */
509 NET_API_STATUS WINAPI NetUserModalsGet(LPCWSTR szServer, DWORD level, LPBYTE *pbuffer)
510 {
511     FIXME("%s %ld %p\n", debugstr_w( szServer ), level, pbuffer );
512     return NERR_InternalError;
513 }
514
515 NET_API_STATUS WINAPI NetLocalGroupAdd( LPCWSTR servername, DWORD level,
516                  LPBYTE buf, LPDWORD parm_err)
517 {
518     FIXME("%s %ld %p %p\n", debugstr_w( servername ), level, buf, parm_err);
519     return NERR_Success;
520 }
521
522 NET_API_STATUS WINAPI NetLocalGroupSetMembers( LPCWSTR servername,
523              LPCWSTR groupname, DWORD level, LPBYTE buf, DWORD totalentries)
524 {
525     FIXME("%s %s %ld %p %ld\n", debugstr_w(servername), debugstr_w(groupname),
526           level, buf, totalentries);
527     return NERR_Success;
528 }