/*++ Copyright (c) 2000 Microsoft Corporation Module Name : umrdpdrv.c Abstract: User-Mode Component for RDP Device Management that Handles Drive Device- Specific tasks. This is a supporting module. The main module is umrdpdr.c. Author: Joy Chik 2/1/2000 Revision History: --*/ #include "precomp.h" #include #include #include "umrdpdr.h" #include "drdevlst.h" #include "umrdpdrv.h" #include "drdbg.h" // Global debug flag. extern DWORD GLOBAL_DEBUG_FLAGS; extern WCHAR ProviderName[MAX_PATH]; BOOL UMRDPDRV_HandleDriveAnnounceEvent( IN PDRDEVLST installedDevices, IN PRDPDR_DRIVEDEVICE_SUB pDriveAnnounce, HANDLE TokenForLoggedOnUser ) /*++ Routine Description: Handle a drive device announce event from the "dr" by adding a record for the device to the list of installed devices. Arguments: installedDevices - Comprehensive device list. pDriveAnnounce - Drive device announce event. TokenForLoggedOnUser - user token Return Value: Return TRUE on success. FALSE, otherwise. --*/ { DWORD status; BOOL fImpersonated; BOOL result; DWORD offset; LPNETRESOURCEW NetResource; WCHAR RemoteName[RDPDR_MAX_COMPUTER_NAME_LENGTH + 4 + RDPDR_MAX_DOSNAMELEN]; DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_HandleDriveAnnounceEvent with clientName %ws.\n", pDriveAnnounce->clientName)); DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_HandleDriveAnnounceEvent with drive %ws.\n", pDriveAnnounce->driveName)); DBGMSG(DBG_TRACE, ("UMRDPDRV:Preferred DOS name is %s.\n", pDriveAnnounce->deviceFields.PreferredDosName)); ASSERT((pDriveAnnounce->deviceFields.DeviceType == RDPDR_DTYP_FILESYSTEM)); ASSERT(TokenForLoggedOnUser != NULL); ASSERT(ProviderName[0] != L'\0'); // We need to impersonate the logged on user fImpersonated = ImpersonateLoggedOnUser(TokenForLoggedOnUser); if (fImpersonated) { DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_HandleDriveAnnounceEvent userToken: %p fImpersonated : %d.\n", TokenForLoggedOnUser, fImpersonated)); // Set up remote name in the format of \\clientname\drivename // Note: We don't want : for the drivename wcscpy(RemoteName, L"\\\\"); wcscat(RemoteName, pDriveAnnounce->clientName); wcscat(RemoteName, L"\\"); wcscat(RemoteName, pDriveAnnounce->driveName); if (RemoteName[wcslen(RemoteName) - 1] == L':') { RemoteName[wcslen(RemoteName) - 1] = L'\0'; } // Allocate the net resource struct NetResource = (LPNETRESOURCEW) LocalAlloc(LPTR, sizeof(NETRESOURCEW)); if (NetResource) { NetResource->dwScope = 0; NetResource->lpLocalName = NULL; NetResource->lpRemoteName = RemoteName; NetResource->lpProvider = ProviderName; status = WNetAddConnection2(NetResource, NULL, NULL, 0); if ( status == NO_ERROR) { DBGMSG(DBG_TRACE, ("UMRDPDRV:Added drive connection %ws\n", RemoteName)); result = TRUE; } else { DBGMSG(DBG_TRACE, ("UMRDPDRV:Failed to add drive connection %ws: %x\n", RemoteName, status)); result = FALSE; } LocalFree(NetResource); } else { DBGMSG(DBG_ERROR, ("UMRDPDRV:Failed to allocate NetResource\n")); result = FALSE; } if (result) { // Record the drive devices so that we can remove the connection // on disconnect/logoff result = DRDEVLST_Add(installedDevices, pDriveAnnounce->deviceFields.DeviceId, UMRDPDR_INVALIDSERVERDEVICEID, pDriveAnnounce->deviceFields.DeviceType, RemoteName, pDriveAnnounce->driveName, pDriveAnnounce->deviceFields.PreferredDosName ); if (result) { // Find the drive device in the devlist result = DRDEVLST_FindByClientDeviceIDAndDeviceType(installedDevices, pDriveAnnounce->deviceFields.DeviceId, pDriveAnnounce->deviceFields.DeviceType, &offset); if (result) { DBGMSG(DBG_TRACE, ("UMRDPDRV:Create shell reg folder for %ws\n", RemoteName)); // Create shell reg folder for the drive connection CreateDriveFolder(RemoteName, pDriveAnnounce->clientDisplayName, &(installedDevices->devices[offset])); } else { DBGMSG(DBG_ERROR, ("UMRDPDRV:Failed to find the device %ws in the devlist\n", pDriveAnnounce->driveName)); WNetCancelConnection2(RemoteName, 0, TRUE); } } else { DBGMSG(DBG_ERROR, ("UMRDPDRV:Failed to add the device %ws to the devlist\n", pDriveAnnounce->driveName)); WNetCancelConnection2(RemoteName, 0, TRUE); } } // Revert the thread token to self RevertToSelf(); } else { DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_HandleDriveAnnounceEvent, impersonation failed\n")); result = FALSE; } return result; } BOOL UMRDPDRV_DeleteDriveConnection( IN PDRDEVLSTENTRY deviceEntry, HANDLE TokenForLoggedOnUser ) /*++ Routine Description: Delete drive device connection on disconnect / logoff Arguments: deviceEntry - Drive Device to be deleted Return Value: Return TRUE on success. FALSE, otherwise. --*/ { DWORD status; BOOL result; BOOL fImpersonated; WCHAR *szGuid; DBGMSG(DBG_TRACE, ("UMRDPDRV:Delete client drive connection %ws\n", deviceEntry->serverDeviceName)); // We need to impersonate the logged on user fImpersonated = ImpersonateLoggedOnUser(TokenForLoggedOnUser); if (fImpersonated) { DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_DeleteDriveConnection userToken: %p fImpersonated : %d.\n", TokenForLoggedOnUser, fImpersonated)); // Remove the drive UNC connection status = WNetCancelConnection2(deviceEntry->serverDeviceName, 0, TRUE); // Remove the shell reg folder DeleteDriveFolder(deviceEntry); if (status == NO_ERROR) { DBGMSG(DBG_TRACE, ("UMRDPDRV: Deleted client drive connection %ws\n", deviceEntry->serverDeviceName)); result = TRUE; } else { DBGMSG(DBG_ERROR, ("UMRDPDRV: Failed to delete client drive connection %ws: %x\n", deviceEntry->serverDeviceName, status)); result = FALSE; } // Revert the thread token to self RevertToSelf(); } else { DBGMSG(DBG_TRACE, ("UMRDPDRV:UMRDPDRV_DeleteDriveConnection, impersonation failed\n")); result = FALSE; } return result; }