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.

5021 lines
141 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. dstree.cxx
  5. Abstract:
  6. This module is a development tool. It creates dummy entries in the DS.
  7. The file replication service treats the dummy entries as a topology.
  8. Without this tool, creating interesting topologies would require many
  9. more machines than I have on hand.
  10. The command is run as, "dstree <command-file". command-file is a list
  11. of command lines and comment lines.
  12. Command lines are read from standard in, parsed, and then shipped
  13. off to the command subroutines. The command line syntax is:
  14. command,site,settings,server,connection,fromserver
  15. "command" is any of add|delete|list|show|quit. Leading whitespace is
  16. ignored. Whitespace between commas counts. The comma separated strings
  17. following "command" are optional. The command line can stop anytime
  18. after "command" and the command will on be applied to that portion
  19. of the "Distinquished Name".
  20. Comment lines are empty lines or lines that begin with /, #, or !.
  21. The files dstree.add and dstree.del are command files. They create
  22. and delete a bogus topology.
  23. Author:
  24. Billy J. Fuller 3-Mar-1997 (From Jim McNelis)
  25. Environment
  26. User mode winnt
  27. --*/
  28. #include <ntreppch.h>
  29. #pragma hdrstop
  30. #include <frs.h>
  31. #include <lmcons.h>
  32. #include <lmapibuf.h>
  33. #include <winsock2.h>
  34. #include <ntdsapi.h>
  35. #define FREE(_x_) { if (_x_) free(_x_); _x_ = NULL; }
  36. //
  37. // Some useful DS object classes and object attributes
  38. // that are not included in frs.h
  39. //
  40. #define CN_TEST_SETTINGS L"NTFRS Test Settings"
  41. #define ATTR_SYSTEM_FLAGS L"systemFlags"
  42. #define ATTR_SYSTEM_MAY_CONTAIN L"systemMayContain"
  43. #define ATTR_SYSTEM_MUST_CONTAIN L"systemMustContain"
  44. #define ATTR_SYSTEM_POSS_SUPERIORS L"systemPossSuperiors"
  45. #define SCHEMA_NAMING_CONTEXT L"cn=schema"
  46. #define ATTR_TRUE L"TRUE"
  47. #define ATTR_OPTIONS_0 L"0"
  48. //
  49. // For DumpValues
  50. //
  51. PWCHAR GuidAttrs[] = {
  52. L"objectGUID",
  53. L"schemaIDGUID",
  54. L"frsVersionGUID",
  55. NULL
  56. };
  57. PWCHAR BerAttrs[] = {
  58. L"replPropertyMetaData",
  59. L"invocationId",
  60. L"defaultSecurityDescriptor",
  61. L"objectSid",
  62. L"lmPwdHistory",
  63. L"ntPwdHistory",
  64. L"oMObjectClass",
  65. NULL
  66. };
  67. //
  68. // For HammerSchema
  69. //
  70. struct AlterAttr {
  71. PWCHAR Attr;
  72. PWCHAR Value;
  73. };
  74. struct AlterClass {
  75. PWCHAR Cn;
  76. struct AlterAttr AlterAttrs[32];
  77. };
  78. struct AlterClass Computer = {
  79. L"Computer",
  80. L"mayContain", L"frsComputerReferenceBL",
  81. NULL, NULL
  82. };
  83. struct AlterClass NtFrsSettings = {
  84. L"NTFRS-Settings",
  85. L"possSuperiors", L"container",
  86. L"possSuperiors", L"organization",
  87. L"possSuperiors", L"organizationalUnit",
  88. L"mayContain", L"managedBy",
  89. L"mayContain", L"frsExtensions",
  90. NULL, NULL
  91. };
  92. struct AlterClass NtFrsReplicaSet = {
  93. L"NTFRS-Replica-Set",
  94. L"mayContain", L"frsVersionGuid",
  95. L"mayContain", L"FrsReplicaSetGuid",
  96. L"mayContain", L"frsPrimaryMember",
  97. L"mayContain", L"managedBy",
  98. L"mayContain", L"frsReplicaSetType",
  99. L"mayContain", L"frsDirectoryFilter",
  100. L"mayContain", L"frsDSPoll",
  101. L"mayContain", L"frsExtensions",
  102. L"mayContain", L"frsFileFilter",
  103. L"mayContain", L"frsFlags",
  104. L"mayContain", L"frsLevelLimit",
  105. L"mayContain", L"frsPartnerAuthLevel",
  106. L"mayContain", L"frsRootSecurity",
  107. L"mayContain", L"frsServiceCommand",
  108. NULL, NULL
  109. };
  110. struct AlterClass NtDsConnection = {
  111. L"NTDS-Connection",
  112. L"possSuperiors", L"nTFRSMember",
  113. NULL, NULL
  114. };
  115. struct AlterClass Dump = {
  116. L"Server-Reference",
  117. L"systemFlags", L"",
  118. NULL, NULL
  119. };
  120. //
  121. // ATTRIBUTES
  122. //
  123. struct AlterClass FrsExtensions = {
  124. L"Frs-Extensions",
  125. L"cn", L"Frs-Extensions",
  126. L"adminDisplayName", L"Frs-Extensions",
  127. L"adminDescription", L"Frs-Extensions",
  128. L"lDAPDisplayName", L"frsExtensions",
  129. L"objectClass", L"attributeSchema",
  130. L"attributeId", L"1.2.840.113556.1.4.7000.82",
  131. L"oMSyntax", L"4",
  132. L"attributeSyntax", L"2.5.5.10",
  133. L"isSingleValued", L"TRUE",
  134. L"systemOnly", L"FALSE",
  135. L"rangeLower", L"1",
  136. L"rangeUpper", L"65536",
  137. L"hideFromAB", L"TRUE",
  138. NULL, NULL
  139. };
  140. struct AlterClass FrsVersionGuid = {
  141. L"Frs-Version-GUID",
  142. L"cn", L"Frs-Version-GUID",
  143. L"adminDisplayName", L"Frs-Version-GUID",
  144. L"adminDescription", L"Frs-Version-GUID",
  145. L"lDAPDisplayName", L"frsVersionGUID",
  146. L"objectClass", L"attributeSchema",
  147. L"attributeId", L"1.2.840.113556.1.4.7000.83",
  148. L"oMSyntax", L"4",
  149. L"attributeSyntax", L"2.5.5.10",
  150. L"isSingleValued", L"TRUE",
  151. L"systemOnly", L"FALSE",
  152. L"hideFromAB", L"TRUE",
  153. NULL, NULL
  154. };
  155. struct AlterClass FrsReplicaSetGuid = {
  156. L"Frs-Replica-Set-GUID",
  157. L"cn", L"Frs-Replica-Set-GUID",
  158. L"adminDisplayName", L"Frs-Replica-Set-GUID",
  159. L"adminDescription", L"Frs-Replica-Set-GUID",
  160. L"lDAPDisplayName", L"frsReplicaSetGUID",
  161. L"objectClass", L"attributeSchema",
  162. L"attributeId", L"1.2.840.113556.1.4.7000.84",
  163. L"oMSyntax", L"4",
  164. L"attributeSyntax", L"2.5.5.10",
  165. L"isSingleValued", L"TRUE",
  166. L"systemOnly", L"FALSE",
  167. L"rangeLower", L"16",
  168. L"rangeUpper", L"16",
  169. L"hideFromAB", L"TRUE",
  170. NULL, NULL
  171. };
  172. struct AlterClass FrsDsPoll = {
  173. L"Frs-DS-Poll",
  174. L"cn", L"Frs-DS-Poll",
  175. L"adminDisplayName", L"Frs-DS-Poll",
  176. L"adminDescription", L"Frs-DS-Poll",
  177. L"lDAPDisplayName", L"frsDSPoll",
  178. L"objectClass", L"attributeSchema",
  179. L"attributeId", L"1.2.840.113556.1.4.7000.85",
  180. L"oMSyntax", L"2",
  181. L"attributeSyntax", L"2.5.5.9",
  182. L"isSingleValued", L"TRUE",
  183. L"systemOnly", L"FALSE",
  184. L"hideFromAB", L"TRUE",
  185. NULL, NULL
  186. };
  187. //
  188. // replica set types
  189. //
  190. struct AlterClass FrsReplicaSetType = {
  191. L"Frs-Replica-Set-Type",
  192. L"cn", L"Frs-Replica-Set-Type",
  193. L"adminDisplayName", L"Frs-Replica-Set-Type",
  194. L"adminDescription", L"Frs-Replica-Set-Type",
  195. L"lDAPDisplayName", L"frsReplicaSetType",
  196. L"objectClass", L"attributeSchema",
  197. L"attributeId", L"1.2.840.113556.1.4.7000.86",
  198. L"oMSyntax", L"2",
  199. L"attributeSyntax", L"2.5.5.9",
  200. L"isSingleValued", L"TRUE",
  201. L"systemOnly", L"FALSE",
  202. L"hideFromAB", L"TRUE",
  203. NULL, NULL
  204. };
  205. struct AlterClass FrsDirectoryFilter = {
  206. L"Frs-Directory-Filter",
  207. L"cn", L"Frs-Directory-Filter",
  208. L"adminDisplayName", L"Frs-Directory-Filter",
  209. L"adminDescription", L"bjf l;kjlkj xyz",
  210. L"lDAPDisplayName", L"frsDirectoryFilter",
  211. L"objectClass", L"attributeSchema",
  212. L"attributeId", L"1.2.840.113556.1.4.7000.87",
  213. L"oMSyntax", L"64",
  214. L"attributeSyntax", L"2.5.5.12",
  215. L"isSingleValued", L"TRUE",
  216. L"systemOnly", L"FALSE",
  217. L"rangeLower", L"1",
  218. L"rangeUpper", L"1024",
  219. L"hideFromAB", L"TRUE",
  220. NULL, NULL
  221. };
  222. //
  223. // OIDs out of sequence
  224. //
  225. struct AlterClass FrsControlDataCreation = {
  226. L"Frs-Control-Data-Creation",
  227. L"cn", L"Frs-Control-Data-Creation",
  228. L"adminDisplayName", L"Frs-Control-Data-Creation",
  229. L"adminDescription", L"bob",
  230. L"lDAPDisplayName", L"frsControlDataCreation",
  231. L"objectClass", L"attributeSchema",
  232. L"attributeId", L"1.2.840.113556.1.4.7002.00",
  233. L"oMSyntax", L"64",
  234. L"attributeSyntax", L"2.5.5.12",
  235. L"isSingleValued", L"TRUE",
  236. L"systemOnly", L"FALSE",
  237. L"rangeLower", L"0",
  238. L"rangeUpper", L"32",
  239. L"hideFromAB", L"TRUE",
  240. NULL, NULL
  241. };
  242. struct AlterClass FrsControlInboundBacklog = {
  243. L"Frs-Control-Inbound-Backlog",
  244. L"cn", L"Frs-Control-Inbound-Backlog",
  245. L"adminDisplayName", L"Frs-Control-Inbound-Backlog",
  246. L"adminDescription", L"george",
  247. L"lDAPDisplayName", L"frsControlInboundBacklog",
  248. L"objectClass", L"attributeSchema",
  249. L"attributeId", L"1.2.840.113556.1.4.7002.01",
  250. L"oMSyntax", L"64",
  251. L"attributeSyntax", L"2.5.5.12",
  252. L"isSingleValued", L"TRUE",
  253. L"systemOnly", L"FALSE",
  254. L"rangeLower", L"0",
  255. L"rangeUpper", L"32",
  256. L"hideFromAB", L"TRUE",
  257. NULL, NULL
  258. };
  259. struct AlterClass FrsControlOutboundBacklog = {
  260. L"Frs-Control-Outbound-Backlog",
  261. L"cn", L"Frs-Control-Outbound-Backlog",
  262. L"adminDisplayName", L"Frs-Control-Outbound-Backlog",
  263. L"adminDescription", L"Frs-Control-Outbound-Backlog",
  264. L"lDAPDisplayName", L"frsControlOutboundBacklog",
  265. L"objectClass", L"attributeSchema",
  266. L"attributeId", L"1.2.840.113556.1.4.7002.02",
  267. L"oMSyntax", L"64",
  268. L"attributeSyntax", L"2.5.5.12",
  269. L"isSingleValued", L"TRUE",
  270. L"systemOnly", L"FALSE",
  271. L"rangeLower", L"0",
  272. L"rangeUpper", L"32",
  273. L"hideFromAB", L"TRUE",
  274. NULL, NULL
  275. };
  276. struct AlterClass FrsFaultCondition = {
  277. L"Frs-Fault-Condition",
  278. L"cn", L"Frs-Fault-Condition",
  279. L"adminDisplayName", L"Frs-Fault-Condition",
  280. L"adminDescription", L"Frs-Fault-Condition",
  281. L"lDAPDisplayName", L"frsFaultCondition",
  282. L"objectClass", L"attributeSchema",
  283. L"attributeId", L"1.2.840.113556.1.4.7002.03",
  284. L"oMSyntax", L"64",
  285. L"attributeSyntax", L"2.5.5.12",
  286. L"isSingleValued", L"TRUE",
  287. L"systemOnly", L"FALSE",
  288. L"rangeLower", L"1",
  289. L"rangeUpper", L"16",
  290. L"hideFromAB", L"TRUE",
  291. NULL, NULL
  292. };
  293. struct AlterClass FrsVersion = {
  294. L"Frs-Version",
  295. L"cn", L"Frs-Version",
  296. L"adminDisplayName", L"Frs-Version",
  297. L"adminDescription", L"Frs-Version",
  298. L"lDAPDisplayName", L"frsVersion",
  299. L"objectClass", L"attributeSchema",
  300. L"attributeId", L"1.2.840.113556.1.4.7002.04",
  301. L"oMSyntax", L"64",
  302. L"attributeSyntax", L"2.5.5.12",
  303. L"isSingleValued", L"TRUE",
  304. L"systemOnly", L"FALSE",
  305. L"rangeLower", L"0",
  306. L"rangeUpper", L"32",
  307. L"hideFromAB", L"TRUE",
  308. NULL, NULL
  309. };
  310. struct AlterClass FrsPrimaryMember = {
  311. L"Frs-Primary-Member",
  312. L"cn", L"Frs-Primary-Member",
  313. L"adminDisplayName", L"Frs-Primary-Member",
  314. L"adminDescription", L"Frs-Primary-Member",
  315. L"lDAPDisplayName", L"frsPrimaryMember",
  316. L"objectClass", L"attributeSchema",
  317. L"attributeId", L"1.2.840.113556.1.4.7002.05",
  318. L"oMSyntax", L"127",
  319. L"attributeSyntax", L"2.5.5.1",
  320. L"isSingleValued", L"TRUE",
  321. L"systemOnly", L"FALSE",
  322. L"systemFlags", L"2",
  323. L"linkID", L"104",
  324. L"hideFromAB", L"TRUE",
  325. NULL, NULL
  326. };
  327. //
  328. // END OIDs out of sequence
  329. //
  330. struct AlterClass FrsFileFilter = {
  331. L"Frs-File-Filter",
  332. L"cn", L"Frs-File-Filter",
  333. L"adminDisplayName", L"Frs-File-Filter",
  334. L"adminDescription", L"sue and and and",
  335. L"lDAPDisplayName", L"frsFileFilter",
  336. L"objectClass", L"attributeSchema",
  337. L"attributeId", L"1.2.840.113556.1.4.7000.88",
  338. L"oMSyntax", L"64",
  339. L"attributeSyntax", L"2.5.5.12",
  340. L"isSingleValued", L"TRUE",
  341. L"systemOnly", L"FALSE",
  342. L"rangeLower", L"1",
  343. L"rangeUpper", L"1024",
  344. L"hideFromAB", L"TRUE",
  345. NULL, NULL
  346. };
  347. struct AlterClass FrsFlags = {
  348. L"Frs-Flags",
  349. L"cn", L"Frs-Flags",
  350. L"adminDisplayName", L"Frs-Flags",
  351. L"adminDescription", L"Frs-Flags",
  352. L"lDAPDisplayName", L"frsFlags",
  353. L"objectClass", L"attributeSchema",
  354. L"attributeId", L"1.2.840.113556.1.4.7000.89",
  355. L"oMSyntax", L"2",
  356. L"attributeSyntax", L"2.5.5.9",
  357. L"isSingleValued", L"TRUE",
  358. L"systemOnly", L"FALSE",
  359. L"hideFromAB", L"TRUE",
  360. NULL, NULL
  361. };
  362. struct AlterClass FrsLevelLimit = {
  363. L"Frs-Level-Limit",
  364. L"cn", L"Frs-Level-Limit",
  365. L"adminDisplayName", L"Frs-Level-Limit",
  366. L"adminDescription", L"Frs-Level-Limit",
  367. L"lDAPDisplayName", L"frsLevelLimit",
  368. L"objectClass", L"attributeSchema",
  369. L"attributeId", L"1.2.840.113556.1.4.7000.90",
  370. L"oMSyntax", L"2",
  371. L"attributeSyntax", L"2.5.5.9",
  372. L"isSingleValued", L"TRUE",
  373. L"systemOnly", L"FALSE",
  374. L"hideFromAB", L"TRUE",
  375. NULL, NULL
  376. };
  377. struct AlterClass FrsPartnerAuthLevel = {
  378. L"Frs-Partner-Auth-Level",
  379. L"cn", L"Frs-Partner-Auth-Level",
  380. L"adminDisplayName", L"Frs-Partner-Auth-Level",
  381. L"adminDescription", L"Frs-Partner-Auth-Level",
  382. L"lDAPDisplayName", L"frsPartnerAuthLevel",
  383. L"objectClass", L"attributeSchema",
  384. L"attributeId", L"1.2.840.113556.1.4.7000.91",
  385. L"oMSyntax", L"2",
  386. L"attributeSyntax", L"2.5.5.9",
  387. L"isSingleValued", L"TRUE",
  388. L"systemOnly", L"FALSE",
  389. L"hideFromAB", L"TRUE",
  390. NULL, NULL
  391. };
  392. struct AlterClass FrsRootSecurity = {
  393. L"Frs-Root-Security",
  394. L"cn", L"Frs-Root-Security",
  395. L"adminDisplayName", L"Frs-Root-Security",
  396. L"adminDescription", L"Frs-Root-Security",
  397. L"lDAPDisplayName", L"frsRootSecurity",
  398. L"objectClass", L"attributeSchema",
  399. L"attributeId", L"1.2.840.113556.1.4.7000.92",
  400. L"oMSyntax", L"66",
  401. L"attributeSyntax", L"2.5.5.15",
  402. L"isSingleValued", L"TRUE",
  403. L"systemOnly", L"FALSE",
  404. L"hideFromAB", L"TRUE",
  405. NULL, NULL
  406. };
  407. struct AlterClass FrsServiceCommand = {
  408. L"Frs-Service-Command",
  409. L"cn", L"Frs-Service-Command",
  410. L"adminDisplayName", L"Frs-Service-Command",
  411. L"adminDescription", L"Frs-Service-Command",
  412. L"lDAPDisplayName", L"frsServiceCommand",
  413. L"objectClass", L"attributeSchema",
  414. L"attributeId", L"1.2.840.113556.1.4.7000.93",
  415. L"oMSyntax", L"64",
  416. L"attributeSyntax", L"2.5.5.12",
  417. L"isSingleValued", L"TRUE",
  418. L"systemOnly", L"FALSE",
  419. L"rangeLower", L"0",
  420. L"rangeUpper", L"512",
  421. L"hideFromAB", L"TRUE",
  422. NULL, NULL
  423. };
  424. struct AlterClass FrsUpdateTimeout = {
  425. L"Frs-Update-Timeout",
  426. L"cn", L"Frs-Update-Timeout",
  427. L"adminDisplayName", L"Frs-Update-Timeout",
  428. L"adminDescription", L"Frs-Update-Timeout",
  429. L"lDAPDisplayName", L"frsUpdateTimeout",
  430. L"objectClass", L"attributeSchema",
  431. L"attributeId", L"1.2.840.113556.1.4.7000.94",
  432. L"oMSyntax", L"2",
  433. L"attributeSyntax", L"2.5.5.9",
  434. L"isSingleValued", L"TRUE",
  435. L"systemOnly", L"FALSE",
  436. L"hideFromAB", L"TRUE",
  437. NULL, NULL
  438. };
  439. struct AlterClass FrsWorkingPath = {
  440. L"Frs-Working-Path",
  441. L"cn", L"Frs-Working-Path",
  442. L"adminDisplayName", L"Frs-Working-Path",
  443. L"adminDescription", L"Frs-Working-Path",
  444. L"lDAPDisplayName", L"frsWorkingPath",
  445. L"objectClass", L"attributeSchema",
  446. L"attributeId", L"1.2.840.113556.1.4.7000.95",
  447. L"oMSyntax", L"64",
  448. L"attributeSyntax", L"2.5.5.12",
  449. L"isSingleValued", L"TRUE",
  450. L"systemOnly", L"FALSE",
  451. L"rangeLower", L"0",
  452. L"rangeUpper", L"512",
  453. L"hideFromAB", L"TRUE",
  454. NULL, NULL
  455. };
  456. struct AlterClass FrsStagingPath = {
  457. L"Frs-Staging-Path",
  458. L"cn", L"Frs-Staging-Path",
  459. L"adminDisplayName", L"Frs-Staging-Path",
  460. L"adminDescription", L"Frs-Staging-Path",
  461. L"lDAPDisplayName", L"frsStagingPath",
  462. L"objectClass", L"attributeSchema",
  463. L"attributeId", L"1.2.840.113556.1.4.7000.96",
  464. L"oMSyntax", L"64",
  465. L"attributeSyntax", L"2.5.5.12",
  466. L"isSingleValued", L"TRUE",
  467. L"systemOnly", L"FALSE",
  468. L"rangeLower", L"0",
  469. L"rangeUpper", L"512",
  470. L"hideFromAB", L"TRUE",
  471. NULL, NULL
  472. };
  473. struct AlterClass FrsServiceCommandStatus = {
  474. L"Frs-Service-Command-Status",
  475. L"cn", L"Frs-Service-Command-Status",
  476. L"adminDisplayName", L"Frs-Service-Command-Status",
  477. L"adminDescription", L"frsServiceCommandStatus",
  478. L"lDAPDisplayName", L"frsServiceCommandStatus",
  479. L"objectClass", L"attributeSchema",
  480. L"attributeId", L"1.2.840.113556.1.4.7000.98",
  481. L"oMSyntax", L"64",
  482. L"attributeSyntax", L"2.5.5.12",
  483. L"isSingleValued", L"TRUE",
  484. L"systemOnly", L"FALSE",
  485. L"rangeLower", L"0",
  486. L"rangeUpper", L"512",
  487. L"hideFromAB", L"TRUE",
  488. NULL, NULL
  489. };
  490. struct AlterClass FrsTimeLastCommand = {
  491. L"Frs-Time-Last-Command",
  492. L"cn", L"Frs-Time-Last-Command",
  493. L"adminDisplayName", L"Frs-Time-Last-Command",
  494. L"adminDescription", L"Frs-Time-Last-Command",
  495. L"lDAPDisplayName", L"frsTimeLastCommand",
  496. L"objectClass", L"attributeSchema",
  497. L"attributeId", L"1.2.840.113556.1.4.7000.99",
  498. L"oMSyntax", L"23",
  499. L"attributeSyntax", L"2.5.5.11",
  500. L"isSingleValued", L"TRUE",
  501. L"systemOnly", L"FALSE",
  502. L"hideFromAB", L"TRUE",
  503. NULL, NULL
  504. };
  505. struct AlterClass FrsTimeLastConfigChange = {
  506. L"Frs-Time-Last-Config-Change",
  507. L"cn", L"Frs-Time-Last-Config-Change",
  508. L"adminDisplayName", L"Frs-Time-Last-Config-Change",
  509. L"adminDescription", L"Frs-Time-Last-Config-Change",
  510. L"lDAPDisplayName", L"frsTimeLastConfigChange",
  511. L"objectClass", L"attributeSchema",
  512. L"attributeId", L"1.2.840.113556.1.4.7001.01",
  513. L"oMSyntax", L"23",
  514. L"attributeSyntax", L"2.5.5.11",
  515. L"isSingleValued", L"TRUE",
  516. L"systemOnly", L"FALSE",
  517. L"hideFromAB", L"TRUE",
  518. NULL, NULL
  519. };
  520. struct AlterClass FrsRootPath = {
  521. L"Frs-Root-Path",
  522. L"cn", L"Frs-Root-Path",
  523. L"adminDisplayName", L"Frs-Root-Path",
  524. L"adminDescription", L"Frs-Root-Path",
  525. L"lDAPDisplayName", L"frsRootPath",
  526. L"objectClass", L"attributeSchema",
  527. L"attributeId", L"1.2.840.113556.1.4.7001.02",
  528. L"oMSyntax", L"64",
  529. L"attributeSyntax", L"2.5.5.12",
  530. L"isSingleValued", L"TRUE",
  531. L"systemOnly", L"FALSE",
  532. L"rangeLower", L"0",
  533. L"rangeUpper", L"512",
  534. L"hideFromAB", L"TRUE",
  535. NULL, NULL
  536. };
  537. struct AlterClass FrsComputerReference = {
  538. L"Frs-Computer-Reference",
  539. L"cn", L"Frs-Computer-Reference",
  540. L"adminDisplayName", L"Frs-Computer-Reference",
  541. L"adminDescription", L"Frs-Computer-Reference",
  542. L"lDAPDisplayName", L"frsComputerReference",
  543. L"objectClass", L"attributeSchema",
  544. L"attributeId", L"1.2.840.113556.1.4.7001.03",
  545. L"oMSyntax", L"127",
  546. L"attributeSyntax", L"2.5.5.1",
  547. L"isSingleValued", L"TRUE",
  548. L"systemOnly", L"FALSE",
  549. L"systemFlags", L"2",
  550. L"linkID", L"100",
  551. L"hideFromAB", L"TRUE",
  552. NULL, NULL
  553. };
  554. struct AlterClass FrsComputerReferenceBl = {
  555. L"Frs-Computer-Reference-BL",
  556. L"cn", L"Frs-Computer-Reference-BL",
  557. L"adminDisplayName", L"Frs-Computer-Reference-BL",
  558. L"adminDescription", L"Frs-Computer-Reference-BL",
  559. L"lDAPDisplayName", L"frsComputerReferenceBL",
  560. L"objectClass", L"attributeSchema",
  561. L"attributeId", L"1.2.840.113556.1.4.7001.04",
  562. L"oMSyntax", L"127",
  563. L"attributeSyntax", L"2.5.5.1",
  564. L"isSingleValued", L"FALSE",
  565. L"systemOnly", L"FALSE",
  566. L"linkID", L"101",
  567. L"hideFromAB", L"TRUE",
  568. NULL, NULL
  569. };
  570. struct AlterClass FrsMemberReference = {
  571. L"Frs-Member-Reference",
  572. L"cn", L"Frs-Member-Reference",
  573. L"adminDisplayName", L"Frs-Member-Reference",
  574. L"adminDescription", L"Frs-Member-Reference",
  575. L"lDAPDisplayName", L"frsMemberReference",
  576. L"objectClass", L"attributeSchema",
  577. L"attributeId", L"1.2.840.113556.1.4.7001.05",
  578. L"oMSyntax", L"127",
  579. L"attributeSyntax", L"2.5.5.1",
  580. L"isSingleValued", L"TRUE",
  581. L"systemOnly", L"FALSE",
  582. L"systemFlags", L"2",
  583. L"linkID", L"102",
  584. L"hideFromAB", L"TRUE",
  585. NULL, NULL
  586. };
  587. struct AlterClass FrsMemberReferenceBl = {
  588. L"Frs-Member-Reference-BL",
  589. L"cn", L"Frs-Member-Reference-BL",
  590. L"adminDisplayName", L"Frs-Member-Reference-BL",
  591. L"adminDescription", L"Frs-Member-Reference-BL",
  592. L"lDAPDisplayName", L"frsMemberReferenceBL",
  593. L"objectClass", L"attributeSchema",
  594. L"attributeId", L"1.2.840.113556.1.4.7001.06",
  595. L"oMSyntax", L"127",
  596. L"attributeSyntax", L"2.5.5.1",
  597. L"isSingleValued", L"TRUE",
  598. L"systemOnly", L"FALSE",
  599. L"linkID", L"103",
  600. L"hideFromAB", L"TRUE",
  601. NULL, NULL
  602. };
  603. //
  604. // CLASSES
  605. //
  606. struct AlterClass NtFrsMember = {
  607. L"NTFRS-Member",
  608. L"cn", L"NTFRS-Member",
  609. L"adminDisplayName", L"NTFRS-Member",
  610. L"adminDescription", L"NTFRS-Member",
  611. L"lDAPDisplayName", L"nTFRSMember",
  612. L"objectClass", L"classSchema",
  613. L"rDNAttID", L"cn",
  614. L"defaultHidingValue", L"TRUE",
  615. L"hideFromAB", L"TRUE",
  616. L"subClassOf", L"leaf",
  617. L"systemOnly", L"FALSE",
  618. L"governsId", L"1.2.840.113556.1.4.7001.07",
  619. L"objectClassCategory", L"1",
  620. NULL, NULL
  621. };
  622. struct AlterClass NtFrsSubscriptions = {
  623. L"NTFRS-Subscriptions",
  624. L"cn", L"NTFRS-Subscriptions",
  625. L"adminDisplayName", L"NTFRS-Subscriptions",
  626. L"adminDescription", L"NTFRS-Subscriptions",
  627. L"lDAPDisplayName", L"nTFRSSubscriptions",
  628. L"objectClass", L"classSchema",
  629. L"rDNAttID", L"cn",
  630. L"defaultHidingValue", L"TRUE",
  631. L"hideFromAB", L"TRUE",
  632. L"subClassOf", L"leaf",
  633. L"systemOnly", L"FALSE",
  634. L"governsId", L"1.2.840.113556.1.4.7001.08",
  635. L"objectClassCategory", L"1",
  636. NULL, NULL
  637. };
  638. struct AlterClass NtFrsSubscriber = {
  639. L"NTFRS-Subscriber",
  640. L"cn", L"NTFRS-Subscriber",
  641. L"adminDisplayName", L"NTFRS-Subscriber",
  642. L"adminDescription", L"NTFRS-Subscriber",
  643. L"lDAPDisplayName", L"nTFRSSubscriber",
  644. L"objectClass", L"classSchema",
  645. L"rDNAttID", L"cn",
  646. L"defaultHidingValue", L"TRUE",
  647. L"hideFromAB", L"TRUE",
  648. L"subClassOf", L"leaf",
  649. L"systemOnly", L"FALSE",
  650. L"governsId", L"1.2.840.113556.1.4.7001.09",
  651. L"objectClassCategory", L"1",
  652. NULL, NULL
  653. };
  654. struct AlterClass NtFrsMemberEx = {
  655. L"NTFRS-Member",
  656. L"possSuperiors", L"nTFRSReplicaSet",
  657. L"mayContain", L"frsExtensions",
  658. L"mayContain", L"frsPartnerAuthLevel",
  659. L"mayContain", L"frsRootSecurity",
  660. L"mayContain", L"frsServiceCommand",
  661. L"mayContain", L"schedule",
  662. L"mayContain", L"frsComputerReference",
  663. L"mayContain", L"ServerReference",
  664. L"mayContain", L"frsMemberReferenceBL",
  665. L"mayContain", L"frsUpdateTimeout",
  666. L"mayContain", L"frsControlDataCreation",
  667. L"mayContain", L"frsControlInboundBacklog",
  668. L"mayContain", L"frsControlOutboundBacklog",
  669. L"mayContain", L"frsFlags",
  670. NULL, NULL
  671. };
  672. struct AlterClass NtFrsSubscriptionsEx = {
  673. L"NTFRS-Subscriptions",
  674. L"possSuperiors", L"computer",
  675. L"possSuperiors", L"nTFRSSubscriptions",
  676. L"mayContain", L"frsWorkingPath",
  677. L"mayContain", L"frsVersion",
  678. L"mayContain", L"frsExtensions",
  679. NULL, NULL
  680. };
  681. struct AlterClass NtFrsSubscriberEx = {
  682. L"NTFRS-Subscriber",
  683. L"possSuperiors", L"nTFRSSubscriptions",
  684. L"mustContain", L"frsRootPath",
  685. L"mustContain", L"frsStagingPath",
  686. L"mayContain", L"frsExtensions",
  687. L"mayContain", L"frsFlags",
  688. L"mayContain", L"frsFaultCondition",
  689. L"mayContain", L"frsMemberReference",
  690. L"mayContain", L"frsUpdateTimeout",
  691. L"mayContain", L"frsServiceCommand",
  692. L"mayContain", L"frsServiceCommandStatus",
  693. L"mayContain", L"schedule",
  694. L"mayContain", L"frsTimeLastCommand",
  695. L"mayContain", L"frsTimeLastConfigChange",
  696. NULL, NULL
  697. };
  698. //
  699. // CREATE ATTRIBUTES
  700. //
  701. struct AlterClass *CreateAttributes[] = {
  702. &FrsExtensions,
  703. &FrsVersionGuid,
  704. &FrsReplicaSetGuid,
  705. &FrsDsPoll,
  706. &FrsReplicaSetType,
  707. &FrsDirectoryFilter,
  708. &FrsFileFilter,
  709. &FrsFlags,
  710. &FrsLevelLimit,
  711. &FrsPartnerAuthLevel,
  712. &FrsRootSecurity,
  713. &FrsServiceCommand,
  714. &FrsUpdateTimeout,
  715. &FrsWorkingPath,
  716. &FrsStagingPath,
  717. &FrsServiceCommandStatus,
  718. &FrsTimeLastCommand,
  719. &FrsTimeLastConfigChange,
  720. &FrsRootPath,
  721. &FrsComputerReference,
  722. &FrsComputerReferenceBl,
  723. &FrsMemberReference,
  724. &FrsMemberReferenceBl,
  725. &FrsControlDataCreation,
  726. &FrsControlInboundBacklog,
  727. &FrsControlOutboundBacklog,
  728. &FrsFaultCondition,
  729. &FrsVersion,
  730. &FrsPrimaryMember,
  731. NULL
  732. };
  733. //
  734. // CREATE CLASSES
  735. //
  736. struct AlterClass *CreateClasses[] = {
  737. &NtFrsMember,
  738. &NtFrsSubscriptions,
  739. &NtFrsSubscriber,
  740. NULL
  741. };
  742. //
  743. // ALTER EXISTING CLASSES
  744. //
  745. struct AlterClass *AlterSchema[] = {
  746. &Computer,
  747. &NtFrsSettings,
  748. &NtFrsReplicaSet,
  749. &NtDsConnection,
  750. &NtFrsMemberEx,
  751. &NtFrsSubscriptionsEx,
  752. &NtFrsSubscriberEx,
  753. NULL
  754. };
  755. PWCHAR
  756. MakeRdn(
  757. IN PWCHAR DN
  758. )
  759. /*++
  760. Routine Description:
  761. Extract the base component (relative distinguished name) from a
  762. distinguished name. The distinguished name is assumed to be in
  763. DS format (CN=xyz,CN=next one,...). In this case, the returned
  764. RDN is "xyz".
  765. Arguments:
  766. DN - distinguished name
  767. Return Value:
  768. A zero-terminated string. The string is freed with FREE_NO_HEADER().
  769. --*/
  770. {
  771. DWORD RDNLen;
  772. PWCHAR RDN;
  773. if (DN == NULL) {
  774. return NULL;
  775. }
  776. // Skip the first CN=; if any
  777. RDN = wcsstr(DN, L"CN=");
  778. if (RDN == DN)
  779. DN += 3;
  780. // Return the string up to the first delimiter or EOS
  781. RDNLen = wcscspn(DN, L",");
  782. RDN = (PWCHAR)malloc(sizeof(WCHAR) * (RDNLen + 1));
  783. wcsncpy(RDN, DN, RDNLen);
  784. RDN[RDNLen] = L'\0';
  785. return RDN;
  786. }
  787. PWCHAR
  788. FrsDsMakeParentDn(
  789. IN PWCHAR Dn
  790. )
  791. /*++
  792. Routine Description:
  793. Arguments:
  794. Return Value:
  795. --*/
  796. {
  797. DWORD PLen;
  798. if (Dn == NULL) {
  799. return NULL;
  800. }
  801. PLen = wcscspn(Dn, L",");
  802. if (Dn[PLen] != L',') {
  803. return NULL;
  804. }
  805. return FrsWcsDup(&Dn[PLen + 1]);
  806. }
  807. VOID
  808. AddMod(
  809. IN PWCHAR AttrType,
  810. IN PWCHAR AttrValue,
  811. IN OUT LDAPMod ***pppMod
  812. )
  813. /*++
  814. Routine Description:
  815. Add an attribute (plus values) to a structure that will eventually be
  816. used in an ldap_add() function to add an object to the DS. The null-
  817. terminated array referenced by pppMod grows with each call to this
  818. routine. The array is freed by the caller using FreeMod().
  819. Arguments:
  820. AttrType - The object class of the object.
  821. AttrValue - The value of the attribute.
  822. pppMod - Address of an array of pointers to "attributes". Don't
  823. give me that look -- this is an LDAP thing.
  824. Return Value:
  825. The pppMod array grows by one entry. The caller must free it with
  826. FreeMod().
  827. --*/
  828. {
  829. DWORD NumMod; // Number of entries in the Mod array
  830. LDAPMod **ppMod; // Address of the first entry in the Mod array
  831. LDAPMod *Attr; // An attribute structure
  832. PWCHAR *Values; // An array of pointers to bervals
  833. if (AttrValue == NULL)
  834. return;
  835. //
  836. // The null-terminated array doesn't exist; create it
  837. //
  838. if (*pppMod == NULL) {
  839. *pppMod = (LDAPMod **)malloc(sizeof (*pppMod));
  840. **pppMod = NULL;
  841. }
  842. //
  843. // Increase the array's size by 1
  844. //
  845. for (ppMod = *pppMod, NumMod = 2; *ppMod != NULL; ++ppMod, ++NumMod);
  846. *pppMod = (LDAPMod **)realloc(*pppMod, sizeof (*pppMod) * NumMod);
  847. //
  848. // Add the new attribute + value to the Mod array
  849. //
  850. Values = (PWCHAR *)malloc(sizeof (PWCHAR) * 2);
  851. Values[0] = _wcsdup(AttrValue);
  852. Values[1] = NULL;
  853. Attr = (LDAPMod *)malloc(sizeof (*Attr));
  854. Attr->mod_values = Values;
  855. Attr->mod_type = _wcsdup(AttrType);
  856. Attr->mod_op = LDAP_MOD_ADD;
  857. (*pppMod)[NumMod - 1] = NULL;
  858. (*pppMod)[NumMod - 2] = Attr;
  859. }
  860. VOID
  861. AddBerMod(
  862. IN PWCHAR AttrType,
  863. IN PCHAR AttrValue,
  864. IN DWORD AttrValueLen,
  865. IN OUT LDAPMod ***pppMod
  866. )
  867. /*++
  868. Routine Description:
  869. Add an attribute (plus values) to a structure that will eventually be
  870. used in an ldap_add() function to add an object to the DS. The null-
  871. terminated array referenced by pppMod grows with each call to this
  872. routine. The array is freed by the caller using FreeMod().
  873. Arguments:
  874. AttrType - The object class of the object.
  875. AttrValue - The value of the attribute.
  876. AttrValueLen - length of the attribute
  877. pppMod - Address of an array of pointers to "attributes". Don't
  878. give me that look -- this is an LDAP thing.
  879. Return Value:
  880. The pppMod array grows by one entry. The caller must free it with
  881. FreeMod().
  882. --*/
  883. {
  884. DWORD NumMod; // Number of entries in the Mod array
  885. LDAPMod **ppMod; // Address of the first entry in the Mod array
  886. LDAPMod *Attr; // An attribute structure
  887. PLDAP_BERVAL Berval;
  888. PLDAP_BERVAL *Values; // An array of pointers to bervals
  889. if (AttrValue == NULL)
  890. return;
  891. //
  892. // The null-terminated array doesn't exist; create it
  893. //
  894. if (*pppMod == NULL) {
  895. *pppMod = (LDAPMod **)malloc(sizeof (*pppMod));
  896. **pppMod = NULL;
  897. }
  898. //
  899. // Increase the array's size by 1
  900. //
  901. for (ppMod = *pppMod, NumMod = 2; *ppMod != NULL; ++ppMod, ++NumMod);
  902. *pppMod = (LDAPMod **)realloc(*pppMod, sizeof (*pppMod) * NumMod);
  903. //
  904. // Construct a berval
  905. //
  906. Berval = (PLDAP_BERVAL)malloc(sizeof(LDAP_BERVAL));
  907. Berval->bv_len = AttrValueLen;
  908. Berval->bv_val = (PCHAR)malloc(AttrValueLen);
  909. CopyMemory(Berval->bv_val, AttrValue, AttrValueLen);
  910. //
  911. // Add the new attribute + value to the Mod array
  912. //
  913. Values = (PLDAP_BERVAL *)malloc(sizeof (PLDAP_BERVAL) * 2);
  914. Values[0] = Berval;
  915. Values[1] = NULL;
  916. Attr = (LDAPMod *)malloc(sizeof (*Attr));
  917. Attr->mod_bvalues = Values;
  918. Attr->mod_type = _wcsdup(AttrType);
  919. Attr->mod_op = LDAP_MOD_BVALUES | LDAP_MOD_REPLACE;
  920. (*pppMod)[NumMod - 1] = NULL;
  921. (*pppMod)[NumMod - 2] = Attr;
  922. }
  923. VOID
  924. FreeMod(
  925. IN OUT LDAPMod ***pppMod
  926. )
  927. /*++
  928. Routine Description:
  929. Free the structure built by successive calls to AddMod().
  930. Arguments:
  931. pppMod - Address of a null-terminated array.
  932. Return Value:
  933. *pppMod set to NULL.
  934. --*/
  935. {
  936. DWORD i, j;
  937. LDAPMod **ppMod;
  938. if (!pppMod || !*pppMod) {
  939. return;
  940. }
  941. //
  942. // For each attibute
  943. //
  944. ppMod = *pppMod;
  945. for (i = 0; ppMod[i] != NULL; ++i) {
  946. //
  947. // For each value of the attribute
  948. //
  949. for (j = 0; (ppMod[i])->mod_values[j] != NULL; ++j) {
  950. //
  951. // Free the value
  952. //
  953. if (ppMod[i]->mod_op & LDAP_MOD_BVALUES) {
  954. free(ppMod[i]->mod_bvalues[j]->bv_val);
  955. }
  956. free((ppMod[i])->mod_values[j]);
  957. }
  958. free((ppMod[i])->mod_values); // Free the array of pointers to values
  959. free((ppMod[i])->mod_type); // Free the string identifying the attribute
  960. free(ppMod[i]); // Free the attribute
  961. }
  962. free(ppMod); // Free the array of pointers to attributes
  963. *pppMod = NULL; // Now ready for more calls to AddMod()
  964. }
  965. BOOL
  966. LdapSearch(
  967. IN PLDAP ldap,
  968. IN PWCHAR Base,
  969. IN ULONG Scope,
  970. IN PWCHAR Filter,
  971. IN PWCHAR Attrs[],
  972. IN ULONG AttrsOnly,
  973. IN LDAPMessage **Res,
  974. IN BOOL Quiet
  975. )
  976. /*++
  977. Routine Description:
  978. Issue the ldap ldap_search_s call, check for errors, and check for
  979. a shutdown in progress.
  980. Arguments:
  981. ldap
  982. Base
  983. Scope
  984. Filter
  985. Attrs
  986. AttrsOnly
  987. Res
  988. Return Value:
  989. The ldap array of values or NULL if the Base, DesiredAttr, or its values
  990. does not exist. The ldap array is freed with ldap_value_free().
  991. --*/
  992. {
  993. DWORD LStatus;
  994. //
  995. // Issue the ldap search
  996. //
  997. LStatus = ldap_search_s(ldap, Base, Scope, Filter, Attrs, AttrsOnly, Res);
  998. //
  999. // Check for errors
  1000. //
  1001. if (LStatus != LDAP_SUCCESS) {
  1002. if (!Quiet) {
  1003. fprintf(stderr, "WARN - Error searching %ws for %ws; LStatus %d: %ws\n",
  1004. Base, Filter, LStatus, ldap_err2string(LStatus));
  1005. }
  1006. return FALSE;
  1007. }
  1008. //
  1009. // Return TRUE if not shutting down
  1010. //
  1011. return TRUE;
  1012. }
  1013. BOOL
  1014. FrsDsVerifySchedule(
  1015. IN PWCHAR Name,
  1016. IN ULONG ScheduleLength,
  1017. IN PSCHEDULE Schedule
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. Check the schedule for consistency
  1022. Arguments:
  1023. Name
  1024. Schedule
  1025. Return Value:
  1026. None.
  1027. --*/
  1028. {
  1029. ULONG i, j;
  1030. ULONG Num;
  1031. ULONG Len;
  1032. ULONG NumType;
  1033. PUCHAR NewScheduleData;
  1034. PUCHAR OldScheduleData;
  1035. if (!Schedule) {
  1036. return TRUE;
  1037. }
  1038. //
  1039. // Too many schedules
  1040. //
  1041. Num = Schedule->NumberOfSchedules;
  1042. if (Num > 3) {
  1043. fprintf(stderr, "%ws has %d schedules\n", Name, Num);
  1044. return FALSE;
  1045. }
  1046. //
  1047. // Too few schedules
  1048. //
  1049. if (Num < 1) {
  1050. fprintf(stderr, "%ws has %d schedules\n", Name, Num);
  1051. return FALSE;
  1052. }
  1053. //
  1054. // Not enough memory
  1055. //
  1056. Len = sizeof(SCHEDULE) +
  1057. (sizeof(SCHEDULE_HEADER) * (Num - 1)) +
  1058. (SCHEDULE_DATA_BYTES * Num);
  1059. if (ScheduleLength < Len) {
  1060. fprintf(stderr, "%ws is short (ds) by %d bytes (%d - %d), %d\n",
  1061. Name,
  1062. Len - ScheduleLength,
  1063. Len,
  1064. ScheduleLength,
  1065. Schedule->Size);
  1066. return FALSE;
  1067. }
  1068. if (Schedule->Size < Len) {
  1069. fprintf(stderr, "%ws is short (size) by %d bytes (%d - %d), %d\n",
  1070. Name,
  1071. Len - Schedule->Size,
  1072. Len,
  1073. Schedule->Size,
  1074. Schedule->Size);
  1075. return FALSE;
  1076. }
  1077. Schedule->Size = Len;
  1078. //
  1079. // Invalid type
  1080. //
  1081. for (i = 0; i < Num; ++i) {
  1082. switch (Schedule->Schedules[i].Type) {
  1083. case SCHEDULE_INTERVAL:
  1084. break;
  1085. case SCHEDULE_BANDWIDTH:
  1086. break;
  1087. case SCHEDULE_PRIORITY:
  1088. break;
  1089. default:
  1090. fprintf(stderr, "%ws has an invalid schedule type (%d)\n",
  1091. Name,
  1092. Schedule->Schedules[i].Type);
  1093. return FALSE;
  1094. }
  1095. }
  1096. //
  1097. // Only 0 or 1 interval
  1098. //
  1099. for (NumType = i = 0; i < Num; ++i)
  1100. if (Schedule->Schedules[i].Type == SCHEDULE_INTERVAL)
  1101. ++NumType;
  1102. if (NumType > 1) {
  1103. fprintf(stderr, "%ws has %d interval schedules\n",
  1104. Name,
  1105. NumType);
  1106. return FALSE;
  1107. }
  1108. //
  1109. // Only 0 or 1 bandwidth
  1110. //
  1111. for (NumType = i = 0; i < Num; ++i)
  1112. if (Schedule->Schedules[i].Type == SCHEDULE_BANDWIDTH)
  1113. ++NumType;
  1114. if (NumType > 1) {
  1115. fprintf(stderr, "%ws has %d bandwidth schedules\n",
  1116. Name,
  1117. NumType);
  1118. return FALSE;
  1119. }
  1120. //
  1121. // Only 0 or 1 priority
  1122. //
  1123. for (NumType = i = 0; i < Num; ++i)
  1124. if (Schedule->Schedules[i].Type == SCHEDULE_PRIORITY)
  1125. ++NumType;
  1126. if (NumType > 1) {
  1127. fprintf(stderr, "%ws has %d priority schedules\n",
  1128. Name,
  1129. NumType);
  1130. return FALSE;
  1131. }
  1132. //
  1133. // Invalid offset
  1134. //
  1135. for (i = 0; i < Num; ++i) {
  1136. if (Schedule->Schedules[i].Offset >
  1137. ScheduleLength - SCHEDULE_DATA_BYTES) {
  1138. fprintf(stderr, "%ws has an invalid offset (%d)\n",
  1139. Name,
  1140. Schedule->Schedules[i].Offset);
  1141. return FALSE;
  1142. }
  1143. }
  1144. return TRUE;
  1145. }
  1146. VOID
  1147. PrintShortSchedule(
  1148. IN PWCHAR Indent,
  1149. IN PSCHEDULE Schedule,
  1150. IN ULONG ScheduleLen
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. Print a short form of the schedule
  1155. Arguments:
  1156. Return Value:
  1157. None.
  1158. --*/
  1159. {
  1160. ULONG i;
  1161. if (!FrsDsVerifySchedule(L"<unknown>", ScheduleLen, Schedule)) {
  1162. return;
  1163. }
  1164. if (!Schedule || !Schedule->NumberOfSchedules) {
  1165. printf("%wsSchedule=\n", Indent);
  1166. return;
  1167. }
  1168. for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
  1169. if (!i) {
  1170. printf("%wsSchedule=Type %d", Indent, Schedule->Schedules[i].Type);
  1171. } else {
  1172. printf(", %d", Schedule->Schedules[i].Type);
  1173. }
  1174. }
  1175. printf("\n");
  1176. }
  1177. VOID
  1178. PrintLongSchedule(
  1179. IN PWCHAR Indent1,
  1180. IN PWCHAR Indent2,
  1181. IN PSCHEDULE Schedule,
  1182. IN ULONG ScheduleLen
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. Print a short form of the schedule
  1187. Arguments:
  1188. Return Value:
  1189. None.
  1190. --*/
  1191. {
  1192. ULONG i;
  1193. ULONG Day;
  1194. ULONG Hour;
  1195. BOOL PrintIt;
  1196. PUCHAR ScheduleData;
  1197. if (!FrsDsVerifySchedule(L"<unknown>", ScheduleLen, Schedule)) {
  1198. return;
  1199. }
  1200. if (!Schedule || !Schedule->NumberOfSchedules) {
  1201. printf("%ws%wsSchedule=\n", Indent1, Indent2);
  1202. return;
  1203. }
  1204. for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
  1205. if (!i) {
  1206. printf("%ws%wsSchedule=Type %d",
  1207. Indent1,
  1208. Indent2,
  1209. Schedule->Schedules[i].Type);
  1210. } else {
  1211. printf(", %d", Schedule->Schedules[i].Type);
  1212. }
  1213. }
  1214. printf("\n");
  1215. for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
  1216. ScheduleData = ((PUCHAR)Schedule) + Schedule->Schedules[i].Offset;
  1217. if (Schedule->Schedules[i].Type != SCHEDULE_INTERVAL) {
  1218. continue;
  1219. }
  1220. for (Day = 0; Day < 7; ++Day) {
  1221. if (Day) {
  1222. PrintIt = FALSE;
  1223. for (Hour = 0; Hour < 24; ++Hour) {
  1224. if (*(ScheduleData + (Day * 24) + Hour) !=
  1225. *(ScheduleData + ((Day - 1) * 24) + Hour)) {
  1226. PrintIt = TRUE;
  1227. break;
  1228. }
  1229. }
  1230. } else {
  1231. PrintIt = TRUE;
  1232. }
  1233. if (!PrintIt) {
  1234. continue;
  1235. }
  1236. printf("%ws%ws Day %1d: ", Indent1, Indent2, Day + 1);
  1237. for (Hour = 0; Hour < 24; ++Hour) {
  1238. printf("%1x", *(ScheduleData + (Day * 24) + Hour) & 0x0F);
  1239. }
  1240. printf("\n");
  1241. }
  1242. printf("\n");
  1243. }
  1244. }
  1245. VOID
  1246. PrintSchedule(
  1247. IN PSCHEDULE Schedule
  1248. )
  1249. /*++
  1250. Routine Description:
  1251. Print the schedule
  1252. Arguments:
  1253. Schedule
  1254. Return Value:
  1255. None.
  1256. --*/
  1257. {
  1258. ULONG i;
  1259. if (Schedule) for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
  1260. printf(" Schedule %d\n", i);
  1261. printf(" Type : %d\n", Schedule->Schedules[i].Type);
  1262. printf(" Offset: %d\n", Schedule->Schedules[i].Offset);
  1263. }
  1264. }
  1265. PCHAR
  1266. FrsWtoA(
  1267. PWCHAR Wstr
  1268. )
  1269. /*++
  1270. Routine Description:
  1271. Translate a wide char string into a newly allocated char string.
  1272. Arguments:
  1273. Wstr - wide char string
  1274. Return Value:
  1275. Duplicated string. Free with FrsFree().
  1276. --*/
  1277. {
  1278. PCHAR Astr;
  1279. //
  1280. // E.g., when duplicating NodePartner when none exists
  1281. //
  1282. if (Wstr == NULL)
  1283. return NULL;
  1284. Astr = (PCHAR)malloc(wcslen(Wstr) + 1);
  1285. sprintf(Astr, "%ws", Wstr);
  1286. return Astr;
  1287. }
  1288. PWCHAR
  1289. FrsAtoW(
  1290. PCHAR Astr
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. Translate a wide char string into a newly allocated char string.
  1295. Arguments:
  1296. Wstr - wide char string
  1297. Return Value:
  1298. Duplicated string. Free with FrsFree().
  1299. --*/
  1300. {
  1301. PWCHAR Wstr;
  1302. //
  1303. // E.g., when duplicating NodePartner when none exists
  1304. //
  1305. if (Astr == NULL) {
  1306. return NULL;
  1307. }
  1308. Wstr = (PWCHAR)malloc((strlen(Astr) + 1) * sizeof(WCHAR));
  1309. swprintf(Wstr, L"%hs", Astr);
  1310. return Wstr;
  1311. }
  1312. PWCHAR
  1313. FrsWcsDup(
  1314. PWCHAR OldStr
  1315. )
  1316. /*++
  1317. Routine Description:
  1318. Duplicate a string using our memory allocater
  1319. Arguments:
  1320. OldArg - string to duplicate
  1321. Return Value:
  1322. Duplicated string. Free with FrsFree().
  1323. --*/
  1324. {
  1325. PWCHAR NewStr;
  1326. //
  1327. // E.g., when duplicating NodePartner when none exists
  1328. //
  1329. if (OldStr == NULL)
  1330. return NULL;
  1331. NewStr = (PWCHAR)malloc((wcslen(OldStr) + 1) * sizeof(WCHAR));
  1332. wcscpy(NewStr, OldStr);
  1333. return NewStr;
  1334. }
  1335. PWCHAR
  1336. FrsWcsCat(
  1337. PWCHAR First,
  1338. PWCHAR Second
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. Concatenate two strings into a new string using our memory allocater
  1343. Arguments:
  1344. First - First string in the concat
  1345. Second - Second string in the concat
  1346. Return Value:
  1347. Duplicated and concatentated string. Free with FrsFree().
  1348. --*/
  1349. {
  1350. DWORD Bytes;
  1351. PWCHAR New;
  1352. // size of new string
  1353. Bytes = (wcslen(First) + wcslen(Second) + 1) * sizeof(WCHAR);
  1354. New = (PWCHAR)malloc(Bytes);
  1355. // Not as efficient as I would like but this routine is seldom used
  1356. wcscpy(New, First);
  1357. wcscat(New, Second);
  1358. return New;
  1359. }
  1360. ULONG NumSchedules;
  1361. VOID
  1362. ConditionalBuildSchedule(
  1363. PSCHEDULE *Schedule,
  1364. PULONG ScheduleLength
  1365. )
  1366. /*++
  1367. Routine Description:
  1368. Build a schedule with the specified number of schedules
  1369. Arguments:
  1370. Schedule
  1371. ScheduleLength
  1372. Return Value:
  1373. Schedule or NULL. Free with free();
  1374. --*/
  1375. {
  1376. PBYTE ScheduleData;
  1377. ULONG j;
  1378. //
  1379. // No schedule, yet
  1380. //
  1381. *Schedule = NULL;
  1382. *ScheduleLength = 0;
  1383. //
  1384. // Create variable sized schedules
  1385. //
  1386. ++NumSchedules;
  1387. if (NumSchedules > 3) {
  1388. NumSchedules = 1; // shouldn't always create schedule
  1389. }
  1390. if (NumSchedules == 0) {
  1391. return;
  1392. }
  1393. //
  1394. // Construct a phoney schedule; always "on"
  1395. //
  1396. *ScheduleLength = sizeof(SCHEDULE) +
  1397. ((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
  1398. (NumSchedules * SCHEDULE_DATA_BYTES);
  1399. *Schedule = (PSCHEDULE)malloc(*ScheduleLength);
  1400. ZeroMemory(*Schedule, *ScheduleLength);
  1401. (*Schedule)->Size = *ScheduleLength;
  1402. (*Schedule)->NumberOfSchedules = NumSchedules;
  1403. (*Schedule)->Schedules[0].Type = SCHEDULE_INTERVAL;
  1404. (*Schedule)->Schedules[0].Offset = sizeof(SCHEDULE) +
  1405. ((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
  1406. (0 * SCHEDULE_DATA_BYTES);
  1407. if (NumSchedules == 1) {
  1408. goto setschedule;
  1409. }
  1410. (*Schedule)->Schedules[1].Type = SCHEDULE_PRIORITY;
  1411. (*Schedule)->Schedules[1].Offset = sizeof(SCHEDULE) +
  1412. ((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
  1413. (1 * SCHEDULE_DATA_BYTES);
  1414. if (NumSchedules == 2) {
  1415. goto setschedule;
  1416. }
  1417. (*Schedule)->Schedules[2].Type = SCHEDULE_BANDWIDTH;
  1418. (*Schedule)->Schedules[2].Offset = sizeof(SCHEDULE) +
  1419. ((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
  1420. (2 * SCHEDULE_DATA_BYTES);
  1421. if (NumSchedules == 3) {
  1422. goto setschedule;
  1423. }
  1424. setschedule:
  1425. ScheduleData = ((PBYTE)(*Schedule));
  1426. for (j = 0; j < (SCHEDULE_DATA_BYTES * NumSchedules); ++j) {
  1427. *(ScheduleData + (*Schedule)->Schedules[0].Offset + j) = 0xff;
  1428. }
  1429. }
  1430. DWORD
  1431. FrsDsGetDcInfo(
  1432. IN PDOMAIN_CONTROLLER_INFO *DcInfo,
  1433. IN DWORD Flags
  1434. )
  1435. /*++
  1436. Routine Description:
  1437. Open and bind to a dc
  1438. Arguments:
  1439. DcInfo - Dc Info
  1440. Flags - DsGetDcName(Flags)
  1441. Return Value:
  1442. DsGetDcName
  1443. --*/
  1444. {
  1445. DWORD WStatus;
  1446. WStatus = DsGetDcName(NULL, // Computer to remote to
  1447. NULL, // Domain - use our own
  1448. NULL, // Domain Guid
  1449. NULL, // Site Guid
  1450. Flags,
  1451. DcInfo); // Return info
  1452. //
  1453. // Report the error and retry for any DC
  1454. //
  1455. if (!WIN_SUCCESS(WStatus)) {
  1456. fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n", WStatus);
  1457. return WStatus;
  1458. }
  1459. printf("DCINFO for %08x:\n", Flags);
  1460. printf("\tDomainControllerName : %ws\n", (*DcInfo)->DomainControllerName);
  1461. printf("\tDomainControllerAddress: %ws\n", (*DcInfo)->DomainControllerAddress);
  1462. printf("\tDomainControllerType : %08x\n",(*DcInfo)->DomainControllerAddressType);
  1463. printf("\tDomainName : %ws\n", (*DcInfo)->DomainName);
  1464. // printf("\tForestName : %ws\n", (*DcInfo)->DnsForestName);
  1465. printf("\tDcSiteName : %ws\n", (*DcInfo)->DcSiteName);
  1466. printf("\tClientSiteName : %ws\n", (*DcInfo)->ClientSiteName);
  1467. printf("\tFlags : %08x\n",(*DcInfo)->Flags);
  1468. return WStatus;
  1469. }
  1470. PLDAP
  1471. FrsDsOpenDs(
  1472. VOID
  1473. )
  1474. /*++
  1475. Routine Description:
  1476. Open and bind to the a primary domain controller.
  1477. Arguments:
  1478. None.
  1479. Return Value:
  1480. The address of a open, bound LDAP port or NULL if the operation was
  1481. unsuccessful. The caller must free the structure with ldap_unbind().
  1482. --*/
  1483. {
  1484. DWORD WStatus;
  1485. PLDAP ldap = NULL; // ldap handle
  1486. PWCHAR DcAddr;
  1487. PWCHAR DcDnsName;
  1488. PDOMAIN_CONTROLLER_INFO DcInfo;
  1489. ULONG ulOptions;
  1490. //
  1491. // Get Info about a Global Catalogue
  1492. // Domain Controller (need the IP address)
  1493. //
  1494. // (Nope; try to live without it, Billy)
  1495. //
  1496. bugbug("FORCE_REDISCOVERY was removed per Herron")
  1497. WStatus = FrsDsGetDcInfo(&DcInfo,
  1498. DS_DIRECTORY_SERVICE_REQUIRED | // Flags
  1499. DS_WRITABLE_REQUIRED);
  1500. //
  1501. // Report the error and retry for any DC
  1502. //
  1503. if (!WIN_SUCCESS(WStatus)) {
  1504. printf("Retrying FrsDsGetDcInfo with force rediscovery\n");
  1505. FrsDsGetDcInfo(&DcInfo,
  1506. DS_DIRECTORY_SERVICE_REQUIRED | // Flags
  1507. DS_WRITABLE_REQUIRED |
  1508. DS_FORCE_REDISCOVERY);
  1509. }
  1510. if (!WIN_SUCCESS(WStatus)) {
  1511. fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n", WStatus);
  1512. }
  1513. DcAddr = DcInfo->DomainControllerAddress;
  1514. DcDnsName = DcInfo->DomainControllerName;
  1515. //
  1516. // if ldap_open is called with a server name the api will call DsGetDcName
  1517. // passing the server name as the domainname parm...bad, because
  1518. // DsGetDcName will make a load of DNS queries based on the server name,
  1519. // it is designed to construct these queries from a domain name...so all
  1520. // these queries will be bogus, meaning they will waste network bandwidth,
  1521. // time to fail, and worst case cause expensive on demand links to come up
  1522. // as referrals/forwarders are contacted to attempt to resolve the bogus
  1523. // names. By setting LDAP_OPT_AREC_EXCLUSIVE to on using ldap_set_option
  1524. // after the ldap_init but before any other operation using the ldap
  1525. // handle from ldap_init, the delayed connection setup will not call
  1526. // DsGetDcName, just gethostbyname, or if an IP is passed, the ldap client
  1527. // will detect that and use the address directly.
  1528. //
  1529. //
  1530. // DC's DNS name (w/o the leading \\)
  1531. //
  1532. if (!ldap &&
  1533. DcDnsName &&
  1534. (wcslen(DcDnsName) > 2) &&
  1535. DcDnsName[0] == L'\\' &&
  1536. DcDnsName[1] == L'\\') {
  1537. // ldap = ldap_open(DcDnsName + 2, LDAP_PORT);
  1538. ldap = ldap_init(DcDnsName + 2, LDAP_PORT);
  1539. if (!ldap) {
  1540. // fprintf(stderr, "WARN - ldap_open(DcDnsName + 2 %ws); WStatus %d\n",
  1541. // DcDnsName + 2,
  1542. // WStatus);
  1543. fprintf(stderr, "WARN - ldap_init(DcDnsName + 2 %ws); WStatus %d\n",
  1544. DcDnsName + 2,
  1545. WStatus);
  1546. } else {
  1547. // printf("ldap_open(DcDnsName + 2 %ws) succeeded\n", DcDnsName + 2);
  1548. printf("ldap_init(DcDnsName + 2 %ws) succeeded\n", DcDnsName + 2);
  1549. }
  1550. }
  1551. //
  1552. // DC's IP Address (w/o the leading \\)
  1553. //
  1554. if (!ldap &&
  1555. DcAddr &&
  1556. (wcslen(DcAddr) > 2) &&
  1557. DcAddr[0] == L'\\' &&
  1558. DcAddr[1] == L'\\') {
  1559. // ldap = ldap_open(DcAddr + 2, LDAP_PORT);
  1560. ldap = ldap_init(DcAddr + 2, LDAP_PORT);
  1561. if (!ldap) {
  1562. // fprintf(stderr, "WARN - ldap_open(DcAddr + 2 %ws); WStatus %d\n",
  1563. // DcAddr + 2,
  1564. // WStatus);
  1565. fprintf(stderr, "WARN - ldap_init(DcAddr + 2 %ws); WStatus %d\n",
  1566. DcAddr + 2,
  1567. WStatus);
  1568. } else {
  1569. // printf("ldap_open(DcAddr + 2 %ws) succeeded\n", DcAddr + 2);
  1570. printf("ldap_init(DcAddr + 2 %ws) succeeded\n", DcAddr + 2);
  1571. }
  1572. }
  1573. //
  1574. // DC's DNS name
  1575. //
  1576. if (!ldap && DcDnsName) {
  1577. // ldap = ldap_open(DcDnsName, LDAP_PORT);
  1578. ldap = ldap_init(DcDnsName, LDAP_PORT);
  1579. if (!ldap) {
  1580. // fprintf(stderr, "WARN - ldap_open(DcDnsName %ws); WStatus %d\n",
  1581. // DcDnsName,
  1582. // WStatus);
  1583. fprintf(stderr, "WARN - ldap_init(DcDnsName %ws); WStatus %d\n",
  1584. DcDnsName,
  1585. WStatus);
  1586. } else {
  1587. // printf("ldap_open(DcDnsName %ws) succeeded\n", DcDnsName);
  1588. printf("ldap_init(DcDnsName %ws) succeeded\n", DcDnsName);
  1589. }
  1590. }
  1591. //
  1592. // DC's IP Address
  1593. //
  1594. if (!ldap && DcAddr) {
  1595. // ldap = ldap_open(DcAddr, LDAP_PORT);
  1596. ldap = ldap_init(DcAddr, LDAP_PORT);
  1597. if (!ldap) {
  1598. // fprintf(stderr, "WARN - ldap_open(DcAddr %ws); WStatus %d\n",
  1599. // DcAddr,
  1600. // WStatus);
  1601. fprintf(stderr, "WARN - ldap_init(DcAddr %ws); WStatus %d\n",
  1602. DcAddr,
  1603. WStatus);
  1604. } else {
  1605. // printf("ldap_open(DcAddr %ws) succeeded\n", DcAddr);
  1606. printf("ldap_init(DcAddr %ws) succeeded\n", DcAddr);
  1607. }
  1608. }
  1609. //
  1610. // Whatever it is, we can't find it.
  1611. //
  1612. if (!ldap) {
  1613. // fprintf(stderr, "ERROR - ldap_open(DNS %ws, IP %ws); WStatus %d\n",
  1614. // DcDnsName,
  1615. // DcAddr,
  1616. // WStatus);
  1617. fprintf(stderr, "ERROR - ldap_init(DNS %ws, IP %ws); WStatus %d\n",
  1618. DcDnsName,
  1619. DcAddr,
  1620. WStatus);
  1621. return NULL;
  1622. }
  1623. //
  1624. // set the option as explained in the comment above.
  1625. //
  1626. ulOptions = PtrToUlong(LDAP_OPT_ON);
  1627. ldap_set_option(ldap, LDAP_OPT_AREC_EXCLUSIVE, &ulOptions);
  1628. //
  1629. // ldap cannot be used until after the bind operation
  1630. //
  1631. WStatus = ldap_bind_s(ldap, NULL, NULL, LDAP_AUTH_NEGOTIATE);
  1632. if (WStatus != LDAP_SUCCESS) {
  1633. fprintf(stderr, "ERROR - ldap_bind_s: %ws\n", ldap_err2string(WStatus));
  1634. ldap_unbind(ldap);
  1635. return NULL;
  1636. }
  1637. return ldap;
  1638. }
  1639. PWCHAR *
  1640. GetValues(
  1641. IN PLDAP Ldap,
  1642. IN PWCHAR Dn,
  1643. IN PWCHAR DesiredAttr,
  1644. IN BOOL Quiet
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Return the DS values for one attribute in an object.
  1649. Arguments:
  1650. ldap - An open, bound ldap port.
  1651. Base - The "pathname" of a DS object.
  1652. DesiredAttr - Return values for this attribute.
  1653. Quiet
  1654. Return Value:
  1655. An array of char pointers that represents the values for the attribute.
  1656. The caller must free the array with ldap_value_free(). NULL if unsuccessful.
  1657. --*/
  1658. {
  1659. PWCHAR Attr;
  1660. BerElement *Ber;
  1661. PLDAPMessage LdapMsg;
  1662. PLDAPMessage LdapEntry;
  1663. PWCHAR Attrs[2];
  1664. PWCHAR *Values = NULL;
  1665. //
  1666. // Search Base for all of its attributes + values
  1667. //
  1668. Attrs[0] = DesiredAttr;
  1669. Attrs[1] = NULL;
  1670. //
  1671. // Issue the ldap search
  1672. //
  1673. if (!LdapSearch(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY,
  1674. Attrs, 0, &LdapMsg, Quiet)) {
  1675. return NULL;
  1676. }
  1677. LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  1678. if (LdapEntry) {
  1679. Attr = ldap_first_attribute(Ldap, LdapEntry, &Ber);
  1680. if (Attr) {
  1681. Values = ldap_get_values(Ldap, LdapEntry, Attr);
  1682. }
  1683. }
  1684. ldap_msgfree(LdapMsg);
  1685. return Values;
  1686. }
  1687. VOID
  1688. GuidToStr(
  1689. IN GUID *pGuid,
  1690. OUT PWCHAR s
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. Convert a GUID to a string.
  1695. Arguments:
  1696. pGuid - ptr to the GUID.
  1697. s - The output character buffer.
  1698. Must be at least GUID_CHAR_LEN (36 bytes) long.
  1699. Function Return Value:
  1700. None.
  1701. --*/
  1702. {
  1703. if (pGuid != NULL) {
  1704. swprintf(s, L"%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
  1705. pGuid->Data1,
  1706. pGuid->Data2,
  1707. pGuid->Data3,
  1708. pGuid->Data4[0],
  1709. pGuid->Data4[1],
  1710. pGuid->Data4[2],
  1711. pGuid->Data4[3],
  1712. pGuid->Data4[4],
  1713. pGuid->Data4[5],
  1714. pGuid->Data4[6],
  1715. pGuid->Data4[7]);
  1716. } else {
  1717. swprintf(s, L"<null>");
  1718. }
  1719. }
  1720. PWCHAR
  1721. GetRootDn(
  1722. IN PLDAP Ldap,
  1723. IN PWCHAR NamingContext
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. Arguments:
  1728. Return Value:
  1729. --*/
  1730. {
  1731. PWCHAR Root; // DS pathname of configuration container
  1732. PWCHAR *Values; // values from the attribute "namingContexts"
  1733. DWORD NumVals; // number of values
  1734. //
  1735. // Return all of the values for the attribute namingContexts
  1736. //
  1737. Values = GetValues(Ldap, CN_ROOT, ATTR_NAMING_CONTEXTS, FALSE);
  1738. if (Values == NULL)
  1739. return NULL;
  1740. //
  1741. // Find the naming context that begins with CN=Configuration
  1742. //
  1743. NumVals = ldap_count_values(Values);
  1744. while (NumVals--) {
  1745. _wcslwr(Values[NumVals]);
  1746. Root = wcsstr(Values[NumVals], NamingContext);
  1747. if (Root != NULL && Root == Values[NumVals]) {
  1748. Root = FrsWcsDup(Root);
  1749. ldap_value_free(Values);
  1750. return Root;
  1751. }
  1752. }
  1753. printf("ERROR - COULD NOT FIND %ws\n", NamingContext);
  1754. ldap_value_free(Values);
  1755. return NULL;
  1756. }
  1757. PWCHAR
  1758. ExtendDn(
  1759. IN PWCHAR Dn,
  1760. IN PWCHAR Cn
  1761. )
  1762. /*++
  1763. Routine Description:
  1764. Extend an existing DN with a new CN= component.
  1765. Arguments:
  1766. Dn - distinguished name
  1767. Cn - common name
  1768. Return Value:
  1769. CN=Cn,Dn
  1770. --*/
  1771. {
  1772. ULONG Len;
  1773. PWCHAR NewDn;
  1774. if (!Dn || !Cn) {
  1775. return NULL;
  1776. }
  1777. Len = wcslen(L"CN=,") + wcslen(Dn) + wcslen(Cn) + 1;
  1778. NewDn = (PWCHAR)malloc(Len * sizeof(WCHAR));
  1779. wcscpy(NewDn, L"CN=");
  1780. wcscat(NewDn, Cn);
  1781. wcscat(NewDn, L",");
  1782. wcscat(NewDn, Dn);
  1783. return NewDn;
  1784. }
  1785. PVOID *
  1786. FindValues(
  1787. IN PLDAP Ldap,
  1788. IN PLDAPMessage LdapEntry,
  1789. IN PWCHAR DesiredAttr,
  1790. IN BOOL DoBerValues
  1791. )
  1792. /*++
  1793. Routine Description:
  1794. Return the DS values for one attribute in an entry.
  1795. Arguments:
  1796. Ldap - An open, bound ldap port.
  1797. LdapEntry - An ldap entry returned by ldap_search_s()
  1798. DesiredAttr - Return values for this attribute.
  1799. DoVerValues - Return the bervals
  1800. Return Value:
  1801. An array of char pointers that represents the values for the attribute.
  1802. The caller must free the array with ldap_value_free(). NULL if unsuccessful.
  1803. --*/
  1804. {
  1805. PWCHAR LdapAttr; // Retrieved from an ldap entry
  1806. BerElement *Ber; // Needed for scanning attributes
  1807. //
  1808. // Search the entry for the desired attribute
  1809. //
  1810. for (LdapAttr = ldap_first_attribute(Ldap, LdapEntry, &Ber);
  1811. LdapAttr != NULL;
  1812. LdapAttr = ldap_next_attribute(Ldap, LdapEntry, Ber)) {
  1813. if (_wcsicmp(DesiredAttr, LdapAttr) == 0) {
  1814. //
  1815. // Return the values for DesiredAttr
  1816. //
  1817. if (DoBerValues) {
  1818. return (PVOID *)ldap_get_values_len(Ldap, LdapEntry, LdapAttr);
  1819. } else {
  1820. return (PVOID *)ldap_get_values(Ldap, LdapEntry, LdapAttr);
  1821. }
  1822. }
  1823. }
  1824. return NULL;
  1825. }
  1826. PWCHAR
  1827. FindValue(
  1828. IN PLDAP Ldap,
  1829. IN PLDAPMessage LdapEntry,
  1830. IN PWCHAR DesiredAttr
  1831. )
  1832. /*++
  1833. Routine Description:
  1834. Return a copy of the first DS value for one attribute in an entry.
  1835. Arguments:
  1836. Ldap - An open, bound ldap port.
  1837. LdapEntry - An ldap entry returned by ldap_search_s()
  1838. DesiredAttr - Return values for this attribute.
  1839. Return Value:
  1840. A zero-terminated string or NULL if the attribute or its value
  1841. doesn't exist. The string is freed with FREE_NO_HEADER().
  1842. --*/
  1843. {
  1844. PWCHAR Val;
  1845. PWCHAR *Values;
  1846. // Get ldap's array of values
  1847. Values = (PWCHAR *)FindValues(Ldap, LdapEntry, DesiredAttr, FALSE);
  1848. // Copy the first value (if any)
  1849. Val = (Values) ? FrsWcsDup(Values[0]) : NULL;
  1850. // Free ldap's array of values
  1851. ldap_value_free(Values);
  1852. return Val;
  1853. }
  1854. BOOL
  1855. FindBerValue(
  1856. IN PLDAP ldap,
  1857. IN PLDAPMessage Entry,
  1858. IN PWCHAR DesiredAttr,
  1859. OUT ULONG *Len,
  1860. OUT VOID **Value
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. Return a copy of the attributes object's schedule
  1865. Arguments:
  1866. ldap - An open, bound ldap port.
  1867. Entry - An ldap entry returned by ldap_search_s()
  1868. DesiredAttr - desired attribute
  1869. Len - length of Value
  1870. Value - binary value
  1871. Return Value:
  1872. The address of a schedule or NULL. Free with FrsFree().
  1873. --*/
  1874. {
  1875. PLDAP_BERVAL *Values;
  1876. PSCHEDULE Schedule;
  1877. *Len = 0;
  1878. *Value = NULL;
  1879. //
  1880. // Get ldap's array of values
  1881. //
  1882. Values = (PLDAP_BERVAL *)FindValues(ldap, Entry, DesiredAttr, TRUE);
  1883. if (!Values) {
  1884. return FALSE;
  1885. }
  1886. //
  1887. // Return a copy of the schedule
  1888. //
  1889. *Len = Values[0]->bv_len;
  1890. if (*Len) {
  1891. *Value = (PWCHAR)malloc(*Len);
  1892. CopyMemory(*Value, Values[0]->bv_val, *Len);
  1893. }
  1894. ldap_value_free_len(Values);
  1895. return TRUE;
  1896. }
  1897. VOID
  1898. DumpValues(
  1899. IN PLDAP Ldap,
  1900. IN PWCHAR Dn,
  1901. IN DWORD Scope,
  1902. IN PWCHAR Class,
  1903. IN PWCHAR Attrs[],
  1904. IN BOOL IfEmpty
  1905. )
  1906. /*++
  1907. Routine Description:
  1908. Print the values and attributes for an object in the DS.
  1909. Arguments:
  1910. ldap - An open, bound ldap port.
  1911. Base - The "pathname" of a DS object.
  1912. Scope - Dump the values about the object (LDAP_SCOPE_BASE) or
  1913. about the objects contained in this object (LDAP_SCOPE_ONELEVEL)
  1914. Return Value:
  1915. None.
  1916. --*/
  1917. {
  1918. PWCHAR Attr; // Retrieved from an ldap entry
  1919. BerElement *Ber; // Needed for scanning attributes
  1920. PLDAPMessage Msg; // Opaque stuff from ldap subsystem
  1921. PLDAPMessage Entry; // Opaque stuff from ldap subsystem
  1922. PWCHAR *Values; // Array of values for desired attribute
  1923. PLDAP_BERVAL *Balues; // Array of values for desired attribute
  1924. DWORD NumVals; // Number of entries in Values
  1925. PWCHAR Rdn; // An entries "pathname" in the DS
  1926. WCHAR GuidStr[GUID_CHAR_LEN + 1];
  1927. PWCHAR EntryDn;
  1928. ULONG i;
  1929. //
  1930. // Search Base for all of the attributes + values of Class
  1931. //
  1932. if (!LdapSearch(Ldap, Dn, Scope, Class,
  1933. Attrs, 0, &Msg, !IfEmpty)) {
  1934. return;
  1935. }
  1936. //
  1937. // Scan the entries returned from ldap_search
  1938. //
  1939. for (Entry = ldap_first_entry(Ldap, Msg);
  1940. Entry != NULL;
  1941. Entry = ldap_next_entry(Ldap, Entry)) {
  1942. EntryDn = FindValue(Ldap, Entry, ATTR_DN);
  1943. if (EntryDn) {
  1944. Attr = ldap_first_attribute(Ldap, Entry, &Ber);
  1945. if (Attr) {
  1946. Attr = ldap_next_attribute(Ldap, Entry, Ber);
  1947. }
  1948. if (!IfEmpty && !Attr) {
  1949. continue;
  1950. }
  1951. Rdn = MakeRdn(EntryDn);
  1952. printf("%ws\n", Rdn);
  1953. FREE(EntryDn);
  1954. FREE(Rdn);
  1955. } else {
  1956. Attr = ldap_first_attribute(Ldap, Entry, &Ber);
  1957. if (!IfEmpty && !Attr) {
  1958. continue;
  1959. }
  1960. printf("Entry has no distinguished name\n");
  1961. }
  1962. //
  1963. // Scan the attributes of an entry
  1964. //
  1965. for (Attr = ldap_first_attribute(Ldap, Entry, &Ber);
  1966. Attr != NULL;
  1967. Attr = ldap_next_attribute(Ldap, Entry, Ber)) {
  1968. //
  1969. // Printed above; don't repeat
  1970. //
  1971. if (!wcscmp(Attr, ATTR_DN)) {
  1972. continue;
  1973. }
  1974. //
  1975. // Print the values
  1976. //
  1977. printf(" %ws\n", Attr);
  1978. for (i = 0; GuidAttrs[i]; ++i) {
  1979. if (!wcscmp(Attr, GuidAttrs[i])) {
  1980. Balues = ldap_get_values_len(Ldap, Entry, Attr);
  1981. NumVals = ldap_count_values_len(Balues);
  1982. if (NumVals) {
  1983. GuidToStr((GUID *)Balues[0]->bv_val, GuidStr);
  1984. printf(" Length %d; %ws\n",
  1985. Balues[0]->bv_len, GuidStr);
  1986. }
  1987. ldap_value_free_len(Balues);
  1988. break;
  1989. }
  1990. }
  1991. if (GuidAttrs[i]) {
  1992. continue;
  1993. }
  1994. for (i = 0; BerAttrs[i]; ++i) {
  1995. if (!wcscmp(Attr, BerAttrs[i])) {
  1996. Balues = ldap_get_values_len(Ldap, Entry, Attr);
  1997. NumVals = ldap_count_values_len(Balues);
  1998. if (NumVals) {
  1999. printf(" Length %d\n",
  2000. Balues[0]->bv_len);
  2001. }
  2002. ldap_value_free_len(Balues);
  2003. break;
  2004. }
  2005. }
  2006. if (BerAttrs[i]) {
  2007. continue;
  2008. }
  2009. if (!wcscmp(Attr, L"schedule")) {
  2010. Balues = ldap_get_values_len(Ldap, Entry, Attr);
  2011. NumVals = ldap_count_values_len(Balues);
  2012. if (NumVals) {
  2013. printf(" Length %d; Number %d\n",
  2014. NumVals,
  2015. Balues[0]->bv_len,
  2016. ((PSCHEDULE)(Balues[0]->bv_val))->NumberOfSchedules);
  2017. }
  2018. ldap_value_free_len(Balues);
  2019. continue;
  2020. }
  2021. Values = ldap_get_values(Ldap, Entry, Attr);
  2022. NumVals = ldap_count_values(Values);
  2023. while (NumVals--) {
  2024. printf(" %ws\n", Values[NumVals]);
  2025. }
  2026. ldap_value_free(Values);
  2027. }
  2028. }
  2029. ldap_msgfree(Msg);
  2030. }
  2031. DWORD
  2032. GetDnsName(
  2033. IN PWCHAR Server,
  2034. OUT PWCHAR *DnsName
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. Retrieve this machine's DNS name.
  2039. Arguments:
  2040. Server
  2041. DnsName - wide char version of dns name
  2042. Return Value:
  2043. WSA Status
  2044. --*/
  2045. {
  2046. INT SStatus;
  2047. WORD DnsVersion = MAKEWORD(1, 1);
  2048. struct hostent *Host;
  2049. WSADATA WSAData;
  2050. PCHAR DnsNameA;
  2051. PCHAR ServerA;
  2052. *DnsName = NULL;
  2053. //
  2054. // Get this machine's DNS name
  2055. //
  2056. //
  2057. // Initialize the socket subsystem
  2058. //
  2059. if (SStatus = WSAStartup(DnsVersion, &WSAData)) {
  2060. fprintf(stderr, "Can't get DNS name; Socket startup error %d\n",
  2061. SStatus);
  2062. return SStatus;
  2063. };
  2064. //
  2065. // Get the DNS name
  2066. //
  2067. ServerA = FrsWtoA(Server);
  2068. Host = gethostbyname(ServerA);
  2069. FREE(ServerA);
  2070. if (Host == NULL) {
  2071. SStatus = WSAGetLastError();
  2072. fprintf(stderr, "Can't get DNS name for %ws; gethostbyname error %d\n",
  2073. Server, SStatus);
  2074. return SStatus;
  2075. }
  2076. if (Host->h_name == NULL) {
  2077. fprintf(stderr, "DNS name for %ws is NULL\n", Server);
  2078. return WSAEFAULT;
  2079. }
  2080. //
  2081. // Return both the ASCII and UNICODE versions
  2082. //
  2083. *DnsName = FrsAtoW(Host->h_name);
  2084. WSACleanup();
  2085. return 0;
  2086. }
  2087. PWCHAR
  2088. GetNextDn(
  2089. IN PLDAP Ldap,
  2090. PLDAPMessage LdapEntry,
  2091. IN PWCHAR ParentDn
  2092. )
  2093. /*++
  2094. Routine Description:
  2095. Arguments:
  2096. Return Value:
  2097. None.
  2098. --*/
  2099. {
  2100. PWCHAR Cn = NULL;
  2101. PWCHAR Dn = NULL;
  2102. Cn = FindValue(Ldap, LdapEntry, ATTR_CN);
  2103. if (Cn) {
  2104. Dn = ExtendDn(ParentDn, Cn);
  2105. FREE(Cn)
  2106. }
  2107. return Dn;
  2108. }
  2109. PWCHAR
  2110. DumpAttrs(
  2111. IN PLDAP Ldap,
  2112. PLDAPMessage LdapEntry,
  2113. IN PWCHAR ParentDn,
  2114. IN PWCHAR *Attrs,
  2115. IN PWCHAR Indent
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. Arguments:
  2120. Return Value:
  2121. None.
  2122. --*/
  2123. {
  2124. DWORD NumVals;
  2125. ULONG ScheduleLen;
  2126. ULONG ExtensionsLen;
  2127. PSCHEDULE Schedule = NULL;
  2128. PCHAR Extensions = NULL;
  2129. PWCHAR Val = NULL;
  2130. PWCHAR Rdn = NULL;
  2131. PWCHAR Pdn = NULL;
  2132. PWCHAR PRdn = NULL;
  2133. PWCHAR *Values = NULL;
  2134. if (!Attrs) {
  2135. return NULL;
  2136. }
  2137. while (*Attrs) {
  2138. //
  2139. // Don't bother, the Cn will do
  2140. //
  2141. if (!wcscmp(*Attrs, ATTR_DN)) {
  2142. ++Attrs;
  2143. continue;
  2144. }
  2145. if (!wcscmp(*Attrs, ATTR_COMPUTER_REF_BL)) {
  2146. Values = ldap_get_values(Ldap, LdapEntry, *Attrs);
  2147. NumVals = ldap_count_values(Values);
  2148. while (NumVals--) {
  2149. Rdn = MakeRdn(Values[NumVals]);
  2150. Pdn = FrsDsMakeParentDn(Values[NumVals]);
  2151. PRdn = MakeRdn(Pdn);
  2152. printf(" %ws%ws=%ws\\%ws\n", Indent, *Attrs, PRdn, Rdn);
  2153. FREE(Rdn);
  2154. FREE(Pdn);
  2155. FREE(PRdn);
  2156. }
  2157. ldap_value_free(Values);
  2158. } else if (!wcscmp(*Attrs, ATTR_SCHEDULE)) {
  2159. FindBerValue(Ldap,
  2160. LdapEntry,
  2161. ATTR_SCHEDULE,
  2162. &ScheduleLen,
  2163. (VOID **)&Schedule);
  2164. if (Schedule) {
  2165. // PrintShortSchedule(Indent, Schedule, ScheduleLen);
  2166. PrintLongSchedule(L" ", Indent, Schedule, ScheduleLen);
  2167. FREE(Schedule);
  2168. } else {
  2169. printf(" %wsSchedule=\n", Indent);
  2170. }
  2171. } else if (!wcscmp(*Attrs, ATTR_EXTENSIONS)) {
  2172. FindBerValue(Ldap,
  2173. LdapEntry,
  2174. ATTR_EXTENSIONS,
  2175. &ExtensionsLen,
  2176. (VOID **)&Extensions);
  2177. if (Extensions) {
  2178. FREE(Extensions);
  2179. printf(" %wsExtensions=%d\n", Indent, ExtensionsLen);
  2180. } else {
  2181. printf(" %wsExtensions=\n", Indent);
  2182. }
  2183. } else if (!wcscmp(*Attrs, ATTR_NAMING_CONTEXTS)) {
  2184. Values = ldap_get_values(Ldap, LdapEntry, *Attrs);
  2185. NumVals = ldap_count_values(Values);
  2186. while (NumVals--) {
  2187. printf(" %ws%ws=%ws\n", Indent, *Attrs, Values[NumVals]);
  2188. }
  2189. ldap_value_free(Values);
  2190. } else {
  2191. Val = FindValue(Ldap, LdapEntry, *Attrs);
  2192. if (Val) {
  2193. if (!wcscmp(*Attrs, ATTR_CN)) {
  2194. printf("%ws%ws\n", Indent, Val);
  2195. } else if (!wcscmp(*Attrs, ATTR_FROM_SERVER) ||
  2196. !wcscmp(*Attrs, ATTR_PRIMARY_MEMBER) ||
  2197. !wcscmp(*Attrs, ATTR_COMPUTER_REF) ||
  2198. !wcscmp(*Attrs, ATTR_COMPUTER_REF_BL) ||
  2199. !wcscmp(*Attrs, ATTR_MEMBER_REF) ||
  2200. !wcscmp(*Attrs, ATTR_MEMBER_REF_BL) ||
  2201. !wcscmp(*Attrs, ATTR_SERVER_REF_BL) ||
  2202. !wcscmp(*Attrs, ATTR_SERVER_REF)) {
  2203. Rdn = MakeRdn(Val);
  2204. Pdn = FrsDsMakeParentDn(Val);
  2205. PRdn = MakeRdn(Pdn);
  2206. printf(" %ws%ws=%ws\\%ws\n", Indent, *Attrs, PRdn, Rdn);
  2207. FREE(Rdn);
  2208. FREE(Pdn);
  2209. FREE(PRdn);
  2210. } else {
  2211. printf(" %ws%ws=%ws\n", Indent, *Attrs, Val);
  2212. }
  2213. FREE(Val);
  2214. } else {
  2215. printf(" %ws%ws=\n", Indent, *Attrs);
  2216. }
  2217. }
  2218. ++Attrs;
  2219. }
  2220. return GetNextDn(Ldap, LdapEntry, ParentDn);
  2221. }
  2222. VOID
  2223. DumpCxtions(
  2224. IN PLDAP Ldap,
  2225. IN PWCHAR ParentDn
  2226. )
  2227. /*++
  2228. Routine Description:
  2229. Arguments:
  2230. Return Value:
  2231. None.
  2232. --*/
  2233. {
  2234. PWCHAR DesiredAttrs[16];
  2235. PLDAPMessage LdapMsg = NULL;
  2236. PLDAPMessage LdapEntry = NULL;
  2237. PWCHAR NextDn = NULL;
  2238. //
  2239. // Cxtions
  2240. //
  2241. DesiredAttrs[0] = ATTR_CN;
  2242. DesiredAttrs[1] = ATTR_FROM_SERVER;
  2243. DesiredAttrs[2] = ATTR_SCHEDULE;
  2244. DesiredAttrs[3] = ATTR_ENABLED_CXTION;
  2245. DesiredAttrs[4] = NULL;
  2246. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_CXTION,
  2247. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2248. //
  2249. // Scan the entries returned from ldap_search
  2250. //
  2251. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2252. LdapEntry != NULL;
  2253. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2254. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2255. if (NextDn) {
  2256. FREE(NextDn);
  2257. }
  2258. }
  2259. ldap_msgfree(LdapMsg);
  2260. LdapMsg = NULL;
  2261. }
  2262. }
  2263. VOID
  2264. DumpMembers(
  2265. IN PLDAP Ldap,
  2266. IN PWCHAR ParentDn
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. Arguments:
  2271. Return Value:
  2272. None.
  2273. --*/
  2274. {
  2275. PWCHAR DesiredAttrs[16];
  2276. PLDAPMessage LdapMsg = NULL;
  2277. PLDAPMessage LdapEntry = NULL;
  2278. PWCHAR NextDn = NULL;
  2279. //
  2280. // Servers
  2281. //
  2282. DesiredAttrs[0] = ATTR_CN;
  2283. DesiredAttrs[1] = ATTR_COMPUTER_REF;
  2284. DesiredAttrs[2] = ATTR_MEMBER_REF_BL;
  2285. DesiredAttrs[3] = ATTR_SERVER_REF;
  2286. DesiredAttrs[4] = NULL;
  2287. // DesiredAttrs[4] = ATTR_CONTROL_CREATION;
  2288. // DesiredAttrs[5] = ATTR_INBOUND_BACKLOG;
  2289. // DesiredAttrs[6] = ATTR_OUTBOUND_BACKLOG;
  2290. // DesiredAttrs[7] = ATTR_SERVICE_COMMAND;
  2291. // DesiredAttrs[8] = ATTR_UPDATE_TIMEOUT;
  2292. // DesiredAttrs[9] = ATTR_EXTENSIONS;
  2293. // DesiredAttrs[10] = ATTR_FLAGS;
  2294. // DesiredAttrs[11] = ATTR_AUTH_LEVEL;
  2295. DesiredAttrs[12] = NULL;
  2296. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_MEMBER,
  2297. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2298. //
  2299. // Scan the entries returned from ldap_search
  2300. //
  2301. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2302. LdapEntry != NULL;
  2303. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2304. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2305. if (NextDn) {
  2306. DumpCxtions(Ldap, NextDn);
  2307. FREE(NextDn);
  2308. }
  2309. }
  2310. ldap_msgfree(LdapMsg);
  2311. LdapMsg = NULL;
  2312. }
  2313. }
  2314. VOID
  2315. DumpSets(
  2316. IN PLDAP Ldap,
  2317. IN PWCHAR ParentDn
  2318. )
  2319. /*++
  2320. Routine Description:
  2321. Arguments:
  2322. Return Value:
  2323. None.
  2324. --*/
  2325. {
  2326. PWCHAR DesiredAttrs[16];
  2327. PLDAPMessage LdapMsg = NULL;
  2328. PLDAPMessage LdapEntry = NULL;
  2329. PWCHAR NextDn = NULL;
  2330. //
  2331. // Sets
  2332. //
  2333. DesiredAttrs[0] = ATTR_CN;
  2334. DesiredAttrs[1] = ATTR_PRIMARY_MEMBER;
  2335. DesiredAttrs[2] = ATTR_SET_TYPE;
  2336. DesiredAttrs[3] = ATTR_SCHEDULE;
  2337. DesiredAttrs[4] = ATTR_DIRECTORY_FILTER;
  2338. DesiredAttrs[5] = ATTR_FILE_FILTER;
  2339. DesiredAttrs[6] = NULL;
  2340. // DesiredAttrs[7] = ATTR_DS_POLL;
  2341. // DesiredAttrs[8] = ATTR_EXTENSIONS;
  2342. // DesiredAttrs[9] = ATTR_FLAGS;
  2343. // DesiredAttrs[10] = ATTR_LEVEL_LIMIT;
  2344. // DesiredAttrs[11] = ATTR_AUTH_LEVEL;
  2345. DesiredAttrs[12] = NULL;
  2346. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_REPLICA_SET,
  2347. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2348. //
  2349. // Scan the entries returned from ldap_search
  2350. //
  2351. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2352. LdapEntry != NULL;
  2353. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2354. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2355. if (NextDn) {
  2356. DumpMembers(Ldap, NextDn);
  2357. FREE(NextDn);
  2358. }
  2359. }
  2360. ldap_msgfree(LdapMsg);
  2361. LdapMsg = NULL;
  2362. }
  2363. }
  2364. VOID
  2365. DumpContexts(
  2366. IN PLDAP Ldap
  2367. )
  2368. /*++
  2369. Routine Description:
  2370. Dump every ds object related to replication
  2371. Arguments:
  2372. Ldap
  2373. Return Value:
  2374. None.
  2375. --*/
  2376. {
  2377. PWCHAR DesiredAttrs[16];
  2378. PWCHAR NextDn = NULL;
  2379. PLDAPMessage LdapMsg = NULL;
  2380. PLDAPMessage LdapEntry = NULL;
  2381. //
  2382. // Setting
  2383. //
  2384. DesiredAttrs[0] = ATTR_NAMING_CONTEXTS;
  2385. DesiredAttrs[1] = ATTR_DEFAULT_NAMING_CONTEXT;
  2386. DesiredAttrs[2] = NULL;
  2387. if (LdapSearch(Ldap, CN_ROOT, LDAP_SCOPE_BASE, CATEGORY_ANY,
  2388. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2389. //
  2390. // Scan the entries returned from ldap_search
  2391. //
  2392. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2393. LdapEntry != NULL;
  2394. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2395. NextDn = DumpAttrs(Ldap, LdapEntry, CN_ROOT, DesiredAttrs, L"");
  2396. if (NextDn) {
  2397. FREE(NextDn);
  2398. }
  2399. }
  2400. ldap_msgfree(LdapMsg);
  2401. LdapMsg = NULL;
  2402. }
  2403. }
  2404. VOID
  2405. DumpAdminWorld(
  2406. IN PLDAP Ldap
  2407. )
  2408. /*++
  2409. Routine Description:
  2410. Dump every ds object related to replication
  2411. Arguments:
  2412. Ldap
  2413. Return Value:
  2414. None.
  2415. --*/
  2416. {
  2417. PWCHAR DesiredAttrs[16];
  2418. PWCHAR ConfigDn = NULL;
  2419. PWCHAR ServicesDn = NULL;
  2420. PWCHAR NextDn = NULL;
  2421. PLDAPMessage LdapMsg = NULL;
  2422. PLDAPMessage LdapEntry = NULL;
  2423. //
  2424. // Services
  2425. //
  2426. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  2427. if (!ConfigDn) {
  2428. return;
  2429. }
  2430. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  2431. //
  2432. // Setting
  2433. //
  2434. DesiredAttrs[0] = ATTR_CN;
  2435. DesiredAttrs[1] = NULL;
  2436. // DesiredAttrs[1] = ATTR_EXTENSIONS;
  2437. DesiredAttrs[2] = NULL;
  2438. if (LdapSearch(Ldap, ServicesDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTFRS_SETTINGS,
  2439. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2440. //
  2441. // Scan the entries returned from ldap_search
  2442. //
  2443. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2444. LdapEntry != NULL;
  2445. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2446. NextDn = DumpAttrs(Ldap, LdapEntry, ServicesDn, DesiredAttrs, L"");
  2447. if (NextDn) {
  2448. DumpSets(Ldap, NextDn);
  2449. FREE(NextDn);
  2450. }
  2451. }
  2452. ldap_msgfree(LdapMsg);
  2453. LdapMsg = NULL;
  2454. }
  2455. FREE(ServicesDn);
  2456. FREE(ConfigDn);
  2457. }
  2458. VOID
  2459. DumpSubscribers(
  2460. IN PLDAP Ldap,
  2461. IN PWCHAR ParentDn
  2462. )
  2463. /*++
  2464. Routine Description:
  2465. Arguments:
  2466. Return Value:
  2467. None.
  2468. --*/
  2469. {
  2470. PWCHAR DesiredAttrs[16];
  2471. PLDAPMessage LdapMsg = NULL;
  2472. PLDAPMessage LdapEntry = NULL;
  2473. PWCHAR NextDn = NULL;
  2474. //
  2475. // Subscribers
  2476. //
  2477. DesiredAttrs[0] = ATTR_CN;
  2478. DesiredAttrs[1] = ATTR_REPLICA_ROOT;
  2479. DesiredAttrs[2] = ATTR_REPLICA_STAGE;
  2480. DesiredAttrs[3] = ATTR_MEMBER_REF;
  2481. DesiredAttrs[4] = ATTR_SCHEDULE;
  2482. DesiredAttrs[5] = NULL;
  2483. // DesiredAttrs[4] = ATTR_EXTENSIONS;
  2484. // DesiredAttrs[5] = ATTR_FAULT_CONDITION;
  2485. // DesiredAttrs[6] = ATTR_FLAGS;
  2486. // DesiredAttrs[7] = ATTR_SERVICE_COMMAND;
  2487. // DesiredAttrs[8] = ATTR_SERVICE_COMMAND_STATUS;
  2488. // DesiredAttrs[9] = ATTR_UPDATE_TIMEOUT;
  2489. DesiredAttrs[10] = NULL;
  2490. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_SUBSCRIBER,
  2491. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2492. //
  2493. // Scan the entries returned from ldap_search
  2494. //
  2495. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2496. LdapEntry != NULL;
  2497. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2498. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2499. if (NextDn) {
  2500. DumpSubscribers(Ldap, NextDn);
  2501. FREE(NextDn);
  2502. }
  2503. }
  2504. ldap_msgfree(LdapMsg);
  2505. LdapMsg = NULL;
  2506. }
  2507. }
  2508. VOID
  2509. DumpSubscriptions(
  2510. IN PLDAP Ldap,
  2511. IN PWCHAR ParentDn
  2512. )
  2513. /*++
  2514. Routine Description:
  2515. Arguments:
  2516. Return Value:
  2517. None.
  2518. --*/
  2519. {
  2520. PWCHAR DesiredAttrs[16];
  2521. PLDAPMessage LdapMsg = NULL;
  2522. PLDAPMessage LdapEntry = NULL;
  2523. PWCHAR NextDn = NULL;
  2524. //
  2525. // Servers
  2526. //
  2527. DesiredAttrs[0] = ATTR_CN;
  2528. DesiredAttrs[1] = ATTR_WORKING;
  2529. DesiredAttrs[2] = NULL;
  2530. // DesiredAttrs[2] = ATTR_EXTENSIONS;
  2531. // DesiredAttrs[3] = ATTR_VERSION;
  2532. DesiredAttrs[4] = NULL;
  2533. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_SUBSCRIPTIONS,
  2534. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2535. //
  2536. // Scan the entries returned from ldap_search
  2537. //
  2538. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2539. LdapEntry != NULL;
  2540. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2541. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2542. if (NextDn) {
  2543. DumpSubscribers(Ldap, NextDn);
  2544. FREE(NextDn);
  2545. }
  2546. }
  2547. ldap_msgfree(LdapMsg);
  2548. LdapMsg = NULL;
  2549. }
  2550. }
  2551. VOID
  2552. DumpUserWorld(
  2553. IN PLDAP Ldap
  2554. )
  2555. /*++
  2556. Routine Description:
  2557. Dump every ds object related to replication
  2558. Arguments:
  2559. Ldap
  2560. Return Value:
  2561. None.
  2562. --*/
  2563. {
  2564. DWORD WStatus;
  2565. PWCHAR DesiredAttrs[16];
  2566. DWORD NumVals;
  2567. PWCHAR *Values = NULL;
  2568. PWCHAR NextDn = NULL;
  2569. PWCHAR DefaultDn = NULL;
  2570. PLDAPMessage LdapMsg = NULL;
  2571. PLDAPMessage LdapEntry = NULL;
  2572. HANDLE Handle = NULL;
  2573. DS_NAME_RESULT *Cracked = NULL;
  2574. WCHAR **Crackee;
  2575. PDOMAIN_CONTROLLER_INFO DcInfo;
  2576. //
  2577. // Return all of the values for the attribute namingContexts
  2578. //
  2579. Values = GetValues(Ldap, CN_ROOT, ATTR_DEFAULT_NAMING_CONTEXT, TRUE);
  2580. if (!Values) {
  2581. fprintf(stderr, "ERROR - Can't find %ws in %ws\n",
  2582. ATTR_DEFAULT_NAMING_CONTEXT,
  2583. CN_ROOT);
  2584. return;
  2585. }
  2586. DefaultDn = FrsWcsDup(Values[0]);
  2587. ldap_value_free(Values);
  2588. //
  2589. // Get Info about a Primary Domain Controller (need the IP address)
  2590. //
  2591. WStatus = FrsDsGetDcInfo(&DcInfo,
  2592. DS_DIRECTORY_SERVICE_REQUIRED | // Flags
  2593. DS_WRITABLE_REQUIRED);
  2594. //
  2595. // Report the error and carry on
  2596. //
  2597. if (!WIN_SUCCESS(WStatus)) {
  2598. fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n",
  2599. WStatus);
  2600. } else {
  2601. WStatus = DsBind(DcInfo->DomainControllerName, NULL, &Handle);
  2602. if (!WIN_SUCCESS(WStatus)) {
  2603. fprintf(stderr, "ERROR - DsBind(%ws); WStatus %d %08x\n",
  2604. DcInfo->DomainControllerName,
  2605. WStatus,
  2606. WStatus);
  2607. WStatus = DsBind(DcInfo->DomainControllerAddress, NULL, &Handle);
  2608. if (!WIN_SUCCESS(WStatus)) {
  2609. fprintf(stderr, "ERROR - DsBind(%ws); WStatus %d %08x\n",
  2610. DcInfo->DomainControllerAddress,
  2611. WStatus,
  2612. WStatus);
  2613. } else {
  2614. printf("DsBind(%ws) succeeded\n", DcInfo->DomainControllerAddress);
  2615. }
  2616. } else {
  2617. printf("DsBind(%ws) succeeded\n", DcInfo->DomainControllerName);
  2618. }
  2619. }
  2620. //
  2621. // Find the naming context that begins with CN=Configuration
  2622. //
  2623. //
  2624. // Computers
  2625. //
  2626. DesiredAttrs[0] = ATTR_CN;
  2627. DesiredAttrs[1] = ATTR_SAM;
  2628. DesiredAttrs[2] = ATTR_DNS_HOST_NAME;
  2629. DesiredAttrs[3] = ATTR_DN;
  2630. DesiredAttrs[4] = ATTR_COMPUTER_REF_BL;
  2631. DesiredAttrs[5] = ATTR_SERVER_REF;
  2632. DesiredAttrs[6] = ATTR_SERVER_REF_BL;
  2633. DesiredAttrs[7] = ATTR_USER_ACCOUNT_CONTROL;
  2634. DesiredAttrs[8] = NULL;
  2635. if (LdapSearch(Ldap, DefaultDn, LDAP_SCOPE_SUBTREE, CATEGORY_COMPUTER,
  2636. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2637. //
  2638. // Scan the entries returned from ldap_search
  2639. //
  2640. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2641. LdapEntry != NULL;
  2642. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2643. NextDn = DumpAttrs(Ldap, LdapEntry, DefaultDn, DesiredAttrs, L"");
  2644. FREE(NextDn);
  2645. NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
  2646. if (NextDn && HANDLE_IS_VALID(Handle)) {
  2647. Crackee = &NextDn;
  2648. WStatus = DsCrackNames(Handle,
  2649. DS_NAME_NO_FLAGS,
  2650. // DS_NAME_FLAG_SYNTACTICAL_ONLY,
  2651. DS_FQDN_1779_NAME,
  2652. DS_NT4_ACCOUNT_NAME,
  2653. //DS_CANONICAL_NAME,
  2654. 1,
  2655. Crackee,
  2656. &Cracked);
  2657. if (!WIN_SUCCESS(WStatus)) {
  2658. printf("ERROR - Cracking name; WStatus %d\n", WStatus);
  2659. } else if (Cracked &&
  2660. Cracked->cItems &&
  2661. Cracked->rItems) {
  2662. if (Cracked->rItems->status) {
  2663. printf(" ERROR - Can't crack name; status %d\n",
  2664. Cracked->rItems->status);
  2665. } else {
  2666. printf(" Cracked Domain : %ws\n",
  2667. Cracked->rItems->pDomain);
  2668. printf(" Cracked Account: %ws\n",
  2669. Cracked->rItems->pName);
  2670. }
  2671. DsFreeNameResult(Cracked);
  2672. Cracked = NULL;
  2673. }
  2674. }
  2675. if (NextDn) {
  2676. DumpSubscriptions(Ldap, NextDn);
  2677. FREE(NextDn);
  2678. }
  2679. }
  2680. ldap_msgfree(LdapMsg);
  2681. LdapMsg = NULL;
  2682. }
  2683. //out:
  2684. if (HANDLE_IS_VALID(Handle)) {
  2685. DsUnBind(&Handle);
  2686. }
  2687. FREE(DefaultDn);
  2688. }
  2689. VOID
  2690. DumpDsDsa(
  2691. IN PLDAP Ldap,
  2692. IN PWCHAR ParentDn
  2693. )
  2694. /*++
  2695. Routine Description:
  2696. Arguments:
  2697. Return Value:
  2698. None.
  2699. --*/
  2700. {
  2701. PWCHAR DesiredAttrs[16];
  2702. PLDAPMessage LdapMsg = NULL;
  2703. PLDAPMessage LdapEntry = NULL;
  2704. PWCHAR NextDn = NULL;
  2705. //
  2706. // Servers
  2707. //
  2708. DesiredAttrs[0] = ATTR_CN;
  2709. DesiredAttrs[1] = ATTR_DN;
  2710. DesiredAttrs[2] = ATTR_SCHEDULE;
  2711. DesiredAttrs[3] = ATTR_SERVER_REF;
  2712. DesiredAttrs[4] = NULL;
  2713. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTDS_DSA,
  2714. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2715. //
  2716. // Scan the entries returned from ldap_search
  2717. //
  2718. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2719. LdapEntry != NULL;
  2720. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2721. NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
  2722. if (NextDn) {
  2723. DumpCxtions(Ldap, NextDn);
  2724. FREE(NextDn);
  2725. }
  2726. }
  2727. ldap_msgfree(LdapMsg);
  2728. LdapMsg = NULL;
  2729. }
  2730. }
  2731. VOID
  2732. DumpSysVolWorld(
  2733. IN PLDAP Ldap
  2734. )
  2735. /*++
  2736. Routine Description:
  2737. Arguments:
  2738. Ldap
  2739. Return Value:
  2740. None.
  2741. --*/
  2742. {
  2743. PWCHAR DesiredAttrs[16];
  2744. PWCHAR NextDn = NULL;
  2745. PLDAPMessage LdapMsg = NULL;
  2746. PLDAPMessage LdapEntry = NULL;
  2747. PWCHAR ConfigDn = NULL;
  2748. PWCHAR SitesDn = NULL;
  2749. //
  2750. // Return all of the values for the attribute namingContexts
  2751. //
  2752. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  2753. if (!ConfigDn) {
  2754. return;
  2755. }
  2756. SitesDn = ExtendDn(ConfigDn, CN_SITES);
  2757. //
  2758. // Setting
  2759. //
  2760. DesiredAttrs[0] = ATTR_CN;
  2761. DesiredAttrs[1] = ATTR_DNS_HOST_NAME;
  2762. DesiredAttrs[2] = ATTR_DN;
  2763. DesiredAttrs[3] = ATTR_SERVER_REF;
  2764. DesiredAttrs[4] = ATTR_SERVER_REF_BL;
  2765. DesiredAttrs[5] = NULL;
  2766. if (LdapSearch(Ldap, SitesDn, LDAP_SCOPE_SUBTREE, CATEGORY_SERVER,
  2767. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2768. //
  2769. // Scan the entries returned from ldap_search
  2770. //
  2771. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2772. LdapEntry != NULL;
  2773. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2774. NextDn = DumpAttrs(Ldap, LdapEntry, SitesDn, DesiredAttrs, L"");
  2775. if (NextDn) {
  2776. FREE(NextDn);
  2777. }
  2778. NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
  2779. if (NextDn) {
  2780. DumpDsDsa(Ldap, NextDn);
  2781. FREE(NextDn);
  2782. }
  2783. }
  2784. ldap_msgfree(LdapMsg);
  2785. LdapMsg = NULL;
  2786. }
  2787. //out:
  2788. FREE(ConfigDn);
  2789. FREE(SitesDn);
  2790. }
  2791. VOID
  2792. ScriptCxtions(
  2793. IN PLDAP Ldap,
  2794. IN PWCHAR Set,
  2795. IN PWCHAR ServerDn
  2796. )
  2797. /*++
  2798. Routine Description:
  2799. Arguments:
  2800. Return Value:
  2801. None.
  2802. --*/
  2803. {
  2804. PWCHAR DesiredAttrs[16];
  2805. PLDAPMessage LdapMsg = NULL;
  2806. PLDAPMessage LdapEntry = NULL;
  2807. PWCHAR NextDn = NULL;
  2808. PWCHAR From = NULL;
  2809. PWCHAR Partner = NULL;
  2810. PWCHAR Partners = NULL;
  2811. PWCHAR Server = NULL;
  2812. PWCHAR Tmp = NULL;
  2813. Server = MakeRdn(ServerDn);
  2814. //
  2815. // Cxtions
  2816. //
  2817. DesiredAttrs[0] = ATTR_FROM_SERVER;
  2818. DesiredAttrs[1] = NULL;
  2819. if (LdapSearch(Ldap, ServerDn, LDAP_SCOPE_ONELEVEL, CATEGORY_CXTION,
  2820. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2821. //
  2822. // Scan the entries returned from ldap_search
  2823. //
  2824. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2825. LdapEntry != NULL;
  2826. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2827. From = FindValue(Ldap, LdapEntry, ATTR_FROM_SERVER);
  2828. if (From) {
  2829. Partner = MakeRdn(From);
  2830. if (Partner) {
  2831. if (Partners) {
  2832. Tmp = Partners;
  2833. Partners = FrsWcsCat(Tmp, L" ");
  2834. FREE(Tmp);
  2835. Tmp = Partners;
  2836. Partners = FrsWcsCat(Tmp, Partner);
  2837. FREE(Tmp);
  2838. FREE(Partner);
  2839. } else {
  2840. Partners = Partner;
  2841. }
  2842. }
  2843. FREE(From);
  2844. }
  2845. }
  2846. ldap_msgfree(LdapMsg);
  2847. LdapMsg = NULL;
  2848. }
  2849. if (Partners) {
  2850. printf("dstree /i %ws %ws %ws\n", Set, Server, Partners);
  2851. }
  2852. FREE(Server);
  2853. }
  2854. VOID
  2855. GetRootAndStage(
  2856. IN PLDAP Ldap,
  2857. IN PWCHAR SubscriberDn,
  2858. OUT PWCHAR *Root,
  2859. OUT PWCHAR *Stage
  2860. )
  2861. /*++
  2862. Routine Description:
  2863. Arguments:
  2864. Return Value:
  2865. None.
  2866. --*/
  2867. {
  2868. PWCHAR DesiredAttrs[16];
  2869. PLDAPMessage LdapMsg = NULL;
  2870. PLDAPMessage LdapEntry = NULL;
  2871. *Root = NULL;
  2872. *Stage = NULL;
  2873. //
  2874. // Subscriber
  2875. //
  2876. DesiredAttrs[0] = ATTR_REPLICA_ROOT;
  2877. DesiredAttrs[1] = ATTR_REPLICA_STAGE;
  2878. DesiredAttrs[2] = NULL;
  2879. if (LdapSearch(Ldap, SubscriberDn, LDAP_SCOPE_BASE, CATEGORY_SUBSCRIBER,
  2880. DesiredAttrs, 0, &LdapMsg, TRUE)) {
  2881. LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2882. if (LdapEntry) {
  2883. *Root = FindValue(Ldap, LdapEntry, ATTR_REPLICA_ROOT);
  2884. *Stage = FindValue(Ldap, LdapEntry, ATTR_REPLICA_STAGE);
  2885. }
  2886. ldap_msgfree(LdapMsg);
  2887. LdapMsg = NULL;
  2888. }
  2889. }
  2890. VOID
  2891. ScriptMembers(
  2892. IN PLDAP Ldap,
  2893. IN PWCHAR SetDn,
  2894. IN BOOL ScriptingServers
  2895. )
  2896. /*++
  2897. Routine Description:
  2898. Arguments:
  2899. Return Value:
  2900. None.
  2901. --*/
  2902. {
  2903. PWCHAR DesiredAttrs[16];
  2904. PLDAPMessage LdapMsg = NULL;
  2905. PLDAPMessage LdapEntry = NULL;
  2906. PWCHAR NextDn = NULL;
  2907. PWCHAR Set = NULL;
  2908. PWCHAR Cn = NULL;
  2909. PWCHAR Root = NULL;
  2910. PWCHAR Stage = NULL;
  2911. PWCHAR MemberBl = NULL;
  2912. Set = MakeRdn(SetDn);
  2913. //
  2914. // Servers
  2915. //
  2916. DesiredAttrs[0] = ATTR_CN;
  2917. DesiredAttrs[1] = ATTR_REPLICA_ROOT;
  2918. DesiredAttrs[2] = ATTR_REPLICA_STAGE;
  2919. DesiredAttrs[3] = ATTR_MEMBER_REF_BL;
  2920. DesiredAttrs[4] = NULL;
  2921. if (LdapSearch(Ldap, SetDn, LDAP_SCOPE_ONELEVEL, CATEGORY_MEMBER,
  2922. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2923. //
  2924. // Scan the entries returned from ldap_search
  2925. //
  2926. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2927. LdapEntry != NULL;
  2928. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2929. if (ScriptingServers) {
  2930. Cn = FindValue(Ldap, LdapEntry, ATTR_CN);
  2931. MemberBl = FindValue(Ldap, LdapEntry, ATTR_MEMBER_REF_BL);
  2932. if (MemberBl) {
  2933. GetRootAndStage(Ldap, MemberBl, &Root, &Stage);
  2934. }
  2935. if (Cn) {
  2936. if (Root && Stage) {
  2937. printf("dstree /c %ws %ws %ws %ws\n", Set, Cn, Root, Stage);
  2938. } else {
  2939. printf("dstree /c %ws %ws\n", Set, Cn);
  2940. }
  2941. FREE(Cn);
  2942. FREE(Root);
  2943. FREE(Stage);
  2944. FREE(MemberBl);
  2945. }
  2946. } else {
  2947. NextDn = GetNextDn(Ldap, LdapEntry, SetDn);
  2948. if (NextDn) {
  2949. ScriptCxtions(Ldap, Set, NextDn);
  2950. FREE(NextDn);
  2951. }
  2952. }
  2953. }
  2954. ldap_msgfree(LdapMsg);
  2955. LdapMsg = NULL;
  2956. }
  2957. FREE(Set);
  2958. }
  2959. VOID
  2960. ScriptSets(
  2961. IN PLDAP Ldap,
  2962. IN PWCHAR ParentDn
  2963. )
  2964. /*++
  2965. Routine Description:
  2966. Arguments:
  2967. Return Value:
  2968. None.
  2969. --*/
  2970. {
  2971. PWCHAR DesiredAttrs[16];
  2972. PLDAPMessage LdapMsg = NULL;
  2973. PLDAPMessage LdapEntry = NULL;
  2974. PWCHAR NextDn = NULL;
  2975. //
  2976. // Sets
  2977. //
  2978. DesiredAttrs[0] = ATTR_CN;
  2979. DesiredAttrs[1] = NULL;
  2980. if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_REPLICA_SET,
  2981. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  2982. //
  2983. // Scan the entries returned from ldap_search
  2984. //
  2985. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2986. LdapEntry != NULL;
  2987. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  2988. NextDn = GetNextDn(Ldap, LdapEntry, ParentDn);
  2989. if (NextDn) {
  2990. ScriptMembers(Ldap, NextDn, TRUE);
  2991. FREE(NextDn);
  2992. }
  2993. }
  2994. //
  2995. // Scan the entries returned from ldap_search
  2996. //
  2997. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  2998. LdapEntry != NULL;
  2999. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  3000. NextDn = GetNextDn(Ldap,
  3001. LdapEntry,
  3002. ParentDn);
  3003. if (NextDn) {
  3004. ScriptMembers(Ldap, NextDn, FALSE);
  3005. FREE(NextDn);
  3006. }
  3007. }
  3008. ldap_msgfree(LdapMsg);
  3009. LdapMsg = NULL;
  3010. }
  3011. }
  3012. VOID
  3013. ScriptReplicationWorld(
  3014. VOID
  3015. )
  3016. /*++
  3017. Routine Description:
  3018. Arguments:
  3019. None.
  3020. Return Value:
  3021. None.
  3022. --*/
  3023. {
  3024. PWCHAR DesiredAttrs[16];
  3025. PLDAP Ldap = NULL;
  3026. PWCHAR ConfigDn = NULL;
  3027. PWCHAR ServicesDn = NULL;
  3028. PWCHAR NextDn = NULL;
  3029. PWCHAR SettingsDn = NULL;
  3030. PLDAPMessage LdapMsg = NULL;
  3031. PLDAPMessage LdapEntry = NULL;
  3032. //
  3033. // Bind to the ds
  3034. //
  3035. Ldap = FrsDsOpenDs();
  3036. if (!Ldap) {
  3037. return;
  3038. }
  3039. //
  3040. // Services
  3041. //
  3042. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  3043. if (!ConfigDn) {
  3044. return;
  3045. }
  3046. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  3047. SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
  3048. ScriptSets(Ldap, SettingsDn);
  3049. #if 0
  3050. Don't script all of the settings; only the test settings
  3051. //
  3052. // Setting
  3053. //
  3054. DesiredAttrs[0] = ATTR_CN;
  3055. DesiredAttrs[1] = NULL;
  3056. if (LdapSearch(Ldap, ServicesDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTFRS_SETTINGS,
  3057. DesiredAttrs, 0, &LdapMsg, FALSE)) {
  3058. //
  3059. // Scan the entries returned from ldap_search
  3060. //
  3061. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  3062. LdapEntry != NULL;
  3063. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  3064. NextDn = GetNextDn(Ldap, LdapEntry, ServicesDn);
  3065. if (NextDn) {
  3066. ScriptSets(Ldap, NextDn);
  3067. FREE(NextDn);
  3068. }
  3069. }
  3070. ldap_msgfree(LdapMsg);
  3071. LdapMsg = NULL;
  3072. }
  3073. #endif 0
  3074. ldap_unbind(Ldap);
  3075. FREE(ServicesDn);
  3076. FREE(ConfigDn);
  3077. FREE(SettingsDn);
  3078. }
  3079. VOID
  3080. DoListSchema(
  3081. IN PLDAP Ldap,
  3082. IN PWCHAR SchemaDn,
  3083. IN struct AlterClass *Lists[]
  3084. )
  3085. /*++
  3086. Routine Description:
  3087. Dump schema
  3088. Arguments:
  3089. None.
  3090. Return Value:
  3091. None.
  3092. --*/
  3093. {
  3094. ULONG i, j;
  3095. ULONG NumAttrs;
  3096. DWORD LStatus;
  3097. PWCHAR Attrs[64];
  3098. PWCHAR Dn = NULL;
  3099. for (j = 0; Lists[j]; ++j) {
  3100. Dn = ExtendDn(SchemaDn, Lists[j]->Cn);
  3101. NumAttrs = 0;
  3102. for (i = 0; Lists[j]->AlterAttrs[i].Attr; ++i) {
  3103. if (NumAttrs) {
  3104. if (!wcscmp(Attrs[NumAttrs - 1],
  3105. Lists[j]->AlterAttrs[i].Attr)) {
  3106. continue;
  3107. }
  3108. }
  3109. Attrs[NumAttrs++] = Lists[j]->AlterAttrs[i].Attr;
  3110. }
  3111. if (NumAttrs) {
  3112. Attrs[NumAttrs + 0] = ATTR_DN;
  3113. Attrs[NumAttrs + 1] = ATTR_SYSTEM_FLAGS;
  3114. Attrs[NumAttrs + 2] = ATTR_SYSTEM_MAY_CONTAIN;
  3115. Attrs[NumAttrs + 3] = ATTR_SYSTEM_MUST_CONTAIN;
  3116. Attrs[NumAttrs + 4] = ATTR_SYSTEM_POSS_SUPERIORS;
  3117. Attrs[NumAttrs + 5] = NULL;
  3118. DumpValues(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY, Attrs, FALSE);
  3119. }
  3120. FREE(Dn);
  3121. }
  3122. }
  3123. VOID
  3124. ListSchema(
  3125. VOID
  3126. )
  3127. /*++
  3128. Routine Description:
  3129. Dump schema
  3130. Arguments:
  3131. None.
  3132. Return Value:
  3133. None.
  3134. --*/
  3135. {
  3136. ULONG i, j;
  3137. ULONG NumAttrs;
  3138. DWORD LStatus;
  3139. PLDAP Ldap = NULL;
  3140. PWCHAR SchemaDn = NULL;
  3141. PWCHAR Dn = NULL;
  3142. LDAPMod **Mod = NULL;
  3143. PWCHAR Attrs[64];
  3144. //
  3145. // Bind to the ds
  3146. //
  3147. Ldap = FrsDsOpenDs();
  3148. if (!Ldap) {
  3149. return;
  3150. }
  3151. SchemaDn = GetRootDn(Ldap, SCHEMA_NAMING_CONTEXT);
  3152. if (!SchemaDn) {
  3153. return;
  3154. }
  3155. DoListSchema(Ldap, SchemaDn, AlterSchema);
  3156. DoListSchema(Ldap, SchemaDn, CreateClasses);
  3157. DoListSchema(Ldap, SchemaDn, CreateAttributes);
  3158. ldap_unbind(Ldap);
  3159. FREE(SchemaDn);
  3160. }
  3161. VOID
  3162. CreateSchema(
  3163. IN PLDAP Ldap,
  3164. IN PWCHAR SchemaDn,
  3165. IN struct AlterClass *Creates[],
  3166. IN DWORD ExpectedError
  3167. )
  3168. /*++
  3169. Routine Description:
  3170. Arguments:
  3171. Return Value:
  3172. None.
  3173. --*/
  3174. {
  3175. DWORD LStatus;
  3176. ULONG i, j;
  3177. PWCHAR Dn = NULL;
  3178. LDAPMod **Mod = NULL;
  3179. //
  3180. // CREATE ATTRIBUTES OR CLASSES
  3181. //
  3182. for (j = 0; Creates[j]; ++j) {
  3183. Dn = ExtendDn(SchemaDn, Creates[j]->Cn);
  3184. printf(" %-30ws: CRE\n", Creates[j]->Cn);
  3185. for (i = 0; Creates[j]->AlterAttrs[i].Attr; ++i) {
  3186. AddMod(Creates[j]->AlterAttrs[i].Attr,
  3187. Creates[j]->AlterAttrs[i].Value,
  3188. &Mod);
  3189. }
  3190. LStatus = ldap_add_s(Ldap, Dn, Mod);
  3191. if (LStatus != LDAP_SUCCESS &&
  3192. LStatus != ExpectedError) {
  3193. fprintf(stderr, "%-30ws ERROR %ws\n",
  3194. L"", ldap_err2string(LStatus));
  3195. }
  3196. FreeMod(&Mod);
  3197. FREE(Dn);
  3198. }
  3199. }
  3200. VOID
  3201. UpdateSchema(
  3202. IN PLDAP Ldap,
  3203. IN PWCHAR SchemaDn,
  3204. IN BOOL Hammering,
  3205. IN struct AlterClass *Updates[]
  3206. )
  3207. /*++
  3208. Routine Description:
  3209. Arguments:
  3210. Return Value:
  3211. None.
  3212. --*/
  3213. {
  3214. DWORD LStatus;
  3215. ULONG i, j;
  3216. PWCHAR Dn = NULL;
  3217. LDAPMod **Mod = NULL;
  3218. //
  3219. // ALTER EXISTING CLASSES
  3220. //
  3221. for (j = 0; Updates[j]; ++j) {
  3222. Dn = ExtendDn(SchemaDn, Updates[j]->Cn);
  3223. for (i = 0; Updates[j]->AlterAttrs[i].Attr; ++i) {
  3224. AddMod(Updates[j]->AlterAttrs[i].Attr,
  3225. Updates[j]->AlterAttrs[i].Value,
  3226. &Mod);
  3227. if (Hammering) {
  3228. printf(" %-30ws: ADD %ws = %ws\n",
  3229. Updates[j]->Cn,
  3230. Updates[j]->AlterAttrs[i].Attr,
  3231. Updates[j]->AlterAttrs[i].Value);
  3232. LStatus = ldap_modify_s(Ldap, Dn, Mod);
  3233. if (LStatus != LDAP_SUCCESS &&
  3234. LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS) {
  3235. fprintf(stderr, "%-30ws ERROR %ws\n",
  3236. L"", ldap_err2string(LStatus));
  3237. }
  3238. } else {
  3239. printf(" %-30ws: DEL %ws = %ws\n",
  3240. Updates[j]->Cn,
  3241. Updates[j]->AlterAttrs[i].Attr,
  3242. Updates[j]->AlterAttrs[i].Value);
  3243. Mod[0]->mod_op = LDAP_MOD_DELETE;
  3244. LStatus = ldap_modify_s(Ldap, Dn, Mod);
  3245. if (LStatus != LDAP_SUCCESS &&
  3246. LStatus != LDAP_NO_SUCH_ATTRIBUTE &&
  3247. LStatus != LDAP_NO_SUCH_OBJECT) {
  3248. fprintf(stderr, "%-30ws ERROR %ws\n",
  3249. L"", ldap_err2string(LStatus));
  3250. }
  3251. }
  3252. FreeMod(&Mod);
  3253. }
  3254. FREE(Dn);
  3255. }
  3256. }
  3257. VOID
  3258. DeleteSchema(
  3259. IN PLDAP Ldap,
  3260. IN PWCHAR SchemaDn,
  3261. IN struct AlterClass *Deletes[],
  3262. IN DWORD ExpectedError
  3263. )
  3264. /*++
  3265. Routine Description:
  3266. Arguments:
  3267. Return Value:
  3268. None.
  3269. --*/
  3270. {
  3271. PWCHAR Dn = NULL;
  3272. DWORD LStatus;
  3273. ULONG j;
  3274. //
  3275. // DELETE ATTRIBUTES OR CLASSES
  3276. //
  3277. for (j = 0; Deletes[j]; ++j) {
  3278. Dn = ExtendDn(SchemaDn, Deletes[j]->Cn);
  3279. printf(" %-30ws: DEL\n", Deletes[j]->Cn);
  3280. LStatus = ldap_delete_s(Ldap, Dn);
  3281. if (LStatus != LDAP_SUCCESS &&
  3282. LStatus != ExpectedError) {
  3283. fprintf(stderr, "%-30ws ERROR %ws\n",
  3284. L"", ldap_err2string(LStatus));
  3285. }
  3286. FREE(Dn);
  3287. }
  3288. }
  3289. VOID
  3290. RefreshSchema(
  3291. IN PLDAP Ldap
  3292. )
  3293. /*++
  3294. Routine Description:
  3295. Arguments:
  3296. None.
  3297. Return Value:
  3298. None.
  3299. --*/
  3300. {
  3301. DWORD LStatus;
  3302. LDAPMod **Mod = NULL;
  3303. AddMod(L"schemaUpdateNow", L"1", &Mod);
  3304. LStatus = ldap_modify_s(Ldap, L"", Mod);
  3305. FreeMod(&Mod);
  3306. if (LStatus != LDAP_SUCCESS) {
  3307. fprintf(stderr, "Can't force schema update; %ws\n",
  3308. ldap_err2string(LStatus));
  3309. printf("Waiting 5 minutes for schema updates to take effect\n");
  3310. Sleep(5 * 60 * 1000);
  3311. }
  3312. }
  3313. #define NTDS_SERVICE L"NTDS"
  3314. #define NTDS_ROOT L"System\\CurrentControlSet\\Services\\" NTDS_SERVICE
  3315. #define NTDS_PARAMETERS NTDS_ROOT L"\\Parameters"
  3316. #define NTDS_UPDATE_SCHEMA L"Schema Update Allowed"
  3317. #define NTDS_DELETE_SCHEMA L"Schema Delete Allowed"
  3318. BOOL
  3319. PutRegDWord(
  3320. IN PWCHAR FQKey,
  3321. IN PWCHAR Value,
  3322. IN DWORD DWord
  3323. )
  3324. /*++
  3325. Routine Description:
  3326. This function writes a keyword value into the registry.
  3327. Arguments:
  3328. HKey - Key to be read
  3329. Param - value string to update
  3330. DWord - dword to be written
  3331. Return Value:
  3332. TRUE - Success
  3333. FALSE - Not
  3334. --*/
  3335. {
  3336. #define DEBSUB "PutRegDWord:"
  3337. HKEY HKey;
  3338. DWORD WStatus;
  3339. //
  3340. // Open the key
  3341. //
  3342. WStatus = RegOpenKey(HKEY_LOCAL_MACHINE, FQKey, &HKey);
  3343. if (!WIN_SUCCESS(WStatus)) {
  3344. fprintf(stderr, "[%ws] \"%ws\" Could not open. WStatus %d\n",
  3345. FQKey, Value, WStatus);
  3346. return FALSE;
  3347. }
  3348. //
  3349. //
  3350. // Write the value
  3351. //
  3352. WStatus = RegSetValueEx(HKey,
  3353. Value,
  3354. 0,
  3355. REG_DWORD,
  3356. (PUCHAR)&DWord,
  3357. sizeof(DWord));
  3358. if (!WIN_SUCCESS(WStatus)) {
  3359. fprintf(stderr, "%ws: Value not written; WStatus %d\n", Value, WStatus);
  3360. return FALSE;
  3361. }
  3362. return TRUE;
  3363. }
  3364. VOID
  3365. HammerSchema(
  3366. IN BOOL Hammering
  3367. )
  3368. /*++
  3369. Routine Description:
  3370. Arguments:
  3371. None.
  3372. Return Value:
  3373. None.
  3374. --*/
  3375. {
  3376. DWORD LStatus;
  3377. PLDAP Ldap = NULL;
  3378. PWCHAR SchemaDn = NULL;
  3379. PWCHAR Dn = NULL;
  3380. LDAPMod **Mod = NULL;
  3381. ULONG i, j;
  3382. if (Hammering) {
  3383. printf("UPDATING SCHEMA...\n");
  3384. if (!PutRegDWord(NTDS_PARAMETERS, NTDS_UPDATE_SCHEMA, 1)) {
  3385. fprintf(stderr, "Could not enable schema update\n");
  3386. return;
  3387. }
  3388. } else {
  3389. printf("RESTORING SCHEMA...\n");
  3390. if (!PutRegDWord(NTDS_PARAMETERS, NTDS_UPDATE_SCHEMA, 1)) {
  3391. fprintf(stderr, "Could not enable schema update\n");
  3392. return;
  3393. }
  3394. if (!PutRegDWord(NTDS_PARAMETERS, NTDS_DELETE_SCHEMA, 1)) {
  3395. fprintf(stderr, "Could not enable schema deletes\n");
  3396. return;
  3397. }
  3398. }
  3399. //
  3400. // Bind to the ds
  3401. //
  3402. Ldap = FrsDsOpenDs();
  3403. if (!Ldap) {
  3404. return;
  3405. }
  3406. SchemaDn = GetRootDn(Ldap, SCHEMA_NAMING_CONTEXT);
  3407. if (!SchemaDn) {
  3408. return;
  3409. }
  3410. //
  3411. // CREATE/DELETE ATTRIBUTES AND CLASSES
  3412. //
  3413. if (Hammering) {
  3414. CreateSchema(Ldap,
  3415. SchemaDn,
  3416. CreateAttributes,
  3417. LDAP_ALREADY_EXISTS);
  3418. RefreshSchema(Ldap);
  3419. CreateSchema(Ldap,
  3420. SchemaDn,
  3421. CreateClasses,
  3422. LDAP_ALREADY_EXISTS);
  3423. RefreshSchema(Ldap);
  3424. UpdateSchema(Ldap,
  3425. SchemaDn,
  3426. Hammering,
  3427. AlterSchema);
  3428. } else {
  3429. UpdateSchema(Ldap,
  3430. SchemaDn,
  3431. Hammering,
  3432. AlterSchema);
  3433. RefreshSchema(Ldap);
  3434. DeleteSchema(Ldap,
  3435. SchemaDn,
  3436. CreateClasses,
  3437. LDAP_NO_SUCH_OBJECT);
  3438. RefreshSchema(Ldap);
  3439. DeleteSchema(Ldap,
  3440. SchemaDn,
  3441. CreateAttributes,
  3442. LDAP_NO_SUCH_OBJECT);
  3443. }
  3444. RefreshSchema(Ldap);
  3445. if (Hammering) {
  3446. printf("SCHEMA UPDATE COMPLETE\n");
  3447. } else {
  3448. printf("SCHEMA RESTORE COMPLETE\n");
  3449. }
  3450. ldap_unbind(Ldap);
  3451. FREE(SchemaDn);
  3452. return;
  3453. }
  3454. PWCHAR
  3455. GetCoDn(
  3456. IN PLDAP Ldap,
  3457. IN PWCHAR Member,
  3458. OUT PWCHAR *ServerDn
  3459. )
  3460. /*++
  3461. Routine Description:
  3462. Find the computer object for Member
  3463. Arguments:
  3464. Ldap
  3465. Member
  3466. ServerDn
  3467. Return Value:
  3468. Dn of computer object or NULL. Free with FREE.
  3469. --*/
  3470. {
  3471. PWCHAR *Values = NULL;
  3472. PLDAPMessage LdapMsg = NULL;
  3473. PLDAPMessage LdapEntry = NULL;
  3474. PWCHAR CoDn = NULL;
  3475. PWCHAR Attrs[16];
  3476. WCHAR Filter[MAX_PATH + 1];
  3477. //
  3478. // Find the default naming context
  3479. //
  3480. Values = GetValues(Ldap, CN_ROOT, ATTR_DEFAULT_NAMING_CONTEXT, TRUE);
  3481. if (!Values) {
  3482. return NULL;
  3483. }
  3484. //
  3485. // Find the computer object with class=computer
  3486. //
  3487. swprintf(Filter,
  3488. L"(&%s(sAMAccountName=%s$))",
  3489. CATEGORY_COMPUTER,
  3490. Member);
  3491. Attrs[0] = ATTR_DN;
  3492. Attrs[1] = ATTR_SERVER_REF;
  3493. Attrs[2] = ATTR_SERVER_REF_BL;
  3494. Attrs[3] = NULL;
  3495. if (LdapSearch(Ldap, Values[0], LDAP_SCOPE_SUBTREE, Filter,
  3496. Attrs, 0, &LdapMsg, FALSE)) {
  3497. LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  3498. if (LdapEntry) {
  3499. CoDn = FindValue(Ldap, LdapEntry, ATTR_DN);
  3500. if (ServerDn) {
  3501. *ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF_BL);
  3502. if (!*ServerDn) {
  3503. *ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF);
  3504. }
  3505. }
  3506. }
  3507. ldap_msgfree(LdapMsg);
  3508. }
  3509. if (CoDn) {
  3510. return CoDn;
  3511. }
  3512. //
  3513. // Find the computer object with class=computer (possible after
  3514. // an NT4 to NT5 upgrade.
  3515. //
  3516. swprintf(Filter,
  3517. L"(&%s(sAMAccountName=%s$))",
  3518. CATEGORY_USER,
  3519. Member);
  3520. Attrs[0] = ATTR_DN;
  3521. Attrs[1] = ATTR_SERVER_REF;
  3522. Attrs[2] = ATTR_SERVER_REF_BL;
  3523. Attrs[3] = NULL;
  3524. if (LdapSearch(Ldap, Values[0], LDAP_SCOPE_SUBTREE, Filter,
  3525. Attrs, 0, &LdapMsg, FALSE)) {
  3526. LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  3527. if (LdapEntry) {
  3528. CoDn = FindValue(Ldap, LdapEntry, ATTR_DN);
  3529. if (ServerDn) {
  3530. *ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF_BL);
  3531. if (!*ServerDn) {
  3532. *ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF);
  3533. }
  3534. }
  3535. }
  3536. ldap_msgfree(LdapMsg);
  3537. }
  3538. ldap_value_free(Values);
  3539. return CoDn;
  3540. }
  3541. PWCHAR
  3542. GetSiteName(
  3543. IN PWCHAR Member
  3544. )
  3545. /*++
  3546. Routine Description:
  3547. Retrieve this machine's site name. We assume the site name
  3548. matches the site container's name in the DS.
  3549. Arguments:
  3550. Member - corresponds to site container's name
  3551. Return Value:
  3552. Site name or NULL. Free with FREE.
  3553. --*/
  3554. {
  3555. DWORD WStatus;
  3556. PWCHAR Name;
  3557. PWCHAR Site;
  3558. //
  3559. // Get this machine's DNS name
  3560. //
  3561. WStatus = DsGetSiteName(Member, &Name);
  3562. if (!WIN_SUCCESS(WStatus)) {
  3563. return NULL;
  3564. }
  3565. Site = FrsWcsDup(Name);
  3566. NetApiBufferFree(Name);
  3567. return Site;
  3568. }
  3569. PWCHAR
  3570. GetServerDn(
  3571. IN PLDAP Ldap,
  3572. IN PWCHAR Member
  3573. )
  3574. /*++
  3575. Routine Description:
  3576. Find our server object (assumes that machine name == server name)
  3577. Arguments:
  3578. Ldap
  3579. Member
  3580. Return Value:
  3581. Server DN (if any)
  3582. --*/
  3583. {
  3584. PWCHAR *Values = NULL;
  3585. PWCHAR ConfigDn = NULL;
  3586. PWCHAR SitesDn = NULL;
  3587. PWCHAR Site = NULL;
  3588. PWCHAR SiteDn = NULL;
  3589. PWCHAR ServersDn = NULL;
  3590. PWCHAR ServerDn = NULL;
  3591. PWCHAR SettingsDn = NULL;
  3592. PWCHAR RealServerDn = NULL;
  3593. //
  3594. // Return all of the values for the attribute namingContexts
  3595. //
  3596. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  3597. if (!ConfigDn) {
  3598. return NULL;
  3599. }
  3600. SitesDn = ExtendDn(ConfigDn, CN_SITES);
  3601. Site = GetSiteName(Member);
  3602. if (!Site) {
  3603. goto out;
  3604. }
  3605. SiteDn = ExtendDn(SitesDn, Site);
  3606. ServersDn = ExtendDn(SiteDn, CN_SERVERS);
  3607. ServerDn = ExtendDn(ServersDn, Member);
  3608. SettingsDn = ExtendDn(ServerDn, CN_NTDS_SETTINGS);
  3609. Values = GetValues(Ldap, SettingsDn, ATTR_DN, TRUE);
  3610. if (!Values) {
  3611. goto out;
  3612. }
  3613. RealServerDn = FrsWcsDup(Values[0]);
  3614. out:
  3615. FREE(ConfigDn);
  3616. FREE(SitesDn);
  3617. FREE(SiteDn);
  3618. FREE(Site);
  3619. FREE(ServersDn);
  3620. FREE(ServerDn);
  3621. FREE(SettingsDn);
  3622. return RealServerDn;
  3623. }
  3624. #define SIZEOF_EXTENSIONS 127
  3625. VOID
  3626. CreateReplicationWorld(
  3627. IN DWORD argc,
  3628. IN PWCHAR *Argv,
  3629. IN BOOL IsPrimary
  3630. )
  3631. /*++
  3632. Routine Description:
  3633. Create the required objects
  3634. Arguments:
  3635. Return Value:
  3636. None.
  3637. --*/
  3638. {
  3639. DWORD WStatus;
  3640. DWORD LStatus;
  3641. ULONG ScheduleLength;
  3642. PWCHAR Member;
  3643. PWCHAR Set;
  3644. PWCHAR Root;
  3645. PWCHAR Stage;
  3646. GUID NewGuid;
  3647. GUID OldGuid;
  3648. CHAR Extensions[SIZEOF_EXTENSIONS];
  3649. PLDAP Ldap = NULL;
  3650. PWCHAR CoDn = NULL;
  3651. PWCHAR SubsDn = NULL;
  3652. PWCHAR SubDn = NULL;
  3653. PWCHAR Subscriber = NULL;
  3654. PWCHAR ConfigDn = NULL;
  3655. PWCHAR ServerDn = NULL;
  3656. PWCHAR ServicesDn = NULL;
  3657. PWCHAR SettingsDn = NULL;
  3658. PWCHAR SetDn = NULL;
  3659. PWCHAR MemberDn = NULL;
  3660. PLDAPMessage LdapMsg = NULL;
  3661. PLDAPMessage LdapEntry = NULL;
  3662. PSCHEDULE Schedule = NULL;
  3663. PWCHAR Cn = NULL;
  3664. LDAPMod **Mod = NULL;
  3665. Set = Argv[2];
  3666. if (argc > 2) {
  3667. Member = Argv[3];
  3668. }
  3669. if (argc > 3) {
  3670. Root = Argv[4];
  3671. Stage = Argv[5];
  3672. }
  3673. //
  3674. // Bind to the ds
  3675. //
  3676. Ldap = FrsDsOpenDs();
  3677. if (!Ldap) {
  3678. return;
  3679. }
  3680. //
  3681. // ADMIN SIDE
  3682. //
  3683. //
  3684. // Services Dn
  3685. //
  3686. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  3687. if (!ConfigDn) {
  3688. return;
  3689. }
  3690. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  3691. SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
  3692. //
  3693. // Settings
  3694. //
  3695. UuidCreateNil(&OldGuid);
  3696. AddMod(ATTR_CLASS, ATTR_NTFRS_SETTINGS, &Mod);
  3697. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3698. LStatus = ldap_add_s(Ldap, SettingsDn, Mod);
  3699. FreeMod(&Mod);
  3700. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3701. //
  3702. // May be a new schema that lacks the old version guid
  3703. //
  3704. AddBerMod(ATTR_OLD_VERSION_GUID, (PCHAR)&OldGuid, sizeof(GUID), &Mod);
  3705. AddMod(ATTR_CLASS, ATTR_NTFRS_SETTINGS, &Mod);
  3706. // AddBerMod(ATTR_EXTENSIONS, Extensions, sizeof(SIZEOF_EXTENSIONS), &Mod);
  3707. LStatus = ldap_add_s(Ldap, SettingsDn, Mod);
  3708. FreeMod(&Mod);
  3709. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3710. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3711. SettingsDn, ldap_err2string(LStatus));
  3712. goto out;
  3713. }
  3714. }
  3715. //
  3716. // Set
  3717. //
  3718. SetDn = ExtendDn(SettingsDn, Set);
  3719. AddMod(ATTR_CLASS, ATTR_REPLICA_SET, &Mod);
  3720. AddMod(ATTR_SET_TYPE, FRS_RSTYPE_OTHERW, &Mod);
  3721. // AddMod(ATTR_DIRECTORY_FILTER, ATTR_DIRECTORY_FILTER, &Mod);
  3722. // AddMod(ATTR_FILE_FILTER, ATTR_FILE_FILTER, &Mod);
  3723. // AddMod(ATTR_DS_POLL, L"17", &Mod);
  3724. // AddMod(ATTR_FLAGS, L"18", &Mod);
  3725. // AddMod(ATTR_LEVEL_LIMIT, L"18", &Mod);
  3726. // AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
  3727. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3728. // AddBerMod(ATTR_NEW_SET_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
  3729. // AddBerMod(ATTR_NEW_VERSION_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
  3730. ConditionalBuildSchedule(&Schedule, &ScheduleLength);
  3731. if (Schedule) {
  3732. AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
  3733. }
  3734. LStatus = ldap_add_s(Ldap, SetDn, Mod);
  3735. FreeMod(&Mod);
  3736. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3737. //
  3738. // May be a new schema that lacks the old set guid
  3739. //
  3740. AddMod(ATTR_CLASS, ATTR_REPLICA_SET, &Mod);
  3741. AddMod(ATTR_SET_TYPE, FRS_RSTYPE_OTHERW, &Mod);
  3742. // AddMod(ATTR_DIRECTORY_FILTER, ATTR_DIRECTORY_FILTER, &Mod);
  3743. // AddMod(ATTR_FILE_FILTER, ATTR_FILE_FILTER, &Mod);
  3744. // AddMod(ATTR_DS_POLL, L"17", &Mod);
  3745. // AddMod(ATTR_FLAGS, L"18", &Mod);
  3746. // AddMod(ATTR_LEVEL_LIMIT, L"18", &Mod);
  3747. // AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
  3748. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3749. AddBerMod(ATTR_OLD_SET_GUID, (PCHAR)&OldGuid, sizeof(GUID), &Mod);
  3750. AddBerMod(ATTR_NEW_SET_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
  3751. AddBerMod(ATTR_NEW_VERSION_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
  3752. ConditionalBuildSchedule(&Schedule, &ScheduleLength);
  3753. if (Schedule) {
  3754. AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
  3755. }
  3756. LStatus = ldap_add_s(Ldap, SetDn, Mod);
  3757. FreeMod(&Mod);
  3758. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3759. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3760. SetDn, ldap_err2string(LStatus));
  3761. goto out;
  3762. }
  3763. }
  3764. if (argc < 4) {
  3765. goto out;
  3766. }
  3767. //
  3768. // Member
  3769. //
  3770. CoDn = GetCoDn(Ldap, Member, &ServerDn);
  3771. if (!CoDn) {
  3772. fprintf(stderr, "ERROR - Can't get computer object for %ws\n", Member);
  3773. goto out;
  3774. }
  3775. //
  3776. // The CO doesn't have a server reference; create one
  3777. //
  3778. if (!ServerDn) {
  3779. ServerDn = GetServerDn(Ldap, Member);
  3780. if (ServerDn) {
  3781. AddMod(ATTR_SERVER_REF, ServerDn, &Mod);
  3782. LStatus = ldap_modify_s(Ldap, CoDn, Mod);
  3783. FreeMod(&Mod);
  3784. if (LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS &&
  3785. LStatus != LDAP_SUCCESS) {
  3786. AddMod(ATTR_SERVER_REF, CoDn, &Mod);
  3787. LStatus = ldap_modify_s(Ldap, ServerDn, Mod);
  3788. FreeMod(&Mod);
  3789. if (LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS &&
  3790. LStatus != LDAP_SUCCESS) {
  3791. fprintf(stderr, "ERROR - Can't update server reference for %ws: %ws\n",
  3792. CoDn, ldap_err2string(LStatus));
  3793. fprintf(stderr, "ERROR - Server %ws\n", ServerDn);
  3794. FREE(ServerDn);
  3795. }
  3796. }
  3797. }
  3798. }
  3799. MemberDn = ExtendDn(SetDn, Member);
  3800. AddMod(ATTR_CLASS, ATTR_MEMBER, &Mod);
  3801. AddMod(ATTR_COMPUTER_REF, CoDn, &Mod);
  3802. // AddMod(ATTR_CONTROL_CREATION, ATTR_CONTROL_CREATION, &Mod);
  3803. // AddMod(ATTR_INBOUND_BACKLOG, ATTR_INBOUND_BACKLOG, &Mod);
  3804. // AddMod(ATTR_OUTBOUND_BACKLOG, ATTR_OUTBOUND_BACKLOG, &Mod);
  3805. // AddMod(ATTR_SERVICE_COMMAND, ATTR_SERVICE_COMMAND, &Mod);
  3806. // AddMod(ATTR_UPDATE_TIMEOUT, L"50", &Mod);
  3807. // AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
  3808. // AddMod(ATTR_FLAGS, L"3", &Mod);
  3809. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3810. if (ServerDn) {
  3811. AddMod(ATTR_SERVER_REF, ServerDn, &Mod);
  3812. }
  3813. LStatus = ldap_add_s(Ldap, MemberDn, Mod);
  3814. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3815. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3816. MemberDn, ldap_err2string(LStatus));
  3817. goto out;
  3818. }
  3819. FreeMod(&Mod);
  3820. //
  3821. // Primary member reference on set
  3822. //
  3823. if (IsPrimary) {
  3824. AddMod(ATTR_PRIMARY_MEMBER, MemberDn, &Mod);
  3825. Mod[0]->mod_op = LDAP_MOD_REPLACE;
  3826. LStatus = ldap_modify_s(Ldap, SetDn, Mod);
  3827. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3828. fprintf(stderr, "ERROR - Can't set primary member to %ws for %ws: %ws\n",
  3829. MemberDn, SetDn, ldap_err2string(LStatus));
  3830. goto out;
  3831. }
  3832. FreeMod(&Mod);
  3833. }
  3834. //
  3835. // USER SIDE
  3836. //
  3837. //
  3838. // Subscriptions
  3839. //
  3840. SubsDn = ExtendDn(CoDn, CN_SUBSCRIPTIONS);
  3841. AddMod(ATTR_CLASS, ATTR_SUBSCRIPTIONS, &Mod);
  3842. // AddMod(ATTR_WORKING, L"%SystemRoot%\\ntfrs", &Mod);
  3843. // AddMod(ATTR_VERSION, ATTR_VERSION, &Mod);
  3844. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3845. LStatus = ldap_add_s(Ldap, SubsDn, Mod);
  3846. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3847. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3848. SubsDn, ldap_err2string(LStatus));
  3849. goto out;
  3850. }
  3851. FreeMod(&Mod);
  3852. //
  3853. // Subscriber
  3854. //
  3855. Subscriber = FrsWcsCat(Set, Member);
  3856. SubDn = ExtendDn(SubsDn, Subscriber);
  3857. AddMod(ATTR_CLASS, ATTR_SUBSCRIBER, &Mod);
  3858. AddMod(ATTR_REPLICA_ROOT, Root, &Mod);
  3859. AddMod(ATTR_REPLICA_STAGE, Stage, &Mod);
  3860. AddMod(ATTR_MEMBER_REF, MemberDn, &Mod);
  3861. // AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
  3862. // AddMod(ATTR_FAULT_CONDITION, L"NONE", &Mod);
  3863. // AddMod(ATTR_FLAGS, L"1", &Mod);
  3864. // AddMod(ATTR_SERVICE_COMMAND, ATTR_SERVICE_COMMAND, &Mod);
  3865. // AddMod(ATTR_SERVICE_COMMAND_STATUS, L"100", &Mod);
  3866. // AddMod(ATTR_UPDATE_TIMEOUT, L"100", &Mod);
  3867. ConditionalBuildSchedule(&Schedule, &ScheduleLength);
  3868. if (Schedule) {
  3869. AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
  3870. FREE(Schedule);
  3871. }
  3872. LStatus = ldap_add_s(Ldap, SubDn, Mod);
  3873. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3874. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3875. SubDn, ldap_err2string(LStatus));
  3876. goto out;
  3877. }
  3878. FreeMod(&Mod);
  3879. out:
  3880. ldap_unbind(Ldap);
  3881. if (LdapMsg) {
  3882. ldap_msgfree(LdapMsg);
  3883. }
  3884. FREE(Schedule);
  3885. FREE(Cn);
  3886. FREE(ConfigDn);
  3887. FREE(ServicesDn);
  3888. FREE(SetDn);
  3889. FREE(SettingsDn);
  3890. FREE(MemberDn);
  3891. FREE(CoDn);
  3892. FREE(SubsDn);
  3893. FREE(Subscriber);
  3894. FREE(SubDn);
  3895. FREE(ServerDn);
  3896. FreeMod(&Mod);
  3897. }
  3898. PWCHAR DupNames[] = {L"_A", L"_B", L"_C", L"_D", L"_E", L"_F", L"_G", L"_H", NULL};
  3899. VOID
  3900. CreateInbounds(
  3901. IN DWORD argc,
  3902. IN WCHAR **Argv
  3903. )
  3904. /*++
  3905. Routine Description:
  3906. Arguments:
  3907. Return Value:
  3908. None.
  3909. --*/
  3910. {
  3911. ULONG i;
  3912. DWORD LStatus;
  3913. ULONG ScheduleLength;
  3914. ULONG dupx;
  3915. PLDAP Ldap = NULL;
  3916. PWCHAR Cxtion = NULL;
  3917. PWCHAR ConfigDn = NULL;
  3918. PWCHAR ServicesDn = NULL;
  3919. PWCHAR SettingsDn = NULL;
  3920. PWCHAR SetDn = NULL;
  3921. PWCHAR ServerDn = NULL;
  3922. PWCHAR CxtionDn = NULL;
  3923. PWCHAR CxtionDnDup = NULL;
  3924. PWCHAR PartnerDn = NULL;
  3925. PLDAPMessage LdapMsg = NULL;
  3926. PLDAPMessage LdapEntry = NULL;
  3927. PSCHEDULE Schedule = NULL;
  3928. LDAPMod **Mod = NULL;
  3929. //
  3930. // Bind to the ds
  3931. //
  3932. Ldap = FrsDsOpenDs();
  3933. if (!Ldap) {
  3934. return;
  3935. }
  3936. //
  3937. // Server Dn
  3938. //
  3939. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  3940. if (!ConfigDn) {
  3941. return;
  3942. }
  3943. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  3944. SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
  3945. SetDn = ExtendDn(SettingsDn, Argv[2]);
  3946. ServerDn = ExtendDn(SetDn, Argv[3]);
  3947. for (i = 4; i < argc; ++i) {
  3948. PartnerDn = ExtendDn(SetDn, Argv[i]);
  3949. Cxtion = FrsWcsCat(L"From_", Argv[i]);
  3950. CxtionDn = ExtendDn(ServerDn, Cxtion);
  3951. FREE(Cxtion);
  3952. //
  3953. // Inbounds
  3954. //
  3955. AddMod(ATTR_CLASS, ATTR_CXTION, &Mod);
  3956. AddMod(ATTR_FROM_SERVER, PartnerDn, &Mod);
  3957. AddMod(ATTR_ENABLED_CXTION, ATTR_TRUE, &Mod);
  3958. AddMod(ATTR_OPTIONS, ATTR_OPTIONS_0, &Mod);
  3959. ConditionalBuildSchedule(&Schedule, &ScheduleLength);
  3960. if (Schedule) {
  3961. AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
  3962. FREE(Schedule);
  3963. }
  3964. LStatus = ldap_add_s(Ldap, CxtionDn, Mod);
  3965. dupx = 0;
  3966. while ((LStatus == LDAP_ALREADY_EXISTS) && (DupNames[dupx] != NULL)) {
  3967. //
  3968. // Try to create a duplicate connection object by putting a suffix on the name.
  3969. //
  3970. Cxtion = FrsWcsCat(L"From_", Argv[i]);
  3971. CxtionDnDup = FrsWcsCat(Cxtion, DupNames[dupx]);
  3972. CxtionDn = ExtendDn(ServerDn, CxtionDnDup);
  3973. FREE(Cxtion);
  3974. FREE(CxtionDnDup);
  3975. LStatus = ldap_add_s(Ldap, CxtionDn, Mod);
  3976. if (LStatus != LDAP_ALREADY_EXISTS) {
  3977. //
  3978. // Dup cxtion created.
  3979. //
  3980. break;
  3981. }
  3982. dupx++;
  3983. }
  3984. if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
  3985. fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
  3986. CxtionDn, ldap_err2string(LStatus));
  3987. }
  3988. FreeMod(&Mod);
  3989. FREE(PartnerDn);
  3990. FREE(CxtionDn);
  3991. }
  3992. FREE(ServerDn);
  3993. FREE(SetDn);
  3994. FREE(SettingsDn);
  3995. FREE(ServicesDn);
  3996. FREE(ConfigDn);
  3997. if (Ldap) {
  3998. ldap_unbind(Ldap);
  3999. }
  4000. }
  4001. BOOL
  4002. DeleteUserSubTree(
  4003. IN PLDAP Ldap,
  4004. IN PWCHAR Dn
  4005. )
  4006. /*++
  4007. Routine Description:
  4008. Arguments:
  4009. Return Value:
  4010. --*/
  4011. {
  4012. DWORD LStatus;
  4013. PWCHAR DesiredAttrs[16];
  4014. PWCHAR Bl = NULL;
  4015. PWCHAR Co = NULL;
  4016. PWCHAR SubsDn = NULL;
  4017. PLDAPMessage LdapMsg = NULL;
  4018. PLDAPMessage LdapEntry = NULL;
  4019. DesiredAttrs[0] = ATTR_MEMBER_REF_BL;
  4020. DesiredAttrs[1] = ATTR_COMPUTER_REF;
  4021. DesiredAttrs[2] = ATTR_CLASS;
  4022. DesiredAttrs[3] = NULL;
  4023. LStatus = ldap_search_s(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY,
  4024. DesiredAttrs, 0, &LdapMsg);
  4025. if (LStatus == LDAP_SUCCESS) {
  4026. LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  4027. Co = FindValue(Ldap, LdapEntry, ATTR_COMPUTER_REF);
  4028. Bl = FindValue(Ldap, LdapEntry, ATTR_MEMBER_REF_BL);
  4029. if (Bl && Dn) {
  4030. LStatus = ldap_delete_s(Ldap, Bl);
  4031. if (LStatus != LDAP_SUCCESS && LStatus != LDAP_NO_SUCH_OBJECT) {
  4032. fprintf(stderr, "ERROR - Can't delete BL: %ws\n",
  4033. ldap_err2string(LStatus));
  4034. fprintf(stderr, " %ws\n", Dn);
  4035. fprintf(stderr, " BL %ws\n", Bl);
  4036. FREE(Bl);
  4037. FREE(Dn);
  4038. FREE(Co);
  4039. return FALSE;
  4040. }
  4041. }
  4042. if (Co) {
  4043. SubsDn = ExtendDn(Co, CN_SUBSCRIPTIONS);
  4044. LStatus = ldap_delete_s(Ldap, SubsDn);
  4045. if (LStatus != LDAP_NO_SUCH_OBJECT &&
  4046. LStatus != LDAP_SUCCESS &&
  4047. LStatus != LDAP_NOT_ALLOWED_ON_NONLEAF) {
  4048. fprintf(stderr, "ERROR - Can't delete: %ws\n", ldap_err2string(LStatus));
  4049. fprintf(stderr, " %ws\n", SubsDn);
  4050. FREE(SubsDn);
  4051. FREE(Bl);
  4052. FREE(Dn);
  4053. FREE(Co);
  4054. return FALSE;
  4055. }
  4056. FREE(SubsDn);
  4057. }
  4058. FREE(Bl);
  4059. FREE(Dn);
  4060. FREE(Co);
  4061. ldap_msgfree(LdapMsg);
  4062. } else if (LStatus != LDAP_NO_SUCH_OBJECT) {
  4063. fprintf(stderr, "ERROR - Can't find: %ws\n", ldap_err2string(LStatus));
  4064. fprintf(stderr, " %ws\n", Dn);
  4065. }
  4066. return TRUE;
  4067. }
  4068. VOID
  4069. FrsDsDeleteSubTree(
  4070. IN PLDAP Ldap,
  4071. IN PWCHAR ParentDn
  4072. )
  4073. /*++
  4074. Routine Description:
  4075. Arguments:
  4076. None.
  4077. Return Value:
  4078. None.
  4079. --*/
  4080. {
  4081. DWORD LStatus;
  4082. PWCHAR DesiredAttrs[16];
  4083. PWCHAR NextDn = NULL;
  4084. PLDAPMessage LdapMsg = NULL;
  4085. PLDAPMessage LdapEntry = NULL;
  4086. DesiredAttrs[0] = ATTR_DN;
  4087. DesiredAttrs[1] = NULL;
  4088. LStatus = ldap_search_s(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_ANY,
  4089. DesiredAttrs, 0, &LdapMsg);
  4090. if (LStatus == LDAP_SUCCESS) {
  4091. //
  4092. // Scan the entries returned from ldap_search
  4093. //
  4094. for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
  4095. LdapEntry != NULL;
  4096. LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
  4097. NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
  4098. if (NextDn) {
  4099. FrsDsDeleteSubTree(Ldap, NextDn);
  4100. FREE(NextDn);
  4101. }
  4102. }
  4103. ldap_msgfree(LdapMsg);
  4104. if (DeleteUserSubTree(Ldap, ParentDn)) {
  4105. LStatus = ldap_delete_s(Ldap, ParentDn);
  4106. if (LStatus != LDAP_SUCCESS) {
  4107. fprintf(stderr, "ERROR - Can't delete: %ws\n", ldap_err2string(LStatus));
  4108. fprintf(stderr, " %ws\n", ParentDn);
  4109. }
  4110. }
  4111. } else if (LStatus != LDAP_NO_SUCH_OBJECT) {
  4112. fprintf(stderr, "ERROR - Can't find: %ws\n", ldap_err2string(LStatus));
  4113. fprintf(stderr, " %ws\n", ParentDn);
  4114. }
  4115. }
  4116. VOID
  4117. DeleteReplicationWorld(
  4118. IN DWORD argc,
  4119. IN PWCHAR *Argv,
  4120. IN PWCHAR Settings
  4121. )
  4122. /*++
  4123. Routine Description:
  4124. Create the required objects
  4125. Arguments:
  4126. None.
  4127. Return Value:
  4128. None.
  4129. --*/
  4130. {
  4131. PWCHAR Dn;
  4132. PWCHAR ConfigDn = NULL;
  4133. PWCHAR ServicesDn = NULL;
  4134. PWCHAR SettingsDn = NULL;
  4135. PWCHAR SetDn = NULL;
  4136. PWCHAR ServerDn = NULL;
  4137. PWCHAR Cxtion = NULL;
  4138. PWCHAR CxtionDn = NULL;
  4139. PLDAP Ldap = NULL;
  4140. //
  4141. // Bind to the ds
  4142. //
  4143. Ldap = FrsDsOpenDs();
  4144. if (!Ldap) {
  4145. return;
  4146. }
  4147. //
  4148. // Services
  4149. //
  4150. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  4151. if (!ConfigDn) {
  4152. return;
  4153. }
  4154. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  4155. SettingsDn = ExtendDn(ServicesDn, Settings);
  4156. Dn = SettingsDn;
  4157. if (argc > 2) {
  4158. SetDn = ExtendDn(SettingsDn, Argv[2]);
  4159. Dn = SetDn;
  4160. }
  4161. if (argc > 3) {
  4162. ServerDn = ExtendDn(SetDn, Argv[3]);
  4163. Dn = ServerDn;
  4164. }
  4165. if (argc > 4) {
  4166. Cxtion = FrsWcsCat(L"From_", Argv[4]);
  4167. CxtionDn = ExtendDn(ServerDn, Cxtion);
  4168. Dn = CxtionDn;
  4169. }
  4170. FrsDsDeleteSubTree(Ldap, Dn);
  4171. // out:
  4172. ldap_unbind(Ldap);
  4173. FREE(CxtionDn);
  4174. FREE(Cxtion);
  4175. FREE(ServerDn);
  4176. FREE(SetDn);
  4177. FREE(SettingsDn);
  4178. FREE(ServicesDn);
  4179. FREE(ConfigDn);
  4180. }
  4181. VOID
  4182. ModifyFilter(
  4183. IN DWORD argc,
  4184. IN PWCHAR *Argv
  4185. )
  4186. /*++
  4187. Routine Description:
  4188. Change the file and directory filter for the replica set specified.
  4189. Arguments:
  4190. argc - From main
  4191. argv - From main
  4192. Return Value:
  4193. None.
  4194. --*/
  4195. {
  4196. DWORD LStatus = LDAP_SUCCESS;
  4197. PWCHAR Set;
  4198. PWCHAR NewFilter;
  4199. PWCHAR ConfigDn = NULL;
  4200. PWCHAR ServicesDn = NULL;
  4201. PWCHAR SettingsDn = NULL;
  4202. PWCHAR SetDn = NULL;
  4203. PLDAP Ldap = NULL;
  4204. LDAPMod **Mod = NULL;
  4205. Set = Argv[3];
  4206. if(argc > 4){
  4207. NewFilter = Argv[4];
  4208. }
  4209. else{
  4210. NewFilter = L" ";
  4211. }
  4212. //
  4213. // Bind to the ds
  4214. //
  4215. Ldap = FrsDsOpenDs();
  4216. if (!Ldap) {
  4217. return;
  4218. }
  4219. //
  4220. // ADMIN SIDE
  4221. //
  4222. //
  4223. // Services Dn
  4224. //
  4225. ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
  4226. if (!ConfigDn) {
  4227. return;
  4228. }
  4229. ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
  4230. SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
  4231. SetDn = ExtendDn(SettingsDn, Set);
  4232. if(!wcscmp(Argv[2],L"/clear")){
  4233. if(!wcscmp(Argv[1],L"/dirfilter")){
  4234. AddMod(ATTR_DIRECTORY_FILTER, L" ", &Mod);
  4235. (*Mod)->mod_op = LDAP_MOD_REPLACE;
  4236. }
  4237. else {
  4238. AddMod(ATTR_FILE_FILTER, L" ", &Mod);
  4239. (*Mod)->mod_op = LDAP_MOD_REPLACE;
  4240. }
  4241. LStatus = ldap_modify_s(Ldap, SetDn, Mod);
  4242. }
  4243. else if(!wcscmp(Argv[2],L"/set")){
  4244. if(!wcscmp(Argv[1],L"/dirfilter")){
  4245. AddMod(ATTR_DIRECTORY_FILTER, NewFilter, &Mod);
  4246. (*Mod)->mod_op = LDAP_MOD_REPLACE;
  4247. }
  4248. else {
  4249. AddMod(ATTR_FILE_FILTER, NewFilter, &Mod);
  4250. (*Mod)->mod_op = LDAP_MOD_REPLACE;
  4251. }
  4252. LStatus = ldap_modify_s(Ldap, SetDn, Mod);
  4253. }
  4254. else {
  4255. // Usage(Argv);
  4256. }
  4257. if (LStatus != LDAP_SUCCESS) {
  4258. fprintf(stderr, "Can't change filter; %ws\n",
  4259. ldap_err2string(LStatus));
  4260. }
  4261. FreeMod(&Mod);
  4262. ldap_unbind(Ldap);
  4263. FREE(SetDn);
  4264. FREE(SettingsDn);
  4265. FREE(ServicesDn);
  4266. FREE(ConfigDn);
  4267. }
  4268. PWCHAR *
  4269. ConvertArgv(
  4270. DWORD argc,
  4271. PCHAR *argv
  4272. )
  4273. /*++
  4274. Routine Description:
  4275. Convert short char argv into wide char argv
  4276. Arguments:
  4277. argc - From main
  4278. argv - From main
  4279. Return Value:
  4280. Address of the new argv
  4281. --*/
  4282. {
  4283. PWCHAR *wideargv;
  4284. wideargv = (PWCHAR *)malloc((argc + 1) * sizeof(PWCHAR));
  4285. wideargv[argc] = NULL;
  4286. while (argc-- >= 1) {
  4287. wideargv[argc] = (PWCHAR)malloc((strlen(argv[argc]) + 1) * sizeof(WCHAR));
  4288. wsprintf(wideargv[argc], L"%hs", argv[argc]);
  4289. // _wcslwr(wideargv[argc]);
  4290. }
  4291. return wideargv;
  4292. }
  4293. VOID
  4294. Usage(
  4295. IN PWCHAR *Argv
  4296. )
  4297. /*++
  4298. Routine Description:
  4299. Usage messages.
  4300. Arguments:
  4301. None.
  4302. Return Value:
  4303. None.
  4304. --*/
  4305. {
  4306. printf("%-24s%ws\n", "Pretty Print", Argv[0]);
  4307. printf("%-24s%ws /dumpcontexts\n", "dumpcontexts", Argv[0]);
  4308. printf("%-24s%ws /dumpcomputers\n", "dumpcomputers", Argv[0]);
  4309. printf("%-24s%ws /dumpservers\n", "dumpservers", Argv[0]);
  4310. printf("%-24s%ws /dumpsets\n", "dumpsets", Argv[0]);
  4311. printf("%-24s%ws /?\n", "Help", Argv[0]);
  4312. printf("%-24s%ws /h\n", "Hammer the schema", Argv[0]);
  4313. printf("%-24s%ws /r\n", "Restore the schema", Argv[0]);
  4314. printf("%-24s%ws /l\n", "List the schema", Argv[0]);
  4315. printf("%-24s%ws /s\n", "Produce script", Argv[0]);
  4316. printf("%-24s%ws /d [Set [Server [Partner]]]\n", "Delete", Argv[0]);
  4317. printf("%-24s%ws /c Set [Server [Root Stage]]\n", "Create sets and servers", Argv[0]);
  4318. printf("%-24s%ws /i Set Server Partner ...\n", "Create inbound cxtions", Argv[0]);
  4319. printf("%-24s%ws [/filefilter |/dirfilter] [/set |/clear] Set FilterString\n", "Modify filters", Argv[0]);
  4320. fflush(stdout);
  4321. ExitProcess(0);
  4322. }
  4323. #define DUMP_ALL (0)
  4324. #define DUMP_CONTEXTS (1)
  4325. #define DUMP_SETS (2)
  4326. #define DUMP_COMPUTERS (3)
  4327. #define DUMP_SERVERS (4)
  4328. VOID
  4329. DumpWorld(
  4330. DWORD Dump
  4331. )
  4332. /*++
  4333. Routine Description:
  4334. Dump every ds object related to replication
  4335. Arguments:
  4336. Dump - what to dump.
  4337. Return Value:
  4338. None.
  4339. --*/
  4340. {
  4341. PLDAP Ldap;
  4342. //
  4343. // Bind to the ds
  4344. //
  4345. Ldap = FrsDsOpenDs();
  4346. if (!Ldap) {
  4347. return;
  4348. }
  4349. if (Dump == DUMP_ALL || Dump == DUMP_CONTEXTS) {
  4350. printf("***** CONTEXTS\n");
  4351. DumpContexts(Ldap);
  4352. }
  4353. if (Dump == DUMP_ALL || Dump == DUMP_SETS) {
  4354. printf("***** REPLICA SETS\n");
  4355. DumpAdminWorld(Ldap);
  4356. }
  4357. if (Dump == DUMP_ALL || Dump == DUMP_COMPUTERS) {
  4358. printf("\n***** COMPUTERS\n");
  4359. DumpUserWorld(Ldap);
  4360. }
  4361. if (Dump == DUMP_ALL || Dump == DUMP_SERVERS) {
  4362. printf("\n***** SERVERS\n");
  4363. DumpSysVolWorld(Ldap);
  4364. }
  4365. ldap_unbind(Ldap);
  4366. }
  4367. VOID _cdecl
  4368. main(
  4369. IN DWORD argc,
  4370. IN PCHAR *argv
  4371. )
  4372. /*++
  4373. Routine Description:
  4374. Get access to the DS via ldap. Then read command lines from standard
  4375. in, parse them, and ship them off to the command subroutines. The
  4376. command line is:
  4377. command,site,settings,server,connection,fromserver
  4378. command is any of add|delete|list|show|quit. Leading whitespace is
  4379. ignored. Whitespace between commas counts. The command line can
  4380. stop anytime after "command" and the command will on be applied
  4381. to that portion of the "Distinquished Name".
  4382. Arguments:
  4383. None.
  4384. Return Value:
  4385. Exits with 0 if everything went okay. Otherwise, 1.
  4386. --*/
  4387. {
  4388. PWCHAR *Argv;
  4389. ULONG i;
  4390. ULONG OptLen;
  4391. Argv = ConvertArgv(argc, argv);
  4392. if (argc == 1) {
  4393. DumpWorld(DUMP_ALL);
  4394. fflush(stdout);
  4395. ExitProcess(0);
  4396. }
  4397. for (i = 1; i < argc; ++i) {
  4398. OptLen = wcslen(Argv[i]);
  4399. if (OptLen == 2 &&
  4400. ((wcsstr(Argv[i], L"/?") == Argv[i]) ||
  4401. (wcsstr(Argv[i], L"-?") == Argv[i]))) {
  4402. Usage(Argv);
  4403. } else if (OptLen == 2 &&
  4404. ((wcsstr(Argv[i], L"/s") == Argv[i]) ||
  4405. (wcsstr(Argv[i], L"-s") == Argv[i]))) {
  4406. ScriptReplicationWorld();
  4407. fflush(stdout);
  4408. ExitProcess(0);
  4409. } else if (OptLen == 2 &&
  4410. ((wcsstr(Argv[i], L"/d") == Argv[i]) ||
  4411. (wcsstr(Argv[i], L"-d") == Argv[i]))) {
  4412. if (argc < 2 || argc > 5) {
  4413. Usage(Argv);
  4414. }
  4415. DeleteReplicationWorld(argc, Argv, CN_TEST_SETTINGS);
  4416. fflush(stdout);
  4417. ExitProcess(0);
  4418. } else if (OptLen == 9 &&
  4419. ((wcsstr(Argv[i], L"/dsysvols") == Argv[i]) ||
  4420. (wcsstr(Argv[i], L"-dsysvols") == Argv[i]))) {
  4421. if (argc < 2 || argc > 5) {
  4422. Usage(Argv);
  4423. }
  4424. DeleteReplicationWorld(argc, Argv, CN_SYSVOLS);
  4425. fflush(stdout);
  4426. ExitProcess(0);
  4427. } else if (OptLen == 2 &&
  4428. ((wcsstr(Argv[i], L"/h") == Argv[i]) ||
  4429. (wcsstr(Argv[i], L"-h") == Argv[i]))) {
  4430. HammerSchema(TRUE);
  4431. fflush(stdout);
  4432. ExitProcess(0);
  4433. } else if (OptLen == 2 &&
  4434. ((wcsstr(Argv[i], L"/r") == Argv[i]) ||
  4435. (wcsstr(Argv[i], L"-r") == Argv[i]))) {
  4436. HammerSchema(FALSE);
  4437. fflush(stdout);
  4438. ExitProcess(0);
  4439. } else if (OptLen == 2 &&
  4440. ((wcsstr(Argv[i], L"/l") == Argv[i]) ||
  4441. (wcsstr(Argv[i], L"-l") == Argv[i]))) {
  4442. ListSchema();
  4443. fflush(stdout);
  4444. ExitProcess(0);
  4445. } else if (OptLen == 2 &&
  4446. ((wcsstr(Argv[i], L"/i") == Argv[i]) ||
  4447. (wcsstr(Argv[i], L"-i") == Argv[i]))) {
  4448. if (argc < 5) {
  4449. Usage(Argv);
  4450. }
  4451. CreateInbounds(argc, Argv);
  4452. fflush(stdout);
  4453. ExitProcess(0);
  4454. } else if (OptLen == 2 &&
  4455. ((wcsstr(Argv[i], L"/c") == Argv[i]) ||
  4456. (wcsstr(Argv[i], L"-c") == Argv[i]))) {
  4457. if (argc != 2 && argc != 3 && argc != 6) {
  4458. Usage(Argv);
  4459. }
  4460. CreateReplicationWorld(argc, Argv, FALSE);
  4461. fflush(stdout);
  4462. ExitProcess(0);
  4463. } else if (OptLen == 3 &&
  4464. ((wcsstr(Argv[i], L"/cp") == Argv[i]) ||
  4465. (wcsstr(Argv[i], L"-cp") == Argv[i]))) {
  4466. if (argc != 2 && argc != 3 && argc != 6) {
  4467. Usage(Argv);
  4468. }
  4469. CreateReplicationWorld(argc, Argv, TRUE);
  4470. fflush(stdout);
  4471. ExitProcess(0);
  4472. } else if (OptLen >= 10 &&
  4473. ((wcsstr(Argv[i], L"/filefilter") == Argv[i]) ||
  4474. (wcsstr(Argv[i], L"-filefilter") == Argv[i]) ||
  4475. (wcsstr(Argv[i], L"/dirfilter") == Argv[i]) ||
  4476. (wcsstr(Argv[i], L"-dirfilter") == Argv[i]))) {
  4477. if (argc != 4 && argc != 5) {
  4478. Usage(Argv);
  4479. }
  4480. ModifyFilter(argc, Argv);
  4481. fflush(stdout);
  4482. ExitProcess(0);
  4483. } else if ((wcsstr(Argv[i], L"/dumpcontexts") == Argv[i]) ||
  4484. (wcsstr(Argv[i], L"-dumpcontexts") == Argv[i])) {
  4485. DumpWorld(DUMP_CONTEXTS);
  4486. fflush(stdout);
  4487. ExitProcess(0);
  4488. } else if ((wcsstr(Argv[i], L"/dumpsets") == Argv[i]) ||
  4489. (wcsstr(Argv[i], L"-dumpsets") == Argv[i])) {
  4490. DumpWorld(DUMP_SETS);
  4491. fflush(stdout);
  4492. ExitProcess(0);
  4493. } else if ((wcsstr(Argv[i], L"/dumpcomputers") == Argv[i]) ||
  4494. (wcsstr(Argv[i], L"-dumpcomputers") == Argv[i])) {
  4495. DumpWorld(DUMP_COMPUTERS);
  4496. fflush(stdout);
  4497. ExitProcess(0);
  4498. } else if ((wcsstr(Argv[i], L"/dumpservers") == Argv[i]) ||
  4499. (wcsstr(Argv[i], L"-dumpservers") == Argv[i])) {
  4500. DumpWorld(DUMP_SERVERS);
  4501. fflush(stdout);
  4502. ExitProcess(0);
  4503. } else if ((wcsstr(Argv[i], L"/") == Argv[i]) ||
  4504. (wcsstr(Argv[i], L"-") == Argv[i])) {
  4505. fprintf(stderr, "ERROR - Don't understand %ws\n", Argv[i]);
  4506. Usage(Argv);
  4507. } else {
  4508. Usage(Argv);
  4509. }
  4510. }
  4511. fflush(stdout);
  4512. ExitProcess(0);
  4513. }