/*++ Copyright (c) 2000 Microsoft Corporation Module Name: netshares.c Abstract: Author: Jay Thaler (jthaler) 21 Apr 2000 Revision History: --*/ // // Includes // #include "pch.h" #include "logmsg.h" #include #include #include #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\\ACL\ 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; }