summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/repl/server/replset.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/repl/server/replset.c')
-rw-r--r--private/net/svcdlls/repl/server/replset.c516
1 files changed, 516 insertions, 0 deletions
diff --git a/private/net/svcdlls/repl/server/replset.c b/private/net/svcdlls/repl/server/replset.c
new file mode 100644
index 000000000..471039756
--- /dev/null
+++ b/private/net/svcdlls/repl/server/replset.c
@@ -0,0 +1,516 @@
+/*++
+
+Copyright (c) 1992-1993 Microsoft Corporation
+
+Module Name:
+
+ ReplSet.c
+
+Abstract:
+
+ This file contains NetrReplSetInfo().
+
+Author:
+
+ John Rogers (JohnRo) 10-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:
+
+ 10-Feb-1992 JohnRo
+ Created.
+ 16-Feb-1992 JohnRo
+ Use ReplIs{Interval,GuardTime,Pulse,Random}Valid() macros.
+ 12-Mar-1992 JohnRo
+ Update registry with new values.
+ Added support for setinfo info levels in ReplIsApiRecordValid().
+ 24-Mar-1992 JohnRo
+ Renamed many ReplGlobal vars to ReplConfig vars.
+ 22-Jul-1992 JohnRo
+ RAID 2274: repl svc should impersonate caller.
+ 06-Aug-1992 JohnRo
+ RAID 2252: repl should prevent export on Windows/NT.
+ 27-Aug-1992 JohnRo
+ RAID 4611: Set ParmError if we get an invalid info level (e.g. on
+ a bad import/export list).
+ 22-Oct-92 jimkel
+ Added a call to InitClientList() <- in master.c
+ Added a call to InitClientImpList() <- in client.c
+ These calls cannonicalize the import and export lists and
+ store their cannonicalized forms for internal replicator use.
+ 16-Nov-1992 JohnRo
+ RAID 1537: repl APIs in wrong role kill service.
+ 01-Dec-1992 JohnRo
+ RAID 3844: remote NetReplSetInfo uses local machine type.
+ 16-Dec-1992 JohnRo
+ RAID 1513: Repl does not maintain ACLs (also fix timestamps).
+ 06-Jan-1993 JohnRo
+ Repl WAN support (get rid of repl name list limits).
+ 01-Apr-1993 JohnRo
+ Made changes suggested by PC-LINT 5.0
+ Use NetpKdPrint() where possible.
+--*/
+
+
+// These must be included first:
+
+#include <windef.h> // IN, DWORD, etc.
+#include <lmcons.h> // LAN Manager common definitions
+#include <rpc.h> // Needed by <repl.h>.
+
+// These may be included in any order:
+
+#include <client.h> // RCGlobalExportList, etc.
+#include <confname.h> // REPL_KEYWORD_ equates.
+#include <lmrepl.h> // LPREPL_INFO_0.
+#include <master.h> // RMGlobalImportList, etc.
+#include <netdebug.h> // NetpAssert().
+#include <netlib.h> // NetpMemoryFree(), NetpSetParmError().
+#include <netlock.h> // ACQUIRE_LOCK(), etc.
+#include <prefix.h> // PREFIX_ equates.
+#include <repl.h> // My prototype (in MIDL-generated .h file).
+#include <replconf.h> // ReplConfig routines.
+#include <repldefs.h> // ReplIsRoleValid(), etc.
+#include <replgbl.h> // ReplGlobal and ReplConfig variables.
+#include <rpcutil.h> // NetpImpersonateClient(), NetpRevertToSelf().
+#include <tstring.h> // NetpAlloc{type}From{type}, STRCPY(), TCHAR_EOS, etc.
+#include <winerror.h> // ERROR_ equates, NO_ERROR.
+
+
+//
+// Set config data for the replicator. Only callable when
+// the replicator service is started.
+//
+
+NET_API_STATUS
+NetrReplSetInfo (
+ IN LPTSTR UncServerName OPTIONAL,
+ IN DWORD Level,
+ IN LPCONFIG_CONTAINER Buf,
+ OUT LPDWORD ParmError OPTIONAL
+ )
+{
+ NET_API_STATUS ApiStatus;
+ DWORD OldRole;
+ BOOL Impersonated = FALSE;
+ BOOL Locked = FALSE;
+
+ UNREFERENCED_PARAMETER( UncServerName );
+
+ //
+ // Check for caller's errors.
+ //
+ NetpSetParmError( PARM_ERROR_UNKNOWN ); // Set in case we get bad level.
+
+#define RETURN_BAD_PARM( parm_error ) \
+ { \
+ NetpSetParmError( parm_error ); \
+ ApiStatus = ERROR_INVALID_PARAMETER; \
+ goto Cleanup; /* Don't forget to release lock... */ \
+ }
+
+ if (Buf == NULL) {
+ RETURN_BAD_PARM( PARM_ERROR_UNKNOWN )
+ /*NOTREACHED*/
+ }
+
+ if ( !ReplConfigIsLevelValid( Level, TRUE ) ) { // Yes, allow setinfo lvl
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ }
+
+ //
+ // We need to check all fields before we set any.
+ //
+
+ if ( !ReplConfigIsApiRecordValid (
+ Level,
+ (LPVOID) (Buf->Info0), // BUGBUG: nonportable?
+ ParmError ) ) {
+
+ ApiStatus = ERROR_INVALID_PARAMETER; // ParmError already set.
+ goto Cleanup;
+ }
+
+ //
+ // Impersonate caller, so security check (write to registry) reflects
+ // the client's process, not the repl service process.
+ //
+ ApiStatus = NetpImpersonateClient();
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup;
+ }
+ Impersonated = TRUE;
+
+ //
+ // Get exclusive lock on config variables, so we don't get confused by
+ // another API thread. This also locks the matching registry data.
+ //
+ ACQUIRE_LOCK( ReplConfigLock );
+ Locked = TRUE;
+
+ IF_DEBUG( REPLAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetrReplSetInfo(server side): got config lock OK.\n" ));
+ }
+
+ //
+ // Based on info level, do additional checking and updates.
+ //
+
+ switch (Level) {
+ case 0 :
+ {
+ LPREPL_INFO_0 Buffer = (LPVOID) (Buf->Info0);
+
+ if ( !ReplConfigIsRoleAllowed( NULL, Buffer->rp0_role ) ) {
+ RETURN_BAD_PARM( 1 ) // Role is first field in struct.
+ /*NOTREACHED*/
+ }
+
+ //
+ // Change permanent copy of registry data for the replicator.
+ // This acts as our security check, too.
+ //
+ ApiStatus = ReplConfigWrite(
+ NULL, // no server name
+ Buffer->rp0_role,
+ Buffer->rp0_exportpath,
+ Buffer->rp0_exportlist,
+ Buffer->rp0_importpath,
+ Buffer->rp0_importlist,
+ Buffer->rp0_logonusername,
+ Buffer->rp0_interval,
+ Buffer->rp0_pulse,
+ Buffer->rp0_guardtime,
+ Buffer->rp0_random );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to release lock...
+ }
+
+ //
+ // Change in-memory copy of registry data for the replicator.
+ //
+#define SET_LIST( globalName, fieldName ) \
+ { \
+ LPTSTR Source = Buffer->rp0_ ## fieldName; \
+ if ( (Source!=NULL) && ( (*Source) != TCHAR_EOS ) ) { \
+ if (globalName != NULL) { \
+ if (STRICMP(globalName, Source) == 0) { \
+ /* OK as is; nothing to do. */ \
+ } else { \
+ /* Old and new are different. Free old and alloc new. */ \
+ NetpMemoryFree( globalName ); \
+ globalName = NetpAllocTStrFromTStr( Source ); \
+ if (globalName == NULL) { \
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY; \
+ goto Cleanup; /* Don't forget to release lock... */ \
+ } \
+ } \
+ } else { \
+ /* New name but no old name. Alloc new. */ \
+ globalName = NetpAllocTStrFromTStr( Source ); \
+ if (globalName == NULL) { \
+ ApiStatus = ERROR_NOT_ENOUGH_MEMORY; \
+ goto Cleanup; /* Don't forget to release lock... */ \
+ } \
+ } \
+ } else if (globalName != NULL) { \
+ /* Old list but no new list. Free old. */ \
+ NetpMemoryFree( globalName ); \
+ globalName = NULL; \
+ } \
+ }
+
+
+#define SET_PATH( globalName, fieldName ) \
+ { \
+ LPTSTR Source = Buffer->rp0_ ## fieldName; \
+ NetpAssert( globalName != NULL ); \
+ if ( (Source!=NULL) && ( (*Source) != TCHAR_EOS ) ) { \
+ (void) STRCPY( globalName, Source ); \
+ } else { \
+ globalName[0] = TCHAR_EOS; \
+ } \
+ }
+
+ // Note: because of possible shock to other code, set role last.
+
+ SET_PATH( ReplConfigExportPath, exportpath );
+
+ // The UI will update REPL$ share to reflect new export path.
+ // Repl svc may not be running as admin so can't do NetShareAdd?
+ // BUGBUG: Hey, we impersonated, so maybe we can!
+
+ SET_LIST( ReplConfigExportList, exportlist );
+
+ SET_PATH( ReplConfigImportPath, importpath );
+ RCGlobalFsTimeResolutionSecs =
+ ReplGetFsTimeResolutionSecs( ReplConfigImportPath );
+
+
+ SET_LIST( ReplConfigImportList, importlist );
+
+ // BUGBUG: Set logonusername!!!
+
+ ReplConfigInterval = Buffer->rp0_interval;
+ ReplConfigPulse = Buffer->rp0_pulse;
+ ReplConfigGuardTime = Buffer->rp0_guardtime;
+ ReplConfigRandom = Buffer->rp0_random;
+
+ //
+ // If the role is not changing make sure the internal
+ // variables are updated.
+ //
+
+ OldRole = ReplConfigRole;
+
+ IF_DEBUG( REPLAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetrReplSetInfo(server side): initing lists.\n" ));
+ }
+
+ if ( ReplRoleIncludesExport(Buffer->rp0_role)
+ && ReplRoleIncludesExport(OldRole) ) {
+
+ if (RMGlobalImportList != NULL) {
+ NetpMemoryFree( RMGlobalImportList );
+ RMGlobalImportList = NULL;
+ }
+
+ // NOTE: ReplInitAnyList() assumes caller has config data lock.
+ ApiStatus = ReplInitAnyList(
+ (LPCTSTR) ReplConfigExportList, // uncanon
+ & RMGlobalImportList, // canon list: alloc and set ptr
+ (LPCTSTR) REPL_KEYWORD_EXPLIST, // config keyword name
+ & RMGlobalImportCount ); // set entry count too
+
+ if ( ApiStatus != NO_ERROR )
+ goto Cleanup;
+ }
+
+ if ( ReplRoleIncludesImport(Buffer->rp0_role)
+ && ReplRoleIncludesImport(OldRole) ) {
+
+ if (RCGlobalExportList != NULL) {
+ NetpMemoryFree( RCGlobalExportList );
+ RCGlobalExportList = NULL;
+ }
+
+ // NOTE: ReplInitAnyList() assumes caller has config data lock.
+ ApiStatus = ReplInitAnyList(
+ (LPCTSTR) ReplConfigImportList, // uncanon
+ & RCGlobalExportList, // canon list: alloc and set ptr
+ (LPCTSTR) REPL_KEYWORD_IMPLIST, // config keyword name
+ & RCGlobalExportCount ); // set entry count too
+ if ( ApiStatus != NO_ERROR )
+ goto Cleanup;
+ }
+
+ //
+ // Change the role, including all the side-effects (like
+ // starting and stopping threads). Also set ReplConfigRole.
+ // NOTE: ReplChangeRole assumes caller has exclusive lock on
+ // ReplConfigLock.
+ //
+
+ IF_DEBUG( REPLAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetrReplSetInfo(server side): changing role.\n" ));
+ }
+
+ ApiStatus = ReplChangeRole( Buffer->rp0_role );
+ NetpAssert( ApiStatus == NO_ERROR );
+
+ IF_DEBUG( REPLAPI ) {
+ NetpKdPrint(( PREFIX_REPL
+ "NetrReplSetInfo(server side): "
+ "done changing role.\n" ));
+ }
+
+
+ // Don't forget to unimpersonate.
+ }
+ break;
+
+ case 1000 :
+ {
+ LPREPL_INFO_1000 Buffer = (LPVOID) (Buf->Info1000);
+ DWORD NewValue = Buffer->rp1000_interval;
+
+ if ( !ReplIsIntervalValid( NewValue ) ) {
+ RETURN_BAD_PARM( 1 ) // first field in structure.
+ /*NOTREACHED*/
+ }
+
+ //
+ // Change permanent copy of registry data for the replicator.
+ // This acts as our security check, too.
+ //
+ ApiStatus = ReplConfigWrite(
+ NULL, // no server name
+ ReplConfigRole,
+ ReplConfigExportPath,
+ ReplConfigExportList,
+ ReplConfigImportPath,
+ ReplConfigImportList,
+ ReplConfigLogonUserName,
+ NewValue, // new interval
+ ReplConfigPulse,
+ ReplConfigGuardTime,
+ ReplConfigRandom );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to release lock...
+ }
+
+ ReplConfigInterval = NewValue;
+
+ // Don't forget to unlock and unimpersonate.
+
+ // BUGBUG: Notify anybody?
+ }
+ break;
+
+ case 1001 :
+ {
+ LPREPL_INFO_1001 Buffer = (LPVOID) (Buf->Info1001);
+ DWORD NewValue = Buffer->rp1001_pulse;
+
+ if ( !ReplIsPulseValid( NewValue ) ) {
+ RETURN_BAD_PARM( 1 ) // first field in structure.
+ /*NOTREACHED*/
+ }
+
+ //
+ // Change permanent copy of registry data for the replicator.
+ // This acts as our security check, too.
+ //
+ ApiStatus = ReplConfigWrite(
+ NULL, // no server name
+ ReplConfigRole,
+ ReplConfigExportPath,
+ ReplConfigExportList,
+ ReplConfigImportPath,
+ ReplConfigImportList,
+ ReplConfigLogonUserName,
+ ReplConfigInterval,
+ NewValue, // new pulse
+ ReplConfigGuardTime,
+ ReplConfigRandom );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to release lock...
+ }
+
+ ReplConfigPulse = NewValue;
+
+ // Don't forget to unlock and unimpersonate.
+
+ // BUGBUG: Notify anybody?
+ }
+ break;
+
+ case 1002 :
+ {
+ LPREPL_INFO_1002 Buffer = (LPVOID) (Buf->Info1002);
+ DWORD NewValue = Buffer->rp1002_guardtime;
+
+ if ( !ReplIsGuardTimeValid( NewValue ) ) {
+ RETURN_BAD_PARM( 1 ) // first field in structure.
+ /*NOTREACHED*/
+ }
+
+ //
+ // Change permanent copy of registry data for the replicator.
+ // This acts as our security check, too.
+ //
+ ApiStatus = ReplConfigWrite(
+ NULL, // no server name
+ ReplConfigRole,
+ ReplConfigExportPath,
+ ReplConfigExportList,
+ ReplConfigImportPath,
+ ReplConfigImportList,
+ ReplConfigLogonUserName,
+ ReplConfigInterval,
+ ReplConfigPulse,
+ NewValue, // new guard time
+ ReplConfigRandom );
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to release lock...
+ }
+
+ ReplConfigGuardTime = NewValue;
+
+ // Don't forget to unlock and unimpersonate.
+
+ // BUGBUG: Notify anybody?
+ }
+ break;
+
+ case 1003 :
+ {
+ LPREPL_INFO_1003 Buffer = (LPVOID) (Buf->Info1003);
+ DWORD NewValue = Buffer->rp1003_random;
+
+ if ( !ReplIsRandomValid( NewValue ) ) {
+ RETURN_BAD_PARM( 1 ) // first field in structure.
+ /*NOTREACHED*/
+ }
+
+ //
+ // Change permanent copy of registry data for the replicator.
+ // This acts as our security check, too.
+ //
+ ApiStatus = ReplConfigWrite(
+ NULL, // no server name
+ ReplConfigRole,
+ ReplConfigExportPath,
+ ReplConfigExportList,
+ ReplConfigImportPath,
+ ReplConfigImportList,
+ ReplConfigLogonUserName,
+ ReplConfigInterval,
+ ReplConfigPulse,
+ ReplConfigGuardTime,
+ NewValue ); // new random time
+ if (ApiStatus != NO_ERROR) {
+ goto Cleanup; // Don't forget to release lock...
+ }
+
+ ReplConfigRandom = NewValue;
+
+ // Don't forget to unlock and unimpersonate.
+
+ }
+ break;
+
+ default :
+ NetpAssert( FALSE ); // Can't get here.
+ }
+
+ //
+ // All done.
+ //
+
+Cleanup:
+
+ if (Impersonated) {
+ (VOID) NetpRevertToSelf();
+ }
+
+ if (Locked) {
+ RELEASE_LOCK( ReplConfigLock );
+ }
+
+ if (ApiStatus == NO_ERROR) {
+ NetpSetParmError( PARM_ERROR_NONE );
+ }
+
+ return (ApiStatus);
+
+} // NetpReplSetInfo