|
|
/*++
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));
StringCopy (netshareData->sharePath, path); 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));
StringCopy (netshareData->sharePath, path); 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));
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; StringCopy (netshareData.sharePath, e.CurrentString); 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; }
|