/*++ Copyright (c) 1992-1993 Microsoft Corporation Module Name: ImpLock.c Abstract: This file contains: NetrReplImportDirLock NetrReplImportDirUnlock Author: John Rogers (JohnRo) 08-Jan-1992 Environment: Runs under Windows NT. Requires ANSI C extensions: slash-slash comments, long external names. 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: 08-Jan-1992 JohnRo Created. 27-Jan-1992 JohnRo Netr prototypes are now generated by MIDL and put in repl.h. Changed to use LPTSTR etc. 18-Feb-1992 JohnRo Use Repl{Incr,Decr}LockFields(). 15-Mar-1992 JohnRo Update registry with new values. 22-Jul-1992 JohnRo RAID 2274: repl svc should impersonate caller. 17-Nov-1992 JohnRo RAID 1537: repl APIs in wrong role kill service. 13-Apr-1993 JohnRo RAID 3107: locking directory over the net gives network path not found. Made some changes suggested by PC-LINT 5.0 --*/ // These must be included first: #include // IN, VOID, LPTSTR, etc. #include // NET_API_STATUS, PARM equates, etc. #include // (Required by client.h) #include // Needed by . // These can be in any order: #include // LPCLIENT_LIST_REC, etc. #include // ReplIsDirNameValid(). #include // NERR_ equates, NO_ERROR. #include // ImportDirLockInRegistry(), etc. #include // REPL_UNLOCK_ equates. #include // ACQUIRE_LOCK(), etc. #include // My prototypes (in MIDL-generated .h file). #include // ReplConfigLock, ReplConfigRole. #include // NetpImpersonateClient(), NetpRevertToSelf(). NET_API_STATUS NetrReplImportDirLock ( IN LPTSTR UncServerName OPTIONAL, IN LPTSTR DirName ) /*++ Routine Description: Same as NetReplImportDirLock. Arguments: Same as NetReplImportDirLock. Return Value: Same as NetReplImportDirLock. --*/ { NET_API_STATUS ApiStatus; LPCLIENT_LIST_REC ClientRecord; BOOL Impersonated = FALSE; BOOL LockedClientList = FALSE; BOOL LockedConfigData = FALSE; if (ReplIsDirNameValid( DirName ) == FALSE) { return (ERROR_INVALID_PARAMETER); } // // Get lock on role; we'll need that below. // ACQUIRE_LOCK_SHARED( ReplConfigLock ); LockedConfigData = TRUE; // // // 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 a lock on client list, so we don't get confused by // another API thread. This also locks the matching registry data. // We need this lock even if this side of service is not running, // because the XxxDirLockInRegistry routines are not atomic. // ACQUIRE_LOCK_SHARED( RCGlobalClientListLock ); LockedClientList = TRUE; // // Update lock values in registry first. // This has the side-effect of doing a security check. // ApiStatus = ImportDirLockInRegistry( UncServerName, DirName ); if (ApiStatus != NO_ERROR) { goto Cleanup; } // // Check role and update globals if import half of service is running. // if ( ReplRoleIncludesImport( ReplConfigRole ) ) { ClientRecord = ReplGetClientRec( DirName, NULL ); // No particular master name if (ClientRecord == NULL) { ApiStatus = NERR_UnknownDevDir; // Don't forget to release lock... } else { // // Update lock values in service. // ApiStatus = ReplIncrLockFields( & (ClientRecord->lockcount), & (ClientRecord->time_of_first_lock) ); // Don't forget to release lock... } } Cleanup: if (Impersonated) { (VOID) NetpRevertToSelf(); } if (LockedClientList) { RELEASE_LOCK( RCGlobalClientListLock ); } if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); } return (ApiStatus); } // NetrReplImportDirLock NET_API_STATUS NetrReplImportDirUnlock ( IN LPTSTR UncServerName OPTIONAL, IN LPTSTR DirName, IN DWORD UnlockForce ) /*++ Routine Description: Same as NetReplImportDirUnlock. Arguments: Same as NetReplImportDirUnlock. Return Value: Same as NetReplImportDirUnlock. --*/ { NET_API_STATUS ApiStatus; LPCLIENT_LIST_REC ClientRecord; BOOL Impersonated = FALSE; BOOL LockedClientList = FALSE; BOOL LockedConfigData = FALSE; if (ReplIsDirNameValid( DirName ) == FALSE) { return (ERROR_INVALID_PARAMETER); } else if ( ! ReplIsForceLevelValid( UnlockForce ) ) { return (ERROR_INVALID_PARAMETER); } // // Get lock on role; we'll need that below. // ACQUIRE_LOCK_SHARED( ReplConfigLock ); LockedConfigData = TRUE; // // // 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 a lock on client list, so we don't get confused by // another API thread. This also locks the matching registry data. // We need this lock even if this side of service is not running, // because the XxxDirLockInRegistry routines are not atomic. // ACQUIRE_LOCK_SHARED( RCGlobalClientListLock ); LockedClientList = TRUE; // // Update lock values in registry first. // This has the side-effect of doing a security check. // ApiStatus = ImportDirUnlockInRegistry( UncServerName, DirName, UnlockForce ); if (ApiStatus != NO_ERROR) { goto Cleanup; } // // Check role and update globals if import half of service is running. // if ( ReplRoleIncludesImport( ReplConfigRole ) ) { ClientRecord = ReplGetClientRec( DirName, NULL ); // No particular master name if (ClientRecord == NULL) { ApiStatus = NERR_UnknownDevDir; // Don't forget to release lock... } else { // // Update lock values in service. // ApiStatus = ReplDecrLockFields( & (ClientRecord->lockcount), & (ClientRecord->time_of_first_lock), UnlockForce ); // Don't forget to release lock... } } Cleanup: if (Impersonated) { (VOID) NetpRevertToSelf(); } if (LockedClientList) { RELEASE_LOCK( RCGlobalClientListLock ); } if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); } return (ApiStatus); } // NetrReplImportDirUnlock