我有创建模拟块的代码,以允许对远程 ini 文件进行读取访问,并对远程目录进行写入访问。当要写入的“远程”目录确实是远程计算机 UNC 路径时,系统可以正常写入,但是如果“远程”ini 文件确实是远程 UNC 路径,则 GetPrivateProfileSectionNames 返回 0。但是,如果“远程” ini 文件实际上只是一个本地 UNC 路径,此功能按预期工作。对于ini文件真正在远程计算机上的情况,有没有办法让这个功能按预期工作?
我的模拟块是使用以下一次性类完成的:
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
private WindowsImpersonationContext _impersonatedUserContext;
// Declare signatures for Win32 LogonUser and CloseHandle APIs
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(
string principal,
string authority,
string password,
LogonSessionType logonType,
LogonProvider logonProvider,
out IntPtr token);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RevertToSelf();
// ReSharper disable UnusedMember.Local
enum LogonSessionType : uint
{
Interactive = 2,
Network,
Batch,
Service,
NetworkCleartext = 8,
NewCredentials
}
// ReSharper disable InconsistentNaming
enum LogonProvider : uint
{
Default = 0, // default for platform (use this!)
WinNT35, // sends smoke signals to authority
WinNT40, // uses NTLM
WinNT50 // negotiates Kerb or NTLM
}
// ReSharper restore InconsistentNaming
// ReSharper restore UnusedMember.Local
/// <summary>
/// Class to allow running a segment of code under a given user login context
/// </summary>
/// <param name="user">domain\user</param>
/// <param name="password">user's domain password</param>
public Impersonation(string user, string password)
{
var token = ValidateParametersAndGetFirstLoginToken(user, password);
var duplicateToken = IntPtr.Zero;
try
{
if (DuplicateToken(token, 2, ref duplicateToken) == 0)
{
throw new Exception("DuplicateToken call to reset permissions for this token failed");
}
var identityForLoggedOnUser = new WindowsIdentity(duplicateToken);
_impersonatedUserContext = identityForLoggedOnUser.Impersonate();
if (_impersonatedUserContext == null)
{
throw new Exception("WindowsIdentity.Impersonate() failed");
}
}
finally
{
if (token != IntPtr.Zero)
CloseHandle(token);
if (duplicateToken != IntPtr.Zero)
CloseHandle(duplicateToken);
}
}
private static IntPtr ValidateParametersAndGetFirstLoginToken(string user, string password)
{
if (string.IsNullOrEmpty(user))
{
throw new ConfigurationErrorsException("No user passed into impersonation class");
}
var userHaves = user.Split('\\');
if (userHaves.Length != 2)
{
throw new ConfigurationErrorsException("User must be formatted as follows: domain\\user");
}
if (!RevertToSelf())
{
throw new Exception("RevertToSelf call to remove any prior impersonations failed");
}
IntPtr token;
var result = LogonUser(userHaves[1], userHaves[0],
password,
LogonSessionType.Interactive,
LogonProvider.Default,
out token);
if (!result)
{
throw new ConfigurationErrorsException("Logon for user " + user + " failed.");
}
return token;
}
/// <summary>
/// Dispose
/// </summary>
public void Dispose()
{
// Stop impersonation and revert to the process identity
if (_impersonatedUserContext != null)
{
_impersonatedUserContext.Undo();
_impersonatedUserContext.Dispose();
_impersonatedUserContext = null;
}
}
}
在此类的模拟块实例中,远程 ini 文件可通过以下方式访问:
int bufLen = GetPrivateProfileSectionNames(buffer,
buffer.GetUpperBound(0),
iniFileName);
if (bufLen > 0)
{
//process results
}
与远程计算机打交道时,如何让 GetPrivateProfileSectionNames 返回有效数据?我的用户在这台计算机或远程计算机上是否有权限?