You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1377 lines
40 KiB
1377 lines
40 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
netshares.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>
|
|
#include <Lm.h>
|
|
#include <Lmshare.h>
|
|
|
|
#define DBG_NETSHARES "NetShares"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
#define S_NETSHARES_NAME TEXT("NetShares")
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
/* These flags are relevant for share-level security on VSERVER
|
|
* When operating with user-level security, use SHI50F_FULL - the actual
|
|
* access rights are determined by the NetAccess APIs.
|
|
*/
|
|
#define SHI50F_RDONLY 0x0001
|
|
#define SHI50F_FULL 0x0002
|
|
#define SHI50F_ACCESSMASK (SHI50F_RDONLY|SHI50F_FULL)
|
|
|
|
/* The share is restored on system startup */
|
|
#define SHI50F_PERSIST 0x0100
|
|
/* The share is not normally visible */
|
|
#define SHI50F_SYSTEM 0x0200
|
|
//
|
|
// Win9x migration net share flag, used to distinguish user-level security and
|
|
// password-level security. When it is specified, user-level
|
|
// security is enabled, and NetShares\<share>\ACL\<list> exists.
|
|
//
|
|
#define SHI50F_ACLS 0x1000
|
|
|
|
//
|
|
// Flags that help determine when custom access is enabled
|
|
//
|
|
|
|
#define READ_ACCESS_FLAGS 0x0081
|
|
#define READ_ACCESS_MASK 0x7fff
|
|
#define FULL_ACCESS_FLAGS 0x00b7
|
|
#define FULL_ACCESS_MASK 0x7fff
|
|
|
|
#define INDEXLOCAL 0
|
|
#define INDEXREMOTE 1
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
typedef struct {
|
|
PCTSTR Pattern;
|
|
HASHTABLE_ENUM HashData;
|
|
} NETSHARE_ENUM, *PNETSHARE_ENUM;
|
|
|
|
typedef struct {
|
|
CHAR sharePath[MAX_PATH + 1];
|
|
} NETSHARE_DATAA, *PNETSHARE_DATAA;
|
|
|
|
typedef struct {
|
|
WCHAR sharePath[MAX_PATH + 1];
|
|
} NETSHARE_DATAW, *PNETSHARE_DATAW;
|
|
|
|
#ifdef UNICODE
|
|
#define NETSHARE_DATA NETSHARE_DATAW
|
|
#define PNETSHARE_DATA PNETSHARE_DATAW
|
|
#else
|
|
#define NETSHARE_DATA NETSHARE_DATAA
|
|
#define PNETSHARE_DATA PNETSHARE_DATAA
|
|
#endif
|
|
|
|
//
|
|
// types not defined by public headers
|
|
//
|
|
|
|
typedef NET_API_STATUS (* ScanNetShareEnumNT) (
|
|
LMSTR servername,
|
|
DWORD level,
|
|
PBYTE *bufptr,
|
|
DWORD prefmaxlen,
|
|
PDWORD entriesread,
|
|
PDWORD totalentries,
|
|
PDWORD resume_handle
|
|
);
|
|
|
|
typedef NET_API_STATUS (* ScanNetShareEnum9x) (
|
|
const char * servername,
|
|
short level,
|
|
char * bufptr,
|
|
unsigned short prefmaxlen,
|
|
unsigned short * entriesread,
|
|
unsigned short * totalentries
|
|
);
|
|
|
|
typedef NET_API_STATUS (* ScanNetApiBufferFreeNT) ( void *);
|
|
|
|
typedef NET_API_STATUS (* ScanNetAccessEnum9x) (
|
|
const char * pszServer,
|
|
char * pszBasePath,
|
|
short fsRecursive,
|
|
short sLevel,
|
|
char * pbBuffer,
|
|
unsigned short cbBuffer,
|
|
unsigned short * pcEntriesRead,
|
|
unsigned short * pcTotalAvail
|
|
);
|
|
|
|
#pragma pack(push)
|
|
#pragma pack(1) /* Assume byte packing throughout */
|
|
|
|
struct _share_info_50 {
|
|
char shi50_netname[LM20_NNLEN+1];
|
|
unsigned char shi50_type;
|
|
unsigned short shi50_flags;
|
|
char * shi50_remark;
|
|
char * shi50_path;
|
|
char shi50_rw_password[SHPWLEN+1];
|
|
char shi50_ro_password[SHPWLEN+1];
|
|
};
|
|
|
|
struct access_list_2
|
|
{
|
|
char * acl2_ugname;
|
|
unsigned short acl2_access;
|
|
}; /* access_list_2 */
|
|
|
|
struct access_info_2
|
|
{
|
|
char * acc2_resource_name;
|
|
short acc2_attr;
|
|
unsigned short acc2_count;
|
|
}; /* access_info_2 */
|
|
|
|
#pragma pack(pop)
|
|
|
|
//
|
|
// netapi functions
|
|
//
|
|
|
|
typedef NET_API_STATUS(WINAPI NETSHAREADDW)(
|
|
IN PWSTR servername,
|
|
IN DWORD level,
|
|
IN PBYTE buf,
|
|
OUT PDWORD parm_err
|
|
);
|
|
typedef NETSHAREADDW *PNETSHAREADDW;
|
|
|
|
typedef NET_API_STATUS(WINAPI NETSHAREDELW)(
|
|
IN PWSTR servername,
|
|
IN PWSTR netname,
|
|
IN DWORD reserved
|
|
);
|
|
typedef NETSHAREDELW *PNETSHAREDELW;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
PMHANDLE g_NetSharesPool = NULL;
|
|
PMHANDLE g_PathPool = NULL;
|
|
HASHTABLE g_NetSharesTable;
|
|
MIG_OBJECTTYPEID g_NetShareTypeId = 0;
|
|
static BOOL g_IsWin9x = FALSE;
|
|
GROWBUFFER g_NetShareConversionBuff = INIT_GROWBUFFER;
|
|
BOOL g_NetSharesMigEnabled = FALSE;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private prototypes
|
|
//
|
|
|
|
TYPE_ENUMFIRSTPHYSICALOBJECT EnumFirstNetShare;
|
|
TYPE_ENUMNEXTPHYSICALOBJECT EnumNextNetShare;
|
|
TYPE_ABORTENUMPHYSICALOBJECT AbortEnumNetShare;
|
|
TYPE_CONVERTOBJECTTOMULTISZ ConvertNetShareToMultiSz;
|
|
TYPE_CONVERTMULTISZTOOBJECT ConvertMultiSzToNetShare;
|
|
TYPE_GETNATIVEOBJECTNAME GetNativeNetShareName;
|
|
TYPE_ACQUIREPHYSICALOBJECT AcquireNetShare;
|
|
TYPE_RELEASEPHYSICALOBJECT ReleaseNetShare;
|
|
TYPE_DOESPHYSICALOBJECTEXIST DoesNetShareExist;
|
|
TYPE_REMOVEPHYSICALOBJECT RemoveNetShare;
|
|
TYPE_CREATEPHYSICALOBJECT CreateNetShare;
|
|
TYPE_CONVERTOBJECTCONTENTTOUNICODE ConvertNetShareContentToUnicode;
|
|
TYPE_CONVERTOBJECTCONTENTTOANSI ConvertNetShareContentToAnsi;
|
|
TYPE_FREECONVERTEDOBJECTCONTENT FreeConvertedNetShareContent;
|
|
|
|
//
|
|
// netapi functions
|
|
//
|
|
|
|
PNETSHAREADDW g_NetShareAddW = NULL;
|
|
PNETSHAREDELW g_NetShareDelW = NULL;
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
NetSharesInitialize (
|
|
VOID
|
|
)
|
|
{
|
|
OSVERSIONINFO versionInfo;
|
|
|
|
ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
|
|
versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
if (!GetVersionEx (&versionInfo)) {
|
|
return FALSE;
|
|
}
|
|
g_IsWin9x = (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
|
|
|
g_PathPool = PmCreateNamedPool ("NetShares Paths");
|
|
g_NetSharesTable = HtAllocWithData (sizeof (PNETSHARE_DATA));
|
|
g_NetSharesPool = PmCreateNamedPool ("NetShares");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
NetSharesTerminate (
|
|
VOID
|
|
)
|
|
{
|
|
HASHTABLE_ENUM e;
|
|
PNETSHARE_DATA netshareData;
|
|
|
|
if (g_NetSharesTable) {
|
|
if (EnumFirstHashTableString (&e, g_NetSharesTable)) {
|
|
do {
|
|
netshareData = *((PNETSHARE_DATA *) e.ExtraData);
|
|
if (netshareData) {
|
|
PmReleaseMemory (g_NetSharesPool, netshareData);
|
|
}
|
|
} while (EnumNextHashTableString (&e));
|
|
}
|
|
HtFree (g_NetSharesTable);
|
|
g_NetSharesTable = NULL;
|
|
}
|
|
|
|
PmDestroyPool (g_NetSharesPool);
|
|
g_NetSharesPool = NULL;
|
|
|
|
PmDestroyPool (g_PathPool);
|
|
g_PathPool = NULL;
|
|
}
|
|
|
|
BOOL
|
|
pLoadNetSharesData (
|
|
VOID
|
|
)
|
|
{
|
|
DWORD error;
|
|
PBYTE netBuffer = NULL;
|
|
CHAR netBuf9x[16384]; // static because NetShareEnum is unreliable
|
|
DWORD netNumEntries = 0;
|
|
DWORD totalEntries = 0;
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD level;
|
|
HINSTANCE hInst;
|
|
PCTSTR name = NULL;
|
|
PCTSTR path = NULL;
|
|
PNETSHARE_DATA netshareData;
|
|
|
|
//
|
|
// Get the net share info from the machine
|
|
//
|
|
|
|
level = (g_IsWin9x ? 50 : 502);
|
|
hInst = LoadLibraryA (g_IsWin9x ? "svrapi.dll" : "netapi32.dll");
|
|
if (hInst == 0) {
|
|
SetLastError (ERROR_INVALID_DLL);
|
|
return FALSE;
|
|
}
|
|
|
|
if (g_IsWin9x) {
|
|
struct _share_info_50 *tmpBuf;
|
|
ScanNetShareEnum9x pNetShareEnum9x = NULL;
|
|
ScanNetAccessEnum9x pNetAccessEnum9x = NULL;
|
|
|
|
pNetShareEnum9x = (ScanNetShareEnum9x) GetProcAddress (hInst, "NetShareEnum");
|
|
if (pNetShareEnum9x == NULL) {
|
|
SetLastError (ERROR_INVALID_DLL);
|
|
return FALSE;
|
|
}
|
|
pNetAccessEnum9x = (ScanNetAccessEnum9x) GetProcAddress (hInst, "NetAccessEnum");
|
|
if (pNetAccessEnum9x == NULL) {
|
|
SetLastError (ERROR_INVALID_DLL);
|
|
return FALSE;
|
|
}
|
|
|
|
error = (*pNetShareEnum9x)(NULL,
|
|
(short)level,
|
|
netBuf9x,
|
|
sizeof (netBuf9x),
|
|
(USHORT *)&netNumEntries,
|
|
(USHORT *)&totalEntries);
|
|
|
|
if ((error == ERROR_SUCCESS) || (error == ERROR_MORE_DATA)) {
|
|
|
|
for (i = 0; i < netNumEntries; i++) {
|
|
DWORD dwPerms = 0;
|
|
tmpBuf = (struct _share_info_50 *)(netBuf9x + (i * sizeof(struct _share_info_50)));
|
|
|
|
// Require share to be a user-defined, persistent disk share
|
|
if ((tmpBuf->shi50_flags & SHI50F_SYSTEM) ||
|
|
!(tmpBuf->shi50_flags & SHI50F_PERSIST) ||
|
|
tmpBuf->shi50_type != STYPE_DISKTREE ) {
|
|
continue;
|
|
}
|
|
|
|
if (tmpBuf->shi50_flags & SHI50F_RDONLY) {
|
|
dwPerms = ACCESS_READ;
|
|
} else if (tmpBuf->shi50_flags & SHI50F_FULL) {
|
|
dwPerms = ACCESS_ALL;
|
|
}
|
|
|
|
// JTJTJT: Also store dwPerms
|
|
|
|
//
|
|
// Process custom access permissions
|
|
//
|
|
if ((tmpBuf->shi50_flags & SHI50F_ACCESSMASK) ==
|
|
SHI50F_ACCESSMASK) {
|
|
static CHAR AccessInfoBuf[16384];
|
|
WORD wItemsAvail, wItemsRead;
|
|
error = (*pNetAccessEnum9x) (NULL,
|
|
tmpBuf->shi50_path,
|
|
0,
|
|
2,
|
|
AccessInfoBuf,
|
|
sizeof (AccessInfoBuf),
|
|
&wItemsRead,
|
|
&wItemsAvail
|
|
);
|
|
|
|
if (error != NERR_ACFNotLoaded) {
|
|
BOOL LostCustomAccess = FALSE;
|
|
if (error == ERROR_SUCCESS) {
|
|
struct access_info_2 *pai;
|
|
struct access_list_2 *pal;
|
|
pai = (struct access_info_2 *) AccessInfoBuf;
|
|
pal = (struct access_list_2 *) (&pai[1]);
|
|
|
|
for (j = 0 ; j < pai->acc2_count ; j++) {
|
|
#if 0
|
|
// turn off custom access support
|
|
// implementation is incomplete
|
|
if (pal->acl2_access & READ_ACCESS_FLAGS) {
|
|
Win32Printf (h, " %s, read\r\n",
|
|
pal->acl2_ugname);
|
|
} else if(pal->acl2_access & FULL_ACCESS_FLAGS) {
|
|
Win32Printf (h, " %s, full\r\n",
|
|
pal->acl2_ugname);
|
|
} else
|
|
#endif
|
|
LostCustomAccess = TRUE;
|
|
|
|
pal++;
|
|
}
|
|
if (LostCustomAccess) {
|
|
DEBUGMSG ((DBG_NETSHARES, "Share %s not migrated.", tmpBuf->shi50_netname));
|
|
continue;
|
|
}
|
|
tmpBuf->shi50_flags |= SHI50F_ACLS;
|
|
} else if (error != ERROR_SUCCESS) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
if (!(tmpBuf->shi50_flags & SHI50F_ACLS) &&
|
|
(tmpBuf->shi50_rw_password[0] ||
|
|
tmpBuf->shi50_ro_password[0])) {
|
|
// IDS_SHARE_PASSWORD_NOT_MIGRATED, tmpBuf->shi50_netname
|
|
DEBUGMSG ((DBG_NETSHARES, "Share %s not migrated.", tmpBuf->shi50_netname));
|
|
continue;
|
|
}
|
|
|
|
// everything looks OK, let's add this entry
|
|
name = ConvertAtoT (tmpBuf->shi50_netname);
|
|
path = ConvertAtoT (tmpBuf->shi50_path);
|
|
|
|
netshareData = (PNETSHARE_DATA) PmGetMemory (g_NetSharesPool, sizeof (NETSHARE_DATA));
|
|
ZeroMemory (netshareData, sizeof (NETSHARE_DATA));
|
|
|
|
StringCopyTcharCount (netshareData->sharePath, path, MAX_PATH + 1);
|
|
HtAddStringEx (g_NetSharesTable, name, &netshareData, FALSE);
|
|
|
|
FreeAtoT (name);
|
|
INVALID_POINTER (name);
|
|
FreeAtoT (path);
|
|
INVALID_POINTER (path);
|
|
}
|
|
} else if (error == NERR_ServerNotStarted) {
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
} else {
|
|
ScanNetShareEnumNT pNetShareEnum = NULL;
|
|
SHARE_INFO_502* tmpBuf = NULL;
|
|
|
|
pNetShareEnum = (ScanNetShareEnumNT) GetProcAddress(hInst, "NetShareEnum");
|
|
if (pNetShareEnum == NULL) {
|
|
SetLastError (ERROR_INVALID_DLL);
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Call the NetShareEnum function to list the
|
|
// shares, specifying information level 502.
|
|
//
|
|
error = (*pNetShareEnum)(NULL,
|
|
level,
|
|
(BYTE **) &netBuffer,
|
|
MAX_PREFERRED_LENGTH,
|
|
&netNumEntries,
|
|
&totalEntries,
|
|
NULL);
|
|
|
|
//
|
|
// Loop through the entries; process errors.
|
|
//
|
|
if (error == ERROR_SUCCESS) {
|
|
if ((tmpBuf = (SHARE_INFO_502 *)netBuffer) != NULL) {
|
|
for (i = 0; (i < netNumEntries); i++) {
|
|
if (!(tmpBuf->shi502_type & STYPE_SPECIAL)) {
|
|
|
|
name = ConvertWtoT (tmpBuf->shi502_netname);
|
|
path = ConvertWtoT (tmpBuf->shi502_path);
|
|
|
|
netshareData = (PNETSHARE_DATA) PmGetMemory (g_NetSharesPool, sizeof (NETSHARE_DATA));
|
|
ZeroMemory (netshareData, sizeof (NETSHARE_DATA));
|
|
|
|
StringCopyTcharCount (netshareData->sharePath, path, MAX_PATH + 1);
|
|
HtAddStringEx (g_NetSharesTable, name, &netshareData, FALSE);
|
|
// JTJTJT: also store tmpBuf->shi502_permissions, tmpBuf->shi502_remark));
|
|
|
|
FreeWtoT (name);
|
|
INVALID_POINTER (name);
|
|
FreeWtoT (path);
|
|
INVALID_POINTER (path);
|
|
}
|
|
tmpBuf++;
|
|
}
|
|
}
|
|
} else {
|
|
//SetLastError (IDS_CANNOT_ENUM_NETSHARES);
|
|
return FALSE;
|
|
}
|
|
|
|
if (netBuffer != NULL) {
|
|
ScanNetApiBufferFreeNT pNetApiBufferFree = NULL;
|
|
|
|
pNetApiBufferFree = (ScanNetApiBufferFreeNT) GetProcAddress (hInst, "NetApiBufferFree");
|
|
if (pNetApiBufferFree != NULL)
|
|
(*pNetApiBufferFree) (netBuffer);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pLoadNetEntries (
|
|
VOID
|
|
)
|
|
{
|
|
HMODULE netDll = NULL;
|
|
BOOL result = FALSE;
|
|
|
|
//
|
|
// Get the net api entry points. Sometimes networking isn't installed.
|
|
//
|
|
|
|
__try {
|
|
netDll = LoadLibrary (TEXT("NETAPI32.DLL"));
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
netDll = NULL;
|
|
}
|
|
if (netDll) {
|
|
g_NetShareAddW = (PNETSHAREADDW) GetProcAddress (netDll, "NetShareAdd");
|
|
g_NetShareDelW = (PNETSHAREDELW) GetProcAddress (netDll, "NetShareDel");
|
|
if (g_NetShareAddW && g_NetShareDelW) {
|
|
result = TRUE;
|
|
} else {
|
|
result = FALSE;
|
|
DEBUGMSG ((DBG_NETSHARES, "Not all NETAPI32 entry points were found."));
|
|
}
|
|
} else {
|
|
DEBUGMSG ((DBG_NETSHARES, "NETAPI32 is not installed on this computer."));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesEtmInitialize (
|
|
IN MIG_PLATFORMTYPEID Platform,
|
|
IN PMIG_LOGCALLBACK LogCallback,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
TYPE_REGISTER netSharesTypeData;
|
|
|
|
//
|
|
// We need to register our type callback functions. Types allow us to
|
|
// abstract net shares into generalized objects. The engine can perform
|
|
// global operations with this abstraction (such as undo or compare), and
|
|
// modules can access net shares without knowing the complexities of
|
|
// OS-specific APIs, bugs & workarounds, storage formats, etc. Script
|
|
// modules can implement script capabilities that control net shares
|
|
// without actually inventing special net share syntaxes (or even knowing
|
|
// about net shares).
|
|
//
|
|
|
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
|
|
|
pLoadNetSharesData ();
|
|
|
|
ZeroMemory (&netSharesTypeData, sizeof (TYPE_REGISTER));
|
|
netSharesTypeData.Priority = PRIORITY_NETSHARE;
|
|
|
|
if (Platform == PLATFORM_SOURCE) {
|
|
|
|
netSharesTypeData.EnumFirstPhysicalObject = EnumFirstNetShare;
|
|
netSharesTypeData.EnumNextPhysicalObject = EnumNextNetShare;
|
|
netSharesTypeData.AbortEnumPhysicalObject = AbortEnumNetShare;
|
|
netSharesTypeData.ConvertObjectToMultiSz = ConvertNetShareToMultiSz;
|
|
netSharesTypeData.ConvertMultiSzToObject = ConvertMultiSzToNetShare;
|
|
netSharesTypeData.GetNativeObjectName = GetNativeNetShareName;
|
|
netSharesTypeData.AcquirePhysicalObject = AcquireNetShare;
|
|
netSharesTypeData.ReleasePhysicalObject = ReleaseNetShare;
|
|
netSharesTypeData.ConvertObjectContentToUnicode = ConvertNetShareContentToUnicode;
|
|
netSharesTypeData.ConvertObjectContentToAnsi = ConvertNetShareContentToAnsi;
|
|
netSharesTypeData.FreeConvertedObjectContent = FreeConvertedNetShareContent;
|
|
|
|
g_NetShareTypeId = IsmRegisterObjectType (
|
|
S_NETSHARES_NAME,
|
|
TRUE,
|
|
FALSE,
|
|
&netSharesTypeData
|
|
);
|
|
} else {
|
|
|
|
netSharesTypeData.EnumFirstPhysicalObject = EnumFirstNetShare;
|
|
netSharesTypeData.EnumNextPhysicalObject = EnumNextNetShare;
|
|
netSharesTypeData.AbortEnumPhysicalObject = AbortEnumNetShare;
|
|
netSharesTypeData.ConvertObjectToMultiSz = ConvertNetShareToMultiSz;
|
|
netSharesTypeData.ConvertMultiSzToObject = ConvertMultiSzToNetShare;
|
|
netSharesTypeData.GetNativeObjectName = GetNativeNetShareName;
|
|
netSharesTypeData.AcquirePhysicalObject = AcquireNetShare;
|
|
netSharesTypeData.ReleasePhysicalObject = ReleaseNetShare;
|
|
netSharesTypeData.DoesPhysicalObjectExist = DoesNetShareExist;
|
|
netSharesTypeData.RemovePhysicalObject = RemoveNetShare;
|
|
netSharesTypeData.CreatePhysicalObject = CreateNetShare;
|
|
netSharesTypeData.ConvertObjectContentToUnicode = ConvertNetShareContentToUnicode;
|
|
netSharesTypeData.ConvertObjectContentToAnsi = ConvertNetShareContentToAnsi;
|
|
netSharesTypeData.FreeConvertedObjectContent = FreeConvertedNetShareContent;
|
|
|
|
g_NetShareTypeId = IsmRegisterObjectType (
|
|
S_NETSHARES_NAME,
|
|
TRUE,
|
|
FALSE,
|
|
&netSharesTypeData
|
|
);
|
|
pLoadNetEntries ();
|
|
}
|
|
|
|
MYASSERT (g_NetShareTypeId);
|
|
return TRUE;
|
|
}
|
|
|
|
UINT
|
|
NetSharesCallback (
|
|
IN PCMIG_OBJECTENUMDATA Data,
|
|
IN ULONG_PTR CallerArg
|
|
)
|
|
{
|
|
//
|
|
// This callback gets called for each net share. We simply mark the
|
|
// share to be applied.
|
|
//
|
|
|
|
IsmMakeApplyObject (Data->ObjectTypeId, Data->ObjectName);
|
|
|
|
return CALLBACK_ENUM_CONTINUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesSgmInitialize (
|
|
IN PMIG_LOGCALLBACK LogCallback,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
//
|
|
// Set the log callback (so all log messages to to the app)
|
|
//
|
|
|
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesSgmParse (
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
PCTSTR friendlyName;
|
|
|
|
friendlyName = GetStringResource (MSG_NET_SHARE_NAME);
|
|
|
|
IsmAddComponentAlias (
|
|
S_NETSHARES_NAME,
|
|
MASTERGROUP_SYSTEM,
|
|
friendlyName,
|
|
COMPONENT_NAME,
|
|
FALSE
|
|
);
|
|
|
|
FreeStringResource (friendlyName);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesSgmQueueEnumeration (
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
ENCODEDSTRHANDLE pattern;
|
|
|
|
if (!IsmIsComponentSelected (S_NETSHARES_NAME, 0)) {
|
|
g_NetSharesMigEnabled = FALSE;
|
|
return TRUE;
|
|
}
|
|
g_NetSharesMigEnabled = TRUE;
|
|
|
|
//
|
|
// Queue all net shares to be applied. This could be enhanced to allow a
|
|
// script to drive what should be restored.
|
|
//
|
|
|
|
pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, FALSE);
|
|
IsmQueueEnumeration (g_NetShareTypeId, pattern, NetSharesCallback, (ULONG_PTR) 0, S_NETSHARES_NAME);
|
|
IsmDestroyObjectHandle (pattern);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
NetSharesVcmInitialize (
|
|
IN PMIG_LOGCALLBACK LogCallback,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
//
|
|
// Set the log callback (so all log messages to to the app)
|
|
//
|
|
|
|
LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesVcmParse (
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
return NetSharesSgmParse (Reserved);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
NetSharesVcmQueueEnumeration (
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
ENCODEDSTRHANDLE pattern;
|
|
|
|
if (!IsmIsComponentSelected (S_NETSHARES_NAME, 0)) {
|
|
g_NetSharesMigEnabled = FALSE;
|
|
return TRUE;
|
|
}
|
|
g_NetSharesMigEnabled = TRUE;
|
|
|
|
//
|
|
// Queue all net share objects to be marked as persistent
|
|
//
|
|
|
|
pattern = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, FALSE);
|
|
IsmQueueEnumeration (g_NetShareTypeId, pattern, NetSharesCallback, (ULONG_PTR) 0, S_NETSHARES_NAME);
|
|
IsmDestroyObjectHandle (pattern);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pEnumNetShareWorker (
|
|
OUT PMIG_TYPEOBJECTENUM EnumPtr,
|
|
IN PNETSHARE_ENUM NetShareEnum
|
|
)
|
|
{
|
|
//
|
|
// Test enumerated item against the pattern, and return only
|
|
// when the pattern matches. Also, fill the entire enum
|
|
// structure upon successful enumeration.
|
|
//
|
|
|
|
IsmDestroyObjectString (EnumPtr->ObjectNode);
|
|
EnumPtr->ObjectNode = NULL;
|
|
|
|
IsmDestroyObjectString (EnumPtr->ObjectLeaf);
|
|
EnumPtr->ObjectLeaf = NULL;
|
|
|
|
for (;;) {
|
|
EnumPtr->ObjectName = IsmCreateObjectHandle (NetShareEnum->HashData.String, NULL);
|
|
|
|
if (!ObsPatternMatch (NetShareEnum->Pattern, EnumPtr->ObjectName)) {
|
|
if (!EnumNextHashTableString (&NetShareEnum->HashData)) {
|
|
AbortEnumNetShare (EnumPtr);
|
|
return FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
EnumPtr->NativeObjectName = NetShareEnum->HashData.String;
|
|
|
|
IsmCreateObjectStringsFromHandle (EnumPtr->ObjectName, &EnumPtr->ObjectNode, &EnumPtr->ObjectLeaf);
|
|
|
|
EnumPtr->Level = 1;
|
|
EnumPtr->SubLevel = 0;
|
|
EnumPtr->IsLeaf = FALSE;
|
|
EnumPtr->IsNode = TRUE;
|
|
EnumPtr->Details.DetailsSize = 0;
|
|
EnumPtr->Details.DetailsData = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
EnumFirstNetShare (
|
|
IN OUT PMIG_TYPEOBJECTENUM EnumPtr, CALLER_INITIALIZED
|
|
IN MIG_OBJECTSTRINGHANDLE Pattern,
|
|
IN UINT MaxLevel
|
|
)
|
|
{
|
|
PNETSHARE_ENUM netShareEnum = NULL;
|
|
|
|
if (!g_NetSharesTable) {
|
|
return FALSE;
|
|
}
|
|
|
|
netShareEnum = (PNETSHARE_ENUM) PmGetMemory (g_NetSharesPool, sizeof (NETSHARE_ENUM));
|
|
netShareEnum->Pattern = PmDuplicateString (g_NetSharesPool, Pattern);
|
|
EnumPtr->EtmHandle = (LONG_PTR) netShareEnum;
|
|
|
|
if (EnumFirstHashTableString (&netShareEnum->HashData, g_NetSharesTable)) {
|
|
return pEnumNetShareWorker (EnumPtr, netShareEnum);
|
|
}
|
|
|
|
AbortEnumNetShare (EnumPtr);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
EnumNextNetShare (
|
|
IN OUT PMIG_TYPEOBJECTENUM EnumPtr
|
|
)
|
|
{
|
|
PNETSHARE_ENUM netShareEnum = NULL;
|
|
|
|
netShareEnum = (PNETSHARE_ENUM)(EnumPtr->EtmHandle);
|
|
if (!netShareEnum) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (EnumPtr->ObjectName) {
|
|
IsmDestroyObjectHandle (EnumPtr->ObjectName);
|
|
EnumPtr->ObjectName = NULL;
|
|
}
|
|
|
|
if (EnumNextHashTableString (&netShareEnum->HashData)) {
|
|
return pEnumNetShareWorker (EnumPtr, netShareEnum);
|
|
}
|
|
|
|
AbortEnumNetShare (EnumPtr);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
VOID
|
|
AbortEnumNetShare (
|
|
IN OUT PMIG_TYPEOBJECTENUM EnumPtr
|
|
)
|
|
{
|
|
PNETSHARE_ENUM netShareEnum = NULL;
|
|
|
|
MYASSERT (EnumPtr);
|
|
|
|
netShareEnum = (PNETSHARE_ENUM)(EnumPtr->EtmHandle);
|
|
if (!netShareEnum) {
|
|
return;
|
|
}
|
|
|
|
IsmDestroyObjectHandle (EnumPtr->ObjectName);
|
|
IsmDestroyObjectString (EnumPtr->ObjectNode);
|
|
IsmDestroyObjectString (EnumPtr->ObjectLeaf);
|
|
PmReleaseMemory (g_NetSharesPool, netShareEnum->Pattern);
|
|
PmReleaseMemory (g_NetSharesPool, netShareEnum);
|
|
|
|
ZeroMemory (EnumPtr, sizeof (MIG_TYPEOBJECTENUM));
|
|
}
|
|
|
|
|
|
BOOL
|
|
AcquireNetShare (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName,
|
|
IN OUT PMIG_CONTENT ObjectContent,
|
|
IN MIG_CONTENTTYPE ContentType,
|
|
IN UINT MemoryContentLimit
|
|
)
|
|
{
|
|
PCTSTR node;
|
|
PCTSTR leaf;
|
|
PNETSHARE_DATA netshareData;
|
|
BOOL result = FALSE;
|
|
|
|
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 net shares as files",
|
|
ObjectName
|
|
));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
if (HtFindStringEx (g_NetSharesTable, node, (PVOID)&netshareData, 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)netshareData;
|
|
ObjectContent->MemoryContent.ContentSize = sizeof(NETSHARE_DATA);
|
|
|
|
result = TRUE;
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ReleaseNetShare (
|
|
IN OUT PMIG_CONTENT ObjectContent
|
|
)
|
|
{
|
|
//
|
|
// Clean up routine for the AcquireNetShare function
|
|
//
|
|
|
|
if (ObjectContent) {
|
|
ZeroMemory (ObjectContent, sizeof (MIG_CONTENT));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoesNetShareExist (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName
|
|
)
|
|
{
|
|
PCTSTR node;
|
|
PCTSTR leaf;
|
|
BOOL result = FALSE;
|
|
|
|
//
|
|
// Given an object name (the net share), we must test to see if the
|
|
// share exists on the machine. A table was built at initialization
|
|
// time to provide fast access to net shares.
|
|
//
|
|
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
if (HtFindStringEx (g_NetSharesTable, node, NULL, FALSE)) {
|
|
result = TRUE;
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
RemoveNetShare (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName
|
|
)
|
|
{
|
|
PCTSTR node;
|
|
PCTSTR leaf;
|
|
DWORD result = ERROR_NOT_FOUND;
|
|
PCWSTR name;
|
|
|
|
//
|
|
// Given an object name (the net share), we must delete the share.
|
|
//
|
|
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
if (node && (!leaf)) {
|
|
if (g_IsWin9x) {
|
|
// JTJT: add here
|
|
} else {
|
|
|
|
name = CreateUnicode (node);
|
|
|
|
if (g_NetShareDelW) {
|
|
// record value name deletion
|
|
IsmRecordOperation (JRNOP_DELETE,
|
|
g_NetShareTypeId,
|
|
ObjectName);
|
|
result = g_NetShareDelW (NULL, (PWSTR) name, 0);
|
|
} else {
|
|
result = ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
DestroyUnicode (name);
|
|
}
|
|
if (result != NERR_Success) {
|
|
DEBUGMSG ((DBG_NETSHARES, "Failed to delete existent net share %s", name));
|
|
} else {
|
|
HtRemoveString (g_NetSharesTable, node);
|
|
}
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
return (result == NERR_Success);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CreateNetShare (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName,
|
|
IN PMIG_CONTENT ObjectContent
|
|
)
|
|
{
|
|
PCTSTR node;
|
|
PCTSTR leaf;
|
|
DWORD result = NERR_Success;
|
|
DWORD level;
|
|
SHARE_INFO_502 shareInfo;
|
|
PNETSHARE_DATA netshareData = NULL;
|
|
|
|
//
|
|
// The name of the net share is in the object name's node. The net share
|
|
// content provides the path of the share. Details provide the net share
|
|
// ACLs.
|
|
//
|
|
// Our job is to take the object name, content and details, and create a
|
|
// share. We ignore the case where the content is in a file. This should
|
|
// not apply to net shares.
|
|
//
|
|
|
|
if (!ObjectContent->ContentInFile) {
|
|
if (ObjectContent->MemoryContent.ContentBytes && ObjectContent->MemoryContent.ContentSize) {
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
if (node && (!leaf)) {
|
|
level = (g_IsWin9x ? 50 : 502);
|
|
|
|
netshareData = (PNETSHARE_DATA) PmGetMemory (g_NetSharesPool, sizeof (NETSHARE_DATA));
|
|
CopyMemory (netshareData,
|
|
ObjectContent->MemoryContent.ContentBytes,
|
|
sizeof(NETSHARE_DATA));
|
|
|
|
if (DoesFileExist (netshareData->sharePath)) {
|
|
|
|
if (g_IsWin9x) {
|
|
// JTJT: add here
|
|
} else {
|
|
shareInfo.shi502_netname = (PWSTR) CreateUnicode (node);
|
|
shareInfo.shi502_path = (PWSTR) CreateUnicode (netshareData->sharePath);
|
|
|
|
shareInfo.shi502_type = STYPE_DISKTREE; // JTJTJT: retrieve type
|
|
shareInfo.shi502_remark = NULL; // JTJTJT: retrieve remark
|
|
shareInfo.shi502_permissions = ACCESS_ALL; // JTJTJT: retrieve perms
|
|
shareInfo.shi502_max_uses = -1; // JTJTJT: retrieve max uses
|
|
shareInfo.shi502_current_uses = 0;
|
|
shareInfo.shi502_passwd = NULL; // JTJTJT: retrieve password
|
|
shareInfo.shi502_reserved = 0;
|
|
shareInfo.shi502_security_descriptor = NULL; // JTJTJT: retrieve ACLs
|
|
|
|
if (g_NetShareAddW) {
|
|
IsmRecordOperation (JRNOP_CREATE,
|
|
g_NetShareTypeId,
|
|
ObjectName);
|
|
result = g_NetShareAddW (NULL, level, (PBYTE)&shareInfo, NULL);
|
|
} else {
|
|
result = ERROR_CALL_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
DestroyUnicode (shareInfo.shi502_netname);
|
|
DestroyUnicode (shareInfo.shi502_path);
|
|
}
|
|
|
|
if (result != NERR_Success) {
|
|
DEBUGMSG ((DBG_NETSHARES, "Failed to add net share for %s", node));
|
|
} else {
|
|
HtAddStringEx (g_NetSharesTable, node, &netshareData, FALSE);
|
|
}
|
|
}
|
|
PmReleaseMemory (g_NetSharesPool, netshareData);
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
}
|
|
} else {
|
|
DEBUGMSG ((DBG_WHOOPS, "Did not expect content to come in the form of a file."));
|
|
}
|
|
|
|
return (result == NERR_Success);
|
|
}
|
|
|
|
PCTSTR
|
|
ConvertNetShareToMultiSz (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName,
|
|
IN PMIG_CONTENT ObjectContent
|
|
)
|
|
{
|
|
PCTSTR node = NULL, leaf = NULL;
|
|
PTSTR result;
|
|
PNETSHARE_DATA netshareData;
|
|
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
|
|
//
|
|
// Copy field 1 (share name) and field 2 (share path) to a temp
|
|
// multi-sz buffer
|
|
//
|
|
|
|
MYASSERT (!ObjectContent->ContentInFile);
|
|
MYASSERT (ObjectContent->MemoryContent.ContentBytes);
|
|
g_NetShareConversionBuff.End = 0;
|
|
|
|
GbCopyQuotedString (&g_NetShareConversionBuff, node);
|
|
|
|
if (ObjectContent->MemoryContent.ContentBytes) {
|
|
netshareData = (PNETSHARE_DATA) PmGetMemory (g_NetSharesPool, sizeof (NETSHARE_DATA));
|
|
CopyMemory (&netshareData->sharePath, ObjectContent->MemoryContent.ContentBytes, sizeof(NETSHARE_DATA));
|
|
|
|
GbCopyQuotedString (&g_NetShareConversionBuff, netshareData->sharePath);
|
|
|
|
PmReleaseMemory (g_NetSharesPool, netshareData);
|
|
netshareData = NULL;
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
|
|
//
|
|
// Terminate the multi-sz
|
|
//
|
|
|
|
GbCopyString (&g_NetShareConversionBuff, TEXT(""));
|
|
|
|
//
|
|
// Transfer temp buffer to an ISM-allocated buffer and forget about it
|
|
//
|
|
|
|
result = IsmGetMemory (g_NetShareConversionBuff.End);
|
|
CopyMemory (result, g_NetShareConversionBuff.Buf, g_NetShareConversionBuff.End);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ConvertMultiSzToNetShare (
|
|
IN PCTSTR ObjectMultiSz,
|
|
OUT MIG_OBJECTSTRINGHANDLE *ObjectName,
|
|
OUT PMIG_CONTENT ObjectContent OPTIONAL
|
|
)
|
|
{
|
|
MULTISZ_ENUM e;
|
|
PCTSTR localName = NULL;
|
|
UINT index;
|
|
NETSHARE_DATA netshareData;
|
|
BOOL pathFound = FALSE;
|
|
|
|
//
|
|
// Parse the multi-sz into the net share content and details.
|
|
// The user may have edited the text (and potentially introduced
|
|
// errors).
|
|
//
|
|
|
|
ZeroMemory (&netshareData, sizeof (NETSHARE_DATA));
|
|
|
|
if (ObjectContent) {
|
|
ZeroMemory (ObjectContent, sizeof (MIG_CONTENT));
|
|
}
|
|
|
|
if (EnumFirstMultiSz (&e, ObjectMultiSz)) {
|
|
index = 0;
|
|
do {
|
|
switch (index) {
|
|
case INDEXLOCAL:
|
|
localName = e.CurrentString;
|
|
break;
|
|
case INDEXREMOTE:
|
|
pathFound = TRUE;
|
|
StringCopyTcharCount (netshareData.sharePath, e.CurrentString, MAX_PATH + 1);
|
|
break;
|
|
default:
|
|
// Ignore extra data
|
|
DEBUGMSG ((DBG_WARNING, "Extra net share string ignored: %s", e.CurrentString));
|
|
break;
|
|
}
|
|
|
|
index++;
|
|
|
|
} while (EnumNextMultiSz (&e));
|
|
}
|
|
|
|
if (!localName || !pathFound) {
|
|
//
|
|
// Bogus data, fail
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Fill in all the members of the content structure. Keep in mind
|
|
// we already zeroed the buffer.
|
|
//
|
|
|
|
*ObjectName = IsmCreateObjectHandle (localName, NULL);
|
|
|
|
if (ObjectContent) {
|
|
ObjectContent->MemoryContent.ContentBytes = IsmGetMemory (sizeof (NETSHARE_DATA));
|
|
CopyMemory ((PBYTE) ObjectContent->MemoryContent.ContentBytes, &netshareData, sizeof (NETSHARE_DATA));
|
|
ObjectContent->MemoryContent.ContentSize = sizeof (NETSHARE_DATA);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PCTSTR
|
|
GetNativeNetShareName (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName
|
|
)
|
|
{
|
|
PCTSTR node, leaf;
|
|
UINT size;
|
|
PTSTR result = NULL;
|
|
|
|
//
|
|
// The "native" format is what most people would use to describe our
|
|
// object. For the net share case, we simply get the share name from the
|
|
// node; the node is not encoded in any way, and the leaf is not used.
|
|
//
|
|
|
|
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
|
|
if (node) {
|
|
size = SizeOfString (node);
|
|
if (size) {
|
|
result = IsmGetMemory (size);
|
|
CopyMemory (result, node, size);
|
|
}
|
|
}
|
|
|
|
IsmDestroyObjectString (node);
|
|
INVALID_POINTER (node);
|
|
|
|
IsmDestroyObjectString (leaf);
|
|
INVALID_POINTER (leaf);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
PMIG_CONTENT
|
|
ConvertNetShareContentToUnicode (
|
|
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 (NETSHARE_DATAW));
|
|
if (result->MemoryContent.ContentBytes) {
|
|
DirectDbcsToUnicodeN (
|
|
((PNETSHARE_DATAW)result->MemoryContent.ContentBytes)->sharePath,
|
|
((PNETSHARE_DATAA)ObjectContent->MemoryContent.ContentBytes)->sharePath,
|
|
MAX_PATH + 1
|
|
);
|
|
result->MemoryContent.ContentSize = sizeof (NETSHARE_DATAW);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
PMIG_CONTENT
|
|
ConvertNetShareContentToAnsi (
|
|
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 (NETSHARE_DATAA));
|
|
if (result->MemoryContent.ContentBytes) {
|
|
DirectUnicodeToDbcsN (
|
|
((PNETSHARE_DATAA)result->MemoryContent.ContentBytes)->sharePath,
|
|
((PNETSHARE_DATAW)ObjectContent->MemoryContent.ContentBytes)->sharePath,
|
|
MAX_PATH + 1
|
|
);
|
|
result->MemoryContent.ContentSize = sizeof (NETSHARE_DATAA);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
FreeConvertedNetShareContent (
|
|
IN PMIG_CONTENT ObjectContent
|
|
)
|
|
{
|
|
if (!ObjectContent) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (ObjectContent->MemoryContent.ContentBytes) {
|
|
IsmReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
|
|
}
|
|
|
|
IsmReleaseMemory (ObjectContent);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|