/*++ Copyright (c) 2000 Microsoft Corporation Module Name: nettype.c Abstract: Author: Jay Thaler (jthaler) 21 Apr 2000 Revision History: --*/ // // Includes // #include "pch.h" #include "logmsg.h" #include #define DBG_NETRESOURCES "MappedDrives" // // Strings // #define S_MAPPEDDRIVES_POOL_NAME "MappedDrives" #define S_MAPPEDDRIVES_NAME TEXT("MappedDrives") #define S_CORPNET_NAME TEXT("Net Printers and Drives") // // Constants // // none // // Macros // // none // // Types // typedef struct { PCTSTR Pattern; HASHTABLE_ENUM HashData; } NETRESOURCE_ENUM, *PNETRESOURCE_ENUM; typedef struct { DWORD DisplayType; DWORD Usage; CHAR Comment[MAX_PATH]; } NETDRIVE_DATAA, *PNETDRIVE_DATAA; typedef struct { DWORD DisplayType; DWORD Usage; WCHAR Comment[MAX_PATH]; } NETDRIVE_DATAW, *PNETDRIVE_DATAW; #ifdef UNICODE #define NETDRIVE_DATA NETDRIVE_DATAW #define PNETDRIVE_DATA PNETDRIVE_DATAW #else #define NETDRIVE_DATA NETDRIVE_DATAA #define PNETDRIVE_DATA PNETDRIVE_DATAA #endif // // Globals // PMHANDLE g_MappedDrivesPool = NULL; HASHTABLE g_MappedDrivesTable; HASHTABLE g_DriveCollisionTable; MIG_OBJECTTYPEID g_MappedDriveTypeId = 0; GROWBUFFER g_MappedDriveConversionBuff = INIT_GROWBUFFER; BOOL g_MappedDrivesMigEnabled = FALSE; DWORD g_AvailableDrives = 0; MIG_OPERATIONID g_MappedDriveOp; BOOL g_DelayNetDrivesOp = FALSE; // // Macro expansion list // // None // // Private function prototypes // // None // // Macro expansion definition // // None // // Private prototypes // SGMENUMERATIONCALLBACK SgmMappedDrivesCallback; VCMENUMERATIONCALLBACK VcmMappedDrivesCallback; TYPE_ENUMFIRSTPHYSICALOBJECT EnumFirstMappedDrive; TYPE_ENUMNEXTPHYSICALOBJECT EnumNextMappedDrive; TYPE_ABORTENUMPHYSICALOBJECT AbortEnumMappedDrive; TYPE_CONVERTOBJECTTOMULTISZ ConvertMappedDriveToMultiSz; TYPE_CONVERTMULTISZTOOBJECT ConvertMultiSzToMappedDrive; TYPE_GETNATIVEOBJECTNAME GetNativeMappedDriveName; TYPE_ACQUIREPHYSICALOBJECT AcquireMappedDrive; TYPE_RELEASEPHYSICALOBJECT ReleaseMappedDrive; TYPE_DOESPHYSICALOBJECTEXIST DoesMappedDriveExist; TYPE_REMOVEPHYSICALOBJECT RemoveMappedDrive; TYPE_CREATEPHYSICALOBJECT CreateMappedDrive; TYPE_REPLACEPHYSICALOBJECT ReplaceMappedDrive; TYPE_CONVERTOBJECTCONTENTTOUNICODE ConvertMappedDriveContentToUnicode; TYPE_CONVERTOBJECTCONTENTTOANSI ConvertMappedDriveContentToAnsi; TYPE_FREECONVERTEDOBJECTCONTENT FreeConvertedMappedDriveContent; OPMFILTERCALLBACK FilterMappedDrive; // // Code // BOOL NetDrivesInitialize ( VOID ) { g_MappedDrivesTable = HtAllocWithData (sizeof (PNETDRIVE_DATA)); g_MappedDrivesPool = PmCreateNamedPool (S_MAPPEDDRIVES_POOL_NAME); return (g_MappedDrivesPool != NULL); } VOID NetDrivesTerminate ( VOID ) { HASHTABLE_ENUM e; PNETDRIVE_DATA netdriveData; GbFree (&g_MappedDriveConversionBuff); if (g_MappedDrivesTable) { if (EnumFirstHashTableString (&e, g_MappedDrivesTable)) { do { netdriveData = *((PNETDRIVE_DATA *) e.ExtraData); if (netdriveData) { PmReleaseMemory (g_MappedDrivesPool, netdriveData); } } while (EnumNextHashTableString (&e)); } HtFree (g_MappedDrivesTable); g_MappedDrivesTable = NULL; } if (g_MappedDrivesPool) { PmDestroyPool (g_MappedDrivesPool); g_MappedDrivesPool = NULL; } } BOOL pLoadMappedDrivesData ( VOID ) { DWORD error; LPNETRESOURCE netBuffer = NULL; HANDLE netHandle; DWORD netBufferSize = 16384; // 16K is a good size DWORD netNumEntries = -1; // enumerate all possible entries DWORD i; PNETDRIVE_DATA netDriveData; MIG_OBJECTSTRINGHANDLE netObject = NULL; error = WNetOpenEnum (RESOURCE_REMEMBERED, RESOURCETYPE_DISK, 0, netBuffer, &netHandle); if (error != NO_ERROR) { return FALSE; } netBuffer = PmGetMemory (g_MappedDrivesPool, netBufferSize); do { ZeroMemory(netBuffer, netBufferSize); error = WNetEnumResource (netHandle, &netNumEntries, netBuffer, &netBufferSize); if (error == ERROR_NO_MORE_ITEMS) { break; } if (error != NO_ERROR) { PmReleaseMemory (g_MappedDrivesPool, netBuffer); return FALSE; } for (i=0; iDisplayType = netBuffer[i].dwDisplayType; netDriveData->Usage = netBuffer[i].dwUsage; if (netBuffer[i].lpComment) { StringCopyTcharCount (netDriveData->Comment, netBuffer[i].lpComment, MAX_PATH); } HtAddStringEx (g_MappedDrivesTable, netObject, &netDriveData, FALSE); IsmDestroyObjectHandle (netObject); } } } } while (error != ERROR_NO_MORE_ITEMS); PmReleaseMemory (g_MappedDrivesPool, netBuffer); return TRUE; } BOOL WINAPI NetDrivesEtmInitialize ( IN MIG_PLATFORMTYPEID Platform, IN PMIG_LOGCALLBACK LogCallback, IN PVOID Reserved ) { TYPE_REGISTER mappedDrivesTypeData; LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback); pLoadMappedDrivesData (); ZeroMemory (&mappedDrivesTypeData, sizeof (TYPE_REGISTER)); if (Platform == PLATFORM_SOURCE) { mappedDrivesTypeData.EnumFirstPhysicalObject = EnumFirstMappedDrive; mappedDrivesTypeData.EnumNextPhysicalObject = EnumNextMappedDrive; mappedDrivesTypeData.AbortEnumPhysicalObject = AbortEnumMappedDrive; mappedDrivesTypeData.ConvertObjectToMultiSz = ConvertMappedDriveToMultiSz; mappedDrivesTypeData.ConvertMultiSzToObject = ConvertMultiSzToMappedDrive; mappedDrivesTypeData.GetNativeObjectName = GetNativeMappedDriveName; mappedDrivesTypeData.AcquirePhysicalObject = AcquireMappedDrive; mappedDrivesTypeData.ReleasePhysicalObject = ReleaseMappedDrive; mappedDrivesTypeData.ConvertObjectContentToUnicode = ConvertMappedDriveContentToUnicode; mappedDrivesTypeData.ConvertObjectContentToAnsi = ConvertMappedDriveContentToAnsi; mappedDrivesTypeData.FreeConvertedObjectContent = FreeConvertedMappedDriveContent; g_MappedDriveTypeId = IsmRegisterObjectType ( S_MAPPEDDRIVES_NAME, TRUE, FALSE, &mappedDrivesTypeData ); } else { mappedDrivesTypeData.EnumFirstPhysicalObject = EnumFirstMappedDrive; mappedDrivesTypeData.EnumNextPhysicalObject = EnumNextMappedDrive; mappedDrivesTypeData.AbortEnumPhysicalObject = AbortEnumMappedDrive; mappedDrivesTypeData.ConvertObjectToMultiSz = ConvertMappedDriveToMultiSz; mappedDrivesTypeData.ConvertMultiSzToObject = ConvertMultiSzToMappedDrive; mappedDrivesTypeData.GetNativeObjectName = GetNativeMappedDriveName; mappedDrivesTypeData.AcquirePhysicalObject = AcquireMappedDrive; mappedDrivesTypeData.ReleasePhysicalObject = ReleaseMappedDrive; mappedDrivesTypeData.DoesPhysicalObjectExist = DoesMappedDriveExist; mappedDrivesTypeData.RemovePhysicalObject = RemoveMappedDrive; mappedDrivesTypeData.CreatePhysicalObject = CreateMappedDrive; mappedDrivesTypeData.ReplacePhysicalObject = ReplaceMappedDrive; mappedDrivesTypeData.ConvertObjectContentToUnicode = ConvertMappedDriveContentToUnicode; mappedDrivesTypeData.ConvertObjectContentToAnsi = ConvertMappedDriveContentToAnsi; mappedDrivesTypeData.FreeConvertedObjectContent = FreeConvertedMappedDriveContent; g_MappedDriveTypeId = IsmRegisterObjectType ( S_MAPPEDDRIVES_NAME, TRUE, FALSE, &mappedDrivesTypeData ); } MYASSERT (g_MappedDriveTypeId); return TRUE; } VOID WINAPI NetDrivesEtmNewUserCreated ( IN PCTSTR UserName, IN PCTSTR DomainName, IN PCTSTR UserProfileRoot, IN PSID UserSid ) { // a new user was created, the network drives operations need to be delayed NetDrivesTerminate (); g_DelayNetDrivesOp = TRUE; } BOOL WINAPI NetDrivesSgmInitialize ( IN PMIG_LOGCALLBACK LogCallback, IN PVOID Reserved ) { LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback); return TRUE; } BOOL WINAPI NetDrivesSgmParse ( IN PVOID Reserved ) { PCTSTR friendlyName; friendlyName = GetStringResource (MSG_NET_DRIVES_NAME); //IsmAddComponentAlias ( // S_MAPPEDDRIVES_NAME, // MASTERGROUP_SYSTEM, // friendlyName, // COMPONENT_NAME, // FALSE // ); IsmAddComponentAlias ( S_CORPNET_NAME, MASTERGROUP_SYSTEM, friendlyName, COMPONENT_NAME, FALSE ); FreeStringResource (friendlyName); return TRUE; } UINT SgmMappedDrivesCallback ( IN PCMIG_OBJECTENUMDATA Data, IN ULONG_PTR CallerArg ) { IsmMakeApplyObject (Data->ObjectTypeId, Data->ObjectName); IsmSetOperationOnObject (Data->ObjectTypeId, Data->ObjectName, g_MappedDriveOp, NULL, NULL); IsmMakeNonCriticalObject (Data->ObjectTypeId, Data->ObjectName); return CALLBACK_ENUM_CONTINUE; } BOOL pEnumMappedDriveWorker ( OUT PMIG_TYPEOBJECTENUM EnumPtr, IN PNETRESOURCE_ENUM MappedDriveEnum ) { if (EnumPtr->ObjectNode) { IsmDestroyObjectString (EnumPtr->ObjectNode); EnumPtr->ObjectNode = NULL; } if (EnumPtr->ObjectLeaf) { IsmDestroyObjectString (EnumPtr->ObjectLeaf); EnumPtr->ObjectLeaf = NULL; } if (EnumPtr->NativeObjectName) { PmReleaseMemory (g_MappedDrivesPool, EnumPtr->NativeObjectName); EnumPtr->NativeObjectName = NULL; } do { EnumPtr->ObjectName = MappedDriveEnum->HashData.String; if (!ObsPatternMatch (MappedDriveEnum->Pattern, EnumPtr->ObjectName)) { if (!EnumNextHashTableString (&MappedDriveEnum->HashData)) { AbortEnumMappedDrive (EnumPtr); return FALSE; } continue; } IsmCreateObjectStringsFromHandle (EnumPtr->ObjectName, &EnumPtr->ObjectNode, &EnumPtr->ObjectLeaf); EnumPtr->NativeObjectName = JoinPathsInPoolEx (( g_MappedDrivesPool, EnumPtr->ObjectNode, TEXT("<=>"), EnumPtr->ObjectLeaf, NULL )); EnumPtr->Level = 1; EnumPtr->SubLevel = 0; EnumPtr->IsLeaf = FALSE; EnumPtr->IsNode = TRUE; EnumPtr->Details.DetailsSize = 0; EnumPtr->Details.DetailsData = NULL; return TRUE; } while (TRUE); } BOOL EnumFirstMappedDrive ( IN OUT PMIG_TYPEOBJECTENUM EnumPtr, CALLER_INITIALIZED IN MIG_OBJECTSTRINGHANDLE Pattern, IN UINT MaxLevel ) { PNETRESOURCE_ENUM netResourceEnum = NULL; if (!g_MappedDrivesTable) { AbortEnumMappedDrive (EnumPtr); return FALSE; } netResourceEnum = (PNETRESOURCE_ENUM) PmGetMemory (g_MappedDrivesPool, sizeof (NETRESOURCE_ENUM)); netResourceEnum->Pattern = PmDuplicateString (g_MappedDrivesPool, Pattern); EnumPtr->EtmHandle = (LONG_PTR) netResourceEnum; if (EnumFirstHashTableString (&netResourceEnum->HashData, g_MappedDrivesTable)) { return pEnumMappedDriveWorker (EnumPtr, netResourceEnum); } else { AbortEnumMappedDrive (EnumPtr); return FALSE; } } BOOL EnumNextMappedDrive ( IN OUT PMIG_TYPEOBJECTENUM EnumPtr ) { PNETRESOURCE_ENUM netResourceEnum = NULL; netResourceEnum = (PNETRESOURCE_ENUM)(EnumPtr->EtmHandle); if (!netResourceEnum) { AbortEnumMappedDrive (EnumPtr); return FALSE; } if (EnumNextHashTableString (&netResourceEnum->HashData)) { return pEnumMappedDriveWorker (EnumPtr, netResourceEnum); } else { AbortEnumMappedDrive (EnumPtr); return FALSE; } } VOID AbortEnumMappedDrive ( IN OUT PMIG_TYPEOBJECTENUM EnumPtr ) { PNETRESOURCE_ENUM netResourceEnum = NULL; if (EnumPtr->ObjectNode) { IsmDestroyObjectString (EnumPtr->ObjectNode); EnumPtr->ObjectNode = NULL; } if (EnumPtr->ObjectLeaf) { IsmDestroyObjectString (EnumPtr->ObjectLeaf); EnumPtr->ObjectLeaf = NULL; } if (EnumPtr->NativeObjectName) { PmReleaseMemory (g_MappedDrivesPool, EnumPtr->NativeObjectName); EnumPtr->NativeObjectName = NULL; } netResourceEnum = (PNETRESOURCE_ENUM)(EnumPtr->EtmHandle); if (!netResourceEnum) { ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM)); return; } PmReleaseMemory (g_MappedDrivesPool, netResourceEnum->Pattern); PmReleaseMemory (g_MappedDrivesPool, netResourceEnum); ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM)); } BOOL AcquireMappedDrive ( IN MIG_OBJECTSTRINGHANDLE ObjectName, OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED IN MIG_CONTENTTYPE ContentType, IN UINT MemoryContentLimit ) { BOOL result = FALSE; PNETDRIVE_DATA netdriveData; if (!ObjectContent) { return FALSE; } // NOTE: Do not zero ObjectContent; some of its members were already set if (ContentType == CONTENTTYPE_FILE) { // nobody should request this as a file DEBUGMSG (( DBG_WHOOPS, "Unexpected acquire request for %s: Can't acquire mapped drives as files", ObjectName )); return FALSE; } if (HtFindStringEx (g_MappedDrivesTable, ObjectName, (PVOID) &netdriveData, FALSE)) { // // Fill in all the content members. We already zeroed the struct, // so most of the members are taken care of because they are zero. // ObjectContent->MemoryContent.ContentBytes = (PBYTE)netdriveData; ObjectContent->MemoryContent.ContentSize = sizeof(NETDRIVE_DATA); result = TRUE; } return result; } BOOL ReleaseMappedDrive ( IN OUT PMIG_CONTENT ObjectContent ) { if (ObjectContent) { ZeroMemory (ObjectContent, sizeof (MIG_CONTENT)); } return TRUE; } BOOL DoesMappedDriveExist ( IN MIG_OBJECTSTRINGHANDLE ObjectName ) { if (!g_MappedDrivesTable) { return FALSE; } return (HtFindStringEx (g_MappedDrivesTable, ObjectName, NULL, FALSE) != NULL); } BOOL RemoveMappedDrive ( IN MIG_OBJECTSTRINGHANDLE ObjectName ) { PCTSTR node; PCTSTR leaf; DWORD result = ERROR_NOT_FOUND; if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { if (node && (leaf)) { IsmRecordOperation (JRNOP_DELETE, g_MappedDriveTypeId, ObjectName); // Only set CONNECT_UPDATE_PROFILE when deleting a connection that persists result = WNetCancelConnection2 ((LPCTSTR)node, CONNECT_UPDATE_PROFILE, TRUE); if (result != ERROR_SUCCESS) { DEBUGMSG ((DBG_NETRESOURCES, "Failed to delete existent net resource %s", node)); } } IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } return (result == ERROR_SUCCESS); } BOOL CreateMappedDrive ( IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { PCTSTR node; PCTSTR leaf; NETRESOURCE netResource; BOOL result = ERROR_NOT_FOUND; PNETDRIVE_DATA netDriveData = NULL; if (!ObjectContent->ContentInFile) { if (ObjectContent->MemoryContent.ContentBytes && ObjectContent->MemoryContent.ContentSize) { if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { if (node && (leaf)) { if (g_DelayNetDrivesOp) { // we need to delay this operation // record delayed printer create operation IsmRecordDelayedOperation ( JRNOP_CREATE, g_MappedDriveTypeId, ObjectName, ObjectContent ); result = TRUE; } else { netDriveData = (PNETDRIVE_DATA) PmGetMemory (g_MappedDrivesPool, sizeof (NETDRIVE_DATA)); CopyMemory (netDriveData, ObjectContent->MemoryContent.ContentBytes, sizeof (NETDRIVE_DATA)); ZeroMemory (&netResource, sizeof (NETRESOURCE)); netResource.dwScope = RESOURCE_REMEMBERED; netResource.dwType = RESOURCETYPE_DISK; netResource.dwDisplayType = netDriveData->DisplayType; netResource.dwUsage = netDriveData->Usage; netResource.lpLocalName = (LPTSTR)node; netResource.lpRemoteName = (LPTSTR)leaf; netResource.lpComment = netDriveData->Comment; netResource.lpProvider = NULL; // Let the API determine the provider IsmRecordOperation (JRNOP_CREATE, g_MappedDriveTypeId, ObjectName); result = WNetAddConnection2 (&netResource, NULL, NULL, CONNECT_UPDATE_PROFILE); if (result != ERROR_SUCCESS) { DEBUGMSG ((DBG_NETRESOURCES, "Failed to add net resource for %s", node)); } PmReleaseMemory (g_MappedDrivesPool, netDriveData); } } } } } SetLastError (result); return (result == ERROR_SUCCESS); } BOOL ReplaceMappedDrive ( IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { BOOL result = TRUE; if (g_DelayNetDrivesOp) { // we need to delay this operation // record delayed printer replace operation IsmRecordDelayedOperation ( JRNOP_REPLACE, g_MappedDriveTypeId, ObjectName, ObjectContent ); result = TRUE; } else { // we are going to delete any existing net share with this name, // and create a new one if (DoesMappedDriveExist (ObjectName)) { result = RemoveMappedDrive (ObjectName); } if (result) { result = CreateMappedDrive (ObjectName, ObjectContent); } } return result; } PCTSTR ConvertMappedDriveToMultiSz ( IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { PCTSTR node, leaf; PTSTR result = NULL; BOOL bresult = TRUE; PNETDRIVE_DATA netDriveData; if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { MYASSERT (leaf); g_MappedDriveConversionBuff.End = 0; GbCopyQuotedString (&g_MappedDriveConversionBuff, node); GbCopyQuotedString (&g_MappedDriveConversionBuff, leaf); MYASSERT (ObjectContent->Details.DetailsSize == 0); MYASSERT (!ObjectContent->ContentInFile); MYASSERT (ObjectContent->MemoryContent.ContentSize = sizeof (NETDRIVE_DATA)); if (ObjectContent->MemoryContent.ContentBytes) { netDriveData = (PNETDRIVE_DATA)ObjectContent->MemoryContent.ContentBytes; wsprintf ( (PTSTR) GbGrow (&g_MappedDriveConversionBuff, (sizeof (DWORD) * 2 + 3) * sizeof (TCHAR)), TEXT("0x%08X"), netDriveData->DisplayType ); wsprintf ( (PTSTR) GbGrow (&g_MappedDriveConversionBuff, (sizeof (DWORD) * 2 + 3) * sizeof (TCHAR)), TEXT("0x%08X"), netDriveData->Usage ); GbCopyQuotedString (&g_MappedDriveConversionBuff, netDriveData->Comment); } else { bresult = FALSE; } if (bresult) { GbCopyString (&g_MappedDriveConversionBuff, TEXT("")); result = IsmGetMemory (g_MappedDriveConversionBuff.End); CopyMemory (result, g_MappedDriveConversionBuff.Buf, g_MappedDriveConversionBuff.End); } g_MappedDriveConversionBuff.End = 0; IsmDestroyObjectString (node); INVALID_POINTER (node); IsmDestroyObjectString (leaf); INVALID_POINTER (leaf); } return result; } BOOL ConvertMultiSzToMappedDrive ( IN PCTSTR ObjectMultiSz, OUT MIG_OBJECTSTRINGHANDLE *ObjectName, OUT PMIG_CONTENT ObjectContent CALLER_INITIALIZED OPTIONAL ) { MULTISZ_ENUM multiSzEnum; PCTSTR localName = NULL; PCTSTR remoteName = NULL; NETDRIVE_DATA netDriveData; DWORD dummy; UINT index; g_MappedDriveConversionBuff.End = 0; // // Parse the multi-sz into the net drive content and details. // The user may have edited the text (and potentially introduced // errors). // ZeroMemory (&netDriveData, sizeof (NETDRIVE_DATA)); if (EnumFirstMultiSz (&multiSzEnum, ObjectMultiSz)) { index = 0; do { if (index == 0) { localName = multiSzEnum.CurrentString; } if (index == 1) { remoteName = multiSzEnum.CurrentString; } if (index == 2) { _stscanf (multiSzEnum.CurrentString, TEXT("%lx"), &dummy); netDriveData.DisplayType = dummy; } if (index == 3) { _stscanf (multiSzEnum.CurrentString, TEXT("%lx"), &dummy); netDriveData.Usage = dummy; } if (index == 4) { if (!StringIMatch (multiSzEnum.CurrentString, TEXT(""))) { StringCopyTcharCount (netDriveData.Comment, multiSzEnum.CurrentString, MAX_PATH); } } index++; } while (EnumNextMultiSz (&multiSzEnum)); } if (!localName || !remoteName) { // // Bogus data, fail // return FALSE; } // // Fill in all the members of the content structure. // if (ObjectContent) { ObjectContent->ContentInFile = FALSE; ObjectContent->MemoryContent.ContentSize = sizeof (NETDRIVE_DATA); ObjectContent->MemoryContent.ContentBytes = IsmGetMemory (ObjectContent->MemoryContent.ContentSize); CopyMemory ( (PBYTE)ObjectContent->MemoryContent.ContentBytes, &netDriveData, ObjectContent->MemoryContent.ContentSize ); ObjectContent->Details.DetailsSize = 0; ObjectContent->Details.DetailsData = NULL; } *ObjectName = IsmCreateObjectHandle (localName, remoteName); return TRUE; } PCTSTR GetNativeMappedDriveName ( IN MIG_OBJECTSTRINGHANDLE ObjectName ) { PCTSTR node = NULL, leaf = NULL; PTSTR leafPtr = NULL, leafBegin = NULL, nodePtr = NULL; UINT strSize = 0; PTSTR result = NULL; if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) { if (leaf) { leafPtr = _tcsrchr (leaf, TEXT('\\')); if (leafPtr) { *leafPtr = 0; leafPtr ++; } leafBegin = (PTSTR)leaf; while (*leafBegin == TEXT('\\')) { leafBegin ++; } } if (node) { nodePtr = _tcsrchr (node, TEXT('\\')); if (nodePtr) { *nodePtr = 0; } } if (leafPtr) { if (node) { strSize = CharCount (leafPtr) + \ CharCount (TEXT(" on \'")) + \ CharCount (leafBegin) + \ CharCount (TEXT("\' (")) + \ CharCount (node) + \ CharCount (TEXT(")")) + \ 1; result = IsmGetMemory (strSize * sizeof (TCHAR)); _tcscpy (result, leafPtr); _tcscat (result, TEXT(" on \'")); _tcscat (result, leafBegin); _tcscat (result, TEXT("\' (")); _tcscat (result, node); _tcscat (result, TEXT(")")); } else { strSize = CharCount (leafPtr) + \ CharCount (TEXT(" on \'")) + \ CharCount (leafBegin) + \ CharCount (TEXT("\'")) + \ 1; result = IsmGetMemory (strSize * sizeof (TCHAR)); _tcscpy (result, leafPtr); _tcscat (result, TEXT(" on \'")); _tcscat (result, leafBegin); _tcscat (result, TEXT("\'")); } } else { if (leafBegin) { if (node) { strSize = CharCount (TEXT("\'")) + \ CharCount (leafBegin) + \ CharCount (TEXT("\' (")) + \ CharCount (node) + \ CharCount (TEXT(")")) + \ 1; result = IsmGetMemory (strSize * sizeof (TCHAR)); _tcscpy (result, TEXT("\'")); _tcscat (result, leafBegin); _tcscat (result, TEXT("\' (")); _tcscat (result, node); _tcscat (result, TEXT(")")); } else { strSize = CharCount (TEXT("\'")) + \ CharCount (leafBegin) + \ CharCount (TEXT("\'")) + \ 1; _tcscpy (result, TEXT("\'")); _tcscat (result, leafBegin); _tcscat (result, TEXT("\'")); } } else { if (node) { strSize = CharCount (TEXT("(")) + \ CharCount (node) + \ CharCount (TEXT(")")) + \ 1; result = IsmGetMemory (strSize * sizeof (TCHAR)); _tcscpy (result, TEXT("(")); _tcscat (result, node); _tcscat (result, TEXT(")")); } } } IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } return result; } PMIG_CONTENT ConvertMappedDriveContentToUnicode ( IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { PMIG_CONTENT result = NULL; if (!ObjectContent) { return result; } if (ObjectContent->ContentInFile) { return result; } result = IsmGetMemory (sizeof (MIG_CONTENT)); if (result) { CopyMemory (result, ObjectContent, sizeof (MIG_CONTENT)); if ((ObjectContent->MemoryContent.ContentSize != 0) && (ObjectContent->MemoryContent.ContentBytes != NULL) ) { // convert Mapped Drive content result->MemoryContent.ContentBytes = IsmGetMemory (sizeof (NETDRIVE_DATAW)); if (result->MemoryContent.ContentBytes) { ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->DisplayType = ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->DisplayType; ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->Usage = ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->Usage; DirectDbcsToUnicodeN ( ((PNETDRIVE_DATAW)result->MemoryContent.ContentBytes)->Comment, ((PNETDRIVE_DATAA)ObjectContent->MemoryContent.ContentBytes)->Comment, MAX_PATH ); result->MemoryContent.ContentSize = sizeof (NETDRIVE_DATAW); } } } return result; } PMIG_CONTENT ConvertMappedDriveContentToAnsi ( IN MIG_OBJECTSTRINGHANDLE ObjectName, IN PMIG_CONTENT ObjectContent ) { PMIG_CONTENT result = NULL; if (!ObjectContent) { return result; } if (ObjectContent->ContentInFile) { return result; } result = IsmGetMemory (sizeof (MIG_CONTENT)); if (result) { CopyMemory (result, ObjectContent, sizeof (MIG_CONTENT)); if ((ObjectContent->MemoryContent.ContentSize != 0) && (ObjectContent->MemoryContent.ContentBytes != NULL) ) { // convert Mapped Drive content result->MemoryContent.ContentBytes = IsmGetMemory (sizeof (NETDRIVE_DATAA)); if (result->MemoryContent.ContentBytes) { ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->DisplayType = ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->DisplayType; ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->Usage = ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->Usage; DirectUnicodeToDbcsN ( ((PNETDRIVE_DATAA)result->MemoryContent.ContentBytes)->Comment, ((PNETDRIVE_DATAW)ObjectContent->MemoryContent.ContentBytes)->Comment, MAX_PATH ); result->MemoryContent.ContentSize = sizeof (NETDRIVE_DATAA); } } } return result; } BOOL FreeConvertedMappedDriveContent ( IN PMIG_CONTENT ObjectContent ) { if (!ObjectContent) { return TRUE; } if (ObjectContent->MemoryContent.ContentBytes) { IsmReleaseMemory (ObjectContent->MemoryContent.ContentBytes); } IsmReleaseMemory (ObjectContent); return TRUE; } BOOL WINAPI NetDrivesVcmInitialize ( IN PMIG_LOGCALLBACK LogCallback, IN PVOID Reserved ) { LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback); return TRUE; } BOOL WINAPI NetDrivesVcmParse ( IN PVOID Reserved ) { return NetDrivesSgmParse (Reserved); } UINT VcmMappedDrivesCallback ( IN PCMIG_OBJECTENUMDATA Data, IN ULONG_PTR CallerArg ) { IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName); return CALLBACK_ENUM_CONTINUE; } BOOL pCommonNetDrivesQueueEnumeration ( IN BOOL VcmMode ) { ENCODEDSTRHANDLE pattern; if (!IsmIsComponentSelected (S_MAPPEDDRIVES_NAME, 0) && !IsmIsComponentSelected (S_CORPNET_NAME, 0) ) { g_MappedDrivesMigEnabled = FALSE; return TRUE; } g_MappedDrivesMigEnabled = TRUE; g_MappedDriveOp = IsmRegisterOperation (S_OPERATION_DRIVEMAP_FIXCONTENT, TRUE); pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE); IsmQueueEnumeration ( g_MappedDriveTypeId, pattern, VcmMode ? VcmMappedDrivesCallback : SgmMappedDrivesCallback, (ULONG_PTR) 0, S_MAPPEDDRIVES_NAME ); IsmDestroyObjectHandle (pattern); return TRUE; } BOOL WINAPI NetDrivesSgmQueueEnumeration ( IN PVOID Reserved ) { return pCommonNetDrivesQueueEnumeration (FALSE); } BOOL WINAPI NetDrivesVcmQueueEnumeration ( IN PVOID Reserved ) { return pCommonNetDrivesQueueEnumeration (TRUE); } BOOL WINAPI NetDrivesCsmInitialize ( IN PMIG_LOGCALLBACK LogCallback, IN PVOID Reserved ) { g_AvailableDrives = GetLogicalDrives (); g_DriveCollisionTable = HtAllocWithData (sizeof (TCHAR)); return TRUE; } DWORD pConvertDriveToBit ( PCTSTR driveString ) { DWORD bit = 0; TCHAR driveLetter; if (driveString && *driveString) { driveLetter = (TCHAR)_totlower (*driveString); if (driveLetter >= TEXT('a') && driveLetter <= TEXT('z')) { bit = 0x1 << (driveLetter - TEXT('a')); } } return bit; } BOOL pReserveAvailableDrive ( TCHAR *driveLetter ) { DWORD bit; BOOL success = FALSE; // Start at bit 2 so we only map to C: or higher for (bit = 2; bit < 26; bit++) { if (!(g_AvailableDrives & (1 << bit))) { success = TRUE; g_AvailableDrives |= (1 << bit); *driveLetter = (TCHAR)(TEXT('a') + bit); break; } } return success; } BOOL WINAPI NetDrivesCsmExecute ( VOID ) { GROWBUFFER collisions = INIT_GROWBUFFER; DWORD driveBit; TCHAR existingPath[MAX_PATH + 1]; MULTISZ_ENUM e; TCHAR freeDrive; DWORD bufferSize; MIG_OBJECTSTRINGHANDLE pattern; MIG_OBJECT_ENUM objectEnum; PCTSTR node; PCTSTR leaf; DWORD result; // First, enumerate all the mapped drives and look for collisions pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE); // *,* if (IsmEnumFirstSourceObject (&objectEnum, g_MappedDriveTypeId, pattern)) { do { IsmCreateObjectStringsFromHandle (objectEnum.ObjectName, &node, &leaf); // Leaf is the remote name. driveBit = pConvertDriveToBit (node); if (g_AvailableDrives & driveBit) { // Something is already there. Is it the same thing? ZeroMemory (existingPath, MAX_PATH + 1); bufferSize = MAX_PATH + 1; result = WNetGetConnection (node, existingPath, &bufferSize); if (result != NO_ERROR) { // this might be a fixed drive GbMultiSzAppend (&collisions, node); } else { if (!StringIMatch (existingPath, leaf)) { // Whoops, we have a collision. Save it for later GbMultiSzAppend (&collisions, node); } } } else { // It's free, so let's reserve it. g_AvailableDrives |= driveBit; } IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } while (IsmEnumNextObject (&objectEnum)); } IsmDestroyObjectHandle (pattern); INVALID_POINTER (pattern); // Enumerate collided mappings and find new destinations if (EnumFirstMultiSz (&e, (PCTSTR) collisions.Buf)) { do { if (pReserveAvailableDrive (&freeDrive)) { HtAddStringEx (g_DriveCollisionTable, e.CurrentString, &freeDrive, FALSE); } } while (EnumNextMultiSz (&e)); } GbFree (&collisions); return TRUE; } BOOL WINAPI NetDrivesOpmInitialize ( IN PMIG_LOGCALLBACK LogCallback, IN PVOID Reserved ) { // // Get attribute and operation types // g_MappedDriveOp = IsmRegisterOperation (S_OPERATION_DRIVEMAP_FIXCONTENT, TRUE); // // Register operation callbacks // IsmRegisterOperationFilterCallback (g_MappedDriveOp, FilterMappedDrive, TRUE, TRUE, FALSE); return TRUE; } BOOL WINAPI FilterMappedDrive ( IN PCMIG_FILTERINPUT InputData, OUT PMIG_FILTEROUTPUT OutputData, IN BOOL NoRestoreObject, IN PCMIG_BLOB SourceOperationData, OPTIONAL IN PCMIG_BLOB DestinationOperationData OPTIONAL ) { PTSTR node = NULL; PCTSTR leaf = NULL; MIG_OBJECTSTRINGHANDLE destHandle; TCHAR driveLetter; try { if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_MappedDriveTypeId) { DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterMappedDrive")); __leave; } if (!IsmCreateObjectStringsFromHandle ( InputData->OriginalObject.ObjectName, &node, &leaf )) { __leave; } MYASSERT (node); MYASSERT (leaf); if (node) { if (HtFindStringEx (g_DriveCollisionTable, node, &driveLetter, FALSE)) { node[0] = driveLetter; } destHandle = IsmCreateObjectHandle (node, leaf); if (destHandle) { OutputData->NewObject.ObjectName = destHandle; } } } __finally { IsmDestroyObjectString (node); IsmDestroyObjectString (leaf); } return TRUE; }