在「其他用户」上显示 V2 Credential Provider

遇到了一个跟 此问题 很类似的问题,即如何制作一个可以正确显示 其他用户 的 Credential Provider

1 问题

在制作 V2 版本的 Credential Provider 时,虽然技术参考中说,只要在 GetUserSid 中回传一个空指针的 sid,然后返回 S_FALSE 即可显示一个 其他用户 凭据,类似这样:

HRESULT OtherUserCredential::GetUserSid(PWSTR *ppszSid)
{
    *ppszSid = nullptr;
    return S_FALSE;
}

但是测试时却不是这样, 其他用户 并没有显示出来

2 讨论

这个问题可以分为两个部分:

  1. 其他用户 会在什么时候显示
  2. 如何在 其他用户 上显示 Credential Provider

2.1 其他用户 会在什么时候显示

根据 这个帖子 的信息,只有两种情况会显示 其他用户

  1. 电脑属于某个域
  2. 从 windows XP 进行远程连接

没有加域的电脑,会列出本地的所有可登录账户,而不是上次登录的用户和 其他用户

我们来看一下 win10 下的情况,这里我们使用 微软提供的 win10 虚拟机 创建几个用户

加入域之前,默认的登录界面如下图所示

可以看到 Logon UI 列出了所有可登录的本地账户,但没有 其他用户

接下来我们来编译安装 这里下载 的 Credential Provider V2 Sample 到虚拟机上, 如何安装这里不再详细叙述,但是注意编译时要使用 /MT 编译,否则虚拟机需要安装 VC 运行时, 如有时间我们再详细讨论如何编译注册这个 sample

我们发现 只有一个用户 新增了一个 sign-in options 的连接,点击它会出现 Sample 的图标, 再点击图标,就可以看到我们注册的 Sample 的登录界面

这里改变了分辨率来显示 sample 界面的字段, 只有一个用户是因为 sample 只为一个用户创建了凭据, 其他用户并没有获得 sample 创建的凭据。

然后我们注销 sample,把 vm 加入域,看看登录界面的变化

logon ui 只列出了上次登录的用户,以及 其他用户 ,然后我们再注册 sample 观察一下

上次登录的用户获得了 sample 的凭据,那么 其他用户

答案还是没有,原因前面说过,sample 只创建了一个凭据

不过我们讨论的第一个问题差不多已经有了答案:加入域后,logon ui 才会出现 其他用户

2.2 如何在 其他用户 上显示 sample

显示在 其他用户 上需要修改 sample 的代码,为了尽量简单,我们保留只创建一个凭据的做法, 也就是说,我们只为 其他用户 创建一个凭据

根据 技术参考 ,修改 GetUserSid 函数就可以在 其他用户 上显示, 其实我们也只需要修改这个函数

// Gets the SID of the user corresponding to the credential.
HRESULT CSampleCredential::GetUserSid(
    _Outptr_result_nullonfailure_ PWSTR *ppszSid)
{
    *ppszSid = nullptr;
    return S_FALSE;
}

接下来我们就可以在 vm 上测试

我们可以看到,原本显示在上次用户的凭据,现在显示到了 其他用户

所以我们可以得出结论: 技术参考是对的 :)

我们可以把 vm 退出域,再观察登录界面,这时没有用户有 sample 创建的凭据,因为 sample 只为 其他用户 创建了凭据,而 其他用户 这时不会被显示

3 总结

我们可以得到如下结论

  1. 在域环境下, 其他用户 才会被显示
  2. 如果要显示在 其他用户 中,GetUserSid 需要传递一个空 SID 并返回 S_FALSE