Leaked source code of windows server 2003
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.

860 lines
23 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. fttest.c
  5. Abstract:
  6. Component test for Ds*ForestTrustInformation API
  7. Author:
  8. Cliff Van Dyke (CliffV) August 11, 2000
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. // #include <wincred.h>
  17. // #include <credp.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. // #include <winnetwk.h>
  21. #include <lmcons.h>
  22. #include <lmerr.h>
  23. #include <ntlsa.h>
  24. #include <dsgetdc.h>
  25. #include <ntstatus.dbg>
  26. #include <winerror.dbg>
  27. VOID
  28. NlpDumpSid(
  29. IN DWORD DebugFlag,
  30. IN PSID Sid OPTIONAL
  31. )
  32. /*++
  33. Routine Description:
  34. Dumps a SID to the debugger output
  35. Arguments:
  36. DebugFlag - Debug flag to pass on to NlPrintRoutine
  37. Sid - SID to output
  38. Return Value:
  39. none
  40. --*/
  41. {
  42. //
  43. // Output the SID
  44. //
  45. if ( Sid == NULL ) {
  46. printf( "(null)\n");
  47. } else {
  48. UNICODE_STRING SidString;
  49. NTSTATUS Status;
  50. Status = RtlConvertSidToUnicodeString( &SidString, Sid, TRUE );
  51. if ( !NT_SUCCESS(Status) ) {
  52. printf( "Invalid 0x%lX\n", Status );
  53. } else {
  54. printf( "%wZ\n", &SidString );
  55. RtlFreeUnicodeString( &SidString );
  56. }
  57. }
  58. UNREFERENCED_PARAMETER( DebugFlag );
  59. }
  60. VOID
  61. PrintTime(
  62. LPSTR Comment,
  63. LARGE_INTEGER ConvertTime
  64. )
  65. /*++
  66. Routine Description:
  67. Print the specified time
  68. Arguments:
  69. Comment - Comment to print in front of the time
  70. Time - GMT time to print (Nothing is printed if this is zero)
  71. Return Value:
  72. None
  73. --*/
  74. {
  75. //
  76. // If we've been asked to convert an NT GMT time to ascii,
  77. // Do so
  78. //
  79. if ( ConvertTime.QuadPart != 0 ) {
  80. LARGE_INTEGER LocalTime;
  81. TIME_FIELDS TimeFields;
  82. NTSTATUS Status;
  83. printf( "%s", Comment );
  84. Status = RtlSystemTimeToLocalTime( &ConvertTime, &LocalTime );
  85. if ( !NT_SUCCESS( Status )) {
  86. printf( "Can't convert time from GMT to Local time\n" );
  87. LocalTime = ConvertTime;
  88. }
  89. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  90. printf( "%8.8lx %8.8lx = %ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
  91. ConvertTime.LowPart,
  92. ConvertTime.HighPart,
  93. TimeFields.Month,
  94. TimeFields.Day,
  95. TimeFields.Year,
  96. TimeFields.Hour,
  97. TimeFields.Minute,
  98. TimeFields.Second );
  99. }
  100. }
  101. LPSTR
  102. FindSymbolicNameForStatus(
  103. DWORD Id
  104. )
  105. {
  106. ULONG i;
  107. i = 0;
  108. if (Id == 0) {
  109. return "STATUS_SUCCESS";
  110. }
  111. if (Id & 0xC0000000) {
  112. while (ntstatusSymbolicNames[ i ].SymbolicName) {
  113. if (ntstatusSymbolicNames[ i ].MessageId == (NTSTATUS)Id) {
  114. return ntstatusSymbolicNames[ i ].SymbolicName;
  115. } else {
  116. i += 1;
  117. }
  118. }
  119. }
  120. while (winerrorSymbolicNames[ i ].SymbolicName) {
  121. if (winerrorSymbolicNames[ i ].MessageId == Id) {
  122. return winerrorSymbolicNames[ i ].SymbolicName;
  123. } else {
  124. i += 1;
  125. }
  126. }
  127. #ifdef notdef
  128. while (neteventSymbolicNames[ i ].SymbolicName) {
  129. if (neteventSymbolicNames[ i ].MessageId == Id) {
  130. return neteventSymbolicNames[ i ].SymbolicName
  131. } else {
  132. i += 1;
  133. }
  134. }
  135. #endif // notdef
  136. return NULL;
  137. }
  138. VOID
  139. PrintStatus(
  140. NET_API_STATUS NetStatus
  141. )
  142. /*++
  143. Routine Description:
  144. Print a net status code.
  145. Arguments:
  146. NetStatus - The net status code to print.
  147. Return Value:
  148. None
  149. --*/
  150. {
  151. printf( "Status = %lu 0x%lx", NetStatus, NetStatus );
  152. switch (NetStatus) {
  153. case NERR_Success:
  154. printf( " NERR_Success" );
  155. break;
  156. case NERR_DCNotFound:
  157. printf( " NERR_DCNotFound" );
  158. break;
  159. case NERR_UserNotFound:
  160. printf( " NERR_UserNotFound" );
  161. break;
  162. case NERR_NetNotStarted:
  163. printf( " NERR_NetNotStarted" );
  164. break;
  165. case NERR_WkstaNotStarted:
  166. printf( " NERR_WkstaNotStarted" );
  167. break;
  168. case NERR_ServerNotStarted:
  169. printf( " NERR_ServerNotStarted" );
  170. break;
  171. case NERR_BrowserNotStarted:
  172. printf( " NERR_BrowserNotStarted" );
  173. break;
  174. case NERR_ServiceNotInstalled:
  175. printf( " NERR_ServiceNotInstalled" );
  176. break;
  177. case NERR_BadTransactConfig:
  178. printf( " NERR_BadTransactConfig" );
  179. break;
  180. default:
  181. printf( " %s", FindSymbolicNameForStatus( NetStatus ) );
  182. break;
  183. }
  184. printf( "\n" );
  185. }
  186. VOID
  187. DumpFtinfo(
  188. PLSA_FOREST_TRUST_INFORMATION Ftinfo
  189. )
  190. /*++
  191. Routine Description:
  192. Dumps the buffer content on to the debugger output.
  193. Arguments:
  194. Buffer: buffer pointer.
  195. BufferSize: size of the buffer.
  196. Return Value:
  197. none
  198. --*/
  199. {
  200. ULONG Index;
  201. if ( Ftinfo == NULL ) {
  202. printf( " (null)\n");
  203. } else {
  204. for ( Index=0; Index<Ftinfo->RecordCount; Index++ ) {
  205. switch ( Ftinfo->Entries[Index]->ForestTrustType ) {
  206. case ForestTrustTopLevelName:
  207. printf( " TLN: %wZ",
  208. &Ftinfo->Entries[Index]->ForestTrustData.TopLevelName );
  209. break;
  210. case ForestTrustTopLevelNameEx:
  211. printf( " TEX: %wZ",
  212. &Ftinfo->Entries[Index]->ForestTrustData.TopLevelName );
  213. break;
  214. case ForestTrustDomainInfo:
  215. printf( " Dom: %wZ (%wZ)",
  216. &Ftinfo->Entries[Index]->ForestTrustData.DomainInfo.DnsName,
  217. &Ftinfo->Entries[Index]->ForestTrustData.DomainInfo.NetbiosName );
  218. break;
  219. default:
  220. printf( " Invalid Type: %ld", Ftinfo->Entries[Index]->ForestTrustType );
  221. }
  222. if ( Ftinfo->Entries[Index]->Flags ) {
  223. ULONG Flags = Ftinfo->Entries[Index]->Flags;
  224. printf(" (" );
  225. #define DoFlag( _flag, _text ) \
  226. if ( Flags & _flag ) { \
  227. printf( _text ); \
  228. Flags &= ~_flag; \
  229. }
  230. switch ( Ftinfo->Entries[Index]->ForestTrustType ) {
  231. case ForestTrustTopLevelName:
  232. case ForestTrustTopLevelNameEx:
  233. DoFlag( LSA_TLN_DISABLED_NEW, " TlnNew" );
  234. DoFlag( LSA_TLN_DISABLED_ADMIN, " TlnAdmin" );
  235. DoFlag( LSA_TLN_DISABLED_CONFLICT, " TlnConflict" );
  236. }
  237. switch ( Ftinfo->Entries[Index]->ForestTrustType ) {
  238. case ForestTrustDomainInfo:
  239. DoFlag( LSA_SID_DISABLED_ADMIN, " SidAdmin" );
  240. DoFlag( LSA_SID_DISABLED_CONFLICT, " SidConflict" );
  241. DoFlag( LSA_NB_DISABLED_ADMIN, " NbAdmin" );
  242. DoFlag( LSA_NB_DISABLED_CONFLICT, " NbConflict" );
  243. }
  244. if ( Flags != 0 ) {
  245. printf(" 0x%lX", Flags);
  246. }
  247. printf(")" );
  248. }
  249. switch ( Ftinfo->Entries[Index]->ForestTrustType ) {
  250. case ForestTrustDomainInfo:
  251. printf(" ");
  252. NlpDumpSid( 0, Ftinfo->Entries[Index]->ForestTrustData.DomainInfo.Sid );
  253. break;
  254. default:
  255. printf("\n");
  256. break;
  257. }
  258. }
  259. }
  260. }
  261. //
  262. // Structure describing an Ftinfo entry
  263. //
  264. typedef struct _AN_ENTRY {
  265. ULONG Flags;
  266. LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; // type of record
  267. #define TLN ForestTrustTopLevelName
  268. #define TLNEX ForestTrustTopLevelNameEx
  269. #define DOM ForestTrustDomainInfo
  270. #define EOD (DOM+1)
  271. LPWSTR Name;
  272. PSID Sid;
  273. LPWSTR NetbiosName;
  274. } AN_ENTRY, *PAN_ENTRY;
  275. //
  276. // Define template FTinfo structures.
  277. //
  278. AN_ENTRY Ftinfo0[] = {
  279. { 0, TLN, L"acme.com" },
  280. { 0, EOD },
  281. };
  282. AN_ENTRY Ftinfo1[] = {
  283. { 0, TLN, L"acme.com" },
  284. { 0, TLN, L"ms.com" },
  285. { 0, EOD },
  286. };
  287. AN_ENTRY Ftinfo2[] = {
  288. { 0, TLN, L"acme.com" },
  289. { 0, TLN, L"z.au" },
  290. { 0, EOD },
  291. };
  292. AN_ENTRY Ftinfo3[] = {
  293. { 0, TLN, L"z.au" },
  294. { 0, EOD },
  295. };
  296. AN_ENTRY Ftinfo4[] = {
  297. { 0, TLN, L"corp.acme.com" },
  298. { 0, EOD },
  299. };
  300. AN_ENTRY Ftinfo5[] = {
  301. { 0, TLN, L"x.corp.acme.com" },
  302. { 0, EOD },
  303. };
  304. AN_ENTRY Ftinfo6[] = {
  305. { 0, TLN, L"acme.com" },
  306. { LSA_TLN_DISABLED_ADMIN, TLN, L"ms.com" },
  307. { 0, EOD },
  308. };
  309. AN_ENTRY Ftinfo7[] = {
  310. { 0, TLN, L"acme.com" },
  311. { 0xFFFFFFFF, TLN, L"ms.com" },
  312. { 0, EOD },
  313. };
  314. AN_ENTRY Ftinfo8[] = {
  315. { 0, TLN, L"acme.com" },
  316. { LSA_TLN_DISABLED_ADMIN, TLN, L"ms.com" },
  317. { 0, EOD },
  318. };
  319. AN_ENTRY Ftinfo9[] = {
  320. { 0, TLN, L"acme.com" },
  321. { LSA_TLN_DISABLED_ADMIN, TLN, L"b.a.ms.com" },
  322. { 0, EOD },
  323. };
  324. AN_ENTRY Ftinfo10[] = {
  325. { 0, TLN, L"acme.com" },
  326. { 0, TLN, L"a.ms.com" },
  327. { 0, EOD },
  328. };
  329. AN_ENTRY Ftinfo11[] = {
  330. { 0, TLN, L"acme.com" },
  331. { 0, TLNEX, L"a.acme.com" },
  332. { 0, EOD },
  333. };
  334. SID Sid1 = { 1, 1, SECURITY_NT_AUTHORITY, 1 };
  335. SID Sid2 = { 1, 1, SECURITY_NT_AUTHORITY, 2 };
  336. SID Sid3 = { 1, 1, SECURITY_NT_AUTHORITY, 3 };
  337. SID Sid4 = { 1, 1, SECURITY_NT_AUTHORITY, 4 };
  338. SID Sid5 = { 1, 1, SECURITY_NT_AUTHORITY, 5 };
  339. AN_ENTRY Ftinfo12[] = {
  340. { 0, TLN, L"acme.com" },
  341. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB" },
  342. { 0, EOD },
  343. };
  344. AN_ENTRY Ftinfo13[] = {
  345. { 0, TLN, L"acme.com" },
  346. { LSA_SID_DISABLED_ADMIN, DOM, L"corp.acme.com", &Sid1, L"CORP_NB" },
  347. { 0, EOD },
  348. };
  349. AN_ENTRY Ftinfo13a[] = {
  350. { 0, TLN, L"acme.com" },
  351. { 0xFFFFFFFF, DOM, L"corp.acme.com", &Sid1, L"CORP_NB" },
  352. { 0, EOD },
  353. };
  354. AN_ENTRY Ftinfo14[] = {
  355. { 0, TLN, L"acme.com" },
  356. { 0, TLN, L"acme.com" },
  357. { 0, EOD },
  358. };
  359. AN_ENTRY Ftinfo15[] = {
  360. { 0, TLN, L"acme.com" },
  361. { 0, TLN, L"a.acme.com" },
  362. { 0, EOD },
  363. };
  364. AN_ENTRY Ftinfo16[] = {
  365. { 0, TLN, L"acme.com" },
  366. { 0, TLN, L"acme.com" },
  367. { 0, TLN, L"a.acme.com" },
  368. { 0, TLN, L"b.acme.com" },
  369. { 0, TLN, L"ms.com" },
  370. { 0, EOD },
  371. };
  372. AN_ENTRY Ftinfo17[] = {
  373. { 0, TLN, L"acme.com" },
  374. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  375. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  376. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  377. { 0, EOD },
  378. };
  379. AN_ENTRY Ftinfo18[] = {
  380. { 0, TLN, L"acme.com" },
  381. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  382. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  383. { 0, DOM, L"c2.corp.acme.com", &Sid1, L"CORP_NB2" },
  384. { 0, EOD },
  385. };
  386. AN_ENTRY Ftinfo19[] = {
  387. { 0, TLN, L"acme.com" },
  388. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  389. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  390. { 0, DOM, L"c2.corp.acme.com", &Sid1, L"CORP_NB2" },
  391. { 0, DOM, L"c3.corp.acme.com", &Sid1, L"CORP_NB3" },
  392. { 0, DOM, L"c4.corp.acme.com", &Sid1, L"CORP_NB4" },
  393. { 0, EOD },
  394. };
  395. AN_ENTRY Ftinfo20[] = {
  396. { 0, TLN, L"acme.com" },
  397. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  398. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  399. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  400. { 0, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB3" },
  401. { 0, DOM, L"c4.corp.acme.com", &Sid5, L"CORP_NB4" },
  402. { 0, EOD },
  403. };
  404. AN_ENTRY Ftinfo21[] = {
  405. { 0, TLN, L"acme.com" },
  406. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  407. { LSA_SID_DISABLED_ADMIN, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  408. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  409. { LSA_SID_DISABLED_ADMIN, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB3" },
  410. { 0, DOM, L"c4.corp.acme.com", &Sid5, L"CORP_NB4" },
  411. { 0, EOD },
  412. };
  413. AN_ENTRY Ftinfo22[] = {
  414. { 0, TLN, L"acme.com" },
  415. { LSA_SID_DISABLED_ADMIN, DOM, L"ms.com", &Sid1, L"CORP_NB" },
  416. { 0, EOD },
  417. };
  418. AN_ENTRY Ftinfo23[] = {
  419. { 0, TLN, L"acme.com" },
  420. { 0, DOM, L"corp.ms.com", &Sid1, L"CORP_NB0" },
  421. { 0, DOM, L"c1.corp.ms.com", &Sid2, L"CORP_NB1" },
  422. { 0, DOM, L"c2.corp.ms.com", &Sid3, L"CORP_NB2" },
  423. { 0, EOD },
  424. };
  425. AN_ENTRY Ftinfo24[] = {
  426. { 0, TLN, L"acme.com" },
  427. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  428. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  429. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  430. { 0, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB3" },
  431. { 0, EOD },
  432. };
  433. AN_ENTRY Ftinfo24a[] = {
  434. { 0, TLN, L"acme.com" },
  435. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  436. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  437. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  438. { 0, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB3" },
  439. { LSA_NB_DISABLED_ADMIN, DOM, L"c4.corp.acme.com", &Sid5, L"CORP_NB4" },
  440. { 0, EOD },
  441. };
  442. AN_ENTRY Ftinfo24b[] = {
  443. { 0, TLN, L"acme.com" },
  444. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  445. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  446. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB2" },
  447. { 0, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB3" },
  448. { LSA_NB_DISABLED_CONFLICT, DOM, L"c4.corp.acme.com", &Sid5, L"CORP_NB4" },
  449. { 0, EOD },
  450. };
  451. AN_ENTRY Ftinfo24c[] = {
  452. { 0, TLN, L"acme.com" },
  453. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  454. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  455. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB3" },
  456. { LSA_NB_DISABLED_ADMIN|LSA_NB_DISABLED_CONFLICT, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB2" },
  457. { 0, EOD },
  458. };
  459. AN_ENTRY Ftinfo24d[] = {
  460. { 0, TLN, L"acme.com" },
  461. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  462. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  463. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB3" },
  464. { 0xFFFFFFFF, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB2" },
  465. { 0, EOD },
  466. };
  467. AN_ENTRY Ftinfo24e[] = {
  468. { 0, TLN, L"acme.com" },
  469. { 0, DOM, L"corp.acme.com", &Sid1, L"CORP_NB0" },
  470. { 0, DOM, L"c1.corp.acme.com", &Sid2, L"CORP_NB1" },
  471. { 0, DOM, L"c2.corp.acme.com", &Sid3, L"CORP_NB3" },
  472. { 0, DOM, L"c3.corp.acme.com", &Sid4, L"CORP_NB2" },
  473. { 0, EOD },
  474. };
  475. //
  476. // Structure describine test cases
  477. //
  478. typedef struct _TEST_CASE {
  479. PAN_ENTRY OldFtinfo;
  480. #define PREVIOUS ((PAN_ENTRY) 1)
  481. PAN_ENTRY NewFtinfo;
  482. LPSTR Description;
  483. } TEST_CASE, PTEST_CASE;
  484. //
  485. // Define the test cases
  486. //
  487. TEST_CASE TestCases[] = {
  488. { NULL, Ftinfo0, "Just acme.com TLN" },
  489. { NULL, Ftinfo1, "acme.com and ms.com TLN" },
  490. { NULL, Ftinfo2, "Same but switch the alphabetical order" },
  491. { NULL, Ftinfo3, "Have no TLN for the forest (Should fail w/ ERROR_INVALID_PARAMETER)" },
  492. { NULL, Ftinfo0, "Build acme.com again" },
  493. { PREVIOUS, Ftinfo1, "Add a new ms.com TLN" },
  494. { PREVIOUS, Ftinfo1, "Ensure the new bit doesn't go away" },
  495. { NULL, Ftinfo4, "Exact match on corp.acme.com TLN" },
  496. { NULL, Ftinfo5, "Only child of corp.acme.com TLN (Should fail w/ ERROR_INVALID_PARAMETER)" },
  497. { Ftinfo6, Ftinfo1, "Ensure a disabled TLN stays disabled" },
  498. { Ftinfo7, Ftinfo1, "Ensure all bits are preserved in a TLN" },
  499. { Ftinfo8, Ftinfo10, "Ensure a disabled TLN stays disabled in a child" },
  500. { Ftinfo9, Ftinfo10, "Ensure a disabled TLN does *not* disable a parent" },
  501. { NULL, Ftinfo11, "Ensure a TLNEX is ignored in new" },
  502. { Ftinfo11, Ftinfo0, "Ensure a TLNEX is copied from old" },
  503. { NULL, Ftinfo12, "Trivial single domain forest" },
  504. { Ftinfo13, Ftinfo12, "Ensure a disabled domain remains disabled" },
  505. { NULL, Ftinfo14, "Drop duplicate new TLN entries" },
  506. { NULL, Ftinfo15, "... even if the duplicate is subordinate" },
  507. { NULL, Ftinfo16, "... even if there are many of them" },
  508. { NULL, Ftinfo17, "Try multiple domain entries" },
  509. { NULL, Ftinfo18, "Duplicate Sids are bad" },
  510. { NULL, Ftinfo19, "... even if there are many of them" },
  511. { Ftinfo21, Ftinfo20, "Ensure multiple disabled domains remain disabled" },
  512. { Ftinfo13, Ftinfo0, "Don't let an old disabled domain entry go away" },
  513. { Ftinfo22, Ftinfo0, "... even if there's no TLN for the domain entry" },
  514. { Ftinfo17, Ftinfo20, "Add a new domain" },
  515. { Ftinfo20, Ftinfo17, "Delete old domains" },
  516. { NULL, Ftinfo23, "Ensure there's a TLN for every domain" },
  517. { Ftinfo13a,Ftinfo12, "Ensure all of the possible flag bits are preserved" },
  518. { Ftinfo24a,Ftinfo24, "Ensure that a netbios admin disabled bit doesn't disappear" },
  519. { Ftinfo24b,Ftinfo24, "... but that a netbios conflict does" },
  520. { Ftinfo24c,Ftinfo24, "... Get it right even if the NB entry moves to different sid" },
  521. { Ftinfo24d,Ftinfo24, "... and that all of the other flag bits stay put" },
  522. { PREVIOUS, Ftinfo24e,"... and that we self repait when the trusted domain stops lying" },
  523. };
  524. PLSA_FOREST_TRUST_INFORMATION
  525. BuildFtinfo(
  526. PAN_ENTRY AnEntry
  527. )
  528. /*++
  529. Routine Description:
  530. Builds a FtInfo array from the "easy to initialize" templates.
  531. Arguments:
  532. AnEntry - Pointer to the first entry.
  533. Return Value:
  534. Returns a real ftinfo array.
  535. If this weren't a cheesy test program, the caller should free this memory.
  536. --*/
  537. {
  538. PAN_ENTRY CurrentEntry;
  539. ULONG CurrentIndex;
  540. PLSA_FOREST_TRUST_INFORMATION Ftinfo;
  541. //
  542. // NULL is OK
  543. //
  544. if ( AnEntry == NULL ) {
  545. return NULL;
  546. }
  547. //
  548. // Allocate the return array
  549. //
  550. Ftinfo = LocalAlloc( 0, sizeof(*Ftinfo) );
  551. if ( Ftinfo == NULL ) {
  552. printf( "No memory\n");
  553. return NULL;
  554. }
  555. //
  556. // Count the number of entries
  557. //
  558. Ftinfo->RecordCount = 0;
  559. for ( CurrentEntry=AnEntry;
  560. CurrentEntry->ForestTrustType != EOD;
  561. CurrentEntry++ ) {
  562. Ftinfo->RecordCount ++;
  563. }
  564. //
  565. // Allocate the array of entry pointers.
  566. //
  567. Ftinfo->Entries = LocalAlloc( 0, sizeof(PLSA_FOREST_TRUST_RECORD) * Ftinfo->RecordCount );
  568. if ( Ftinfo->Entries == NULL ) {
  569. printf( "No memory\n");
  570. return NULL;
  571. }
  572. //
  573. // Loop through the entries.
  574. //
  575. CurrentIndex = 0;
  576. for ( CurrentEntry=AnEntry;
  577. CurrentEntry->ForestTrustType != EOD;
  578. CurrentEntry++ ) {
  579. //
  580. // Allocate the entry
  581. //
  582. Ftinfo->Entries[CurrentIndex] = LocalAlloc( LMEM_ZEROINIT, sizeof(LSA_FOREST_TRUST_RECORD) );
  583. if ( Ftinfo->Entries[CurrentIndex] == NULL ) {
  584. printf( "No memory\n");
  585. return NULL;
  586. }
  587. //
  588. // Fill it in
  589. //
  590. Ftinfo->Entries[CurrentIndex]->ForestTrustType = CurrentEntry->ForestTrustType;
  591. Ftinfo->Entries[CurrentIndex]->Flags = CurrentEntry->Flags;
  592. switch ( CurrentEntry->ForestTrustType ) {
  593. case TLN:
  594. case TLNEX:
  595. RtlInitUnicodeString(
  596. &Ftinfo->Entries[CurrentIndex]->ForestTrustData.TopLevelName,
  597. CurrentEntry->Name );
  598. break;
  599. case DOM:
  600. RtlInitUnicodeString(
  601. &Ftinfo->Entries[CurrentIndex]->ForestTrustData.DomainInfo.DnsName,
  602. CurrentEntry->Name );
  603. Ftinfo->Entries[CurrentIndex]->ForestTrustData.DomainInfo.Sid =
  604. CurrentEntry->Sid;
  605. RtlInitUnicodeString(
  606. &Ftinfo->Entries[CurrentIndex]->ForestTrustData.DomainInfo.NetbiosName,
  607. CurrentEntry->NetbiosName );
  608. break;
  609. default:
  610. printf( "Bad forest trust type\n");
  611. return NULL;
  612. }
  613. CurrentIndex ++;
  614. }
  615. return Ftinfo;
  616. }
  617. int __cdecl
  618. main (
  619. IN int argc,
  620. IN char ** argv
  621. )
  622. {
  623. NET_API_STATUS NetStatus;
  624. PLSA_FOREST_TRUST_INFORMATION OldFtinfo;
  625. PLSA_FOREST_TRUST_INFORMATION NewFtinfo;
  626. PLSA_FOREST_TRUST_INFORMATION OutputFtinfo = NULL;
  627. ULONG CaseIndex;
  628. ULONG FirstIndex = 0;
  629. //
  630. // If an argument is specified,
  631. // it is the test number to start with.
  632. //
  633. if ( argc > 1 ) {
  634. char *end;
  635. FirstIndex = strtoul( argv[1], &end, 10 );
  636. }
  637. //
  638. // Loop through the list of tests
  639. //
  640. for ( CaseIndex=FirstIndex; CaseIndex<(sizeof(TestCases)/sizeof(TestCases[0])); CaseIndex++ ) {
  641. printf( "\nCase %ld: %s\n", CaseIndex, TestCases[CaseIndex].Description );
  642. //
  643. // Build the test case FTINFO structures
  644. //
  645. if ( TestCases[CaseIndex].OldFtinfo == PREVIOUS ) {
  646. OldFtinfo = OutputFtinfo;
  647. } else {
  648. OldFtinfo = BuildFtinfo( TestCases[CaseIndex].OldFtinfo );
  649. }
  650. NewFtinfo = BuildFtinfo( TestCases[CaseIndex].NewFtinfo );
  651. //
  652. // Display them
  653. //
  654. printf(" Old Ftinfo:\n");
  655. DumpFtinfo( OldFtinfo );
  656. printf(" New Ftinfo:\n");
  657. DumpFtinfo( NewFtinfo );
  658. //
  659. // Merge them
  660. //
  661. NetStatus = DsMergeForestTrustInformationW( L"corp.acme.com",
  662. NewFtinfo,
  663. OldFtinfo,
  664. &OutputFtinfo );
  665. if ( NetStatus != NERR_Success ) {
  666. printf( "DsMergeForestTrustInformationW failed: ");
  667. PrintStatus( NetStatus );
  668. } else {
  669. printf(" Result Ftinfo:\n");
  670. DumpFtinfo( OutputFtinfo );
  671. }
  672. }
  673. printf("\n\nYee haw. We're done.\n");
  674. return 0;
  675. }