Hi
I'm trying to use the Replicaytion Management Functions in order to force a domain controller synchronization.
In my scenario I have more than one DC on which my application can create some users and groups and it need to wait for DC replication before it can proceed to use them in order to perform other operations (eg. set ACL). My solution is developed with .net framework 1.1 and Windows 2003 technologies.
In the my c# class library used to implement the DC synchronization I have two classes; the "ReplicationManagement" in which I have declared all the win32 function, structs and enumerations used and the "Domain" class with the "Synchronize" method.
In this method I use the "DsBind" and "DsGetDomainControllerInfo" to retrieve the list of domain controller and for each one is called the "DsReplicaSyncAll" function. This call returns the ERROR_INVALID_PARAMETER error (error code 87).
I suppose this error is returned because I make a mistake declaring the "DsReplicaSyncAll" (defined in the "ReplicationManagement" class).
Following the code I have wrote
ReplicationManagement.c
-----------------------------
[DllImport("ntdsapi.dll", SetLastError=true)
public static extern uint DsBind
string DomainControllerName
string DnsDomainName
out IntPtr phD
)
[DllImport("ntdsapi.dll", SetLastError=true)
public static extern uint DsGetDomainControllerInfo
IntPtr hDs
string DomainName
uint InfoLevel
out uint InfoCount
out IntPtr pInf
)
[DllImport("ntdsapi.dll", SetLastError=true)
public static extern uint DsReplicaSyncAll
IntPtr hDS
string szNameContext
ulong uFlags
FnCallBack pFnCallBack, //BOOL (__stdcall * pFnCallBack) (LPVOID, PDS_REPSYNCALL_UPDATEW)
out IntPtr pCallbackData
out IntPtr pError
)
Looking at the "DsReplicaSyncAll" I've wrote a delegate to implement a function pointer for the callback function. In the first version of the code I've tried to define the function with a IntPtr parameter and passing it the IntPtr.Zero value in the function call. Following the delegate declaration
public delegate bool FnCallBack(IntPtr pData, PDS_REPSYNCALL_UPDATE pUpdate)
where the REPSYNCALL_UPDATE is defined by the following struct
[StructLayout(LayoutKind.Sequential, Pack=1)
public struct PDS_REPSYNCALL_UPDAT
public DS_REPSYNCALL_EVENT Event
public IntPtr pErrInfo
public IntPtr pSync
public enum DS_REPSYNCALL_EVENT : uin
DS_REPSYNCALL_EVENT_ERROR = 0
DS_REPSYNCALL_EVENT_SYNC_STARTED = 1
DS_REPSYNCALL_EVENT_SYNC_COMPLETED = 2
DS_REPSYNCALL_EVENT_FINISHED =
In the "Domain.cs" I use the ReplicationManagement.DsReplicaSyncAll as the following
IntPtr phDsDc = IntPtr.Zero
uint uResult = ReplicationManagement.DsBind("dc01", null, out phDsDc
if (uResult <> 0) {...
..
uResult = ReplicationManagement.DsReplicaSyncAll
phDsDc,
"DC=mydomain,DC=net",
ReplicationManagement.DS_REPSYNCALL_ID_SERVERS_BY_DN
new ReplicationManagement.FnCallBack( this.Callback )
out pCallbackData
out pError
)
..
where the Callback is the following function
private bool Callback(IntPtr pData, ReplicationManagement.PDS_REPSYNCALL_UPDATE pUpdate
..
I need to understand if I use correctly the DsReplicaSyncAll in my c# code and how I can solve the problem.
Any help most appreciated
Mattias Sj?gren - 26 May 2004 15:34 GMT
>[DllImport("ntdsapi.dll", SetLastError=true)]
>public static extern uint DsReplicaSyncAll(
[quoted text clipped - 5 lines]
> out IntPtr pErrors
> );
uFlags should be an uint.
>public delegate bool FnCallBack(IntPtr pData, PDS_REPSYNCALL_UPDATE pUpdate);
pUpdate should be a ref parameter (the 'P' means it's a pointer to a
DS_REPSYNCALL_UPDATE struct).
Mattias

Signature
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
virusluca - 27 May 2004 10:46 GMT
Thanks for your help Mattias
I have tried to declare the uFlags parameter as uint and I have added the ref keyword in the delegate declaration but it does not solve the problem
I have also tried to use an IntPtr instead of the PDS_REPSYNCALL_UPDATE struct but nothing
Following the new declaration of the DsReplicaSyncAll and FnCallBack callback
[DllImport("ntdsapi.dll", SetLastError=true)
public static extern uint DsReplicaSyncAll
IntPtr hDS
string szNameContext
uint uFlags
FnCallBack pFnCallBack
//BOOL (__stdcall * pFnCallBack) (LPVOID, PDS_REPSYNCALL_UPDATEW)
IntPtr pCallbackData
out IntPtr pError
)
public delegate bool FnCallBack(IntPtr pData, ref PDS_REPSYNCALL_UPDATE pUpdate)
I have removed the out keyword from the pCallbackData because it is defined as an [in, optional] parameter. The value of the pCallbackData and the pErrors is IntPtr.Zero
I hope you can give me some other considerations
Thanks
LucaE
----- Mattias Sjögren wrote: ----
>[DllImport("ntdsapi.dll", SetLastError=true)
>public static extern uint DsReplicaSyncAll
> IntPtr hDS
> string szNameContext
> ulong uFlags
> FnCallBack pFnCallBack, //BOOL (__stdcall * pFnCallBack) (LPVOID, PDS_REPSYNCALL_UPDATEW)
> out IntPtr pCallbackData
> out IntPtr pError
> )
uFlags should be an uint
>public delegate bool FnCallBack(IntPtr pData, PDS_REPSYNCALL_UPDATE pUpdate)
pUpdate should be a ref parameter (the 'P' means it's a pointer to
DS_REPSYNCALL_UPDATE struct)
Mattia
--
Mattias Sjögren [MVP] mattias @ mvps.or
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.co
Please reply only to the newsgroup