diff options
Diffstat (limited to 'private/net/svcdlls/repl/server/replset.c')
-rw-r--r-- | private/net/svcdlls/repl/server/replset.c | 516 |
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 |