1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#ifndef _MLSVC_SAM_NDL_ 27#define _MLSVC_SAM_NDL_ 28 29#pragma ident "%Z%%M% %I% %E% SMI" 30 31/* 32 * Security Accounts Manager RPC (SAMR) interface definition. 33 */ 34 35#include "ndrtypes.ndl" 36 37 38#define SAMR_OPNUM_ConnectAnon 0x00 39#define SAMR_OPNUM_CloseHandle 0x01 40#define SAMR_OPNUM_QuerySecObject 0x03 41#define SAMR_OPNUM_LookupDomain 0x05 42#define SAMR_OPNUM_EnumLocalDomains 0x06 43#define SAMR_OPNUM_OpenDomain 0x07 44#define SAMR_OPNUM_QueryDomainInfo 0x08 45#define SAMR_OPNUM_CreateDomainGroup 0x0a 46#define SAMR_OPNUM_QueryDomainGroups 0x0b 47#define SAMR_OPNUM_EnumDomainUsers 0x0d 48#define SAMR_OPNUM_CreateDomainAlias 0x0e 49#define SAMR_OPNUM_EnumDomainAliases 0x0f 50#define SAMR_OPNUM_LookupIds 0x10 51#define SAMR_OPNUM_LookupNames 0x11 52#define SAMR_OPNUM_LookupDomainIds 0x12 53#define SAMR_OPNUM_OpenGroup 0x13 54#define SAMR_OPNUM_QueryGroupInfo 0x14 55#define SAMR_OPNUM_StoreGroupInfo 0x15 56#define SAMR_OPNUM_AddGroupMember 0x16 57#define SAMR_OPNUM_DeleteDomainGroup 0x17 58#define SAMR_OPNUM_DeleteGroupMember 0x18 59#define SAMR_OPNUM_ListGroupMembers 0x19 60#define SAMR_OPNUM_OpenAlias 0x1b 61#define SAMR_OPNUM_QueryAliasInfo 0x1c 62#define SAMR_OPNUM_SetAliasInfo 0x1d 63#define SAMR_OPNUM_DeleteDomainAlias 0x1e 64#define SAMR_OPNUM_AddAliasMember 0x1f 65#define SAMR_OPNUM_DeleteAliasMember 0x20 66#define SAMR_OPNUM_QueryAliasMember 0x21 67#define SAMR_OPNUM_OpenUser 0x22 68#define SAMR_OPNUM_DeleteUser 0x23 69#define SAMR_OPNUM_QueryUserInfo 0x24 70#define SAMR_OPNUM_QueryUserGroups 0x27 71#define SAMR_OPNUM_QueryDispInfo 0x28 /* QueryDispInfo1 */ 72#define SAMR_OPNUM_GetUserPwInfo 0x2c 73#define SAMR_OPNUM_EnumDomainGroups 0x30 /* QueryDispInfo3 */ 74#define SAMR_OPNUM_CreateUser 0x32 75#define SAMR_OPNUM_QueryDispInfo4 0x33 76#define SAMR_OPNUM_AddMultiAliasMember 0x34 77#define SAMR_OPNUM_ChangeUserPasswd 0x37 78#define SAMR_OPNUM_GetDomainPwInfo 0x38 79#define SAMR_OPNUM_Connect 0x39 80#define SAMR_OPNUM_SetUserInfo 0x3a 81#define SAMR_OPNUM_Connect3 0x3e 82#define SAMR_OPNUM_Connect4 0x40 83 84 85/* 86 * UNION_INFO_ENT is intended to simplify adding new entries to a union. 87 * If the entry structures are named using the form samr_QueryUserInfoX, 88 * where X is the sitch_value, you can just add a single line. Note 89 * that you must also update the fixup function in mlsvc_sam.c. 90 */ 91#define UNION_INFO_ENT(N,NAME) CASE(N) struct NAME##N info##N 92 93 94/* 95 * Sam account flags used when creating an account. These flags seem 96 * to be very similar to the USER_INFO_X flags (UF_XXX) in lmaccess.h 97 * but the values are different. 98 */ 99#define SAMR_AF_ACCOUNTDISABLE 0x0001 100#define SAMR_AF_HOMEDIR_REQUIRED 0x0002 101#define SAMR_AF_PASSWD_NOTREQD 0x0004 102#define SAMR_AF_TEMP_DUPLICATE_ACCOUNT 0x0008 103#define SAMR_AF_NORMAL_ACCOUNT 0x0010 104#define SAMR_AF_MNS_LOGON_ACCOUNT 0x0020 105#define SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT 0x0040 106#define SAMR_AF_WORKSTATION_TRUST_ACCOUNT 0x0080 107#define SAMR_AF_SERVER_TRUST_ACCOUNT 0x0100 108#define SAMR_AF_DONT_EXPIRE_PASSWD 0x0200 109#define SAMR_AF_ACCOUNT_AUTOLOCK 0x0400 110 111 112#define SAMR_AF_MACHINE_ACCOUNT_MASK ( \ 113 SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT \ 114 | SAMR_AF_WORKSTATION_TRUST_ACCOUNT \ 115 | SAMR_AF_SERVER_TRUST_ACCOUNT) 116 117#define SAMR_AF_ACCOUNT_TYPE_MASK ( \ 118 SAMR_AF_TEMP_DUPLICATE_ACCOUNT \ 119 | SAMR_AF_NORMAL_ACCOUNT \ 120 | SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT \ 121 | SAMR_AF_WORKSTATION_TRUST_ACCOUNT \ 122 | SAMR_AF_SERVER_TRUST_ACCOUNT) 123 124 125/* 126 * specific access rights which can be used in OpenAlias. 127 * extracted from Ethereal network analyzer 128 */ 129#define SAMR_ALIAS_ACCESS_SET_INFO 0x00000010 130#define SAMR_ALIAS_ACCESS_GET_INFO 0x00000008 131#define SAMR_ALIAS_ACCESS_GET_MEMBERS 0x00000004 132#define SAMR_ALIAS_ACCESS_DEL_MEMBER 0x00000002 133#define SAMR_ALIAS_ACCESS_ADD_MEMBER 0x00000001 134 135/* 136 * Definition for a SID. The ndl compiler does not allow a typedef of 137 * a structure containing variable size members. 138 */ 139struct samr_sid { 140 BYTE Revision; 141 BYTE SubAuthCount; 142 BYTE Authority[6]; 143 SIZE_IS(SubAuthCount) 144 DWORD SubAuthority[ANY_SIZE_ARRAY]; 145}; 146 147 148/* 149 * SAMR definition of a security_descriptor. 150 */ 151struct samr_sec_desc { 152 BYTE Revision; 153 BYTE Sbz1; 154 WORD Control; 155 struct samr_sid *owner; 156 struct samr_sid *group; 157 struct samr_sid *sacl; 158 struct samr_sid *dacl; 159}; 160 161 162/* 163 * Definition for a string. The length and allosize should be set to 164 * twice the string length (i.e. strlen(str) * 2). The runtime code 165 * will perform the appropriate string to a wide-char conversions, 166 * so str should point to a regular char * string. 167 */ 168struct samr_string { 169 WORD length; 170 WORD allosize; 171 LPTSTR str; 172}; 173typedef struct samr_string samr_string_t; 174 175 176/* 177 * Alternative varying/conformant string definition - for 178 * non-null terminated strings. This definition must match 179 * mlrpc_vcbuf_t. 180 */ 181struct samr_vcb { 182 /* 183 * size_is (actually a copy of length_is) will 184 * be inserted here by the marshalling library. 185 */ 186 DWORD vc_first_is; 187 DWORD vc_length_is; 188 SIZE_IS(vc_length_is) 189 WORD buffer[ANY_SIZE_ARRAY]; 190}; 191 192struct samr_vcbuf { 193 WORD wclen; 194 WORD wcsize; 195 struct samr_vcb *vcb; 196}; 197typedef struct samr_vcbuf samr_vcbuf_t; 198 199 200/* 201 * Handles appear to be a 20 byte object with the top 4 bytes all zero. 202 * Handles may have some internal structure but this should work since 203 * we always treat it as an opaque handle. They do appear to contain a 204 * sequence number which is incremented when new handle is issued. 205*/ 206 207struct samr_handle { 208 DWORD hand1; 209 DWORD hand2; 210 WORD hand3[2]; 211 BYTE hand4[8]; 212}; 213typedef struct samr_handle samr_handle_t; 214 215/* 216 * A long long, i.e. 64-bit, value. 217 */ 218struct samr_quad { 219 DWORD low; 220 DWORD high; 221}; 222typedef struct samr_quad samr_quad_t; 223 224 225/* 226 *********************************************************************** 227 * ConnectAnon. It looks like the SAM handle is identical to an LSA 228 * handle. See Connect. 229 *********************************************************************** 230 */ 231OPERATION(SAMR_OPNUM_ConnectAnon) 232struct samr_ConnectAnon { 233 IN DWORD *servername; 234 IN DWORD access_mask; 235 OUT samr_handle_t handle; 236 OUT DWORD status; 237}; 238 239 240/* 241 *********************************************************************** 242 * Connect. I'm not sure what the difference is between Connect and 243 * ConnectAnon but this call seems to work better than ConnectAnon. 244 *********************************************************************** 245 */ 246OPERATION(SAMR_OPNUM_Connect) 247struct samr_Connect { 248 IN LPTSTR servername; 249 IN DWORD access_mask; 250 OUT samr_handle_t handle; 251 OUT DWORD status; 252}; 253 254 255/* 256 *********************************************************************** 257 * SamrConnect3. A new form of connect first seen with Windows 2000. 258 * A new field has been added to the input request. Value: 0x00000002. 259 * I haven't looked at the Win2K response yet to see if it differs 260 * from SAMR_OPNUM_Connect. 261 *********************************************************************** 262 */ 263OPERATION(SAMR_OPNUM_Connect3) 264struct samr_Connect3 { 265 IN LPTSTR servername; 266 IN DWORD unknown_02; 267 IN DWORD access_mask; 268 OUT samr_handle_t handle; 269 OUT DWORD status; 270}; 271 272 273/* 274 *********************************************************************** 275 * SamrConnect4. A new form of connect first seen with Windows XP. 276 * The server name is the fully qualified domain name, i.e. 277 * \\server.procom.com. 278 *********************************************************************** 279 */ 280OPERATION(SAMR_OPNUM_Connect4) 281struct samr_Connect4 { 282 IN LPTSTR servername; 283 IN DWORD access_mask; 284 INOUT DWORD unknown2_00000001; 285 INOUT DWORD unknown3_00000001; 286 INOUT DWORD unknown4_00000003; 287 INOUT DWORD unknown5_00000000; 288 OUT samr_handle_t handle; 289 OUT DWORD status; 290}; 291 292 293/* 294 *********************************************************************** 295 * CloseHandle closes an association with the SAM. Using the same 296 * structure as the LSA seems to work. 297 *********************************************************************** 298 */ 299OPERATION(SAMR_OPNUM_CloseHandle) 300struct samr_CloseHandle { 301 IN samr_handle_t handle; 302 OUT samr_handle_t result_handle; 303 OUT DWORD status; 304}; 305 306 307/* 308 *********************************************************************** 309 * LookupDomain: lookup up the domain SID. 310 *********************************************************************** 311 */ 312OPERATION(SAMR_OPNUM_LookupDomain) 313struct samr_LookupDomain { 314 IN samr_handle_t handle; 315 IN samr_string_t domain_name; 316 OUT struct samr_sid *sid; 317 OUT DWORD status; 318}; 319 320 321/* 322 *********************************************************************** 323 * EnumLocalDomain 324 * 325 * This looks like a request to get the local domains supported by a 326 * remote server. NT always seems to return 2 domains: the local 327 * domain (hostname) and the Builtin domain. 328 * 329 * The max_length field is set to 0x2000. 330 * Enum_context is set to 0 in the request and set to entries_read in 331 * the reply. Like most of these enums, total_entries is the same as 332 * entries_read. 333 *********************************************************************** 334 */ 335struct samr_LocalDomainEntry { 336 DWORD unknown; 337 samr_string_t name; 338}; 339 340struct samr_LocalDomainInfo { 341 DWORD entries_read; 342 SIZE_IS(entries_read) 343 struct samr_LocalDomainEntry *entry; 344}; 345 346 347OPERATION(SAMR_OPNUM_EnumLocalDomains) 348struct samr_EnumLocalDomain { 349 IN samr_handle_t handle; 350 INOUT DWORD enum_context; 351 IN DWORD max_length; 352 OUT struct samr_LocalDomainInfo *info; 353 OUT DWORD total_entries; 354 OUT DWORD status; 355}; 356 357 358/* 359 *********************************************************************** 360 * OpenDomain 361 * 362 * Open a specific domain within the SAM. From this I assume that each 363 * SAM can handle multiple domains so you need to identify the one with 364 * which you want to work. Working with a domain handle does appear to 365 * offer the benefit that you can then use RIDs instead of full SIDs, 366 * which simplifies things a bit. The domain handle can be used to get 367 * user and group handles. 368 *********************************************************************** 369 */ 370OPERATION(SAMR_OPNUM_OpenDomain) 371struct samr_OpenDomain { 372 IN samr_handle_t handle; 373 IN DWORD access_mask; 374 IN REFERENCE struct samr_sid *sid; 375 OUT samr_handle_t domain_handle; 376 OUT DWORD status; 377}; 378 379 380/* 381 *********************************************************************** 382 * QueryDomainInfo 383 * 384 * Windows 95 Server Manager sends requests for levels 6 and 7 when 385 * the services menu item is selected. 386 *********************************************************************** 387 */ 388#define SAMR_QUERY_DOMAIN_INFO_2 2 389#define SAMR_QUERY_DOMAIN_INFO_6 6 390#define SAMR_QUERY_DOMAIN_INFO_7 7 391 392 393struct samr_QueryDomainInfo2 { 394 DWORD unknown1; /* 00 00 00 00 */ 395 DWORD unknown2; /* 00 00 00 80 */ 396 samr_string_t s1; 397 samr_string_t domain; 398 samr_string_t s2; 399 DWORD sequence_num; /* 2B 00 00 00 */ 400 DWORD unknown3; /* 00 00 00 00 */ 401 DWORD unknown4; /* 01 00 00 00 */ 402 DWORD unknown5; /* 03 00 00 00 */ 403 DWORD unknown6; /* 01 */ 404 DWORD num_users; 405 DWORD num_groups; 406 DWORD num_aliases; 407}; 408 409 410struct samr_QueryDomainInfo6 { 411 DWORD unknown1; /* 00 00 00 00 */ 412 DWORD unknown2; /* B0 7F 14 00 */ 413 DWORD unknown3; /* 00 00 00 00 */ 414 DWORD unknown4; /* 00 00 00 00 */ 415 DWORD unknown5; /* 00 00 00 00 */ 416}; 417 418 419struct samr_QueryDomainInfo7 { 420 DWORD unknown1; /* 03 00 00 00 */ 421}; 422 423 424union samr_QueryDomainInfo_ru { 425 UNION_INFO_ENT(2,samr_QueryDomainInfo); 426 UNION_INFO_ENT(6,samr_QueryDomainInfo); 427 UNION_INFO_ENT(7,samr_QueryDomainInfo); 428 DEFAULT char *nullptr; 429}; 430 431 432/* 433 * This structure needs to be declared, even though it can't be used in 434 * samr_QueryDomainInfo, in order to calculate the correct fixup offsets. 435 * If ndrgen did the right thing, samr_QueryDomainInfoRes would be one of 436 * the out parameters. However, if we do it that way, the switch_value 437 * isn't known early enough to do the fixup calculation. So it all has 438 * to go in samr_QueryDomainInfo. 439 */ 440struct samr_QueryDomainInfoRes { 441 DWORD address; 442 WORD switch_value; 443 SWITCH(switch_value) 444 union samr_QueryDomainInfo_ru ru; 445}; 446 447 448OPERATION(SAMR_OPNUM_QueryDomainInfo) 449struct samr_QueryDomainInfo { 450 IN samr_handle_t domain_handle; 451 IN WORD info_level; 452 /* 453 * Can't use the standard "OUT result" form because 454 * we need to include members explicitly. 455 * OUT struct samr_QueryDomainInfoRes result; 456 */ 457 OUT DWORD address; 458 OUT WORD switch_value; 459 SWITCH(info_level) 460 OUT union samr_QueryDomainInfo_ru ru; 461 OUT DWORD status; 462}; 463 464#define SAMR_QUERY_ALIAS_INFO_1 1 465#define SAMR_QUERY_ALIAS_INFO_3 3 466 467 468struct samr_QueryAliasInfo1 { 469 WORD level; 470 samr_string_t name; 471 DWORD unknown; 472 samr_string_t desc; 473}; 474 475struct samr_QueryAliasInfo3 { 476 WORD level; 477 samr_string_t desc; 478}; 479 480union samr_QueryAliasInfo_ru { 481 UNION_INFO_ENT(1,samr_QueryAliasInfo); 482 UNION_INFO_ENT(3,samr_QueryAliasInfo); 483 DEFAULT char *nullptr; 484}; 485 486struct samr_QueryAliasInfoRes { 487 DWORD address; 488 WORD switch_value; 489 SWITCH(switch_value) 490 union samr_QueryAliasInfo_ru ru; 491}; 492 493OPERATION(SAMR_OPNUM_QueryAliasInfo) 494struct samr_QueryAliasInfo { 495 IN samr_handle_t alias_handle; 496 IN WORD level; 497 OUT DWORD address; 498 SWITCH (level) 499 OUT union samr_QueryAliasInfo_ru ru; 500 OUT DWORD status; 501}; 502 503OPERATION(SAMR_OPNUM_CreateDomainAlias) 504struct samr_CreateDomainAlias { 505 IN samr_handle_t domain_handle; 506 IN samr_string_t alias_name; 507 IN DWORD access_mask; 508 OUT samr_handle_t alias_handle; 509 OUT DWORD rid; 510 OUT DWORD status; 511}; 512 513OPERATION(SAMR_OPNUM_SetAliasInfo) 514struct samr_SetAliasInfo { 515 IN samr_handle_t alias_handle; 516 IN WORD level; 517 /* TBD */ 518 OUT DWORD status; 519}; 520 521OPERATION(SAMR_OPNUM_DeleteDomainAlias) 522struct samr_DeleteDomainAlias { 523 IN samr_handle_t alias_handle; 524 OUT DWORD status; 525}; 526 527OPERATION(SAMR_OPNUM_OpenAlias) 528struct samr_OpenAlias { 529 IN samr_handle_t domain_handle; 530 IN DWORD access_mask; 531 IN DWORD rid; 532 OUT samr_handle_t alias_handle; 533 OUT DWORD status; 534}; 535 536struct name_rid { 537 DWORD rid; 538 samr_string_t name; 539}; 540 541struct aliases_info { 542 DWORD count; 543 DWORD address; 544 SIZE_IS(count) 545 struct name_rid info[ANY_SIZE_ARRAY]; 546}; 547 548OPERATION(SAMR_OPNUM_EnumDomainAliases) 549struct samr_EnumDomainAliases { 550 IN samr_handle_t domain_handle; 551 IN DWORD resume_handle; 552 IN DWORD mask; 553 OUT DWORD out_resume; 554 OUT struct aliases_info *aliases; 555 OUT DWORD entries; 556 OUT DWORD status; 557}; 558 559struct user_acct_info { 560 DWORD index; 561 DWORD rid; 562 DWORD ctrl; 563 samr_string_t name; 564 samr_string_t fullname; 565 samr_string_t desc; 566}; 567 568struct user_disp_info { 569 DWORD count; 570 /* right now we just need two entries */ 571 struct user_acct_info acct[2]; 572}; 573 574OPERATION(SAMR_OPNUM_QueryDispInfo) 575struct samr_QueryDispInfo { 576 IN samr_handle_t domain_handle; 577 IN WORD level; 578 IN DWORD start_idx; 579 IN DWORD max_entries; 580 IN DWORD pref_maxsize; 581 OUT DWORD total_size; 582 OUT DWORD returned_size; 583 OUT WORD switch_value; 584 OUT DWORD count; 585 OUT struct user_disp_info *users; 586 OUT DWORD status; 587}; 588 589struct group_acct_info { 590 DWORD index; 591 DWORD rid; 592 DWORD ctrl; 593 samr_string_t name; 594 samr_string_t desc; 595}; 596 597struct group_disp_info { 598 DWORD count; 599 /* right now we just need one entry */ 600 struct group_acct_info acct[1]; 601}; 602 603OPERATION(SAMR_OPNUM_EnumDomainGroups) 604struct samr_EnumDomainGroups { 605 IN samr_handle_t domain_handle; 606 IN WORD level; 607 IN DWORD start_idx; 608 IN DWORD max_entries; 609 IN DWORD pref_maxsize; 610 OUT DWORD total_size; 611 OUT DWORD returned_size; 612 OUT WORD switch_value; 613 OUT DWORD count; 614 OUT struct group_disp_info *groups; 615 OUT DWORD status; 616}; 617 618/* 619 *********************************************************************** 620 * OpenUser 621 * 622 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain, 623 * an access mask and the appropriate user rid. The output will be a 624 * handle for use with the specified user. 625 *********************************************************************** 626 */ 627OPERATION(SAMR_OPNUM_OpenUser) 628struct samr_OpenUser { 629 IN samr_handle_t handle; 630 IN DWORD access_mask; 631 IN DWORD rid; 632 OUT samr_handle_t user_handle; 633 OUT DWORD status; 634}; 635 636 637/* 638 *********************************************************************** 639 * DeleteUser 640 *********************************************************************** 641 */ 642OPERATION(SAMR_OPNUM_DeleteUser) 643struct samr_DeleteUser { 644 INOUT samr_handle_t user_handle; 645 OUT DWORD status; 646}; 647 648 649/* 650 *********************************************************************** 651 * QueryUserInfo 652 * 653 * Provides various pieces of information on a specific user (see 654 * SAM_Q_QUERY_USERINFO and SAM_R_QUERY_USERINFO). The handle must 655 * be a valid SAM user handle. 656 * 657 * QueryUserInfo ( 658 * IN samr_handle_t user_handle, 659 * IN WORD switch_value, 660 * OUT union switch(switch_value) { 661 * case 1: struct QueryUserInfo1 *info1; 662 * } bufptr, 663 * OUT DWORD status 664 * ) 665 * 666 * The cases identified so far are: 667 * 668 * 1 = username, fullname, description and some other stuff. 669 * 2 = unknown 670 * 3 = large structure containing user rid, group rid, username 671 * and fullname. 672 * 4 = unknown 673 * 5 = large structure (like 3) containing user rid, group rid, 674 * username, fullname and description. 675 * 6 = username and fullname 676 * 7 = username 677 * 8 = fullname 678 * 9 = group rid 679 * 16 = used after creating a new account 680 * 681 * Due to an ndrgen bug, a function must be provided to to patch the 682 * offsets used by the unmarshalling code at runtime. In order to 683 * simplify things it is useful to use a naming convention that 684 * indicates the switch value for each structure. 685 * 686 *********************************************************************** 687 */ 688 689 690#define SAMR_QUERY_USER_INFO_1 1 691#define SAMR_QUERY_USER_UNAME_AND_FNAME 6 692#define SAMR_QUERY_USER_USERNAME 7 693#define SAMR_QUERY_USER_FULLNAME 8 694#define SAMR_QUERY_USER_GROUPRID 9 695#define SAMR_QUERY_USER_UNKNOWN16 16 696 697 698struct samr_QueryUserInfo1 { 699 samr_string_t username; 700 samr_string_t fullname; 701 DWORD group_rid; 702 samr_string_t description; 703 samr_string_t unknown; 704}; 705 706 707struct samr_QueryUserInfo6 { 708 samr_string_t username; 709 samr_string_t fullname; 710}; 711 712struct samr_QueryUserInfo7 { 713 samr_string_t username; 714}; 715 716 717struct samr_QueryUserInfo8 { 718 samr_string_t fullname; 719}; 720 721 722struct samr_QueryUserInfo9 { 723 DWORD group_rid; 724}; 725 726 727struct samr_QueryUserInfo16 { 728 DWORD unknown; 729}; 730 731 732union QueryUserInfo_result_u { 733 UNION_INFO_ENT(1,samr_QueryUserInfo); 734 UNION_INFO_ENT(6,samr_QueryUserInfo); 735 UNION_INFO_ENT(7,samr_QueryUserInfo); 736 UNION_INFO_ENT(8,samr_QueryUserInfo); 737 UNION_INFO_ENT(9,samr_QueryUserInfo); 738 UNION_INFO_ENT(16,samr_QueryUserInfo); 739 DEFAULT char *nullptr; 740}; 741 742 743/* 744 * This structure needs to be declared, even though it can't be used in 745 * samr_QueryUserInfo, in order to get the appropriate size to calculate 746 * the correct fixup offsets. If ndrgen did the right thing, 747 * QueryUserInfo_result would be one of the out parameters. However, if 748 * we do it that way, the switch_value isn't known early enough to do 749 * the fixup calculation. So it all has to go in samr_QueryUserInfo. 750 */ 751struct QueryUserInfo_result { 752 DWORD address; 753 WORD switch_value; 754 SWITCH(switch_value) 755 union QueryUserInfo_result_u ru; 756}; 757 758 759OPERATION(SAMR_OPNUM_QueryUserInfo) 760struct samr_QueryUserInfo { 761 IN samr_handle_t user_handle; 762 IN WORD switch_value; 763 /* 764 * Can't use this form because we need to include members explicitly. 765 * OUT struct QueryUserInfo_result result; 766 */ 767 OUT DWORD address; 768 OUT WORD switch_index; 769 SWITCH(switch_value) 770 OUT union QueryUserInfo_result_u ru; 771 OUT DWORD status; 772}; 773 774 775/* 776 *********************************************************************** 777 * QueryUserGroups 778 *********************************************************************** 779 */ 780struct samr_UserGroups { 781 DWORD rid; 782 DWORD attr; 783}; 784 785 786struct samr_UserGroupInfo { 787 DWORD n_entry; 788 SIZE_IS(n_entry) 789 struct samr_UserGroups *groups; 790}; 791 792 793OPERATION(SAMR_OPNUM_QueryUserGroups) 794struct samr_QueryUserGroups { 795 IN samr_handle_t user_handle; 796 OUT struct samr_UserGroupInfo *info; 797 OUT DWORD status; 798}; 799 800 801/* 802 *********************************************************************** 803 * LookupName 804 *********************************************************************** 805 */ 806struct samr_LookupNameTable { 807 DWORD n_entry; 808 SIZE_IS(n_entry) 809 samr_string_t names[ANY_SIZE_ARRAY]; 810}; 811 812 813struct samr_LookupRidTable { 814 DWORD n_entry; 815 SIZE_IS(n_entry) 816 DWORD *rid; 817}; 818 819struct samr_RidType { 820 DWORD n_entry; 821 SIZE_IS(n_entry) 822 DWORD *rid_type; 823}; 824 825 826OPERATION(SAMR_OPNUM_LookupNames) 827struct samr_LookupNames { 828 IN samr_handle_t handle; 829 IN DWORD n_entry; 830 IN DWORD max_n_entry; 831 IN DWORD index; 832 IN DWORD total; 833 IN samr_string_t name; 834 OUT struct samr_LookupRidTable rids; 835 OUT struct samr_RidType rid_types; 836 OUT DWORD status; 837}; 838 839 840/* 841 *********************************************************************** 842 * OpenGroup 843 * 844 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain, 845 * an access mask and the appropriate group rid. The output will be a 846 * handle for use with the specified group. 847 *********************************************************************** 848 */ 849OPERATION(SAMR_OPNUM_OpenGroup) 850struct samr_OpenGroup { 851 IN samr_handle_t handle; 852 IN DWORD access_mask; 853 IN DWORD rid; 854 OUT samr_handle_t group_handle; 855 OUT DWORD status; 856}; 857 858 859/* 860 *********************************************************************** 861 * QueryGroupInfo 862 * 863 * Input must be a group handle obtained via SAMR_OPNUM_OpenGroup, 864 * an access mask and the appropriate group rid. The output will 865 * be a handle for use with the specified group. 866 *********************************************************************** 867 */ 868struct samr_QueryGroupInfo1 { 869 samr_string_t groupname; 870}; 871 872 873union samr_QueryGroupInfo_result_u { 874 UNION_INFO_ENT(1,samr_QueryGroupInfo); 875 DEFAULT char *nullptr; 876}; 877 878 879struct samr_QueryGroupInfo_result { 880 DWORD address; 881 WORD switch_index; 882 SWITCH(switch_index) 883 union samr_QueryGroupInfo_result_u ru; 884}; 885 886 887OPERATION(SAMR_OPNUM_QueryGroupInfo) 888struct samr_QueryGroupInfo { 889 IN samr_handle_t group_handle; 890 IN DWORD switch_value; 891 OUT DWORD address; 892 OUT WORD switch_index; 893 SWITCH(switch_index) 894 OUT union samr_QueryGroupInfo_result_u ru; 895 OUT DWORD status; 896}; 897 898 899/* 900 *********************************************************************** 901 * StoreGroupInfo 902 * 903 * This definition is mostly just a place holder in case this is useful 904 * in the future. Note that it may not be correct. The information is 905 * from a netmon trace captured when I added a group description. I 906 * haven't implemented it because we don't have to update anything on 907 * the PDC. The description should almost certainly be in a separate 908 * structure. 909 *********************************************************************** 910 */ 911OPERATION(SAMR_OPNUM_StoreGroupInfo) 912struct samr_StoreGroupInfo { 913 IN samr_handle_t group_handle; 914 IN DWORD switch_value; 915 IN samr_string_t group_description; 916 OUT DWORD status; 917}; 918 919 920/* 921 *********************************************************************** 922 * Request 0x2c is a user request. The only parameter is a user handle. 923 * The response is 12 bytes of the form: 924 * unknown: 00 00 BB 01 (443) 925 * unknown: 00 00 00 00 926 * status: 00 00 00 00 927 * RPC book lists this as GetUsrDomPwInfo. 928 *********************************************************************** 929 */ 930struct samr_UserPwInfo { 931 WORD unknown1; 932 WORD unknown2; 933 DWORD unknown3; 934}; 935 936 937OPERATION(SAMR_OPNUM_GetUserPwInfo) 938struct samr_GetUserPwInfo { 939 IN samr_handle_t user_handle; 940 OUT struct samr_UserPwInfo pw_info; 941 OUT DWORD status; 942}; 943 944 945/* 946 *********************************************************************** 947 * CreateUser 948 * 949 * Create a user in the domain specified by the domain handle. The 950 * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. There 951 * is an unknown value at the end of the request: 0xe00500b0. 952 * The output will be a handle for use with the specified user and the 953 * user's RID. I think the RID may be a pointer but the value came back 954 * as zero once so I've padded it out so that the marshalling doesn't 955 * get confused. 956 *********************************************************************** 957 */ 958OPERATION(SAMR_OPNUM_CreateUser) 959struct samr_CreateUser { 960 IN samr_handle_t handle; 961 IN samr_vcbuf_t username; 962 IN DWORD account_flags; 963 IN DWORD unknown_e00500b0; 964 OUT samr_handle_t user_handle; 965 OUT DWORD maybe_ptr; 966 OUT DWORD rid; 967 OUT DWORD status; 968}; 969 970 971/* 972 *********************************************************************** 973 * ChangeUserPasswd 974 *********************************************************************** 975 */ 976struct samr_newpasswd { 977 BYTE data[516]; 978}; 979 980 981struct samr_oldpasswd { 982 BYTE data[16]; 983}; 984 985 986OPERATION(SAMR_OPNUM_ChangeUserPasswd) 987struct samr_ChangeUserPasswd { 988 IN LPTSTR servername; 989 IN LPTSTR username; 990 IN struct samr_newpasswd *nt_newpasswd; 991 IN struct samr_oldpasswd *nt_oldpasswd; 992 IN struct samr_newpasswd *lm_newpasswd; 993 IN struct samr_oldpasswd *lm_oldpasswd; 994 OUT DWORD status; 995}; 996 997 998/* 999 *********************************************************************** 1000 * GetDomainPwInfo 1001 *********************************************************************** 1002 */ 1003OPERATION(SAMR_OPNUM_GetDomainPwInfo) 1004struct samr_GetDomainPwInfo { 1005 IN LPTSTR servername; 1006 OUT WORD unknown0; 1007 OUT WORD unknown1; 1008 OUT WORD unknown2; 1009 OUT DWORD status; 1010}; 1011 1012 1013/* 1014 *********************************************************************** 1015 * SetUserInfo 1016 * 1017 * +++ 20 byte user handle and the union switch_value +++ 1018 * 00 00 00 00 77 F2 DD D5 66 48 D4 11 AD 5F D1 CD 1019 * 18 43 7A DF 17 00 17 00 1020 * 1021 * +++ 14 dwords (56 bytes) of zeros +++ 1022 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1023 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1024 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1025 * 00 00 00 00 00 00 00 00 1026 * 1027 * +++ 9 sets of something - 72 bytes +++ 1028 * 00 00 02 00 D0 04 8A 77 1029 * 00 00 02 00 D0 04 8A 77 1030 * 00 00 02 00 D0 04 8A 77 1031 * 00 00 02 00 D0 04 8A 77 1032 * 00 00 02 00 D0 04 8A 77 1033 * 00 00 02 00 D0 04 8A 77 1034 * 00 00 02 00 D0 04 8A 77 1035 * 00 00 02 00 D0 04 8A 77 1036 * 00 00 02 00 D0 04 8A 77 1037 * 1038 * +++ 9 DWORD zeros +++ 1039 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1040 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1041 * 00 00 00 00 1042 * 1043 * +++ miscellaneous +++ 1044 * 01 02 00 00 1045 * 80 00 00 00 1046 * FA 27 F8 09 1047 * A8 00 00 00 70 F1 14 00 1048 * 00 00 00 00 00 00 00 00 00 00 00 00 1049 * 1050 * +++ encrypted password buffer - 512 bytes +++ 1051 * 76 68 E8 AA 23 4F 62 C4 81 4E 30 B8 92 29 66 B9 1052 * 12 FF 3A 84 82 3A 55 0F C7 18 EA 56 86 50 D7 C5 1053 * 43 BA 9C F8 32 D4 E0 15 74 A1 6F E1 59 C2 F2 95 1054 * 53 A9 F2 68 9F 7F 29 B9 88 4C 65 A5 C1 DC 0B 44 1055 * B8 3C ED 74 D1 6A F7 09 66 97 94 6B 2C 3A A5 88 1056 * 39 34 C6 FE 24 59 30 2D CF 6D 7F D5 EC B1 9A 84 1057 * E6 57 96 29 40 32 FB 62 9D 93 E2 BE D8 A3 74 88 1058 * 8B 85 BC A0 76 D6 C9 DB 8C AF 81 BD 8A F0 08 8D 1059 * 23 B0 52 FD 69 DE EF A1 36 E5 30 19 BD DA 67 A3 1060 * 81 BD 3F D0 2A A2 8F 60 62 B0 8D 34 9E A4 4F 20 1061 * 4E 79 93 82 58 A8 E5 6F 7A DC 12 13 33 E6 74 02 1062 * 4C 32 F9 FC 1A E1 C5 0D E2 CC 36 8D FC 72 87 DD 1063 * 6C 44 E3 6F 4B FD 46 10 08 89 E5 64 B8 27 14 83 1064 * E7 08 DE CF 69 C7 E1 40 63 DF CB 67 95 73 03 1B 1065 * CA 99 E1 1B 53 2A 89 6B 30 39 CD 5C DF A0 8A 1C 1066 * 4E 50 74 7C 6D 3D E7 EA E9 B2 97 DD 38 7B DA EC 1067 * 1A AD DA CE C4 58 9B 29 F3 6D 30 70 4E 63 6D 84 1068 * DB DC 5B CD 9A 4E 57 9C E4 65 5D 4F 76 E3 C7 52 1069 * 8B 3B 20 0A 3B 4C 4B B1 2E 5B 4D AB BA 2F 45 6A 1070 * CA 17 AD 9F C0 B2 07 FB 56 7F E4 3F 9F D4 C6 8C 1071 * A1 05 BF 53 42 1E 67 F4 57 54 E3 2C 38 CF E1 94 1072 * 75 69 F7 4E 5C 74 CC B3 FD EF 73 3F D5 28 22 EC 1073 * 9B 40 E1 1D 65 44 7C BB 69 88 57 10 05 3A C5 48 1074 * 8E 4F 77 DB 1A 5C 49 9C D5 06 00 AC 79 BC 7E 89 1075 * B0 01 66 70 88 A2 E5 DF 96 DC 75 98 10 12 45 02 1076 * 33 35 6C DF 74 8B 14 2F 26 C6 FD 7A B4 D0 A6 7D 1077 * DE 2B 13 44 EF 34 46 4D 9D 3E C3 75 BC 11 B4 41 1078 * 27 58 25 1E AF AA F0 BB DA 27 7A 1E AE 81 1A 78 1079 * 44 19 DE FC C4 7C 4E 32 44 F7 57 2A 41 A2 85 DC 1080 * C0 AD 5D 6B 58 FD 2E 75 25 B9 F2 B6 19 82 E5 0E 1081 * B6 69 0D C1 27 A9 B6 40 A6 50 49 E5 CB 17 98 65 1082 * 88 18 CA E4 1D 2E 20 F7 DE 8E 7D F2 9D A5 6B CD 1083 * 1084 * D6 79 45 71 1085 * 1086 * +++ table of 9 things +++ 1087 * 01 00 00 00 00 00 00 00 00 00 00 00 1088 * 01 00 00 00 00 00 00 00 00 00 00 00 1089 * 01 00 00 00 00 00 00 00 00 00 00 00 1090 * 01 00 00 00 00 00 00 00 00 00 00 00 1091 * 01 00 00 00 00 00 00 00 00 00 00 00 1092 * 01 00 00 00 00 00 00 00 00 00 00 00 1093 * 01 00 00 00 00 00 00 00 00 00 00 00 1094 * 01 00 00 00 00 00 00 00 00 00 00 00 1095 * 01 00 00 00 00 00 00 00 00 00 00 00 1096 * 1097 * +++ miscellaneous +++ 1098 * EC 04 00 00 00 00 00 00 15 00 00 00 1099 * FF FF FF FF FF FF FF FF FF FF FF FF 1100 * FF FF FF FF FF FF FF FF FF 1101 * 1102 *********************************************************************** 1103 */ 1104 1105#define SAMR_SET_USER_INFO_23 23 1106#define SAMR_SET_USER_DATA_SZ 516 1107 1108#define SAMR_MINS_PER_WEEK 10080 1109#define SAMR_HOURS_PER_WEEK 168 1110 1111#define SAMR_HOURS_MAX_SIZE (SAMR_MINS_PER_WEEK / 8) 1112#define SAMR_HOURS_SET_LEN(LEN) ((LEN) / 8) 1113#define SAMR_SET_USER_HOURS_SZ 21 1114 1115 1116struct samr_sd { 1117 DWORD length; 1118 SIZE_IS(length) 1119 BYTE *data; 1120}; 1121 1122 1123/* 1124 * There is some sort of logon bitmap structure in here, which I 1125 * think is a varying and conformant array, i.e. 1126 * 1127 * struct samr_logon_hours { 1128 * DWORD size_is; (0x04ec) 1129 * DWORD first_is; (zero) 1130 * DWORD length_is; (0xa8) 1131 * BYTE bitmap[21]; 1132 * }; 1133 * 1134 * struct samr_logon_info { 1135 * DWORD length; 1136 * SIZE_IS(length / 8) 1137 * struct samr_logon_hours *hours; 1138 * }; 1139 * 1140 * There are 10080 minutes/week => 10080/8 = 1260 (0x04EC). 1141 * So size_is is set as some sort of maximum. 1142 * 1143 * There are 168 hours/week => 168/8 = 21 (0xA8). Since there are 21 1144 * bytes (all set to 0xFF), this is is probably the default setting. 1145 * 1146 * ndrgen has a problem with complex [size_is] statements. For now, 1147 * we can try to fake it using two separate components. 1148 */ 1149struct samr_logon_hours { 1150 DWORD size; 1151 DWORD first; 1152 DWORD length; 1153 BYTE bitmap[SAMR_SET_USER_HOURS_SZ]; 1154}; 1155 1156 1157struct samr_logon_info { 1158 DWORD units; 1159 DWORD hours; 1160}; 1161 1162 1163struct samr_oem_password { 1164 BYTE password[512]; 1165 DWORD length; 1166}; 1167 1168 1169struct samr_SetUserInfo23 { 1170 samr_quad_t logon_time; /* 00 00 00 00 00 00 00 00 */ 1171 samr_quad_t logoff_time; /* 00 00 00 00 00 00 00 00 */ 1172 samr_quad_t kickoff_time; /* 00 00 00 00 00 00 00 00 */ 1173 samr_quad_t passwd_last_set_time; /* 00 00 00 00 00 00 00 00 */ 1174 samr_quad_t passwd_can_change_time; /* 00 00 00 00 00 00 00 00 */ 1175 samr_quad_t passwd_must_change_time; /* 00 00 00 00 00 00 00 00 */ 1176 1177 samr_vcbuf_t user_name; /* 00 00 00 00 00 00 00 00 */ 1178 samr_vcbuf_t full_name; /* 00 00 02 00 D0 04 8A 77 */ 1179 samr_vcbuf_t home_dir; /* 00 00 02 00 D0 04 8A 77 */ 1180 samr_vcbuf_t home_drive; /* 00 00 02 00 D0 04 8A 77 */ 1181 samr_vcbuf_t logon_script; /* 00 00 02 00 D0 04 8A 77 */ 1182 samr_vcbuf_t profile_path; /* 00 00 02 00 D0 04 8A 77 */ 1183 samr_vcbuf_t acct_desc; /* 00 00 02 00 D0 04 8A 77 */ 1184 samr_vcbuf_t workstations; /* 00 00 02 00 D0 04 8A 77 */ 1185 samr_vcbuf_t unknown1; /* 00 00 02 00 D0 04 8A 77 */ 1186 samr_vcbuf_t unknown2; /* 00 00 02 00 D0 04 8A 77 */ 1187 samr_vcbuf_t lm_password; /* 00 00 00 00 00 00 00 00 */ 1188 samr_vcbuf_t nt_password; /* 00 00 00 00 00 00 00 00 */ 1189 samr_vcbuf_t unknown3; /* 00 00 00 00 00 00 00 00 */ 1190 1191 struct samr_sd sd; /* 00 00 00 00 00 00 00 00 */ 1192 DWORD user_rid; /* 00 00 00 00 */ 1193 DWORD group_rid; /* 01 02 00 00 */ 1194 DWORD acct_info; /* 80 00 00 00 */ 1195 DWORD flags; /* FA 27 F8 09 */ 1196 struct samr_logon_info logon_info; /* A8 00 00 00 70 F1 14 00->0xFF */ 1197 /* 1198 * The following 12 bytes are encoded in Ethereal as: 1199 * 1200 * WORD bad_pwd_count; 1201 * WORD logon_count; 1202 * 1203 * WORD country; (default 0) 1204 * WORD codepage; 1205 * 1206 * BYTE nt_pwd_set; 1207 * BYTE lm_pwd_set; 1208 * BYTE expired_flag; 1209 * BYTE unknown_char; 1210 */ 1211 DWORD unknown4_zero; /* 00 00 00 00 */ 1212 DWORD unknown5_zero; /* 00 00 00 00 */ 1213 DWORD unknown6_zero; /* 00 00 00 00 */ 1214 BYTE password[SAMR_SET_USER_DATA_SZ]; 1215}; 1216 1217 1218union samr_SetUserInfo_u { 1219 UNION_INFO_ENT(23,samr_SetUserInfo); 1220 DEFAULT char *nullptr; 1221}; 1222 1223 1224struct samr_SetUserInfo_s { 1225 WORD index; 1226 WORD switch_value; 1227 SWITCH(switch_value) 1228 union samr_SetUserInfo_u ru; 1229}; 1230 1231 1232/* 1233 IN DWORD unknown_04EC; 1234 IN DWORD unknown_zero; 1235 IN DWORD logon_bitmap_size; 1236 IN BYTE logon_bitmap[SAMR_SET_USER_HOURS_SZ]; 1237*/ 1238OPERATION(SAMR_OPNUM_SetUserInfo) 1239struct samr_SetUserInfo { 1240 IN samr_handle_t user_handle; 1241 IN struct samr_SetUserInfo_s info; 1242 IN struct samr_logon_hours logon_hours; 1243 OUT DWORD status; 1244}; 1245 1246 1247/* 1248 *********************************************************************** 1249 * The SAMR interface definition. 1250 *********************************************************************** 1251 */ 1252INTERFACE(0) 1253union samr_interface { 1254 CASE(SAMR_OPNUM_ConnectAnon) 1255 struct samr_ConnectAnon ConnectAnon; 1256 CASE(SAMR_OPNUM_CloseHandle) 1257 struct samr_CloseHandle CloseHandle; 1258 CASE(SAMR_OPNUM_LookupDomain) 1259 struct samr_LookupDomain LookupDomain; 1260 CASE(SAMR_OPNUM_EnumLocalDomains) 1261 struct samr_EnumLocalDomain EnumLocalDomain; 1262 CASE(SAMR_OPNUM_OpenDomain) 1263 struct samr_OpenDomain OpenDomain; 1264 CASE(SAMR_OPNUM_QueryDomainInfo) 1265 struct samr_QueryDomainInfo QueryDomainInfo; 1266 CASE(SAMR_OPNUM_LookupNames) 1267 struct samr_LookupNames LookupNames; 1268 CASE(SAMR_OPNUM_OpenUser) 1269 struct samr_OpenUser OpenUser; 1270 CASE(SAMR_OPNUM_DeleteUser) 1271 struct samr_DeleteUser DeleteUser; 1272 CASE(SAMR_OPNUM_QueryUserInfo) 1273 struct samr_QueryUserInfo QueryUserInfo; 1274 CASE(SAMR_OPNUM_QueryUserGroups) 1275 struct samr_QueryUserGroups QueryUserGroups; 1276 CASE(SAMR_OPNUM_OpenGroup) 1277 struct samr_OpenGroup OpenGroup; 1278 CASE(SAMR_OPNUM_GetUserPwInfo) 1279 struct samr_GetUserPwInfo GetUserPwInfo; 1280 CASE(SAMR_OPNUM_CreateUser) 1281 struct samr_CreateUser CreateUser; 1282 CASE(SAMR_OPNUM_ChangeUserPasswd) 1283 struct samr_ChangeUserPasswd ChangeUserPasswd; 1284 CASE(SAMR_OPNUM_GetDomainPwInfo) 1285 struct samr_GetDomainPwInfo GetDomainPwInfo; 1286 CASE(SAMR_OPNUM_Connect) 1287 struct samr_Connect Connect; 1288 CASE(SAMR_OPNUM_SetUserInfo) 1289 struct samr_SetUserInfo SetUserInfo; 1290 CASE(SAMR_OPNUM_Connect3) 1291 struct samr_Connect3 Connect3; 1292 CASE(SAMR_OPNUM_Connect4) 1293 struct samr_Connect4 Connect4; 1294 CASE(SAMR_OPNUM_QueryDispInfo) 1295 struct samr_QueryDispInfo QueryDispInfo; 1296 CASE(SAMR_OPNUM_OpenAlias) 1297 struct samr_OpenAlias OpenAlias; 1298 CASE(SAMR_OPNUM_CreateDomainAlias) 1299 struct samr_CreateDomainAlias CreateDomainAlias; 1300 CASE(SAMR_OPNUM_SetAliasInfo) 1301 struct samr_SetAliasInfo SetAliasInfo; 1302 CASE(SAMR_OPNUM_QueryAliasInfo) 1303 struct samr_QueryAliasInfo QueryAliasInfo; 1304 CASE(SAMR_OPNUM_DeleteDomainAlias) 1305 struct samr_DeleteDomainAlias DeleteDomainAlias; 1306 CASE(SAMR_OPNUM_EnumDomainAliases) 1307 struct samr_EnumDomainAliases EnumDomainAliases; 1308 CASE(SAMR_OPNUM_EnumDomainGroups) 1309 struct samr_EnumDomainGroups EnumDomainGroups; 1310}; 1311typedef union samr_interface samr_interface_t; 1312EXTERNTYPEINFO(samr_interface) 1313 1314#endif /* _MLSVC_SAM_NDL_ */ 1315