Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
6.1 KiB

  1. /*--
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. setprefdc.c
  5. Abstract:
  6. Program to set the preferred trusted DC to a particular DC.
  7. Author:
  8. 13-Mar-1997 (Cliff Van Dyke)
  9. --*/
  10. #define UNICODE 1
  11. #include <windows.h>
  12. #include <shellapi.h>
  13. #include <lmcons.h>
  14. #include <lmerr.h>
  15. #include <lmapibuf.h>
  16. #include <lmaccess.h>
  17. #include <lmuse.h>
  18. #include <stdio.h>
  19. #define OneStatus( _x ) \
  20. case _x: \
  21. fprintf( stderr, #_x "\n" ); \
  22. break;
  23. VOID
  24. PrintError( NET_API_STATUS NetStatus )
  25. {
  26. switch ( NetStatus ) {
  27. OneStatus(ERROR_NO_SUCH_DOMAIN);
  28. OneStatus(ERROR_BAD_NETPATH);
  29. OneStatus(ERROR_ACCESS_DENIED);
  30. OneStatus(ERROR_NOT_SUPPORTED);
  31. OneStatus(ERROR_NO_TRUST_SAM_ACCOUNT);
  32. OneStatus(ERROR_NO_TRUST_LSA_SECRET);
  33. OneStatus(ERROR_TRUSTED_DOMAIN_FAILURE);
  34. OneStatus(ERROR_TRUSTED_RELATIONSHIP_FAILURE);
  35. OneStatus(ERROR_NETLOGON_NOT_STARTED);
  36. OneStatus(NO_ERROR);
  37. default:
  38. fprintf( stderr, "%ld\n", NetStatus );
  39. break;
  40. }
  41. }
  42. _cdecl
  43. main(int argc, char **argv)
  44. {
  45. NET_API_STATUS NetStatus;
  46. LPWSTR CommandLine;
  47. LPWSTR *argvw;
  48. int argcw;
  49. LPWSTR ServerName = NULL; // Make local calls
  50. LPWSTR TrustedDomainName;
  51. PNETLOGON_INFO_2 OrigNetlogonInfo2 = NULL;
  52. PNETLOGON_INFO_2 NewNetlogonInfo2 = NULL;
  53. USE_INFO_2 UseInfo2;
  54. int i;
  55. WCHAR UncDcName[UNCLEN+1];
  56. WCHAR ShareName[UNCLEN+1+NNLEN+1];
  57. WCHAR NewDomainAndDc[DNLEN+1+CNLEN+1];
  58. LPWSTR NewDomainAndDcPtr;
  59. LPWSTR DcName;
  60. ULONG DcNameLen;
  61. //
  62. // Get the command line in Unicode
  63. //
  64. CommandLine = GetCommandLine();
  65. argvw = CommandLineToArgvW( CommandLine, &argcw );
  66. if ( argvw == NULL ) {
  67. fprintf( stderr, "Can't convert command line to Unicode: %ld\n", GetLastError() );
  68. return 1;
  69. }
  70. //
  71. // Get the arguments
  72. //
  73. if ( argcw < 3 ) {
  74. Usage:
  75. fprintf( stderr, "Usage: %s <TrustedDomain> <ListOfDcsInTrustedDomain>\n", argv[0]);
  76. return 1;
  77. }
  78. TrustedDomainName = argvw[1];
  79. _wcsupr( TrustedDomainName );
  80. //
  81. // Query the secure channel to find out the current DC being used.
  82. //
  83. NetStatus = I_NetLogonControl2( ServerName,
  84. NETLOGON_CONTROL_TC_QUERY,
  85. 2,
  86. (LPBYTE) &TrustedDomainName,
  87. (LPBYTE *)&OrigNetlogonInfo2 );
  88. if ( NetStatus != NERR_Success ) {
  89. fprintf( stderr, "Cannot determine current trusted DC of domain '%ws': ", TrustedDomainName );
  90. PrintError( NetStatus );
  91. return 1;
  92. }
  93. //
  94. // Loop handling each preferred DC.
  95. //
  96. for ( i=2; i<argcw; i++ ) {
  97. //
  98. // Grab the DC name specified by the caller.
  99. //
  100. DcName = argvw[i];
  101. _wcsupr( DcName );
  102. if ( DcName[0] == L'\\' && DcName[1] == L'\\' ) {
  103. DcName += 2;
  104. }
  105. DcNameLen = wcslen(DcName);
  106. if ( DcNameLen < 1 || DcNameLen > CNLEN ) {
  107. fprintf( stderr, "DcName '%ws' is invalid.\n", DcName );
  108. goto Usage;
  109. }
  110. wcscpy( UncDcName, L"\\\\" );
  111. wcscat( UncDcName, DcName );
  112. //
  113. // If the named DC is already the current DC,
  114. // just tell the caller.
  115. //
  116. if ( OrigNetlogonInfo2->netlog2_trusted_dc_name != NULL &&
  117. _wcsicmp( OrigNetlogonInfo2->netlog2_trusted_dc_name,
  118. UncDcName) == 0 ) {
  119. fprintf( stderr, "DC already is '%ws'.\n", UncDcName );
  120. return 0;
  121. }
  122. //
  123. // Test if this DC is up.
  124. //
  125. wcscpy( ShareName, UncDcName );
  126. wcscat( ShareName, L"\\IPC$" );
  127. UseInfo2.ui2_local = NULL;
  128. UseInfo2.ui2_remote = ShareName;
  129. UseInfo2.ui2_password = NULL;
  130. UseInfo2.ui2_asg_type = USE_IPC;
  131. UseInfo2.ui2_username = NULL;
  132. UseInfo2.ui2_domainname = NULL;
  133. NetStatus = NetUseAdd( NULL, 2, (LPBYTE) &UseInfo2, NULL );
  134. if ( NetStatus == NERR_Success ) {
  135. NetStatus = NetUseDel( NULL, ShareName, FALSE );
  136. if ( NetStatus != NERR_Success ) {
  137. fprintf( stderr, "Cannot remove connection to '%ws' (Continuing): ", UncDcName );
  138. PrintError( NetStatus );
  139. }
  140. } else if ( NetStatus == ERROR_ACCESS_DENIED ) {
  141. /* Server really is up */
  142. } else if ( NetStatus == ERROR_SESSION_CREDENTIAL_CONFLICT ) {
  143. /* We can only assume the server is up */
  144. } else {
  145. fprintf( stderr, "Cannot connect to '%ws': ", UncDcName );
  146. PrintError( NetStatus );
  147. continue;
  148. }
  149. //
  150. // This DC is up. Try to use it.
  151. //
  152. wcscpy( NewDomainAndDc, TrustedDomainName );
  153. wcscat( NewDomainAndDc, L"\\" );
  154. wcscat( NewDomainAndDc, UncDcName+2 );
  155. NewDomainAndDcPtr = NewDomainAndDc;
  156. NetStatus = I_NetLogonControl2( ServerName,
  157. NETLOGON_CONTROL_REDISCOVER,
  158. 2,
  159. (LPBYTE) &NewDomainAndDcPtr,
  160. (LPBYTE *)&NewNetlogonInfo2 );
  161. if ( NetStatus != NERR_Success ) {
  162. fprintf( stderr, "Cannot set new trusted DC to '%ws': ", UncDcName );
  163. PrintError( NetStatus );
  164. continue;
  165. }
  166. //
  167. // If the named DC is now the DC,
  168. // tell the caller.
  169. //
  170. if ( NewNetlogonInfo2->netlog2_trusted_dc_name != NULL &&
  171. _wcsicmp( NewNetlogonInfo2->netlog2_trusted_dc_name,
  172. UncDcName) == 0 ) {
  173. fprintf( stderr, "Successfully set DC to '%ws'.\n", UncDcName );
  174. return 0;
  175. }
  176. fprintf( stderr,
  177. "Cannot set trusted DC to '%ws' it is '%ws': \n",
  178. UncDcName,
  179. NewNetlogonInfo2->netlog2_trusted_dc_name,
  180. NewNetlogonInfo2->netlog2_tc_connection_status );
  181. PrintError( NetStatus );
  182. }
  183. fprintf( stderr, "Failed to set the DC.\n" );
  184. return 1;
  185. }