xref: /reactos/base/services/wkssvc/rpcserver.c (revision a25e7ee9)
1 /*
2  *  ReactOS Services
3  *  Copyright (C) 2015 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * COPYRIGHT:        See COPYING in the top level directory
21  * PROJECT:          ReactOS Services
22  * FILE:             base/services/wkssvc/rpcserver.c
23  * PURPOSE:          Workstation service
24  * PROGRAMMER:       Eric Kohl
25  */
26 
27 /* INCLUDES *****************************************************************/
28 
29 #include "precomp.h"
30 
31 #include "lmerr.h"
32 
33 WINE_DEFAULT_DEBUG_CHANNEL(wkssvc);
34 
35 /* FUNCTIONS *****************************************************************/
36 
37 DWORD
38 WINAPI
RpcThreadRoutine(LPVOID lpParameter)39 RpcThreadRoutine(
40     LPVOID lpParameter)
41 {
42     RPC_STATUS Status;
43 
44     Status = RpcServerUseProtseqEpW(L"ncacn_np", 20, L"\\pipe\\wkssvc", NULL);
45     if (Status != RPC_S_OK)
46     {
47         ERR("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
48         return 0;
49     }
50 
51     Status = RpcServerRegisterIf(wkssvc_v1_0_s_ifspec, NULL, NULL);
52     if (Status != RPC_S_OK)
53     {
54         ERR("RpcServerRegisterIf() failed (Status %lx)\n", Status);
55         return 0;
56     }
57 
58     Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
59     if (Status != RPC_S_OK)
60     {
61         ERR("RpcServerListen() failed (Status %lx)\n", Status);
62     }
63 
64     return 0;
65 }
66 
67 
midl_user_allocate(SIZE_T len)68 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
69 {
70     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
71 }
72 
73 
midl_user_free(void __RPC_FAR * ptr)74 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
75 {
76     HeapFree(GetProcessHeap(), 0, ptr);
77 }
78 
79 
80 static
81 NET_API_STATUS
NetpGetClientLogonId(_Out_ PLUID LogonId)82 NetpGetClientLogonId(
83     _Out_ PLUID LogonId)
84 {
85     HANDLE ThreadToken = NULL;
86     TOKEN_STATISTICS Statistics;
87     ULONG Length;
88     NTSTATUS NtStatus;
89     NET_API_STATUS ApiStatus = NERR_Success;
90 
91     ApiStatus = RpcImpersonateClient(NULL);
92     if (ApiStatus != NERR_Success)
93         return ApiStatus;
94 
95     NtStatus = NtOpenThreadToken(NtCurrentThread(),
96                                  TOKEN_QUERY,
97                                  TRUE,
98                                  &ThreadToken);
99     if (!NT_SUCCESS(NtStatus))
100     {
101         ApiStatus = RtlNtStatusToDosError(NtStatus);
102         goto done;
103     }
104 
105     NtStatus = NtQueryInformationToken(ThreadToken,
106                                        TokenStatistics,
107                                        (PVOID)&Statistics,
108                                        sizeof(Statistics),
109                                        &Length);
110     if (!NT_SUCCESS(NtStatus))
111     {
112         ApiStatus = RtlNtStatusToDosError(NtStatus);
113         goto done;
114     }
115 
116     TRACE("Client LUID: %lx\n", Statistics.AuthenticationId.LowPart);
117     RtlCopyLuid(LogonId, &Statistics.AuthenticationId);
118 
119 done:
120     if (ThreadToken != NULL)
121         NtClose(ThreadToken);
122 
123     RpcRevertToSelf();
124 
125     return ApiStatus;
126 }
127 
128 
129 /* Function 0 */
130 unsigned long
131 __stdcall
NetrWkstaGetInfo(WKSSVC_IDENTIFY_HANDLE ServerName,unsigned long Level,LPWKSTA_INFO * WkstaInfo)132 NetrWkstaGetInfo(
133     WKSSVC_IDENTIFY_HANDLE ServerName,
134     unsigned long Level,
135     LPWKSTA_INFO *WkstaInfo)
136 {
137     WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
138     DWORD dwComputerNameLength;
139     LPCWSTR pszLanRoot = L"";
140     PWKSTA_INFO pWkstaInfo = NULL;
141     LSA_OBJECT_ATTRIBUTES ObjectAttributes;
142     LSA_HANDLE PolicyHandle;
143     PPOLICY_PRIMARY_DOMAIN_INFO DomainInfo = NULL;
144     ULONG LoggedOnUsers;
145     NTSTATUS NtStatus;
146     DWORD dwResult = NERR_Success;
147 
148     TRACE("NetrWkstaGetInfo level %lu\n", Level);
149 
150     dwComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
151     GetComputerNameW(szComputerName, &dwComputerNameLength);
152     dwComputerNameLength++; /* include NULL terminator */
153 
154     ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
155     NtStatus = LsaOpenPolicy(NULL,
156                              &ObjectAttributes,
157                              POLICY_VIEW_LOCAL_INFORMATION,
158                              &PolicyHandle);
159     if (NtStatus != STATUS_SUCCESS)
160     {
161         WARN("LsaOpenPolicy() failed (Status 0x%08lx)\n", NtStatus);
162         return LsaNtStatusToWinError(NtStatus);
163     }
164 
165     NtStatus = LsaQueryInformationPolicy(PolicyHandle,
166                                          PolicyPrimaryDomainInformation,
167                                          (PVOID*)&DomainInfo);
168 
169     LsaClose(PolicyHandle);
170 
171     if (NtStatus != STATUS_SUCCESS)
172     {
173         WARN("LsaQueryInformationPolicy() failed (Status 0x%08lx)\n", NtStatus);
174         return LsaNtStatusToWinError(NtStatus);
175     }
176 
177     if (Level == 102)
178     {
179         MSV1_0_ENUMUSERS_REQUEST EnumRequest;
180         PMSV1_0_ENUMUSERS_RESPONSE EnumResponseBuffer = NULL;
181         DWORD EnumResponseBufferSize = 0;
182         NTSTATUS ProtocolStatus;
183 
184         /* enumerate all currently logged-on users */
185         EnumRequest.MessageType = MsV1_0EnumerateUsers;
186         NtStatus = LsaCallAuthenticationPackage(LsaHandle,
187                                                 LsaAuthenticationPackage,
188                                                 &EnumRequest,
189                                                 sizeof(EnumRequest),
190                                                 (PVOID*)&EnumResponseBuffer,
191                                                 &EnumResponseBufferSize,
192                                                 &ProtocolStatus);
193         if (!NT_SUCCESS(NtStatus))
194         {
195             dwResult = RtlNtStatusToDosError(NtStatus);
196             goto done;
197         }
198 
199         LoggedOnUsers = EnumResponseBuffer->NumberOfLoggedOnUsers;
200 
201         LsaFreeReturnBuffer(EnumResponseBuffer);
202     }
203 
204     switch (Level)
205     {
206         case 100:
207             pWkstaInfo = midl_user_allocate(sizeof(WKSTA_INFO_100));
208             if (pWkstaInfo == NULL)
209             {
210                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
211                 break;
212             }
213 
214             pWkstaInfo->WkstaInfo100.wki100_platform_id = PLATFORM_ID_NT;
215 
216             pWkstaInfo->WkstaInfo100.wki100_computername = midl_user_allocate(dwComputerNameLength * sizeof(WCHAR));
217             if (pWkstaInfo->WkstaInfo100.wki100_computername != NULL)
218                 wcscpy(pWkstaInfo->WkstaInfo100.wki100_computername, szComputerName);
219 
220             pWkstaInfo->WkstaInfo100.wki100_langroup = midl_user_allocate((wcslen(DomainInfo->Name.Buffer) + 1) * sizeof(WCHAR));
221             if (pWkstaInfo->WkstaInfo100.wki100_langroup != NULL)
222                 wcscpy(pWkstaInfo->WkstaInfo100.wki100_langroup, DomainInfo->Name.Buffer);
223 
224             pWkstaInfo->WkstaInfo100.wki100_ver_major = VersionInfo.dwMajorVersion;
225             pWkstaInfo->WkstaInfo100.wki100_ver_minor = VersionInfo.dwMinorVersion;
226 
227             *WkstaInfo = pWkstaInfo;
228             break;
229 
230         case 101:
231             pWkstaInfo = midl_user_allocate(sizeof(WKSTA_INFO_101));
232             if (pWkstaInfo == NULL)
233             {
234                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
235                 break;
236             }
237 
238             pWkstaInfo->WkstaInfo101.wki101_platform_id = PLATFORM_ID_NT;
239 
240             pWkstaInfo->WkstaInfo101.wki101_computername = midl_user_allocate(dwComputerNameLength * sizeof(WCHAR));
241             if (pWkstaInfo->WkstaInfo101.wki101_computername != NULL)
242                 wcscpy(pWkstaInfo->WkstaInfo101.wki101_computername, szComputerName);
243 
244             pWkstaInfo->WkstaInfo101.wki101_langroup = midl_user_allocate((wcslen(DomainInfo->Name.Buffer) + 1) * sizeof(WCHAR));
245             if (pWkstaInfo->WkstaInfo101.wki101_langroup != NULL)
246                 wcscpy(pWkstaInfo->WkstaInfo101.wki101_langroup, DomainInfo->Name.Buffer);
247 
248             pWkstaInfo->WkstaInfo101.wki101_ver_major = VersionInfo.dwMajorVersion;
249             pWkstaInfo->WkstaInfo101.wki101_ver_minor = VersionInfo.dwMinorVersion;
250 
251             pWkstaInfo->WkstaInfo101.wki101_lanroot = midl_user_allocate((wcslen(pszLanRoot) + 1) * sizeof(WCHAR));
252             if (pWkstaInfo->WkstaInfo101.wki101_lanroot != NULL)
253                 wcscpy(pWkstaInfo->WkstaInfo101.wki101_lanroot, pszLanRoot);
254 
255             *WkstaInfo = pWkstaInfo;
256             break;
257 
258         case 102:
259             pWkstaInfo = midl_user_allocate(sizeof(WKSTA_INFO_102));
260             if (pWkstaInfo == NULL)
261             {
262                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
263                 break;
264             }
265 
266             pWkstaInfo->WkstaInfo102.wki102_platform_id = PLATFORM_ID_NT;
267 
268             pWkstaInfo->WkstaInfo102.wki102_computername = midl_user_allocate(dwComputerNameLength * sizeof(WCHAR));
269             if (pWkstaInfo->WkstaInfo102.wki102_computername != NULL)
270                 wcscpy(pWkstaInfo->WkstaInfo102.wki102_computername, szComputerName);
271 
272             pWkstaInfo->WkstaInfo102.wki102_langroup = midl_user_allocate((wcslen(DomainInfo->Name.Buffer) + 1) * sizeof(WCHAR));
273             if (pWkstaInfo->WkstaInfo102.wki102_langroup != NULL)
274                 wcscpy(pWkstaInfo->WkstaInfo102.wki102_langroup, DomainInfo->Name.Buffer);
275 
276             pWkstaInfo->WkstaInfo102.wki102_ver_major = VersionInfo.dwMajorVersion;
277             pWkstaInfo->WkstaInfo102.wki102_ver_minor = VersionInfo.dwMinorVersion;
278 
279             pWkstaInfo->WkstaInfo102.wki102_lanroot = midl_user_allocate((wcslen(pszLanRoot) + 1) * sizeof(WCHAR));
280             if (pWkstaInfo->WkstaInfo102.wki102_lanroot != NULL)
281                 wcscpy(pWkstaInfo->WkstaInfo102.wki102_lanroot, pszLanRoot);
282 
283             pWkstaInfo->WkstaInfo102.wki102_logged_on_users = LoggedOnUsers;
284 
285             *WkstaInfo = pWkstaInfo;
286             break;
287 
288         case 502:
289             pWkstaInfo = midl_user_allocate(sizeof(WKSTA_INFO_502));
290             if (pWkstaInfo == NULL)
291             {
292                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
293                 break;
294             }
295 
296             CopyMemory(&pWkstaInfo->WkstaInfo502, &WkstaInfo502, sizeof(WKSTA_INFO_502));
297 
298             *WkstaInfo = pWkstaInfo;
299             break;
300 
301         default:
302             FIXME("Level %lu unimplemented\n", Level);
303             dwResult = ERROR_INVALID_LEVEL;
304             break;
305     }
306 
307 done:
308     if (DomainInfo != NULL)
309         LsaFreeMemory(DomainInfo);
310 
311     return dwResult;
312 }
313 
314 
315 /* Function 1 */
316 unsigned long
317 __stdcall
NetrWkstaSetInfo(WKSSVC_IDENTIFY_HANDLE ServerName,unsigned long Level,LPWKSTA_INFO WkstaInfo,unsigned long * ErrorParameter)318 NetrWkstaSetInfo(
319     WKSSVC_IDENTIFY_HANDLE ServerName,
320     unsigned long Level,
321     LPWKSTA_INFO WkstaInfo,
322     unsigned long *ErrorParameter)
323 {
324     DWORD dwErrParam = 0;
325     DWORD dwResult = NERR_Success;
326 
327     TRACE("NetrWkstaSetInfo(%lu %p %p)\n",
328           Level, WkstaInfo, ErrorParameter);
329 
330     switch (Level)
331     {
332         case 502:
333             if (WkstaInfo->WkstaInfo502.wki502_keep_conn >= 1 && WkstaInfo->WkstaInfo502.wki502_keep_conn <= 65535)
334             {
335                 WkstaInfo502.wki502_keep_conn = WkstaInfo->WkstaInfo502.wki502_keep_conn;
336             }
337             else
338             {
339                 dwErrParam = WKSTA_KEEPCONN_PARMNUM;
340                 dwResult = ERROR_INVALID_PARAMETER;
341             }
342 
343             if (dwResult == NERR_Success)
344             {
345                 if (WkstaInfo->WkstaInfo502.wki502_max_cmds >= 50 && WkstaInfo->WkstaInfo502.wki502_max_cmds <= 65535)
346                 {
347                     WkstaInfo502.wki502_max_cmds = WkstaInfo->WkstaInfo502.wki502_max_cmds;
348                 }
349                 else
350                 {
351                     dwErrParam = WKSTA_MAXCMDS_PARMNUM;
352                     dwResult = ERROR_INVALID_PARAMETER;
353                 }
354             }
355 
356             if (dwResult == NERR_Success)
357             {
358                 if (WkstaInfo->WkstaInfo502.wki502_sess_timeout >= 60 && WkstaInfo->WkstaInfo502.wki502_sess_timeout <= 65535)
359                 {
360                     WkstaInfo502.wki502_sess_timeout = WkstaInfo->WkstaInfo502.wki502_sess_timeout;
361                 }
362                 else
363                 {
364                     dwErrParam = WKSTA_SESSTIMEOUT_PARMNUM;
365                     dwResult = ERROR_INVALID_PARAMETER;
366                 }
367             }
368 
369             if (dwResult == NERR_Success)
370             {
371                 if (WkstaInfo->WkstaInfo502.wki502_dormant_file_limit != 0)
372                 {
373                     WkstaInfo502.wki502_dormant_file_limit = WkstaInfo->WkstaInfo502.wki502_dormant_file_limit;
374                 }
375                 else
376                 {
377                     dwErrParam = WKSTA_DORMANTFILELIMIT_PARMNUM;
378                     dwResult = ERROR_INVALID_PARAMETER;
379                 }
380             }
381             break;
382 
383         case 1013:
384             if (WkstaInfo->WkstaInfo1013.wki1013_keep_conn >= 1 && WkstaInfo->WkstaInfo1013.wki1013_keep_conn <= 65535)
385             {
386                 WkstaInfo502.wki502_keep_conn = WkstaInfo->WkstaInfo1013.wki1013_keep_conn;
387             }
388             else
389             {
390                 dwErrParam = WKSTA_KEEPCONN_PARMNUM;
391                 dwResult = ERROR_INVALID_PARAMETER;
392             }
393             break;
394 
395         case 1018:
396             if (WkstaInfo->WkstaInfo1018.wki1018_sess_timeout >= 60 && WkstaInfo->WkstaInfo1018.wki1018_sess_timeout <= 65535)
397             {
398                 WkstaInfo502.wki502_sess_timeout = WkstaInfo->WkstaInfo1018.wki1018_sess_timeout;
399             }
400             else
401             {
402                 dwErrParam = WKSTA_SESSTIMEOUT_PARMNUM;
403                 dwResult = ERROR_INVALID_PARAMETER;
404             }
405             break;
406 
407         case 1046:
408             if (WkstaInfo->WkstaInfo1046.wki1046_dormant_file_limit != 0)
409             {
410                 WkstaInfo502.wki502_dormant_file_limit = WkstaInfo->WkstaInfo1046.wki1046_dormant_file_limit;
411             }
412             else
413             {
414                 dwErrParam = WKSTA_DORMANTFILELIMIT_PARMNUM;
415                 dwResult = ERROR_INVALID_PARAMETER;
416             }
417             break;
418 
419         default:
420             ERR("Invalid Level %lu\n", Level);
421             dwResult = ERROR_INVALID_LEVEL;
422             break;
423     }
424 
425     /* Save the workstation in the registry */
426     if (dwResult == NERR_Success)
427     {
428         SaveWorkstationInfo(Level);
429 
430         /* FIXME: Notify the redirector */
431     }
432 
433     if ((dwResult == ERROR_INVALID_PARAMETER) && (ErrorParameter != NULL))
434         *ErrorParameter = dwErrParam;
435 
436     return dwResult;
437 }
438 
439 
440 /* Function 2 */
441 unsigned long
442 __stdcall
NetrWkstaUserEnum(WKSSVC_IDENTIFY_HANDLE ServerName,LPWKSTA_USER_ENUM_STRUCT UserInfo,unsigned long PreferredMaximumLength,unsigned long * TotalEntries,unsigned long * ResumeHandle)443 NetrWkstaUserEnum(
444     WKSSVC_IDENTIFY_HANDLE ServerName,
445     LPWKSTA_USER_ENUM_STRUCT UserInfo,
446     unsigned long PreferredMaximumLength,
447     unsigned long *TotalEntries,
448     unsigned long *ResumeHandle)
449 {
450     MSV1_0_ENUMUSERS_REQUEST EnumRequest;
451     PMSV1_0_ENUMUSERS_RESPONSE EnumResponseBuffer = NULL;
452     MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;
453     PMSV1_0_GETUSERINFO_RESPONSE UserInfoResponseBuffer = NULL;
454     PMSV1_0_GETUSERINFO_RESPONSE *UserInfoArray = NULL;
455     DWORD EnumResponseBufferSize = 0;
456     DWORD UserInfoResponseBufferSize = 0;
457     NTSTATUS Status, ProtocolStatus;
458     ULONG i, start, count;
459     PLUID pLogonId;
460     PULONG pEnumHandle;
461     DWORD dwResult = NERR_Success;
462 
463     PWKSTA_USER_INFO_0 pUserInfo0 = NULL;
464     PWKSTA_USER_INFO_1 pUserInfo1 = NULL;
465 
466     TRACE("NetrWkstaUserEnum(%p %p 0x%lx %p %p)\n",
467           ServerName, UserInfo, PreferredMaximumLength, TotalEntries, ResumeHandle);
468 
469     if (UserInfo->Level > 1)
470     {
471         ERR("Invalid Level %lu\n", UserInfo->Level);
472         return ERROR_INVALID_LEVEL;
473     }
474 
475     /* Enumerate all currently logged-on users */
476     EnumRequest.MessageType = MsV1_0EnumerateUsers;
477     Status = LsaCallAuthenticationPackage(LsaHandle,
478                                           LsaAuthenticationPackage,
479                                           &EnumRequest,
480                                           sizeof(EnumRequest),
481                                           (PVOID*)&EnumResponseBuffer,
482                                           &EnumResponseBufferSize,
483                                           &ProtocolStatus);
484 
485     TRACE("LsaCallAuthenticationPackage Status 0x%08lx ResponseBufferSize %lu\n", Status, EnumResponseBufferSize);
486     if (!NT_SUCCESS(Status))
487     {
488         dwResult = RtlNtStatusToDosError(Status);
489         goto done;
490     }
491 
492     TRACE("LoggedOnUsers: %lu\n", EnumResponseBuffer->NumberOfLoggedOnUsers);
493     TRACE("ResponseBuffer: 0x%p\n", EnumResponseBuffer);
494     TRACE("LogonIds: 0x%p\n", EnumResponseBuffer->LogonIds);
495     TRACE("EnumHandles: 0x%p\n", EnumResponseBuffer->EnumHandles);
496     if (EnumResponseBuffer->NumberOfLoggedOnUsers > 0)
497     {
498         pLogonId = EnumResponseBuffer->LogonIds;
499         pEnumHandle = EnumResponseBuffer->EnumHandles;
500         TRACE("pLogonId: 0x%p\n", pLogonId);
501         TRACE("pEnumHandle: 0x%p\n", pEnumHandle);
502 
503         UserInfoArray = RtlAllocateHeap(RtlGetProcessHeap(),
504                                         HEAP_ZERO_MEMORY,
505                                         EnumResponseBuffer->NumberOfLoggedOnUsers * sizeof(PMSV1_0_GETUSERINFO_RESPONSE));
506         if (UserInfoArray == NULL)
507         {
508             dwResult = ERROR_NOT_ENOUGH_MEMORY;
509             goto done;
510         }
511 
512         for (i = 0; i < EnumResponseBuffer->NumberOfLoggedOnUsers; i++)
513         {
514             TRACE("Logon %lu: 0x%08lx  %lu\n", i, pLogonId->LowPart, *pEnumHandle);
515 
516             UserInfoRequest.MessageType = MsV1_0GetUserInfo;
517             UserInfoRequest.LogonId = *pLogonId;
518             Status = LsaCallAuthenticationPackage(LsaHandle,
519                                                   LsaAuthenticationPackage,
520                                                   &UserInfoRequest,
521                                                   sizeof(UserInfoRequest),
522                                                   (PVOID*)&UserInfoResponseBuffer,
523                                                   &UserInfoResponseBufferSize,
524                                                   &ProtocolStatus);
525             TRACE("LsaCallAuthenticationPackage:MsV1_0GetUserInfo Status 0x%08lx ResponseBufferSize %lu\n", Status, UserInfoResponseBufferSize);
526             if (!NT_SUCCESS(Status))
527             {
528                 dwResult = RtlNtStatusToDosError(Status);
529                 goto done;
530             }
531 
532             UserInfoArray[i] = UserInfoResponseBuffer;
533 
534             TRACE("UserName: %wZ\n", &UserInfoArray[i]->UserName);
535             TRACE("LogonDomain: %wZ\n", &UserInfoArray[i]->LogonDomainName);
536             TRACE("LogonServer: %wZ\n", &UserInfoArray[i]->LogonServer);
537 
538             pLogonId++;
539             pEnumHandle++;
540         }
541 
542         if (PreferredMaximumLength == MAX_PREFERRED_LENGTH)
543         {
544             start = 0;
545             count = EnumResponseBuffer->NumberOfLoggedOnUsers;
546         }
547         else
548         {
549             FIXME("Calculate the start index and the number of matching array entries!");
550             dwResult = ERROR_CALL_NOT_IMPLEMENTED;
551             goto done;
552         }
553 
554         switch (UserInfo->Level)
555         {
556             case 0:
557                 pUserInfo0 = midl_user_allocate(count * sizeof(WKSTA_USER_INFO_0));
558                 if (pUserInfo0 == NULL)
559                 {
560                     ERR("\n");
561                     dwResult = ERROR_NOT_ENOUGH_MEMORY;
562                     break;
563                 }
564 
565                 ZeroMemory(pUserInfo0, count * sizeof(WKSTA_USER_INFO_0));
566 
567                 for (i = 0; i < 0 + count; i++)
568                 {
569                     pUserInfo0[i].wkui0_username = midl_user_allocate(UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
570                     if (pUserInfo0[i].wkui0_username == NULL)
571                     {
572                         ERR("\n");
573                         dwResult = ERROR_NOT_ENOUGH_MEMORY;
574                         break;
575                     }
576 
577                     ZeroMemory(pUserInfo0[i].wkui0_username, UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
578                     CopyMemory(pUserInfo0[i].wkui0_username, UserInfoArray[start + i]->UserName.Buffer, UserInfoArray[start + i]->UserName.Length);
579                 }
580 
581                 UserInfo->WkstaUserInfo.Level0.EntriesRead = count;
582                 UserInfo->WkstaUserInfo.Level0.Buffer = pUserInfo0;
583                 *TotalEntries = EnumResponseBuffer->NumberOfLoggedOnUsers;
584                 *ResumeHandle = 0;
585                 break;
586 
587             case 1:
588                 pUserInfo1 = midl_user_allocate(count * sizeof(WKSTA_USER_INFO_1));
589                 if (pUserInfo1 == NULL)
590                 {
591                     ERR("\n");
592                     dwResult = ERROR_NOT_ENOUGH_MEMORY;
593                     break;
594                 }
595 
596                 ZeroMemory(pUserInfo1, count * sizeof(WKSTA_USER_INFO_1));
597 
598                 for (i = 0; i < 0 + count; i++)
599                 {
600                     pUserInfo1[i].wkui1_username = midl_user_allocate(UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
601                     if (pUserInfo1[i].wkui1_username == NULL)
602                     {
603                         ERR("\n");
604                         dwResult = ERROR_NOT_ENOUGH_MEMORY;
605                         break;
606                     }
607 
608                     ZeroMemory(pUserInfo1[i].wkui1_username, UserInfoArray[start + i]->UserName.Length + sizeof(WCHAR));
609                     CopyMemory(pUserInfo1[i].wkui1_username, UserInfoArray[start + i]->UserName.Buffer, UserInfoArray[start + i]->UserName.Length);
610 
611                     pUserInfo1[i].wkui1_logon_domain = midl_user_allocate(UserInfoArray[start + i]->LogonDomainName.Length + sizeof(WCHAR));
612                     if (pUserInfo1[i].wkui1_logon_domain == NULL)
613                     {
614                         ERR("\n");
615                         dwResult = ERROR_NOT_ENOUGH_MEMORY;
616                         break;
617                     }
618 
619                     ZeroMemory(pUserInfo1[i].wkui1_logon_domain, UserInfoArray[start + i]->LogonDomainName.Length + sizeof(WCHAR));
620                     CopyMemory(pUserInfo1[i].wkui1_logon_domain, UserInfoArray[start + i]->LogonDomainName.Buffer, UserInfoArray[start + i]->LogonDomainName.Length);
621 
622                     // FIXME: wkui1_oth_domains
623 
624                     pUserInfo1[i].wkui1_logon_server = midl_user_allocate(UserInfoArray[start + i]->LogonServer.Length + sizeof(WCHAR));
625                     if (pUserInfo1[i].wkui1_logon_server == NULL)
626                     {
627                         ERR("\n");
628                         dwResult = ERROR_NOT_ENOUGH_MEMORY;
629                         break;
630                     }
631 
632                     ZeroMemory(pUserInfo1[i].wkui1_logon_server, UserInfoArray[start + i]->LogonServer.Length + sizeof(WCHAR));
633                     CopyMemory(pUserInfo1[i].wkui1_logon_server, UserInfoArray[start + i]->LogonServer.Buffer, UserInfoArray[start + i]->LogonServer.Length);
634                 }
635 
636                 UserInfo->WkstaUserInfo.Level1.EntriesRead = count;
637                 UserInfo->WkstaUserInfo.Level1.Buffer = pUserInfo1;
638                 *TotalEntries = EnumResponseBuffer->NumberOfLoggedOnUsers;
639                 *ResumeHandle = 0;
640                 break;
641 
642                 break;
643         }
644     }
645     else
646     {
647         if (UserInfo->Level == 0)
648         {
649             UserInfo->WkstaUserInfo.Level0.Buffer = NULL;
650             UserInfo->WkstaUserInfo.Level0.EntriesRead = 0;
651         }
652         else
653         {
654             UserInfo->WkstaUserInfo.Level1.Buffer = NULL;
655             UserInfo->WkstaUserInfo.Level1.EntriesRead = 0;
656         }
657 
658         *TotalEntries = 0;
659         dwResult = NERR_Success;
660     }
661 
662 done:
663     if (UserInfoArray !=NULL)
664     {
665 
666         for (i = 0; i < EnumResponseBuffer->NumberOfLoggedOnUsers; i++)
667         {
668             if (UserInfoArray[i]->UserName.Buffer != NULL)
669                 LsaFreeReturnBuffer(UserInfoArray[i]->UserName.Buffer);
670 
671             if (UserInfoArray[i]->LogonDomainName.Buffer != NULL)
672                 LsaFreeReturnBuffer(UserInfoArray[i]->LogonDomainName.Buffer);
673 
674             if (UserInfoArray[i]->LogonServer.Buffer != NULL)
675                 LsaFreeReturnBuffer(UserInfoArray[i]->LogonServer.Buffer);
676 
677             LsaFreeReturnBuffer(UserInfoArray[i]);
678         }
679 
680         RtlFreeHeap(RtlGetProcessHeap(), 0, UserInfoArray);
681     }
682 
683     if (EnumResponseBuffer != NULL)
684         LsaFreeReturnBuffer(EnumResponseBuffer);
685 
686     return dwResult;
687 }
688 
689 
690 /* Function 3 */
691 unsigned long
692 __stdcall
NetrWkstaUserGetInfo(WKSSVC_IDENTIFY_HANDLE Unused,unsigned long Level,LPWKSTA_USER_INFO * UserInfo)693 NetrWkstaUserGetInfo(
694     WKSSVC_IDENTIFY_HANDLE Unused,
695     unsigned long Level,
696     LPWKSTA_USER_INFO *UserInfo)
697 {
698     MSV1_0_GETUSERINFO_REQUEST UserInfoRequest;
699     PMSV1_0_GETUSERINFO_RESPONSE UserInfoResponseBuffer = NULL;
700     DWORD UserInfoResponseBufferSize = 0;
701     NTSTATUS Status, ProtocolStatus;
702     LUID LogonId;
703     PWKSTA_USER_INFO pUserInfo;
704     DWORD dwResult = NERR_Success;
705 
706     TRACE("NetrWkstaUserGetInfo(%s, %d, %p)\n", debugstr_w(Unused), Level, UserInfo);
707 
708     if (Unused != NULL)
709         return ERROR_INVALID_PARAMETER;
710 
711     if (Level > 1 && Level != 1101)
712         return ERROR_INVALID_LEVEL;
713 
714     if (Level != 1101)
715     {
716         dwResult = NetpGetClientLogonId(&LogonId);
717         if (dwResult != NERR_Success)
718         {
719             ERR("NetpGetClientLogonId() failed (%u)\n", dwResult);
720             return dwResult;
721         }
722 
723         TRACE("LogonId: 0x%08lx\n", LogonId.LowPart);
724 
725         UserInfoRequest.MessageType = MsV1_0GetUserInfo;
726         UserInfoRequest.LogonId = LogonId;
727         Status = LsaCallAuthenticationPackage(LsaHandle,
728                                               LsaAuthenticationPackage,
729                                               &UserInfoRequest,
730                                               sizeof(UserInfoRequest),
731                                               (PVOID*)&UserInfoResponseBuffer,
732                                               &UserInfoResponseBufferSize,
733                                               &ProtocolStatus);
734         TRACE("LsaCallAuthenticationPackage:MsV1_0GetUserInfo Status 0x%08lx ResponseBufferSize %lu\n", Status, UserInfoResponseBufferSize);
735         if (!NT_SUCCESS(Status))
736         {
737             ERR("\n");
738             return RtlNtStatusToDosError(Status);
739         }
740 
741         TRACE("UserName: %wZ\n", &UserInfoResponseBuffer->UserName);
742         TRACE("LogonDomain: %wZ\n", &UserInfoResponseBuffer->LogonDomainName);
743         TRACE("LogonServer: %wZ\n", &UserInfoResponseBuffer->LogonServer);
744     }
745 
746     switch (Level)
747     {
748         case 0:
749             pUserInfo = midl_user_allocate(sizeof(WKSTA_USER_INFO_0));
750             if (pUserInfo == NULL)
751             {
752                 ERR("\n");
753                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
754                 break;
755             }
756 
757             ZeroMemory(pUserInfo, sizeof(WKSTA_USER_INFO_0));
758 
759             /* User Name */
760             pUserInfo->UserInfo0.wkui0_username =
761                 midl_user_allocate(UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
762             if (pUserInfo->UserInfo0.wkui0_username == NULL)
763             {
764                 ERR("\n");
765                 midl_user_free(pUserInfo);
766                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
767                 break;
768             }
769 
770             ZeroMemory(pUserInfo->UserInfo0.wkui0_username,
771                        UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
772             CopyMemory(pUserInfo->UserInfo0.wkui0_username,
773                        UserInfoResponseBuffer->UserName.Buffer,
774                        UserInfoResponseBuffer->UserName.Length);
775 
776             *UserInfo = pUserInfo;
777             break;
778 
779         case 1:
780             pUserInfo = midl_user_allocate(sizeof(WKSTA_USER_INFO_1));
781             if (pUserInfo == NULL)
782             {
783                 ERR("\n");
784                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
785                 break;
786             }
787 
788             ZeroMemory(pUserInfo, sizeof(WKSTA_USER_INFO_1));
789 
790             /* User Name */
791             pUserInfo->UserInfo1.wkui1_username =
792                 midl_user_allocate(UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
793             if (pUserInfo->UserInfo1.wkui1_username == NULL)
794             {
795                 ERR("\n");
796                 midl_user_free(pUserInfo);
797                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
798                 break;
799             }
800 
801             ZeroMemory(pUserInfo->UserInfo1.wkui1_username,
802                        UserInfoResponseBuffer->UserName.Length + sizeof(WCHAR));
803             CopyMemory(pUserInfo->UserInfo1.wkui1_username,
804                        UserInfoResponseBuffer->UserName.Buffer,
805                        UserInfoResponseBuffer->UserName.Length);
806 
807             /* Logon Domain Name */
808             pUserInfo->UserInfo1.wkui1_logon_domain =
809                 midl_user_allocate(UserInfoResponseBuffer->LogonDomainName.Length + sizeof(WCHAR));
810             if (pUserInfo->UserInfo1.wkui1_logon_domain == NULL)
811             {
812                 ERR("\n");
813                 midl_user_free(pUserInfo->UserInfo1.wkui1_username);
814                 midl_user_free(pUserInfo);
815                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
816                 break;
817             }
818 
819             ZeroMemory(pUserInfo->UserInfo1.wkui1_logon_domain,
820                        UserInfoResponseBuffer->LogonDomainName.Length + sizeof(WCHAR));
821             CopyMemory(pUserInfo->UserInfo1.wkui1_logon_domain,
822                        UserInfoResponseBuffer->LogonDomainName.Buffer,
823                        UserInfoResponseBuffer->LogonDomainName.Length);
824 
825             /* FIXME: wkui1_oth_domains */
826 
827             /* Logon Server */
828             pUserInfo->UserInfo1.wkui1_logon_server =
829                 midl_user_allocate(UserInfoResponseBuffer->LogonServer.Length + sizeof(WCHAR));
830             if (pUserInfo->UserInfo1.wkui1_logon_server == NULL)
831             {
832                 ERR("\n");
833                 midl_user_free(pUserInfo->UserInfo1.wkui1_username);
834                 midl_user_free(pUserInfo->UserInfo1.wkui1_logon_domain);
835                 midl_user_free(pUserInfo);
836                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
837                 break;
838             }
839 
840             ZeroMemory(pUserInfo->UserInfo1.wkui1_logon_server,
841                        UserInfoResponseBuffer->LogonServer.Length + sizeof(WCHAR));
842             CopyMemory(pUserInfo->UserInfo1.wkui1_logon_server,
843                        UserInfoResponseBuffer->LogonServer.Buffer,
844                        UserInfoResponseBuffer->LogonServer.Length);
845 
846             *UserInfo = pUserInfo;
847             break;
848 
849         case 1101:
850             pUserInfo = midl_user_allocate(sizeof(WKSTA_USER_INFO_1101));
851             if (pUserInfo == NULL)
852             {
853                 ERR("Failed to allocate WKSTA_USER_INFO_1101\n");
854                 dwResult = ERROR_NOT_ENOUGH_MEMORY;
855                 break;
856             }
857 
858             ZeroMemory(pUserInfo, sizeof(WKSTA_USER_INFO_1101));
859 
860             /* FIXME: wkui1101_oth_domains */
861 
862             *UserInfo = pUserInfo;
863             break;
864 
865         default:
866             ERR("\n");
867             dwResult = ERROR_INVALID_LEVEL;
868             break;
869     }
870 
871     if (UserInfoResponseBuffer)
872         LsaFreeReturnBuffer(UserInfoResponseBuffer);
873 
874     return dwResult;
875 }
876 
877 
878 /* Function 4 */
879 unsigned long
880 __stdcall
NetrWkstaUserSetInfo(WKSSVC_IDENTIFY_HANDLE Unused,unsigned long Level,LPWKSTA_USER_INFO UserInfo,unsigned long * ErrorParameter)881 NetrWkstaUserSetInfo (
882     WKSSVC_IDENTIFY_HANDLE Unused,
883     unsigned long Level,
884     LPWKSTA_USER_INFO UserInfo,
885     unsigned long *ErrorParameter)
886 {
887     UNIMPLEMENTED;
888     return 0;
889 }
890 
891 
892 /* Function 5 */
893 unsigned long
894 __stdcall
NetrWkstaTransportEnum(WKSSVC_IDENTIFY_HANDLE ServerName,LPWKSTA_TRANSPORT_ENUM_STRUCT TransportInfo,unsigned long PreferredMaximumLength,unsigned long * TotalEntries,unsigned long * ResumeHandle)895 NetrWkstaTransportEnum(
896     WKSSVC_IDENTIFY_HANDLE ServerName,
897     LPWKSTA_TRANSPORT_ENUM_STRUCT TransportInfo,
898     unsigned long PreferredMaximumLength,
899     unsigned long* TotalEntries,
900     unsigned long *ResumeHandle)
901 {
902     UNIMPLEMENTED;
903     return 0;
904 }
905 
906 
907 /* Function 6 */
908 unsigned long
909 __stdcall
NetrWkstaTransportAdd(WKSSVC_IDENTIFY_HANDLE ServerName,unsigned long Level,LPWKSTA_TRANSPORT_INFO_0 TransportInfo,unsigned long * ErrorParameter)910 NetrWkstaTransportAdd(
911     WKSSVC_IDENTIFY_HANDLE ServerName,
912     unsigned long Level,
913     LPWKSTA_TRANSPORT_INFO_0 TransportInfo,
914     unsigned long *ErrorParameter)
915 {
916     UNIMPLEMENTED;
917     return 0;
918 }
919 
920 
921 /* Function 7 */
922 unsigned long
923 __stdcall
NetrWkstaTransportDel(WKSSVC_IDENTIFY_HANDLE ServerName,wchar_t * TransportName,unsigned long ForceLevel)924 NetrWkstaTransportDel(
925     WKSSVC_IDENTIFY_HANDLE ServerName,
926     wchar_t *TransportName,
927     unsigned long ForceLevel)
928 {
929     UNIMPLEMENTED;
930     return 0;
931 }
932 
933 
934 /* Function 8 */
935 unsigned long
936 __stdcall
NetrUseAdd(WKSSVC_IMPERSONATE_HANDLE ServerName,unsigned long Level,LPUSE_INFO InfoStruct,unsigned long * ErrorParameter)937 NetrUseAdd(
938     WKSSVC_IMPERSONATE_HANDLE ServerName,
939     unsigned long Level,
940     LPUSE_INFO InfoStruct,
941     unsigned long *ErrorParameter)
942 {
943     UNIMPLEMENTED;
944     return 0;
945 }
946 
947 
948 /* Function 9 */
949 unsigned long
950 __stdcall
NetrUseGetInfo(WKSSVC_IMPERSONATE_HANDLE ServerName,wchar_t * UseName,unsigned long Level,LPUSE_INFO InfoStruct)951 NetrUseGetInfo(
952     WKSSVC_IMPERSONATE_HANDLE ServerName,
953     wchar_t *UseName,
954     unsigned long Level,
955     LPUSE_INFO InfoStruct)
956 {
957     UNIMPLEMENTED;
958     return 0;
959 }
960 
961 
962 /* Function 10 */
963 unsigned long
964 __stdcall
NetrUseDel(WKSSVC_IMPERSONATE_HANDLE ServerName,wchar_t * UseName,unsigned long ForceLevel)965 NetrUseDel(
966     WKSSVC_IMPERSONATE_HANDLE ServerName,
967     wchar_t *UseName,
968     unsigned long ForceLevel)
969 {
970     UNIMPLEMENTED;
971     return 0;
972 }
973 
974 
975 /* Function 11 */
976 unsigned long
977 __stdcall
NetrUseEnum(WKSSVC_IDENTIFY_HANDLE ServerName,LPUSE_ENUM_STRUCT InfoStruct,unsigned long PreferredMaximumLength,unsigned long * TotalEntries,unsigned long * ResumeHandle)978 NetrUseEnum(
979     WKSSVC_IDENTIFY_HANDLE ServerName,
980     LPUSE_ENUM_STRUCT InfoStruct,
981     unsigned long PreferredMaximumLength,
982     unsigned long *TotalEntries,
983     unsigned long *ResumeHandle)
984 {
985     UNIMPLEMENTED;
986     return 0;
987 }
988 
989 
990 /* Function 12 - Not used on wire */
991 unsigned long
992 __stdcall
NetrMessageBufferSend(void)993 NetrMessageBufferSend(void)
994 {
995     TRACE("NetrMessageBufferSend()\n");
996     return ERROR_NOT_SUPPORTED;
997 }
998 
999 
1000 /* Function 13 */
1001 unsigned long
1002 __stdcall
NetrWorkstationStatisticsGet(WKSSVC_IDENTIFY_HANDLE ServerName,wchar_t * ServiceName,unsigned long Level,unsigned long Options,LPSTAT_WORKSTATION_0 * Buffer)1003 NetrWorkstationStatisticsGet(
1004     WKSSVC_IDENTIFY_HANDLE ServerName,
1005     wchar_t *ServiceName,
1006     unsigned long Level,
1007     unsigned long Options,
1008     LPSTAT_WORKSTATION_0 *Buffer)
1009 {
1010     PSTAT_WORKSTATION_0 pStatBuffer;
1011 
1012     TRACE("NetrWorkstationStatisticsGet(%p %p %lu 0x%lx %p)\n",
1013           ServerName, ServiceName, Level, Options, Buffer);
1014 
1015     if (Level != 0)
1016         return ERROR_INVALID_LEVEL;
1017 
1018     if (Options != 0)
1019         return ERROR_INVALID_PARAMETER;
1020 
1021     pStatBuffer = midl_user_allocate(sizeof(STAT_WORKSTATION_0));
1022     if (pStatBuffer == NULL)
1023         return ERROR_NOT_ENOUGH_MEMORY;
1024 
1025     ZeroMemory(pStatBuffer, sizeof(STAT_WORKSTATION_0));
1026 
1027     // FIXME: Return the actual statistcs data!
1028 
1029     *Buffer = pStatBuffer;
1030 
1031     return NERR_Success;
1032 }
1033 
1034 
1035 /* Function 14 - Not used on wire */
1036 unsigned long
1037 __stdcall
NetrLogonDomainNameAdd(WKSSVC_IDENTIFY_HANDLE DomainName)1038 NetrLogonDomainNameAdd(
1039     WKSSVC_IDENTIFY_HANDLE DomainName)
1040 {
1041     TRACE("NetrLogonDomainNameAdd(%s)\n",
1042           debugstr_w(DomainName));
1043     return ERROR_NOT_SUPPORTED;
1044 }
1045 
1046 
1047 /* Function 15 - Not used on wire */
1048 unsigned long
1049 __stdcall
NetrLogonDomainNameDel(WKSSVC_IDENTIFY_HANDLE DomainName)1050 NetrLogonDomainNameDel(
1051     WKSSVC_IDENTIFY_HANDLE DomainName)
1052 {
1053     TRACE("NetrLogonDomainNameDel(%s)\n",
1054           debugstr_w(DomainName));
1055     return ERROR_NOT_SUPPORTED;
1056 }
1057 
1058 
1059 /* Function 16 - Not used on wire */
1060 unsigned long
1061 __stdcall
NetrJoinDomain(void)1062 NetrJoinDomain(void)
1063 {
1064     TRACE("NetrJoinDomain()\n");
1065     return ERROR_NOT_SUPPORTED;
1066 }
1067 
1068 
1069 /* Function 17 - Not used on wire */
1070 unsigned long
1071 __stdcall
NetrUnjoinDomain(void)1072 NetrUnjoinDomain(void)
1073 {
1074     TRACE("NetrUnjoinDomain()\n");
1075     return ERROR_NOT_SUPPORTED;
1076 }
1077 
1078 
1079 /* Function 18 - Not used on wire */
1080 unsigned long
1081 __stdcall
NetrValidateName(void)1082 NetrValidateName(void)
1083 {
1084     TRACE("NetrValidateName()\n");
1085     return ERROR_NOT_SUPPORTED;
1086 }
1087 
1088 
1089 /* Function 19 - Not used on wire */
1090 unsigned long
1091 __stdcall
NetrRenameMachineInDomain(void)1092 NetrRenameMachineInDomain(void)
1093 {
1094     TRACE("NetrRenameMachineInDomain()\n");
1095     return ERROR_NOT_SUPPORTED;
1096 }
1097 
1098 
1099 /* Function 20 */
1100 unsigned long
1101 __stdcall
NetrGetJoinInformation(WKSSVC_IMPERSONATE_HANDLE ServerName,wchar_t ** NameBuffer,PNETSETUP_JOIN_STATUS BufferType)1102 NetrGetJoinInformation(
1103     WKSSVC_IMPERSONATE_HANDLE ServerName,
1104     wchar_t **NameBuffer,
1105     PNETSETUP_JOIN_STATUS BufferType)
1106 {
1107     TRACE("NetrGetJoinInformation(%p %p %p)\n",
1108           ServerName, NameBuffer, BufferType);
1109 
1110     if (NameBuffer == NULL)
1111         return ERROR_INVALID_PARAMETER;
1112 
1113     return NetpGetJoinInformation(NameBuffer,
1114                                   BufferType);
1115 }
1116 
1117 
1118 /* Function 21 - Not used on wire */
1119 unsigned long
1120 __stdcall
NetrGetJoinableOUs(void)1121 NetrGetJoinableOUs(void)
1122 {
1123     TRACE("NetrGetJoinableOUs()\n");
1124     return ERROR_NOT_SUPPORTED;
1125 }
1126 
1127 
1128 /* Function 22 */
1129 unsigned long
1130 __stdcall
NetrJoinDomain2(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * DomainNameParam,wchar_t * MachineAccountOU,wchar_t * AccountName,PJOINPR_ENCRYPTED_USER_PASSWORD Password,unsigned long Options)1131 NetrJoinDomain2(
1132     handle_t RpcBindingHandle,
1133     wchar_t *ServerName,
1134     wchar_t *DomainNameParam,
1135     wchar_t *MachineAccountOU,
1136     wchar_t *AccountName,
1137     PJOINPR_ENCRYPTED_USER_PASSWORD Password,
1138     unsigned long Options)
1139 {
1140     NET_API_STATUS status;
1141 
1142     FIXME("NetrJoinDomain2(%p %S %S %S %S %p 0x%lx)\n",
1143           RpcBindingHandle, ServerName, DomainNameParam, MachineAccountOU,
1144           AccountName, Password, Options);
1145 
1146     if (DomainNameParam == NULL)
1147         return ERROR_INVALID_PARAMETER;
1148 
1149     if (Options & NETSETUP_JOIN_DOMAIN)
1150     {
1151         FIXME("NetrJoinDomain2: NETSETUP_JOIN_DOMAIN is not supported yet!\n");
1152         status = ERROR_CALL_NOT_IMPLEMENTED;
1153     }
1154     else
1155     {
1156         status = NetpJoinWorkgroup(DomainNameParam);
1157     }
1158 
1159     return status;
1160 }
1161 
1162 
1163 /* Function 23 */
1164 unsigned long
1165 __stdcall
NetrUnjoinDomain2(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * AccountName,PJOINPR_ENCRYPTED_USER_PASSWORD Password,unsigned long Options)1166 NetrUnjoinDomain2(
1167     handle_t RpcBindingHandle,
1168     wchar_t *ServerName,
1169     wchar_t *AccountName,
1170     PJOINPR_ENCRYPTED_USER_PASSWORD Password,
1171     unsigned long Options)
1172 {
1173     UNIMPLEMENTED;
1174     return 0;
1175 }
1176 
1177 
1178 /* Function 24 */
1179 unsigned long
1180 __stdcall
NetrRenameMachineInDomain2(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * MachineName,wchar_t * AccountName,PJOINPR_ENCRYPTED_USER_PASSWORD Password,unsigned long Options)1181 NetrRenameMachineInDomain2(
1182     handle_t RpcBindingHandle,
1183     wchar_t *ServerName,
1184     wchar_t *MachineName,
1185     wchar_t *AccountName,
1186     PJOINPR_ENCRYPTED_USER_PASSWORD Password,
1187     unsigned long Options)
1188 {
1189     UNIMPLEMENTED;
1190     return 0;
1191 }
1192 
1193 
1194 /* Function 25 */
1195 unsigned long
1196 __stdcall
NetrValidateName2(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * NameToValidate,wchar_t * AccountName,PJOINPR_ENCRYPTED_USER_PASSWORD Password,NETSETUP_NAME_TYPE NameType)1197 NetrValidateName2(
1198     handle_t RpcBindingHandle,
1199     wchar_t *ServerName,
1200     wchar_t *NameToValidate,
1201     wchar_t *AccountName,
1202     PJOINPR_ENCRYPTED_USER_PASSWORD Password,
1203     NETSETUP_NAME_TYPE NameType)
1204 {
1205     UNIMPLEMENTED;
1206     return 0;
1207 }
1208 
1209 
1210 /* Function 26 */
1211 unsigned long
1212 __stdcall
NetrGetJoinableOUs2(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * DomainNameParam,wchar_t * AccountName,PJOINPR_ENCRYPTED_USER_PASSWORD Password,unsigned long * OUCount,wchar_t *** OUs)1213 NetrGetJoinableOUs2(
1214     handle_t RpcBindingHandle,
1215     wchar_t *ServerName,
1216     wchar_t *DomainNameParam,
1217     wchar_t *AccountName,
1218     PJOINPR_ENCRYPTED_USER_PASSWORD Password,
1219     unsigned long* OUCount,
1220     wchar_t ***OUs)
1221 {
1222     UNIMPLEMENTED;
1223     return 0;
1224 }
1225 
1226 
1227 /* Function 27 */
1228 unsigned long
1229 __stdcall
NetrAddAlternateComputerName(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * AlternateName,wchar_t * DomainAccount,PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,unsigned long Reserved)1230 NetrAddAlternateComputerName(
1231     handle_t RpcBindingHandle,
1232     wchar_t *ServerName,
1233     wchar_t *AlternateName,
1234     wchar_t *DomainAccount,
1235     PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
1236     unsigned long Reserved)
1237 {
1238     UNIMPLEMENTED;
1239     return 0;
1240 }
1241 
1242 
1243 /* Function 28 */
1244 unsigned long
1245 __stdcall
NetrRemoveAlternateComputerName(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * AlternateName,wchar_t * DomainAccount,PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,unsigned long Reserved)1246 NetrRemoveAlternateComputerName(
1247     handle_t RpcBindingHandle,
1248     wchar_t *ServerName,
1249     wchar_t *AlternateName,
1250     wchar_t *DomainAccount,
1251     PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
1252     unsigned long Reserved)
1253 {
1254     UNIMPLEMENTED;
1255     return 0;
1256 }
1257 
1258 
1259 /* Function 29 */
1260 unsigned long
1261 __stdcall
NetrSetPrimaryComputerName(handle_t RpcBindingHandle,wchar_t * ServerName,wchar_t * PrimaryName,wchar_t * DomainAccount,PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,unsigned long Reserved)1262 NetrSetPrimaryComputerName(
1263     handle_t RpcBindingHandle,
1264     wchar_t *ServerName,
1265     wchar_t *PrimaryName,
1266     wchar_t *DomainAccount,
1267     PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword,
1268     unsigned long Reserved)
1269 {
1270     UNIMPLEMENTED;
1271     return 0;
1272 }
1273 
1274 
1275 /* Function 30 */
1276 unsigned long
1277 __stdcall
NetrEnumerateComputerNames(WKSSVC_IMPERSONATE_HANDLE ServerName,NET_COMPUTER_NAME_TYPE NameType,unsigned long Reserved,PNET_COMPUTER_NAME_ARRAY * ComputerNames)1278 NetrEnumerateComputerNames(
1279     WKSSVC_IMPERSONATE_HANDLE ServerName,
1280     NET_COMPUTER_NAME_TYPE NameType,
1281     unsigned long Reserved,
1282     PNET_COMPUTER_NAME_ARRAY *ComputerNames)
1283 {
1284     UNIMPLEMENTED;
1285     return 0;
1286 }
1287 
1288 /* EOF */
1289