1295 lines
37 KiB
C
1295 lines
37 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
nettype.c
|
|
|
|
Abstract:
|
|
|
|
<abstract>
|
|
|
|
Author:
|
|
|
|
Jay Thaler (jthaler) 21 Apr 2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "logmsg.h"
|
|
#include <Winnetwk.h>
|
|
|
|
#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; i<netNumEntries; i++) {
|
|
if (netBuffer[i].lpLocalName != NULL) {
|
|
netObject = IsmCreateObjectHandle (netBuffer[i].lpLocalName, netBuffer[i].lpRemoteName);
|
|
if (netObject) {
|
|
netDriveData = (PNETDRIVE_DATA) PmGetMemory (g_MappedDrivesPool, sizeof (NETDRIVE_DATA));
|
|
ZeroMemory (netDriveData, sizeof (NETDRIVE_DATA));
|
|
netDriveData->DisplayType = 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("<empty>"))) {
|
|
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;
|
|
}
|
|
|