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 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 68 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 69 { 70 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 71 } 72 73 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 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 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 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 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 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 /* FIXME: wkui1101_oth_domains */ 851 break; 852 853 default: 854 ERR("\n"); 855 dwResult = ERROR_INVALID_LEVEL; 856 break; 857 } 858 859 if (UserInfoResponseBuffer) 860 LsaFreeReturnBuffer(UserInfoResponseBuffer); 861 862 return dwResult; 863 } 864 865 866 /* Function 4 */ 867 unsigned long 868 __stdcall 869 NetrWkstaUserSetInfo ( 870 WKSSVC_IDENTIFY_HANDLE Unused, 871 unsigned long Level, 872 LPWKSTA_USER_INFO UserInfo, 873 unsigned long *ErrorParameter) 874 { 875 UNIMPLEMENTED; 876 return 0; 877 } 878 879 880 /* Function 5 */ 881 unsigned long 882 __stdcall 883 NetrWkstaTransportEnum( 884 WKSSVC_IDENTIFY_HANDLE ServerName, 885 LPWKSTA_TRANSPORT_ENUM_STRUCT TransportInfo, 886 unsigned long PreferredMaximumLength, 887 unsigned long* TotalEntries, 888 unsigned long *ResumeHandle) 889 { 890 UNIMPLEMENTED; 891 return 0; 892 } 893 894 895 /* Function 6 */ 896 unsigned long 897 __stdcall 898 NetrWkstaTransportAdd( 899 WKSSVC_IDENTIFY_HANDLE ServerName, 900 unsigned long Level, 901 LPWKSTA_TRANSPORT_INFO_0 TransportInfo, 902 unsigned long *ErrorParameter) 903 { 904 UNIMPLEMENTED; 905 return 0; 906 } 907 908 909 /* Function 7 */ 910 unsigned long 911 __stdcall 912 NetrWkstaTransportDel( 913 WKSSVC_IDENTIFY_HANDLE ServerName, 914 wchar_t *TransportName, 915 unsigned long ForceLevel) 916 { 917 UNIMPLEMENTED; 918 return 0; 919 } 920 921 922 /* Function 8 */ 923 unsigned long 924 __stdcall 925 NetrUseAdd( 926 WKSSVC_IMPERSONATE_HANDLE ServerName, 927 unsigned long Level, 928 LPUSE_INFO InfoStruct, 929 unsigned long *ErrorParameter) 930 { 931 UNIMPLEMENTED; 932 return 0; 933 } 934 935 936 /* Function 9 */ 937 unsigned long 938 __stdcall 939 NetrUseGetInfo( 940 WKSSVC_IMPERSONATE_HANDLE ServerName, 941 wchar_t *UseName, 942 unsigned long Level, 943 LPUSE_INFO InfoStruct) 944 { 945 UNIMPLEMENTED; 946 return 0; 947 } 948 949 950 /* Function 10 */ 951 unsigned long 952 __stdcall 953 NetrUseDel( 954 WKSSVC_IMPERSONATE_HANDLE ServerName, 955 wchar_t *UseName, 956 unsigned long ForceLevel) 957 { 958 UNIMPLEMENTED; 959 return 0; 960 } 961 962 963 /* Function 11 */ 964 unsigned long 965 __stdcall 966 NetrUseEnum( 967 WKSSVC_IDENTIFY_HANDLE ServerName, 968 LPUSE_ENUM_STRUCT InfoStruct, 969 unsigned long PreferredMaximumLength, 970 unsigned long *TotalEntries, 971 unsigned long *ResumeHandle) 972 { 973 UNIMPLEMENTED; 974 return 0; 975 } 976 977 978 /* Function 12 - Not used on wire */ 979 unsigned long 980 __stdcall 981 NetrMessageBufferSend(void) 982 { 983 TRACE("NetrMessageBufferSend()\n"); 984 return ERROR_NOT_SUPPORTED; 985 } 986 987 988 /* Function 13 */ 989 unsigned long 990 __stdcall 991 NetrWorkstationStatisticsGet( 992 WKSSVC_IDENTIFY_HANDLE ServerName, 993 wchar_t *ServiceName, 994 unsigned long Level, 995 unsigned long Options, 996 LPSTAT_WORKSTATION_0 *Buffer) 997 { 998 PSTAT_WORKSTATION_0 pStatBuffer; 999 1000 TRACE("NetrWorkstationStatisticsGet(%p %p %lu 0x%lx %p)\n", 1001 ServerName, ServiceName, Level, Options, Buffer); 1002 1003 if (Level != 0) 1004 return ERROR_INVALID_LEVEL; 1005 1006 if (Options != 0) 1007 return ERROR_INVALID_PARAMETER; 1008 1009 pStatBuffer = midl_user_allocate(sizeof(STAT_WORKSTATION_0)); 1010 if (pStatBuffer == NULL) 1011 return ERROR_NOT_ENOUGH_MEMORY; 1012 1013 ZeroMemory(pStatBuffer, sizeof(STAT_WORKSTATION_0)); 1014 1015 // FIXME: Return the actual statistcs data! 1016 1017 *Buffer = pStatBuffer; 1018 1019 return NERR_Success; 1020 } 1021 1022 1023 /* Function 14 - Not used on wire */ 1024 unsigned long 1025 __stdcall 1026 NetrLogonDomainNameAdd( 1027 WKSSVC_IDENTIFY_HANDLE DomainName) 1028 { 1029 TRACE("NetrLogonDomainNameAdd(%s)\n", 1030 debugstr_w(DomainName)); 1031 return ERROR_NOT_SUPPORTED; 1032 } 1033 1034 1035 /* Function 15 - Not used on wire */ 1036 unsigned long 1037 __stdcall 1038 NetrLogonDomainNameDel( 1039 WKSSVC_IDENTIFY_HANDLE DomainName) 1040 { 1041 TRACE("NetrLogonDomainNameDel(%s)\n", 1042 debugstr_w(DomainName)); 1043 return ERROR_NOT_SUPPORTED; 1044 } 1045 1046 1047 /* Function 16 - Not used on wire */ 1048 unsigned long 1049 __stdcall 1050 NetrJoinDomain(void) 1051 { 1052 TRACE("NetrJoinDomain()\n"); 1053 return ERROR_NOT_SUPPORTED; 1054 } 1055 1056 1057 /* Function 17 - Not used on wire */ 1058 unsigned long 1059 __stdcall 1060 NetrUnjoinDomain(void) 1061 { 1062 TRACE("NetrUnjoinDomain()\n"); 1063 return ERROR_NOT_SUPPORTED; 1064 } 1065 1066 1067 /* Function 18 - Not used on wire */ 1068 unsigned long 1069 __stdcall 1070 NetrValidateName(void) 1071 { 1072 TRACE("NetrValidateName()\n"); 1073 return ERROR_NOT_SUPPORTED; 1074 } 1075 1076 1077 /* Function 19 - Not used on wire */ 1078 unsigned long 1079 __stdcall 1080 NetrRenameMachineInDomain(void) 1081 { 1082 TRACE("NetrRenameMachineInDomain()\n"); 1083 return ERROR_NOT_SUPPORTED; 1084 } 1085 1086 1087 /* Function 20 */ 1088 unsigned long 1089 __stdcall 1090 NetrGetJoinInformation( 1091 WKSSVC_IMPERSONATE_HANDLE ServerName, 1092 wchar_t **NameBuffer, 1093 PNETSETUP_JOIN_STATUS BufferType) 1094 { 1095 TRACE("NetrGetJoinInformation(%p %p %p)\n", 1096 ServerName, NameBuffer, BufferType); 1097 1098 if (NameBuffer == NULL) 1099 return ERROR_INVALID_PARAMETER; 1100 1101 return NetpGetJoinInformation(NameBuffer, 1102 BufferType); 1103 } 1104 1105 1106 /* Function 21 - Not used on wire */ 1107 unsigned long 1108 __stdcall 1109 NetrGetJoinableOUs(void) 1110 { 1111 TRACE("NetrGetJoinableOUs()\n"); 1112 return ERROR_NOT_SUPPORTED; 1113 } 1114 1115 1116 /* Function 22 */ 1117 unsigned long 1118 __stdcall 1119 NetrJoinDomain2( 1120 handle_t RpcBindingHandle, 1121 wchar_t *ServerName, 1122 wchar_t *DomainNameParam, 1123 wchar_t *MachineAccountOU, 1124 wchar_t *AccountName, 1125 PJOINPR_ENCRYPTED_USER_PASSWORD Password, 1126 unsigned long Options) 1127 { 1128 NET_API_STATUS status; 1129 1130 FIXME("NetrJoinDomain2(%p %S %S %S %S %p 0x%lx)\n", 1131 RpcBindingHandle, ServerName, DomainNameParam, MachineAccountOU, 1132 AccountName, Password, Options); 1133 1134 if (DomainNameParam == NULL) 1135 return ERROR_INVALID_PARAMETER; 1136 1137 if (Options & NETSETUP_JOIN_DOMAIN) 1138 { 1139 FIXME("NetrJoinDomain2: NETSETUP_JOIN_DOMAIN is not supported yet!\n"); 1140 status = ERROR_CALL_NOT_IMPLEMENTED; 1141 } 1142 else 1143 { 1144 status = NetpJoinWorkgroup(DomainNameParam); 1145 } 1146 1147 return status; 1148 } 1149 1150 1151 /* Function 23 */ 1152 unsigned long 1153 __stdcall 1154 NetrUnjoinDomain2( 1155 handle_t RpcBindingHandle, 1156 wchar_t *ServerName, 1157 wchar_t *AccountName, 1158 PJOINPR_ENCRYPTED_USER_PASSWORD Password, 1159 unsigned long Options) 1160 { 1161 UNIMPLEMENTED; 1162 return 0; 1163 } 1164 1165 1166 /* Function 24 */ 1167 unsigned long 1168 __stdcall 1169 NetrRenameMachineInDomain2( 1170 handle_t RpcBindingHandle, 1171 wchar_t *ServerName, 1172 wchar_t *MachineName, 1173 wchar_t *AccountName, 1174 PJOINPR_ENCRYPTED_USER_PASSWORD Password, 1175 unsigned long Options) 1176 { 1177 UNIMPLEMENTED; 1178 return 0; 1179 } 1180 1181 1182 /* Function 25 */ 1183 unsigned long 1184 __stdcall 1185 NetrValidateName2( 1186 handle_t RpcBindingHandle, 1187 wchar_t *ServerName, 1188 wchar_t *NameToValidate, 1189 wchar_t *AccountName, 1190 PJOINPR_ENCRYPTED_USER_PASSWORD Password, 1191 NETSETUP_NAME_TYPE NameType) 1192 { 1193 UNIMPLEMENTED; 1194 return 0; 1195 } 1196 1197 1198 /* Function 26 */ 1199 unsigned long 1200 __stdcall 1201 NetrGetJoinableOUs2( 1202 handle_t RpcBindingHandle, 1203 wchar_t *ServerName, 1204 wchar_t *DomainNameParam, 1205 wchar_t *AccountName, 1206 PJOINPR_ENCRYPTED_USER_PASSWORD Password, 1207 unsigned long* OUCount, 1208 wchar_t ***OUs) 1209 { 1210 UNIMPLEMENTED; 1211 return 0; 1212 } 1213 1214 1215 /* Function 27 */ 1216 unsigned long 1217 __stdcall 1218 NetrAddAlternateComputerName( 1219 handle_t RpcBindingHandle, 1220 wchar_t *ServerName, 1221 wchar_t *AlternateName, 1222 wchar_t *DomainAccount, 1223 PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword, 1224 unsigned long Reserved) 1225 { 1226 UNIMPLEMENTED; 1227 return 0; 1228 } 1229 1230 1231 /* Function 28 */ 1232 unsigned long 1233 __stdcall 1234 NetrRemoveAlternateComputerName( 1235 handle_t RpcBindingHandle, 1236 wchar_t *ServerName, 1237 wchar_t *AlternateName, 1238 wchar_t *DomainAccount, 1239 PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword, 1240 unsigned long Reserved) 1241 { 1242 UNIMPLEMENTED; 1243 return 0; 1244 } 1245 1246 1247 /* Function 29 */ 1248 unsigned long 1249 __stdcall 1250 NetrSetPrimaryComputerName( 1251 handle_t RpcBindingHandle, 1252 wchar_t *ServerName, 1253 wchar_t *PrimaryName, 1254 wchar_t *DomainAccount, 1255 PJOINPR_ENCRYPTED_USER_PASSWORD EncryptedPassword, 1256 unsigned long Reserved) 1257 { 1258 UNIMPLEMENTED; 1259 return 0; 1260 } 1261 1262 1263 /* Function 30 */ 1264 unsigned long 1265 __stdcall 1266 NetrEnumerateComputerNames( 1267 WKSSVC_IMPERSONATE_HANDLE ServerName, 1268 NET_COMPUTER_NAME_TYPE NameType, 1269 unsigned long Reserved, 1270 PNET_COMPUTER_NAME_ARRAY *ComputerNames) 1271 { 1272 UNIMPLEMENTED; 1273 return 0; 1274 } 1275 1276 /* EOF */ 1277