IUrlHistoryStg2::ClearHistory() 无法在服务中工作?
IUrlHistoryStg2::ClearHistory() 方法被记录为每用户。
http://msdn.microsoft.com/en-us/ library/aa767715(VS.85).aspx
当从 SYSTEM 帐户下运行的服务调用它时,我无法定位特定的登录用户。我已通过 WindowsIdentity.Impersonate() 成功模拟用户,但对 ClearHistory() 的调用始终返回 0 表示成功,但不会清除用户的历史记录。
这适用于 XP 和 Win7,因此似乎不是会话隔离问题。
也许因为它是COM,所以在模拟时会查看调用者的进程令牌而不是其线程令牌?
我很困惑为什么冒充用户并不能简单地导致这种方法的成功?
using System;
using System.Runtime.InteropServices;
/**
* wrapper for IUrlHistory
*/
public struct STATURL
{
public static uint SIZEOF_STATURL = (uint)Marshal.SizeOf( typeof(STATURL) );
public uint cbSize;
[MarshalAs(UnmanagedType.LPWStr)] public string pwcsUrl;
[MarshalAs(UnmanagedType.LPWStr)] public string pwcsTitle;
public System.Runtime.InteropServices.ComTypes.FILETIME
ftLastVisited,
ftLastUpdated,
ftExpires;
public uint dwFlags;
}
[ComImport, Guid("3C374A42-BAE4-11CF-BF7D-00AA006946EE"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATURL
{
[PreserveSig]
uint Next(uint celt, out STATURL rgelt, out uint pceltFetched);
void Skip(uint celt);
void Reset();
void Clone(out IEnumSTATURL ppenum);
void SetFilter(
[MarshalAs(UnmanagedType.LPWStr)] string poszFilter,
uint dwFlags);
}
[ComImport, Guid("AFA0DC11-C313-11d0-831A-00C04FD5AE38"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IUrlHistoryStg2
{
#region IUrlHistoryStg methods
void AddUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
[MarshalAs(UnmanagedType.LPWStr)] string pocsTitle,
uint dwFlags);
void DeleteUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
uint dwFlags);
void QueryUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
uint dwFlags,
ref STATURL lpSTATURL);
void BindToObject(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
ref Guid riid,
[MarshalAs(UnmanagedType.IUnknown)] out object ppvOut);
IEnumSTATURL EnumUrls();
#endregion
void AddUrlAndNotify(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
[MarshalAs(UnmanagedType.LPWStr)] string pocsTitle,
uint dwFlags,
[MarshalAs(UnmanagedType.Bool)] bool fWriteHistory,
[MarshalAs(UnmanagedType.IUnknown)] object /*IOleCommandTarget*/
poctNotify,
[MarshalAs(UnmanagedType.IUnknown)] object punkISFolder);
void ClearHistory();
}
[ComImport, Guid("3C374A40-BAE4-11CF-BF7D-00AA006946EE")]
public class UrlHistory /* : IUrlHistoryStg[2] */ {}
public class test
{
static void Main()
{
IUrlHistoryStg2 stg = (IUrlHistoryStg2) new UrlHistory();
stg.ClearHistory();
}
}
The IUrlHistoryStg2::ClearHistory() method is documented as Per-User.
http://msdn.microsoft.com/en-us/library/aa767715(VS.85).aspx
When calling it from a service running under the SYSTEM account, I am unable to target particular logged-on users. I have successfully impersonated the users via WindowsIdentity.Impersonate() but the call to ClearHistory() always returns 0 for success but does not clear the history of the user.
This applies on both XP and Win7 so appears to be not a session isolation issue.
Perhaps because it is COM, something is looking at the Process token of the caller rather than its Thread token when impersonating?
I am confused why impersonating the user does not simply lead to success of this method?
using System;
using System.Runtime.InteropServices;
/**
* wrapper for IUrlHistory
*/
public struct STATURL
{
public static uint SIZEOF_STATURL = (uint)Marshal.SizeOf( typeof(STATURL) );
public uint cbSize;
[MarshalAs(UnmanagedType.LPWStr)] public string pwcsUrl;
[MarshalAs(UnmanagedType.LPWStr)] public string pwcsTitle;
public System.Runtime.InteropServices.ComTypes.FILETIME
ftLastVisited,
ftLastUpdated,
ftExpires;
public uint dwFlags;
}
[ComImport, Guid("3C374A42-BAE4-11CF-BF7D-00AA006946EE"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATURL
{
[PreserveSig]
uint Next(uint celt, out STATURL rgelt, out uint pceltFetched);
void Skip(uint celt);
void Reset();
void Clone(out IEnumSTATURL ppenum);
void SetFilter(
[MarshalAs(UnmanagedType.LPWStr)] string poszFilter,
uint dwFlags);
}
[ComImport, Guid("AFA0DC11-C313-11d0-831A-00C04FD5AE38"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IUrlHistoryStg2
{
#region IUrlHistoryStg methods
void AddUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
[MarshalAs(UnmanagedType.LPWStr)] string pocsTitle,
uint dwFlags);
void DeleteUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
uint dwFlags);
void QueryUrl(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
uint dwFlags,
ref STATURL lpSTATURL);
void BindToObject(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
ref Guid riid,
[MarshalAs(UnmanagedType.IUnknown)] out object ppvOut);
IEnumSTATURL EnumUrls();
#endregion
void AddUrlAndNotify(
[MarshalAs(UnmanagedType.LPWStr)] string pocsUrl,
[MarshalAs(UnmanagedType.LPWStr)] string pocsTitle,
uint dwFlags,
[MarshalAs(UnmanagedType.Bool)] bool fWriteHistory,
[MarshalAs(UnmanagedType.IUnknown)] object /*IOleCommandTarget*/
poctNotify,
[MarshalAs(UnmanagedType.IUnknown)] object punkISFolder);
void ClearHistory();
}
[ComImport, Guid("3C374A40-BAE4-11CF-BF7D-00AA006946EE")]
public class UrlHistory /* : IUrlHistoryStg[2] */ {}
public class test
{
static void Main()
{
IUrlHistoryStg2 stg = (IUrlHistoryStg2) new UrlHistory();
stg.ClearHistory();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果服务或应用程序冒充用户,系统不会加载用户的配置文件。首先尝试调用 LoadUserProfile 。
If a service or an application impersonates a user, the system does not load the user's profile. Try call LoadUserProfile first.
IUrlHistoryStg2 最终使用 Wininet API,例如CommitUrlCacheEntryW
Microsoft 文档指出那:
我反转了这些 API,发现他们检查了从
如果其中任何一个为真,则该 API 存在,错误代码为 0x80070078
因此,幸运的是,您试图实现的目标不可能从服务中实现,您必须使用 CreateProcessAsUser
IUrlHistoryStg2 eventually uses the Wininet APIs such as CommitUrlCacheEntryW
Microsoft documentation states that:
I reversed those API and found out the they have check for
If either is true, the API exists with error code 0x80070078
So, fortunately what you are trying to achieve is not possible from a service and you must use CreateProcessAsUser