- Add support for TBSTYLE_EX_MIXEDBUTTONS.
[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  *                ACCESS_QueryAdminDisplayInformation
261  *
262  *  Creates a buffer with information for the Admin User
263  */
264 void ACCESS_QueryAdminDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
265 {
266     const WCHAR sAdminUserName[] = {
267         'A','d','m','i','n','i','s','t','r','a','t','o','r',0};
268
269     /* sizes of the field buffers in WCHARS */
270     int name_sz, comment_sz, full_name_sz;
271     PNET_DISPLAY_USER usr;
272
273     /* set up buffer */
274     name_sz = lstrlenW(sAdminUserName);
275     comment_sz = 1;
276     full_name_sz = 1;
277     
278     *pdwSize = sizeof(NET_DISPLAY_USER);
279     *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
280     NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
281
282     usr = *buf;
283     usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
284     usr->usri1_comment = (LPWSTR) (
285         ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
286     usr->usri1_full_name = (LPWSTR) (
287         ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
288
289     /* set data */
290     lstrcpyW(usr->usri1_name, sAdminUserName);
291     usr->usri1_comment[0] = 0;
292     usr->usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
293     usr->usri1_full_name[0] = 0;
294     usr->usri1_user_id = 500;
295     usr->usri1_next_index = 0;
296 }
297
298 /************************************************************
299  *                ACCESS_QueryGuestDisplayInformation
300  *
301  *  Creates a buffer with information for the Guest User
302  */
303 void ACCESS_QueryGuestDisplayInformation(PNET_DISPLAY_USER *buf, PDWORD pdwSize)
304 {
305     const WCHAR sGuestUserName[] = {
306         'G','u','e','s','t',0 };
307
308     /* sizes of the field buffers in WCHARS */
309     int name_sz, comment_sz, full_name_sz;
310     PNET_DISPLAY_USER usr;
311
312     /* set up buffer */
313     name_sz = lstrlenW(sGuestUserName);
314     comment_sz = 1;
315     full_name_sz = 1;
316     
317     *pdwSize = sizeof(NET_DISPLAY_USER);
318     *pdwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
319     NetApiBufferAllocate(*pdwSize, (LPVOID *) buf);
320
321     usr = *buf;
322     usr->usri1_name = (LPWSTR) ((PBYTE) usr + sizeof(NET_DISPLAY_USER));
323     usr->usri1_comment = (LPWSTR) (
324         ((PBYTE) usr->usri1_name) + name_sz * sizeof(WCHAR));
325     usr->usri1_full_name = (LPWSTR) (
326         ((PBYTE) usr->usri1_comment) + comment_sz * sizeof(WCHAR));
327
328     /* set data */
329     lstrcpyW(usr->usri1_name, sGuestUserName);
330     usr->usri1_comment[0] = 0;
331     usr->usri1_flags = UF_ACCOUNTDISABLE | UF_SCRIPT | UF_NORMAL_ACCOUNT |
332         UF_DONT_EXPIRE_PASSWD;
333     usr->usri1_full_name[0] = 0;
334     usr->usri1_user_id = 500;
335     usr->usri1_next_index = 0;
336 }
337
338 /************************************************************
339  *                NetQueryDisplayInformation  (NETAPI32.@)
340  * Copies NET_DISPLAY_USER record.
341  */
342 void ACCESS_CopyDisplayUser(PNET_DISPLAY_USER dest, LPWSTR *dest_buf,
343                             PNET_DISPLAY_USER src)
344 {
345     LPWSTR str = *dest_buf;
346
347     src->usri1_name = str;
348     lstrcpyW(src->usri1_name, dest->usri1_name);
349     str = (LPWSTR) (
350         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
351
352     src->usri1_comment = str;
353     lstrcpyW(src->usri1_comment, dest->usri1_comment);
354     str = (LPWSTR) (
355         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
356
357     src->usri1_flags = dest->usri1_flags;
358
359     src->usri1_full_name = str;
360     lstrcpyW(src->usri1_full_name, dest->usri1_full_name);
361     str = (LPWSTR) (
362         ((PBYTE) str) + (lstrlenW(str) + 1) * sizeof(WCHAR));
363
364     src->usri1_user_id = dest->usri1_user_id;
365     src->usri1_next_index = dest->usri1_next_index;
366     *dest_buf = str;
367 }
368
369 /************************************************************
370  *                NetQueryDisplayInformation  (NETAPI32.@)
371  *
372  * The buffer structure:
373  * - array of fixed size record of the level type
374  * - strings, referenced by the record of the level type
375  */
376 NET_API_STATUS WINAPI
377 NetQueryDisplayInformation(
378     LPWSTR ServerName, DWORD Level, DWORD Index, DWORD EntriesRequested,
379     DWORD PreferredMaximumLength, LPDWORD ReturnedEntryCount,
380     PVOID *SortedBuffer)
381 {
382     TRACE("(%s, %ld, %ld, %ld, %ld, %p, %p)\n", debugstr_w(ServerName),
383           Level, Index, EntriesRequested, PreferredMaximumLength,
384           ReturnedEntryCount, SortedBuffer);
385     NETAPI_ForceLocalComputer(ServerName, ERROR_ACCESS_DENIED);
386     switch (Level)
387     {
388     case 1:
389     {
390         /* current record */
391         PNET_DISPLAY_USER inf;
392         /* current available strings buffer */
393         LPWSTR str;
394         PNET_DISPLAY_USER admin, guest;
395         DWORD admin_size, guest_size;
396         LPWSTR name = NULL;
397         DWORD dwSize;
398
399         /* sizes of the field buffers in WCHARS */
400         int name_sz, comment_sz, full_name_sz;
401
402         /* number of the records, returned in SortedBuffer
403            3 - for current user, Administrator and Guest users
404          */
405         int records = 3;
406
407         FIXME("Level %ld partially implemented\n", Level);
408         *ReturnedEntryCount = records;
409         comment_sz = 1;
410         full_name_sz = 1;
411
412         /* get data */
413         dwSize = UNLEN + 1;
414         NetApiBufferAllocate(dwSize, (LPVOID *) &name);
415         if (!GetUserNameW(name, &dwSize))
416         {
417             NetApiBufferFree(name);
418             return ERROR_ACCESS_DENIED;
419         }
420         name_sz = dwSize;
421         ACCESS_QueryAdminDisplayInformation(&admin, &admin_size);
422         ACCESS_QueryGuestDisplayInformation(&guest, &guest_size);
423
424         /* set up buffer */
425         dwSize = sizeof(NET_DISPLAY_USER) * records;
426         dwSize += (name_sz + comment_sz + full_name_sz) * sizeof(WCHAR);
427
428         NetApiBufferAllocate(dwSize +
429                              admin_size - sizeof(NET_DISPLAY_USER) +
430                              guest_size - sizeof(NET_DISPLAY_USER),
431                              (LPVOID *) SortedBuffer);
432         inf = (PNET_DISPLAY_USER) *SortedBuffer;
433         str = (LPWSTR) ((PBYTE) inf + sizeof(NET_DISPLAY_USER) * records);
434         inf->usri1_name = str;
435         str = (LPWSTR) (
436             ((PBYTE) str) + name_sz * sizeof(WCHAR));
437         inf->usri1_comment = str;
438         str = (LPWSTR) (
439             ((PBYTE) str) + comment_sz * sizeof(WCHAR));
440         inf->usri1_full_name = str;
441         str = (LPWSTR) (
442             ((PBYTE) str) + full_name_sz * sizeof(WCHAR));
443
444         /* set data */
445         lstrcpyW(inf->usri1_name, name);
446         NetApiBufferFree(name);
447         inf->usri1_comment[0] = 0;
448         inf->usri1_flags =
449             UF_SCRIPT | UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD;
450         inf->usri1_full_name[0] = 0;
451         inf->usri1_user_id = 0;
452         inf->usri1_next_index = 0;
453
454         inf++;
455         ACCESS_CopyDisplayUser(admin, &str, inf);
456         NetApiBufferFree(admin);
457
458         inf++;
459         ACCESS_CopyDisplayUser(guest, &str, inf);
460         NetApiBufferFree(guest);
461         break;
462     }
463
464     case 2:
465     case 3:
466     {
467         FIXME("Level %ld is not implemented\n", Level);
468         break;
469     }
470
471     default:
472         ERR("Invalid level %ld is specified\n", Level);
473         return ERROR_INVALID_LEVEL;
474     }
475     return NERR_Success;
476 }
477
478 /************************************************************
479  *                NetGetDCName  (NETAPI32.@)
480  *
481  *  Return the name of the primary domain controller (PDC)
482  */
483
484 NET_API_STATUS WINAPI
485 NetGetDCName(LPWSTR servername, LPWSTR domainname, LPBYTE bufptr)
486 {
487   FIXME("stub!\n");
488   return NERR_DCNotFound; /* say we can't find a domain controller */  
489 }
490
491