mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[NETAPI32] Fix NetUserEnum to work on x64
The previous implementation used the resume_handle parameter to return a pointer to the active enumeration context, but resume_handle is a DWORD. To support 64 bit pointers, the enumeration context is inserted into a global linked list and given a unique 32 bit value as identifier for later lookup. The way the function is implemented, leaking a data structure while the MSDN description does not indicate that, seems a little questionable in general, but that is something that I leave to the original author to investigate.
This commit is contained in:
parent
61e35141e8
commit
be97da34ac
3 changed files with 95 additions and 10 deletions
|
@ -26,6 +26,8 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
|
||||||
switch (fdwReason) {
|
switch (fdwReason) {
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
InitializeListHead(&g_EnumContextListHead);
|
||||||
|
InitializeCriticalSection(&g_EnumContextListLock);
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
NetBIOSInit();
|
NetBIOSInit();
|
||||||
NetBTInit();
|
NetBTInit();
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include "nbnamecache.h"
|
#include "nbnamecache.h"
|
||||||
#include "netbios.h"
|
#include "netbios.h"
|
||||||
|
|
||||||
|
extern LIST_ENTRY g_EnumContextListHead;
|
||||||
|
extern CRITICAL_SECTION g_EnumContextListLock;
|
||||||
|
|
||||||
NET_API_STATUS
|
NET_API_STATUS
|
||||||
WINAPI
|
WINAPI
|
||||||
NetpNtStatusToApiStatus(NTSTATUS Status);
|
NetpNtStatusToApiStatus(NTSTATUS Status);
|
||||||
|
|
|
@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
|
||||||
|
|
||||||
typedef struct _ENUM_CONTEXT
|
typedef struct _ENUM_CONTEXT
|
||||||
{
|
{
|
||||||
|
LIST_ENTRY ListLink;
|
||||||
|
ULONG EnumHandle;
|
||||||
|
|
||||||
SAM_HANDLE ServerHandle;
|
SAM_HANDLE ServerHandle;
|
||||||
SAM_HANDLE BuiltinDomainHandle;
|
SAM_HANDLE BuiltinDomainHandle;
|
||||||
SAM_HANDLE AccountDomainHandle;
|
SAM_HANDLE AccountDomainHandle;
|
||||||
|
@ -50,6 +53,9 @@ typedef struct _ENUM_CONTEXT
|
||||||
|
|
||||||
} ENUM_CONTEXT, *PENUM_CONTEXT;
|
} ENUM_CONTEXT, *PENUM_CONTEXT;
|
||||||
|
|
||||||
|
LIST_ENTRY g_EnumContextListHead;
|
||||||
|
CRITICAL_SECTION g_EnumContextListLock;
|
||||||
|
LONG g_EnumContextHandle = 0;
|
||||||
|
|
||||||
static
|
static
|
||||||
ULONG
|
ULONG
|
||||||
|
@ -2662,6 +2668,86 @@ done:
|
||||||
return ApiStatus;
|
return ApiStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NET_API_STATUS
|
||||||
|
AllocateEnumContext(
|
||||||
|
PENUM_CONTEXT *AllocatedEnumContext)
|
||||||
|
{
|
||||||
|
NET_API_STATUS ApiStatus;
|
||||||
|
PENUM_CONTEXT EnumContext;
|
||||||
|
|
||||||
|
/* Allocate the context structure */
|
||||||
|
ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
|
||||||
|
if (ApiStatus != NERR_Success)
|
||||||
|
return ApiStatus;
|
||||||
|
|
||||||
|
/* Initialize the fields */
|
||||||
|
EnumContext->EnumerationContext = 0;
|
||||||
|
EnumContext->Buffer = NULL;
|
||||||
|
EnumContext->Count = 0;
|
||||||
|
EnumContext->Index = 0;
|
||||||
|
EnumContext->BuiltinDone = FALSE;
|
||||||
|
|
||||||
|
/* Set a "unique" handle */
|
||||||
|
EnumContext->EnumHandle = InterlockedIncrement(&g_EnumContextHandle);
|
||||||
|
if (EnumContext->EnumHandle == 0)
|
||||||
|
{
|
||||||
|
EnumContext->EnumHandle = InterlockedIncrement(&g_EnumContextHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the context in the list */
|
||||||
|
EnterCriticalSection(&g_EnumContextListLock);
|
||||||
|
InsertTailList(&g_EnumContextListHead, &EnumContext->ListLink);
|
||||||
|
LeaveCriticalSection(&g_EnumContextListLock);
|
||||||
|
|
||||||
|
*AllocatedEnumContext = EnumContext;
|
||||||
|
return NERR_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
FreeEnumContext(
|
||||||
|
PENUM_CONTEXT EnumContext)
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Remove the context from the list */
|
||||||
|
EnterCriticalSection(&g_EnumContextListLock);
|
||||||
|
RemoveEntryList(&EnumContext->ListLink);
|
||||||
|
LeaveCriticalSection(&g_EnumContextListLock);
|
||||||
|
|
||||||
|
/* Free it */
|
||||||
|
NetApiBufferFree(EnumContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PENUM_CONTEXT
|
||||||
|
LookupEnumContext(
|
||||||
|
SAM_ENUMERATE_HANDLE EnumerationHandle)
|
||||||
|
{
|
||||||
|
PENUM_CONTEXT FoundEnumContext = NULL;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
/* Acquire the list lock */
|
||||||
|
EnterCriticalSection(&g_EnumContextListLock);
|
||||||
|
|
||||||
|
/* Search the list for the handle */
|
||||||
|
for (ListEntry = g_EnumContextListHead.Flink;
|
||||||
|
ListEntry != &g_EnumContextListHead;
|
||||||
|
ListEntry = ListEntry->Flink)
|
||||||
|
{
|
||||||
|
PENUM_CONTEXT EnumContext = CONTAINING_RECORD(ListEntry, ENUM_CONTEXT, ListLink);
|
||||||
|
if (EnumContext->EnumHandle == EnumerationHandle)
|
||||||
|
{
|
||||||
|
FoundEnumContext = EnumContext;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the list lock */
|
||||||
|
LeaveCriticalSection(&g_EnumContextListLock);
|
||||||
|
|
||||||
|
return FoundEnumContext;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* NetUserEnum (NETAPI32.@)
|
* NetUserEnum (NETAPI32.@)
|
||||||
|
@ -2699,20 +2785,14 @@ NetUserEnum(LPCWSTR servername,
|
||||||
|
|
||||||
if (resume_handle != NULL && *resume_handle != 0)
|
if (resume_handle != NULL && *resume_handle != 0)
|
||||||
{
|
{
|
||||||
EnumContext = (PENUM_CONTEXT)*resume_handle;
|
EnumContext = LookupEnumContext(*resume_handle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
|
ApiStatus = AllocateEnumContext(&EnumContext);
|
||||||
if (ApiStatus != NERR_Success)
|
if (ApiStatus != NERR_Success)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
EnumContext->EnumerationContext = 0;
|
|
||||||
EnumContext->Buffer = NULL;
|
|
||||||
EnumContext->Count = 0;
|
|
||||||
EnumContext->Index = 0;
|
|
||||||
EnumContext->BuiltinDone = FALSE;
|
|
||||||
|
|
||||||
Status = SamConnect((servername != NULL) ? &ServerName : NULL,
|
Status = SamConnect((servername != NULL) ? &ServerName : NULL,
|
||||||
&EnumContext->ServerHandle,
|
&EnumContext->ServerHandle,
|
||||||
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
|
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
|
||||||
|
@ -2892,7 +2972,7 @@ done:
|
||||||
SamFreeMemory(EnumContext->Buffer);
|
SamFreeMemory(EnumContext->Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetApiBufferFree(EnumContext);
|
FreeEnumContext(EnumContext);
|
||||||
EnumContext = NULL;
|
EnumContext = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2901,7 +2981,7 @@ done:
|
||||||
SamCloseHandle(UserHandle);
|
SamCloseHandle(UserHandle);
|
||||||
|
|
||||||
if (resume_handle != NULL)
|
if (resume_handle != NULL)
|
||||||
*resume_handle = (DWORD_PTR)EnumContext;
|
*resume_handle = EnumContext ? EnumContext->EnumHandle : 0;
|
||||||
|
|
||||||
*bufptr = (LPBYTE)Buffer;
|
*bufptr = (LPBYTE)Buffer;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue