5022 lines
141 KiB
C++
5022 lines
141 KiB
C++
/*++
|
||
|
||
Copyright (c) 1997-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
dstree.cxx
|
||
|
||
Abstract:
|
||
This module is a development tool. It creates dummy entries in the DS.
|
||
The file replication service treats the dummy entries as a topology.
|
||
Without this tool, creating interesting topologies would require many
|
||
more machines than I have on hand.
|
||
|
||
The command is run as, "dstree <command-file". command-file is a list
|
||
of command lines and comment lines.
|
||
|
||
Command lines are read from standard in, parsed, and then shipped
|
||
off to the command subroutines. The command line syntax is:
|
||
command,site,settings,server,connection,fromserver
|
||
"command" is any of add|delete|list|show|quit. Leading whitespace is
|
||
ignored. Whitespace between commas counts. The comma separated strings
|
||
following "command" are optional. The command line can stop anytime
|
||
after "command" and the command will on be applied to that portion
|
||
of the "Distinquished Name".
|
||
|
||
Comment lines are empty lines or lines that begin with /, #, or !.
|
||
The files dstree.add and dstree.del are command files. They create
|
||
and delete a bogus topology.
|
||
|
||
Author:
|
||
Billy J. Fuller 3-Mar-1997 (From Jim McNelis)
|
||
|
||
Environment
|
||
User mode winnt
|
||
|
||
--*/
|
||
#include <ntreppch.h>
|
||
#pragma hdrstop
|
||
#include <frs.h>
|
||
#include <lmcons.h>
|
||
#include <lmapibuf.h>
|
||
#include <winsock2.h>
|
||
#include <ntdsapi.h>
|
||
|
||
#define FREE(_x_) { if (_x_) free(_x_); _x_ = NULL; }
|
||
|
||
|
||
//
|
||
// Some useful DS object classes and object attributes
|
||
// that are not included in frs.h
|
||
//
|
||
#define CN_TEST_SETTINGS L"NTFRS Test Settings"
|
||
#define ATTR_SYSTEM_FLAGS L"systemFlags"
|
||
#define ATTR_SYSTEM_MAY_CONTAIN L"systemMayContain"
|
||
#define ATTR_SYSTEM_MUST_CONTAIN L"systemMustContain"
|
||
#define ATTR_SYSTEM_POSS_SUPERIORS L"systemPossSuperiors"
|
||
#define SCHEMA_NAMING_CONTEXT L"cn=schema"
|
||
#define ATTR_TRUE L"TRUE"
|
||
#define ATTR_OPTIONS_0 L"0"
|
||
|
||
//
|
||
// For DumpValues
|
||
//
|
||
PWCHAR GuidAttrs[] = {
|
||
L"objectGUID",
|
||
L"schemaIDGUID",
|
||
L"frsVersionGUID",
|
||
NULL
|
||
};
|
||
|
||
PWCHAR BerAttrs[] = {
|
||
L"replPropertyMetaData",
|
||
L"invocationId",
|
||
L"defaultSecurityDescriptor",
|
||
L"objectSid",
|
||
L"lmPwdHistory",
|
||
L"ntPwdHistory",
|
||
L"oMObjectClass",
|
||
NULL
|
||
};
|
||
|
||
//
|
||
// For HammerSchema
|
||
//
|
||
struct AlterAttr {
|
||
PWCHAR Attr;
|
||
PWCHAR Value;
|
||
};
|
||
struct AlterClass {
|
||
PWCHAR Cn;
|
||
struct AlterAttr AlterAttrs[32];
|
||
};
|
||
|
||
struct AlterClass Computer = {
|
||
L"Computer",
|
||
L"mayContain", L"frsComputerReferenceBL",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsSettings = {
|
||
L"NTFRS-Settings",
|
||
L"possSuperiors", L"container",
|
||
L"possSuperiors", L"organization",
|
||
L"possSuperiors", L"organizationalUnit",
|
||
L"mayContain", L"managedBy",
|
||
L"mayContain", L"frsExtensions",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsReplicaSet = {
|
||
L"NTFRS-Replica-Set",
|
||
L"mayContain", L"frsVersionGuid",
|
||
L"mayContain", L"FrsReplicaSetGuid",
|
||
L"mayContain", L"frsPrimaryMember",
|
||
L"mayContain", L"managedBy",
|
||
L"mayContain", L"frsReplicaSetType",
|
||
L"mayContain", L"frsDirectoryFilter",
|
||
L"mayContain", L"frsDSPoll",
|
||
L"mayContain", L"frsExtensions",
|
||
L"mayContain", L"frsFileFilter",
|
||
L"mayContain", L"frsFlags",
|
||
L"mayContain", L"frsLevelLimit",
|
||
L"mayContain", L"frsPartnerAuthLevel",
|
||
L"mayContain", L"frsRootSecurity",
|
||
L"mayContain", L"frsServiceCommand",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtDsConnection = {
|
||
L"NTDS-Connection",
|
||
L"possSuperiors", L"nTFRSMember",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass Dump = {
|
||
L"Server-Reference",
|
||
L"systemFlags", L"",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// ATTRIBUTES
|
||
//
|
||
|
||
struct AlterClass FrsExtensions = {
|
||
L"Frs-Extensions",
|
||
L"cn", L"Frs-Extensions",
|
||
L"adminDisplayName", L"Frs-Extensions",
|
||
L"adminDescription", L"Frs-Extensions",
|
||
L"lDAPDisplayName", L"frsExtensions",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.82",
|
||
L"oMSyntax", L"4",
|
||
L"attributeSyntax", L"2.5.5.10",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"1",
|
||
L"rangeUpper", L"65536",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsVersionGuid = {
|
||
L"Frs-Version-GUID",
|
||
L"cn", L"Frs-Version-GUID",
|
||
L"adminDisplayName", L"Frs-Version-GUID",
|
||
L"adminDescription", L"Frs-Version-GUID",
|
||
L"lDAPDisplayName", L"frsVersionGUID",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.83",
|
||
L"oMSyntax", L"4",
|
||
L"attributeSyntax", L"2.5.5.10",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsReplicaSetGuid = {
|
||
L"Frs-Replica-Set-GUID",
|
||
L"cn", L"Frs-Replica-Set-GUID",
|
||
L"adminDisplayName", L"Frs-Replica-Set-GUID",
|
||
L"adminDescription", L"Frs-Replica-Set-GUID",
|
||
L"lDAPDisplayName", L"frsReplicaSetGUID",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.84",
|
||
L"oMSyntax", L"4",
|
||
L"attributeSyntax", L"2.5.5.10",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"16",
|
||
L"rangeUpper", L"16",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsDsPoll = {
|
||
L"Frs-DS-Poll",
|
||
L"cn", L"Frs-DS-Poll",
|
||
L"adminDisplayName", L"Frs-DS-Poll",
|
||
L"adminDescription", L"Frs-DS-Poll",
|
||
L"lDAPDisplayName", L"frsDSPoll",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.85",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// replica set types
|
||
//
|
||
struct AlterClass FrsReplicaSetType = {
|
||
L"Frs-Replica-Set-Type",
|
||
L"cn", L"Frs-Replica-Set-Type",
|
||
L"adminDisplayName", L"Frs-Replica-Set-Type",
|
||
L"adminDescription", L"Frs-Replica-Set-Type",
|
||
L"lDAPDisplayName", L"frsReplicaSetType",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.86",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsDirectoryFilter = {
|
||
L"Frs-Directory-Filter",
|
||
L"cn", L"Frs-Directory-Filter",
|
||
L"adminDisplayName", L"Frs-Directory-Filter",
|
||
L"adminDescription", L"bjf l;kjlkj xyz",
|
||
L"lDAPDisplayName", L"frsDirectoryFilter",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.87",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"1",
|
||
L"rangeUpper", L"1024",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// OIDs out of sequence
|
||
//
|
||
struct AlterClass FrsControlDataCreation = {
|
||
L"Frs-Control-Data-Creation",
|
||
L"cn", L"Frs-Control-Data-Creation",
|
||
L"adminDisplayName", L"Frs-Control-Data-Creation",
|
||
L"adminDescription", L"bob",
|
||
L"lDAPDisplayName", L"frsControlDataCreation",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.00",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"32",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsControlInboundBacklog = {
|
||
L"Frs-Control-Inbound-Backlog",
|
||
L"cn", L"Frs-Control-Inbound-Backlog",
|
||
L"adminDisplayName", L"Frs-Control-Inbound-Backlog",
|
||
L"adminDescription", L"george",
|
||
L"lDAPDisplayName", L"frsControlInboundBacklog",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.01",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"32",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsControlOutboundBacklog = {
|
||
L"Frs-Control-Outbound-Backlog",
|
||
L"cn", L"Frs-Control-Outbound-Backlog",
|
||
L"adminDisplayName", L"Frs-Control-Outbound-Backlog",
|
||
L"adminDescription", L"Frs-Control-Outbound-Backlog",
|
||
L"lDAPDisplayName", L"frsControlOutboundBacklog",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.02",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"32",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsFaultCondition = {
|
||
L"Frs-Fault-Condition",
|
||
L"cn", L"Frs-Fault-Condition",
|
||
L"adminDisplayName", L"Frs-Fault-Condition",
|
||
L"adminDescription", L"Frs-Fault-Condition",
|
||
L"lDAPDisplayName", L"frsFaultCondition",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.03",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"1",
|
||
L"rangeUpper", L"16",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsVersion = {
|
||
L"Frs-Version",
|
||
L"cn", L"Frs-Version",
|
||
L"adminDisplayName", L"Frs-Version",
|
||
L"adminDescription", L"Frs-Version",
|
||
L"lDAPDisplayName", L"frsVersion",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.04",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"32",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsPrimaryMember = {
|
||
L"Frs-Primary-Member",
|
||
L"cn", L"Frs-Primary-Member",
|
||
L"adminDisplayName", L"Frs-Primary-Member",
|
||
L"adminDescription", L"Frs-Primary-Member",
|
||
L"lDAPDisplayName", L"frsPrimaryMember",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7002.05",
|
||
L"oMSyntax", L"127",
|
||
L"attributeSyntax", L"2.5.5.1",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"systemFlags", L"2",
|
||
L"linkID", L"104",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
//
|
||
// END OIDs out of sequence
|
||
//
|
||
|
||
struct AlterClass FrsFileFilter = {
|
||
L"Frs-File-Filter",
|
||
L"cn", L"Frs-File-Filter",
|
||
L"adminDisplayName", L"Frs-File-Filter",
|
||
L"adminDescription", L"sue and and and",
|
||
L"lDAPDisplayName", L"frsFileFilter",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.88",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"1",
|
||
L"rangeUpper", L"1024",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsFlags = {
|
||
L"Frs-Flags",
|
||
L"cn", L"Frs-Flags",
|
||
L"adminDisplayName", L"Frs-Flags",
|
||
L"adminDescription", L"Frs-Flags",
|
||
L"lDAPDisplayName", L"frsFlags",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.89",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsLevelLimit = {
|
||
L"Frs-Level-Limit",
|
||
L"cn", L"Frs-Level-Limit",
|
||
L"adminDisplayName", L"Frs-Level-Limit",
|
||
L"adminDescription", L"Frs-Level-Limit",
|
||
L"lDAPDisplayName", L"frsLevelLimit",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.90",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsPartnerAuthLevel = {
|
||
L"Frs-Partner-Auth-Level",
|
||
L"cn", L"Frs-Partner-Auth-Level",
|
||
L"adminDisplayName", L"Frs-Partner-Auth-Level",
|
||
L"adminDescription", L"Frs-Partner-Auth-Level",
|
||
L"lDAPDisplayName", L"frsPartnerAuthLevel",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.91",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsRootSecurity = {
|
||
L"Frs-Root-Security",
|
||
L"cn", L"Frs-Root-Security",
|
||
L"adminDisplayName", L"Frs-Root-Security",
|
||
L"adminDescription", L"Frs-Root-Security",
|
||
L"lDAPDisplayName", L"frsRootSecurity",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.92",
|
||
L"oMSyntax", L"66",
|
||
L"attributeSyntax", L"2.5.5.15",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsServiceCommand = {
|
||
L"Frs-Service-Command",
|
||
L"cn", L"Frs-Service-Command",
|
||
L"adminDisplayName", L"Frs-Service-Command",
|
||
L"adminDescription", L"Frs-Service-Command",
|
||
L"lDAPDisplayName", L"frsServiceCommand",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.93",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"512",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsUpdateTimeout = {
|
||
L"Frs-Update-Timeout",
|
||
L"cn", L"Frs-Update-Timeout",
|
||
L"adminDisplayName", L"Frs-Update-Timeout",
|
||
L"adminDescription", L"Frs-Update-Timeout",
|
||
L"lDAPDisplayName", L"frsUpdateTimeout",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.94",
|
||
L"oMSyntax", L"2",
|
||
L"attributeSyntax", L"2.5.5.9",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsWorkingPath = {
|
||
L"Frs-Working-Path",
|
||
L"cn", L"Frs-Working-Path",
|
||
L"adminDisplayName", L"Frs-Working-Path",
|
||
L"adminDescription", L"Frs-Working-Path",
|
||
L"lDAPDisplayName", L"frsWorkingPath",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.95",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"512",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsStagingPath = {
|
||
L"Frs-Staging-Path",
|
||
L"cn", L"Frs-Staging-Path",
|
||
L"adminDisplayName", L"Frs-Staging-Path",
|
||
L"adminDescription", L"Frs-Staging-Path",
|
||
L"lDAPDisplayName", L"frsStagingPath",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.96",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"512",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsServiceCommandStatus = {
|
||
L"Frs-Service-Command-Status",
|
||
L"cn", L"Frs-Service-Command-Status",
|
||
L"adminDisplayName", L"Frs-Service-Command-Status",
|
||
L"adminDescription", L"frsServiceCommandStatus",
|
||
L"lDAPDisplayName", L"frsServiceCommandStatus",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.98",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"512",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsTimeLastCommand = {
|
||
L"Frs-Time-Last-Command",
|
||
L"cn", L"Frs-Time-Last-Command",
|
||
L"adminDisplayName", L"Frs-Time-Last-Command",
|
||
L"adminDescription", L"Frs-Time-Last-Command",
|
||
L"lDAPDisplayName", L"frsTimeLastCommand",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7000.99",
|
||
L"oMSyntax", L"23",
|
||
L"attributeSyntax", L"2.5.5.11",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsTimeLastConfigChange = {
|
||
L"Frs-Time-Last-Config-Change",
|
||
L"cn", L"Frs-Time-Last-Config-Change",
|
||
L"adminDisplayName", L"Frs-Time-Last-Config-Change",
|
||
L"adminDescription", L"Frs-Time-Last-Config-Change",
|
||
L"lDAPDisplayName", L"frsTimeLastConfigChange",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.01",
|
||
L"oMSyntax", L"23",
|
||
L"attributeSyntax", L"2.5.5.11",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsRootPath = {
|
||
L"Frs-Root-Path",
|
||
L"cn", L"Frs-Root-Path",
|
||
L"adminDisplayName", L"Frs-Root-Path",
|
||
L"adminDescription", L"Frs-Root-Path",
|
||
L"lDAPDisplayName", L"frsRootPath",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.02",
|
||
L"oMSyntax", L"64",
|
||
L"attributeSyntax", L"2.5.5.12",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"rangeLower", L"0",
|
||
L"rangeUpper", L"512",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsComputerReference = {
|
||
L"Frs-Computer-Reference",
|
||
L"cn", L"Frs-Computer-Reference",
|
||
L"adminDisplayName", L"Frs-Computer-Reference",
|
||
L"adminDescription", L"Frs-Computer-Reference",
|
||
L"lDAPDisplayName", L"frsComputerReference",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.03",
|
||
L"oMSyntax", L"127",
|
||
L"attributeSyntax", L"2.5.5.1",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"systemFlags", L"2",
|
||
L"linkID", L"100",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsComputerReferenceBl = {
|
||
L"Frs-Computer-Reference-BL",
|
||
L"cn", L"Frs-Computer-Reference-BL",
|
||
L"adminDisplayName", L"Frs-Computer-Reference-BL",
|
||
L"adminDescription", L"Frs-Computer-Reference-BL",
|
||
L"lDAPDisplayName", L"frsComputerReferenceBL",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.04",
|
||
L"oMSyntax", L"127",
|
||
L"attributeSyntax", L"2.5.5.1",
|
||
L"isSingleValued", L"FALSE",
|
||
L"systemOnly", L"FALSE",
|
||
L"linkID", L"101",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsMemberReference = {
|
||
L"Frs-Member-Reference",
|
||
L"cn", L"Frs-Member-Reference",
|
||
L"adminDisplayName", L"Frs-Member-Reference",
|
||
L"adminDescription", L"Frs-Member-Reference",
|
||
L"lDAPDisplayName", L"frsMemberReference",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.05",
|
||
L"oMSyntax", L"127",
|
||
L"attributeSyntax", L"2.5.5.1",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"systemFlags", L"2",
|
||
L"linkID", L"102",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass FrsMemberReferenceBl = {
|
||
L"Frs-Member-Reference-BL",
|
||
L"cn", L"Frs-Member-Reference-BL",
|
||
L"adminDisplayName", L"Frs-Member-Reference-BL",
|
||
L"adminDescription", L"Frs-Member-Reference-BL",
|
||
L"lDAPDisplayName", L"frsMemberReferenceBL",
|
||
L"objectClass", L"attributeSchema",
|
||
L"attributeId", L"1.2.840.113556.1.4.7001.06",
|
||
L"oMSyntax", L"127",
|
||
L"attributeSyntax", L"2.5.5.1",
|
||
L"isSingleValued", L"TRUE",
|
||
L"systemOnly", L"FALSE",
|
||
L"linkID", L"103",
|
||
L"hideFromAB", L"TRUE",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// CLASSES
|
||
//
|
||
struct AlterClass NtFrsMember = {
|
||
L"NTFRS-Member",
|
||
L"cn", L"NTFRS-Member",
|
||
L"adminDisplayName", L"NTFRS-Member",
|
||
L"adminDescription", L"NTFRS-Member",
|
||
L"lDAPDisplayName", L"nTFRSMember",
|
||
L"objectClass", L"classSchema",
|
||
L"rDNAttID", L"cn",
|
||
L"defaultHidingValue", L"TRUE",
|
||
L"hideFromAB", L"TRUE",
|
||
L"subClassOf", L"leaf",
|
||
L"systemOnly", L"FALSE",
|
||
L"governsId", L"1.2.840.113556.1.4.7001.07",
|
||
L"objectClassCategory", L"1",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsSubscriptions = {
|
||
L"NTFRS-Subscriptions",
|
||
L"cn", L"NTFRS-Subscriptions",
|
||
L"adminDisplayName", L"NTFRS-Subscriptions",
|
||
L"adminDescription", L"NTFRS-Subscriptions",
|
||
L"lDAPDisplayName", L"nTFRSSubscriptions",
|
||
L"objectClass", L"classSchema",
|
||
L"rDNAttID", L"cn",
|
||
L"defaultHidingValue", L"TRUE",
|
||
L"hideFromAB", L"TRUE",
|
||
L"subClassOf", L"leaf",
|
||
L"systemOnly", L"FALSE",
|
||
L"governsId", L"1.2.840.113556.1.4.7001.08",
|
||
L"objectClassCategory", L"1",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsSubscriber = {
|
||
L"NTFRS-Subscriber",
|
||
L"cn", L"NTFRS-Subscriber",
|
||
L"adminDisplayName", L"NTFRS-Subscriber",
|
||
L"adminDescription", L"NTFRS-Subscriber",
|
||
L"lDAPDisplayName", L"nTFRSSubscriber",
|
||
L"objectClass", L"classSchema",
|
||
L"rDNAttID", L"cn",
|
||
L"defaultHidingValue", L"TRUE",
|
||
L"hideFromAB", L"TRUE",
|
||
L"subClassOf", L"leaf",
|
||
L"systemOnly", L"FALSE",
|
||
L"governsId", L"1.2.840.113556.1.4.7001.09",
|
||
L"objectClassCategory", L"1",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsMemberEx = {
|
||
L"NTFRS-Member",
|
||
L"possSuperiors", L"nTFRSReplicaSet",
|
||
L"mayContain", L"frsExtensions",
|
||
L"mayContain", L"frsPartnerAuthLevel",
|
||
L"mayContain", L"frsRootSecurity",
|
||
L"mayContain", L"frsServiceCommand",
|
||
L"mayContain", L"schedule",
|
||
L"mayContain", L"frsComputerReference",
|
||
L"mayContain", L"ServerReference",
|
||
L"mayContain", L"frsMemberReferenceBL",
|
||
L"mayContain", L"frsUpdateTimeout",
|
||
L"mayContain", L"frsControlDataCreation",
|
||
L"mayContain", L"frsControlInboundBacklog",
|
||
L"mayContain", L"frsControlOutboundBacklog",
|
||
L"mayContain", L"frsFlags",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsSubscriptionsEx = {
|
||
L"NTFRS-Subscriptions",
|
||
L"possSuperiors", L"computer",
|
||
L"possSuperiors", L"nTFRSSubscriptions",
|
||
L"mayContain", L"frsWorkingPath",
|
||
L"mayContain", L"frsVersion",
|
||
L"mayContain", L"frsExtensions",
|
||
NULL, NULL
|
||
};
|
||
|
||
struct AlterClass NtFrsSubscriberEx = {
|
||
L"NTFRS-Subscriber",
|
||
L"possSuperiors", L"nTFRSSubscriptions",
|
||
L"mustContain", L"frsRootPath",
|
||
L"mustContain", L"frsStagingPath",
|
||
L"mayContain", L"frsExtensions",
|
||
L"mayContain", L"frsFlags",
|
||
L"mayContain", L"frsFaultCondition",
|
||
L"mayContain", L"frsMemberReference",
|
||
L"mayContain", L"frsUpdateTimeout",
|
||
L"mayContain", L"frsServiceCommand",
|
||
L"mayContain", L"frsServiceCommandStatus",
|
||
L"mayContain", L"schedule",
|
||
L"mayContain", L"frsTimeLastCommand",
|
||
L"mayContain", L"frsTimeLastConfigChange",
|
||
NULL, NULL
|
||
};
|
||
|
||
//
|
||
// CREATE ATTRIBUTES
|
||
//
|
||
struct AlterClass *CreateAttributes[] = {
|
||
&FrsExtensions,
|
||
&FrsVersionGuid,
|
||
&FrsReplicaSetGuid,
|
||
&FrsDsPoll,
|
||
&FrsReplicaSetType,
|
||
&FrsDirectoryFilter,
|
||
&FrsFileFilter,
|
||
&FrsFlags,
|
||
&FrsLevelLimit,
|
||
&FrsPartnerAuthLevel,
|
||
&FrsRootSecurity,
|
||
&FrsServiceCommand,
|
||
&FrsUpdateTimeout,
|
||
&FrsWorkingPath,
|
||
&FrsStagingPath,
|
||
&FrsServiceCommandStatus,
|
||
&FrsTimeLastCommand,
|
||
&FrsTimeLastConfigChange,
|
||
&FrsRootPath,
|
||
&FrsComputerReference,
|
||
&FrsComputerReferenceBl,
|
||
&FrsMemberReference,
|
||
&FrsMemberReferenceBl,
|
||
&FrsControlDataCreation,
|
||
&FrsControlInboundBacklog,
|
||
&FrsControlOutboundBacklog,
|
||
&FrsFaultCondition,
|
||
&FrsVersion,
|
||
&FrsPrimaryMember,
|
||
NULL
|
||
};
|
||
|
||
//
|
||
// CREATE CLASSES
|
||
//
|
||
struct AlterClass *CreateClasses[] = {
|
||
&NtFrsMember,
|
||
&NtFrsSubscriptions,
|
||
&NtFrsSubscriber,
|
||
NULL
|
||
};
|
||
|
||
//
|
||
// ALTER EXISTING CLASSES
|
||
//
|
||
struct AlterClass *AlterSchema[] = {
|
||
&Computer,
|
||
&NtFrsSettings,
|
||
&NtFrsReplicaSet,
|
||
&NtDsConnection,
|
||
&NtFrsMemberEx,
|
||
&NtFrsSubscriptionsEx,
|
||
&NtFrsSubscriberEx,
|
||
NULL
|
||
};
|
||
|
||
|
||
PWCHAR
|
||
MakeRdn(
|
||
IN PWCHAR DN
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Extract the base component (relative distinguished name) from a
|
||
distinguished name. The distinguished name is assumed to be in
|
||
DS format (CN=xyz,CN=next one,...). In this case, the returned
|
||
RDN is "xyz".
|
||
|
||
Arguments:
|
||
DN - distinguished name
|
||
|
||
Return Value:
|
||
A zero-terminated string. The string is freed with FREE_NO_HEADER().
|
||
--*/
|
||
{
|
||
DWORD RDNLen;
|
||
PWCHAR RDN;
|
||
|
||
if (DN == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
// Skip the first CN=; if any
|
||
RDN = wcsstr(DN, L"CN=");
|
||
if (RDN == DN)
|
||
DN += 3;
|
||
|
||
// Return the string up to the first delimiter or EOS
|
||
RDNLen = wcscspn(DN, L",");
|
||
RDN = (PWCHAR)malloc(sizeof(WCHAR) * (RDNLen + 1));
|
||
wcsncpy(RDN, DN, RDNLen);
|
||
RDN[RDNLen] = L'\0';
|
||
|
||
return RDN;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
FrsDsMakeParentDn(
|
||
IN PWCHAR Dn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
--*/
|
||
{
|
||
DWORD PLen;
|
||
|
||
if (Dn == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
PLen = wcscspn(Dn, L",");
|
||
if (Dn[PLen] != L',') {
|
||
return NULL;
|
||
}
|
||
return FrsWcsDup(&Dn[PLen + 1]);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
AddMod(
|
||
IN PWCHAR AttrType,
|
||
IN PWCHAR AttrValue,
|
||
IN OUT LDAPMod ***pppMod
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Add an attribute (plus values) to a structure that will eventually be
|
||
used in an ldap_add() function to add an object to the DS. The null-
|
||
terminated array referenced by pppMod grows with each call to this
|
||
routine. The array is freed by the caller using FreeMod().
|
||
|
||
Arguments:
|
||
AttrType - The object class of the object.
|
||
AttrValue - The value of the attribute.
|
||
pppMod - Address of an array of pointers to "attributes". Don't
|
||
give me that look -- this is an LDAP thing.
|
||
|
||
Return Value:
|
||
The pppMod array grows by one entry. The caller must free it with
|
||
FreeMod().
|
||
--*/
|
||
{
|
||
DWORD NumMod; // Number of entries in the Mod array
|
||
LDAPMod **ppMod; // Address of the first entry in the Mod array
|
||
LDAPMod *Attr; // An attribute structure
|
||
PWCHAR *Values; // An array of pointers to bervals
|
||
|
||
if (AttrValue == NULL)
|
||
return;
|
||
|
||
//
|
||
// The null-terminated array doesn't exist; create it
|
||
//
|
||
if (*pppMod == NULL) {
|
||
*pppMod = (LDAPMod **)malloc(sizeof (*pppMod));
|
||
**pppMod = NULL;
|
||
}
|
||
|
||
//
|
||
// Increase the array's size by 1
|
||
//
|
||
for (ppMod = *pppMod, NumMod = 2; *ppMod != NULL; ++ppMod, ++NumMod);
|
||
*pppMod = (LDAPMod **)realloc(*pppMod, sizeof (*pppMod) * NumMod);
|
||
|
||
//
|
||
// Add the new attribute + value to the Mod array
|
||
//
|
||
Values = (PWCHAR *)malloc(sizeof (PWCHAR) * 2);
|
||
Values[0] = _wcsdup(AttrValue);
|
||
Values[1] = NULL;
|
||
|
||
Attr = (LDAPMod *)malloc(sizeof (*Attr));
|
||
Attr->mod_values = Values;
|
||
Attr->mod_type = _wcsdup(AttrType);
|
||
Attr->mod_op = LDAP_MOD_ADD;
|
||
|
||
(*pppMod)[NumMod - 1] = NULL;
|
||
(*pppMod)[NumMod - 2] = Attr;
|
||
}
|
||
|
||
|
||
VOID
|
||
AddBerMod(
|
||
IN PWCHAR AttrType,
|
||
IN PCHAR AttrValue,
|
||
IN DWORD AttrValueLen,
|
||
IN OUT LDAPMod ***pppMod
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Add an attribute (plus values) to a structure that will eventually be
|
||
used in an ldap_add() function to add an object to the DS. The null-
|
||
terminated array referenced by pppMod grows with each call to this
|
||
routine. The array is freed by the caller using FreeMod().
|
||
|
||
Arguments:
|
||
AttrType - The object class of the object.
|
||
AttrValue - The value of the attribute.
|
||
AttrValueLen - length of the attribute
|
||
pppMod - Address of an array of pointers to "attributes". Don't
|
||
give me that look -- this is an LDAP thing.
|
||
|
||
Return Value:
|
||
The pppMod array grows by one entry. The caller must free it with
|
||
FreeMod().
|
||
--*/
|
||
{
|
||
DWORD NumMod; // Number of entries in the Mod array
|
||
LDAPMod **ppMod; // Address of the first entry in the Mod array
|
||
LDAPMod *Attr; // An attribute structure
|
||
PLDAP_BERVAL Berval;
|
||
PLDAP_BERVAL *Values; // An array of pointers to bervals
|
||
|
||
if (AttrValue == NULL)
|
||
return;
|
||
|
||
//
|
||
// The null-terminated array doesn't exist; create it
|
||
//
|
||
if (*pppMod == NULL) {
|
||
*pppMod = (LDAPMod **)malloc(sizeof (*pppMod));
|
||
**pppMod = NULL;
|
||
}
|
||
|
||
//
|
||
// Increase the array's size by 1
|
||
//
|
||
for (ppMod = *pppMod, NumMod = 2; *ppMod != NULL; ++ppMod, ++NumMod);
|
||
*pppMod = (LDAPMod **)realloc(*pppMod, sizeof (*pppMod) * NumMod);
|
||
|
||
//
|
||
// Construct a berval
|
||
//
|
||
Berval = (PLDAP_BERVAL)malloc(sizeof(LDAP_BERVAL));
|
||
Berval->bv_len = AttrValueLen;
|
||
Berval->bv_val = (PCHAR)malloc(AttrValueLen);
|
||
CopyMemory(Berval->bv_val, AttrValue, AttrValueLen);
|
||
|
||
//
|
||
// Add the new attribute + value to the Mod array
|
||
//
|
||
Values = (PLDAP_BERVAL *)malloc(sizeof (PLDAP_BERVAL) * 2);
|
||
Values[0] = Berval;
|
||
Values[1] = NULL;
|
||
|
||
Attr = (LDAPMod *)malloc(sizeof (*Attr));
|
||
Attr->mod_bvalues = Values;
|
||
Attr->mod_type = _wcsdup(AttrType);
|
||
Attr->mod_op = LDAP_MOD_BVALUES | LDAP_MOD_REPLACE;
|
||
|
||
(*pppMod)[NumMod - 1] = NULL;
|
||
(*pppMod)[NumMod - 2] = Attr;
|
||
}
|
||
|
||
|
||
VOID
|
||
FreeMod(
|
||
IN OUT LDAPMod ***pppMod
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Free the structure built by successive calls to AddMod().
|
||
|
||
Arguments:
|
||
pppMod - Address of a null-terminated array.
|
||
|
||
Return Value:
|
||
*pppMod set to NULL.
|
||
--*/
|
||
{
|
||
DWORD i, j;
|
||
LDAPMod **ppMod;
|
||
|
||
if (!pppMod || !*pppMod) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// For each attibute
|
||
//
|
||
ppMod = *pppMod;
|
||
for (i = 0; ppMod[i] != NULL; ++i) {
|
||
//
|
||
// For each value of the attribute
|
||
//
|
||
for (j = 0; (ppMod[i])->mod_values[j] != NULL; ++j) {
|
||
//
|
||
// Free the value
|
||
//
|
||
if (ppMod[i]->mod_op & LDAP_MOD_BVALUES) {
|
||
free(ppMod[i]->mod_bvalues[j]->bv_val);
|
||
}
|
||
free((ppMod[i])->mod_values[j]);
|
||
}
|
||
free((ppMod[i])->mod_values); // Free the array of pointers to values
|
||
free((ppMod[i])->mod_type); // Free the string identifying the attribute
|
||
free(ppMod[i]); // Free the attribute
|
||
}
|
||
free(ppMod); // Free the array of pointers to attributes
|
||
*pppMod = NULL; // Now ready for more calls to AddMod()
|
||
}
|
||
|
||
|
||
BOOL
|
||
LdapSearch(
|
||
IN PLDAP ldap,
|
||
IN PWCHAR Base,
|
||
IN ULONG Scope,
|
||
IN PWCHAR Filter,
|
||
IN PWCHAR Attrs[],
|
||
IN ULONG AttrsOnly,
|
||
IN LDAPMessage **Res,
|
||
IN BOOL Quiet
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Issue the ldap ldap_search_s call, check for errors, and check for
|
||
a shutdown in progress.
|
||
|
||
Arguments:
|
||
ldap
|
||
Base
|
||
Scope
|
||
Filter
|
||
Attrs
|
||
AttrsOnly
|
||
Res
|
||
|
||
Return Value:
|
||
The ldap array of values or NULL if the Base, DesiredAttr, or its values
|
||
does not exist. The ldap array is freed with ldap_value_free().
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
|
||
//
|
||
// Issue the ldap search
|
||
//
|
||
LStatus = ldap_search_s(ldap, Base, Scope, Filter, Attrs, AttrsOnly, Res);
|
||
//
|
||
// Check for errors
|
||
//
|
||
if (LStatus != LDAP_SUCCESS) {
|
||
if (!Quiet) {
|
||
fprintf(stderr, "WARN - Error searching %ws for %ws; LStatus %d: %ws\n",
|
||
Base, Filter, LStatus, ldap_err2string(LStatus));
|
||
}
|
||
return FALSE;
|
||
}
|
||
//
|
||
// Return TRUE if not shutting down
|
||
//
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FrsDsVerifySchedule(
|
||
IN PWCHAR Name,
|
||
IN ULONG ScheduleLength,
|
||
IN PSCHEDULE Schedule
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Check the schedule for consistency
|
||
|
||
Arguments:
|
||
Name
|
||
Schedule
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i, j;
|
||
ULONG Num;
|
||
ULONG Len;
|
||
ULONG NumType;
|
||
PUCHAR NewScheduleData;
|
||
PUCHAR OldScheduleData;
|
||
|
||
if (!Schedule) {
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// Too many schedules
|
||
//
|
||
Num = Schedule->NumberOfSchedules;
|
||
if (Num > 3) {
|
||
fprintf(stderr, "%ws has %d schedules\n", Name, Num);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Too few schedules
|
||
//
|
||
if (Num < 1) {
|
||
fprintf(stderr, "%ws has %d schedules\n", Name, Num);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Not enough memory
|
||
//
|
||
Len = sizeof(SCHEDULE) +
|
||
(sizeof(SCHEDULE_HEADER) * (Num - 1)) +
|
||
(SCHEDULE_DATA_BYTES * Num);
|
||
|
||
if (ScheduleLength < Len) {
|
||
fprintf(stderr, "%ws is short (ds) by %d bytes (%d - %d), %d\n",
|
||
Name,
|
||
Len - ScheduleLength,
|
||
Len,
|
||
ScheduleLength,
|
||
Schedule->Size);
|
||
return FALSE;
|
||
}
|
||
|
||
if (Schedule->Size < Len) {
|
||
fprintf(stderr, "%ws is short (size) by %d bytes (%d - %d), %d\n",
|
||
Name,
|
||
Len - Schedule->Size,
|
||
Len,
|
||
Schedule->Size,
|
||
Schedule->Size);
|
||
return FALSE;
|
||
}
|
||
Schedule->Size = Len;
|
||
|
||
//
|
||
// Invalid type
|
||
//
|
||
for (i = 0; i < Num; ++i) {
|
||
switch (Schedule->Schedules[i].Type) {
|
||
case SCHEDULE_INTERVAL:
|
||
break;
|
||
case SCHEDULE_BANDWIDTH:
|
||
break;
|
||
case SCHEDULE_PRIORITY:
|
||
break;
|
||
default:
|
||
fprintf(stderr, "%ws has an invalid schedule type (%d)\n",
|
||
Name,
|
||
Schedule->Schedules[i].Type);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Only 0 or 1 interval
|
||
//
|
||
for (NumType = i = 0; i < Num; ++i)
|
||
if (Schedule->Schedules[i].Type == SCHEDULE_INTERVAL)
|
||
++NumType;
|
||
if (NumType > 1) {
|
||
fprintf(stderr, "%ws has %d interval schedules\n",
|
||
Name,
|
||
NumType);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Only 0 or 1 bandwidth
|
||
//
|
||
for (NumType = i = 0; i < Num; ++i)
|
||
if (Schedule->Schedules[i].Type == SCHEDULE_BANDWIDTH)
|
||
++NumType;
|
||
if (NumType > 1) {
|
||
fprintf(stderr, "%ws has %d bandwidth schedules\n",
|
||
Name,
|
||
NumType);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Only 0 or 1 priority
|
||
//
|
||
for (NumType = i = 0; i < Num; ++i)
|
||
if (Schedule->Schedules[i].Type == SCHEDULE_PRIORITY)
|
||
++NumType;
|
||
if (NumType > 1) {
|
||
fprintf(stderr, "%ws has %d priority schedules\n",
|
||
Name,
|
||
NumType);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Invalid offset
|
||
//
|
||
for (i = 0; i < Num; ++i) {
|
||
if (Schedule->Schedules[i].Offset >
|
||
ScheduleLength - SCHEDULE_DATA_BYTES) {
|
||
fprintf(stderr, "%ws has an invalid offset (%d)\n",
|
||
Name,
|
||
Schedule->Schedules[i].Offset);
|
||
return FALSE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
PrintShortSchedule(
|
||
IN PWCHAR Indent,
|
||
IN PSCHEDULE Schedule,
|
||
IN ULONG ScheduleLen
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Print a short form of the schedule
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i;
|
||
|
||
if (!FrsDsVerifySchedule(L"<unknown>", ScheduleLen, Schedule)) {
|
||
return;
|
||
}
|
||
|
||
if (!Schedule || !Schedule->NumberOfSchedules) {
|
||
printf("%wsSchedule=\n", Indent);
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
|
||
if (!i) {
|
||
printf("%wsSchedule=Type %d", Indent, Schedule->Schedules[i].Type);
|
||
} else {
|
||
printf(", %d", Schedule->Schedules[i].Type);
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
|
||
|
||
VOID
|
||
PrintLongSchedule(
|
||
IN PWCHAR Indent1,
|
||
IN PWCHAR Indent2,
|
||
IN PSCHEDULE Schedule,
|
||
IN ULONG ScheduleLen
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Print a short form of the schedule
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i;
|
||
ULONG Day;
|
||
ULONG Hour;
|
||
BOOL PrintIt;
|
||
PUCHAR ScheduleData;
|
||
|
||
if (!FrsDsVerifySchedule(L"<unknown>", ScheduleLen, Schedule)) {
|
||
return;
|
||
}
|
||
|
||
if (!Schedule || !Schedule->NumberOfSchedules) {
|
||
printf("%ws%wsSchedule=\n", Indent1, Indent2);
|
||
return;
|
||
}
|
||
for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
|
||
if (!i) {
|
||
printf("%ws%wsSchedule=Type %d",
|
||
Indent1,
|
||
Indent2,
|
||
Schedule->Schedules[i].Type);
|
||
} else {
|
||
printf(", %d", Schedule->Schedules[i].Type);
|
||
}
|
||
}
|
||
printf("\n");
|
||
|
||
for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
|
||
ScheduleData = ((PUCHAR)Schedule) + Schedule->Schedules[i].Offset;
|
||
if (Schedule->Schedules[i].Type != SCHEDULE_INTERVAL) {
|
||
continue;
|
||
}
|
||
for (Day = 0; Day < 7; ++Day) {
|
||
if (Day) {
|
||
PrintIt = FALSE;
|
||
for (Hour = 0; Hour < 24; ++Hour) {
|
||
if (*(ScheduleData + (Day * 24) + Hour) !=
|
||
*(ScheduleData + ((Day - 1) * 24) + Hour)) {
|
||
PrintIt = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
PrintIt = TRUE;
|
||
}
|
||
if (!PrintIt) {
|
||
continue;
|
||
}
|
||
printf("%ws%ws Day %1d: ", Indent1, Indent2, Day + 1);
|
||
for (Hour = 0; Hour < 24; ++Hour) {
|
||
printf("%1x", *(ScheduleData + (Day * 24) + Hour) & 0x0F);
|
||
}
|
||
printf("\n");
|
||
}
|
||
printf("\n");
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
PrintSchedule(
|
||
IN PSCHEDULE Schedule
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Print the schedule
|
||
|
||
Arguments:
|
||
Schedule
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i;
|
||
|
||
if (Schedule) for (i = 0; i < Schedule->NumberOfSchedules; ++i) {
|
||
printf(" Schedule %d\n", i);
|
||
printf(" Type : %d\n", Schedule->Schedules[i].Type);
|
||
printf(" Offset: %d\n", Schedule->Schedules[i].Offset);
|
||
}
|
||
}
|
||
|
||
|
||
PCHAR
|
||
FrsWtoA(
|
||
PWCHAR Wstr
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Translate a wide char string into a newly allocated char string.
|
||
|
||
Arguments:
|
||
Wstr - wide char string
|
||
|
||
Return Value:
|
||
Duplicated string. Free with FrsFree().
|
||
--*/
|
||
{
|
||
PCHAR Astr;
|
||
|
||
//
|
||
// E.g., when duplicating NodePartner when none exists
|
||
//
|
||
if (Wstr == NULL)
|
||
return NULL;
|
||
|
||
Astr = (PCHAR)malloc(wcslen(Wstr) + 1);
|
||
sprintf(Astr, "%ws", Wstr);
|
||
|
||
return Astr;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
FrsAtoW(
|
||
PCHAR Astr
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Translate a wide char string into a newly allocated char string.
|
||
|
||
Arguments:
|
||
Wstr - wide char string
|
||
|
||
Return Value:
|
||
Duplicated string. Free with FrsFree().
|
||
--*/
|
||
{
|
||
PWCHAR Wstr;
|
||
|
||
//
|
||
// E.g., when duplicating NodePartner when none exists
|
||
//
|
||
if (Astr == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
Wstr = (PWCHAR)malloc((strlen(Astr) + 1) * sizeof(WCHAR));
|
||
swprintf(Wstr, L"%hs", Astr);
|
||
|
||
return Wstr;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
FrsWcsDup(
|
||
PWCHAR OldStr
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Duplicate a string using our memory allocater
|
||
|
||
Arguments:
|
||
OldArg - string to duplicate
|
||
|
||
Return Value:
|
||
Duplicated string. Free with FrsFree().
|
||
--*/
|
||
{
|
||
PWCHAR NewStr;
|
||
|
||
//
|
||
// E.g., when duplicating NodePartner when none exists
|
||
//
|
||
if (OldStr == NULL)
|
||
return NULL;
|
||
|
||
NewStr = (PWCHAR)malloc((wcslen(OldStr) + 1) * sizeof(WCHAR));
|
||
wcscpy(NewStr, OldStr);
|
||
|
||
return NewStr;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
FrsWcsCat(
|
||
PWCHAR First,
|
||
PWCHAR Second
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Concatenate two strings into a new string using our memory allocater
|
||
|
||
Arguments:
|
||
First - First string in the concat
|
||
Second - Second string in the concat
|
||
|
||
Return Value:
|
||
Duplicated and concatentated string. Free with FrsFree().
|
||
--*/
|
||
{
|
||
DWORD Bytes;
|
||
PWCHAR New;
|
||
|
||
// size of new string
|
||
Bytes = (wcslen(First) + wcslen(Second) + 1) * sizeof(WCHAR);
|
||
New = (PWCHAR)malloc(Bytes);
|
||
|
||
// Not as efficient as I would like but this routine is seldom used
|
||
wcscpy(New, First);
|
||
wcscat(New, Second);
|
||
|
||
return New;
|
||
}
|
||
|
||
|
||
ULONG NumSchedules;
|
||
VOID
|
||
ConditionalBuildSchedule(
|
||
PSCHEDULE *Schedule,
|
||
PULONG ScheduleLength
|
||
)
|
||
|
||
/*++
|
||
Routine Description:
|
||
Build a schedule with the specified number of schedules
|
||
|
||
Arguments:
|
||
Schedule
|
||
ScheduleLength
|
||
|
||
Return Value:
|
||
Schedule or NULL. Free with free();
|
||
--*/
|
||
{
|
||
PBYTE ScheduleData;
|
||
ULONG j;
|
||
|
||
//
|
||
// No schedule, yet
|
||
//
|
||
*Schedule = NULL;
|
||
*ScheduleLength = 0;
|
||
|
||
//
|
||
// Create variable sized schedules
|
||
//
|
||
++NumSchedules;
|
||
if (NumSchedules > 3) {
|
||
NumSchedules = 1; // shouldn't always create schedule
|
||
}
|
||
if (NumSchedules == 0) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Construct a phoney schedule; always "on"
|
||
//
|
||
*ScheduleLength = sizeof(SCHEDULE) +
|
||
((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
|
||
(NumSchedules * SCHEDULE_DATA_BYTES);
|
||
|
||
*Schedule = (PSCHEDULE)malloc(*ScheduleLength);
|
||
ZeroMemory(*Schedule, *ScheduleLength);
|
||
(*Schedule)->Size = *ScheduleLength;
|
||
(*Schedule)->NumberOfSchedules = NumSchedules;
|
||
(*Schedule)->Schedules[0].Type = SCHEDULE_INTERVAL;
|
||
(*Schedule)->Schedules[0].Offset = sizeof(SCHEDULE) +
|
||
((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
|
||
(0 * SCHEDULE_DATA_BYTES);
|
||
if (NumSchedules == 1) {
|
||
goto setschedule;
|
||
}
|
||
(*Schedule)->Schedules[1].Type = SCHEDULE_PRIORITY;
|
||
(*Schedule)->Schedules[1].Offset = sizeof(SCHEDULE) +
|
||
((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
|
||
(1 * SCHEDULE_DATA_BYTES);
|
||
if (NumSchedules == 2) {
|
||
goto setschedule;
|
||
}
|
||
(*Schedule)->Schedules[2].Type = SCHEDULE_BANDWIDTH;
|
||
(*Schedule)->Schedules[2].Offset = sizeof(SCHEDULE) +
|
||
((NumSchedules - 1) * sizeof(SCHEDULE_HEADER)) +
|
||
(2 * SCHEDULE_DATA_BYTES);
|
||
if (NumSchedules == 3) {
|
||
goto setschedule;
|
||
}
|
||
|
||
setschedule:
|
||
ScheduleData = ((PBYTE)(*Schedule));
|
||
for (j = 0; j < (SCHEDULE_DATA_BYTES * NumSchedules); ++j) {
|
||
*(ScheduleData + (*Schedule)->Schedules[0].Offset + j) = 0xff;
|
||
}
|
||
}
|
||
|
||
|
||
DWORD
|
||
FrsDsGetDcInfo(
|
||
IN PDOMAIN_CONTROLLER_INFO *DcInfo,
|
||
IN DWORD Flags
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Open and bind to a dc
|
||
|
||
Arguments:
|
||
DcInfo - Dc Info
|
||
Flags - DsGetDcName(Flags)
|
||
|
||
Return Value:
|
||
DsGetDcName
|
||
--*/
|
||
{
|
||
DWORD WStatus;
|
||
|
||
WStatus = DsGetDcName(NULL, // Computer to remote to
|
||
NULL, // Domain - use our own
|
||
NULL, // Domain Guid
|
||
NULL, // Site Guid
|
||
Flags,
|
||
DcInfo); // Return info
|
||
//
|
||
// Report the error and retry for any DC
|
||
//
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n", WStatus);
|
||
return WStatus;
|
||
}
|
||
printf("DCINFO for %08x:\n", Flags);
|
||
printf("\tDomainControllerName : %ws\n", (*DcInfo)->DomainControllerName);
|
||
printf("\tDomainControllerAddress: %ws\n", (*DcInfo)->DomainControllerAddress);
|
||
printf("\tDomainControllerType : %08x\n",(*DcInfo)->DomainControllerAddressType);
|
||
printf("\tDomainName : %ws\n", (*DcInfo)->DomainName);
|
||
// printf("\tForestName : %ws\n", (*DcInfo)->DnsForestName);
|
||
printf("\tDcSiteName : %ws\n", (*DcInfo)->DcSiteName);
|
||
printf("\tClientSiteName : %ws\n", (*DcInfo)->ClientSiteName);
|
||
printf("\tFlags : %08x\n",(*DcInfo)->Flags);
|
||
return WStatus;
|
||
}
|
||
|
||
|
||
PLDAP
|
||
FrsDsOpenDs(
|
||
VOID
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Open and bind to the a primary domain controller.
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
The address of a open, bound LDAP port or NULL if the operation was
|
||
unsuccessful. The caller must free the structure with ldap_unbind().
|
||
--*/
|
||
{
|
||
DWORD WStatus;
|
||
PLDAP ldap = NULL; // ldap handle
|
||
PWCHAR DcAddr;
|
||
PWCHAR DcDnsName;
|
||
PDOMAIN_CONTROLLER_INFO DcInfo;
|
||
ULONG ulOptions;
|
||
|
||
//
|
||
// Get Info about a Global Catalogue
|
||
// Domain Controller (need the IP address)
|
||
//
|
||
// (Nope; try to live without it, Billy)
|
||
//
|
||
bugbug("FORCE_REDISCOVERY was removed per Herron")
|
||
WStatus = FrsDsGetDcInfo(&DcInfo,
|
||
DS_DIRECTORY_SERVICE_REQUIRED | // Flags
|
||
DS_WRITABLE_REQUIRED);
|
||
//
|
||
// Report the error and retry for any DC
|
||
//
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
printf("Retrying FrsDsGetDcInfo with force rediscovery\n");
|
||
FrsDsGetDcInfo(&DcInfo,
|
||
DS_DIRECTORY_SERVICE_REQUIRED | // Flags
|
||
DS_WRITABLE_REQUIRED |
|
||
DS_FORCE_REDISCOVERY);
|
||
}
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n", WStatus);
|
||
}
|
||
DcAddr = DcInfo->DomainControllerAddress;
|
||
DcDnsName = DcInfo->DomainControllerName;
|
||
|
||
//
|
||
// if ldap_open is called with a server name the api will call DsGetDcName
|
||
// passing the server name as the domainname parm...bad, because
|
||
// DsGetDcName will make a load of DNS queries based on the server name,
|
||
// it is designed to construct these queries from a domain name...so all
|
||
// these queries will be bogus, meaning they will waste network bandwidth,
|
||
// time to fail, and worst case cause expensive on demand links to come up
|
||
// as referrals/forwarders are contacted to attempt to resolve the bogus
|
||
// names. By setting LDAP_OPT_AREC_EXCLUSIVE to on using ldap_set_option
|
||
// after the ldap_init but before any other operation using the ldap
|
||
// handle from ldap_init, the delayed connection setup will not call
|
||
// DsGetDcName, just gethostbyname, or if an IP is passed, the ldap client
|
||
// will detect that and use the address directly.
|
||
//
|
||
|
||
//
|
||
// DC's DNS name (w/o the leading \\)
|
||
//
|
||
if (!ldap &&
|
||
DcDnsName &&
|
||
(wcslen(DcDnsName) > 2) &&
|
||
DcDnsName[0] == L'\\' &&
|
||
DcDnsName[1] == L'\\') {
|
||
// ldap = ldap_open(DcDnsName + 2, LDAP_PORT);
|
||
ldap = ldap_init(DcDnsName + 2, LDAP_PORT);
|
||
if (!ldap) {
|
||
// fprintf(stderr, "WARN - ldap_open(DcDnsName + 2 %ws); WStatus %d\n",
|
||
// DcDnsName + 2,
|
||
// WStatus);
|
||
fprintf(stderr, "WARN - ldap_init(DcDnsName + 2 %ws); WStatus %d\n",
|
||
DcDnsName + 2,
|
||
WStatus);
|
||
} else {
|
||
// printf("ldap_open(DcDnsName + 2 %ws) succeeded\n", DcDnsName + 2);
|
||
printf("ldap_init(DcDnsName + 2 %ws) succeeded\n", DcDnsName + 2);
|
||
}
|
||
}
|
||
|
||
//
|
||
// DC's IP Address (w/o the leading \\)
|
||
//
|
||
if (!ldap &&
|
||
DcAddr &&
|
||
(wcslen(DcAddr) > 2) &&
|
||
DcAddr[0] == L'\\' &&
|
||
DcAddr[1] == L'\\') {
|
||
// ldap = ldap_open(DcAddr + 2, LDAP_PORT);
|
||
ldap = ldap_init(DcAddr + 2, LDAP_PORT);
|
||
if (!ldap) {
|
||
// fprintf(stderr, "WARN - ldap_open(DcAddr + 2 %ws); WStatus %d\n",
|
||
// DcAddr + 2,
|
||
// WStatus);
|
||
fprintf(stderr, "WARN - ldap_init(DcAddr + 2 %ws); WStatus %d\n",
|
||
DcAddr + 2,
|
||
WStatus);
|
||
} else {
|
||
// printf("ldap_open(DcAddr + 2 %ws) succeeded\n", DcAddr + 2);
|
||
printf("ldap_init(DcAddr + 2 %ws) succeeded\n", DcAddr + 2);
|
||
}
|
||
}
|
||
|
||
//
|
||
// DC's DNS name
|
||
//
|
||
if (!ldap && DcDnsName) {
|
||
// ldap = ldap_open(DcDnsName, LDAP_PORT);
|
||
ldap = ldap_init(DcDnsName, LDAP_PORT);
|
||
if (!ldap) {
|
||
// fprintf(stderr, "WARN - ldap_open(DcDnsName %ws); WStatus %d\n",
|
||
// DcDnsName,
|
||
// WStatus);
|
||
fprintf(stderr, "WARN - ldap_init(DcDnsName %ws); WStatus %d\n",
|
||
DcDnsName,
|
||
WStatus);
|
||
} else {
|
||
// printf("ldap_open(DcDnsName %ws) succeeded\n", DcDnsName);
|
||
printf("ldap_init(DcDnsName %ws) succeeded\n", DcDnsName);
|
||
}
|
||
}
|
||
|
||
//
|
||
// DC's IP Address
|
||
//
|
||
if (!ldap && DcAddr) {
|
||
// ldap = ldap_open(DcAddr, LDAP_PORT);
|
||
ldap = ldap_init(DcAddr, LDAP_PORT);
|
||
if (!ldap) {
|
||
// fprintf(stderr, "WARN - ldap_open(DcAddr %ws); WStatus %d\n",
|
||
// DcAddr,
|
||
// WStatus);
|
||
fprintf(stderr, "WARN - ldap_init(DcAddr %ws); WStatus %d\n",
|
||
DcAddr,
|
||
WStatus);
|
||
} else {
|
||
// printf("ldap_open(DcAddr %ws) succeeded\n", DcAddr);
|
||
printf("ldap_init(DcAddr %ws) succeeded\n", DcAddr);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Whatever it is, we can't find it.
|
||
//
|
||
if (!ldap) {
|
||
// fprintf(stderr, "ERROR - ldap_open(DNS %ws, IP %ws); WStatus %d\n",
|
||
// DcDnsName,
|
||
// DcAddr,
|
||
// WStatus);
|
||
fprintf(stderr, "ERROR - ldap_init(DNS %ws, IP %ws); WStatus %d\n",
|
||
DcDnsName,
|
||
DcAddr,
|
||
WStatus);
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// set the option as explained in the comment above.
|
||
//
|
||
ulOptions = PtrToUlong(LDAP_OPT_ON);
|
||
ldap_set_option(ldap, LDAP_OPT_AREC_EXCLUSIVE, &ulOptions);
|
||
|
||
//
|
||
// ldap cannot be used until after the bind operation
|
||
//
|
||
WStatus = ldap_bind_s(ldap, NULL, NULL, LDAP_AUTH_NEGOTIATE);
|
||
if (WStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - ldap_bind_s: %ws\n", ldap_err2string(WStatus));
|
||
ldap_unbind(ldap);
|
||
return NULL;
|
||
}
|
||
|
||
return ldap;
|
||
}
|
||
|
||
|
||
PWCHAR *
|
||
GetValues(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Dn,
|
||
IN PWCHAR DesiredAttr,
|
||
IN BOOL Quiet
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Return the DS values for one attribute in an object.
|
||
|
||
Arguments:
|
||
ldap - An open, bound ldap port.
|
||
Base - The "pathname" of a DS object.
|
||
DesiredAttr - Return values for this attribute.
|
||
Quiet
|
||
|
||
Return Value:
|
||
An array of char pointers that represents the values for the attribute.
|
||
The caller must free the array with ldap_value_free(). NULL if unsuccessful.
|
||
--*/
|
||
{
|
||
PWCHAR Attr;
|
||
BerElement *Ber;
|
||
PLDAPMessage LdapMsg;
|
||
PLDAPMessage LdapEntry;
|
||
PWCHAR Attrs[2];
|
||
PWCHAR *Values = NULL;
|
||
|
||
//
|
||
// Search Base for all of its attributes + values
|
||
//
|
||
Attrs[0] = DesiredAttr;
|
||
Attrs[1] = NULL;
|
||
|
||
//
|
||
// Issue the ldap search
|
||
//
|
||
if (!LdapSearch(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY,
|
||
Attrs, 0, &LdapMsg, Quiet)) {
|
||
return NULL;
|
||
}
|
||
LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
if (LdapEntry) {
|
||
Attr = ldap_first_attribute(Ldap, LdapEntry, &Ber);
|
||
if (Attr) {
|
||
Values = ldap_get_values(Ldap, LdapEntry, Attr);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
return Values;
|
||
}
|
||
|
||
|
||
VOID
|
||
GuidToStr(
|
||
IN GUID *pGuid,
|
||
OUT PWCHAR s
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Convert a GUID to a string.
|
||
|
||
Arguments:
|
||
pGuid - ptr to the GUID.
|
||
s - The output character buffer.
|
||
Must be at least GUID_CHAR_LEN (36 bytes) long.
|
||
|
||
Function Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
if (pGuid != NULL) {
|
||
swprintf(s, L"%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
|
||
pGuid->Data1,
|
||
pGuid->Data2,
|
||
pGuid->Data3,
|
||
pGuid->Data4[0],
|
||
pGuid->Data4[1],
|
||
pGuid->Data4[2],
|
||
pGuid->Data4[3],
|
||
pGuid->Data4[4],
|
||
pGuid->Data4[5],
|
||
pGuid->Data4[6],
|
||
pGuid->Data4[7]);
|
||
} else {
|
||
swprintf(s, L"<null>");
|
||
}
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
GetRootDn(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR NamingContext
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
--*/
|
||
{
|
||
PWCHAR Root; // DS pathname of configuration container
|
||
PWCHAR *Values; // values from the attribute "namingContexts"
|
||
DWORD NumVals; // number of values
|
||
|
||
//
|
||
// Return all of the values for the attribute namingContexts
|
||
//
|
||
Values = GetValues(Ldap, CN_ROOT, ATTR_NAMING_CONTEXTS, FALSE);
|
||
if (Values == NULL)
|
||
return NULL;
|
||
|
||
//
|
||
// Find the naming context that begins with CN=Configuration
|
||
//
|
||
NumVals = ldap_count_values(Values);
|
||
while (NumVals--) {
|
||
_wcslwr(Values[NumVals]);
|
||
Root = wcsstr(Values[NumVals], NamingContext);
|
||
if (Root != NULL && Root == Values[NumVals]) {
|
||
Root = FrsWcsDup(Root);
|
||
ldap_value_free(Values);
|
||
return Root;
|
||
}
|
||
}
|
||
printf("ERROR - COULD NOT FIND %ws\n", NamingContext);
|
||
ldap_value_free(Values);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
ExtendDn(
|
||
IN PWCHAR Dn,
|
||
IN PWCHAR Cn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Extend an existing DN with a new CN= component.
|
||
|
||
Arguments:
|
||
Dn - distinguished name
|
||
Cn - common name
|
||
|
||
Return Value:
|
||
CN=Cn,Dn
|
||
--*/
|
||
{
|
||
ULONG Len;
|
||
PWCHAR NewDn;
|
||
|
||
if (!Dn || !Cn) {
|
||
return NULL;
|
||
}
|
||
|
||
Len = wcslen(L"CN=,") + wcslen(Dn) + wcslen(Cn) + 1;
|
||
NewDn = (PWCHAR)malloc(Len * sizeof(WCHAR));
|
||
wcscpy(NewDn, L"CN=");
|
||
wcscat(NewDn, Cn);
|
||
wcscat(NewDn, L",");
|
||
wcscat(NewDn, Dn);
|
||
return NewDn;
|
||
}
|
||
|
||
|
||
PVOID *
|
||
FindValues(
|
||
IN PLDAP Ldap,
|
||
IN PLDAPMessage LdapEntry,
|
||
IN PWCHAR DesiredAttr,
|
||
IN BOOL DoBerValues
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Return the DS values for one attribute in an entry.
|
||
|
||
Arguments:
|
||
Ldap - An open, bound ldap port.
|
||
LdapEntry - An ldap entry returned by ldap_search_s()
|
||
DesiredAttr - Return values for this attribute.
|
||
DoVerValues - Return the bervals
|
||
|
||
Return Value:
|
||
An array of char pointers that represents the values for the attribute.
|
||
The caller must free the array with ldap_value_free(). NULL if unsuccessful.
|
||
--*/
|
||
{
|
||
PWCHAR LdapAttr; // Retrieved from an ldap entry
|
||
BerElement *Ber; // Needed for scanning attributes
|
||
|
||
//
|
||
// Search the entry for the desired attribute
|
||
//
|
||
for (LdapAttr = ldap_first_attribute(Ldap, LdapEntry, &Ber);
|
||
LdapAttr != NULL;
|
||
LdapAttr = ldap_next_attribute(Ldap, LdapEntry, Ber)) {
|
||
if (_wcsicmp(DesiredAttr, LdapAttr) == 0) {
|
||
//
|
||
// Return the values for DesiredAttr
|
||
//
|
||
if (DoBerValues) {
|
||
return (PVOID *)ldap_get_values_len(Ldap, LdapEntry, LdapAttr);
|
||
} else {
|
||
return (PVOID *)ldap_get_values(Ldap, LdapEntry, LdapAttr);
|
||
}
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
FindValue(
|
||
IN PLDAP Ldap,
|
||
IN PLDAPMessage LdapEntry,
|
||
IN PWCHAR DesiredAttr
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Return a copy of the first DS value for one attribute in an entry.
|
||
|
||
Arguments:
|
||
Ldap - An open, bound ldap port.
|
||
LdapEntry - An ldap entry returned by ldap_search_s()
|
||
DesiredAttr - Return values for this attribute.
|
||
|
||
Return Value:
|
||
A zero-terminated string or NULL if the attribute or its value
|
||
doesn't exist. The string is freed with FREE_NO_HEADER().
|
||
--*/
|
||
{
|
||
PWCHAR Val;
|
||
PWCHAR *Values;
|
||
|
||
// Get ldap's array of values
|
||
Values = (PWCHAR *)FindValues(Ldap, LdapEntry, DesiredAttr, FALSE);
|
||
|
||
// Copy the first value (if any)
|
||
Val = (Values) ? FrsWcsDup(Values[0]) : NULL;
|
||
|
||
// Free ldap's array of values
|
||
ldap_value_free(Values);
|
||
|
||
return Val;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FindBerValue(
|
||
IN PLDAP ldap,
|
||
IN PLDAPMessage Entry,
|
||
IN PWCHAR DesiredAttr,
|
||
OUT ULONG *Len,
|
||
OUT VOID **Value
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Return a copy of the attributes object's schedule
|
||
|
||
Arguments:
|
||
ldap - An open, bound ldap port.
|
||
Entry - An ldap entry returned by ldap_search_s()
|
||
DesiredAttr - desired attribute
|
||
Len - length of Value
|
||
Value - binary value
|
||
|
||
Return Value:
|
||
The address of a schedule or NULL. Free with FrsFree().
|
||
--*/
|
||
{
|
||
PLDAP_BERVAL *Values;
|
||
PSCHEDULE Schedule;
|
||
|
||
*Len = 0;
|
||
*Value = NULL;
|
||
|
||
//
|
||
// Get ldap's array of values
|
||
//
|
||
Values = (PLDAP_BERVAL *)FindValues(ldap, Entry, DesiredAttr, TRUE);
|
||
if (!Values) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Return a copy of the schedule
|
||
//
|
||
*Len = Values[0]->bv_len;
|
||
if (*Len) {
|
||
*Value = (PWCHAR)malloc(*Len);
|
||
CopyMemory(*Value, Values[0]->bv_val, *Len);
|
||
}
|
||
ldap_value_free_len(Values);
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpValues(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Dn,
|
||
IN DWORD Scope,
|
||
IN PWCHAR Class,
|
||
IN PWCHAR Attrs[],
|
||
IN BOOL IfEmpty
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Print the values and attributes for an object in the DS.
|
||
|
||
Arguments:
|
||
ldap - An open, bound ldap port.
|
||
Base - The "pathname" of a DS object.
|
||
Scope - Dump the values about the object (LDAP_SCOPE_BASE) or
|
||
about the objects contained in this object (LDAP_SCOPE_ONELEVEL)
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR Attr; // Retrieved from an ldap entry
|
||
BerElement *Ber; // Needed for scanning attributes
|
||
PLDAPMessage Msg; // Opaque stuff from ldap subsystem
|
||
PLDAPMessage Entry; // Opaque stuff from ldap subsystem
|
||
PWCHAR *Values; // Array of values for desired attribute
|
||
PLDAP_BERVAL *Balues; // Array of values for desired attribute
|
||
DWORD NumVals; // Number of entries in Values
|
||
PWCHAR Rdn; // An entries "pathname" in the DS
|
||
WCHAR GuidStr[GUID_CHAR_LEN + 1];
|
||
PWCHAR EntryDn;
|
||
ULONG i;
|
||
|
||
//
|
||
// Search Base for all of the attributes + values of Class
|
||
//
|
||
if (!LdapSearch(Ldap, Dn, Scope, Class,
|
||
Attrs, 0, &Msg, !IfEmpty)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (Entry = ldap_first_entry(Ldap, Msg);
|
||
Entry != NULL;
|
||
Entry = ldap_next_entry(Ldap, Entry)) {
|
||
|
||
EntryDn = FindValue(Ldap, Entry, ATTR_DN);
|
||
if (EntryDn) {
|
||
Attr = ldap_first_attribute(Ldap, Entry, &Ber);
|
||
if (Attr) {
|
||
Attr = ldap_next_attribute(Ldap, Entry, Ber);
|
||
}
|
||
if (!IfEmpty && !Attr) {
|
||
continue;
|
||
}
|
||
Rdn = MakeRdn(EntryDn);
|
||
printf("%ws\n", Rdn);
|
||
FREE(EntryDn);
|
||
FREE(Rdn);
|
||
} else {
|
||
Attr = ldap_first_attribute(Ldap, Entry, &Ber);
|
||
if (!IfEmpty && !Attr) {
|
||
continue;
|
||
}
|
||
printf("Entry has no distinguished name\n");
|
||
}
|
||
|
||
//
|
||
// Scan the attributes of an entry
|
||
//
|
||
for (Attr = ldap_first_attribute(Ldap, Entry, &Ber);
|
||
Attr != NULL;
|
||
Attr = ldap_next_attribute(Ldap, Entry, Ber)) {
|
||
|
||
//
|
||
// Printed above; don't repeat
|
||
//
|
||
if (!wcscmp(Attr, ATTR_DN)) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Print the values
|
||
//
|
||
printf(" %ws\n", Attr);
|
||
|
||
for (i = 0; GuidAttrs[i]; ++i) {
|
||
if (!wcscmp(Attr, GuidAttrs[i])) {
|
||
Balues = ldap_get_values_len(Ldap, Entry, Attr);
|
||
NumVals = ldap_count_values_len(Balues);
|
||
if (NumVals) {
|
||
GuidToStr((GUID *)Balues[0]->bv_val, GuidStr);
|
||
printf(" Length %d; %ws\n",
|
||
Balues[0]->bv_len, GuidStr);
|
||
}
|
||
ldap_value_free_len(Balues);
|
||
break;
|
||
}
|
||
}
|
||
if (GuidAttrs[i]) {
|
||
continue;
|
||
}
|
||
for (i = 0; BerAttrs[i]; ++i) {
|
||
if (!wcscmp(Attr, BerAttrs[i])) {
|
||
Balues = ldap_get_values_len(Ldap, Entry, Attr);
|
||
NumVals = ldap_count_values_len(Balues);
|
||
if (NumVals) {
|
||
printf(" Length %d\n",
|
||
Balues[0]->bv_len);
|
||
}
|
||
ldap_value_free_len(Balues);
|
||
break;
|
||
}
|
||
}
|
||
if (BerAttrs[i]) {
|
||
continue;
|
||
}
|
||
|
||
if (!wcscmp(Attr, L"schedule")) {
|
||
Balues = ldap_get_values_len(Ldap, Entry, Attr);
|
||
NumVals = ldap_count_values_len(Balues);
|
||
if (NumVals) {
|
||
printf(" Length %d; Number %d\n",
|
||
NumVals,
|
||
Balues[0]->bv_len,
|
||
((PSCHEDULE)(Balues[0]->bv_val))->NumberOfSchedules);
|
||
}
|
||
ldap_value_free_len(Balues);
|
||
continue;
|
||
}
|
||
Values = ldap_get_values(Ldap, Entry, Attr);
|
||
NumVals = ldap_count_values(Values);
|
||
while (NumVals--) {
|
||
printf(" %ws\n", Values[NumVals]);
|
||
}
|
||
ldap_value_free(Values);
|
||
}
|
||
}
|
||
ldap_msgfree(Msg);
|
||
}
|
||
|
||
|
||
DWORD
|
||
GetDnsName(
|
||
IN PWCHAR Server,
|
||
OUT PWCHAR *DnsName
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Retrieve this machine's DNS name.
|
||
|
||
Arguments:
|
||
Server
|
||
DnsName - wide char version of dns name
|
||
|
||
Return Value:
|
||
WSA Status
|
||
--*/
|
||
{
|
||
INT SStatus;
|
||
WORD DnsVersion = MAKEWORD(1, 1);
|
||
struct hostent *Host;
|
||
WSADATA WSAData;
|
||
PCHAR DnsNameA;
|
||
PCHAR ServerA;
|
||
|
||
*DnsName = NULL;
|
||
|
||
//
|
||
// Get this machine's DNS name
|
||
//
|
||
|
||
//
|
||
// Initialize the socket subsystem
|
||
//
|
||
if (SStatus = WSAStartup(DnsVersion, &WSAData)) {
|
||
fprintf(stderr, "Can't get DNS name; Socket startup error %d\n",
|
||
SStatus);
|
||
return SStatus;
|
||
};
|
||
//
|
||
// Get the DNS name
|
||
//
|
||
ServerA = FrsWtoA(Server);
|
||
Host = gethostbyname(ServerA);
|
||
FREE(ServerA);
|
||
if (Host == NULL) {
|
||
SStatus = WSAGetLastError();
|
||
fprintf(stderr, "Can't get DNS name for %ws; gethostbyname error %d\n",
|
||
Server, SStatus);
|
||
return SStatus;
|
||
}
|
||
if (Host->h_name == NULL) {
|
||
fprintf(stderr, "DNS name for %ws is NULL\n", Server);
|
||
return WSAEFAULT;
|
||
}
|
||
//
|
||
// Return both the ASCII and UNICODE versions
|
||
//
|
||
*DnsName = FrsAtoW(Host->h_name);
|
||
WSACleanup();
|
||
return 0;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
GetNextDn(
|
||
IN PLDAP Ldap,
|
||
PLDAPMessage LdapEntry,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR Cn = NULL;
|
||
PWCHAR Dn = NULL;
|
||
|
||
Cn = FindValue(Ldap, LdapEntry, ATTR_CN);
|
||
if (Cn) {
|
||
Dn = ExtendDn(ParentDn, Cn);
|
||
FREE(Cn)
|
||
}
|
||
return Dn;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
DumpAttrs(
|
||
IN PLDAP Ldap,
|
||
PLDAPMessage LdapEntry,
|
||
IN PWCHAR ParentDn,
|
||
IN PWCHAR *Attrs,
|
||
IN PWCHAR Indent
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD NumVals;
|
||
ULONG ScheduleLen;
|
||
ULONG ExtensionsLen;
|
||
PSCHEDULE Schedule = NULL;
|
||
PCHAR Extensions = NULL;
|
||
PWCHAR Val = NULL;
|
||
PWCHAR Rdn = NULL;
|
||
PWCHAR Pdn = NULL;
|
||
PWCHAR PRdn = NULL;
|
||
PWCHAR *Values = NULL;
|
||
|
||
if (!Attrs) {
|
||
return NULL;
|
||
}
|
||
|
||
while (*Attrs) {
|
||
//
|
||
// Don't bother, the Cn will do
|
||
//
|
||
if (!wcscmp(*Attrs, ATTR_DN)) {
|
||
++Attrs;
|
||
continue;
|
||
}
|
||
if (!wcscmp(*Attrs, ATTR_COMPUTER_REF_BL)) {
|
||
Values = ldap_get_values(Ldap, LdapEntry, *Attrs);
|
||
NumVals = ldap_count_values(Values);
|
||
while (NumVals--) {
|
||
Rdn = MakeRdn(Values[NumVals]);
|
||
Pdn = FrsDsMakeParentDn(Values[NumVals]);
|
||
PRdn = MakeRdn(Pdn);
|
||
printf(" %ws%ws=%ws\\%ws\n", Indent, *Attrs, PRdn, Rdn);
|
||
FREE(Rdn);
|
||
FREE(Pdn);
|
||
FREE(PRdn);
|
||
}
|
||
ldap_value_free(Values);
|
||
} else if (!wcscmp(*Attrs, ATTR_SCHEDULE)) {
|
||
FindBerValue(Ldap,
|
||
LdapEntry,
|
||
ATTR_SCHEDULE,
|
||
&ScheduleLen,
|
||
(VOID **)&Schedule);
|
||
if (Schedule) {
|
||
// PrintShortSchedule(Indent, Schedule, ScheduleLen);
|
||
PrintLongSchedule(L" ", Indent, Schedule, ScheduleLen);
|
||
FREE(Schedule);
|
||
} else {
|
||
printf(" %wsSchedule=\n", Indent);
|
||
}
|
||
} else if (!wcscmp(*Attrs, ATTR_EXTENSIONS)) {
|
||
FindBerValue(Ldap,
|
||
LdapEntry,
|
||
ATTR_EXTENSIONS,
|
||
&ExtensionsLen,
|
||
(VOID **)&Extensions);
|
||
if (Extensions) {
|
||
FREE(Extensions);
|
||
printf(" %wsExtensions=%d\n", Indent, ExtensionsLen);
|
||
} else {
|
||
printf(" %wsExtensions=\n", Indent);
|
||
}
|
||
} else if (!wcscmp(*Attrs, ATTR_NAMING_CONTEXTS)) {
|
||
Values = ldap_get_values(Ldap, LdapEntry, *Attrs);
|
||
NumVals = ldap_count_values(Values);
|
||
while (NumVals--) {
|
||
printf(" %ws%ws=%ws\n", Indent, *Attrs, Values[NumVals]);
|
||
}
|
||
ldap_value_free(Values);
|
||
} else {
|
||
Val = FindValue(Ldap, LdapEntry, *Attrs);
|
||
if (Val) {
|
||
if (!wcscmp(*Attrs, ATTR_CN)) {
|
||
printf("%ws%ws\n", Indent, Val);
|
||
} else if (!wcscmp(*Attrs, ATTR_FROM_SERVER) ||
|
||
!wcscmp(*Attrs, ATTR_PRIMARY_MEMBER) ||
|
||
!wcscmp(*Attrs, ATTR_COMPUTER_REF) ||
|
||
!wcscmp(*Attrs, ATTR_COMPUTER_REF_BL) ||
|
||
!wcscmp(*Attrs, ATTR_MEMBER_REF) ||
|
||
!wcscmp(*Attrs, ATTR_MEMBER_REF_BL) ||
|
||
!wcscmp(*Attrs, ATTR_SERVER_REF_BL) ||
|
||
!wcscmp(*Attrs, ATTR_SERVER_REF)) {
|
||
Rdn = MakeRdn(Val);
|
||
Pdn = FrsDsMakeParentDn(Val);
|
||
PRdn = MakeRdn(Pdn);
|
||
printf(" %ws%ws=%ws\\%ws\n", Indent, *Attrs, PRdn, Rdn);
|
||
FREE(Rdn);
|
||
FREE(Pdn);
|
||
FREE(PRdn);
|
||
} else {
|
||
printf(" %ws%ws=%ws\n", Indent, *Attrs, Val);
|
||
}
|
||
FREE(Val);
|
||
} else {
|
||
printf(" %ws%ws=\n", Indent, *Attrs);
|
||
}
|
||
}
|
||
++Attrs;
|
||
}
|
||
return GetNextDn(Ldap, LdapEntry, ParentDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpCxtions(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Cxtions
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_FROM_SERVER;
|
||
DesiredAttrs[2] = ATTR_SCHEDULE;
|
||
DesiredAttrs[3] = ATTR_ENABLED_CXTION;
|
||
DesiredAttrs[4] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_CXTION,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpMembers(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Servers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_COMPUTER_REF;
|
||
DesiredAttrs[2] = ATTR_MEMBER_REF_BL;
|
||
DesiredAttrs[3] = ATTR_SERVER_REF;
|
||
DesiredAttrs[4] = NULL;
|
||
// DesiredAttrs[4] = ATTR_CONTROL_CREATION;
|
||
// DesiredAttrs[5] = ATTR_INBOUND_BACKLOG;
|
||
// DesiredAttrs[6] = ATTR_OUTBOUND_BACKLOG;
|
||
// DesiredAttrs[7] = ATTR_SERVICE_COMMAND;
|
||
// DesiredAttrs[8] = ATTR_UPDATE_TIMEOUT;
|
||
// DesiredAttrs[9] = ATTR_EXTENSIONS;
|
||
// DesiredAttrs[10] = ATTR_FLAGS;
|
||
// DesiredAttrs[11] = ATTR_AUTH_LEVEL;
|
||
DesiredAttrs[12] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_MEMBER,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
DumpCxtions(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpSets(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Sets
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_PRIMARY_MEMBER;
|
||
DesiredAttrs[2] = ATTR_SET_TYPE;
|
||
DesiredAttrs[3] = ATTR_SCHEDULE;
|
||
DesiredAttrs[4] = ATTR_DIRECTORY_FILTER;
|
||
DesiredAttrs[5] = ATTR_FILE_FILTER;
|
||
DesiredAttrs[6] = NULL;
|
||
// DesiredAttrs[7] = ATTR_DS_POLL;
|
||
// DesiredAttrs[8] = ATTR_EXTENSIONS;
|
||
// DesiredAttrs[9] = ATTR_FLAGS;
|
||
// DesiredAttrs[10] = ATTR_LEVEL_LIMIT;
|
||
// DesiredAttrs[11] = ATTR_AUTH_LEVEL;
|
||
DesiredAttrs[12] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_REPLICA_SET,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
DumpMembers(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpContexts(
|
||
IN PLDAP Ldap
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump every ds object related to replication
|
||
|
||
Arguments:
|
||
Ldap
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PWCHAR NextDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
//
|
||
// Setting
|
||
//
|
||
DesiredAttrs[0] = ATTR_NAMING_CONTEXTS;
|
||
DesiredAttrs[1] = ATTR_DEFAULT_NAMING_CONTEXT;
|
||
DesiredAttrs[2] = NULL;
|
||
if (LdapSearch(Ldap, CN_ROOT, LDAP_SCOPE_BASE, CATEGORY_ANY,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, CN_ROOT, DesiredAttrs, L"");
|
||
if (NextDn) {
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpAdminWorld(
|
||
IN PLDAP Ldap
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump every ds object related to replication
|
||
|
||
Arguments:
|
||
Ldap
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
//
|
||
// Services
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
|
||
//
|
||
// Setting
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = NULL;
|
||
// DesiredAttrs[1] = ATTR_EXTENSIONS;
|
||
DesiredAttrs[2] = NULL;
|
||
if (LdapSearch(Ldap, ServicesDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTFRS_SETTINGS,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ServicesDn, DesiredAttrs, L"");
|
||
if (NextDn) {
|
||
DumpSets(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
|
||
FREE(ServicesDn);
|
||
FREE(ConfigDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpSubscribers(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Subscribers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_REPLICA_ROOT;
|
||
DesiredAttrs[2] = ATTR_REPLICA_STAGE;
|
||
DesiredAttrs[3] = ATTR_MEMBER_REF;
|
||
DesiredAttrs[4] = ATTR_SCHEDULE;
|
||
DesiredAttrs[5] = NULL;
|
||
// DesiredAttrs[4] = ATTR_EXTENSIONS;
|
||
// DesiredAttrs[5] = ATTR_FAULT_CONDITION;
|
||
// DesiredAttrs[6] = ATTR_FLAGS;
|
||
// DesiredAttrs[7] = ATTR_SERVICE_COMMAND;
|
||
// DesiredAttrs[8] = ATTR_SERVICE_COMMAND_STATUS;
|
||
// DesiredAttrs[9] = ATTR_UPDATE_TIMEOUT;
|
||
DesiredAttrs[10] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_SUBSCRIBER,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
DumpSubscribers(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpSubscriptions(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Servers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_WORKING;
|
||
DesiredAttrs[2] = NULL;
|
||
// DesiredAttrs[2] = ATTR_EXTENSIONS;
|
||
// DesiredAttrs[3] = ATTR_VERSION;
|
||
DesiredAttrs[4] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_SUBSCRIPTIONS,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
DumpSubscribers(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpUserWorld(
|
||
IN PLDAP Ldap
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump every ds object related to replication
|
||
|
||
Arguments:
|
||
Ldap
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD WStatus;
|
||
PWCHAR DesiredAttrs[16];
|
||
DWORD NumVals;
|
||
PWCHAR *Values = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
PWCHAR DefaultDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
HANDLE Handle = NULL;
|
||
DS_NAME_RESULT *Cracked = NULL;
|
||
WCHAR **Crackee;
|
||
PDOMAIN_CONTROLLER_INFO DcInfo;
|
||
|
||
//
|
||
// Return all of the values for the attribute namingContexts
|
||
//
|
||
Values = GetValues(Ldap, CN_ROOT, ATTR_DEFAULT_NAMING_CONTEXT, TRUE);
|
||
if (!Values) {
|
||
fprintf(stderr, "ERROR - Can't find %ws in %ws\n",
|
||
ATTR_DEFAULT_NAMING_CONTEXT,
|
||
CN_ROOT);
|
||
return;
|
||
}
|
||
DefaultDn = FrsWcsDup(Values[0]);
|
||
ldap_value_free(Values);
|
||
|
||
//
|
||
// Get Info about a Primary Domain Controller (need the IP address)
|
||
//
|
||
WStatus = FrsDsGetDcInfo(&DcInfo,
|
||
DS_DIRECTORY_SERVICE_REQUIRED | // Flags
|
||
DS_WRITABLE_REQUIRED);
|
||
//
|
||
// Report the error and carry on
|
||
//
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "ERROR - Could not get DC Info; WStatus %d\n",
|
||
WStatus);
|
||
} else {
|
||
WStatus = DsBind(DcInfo->DomainControllerName, NULL, &Handle);
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "ERROR - DsBind(%ws); WStatus %d %08x\n",
|
||
DcInfo->DomainControllerName,
|
||
WStatus,
|
||
WStatus);
|
||
WStatus = DsBind(DcInfo->DomainControllerAddress, NULL, &Handle);
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "ERROR - DsBind(%ws); WStatus %d %08x\n",
|
||
DcInfo->DomainControllerAddress,
|
||
WStatus,
|
||
WStatus);
|
||
} else {
|
||
printf("DsBind(%ws) succeeded\n", DcInfo->DomainControllerAddress);
|
||
}
|
||
} else {
|
||
printf("DsBind(%ws) succeeded\n", DcInfo->DomainControllerName);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Find the naming context that begins with CN=Configuration
|
||
//
|
||
//
|
||
// Computers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_SAM;
|
||
DesiredAttrs[2] = ATTR_DNS_HOST_NAME;
|
||
DesiredAttrs[3] = ATTR_DN;
|
||
DesiredAttrs[4] = ATTR_COMPUTER_REF_BL;
|
||
DesiredAttrs[5] = ATTR_SERVER_REF;
|
||
DesiredAttrs[6] = ATTR_SERVER_REF_BL;
|
||
DesiredAttrs[7] = ATTR_USER_ACCOUNT_CONTROL;
|
||
DesiredAttrs[8] = NULL;
|
||
if (LdapSearch(Ldap, DefaultDn, LDAP_SCOPE_SUBTREE, CATEGORY_COMPUTER,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, DefaultDn, DesiredAttrs, L"");
|
||
FREE(NextDn);
|
||
NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
|
||
if (NextDn && HANDLE_IS_VALID(Handle)) {
|
||
Crackee = &NextDn;
|
||
WStatus = DsCrackNames(Handle,
|
||
DS_NAME_NO_FLAGS,
|
||
// DS_NAME_FLAG_SYNTACTICAL_ONLY,
|
||
|
||
DS_FQDN_1779_NAME,
|
||
|
||
DS_NT4_ACCOUNT_NAME,
|
||
//DS_CANONICAL_NAME,
|
||
|
||
1,
|
||
Crackee,
|
||
&Cracked);
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
printf("ERROR - Cracking name; WStatus %d\n", WStatus);
|
||
} else if (Cracked &&
|
||
Cracked->cItems &&
|
||
Cracked->rItems) {
|
||
if (Cracked->rItems->status) {
|
||
printf(" ERROR - Can't crack name; status %d\n",
|
||
Cracked->rItems->status);
|
||
} else {
|
||
printf(" Cracked Domain : %ws\n",
|
||
Cracked->rItems->pDomain);
|
||
printf(" Cracked Account: %ws\n",
|
||
Cracked->rItems->pName);
|
||
}
|
||
DsFreeNameResult(Cracked);
|
||
Cracked = NULL;
|
||
}
|
||
}
|
||
if (NextDn) {
|
||
DumpSubscriptions(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
|
||
//out:
|
||
if (HANDLE_IS_VALID(Handle)) {
|
||
DsUnBind(&Handle);
|
||
}
|
||
FREE(DefaultDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpDsDsa(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Servers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_DN;
|
||
DesiredAttrs[2] = ATTR_SCHEDULE;
|
||
DesiredAttrs[3] = ATTR_SERVER_REF;
|
||
DesiredAttrs[4] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTDS_DSA,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, ParentDn, DesiredAttrs, L" ");
|
||
if (NextDn) {
|
||
DumpCxtions(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DumpSysVolWorld(
|
||
IN PLDAP Ldap
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
Ldap
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PWCHAR NextDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR SitesDn = NULL;
|
||
|
||
//
|
||
// Return all of the values for the attribute namingContexts
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
SitesDn = ExtendDn(ConfigDn, CN_SITES);
|
||
|
||
//
|
||
// Setting
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_DNS_HOST_NAME;
|
||
DesiredAttrs[2] = ATTR_DN;
|
||
DesiredAttrs[3] = ATTR_SERVER_REF;
|
||
DesiredAttrs[4] = ATTR_SERVER_REF_BL;
|
||
DesiredAttrs[5] = NULL;
|
||
if (LdapSearch(Ldap, SitesDn, LDAP_SCOPE_SUBTREE, CATEGORY_SERVER,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = DumpAttrs(Ldap, LdapEntry, SitesDn, DesiredAttrs, L"");
|
||
if (NextDn) {
|
||
FREE(NextDn);
|
||
}
|
||
NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
|
||
if (NextDn) {
|
||
DumpDsDsa(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
//out:
|
||
FREE(ConfigDn);
|
||
FREE(SitesDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
ScriptCxtions(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Set,
|
||
IN PWCHAR ServerDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
PWCHAR From = NULL;
|
||
PWCHAR Partner = NULL;
|
||
PWCHAR Partners = NULL;
|
||
PWCHAR Server = NULL;
|
||
PWCHAR Tmp = NULL;
|
||
|
||
Server = MakeRdn(ServerDn);
|
||
|
||
//
|
||
// Cxtions
|
||
//
|
||
DesiredAttrs[0] = ATTR_FROM_SERVER;
|
||
DesiredAttrs[1] = NULL;
|
||
if (LdapSearch(Ldap, ServerDn, LDAP_SCOPE_ONELEVEL, CATEGORY_CXTION,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
From = FindValue(Ldap, LdapEntry, ATTR_FROM_SERVER);
|
||
if (From) {
|
||
Partner = MakeRdn(From);
|
||
if (Partner) {
|
||
if (Partners) {
|
||
Tmp = Partners;
|
||
Partners = FrsWcsCat(Tmp, L" ");
|
||
FREE(Tmp);
|
||
Tmp = Partners;
|
||
Partners = FrsWcsCat(Tmp, Partner);
|
||
FREE(Tmp);
|
||
FREE(Partner);
|
||
} else {
|
||
Partners = Partner;
|
||
}
|
||
}
|
||
FREE(From);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
if (Partners) {
|
||
printf("dstree /i %ws %ws %ws\n", Set, Server, Partners);
|
||
}
|
||
FREE(Server);
|
||
}
|
||
|
||
|
||
VOID
|
||
GetRootAndStage(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SubscriberDn,
|
||
OUT PWCHAR *Root,
|
||
OUT PWCHAR *Stage
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
*Root = NULL;
|
||
*Stage = NULL;
|
||
|
||
//
|
||
// Subscriber
|
||
//
|
||
DesiredAttrs[0] = ATTR_REPLICA_ROOT;
|
||
DesiredAttrs[1] = ATTR_REPLICA_STAGE;
|
||
DesiredAttrs[2] = NULL;
|
||
if (LdapSearch(Ldap, SubscriberDn, LDAP_SCOPE_BASE, CATEGORY_SUBSCRIBER,
|
||
DesiredAttrs, 0, &LdapMsg, TRUE)) {
|
||
LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
if (LdapEntry) {
|
||
*Root = FindValue(Ldap, LdapEntry, ATTR_REPLICA_ROOT);
|
||
*Stage = FindValue(Ldap, LdapEntry, ATTR_REPLICA_STAGE);
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
ScriptMembers(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SetDn,
|
||
IN BOOL ScriptingServers
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
PWCHAR Set = NULL;
|
||
PWCHAR Cn = NULL;
|
||
PWCHAR Root = NULL;
|
||
PWCHAR Stage = NULL;
|
||
PWCHAR MemberBl = NULL;
|
||
|
||
Set = MakeRdn(SetDn);
|
||
|
||
//
|
||
// Servers
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = ATTR_REPLICA_ROOT;
|
||
DesiredAttrs[2] = ATTR_REPLICA_STAGE;
|
||
DesiredAttrs[3] = ATTR_MEMBER_REF_BL;
|
||
DesiredAttrs[4] = NULL;
|
||
if (LdapSearch(Ldap, SetDn, LDAP_SCOPE_ONELEVEL, CATEGORY_MEMBER,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
if (ScriptingServers) {
|
||
Cn = FindValue(Ldap, LdapEntry, ATTR_CN);
|
||
MemberBl = FindValue(Ldap, LdapEntry, ATTR_MEMBER_REF_BL);
|
||
if (MemberBl) {
|
||
GetRootAndStage(Ldap, MemberBl, &Root, &Stage);
|
||
}
|
||
if (Cn) {
|
||
if (Root && Stage) {
|
||
printf("dstree /c %ws %ws %ws %ws\n", Set, Cn, Root, Stage);
|
||
} else {
|
||
printf("dstree /c %ws %ws\n", Set, Cn);
|
||
}
|
||
FREE(Cn);
|
||
FREE(Root);
|
||
FREE(Stage);
|
||
FREE(MemberBl);
|
||
}
|
||
} else {
|
||
NextDn = GetNextDn(Ldap, LdapEntry, SetDn);
|
||
if (NextDn) {
|
||
ScriptCxtions(Ldap, Set, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
FREE(Set);
|
||
}
|
||
|
||
|
||
VOID
|
||
ScriptSets(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
|
||
//
|
||
// Sets
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = NULL;
|
||
if (LdapSearch(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_REPLICA_SET,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = GetNextDn(Ldap, LdapEntry, ParentDn);
|
||
if (NextDn) {
|
||
ScriptMembers(Ldap, NextDn, TRUE);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = GetNextDn(Ldap,
|
||
LdapEntry,
|
||
ParentDn);
|
||
if (NextDn) {
|
||
ScriptMembers(Ldap, NextDn, FALSE);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
ScriptReplicationWorld(
|
||
VOID
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR DesiredAttrs[16];
|
||
PLDAP Ldap = NULL;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR NextDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Services
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
|
||
ScriptSets(Ldap, SettingsDn);
|
||
|
||
#if 0
|
||
Don't script all of the settings; only the test settings
|
||
//
|
||
// Setting
|
||
//
|
||
DesiredAttrs[0] = ATTR_CN;
|
||
DesiredAttrs[1] = NULL;
|
||
if (LdapSearch(Ldap, ServicesDn, LDAP_SCOPE_ONELEVEL, CATEGORY_NTFRS_SETTINGS,
|
||
DesiredAttrs, 0, &LdapMsg, FALSE)) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = GetNextDn(Ldap, LdapEntry, ServicesDn);
|
||
if (NextDn) {
|
||
ScriptSets(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
LdapMsg = NULL;
|
||
}
|
||
#endif 0
|
||
|
||
ldap_unbind(Ldap);
|
||
FREE(ServicesDn);
|
||
FREE(ConfigDn);
|
||
FREE(SettingsDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
DoListSchema(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SchemaDn,
|
||
IN struct AlterClass *Lists[]
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump schema
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i, j;
|
||
ULONG NumAttrs;
|
||
DWORD LStatus;
|
||
PWCHAR Attrs[64];
|
||
PWCHAR Dn = NULL;
|
||
|
||
for (j = 0; Lists[j]; ++j) {
|
||
Dn = ExtendDn(SchemaDn, Lists[j]->Cn);
|
||
NumAttrs = 0;
|
||
for (i = 0; Lists[j]->AlterAttrs[i].Attr; ++i) {
|
||
if (NumAttrs) {
|
||
if (!wcscmp(Attrs[NumAttrs - 1],
|
||
Lists[j]->AlterAttrs[i].Attr)) {
|
||
continue;
|
||
}
|
||
}
|
||
Attrs[NumAttrs++] = Lists[j]->AlterAttrs[i].Attr;
|
||
}
|
||
if (NumAttrs) {
|
||
Attrs[NumAttrs + 0] = ATTR_DN;
|
||
Attrs[NumAttrs + 1] = ATTR_SYSTEM_FLAGS;
|
||
Attrs[NumAttrs + 2] = ATTR_SYSTEM_MAY_CONTAIN;
|
||
Attrs[NumAttrs + 3] = ATTR_SYSTEM_MUST_CONTAIN;
|
||
Attrs[NumAttrs + 4] = ATTR_SYSTEM_POSS_SUPERIORS;
|
||
Attrs[NumAttrs + 5] = NULL;
|
||
DumpValues(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY, Attrs, FALSE);
|
||
}
|
||
FREE(Dn);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
ListSchema(
|
||
VOID
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump schema
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i, j;
|
||
ULONG NumAttrs;
|
||
DWORD LStatus;
|
||
PLDAP Ldap = NULL;
|
||
PWCHAR SchemaDn = NULL;
|
||
PWCHAR Dn = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
PWCHAR Attrs[64];
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
SchemaDn = GetRootDn(Ldap, SCHEMA_NAMING_CONTEXT);
|
||
if (!SchemaDn) {
|
||
return;
|
||
}
|
||
DoListSchema(Ldap, SchemaDn, AlterSchema);
|
||
DoListSchema(Ldap, SchemaDn, CreateClasses);
|
||
DoListSchema(Ldap, SchemaDn, CreateAttributes);
|
||
ldap_unbind(Ldap);
|
||
FREE(SchemaDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
CreateSchema(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SchemaDn,
|
||
IN struct AlterClass *Creates[],
|
||
IN DWORD ExpectedError
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
ULONG i, j;
|
||
PWCHAR Dn = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
//
|
||
// CREATE ATTRIBUTES OR CLASSES
|
||
//
|
||
for (j = 0; Creates[j]; ++j) {
|
||
Dn = ExtendDn(SchemaDn, Creates[j]->Cn);
|
||
printf(" %-30ws: CRE\n", Creates[j]->Cn);
|
||
for (i = 0; Creates[j]->AlterAttrs[i].Attr; ++i) {
|
||
AddMod(Creates[j]->AlterAttrs[i].Attr,
|
||
Creates[j]->AlterAttrs[i].Value,
|
||
&Mod);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, Dn, Mod);
|
||
if (LStatus != LDAP_SUCCESS &&
|
||
LStatus != ExpectedError) {
|
||
fprintf(stderr, "%-30ws ERROR %ws\n",
|
||
L"", ldap_err2string(LStatus));
|
||
}
|
||
FreeMod(&Mod);
|
||
FREE(Dn);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
UpdateSchema(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SchemaDn,
|
||
IN BOOL Hammering,
|
||
IN struct AlterClass *Updates[]
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
ULONG i, j;
|
||
PWCHAR Dn = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
//
|
||
// ALTER EXISTING CLASSES
|
||
//
|
||
for (j = 0; Updates[j]; ++j) {
|
||
Dn = ExtendDn(SchemaDn, Updates[j]->Cn);
|
||
for (i = 0; Updates[j]->AlterAttrs[i].Attr; ++i) {
|
||
AddMod(Updates[j]->AlterAttrs[i].Attr,
|
||
Updates[j]->AlterAttrs[i].Value,
|
||
&Mod);
|
||
if (Hammering) {
|
||
printf(" %-30ws: ADD %ws = %ws\n",
|
||
Updates[j]->Cn,
|
||
Updates[j]->AlterAttrs[i].Attr,
|
||
Updates[j]->AlterAttrs[i].Value);
|
||
LStatus = ldap_modify_s(Ldap, Dn, Mod);
|
||
if (LStatus != LDAP_SUCCESS &&
|
||
LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS) {
|
||
fprintf(stderr, "%-30ws ERROR %ws\n",
|
||
L"", ldap_err2string(LStatus));
|
||
}
|
||
} else {
|
||
printf(" %-30ws: DEL %ws = %ws\n",
|
||
Updates[j]->Cn,
|
||
Updates[j]->AlterAttrs[i].Attr,
|
||
Updates[j]->AlterAttrs[i].Value);
|
||
Mod[0]->mod_op = LDAP_MOD_DELETE;
|
||
LStatus = ldap_modify_s(Ldap, Dn, Mod);
|
||
if (LStatus != LDAP_SUCCESS &&
|
||
LStatus != LDAP_NO_SUCH_ATTRIBUTE &&
|
||
LStatus != LDAP_NO_SUCH_OBJECT) {
|
||
fprintf(stderr, "%-30ws ERROR %ws\n",
|
||
L"", ldap_err2string(LStatus));
|
||
}
|
||
}
|
||
FreeMod(&Mod);
|
||
}
|
||
FREE(Dn);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DeleteSchema(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR SchemaDn,
|
||
IN struct AlterClass *Deletes[],
|
||
IN DWORD ExpectedError
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR Dn = NULL;
|
||
DWORD LStatus;
|
||
ULONG j;
|
||
|
||
//
|
||
// DELETE ATTRIBUTES OR CLASSES
|
||
//
|
||
for (j = 0; Deletes[j]; ++j) {
|
||
Dn = ExtendDn(SchemaDn, Deletes[j]->Cn);
|
||
printf(" %-30ws: DEL\n", Deletes[j]->Cn);
|
||
LStatus = ldap_delete_s(Ldap, Dn);
|
||
if (LStatus != LDAP_SUCCESS &&
|
||
LStatus != ExpectedError) {
|
||
fprintf(stderr, "%-30ws ERROR %ws\n",
|
||
L"", ldap_err2string(LStatus));
|
||
}
|
||
FREE(Dn);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
RefreshSchema(
|
||
IN PLDAP Ldap
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
AddMod(L"schemaUpdateNow", L"1", &Mod);
|
||
LStatus = ldap_modify_s(Ldap, L"", Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "Can't force schema update; %ws\n",
|
||
ldap_err2string(LStatus));
|
||
printf("Waiting 5 minutes for schema updates to take effect\n");
|
||
Sleep(5 * 60 * 1000);
|
||
}
|
||
}
|
||
|
||
#define NTDS_SERVICE L"NTDS"
|
||
#define NTDS_ROOT L"System\\CurrentControlSet\\Services\\" NTDS_SERVICE
|
||
#define NTDS_PARAMETERS NTDS_ROOT L"\\Parameters"
|
||
#define NTDS_UPDATE_SCHEMA L"Schema Update Allowed"
|
||
#define NTDS_DELETE_SCHEMA L"Schema Delete Allowed"
|
||
|
||
|
||
BOOL
|
||
PutRegDWord(
|
||
IN PWCHAR FQKey,
|
||
IN PWCHAR Value,
|
||
IN DWORD DWord
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
This function writes a keyword value into the registry.
|
||
|
||
Arguments:
|
||
HKey - Key to be read
|
||
Param - value string to update
|
||
DWord - dword to be written
|
||
|
||
Return Value:
|
||
TRUE - Success
|
||
FALSE - Not
|
||
--*/
|
||
{
|
||
#define DEBSUB "PutRegDWord:"
|
||
HKEY HKey;
|
||
DWORD WStatus;
|
||
|
||
//
|
||
// Open the key
|
||
//
|
||
WStatus = RegOpenKey(HKEY_LOCAL_MACHINE, FQKey, &HKey);
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "[%ws] \"%ws\" Could not open. WStatus %d\n",
|
||
FQKey, Value, WStatus);
|
||
return FALSE;
|
||
}
|
||
//
|
||
|
||
//
|
||
// Write the value
|
||
//
|
||
WStatus = RegSetValueEx(HKey,
|
||
Value,
|
||
0,
|
||
REG_DWORD,
|
||
(PUCHAR)&DWord,
|
||
sizeof(DWord));
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
fprintf(stderr, "%ws: Value not written; WStatus %d\n", Value, WStatus);
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
HammerSchema(
|
||
IN BOOL Hammering
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
PLDAP Ldap = NULL;
|
||
PWCHAR SchemaDn = NULL;
|
||
PWCHAR Dn = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
ULONG i, j;
|
||
|
||
if (Hammering) {
|
||
printf("UPDATING SCHEMA...\n");
|
||
if (!PutRegDWord(NTDS_PARAMETERS, NTDS_UPDATE_SCHEMA, 1)) {
|
||
fprintf(stderr, "Could not enable schema update\n");
|
||
return;
|
||
}
|
||
} else {
|
||
printf("RESTORING SCHEMA...\n");
|
||
if (!PutRegDWord(NTDS_PARAMETERS, NTDS_UPDATE_SCHEMA, 1)) {
|
||
fprintf(stderr, "Could not enable schema update\n");
|
||
return;
|
||
}
|
||
if (!PutRegDWord(NTDS_PARAMETERS, NTDS_DELETE_SCHEMA, 1)) {
|
||
fprintf(stderr, "Could not enable schema deletes\n");
|
||
return;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
SchemaDn = GetRootDn(Ldap, SCHEMA_NAMING_CONTEXT);
|
||
if (!SchemaDn) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// CREATE/DELETE ATTRIBUTES AND CLASSES
|
||
//
|
||
if (Hammering) {
|
||
CreateSchema(Ldap,
|
||
SchemaDn,
|
||
CreateAttributes,
|
||
LDAP_ALREADY_EXISTS);
|
||
RefreshSchema(Ldap);
|
||
CreateSchema(Ldap,
|
||
SchemaDn,
|
||
CreateClasses,
|
||
LDAP_ALREADY_EXISTS);
|
||
RefreshSchema(Ldap);
|
||
UpdateSchema(Ldap,
|
||
SchemaDn,
|
||
Hammering,
|
||
AlterSchema);
|
||
} else {
|
||
UpdateSchema(Ldap,
|
||
SchemaDn,
|
||
Hammering,
|
||
AlterSchema);
|
||
RefreshSchema(Ldap);
|
||
DeleteSchema(Ldap,
|
||
SchemaDn,
|
||
CreateClasses,
|
||
LDAP_NO_SUCH_OBJECT);
|
||
RefreshSchema(Ldap);
|
||
DeleteSchema(Ldap,
|
||
SchemaDn,
|
||
CreateAttributes,
|
||
LDAP_NO_SUCH_OBJECT);
|
||
}
|
||
RefreshSchema(Ldap);
|
||
if (Hammering) {
|
||
printf("SCHEMA UPDATE COMPLETE\n");
|
||
} else {
|
||
printf("SCHEMA RESTORE COMPLETE\n");
|
||
}
|
||
ldap_unbind(Ldap);
|
||
FREE(SchemaDn);
|
||
return;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
GetCoDn(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Member,
|
||
OUT PWCHAR *ServerDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Find the computer object for Member
|
||
|
||
Arguments:
|
||
Ldap
|
||
Member
|
||
ServerDn
|
||
|
||
Return Value:
|
||
Dn of computer object or NULL. Free with FREE.
|
||
--*/
|
||
{
|
||
PWCHAR *Values = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PWCHAR CoDn = NULL;
|
||
PWCHAR Attrs[16];
|
||
WCHAR Filter[MAX_PATH + 1];
|
||
|
||
|
||
|
||
//
|
||
// Find the default naming context
|
||
//
|
||
Values = GetValues(Ldap, CN_ROOT, ATTR_DEFAULT_NAMING_CONTEXT, TRUE);
|
||
if (!Values) {
|
||
return NULL;
|
||
}
|
||
//
|
||
// Find the computer object with class=computer
|
||
//
|
||
swprintf(Filter,
|
||
L"(&%s(sAMAccountName=%s$))",
|
||
CATEGORY_COMPUTER,
|
||
Member);
|
||
|
||
Attrs[0] = ATTR_DN;
|
||
Attrs[1] = ATTR_SERVER_REF;
|
||
Attrs[2] = ATTR_SERVER_REF_BL;
|
||
Attrs[3] = NULL;
|
||
if (LdapSearch(Ldap, Values[0], LDAP_SCOPE_SUBTREE, Filter,
|
||
Attrs, 0, &LdapMsg, FALSE)) {
|
||
LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
if (LdapEntry) {
|
||
CoDn = FindValue(Ldap, LdapEntry, ATTR_DN);
|
||
if (ServerDn) {
|
||
*ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF_BL);
|
||
if (!*ServerDn) {
|
||
*ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF);
|
||
}
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
}
|
||
if (CoDn) {
|
||
return CoDn;
|
||
}
|
||
//
|
||
// Find the computer object with class=computer (possible after
|
||
// an NT4 to NT5 upgrade.
|
||
//
|
||
swprintf(Filter,
|
||
L"(&%s(sAMAccountName=%s$))",
|
||
CATEGORY_USER,
|
||
Member);
|
||
|
||
Attrs[0] = ATTR_DN;
|
||
Attrs[1] = ATTR_SERVER_REF;
|
||
Attrs[2] = ATTR_SERVER_REF_BL;
|
||
Attrs[3] = NULL;
|
||
if (LdapSearch(Ldap, Values[0], LDAP_SCOPE_SUBTREE, Filter,
|
||
Attrs, 0, &LdapMsg, FALSE)) {
|
||
LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
if (LdapEntry) {
|
||
CoDn = FindValue(Ldap, LdapEntry, ATTR_DN);
|
||
if (ServerDn) {
|
||
*ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF_BL);
|
||
if (!*ServerDn) {
|
||
*ServerDn = FindValue(Ldap, LdapEntry, ATTR_SERVER_REF);
|
||
}
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
}
|
||
ldap_value_free(Values);
|
||
return CoDn;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
GetSiteName(
|
||
IN PWCHAR Member
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Retrieve this machine's site name. We assume the site name
|
||
matches the site container's name in the DS.
|
||
|
||
Arguments:
|
||
Member - corresponds to site container's name
|
||
|
||
Return Value:
|
||
Site name or NULL. Free with FREE.
|
||
--*/
|
||
{
|
||
DWORD WStatus;
|
||
PWCHAR Name;
|
||
PWCHAR Site;
|
||
|
||
//
|
||
// Get this machine's DNS name
|
||
//
|
||
WStatus = DsGetSiteName(Member, &Name);
|
||
if (!WIN_SUCCESS(WStatus)) {
|
||
return NULL;
|
||
}
|
||
Site = FrsWcsDup(Name);
|
||
NetApiBufferFree(Name);
|
||
return Site;
|
||
}
|
||
|
||
|
||
PWCHAR
|
||
GetServerDn(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Member
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Find our server object (assumes that machine name == server name)
|
||
|
||
Arguments:
|
||
Ldap
|
||
Member
|
||
|
||
Return Value:
|
||
Server DN (if any)
|
||
--*/
|
||
{
|
||
PWCHAR *Values = NULL;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR SitesDn = NULL;
|
||
PWCHAR Site = NULL;
|
||
PWCHAR SiteDn = NULL;
|
||
PWCHAR ServersDn = NULL;
|
||
PWCHAR ServerDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PWCHAR RealServerDn = NULL;
|
||
|
||
//
|
||
// Return all of the values for the attribute namingContexts
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return NULL;
|
||
}
|
||
SitesDn = ExtendDn(ConfigDn, CN_SITES);
|
||
Site = GetSiteName(Member);
|
||
if (!Site) {
|
||
goto out;
|
||
}
|
||
SiteDn = ExtendDn(SitesDn, Site);
|
||
ServersDn = ExtendDn(SiteDn, CN_SERVERS);
|
||
ServerDn = ExtendDn(ServersDn, Member);
|
||
SettingsDn = ExtendDn(ServerDn, CN_NTDS_SETTINGS);
|
||
Values = GetValues(Ldap, SettingsDn, ATTR_DN, TRUE);
|
||
if (!Values) {
|
||
goto out;
|
||
}
|
||
RealServerDn = FrsWcsDup(Values[0]);
|
||
|
||
out:
|
||
FREE(ConfigDn);
|
||
FREE(SitesDn);
|
||
FREE(SiteDn);
|
||
FREE(Site);
|
||
FREE(ServersDn);
|
||
FREE(ServerDn);
|
||
FREE(SettingsDn);
|
||
return RealServerDn;
|
||
}
|
||
|
||
|
||
#define SIZEOF_EXTENSIONS 127
|
||
VOID
|
||
CreateReplicationWorld(
|
||
IN DWORD argc,
|
||
IN PWCHAR *Argv,
|
||
IN BOOL IsPrimary
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Create the required objects
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD WStatus;
|
||
DWORD LStatus;
|
||
ULONG ScheduleLength;
|
||
PWCHAR Member;
|
||
PWCHAR Set;
|
||
PWCHAR Root;
|
||
PWCHAR Stage;
|
||
GUID NewGuid;
|
||
GUID OldGuid;
|
||
CHAR Extensions[SIZEOF_EXTENSIONS];
|
||
PLDAP Ldap = NULL;
|
||
PWCHAR CoDn = NULL;
|
||
PWCHAR SubsDn = NULL;
|
||
PWCHAR SubDn = NULL;
|
||
PWCHAR Subscriber = NULL;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServerDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PWCHAR SetDn = NULL;
|
||
PWCHAR MemberDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PSCHEDULE Schedule = NULL;
|
||
PWCHAR Cn = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
Set = Argv[2];
|
||
if (argc > 2) {
|
||
Member = Argv[3];
|
||
}
|
||
if (argc > 3) {
|
||
Root = Argv[4];
|
||
Stage = Argv[5];
|
||
}
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// ADMIN SIDE
|
||
//
|
||
//
|
||
// Services Dn
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
|
||
|
||
//
|
||
// Settings
|
||
//
|
||
UuidCreateNil(&OldGuid);
|
||
AddMod(ATTR_CLASS, ATTR_NTFRS_SETTINGS, &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
LStatus = ldap_add_s(Ldap, SettingsDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
//
|
||
// May be a new schema that lacks the old version guid
|
||
//
|
||
AddBerMod(ATTR_OLD_VERSION_GUID, (PCHAR)&OldGuid, sizeof(GUID), &Mod);
|
||
AddMod(ATTR_CLASS, ATTR_NTFRS_SETTINGS, &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, sizeof(SIZEOF_EXTENSIONS), &Mod);
|
||
LStatus = ldap_add_s(Ldap, SettingsDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
SettingsDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Set
|
||
//
|
||
SetDn = ExtendDn(SettingsDn, Set);
|
||
AddMod(ATTR_CLASS, ATTR_REPLICA_SET, &Mod);
|
||
AddMod(ATTR_SET_TYPE, FRS_RSTYPE_OTHERW, &Mod);
|
||
// AddMod(ATTR_DIRECTORY_FILTER, ATTR_DIRECTORY_FILTER, &Mod);
|
||
// AddMod(ATTR_FILE_FILTER, ATTR_FILE_FILTER, &Mod);
|
||
// AddMod(ATTR_DS_POLL, L"17", &Mod);
|
||
// AddMod(ATTR_FLAGS, L"18", &Mod);
|
||
// AddMod(ATTR_LEVEL_LIMIT, L"18", &Mod);
|
||
// AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
// AddBerMod(ATTR_NEW_SET_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
|
||
// AddBerMod(ATTR_NEW_VERSION_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
|
||
ConditionalBuildSchedule(&Schedule, &ScheduleLength);
|
||
if (Schedule) {
|
||
AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, SetDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
//
|
||
// May be a new schema that lacks the old set guid
|
||
//
|
||
AddMod(ATTR_CLASS, ATTR_REPLICA_SET, &Mod);
|
||
AddMod(ATTR_SET_TYPE, FRS_RSTYPE_OTHERW, &Mod);
|
||
// AddMod(ATTR_DIRECTORY_FILTER, ATTR_DIRECTORY_FILTER, &Mod);
|
||
// AddMod(ATTR_FILE_FILTER, ATTR_FILE_FILTER, &Mod);
|
||
// AddMod(ATTR_DS_POLL, L"17", &Mod);
|
||
// AddMod(ATTR_FLAGS, L"18", &Mod);
|
||
// AddMod(ATTR_LEVEL_LIMIT, L"18", &Mod);
|
||
// AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
AddBerMod(ATTR_OLD_SET_GUID, (PCHAR)&OldGuid, sizeof(GUID), &Mod);
|
||
AddBerMod(ATTR_NEW_SET_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
|
||
AddBerMod(ATTR_NEW_VERSION_GUID, (PCHAR)&NewGuid, sizeof(GUID), &Mod);
|
||
ConditionalBuildSchedule(&Schedule, &ScheduleLength);
|
||
if (Schedule) {
|
||
AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, SetDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
SetDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
}
|
||
|
||
if (argc < 4) {
|
||
goto out;
|
||
}
|
||
|
||
//
|
||
// Member
|
||
//
|
||
CoDn = GetCoDn(Ldap, Member, &ServerDn);
|
||
if (!CoDn) {
|
||
fprintf(stderr, "ERROR - Can't get computer object for %ws\n", Member);
|
||
goto out;
|
||
}
|
||
//
|
||
// The CO doesn't have a server reference; create one
|
||
//
|
||
if (!ServerDn) {
|
||
ServerDn = GetServerDn(Ldap, Member);
|
||
if (ServerDn) {
|
||
AddMod(ATTR_SERVER_REF, ServerDn, &Mod);
|
||
LStatus = ldap_modify_s(Ldap, CoDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS &&
|
||
LStatus != LDAP_SUCCESS) {
|
||
AddMod(ATTR_SERVER_REF, CoDn, &Mod);
|
||
LStatus = ldap_modify_s(Ldap, ServerDn, Mod);
|
||
FreeMod(&Mod);
|
||
if (LStatus != LDAP_ATTRIBUTE_OR_VALUE_EXISTS &&
|
||
LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't update server reference for %ws: %ws\n",
|
||
CoDn, ldap_err2string(LStatus));
|
||
fprintf(stderr, "ERROR - Server %ws\n", ServerDn);
|
||
FREE(ServerDn);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
MemberDn = ExtendDn(SetDn, Member);
|
||
AddMod(ATTR_CLASS, ATTR_MEMBER, &Mod);
|
||
AddMod(ATTR_COMPUTER_REF, CoDn, &Mod);
|
||
// AddMod(ATTR_CONTROL_CREATION, ATTR_CONTROL_CREATION, &Mod);
|
||
// AddMod(ATTR_INBOUND_BACKLOG, ATTR_INBOUND_BACKLOG, &Mod);
|
||
// AddMod(ATTR_OUTBOUND_BACKLOG, ATTR_OUTBOUND_BACKLOG, &Mod);
|
||
// AddMod(ATTR_SERVICE_COMMAND, ATTR_SERVICE_COMMAND, &Mod);
|
||
// AddMod(ATTR_UPDATE_TIMEOUT, L"50", &Mod);
|
||
// AddMod(ATTR_AUTH_LEVEL, L"18", &Mod);
|
||
// AddMod(ATTR_FLAGS, L"3", &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
if (ServerDn) {
|
||
AddMod(ATTR_SERVER_REF, ServerDn, &Mod);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, MemberDn, Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
MemberDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
FreeMod(&Mod);
|
||
|
||
//
|
||
// Primary member reference on set
|
||
//
|
||
if (IsPrimary) {
|
||
AddMod(ATTR_PRIMARY_MEMBER, MemberDn, &Mod);
|
||
Mod[0]->mod_op = LDAP_MOD_REPLACE;
|
||
LStatus = ldap_modify_s(Ldap, SetDn, Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't set primary member to %ws for %ws: %ws\n",
|
||
MemberDn, SetDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
FreeMod(&Mod);
|
||
}
|
||
|
||
//
|
||
// USER SIDE
|
||
//
|
||
//
|
||
// Subscriptions
|
||
//
|
||
SubsDn = ExtendDn(CoDn, CN_SUBSCRIPTIONS);
|
||
AddMod(ATTR_CLASS, ATTR_SUBSCRIPTIONS, &Mod);
|
||
// AddMod(ATTR_WORKING, L"%SystemRoot%\\ntfrs", &Mod);
|
||
// AddMod(ATTR_VERSION, ATTR_VERSION, &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
LStatus = ldap_add_s(Ldap, SubsDn, Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
SubsDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
FreeMod(&Mod);
|
||
|
||
//
|
||
// Subscriber
|
||
//
|
||
Subscriber = FrsWcsCat(Set, Member);
|
||
SubDn = ExtendDn(SubsDn, Subscriber);
|
||
AddMod(ATTR_CLASS, ATTR_SUBSCRIBER, &Mod);
|
||
AddMod(ATTR_REPLICA_ROOT, Root, &Mod);
|
||
AddMod(ATTR_REPLICA_STAGE, Stage, &Mod);
|
||
AddMod(ATTR_MEMBER_REF, MemberDn, &Mod);
|
||
// AddBerMod(ATTR_EXTENSIONS, Extensions, SIZEOF_EXTENSIONS, &Mod);
|
||
// AddMod(ATTR_FAULT_CONDITION, L"NONE", &Mod);
|
||
// AddMod(ATTR_FLAGS, L"1", &Mod);
|
||
// AddMod(ATTR_SERVICE_COMMAND, ATTR_SERVICE_COMMAND, &Mod);
|
||
// AddMod(ATTR_SERVICE_COMMAND_STATUS, L"100", &Mod);
|
||
// AddMod(ATTR_UPDATE_TIMEOUT, L"100", &Mod);
|
||
ConditionalBuildSchedule(&Schedule, &ScheduleLength);
|
||
if (Schedule) {
|
||
AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
|
||
FREE(Schedule);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, SubDn, Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
SubDn, ldap_err2string(LStatus));
|
||
goto out;
|
||
}
|
||
FreeMod(&Mod);
|
||
|
||
out:
|
||
ldap_unbind(Ldap);
|
||
if (LdapMsg) {
|
||
ldap_msgfree(LdapMsg);
|
||
}
|
||
FREE(Schedule);
|
||
FREE(Cn);
|
||
FREE(ConfigDn);
|
||
FREE(ServicesDn);
|
||
FREE(SetDn);
|
||
FREE(SettingsDn);
|
||
FREE(MemberDn);
|
||
FREE(CoDn);
|
||
FREE(SubsDn);
|
||
FREE(Subscriber);
|
||
FREE(SubDn);
|
||
FREE(ServerDn);
|
||
FreeMod(&Mod);
|
||
}
|
||
|
||
|
||
PWCHAR DupNames[] = {L"_A", L"_B", L"_C", L"_D", L"_E", L"_F", L"_G", L"_H", NULL};
|
||
VOID
|
||
CreateInbounds(
|
||
IN DWORD argc,
|
||
IN WCHAR **Argv
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
ULONG i;
|
||
DWORD LStatus;
|
||
ULONG ScheduleLength;
|
||
ULONG dupx;
|
||
PLDAP Ldap = NULL;
|
||
PWCHAR Cxtion = NULL;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PWCHAR SetDn = NULL;
|
||
PWCHAR ServerDn = NULL;
|
||
PWCHAR CxtionDn = NULL;
|
||
PWCHAR CxtionDnDup = NULL;
|
||
|
||
PWCHAR PartnerDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
PSCHEDULE Schedule = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Server Dn
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
|
||
|
||
|
||
SetDn = ExtendDn(SettingsDn, Argv[2]);
|
||
ServerDn = ExtendDn(SetDn, Argv[3]);
|
||
|
||
for (i = 4; i < argc; ++i) {
|
||
PartnerDn = ExtendDn(SetDn, Argv[i]);
|
||
Cxtion = FrsWcsCat(L"From_", Argv[i]);
|
||
CxtionDn = ExtendDn(ServerDn, Cxtion);
|
||
FREE(Cxtion);
|
||
|
||
//
|
||
// Inbounds
|
||
//
|
||
AddMod(ATTR_CLASS, ATTR_CXTION, &Mod);
|
||
AddMod(ATTR_FROM_SERVER, PartnerDn, &Mod);
|
||
AddMod(ATTR_ENABLED_CXTION, ATTR_TRUE, &Mod);
|
||
AddMod(ATTR_OPTIONS, ATTR_OPTIONS_0, &Mod);
|
||
ConditionalBuildSchedule(&Schedule, &ScheduleLength);
|
||
if (Schedule) {
|
||
AddBerMod(ATTR_SCHEDULE, (PCHAR)Schedule, ScheduleLength, &Mod);
|
||
FREE(Schedule);
|
||
}
|
||
LStatus = ldap_add_s(Ldap, CxtionDn, Mod);
|
||
|
||
dupx = 0;
|
||
while ((LStatus == LDAP_ALREADY_EXISTS) && (DupNames[dupx] != NULL)) {
|
||
//
|
||
// Try to create a duplicate connection object by putting a suffix on the name.
|
||
//
|
||
Cxtion = FrsWcsCat(L"From_", Argv[i]);
|
||
CxtionDnDup = FrsWcsCat(Cxtion, DupNames[dupx]);
|
||
CxtionDn = ExtendDn(ServerDn, CxtionDnDup);
|
||
FREE(Cxtion);
|
||
FREE(CxtionDnDup);
|
||
|
||
LStatus = ldap_add_s(Ldap, CxtionDn, Mod);
|
||
if (LStatus != LDAP_ALREADY_EXISTS) {
|
||
//
|
||
// Dup cxtion created.
|
||
//
|
||
break;
|
||
}
|
||
dupx++;
|
||
}
|
||
if (LStatus != LDAP_ALREADY_EXISTS && LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't create %ws: %ws\n",
|
||
CxtionDn, ldap_err2string(LStatus));
|
||
}
|
||
FreeMod(&Mod);
|
||
FREE(PartnerDn);
|
||
FREE(CxtionDn);
|
||
}
|
||
FREE(ServerDn);
|
||
FREE(SetDn);
|
||
FREE(SettingsDn);
|
||
FREE(ServicesDn);
|
||
FREE(ConfigDn);
|
||
if (Ldap) {
|
||
ldap_unbind(Ldap);
|
||
}
|
||
}
|
||
|
||
|
||
BOOL
|
||
DeleteUserSubTree(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR Dn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
PWCHAR DesiredAttrs[16];
|
||
PWCHAR Bl = NULL;
|
||
PWCHAR Co = NULL;
|
||
PWCHAR SubsDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
DesiredAttrs[0] = ATTR_MEMBER_REF_BL;
|
||
DesiredAttrs[1] = ATTR_COMPUTER_REF;
|
||
DesiredAttrs[2] = ATTR_CLASS;
|
||
DesiredAttrs[3] = NULL;
|
||
LStatus = ldap_search_s(Ldap, Dn, LDAP_SCOPE_BASE, CATEGORY_ANY,
|
||
DesiredAttrs, 0, &LdapMsg);
|
||
if (LStatus == LDAP_SUCCESS) {
|
||
LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
|
||
Co = FindValue(Ldap, LdapEntry, ATTR_COMPUTER_REF);
|
||
Bl = FindValue(Ldap, LdapEntry, ATTR_MEMBER_REF_BL);
|
||
if (Bl && Dn) {
|
||
LStatus = ldap_delete_s(Ldap, Bl);
|
||
if (LStatus != LDAP_SUCCESS && LStatus != LDAP_NO_SUCH_OBJECT) {
|
||
fprintf(stderr, "ERROR - Can't delete BL: %ws\n",
|
||
ldap_err2string(LStatus));
|
||
fprintf(stderr, " %ws\n", Dn);
|
||
fprintf(stderr, " BL %ws\n", Bl);
|
||
FREE(Bl);
|
||
FREE(Dn);
|
||
FREE(Co);
|
||
return FALSE;
|
||
}
|
||
}
|
||
if (Co) {
|
||
SubsDn = ExtendDn(Co, CN_SUBSCRIPTIONS);
|
||
LStatus = ldap_delete_s(Ldap, SubsDn);
|
||
if (LStatus != LDAP_NO_SUCH_OBJECT &&
|
||
LStatus != LDAP_SUCCESS &&
|
||
LStatus != LDAP_NOT_ALLOWED_ON_NONLEAF) {
|
||
fprintf(stderr, "ERROR - Can't delete: %ws\n", ldap_err2string(LStatus));
|
||
fprintf(stderr, " %ws\n", SubsDn);
|
||
FREE(SubsDn);
|
||
FREE(Bl);
|
||
FREE(Dn);
|
||
FREE(Co);
|
||
return FALSE;
|
||
}
|
||
FREE(SubsDn);
|
||
}
|
||
FREE(Bl);
|
||
FREE(Dn);
|
||
FREE(Co);
|
||
ldap_msgfree(LdapMsg);
|
||
} else if (LStatus != LDAP_NO_SUCH_OBJECT) {
|
||
fprintf(stderr, "ERROR - Can't find: %ws\n", ldap_err2string(LStatus));
|
||
fprintf(stderr, " %ws\n", Dn);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
FrsDsDeleteSubTree(
|
||
IN PLDAP Ldap,
|
||
IN PWCHAR ParentDn
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus;
|
||
PWCHAR DesiredAttrs[16];
|
||
PWCHAR NextDn = NULL;
|
||
PLDAPMessage LdapMsg = NULL;
|
||
PLDAPMessage LdapEntry = NULL;
|
||
|
||
DesiredAttrs[0] = ATTR_DN;
|
||
DesiredAttrs[1] = NULL;
|
||
LStatus = ldap_search_s(Ldap, ParentDn, LDAP_SCOPE_ONELEVEL, CATEGORY_ANY,
|
||
DesiredAttrs, 0, &LdapMsg);
|
||
if (LStatus == LDAP_SUCCESS) {
|
||
//
|
||
// Scan the entries returned from ldap_search
|
||
//
|
||
for (LdapEntry = ldap_first_entry(Ldap, LdapMsg);
|
||
LdapEntry != NULL;
|
||
LdapEntry = ldap_next_entry(Ldap, LdapEntry)) {
|
||
NextDn = FindValue(Ldap, LdapEntry, ATTR_DN);
|
||
if (NextDn) {
|
||
FrsDsDeleteSubTree(Ldap, NextDn);
|
||
FREE(NextDn);
|
||
}
|
||
}
|
||
ldap_msgfree(LdapMsg);
|
||
if (DeleteUserSubTree(Ldap, ParentDn)) {
|
||
LStatus = ldap_delete_s(Ldap, ParentDn);
|
||
if (LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "ERROR - Can't delete: %ws\n", ldap_err2string(LStatus));
|
||
fprintf(stderr, " %ws\n", ParentDn);
|
||
}
|
||
}
|
||
} else if (LStatus != LDAP_NO_SUCH_OBJECT) {
|
||
fprintf(stderr, "ERROR - Can't find: %ws\n", ldap_err2string(LStatus));
|
||
fprintf(stderr, " %ws\n", ParentDn);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
DeleteReplicationWorld(
|
||
IN DWORD argc,
|
||
IN PWCHAR *Argv,
|
||
IN PWCHAR Settings
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Create the required objects
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PWCHAR Dn;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PWCHAR SetDn = NULL;
|
||
PWCHAR ServerDn = NULL;
|
||
PWCHAR Cxtion = NULL;
|
||
PWCHAR CxtionDn = NULL;
|
||
PLDAP Ldap = NULL;
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Services
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
SettingsDn = ExtendDn(ServicesDn, Settings);
|
||
Dn = SettingsDn;
|
||
if (argc > 2) {
|
||
SetDn = ExtendDn(SettingsDn, Argv[2]);
|
||
Dn = SetDn;
|
||
}
|
||
if (argc > 3) {
|
||
ServerDn = ExtendDn(SetDn, Argv[3]);
|
||
Dn = ServerDn;
|
||
}
|
||
if (argc > 4) {
|
||
Cxtion = FrsWcsCat(L"From_", Argv[4]);
|
||
CxtionDn = ExtendDn(ServerDn, Cxtion);
|
||
Dn = CxtionDn;
|
||
}
|
||
|
||
FrsDsDeleteSubTree(Ldap, Dn);
|
||
|
||
// out:
|
||
ldap_unbind(Ldap);
|
||
FREE(CxtionDn);
|
||
FREE(Cxtion);
|
||
FREE(ServerDn);
|
||
FREE(SetDn);
|
||
FREE(SettingsDn);
|
||
FREE(ServicesDn);
|
||
FREE(ConfigDn);
|
||
}
|
||
|
||
|
||
VOID
|
||
ModifyFilter(
|
||
IN DWORD argc,
|
||
IN PWCHAR *Argv
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Change the file and directory filter for the replica set specified.
|
||
|
||
Arguments:
|
||
argc - From main
|
||
argv - From main
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
DWORD LStatus = LDAP_SUCCESS;
|
||
PWCHAR Set;
|
||
PWCHAR NewFilter;
|
||
PWCHAR ConfigDn = NULL;
|
||
PWCHAR ServicesDn = NULL;
|
||
PWCHAR SettingsDn = NULL;
|
||
PWCHAR SetDn = NULL;
|
||
PLDAP Ldap = NULL;
|
||
LDAPMod **Mod = NULL;
|
||
|
||
Set = Argv[3];
|
||
if(argc > 4){
|
||
NewFilter = Argv[4];
|
||
}
|
||
else{
|
||
NewFilter = L" ";
|
||
}
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// ADMIN SIDE
|
||
//
|
||
//
|
||
// Services Dn
|
||
//
|
||
ConfigDn = GetRootDn(Ldap, CONFIG_NAMING_CONTEXT);
|
||
if (!ConfigDn) {
|
||
return;
|
||
}
|
||
ServicesDn = ExtendDn(ConfigDn, CN_SERVICES);
|
||
SettingsDn = ExtendDn(ServicesDn, CN_TEST_SETTINGS);
|
||
SetDn = ExtendDn(SettingsDn, Set);
|
||
|
||
if(!wcscmp(Argv[2],L"/clear")){
|
||
if(!wcscmp(Argv[1],L"/dirfilter")){
|
||
AddMod(ATTR_DIRECTORY_FILTER, L" ", &Mod);
|
||
(*Mod)->mod_op = LDAP_MOD_REPLACE;
|
||
}
|
||
else {
|
||
AddMod(ATTR_FILE_FILTER, L" ", &Mod);
|
||
(*Mod)->mod_op = LDAP_MOD_REPLACE;
|
||
}
|
||
LStatus = ldap_modify_s(Ldap, SetDn, Mod);
|
||
}
|
||
else if(!wcscmp(Argv[2],L"/set")){
|
||
if(!wcscmp(Argv[1],L"/dirfilter")){
|
||
AddMod(ATTR_DIRECTORY_FILTER, NewFilter, &Mod);
|
||
(*Mod)->mod_op = LDAP_MOD_REPLACE;
|
||
}
|
||
else {
|
||
AddMod(ATTR_FILE_FILTER, NewFilter, &Mod);
|
||
(*Mod)->mod_op = LDAP_MOD_REPLACE;
|
||
}
|
||
LStatus = ldap_modify_s(Ldap, SetDn, Mod);
|
||
}
|
||
else {
|
||
// Usage(Argv);
|
||
}
|
||
|
||
if (LStatus != LDAP_SUCCESS) {
|
||
fprintf(stderr, "Can't change filter; %ws\n",
|
||
ldap_err2string(LStatus));
|
||
}
|
||
FreeMod(&Mod);
|
||
ldap_unbind(Ldap);
|
||
FREE(SetDn);
|
||
FREE(SettingsDn);
|
||
FREE(ServicesDn);
|
||
FREE(ConfigDn);
|
||
}
|
||
|
||
|
||
PWCHAR *
|
||
ConvertArgv(
|
||
DWORD argc,
|
||
PCHAR *argv
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Convert short char argv into wide char argv
|
||
|
||
Arguments:
|
||
argc - From main
|
||
argv - From main
|
||
|
||
Return Value:
|
||
Address of the new argv
|
||
--*/
|
||
{
|
||
PWCHAR *wideargv;
|
||
|
||
wideargv = (PWCHAR *)malloc((argc + 1) * sizeof(PWCHAR));
|
||
wideargv[argc] = NULL;
|
||
|
||
while (argc-- >= 1) {
|
||
wideargv[argc] = (PWCHAR)malloc((strlen(argv[argc]) + 1) * sizeof(WCHAR));
|
||
wsprintf(wideargv[argc], L"%hs", argv[argc]);
|
||
// _wcslwr(wideargv[argc]);
|
||
}
|
||
return wideargv;
|
||
}
|
||
|
||
|
||
VOID
|
||
Usage(
|
||
IN PWCHAR *Argv
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Usage messages.
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
printf("%-24s%ws\n", "Pretty Print", Argv[0]);
|
||
printf("%-24s%ws /dumpcontexts\n", "dumpcontexts", Argv[0]);
|
||
printf("%-24s%ws /dumpcomputers\n", "dumpcomputers", Argv[0]);
|
||
printf("%-24s%ws /dumpservers\n", "dumpservers", Argv[0]);
|
||
printf("%-24s%ws /dumpsets\n", "dumpsets", Argv[0]);
|
||
printf("%-24s%ws /?\n", "Help", Argv[0]);
|
||
printf("%-24s%ws /h\n", "Hammer the schema", Argv[0]);
|
||
printf("%-24s%ws /r\n", "Restore the schema", Argv[0]);
|
||
printf("%-24s%ws /l\n", "List the schema", Argv[0]);
|
||
printf("%-24s%ws /s\n", "Produce script", Argv[0]);
|
||
printf("%-24s%ws /d [Set [Server [Partner]]]\n", "Delete", Argv[0]);
|
||
printf("%-24s%ws /c Set [Server [Root Stage]]\n", "Create sets and servers", Argv[0]);
|
||
printf("%-24s%ws /i Set Server Partner ...\n", "Create inbound cxtions", Argv[0]);
|
||
printf("%-24s%ws [/filefilter |/dirfilter] [/set |/clear] Set FilterString\n", "Modify filters", Argv[0]);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
}
|
||
|
||
|
||
#define DUMP_ALL (0)
|
||
#define DUMP_CONTEXTS (1)
|
||
#define DUMP_SETS (2)
|
||
#define DUMP_COMPUTERS (3)
|
||
#define DUMP_SERVERS (4)
|
||
VOID
|
||
DumpWorld(
|
||
DWORD Dump
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Dump every ds object related to replication
|
||
|
||
Arguments:
|
||
Dump - what to dump.
|
||
|
||
Return Value:
|
||
None.
|
||
--*/
|
||
{
|
||
PLDAP Ldap;
|
||
|
||
//
|
||
// Bind to the ds
|
||
//
|
||
Ldap = FrsDsOpenDs();
|
||
if (!Ldap) {
|
||
return;
|
||
}
|
||
|
||
if (Dump == DUMP_ALL || Dump == DUMP_CONTEXTS) {
|
||
printf("***** CONTEXTS\n");
|
||
DumpContexts(Ldap);
|
||
}
|
||
|
||
if (Dump == DUMP_ALL || Dump == DUMP_SETS) {
|
||
printf("***** REPLICA SETS\n");
|
||
DumpAdminWorld(Ldap);
|
||
}
|
||
|
||
if (Dump == DUMP_ALL || Dump == DUMP_COMPUTERS) {
|
||
printf("\n***** COMPUTERS\n");
|
||
DumpUserWorld(Ldap);
|
||
}
|
||
|
||
if (Dump == DUMP_ALL || Dump == DUMP_SERVERS) {
|
||
printf("\n***** SERVERS\n");
|
||
DumpSysVolWorld(Ldap);
|
||
}
|
||
|
||
ldap_unbind(Ldap);
|
||
}
|
||
|
||
|
||
VOID _cdecl
|
||
main(
|
||
IN DWORD argc,
|
||
IN PCHAR *argv
|
||
)
|
||
/*++
|
||
Routine Description:
|
||
Get access to the DS via ldap. Then read command lines from standard
|
||
in, parse them, and ship them off to the command subroutines. The
|
||
command line is:
|
||
command,site,settings,server,connection,fromserver
|
||
command is any of add|delete|list|show|quit. Leading whitespace is
|
||
ignored. Whitespace between commas counts. The command line can
|
||
stop anytime after "command" and the command will on be applied
|
||
to that portion of the "Distinquished Name".
|
||
|
||
Arguments:
|
||
None.
|
||
|
||
Return Value:
|
||
Exits with 0 if everything went okay. Otherwise, 1.
|
||
--*/
|
||
{
|
||
PWCHAR *Argv;
|
||
ULONG i;
|
||
ULONG OptLen;
|
||
|
||
Argv = ConvertArgv(argc, argv);
|
||
|
||
if (argc == 1) {
|
||
DumpWorld(DUMP_ALL);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
}
|
||
|
||
for (i = 1; i < argc; ++i) {
|
||
OptLen = wcslen(Argv[i]);
|
||
if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/?") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-?") == Argv[i]))) {
|
||
Usage(Argv);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/s") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-s") == Argv[i]))) {
|
||
ScriptReplicationWorld();
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/d") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-d") == Argv[i]))) {
|
||
if (argc < 2 || argc > 5) {
|
||
Usage(Argv);
|
||
}
|
||
DeleteReplicationWorld(argc, Argv, CN_TEST_SETTINGS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 9 &&
|
||
((wcsstr(Argv[i], L"/dsysvols") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dsysvols") == Argv[i]))) {
|
||
if (argc < 2 || argc > 5) {
|
||
Usage(Argv);
|
||
}
|
||
DeleteReplicationWorld(argc, Argv, CN_SYSVOLS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/h") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-h") == Argv[i]))) {
|
||
HammerSchema(TRUE);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/r") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-r") == Argv[i]))) {
|
||
HammerSchema(FALSE);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/l") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-l") == Argv[i]))) {
|
||
ListSchema();
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/i") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-i") == Argv[i]))) {
|
||
if (argc < 5) {
|
||
Usage(Argv);
|
||
}
|
||
CreateInbounds(argc, Argv);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 2 &&
|
||
((wcsstr(Argv[i], L"/c") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-c") == Argv[i]))) {
|
||
if (argc != 2 && argc != 3 && argc != 6) {
|
||
Usage(Argv);
|
||
}
|
||
CreateReplicationWorld(argc, Argv, FALSE);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen == 3 &&
|
||
((wcsstr(Argv[i], L"/cp") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-cp") == Argv[i]))) {
|
||
if (argc != 2 && argc != 3 && argc != 6) {
|
||
Usage(Argv);
|
||
}
|
||
CreateReplicationWorld(argc, Argv, TRUE);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if (OptLen >= 10 &&
|
||
((wcsstr(Argv[i], L"/filefilter") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-filefilter") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"/dirfilter") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dirfilter") == Argv[i]))) {
|
||
if (argc != 4 && argc != 5) {
|
||
Usage(Argv);
|
||
}
|
||
ModifyFilter(argc, Argv);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if ((wcsstr(Argv[i], L"/dumpcontexts") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dumpcontexts") == Argv[i])) {
|
||
DumpWorld(DUMP_CONTEXTS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if ((wcsstr(Argv[i], L"/dumpsets") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dumpsets") == Argv[i])) {
|
||
DumpWorld(DUMP_SETS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if ((wcsstr(Argv[i], L"/dumpcomputers") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dumpcomputers") == Argv[i])) {
|
||
DumpWorld(DUMP_COMPUTERS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if ((wcsstr(Argv[i], L"/dumpservers") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-dumpservers") == Argv[i])) {
|
||
DumpWorld(DUMP_SERVERS);
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
} else if ((wcsstr(Argv[i], L"/") == Argv[i]) ||
|
||
(wcsstr(Argv[i], L"-") == Argv[i])) {
|
||
fprintf(stderr, "ERROR - Don't understand %ws\n", Argv[i]);
|
||
Usage(Argv);
|
||
} else {
|
||
Usage(Argv);
|
||
}
|
||
}
|
||
fflush(stdout);
|
||
ExitProcess(0);
|
||
}
|