summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/repl/common
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/repl/common')
-rw-r--r--private/net/svcdlls/repl/common/abspath.c86
-rw-r--r--private/net/svcdlls/repl/common/allowrol.c130
-rw-r--r--private/net/svcdlls/repl/common/chnglock.c131
-rw-r--r--private/net/svcdlls/repl/common/chngnot.c424
-rw-r--r--private/net/svcdlls/repl/common/chngnot.h85
-rw-r--r--private/net/svcdlls/repl/common/data.c45
-rw-r--r--private/net/svcdlls/repl/common/delfile.c262
-rw-r--r--private/net/svcdlls/repl/common/dirname.c112
-rw-r--r--private/net/svcdlls/repl/common/dirname.h64
-rw-r--r--private/net/svcdlls/repl/common/easize.c236
-rw-r--r--private/net/svcdlls/repl/common/expalloc.c120
-rw-r--r--private/net/svcdlls/repl/common/expbuild.c160
-rw-r--r--private/net/svcdlls/repl/common/expconf.c694
-rw-r--r--private/net/svcdlls/repl/common/expdir.h265
-rw-r--r--private/net/svcdlls/repl/common/expenum.c298
-rw-r--r--private/net/svcdlls/repl/common/expget.c110
-rw-r--r--private/net/svcdlls/repl/common/explock.c162
-rw-r--r--private/net/svcdlls/repl/common/expset.c195
-rw-r--r--private/net/svcdlls/repl/common/expvalid.c177
-rw-r--r--private/net/svcdlls/repl/common/fixlocks.c194
-rw-r--r--private/net/svcdlls/repl/common/fsresolu.c220
-rw-r--r--private/net/svcdlls/repl/common/ignorenm.c100
-rw-r--r--private/net/svcdlls/repl/common/impalloc.c118
-rw-r--r--private/net/svcdlls/repl/common/impbuild.c203
-rw-r--r--private/net/svcdlls/repl/common/impconf.c720
-rw-r--r--private/net/svcdlls/repl/common/impdir.h259
-rw-r--r--private/net/svcdlls/repl/common/impenum.c321
-rw-r--r--private/net/svcdlls/repl/common/impget.c149
-rw-r--r--private/net/svcdlls/repl/common/implock.c172
-rw-r--r--private/net/svcdlls/repl/common/imports.h58
-rw-r--r--private/net/svcdlls/repl/common/impstate.c124
-rw-r--r--private/net/svcdlls/repl/common/impvalid.c118
-rw-r--r--private/net/svcdlls/repl/common/iniparm.h87
-rw-r--r--private/net/svcdlls/repl/common/lstvalid.c162
-rw-r--r--private/net/svcdlls/repl/common/makefile6
-rw-r--r--private/net/svcdlls/repl/common/replbld.c190
-rw-r--r--private/net/svcdlls/repl/common/replconf.c666
-rw-r--r--private/net/svcdlls/repl/common/replconf.h167
-rw-r--r--private/net/svcdlls/repl/common/repldefs.h831
-rw-r--r--private/net/svcdlls/repl/common/replerr.c298
-rw-r--r--private/net/svcdlls/repl/common/replgbl.h139
-rw-r--r--private/net/svcdlls/repl/common/replname.h35
-rw-r--r--private/net/svcdlls/repl/common/replp.c271
-rw-r--r--private/net/svcdlls/repl/common/replp.h70
-rw-r--r--private/net/svcdlls/repl/common/repvalid.c198
-rw-r--r--private/net/svcdlls/repl/common/sources133
-rw-r--r--private/net/svcdlls/repl/common/userlock.c158
47 files changed, 9923 insertions, 0 deletions
diff --git a/private/net/svcdlls/repl/common/abspath.c b/private/net/svcdlls/repl/common/abspath.c
new file mode 100644
index 000000000..6f73022d0
--- /dev/null
+++ b/private/net/svcdlls/repl/common/abspath.c
@@ -0,0 +1,86 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ AbsPath.c
+
+Abstract:
+
+ This file contains ReplCheckAbsPathSyntax().
+
+Author:
+
+ John Rogers (JohnRo) 27-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 27-Jan-1992 JohnRo
+ Created as part of replconf stuff..
+ 21-Feb-1992 JohnRo
+ Extracted this code for slightly more general use.
+ 19-Mar-1992 JohnRo
+ Richard Firth fixed a canon bug, which I was unintentionally
+ depending on here.
+ 20-Mar-1992 JohnRo
+ Include header file with my prototype, just to be on the safe side.
+ 17-Aug-1992 JohnRo
+ RAID 3174: NetReplSetInfo (and repl registry) allow bad paths.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // MAX_PATH, etc.
+#include <lmcons.h> // LAN Manager common definitions
+
+// These can be in any order:
+
+#include <icanon.h> // I_NetPathCanonicalize(), ITYPE_ equates.
+#include <repldefs.h> // My prototype.
+#include <winerror.h> // ERROR_, NO_ERROR equates.
+
+
+
+
+NET_API_STATUS
+ReplCheckAbsPathSyntax (
+ IN LPTSTR AbsPath
+ )
+{
+ DWORD ActualType = 0; // 0 means we don't know yet.
+ NET_API_STATUS ApiStatus;
+ TCHAR CanonBuf[MAX_PATH];
+
+ ApiStatus = I_NetPathCanonicalize(
+ NULL,
+ AbsPath,
+ CanonBuf,
+ sizeof(CanonBuf),
+ NULL,
+ &ActualType,
+ 0);
+
+ //
+ // Check the type of the input.
+ //
+
+ if (ApiStatus != NO_ERROR) {
+ return (ApiStatus);
+ } else if (ActualType == ITYPE_PATH_ABSD) { // abs path with drive.
+ return (NO_ERROR);
+ } else {
+ return (ERROR_INVALID_DATA);
+ }
+
+ /*NOTREACHED*/
+
+} // ReplCheckAbsPathSyntax
diff --git a/private/net/svcdlls/repl/common/allowrol.c b/private/net/svcdlls/repl/common/allowrol.c
new file mode 100644
index 000000000..fa6bc12ae
--- /dev/null
+++ b/private/net/svcdlls/repl/common/allowrol.c
@@ -0,0 +1,130 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ AllowRol.c
+
+Abstract:
+
+ Just contains ReplConfigIsRoleAllowed().
+
+Author:
+
+ John Rogers (JohnRo) 07-Aug-1992
+
+Revision History:
+
+ 07-Aug-1992 JohnRo
+ Created for RAID 2252: repl should prevent export on Windows/NT.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 06-Apr-1993 JohnRo
+ RAID 1938: Replicator un-ACLs files when not given enough permission.
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <nt.h> // NT_PRODUCT_TYPE, etc.
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h> // BOOL, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), FORMAT_ equates.
+#include <netlibnt.h> // NetpGetProductType().
+#include <prefix.h> // PREFIX_ equates.
+#include <replconf.h> // My prototype.
+#include <repldefs.h> // ReplRoleIncludesExport(), ReplRoleIsValid(), etc.
+#include <winerror.h> // ERROR_ and NO_ERROR equates.
+
+
+//
+// Return this value if we aren't sure whether or not to allow the role.
+//
+#define DEFAULT_ROLE_ALLOWED TRUE
+
+
+BOOL
+ReplConfigIsRoleAllowed(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Role
+ )
+
+/*++
+
+Routine Description:
+
+ Indicates whether the given role is allowed based on the current product
+ type. Callable whether or not service is started.
+
+Arguments:
+
+ Role - the desired replicator role.
+
+Return Value:
+
+ TRUE iff Role is valid and Role is consistent with the current product type.
+
+--*/
+
+{
+ NET_API_STATUS ApiStatus;
+ NT_PRODUCT_TYPE ProductType;
+
+ if ( !ReplIsRoleValid( Role ) ) {
+ return (FALSE);
+ }
+
+ //
+ // Ask NT what type of system we're running on.
+ //
+ ApiStatus = NetpGetProductType(
+ UncServerName,
+ &ProductType );
+
+ if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL "ReplConfigIsRoleAllowed: unexpected failure "
+ "of NetpGetProductType(); assuming default.\n" ));
+
+ return (DEFAULT_ROLE_ALLOWED);
+ }
+
+ //
+ // Decide what to do based on the product type we got back.
+ //
+ if ((ProductType == NtProductLanManNt)
+ || (ProductType == NtProductServer) ) {
+
+ return (TRUE); // All roles are valid with NT AS.
+
+ } else if (ProductType == NtProductWinNt) {
+
+ if (ReplRoleIncludesExport( Role ) ) {
+ return (FALSE);
+ } else {
+ NetpAssert( Role == REPL_ROLE_IMPORT );
+ return (TRUE); // Import is allowed on all product types.
+ }
+
+ /*NOTREACHED*/
+
+ } else {
+ NetpKdPrint(( PREFIX_REPL "ReplConfigIsRoleAllowed: unexpected product "
+ "type " FORMAT_DWORD "\n", ProductType ));
+ NetpAssert( FALSE ); // Unexpected product type.
+
+ return (DEFAULT_ROLE_ALLOWED);
+ }
+
+ /*NOTREACHED*/
+
+}
diff --git a/private/net/svcdlls/repl/common/chnglock.c b/private/net/svcdlls/repl/common/chnglock.c
new file mode 100644
index 000000000..b559578b1
--- /dev/null
+++ b/private/net/svcdlls/repl/common/chnglock.c
@@ -0,0 +1,131 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ChngLock.c
+
+Abstract:
+
+ This file contains:
+
+ ReplIncrLockFields
+ ReplDecrLockFields
+
+Author:
+
+ John Rogers (JohnRo) 07-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 07-Jan-1992 JohnRo
+ Created.
+ 18-Feb-1992 JohnRo
+ Extracted these bits of code from server for use by DLL stubs too.
+ 22-Feb-1992 JohnRo
+ Made changes suggested by PC-LINT.
+ 26-Feb-1992 JohnRo
+ Check lock fields for validity.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These can be in any order:
+
+#include <lmrepl.h> // REPL_UNLOCK_ equates.
+#include <netdebug.h> // NetpAssert(), etc.
+#include <repldefs.h> // My prototypes, etc.
+#include <replp.h> // NetpReplTimeNow().
+#include <winerror.h> // ERROR_ and NO_ERROR equates.
+
+
+NET_API_STATUS
+ReplIncrLockFields (
+ IN OUT LPDWORD LockCountPtr,
+ IN OUT LPDWORD LockTimePtr
+ )
+
+{
+ NetpAssert( LockCountPtr != NULL );
+ NetpAssert( LockTimePtr != NULL );
+
+ NetpAssert( ReplAreLockFieldsValid( *LockCountPtr, *LockTimePtr ) );
+
+ if ( *LockCountPtr == 0) {
+
+ *LockCountPtr = 1;
+ *LockTimePtr = NetpReplTimeNow();
+
+ } else {
+
+ // Not first time.
+ ++ (*LockCountPtr);
+
+ NetpAssert( (*LockCountPtr) > 0 );
+ NetpAssert( (*LockTimePtr) > 0 );
+
+ }
+
+ NetpAssert( ReplAreLockFieldsValid( *LockCountPtr, *LockTimePtr ) );
+
+ return (NO_ERROR);
+
+} // ReplIncrLockFields
+
+
+NET_API_STATUS
+ReplDecrLockFields (
+ IN OUT LPDWORD LockCountPtr,
+ IN OUT LPDWORD LockTimePtr,
+ IN DWORD UnlockForce
+ )
+
+{
+ NET_API_STATUS ApiStatus;
+
+ NetpAssert( LockCountPtr != NULL );
+ NetpAssert( LockTimePtr != NULL );
+
+ NetpAssert( ReplAreLockFieldsValid( *LockCountPtr, *LockTimePtr ) );
+
+ if ( !ReplIsForceLevelValid( UnlockForce ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ if ((*LockCountPtr) == 0) { // not locked now.
+
+ ApiStatus = ERROR_INVALID_PARAMETER;
+
+ } else {
+
+ if (UnlockForce == REPL_UNLOCK_NOFORCE) {
+ --(*LockCountPtr);
+ } else {
+ (*LockCountPtr) = 0;
+ }
+
+ if ((*LockCountPtr) == 0) { // not locked any more.
+
+ *LockTimePtr = 0;
+
+ }
+
+ ApiStatus = NO_ERROR;
+ }
+
+ NetpAssert( ReplAreLockFieldsValid( *LockCountPtr, *LockTimePtr ) );
+
+ return (ApiStatus);
+
+} // ReplDecrLockFields
diff --git a/private/net/svcdlls/repl/common/chngnot.c b/private/net/svcdlls/repl/common/chngnot.c
new file mode 100644
index 000000000..31ddc8339
--- /dev/null
+++ b/private/net/svcdlls/repl/common/chngnot.c
@@ -0,0 +1,424 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ ChngNot.c
+
+Abstract:
+
+ This is a package of change notify routines:
+
+ ReplSetupChangeNotify
+ ReplEnableChangeNotify
+ ReplGetChangeNotifyStatus
+ ReplExtractChangeNotifyFirstDir
+ ReplCloseChangeNotify
+
+Author:
+
+ John Rogers (JohnRo) 28-Nov-1992
+
+Environment:
+
+ NT only.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 28-Nov-1992 JohnRo
+ Repl should use filesystem change notify. (Created these routines
+ from MadanA's test code in ReplTest/Watch.c)
+ 08-Dec-1992 JohnRo
+ Made changes suggested by PC-LINT 5.0
+ 14-Jan-1993 JohnRo
+ RAID 7053: locked trees added to pulse msg. (Actually fix all
+ kinds of remote lock handling.)
+ 26-Feb-1993 JohnRo
+ RAID 13126: Fix repl memory leak.
+ Made changes suggested by PC-LINT 5.0
+ Corrected copyright dates.
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+
+// These must be included first:
+
+#include <nt.h> // NT definitions
+#include <ntrtl.h> // NT runtime library definitions (needed by nturtl.h)
+#include <nturtl.h> // RtlDosPathNameToNtPathName_U().
+#include <windef.h> // LPVOID, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+#include <chngnot.h> // My prototypes, REPL_CHANGE_NOTIFY_HANDLE, etc.
+#include <netdebug.h> // DBGSTATIC, NetpKdPrint(), FORMAT_ equates, etc.
+#include <netlib.h> // NetpMemoryAllocate(), etc.
+#include <netlibnt.h> // NetpNtStatusToApiStatus().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG().
+#include <tstr.h> // TCHAR_EOS.
+#include <winerror.h> // NO_ERROR, ERROR_ equates.
+
+
+// Arbitrary amount for buffer which will be filled-in.
+// BUGBUG: We don't even use this buffer yet!
+#define BUFFER_SIZE (1024 * 10)
+
+
+//
+// Define which kinds of changes we want to actually get notified about.
+// We don't use access time in checksum, so skip FILE_NOTIFY_CHANGE_LAST_ACCESS.
+// Ditto for the creation time (FILE_NOTIFY_CHANGE_CREATION).
+// BUGBUG: we copy security info but don't checksum it yet!
+//
+
+#define MY_CHANGE_NOTIFY_FILTER \
+ ( \
+ FILE_NOTIFY_CHANGE_FILE_NAME | \
+ FILE_NOTIFY_CHANGE_DIR_NAME | \
+ FILE_NOTIFY_CHANGE_ATTRIBUTES | \
+ FILE_NOTIFY_CHANGE_SIZE | \
+ FILE_NOTIFY_CHANGE_LAST_WRITE | \
+ FILE_NOTIFY_CHANGE_EA | \
+ FILE_NOTIFY_CHANGE_SECURITY \
+ )
+
+
+DBGSTATIC BOOL
+ReplIsChangeNotifyHandleValid(
+ IN LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ )
+{
+ if (ReplHandle == NULL) {
+ return (FALSE);
+ } else if ( (ReplHandle->WaitableHandle) == (LPVOID) NULL ) {
+ return (FALSE);
+ } else if ( (ReplHandle->Buffer) == NULL ) {
+ return (FALSE);
+ } else if ( (ReplHandle->BufferSize) == 0 ) {
+ return (FALSE);
+ }
+ // BUGBUG: Check ReplHandle->NextElementInBuffer too.
+ // BUGBUG: Check ReplHandle->BufferBytesValid too.
+ return (TRUE);
+}
+
+
+NET_API_STATUS
+ReplSetupChangeNotify(
+ IN LPTSTR AbsPath,
+ OUT LPREPL_CHANGE_NOTIFY_HANDLE *ReplHandle
+ )
+{
+ NET_API_STATUS ApiStatus;
+ UNICODE_STRING DirName;
+ NTSTATUS NtStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ BOOL PathAllocated = FALSE;
+ LPREPL_CHANGE_NOTIFY_HANDLE ReplStruct = NULL;
+
+
+ //
+ // Check for caller's errors.
+ //
+
+ NetpAssert( AbsPath != NULL );
+ NetpAssert( (*AbsPath) != TCHAR_EOS );
+ NetpAssert( ReplHandle != NULL );
+
+ //
+ // Allocate repl "handle" (structure).
+ //
+
+ ReplStruct = NetpMemoryAllocate( sizeof( REPL_CHANGE_NOTIFY_HANDLE ) );
+ if (ReplStruct == NULL) {
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ //
+ // Fill-in fields in repl struct, so we don't confuse cleanup code.
+ //
+
+ ReplStruct->Buffer = NULL;
+ ReplStruct->BufferSize = 0;
+ ReplStruct->WaitableHandle = NULL;
+
+ //
+ // Allocate change buffer.
+ //
+
+ ReplStruct->Buffer = NetpMemoryAllocate( BUFFER_SIZE );
+ if (ReplStruct->Buffer == NULL) {
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+ ReplStruct->BufferSize = BUFFER_SIZE;
+
+ //
+ // Arrange NT-style stuff so we can open the directory.
+ //
+
+ if (! RtlDosPathNameToNtPathName_U(
+ AbsPath,
+ &DirName,
+ NULL,
+ NULL
+ )) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ NetpKdPrint(( PREFIX_REPL "ReplSetupChangeNotify: "
+ "Could not convert DOS path to NT path; returning "
+ FORMAT_API_STATUS ".\n", ApiStatus ));
+ goto Cleanup;
+ }
+ PathAllocated = TRUE;
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DirName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ //
+ // Open the diretory.
+ //
+
+ NtStatus = NtOpenFile(
+ &(ReplStruct->WaitableHandle),
+ SYNCHRONIZE | FILE_LIST_DIRECTORY,
+ &ObjectAttributes,
+ &(ReplStruct->IoStatusBlock),
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_DIRECTORY_FILE
+ );
+
+ if (NT_SUCCESS(NtStatus)) {
+ NtStatus = ReplStruct->IoStatusBlock.Status;
+ }
+
+ if (! NT_SUCCESS(NtStatus)) {
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+ NetpKdPrint(( PREFIX_REPL "ReplSetupChangeNotify: "
+ "NtOpenFile " FORMAT_LPTSTR " failed: " FORMAT_NTSTATUS
+ "; returning " FORMAT_API_STATUS ".\n",
+ AbsPath, NtStatus, ApiStatus ));
+ ReplStruct->WaitableHandle = NULL; // BUGBUG: not necessary?
+ goto Cleanup;
+ }
+
+ IF_DEBUG( CHNGNOT ) {
+ NetpKdPrint(( PREFIX_REPL "ReplSetupChangeNotify: "
+ "Succeeded in opening dir.\n" ));
+ }
+
+ ApiStatus = NO_ERROR;
+
+Cleanup:
+ if (ApiStatus != NO_ERROR) {
+ if (ReplStruct->Buffer != NULL) {
+ NetpMemoryFree( ReplStruct->Buffer );
+ }
+ if (ReplStruct != NULL) {
+ NetpMemoryFree( ReplStruct );
+ }
+ *ReplHandle = NULL;
+ } else {
+ NetpAssert( ReplStruct != NULL );
+ *ReplHandle = ReplStruct;
+
+ NetpAssert( ReplIsChangeNotifyHandleValid( *ReplHandle ) );
+ }
+
+ IF_DEBUG( CHNGNOT ) {
+ NetpKdPrint(( PREFIX_REPL "ReplSetupChangeNotify: "
+ "returning " FORMAT_API_STATUS ".\n", ApiStatus ));
+ }
+
+ if (PathAllocated) {
+ (VOID) RtlFreeHeap( RtlProcessHeap(), 0, DirName.Buffer );
+ }
+
+
+ return (ApiStatus);
+
+} // ReplSetupChangeNotify
+
+
+NET_API_STATUS
+ReplEnableChangeNotify(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ )
+{
+ NET_API_STATUS ApiStatus;
+ NTSTATUS NtStatus;
+
+ //
+ // Now tell the system that we're going to watch for changes.
+ //
+
+ NtStatus = NtNotifyChangeDirectoryFile(
+ ReplHandle->WaitableHandle,
+ NULL, // No event, wait on handle
+ NULL, // No APC routine
+ NULL, // No APC context
+ &(ReplHandle->IoStatusBlock),
+ ReplHandle->Buffer,
+ BUFFER_SIZE,
+ MY_CHANGE_NOTIFY_FILTER,
+ (BOOLEAN) TRUE // Watch for change in the entire tree
+ );
+
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+
+ NetpKdPrint(( PREFIX_REPL "ReplEnableChangeNotify: "
+ "NtNotifyChangeDirectoryFile failed " FORMAT_NTSTATUS
+ "; returning " FORMAT_API_STATUS "\n",
+ NtStatus, ApiStatus ));
+ NetpAssert( ApiStatus != NO_ERROR )
+ goto Cleanup;
+ }
+
+ ApiStatus = NO_ERROR;
+
+Cleanup:
+ IF_DEBUG( CHNGNOT ) {
+ NetpKdPrint(( PREFIX_REPL "ReplEnableChangeNotify: "
+ "returning " FORMAT_API_STATUS ".\n", ApiStatus ));
+ }
+
+ return (ApiStatus);
+
+} // ReplEnableChangeNotify
+
+
+NET_API_STATUS
+ReplGetChangeNotifyStatus(
+ IN LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ )
+{
+ NET_API_STATUS ApiStatus;
+ NTSTATUS NtStatus;
+
+ NetpAssert( ReplIsChangeNotifyHandleValid( ReplHandle ) );
+
+ // BUGBUG: What status do we get if buffer overflowed?
+
+ NtStatus = ReplHandle->IoStatusBlock.Status;
+
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+
+ ReplHandle->BufferBytesValid = ReplHandle->IoStatusBlock.Information;
+ NetpAssert( ReplIsChangeNotifyHandleValid( ReplHandle ) );
+
+ IF_DEBUG( CHNGNOT ) {
+ NetpKdPrint(( PREFIX_REPL "ReplGetChangeNotifyStatus: "
+ "NT status is " FORMAT_NTSTATUS ", "
+ "num bytes valid is " FORMAT_DWORD ", "
+ "returning " FORMAT_API_STATUS ".\n",
+ NtStatus, ReplHandle->BufferBytesValid, ApiStatus ));
+ }
+
+ return (ApiStatus);
+
+} // ReplGetChangeNotifyStatus
+
+
+NET_API_STATUS
+ReplExtractChangeNotifyFirstDir(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle,
+ IN BOOL FirstTime,
+ OUT LPTSTR FirstLevelDirName
+ )
+{
+ LPVOID BufferValidEnd;
+ DWORD CharsLeft;
+ LPTSTR InCharPtr, OutCharPtr;
+ PFILE_NOTIFY_INFORMATION EntryPtr;
+
+ NetpAssert( ReplIsChangeNotifyHandleValid( ReplHandle ) );
+
+ if (FirstTime) {
+ ReplHandle->NextElementInBuffer = ReplHandle->Buffer;
+ }
+ EntryPtr = ReplHandle->NextElementInBuffer;
+
+ BufferValidEnd =
+ ((LPBYTE)(ReplHandle->Buffer))
+ + (ReplHandle->BufferBytesValid);
+ if ( BufferValidEnd >= ReplHandle->NextElementInBuffer ) {
+ return (ERROR_NO_MORE_ITEMS);
+ }
+
+ NetpAssert( EntryPtr->FileNameLength > 0 );
+ NetpAssert( (EntryPtr->FileNameLength % sizeof(WCHAR)) == 0 );
+
+ NetpAssert( sizeof(WCHAR) == sizeof(TCHAR) );
+ InCharPtr = (LPTSTR) (LPVOID) (EntryPtr->FileName);
+ OutCharPtr = FirstLevelDirName;
+ CharsLeft = (EntryPtr->FileNameLength) / sizeof(WCHAR);
+
+ /*lint -save -e716 */ // disable warnings for while(TRUE)
+ while (TRUE) {
+ if (CharsLeft == 0) {
+ break;
+ } else if ( IS_PATH_SEPARATOR( *InCharPtr ) ) {
+ break;
+ }
+
+ *OutCharPtr = *InCharPtr;
+
+ --CharsLeft;
+ ++InCharPtr;
+ ++OutCharPtr;
+ }
+ /*lint -restore */ // re-enable warnings for while(TRUE)
+
+ *OutCharPtr = TCHAR_EOS;
+
+ IF_DEBUG( CHNGNOT ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplExtractChangeNotifyFirstDir: first level dir is '"
+ FORMAT_LPTSTR "'\n", FirstLevelDirName ));
+ }
+
+ ReplHandle->NextElementInBuffer =
+ ((LPBYTE)EntryPtr)
+ + EntryPtr->NextEntryOffset;
+
+ NetpAssert( ReplIsChangeNotifyHandleValid( ReplHandle ) );
+
+ return (NO_ERROR);
+
+} // ReplExtractChangeNotifyFirstDir
+
+
+NET_API_STATUS
+ReplCloseChangeNotify(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ )
+{
+ NetpAssert( ReplIsChangeNotifyHandleValid( ReplHandle ) );
+
+ if (ReplHandle != NULL) {
+ if (ReplHandle->Buffer != NULL) {
+ NetpMemoryFree( ReplHandle->Buffer );
+ }
+ if ((ReplHandle->WaitableHandle) != NULL) {
+ (VOID) NtClose( ReplHandle->WaitableHandle );
+ }
+ NetpMemoryFree( ReplHandle );
+ }
+
+ return (NO_ERROR);
+
+} // ReplCloseChangeNotify
diff --git a/private/net/svcdlls/repl/common/chngnot.h b/private/net/svcdlls/repl/common/chngnot.h
new file mode 100644
index 000000000..5b585e404
--- /dev/null
+++ b/private/net/svcdlls/repl/common/chngnot.h
@@ -0,0 +1,85 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ChngNot.h
+
+Abstract:
+
+ This module defines some change notify datatypes and routines.
+
+Author:
+
+ John Rogers (JohnRo) 25-Nov-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 25-Nov-1992 JohnRo
+ Repl should use filesystem change notify.
+
+--*/
+
+
+#ifndef _CHNGNOT_
+#define _CHNGNOT_
+
+
+typedef struct _REPL_CHANGE_NOTIFY_HANDLE {
+
+ // Handle for use by callers.
+ HANDLE WaitableHandle;
+
+ // From here on are "implementation details"; callers should NOT use them.
+ LPVOID Buffer;
+ DWORD BufferSize;
+ DWORD BufferBytesValid;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LPVOID NextElementInBuffer; // Points in Buffer, or is NULL.
+
+} REPL_CHANGE_NOTIFY_HANDLE;
+
+typedef REPL_CHANGE_NOTIFY_HANDLE * PREPL_CHANGE_NOTIFY_HANDLE;
+typedef REPL_CHANGE_NOTIFY_HANDLE * LPREPL_CHANGE_NOTIFY_HANDLE;
+
+
+NET_API_STATUS
+ReplSetupChangeNotify(
+ IN LPTSTR AbsPath,
+ OUT LPREPL_CHANGE_NOTIFY_HANDLE *ReplHandle
+ );
+
+
+NET_API_STATUS
+ReplEnableChangeNotify(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ );
+
+
+NET_API_STATUS
+ReplGetChangeNotifyStatus(
+ IN LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ );
+
+
+NET_API_STATUS
+ReplExtractChangeNotifyFirstDir(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle,
+ IN BOOL FirstTime,
+ OUT LPTSTR FirstLevelDirName
+ );
+
+
+NET_API_STATUS
+ReplCloseChangeNotify(
+ IN OUT LPREPL_CHANGE_NOTIFY_HANDLE ReplHandle
+ );
+
+
+#endif // _CHNGNOT_
diff --git a/private/net/svcdlls/repl/common/data.c b/private/net/svcdlls/repl/common/data.c
new file mode 100644
index 000000000..c38b87824
--- /dev/null
+++ b/private/net/svcdlls/repl/common/data.c
@@ -0,0 +1,45 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Data.c
+
+Abstract:
+
+ Global data for repl debug routines. (Debug only, so no security problems.)
+
+Author:
+
+ John Rogers (JohnRo) 14-Mar-1992
+
+Environment:
+
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 14-Mar-1992 JohnRo
+ Created.
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // DWORD, etc.
+#include <lmcons.h> // Needed by repldefs.h/netlib.h.
+
+// These may be included in any order:
+
+#include <repldefs.h> // REPL_DEBUG_ALL.
+
+#if DBG
+
+//DWORD ReplGlobalTrace = 0;
+DWORD ReplGlobalTrace = 0; //REPL_DEBUG_ALL;
+
+#endif
+
+// That's all, folks!
diff --git a/private/net/svcdlls/repl/common/delfile.c b/private/net/svcdlls/repl/common/delfile.c
new file mode 100644
index 000000000..4d4600631
--- /dev/null
+++ b/private/net/svcdlls/repl/common/delfile.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ DelFile.c
+
+Abstract:
+
+ This file just contains ReplDeleteFile.
+
+ This is callable even if the replicator service is not started.
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft) 26-Apr-1993
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 26-Apr-1993 JohnRo
+ Created for RAID 7313: repl needs change permission to work on NTFS,
+ or we need to delete files differently.
+
+--*/
+
+
+// These must be included first:
+
+#include <nt.h> // NT_SUCCESS(), etc.
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h> // IN, GetLastError(), LPCTSTR, OPTIONAL, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netdebug.h> // NetpKdPrint(), FORMAT_ equates, etc.
+#include <netlibnt.h> // NetpNtStatusToApiStatus().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), my prototype, USE_ equates, etc.
+#include <tstr.h> // TCHAR_EOS.
+#include <winerror.h> // ERROR_ and NO_ERROR equates.
+
+
+// BUGBUG: undo this!
+#undef USE_BACKUP_APIS
+
+
+NET_API_STATUS
+ReplDeleteFile(
+ IN LPCTSTR FileName
+ )
+{
+ NET_API_STATUS ApiStatus;
+#ifdef USE_BACKUP_APIS
+ HANDLE FileHandle = INVALID_HANDLE_VALUE;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ const ACCESS_MASK MyAccessDesired =
+ ( DELETE
+ | FILE_READ_ATTRIBUTES
+ | FILE_READ_DATA
+ | FILE_READ_EA
+ | FILE_TRAVERSE
+ | SYNCHRONIZE
+ );
+
+ const ULONG MyOpenOptions =
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_DELETE_ON_CLOSE
+ | FILE_OPEN_FOR_BACKUP_INTENT
+ ;
+
+ const ULONG MyShareAccess =
+ FILE_SHARE_READ; // BUGBUG
+// FILE_SHARE_DELETE;
+
+ NTSTATUS NtStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ BOOL PathAllocated = FALSE;
+ UNICODE_STRING UnicodePath;
+#endif
+
+ //
+ // Check for caller errors.
+ //
+
+ if ( (FileName==NULL) || ((*FileName)==TCHAR_EOS) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ //
+ // Tell the world what we're going to do.
+ //
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplDeleteFile: *** DELETING FILE *** '" FORMAT_LPTSTR "'.\n",
+ FileName ));
+ }
+
+ //
+ // return no error if the file does not exist.
+ //
+ if ( !ReplFileOrDirExists( FileName ) ) {
+ return( NO_ERROR );
+ }
+
+#ifndef USE_BACKUP_APIS
+
+ //
+ // If the file system ACL allows us to delete, we can just
+ // use the Win32 APIs for this.
+ //
+
+ if ( ! DeleteFile( (LPTSTR) FileName ) ) {
+ ApiStatus = (NET_API_STATUS) GetLastError();
+ } else {
+ ApiStatus = NO_ERROR;
+ }
+
+#else
+
+ //
+ // It turns out that "backup semantics" is very powerful. It allows
+ // us to create files in directories which have read-only ACLs.
+ // Unfortunately, there isn't a "backup semantics" flag for DeleteFile(),
+ // so we need to use the NT APIs to get the same effect.
+ //
+
+ //
+ // Convert file name to NT style.
+ //
+
+ RtlInitUnicodeString(
+ & UnicodePath, // output: struct
+ FileName ); // input: null terminated
+
+ if( !RtlDosPathNameToNtPathName_U(
+ FileName,
+ &UnicodePath,
+ NULL,
+ NULL) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplDeleteFile: RtlDosPathNameToNtPathname_U"
+ " of file '" FORMAT_LPTSTR "' failed.\n", FileName ));
+
+ // BUGBUG: this is just our best guess for an error code this.
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+ NetpAssert( UnicodePath.Buffer != NULL );
+ PathAllocated = TRUE;
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ (LPVOID) &UnicodePath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ //
+ // Open the file, with backup semantics and delete on close.
+ //
+
+ NtStatus = NtOpenFile(
+ & FileHandle,
+ MyAccessDesired,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ MyShareAccess,
+ MyOpenOptions );
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplDeleteFile: NtOpenFile of file '"
+ FORMAT_LPTSTR "' gave NT status " FORMAT_NTSTATUS ".\n",
+ FileName, NtStatus ));
+
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+ NetpAssert( NtStatus == STATUS_SUCCESS );
+ NetpAssert( FileHandle != INVALID_HANDLE_VALUE );
+
+ //
+ // Close the file, which will delete it since we gave the
+ // FILE_CLOSE_ON_DELETE flag.
+ //
+
+ NtStatus = NtClose( FileHandle );
+ FileHandle = INVALID_HANDLE_VALUE;
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplDeleteFile: NtClose failed, "
+ " NT status is " FORMAT_NTSTATUS
+ ".\n", NtStatus ));
+
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+ NetpAssert( NtStatus == STATUS_SUCCESS );
+
+ (void) NtClose( FileHandle );
+ FileHandle = INVALID_HANDLE_VALUE;
+
+ (VOID) RtlFreeHeap( RtlProcessHeap(), 0, UnicodePath.Buffer );
+ PathAllocated = FALSE;
+
+ ApiStatus = NO_ERROR;
+
+#endif
+
+
+Cleanup:
+
+ if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplDeleteFile: ERROR " FORMAT_API_STATUS ".\n",
+ ApiStatus ));
+
+ //
+ // Log the error.
+ // BUGBUG: extract master server name and log there too.
+ //
+ ReplErrorLog(
+ NULL, // no server name (log locally)
+ NELOG_ReplSysErr, // log code
+ ApiStatus,
+ NULL, // optional str1
+ NULL); // optional str2
+ }
+
+#ifdef USE_BACKUP_APIS
+ if (FileHandle != INVALID_HANDLE_VALUE) {
+ (VOID) NtClose( FileHandle );
+ }
+
+ if (PathAllocated) {
+ (VOID) RtlFreeHeap( RtlProcessHeap(), 0, UnicodePath.Buffer );
+ }
+#endif
+
+ return (ApiStatus);
+
+}
diff --git a/private/net/svcdlls/repl/common/dirname.c b/private/net/svcdlls/repl/common/dirname.c
new file mode 100644
index 000000000..b172cc862
--- /dev/null
+++ b/private/net/svcdlls/repl/common/dirname.c
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ DirName.c
+
+Abstract:
+
+ This module has some simple replicator directory name helpers.
+
+Author:
+
+ John Rogers (JohnRo) 07-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 07-Jan-1992 JohnRo
+ Created.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 26-Mar-1992 JohnRo
+ Added check to disallow "c:\stuff" form.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // PATHLEN, etc.
+
+// These can be in any order:
+
+#include <dirname.h> // My prototypes.
+#include <tstr.h> // STRLEN().
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+BOOL
+ReplIsDirNameValid(
+ IN LPTSTR DirName
+ )
+
+/*++
+
+Routine Description:
+
+ ReplIsDirNameValid checks to see if a replicator directory name is
+ syntactically valid. No check is made to see if the directory exists.
+
+Arguments:
+
+ DirName points to a string containing an alleged replicator directory
+ name.
+
+Return Value:
+
+ BOOL - TRUE iff the directory name is valid.
+
+--*/
+
+{
+ TCHAR FirstChar;
+
+ if ( (DirName == NULL) || (*DirName == L'\0') ) {
+ return (FALSE);
+ }
+ FirstChar = DirName[0];
+
+
+ if (STRLEN( DirName ) > PATHLEN) {
+ return (FALSE);
+ }
+
+ if (ISALPHA( FirstChar )) {
+ if (STRLEN(DirName) >= 2) {
+
+ if (DirName[1] == TCHAR_COLON) { // Sneak in "c:\stuff"?
+ return (FALSE); // Name not valid!
+ }
+ }
+ }
+
+ //
+ // BUGBUG: This is just a quick partial hack. Eventually we should
+ // call the canon routines.
+ //
+
+ switch (FirstChar) {
+ case TCHAR_BACKSLASH:
+ // Name must be relative; no UNC or absolute paths allowed.
+ /*FALLTHROUGH*/
+ case TCHAR_FWDSLASH:
+ // Name must be relative; no UNC or absolute paths allowed.
+ /*FALLTHROUGH*/
+
+ return (FALSE); // name is not valid
+
+ default:
+ return (TRUE);
+ }
+
+ /*NOTREACHED*/
+
+} // ReplIsDirNameValid
diff --git a/private/net/svcdlls/repl/common/dirname.h b/private/net/svcdlls/repl/common/dirname.h
new file mode 100644
index 000000000..f201b63b7
--- /dev/null
+++ b/private/net/svcdlls/repl/common/dirname.h
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) 1991-92 Microsoft Corporation
+
+Module Name:
+
+ DirName.h
+
+Abstract:
+
+ This module has some simple replicator directory name helpers.
+
+Author:
+
+ John Rogers (JohnRo) 31-Dec-1991
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 31-Dec-1991 JohnRo
+ Created.
+ 08-Jan-1992 JohnRo
+ Added ReplDirNamesMatch() macro.
+ 09-Jan-1992 JohnRo
+ Use _wcscmpi() instead of wcscmpi().
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 05-Dec-1992 JohnRo
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+#ifndef _DIRNAME_
+#define _DIRNAME_
+
+
+// Don't complain about "unneeded" includes of these files:
+/*lint -efile(764,tstr.h) */
+#include <tstr.h> // STRICMP().
+
+
+// BOOL
+// ReplDirNamesMatch(
+// IN LPTSTR OneName,
+// IN LPTSTR TheOther
+// );
+//
+// BUGBUG: Should this canonicalize? (E.g. ".\a" == "a"?)
+//
+#define ReplDirNamesMatch(OneName,TheOther) \
+ ( ( (STRICMP( (OneName), (TheOther))) == 0 ) ? TRUE : FALSE )
+
+
+BOOL
+ReplIsDirNameValid(
+ IN LPTSTR DirName
+ );
+
+
+#endif // _DIRNAME_
diff --git a/private/net/svcdlls/repl/common/easize.c b/private/net/svcdlls/repl/common/easize.c
new file mode 100644
index 000000000..dbf292fb3
--- /dev/null
+++ b/private/net/svcdlls/repl/common/easize.c
@@ -0,0 +1,236 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ EaSize.c
+
+Abstract:
+
+ Compute size of full EA list (using OS/2 semantics) for a file or
+ directory. This must match OS/2 usage, down to the bit, as this
+ value is used in the replicator checksum. One thing in particular:
+ the "EA size" of a file with no EAs is 4, as it takes four bytes to
+ indicate empty full EA list.
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft) 10-May-1993
+
+Revision History:
+
+ 10-May-1993 JohnRo
+ Created for RAID 3258: file not updated due to
+ ERROR_INVALID_USER_BUFFER (actually, massive rework of buggy
+ version in repl/server/filefind.c).
+
+--*/
+
+
+// These must be included first:
+
+#include <nt.h> // NT definitions
+#include <ntrtl.h> // NT runtime library definitions
+#include <nturtl.h>
+#include <windows.h>
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+#include <lmerr.h> // NERR_ equates.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), FORMAT_ equates.
+#include <netlibnt.h> // NetpNtStatusToApiStatus().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), ReplErrorLog(), ReplGetEaSize(), etc.
+#include <tstr.h> // STRLEN(), etc.
+
+
+#define MY_ACCESS_DESIRED ( FILE_READ_DATA | FILE_READ_EA \
+ | FILE_TRAVERSE \
+ | SYNCHRONIZE | FILE_READ_ATTRIBUTES )
+
+
+DWORD
+ReplGetEaSize(
+ IN LPCTSTR Path
+ )
+
+/*++
+
+Routine Description:
+
+ Retrive EaSize of the given file and convert it to DosFindFirst2
+ EaSize.
+
+Arguments:
+
+ Path - file name. May refer to file or directory. May include drive
+ letter (e.g. "d:\import\dir\file.ext") or be UNC path (e.g.
+ "\\server\repl$\dir\dir2\file.ext").
+
+Return Value:
+
+ Return DosFindFirst2 EaSize. This value will be 4 if no EAs exist or
+ an error occurs.
+
+--*/
+
+{
+ NET_API_STATUS ApiStatus = NO_ERROR;
+ FILE_EA_INFORMATION EaInfo;
+ DWORD EaSize = EA_MIN_SIZE; // initially set to return on err
+ HANDLE FileHandle = INVALID_HANDLE_VALUE;
+ UNICODE_STRING FileName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ NTSTATUS NtStatus = STATUS_SUCCESS;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ BOOL PathAllocated = FALSE;
+ DWORD PathLength;
+
+ NetpAssert( Path != NULL );
+ NetpAssert( (*Path) != TCHAR_EOS );
+
+ //
+ // Some systems don't like NtQueryEaFile with names like:
+ //
+ // \\server\REPL$\dir\.
+ // \\server\REPL$\dir\..
+ //
+ // so avoid them. (They won't be used in checksums anyway, so it
+ // doesn't matter if we lie about their EA sizes.)
+ //
+ PathLength = STRLEN(Path);
+ if (PathLength >= 2) {
+ LPCTSTR LastTwoChars = &Path[ PathLength-2 ];
+ NetpAssert( (*LastTwoChars) != TCHAR_EOS );
+ if (STRCMP( LastTwoChars, SLASH_DOT ) == 0) {
+ goto Cleanup;
+ }
+ }
+ if (PathLength >= 3) {
+ LPCTSTR LastThreeChars = &Path[ PathLength-3 ];
+ NetpAssert( (*LastThreeChars) != TCHAR_EOS );
+ if (STRCMP( LastThreeChars, SLASH_DOT_DOT ) == 0) {
+ goto Cleanup;
+ }
+ }
+
+#ifndef UNICODE
+#error Fix code below if UNICODE is not defined any more.
+#endif
+
+ if( !RtlDosPathNameToNtPathName_U(
+ Path,
+ &FileName,
+ NULL,
+ NULL
+ ) ) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: "
+ "Could not convert DOS path '" FORMAT_LPTSTR "' "
+ "to NT path.\n", Path ));
+
+ ApiStatus = NERR_InternalError;
+ goto Cleanup;
+ }
+ PathAllocated = TRUE;
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ NtStatus = NtOpenFile(
+ &FileHandle,
+ MY_ACCESS_DESIRED,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT ); // open options
+
+ if (! NT_SUCCESS(NtStatus)) {
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: NtOpenFile " FORMAT_LPTSTR " failed: "
+ FORMAT_NTSTATUS "\n",
+ Path, NtStatus ));
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+
+ IF_DEBUG( FILEFIND ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: Succeeded in opening dir.\n" ));
+ }
+
+ NtStatus = NtQueryInformationFile(
+ FileHandle,
+ &IoStatusBlock,
+ &EaInfo,
+ sizeof(FILE_EA_INFORMATION),
+ FileEaInformation ); // information class
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: NtQueryInformationFile for "
+ FORMAT_LPTSTR " FAILED, NtStatus="
+ FORMAT_NTSTATUS ", iosb.info=" FORMAT_ULONG "\n",
+ Path, NtStatus, IoStatusBlock.Information ));
+ ApiStatus = NetpNtStatusToApiStatus( NtStatus );
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+
+ EaSize = EaInfo.EaSize;
+ if (EaSize == 0) {
+ EaSize = EA_MIN_SIZE;
+ }
+
+Cleanup:
+
+ //
+ // Take care of things and return EaSize to caller.
+ // Also use ApiStatus to decide whether or not to log anything.
+ //
+
+ if (ApiStatus != NO_ERROR) {
+
+ // BUGBUG: log this remotely too.
+ ReplErrorLog(
+ NULL, // no server name (local)
+ NELOG_ReplSysErr, // log code
+ ApiStatus, // error code we got
+ NULL, // no optional str 1
+ NULL ); // no optional str 2
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: ERROR processing '" FORMAT_LPTSTR "', "
+ "final NT status " FORMAT_NTSTATUS ", "
+ "final API status " FORMAT_API_STATUS ".\n",
+ Path, NtStatus, ApiStatus ));
+ }
+
+ IF_DEBUG( FILEFIND ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetEaSize: returning EA size " FORMAT_DWORD " "
+ "for " FORMAT_LPTSTR ", final NT status " FORMAT_NTSTATUS ", "
+ "final API status " FORMAT_API_STATUS ".\n",
+ EaSize, Path, NtStatus, ApiStatus ));
+ }
+
+ if (PathAllocated) {
+ (VOID) RtlFreeHeap( RtlProcessHeap(), 0, FileName.Buffer );
+ }
+
+ if (FileHandle != INVALID_HANDLE_VALUE) {
+ (void) NtClose(FileHandle);
+ }
+
+ return (EaSize);
+}
diff --git a/private/net/svcdlls/repl/common/expalloc.c b/private/net/svcdlls/repl/common/expalloc.c
new file mode 100644
index 000000000..da5fe7f1c
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expalloc.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ExpAlloc.c
+
+Abstract:
+
+ This file contains ExportDirAllocApiRecords().
+
+Author:
+
+ John Rogers (JohnRo) 22-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 22-Jan-1992 JohnRo
+ Created.
+ 28-Jan-1992 JohnRo
+ Changed ExportDirAllocApiRecords() to allow arrays.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS, PARM equates, etc.
+#include <rap.h> // Needed by <strucinf.h>.
+
+// These can be in any order:
+
+#include <expdir.h> // My prototype.
+#include <lmapibuf.h> // NetApiBufferAllocate().
+#include <netdebug.h> // NetpAssert().
+#include <netlib.h> // NetpPointerPlusSomeBytes().
+#include <strucinf.h> // Netp{various}StructureInfo().
+#include <winerror.h> // ERROR_* defines; NO_ERROR.
+
+
+NET_API_STATUS
+ExportDirAllocApiRecords (
+ IN DWORD Level,
+ IN DWORD EntryCount,
+ OUT LPBYTE * BufPtr,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ )
+
+{
+ LPBYTE FirstRecord = NULL;
+ NET_API_STATUS ApiStatus;
+ DWORD EntrySize;
+
+ //
+ // Check for caller errors.
+ //
+ if (BufPtr == NULL) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ * BufPtr = NULL; // Don't confuse caller about possible alloc'ed data.
+
+ if (EntryCount == 0) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ //
+ // Compute size of an entry (and check caller's Level too).
+ //
+ ApiStatus = NetpReplExportDirStructureInfo (
+ Level,
+ PARMNUM_ALL,
+ TRUE, // want native sizes
+ NULL, // don't need DataDesc16
+ NULL, // don't need DataDesc32
+ NULL, // don't need DataDescSmb
+ & EntrySize, // need max size of structure
+ NULL, // don't need FixedSize
+ NULL); // don't need StringSize
+ if (ApiStatus != NO_ERROR) {
+ return (ApiStatus);
+ }
+ NetpAssert( EntrySize > 0 );
+
+ //
+ // Allocate the output area.
+ //
+ ApiStatus = NetApiBufferAllocate(
+ EntrySize * EntryCount,
+ (LPVOID *) & FirstRecord);
+ if (ApiStatus != NO_ERROR) {
+
+ // ApiStatus is already set to return error to caller.
+
+ } else {
+ NetpAssert( FirstRecord != NULL );
+
+ //
+ // Tell caller where top of string area is.
+ //
+ * StringLocation = NetpPointerPlusSomeBytes(
+ FirstRecord,
+ EntrySize * EntryCount );
+
+ }
+
+ //
+ // Tell caller how everything went.
+ //
+ * BufPtr = FirstRecord;
+ return (ApiStatus);
+
+}
diff --git a/private/net/svcdlls/repl/common/expbuild.c b/private/net/svcdlls/repl/common/expbuild.c
new file mode 100644
index 000000000..690f23bff
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expbuild.c
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpBuild.c
+
+Abstract:
+
+ This file contains ExportDirBuildApiRecord. This is used by
+ NetrReplExportDirGetInfo and NetrReplExportDirEnum.
+
+Author:
+
+ John Rogers (JohnRo) 08-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ This code assumes that the export dir info levels are subsets of each other.
+ Also, this routine is callable whether or not the replicator service is
+ started.
+
+Revision History:
+
+ 08-Jan-1992 JohnRo
+ Created.
+ 08-Jan-1992 JohnRo
+ Fixed level 1 trashing bug.
+ 21-Jan-1992 JohnRo
+ Changed ExportDirBuildApiRecord's interface.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 26-Feb-1992 JohnRo
+ API records now contain timestamps instead of elapsed times.
+ Check lock fields for validity.
+ Added assertion of valid record at end.
+ 15-Mar-1992 JohnRo
+ Improve setinfo info level support.
+ 28-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ 08-Feb-1993 JohnRo
+ PC-LINT found a bug.
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS, PARM equates, etc.
+#include <repldefs.h> // ReplIsIntegrityValid(), etc.
+
+// These can be in any order:
+
+#include <align.h> // POINTER_IS_ALIGNED(), ALIGN_TCHAR.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototype, ExportDirIsLevelValid().
+#include <lmrepl.h> // LPREPL_EDIR_INFO_1, REPL_EXTENT_ stuff, etc.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <tstr.h> // STRLEN(), etc.
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+NET_API_STATUS
+ExportDirBuildApiRecord (
+ IN DWORD Level,
+ IN LPTSTR DirName,
+ IN DWORD Integrity,
+ IN DWORD Extent,
+ IN DWORD LockCount,
+ IN DWORD TimeOfFirstLock, // Seconds since 1970.
+ OUT LPVOID Buffer,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ )
+
+{
+ LPREPL_EDIR_INFO_2 ApiRecord = Buffer; // superset info level
+ LPTSTR StringDest;
+ DWORD StringLength;
+
+ NetpAssert( StringLocation != NULL);
+ NetpAssert( *StringLocation != NULL);
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirBuildApiRecord: building record at " FORMAT_LPVOID
+ ", *str loc is " FORMAT_LPVOID ".\n",
+ (LPVOID) Buffer, (LPVOID) *StringLocation ));
+ }
+
+ //
+ // Check for caller errors.
+ //
+ if (Buffer == NULL) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+ NetpAssert( DirName != NULL);
+ if ( !ReplIsDirNameValid( DirName ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+ NetpAssert( Buffer != NULL);
+ if ( !ExportDirIsLevelValid( Level, FALSE ) ) { // don't allow setinfo.
+ return (ERROR_INVALID_LEVEL);
+ }
+ NetpAssert( ReplAreLockFieldsValid( LockCount, TimeOfFirstLock ) );
+
+ //
+ // First do subset common to all info levels.
+ //
+ StringLength = (DWORD) STRLEN( DirName );
+
+ NetpAssert( POINTER_IS_ALIGNED( *StringLocation, ALIGN_TCHAR ) );
+ StringDest = (LPTSTR) (LPVOID) (*StringLocation);
+ StringDest -= (StringLength + 1);
+
+ *StringLocation = (LPBYTE) (LPVOID) StringDest;
+
+ ApiRecord->rped2_dirname = StringDest;
+
+ (void) STRCPY(
+ StringDest, // dest
+ DirName); // src
+
+ //
+ // Next do stuff found in 1 and 2.
+ //
+ if (Level > 0) {
+ NetpAssert( ReplIsIntegrityValid( Integrity ) );
+ ApiRecord->rped2_integrity = Integrity;
+
+ NetpAssert( ReplIsExtentValid( Extent ) );
+ ApiRecord->rped2_extent = Extent;
+
+ //
+ // Now stuff only in level 2.
+ //
+ if (Level == 2) {
+ ApiRecord->rped2_lockcount = LockCount;
+
+ if (TimeOfFirstLock == 0) {
+ ApiRecord->rped2_locktime = 0;
+ } else {
+ ApiRecord->rped2_locktime = TimeOfFirstLock;
+ }
+ }
+ }
+
+ NetpAssert( ExportDirIsApiRecordValid( Level, ApiRecord, NULL ) );
+
+ return (NO_ERROR);
+
+}
diff --git a/private/net/svcdlls/repl/common/expconf.c b/private/net/svcdlls/repl/common/expconf.c
new file mode 100644
index 000000000..eadffc5a0
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expconf.c
@@ -0,0 +1,694 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpConf.c
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator export directory worker routines.
+
+Author:
+
+ John Rogers (JohnRo) 09-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 09-Jan-1992 JohnRo
+ Created.
+ 23-Jan-1992 JohnRo
+ Clarify units for time parameters.
+ 28-Jan-1992 JohnRo
+ Added ExportDirConfigDataExists() and ExportDirDeleteConfigData().
+ ExportDirReadConfigData() should return NERR_UnknownDevDir.
+ Changed to use LPTSTR etc.
+ 03-Feb-1992 JohnRo
+ Corrected config _write where extent trashed integrity value.
+ Got rid of extra parse of comma.
+ Call ReplConfigReportBadParmValue() to inform user.
+ Corrected lengths used for integrity and extent.
+ 10-Feb-1992 JohnRo
+ ExportDirReadConfigData() should handle section not found.
+ 13-Feb-1992 JohnRo
+ Implement ExportDirDeleteConfigData().
+ Moved section name equates to ConfName.h.
+ 26-Feb-1992 JohnRo
+ API records now contain timestamps instead of elapsed times.
+ 23-Mar-1992 JohnRo
+ Get rid of old config helpers.
+ 10-Jul-1992 JohnRo
+ RAID 10503: srv mgr: repl dialog doesn't come up.
+ Use PREFIX_ equates.
+ 23-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ 29-Sep-1992 JohnRo
+ Also fix remote repl admin.
+ 04-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ Made changes suggested by PC-LINT 5.0
+ 21-Jan-1993 JohnRo
+ RAID 7717: Repl assert if not logged on correctly. (Also do event
+ logging for real.)
+ More changes suggested by PC-LINT 5.0
+ 25-Jan-1993 JohnRo
+ RAID 12914: avoid double close and free mem in ExportDirDeleteConfigData
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+#include <windef.h> // Win32 type definitions
+#include <lmcons.h> // LAN Manager common definitions
+#include <repldefs.h> // IF_DEBUG(), DWORDLEN.
+
+#include <config.h> // NetpConfig helpers.
+#include <confname.h> // SECT_NT_ equates.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototypes.
+#include <lmapibuf.h> // NetApiBufferFree().
+#include <lmerr.h> // NERR_, ERROR_, NO_ERROR equates.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <lmrepl.h> // REPL_INTEGRITY equates, etc.
+#include <netdebug.h> // NetpAssert(), etc.
+#include <netlib.h> // NetpPointerPlusSomeBytes().
+#include <prefix.h> // PREFIX_ equates.
+#include <replconf.h> // ReplConfigReportBadParmValue().
+#include <tstr.h> // STRCPY(), ATOL().
+
+
+#define STRING_FILE (LPVOID) TEXT("FILE")
+#define STRING_TREE (LPVOID) TEXT("TREE")
+
+#define MAX_INTEGRITY_LEN 4
+#define MAX_EXTENT_LEN 4
+
+#define EXPORT_VALUE_ARRAY_LEN \
+ (MAX_INTEGRITY_LEN /* integrity */ \
+ + 1 /* , */ \
+ + MAX_EXTENT_LEN /* extent */ \
+ + 1 /* , */ \
+ + DWORDLEN /* lockcount */ \
+ + 1 /* , */ \
+ + DWORDLEN ) /* locktime (seconds since 1970) */
+
+
+// Tells whether or not config data for this directory exists.
+// Callable even if the replicator service is not started.
+BOOL
+ExportDirConfigDataExists (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPTSTR Value = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ NetpAssert( ReplIsDirNameValid( DirName ) );
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS, // area (instead of parameters)
+ TRUE); // read-only
+ if (ApiStatus != NO_ERROR) {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ return (FALSE); // section doesn't exist, so dir data doesn't.
+ }
+
+ //
+ // Read the value from the config file/whatever.
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ & Value); // alloc and set ptr
+
+ //
+ // We're done with this, so close the config data and toss the buffer we
+ // got. But remember the status from NetpGetConfigValue!
+ //
+ if (Value != NULL) {
+ (void) NetApiBufferFree( Value );
+ }
+ (void) NetpCloseConfigData( Handle );
+
+ //
+ // Now check the status of the Get.
+ //
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ return (FALSE); // doesn't exist
+ } else if (ApiStatus == NO_ERROR) {
+ return (TRUE); // exists
+ } else {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ return (FALSE); // Unexpected error, so assume it doesn't exist.
+ }
+
+ /*NOTREACHED*/
+
+} // ExportDirConfigDataExists
+
+
+// Delete config data for this directory.
+// Returns NERR_UnknownDevDir if config data doesn't exist for this dir.
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirDeleteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS, // area (instead of parameters)
+ FALSE ); // not read-only
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Delete this keyword from this section.
+ //
+ ApiStatus = NetpDeleteConfigKeyword(
+ Handle,
+ DirName ); // keyword is dir name
+
+ IF_DEBUG(EXPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirDeleteConfigData( " FORMAT_LPTSTR " ): conf del ret "
+ FORMAT_API_STATUS ".\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local"),
+ ApiStatus ));
+ }
+
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+Cleanup:
+
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ExportDirDeleteConfigData
+
+
+// Parse config data for a single export directory. Callable whether or not
+// the replicator service is started. (This function is used in this file
+// and by the NetReplExportDirEnum routine.)
+NET_API_STATUS
+ExportDirParseConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR ValueString,
+ OUT LPDWORD IntegrityPtr,
+ OUT LPDWORD ExtentPtr,
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ )
+{
+ LPTSTR CurrentValuePtr = ValueString;
+
+ //
+ // Check for caller's errors.
+ //
+ NetpAssert( ValueString != NULL );
+ if (STRLEN( ValueString ) > EXPORT_VALUE_ARRAY_LEN) {
+ goto ReportBadConfigLine;
+ }
+
+ //
+ // Start parsing the value, which begins with a string containing the
+ // integrity.
+ //
+
+#define TRY_INTEGRITY( IntegrityEquate, IntegrityString ) \
+ { \
+ DWORD HopefulStringLength = STRLEN(IntegrityString); \
+ if (STRNCMP( CurrentValuePtr, (IntegrityString), HopefulStringLength) == 0) { \
+ *IntegrityPtr = (IntegrityEquate); \
+ CurrentValuePtr = (LPTSTR) (LPVOID) \
+ NetpPointerPlusSomeBytes( CurrentValuePtr, \
+ HopefulStringLength * sizeof(TCHAR) ); \
+ goto DoneIntegrity; \
+ } \
+ }
+
+ TRY_INTEGRITY( REPL_INTEGRITY_FILE, STRING_FILE )
+
+ TRY_INTEGRITY( REPL_INTEGRITY_TREE, STRING_TREE )
+
+ goto ReportBadConfigLine;
+
+DoneIntegrity:
+
+ //
+ // Parse the comma after the integrity string.
+ //
+
+#define PARSE_CHAR(AsciiChar) \
+ { \
+ if (*CurrentValuePtr == MAKE_TCHAR(AsciiChar)) { \
+ ++CurrentValuePtr; \
+ } else { \
+ goto ReportBadConfigLine; \
+ } \
+ }
+
+#define PARSE_COMMA( ) PARSE_CHAR(',')
+
+ PARSE_COMMA();
+
+ //
+ // Now do the extent string.
+ //
+
+#define TRY_EXTENT( ExtentEquate, ExtentString ) \
+ { \
+ DWORD HopefulStringLength = STRLEN(ExtentString); \
+ if (STRNCMP( CurrentValuePtr, (ExtentString), HopefulStringLength) == 0) { \
+ *ExtentPtr = (ExtentEquate); \
+ CurrentValuePtr = (LPTSTR) (LPVOID) \
+ NetpPointerPlusSomeBytes( CurrentValuePtr, \
+ HopefulStringLength * sizeof(TCHAR) ); \
+ goto DoneExtent; \
+ } \
+ }
+
+ TRY_EXTENT( REPL_EXTENT_FILE, STRING_FILE )
+
+ TRY_EXTENT( REPL_EXTENT_TREE, STRING_TREE )
+
+ goto ReportBadConfigLine;
+
+DoneExtent:
+
+ PARSE_COMMA();
+
+ //
+ // Parse the numbers on the rest of the line.
+ //
+
+#define PARSE_DWORD( NumberPtr ) \
+ { \
+ if ( ! ISDIGIT( *CurrentValuePtr ) ) { \
+ goto ReportBadConfigLine; \
+ } \
+ NetpAssert( NumberPtr != NULL ); \
+ * NumberPtr = (DWORD) ATOL( CurrentValuePtr ); \
+ while ( ISDIGIT( *CurrentValuePtr ) ) { \
+ ++CurrentValuePtr; \
+ } \
+ }
+
+ PARSE_DWORD( LockCountPtr );
+
+ PARSE_COMMA();
+
+ PARSE_DWORD( LockTimePtr );
+
+ IF_DEBUG(EXPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirParseConfigValue: Value = '" FORMAT_LPTSTR "',\n",
+ ValueString ));
+ NetpKdPrint((
+ " Integrity = " FORMAT_DWORD
+ ", Extent = " FORMAT_DWORD
+ ", lock count = " FORMAT_DWORD ".\n",
+ *IntegrityPtr, *ExtentPtr, *LockCountPtr ));
+ NetpDbgDisplayTimestamp( "lock time", *LockTimePtr );
+ }
+
+ if ( ! ReplIsIntegrityValid( *IntegrityPtr ) ) {
+ goto ReportBadConfigLine;
+ }
+ if ( ! ReplIsExtentValid( *ExtentPtr ) ) {
+ goto ReportBadConfigLine;
+ }
+
+ return (NO_ERROR);
+
+ReportBadConfigLine:
+
+ // BUGBUG: Sure would be nice if we could include dirname here.
+
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS,
+ ValueString );
+ return (ERROR_INVALID_DATA);
+
+} // ExportDirParseConfigData
+
+
+// Read config data for a single export directory. Callable whether or not
+// the replicator service is started. Returns NERR_UnknownDevDir if no
+// config data exists for this directory.
+NET_API_STATUS
+ExportDirReadConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ OUT LPDWORD IntegrityPtr,
+ OUT LPDWORD ExtentPtr,
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPTSTR Value = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS, // area (instead of parameters)
+ TRUE); // read-only
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Read the value from the config file/whatever.
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ & Value); // alloc and set ptr
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+ NetpAssert( Value != NULL );
+
+ IF_DEBUG(EXPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirReadConfigValue( " FORMAT_LPTSTR " ): '"
+ FORMAT_LPTSTR "' = '" FORMAT_LPTSTR "'.\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local"),
+ DirName, Value ));
+ }
+
+ //
+ // Parse the value string...
+ //
+ ApiStatus = ExportDirParseConfigData (
+ UncServerName,
+ Value,
+ IntegrityPtr,
+ ExtentPtr,
+ LockCountPtr,
+ LockTimePtr); // Seconds since 1970.
+ // Fall through and log error if any.
+
+Cleanup:
+
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ (VOID) NetApiBufferFree( Value );
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+ return (ApiStatus);
+
+} // ExportDirReadConfigData
+
+
+
+
+
+// Write config data for a single export directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ExportDirWriteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Integrity,
+ IN DWORD Extent,
+ IN DWORD LockCount,
+ IN DWORD LockTime // Seconds since 1970.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ TCHAR ValueArray[EXPORT_VALUE_ARRAY_LEN+1];
+
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( ! ReplIsIntegrityValid( Integrity ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( ! ReplIsExtentValid( Extent ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS, // area (instead of parameters)
+ FALSE); // not read-only
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Start building the value, which begins with a string containing the
+ // integrity.
+ //
+ switch (Integrity) {
+ case REPL_INTEGRITY_FILE:
+
+ (void) STRCPY( ValueArray, STRING_FILE);
+ break;
+
+ case REPL_INTEGRITY_TREE:
+
+ (void) STRCPY( ValueArray, STRING_TREE);
+ break;
+
+ default:
+ NetpAssert( FALSE );
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Fields get seperated by commas.
+ //
+/*lint -save -e767 */ // Don't complain about different definitions
+#define WRITE_COMMA( ) \
+ (void) STRCAT( ValueArray, (LPVOID) TEXT(",") )
+/*lint -restore */ // Resume checking for different macro definitions
+
+ WRITE_COMMA();
+
+ //
+ // Next we do the extent.
+ //
+ switch (Extent) {
+ case REPL_EXTENT_FILE:
+
+ (void) STRCAT( ValueArray, STRING_FILE);
+ break;
+
+ case REPL_EXTENT_TREE:
+
+ (void) STRCAT( ValueArray, STRING_TREE);
+ break;
+
+ default:
+ NetpAssert( FALSE );
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ WRITE_COMMA();
+
+ //
+ // Now do the last two fields, with are both DWORDS.
+ //
+
+/*lint -save -e767 */ // Don't complain about different definitions
+#define WRITE_DWORD( Number ) \
+ { \
+ LPTSTR StrEnd = & ValueArray[ STRLEN( ValueArray ) ]; \
+ (void) ULTOA( (Number), StrEnd, /* radix */ 10 ); \
+ }
+/*lint -restore */ // Resume checking for different macro definitions
+
+ WRITE_DWORD( LockCount );
+
+ WRITE_COMMA();
+
+ WRITE_DWORD( LockTime ); // Seconds since 1970.
+
+ IF_DEBUG(EXPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirWriteConfigValue( " FORMAT_LPTSTR "): '"
+ FORMAT_LPTSTR "' = '" FORMAT_LPTSTR "'.\n",
+ (UncServerName!=NULL) ? UncServerName : (LPVOID) TEXT("local"),
+ DirName, ValueArray ));
+ }
+
+ //
+ // Write this value out to the config file/whatever.
+ //
+ ApiStatus = NetpSetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ ValueArray);
+ // Faill through and log error if any.
+
+
+Cleanup:
+
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ExportDirWriteConfigData
diff --git a/private/net/svcdlls/repl/common/expdir.h b/private/net/svcdlls/repl/common/expdir.h
new file mode 100644
index 000000000..292b705fb
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expdir.h
@@ -0,0 +1,265 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpDir.h
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator export directory worker routines.
+
+Author:
+
+ John Rogers (JohnRo) 08-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ You must include LmCons.h before this file.
+
+Revision History:
+
+ 08-Jan-1992 JohnRo
+ Created.
+ 09-Jan-1992 JohnRo
+ Added EXPORT_DIR_SECTION_NAME equate.
+ Added ExportDir{Read,Write}ConfigData.
+ 20-Jan-1992 JohnRo
+ Netr prototypes are now generated by MIDL and put in repl.h.
+ 23-Jan-1992 JohnRo
+ Clarify units for time parameters.
+ Changed EXPORT_DIR_SECTION_NAME.
+ Changed ExportDirBuildApiRecord's interface.
+ Added ExportDirIsApiRecordValid().
+ Added ExportDirAllocApiRecord().
+ 28-Jan-1992 JohnRo
+ Changed ExportDirAllocApiRecords() to allow arrays.
+ Added ExportDirConfigDataExists() and ExportDirDeleteConfigData().
+ Changed to use LPTSTR etc.
+ 09-Feb-1992 JohnRo
+ Added ExportDir{Start,Stop}Repl routines.
+ 13-Feb-1992 JohnRo
+ Moved section name equates to ConfName.h.
+ 15-Mar-1992 JohnRo
+ Update registry with new values.
+ Improve support for setinfo info levels.
+ 23-Mar-1992 JohnRo
+ Added ExportDirReadMasterList().
+ 30-Jul-1992 JohnRo
+ Help PC-LINT understand ExportDirIsLevelValid().
+ 29-Sep-1992 JohnRo
+ RAID 7962: Repl APIs in wrong role kill svc.
+ Also fix remote repl admin.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 13-Jan-1993 JohnRo
+ RAID 7053: locked trees added to pulse msg. (Actually fix all
+ kinds of remote lock handling.)
+ 13-Apr-1993 JohnRo
+ RAID 3107: locking directory over the net gives network path not found.
+
+--*/
+
+
+#ifndef _EXPDIR_
+#define _EXPDIR_
+
+
+#include <netlib.h> // IN_RANGE().
+
+
+//
+// Export dir helper routines and macros:
+//
+
+// Allocate one or more API records for an export directory. Callable whether
+// or not the replicator service is started. (Used in getinfo stub, getinfo
+// worker, and enum stub.)
+NET_API_STATUS
+ExportDirAllocApiRecords (
+ IN DWORD Level,
+ IN DWORD EntryCount,
+ OUT LPBYTE * BufPtr,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ );
+
+// Build API record for an export directory. Callable whether or not
+// the replicator service is started. (Used in getinfo and enum.)
+NET_API_STATUS
+ExportDirBuildApiRecord (
+ IN DWORD Level,
+ IN LPTSTR DirName,
+ IN DWORD Integrity,
+ IN DWORD Extent,
+ IN DWORD LockCount,
+ IN DWORD TimeOfFirstLock, // Seconds since 1970.
+ OUT LPVOID Buffer,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ );
+
+// Tells whether or not config data for this directory exists.
+// Callable even if the replicator service is not started.
+BOOL
+ExportDirConfigDataExists (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ );
+
+NET_API_STATUS
+ExportDirConfigSetInfo (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ IN LPVOID Buf,
+ OUT LPDWORD ParmError OPTIONAL
+ );
+
+// Delete config data for this directory.
+// Returns NERR_UnknownDevDir if config data doesn't exist for this dir.
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirDeleteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirEnumApiRecords(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr,
+ IN DWORD PrefMaxSize,
+ OUT LPDWORD EntriesRead,
+ OUT LPDWORD TotalEntries
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirFixUserLockFiles(
+ IN LPCTSTR ExportPath, // Must include drive letter.
+ IN LPCTSTR DirName,
+ IN DWORD LockCount
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirGetApiRecord (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr
+ );
+
+BOOL
+ExportDirIsApiRecordValid (
+ IN DWORD Level,
+ IN LPVOID ApiRecord,
+ OUT LPDWORD ParmError OPTIONAL
+ );
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RMGlobalListLock.
+NET_API_STATUS
+ExportDirLockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName
+ );
+
+// Parse config data for a single export directory. Callable whether or not
+// the replicator service is started. (This function is used by routines
+// in Repl/Common/ExpConf.c and by the NetReplExportDirEnum routine.)
+NET_API_STATUS
+ExportDirParseConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR ValueString,
+ OUT LPDWORD IntegrityPtr,
+ OUT LPDWORD ExtentPtr,
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ );
+
+// Read config data for a single export directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ExportDirReadConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ OUT LPDWORD IntegrityPtr,
+ OUT LPDWORD ExtentPtr,
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ );
+
+// Read export dirs into service's master list.
+// Only callable locally, when service is started.
+// This also fixes the USERLOCK.* file(s) to match the lock count in registry.
+NET_API_STATUS
+ExportDirReadMasterList(
+ VOID
+ );
+
+// Read specified export dir into service's master list.
+NET_API_STATUS
+ExportDirGetRegistryValues(
+ IN LPTSTR ServiceRegPath OPTIONAL,
+ IN LPTSTR TargetName
+ );
+
+// Start replicating (exporting).
+// Called when service starts or user does NetReplSetInfo() and changes role.
+NET_API_STATUS
+ExportDirStartRepl (
+ IN BOOL ServiceIsStarting
+ );
+
+// Stop replicating (exporting).
+// Called when service stops or user does NetReplSetInfo() and changes role.
+NET_API_STATUS
+ExportDirStopRepl (
+ VOID
+ );
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RMGlobalListLock.
+NET_API_STATUS
+ExportDirUnlockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD UnlockForce
+ );
+
+// Write config data for a single export directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ExportDirWriteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Integrity,
+ IN DWORD Extent,
+ IN DWORD LockCount,
+ IN DWORD LockTime // Seconds since 1970.
+ );
+
+// BOOL
+// ExportDirIsLevelValid(
+// IN DWORD Level, // Info level
+// IN BOOL SetInfo // Are setinfo levels allowed?
+// );
+//
+#define ExportDirIsLevelValid(Level,SetInfo) \
+ /*lint -e506 */ /* don't complain about constant values here */ \
+ ( ( (Level) <= 2 ) \
+ || ( (SetInfo) && (IN_RANGE((Level), 1000, 1001)) ) ) \
+ /*lint +e506 */ \
+
+
+#endif // _EXPDIR_
diff --git a/private/net/svcdlls/repl/common/expenum.c b/private/net/svcdlls/repl/common/expenum.c
new file mode 100644
index 000000000..ffef39aa8
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expenum.c
@@ -0,0 +1,298 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpEnum.c
+
+Abstract:
+
+ ExportDirEnumApiRecords().
+
+Author:
+
+ John Rogers (JohnRo) 29-Sep-1992
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+ 29-Sep-1992 JohnRo
+ RAID 7962: Repl APIs in wrong role kill svc. (Extracted this code from
+ NetExportDirEnum's DLL stub.)
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 10-Mar-1993 JohnRo
+ RAID 12871: replication UI shows nothing (adding entry while enumerating
+ results in empty list).
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+
+// These must be included first:
+
+
+#include <windows.h>
+#include <lmcons.h> // NET_API_STATUS, etc.
+#include <netdebug.h> // NetpAssert().
+
+// These may be included in any order:
+
+#include <config.h> // LPNET_CONFIG_HANDLE, Netp config routines.
+#include <confname.h> // SECT_NT_ equates.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // ExportDirIsApiRecordValid(), my prototype, etc.
+#include <lmerr.h> // NERR_ and ERROR_ equates, NO_ERROR.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netlib.h> // NetpSetParmError(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), ReplErrorLog(), etc.
+#include <strucinf.h> // NetpReplExportDirStructureInfo().
+
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirEnumApiRecords(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr,
+ IN DWORD PrefMaxSize,
+ OUT LPDWORD EntriesRead,
+ OUT LPDWORD TotalEntries
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPVOID ArrayEntry;
+ LPVOID ArrayStart = NULL;
+ DWORD EntriesAllocated = 0;
+ DWORD EntriesFound = 0;
+ BOOL FirstTime;
+ DWORD FixedEntrySize;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPBYTE StringLocation;
+
+ UNREFERENCED_PARAMETER( PrefMaxSize );
+
+ if ( !ExportDirIsLevelValid( Level, FALSE ) ) {
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ } else if (BufPtr == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ } else if (EntriesRead == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ } else if (TotalEntries == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ //
+ // Set outputs in case we run into an error.
+ //
+
+ * BufPtr = NULL;
+ * EntriesRead = 0;
+ * TotalEntries = 0;
+
+ //
+ // Figure-out the size of a fixed entry for this info level.
+ //
+ ApiStatus = NetpReplExportDirStructureInfo (
+ Level,
+ PARMNUM_ALL,
+ TRUE, // want native sizes
+ NULL, // don't need data desc 16
+ NULL, // don't need data desc 32
+ NULL, // don't need data desc SMB
+ NULL, // don't need max size
+ & FixedEntrySize,
+ NULL ); // don't need string size
+
+ NetpAssert( ApiStatus == NO_ERROR ); // Already checked args.
+ NetpAssert( FixedEntrySize > 0 );
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // service name
+ (LPTSTR) SECT_NT_REPLICATOR_EXPORTS, // area under service
+ TRUE); // read-only
+ if (ApiStatus != NO_ERROR) {
+
+ // Handle section not found as empty enum array (not error).
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NO_ERROR;
+ goto Cleanup;
+ }
+
+ goto Cleanup;
+ }
+
+ //
+ // Loop, expanding buffer if necessary, until we get it large enough.
+ //
+
+ do {
+
+ //
+ // Count entries in config data.
+ //
+ ApiStatus = NetpNumberOfConfigKeywords (
+ Handle,
+ & EntriesAllocated );
+
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ } else if (EntriesAllocated == 0) {
+ goto Cleanup;
+ }
+
+ //
+ // Alloc the array...
+ //
+ ApiStatus = ExportDirAllocApiRecords (
+ Level,
+ EntriesAllocated,
+ (LPBYTE *) & ArrayStart,
+ & StringLocation ); // Points just past top of data.
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( ArrayStart != NULL );
+ } else {
+ goto Cleanup;
+ }
+
+ //
+ // Go back and reread, filling-in the config data as we go.
+ //
+
+ ArrayEntry = ArrayStart;
+ FirstTime = TRUE;
+
+ while (ApiStatus == NO_ERROR) {
+ LPTSTR DirName;
+ DWORD Integrity, Extent, LockCount, LockTime;
+ LPTSTR ValueString;
+
+ ApiStatus = NetpEnumConfigSectionValues (
+ Handle,
+ & DirName, // Keyword - alloc and set ptr.
+ & ValueString, // Must be freed by NetApiBufferFree().
+ FirstTime );
+
+ FirstTime = FALSE;
+
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( DirName != NULL );
+ NetpAssert( ValueString != NULL );
+
+ ++EntriesFound;
+ if (EntriesFound > EntriesAllocated) {
+ EntriesFound = 0;
+ NetpMemoryFree( ArrayStart );
+ ArrayStart = NULL;
+ ApiStatus = ERROR_MORE_DATA;
+ break; // exit per-entry loop and try again
+ }
+
+ if ( !ReplIsDirNameValid( DirName ) ) {
+ // BUGBUG: perhaps delete entry, log event, and continue?
+ ApiStatus = ERROR_INVALID_DATA;
+ NetpMemoryFree( DirName );
+ NetpMemoryFree( ValueString );
+ goto Cleanup;
+ }
+
+ //
+ // Parse the value string...
+ //
+ ApiStatus = ExportDirParseConfigData (
+ UncServerName,
+ ValueString,
+ & Integrity,
+ & Extent,
+ & LockCount,
+ & LockTime); // Seconds since 1970.
+
+ NetpMemoryFree( ValueString );
+
+ if (ApiStatus == NO_ERROR) {
+ //
+ // Build API record for this entry.
+ //
+ ApiStatus = ExportDirBuildApiRecord (
+ Level,
+ DirName,
+ Integrity,
+ Extent,
+ LockCount,
+ LockTime, // Seconds since 1970.
+ ArrayEntry,
+ & StringLocation );
+ if (ApiStatus != NO_ERROR) {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirEnumApiRecords: error "
+ FORMAT_API_STATUS " from exp build.\n",
+ ApiStatus ));
+ NetpAssert( FALSE );
+ goto Cleanup;
+ }
+
+ ArrayEntry = NetpPointerPlusSomeBytes(
+ ArrayEntry, FixedEntrySize );
+ }
+ NetpMemoryFree( DirName );
+
+ }
+
+ } // while not error (may be NERR_CfgParamNotFound at end).
+
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NO_ERROR;
+ } else {
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+
+ } while (ApiStatus == ERROR_MORE_DATA);
+
+ //
+ // All done.
+ //
+
+Cleanup:
+
+ if (Handle != NULL) {
+ (VOID) NetpCloseConfigData( Handle );
+ }
+
+ NetpAssert( ApiStatus != ERROR_MORE_DATA );
+ if (ApiStatus == NO_ERROR) {
+ * BufPtr = ArrayStart;
+ * EntriesRead = EntriesFound;
+ * TotalEntries = EntriesFound;
+ } else {
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirEnumApiRecords: returning status " FORMAT_API_STATUS
+ ".\n", ApiStatus ));
+
+ // Log the error.
+ ReplErrorLog(
+ UncServerName, // log here and there.
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL, // no str1
+ NULL ); // no str2
+
+ }
+
+ return ApiStatus;
+
+}
diff --git a/private/net/svcdlls/repl/common/expget.c b/private/net/svcdlls/repl/common/expget.c
new file mode 100644
index 000000000..c6a4bbaf9
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expget.c
@@ -0,0 +1,110 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpGet.c
+
+Abstract:
+
+ ExportDirGetApiRecord().
+
+Author:
+
+ John Rogers (JohnRo) 13-Nov-1992
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+ 13-Nov-1992 JohnRo
+ RAID 1537: Repl APIs in wrong role kill svc. (Extracted from DLL
+ stubs.)
+ 04-Jan-1993 JohnRo
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+
+// These must be included first:
+
+#include <windows.h>
+#include <lmcons.h> // NET_API_STATUS, etc.
+
+// These may be included in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototype, ExportDirIsApiRecordValid(), etc.
+#include <netdebug.h> // NetpAssert().
+
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ExportDirGetApiRecord (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr
+ )
+{
+ NET_API_STATUS ApiStatus;
+
+ LPVOID ApiRecord = NULL;
+ DWORD Integrity, Extent, LockCount;
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+ LPBYTE StringLocation; // Points just past top of data.
+
+ ApiStatus = NO_ERROR; // Innocent until proven guilty.
+
+ if (! ReplIsDirNameValid(DirName)) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ } else if ( !ExportDirIsLevelValid( Level, FALSE ) ) {
+ ApiStatus = ERROR_INVALID_LEVEL;
+ } else if (BufPtr == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ }
+
+ if (ApiStatus == NO_ERROR) {
+ // Read config data for a single export directory.
+ ApiStatus = ExportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & Integrity,
+ & Extent,
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+ }
+ if (ApiStatus == NO_ERROR) {
+
+ ApiStatus = ExportDirAllocApiRecords (
+ Level,
+ 1, // only 1 record.
+ (LPBYTE *) & ApiRecord, // alloc and set ptr
+ (LPBYTE *) & StringLocation ); // Points just past top of data.
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( ApiRecord != NULL );
+ ApiStatus = ExportDirBuildApiRecord (
+ Level,
+ DirName,
+ Integrity,
+ Extent,
+ LockCount,
+ TimeOfFirstLock, // Seconds since 1970.
+ ApiRecord,
+ (LPBYTE *) (LPVOID) & StringLocation);
+ NetpAssert( ApiStatus == NO_ERROR ); // We checked all parms.
+ }
+
+ }
+
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( ApiRecord != NULL );
+ NetpAssert( ExportDirIsApiRecordValid( Level, ApiRecord, NULL ) );
+ }
+ *BufPtr = ApiRecord; // will be NULL on error.
+
+ return ApiStatus;
+}
diff --git a/private/net/svcdlls/repl/common/explock.c b/private/net/svcdlls/repl/common/explock.c
new file mode 100644
index 000000000..e1abace61
--- /dev/null
+++ b/private/net/svcdlls/repl/common/explock.c
@@ -0,0 +1,162 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpLock.c
+
+Abstract:
+
+ Common registry lock/unlock routines for export dirs.
+
+Author:
+
+ John Rogers (JohnRo) 15-Mar-1992
+
+Environment:
+
+ User Mode - Win32
+
+Notes:
+
+ This file is extremely similar to ImpLock.c. If you fix any bugs here,
+ make sure they're reflected there, and vice versa.
+
+Revision History:
+
+ 15-Mar-1992 JohnRo
+ Created these routines.
+ 23-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ 29-Sep-1992 JohnRo
+ Also fix remote repl admin.
+ 13-Apr-1993 JohnRo
+ RAID 3107: locking directory over the net gives network path not found.
+ Made changes suggested by PC-LINT 5.0
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h>
+#include <lmcons.h> // NET_API_STATUS, etc.
+
+// These may be included in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototypes, etc.
+#include <lmrepl.h> // REPL_UNLOCK_FORCE equates.
+#include <netdebug.h> // NetpKdPrint(), etc.
+#include <repldefs.h> // IF_DEBUG().
+#include <winerror.h> // NO_ERROR, ERROR_ equates.
+
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RMGlobalListLock.
+NET_API_STATUS
+ExportDirLockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD Integrity, Extent, LockCount;
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+
+ IF_DEBUG(REPL) {
+ NetpKdPrint(( "ExportDirLockInRegistry( " FORMAT_LPTSTR
+ "): beginning...\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local") ));
+ }
+
+ if ( !ReplIsDirNameValid(DirName)) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // Read config data for a single export directory.
+ ApiStatus = ExportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & Integrity,
+ & Extent,
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+ if (ApiStatus == NO_ERROR) {
+
+ ApiStatus = ReplIncrLockFields(
+ & LockCount,
+ & TimeOfFirstLock );
+ }
+ if (ApiStatus == NO_ERROR) {
+ ApiStatus = ExportDirWriteConfigData (
+ UncServerName,
+ DirName,
+ Integrity,
+ Extent,
+ LockCount,
+ TimeOfFirstLock ); // Seconds since 1970.
+ }
+
+ return (ApiStatus);
+
+} // ExportDirLockInRegistry
+
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RMGlobalListLock.
+NET_API_STATUS
+ExportDirUnlockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD UnlockForce
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD Integrity, Extent, LockCount;
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+
+ IF_DEBUG(REPL) {
+ NetpKdPrint(( "ExportDirUnlockInRegistry( " FORMAT_LPTSTR
+ "): beginning...\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local") ));
+ }
+
+ if ( !ReplIsDirNameValid(DirName)) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplIsForceLevelValid( UnlockForce ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // Read config data for a single export directory.
+ ApiStatus = ExportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & Integrity,
+ & Extent,
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+
+ if (ApiStatus == NO_ERROR) {
+
+ ApiStatus = ReplDecrLockFields(
+ & LockCount,
+ & TimeOfFirstLock,
+ UnlockForce );
+ }
+ if (ApiStatus == NO_ERROR) {
+ ApiStatus = ExportDirWriteConfigData (
+ UncServerName,
+ DirName,
+ Integrity,
+ Extent,
+ LockCount,
+ TimeOfFirstLock ); // Seconds since 1970.
+ }
+
+ return (ApiStatus);
+
+} // ExportDirUnlockInRegistry
diff --git a/private/net/svcdlls/repl/common/expset.c b/private/net/svcdlls/repl/common/expset.c
new file mode 100644
index 000000000..9744f9c2c
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expset.c
@@ -0,0 +1,195 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpSet.c
+
+Abstract:
+
+ ExportDirSetInfo().
+
+Author:
+
+ John Rogers (JohnRo) 29-Sep-1992
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+ 29-Sep-1992 JohnRo
+ RAID 7962: Repl APIs in wrong role kill svc. (Extracted code from DLL
+ stubs.)
+ 30-Dec-1992 JohnRo
+ Corrected debug bit usage.
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windows.h>
+#include <lmcons.h> // NET_API_STATUS, etc.
+#include <repldefs.h> // IF_DEBUG().
+
+// These may be included in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototype, ExportDirIsApiRecordValid(), etc.
+#include <lmrepl.h> // LPREPL_EDIR_INFO_1, etc.
+#include <netdebug.h> // NetpKdPrint(), etc.
+#include <prefix.h> // PREFIX_ equates.
+
+
+NET_API_STATUS
+ExportDirConfigSetInfo (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ IN LPVOID Buffer,
+ OUT LPDWORD ParmError OPTIONAL
+ )
+{
+ NET_API_STATUS ApiStatus;
+
+ DWORD Integrity, Extent, LockCount;
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+
+ ApiStatus = NO_ERROR; // Innocent until proven guilty.
+
+ NetpSetParmError( PARM_ERROR_UNKNOWN ); // Assume error until proven...
+ if (! ReplIsDirNameValid(DirName)) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetReplExportDirSetInfo: Invalid dir name parm.\n" ));
+ }
+ }
+ if (Buffer == NULL) {
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetReplExportDirSetInfo: null buffer pointer.\n" ));
+ }
+
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // BUGBUG: ParmError is not set in many paths through here!
+
+ if (ApiStatus == NO_ERROR) {
+
+ // Read config data for a single export directory.
+ // We have to do this 'cos the set info struct (level 1) is
+ // a subset of the info we need to do a write.
+ ApiStatus = ExportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & Integrity,
+ & Extent,
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+ }
+
+ if (ApiStatus == NO_ERROR) {
+
+ if (Level == 1) {
+ LPREPL_EDIR_INFO_1 ApiRecord = Buffer;
+
+ if ( !ExportDirIsApiRecordValid(
+ Level, ApiRecord, ParmError ) ) {
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetReplExportDirSetInfo: Invalid level 1 record, "
+ "ParmError is " FORMAT_DWORD "\n",
+ (ParmError!=NULL)
+ ? (*ParmError)
+ : PARM_ERROR_UNKNOWN ));
+ }
+
+ ApiStatus = ERROR_INVALID_PARAMETER;
+
+ } else {
+
+ // BUGBUG: Match DirName and ApiRecord->rped1_dirname.
+
+ // Write config data for this export directory.
+ ApiStatus = ExportDirWriteConfigData (
+ UncServerName,
+ DirName, // new dir name (same)
+ ApiRecord->rped1_integrity, // new integrity
+ ApiRecord->rped1_extent, // new extent
+ LockCount, // old lock count
+ TimeOfFirstLock ); // old lock time
+ }
+
+ } else if ( (Level==1000) || (Level==1001) ) {
+
+ if (ApiStatus == NO_ERROR) {
+ if (Level==1000) {
+ LPREPL_EDIR_INFO_1000 ApiRecord = Buffer;
+ Integrity = ApiRecord->rped1000_integrity;
+
+ if ( !ReplIsIntegrityValid( Integrity ) ) {
+ NetpSetParmError( 1 ); // error in first field.
+ ApiStatus = ERROR_INVALID_PARAMETER;
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetReplExportDirSetInfo: "
+ "Bad integrity value.\n" ));
+ }
+
+ } else {
+ // Write the revised value below.
+
+ NetpSetParmError( PARM_ERROR_NONE );
+ }
+ } else {
+ LPREPL_EDIR_INFO_1001 ApiRecord = Buffer;
+ NetpAssert( Level == 1001 );
+ Extent = ApiRecord->rped1001_extent;
+
+ if ( !ReplIsExtentValid( Extent ) ) {
+ NetpSetParmError( 1 ); // error in first field.
+ ApiStatus = ERROR_INVALID_PARAMETER;
+
+ IF_DEBUG( EXPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetReplExportDirSetInfo: "
+ "Bad extent value.\n" ));
+ }
+
+ } else {
+ // Write the revised value below.
+ NetpSetParmError( PARM_ERROR_NONE );
+ ApiStatus = NO_ERROR;
+ }
+ }
+
+ if (ApiStatus == NO_ERROR) {
+ // Write config data for this export directory.
+ ApiStatus = ExportDirWriteConfigData (
+ UncServerName,
+ DirName,
+ Integrity,
+ Extent,
+ LockCount,
+ TimeOfFirstLock );
+ NetpSetParmError( PARM_ERROR_NONE );
+ }
+ }
+ } else {
+ ApiStatus = ERROR_INVALID_LEVEL;
+ }
+ }
+
+ return ApiStatus;
+}
diff --git a/private/net/svcdlls/repl/common/expvalid.c b/private/net/svcdlls/repl/common/expvalid.c
new file mode 100644
index 000000000..0fe5c5bf4
--- /dev/null
+++ b/private/net/svcdlls/repl/common/expvalid.c
@@ -0,0 +1,177 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ExpValid.c
+
+Abstract:
+
+ This file contains ExportDirIsApiRecordValid().
+
+Author:
+
+ John Rogers (JohnRo) 22-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ This code assumes that the info levels are subsets of each other.
+
+Revision History:
+
+ 22-Jan-1992 JohnRo
+ Created ExportDirIsApiRecordValid() from code in NetrReplExportDirAdd().
+ 28-Jan-1992 JohnRo
+ Oops, this code accidently said level 1 was invalid.
+ 30-Jan-1992 JohnRo
+ Made changes suggested by PC-LINT.
+ 18-Feb-1992 JohnRo
+ Handle level 2 as well.
+ 27-Feb-1992 JohnRo
+ Really allow level 2.
+ Check lock fields for validity.
+ 15-Mar-1992 JohnRo
+ Improve setinfo info level support.
+ 23-Mar-1993 JohnRo
+ Added debug output.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS, PARM equates, etc.
+#include <repldefs.h> // ReplIsIntegrityValid(), etc.
+
+// These can be in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototype.
+#include <lmrepl.h> // LPREPL_EDIR_INFO_1, REPL_EXTENT_ stuff, etc.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint().
+#include <netlib.h> // NetpSetParmError().
+#include <prefix.h> // PREFIX_ equates.
+
+#define INDICATE_ERROR( text ) \
+ { \
+ NetpKdPrint(( PREFIX_REPL \
+ "ExportDirIsApiRecordValid: " text ".\n" )); \
+ /* NetpDbgHexDump( Buf, REASONABLE_DUMP_SIZE ); */ \
+ }
+
+
+BOOL
+ExportDirIsApiRecordValid (
+ IN DWORD Level,
+ IN LPVOID Buf,
+ OUT LPDWORD ParmError OPTIONAL
+ )
+
+{
+
+ //
+ // First, make sure level is valid and there's actually a struct there.
+ //
+ NetpSetParmError( PARM_ERROR_UNKNOWN ); // Assume error until proven...
+ if ( !ExportDirIsLevelValid( Level, TRUE) ) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirIsApiRecordValid: bad info level.\n" ));
+
+ return (FALSE); // No, it's not valid.
+ }
+ if (Buf == NULL) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirIsApiRecordValid: null buf ptr.\n" ));
+
+ return (FALSE); // No, it's not valid.
+ }
+
+ if (Level < PARMNUM_BASE_INFOLEVEL) {
+ LPREPL_EDIR_INFO_2 ApiRecord; // Superset info level.
+ ApiRecord = Buf;
+
+ //
+ // Check item(s) common to all levels.
+ //
+ if ( !ReplIsDirNameValid(ApiRecord->rped2_dirname) ) {
+ NetpSetParmError( 1 ); // Error in first field in ApiRecord.
+
+ INDICATE_ERROR(
+ "ExportDirIsApiRecordValid: bad dir name.\n" );
+
+ return (FALSE); // No, it's not valid.
+ }
+
+ //
+ // Check items unique to level 1 and 2.
+ //
+ if (Level > 0) {
+ if ( !ReplIsIntegrityValid(ApiRecord->rped2_integrity) ) {
+ NetpSetParmError( 2 ); // Error in second field in ApiRecord.
+
+ INDICATE_ERROR( "bad integrity (struct)" );
+
+ return (FALSE); // No, it's not valid.
+ }
+ if ( !ReplIsExtentValid(ApiRecord->rped2_extent) ) {
+ NetpSetParmError( 3 ); // Error in third field in ApiRecord.
+
+ INDICATE_ERROR( "bad extent (struct)" );
+
+ return (FALSE); // No, it's not valid.
+ }
+
+ if (Level >= 2) {
+ if ( !ReplAreLockFieldsValid( ApiRecord->rped2_lockcount,
+ ApiRecord->rped2_locktime ) ) {
+ NetpSetParmError( 4 ); // Err in fourth and/or fifth field.
+
+ INDICATE_ERROR( "bad lock fields" );
+
+ return (FALSE); // No, it's not valid.
+ }
+ }
+ }
+
+ } else if (Level == REPL_EXPORT_INTEGRITY_INFOLEVEL) {
+
+ DWORD NewIntegrity = * (LPDWORD) (LPVOID) Buf;
+
+ if ( !ReplIsIntegrityValid( NewIntegrity ) ) {
+ NetpSetParmError( 1 ); // Error in first field in ApiRecord.
+
+ INDICATE_ERROR( "bad integrity (field)" );
+
+ return (FALSE); // No, it's not valid.
+ }
+
+ } else {
+
+ DWORD NewExtent = * (LPDWORD) (LPVOID) Buf;
+ NetpAssert( Level == REPL_EXPORT_EXTENT_INFOLEVEL );
+ if ( !ReplIsExtentValid( NewExtent ) ) {
+ NetpSetParmError( 1 ); // Error in first field in ApiRecord.
+
+ INDICATE_ERROR( "bad extent (field)" );
+
+ return (FALSE); // No, it's not valid.
+ }
+
+ }
+
+ //
+ // Everything went OK. Tell caller.
+ //
+ NetpSetParmError( PARM_ERROR_NONE );
+ return (TRUE); // Yes, it's valid.
+
+}
diff --git a/private/net/svcdlls/repl/common/fixlocks.c b/private/net/svcdlls/repl/common/fixlocks.c
new file mode 100644
index 000000000..6cb44c389
--- /dev/null
+++ b/private/net/svcdlls/repl/common/fixlocks.c
@@ -0,0 +1,194 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ FixLocks.c
+
+Abstract:
+
+ This routine (ExportDirFixUserLockFiles) makes sure that the local
+ disk's UserLock.* file(s) are in agreement with the lock count from
+ the registry. The file(s) are deleted and/or created as necessary.
+
+ This is callable even if the replicator service is not started.
+
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft) 14-Jan-1993
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 14-Jan-1993 JohnRo
+ Created for RAID 7053: locked trees added to pulse msg. (Actually
+ fix all kinds of remote lock handling.)
+ 26-Apr-1993 JohnRo
+ RAID 7313: repl needs change permission to work on NTFS, or we need
+ to delete files differently.
+
+--*/
+
+
+// These must be included first:
+
+#include <windows.h> // IN, GetLastError(), LPCTSTR, OPTIONAL, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <expdir.h> // My prototype.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), FORMAT_ equates, etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // SLASH, ReplCheckAbsPathSyntax(), etc.
+#include <tstr.h> // STRCAT(), STRCPY(), STRLEN().
+#include <winerror.h> // ERROR_, NO_ERROR equates.
+
+
+NET_API_STATUS
+ExportDirFixUserLockFiles(
+ IN LPCTSTR ExportPath, // Must include drive letter.
+ IN LPCTSTR DirName,
+ IN DWORD LockCount
+ )
+{
+ NET_API_STATUS ApiStatus;
+ HANDLE FileHandle = NULL;
+ TCHAR LockFileName[MAX_PATH+1];
+ BOOL NtUserLockExists;
+
+ //
+ // Check for caller errors.
+ //
+ if ( !ReplIsDirNameValid( (LPTSTR) DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+ ApiStatus = ReplCheckAbsPathSyntax( (LPTSTR) ExportPath );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ }
+
+ //
+ // Build NT version of lock file name.
+ //
+ (VOID) STRCPY( LockFileName, ExportPath );
+ (VOID) STRCAT( LockFileName, SLASH );
+ (VOID) STRCAT( LockFileName, DirName );
+ (VOID) STRCAT( LockFileName, SLASH );
+ (VOID) STRCAT( LockFileName, USERLOCK_NT );
+
+ NetpAssert( STRLEN( LockFileName ) <= MAX_PATH );
+
+ //
+ // See if the NT version of the user lock file exists.
+ //
+ NtUserLockExists = ReplFileOrDirExists( LockFileName );
+
+ if ( NtUserLockExists && (LockCount==0) ) {
+
+ //
+ // Delete extraneous NT lock file.
+ //
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirFixUserLockFiles: "
+ "deleting extraneous user lock file '" FORMAT_LPTSTR "'...\n",
+ LockFileName ));
+ ApiStatus = ReplDeleteFile( LockFileName );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ }
+
+ } else if ( (!NtUserLockExists) && (LockCount>0) ) {
+
+ //
+ // Create a lock file if we can. (The directory might not exist yet,
+ // so we might not be able to do this. No problem.)
+ //
+ FileHandle = CreateFile(
+ (LPCTSTR) LockFileName, // name of file to create.
+ GENERIC_WRITE, // desired access.
+ FILE_SHARE_WRITE, // share mode: we don't care.
+ NULL, // default security attr.
+ CREATE_ALWAYS, // create disposition.
+ FILE_FLAG_WRITE_THROUGH, // flags&attr: don't cache writes.
+ NULL ); // no template file.
+ if (FileHandle == INVALID_HANDLE_VALUE) {
+ ApiStatus = (NET_API_STATUS) GetLastError();
+ NetpAssert( ApiStatus != NO_ERROR );
+
+ if (ApiStatus == ERROR_PATH_NOT_FOUND) {
+ // First-level dir doesn't exist yet. That's OK, as pulser
+ // will correct for this when it gets created.
+ ApiStatus = NO_ERROR;
+ } else if (ApiStatus == ERROR_WRITE_PROTECT) {
+ // Perhaps just CD-ROM? OK, as registry lock count is correct,
+ // and ReplCheckExportLocks() checks registry before file
+ // system.
+
+ ReplErrorLog(
+ NULL, // no server name (log locally)
+ NELOG_ReplAccessDenied, // log code
+ ApiStatus,
+ NULL, // optional str1
+ NULL); // optional str2
+
+ // Don't prevent repl from exporting CD-ROM.
+ ApiStatus = NO_ERROR;
+ } else if (ApiStatus == ERROR_ACCESS_DENIED) {
+
+ // Log in case service is running in wrong account, or
+ // an ACL is wrong somewhere.
+ ReplErrorLog(
+ NULL, // no server name (log locally)
+ NELOG_ReplAccessDenied, // log code
+ ApiStatus,
+ NULL, // optional str1
+ NULL); // optional str2
+
+ // Don't prevent repl from exporting CD-ROM.
+ ApiStatus = NO_ERROR;
+ }
+ goto Cleanup; // go log error.
+ }
+ // Fall through to close the file in cleanup code.
+ }
+
+ ApiStatus = NO_ERROR;
+
+Cleanup:
+
+ if (FileHandle != NULL) {
+ (VOID) CloseHandle( FileHandle );
+ }
+
+ if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ExportDirFixUserLockFiles: ERROR " FORMAT_API_STATUS ".\n",
+ ApiStatus ));
+
+ //
+ // Log the error.
+ // BUGBUG: extract master server name and log there too.
+ //
+ ReplErrorLog(
+ NULL, // no server name (log locally)
+ NELOG_ReplSysErr, // log code
+ ApiStatus,
+ NULL, // optional str1
+ NULL); // optional str2
+ }
+ return (ApiStatus);
+
+}
diff --git a/private/net/svcdlls/repl/common/fsresolu.c b/private/net/svcdlls/repl/common/fsresolu.c
new file mode 100644
index 000000000..092bf946f
--- /dev/null
+++ b/private/net/svcdlls/repl/common/fsresolu.c
@@ -0,0 +1,220 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ FsResolu.c
+
+Abstract:
+
+ Module only contains ReplGetFsTimeResolutionSecs().
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft)
+
+Environment:
+
+ User mode only.
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 17-Dec-1992 JohnRo
+ Created for RAID 1513: Repl does not maintain ACLs. (Also fix
+ HPFS->FAT timestamp.)
+ 26-Feb-1993 JohnRo
+ RAID 13126: Fix repl memory leak.
+
+--*/
+
+// These must be included first:
+
+#include <nt.h> // NtOpenFile(), ULONG, etc.
+#include <ntrtl.h> // PLARGE_INTEGER, TIME_FIELDS, etc.
+#include <nturtl.h> // Needed for ntrtl.h and windows.h to co-exist.
+
+#include <windows.h> // GetLastError(), etc.
+#include <lmcons.h>
+
+// These may be included in any order:
+
+#include <netdebug.h> // DBGSTATIC, NetpKdPrint(), FORMAT_ equates, etc.
+#include <netlib.h> // NetpMemoryAllocate(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // My prototype, UNKNOWN_FS_RESOLUTION, etc.
+#include <tstring.h> // NetpNCopyWStrToTStr().
+#include <winerror.h> // NO_ERROR.
+
+
+DWORD
+ReplGetFsTimeResolutionSecs(
+ IN LPCTSTR AbsPath
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD ResolutionSecs = UNKNOWN_FS_RESOLUTION;
+ HANDLE FileHandle = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
+ NTSTATUS NtStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ const ULONG OpenOptions =
+ FILE_SYNCHRONOUS_IO_NONALERT
+#if 0
+ | ( IsDirectory ? FILE_DIRECTORY_FILE : 0 )
+#endif
+ ;
+
+ TCHAR FsName[MAXIMUM_FILENAME_LENGTH+1];
+ DWORD FsNameLen; // char count in FsName, w/o nul char.
+ BOOL PathAllocated = FALSE;
+ UNICODE_STRING UnicodePath;
+ PFILE_FS_ATTRIBUTE_INFORMATION VolumeInfo = NULL;
+ ULONG VolumeInfoSize;
+
+ NetpAssert( AbsPath != NULL );
+ ApiStatus = ReplCheckAbsPathSyntax( (LPTSTR) AbsPath );
+ NetpAssert( ApiStatus == NO_ERROR );
+
+ RtlInitUnicodeString(
+ & UnicodePath, // output: struct
+ AbsPath ); // input: null terminated
+
+ if( !RtlDosPathNameToNtPathName_U(
+ AbsPath,
+ &UnicodePath,
+ NULL,
+ NULL) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplGetFsTimeResolutionSecs: RtlDosPathNameToNtPathname_U"
+ " of source '" FORMAT_LPTSTR "' failed.\n", AbsPath ));
+
+ // BUGBUG: log error
+ goto Cleanup;
+ }
+ PathAllocated = TRUE;
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ (LPVOID) &UnicodePath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+ NtStatus = NtOpenFile(
+ & FileHandle,
+ SYNCHRONIZE | // desired ...
+ FILE_READ_ATTRIBUTES, // ... access
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ, // share access
+ OpenOptions );
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplGetFsTimeResolutionSecs: NtOpenFile of source '"
+ FORMAT_LPTSTR "' gave NT status " FORMAT_NTSTATUS ".\n",
+ AbsPath, NtStatus ));
+
+ // BUGBUG: log error
+ goto Cleanup;
+ }
+
+ //
+ // Alloc space for volume fs attr info (including various strings
+ // after the structure).
+ //
+ VolumeInfoSize =
+ sizeof(FILE_FS_ATTRIBUTE_INFORMATION)
+ + ( (MAXIMUM_FILENAME_LENGTH+1) * sizeof(WCHAR) );
+ VolumeInfo = NetpMemoryAllocate( VolumeInfoSize );
+ if (VolumeInfo == NULL) {
+ // BUGBUG: log the error!
+ goto Cleanup;
+ }
+
+ NtStatus = NtQueryVolumeInformationFile(
+ FileHandle,
+ &IoStatusBlock,
+ (PVOID) VolumeInfo,
+ VolumeInfoSize,
+ FileFsAttributeInformation ); // FS info class
+
+ if ( !NT_SUCCESS( NtStatus ) ) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ReplGetFsTimeResolutionSecs: NtQueryVolumeInformationFile "
+ "FAILED, NT status is " FORMAT_NTSTATUS ".\n",
+ NtStatus ));
+
+ // BUGBUG: log error
+ goto Cleanup;
+ }
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetFsTimeResolutionSecs: got volume info, "
+ "name len is " FORMAT_DWORD ", name[0] is " FORMAT_WCHAR ".\n",
+ (DWORD) (VolumeInfo->FileSystemNameLength),
+ VolumeInfo->FileSystemName[0] ));
+ }
+ NetpAssert( ((VolumeInfo->FileSystemNameLength) % sizeof(WCHAR)) == 0 );
+
+ FsNameLen = (VolumeInfo->FileSystemNameLength) / sizeof(WCHAR);
+ // len w/o nul
+
+ ApiStatus = NetpNCopyWStrToTStr(
+ FsName, // dest
+ VolumeInfo->FileSystemName, // src
+ FsNameLen); // chars
+ NetpAssert( ApiStatus == NO_ERROR );
+ FsName[ FsNameLen ] = L'\0';
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetFsTimeResolutionSecs: got fs name '" FORMAT_LPTSTR
+ "'.\n", FsName ));
+ }
+
+ //
+ // Compute ResolutionSecs using known file system names.
+ //
+ if (STRICMP( FsName, (LPTSTR) TEXT("FAT") ) == 0) {
+ ResolutionSecs = 2;
+ goto Cleanup;
+ }
+ if (STRICMP( FsName, (LPTSTR) TEXT("HPFS") ) == 0) {
+ ResolutionSecs = 1;
+ goto Cleanup;
+ }
+ if (STRICMP( FsName, (LPTSTR) TEXT("NTFS") ) == 0) {
+ ResolutionSecs = 1;
+ goto Cleanup;
+ }
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplGetFsTimeResolutionSecs: UNKNOWN fs name of '"
+ "'.\n", FsName ));
+ // BUGBUG: log this error!
+ ResolutionSecs = UNKNOWN_FS_RESOLUTION;
+
+Cleanup:
+
+ if (FileHandle != NULL) {
+ (VOID) NtClose( FileHandle );
+ }
+
+ if (VolumeInfo != NULL) {
+ NetpMemoryFree( VolumeInfo );
+ }
+
+ if (PathAllocated) {
+ (VOID) RtlFreeHeap( RtlProcessHeap(), 0, UnicodePath.Buffer );
+ }
+
+ return (ResolutionSecs);
+}
diff --git a/private/net/svcdlls/repl/common/ignorenm.c b/private/net/svcdlls/repl/common/ignorenm.c
new file mode 100644
index 000000000..335655e7d
--- /dev/null
+++ b/private/net/svcdlls/repl/common/ignorenm.c
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ IgnoreNm.c
+
+Abstract:
+
+ This file contains ReplIgnoreDirOrFileName().
+
+Author:
+
+ John Rogers (JohnRo) 25-Feb-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 25-Feb-1992 JohnRo
+ Created this routine.
+ 19-Aug-1992 JohnRo
+ RAID 3603: import tree (TMPREE.RP$) generated at startup.
+ 08-Dec-1992 JohnRo
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // MAX_PATH, etc.
+#include <lmcons.h> // LAN Manager common definitions
+
+// These can be in any order:
+
+#include <client.h> // RP, TMP_TREE, etc.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <netdebug.h> // NetpAssert().
+#include <repldefs.h> // My prototype, DOT, DOT_DOT.
+#include <tstr.h> // TCHAR_ equates, STRLEN(), etc.
+#include <winerror.h> // ERROR_, NO_ERROR equates.
+
+
+
+
+BOOL
+ReplIgnoreDirOrFileName (
+ IN LPTSTR Name
+ )
+{
+ INT len;
+
+ NetpAssert( Name != NULL );
+ NetpAssert( (*Name) != TCHAR_EOS );
+ NetpAssert( ReplIsDirNameValid( Name ) ); // Not abs path, UNC, "c:x".
+
+ //
+ // Definitely ignore "." and "..".
+ //
+ if ( (STRCMP(Name, DOT)==0) || (STRCMP(Name, DOT_DOT)==0) ) {
+ return (TRUE); // yes, ignore this one.
+ }
+
+ //
+ // Ignore "*.RP$". This also gets TMPTREE.RP$, TMPTREEX.RP$.
+ //
+ len = ((INT) STRLEN( Name )) - ((INT)STRLEN( RP ));
+
+ if ( (len > 0) && (STRICMP(&Name[len], RP) == 0) ) {
+ return (TRUE); // yes, ignore this one.
+ }
+ NetpAssert( STRICMP(Name, TMP_TREE) != 0 );
+ NetpAssert( STRICMP(Name, TMP_TREEX) != 0 );
+
+ //
+ // Ignore "REPL.INI".
+ //
+ if (STRICMP(Name, REPL_INI) == 0) {
+ return (TRUE); // yes, ignore this one.
+ }
+
+ //
+ // Ignore "USERLOCK.*".
+ //
+ if (STRNICMP(Name, ULOCK_PREFIX, STRLEN(ULOCK_PREFIX)) == 0) {
+ return (TRUE); // yes, ignore this one.
+ }
+
+ //
+ // None of the above.
+ //
+ return (FALSE); // No, don't ignore this one.
+
+} // ReplIgnoreDirOrFileName
diff --git a/private/net/svcdlls/repl/common/impalloc.c b/private/net/svcdlls/repl/common/impalloc.c
new file mode 100644
index 000000000..e60e6cbce
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impalloc.c
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ImpAlloc.c
+
+Abstract:
+
+ This file contains ImportDirAllocApiRecords().
+
+Author:
+
+ John Rogers (JohnRo) 19-Feb-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 19-Feb-1992 JohnRo
+ Created this routine by cloning ExportDirAllocApiRecords().
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS, PARM equates, etc.
+#include <rap.h> // Needed by <strucinf.h>.
+
+// These can be in any order:
+
+#include <impdir.h> // My prototype.
+#include <lmapibuf.h> // NetApiBufferAllocate().
+#include <netdebug.h> // NetpAssert().
+#include <netlib.h> // NetpPointerPlusSomeBytes().
+#include <strucinf.h> // Netp{various}StructureInfo().
+#include <winerror.h> // ERROR_* defines; NO_ERROR.
+
+
+NET_API_STATUS
+ImportDirAllocApiRecords (
+ IN DWORD Level,
+ IN DWORD EntryCount,
+ OUT LPBYTE * BufPtr,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ )
+
+{
+ LPBYTE FirstRecord = NULL;
+ NET_API_STATUS ApiStatus;
+ DWORD EntrySize;
+
+ //
+ // Check for caller errors.
+ //
+ if (BufPtr == NULL) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ * BufPtr = NULL; // Don't confuse caller about possible alloc'ed data.
+
+ if (EntryCount == 0) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ //
+ // Compute size of an entry (and check caller's Level too).
+ //
+ ApiStatus = NetpReplImportDirStructureInfo (
+ Level,
+ PARMNUM_ALL,
+ TRUE, // want native sizes
+ NULL, // don't need DataDesc16
+ NULL, // don't need DataDesc32
+ NULL, // don't need DataDescSmb
+ & EntrySize, // need max size of structure
+ NULL, // don't need FixedSize
+ NULL); // don't need StringSize
+ if (ApiStatus != NO_ERROR) {
+ return (ApiStatus);
+ }
+ NetpAssert( EntrySize > 0 );
+
+ //
+ // Allocate the output area.
+ //
+ ApiStatus = NetApiBufferAllocate(
+ EntrySize * EntryCount,
+ (LPVOID *) & FirstRecord);
+ if (ApiStatus != NO_ERROR) {
+
+ // ApiStatus is already set to return error to caller.
+
+ } else {
+ NetpAssert( FirstRecord != NULL );
+
+ //
+ // Tell caller where top of string area is.
+ //
+ * StringLocation = NetpPointerPlusSomeBytes(
+ FirstRecord,
+ EntrySize * EntryCount );
+
+ }
+
+ //
+ // Tell caller how everything went.
+ //
+ * BufPtr = FirstRecord;
+ return (ApiStatus);
+
+}
diff --git a/private/net/svcdlls/repl/common/impbuild.c b/private/net/svcdlls/repl/common/impbuild.c
new file mode 100644
index 000000000..8043fd8fc
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impbuild.c
@@ -0,0 +1,203 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpBuild.c
+
+Abstract:
+
+ This file contains ImportDirBuildApiRecord. This is used by
+ NetrReplImportDirGetInfo and NetrReplImportDirEnum.
+
+Author:
+
+ John Rogers (JohnRo) 08-Jan-1992
+
+Environment:
+
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ This code assumes that the import dir info levels are subsets of each other.
+
+Revision History:
+
+ 08-Jan-1992 JohnRo
+ Created.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 27-Jan-1992 JohnRo
+ Changed interface to allow use when service is not running.
+ 21-Feb-1992 JohnRo
+ Fixed bug checking state parameter.
+ UncMaster parm is optional.
+ Added check of UncMaster validity.
+ Undid redundant checks of Buffer (3 of them!)
+ 21-Feb-1992 JohnRo
+ Changed ImportDirBuildApiRecord() so master name is not a UNC name.
+ 22-Feb-1992 JohnRo
+ Made changes suggested by PC-LINT.
+ 26-Feb-1992 JohnRo
+ Check lock fields for validity.
+ API records now contain timestamps instead of elapsed times.
+ Added assertion of valid record at end.
+ 25-Mar-1992 JohnRo
+ Avoid obsolete state values.
+ 27-Mar-1992 JohnRo
+ Allow MasterName to point to a null char.
+ 28-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ Added debug output of structure after we build it.
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS.
+#include <repldefs.h> // ReplIsIntegrityValid(), IF_DEBUG(), SLASH_SLASH, etc.
+
+// These can be in any order:
+
+#include <align.h> // POINTER_IS_ALIGNED(), ALIGN_TCHAR.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototype, ImportDirIsLevelValid().
+#include <lmrepl.h> // LPREPL_IDIR_INFO_1, REPL_EXTENT_ stuff, etc.
+#include <names.h> // NetpIsComputerNameValid().
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <tstr.h> // STRLEN(), TCHAR_EOS, etc.
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+NET_API_STATUS
+ImportDirBuildApiRecord (
+ IN DWORD Level,
+ IN LPTSTR DirName,
+ IN DWORD State,
+ IN LPTSTR MasterName OPTIONAL, // computer name (not UNC).
+ IN DWORD TimeOfLastUpdate, // Seconds since 1970.
+ IN DWORD LockCount,
+ IN DWORD TimeOfFirstLock, // Seconds since 1970.
+ OUT LPVOID Buffer,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ )
+
+{
+ LPREPL_IDIR_INFO_1 ApiRecord = Buffer; // superset info level
+ LPTSTR StringDest;
+ DWORD StringLength;
+
+ NetpAssert( StringLocation != NULL);
+ NetpAssert( *StringLocation != NULL);
+
+ IF_DEBUG( IMPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirBuildApiRecord: building record at " FORMAT_LPVOID
+ ", *str loc is " FORMAT_LPVOID ".\n",
+ (LPVOID) Buffer, (LPVOID) *StringLocation ));
+ }
+
+ if ( (MasterName != NULL) && ((*MasterName) == TCHAR_EOS) ) {
+ MasterName = NULL;
+ }
+
+ //
+ // Check for caller errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ return (ERROR_INVALID_DATA);
+ } else if (Buffer == NULL) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplIsStateValid( State ) ) {
+ return (ERROR_INVALID_DATA);
+ } else if ( !ImportDirIsLevelValid( Level ) ) {
+ return (ERROR_INVALID_LEVEL);
+ } else if ((MasterName!=NULL) && !NetpIsComputerNameValid(MasterName)) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplAreLockFieldsValid( LockCount, TimeOfFirstLock ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ //
+ // First do subset common to both info levels.
+ //
+ StringLength = (DWORD) STRLEN( DirName );
+
+ NetpAssert( POINTER_IS_ALIGNED( *StringLocation, ALIGN_TCHAR ) );
+ StringDest = (LPTSTR) (LPVOID) (*StringLocation);
+ StringDest -= (StringLength + 1);
+
+ *StringLocation = (LPBYTE) (LPVOID) StringDest;
+
+ ApiRecord->rpid1_dirname = StringDest;
+
+ (void) STRCPY(
+ StringDest, // dest
+ DirName); // src
+
+ //
+ // Next do stuff only found in level 1.
+ //
+ if (Level > 0) {
+
+ //
+ // Do master name (only other string)...
+ //
+ if (MasterName != NULL) {
+ StringLength = (DWORD) STRLEN( MasterName ) + 2; // Ch to UNC.
+
+ NetpAssert( POINTER_IS_ALIGNED( *StringLocation, ALIGN_TCHAR ) );
+ StringDest = (LPTSTR) (LPVOID) (*StringLocation);
+ StringDest -= (StringLength + 1);
+
+ *StringLocation = (LPBYTE) (LPVOID) StringDest;
+
+ ApiRecord->rpid1_mastername = StringDest;
+
+ (void) STRCPY(
+ StringDest, // dest
+ SLASH_SLASH ); // src
+ (void) STRCAT(
+ StringDest, // dest
+ MasterName); // src
+ } else {
+ ApiRecord->rpid1_mastername = NULL;
+ }
+
+ //
+ // Now do simple stuff...
+ //
+ {
+ ApiRecord->rpid1_state = State;
+ }
+
+ ApiRecord->rpid1_last_update_time = TimeOfLastUpdate;
+
+ ApiRecord->rpid1_lockcount = LockCount;
+
+ if (TimeOfFirstLock == 0) {
+ ApiRecord->rpid1_locktime = 0;
+ } else {
+ ApiRecord->rpid1_locktime = TimeOfFirstLock;
+ }
+ }
+
+ IF_DEBUG( IMPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirBuildApiRecord: built structure:\n" ));
+ NetpDbgDisplayReplImportDir( Level, Buffer );
+ }
+
+ NetpAssert( ImportDirIsApiRecordValid( Level, ApiRecord, NULL ) );
+
+ return (NO_ERROR);
+
+}
diff --git a/private/net/svcdlls/repl/common/impconf.c b/private/net/svcdlls/repl/common/impconf.c
new file mode 100644
index 000000000..127812f2a
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impconf.c
@@ -0,0 +1,720 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpConf.c
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator import directory worker routines.
+
+Author:
+
+ John Rogers (JohnRo) 09-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 09-Jan-1992 JohnRo
+ Created.
+ 23-Jan-1992 JohnRo
+ Clarify units for time parameters.
+ 27-Jan-1992 JohnRo
+ ImportDirReadConfigData() should return NERR_UnknownDevDir.
+ Changed to use LPTSTR etc.
+ 10-Feb-1992 JohnRo
+ ImportDirReadConfigData() should handle section not found.
+ 13-Feb-1992 JohnRo
+ Moved section name equates to ConfName.h.
+ 21-Feb-1992 JohnRo
+ Fixed bugs handling UNC master.
+ Added support for REPL_STATE_NOT_STARTED.
+ Added ImportDirDeleteConfigData() and ImportDirConfigDataExists().
+ 27-Feb-1992 JohnRo
+ Changed state not started to state never replicated.
+ 25-Mar-1992 JohnRo
+ Avoid obsolete state values.
+ Get rid of old config helpers.
+ 26-Mar-1992 JohnRo
+ Fixed bug parsing UncMaster.
+ 10-Jul-1992 JohnRo
+ RAID 10503: srv mgr: repl dialog doesn't come up.
+ Use PREFIX_ equates.
+ 23-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ 29-Sep-1992 JohnRo
+ Fix remote repl admin.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 21-Jan-1993 JohnRo
+ RAID 7717: Repl assert if not logged on correctly. (Also do event
+ logging for real.)
+ Made changes suggested by PC-LINT 5.0
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // Win32 type definitions
+#include <lmcons.h> // LAN Manager common definitions
+
+// These may be included in any order:
+
+#include <config.h> // NetpConfig helpers.
+#include <confname.h> // SECT_NT_ equates.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototypes.
+#include <lmapibuf.h> // NetApiBufferFree().
+#include <lmerr.h> // NO_ERROR, ERROR_, and NERR_ equates.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <lmrepl.h> // REPL_STATE_ equates.
+#include <names.h> // NetpIsUncComputerNameValid().
+#include <netdebug.h> // NetpAssert(), etc.
+#include <netlib.h> // NetpPointerPlusSomeBytes().
+#include <prefix.h> // PREFIX_ equates.
+#include <replconf.h> // ReplConfigReportBadParmValue().
+#include <repldefs.h> // IF_DEBUG(), DWORDLEN, ReplErrorLog().
+#include <tstr.h> // STRCPY(), ATOL().
+
+
+#define IMPORT_VALUE_ARRAY_LEN \
+ (STATE_LEN /* state */ \
+ + 1 /* , */ \
+ + UNCLEN /* master */ \
+ + 1 /* , */ \
+ + DWORDLEN /* last_update_time (seconds since 1970) */ \
+ + 1 /* , */ \
+ + DWORDLEN /* lockcount */ \
+ + 1 /* , */ \
+ + DWORDLEN ) /* locktime (seconds since 1970) */
+
+#define OPTIONAL_LPTSTR( tstr ) \
+ ( (tstr) ? (tstr) : (LPTSTR) TEXT("<noname>") )
+
+
+// Tells whether or not config data for this directory exists.
+// Callable even if the replicator service is not started.
+BOOL
+ImportDirConfigDataExists (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle;
+ LPTSTR Value;
+
+ //
+ // Check for caller's errors.
+ //
+ NetpAssert( ReplIsDirNameValid( DirName ) );
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS, // area (instead of parameters)
+ TRUE); // read-only
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+
+ return (FALSE); // section doesn't exist, so dir data doesn't.
+ }
+
+ //
+ // Read the value from the config file/whatever.
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ & Value); // alloc and set ptr
+
+ //
+ // We're done with this, so close the config data and toss the buffer we
+ // got. But remember the status from NetpGetConfigValue!
+ //
+ if (Value != NULL) {
+ (void) NetApiBufferFree( Value );
+ }
+ (void) NetpCloseConfigData( Handle );
+
+ //
+ // Now check the status of the Get.
+ //
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ return (FALSE); // doesn't exist
+ } else if (ApiStatus == NO_ERROR) {
+ return (TRUE); // exists
+ } else {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+
+ return (FALSE); // Say it doesn't exist, since we don't know.
+ }
+
+ /*NOTREACHED*/
+
+} // ImportDirConfigDataExists
+
+
+// Delete config data for this directory.
+// Returns NERR_UnknownDevDir if config data doesn't exist for this dir.
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ImportDirDeleteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // Log error below.
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS, // area (instead of parameters)
+ FALSE ); // not read-only
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // Log error below.
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Log error below.
+ }
+
+ //
+ // Delete this keyword from this section.
+ //
+ ApiStatus = NetpDeleteConfigKeyword(
+ Handle,
+ DirName ); // keyword is dir name
+
+ IF_DEBUG(EXPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirDeleteConfigData: conf del ret " FORMAT_API_STATUS
+ ".\n", ApiStatus ));
+ }
+
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // Log error below.
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Log error below.
+ }
+
+ //
+ // All done.
+ //
+Cleanup:
+
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (ApiStatus != NO_ERROR) {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+
+ return (ApiStatus);
+
+} // ImportDirDeleteConfigData
+
+
+// Parse config data for a single import directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ImportDirParseConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR ValueString,
+ OUT LPDWORD StatePtr,
+ OUT LPTSTR UncMasterPtr,
+ OUT LPDWORD LastUpdateTimePtr, // Seconds since 1970.
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ )
+{
+ LPTSTR CurrentValuePtr = ValueString;
+
+ //
+ // Check for caller's errors.
+ //
+ NetpAssert( ValueString != NULL);
+ if (STRLEN( ValueString ) > IMPORT_VALUE_ARRAY_LEN) {
+ goto ReportBadConfigLine;
+ }
+
+ //
+ // Start parsing the value, which begins with a string containing the
+ // state.
+ //
+
+#define TRY_STATE( StateEquate, StateString ) \
+ { \
+ DWORD HopefulStringLength = STRLEN(StateString); \
+ if (STRNCMP( CurrentValuePtr, (StateString), HopefulStringLength) == 0) { \
+ *StatePtr = (StateEquate); \
+ CurrentValuePtr = (LPTSTR) (LPVOID) \
+ NetpPointerPlusSomeBytes( CurrentValuePtr, \
+ HopefulStringLength * sizeof(TCHAR) ); \
+ goto DoneState; \
+ } \
+ }
+
+ TRY_STATE( REPL_STATE_OK, OK_RP )
+
+ TRY_STATE( REPL_STATE_NO_SYNC, NO_SYNC_RP )
+
+ TRY_STATE( REPL_STATE_NO_MASTER, NO_MASTER_RP )
+
+ TRY_STATE( REPL_STATE_NEVER_REPLICATED, NEVER_REPLICATED_RP )
+
+ goto ReportBadConfigLine;
+
+DoneState:
+
+ //
+ // Parse the rest of the value string.
+ //
+
+#define PARSE_CHAR(AsciiChar) \
+ { \
+ if (*CurrentValuePtr == MAKE_TCHAR(AsciiChar)) { \
+ ++CurrentValuePtr; \
+ } else { \
+ goto ReportBadConfigLine; \
+ } \
+ }
+
+#define PARSE_COMMA( ) PARSE_CHAR(',')
+
+ PARSE_COMMA();
+
+ //
+ // Parse the (optional) UNC master name.
+ //
+ if (*CurrentValuePtr == MAKE_TCHAR('\\')) {
+ LPTSTR StringAfterMasterName;
+
+ StringAfterMasterName = STRCHR( CurrentValuePtr, MAKE_TCHAR(',') );
+ if (StringAfterMasterName == NULL) {
+ goto ReportBadConfigLine;
+ }
+
+ *StringAfterMasterName = TCHAR_EOS; // changes master to its own str.
+ if ( !NetpIsUncComputerNameValid( CurrentValuePtr ) ) {
+ goto ReportBadConfigLine;
+ }
+
+ (void) STRCPY( UncMasterPtr, CurrentValuePtr );
+ *StringAfterMasterName = MAKE_TCHAR(','); // put line back as is was
+ CurrentValuePtr = StringAfterMasterName; // skip to the comma.
+ } else if (*CurrentValuePtr == MAKE_TCHAR(',')) {
+ if (UncMasterPtr != NULL) {
+ *UncMasterPtr = TCHAR_EOS;
+ }
+ } else {
+ goto ReportBadConfigLine;
+ }
+
+ PARSE_COMMA();
+
+ //
+ // Parse the numbers on the rest of the line.
+ //
+
+#define PARSE_DWORD( NumberPtr ) \
+ { \
+ if ( ! ISDIGIT( *CurrentValuePtr ) ) { \
+ goto ReportBadConfigLine; \
+ } \
+ NetpAssert( NumberPtr != NULL ); \
+ * NumberPtr = (DWORD) ATOL( CurrentValuePtr ); \
+ while ( ISDIGIT( *CurrentValuePtr ) ) { \
+ ++CurrentValuePtr; \
+ } \
+ }
+
+ PARSE_DWORD( LastUpdateTimePtr ); // Seconds since 1970.
+
+ PARSE_COMMA();
+
+ PARSE_DWORD( LockCountPtr );
+
+ PARSE_COMMA();
+
+ PARSE_DWORD( LockTimePtr ); // Seconds since 1970.
+
+ IF_DEBUG(IMPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirParseConfigValue: Value = '" FORMAT_LPTSTR "',\n",
+ ValueString ));
+ NetpKdPrint((
+ " State = " FORMAT_DWORD
+ ", UncMaster = '" FORMAT_LPTSTR "'.\n",
+ *StatePtr, OPTIONAL_LPTSTR(UncMasterPtr) ));
+ NetpKdPrint((
+ " last update time (secs since 1970) = " FORMAT_DWORD
+ ", lock count = " FORMAT_DWORD
+ ", lock time (secs since 1970) = " FORMAT_DWORD ".\n",
+ *LastUpdateTimePtr, *LockCountPtr, *LockTimePtr ));
+ }
+
+ if ( ! ReplIsStateValid( *StatePtr ) ) {
+ goto ReportBadConfigLine;
+ }
+
+ return (NO_ERROR);
+
+ReportBadConfigLine:
+
+ // BUGBUG: Sure would be nice if we could include dirname here.
+
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS,
+ ValueString );
+
+ return (ERROR_INVALID_DATA);
+
+} // ImportDirParseConfigData
+
+
+// Read config data for a single import directory. Callable whether or not
+// the replicator service is started. Returns NERR_UnknownDevDir if there
+// is no config data for this directory.
+NET_API_STATUS
+ImportDirReadConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ OUT LPDWORD StatePtr,
+ OUT LPTSTR UncMasterPtr,
+ OUT LPDWORD LastUpdateTimePtr, // Seconds since 1970.
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPTSTR Value = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS, // area (instead of parameters)
+ TRUE); // read-only
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Read the value from the config file/whatever.
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ & Value); // alloc and set ptr
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NERR_UnknownDevDir;
+ goto Cleanup; // go log error
+ } else if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+ NetpAssert( Value != NULL );
+
+ IF_DEBUG(IMPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirReadConfigValue( " FORMAT_LPTSTR "): '"
+ FORMAT_LPTSTR "' = '" FORMAT_LPTSTR "'.\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local"),
+ DirName, Value ));
+ }
+
+ //
+ // Parse the value string...
+ //
+ ApiStatus = ImportDirParseConfigData (
+ UncServerName,
+ Value,
+ StatePtr,
+ UncMasterPtr,
+ LastUpdateTimePtr, // Seconds since 1970.
+ LockCountPtr,
+ LockTimePtr); // Seconds since 1970.
+ // Fall through and log error if this failed.
+
+Cleanup:
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (Value != NULL) {
+ (VOID) NetApiBufferFree( Value );
+ }
+
+ if (ApiStatus != NO_ERROR) {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ImportDirReadConfigData
+
+
+
+
+
+// Write config data for a single import directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ImportDirWriteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD State,
+ IN LPTSTR UncMaster OPTIONAL,
+ IN DWORD LastUpdateTime, // Seconds since 1970.
+ IN DWORD LockCount,
+ IN DWORD LockTime // Seconds since 1970.
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ TCHAR ValueArray[IMPORT_VALUE_ARRAY_LEN+1];
+
+ IF_DEBUG(IMPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirWriteConfigValue:( " FORMAT_LPTSTR " ): DirName = "
+ FORMAT_LPTSTR ".\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local"),
+ DirName ));
+ NetpKdPrint((
+ " State = " FORMAT_DWORD
+ ", UncMaster = '" FORMAT_LPTSTR "'.\n",
+ State, OPTIONAL_LPTSTR(UncMaster) ));
+ NetpKdPrint((
+ " last update time (secs since 1970) = " FORMAT_DWORD
+ ", lock count = " FORMAT_DWORD
+ ", lock time (secs since 1970) = " FORMAT_DWORD ".\n",
+ LastUpdateTime, LockCount, LockTime ));
+ }
+ //
+ // Check for caller's errors.
+ //
+ if ( ! ReplIsDirNameValid( DirName ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( ! ReplIsStateValid( State ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if (UncMaster != NULL) {
+ if ( ! NetpIsUncComputerNameValid( UncMaster ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ }
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // section
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS, // area (instead of parameters)
+ FALSE); // not read-only
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Start building the value, which begins with a string containing the
+ // state.
+ //
+ switch (State) {
+ case REPL_STATE_OK:
+
+ (void) STRCPY( ValueArray, OK_RP);
+ break;
+
+ case REPL_STATE_NO_SYNC:
+
+ (void) STRCPY( ValueArray, NO_SYNC_RP);
+ break;
+
+ case REPL_STATE_NO_MASTER:
+
+ (void) STRCPY( ValueArray, NO_MASTER_RP);
+ break;
+
+ case REPL_STATE_NEVER_REPLICATED:
+
+ (void) STRCPY( ValueArray, NEVER_REPLICATED_RP);
+ break;
+
+ default:
+ NetpAssert( FALSE );
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Build the rest of the value string.
+ //
+ (void) STRCAT( ValueArray, (LPTSTR) TEXT(",") );
+
+ if (UncMaster != NULL) {
+ (void) STRCAT( ValueArray, UncMaster );
+ }
+
+/*lint -save -e767 */ // Don't complain about different definitions
+#define WRITE_COMMA( ) \
+ (void) STRCAT( ValueArray, (LPTSTR) TEXT(",") )
+/*lint -restore */ // Resume checking for different macro definitions
+
+/*lint -save -e767 */ // Don't complain about different definitions
+#define WRITE_DWORD( Number ) \
+ { \
+ LPTSTR StrEnd = & ValueArray[ STRLEN( ValueArray ) ]; \
+ (void) ULTOA( (Number), StrEnd, /* radix */ 10 ); \
+ }
+/*lint -restore */ // Resume checking for different macro definitions
+
+ WRITE_COMMA();
+
+ WRITE_DWORD( LastUpdateTime ); // Seconds since 1970.
+
+ WRITE_COMMA();
+
+ WRITE_DWORD( LockCount );
+
+ WRITE_COMMA();
+
+ WRITE_DWORD( LockTime ); // Seconds since 1970.
+
+ IF_DEBUG(IMPAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirWriteConfigValue: '" FORMAT_LPTSTR "' = '"
+ FORMAT_LPTSTR "'.\n", DirName, ValueArray ));
+ }
+
+ //
+ // Write this value out to the config file/whatever.
+ //
+ ApiStatus = NetpSetConfigValue(
+ Handle,
+ DirName, // keyword is dir name
+ ValueArray);
+ // Fall through and log error if one happened.
+
+Cleanup:
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (ApiStatus != NO_ERROR) {
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ImportDirWriteConfigData
diff --git a/private/net/svcdlls/repl/common/impdir.h b/private/net/svcdlls/repl/common/impdir.h
new file mode 100644
index 000000000..d38228c36
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impdir.h
@@ -0,0 +1,259 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpDir.h
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator import directory worker routines.
+
+Author:
+
+ John Rogers (JohnRo) 07-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ You must include LmCons.h and ReplDefs.h before this file.
+
+Revision History:
+
+ 07-Jan-1992 JohnRo
+ Created.
+ 09-Jan-1992 JohnRo
+ Added ImportDirBuildApiRecord().
+ Added IMPORT_DIR_SECTION_NAME equate.
+ Added ImportDir{Read,Write}ConfigData.
+ 16-Jan-1992 JohnRo
+ Corrected "Notes" comment above.
+ 20-Jan-1992 JohnRo
+ Netr prototypes are now generated by MIDL and put in repl.h.
+ 23-Jan-1992 JohnRo
+ Clarify units for time parameters.
+ Changed IMPORT_DIR_SECTION_NAME.
+ 27-Jan-1992 JohnRo
+ Added ImportDirSetState().
+ Changed to use LPTSTR etc.
+ Changed to avoid use of client-specific data structure.
+ 09-Feb-1992 JohnRo
+ Added ImportDir{Start,Stop}Repl routines.
+ 13-Feb-1992 JohnRo
+ Moved section name equates to ConfName.h.
+ 19-Feb-1992 JohnRo
+ Added ImportDirIsApiRecordValid() and various other routines.
+ 21-Feb-1992 JohnRo
+ UncMaster parm is optional to ImportDirBuildApiRecord.
+ 21-Feb-1992 JohnRo
+ Changed ImportDirBuildApiRecord() so master name is not a UNC name.
+ 15-Mar-1992 JohnRo
+ Update registry with new values.
+ 23-Mar-1992 JohnRo
+ Added ImportDirReadClientList().
+ 24-Mar-1992 JohnRo
+ UncMaster parm is optional to ImportDirWriteConfigData().
+ 30-Jul-1992 JohnRo
+ Help PC-LINT understand ImportDirIsLevelValid().
+ 25-Sep-1992 JohnRo
+ RAID 5494: repl svc does not maintain time stamp on import startup.
+ 29-Sep-1992 JohnRo
+ RAID 7962: Repl APIs in wrong role kill svc.
+ Also fix remote repl admin.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 13-Apr-1993 JohnRo
+ RAID 3107: locking directory over the net gives network path not found.
+
+--*/
+
+
+#ifndef _IMPDIR_
+#define _IMPDIR_
+
+
+//
+// Import dir helper routines and macros:
+//
+
+
+// Allocate one or more API records for an import directory. Callable whether
+// or not the replicator service is started. (Used in getinfo stub, getinfo
+// worker, and enum stub.)
+NET_API_STATUS
+ImportDirAllocApiRecords (
+ IN DWORD Level,
+ IN DWORD EntryCount,
+ OUT LPBYTE * BufPtr,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ );
+
+NET_API_STATUS
+ImportDirBuildApiRecord (
+ IN DWORD Level,
+ IN LPTSTR DirName,
+ IN DWORD State,
+ IN LPTSTR MasterName OPTIONAL, // computer name (not UNC).
+ IN DWORD TimeOfLastUpdate, // Seconds since 1970.
+ IN DWORD LockCount,
+ IN DWORD TimeOfFirstLock, // Seconds since 1970.
+ OUT LPVOID Buffer,
+ IN OUT LPBYTE *StringLocation // Points just past top of data.
+ );
+
+// Tells whether or not config data for this directory exists.
+// Callable even if the replicator service is not started.
+BOOL
+ImportDirConfigDataExists (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ );
+
+NET_API_STATUS
+ImportDirConfigSetInfo (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ IN LPVOID Buf,
+ OUT LPDWORD ParmError OPTIONAL
+ );
+
+// Delete config data for this directory.
+// Returns NERR_UnknownDevDir if config data doesn't exist for this dir.
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ImportDirDeleteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName // Caller must check dir name syntax.
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ImportDirEnumApiRecords(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr,
+ IN DWORD PrefMaxSize,
+ OUT LPDWORD EntriesRead,
+ OUT LPDWORD TotalEntries
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ImportDirGetApiRecord (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr
+ );
+
+BOOL
+ImportDirIsApiRecordValid (
+ IN DWORD Level,
+ IN LPVOID ApiRecord,
+ OUT LPDWORD ParmError OPTIONAL
+ );
+
+// BOOL
+// ImportDirIsLevelValid(
+// IN DWORD Level
+// );
+//
+#define ImportDirIsLevelValid(Level) \
+ /*lint -e506 */ /* don't complain about constant values here */ \
+ ( ((Level) <= 1 ) ? TRUE : FALSE ) \
+ /*lint +e506 */ \
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RCGlobalListLock.
+NET_API_STATUS
+ImportDirLockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName
+ );
+
+// Parse config data for a single import directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ImportDirParseConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR KeywordValue,
+ OUT LPDWORD StatePtr,
+ OUT LPTSTR MasterPtr,
+ OUT LPDWORD LastUpdateTimePtr, // Seconds since 1970.
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ );
+
+// Read import dirs into service's client list.
+// Only callable as part of the service itself.
+NET_API_STATUS
+ImportDirReadClientList(
+ VOID
+ );
+
+// Read config data for a single import directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ImportDirReadConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ OUT LPDWORD StatePtr,
+ OUT LPTSTR MasterPtr,
+ OUT LPDWORD LastUpdateTimePtr, // Seconds since 1970.
+ OUT LPDWORD LockCountPtr,
+ OUT LPDWORD LockTimePtr // Seconds since 1970.
+ );
+
+// Change the state for a single import directory.
+NET_API_STATUS
+ImportDirSetState (
+ IN LPTSTR DirName,
+ IN DWORD State // Must be REPL_STATE_ value.
+ );
+
+// Start replicating (importing).
+// Called when service starts or user does NetReplSetInfo() and changes role.
+NET_API_STATUS
+ImportDirStartRepl (
+ IN BOOL ServiceIsStarting
+ );
+
+// Stop replicating (importing).
+// Called when service stops or user does NetReplSetInfo() and changes role.
+NET_API_STATUS
+ImportDirStopRepl (
+ VOID
+ );
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RCGlobalListLock.
+NET_API_STATUS
+ImportDirUnlockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD UnlockForce
+ );
+
+// Write config data for a single import directory. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ImportDirWriteConfigData (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD State,
+ IN LPTSTR UncMaster OPTIONAL,
+ IN DWORD LastUpdateTime, // Seconds since 1970.
+ IN DWORD LockCount,
+ IN DWORD LockTime // Seconds since 1970.
+ );
+
+
+#endif // _IMPDIR_
diff --git a/private/net/svcdlls/repl/common/impenum.c b/private/net/svcdlls/repl/common/impenum.c
new file mode 100644
index 000000000..0d03aba40
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impenum.c
@@ -0,0 +1,321 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpEnum.c
+
+Abstract:
+
+ ImporDirEnumApiRecords.
+
+Author:
+
+ John Rogers (JohnRo) 17-Dec-1991
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+ 16-Nov-1992 JohnRo
+ RAID 1537: Repl APIs in wrong role kill svc. (Extracted from DLL stub.)
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 10-Mar-1993 JohnRo
+ RAID 12871: replication UI shows nothing (adding entry while enumerating
+ results in empty list).
+ Made changes suggested by PC-LINT 5.0
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windows.h> // IN, DWORD, etc.
+#include <lmcons.h> // NET_API_STATUS, etc.
+
+// These may be included in any order:
+
+#include <config.h> // LPNET_CONFIG_HANDLE, Netp config routines.
+#include <confname.h> // SECT_NT_ equates.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototype.
+#include <lmerr.h> // NERR_ and ERROR_ equates, NO_ERROR.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), ReplErrorLog(), etc.
+#include <strucinf.h> // NetpReplImportDirStructureInfo().
+
+
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ImportDirEnumApiRecords(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr,
+ IN DWORD PrefMaxSize,
+ OUT LPDWORD EntriesRead,
+ OUT LPDWORD TotalEntries
+ )
+
+{
+ NET_API_STATUS ApiStatus;
+
+ LPVOID ArrayEntry;
+ LPVOID ArrayStart = NULL;
+ DWORD EntriesAllocated = 0;
+ DWORD EntriesFound = 0;
+ BOOL FirstTime;
+ DWORD FixedEntrySize;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPBYTE StringLocation;
+
+ UNREFERENCED_PARAMETER( PrefMaxSize );
+
+ IF_DEBUG( IMPAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirEnumApiRecords( " FORMAT_LPTSTR
+ " ): doing parameter checks...\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local")
+ ));
+ }
+
+ if ( ! ImportDirIsLevelValid( Level ) ) {
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ } else if (BufPtr == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ } else if (EntriesRead == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ } else if (TotalEntries == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ //
+ // Set outputs in case we run into an error.
+ //
+
+ * BufPtr = NULL;
+ * EntriesRead = 0;
+ * TotalEntries = 0;
+
+ //
+ // Figure-out the size of a fixed entry for this info level.
+ //
+ ApiStatus = NetpReplImportDirStructureInfo (
+ Level,
+ PARMNUM_ALL,
+ TRUE, // want native sizes
+ NULL, // don't need data desc 16
+ NULL, // don't need data desc 32
+ NULL, // don't need data desc SMB
+ NULL, // don't need max size
+ & FixedEntrySize,
+ NULL ); // don't need string size
+
+ NetpAssert( ApiStatus == NO_ERROR ); // Already checked args.
+ NetpAssert( FixedEntrySize > 0 );
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigDataEx(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR, // service name
+ (LPTSTR) SECT_NT_REPLICATOR_IMPORTS, // area under service
+ TRUE); // read-only
+ if (ApiStatus != NO_ERROR) {
+
+ // Handle section not found as empty enum array (not error).
+ if (ApiStatus == NERR_CfgCompNotFound) {
+ ApiStatus = NO_ERROR;
+ goto Cleanup;
+ }
+
+ goto Cleanup;
+ }
+
+ //
+ // Loop, expanding buffer if necessary, until we get it large enough.
+ //
+
+ do {
+
+ //
+ // Count entries in config data.
+ //
+ ApiStatus = NetpNumberOfConfigKeywords (
+ Handle,
+ & EntriesAllocated );
+
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ } else if (EntriesAllocated == 0) {
+ goto Cleanup;
+ }
+
+ //
+ // Alloc and/or expand the array...
+ //
+ ApiStatus = ImportDirAllocApiRecords (
+ Level,
+ EntriesAllocated,
+ (LPBYTE *) (LPVOID) & ArrayStart,
+ & StringLocation ); // Points just past top of data.
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( ArrayStart != NULL );
+ } else {
+ goto Cleanup;
+ }
+
+ //
+ // Go back and reread, filling-in the config data as we go.
+ //
+
+ ArrayEntry = ArrayStart;
+ FirstTime = TRUE;
+
+ while (ApiStatus == NO_ERROR) {
+ LPTSTR DirName;
+ DWORD LockCount;
+ DWORD State;
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+ DWORD TimeOfLastUpdate; // Seconds since 1970.
+ TCHAR UncMaster[UNCLEN+1];
+ LPTSTR ValueString;
+
+ ApiStatus = NetpEnumConfigSectionValues (
+ Handle,
+ & DirName, // Keyword - alloc and set ptr.
+ & ValueString, // Must be freed by NetApiBufferFree().
+ FirstTime );
+
+ FirstTime = FALSE;
+
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( DirName != NULL );
+ NetpAssert( ValueString != NULL );
+
+ ++EntriesFound;
+ if (EntriesFound > EntriesAllocated) {
+ EntriesFound = 0;
+ NetpMemoryFree( ArrayStart );
+ ArrayStart = NULL;
+ ApiStatus = ERROR_MORE_DATA;
+ break; // exit per-entry loop and try again
+ }
+
+ if ( !ReplIsDirNameValid( DirName ) ) {
+ // BUGBUG: perhaps delete entry, log event, and continue?
+ ApiStatus = ERROR_INVALID_DATA;
+ NetpMemoryFree( DirName );
+ NetpMemoryFree( ValueString );
+ goto Cleanup;
+ }
+
+ //
+ // Parse the value string...
+ //
+ ApiStatus = ImportDirParseConfigData (
+ UncServerName,
+ ValueString,
+ & State,
+ UncMaster,
+ & TimeOfLastUpdate, // Seconds since 1970.
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+
+ NetpMemoryFree( ValueString );
+
+ if (ApiStatus == NO_ERROR) {
+ LPTSTR MasterName;
+ NetpAssert( ArrayEntry != NULL );
+
+ if (*UncMaster) {
+ MasterName = UncMaster + 2; // Chg from UNC to non.
+ } else {
+ MasterName = NULL;
+ }
+
+ //
+ // Build API record for this entry.
+ //
+ ApiStatus = ImportDirBuildApiRecord (
+ Level,
+ DirName,
+ State, // State when svc was running.
+ MasterName,
+ TimeOfLastUpdate, // Seconds since 1970.
+ LockCount,
+ TimeOfFirstLock, // Seconds since 1970.
+ ArrayEntry,
+ & StringLocation );
+ if (ApiStatus != NO_ERROR) {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirEnumApiRecords: error "
+ FORMAT_API_STATUS " from imp build.\n",
+ ApiStatus ));
+ NetpAssert( FALSE );
+ goto Cleanup;
+ }
+
+ ArrayEntry = NetpPointerPlusSomeBytes(
+ ArrayEntry, FixedEntrySize );
+ }
+ NetpMemoryFree( DirName );
+
+ }
+
+ } // while not error (may be NERR_CfgParamNotFound at end).
+
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ApiStatus = NO_ERROR;
+ } else {
+ NetpAssert( ApiStatus != NO_ERROR );
+ goto Cleanup;
+ }
+
+ } while (ApiStatus == ERROR_MORE_DATA);
+
+ //
+ // All done.
+ //
+
+Cleanup:
+
+ if (Handle != NULL) {
+ (VOID) NetpCloseConfigData( Handle );
+ }
+
+ NetpAssert( ApiStatus != ERROR_MORE_DATA );
+ if (ApiStatus == NO_ERROR) {
+ * BufPtr = ArrayStart;
+ * EntriesRead = EntriesFound;
+ * TotalEntries = EntriesFound;
+ } else {
+ NetpKdPrint(( PREFIX_REPL
+ "ImportDirEnumApiRecords: returning status " FORMAT_API_STATUS
+ ".\n", ApiStatus ));
+
+ // Log the error.
+ ReplErrorLog(
+ UncServerName, // log here and there.
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL, // no str1
+ NULL ); // no str2
+ }
+
+ return ApiStatus;
+
+}
diff --git a/private/net/svcdlls/repl/common/impget.c b/private/net/svcdlls/repl/common/impget.c
new file mode 100644
index 000000000..54a9e0513
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impget.c
@@ -0,0 +1,149 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ImpGet.c
+
+Abstract:
+
+ Read an API record with import directory info from the registry.
+ Callable even if the replicator service is not started.
+
+Author:
+
+ John Rogers (JohnRo) 09-Nov-1992
+
+Environment:
+
+ User Mode - Win32
+
+Revision History:
+
+ 09-Nov-1992 JohnRo
+ Created for RAID 7962: Repl APIs in wrong role kill svc.
+
+--*/
+
+
+// These must be included first:
+
+//#include <nt.h> // Needed by <config.h> temporarily.
+//#include <ntrtl.h> // Needed by <config.h> temporarily.
+#include <windef.h> // IN, DWORD, etc.
+
+#include <lmcons.h> // NET_API_STATUS, etc.
+//#include <rap.h> // Needed by <strucinf.h>.
+//#include <repldefs.h> // Needed by <impdir.h>.
+//#include <rpc.h> // Needed by <netrpc.h>.
+
+// These may be included in any order:
+
+//#include <config.h> // LPNET_CONFIG_HANDLE, Netp config routines.
+//#include <confname.h> // SECT_NT_ equates.
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My ptototype, ImportDirIsApiRecordValid(), etc.
+#include <lmapibuf.h> // NetApiBufferFree().
+//#include <lmrepl.h> // My prototypes, etc.
+//#include <lmsvc.h> // SERVICE_ equates.
+#include <netdebug.h> // NetpAssert().
+//#include <netlib.h> // NetpSetParmError() macro.
+//#include <netrpc.h> // NET_REMOTE macros.
+//#include <prefix.h> // PREFIX_ equates.
+//#include <repl.h> // MIDL-generated NetrRepl prototypes.
+//#include <rpcutil.h> // GENERIC_INFO_CONTAINER, etc.
+//#include <strucinf.h> // NetpReplImportDirStructureInfo().
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+
+NET_API_STATUS
+ImportDirGetApiRecord (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD Level,
+ OUT LPBYTE * BufPtr
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPVOID ApiRecord = NULL;
+ DWORD LockCount;
+ LPTSTR MasterName;
+ DWORD State;
+ LPBYTE StringLocation; // Points just past top of data.
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+ DWORD TimeOfLastUpdate; // Seconds since 1970.
+ TCHAR UncMaster[UNCLEN+1];
+
+ if ( !ReplIsDirNameValid( DirName )) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ } else if ( !ImportDirIsLevelValid( Level ) ) {
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ } else if (BufPtr == NULL) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ //
+ // Read config data for a single import directory.
+ //
+ ApiStatus = ImportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & State,
+ UncMaster,
+ & TimeOfLastUpdate, // Seconds since 1970.
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ }
+
+ ApiStatus = ImportDirAllocApiRecords (
+ Level,
+ 1, // only 1 record.
+ (LPBYTE *) & ApiRecord, // alloc and set ptr
+ (LPBYTE *) & StringLocation ); // Points just past top of data.
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ }
+ NetpAssert( ApiRecord != NULL );
+
+ if (*UncMaster) {
+ MasterName = UncMaster + 2; // Chg from UNC to non.
+ } else {
+ MasterName = NULL;
+ }
+
+ ApiStatus = ImportDirBuildApiRecord (
+ Level,
+ DirName,
+ State,
+ MasterName,
+ TimeOfLastUpdate, // Seconds since 1970
+ LockCount,
+ TimeOfFirstLock, // Seconds since 1970.
+ ApiRecord,
+ (LPBYTE *) (LPVOID) & StringLocation);
+ NetpAssert( ApiStatus == NO_ERROR ); // We checked all parms.
+
+
+Cleanup:
+
+ if (ApiStatus == NO_ERROR) {
+ NetpAssert( ApiRecord != NULL );
+ *BufPtr = ApiRecord;
+ } else {
+ *BufPtr = NULL;
+ if (ApiRecord != NULL) {
+ (VOID) NetApiBufferFree( ApiRecord );
+ }
+ }
+
+ return ApiStatus;
+
+}
diff --git a/private/net/svcdlls/repl/common/implock.c b/private/net/svcdlls/repl/common/implock.c
new file mode 100644
index 000000000..c94a70f05
--- /dev/null
+++ b/private/net/svcdlls/repl/common/implock.c
@@ -0,0 +1,172 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpLock.c
+
+Abstract:
+
+ Routines to update lock fields in registry (for import dirs).
+
+Author:
+
+ John Rogers (JohnRo) 15-Mar-1992
+
+Environment:
+
+ User Mode - Win32
+
+Notes:
+
+ This file is extremely similar to ExpLock.c. If you fix any bugs here,
+ make sure they're reflected there, and vice versa.
+
+Revision History:
+
+ 15-Mar-1992 JohnRo
+ Update registry with new values.
+ 29-Sep-1992 JohnRo
+ Also fix remote repl admin.
+ 13-Apr-1993 JohnRo
+ RAID 3107: locking directory over the net gives network path not found.
+ Made changes suggested by PC-LINT 5.0
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, DWORD, etc.
+#include <lmcons.h> // NET_API_STATUS, etc.
+
+// These may be included in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototypes, etc.
+#include <lmrepl.h> // REPL_FORCE_ equates.
+#include <netdebug.h> // NetpKdPrint().
+#include <repldefs.h> // Stuff.
+#include <winerror.h> // NO_ERROR, ERROR_ equates.
+
+
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RCGlobalListLock.
+NET_API_STATUS
+ImportDirLockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD LockCount;
+ DWORD State;
+ TCHAR UncMaster[UNCLEN+1];
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+ DWORD TimeOfLastUpdate; // Seconds since 1970.
+
+ IF_DEBUG(REPL) {
+ NetpKdPrint(( "ImportDirLockInRegistry( " FORMAT_LPTSTR
+ "): beginnning...\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local") ));
+ }
+
+ if ( !ReplIsDirNameValid( DirName )) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // Read config data for a single import directory.
+ ApiStatus = ImportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & State,
+ UncMaster,
+ & TimeOfLastUpdate, // Seconds since 1970.
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+
+ if (ApiStatus == NO_ERROR) {
+
+ ApiStatus = ReplIncrLockFields(
+ & LockCount,
+ & TimeOfFirstLock );
+ }
+ if (ApiStatus == NO_ERROR) {
+ ApiStatus = ImportDirWriteConfigData (
+ UncServerName,
+ DirName,
+ State,
+ (*UncMaster) ? UncMaster : NULL,
+ TimeOfLastUpdate, // Seconds since 1970.
+ LockCount,
+ TimeOfFirstLock ); // Seconds since 1970.
+ }
+
+ return ApiStatus;
+
+} // ImportDirLockInRegistry
+
+
+// Callable whether or not service is started.
+// If service is running, assume caller has lock (any kind) on RCGlobalListLock.
+NET_API_STATUS
+ImportDirUnlockInRegistry(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR DirName,
+ IN DWORD UnlockForce
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD LockCount;
+ DWORD State;
+ TCHAR UncMaster[UNCLEN+1];
+ DWORD TimeOfFirstLock; // Seconds since 1970.
+ DWORD TimeOfLastUpdate; // Seconds since 1970.
+
+ IF_DEBUG(REPL) {
+ NetpKdPrint(( "ImportDirUnlockInRegistry( " FORMAT_LPTSTR
+ "): beginnning...\n",
+ (UncServerName!=NULL) ? UncServerName : (LPTSTR) TEXT("local") ));
+ }
+
+ if ( !ReplIsDirNameValid( DirName )) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // Read config data for a single import directory.
+ ApiStatus = ImportDirReadConfigData (
+ UncServerName,
+ DirName,
+ & State,
+ UncMaster,
+ & TimeOfLastUpdate, // Seconds since 1970.
+ & LockCount,
+ & TimeOfFirstLock ); // Seconds since 1970.
+
+ if (ApiStatus == NO_ERROR) {
+
+ ApiStatus = ReplDecrLockFields(
+ & LockCount,
+ & TimeOfFirstLock,
+ UnlockForce );
+ }
+ if (ApiStatus == NO_ERROR) {
+ // Write the new or revised data.
+ ApiStatus = ImportDirWriteConfigData (
+ UncServerName,
+ DirName,
+ State,
+ (*UncMaster) ? UncMaster : NULL,
+ TimeOfLastUpdate, // Seconds since 1970.
+ LockCount,
+ TimeOfFirstLock ); // Seconds since 1970.
+
+ }
+
+ return ApiStatus;
+
+} // ImportDirUnlockInRegistry
diff --git a/private/net/svcdlls/repl/common/imports.h b/private/net/svcdlls/repl/common/imports.h
new file mode 100644
index 000000000..5a1f5577c
--- /dev/null
+++ b/private/net/svcdlls/repl/common/imports.h
@@ -0,0 +1,58 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ imports.h
+
+Abstract:
+
+ This file allows us to include standard system header files in the
+ .idl file. The main .idl file imports a file called import.idl.
+ This allows the .idl file to use the types defined in these header
+ files. It also causes the following line to be added in the
+ MIDL generated header file:
+
+ #include "imports.h"
+
+ Thus these types are available to the RPC stub routines as well.
+
+Author:
+
+ John Rogers (JohnRo) 17-Jan-1992
+
+Revision History:
+
+ 17-Jan-1992 JohnRo
+ Created the repl service RPC stuff from Rita's workstation RPC stuff.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 16-Feb-1992 JohnRo
+ Corrected use of LPTSTR.
+
+--*/
+
+
+#include <windef.h>
+#include <lmcons.h>
+
+#ifdef MIDL_PASS
+
+#ifdef UNICODE
+#define LPTSTR [string] wchar_t *
+#else
+#define LPTSTR [string] LPTSTR
+#endif
+
+#define LPSTR [string] char_t *
+#define LPCSTR [string] char_t *
+#define LPWSTR [string] wchar_t *
+#define LPCWSTR [string] wchar_t *
+
+//#define LPSTR [string] LPSTR
+#define BOOL DWORD
+
+#endif
+
+#include <lmrepl.h>
diff --git a/private/net/svcdlls/repl/common/impstate.c b/private/net/svcdlls/repl/common/impstate.c
new file mode 100644
index 000000000..ab467aa2e
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impstate.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ImpState.c
+
+Abstract:
+
+ This file contains ImportDirSetState().
+
+Author:
+
+ John Rogers (JohnRo) 27-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 27-Jan-1992 JohnRo
+ Created.
+ 26-Mar-1992 JohnRo
+ Added more argument checking.
+ 26-Mar-1992 JohnRo
+ Don't pass ImportDirWriteConfigData() UncMaster as ptr to null char.
+ 29-Sep-1992 JohnRo
+ Fix remote repl admin.
+ 04-Dec-1992 JohnRo
+ Handle unexpected errors better.
+ Use PREFIX_ equates.
+ Made changes suggested by PC-LINT 5.0
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+--*/
+
+
+#include <windef.h> // Win32 type definitions
+#include <lmcons.h> // NET_API_STATUS, UNCLEN.
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototypes, IMPORT_DIR_SECTION_NAME.
+#include <lmerr.h> // ERROR_, NERR_, NO_ERROR equates.
+#include <netdebug.h> // NetpAssert().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), ReplIsStateValid(), etc.
+#include <tstr.h> // TCHAR_EOS.
+
+
+// Change the state for a single import directory.
+// Creates an entry with defaults if necessary.
+NET_API_STATUS
+ImportDirSetState (
+ IN LPTSTR DirName,
+ IN DWORD State
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD LastUpdateTime; // Seconds since 1970.
+ DWORD LockCount;
+ DWORD LockTime; // Seconds since 1970.
+ DWORD OldState;
+ TCHAR UncMaster[UNCLEN+1];
+
+ NetpAssert( ReplIsDirNameValid( DirName ) );
+ NetpAssert( ReplIsStateValid( State ) );
+
+ // Read config data for a this import directory.
+ ApiStatus = ImportDirReadConfigData (
+ NULL, // no server name
+ DirName,
+ & OldState,
+ UncMaster,
+ & LastUpdateTime, // Seconds since 1970.
+ & LockCount,
+ & LockTime); // Seconds since 1970.
+
+ if (ApiStatus == NERR_UnknownDevDir) {
+
+ // Set defaults.
+ LastUpdateTime = 0;
+ LockCount = 0;
+ LockTime = 0;
+ UncMaster[0] = TCHAR_EOS;
+
+ } else if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ImportDirSetState: unexpected ret "
+ FORMAT_API_STATUS " from ImportDirReadConfigData("
+ FORMAT_LPTSTR ").\n",
+ ApiStatus, DirName ));
+ goto Cleanup;
+
+ }
+
+ // Write revised config data for this directory.
+ ApiStatus = ImportDirWriteConfigData (
+ NULL, // no server name
+ DirName,
+ State,
+ (*UncMaster) ? UncMaster : NULL,
+ LastUpdateTime, // Seconds since 1970.
+ LockCount,
+ LockTime ); // Seconds since 1970.
+
+ if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL_CLIENT
+ "ImportDirSetState: unexpected ret "
+ FORMAT_API_STATUS " from ImportDirWriteConfigData("
+ FORMAT_LPTSTR ").\n",
+ ApiStatus, DirName ));
+ }
+
+Cleanup:
+ return (ApiStatus);
+
+} // ImportDirSetState
diff --git a/private/net/svcdlls/repl/common/impvalid.c b/private/net/svcdlls/repl/common/impvalid.c
new file mode 100644
index 000000000..2fc7eeb6d
--- /dev/null
+++ b/private/net/svcdlls/repl/common/impvalid.c
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ImpValid.c
+
+Abstract:
+
+ This file contains ImportDirIsApiRecordValid().
+
+Author:
+
+ John Rogers (JohnRo) 22-Jan-1992
+
+Environment:
+
+ Runs under Windows NT.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ This code assumes that the info levels are subsets of each other.
+
+Revision History:
+
+ 18-Feb-1992 JohnRo
+ Added ImportDirIsApiRecordValid().
+ 21-Feb-1992 JohnRo
+ rpid1_mastername is a UNC name.
+ 27-Feb-1992 JohnRo
+ Check lock fields for validity.
+ rpid1_mastername is optional.
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, VOID, LPTSTR, etc.
+#include <lmcons.h> // NET_API_STATUS, PARM equates, etc.
+#include <repldefs.h> // IF_DEBUG(), ReplIsIntegrityValid(), etc.
+
+// These can be in any order:
+
+#include <dirname.h> // ReplIsDirNameValid().
+#include <impdir.h> // My prototype.
+#include <lmrepl.h> // LPREPL_EDIR_INFO_1, REPL_EXTENT_ stuff, etc.
+#include <names.h> // NetpIsUncComputerNameValid().
+#include <netlib.h> // NetpSetParmError().
+
+
+BOOL
+ImportDirIsApiRecordValid (
+ IN DWORD Level,
+ IN LPVOID Buf,
+ OUT LPDWORD ParmError OPTIONAL
+ )
+
+{
+ LPREPL_IDIR_INFO_1 ApiRecord; // Superset info level.
+
+ //
+ // First, make sure level is valid and there's actually a struct there.
+ //
+ NetpSetParmError( PARM_ERROR_UNKNOWN ); // Assume error until proven...
+ if (Level > 1) {
+ return (FALSE); // No, it's not valid.
+ }
+ if (Buf == NULL) {
+ return (FALSE); // No, it's not valid.
+ }
+ ApiRecord = Buf;
+
+ //
+ // Check item(s) common to all levels.
+ //
+ if ( ! ReplIsDirNameValid(ApiRecord->rpid1_dirname) ) {
+ NetpSetParmError( 1 ); // Error in first field in ApiRecord.
+ return (FALSE); // No, it's not valid.
+ }
+
+ //
+ // Check items unique to level 1.
+ //
+ if (Level > 0) {
+ if ( ! ReplIsStateValid(ApiRecord->rpid1_state) ) {
+ NetpSetParmError( 2 ); // Error in second field in ApiRecord.
+ return (FALSE); // No, it's not valid.
+ }
+
+ if ( ApiRecord->rpid1_mastername != NULL ) {
+ if ( ! NetpIsUncComputerNameValid(ApiRecord->rpid1_mastername) ) {
+ NetpSetParmError( 3 ); // Error in third field in ApiRecord.
+ return (FALSE); // No, it's not valid.
+ }
+ }
+
+
+ // BUGBUG: No check possible for the following field?
+ // 4 (last_update_time)
+
+ if ( !ReplAreLockFieldsValid( ApiRecord->rpid1_lockcount,
+ ApiRecord->rpid1_locktime) ) {
+ NetpSetParmError( 5 ); // Error in fifth/sixth field.
+ return (FALSE); // No, it's not valid.
+ }
+
+ }
+
+ //
+ // Everything went OK. Tell caller.
+ //
+ NetpSetParmError( PARM_ERROR_NONE );
+ return (TRUE); // Yes, it's valid.
+
+}
diff --git a/private/net/svcdlls/repl/common/iniparm.h b/private/net/svcdlls/repl/common/iniparm.h
new file mode 100644
index 000000000..861f8f0bf
--- /dev/null
+++ b/private/net/svcdlls/repl/common/iniparm.h
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 1987-1992 Microsoft Corporation
+
+Module Name:
+ iniparm.h
+
+Abstract:
+ Function prototypes and some global data
+
+Author:
+ Ported from Lan Man 2.x
+
+Environment:
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+ 10/23/91 (madana)
+ ported to NT. Converted to NT style.
+ 20-Jan-1992 JohnRo
+ More changes suggested by PC-LINT.
+ Removed support for lanman dir switch and/or config keyword.
+ The tryuser variable should be treated as a BOOL.
+ 24-Jan-1992 JohnRo
+ Added KEYWORD_ equates (for config use) and got rid of SW_ equates.
+ Added default equates for integrity and extent.
+ Changed BOTH_SW etc to be TCHARs.
+ Moved current role from P_repl_sw to ReplGlobalRole.
+ Use REPL_ROLE_ equates just like the APIs do.
+ 13-Feb-1992 JohnRo
+ Renamed KEYWORD_ equates to REPL_KEYWORD_ and moved to <confname.h>.
+ Got rid of DEFAULT_REPL equate. Ditto DEFAULT_EXPORTPATH etc.
+ 29-Jul-1992 JohnRo
+ RAID 2650: repl svc should handle new subdirs.
+
+
+--*/
+
+
+#ifndef _INIPARM_
+#define _INIPARM_
+
+
+// default parameters
+
+//#define DEFAULT_REPL NULL
+
+//#define DEFAULT_EXPPATH NULL
+//#define DEFAULT_IMPPATH NULL
+
+#define DEFAULT_EXPLIST NULL
+#define DEFAULT_IMPLIST NULL
+
+#define DEFAULT_TRYUSER TRUE
+
+#define DEFAULT_INTEGRITY REPL_INTEGRITY_FILE
+#define DEFAULT_EXTENT REPL_EXTENT_TREE
+
+#define DEFAULT_STATE REPL_STATE_NEVER_REPLICATED
+
+
+// parameter range
+
+#define DEFAULT_LOGON NULL
+#define DEFAULT_PASSWD NULL
+#define DEFAULT_SYNC 5
+#define MAX_SYNC 60
+#define MIN_SYNC 1
+#define DEFAULT_PULSE 3
+#define MAX_PULSE 10
+#define MIN_PULSE 1
+#define DEFAULT_GUARD 2
+#define MAX_GUARD 30
+#define MIN_GUARD 0
+#define DEFAULT_RANDOM 60
+#define MAX_RANDOM 120
+#define MIN_RANDOM 1
+
+
+//
+// (Global config variables used to be declared here.
+// They are now declared in ReplGbl.h --JohnRo, 24-Jan-1992.)
+//
+
+
+#endif // _INIPARM_
diff --git a/private/net/svcdlls/repl/common/lstvalid.c b/private/net/svcdlls/repl/common/lstvalid.c
new file mode 100644
index 000000000..20e853a06
--- /dev/null
+++ b/private/net/svcdlls/repl/common/lstvalid.c
@@ -0,0 +1,162 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ LstValid.c
+
+Abstract:
+
+ ReplConfigIsListValid() is used to validate the syntax of export lists
+ and import lists. No existence checking is done.
+
+Author:
+
+ John Rogers, using code ported from Lan Man 2.x
+
+Environment:
+
+ Requires ANSI C extensions: slash-slash comments, long external names.
+ Tab size is set to 4.
+
+Revision History:
+
+ 14-Aug-1992 JohnRo
+ RAID 3601: repl APIs should checked import & export lists.
+ (Extracted this code from repl/server/master.c to help track down bogus
+ import/export lists.)
+ 27-Aug-1992 JohnRo
+ RAID 4611: repl: fix import/export lists.
+ 05-Jan-1993 JohnRo
+ Repl WAN support.
+ Made changes suggested by PC-LINT 5.0
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+
+
+--*/
+
+// These must be included first:
+
+#include <windows.h>
+#include <lmcons.h>
+
+// These may be included in any order:
+
+#include <netdebug.h> // NetpKdPrint(), FORMAT_ equates, etc.
+#include <netlib.h> // NetpMemoryAllocate(), NetpIsServerStarted().
+#include <icanon.h>
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG(), etc.
+#include <replconf.h> // My prototypes.
+#include <tstr.h> // STRSIZE(), TCHAR_EOS.
+
+
+BOOL
+ReplConfigIsListValid(
+ IN LPTSTR UncanonList OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Makes sure the synax of List is valid.
+ Callable whether or not service is started.
+
+Arguments:
+
+ UncanonList - optionally points to a semicolon-separated list of domain
+ names (e.g. TEXT("MyDomain")) and server names (e.g.
+ TEXT("SomeServer")).
+
+Return Value:
+
+ BOOL - TRUE iff List has valid syntax.
+
+--*/
+{
+ NET_API_STATUS ApiStatus;
+ DWORD EntryCount;
+ LPTSTR CanonList;
+ DWORD CanonListSize;
+
+ //
+ // Handle simple cases first.
+ //
+
+ if (UncanonList == NULL) {
+ return (TRUE); // yes, syntax is valid.
+ }
+ if (*UncanonList == TCHAR_EOS) {
+ return (TRUE); // yes, syntax is valid.
+ }
+
+ //
+ // Allocate temp space for parsed list.
+ //
+
+ CanonListSize = STRSIZE( UncanonList );
+
+ CanonList = NetpMemoryAllocate( CanonListSize );
+
+ if (CanonList == NULL) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplConfigIsListValid() can't allocate memory for "
+ "CanonList.\n" ));
+
+ return (FALSE); // can't tell if syntax is valid, so assume not.
+ }
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplConfigIsListValid before canon:\n" ));
+ NetpDbgDisplayReplList(
+ "uncanon list",
+ UncanonList );
+ }
+
+ //
+ // Do the actual parse.
+ //
+
+ ApiStatus = I_NetListCanonicalize(NULL,
+ UncanonList,
+ (LPTSTR) LIST_DELIMITER_STR_UI,
+ CanonList,
+ CanonListSize,
+ &EntryCount,
+ NULL, // PathTypes
+ 0, // PathTypesLen
+ (NAMETYPE_COMPUTER |
+ OUTLIST_TYPE_API |
+ INLC_FLAGS_MULTIPLE_DELIMITERS |
+ INLC_FLAGS_CANONICALIZE
+ ));
+
+ if (ApiStatus != NO_ERROR) {
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplConfigIsListValid() is in trouble calling "
+ "I_NetListCanonicalize, ApiStatus is " FORMAT_API_STATUS
+ "\n", ApiStatus ));
+
+ NetpMemoryFree(CanonList);
+
+ return (FALSE); // syntax is not valid, so say so.
+ }
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplConfigIsListValid after canon:\n" ));
+ NetpDbgDisplayReplList(
+ "canon list",
+ CanonList );
+ }
+
+ NetpMemoryFree( CanonList );
+
+ return (TRUE); // yes, syntax is valid.
+}
diff --git a/private/net/svcdlls/repl/common/makefile b/private/net/svcdlls/repl/common/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/net/svcdlls/repl/common/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/net/svcdlls/repl/common/replbld.c b/private/net/svcdlls/repl/common/replbld.c
new file mode 100644
index 000000000..b20694427
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replbld.c
@@ -0,0 +1,190 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplBld.c
+
+Abstract:
+
+ This file contains ReplConfigAllocAndBuildApiRecord().
+
+Author:
+
+ John Rogers (JohnRo) 23-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 23-Jan-1992 JohnRo
+ Created.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ 18-Feb-1992 JohnRo
+ Validate more of caller's parms.
+ Added assertion check of built record.
+ 11-Mar-1992 JohnRo
+ Fixed an error code.
+ 30-Apr-1993 JohnRo
+ Use NetpKdPrint() where possible.
+ Use PREFIX_ equates.
+
+--*/
+
+
+#include <windef.h> // IN, DWORD, etc.
+#include <lmcons.h> // LAN Manager common definitions
+#include <repldefs.h> // IF_DEBUG().
+
+#include <align.h> // ALIGN_ equates.
+#include <lmapibuf.h> // NetApiBufferAllocate().
+#include <lmrepl.h> // LMREPL_INFO_0.
+#include <netdebug.h> // NetpKdPrint(), etc.
+#include <netlib.h> // NetpCopyDataToBuffer(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <replconf.h> // My prototype.
+#include <tstr.h> // STRLEN().
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+#define POSSIBLE_STRSIZE(s) ((s) ? STRSIZE(s) : 0)
+
+
+// Allocate and build a repl config API record. Callable whether or not
+// the replicator service is started.
+NET_API_STATUS
+ReplConfigAllocAndBuildApiRecord (
+ IN DWORD Level,
+ IN DWORD Role,
+ IN LPTSTR ExportPath OPTIONAL,
+ IN LPTSTR ExportList OPTIONAL,
+ IN LPTSTR ImportPath OPTIONAL,
+ IN LPTSTR ImportList OPTIONAL,
+ IN LPTSTR LogonUserName OPTIONAL,
+ IN DWORD Interval,
+ IN DWORD Pulse,
+ IN DWORD GuardTime,
+ IN DWORD Random,
+ OUT LPBYTE * BufPtr // Alloc and set pointer.
+ )
+
+
+{
+ NET_API_STATUS ApiStatus;
+ LPREPL_INFO_0 Buffer;
+ LPVOID OutFixedDataEnd;
+ DWORD SizeNeeded;
+ LPBYTE StringLocation;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( Level != 0 ) {
+ return (ERROR_INVALID_LEVEL);
+ } else if (BufPtr == NULL) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+ * BufPtr = NULL; // Test for memory access fault.
+ if ( !ReplIsIntervalValid(Interval) ) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplIsPulseValid( Pulse ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplIsGuardTimeValid( GuardTime ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ } else if ( !ReplIsRandomValid( Random ) ) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ ApiStatus = ReplCheckAbsPathSyntax( ExportPath );
+ if (ApiStatus != NO_ERROR) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ ApiStatus = ReplCheckAbsPathSyntax( ImportPath );
+ if (ApiStatus != NO_ERROR) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+
+ // BUGBUG: Check ImportList and ExportList.
+ // BUGBUG: Check LogonUserName.
+
+ //
+ // Compute how much space we'll need and allocate it.
+ //
+ SizeNeeded = sizeof(REPL_INFO_0)
+ + POSSIBLE_STRSIZE(ExportPath)
+ + POSSIBLE_STRSIZE(ExportList)
+ + POSSIBLE_STRSIZE(ImportPath)
+ + POSSIBLE_STRSIZE(ImportList)
+ + POSSIBLE_STRSIZE(LogonUserName);
+
+ ApiStatus = NetApiBufferAllocate(
+ SizeNeeded,
+ (LPVOID *) & Buffer);
+ if (ApiStatus != NO_ERROR) {
+ return (ApiStatus);
+ }
+ NetpAssert( Buffer != NULL );
+
+ //
+ // Fill in the numbers in the structure.
+ //
+
+ Buffer->rp0_role = Role;
+ Buffer->rp0_interval = Interval;
+ Buffer->rp0_pulse = Pulse;
+ Buffer->rp0_guardtime = GuardTime;
+ Buffer->rp0_random = Random;
+
+ //
+ // Do the strings...
+ //
+
+ OutFixedDataEnd = NetpPointerPlusSomeBytes( Buffer, sizeof(REPL_INFO_0) );
+ StringLocation = NetpPointerPlusSomeBytes( Buffer, SizeNeeded );
+
+#define COPY_TSTRING_FIELD( destField, srcVar ) \
+ { \
+ if (srcVar != NULL) { \
+ BOOL CopyOK; \
+ CopyOK = NetpCopyDataToBuffer( \
+ (LPVOID) srcVar, \
+ STRSIZE(srcVar), \
+ OutFixedDataEnd, \
+ & StringLocation, \
+ (LPVOID) & Buffer->rp0_ ## destField, \
+ ALIGN_TCHAR); \
+ NetpAssert(CopyOK); \
+ } else { \
+ Buffer->rp0_ ## destField = NULL; \
+ } \
+ }
+
+ COPY_TSTRING_FIELD( exportpath, ExportPath );
+ COPY_TSTRING_FIELD( exportlist, ExportList );
+ COPY_TSTRING_FIELD( importpath, ImportPath );
+ COPY_TSTRING_FIELD( importlist, ImportList );
+ COPY_TSTRING_FIELD( logonusername, LogonUserName );
+
+ //
+ // All done.
+ //
+
+ IF_DEBUG(REPLAPI) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplConfigAllocAndBuildApiRecord: built structure...\n" ));
+ NetpDbgDisplayRepl( Level, Buffer );
+ }
+
+ NetpAssert( ReplConfigIsApiRecordValid( Level, Buffer, NULL ) );
+
+ * BufPtr = (LPVOID) Buffer;
+ return (NO_ERROR);
+
+} // ReplConfigAllocAndBuildApiRecord
diff --git a/private/net/svcdlls/repl/common/replconf.c b/private/net/svcdlls/repl/common/replconf.c
new file mode 100644
index 000000000..5b40f032f
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replconf.c
@@ -0,0 +1,666 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplConf.c
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator export directory worker routines.
+
+Author:
+
+ John Rogers (JohnRo) 27-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 27-Jan-1992 JohnRo
+ Created.
+ 04-Feb-1992 JohnRo
+ Fixed bug handling return code from ReplIsAbsPathValid().
+ Improved handling of default strings (which may be NULL pointers).
+ 13-Feb-1992 JohnRo
+ Do some handling of errors for missing parameters.
+ Moved section name and keyword equates to ConfName.h.
+ 18-Feb-1992 JohnRo
+ Handle optional keywords in _write routine.
+ Fixed some overlooked cleanup in error paths in _read routine.
+ Moved ReplCheckAbsPathSyntax() out for general use.
+ Fixed occasional wrong keyword in error messages.
+ 24-Feb-1992 JohnRo
+ Interval is obsolete for NT: don't keep in registry.
+ (Keep in APIs just in case we implement repl APIs for OS/2, etc.)
+ 26-Feb-1992 JohnRo
+ Fixed bug in defaulting the interval.
+ 11-Mar-1992 JohnRo
+ Added some error checking for export path and import path on write.
+ Improved some error handling after calling NetpOpenConfigData().
+ 23-Mar-1992 JohnRo
+ Get rid of old config helpers.
+ 27-Aug-1992 JohnRo
+ RAID 4611: validate ImportList and ExportList as read from registry.
+ 21-Sep-1992 JohnRo
+ RAID 6685: ReplConfigRead trashes Server Manager.
+ 04-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ Improve range check of guard time field.
+ Also, the interval (sync) field is not obsolete after all.
+ 05-Jan-1993 JohnRo
+ Repl WAN support (get rid of repl name list limits).
+ Made changes suggested by PC-LINT 5.0
+ 26-Jan-1993 JohnRo
+ RAID 7717: Repl assert if not logged on correctly. (Also do event
+ logging for real.)
+
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // MAX_PATH, etc.
+#include <lmcons.h> // LAN Manager common definitions
+
+// These may be included in any order:
+
+#include <config.h> // NetpConfig helpers, LPNET_CONFIG_HANDLE.
+#include <confname.h> // SECT_NT_ equates, REPL_KEYWORD_ too.
+#include <lmapibuf.h> // NetApiBufferFree().
+#include <lmerr.h> // NERR_, ERROR_, NO_ERROR equates.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <lmrepl.h> // REPL_ROLE equates, etc.
+#include <netdebug.h> // NetpAssert(), FORMAT_ equates, etc.
+#include <replconf.h> // My prototypes.
+#include <repldefs.h> // IF_DEBUG(), ReplCheckAbsPathSyntax().
+#include <tstr.h> // STRICMP(), TCHAR_EOS, etc.
+
+
+//
+// Macro to set an output from a default string value (which may be NULL).
+//
+#define SET_STRING_TO_DEFAULT( output, default ) \
+ { \
+ /*lint -save -e506 */ /* don't complain about constant values here */ \
+ if (default != NULL) { \
+ (void) STRCPY( output, default ); \
+ } else { \
+ *output = TCHAR_EOS; \
+ } \
+ /*lint -restore */ \
+ }
+
+
+
+// Callable whether or not service is started.
+// All outputs are undefined if return value is not NO_ERROR.
+NET_API_STATUS
+ReplConfigRead(
+ IN LPTSTR UncServerName OPTIONAL,
+ OUT LPDWORD Role,
+ OUT LPTSTR ExportPath,
+ OUT LPTSTR *ExportList, // alloc and set ptr
+ OUT LPTSTR ImportPath,
+ OUT LPTSTR *ImportList, // alloc and set ptr
+ OUT LPTSTR LogonUserName,
+ OUT LPDWORD Interval,
+ OUT LPDWORD Pulse,
+ OUT LPDWORD GuardTime,
+ OUT LPDWORD Random
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD DwordValue;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+ LPTSTR StringValue = NULL;
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigData(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR,
+ TRUE); // read-only
+ if (ApiStatus != NO_ERROR) {
+
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Read role (REPLICATOR switch)...
+ // This value is required.
+ // For historical reasons, this can be a string ("Both" etc) or a DWORD
+ // (REPL_ROLE_BOTH etc).
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_ROLE, // KeyWanted
+ & StringValue); // alloc and set ptr
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ NULL );
+
+ goto Cleanup; // go log error
+
+ } else if (ApiStatus == NO_ERROR) { // Read of string value OK.
+
+ DWORD CharCount;
+ NetpAssert( StringValue != NULL );
+ CharCount = STRLEN( StringValue );
+
+ if ( STRSPN( StringValue, (LPTSTR) TEXT("0123456789") ) == CharCount ) {
+ //
+ // Convert the string to a numeric value.
+ //
+ *Role = (DWORD) ATOL( StringValue );
+
+ if ( !ReplIsRoleValid( *Role ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ StringValue );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup;
+ }
+ } else if (STRICMP(StringValue, (LPTSTR) REPL_KEYWORD_ROLE_BOTH) == 0) {
+ *Role = REPL_ROLE_BOTH;
+ } else if (STRICMP(StringValue, (LPTSTR) REPL_KEYWORD_ROLE_EXPORT) == 0) {
+ *Role = REPL_ROLE_EXPORT;
+ } else if (STRICMP(StringValue, (LPTSTR) REPL_KEYWORD_ROLE_IMPORT) == 0) {
+ *Role = REPL_ROLE_IMPORT;
+ } else {
+
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ StringValue );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup;
+
+ }
+ (void) NetApiBufferFree( StringValue );
+ StringValue = NULL;
+
+ } else if (ApiStatus == ERROR_INVALID_DATA) { // Probably REG_DWORD...
+
+ ApiStatus = NetpGetConfigDword (
+ Handle,
+ (LPTSTR) REPL_KEYWORD_ROLE, // Key wanted
+ (DWORD) -1, // default value (none!)
+ Role ); // set *Role with default or value read
+ if (ApiStatus != NO_ERROR) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ NULL );
+ goto Cleanup; // go log error
+ } else if ( !ReplIsRoleValid( *Role ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ NULL );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup;
+ }
+
+ } else {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ NULL );
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Read the export and import paths.
+ // Unlike LM2.x, these values do not have defaults under NT.
+ //
+#define READ_PATH( keyword, output ) \
+ { \
+ ApiStatus = NetpGetConfigValue( \
+ Handle, \
+ (LPTSTR) keyword, \
+ & StringValue); \
+ if (ApiStatus == NERR_CfgParamNotFound) { \
+ ReplConfigReportBadParmValue( \
+ UncServerName, (LPTSTR) keyword, NULL ); \
+ goto Cleanup; \
+ } else if (ApiStatus == NO_ERROR) { \
+ NetpAssert( StringValue != NULL ); \
+ ApiStatus = ReplCheckAbsPathSyntax( StringValue ); \
+ if (ApiStatus == NO_ERROR) { \
+ (void) STRCPY( output, StringValue ); \
+ } else if (ApiStatus == ERROR_INVALID_DATA) { \
+ ReplConfigReportBadParmValue( \
+ UncServerName, (LPTSTR) keyword, StringValue ); \
+ goto Cleanup; \
+ } else { \
+ ReplConfigReportBadParmValue( \
+ UncServerName, (LPTSTR) keyword, StringValue ); \
+ ApiStatus = ERROR_INVALID_DATA; \
+ goto Cleanup; \
+ } \
+ (void) NetApiBufferFree( StringValue ); \
+ StringValue = NULL; \
+ } else { \
+ goto Cleanup; /* go log error */ \
+ } \
+ }
+
+ READ_PATH( REPL_KEYWORD_EXPPATH, ExportPath );
+ READ_PATH( REPL_KEYWORD_IMPPATH, ImportPath );
+
+ //
+ // Read the export and import lists.
+ //
+#define READ_LIST( keyword, default, output ) \
+ { \
+ ApiStatus = NetpGetConfigValue( \
+ Handle, \
+ (LPTSTR) keyword, \
+ & StringValue); \
+ if (ApiStatus == NERR_CfgParamNotFound) { \
+ *output = NULL; \
+ } else if (ApiStatus == NO_ERROR) { \
+ NetpAssert( output != NULL ); \
+ NetpAssert( StringValue != NULL ); \
+ if ( !ReplConfigIsListValid( StringValue ) ) { \
+ ReplConfigReportBadParmValue( \
+ UncServerName, (LPTSTR) keyword, StringValue ); \
+ ApiStatus = ERROR_INVALID_DATA; \
+ goto Cleanup; \
+ } \
+ *output = StringValue; \
+ StringValue = NULL; /* don't confuse cleanup code */ \
+ } else { \
+ goto Cleanup; /* go log error */ \
+ } \
+ }
+
+ READ_LIST( REPL_KEYWORD_EXPLIST, DEFAULT_EXPLIST, ExportList );
+ READ_LIST( REPL_KEYWORD_IMPLIST, DEFAULT_IMPLIST, ImportList );
+
+ //
+ // Read logon user name.
+ //
+ ApiStatus = NetpGetConfigValue(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_LOGON,
+ & StringValue);
+ if (ApiStatus == NERR_CfgParamNotFound) {
+ SET_STRING_TO_DEFAULT( LogonUserName, DEFAULT_LOGON );
+ } else if (ApiStatus == NO_ERROR) {
+ NetpAssert( StringValue != NULL );
+ /* BUGBUG: add error check on value! */
+ (void) STRCPY( LogonUserName, StringValue );
+ (void) NetApiBufferFree( StringValue );
+ StringValue = NULL;
+ } else {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Read interval (also called SYNC)...
+ //
+ ApiStatus = NetpGetConfigDword(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_INTERVAL,
+ DEFAULT_SYNC,
+ & DwordValue );
+ if (ApiStatus != NO_ERROR) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_INTERVAL,
+ NULL );
+ goto Cleanup; // go log error
+ }
+
+ if ( !ReplIsIntervalValid( DwordValue ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_INTERVAL,
+ NULL );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup; // go log error
+ } else {
+ * Interval = DwordValue;
+ }
+
+ //
+ // Read pulse...
+ //
+ ApiStatus = NetpGetConfigDword(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_PULSE,
+ DEFAULT_PULSE,
+ & DwordValue );
+ if (ApiStatus != NO_ERROR) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_PULSE,
+ NULL );
+ goto Cleanup; // go log error
+ }
+
+ if ( !ReplIsPulseValid( DwordValue ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_PULSE,
+ NULL );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup; // go log error
+ } else {
+ * Pulse = DwordValue;
+ }
+
+ //
+ // Read guardtime...
+ //
+ ApiStatus = NetpGetConfigDword(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_GUARD,
+ DEFAULT_GUARD,
+ & DwordValue );
+ if (ApiStatus != NO_ERROR) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_GUARD,
+ NULL );
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsGuardTimeValid( DwordValue ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_GUARD,
+ NULL );
+
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup; // go log error
+ } else if ( DwordValue > ( (*Interval) / 2 ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_GUARD,
+ NULL );
+
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup; // go log error
+ } else {
+ * GuardTime = DwordValue;
+ }
+
+ //
+ // Read random...
+ //
+ ApiStatus = NetpGetConfigDword(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_RANDOM,
+ DEFAULT_RANDOM,
+ & DwordValue );
+ if (ApiStatus != NO_ERROR) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_RANDOM,
+ NULL );
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsRandomValid( DwordValue ) ) {
+ ReplConfigReportBadParmValue(
+ UncServerName,
+ (LPTSTR) REPL_KEYWORD_RANDOM,
+ NULL );
+ ApiStatus = ERROR_INVALID_DATA;
+ goto Cleanup; // go log error
+ } else {
+ * Random = DwordValue;
+ }
+
+ ApiStatus = NO_ERROR;
+
+ //
+ // All done.
+ //
+
+Cleanup:
+
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (StringValue != NULL) {
+ (VOID) NetApiBufferFree( StringValue );
+ }
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ReplConfigRead
+
+
+
+
+
+// Write config data for the replicator.
+// Callable whether or not service is started.
+NET_API_STATUS
+ReplConfigWrite(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Role,
+ IN LPTSTR ExportPath OPTIONAL,
+ IN LPTSTR ExportList OPTIONAL,
+ IN LPTSTR ImportPath OPTIONAL,
+ IN LPTSTR ImportList OPTIONAL,
+ IN LPTSTR LogonUserName OPTIONAL,
+ IN DWORD Interval,
+ IN DWORD Pulse,
+ IN DWORD GuardTime,
+ IN DWORD Random
+ )
+{
+ NET_API_STATUS ApiStatus;
+ LPNET_CONFIG_HANDLE Handle = NULL;
+
+ //
+ // Check for caller's errors.
+ //
+ if ( !ReplIsRoleValid( Role ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplConfigIsRoleAllowed( UncServerName, Role ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplConfigIsListValid( ExportList ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplConfigIsListValid( ImportList ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsIntervalValid( Interval ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsPulseValid( Pulse ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsGuardTimeValid( GuardTime ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+ if ( !ReplIsRandomValid( Random ) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // go log error
+ }
+
+ ApiStatus = ReplCheckAbsPathSyntax( ExportPath );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ ApiStatus = ReplCheckAbsPathSyntax( ImportPath );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ // BUGBUG: Error check LogonUserName.
+
+ //
+ // Open the right section of the config file/whatever.
+ //
+ ApiStatus = NetpOpenConfigData(
+ & Handle,
+ UncServerName,
+ (LPTSTR) SECT_NT_REPLICATOR,
+ FALSE); // not read-only
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+ //
+ // Write role (replicate switch).
+ // This used to be a string (e.g. "Both"), but is now a number.
+ //
+
+ ApiStatus = NetpSetConfigDword(
+ Handle,
+ (LPTSTR) REPL_KEYWORD_ROLE,
+ Role );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // go log error
+ }
+
+#define WRITE_OPTIONAL_STRING( keyword, value ) \
+ { \
+ if ( ( (value)!=NULL) && ( (*(value)) != TCHAR_EOS ) ) { \
+ ApiStatus = NetpSetConfigValue( \
+ Handle, \
+ (LPTSTR) keyword, \
+ value ); \
+ if (ApiStatus != NO_ERROR) { \
+ goto Cleanup; /* go log error */ \
+ } \
+ } else { \
+ ApiStatus = NetpDeleteConfigKeyword( \
+ Handle, \
+ (LPTSTR) keyword); \
+ if ( (ApiStatus!=NO_ERROR) \
+ && (ApiStatus!=NERR_CfgParamNotFound) ) { \
+ goto Cleanup; /* go log error */ \
+ } \
+ } \
+ }
+
+ //
+ // Write export and import paths.
+ //
+
+#define WRITE_PATH( keyword, value ) \
+ WRITE_OPTIONAL_STRING( keyword, value )
+
+ WRITE_PATH( REPL_KEYWORD_EXPPATH, ExportPath );
+
+ WRITE_PATH( REPL_KEYWORD_IMPPATH, ImportPath );
+
+ //
+ // Write export and import lists.
+ //
+
+#define WRITE_LIST( keyword, value ) \
+ WRITE_OPTIONAL_STRING( keyword, value )
+
+ WRITE_LIST( REPL_KEYWORD_EXPLIST, ExportList );
+
+ WRITE_LIST( REPL_KEYWORD_IMPLIST, ImportList );
+
+ //
+ // Write logon user name.
+ //
+ WRITE_OPTIONAL_STRING( REPL_KEYWORD_LOGON, LogonUserName )
+
+ //
+ // Write DWORDs (interval, pulse, guardtime, random).
+ //
+
+/*lint -save -e767 */ // Don't complain about different definitions
+#define WRITE_DWORD( keyword, num ) \
+ { \
+ ApiStatus = NetpSetConfigDword( \
+ Handle, \
+ (LPTSTR) keyword, \
+ num ); \
+ if (ApiStatus != NO_ERROR) { \
+ goto Cleanup; /* go log error */ \
+ } \
+ }
+/*lint -restore */ // Resume checking for different macro definitions
+
+ WRITE_DWORD( REPL_KEYWORD_INTERVAL, Interval );
+
+ WRITE_DWORD( REPL_KEYWORD_PULSE, Pulse );
+
+ WRITE_DWORD( REPL_KEYWORD_GUARD, GuardTime );
+
+ WRITE_DWORD( REPL_KEYWORD_RANDOM, Random );
+
+ ApiStatus = NO_ERROR;
+
+Cleanup:
+
+ //
+ // All done.
+ //
+ if ( Handle != NULL ) {
+ NET_API_STATUS CloseStatus;
+
+ CloseStatus = NetpCloseConfigData( Handle );
+
+ // Return this error iff it is first error we've gotten.
+ if ( (ApiStatus == NO_ERROR) && (CloseStatus != NO_ERROR) ) {
+ ApiStatus = CloseStatus;
+ }
+ }
+
+ if (ApiStatus != NO_ERROR) {
+
+ // Log error on server we were trying to access.
+ ReplErrorLog(
+ UncServerName,
+ NELOG_ReplSysErr,
+ ApiStatus,
+ NULL,
+ NULL );
+ }
+
+ return (ApiStatus);
+
+} // ReplConfigWrite
diff --git a/private/net/svcdlls/repl/common/replconf.h b/private/net/svcdlls/repl/common/replconf.h
new file mode 100644
index 000000000..ec81336c6
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replconf.h
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplConf.h
+
+Abstract:
+
+ This file contains structures, function prototypes, and definitions
+ for the replicator "config API" workers.
+
+Author:
+
+ John Rogers (JohnRo) 15-Jan-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ You must include LmCons.h before this file.
+
+Revision History:
+
+ 15-Jan-1992 JohnRo
+ Created.
+ 20-Jan-1992 JohnRo
+ Netr prototypes are now generated by MIDL and put in repl.h.
+ 23-Jan-1992 JohnRo
+ Added ReplConfigIsLevelValid() and some prototypes.
+ 13-Feb-1992 JohnRo
+ Added ReplConfigIsApiRecordValid().
+ Added ReplConfigReportBadParmValue().
+ Clarify that certain functions can be called if service is not started.
+ 11-Mar-1992 JohnRo
+ Added support for setinfo info levels in ReplConfigIsLevelValid().
+ 24-Mar-1992 JohnRo
+ Renamed many ReplGlobal vars to ReplConfig vars.
+ 20-Jul-1992 JohnRo
+ RAID 2252: repl should prevent export on Windows/NT.
+ 14-Aug-1992 JohnRo
+ RAID 3601: repl APIs should checked import & export lists.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 05-Jan-1993 JohnRo
+ Repl WAN support (get rid of repl name list limits).
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+
+#ifndef _REPLCONF_
+#define _REPLCONF_
+
+
+#include <netlib.h> // IN_RANGE().
+
+
+BOOL
+ReplConfigIsApiRecordValid (
+ IN DWORD Level,
+ IN LPVOID ApiRecord,
+ OUT LPDWORD ParmError OPTIONAL
+ );
+
+// BOOL
+// ReplConfigIsLevelValid(
+// IN DWORD Level, // Info level
+// IN BOOL SetInfo // Are setinfo levels allowed?
+// );
+//
+#define ReplConfigIsLevelValid(Level,SetInfo) \
+ ( \
+ /*lint -e506 */ /* don't complain about constant values here */ \
+ ( (Level) == 0 ) \
+ || ( (SetInfo) && (IN_RANGE((Level), 1000, 1003)) ) \
+ /*lint +e506 */ \
+ )
+
+
+// Indicates whether or not the syntax of a list (export or import) is
+// valid. Does no checking for the existence of items in the list.
+// Callable whether or not service is started.
+BOOL
+ReplConfigIsListValid(
+ IN LPTSTR List OPTIONAL
+ );
+
+
+// Indicates whether the given role is allowed based on the current product
+// type. Callable whether or not service is started.
+BOOL
+ReplConfigIsRoleAllowed(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Role
+ );
+
+// Callable whether or not service is started.
+NET_API_STATUS
+ReplConfigAllocAndBuildApiRecord (
+ IN DWORD Level,
+ IN DWORD Role,
+ IN LPTSTR ExportPath OPTIONAL,
+ IN LPTSTR ExportList OPTIONAL,
+ IN LPTSTR ImportPath OPTIONAL,
+ IN LPTSTR ImportList OPTIONAL,
+ IN LPTSTR LogonUserName OPTIONAL,
+ IN DWORD Interval,
+ IN DWORD Pulse,
+ IN DWORD GuardTime,
+ IN DWORD Random,
+ OUT LPBYTE * BufPtr // Alloc and set pointer.
+ );
+
+
+// Callable whether or not service is started.
+NET_API_STATUS
+ReplConfigRead(
+ IN LPTSTR UncServerName OPTIONAL,
+ OUT LPDWORD Role,
+ OUT LPTSTR ExportPath,
+ OUT LPTSTR *ExportList, // Alloc and set pointer.
+ OUT LPTSTR ImportPath,
+ OUT LPTSTR *ImportList, // Alloc and set pointer.
+ OUT LPTSTR LogonUserName,
+ OUT LPDWORD Interval,
+ OUT LPDWORD Pulse,
+ OUT LPDWORD GuardTime,
+ OUT LPDWORD Random
+ );
+
+// Routine to report a bad parm value.
+// There are two different versions of this routine,
+// in client/report.c and server/error.c
+// client/report.c is callable whether or not service is started.
+// server/error.c only runs when service is starting; it talks to the service
+// controller.
+VOID
+ReplConfigReportBadParmValue(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN LPTSTR SwitchName,
+ IN LPTSTR TheValue OPTIONAL
+ );
+
+// Callable whether or not service is started.
+NET_API_STATUS
+ReplConfigWrite(
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Role,
+ IN LPTSTR ExportPath OPTIONAL,
+ IN LPTSTR ExportList OPTIONAL,
+ IN LPTSTR ImportPath OPTIONAL,
+ IN LPTSTR ImportList OPTIONAL,
+ IN LPTSTR LogonUserName OPTIONAL,
+ IN DWORD Interval,
+ IN DWORD Pulse,
+ IN DWORD GuardTime,
+ IN DWORD Random
+ );
+
+
+#endif // _REPLCONF_
diff --git a/private/net/svcdlls/repl/common/repldefs.h b/private/net/svcdlls/repl/common/repldefs.h
new file mode 100644
index 000000000..8a58fd41f
--- /dev/null
+++ b/private/net/svcdlls/repl/common/repldefs.h
@@ -0,0 +1,831 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+ repldefs.h
+
+Abstract:
+ Function prototypes and some global data
+
+Author:
+ Ported from Lan Man 2.x
+
+Environment:
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+ 10/07/91 (madana)
+ ported to NT. Converted to NT style.
+ 17-Dec-1991 JohnRo
+ Use BOOL (Win32) rather than BOOLEAN (NT) where possible..
+ Replaced tabs in source file.
+ 26-Dec-1991 JohnRo
+ Added ReplIsIntegrityValid() and ReplIsExtentValid().
+ 08-Jan-1992 JohnRo
+ Added ReplIsForceLevelValid().
+ Added and revised trace bits.
+ 20-Jan-1992 JohnRo
+ Avoid lint warnings about IF_DEBUG stuff.
+ Changed ReplMain() prototype to match svc controller's needs.
+ ReportStatus() should add thread ID to status being reported.
+ Added DWORDLEN for use in config routines.
+ Temporarily enable all debug outputs.
+ Delete REPL_SECTION (use SECT_NT_REPLICATOR in config.h instead).
+ 22-Jan-1992 JohnRo
+ Added ReplRoleIncludes{Client,Master} macros.
+ Added REPL_ROLE_STOPPED (private) equate.
+ 27-Jan-1992 JohnRo
+ Added debug trace flags for DLL stubs.
+ Moved private REPL_STATE_ equates and ReplIsStateValid() to
+ <repldefs.h>. Ditto for the _RP equates and STATE_LEN.
+ Changed to use LPTSTR etc.
+ Added ReplIsRoleValid() (checks for everything but stopped).
+ Changed macro names to ReplRoleIncludes{Export,Import}.
+ 09-Feb-1992 JohnRo
+ Set up to dynamically change role.
+ 20-Feb-1992 JohnRo
+ Added support for REPL_STATE_NOT_STARTED.
+ Added Repl{Incr,Decr}LockFields().
+ Added ReplCheckAbsPathSyntax().
+ Added ReplIs{Interval,GuardTime,Pulse,Random}Valid().
+ 22-Feb-1992 JohnRo
+ Clarify that text parm to ReplFinish() is optional.
+ 26-Feb-1992 JohnRo
+ Added ReplLockFieldsAreValid() macro.
+ Created ReplIgnoreDirOrFileName().
+ 27-Feb-1992 JohnRo
+ Changed state not started to state never replicated.
+ 05-Mar-1992 JohnRo
+ Changed ReplMain's interface to match new service controller.
+ Cranked-down max tree depth for testing only.
+ 13-Mar-1992 JohnRo
+ Fixed bug handling tree depth.
+ Wait hint is in milliseconds for new service controller.
+ 15-Mar-1992 JohnRo
+ Put back IF_DEBUG() the way it belongs.
+ 24-Mar-1992 JohnRo
+ Got rid of useless master and client termination codes.
+ Use integrity and extent equates in <lmrepl.h>.
+ Modify REPL$ share handling.
+ Put tree depth back to normal max value.
+ 25-Mar-1992 JohnRo
+ Avoid obsolete state values.
+ 09-Apr-1992 JohnRo
+ Prepare for WCHAR.H (_wcsicmp vs _wcscmpi, etc).
+ 15-Jul-1992 JohnRo
+ RAID 10503: srv mgr: repl dialog doesn't come up.
+ Avoid compiler warnings.
+ 11-Aug-1992 JohnRo
+ RAID 3288: repl svc should preserve ACLs on copy.
+ 01-Sep-1992 JohnRo
+ RAID 3721: repl svc does not stop with shutdown msg.
+ 04-Dec-1992 JohnRo
+ Repl should use filesystem change notify.
+ Added trace bits for file find routines and checksum routines.
+ Made changes suggested by PC-LINT 5.0
+ 08-Dec-1992 JohnRo
+ RAID 3316: access violation while stopping the replicator
+ 17-Dec-1992 JohnRo
+ RAID 1513: Repl does not maintain ACLs. (Also fix HPFS->FAT timestamp.)
+ Made changes suggested by PC-LINT 5.0
+ 05-Jan-1993 JohnRo
+ Repl WAN support (get rid of repl name list limits).
+ 13-Jan-1993 JohnRo
+ RAID 7053: locked trees added to pulse msg. (Actually fix all
+ kinds of remote lock handling.)
+ 15-Jan-1993 JohnRo
+ RAID 7717: Repl assert if not logged on correctly. (Also do event
+ logging for real.)
+ 22-Jan-1993 JohnRo
+ RAID 7983: Repl svc needs to change process token to really copy ACLs.
+ 17-Feb-1993 JohnRo
+ RAID 11365: Fixed various repl mailslot problems.
+ Also get rid of obsolete default import/export path equates.
+ Made PC-LINT changes for free build.
+ 25-Jan-1993 JohnRo
+ RAID 12237: replicator tree depth exceeded.
+ 30-Mar-1993 JohnRo
+ Reduce checksum frequency by using change notify on import tree.
+ 06-Apr-1993 JohnRo
+ RAID 1938: Replicator un-ACLs files when not given enough permission.
+ 21-Apr-1993 JohnRo
+ RAID 7313: repl needs change permission to work on NTFS, or we need
+ to delete files differently.
+ 07-May-1993 JohnRo
+ RAID 3258: file not updated due to ERROR_INVALID_USER_BUFFER.
+ 21-May-1993 JohnRo
+ RAID 11103: repl svc doesn't handle time being set back.
+ 10-Jun-1993 JohnRo
+ RAID 13080: Allow repl between different timezones.
+ 24-Aug-1993 JohnRo
+ RAID 788 (was 16419): Repl: spaces in computer names do not work again.
+
+--*/
+
+
+#ifndef _REPLDEFS_
+#define _REPLDEFS_
+
+
+// Don't complain about "unneeded" includes of these files:
+/*lint -efile(764,iniparm.h,lmrepl.h,netlib.h,windows.h) */
+/*lint -efile(766,iniparm.h,lmrepl.h,netlib.h,windows.h) */
+#include <windows.h> // PSECURITY_ATTRIBUTES.
+#include <iniparm.h> // MIN_SYNC, etc.
+#include <lmrepl.h> // REPL_EXTENT_FILE, etc.
+#include <netlib.h> // IN_RANGE().
+
+
+//
+// Conditional compilation options:
+//
+
+#define USE_BACKUP_APIS
+
+// Uncomment this out when GetFileSecurity() stops returning
+// ERROR_BAD_DESCRIPTOR_FORMAT for UNC names.
+#define USE_UNC_GETFILESEC
+
+
+
+//
+// Mailslot names and related lengths.
+//
+
+#define MASTER_SLOT_NAME TEXT("\\MAILSLOT\\NET\\REPL_MAS")
+#define CLIENT_SLOT_NAME TEXT("\\MAILSLOT\\NET\\REPL_CLI")
+
+// Length of CLIENT_SLOT_NAME in TCHARs, including the null char.
+#define CLIENT_SLOT_NAME_LEN ( sizeof(CLIENT_SLOT_NAME) / sizeof(TCHAR) )
+
+#define MAX_2_MSLOT_SIZE (441 - (CLIENT_SLOT_NAME_LEN + CNLEN + 1))
+
+// Length of full client slot name (including null char) in TCHARs.
+#define FULL_SLOT_NAME_SIZE (CLIENT_SLOT_NAME_LEN + CNLEN + 1 + 2)
+
+// Minimum size of DosFindFirst2 EaSize, for cbList field.
+#define EA_MIN_SIZE 4
+
+
+//
+// Various other constants.
+//
+
+#define RADIX 10
+
+#define SLASH (LPTSTR) TEXT("\\")
+#define SLASH_DOT (LPTSTR) TEXT("\\.")
+#define SLASH_DOT_DOT (LPTSTR) TEXT("\\..")
+#define SLASH_SLASH (LPTSTR) TEXT("\\\\")
+#define STAR_DOT_STAR (LPTSTR) TEXT("*.*")
+#define DOT (LPTSTR) TEXT(".")
+#define DOT_DOT (LPTSTR) TEXT("..")
+
+
+// List of separator chars we allow between names in import and export lists.
+#define REPL_LIST_DELIMITER_STR ((LPTSTR) TEXT("\t;,"))
+
+
+// Define a value for unknown file system time resolution.
+#define UNKNOWN_FS_RESOLUTION ( (DWORD) 0 )
+
+
+// DWORDLEN: DWORD takes this many decimal digits to store.
+// BUGBUG This assumes that DWORD is 32-bits or less.
+#define DWORDLEN 10
+
+
+//
+// Service controller wait hints.
+// These values are in milliseconds (formerly tenths of a second under LM 2.x).
+// Max usable wait hint is 255 tenths of a second (25.5 seconds).
+// NET.EXE's use of NetService APIs means we are stuck with this limit for now.
+//
+#define MAX_USABLE_WAIT_HINT (25500)
+
+// Service controller status wait hint. We use this for starting and
+// stopping.
+#define REPL_WAIT_HINT MAX_USABLE_WAIT_HINT
+
+
+//
+// Time might go backwards (because of syncing the clock or somebody changing
+// the date and time), so define how much of this we can ignore. This value
+// is in seconds. Since interval times are given in minutes, this value should
+// be over a minute. 110 seconds is a first guess (almost 2 minutes).
+//
+#define BACKWARDS_TIME_CHNG_ALLOWED_SECS 110
+
+
+//
+// AlertLogExit codes.
+//
+#define EXIT 1
+#define NO_EXIT 0
+
+//
+// Message types.
+//
+
+// Sync messages
+#define SYNC_MSG 1
+#define GUARD_MSG 2
+#define PULSE_MSG 3
+
+// Query messages
+#define IS_DIR_SUPPORTED 11
+#define IS_MASTER 12
+#define DIR_NOT_SUPPORTED 13
+#define DIR_SUPPORTED 14
+#define NOT_MASTER_DIR 15
+#define MASTER_DIR 16
+#define DIR_COLLIDE 17
+
+// Internal pseudo-messages
+#define GUARD_TIMEOUT 20
+#define DUPL_TIMEOUT 21
+#define PULSE_1_TIMEOUT 22
+#define PULSE_2_TIMEOUT 23
+#define PULSE_3_TIMEOUT 24
+#define NEXT_AVAILABLE_MESSAGE_NUMBER 25
+
+
+// Update opcodes.
+#define START 1
+#define UPDATE 2
+#define END 3
+#define PULSE 4
+#define GUARD 5
+
+
+// Security information to copy with the files and directories.
+// BUGBUG: Add SACL to this? Add other items when NT supports them!
+#define REPL_SECURITY_TO_COPY \
+ ( OWNER_SECURITY_INFORMATION \
+ | GROUP_SECURITY_INFORMATION \
+ | DACL_SECURITY_INFORMATION )
+
+
+
+#define REPL_SHARE (LPTSTR) TEXT("REPL$")
+
+#define REPL_INI (LPTSTR) TEXT("REPL.INI")
+
+// Unlike downlevel, we represent one or more user locks by just one file.
+// The lock count is kept in the registry.
+#define USERLOCK_NT (LPTSTR) TEXT("USERLOCK.NT$")
+
+
+#define NT_MSG_TOKEN 0xFFFFFFFF
+
+
+//
+// These former "signal file" names are now used as state strings in the
+// config data for each directory.
+//
+#define OK_RP (LPTSTR) TEXT("OK.RP$")
+#define NO_MASTER_RP (LPTSTR) TEXT("NO_MASTR.RP$")
+#define NO_SYNC_RP (LPTSTR) TEXT("NO_SYNC.RP$")
+#define NEVER_REPLICATED_RP (LPTSTR) TEXT("NEVERREP.RP$") /* Added for APIs. */
+
+//
+// Max len of the above strings. Since they were FAT file names (8.3), then
+// the max len (in chars) is 8 + 1 (dot) + 3 (extension).
+//
+#define STATE_LEN (8+1+3)
+
+
+//
+// Debug Definititions
+//
+
+#define REPL_DEBUG_REPL 0x00000001 // General debugging
+#define REPL_DEBUG_MAJOR 0x00000002 // Major events
+
+#define REPL_DEBUG_CLIENT 0x00000010 // Debug the Client
+#define REPL_DEBUG_WATCHD 0x00000020 // Debug the Watchdog thread
+#define REPL_DEBUG_SYNC 0x00000040 // Debug the Syncer thread
+
+#define REPL_DEBUG_MASTER 0x00000100 // Debug the Master
+#define REPL_DEBUG_PULSER 0x00000200 // Debug the Master
+#define REPL_DEBUG_COPYTIME 0x00000800 // Debug the time copy routines.
+
+#define REPL_DEBUG_EXPAPI 0x00010000 // Debug export API routines
+#define REPL_DEBUG_IMPAPI 0x00020000 // Debug import API routines
+#define REPL_DEBUG_REPLAPI 0x00040000 // Debug repl API routines
+
+#define REPL_DEBUG_DIRNAME 0x01000000 // Debug dirname helpers
+#define REPL_DEBUG_DLLSTUB 0x02000000 // DLL stubs.
+#define REPL_DEBUG_RPCBIND 0x04000000 // RPC bind/unbind routines.
+#define REPL_DEBUG_SVCCTRL 0x08000000 // Service controller stuff.
+#define REPL_DEBUG_FILEFIND 0x10000000 // File find routines.
+#define REPL_DEBUG_CHECKSUM 0x20000000 // Checksum routines.
+#define REPL_DEBUG_CHNGNOT 0x40000000 // Change notify routines.
+
+#define REPL_DEBUG_STALLER 0x80000000 // Staller thread stuff.
+#define REPL_DEBUG_STOPPER REPL_DEBUG_STALLER // Stopper thread too.
+
+#define REPL_DEBUG_ALL ((DWORD) -1) // All possible debug bits.
+
+
+
+// Private role (in addition to REPL_ROLE_ equates in LmRepl.h).
+#define REPL_ROLE_STOPPED ( (DWORD) 'S' ) // arbitrary value
+
+
+#undef IF_DEBUG
+
+#if DBG
+
+extern DWORD ReplGlobalTrace;
+
+#define IF_DEBUG(Function) if (ReplGlobalTrace & REPL_DEBUG_ ## Function)
+
+#else
+
+#define IF_DEBUG(Function) \
+ /*lint -save -e506 */ /* don't complain about constant values here */ \
+ if (FALSE) \
+ /*lint -restore */
+
+#endif // DBG
+
+//
+// ReplNetNameCompare
+//
+
+#ifdef UNICODE
+
+#define ReplNetNameCompare(_a, _b, _c, _e, _f ) \
+ I_NetNameCompare((_a), (_b), (_c), (_e), (_f) )
+
+#define ReplNetPathCompare(_a, _b, _c, _e, _f ) \
+ I_NetPathCompare((_a), (_b), (_c), (_e), (_f) )
+
+#else // UNICODE
+
+#define ReplNetNameCompare(_a, _b, _c, _e, _f ) \
+ stricmp( (_b), (_c) )
+
+#define ReplNetPathCompare(_a, _b, _c, _e, _f ) \
+ stricmp( (_b), (_c) )
+
+#endif // UNICODE
+
+//
+// S T R U C T U R E S
+//
+
+
+//
+// Definition of the checksum of a particular directory tree.
+//
+
+struct checksum_rec {
+ DWORD checksum;
+ DWORD count;
+};
+
+typedef struct checksum_rec CHECKSUM_REC;
+typedef struct checksum_rec * PCHECKSUM_REC;
+typedef struct checksum_rec * LPCHECKSUM_REC;
+
+// MESSAGE STRUCTURES.
+
+struct msg_header {
+ DWORD msg_type;
+ TCHAR sender[CNLEN+1];
+ TCHAR senders_domain[DNLEN+1];
+};
+
+typedef struct msg_header MSG_HEADER;
+typedef struct msg_header *PMSG_HEADER;
+typedef struct msg_header *LPMSG_HEADER;
+
+struct status_rec {
+ TCHAR dir_name[PATHLEN];
+ DWORD opcode; // 1 - start, 2 - update, 3 - end.
+ DWORD checksum;
+ DWORD count;
+ DWORD integrity;
+ DWORD extent;
+};
+
+typedef struct status_rec STATUS_REC;
+typedef struct status_rec *PSTATUS_REC;
+typedef struct status_rec *LPSTATUS_REC;
+
+struct msg_status_rec {
+ DWORD dir_name_offset; // offset where name string is
+ // from msg buffer start
+
+ DWORD opcode; // 1 - start, 2 - update, 3 - end.
+ DWORD checksum;
+ DWORD count;
+ DWORD integrity;
+ DWORD extent;
+
+};
+
+typedef struct msg_status_rec MSG_STATUS_REC;
+typedef struct msg_status_rec *PMSG_STATUS_REC;
+typedef struct msg_status_rec *LPMSG_STATUS_REC;
+
+struct repl_info {
+ DWORD random;
+ DWORD sync_rate;
+ DWORD pulse_rate;
+ DWORD guard_time;
+};
+
+typedef struct repl_info REPL_INFO;
+typedef struct repl_info *PREPL_INFO;
+typedef struct repl_info *LPREPL_INFO;
+
+struct query_msg {
+ MSG_HEADER header;
+ TCHAR dir_name[PATHLEN]; // ASCIIZ dir/tree name.
+};
+
+typedef struct query_msg QUERY_MSG;
+typedef struct query_msg *PQUERY_MSG;
+typedef struct query_msg *LPQUERY_MSG;
+
+struct sync_msg {
+ MSG_HEADER header;
+ REPL_INFO info;
+ DWORD update_count;
+
+ //
+ // here come update_count msg_status_rec records, the file name strings
+ // stuffed at the end of the buffer by NetPackStr, dir_name is the
+ // offset from the start of the message.
+ //
+
+};
+
+typedef struct sync_msg SYNCMSG;
+typedef struct sync_msg *PSYNCMSG;
+typedef struct sync_msg *LPSYNCMSG;
+
+//
+// Global procedure definitions
+//
+
+VOID
+AlertLogExit(
+ IN NET_API_STATUS alert_code,
+ IN NET_API_STATUS errlog_code,
+ IN NET_API_STATUS sys_code,
+ IN LPTSTR str1,
+ IN LPTSTR str2,
+ IN BOOL exit_flag
+ );
+
+VOID
+ReportStatus(
+ IN DWORD State,
+ IN NET_API_STATUS ApiStatus,
+ IN DWORD WaitHint,
+ IN DWORD CheckPoint
+ );
+
+VOID
+ReplFinish (
+ IN NET_API_STATUS ApiStatus
+ );
+
+VOID
+ScanTree(
+ IN LONG MasterTimeZoneOffsetSecs, // exporter offset from GMT
+ IN OUT LPTSTR Path, // path plus scratch space (to PATHLEN+1)
+ OUT PCHECKSUM_REC ScanRec
+ );
+
+VOID
+ScanDir(
+ IN LONG MasterTimeZoneOffsetSecs, // exporter offset from GMT
+ IN OUT LPTSTR Path, // path plus scratch space (to PATHLEN+1)
+ OUT PCHECKSUM_REC ScanRec,
+ IN DWORD Flag
+ );
+
+NET_API_STATUS
+Parse(
+ IN DWORD argc,
+ IN LPTSTR argv[]
+ );
+
+VOID
+ReplMain(
+ IN DWORD dwNumServicesArgs,
+ IN LPTSTR *lpServiceArgVectors
+ );
+
+VOID
+InitParseData(
+ VOID
+ );
+
+VOID
+FreeParseData(
+ VOID
+ );
+
+DWORD
+ReplMasterMain(
+ IN LPVOID parm // NULL if service is starting; non-NULL if role is changing
+ );
+
+// BOOL
+// ReplAreLockFieldsValid (
+// IN DWORD LockCount,
+// IN DWORD LockTime
+// );
+//
+#define ReplAreLockFieldsValid(LockCount,LockTime) \
+ ( ( ((LockCount)!=0) && ((LockTime)!=0) ) \
+ || ( ((LockCount)==0) && ((LockTime)==0) ) )
+
+NET_API_STATUS
+ReplChangeRole(
+ IN DWORD NewRole
+ );
+
+NET_API_STATUS
+ReplCheckAbsPathSyntax (
+ IN LPTSTR AbsPath
+ );
+
+DWORD
+ReplClientMain(
+ IN LPVOID parm // NULL if service is starting; non-NULL if role is changing
+ );
+
+NET_API_STATUS
+ReplCopyDirectoryItself(
+ IN LPCTSTR SourcePath,
+ IN LPCTSTR DestPath,
+ IN BOOL bFailIfExists
+ );
+
+NET_API_STATUS
+ReplCopyFile(
+ IN LPCTSTR SourcePath,
+ IN LPCTSTR DestPath,
+ IN BOOL bFailIfExists
+ );
+
+VOID
+ReplCopyJustDateTime(
+ IN LPCTSTR SourcePath,
+ IN LPCTSTR DestPath,
+ IN BOOL IsDirectory
+ );
+
+NET_API_STATUS
+ReplCopySecurity(
+ IN LPCTSTR SourcePath,
+ IN LPCTSTR DestPath
+ );
+
+NET_API_STATUS
+ReplDecrLockFields (
+ IN OUT LPDWORD LockCountPtr,
+ IN OUT LPDWORD LockTimePtr,
+ IN DWORD UnlockForce // Use REPL_UNLOCK_FORCE or REPL_UNLOCK_NOFORCE.
+ );
+
+NET_API_STATUS
+ReplDeleteFile(
+ IN LPCTSTR FileName
+ );
+
+NET_API_STATUS
+ReplDisableBackupPermission(
+ VOID
+ );
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ReplDoUserLockFilesExist(
+ IN LPCTSTR Path, // May be absolute path (with drive) or UNC path.
+ OUT LPBOOL IsLockedPtr
+ );
+
+NET_API_STATUS
+ReplEnableBackupPermission(
+ VOID
+ );
+
+VOID
+ReplErrorLog(
+ IN LPCTSTR UncServerName OPTIONAL,
+ IN NET_API_STATUS l_code,
+ IN NET_API_STATUS s_code,
+ IN LPTSTR str1 OPTIONAL,
+ IN LPTSTR str2 OPTIONAL
+ );
+
+BOOL
+ReplFileOrDirExists(
+ IN LPCTSTR FileName
+ );
+
+DWORD
+ReplGetEaSize(
+ IN LPCTSTR Path
+ );
+
+BOOL
+ReplIsFileTimeCloseEnough(
+ IN LPVOID MasterFileTime, // Points to a FILETIME value.
+ IN LPVOID ClientFileTime // Points to a FILETIME value.
+ );
+
+// Returns UNKNOWN_FS_RESOLUTION on error.
+DWORD
+ReplGetFsTimeResolutionSecs(
+ IN LPCTSTR AbsPath
+ );
+
+BOOL
+ReplIgnoreDirOrFileName (
+ IN LPTSTR Name
+ );
+
+NET_API_STATUS
+ReplIncrLockFields (
+ IN OUT LPDWORD LockCountPtr,
+ IN OUT LPDWORD LockTimePtr
+ );
+
+NET_API_STATUS
+ReplInitAnyList(
+ IN LPCTSTR UncanonList OPTIONAL,
+ IN OUT LPTSTR ** NameListPtr, // Allocated by this routine (or set to NULL).
+ IN LPCTSTR ConfigKeywordName,
+ OUT LPDWORD EntryCount
+ );
+
+NET_API_STATUS
+ReplInitBackupPermission(
+ VOID
+ );
+
+// BOOL
+// ReplIsExtentValid(
+// IN DWORD parm
+// );
+//
+#define ReplIsExtentValid(parm) \
+ ( ((parm) == REPL_EXTENT_FILE) || ((parm) == REPL_EXTENT_TREE) )
+
+// BOOL
+// ReplIsForceLevelValid(
+// IN DWORD Force
+// );
+//
+#define ReplIsForceLevelValid(Force) \
+ ( ((Force) == REPL_UNLOCK_FORCE) || ((Force) == REPL_UNLOCK_NOFORCE) )
+
+// BOOL
+// ReplIsGuardTimeValid(
+// IN DWORD parm
+// );
+//
+#if MIN_GUARD // low bound > 0
+#define ReplIsGuardTimeValid(parm) \
+ ( IN_RANGE( (parm), MIN_GUARD, MAX_GUARD ) )
+#else // MIN_GUARD is zero.
+#define ReplIsGuardTimeValid(parm) \
+ ( (parm) <= MAX_GUARD )
+#endif
+
+// BOOL
+// ReplIsIntegrityValid(
+// IN DWORD parm
+// );
+//
+#define ReplIsIntegrityValid(parm) \
+ ( ((parm) == REPL_INTEGRITY_FILE) || ((parm) == REPL_INTEGRITY_TREE) )
+
+// BOOL
+// ReplIsIntervalValid(
+// IN DWORD parm
+// );
+//
+#define ReplIsIntervalValid(parm) \
+ ( IN_RANGE((parm), MIN_SYNC, MAX_SYNC) )
+
+// BOOL
+// ReplIsPulseValid(
+// IN DWORD parm
+// );
+//
+#define ReplIsPulseValid(parm) \
+ ( IN_RANGE(parm, MIN_PULSE, MAX_PULSE) )
+
+// BOOL
+// ReplIsRandomValid(
+// IN DWORD parm
+// );
+//
+#define ReplIsRandomValid(parm) \
+ ( IN_RANGE((parm), MIN_RANDOM, MAX_RANDOM) )
+
+// BOOL
+// ReplIsRoleValid(
+// IN DWORD role
+// );
+//
+// Check for valid roles (not including stopped, which is for internal use).
+//
+#define ReplIsRoleValid(role) \
+ ( ((role) == REPL_ROLE_BOTH) \
+ || ((role) == REPL_ROLE_EXPORT) \
+ || ((role) == REPL_ROLE_IMPORT) )
+
+
+// Check for valid state. This includes the "private" state values.
+#define ReplIsStateValid( State ) \
+ ( ((State)==REPL_STATE_OK) \
+ || ((State)==REPL_STATE_NO_MASTER) \
+ || ((State)==REPL_STATE_NO_SYNC) \
+ || ((State)==REPL_STATE_NEVER_REPLICATED) )
+
+NET_API_STATUS
+ReplMakeSecurityAttributes(
+ IN LPCTSTR SourcePath,
+ OUT PSECURITY_ATTRIBUTES * DestSecurityAttrPtr // alloc and set ptr
+ );
+
+NET_API_STATUS
+ReplMarshallQueryMsg(
+ IN PBYTE InBuf,
+ OUT PBYTE OutBuf,
+ IN LPDWORD BytesRead
+ );
+
+
+// BOOL
+// ReplRoleIncludesExport(role)
+// IN DWORD Role
+// );
+#define ReplRoleIncludesExport(role) \
+ ( ((role) == REPL_ROLE_EXPORT) || ((role) == REPL_ROLE_BOTH) )
+
+
+// BOOL
+// ReplRoleIncludesImport(role)
+// IN DWORD Role
+// );
+#define ReplRoleIncludesImport(role) \
+ ( ((role) == REPL_ROLE_IMPORT) || ((role) == REPL_ROLE_BOTH) )
+
+DWORD
+ReplStaller(
+ IN LPVOID Parm
+ );
+
+DWORD
+ReplStopper(
+ IN LPVOID Parm
+ );
+
+VOID
+ReplStopService(
+ VOID
+ );
+
+NET_API_STATUS
+ReplUnmarshallMessage(
+ IN PBYTE InBuf,
+ IN DWORD InBufLen,
+ OUT PBYTE OutBuf,
+ IN DWORD OutBufLen,
+ OUT LPDWORD BytesRead
+ );
+
+NET_API_STATUS
+ReplUnmarshallSyncMsg(
+ IN PBYTE InBuf,
+ IN DWORD InBufLen,
+ OUT PBYTE OutBuf,
+ IN DWORD OutBufLen,
+ OUT LPDWORD BytesRead
+ );
+
+NET_API_STATUS
+ReplUnmarshallQueryMsg(
+ IN PBYTE InBuf,
+ IN DWORD InBufLen,
+ OUT PBYTE OutBuf,
+ IN DWORD OutBufLen,
+ OUT LPDWORD BytesRead
+ );
+
+
+#endif // _REPLDEFS_
diff --git a/private/net/svcdlls/repl/common/replerr.c b/private/net/svcdlls/repl/common/replerr.c
new file mode 100644
index 000000000..510fe5161
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replerr.c
@@ -0,0 +1,298 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplErr.c
+
+Abstract:
+
+ Contains one routine for error handling: ReplErrorLog().
+
+ This routine is shared by the APIs (client side) and the service itself.
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft) 21-Jan-1993
+ (Actually, just massive rework of LM 2.x code via MadanA and RitaW.)
+
+Environment:
+
+ User mode only.
+ Uses Win32 stuff: ReportEvent(), etc.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 21-Jan-1993 JohnRo
+ Created for RAID 7717: Repl assert if not logged on correctly. (Also
+ do event logging for real.)
+ 15-Feb-1993 JohnRo
+ RAID 10685: user name not in repl event log.
+ 13-May-1993 JohnRo
+ RAID 9741: Replicator logs same event over and over.
+ Changed debug bit to MAJOR for this.
+ Changed debug output on errors to be unconditional.
+
+--*/
+
+
+// These must be included first:
+
+#define NOMINMAX // Let stdlib.h define min() and max()
+#include <windows.h> // LocalFree(), ReportEvent(), etc.
+#include <lmcons.h>
+
+// These may be included in any order:
+
+#include <icanon.h> // NetpIsRemote(), ISREMOTE, etc.
+#include <lmsname.h> // SERVICE_REPL.
+#include <netdebug.h> // DBGSTATIC, NetpKdPrint(), FORMAT_ equates, etc.
+#include <netlib.h> // NetpGetUserSid().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // My prototypes.
+#include <tstr.h> // ULTOA(). (includes stdlib.h)
+
+
+//
+// Static values which we use to prevent logging the same error code over
+// and over.
+// BUGBUG: Add server name, str1, str2 static variables someday.
+//
+
+DBGSTATIC NET_API_STATUS ReplLastLogCode = NO_ERROR;
+DBGSTATIC NET_API_STATUS ReplLastApiStatus = NO_ERROR;
+
+
+VOID
+ReplErrorLog(
+ IN LPCTSTR UncServerName OPTIONAL,
+ IN NET_API_STATUS LogCode,
+ IN NET_API_STATUS StatusCode,
+ IN LPTSTR str1 OPTIONAL,
+ IN LPTSTR str2 OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Writes entry into event log.
+
+ This is a recursive routine. It writes a message remotely and then
+ recursively calls itself to copy the message locally.
+
+Arguments:
+
+ UncServerName - Name of server on which to log this error.
+
+ LogCode - Error log msg code (must appear in lmerrlog.h).
+
+ StatusCode - In case of system / network error, the code. Should be zero
+ if not needed for message.
+
+ str1 - Merge string for msg. Should be NULL if not needed for message.
+
+ str2 - Merge string for msg. Should be NULL if not needed for message.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NET_API_STATUS ApiStatus;
+ TCHAR ErrCodeString[DWORDLEN+1]; // Long enough for any status.
+ HANDLE LogHandle = NULL;
+ LPTSTR StringArray[3]; // Space for ptrs to err code, str1, str2.
+ WORD StringCount = 0; // Num of ptrs in StringArray (so far).
+ BOOL SuccessFlag;
+ PSID UserSid = NULL;
+
+
+ IF_DEBUG( MAJOR ) {
+ NetpKdPrint(( PREFIX_REPL
+ "Error log message: " FORMAT_API_STATUS, LogCode ));
+
+ }
+
+ //
+ // Is this a redundant event log?
+ //
+ // To make life easier on ourselves,
+ // we only avoid redundant logs of local events with no optional strings.
+ // That covers the common cases well (like NELOG_ReplSysErr).
+ // And we don't have to worry about allocating/deallocating the strings
+ // either.
+ //
+
+ if ( (LogCode==ReplLastLogCode)
+ && (StatusCode==ReplLastApiStatus)
+ && (UncServerName==NULL)
+ && (str1==NULL)
+ && (str2==NULL) ) {
+
+ goto Cleanup; // Yes, this is redundant.
+ }
+
+ ReplLastLogCode = LogCode;
+ ReplLastApiStatus = StatusCode;
+
+ //
+ // Is sys/net error specified? If so, convert to string and store
+ // pointer in StringArray.
+ //
+
+ if (StatusCode != 0) {
+
+ (VOID) ULTOA(StatusCode, ErrCodeString, RADIX);
+
+ StringArray[StringCount] = ErrCodeString;
+ ++StringCount;
+
+ IF_DEBUG( MAJOR ) {
+ NetpKdPrint(( " " FORMAT_API_STATUS, StatusCode ));
+ }
+ }
+
+ //
+ // Now take care of (optional) char strings.
+ //
+
+ if (str1 != NULL) {
+ StringArray[StringCount] = str1;
+ ++StringCount;
+
+ IF_DEBUG( MAJOR ) {
+ NetpKdPrint(( " " FORMAT_LPTSTR, str1 ));
+ }
+ }
+ if (str2 != NULL) {
+ StringArray[StringCount] = str2;
+ ++StringCount;
+
+ IF_DEBUG( MAJOR ) {
+ NetpKdPrint(( " " FORMAT_LPTSTR, str2 ));
+ }
+ }
+
+ IF_DEBUG( MAJOR ) {
+ NetpKdPrint(( "\n" ));
+ }
+
+ NetpAssert( StringCount <= 3 ); // Update StringArray size if not.
+
+ //
+ // Get event log handle using out service name as source.
+ //
+
+ LogHandle = RegisterEventSource(
+ (LPTSTR) UncServerName,
+ (LPTSTR) SERVICE_REPL );
+
+ if (LogHandle == NULL) {
+ NetpKdPrint(( PREFIX_REPL "RegisterEventSource FAILED! status: "
+ FORMAT_API_STATUS "\n",
+ (NET_API_STATUS) GetLastError() ));
+ // Nothing to do; we can't log the fact that we can't log an error!
+ goto Cleanup;
+ }
+
+ //
+ // Get SID of user which invoked this thread, if applicable.
+ //
+
+ ApiStatus = NetpGetUserSid(
+ &UserSid ); // alloc and set ptr (free with LocalFree).
+
+ if (ApiStatus != NO_ERROR) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplErrorLog: Can't get SID for user, status="
+ FORMAT_API_STATUS "...\n", ApiStatus ));
+
+ // Log without user ID is better than none, so continue...
+ UserSid = NULL;
+ }
+
+ //
+ // Log the error code specified.
+ //
+
+ SuccessFlag = ReportEvent(
+ LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // Event category.
+ LogCode, // Message ID.
+ UserSid,
+ StringCount,
+ 0, // Zero bytes of raw data.
+ StringArray, // Pointer to array of ptrs to insert strings.
+ (PVOID) NULL ); // No pointer to raw data.
+
+ if ( !SuccessFlag ) {
+
+ ApiStatus = (NET_API_STATUS) GetLastError();
+ NetpAssert( ApiStatus != NO_ERROR );
+
+ NetpKdPrint(( PREFIX_REPL
+ "FAILED ReportEvent call, status " FORMAT_API_STATUS ".\n",
+ ApiStatus ));
+
+ // Not much else we can do but continue...
+ }
+
+ //
+ // We're done with the event log handle.
+ //
+
+ SuccessFlag = DeregisterEventSource(LogHandle);
+
+ if ( !SuccessFlag ) {
+
+ ApiStatus = (NET_API_STATUS) GetLastError();
+ NetpAssert( ApiStatus != NO_ERROR );
+
+ NetpKdPrint(( PREFIX_REPL
+ "FAILED DeregisterEventSource call, status "
+ FORMAT_API_STATUS ".\n",
+ ApiStatus ));
+
+ // Not much else we can do but continue...
+ }
+
+ //
+ // If we were doing a remote message, then log a copy locally.
+ //
+ if ( (UncServerName!=NULL) && (UncServerName[0]!=TCHAR_EOS) ) {
+
+ DWORD Location;
+
+ ApiStatus = NetpIsRemote(
+ (LPTSTR) UncServerName, // input: uncanon name
+ & Location, // output: local or remote flag
+ NULL, // don't need canon name output
+ 0); // flags: normal
+
+ if ( (ApiStatus!=NO_ERROR) || (Location==(DWORD)ISREMOTE) ) {
+
+ // RECURSIVE CALL: Log error locally too, just in case.
+ ReplErrorLog(
+ NULL, // No server name this time.
+ LogCode,
+ StatusCode,
+ str1,
+ str2 );
+ }
+ }
+
+ //
+ // Clean up...
+ //
+
+Cleanup:
+
+ if (UserSid != NULL) {
+ (VOID) LocalFree( UserSid );
+ }
+
+}
diff --git a/private/net/svcdlls/repl/common/replgbl.h b/private/net/svcdlls/repl/common/replgbl.h
new file mode 100644
index 000000000..44d99c8bd
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replgbl.h
@@ -0,0 +1,139 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplGbl.h
+
+Abstract:
+
+ Constants and some global data definition.
+
+Author:
+
+ Ported from Lan Man 2.x
+
+Environment:
+
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Notes:
+
+ The caller must include <lmcons.h> before this file.
+
+Revision History:
+
+ 10/28/91 (madana)
+ ported to NT. Converted to NT style.
+ 20-Jan-1992 JohnRo
+ Changed file name from repl.h to replgbl.h to avoid MIDL conflict.
+ More changes suggested by PC-LINT.
+ 22-Jan-1992 JohnRo
+ Moved current role from P_repl_sw to ReplGlobalRole.
+ 24-Jan-1992 JohnRo
+ Changed to use LPTSTR etc.
+ Added ReplGlobal variables corresponding to the old P_ variables.
+ 09-Feb-1992 JohnRo
+ Set up to dynamically change role.
+ 05-Mar-1992 JohnRo
+ Changed ReplMain's interface to match new service controller.
+ 06-Mar-1992 JohnRo
+ Avoid starting RPC server too soon.
+ 24-Mar-1992 JohnRo
+ Renamed many ReplGlobal vars to ReplConfig vars.
+ 11-Aug-1992 JohnRo
+ RAID 2115: repl svc should wait while stopping or changing roles.
+ 08-Dec-1992 JohnRo
+ RAID 3316: access violation while stopping the replicator
+ 05-Jan-1993 JohnRo
+ Repl WAN support (get rid of repl name list limits).
+ 24-May-1993 JohnRo
+ RAID 10587: repl could deadlock with changed NetpStopRpcServer(), so
+ just call ExitProcess() instead.
+
+--*/
+
+
+#ifndef _REPLGBL_
+#define _REPLGBL_
+
+
+#include <netlock.h> // LPNET_LOCK.
+//#include <repldefs.h> // MAX_NAME_BUF.
+#include <winsvc.h> // SERVICE_STATUS_HANDLE, etc.
+
+
+//
+// "config" variables (read at startup and settable by NetReplSetInfo).
+//
+
+extern LPNET_LOCK ReplConfigLock; // decl and init in repl.c
+extern DWORD ReplConfigRole; // Locked by ReplConfigLock.
+extern TCHAR ReplConfigExportPath[PATHLEN+1]; // Ditto.
+extern LPTSTR ReplConfigExportList; // Ditto.
+extern TCHAR ReplConfigImportPath[PATHLEN+1]; // Ditto.
+extern LPTSTR ReplConfigImportList; // Ditto.
+extern TCHAR ReplConfigLogonUserName[UNLEN+1]; // Ditto.
+extern DWORD ReplConfigInterval; // Ditto.
+extern DWORD ReplConfigPulse; // Ditto.
+extern DWORD ReplConfigGuardTime; // Ditto.
+extern DWORD ReplConfigRandom; // Ditto.
+
+//
+// Variables to control termination of the service.
+//
+
+extern HANDLE ReplGlobalClientTerminateEvent;
+extern HANDLE ReplGlobalMasterTerminateEvent;
+
+//
+// Variables to control service startup.
+//
+
+extern HANDLE ReplGlobalExportStartupEvent;
+extern HANDLE ReplGlobalImportStartupEvent;
+
+//
+// Variables to control service stop.
+//
+
+extern BOOL ReplGlobalIsServiceStopping;
+extern DWORD ReplGlobalCheckpoint;
+
+//
+// client thread handle
+//
+extern HANDLE ReplGlobalClientThreadHandle;
+
+
+//
+// master thread handle
+//
+extern HANDLE ReplGlobalMasterThreadHandle;
+
+
+//
+// Variables to control service error report.
+//
+
+extern SERVICE_STATUS_HANDLE ReplGlobalServiceHandle;
+extern DWORD ReplGlobalUninstallUicCode;
+
+//
+// We talk to both downlevel and NT clients, who want ANSI and Unicode
+// strings respectively. So, let's maintain copies of this (presumably
+// constant) data in both forms:
+//
+extern WCHAR ReplGlobalUnicodeComputerName[CNLEN+1];
+extern WCHAR ReplGlobalUnicodeDomainName[DNLEN+1];
+
+extern CHAR ReplGlobalAnsiComputerName[CNLEN+1];
+extern CHAR ReplGlobalAnsiDomainName[DNLEN+1];
+
+extern LPTSTR ReplGlobalComputerName; // points to one of the above.
+extern LPTSTR ReplGlobalDomainName; // points to one of the above.
+
+
+#endif // _REPLGBL_
diff --git a/private/net/svcdlls/repl/common/replname.h b/private/net/svcdlls/repl/common/replname.h
new file mode 100644
index 000000000..36afcecc2
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replname.h
@@ -0,0 +1,35 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ReplName.h
+
+Abstract:
+
+ Private header file which defines the replicator's interface name.
+
+Author:
+
+ John Rogers (JohnRo) 16-Jan-1992
+
+Revision History:
+
+ 16-Jan-1992 JohnRo
+ Created the repl service RPC stuff from Rita's workstation RPC stuff.
+ 16-Dec-1992 JohnRo
+ Made changes suggested by PC-LINT 5.0
+ Made this file include-able multiple times.
+
+--*/
+
+
+#ifndef _REPLNAME_
+#define _REPLNAME_
+
+
+#define REPLICATOR_INTERFACE_NAME (LPTSTR) TEXT("repl")
+
+
+#endif // _REPLNAME_
diff --git a/private/net/svcdlls/repl/common/replp.c b/private/net/svcdlls/repl/common/replp.c
new file mode 100644
index 000000000..f474e28aa
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replp.c
@@ -0,0 +1,271 @@
+/*++
+
+Copyright (c) 1987-92 Microsoft Corporation
+
+Module Name:
+
+ replp.c
+
+Abstract:
+
+ contains library functions that may be moved to netlib later.
+
+Author:
+
+ 10/24/91 madana
+
+Environment:
+
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 16-Jan-1992 JohnRo
+ Avoid using private logon functions.
+ Fixed bug regarding returned value from NetpReplWriteMail functions.
+ Fixed mistake in NetpKdPrint format string by using equate.
+ 23-Jan-1992 JohnRo
+ Indicate that NetpReplTimeNow(()) can be called even if service is
+ 30-Jan-1992 JohnRo
+ Made changes suggested by PC-LINT.
+ 17-Feb-1992 JohnRo
+ Added a little checking of mailslot name.
+ 21-Feb-1992 JohnRo
+ Minor changes to mailslot name handling.
+ 27-Feb-1992 JohnRo
+ Added debug code regarding NetpReplTimeNow().
+ 11-Nov-1992 JohnRo
+ Fixed handle leak if WriteFile() fails.
+ More debug output of time.
+ Use PREFIX_ equates.
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windef.h>
+#include <winbase.h>
+
+#include <lmcons.h>
+#include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates, etc.
+#include <netlib.h> // NetpMemoryFree().
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // IF_DEBUG().
+#include <tstring.h> // NetpAlloc{type}From{type}(), etc.
+#include <winerror.h> // NO_ERROR, ERROR_ equates.
+
+
+DWORD
+NetpReplTimeNow(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Returns the current time in terms of number of seconds since
+ Jan 1, 1970.
+
+ Note that this can be called even if service is not started.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the current time in terms of number of seconds since
+ Jan 1, 1970.
+
+--*/
+{
+ BOOL ConvOk;
+ NTSTATUS NtStatus;
+ LARGE_INTEGER TimeNow;
+ DWORD Time1970;
+
+#define SOME_BOGUS_VALUE 12345
+
+ NtStatus = NtQuerySystemTime( &TimeNow );
+ NetpAssert( NT_SUCCESS( NtStatus ) );
+
+ Time1970 = SOME_BOGUS_VALUE;
+ ConvOk = RtlTimeToSecondsSince1970( &TimeNow, (PULONG) &Time1970 );
+
+ IF_DEBUG( REPL ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetpReplTimeNow: RTL says it is " FORMAT_DWORD ".\n",
+ Time1970 ));
+ NetpDbgDisplayTimestamp( " (formatted)", Time1970 );
+ }
+ NetpAssert( ConvOk );
+ NetpAssert( Time1970 != SOME_BOGUS_VALUE );
+
+ return Time1970;
+
+} // NetpReplTimeNow
+
+
+
+
+NET_API_STATUS
+NetpReplWriteMailW(
+ IN LPWSTR MailslotName,
+ IN LPBYTE Message,
+ IN DWORD MessageLength
+ )
+/*++
+
+Routine Description :
+
+ Writes a mail message to the specified mailslot.
+
+Arguments :
+
+ MailslotName : Name of the mailslot where to write the mail
+ Message : mail message
+ Messagelength : mail message length
+
+Return Value :
+
+ NO_ERROR : if the mail is successfully written to the mailslot
+ (other) : otherwise error code from CreateFileW or WriteFile.
+
+Threads:
+
+ Only called by master, pulser, and syncer threads.
+
+--*/
+{
+
+ NET_API_STATUS ApiStatus;
+ HANDLE FileHandle;
+ DWORD NumberOfBytesWritten;
+
+ NetpAssert( MailslotName != NULL );
+ NetpAssert( MailslotName[0] == L'\\' );
+ NetpAssert( MailslotName[1] == L'\\' );
+
+ NetpAssert( Message != NULL );
+ NetpAssert( MessageLength != 0 );
+
+ //
+ // Open the mailslot to write.
+ //
+
+ FileHandle = CreateFileW(
+ MailslotName,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+
+ if ( FileHandle == (HANDLE) (-1)) {
+ ApiStatus = GetLastError();
+ NetpKdPrint(( PREFIX_REPL
+ "Problem with opening mailslot '" FORMAT_LPWSTR
+ "', error " FORMAT_API_STATUS ".\n",
+ MailslotName, ApiStatus));
+
+ NetpAssert( ApiStatus != NO_ERROR );
+ NetpAssert( ApiStatus != ERROR_INVALID_FUNCTION );
+
+ return (ApiStatus);
+ }
+
+
+
+ //
+ // Write message to mailslot
+ //
+
+ if ( !WriteFile(
+ FileHandle,
+ Message,
+ MessageLength,
+ &NumberOfBytesWritten,
+ NULL
+ ) ) {
+
+ ApiStatus = GetLastError();
+
+ NetpKdPrint(( PREFIX_REPL
+ "Error writing to " FORMAT_LPWSTR
+ " mailslot, error " FORMAT_API_STATUS ".\n",
+ MailslotName, ApiStatus));
+
+ NetpAssert( ApiStatus != NO_ERROR );
+ NetpAssert( ApiStatus != ERROR_INVALID_FUNCTION );
+
+ (VOID) CloseHandle(FileHandle);
+ return (ApiStatus);
+ }
+
+ (VOID) CloseHandle(FileHandle);
+
+ return (NO_ERROR);
+
+} // NetpReplWriteMailW
+
+
+
+
+NET_API_STATUS
+NetpReplWriteMailA(
+ IN LPSTR MailslotName,
+ IN LPBYTE Message,
+ IN DWORD MessageLength
+ )
+/*++
+
+Routine Description :
+
+ Same as NetpReplWriteMailW, but the mailslot name is specified as
+ ANSI string.
+
+ Writes a mail message to the specified mailslot.
+
+Arguments :
+
+ MailslotName : Name of the mailslot where to write the mail
+ Message : mail message
+ Messagelength : mail message length
+
+Return Value :
+
+ NO_ERROR : if the mail is successfully written to the mailslot
+ (other) : otherwise error code from CreateFileW or WriteFile.
+
+--*/
+{
+
+ NET_API_STATUS ApiStatus;
+ LPWSTR UnicodeMailslotName;
+
+ NetpAssert( MailslotName != NULL );
+ NetpAssert( MailslotName[0] == '\\' );
+ NetpAssert( MailslotName[1] == '\\' );
+
+ NetpAssert( Message != NULL );
+ NetpAssert( MessageLength != 0 );
+
+ UnicodeMailslotName = NetpAllocWStrFromStr( MailslotName );
+
+ if( UnicodeMailslotName == NULL) {
+
+ return (ERROR_NOT_ENOUGH_MEMORY);
+
+ }
+
+ ApiStatus = NetpReplWriteMailW(UnicodeMailslotName, Message, MessageLength);
+
+ NetpMemoryFree( UnicodeMailslotName );
+
+ return (ApiStatus);
+
+} // NetpReplWriteMailA
diff --git a/private/net/svcdlls/repl/common/replp.h b/private/net/svcdlls/repl/common/replp.h
new file mode 100644
index 000000000..fcdbee408
--- /dev/null
+++ b/private/net/svcdlls/repl/common/replp.h
@@ -0,0 +1,70 @@
+/*++
+
+Copyright (c) 1987-92 Microsoft Corporation
+
+Module Name:
+
+ replp.h
+
+Abstract:
+
+ contains library functions that may be moved to netlib later.
+
+Author:
+
+ 10/24/91 madana
+
+Environment:
+
+ Contains NT-specific code.
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 05-Jan-1992 JohnRo
+ Fixed bug regarding returned value from NetpReplWriteMail functions.
+ 23-Jan-1992 JohnRo
+ Indicate that NetpReplTimeNow() can be called even if service is
+ not started.
+
+--*/
+
+
+#ifndef _REPLP_
+#define _REPLP_
+
+
+#ifdef UNICODE
+
+#define NetpReplWriteMail NetpReplWriteMailW
+
+#else // UNICODE
+
+#define NetpReplWriteMail NetpReplWriteMailA
+
+#endif // UNICODE
+
+
+NET_API_STATUS
+NetpReplWriteMailW(
+ IN LPWSTR,
+ IN LPBYTE,
+ IN DWORD
+ );
+
+NET_API_STATUS
+NetpReplWriteMailA(
+ IN LPSTR,
+ IN LPBYTE,
+ IN DWORD
+ );
+
+// Return number of seconds since 1970.
+// This can be called even if service is not started.
+DWORD
+NetpReplTimeNow(
+ VOID
+ );
+
+
+#endif // _REPLP_
diff --git a/private/net/svcdlls/repl/common/repvalid.c b/private/net/svcdlls/repl/common/repvalid.c
new file mode 100644
index 000000000..428b891b6
--- /dev/null
+++ b/private/net/svcdlls/repl/common/repvalid.c
@@ -0,0 +1,198 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ RepValid.c
+
+Abstract:
+
+ This file contains ReplConfigIsApiRecordValid().
+
+Author:
+
+ John Rogers (JohnRo) 14-Feb-1992
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 14-Feb-1992 JohnRo
+ Created.
+ 18-Feb-1992 JohnRo
+ Use ReplCheckAbsPathSyntax().
+ Use ReplIs{Interval,GuardTime,Pulse,Random}Valid() macros.
+ 10-Mar-1992 JohnRo
+ Added support for setinfo info levels.
+ 14-Aug-1992 JohnRo
+ Help track down bogus import/export lists.
+ 04-Jan-1993 JohnRo
+ Made changes suggested by PC-LINT 5.0
+
+--*/
+
+
+#include <windef.h> // IN, DWORD, etc.
+#include <lmcons.h> // LAN Manager common definitions
+#include <rpc.h> // Needed by <repl.h>.
+
+#include <iniparm.h> // MIN_ and MAX_ equates.
+#include <lmrepl.h> // LPREPL_INFO_0.
+#include <netlib.h> // IN_RANGE().
+#include <replconf.h> // ReplConfigIsListValid().
+#include <repldefs.h> // ReplIsRoleValid().
+#include <winerror.h> // ERROR_ and NO_ERROR equates.
+
+
+BOOL
+ReplConfigIsApiRecordValid (
+ IN DWORD Level, // Level must not be a setinfo-only level.
+ IN LPVOID ApiRecord,
+ OUT LPDWORD ParmError OPTIONAL // Set implicitly by some macros.
+ )
+
+{
+
+ if (ApiRecord == NULL) {
+ NetpSetParmError( PARM_ERROR_UNKNOWN );
+ return (FALSE); // No, it is not valid.
+ }
+
+ //
+ // Check the actual data, based on the level.
+ //
+
+ switch (Level) {
+ case 0 :
+ {
+ LPREPL_INFO_0 Buffer = ApiRecord;
+
+
+#define CHECK_LIST( fieldName, parm_error ) \
+ { \
+ if (Buffer->rp0_ ## fieldName) { \
+ if ( !ReplConfigIsListValid( Buffer->rp0_ ## fieldName ) ) { \
+ NetpSetParmError( parm_error ); \
+ return (FALSE); /* No, it is not valid. */ \
+ } \
+ } \
+ }
+
+
+#define CHECK_PATH( fieldName, parm_error ) \
+ { \
+ DWORD ApiStatus; \
+ if (Buffer->rp0_ ## fieldName) { \
+ ApiStatus = ReplCheckAbsPathSyntax( Buffer->rp0_ ## fieldName ); \
+ if (ApiStatus != NO_ERROR) { \
+ NetpSetParmError( parm_error ); \
+ return (FALSE); /* No, it is not valid. */ \
+ } \
+ } \
+ }
+
+
+ if ( ! ReplIsRoleValid( Buffer->rp0_role ) ) {
+ NetpSetParmError( 1 ); // first field in structure
+ return (FALSE); // No, it is not valid.
+ }
+
+ CHECK_PATH( exportpath, 2 ); // second...
+
+ CHECK_LIST( exportlist, 3 ); // third...
+
+ CHECK_PATH( importpath, 4 ); // fourth...
+
+ CHECK_LIST( importlist, 5 ); // fifth...
+
+ // BUGBUG: Handle logonusername!!! // sixth...
+
+ if ( !ReplIsIntervalValid( Buffer->rp0_interval ) ) {
+ NetpSetParmError( 7 ); // seventh...
+ return (FALSE); // No, it is not valid.
+ }
+
+ if ( !ReplIsPulseValid( Buffer->rp0_pulse ) ) {
+ NetpSetParmError( 8 ); // eighth...
+ return (FALSE); // No, it is not valid.
+ }
+
+ if ( !ReplIsGuardTimeValid( Buffer->rp0_guardtime ) ) {
+ NetpSetParmError( 9 ); // ninth...
+ return (FALSE); // No, it is not valid.
+ }
+
+ if ( !ReplIsRandomValid( Buffer->rp0_random ) ) {
+ NetpSetParmError( 10 ); // tenth...
+ return (FALSE); // No, it is not valid.
+ }
+
+
+ }
+ return (TRUE); // yes, it's valid.
+
+ case 1000 :
+ {
+ LPREPL_INFO_1000 Buffer = (LPVOID) ApiRecord;
+ DWORD NewValue = Buffer->rp1000_interval;
+
+ if ( !ReplIsIntervalValid( NewValue ) ) {
+ NetpSetParmError( 1 ); // first field in structure.
+ return (FALSE); // No, it is not valid.
+ }
+
+ }
+ return (TRUE); // yes, it's valid.
+
+ case 1001 :
+ {
+ LPREPL_INFO_1001 Buffer = (LPVOID) ApiRecord;
+ DWORD NewValue = Buffer->rp1001_pulse;
+
+ if ( !ReplIsPulseValid( NewValue ) ) {
+ NetpSetParmError( 1 ); // first field in structure.
+ return (FALSE); // No, it is not valid.
+ }
+
+ }
+ return (TRUE); // yes, it's valid.
+
+ case 1002 :
+ {
+ LPREPL_INFO_1002 Buffer = (LPVOID) ApiRecord;
+ DWORD NewValue = Buffer->rp1002_guardtime;
+
+ if ( !ReplIsGuardTimeValid( NewValue ) ) {
+ NetpSetParmError( 1 ); // first field in structure.
+ return (FALSE); // No, it is not valid.
+ }
+
+ }
+ return (TRUE); // yes, it's valid.
+
+ case 1003 :
+ {
+ LPREPL_INFO_1003 Buffer = (LPVOID) ApiRecord;
+ DWORD NewValue = Buffer->rp1003_random;
+
+ if ( !ReplIsRandomValid( NewValue ) ) {
+ NetpSetParmError( 1 ); // first field in structure.
+ return (FALSE); // No, it is not valid.
+ }
+
+ }
+ return (TRUE); // yes, it's valid.
+
+ default :
+ NetpSetParmError( PARM_ERROR_UNKNOWN );
+ return (FALSE); // Don't know level, so say record is not valid.
+ }
+
+ /*NOTREACHED*/
+
+} // ReplConfigIsApiRecordValid
diff --git a/private/net/svcdlls/repl/common/sources b/private/net/svcdlls/repl/common/sources
new file mode 100644
index 000000000..9dbfb0d69
--- /dev/null
+++ b/private/net/svcdlls/repl/common/sources
@@ -0,0 +1,133 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+!ENDIF
+
+#
+# The MAJORCOMP and MINORCOMP variables are defined
+# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in
+# cross compiling to provide unique filenames in a flat namespace.
+#
+
+MAJORCOMP=net
+MINORCOMP=repl
+
+
+NTPROFILEINPUT=YES
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=replcom
+
+#
+# The TARGETPATH and TARGETTYPE variables are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or
+# BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode
+# apps and don't need to build a library.
+#
+
+TARGETPATH=obj
+
+# Pick one of the following and delete the others
+TARGETTYPE=LIBRARY
+
+#
+# The TARGETLIBS specifies additional libraries to link with you target
+# image. Each library path specification should contain an asterisk (*)
+# where the machine specific subdirectory name should go.
+#
+
+TARGETLIBS=
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+# ..\server is where IgnoreNm.c gets Client.h until we can move some
+# equates from Client.h to ReplDefs.h.
+INCLUDES=.;..\..\..\inc;..\..\..\api;..\..\..\..\inc;..\server
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+!IFNDEF DISABLE_NET_UNICODE
+UNICODE=1
+NET_C_DEFINES=-DUNICODE
+!ENDIF
+
+USE_CRTDLL=1
+
+SOURCES= \
+ AbsPath.c \
+ AllowRol.c \
+ ChngLock.c \
+ ChngNot.c \
+ Data.c \
+ DelFile.c \
+ DirName.c \
+ EaSize.c \
+ ExpAlloc.c \
+ ExpBuild.c \
+ ExpConf.c \
+ ExpEnum.c \
+ ExpGet.c \
+ ExpLock.c \
+ ExpSet.c \
+ ExpValid.c \
+ FixLocks.c \
+ FsResolu.c \
+ IgnoreNm.c \
+ ImpAlloc.c \
+ ImpBuild.c \
+ ImpConf.c \
+ ImpGet.c \
+ ImpLock.c \
+ ImpState.c \
+ ImpEnum.c \
+ ImpValid.c \
+ LstValid.c \
+ ReplBld.c \
+ ReplConf.c \
+ ReplErr.c \
+ ReplP.c \
+ RepValid.c \
+ UserLock.c
+
+#
+# Next specify options for the compiler.
+#
+
+# C_DEFINES=-DTRACE -DTRACE2 -DDEBUG
+
+C_DEFINES=-DRPC_NO_WINDOWS_H
+WARNING_LEVEL=-W4
+
diff --git a/private/net/svcdlls/repl/common/userlock.c b/private/net/svcdlls/repl/common/userlock.c
new file mode 100644
index 000000000..c142993ad
--- /dev/null
+++ b/private/net/svcdlls/repl/common/userlock.c
@@ -0,0 +1,158 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ UserLock.c
+
+Abstract:
+
+ ReplDoUserLockFilesExist().
+
+ This routine checks for UserLock.* files in the directory given.
+ The directory may be a UNC path name.
+
+ This is callable even if the replicator service is not started.
+
+Author:
+
+ JR (John Rogers, JohnRo@Microsoft)) 13-Jan-1993
+
+Environment:
+
+ User Mode - Win32
+ Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
+ Requires ANSI C extensions: slash-slash comments, long external names.
+
+Revision History:
+
+ 13-Jan-1993 JohnRo
+ Created for RAID 7053: locked trees added to pulse msg. (Actually
+ fix all kinds of remote lock handling.)
+ 02-Feb-1993 JohnRo
+ RAID 8355: Downlevel lock file check causes assert in repl importer.
+
+--*/
+
+
+// These must be included first:
+
+#include <windows.h> // FindFirstFile(), IN, LPCTSTR, OPTIONAL, etc.
+#include <lmcons.h> // NET_API_STATUS.
+
+// These may be included in any order:
+
+
+#include <client.h> // USER_LOCK.
+#include <lmerrlog.h> // NELOG_ equates.
+#include <netdebug.h> // NetpAssert(), NetpKdPrint(), FORMAT_ equates, etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repldefs.h> // My prototype, ReplErrorLog(), SLASH, etc.
+#include <tstr.h> // IS_PATH_SEPARATOR(), STRCAT(), STRCPY(), STRLEN().
+#include <winerror.h> // ERROR_, NO_ERROR equates.
+
+
+// Callable even if the replicator service is not started.
+NET_API_STATUS
+ReplDoUserLockFilesExist(
+ IN LPCTSTR Path, // May be absolute path (with drive) or UNC path.
+ OUT LPBOOL IsLockedPtr
+ )
+{
+ NET_API_STATUS ApiStatus;
+ BOOL DirLocked = FALSE; // Default is not locked.
+ WIN32_FIND_DATA FindData;
+ HANDLE FindHandle = INVALID_HANDLE_VALUE;
+ TCHAR SearchPattern[MAX_PATH+1];
+
+ //
+ // Check for caller errors.
+ //
+ NetpAssert( IsLockedPtr != NULL );
+
+ if ( IS_PATH_SEPARATOR(Path[0]) ) {
+ // BUGBUG: Syntax check somehow.
+ // NetpAssert( NetpIsRemotePathValid( Path ) );
+ if ( ! IS_PATH_SEPARATOR(Path[1]) ) {
+ ApiStatus = ERROR_INVALID_PARAMETER;
+ goto Cleanup; // Don't forget to unlock stuff.
+ }
+ } else {
+ ApiStatus = ReplCheckAbsPathSyntax( (LPTSTR) Path );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to unlock stuff.
+ }
+ }
+
+ //
+ // Build a search pattern. This will look like one of the following:
+ // c:\dir1\dir2\dir3\USERLOCK.*
+ // \\server\REPL$\dirname\USERLOCK.*
+ //
+
+ (VOID) STRCPY( SearchPattern, (LPTSTR) Path );
+ (VOID) STRCAT( SearchPattern, SLASH );
+ (VOID) STRCAT( SearchPattern, USER_LOCK ); // "USERLOCK.*".
+
+ NetpAssert( STRLEN( SearchPattern ) <= MAX_PATH );
+
+ // NetpAssert( NetpIsRemotePathValid( SearchPattern ) );
+
+ //
+ // Check if any USERLOCK.* exists.
+ //
+ FindHandle = FindFirstFile(
+ SearchPattern,
+ &FindData );
+ if (FindHandle != INVALID_HANDLE_VALUE) {
+ // Yes, there is a lock file.
+ DirLocked = TRUE;
+ ApiStatus = NO_ERROR;
+ } else {
+ ApiStatus = (NET_API_STATUS) GetLastError();
+ IF_DEBUG( FILEFIND ) {
+ NetpKdPrint(( PREFIX_REPL
+ "ReplDoUserLockFilesExist: got err " FORMAT_API_STATUS
+ " from FindFirstFile.\n",
+ ApiStatus ));
+ }
+ NetpAssert( ApiStatus != NO_ERROR );
+ if (ApiStatus == ERROR_FILE_NOT_FOUND) {
+ // No lock file.
+ DirLocked = FALSE;
+ ApiStatus = NO_ERROR;
+ }
+ // Unexpected error will be logged below.
+ }
+
+
+Cleanup:
+
+ if (ApiStatus != NO_ERROR) {
+
+ ReplErrorLog(
+ NULL, // local (no server name)
+ NELOG_ReplSysErr, // log code
+ ApiStatus, // the unexpected error code
+ NULL, // no optional str1
+ NULL ); // no optional str2
+
+ // BUGBUG: log unexpected error on remote machine too, if UNC path.
+
+ NetpKdPrint(( PREFIX_REPL
+ "ReplDoUserLockFilesExist: ERROR " FORMAT_API_STATUS ".\n",
+ ApiStatus ));
+ }
+
+ if (FindHandle != INVALID_HANDLE_VALUE) {
+ (VOID) FindClose( FindHandle );
+ }
+
+ if (IsLockedPtr != NULL) {
+ *IsLockedPtr = DirLocked;
+ }
+
+ return (ApiStatus);
+
+}