/*++ Copyright (c) 1992-1993 Microsoft Corporation Module Name: ImpAdd.c Abstract: This file contains NetrReplImportDirAdd. Author: John Rogers (JohnRo) 09-Jan-1992 Environment: Runs under Windows NT. Requires ANSI C extensions: slash-slash comments, long external names. Revision History: 09-Jan-1992 JohnRo Created. 20-Jan-1992 JohnRo Netr prototypes are now generated by MIDL and put in repl.h. 20-Jan-1992 JohnRo Changed prototype to match MIDL requirements. 24-Jan-1992 JohnRo Changed to use LPTSTR etc. 15-Mar-1992 JohnRo Update registry with new values. 27-Mar-1992 JohnRo NetrImportDirAdd() sometimes forgot to release a lock. 27-Mar-1992 JohnRo Try fixing bug where bad name gets put in registry. 08-May-1992 JohnRo Fixed link problem in free (nondebug) build. 22-Jul-1992 JohnRo RAID 2274: repl svc should impersonate caller. 09-Nov-1992 JohnRo RAID 7962: Repl APIs in wrong role kill svc. Fix remote repl admin. 02-Apr-1993 JohnRo Use NetpKdPrint() where possible. --*/ // These must be included first: #include // IN, VOID, LPTSTR, etc. #include // NET_API_STATUS, PARM equates, etc. #include // IF_DEBUG(), needed by . #include // Needed by . // These can be in any order: #include // LPCLIENT_LIST_REC, etc. #include // ReplIsDirNameValid(). #include // ImportDirWriteConfigData(), etc. #include // LPREPL_IDIR_INFO_1, REPL_EXTENT_ stuff, etc. #include // NetpAssert(), NetpKdPrint(), etc. #include // NetpSetParmError(). #include // My prototype (in MIDL-generated .h file). #include // ReplConfigLock, ReplConfigRole. #include // ERROR_ equates, NO_ERROR. #include // NetpImpersonateClient(), NetpRevertToSelf(). NET_API_STATUS NetrReplImportDirAdd ( IN LPTSTR UncServerName OPTIONAL, IN DWORD Level, IN LPIMPORT_CONTAINER Buf, // RPC container (union) OUT LPDWORD ParmError OPTIONAL // name used by NetpSetParmError() macro. ) /*++ Routine Description: Same as NetReplImportDirAdd. Arguments: Same as NetReplImportDirAdd. Return Value: Same as NetReplImportDirAdd. --*/ { LPREPL_IDIR_INFO_0 ApiRecord; // level 0 by definition NET_API_STATUS ApiStatus; BOOL Impersonated = FALSE; LPCLIENT_LIST_REC InternalRecord; BOOL LockedClientList = FALSE; BOOL LockedConfigData = FALSE; // // Check for caller errors. // NetpSetParmError( PARM_ERROR_UNKNOWN ); // Assume error until proven... if (Level != 0) { return (ERROR_INVALID_LEVEL); } if (Buf == NULL) { return (ERROR_INVALID_PARAMETER); } ApiRecord = Buf->Info0; // level 0 by definition NetpAssert( ApiRecord != NULL ); if (ReplIsDirNameValid(ApiRecord->rpid0_dirname) == FALSE) { NetpSetParmError( 1 ); // Error in first field in ApiRecord. return (ERROR_INVALID_PARAMETER); } // // 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; // // Lock config data so role doesn't change while we're executing. // ACQUIRE_LOCK_SHARED( ReplConfigLock ); LockedConfigData = TRUE; if ( !ReplRoleIncludesImport( ReplConfigRole ) ) { // Make sure there is no existing record for this directory. if (ImportDirConfigDataExists( UncServerName, ApiRecord->rpid0_dirname )) { ApiStatus = ERROR_ALREADY_EXISTS; goto Cleanup; } // Write the new or revised data. ApiStatus = ImportDirWriteConfigData ( UncServerName, ApiRecord->rpid0_dirname, REPL_STATE_NEVER_REPLICATED, NULL, // no master. (DWORD) 0, // last update time, secs since 1970. (DWORD) 0, // lock count (DWORD) 0 ); // time of first lock, secs since 1970. goto Cleanup; } // // Import-side of service is running... // Get exclusive lock on client list, so we don't get confused by // another API thread. This also locks the matching registry data. // ACQUIRE_LOCK( RCGlobalClientListLock ); LockedClientList = TRUE; // // Find record in client list. // InternalRecord = ReplGetClientRec( ApiRecord->rpid0_dirname, NULL); // don't care which master if (InternalRecord != NULL) { ApiStatus = ERROR_ALREADY_EXISTS; // BUGBUG: better error code? // Don't forget to release lock... } else { IF_DEBUG(IMPAPI) { NetpKdPrint(( "NetrReplImportDirAdd: adding API record...\n" )); NetpDbgDisplayReplImportDir( Level, (LPVOID) ApiRecord ); } // // Call somebody to add to the registry. // This has the side-effect of doing a security check. // ApiStatus = ImportDirWriteConfigData ( UncServerName, ApiRecord->rpid0_dirname, REPL_STATE_NEVER_REPLICATED, NULL, // no master name 0, // no last update time 0, // no locks 0 ); // no lock time if (ApiStatus == NO_ERROR) { // // Create a new client record and add it to the appropriate list(s). // InternalRecord = ReplAddClientRec( ApiRecord->rpid0_dirname, NULL, // BUGBUG: need PSYNCMSG here NULL); // BUGBUG: need PMSG_STATUS_REC here IF_DEBUG(IMPAPI) { NetpKdPrint(( "NetrReplImportDirAdd: done adding API record, " "got client record at " FORMAT_LPVOID ".\n", (LPVOID) InternalRecord )); } // // Assumption: ReplAddClientRec can only fail if it can't allocate // memory. // if (InternalRecord == NULL) { ApiStatus = ERROR_NOT_ENOUGH_MEMORY; // Don't forget to release lock... } else { ApiStatus = NO_ERROR; } } } Cleanup: if (Impersonated) { (VOID) NetpRevertToSelf(); } if (LockedClientList) { RELEASE_LOCK( RCGlobalClientListLock ); } if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); } if (ApiStatus == NO_ERROR) { NetpSetParmError( PARM_ERROR_NONE ); } return (ApiStatus); }