为什么在模拟会话中定义的DOS设备不会出现在资源pipe理器中

我有一个使用DefineDosDevice函数创buildDOS设备的本地系统帐户下运行的Windows服务。 该服务正在W2K8远程桌面服务器上运行。 如果设备是使用服务凭证创build的,则它们将在GLOBAL设备名称空间中创build,因此可供所有用户看到。 我需要这些设备只对特定的交互会话可见。

我通过模仿在其会话中希望驱动器出现的用户来实现这一点。 这是非常简单的,只要会话ID是可用的。 下面是我写的一个简单的testing应用程序来说明问题:

int _tmain(int argc, _TCHAR* argv[]) { BOOL result = TRUE; if(argc > 3 && !wcscmp(argv[2], L"/i")) { HANDLE hToken = 0; DWORD dwSessionId = _wtoi(argv[3]); result = WTSQueryUserToken(dwSessionId, &hToken); if(result) result = ImpersonateLoggedOnUser(hToken); } if(result) { LPTSTR drive = argv[1]; DefineDosDevice(DDD_REMOVE_DEFINITION, drive, NULL); result = DefineDosDevice(0, drive, L"C:\\test"); } if(!result) { printf("Error: %d\n", GetLastError()); } return 0; } 

为了testing这段代码,我创build了一个在LocalSystem帐户下启动一个命令shell的服务:

sc创buildtest_svc binpath =“cmd / K start”type = own type = interact

此服务无法启动,但在失败之前,它会生成一个在LocalSystem帐户下运行的命令shell。

从LocalSystem cmd.exe运行:

MySubst.exe x:/我2

调用ImpersonateLoggedOnUser(),然后调用DefineDosDevice()

从运行在用户会话中的cmd.exe运行:

MySubst.exe y:

其中调用DefineDosDevice 而不调用ImpersonateLoggedOnUser()。

这工作。 从cmd.exe我可以访问两个驱动器X:和Y :. 我可以从开始菜单启动notepad.exe,并查看X:和Y:驱动器。 此外,如果我用不同的用户创build一个新的terminal服务会话,我不会看到X:或Y :.

但是,资源pipe理器只显示“所有计算机”下的Y:驱动器。 Y:是通过在目标会话中运行cmd.exe运行我的testing应用程序而创build的驱动器,即未完成模拟。 如果我从任务pipe理器重新启动explorer.exe,则显示X:和Y:驱动器。

我也使用SysInternals中的WinObj.exe来检查定义的Win NT设备。 我所看到的是:

 - Sessions - 0 - DosDevices 00000000-000057607 

(57607是与我正在冒充的会话关联的login会话的ID)

“00000000-000057607”的内容是:

 Global SymbolicLink \Global?? X: SymbolicLink \\??\C:\test Y: SymbolicLink \\??\C:\test 

根据WinObj,这两个DOS设备是相同的。 它们属于同一个会话和login会话。 它们是相同的NT对象的符号链接。

怎么可能是其中一个出现在资源pipe理器中,另一个则不是。

@arx和@HarryJohnston是在钱上。 如果我从与explorer相同的会话中的线程广播WM_DEVICECHANGE消息,则新驱动器出现在“我的电脑”中。 代码如下:

 DWORD recipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS; DEV_BROADCAST_VOLUME msg; ZeroMemory(&msg, sizeof(msg)); msg.dbcv_size = sizeof(msg); msg.dbcv_devicetype = DBT_DEVTYP_VOLUME; msg.dbcv_unitmask = 1 << ('X' - 'A'); long success = BroadcastSystemMessage(0, &recipients, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&msg);