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