Why DOS devices defined in a session without impersonation are not displayed in Explorer

I have a Windows service running under the Local System account, which creates DOS devices using the DefineDosDevice function. The service runs on a remote W2K8 desktop server. If devices are created using service credentials, they are created in the namespace of GLOBAL devices and are therefore visible to all users. I need devices that are visible only for a specific interaction session.

I accomplish this by personifying the user in whose session I want the drives to display. This is pretty simple if a session id is available. Here is a simple test application that I wrote to illustrate the problem:

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;
}

, , LocalSystem:

sc create test_svc binpath = "cmd/K start" type = =

, , LocalSystem.

LocalSystem cmd.exe :

MySubst.exe x:/i 2

ImpersonateLoggedOnUser(), DefineDosDevice()

cmd.exe, , :

MySubst.exe y:

DefineDosDevice ImpersonateLoggedOnUser().

. cmd.exe X: Y:. notepad.exe "" X: Y:. , , X: Y:.

Explorer Y: " ". Y: , cmd.exe, , .. . explorer.exe , X: Y:.

WinObj.exe SysInternals Win NT. :

- Sessions
    - 0
        - DosDevices
            00000000-000057607

(57607 - , , )

"00000000-000057607":

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

WinObj, dos . . NT.

, Explorer, - .

+5
1

@arx @HarryJohnston . 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);
+4

All Articles