mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +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) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
InitializeListHead(&g_EnumContextListHead);
|
||||
InitializeCriticalSection(&g_EnumContextListLock);
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
NetBIOSInit();
|
||||
NetBTInit();
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "nbnamecache.h"
|
||||
#include "netbios.h"
|
||||
|
||||
extern LIST_ENTRY g_EnumContextListHead;
|
||||
extern CRITICAL_SECTION g_EnumContextListLock;
|
||||
|
||||
NET_API_STATUS
|
||||
WINAPI
|
||||
NetpNtStatusToApiStatus(NTSTATUS Status);
|
||||
|
|
|
@ -36,6 +36,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
|
|||
|
||||
typedef struct _ENUM_CONTEXT
|
||||
{
|
||||
LIST_ENTRY ListLink;
|
||||
ULONG EnumHandle;
|
||||
|
||||
SAM_HANDLE ServerHandle;
|
||||
SAM_HANDLE BuiltinDomainHandle;
|
||||
SAM_HANDLE AccountDomainHandle;
|
||||
|
@ -50,6 +53,9 @@ typedef struct _ENUM_CONTEXT
|
|||
|
||||
} ENUM_CONTEXT, *PENUM_CONTEXT;
|
||||
|
||||
LIST_ENTRY g_EnumContextListHead;
|
||||
CRITICAL_SECTION g_EnumContextListLock;
|
||||
LONG g_EnumContextHandle = 0;
|
||||
|
||||
static
|
||||
ULONG
|
||||
|
@ -2662,6 +2668,86 @@ done:
|
|||
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.@)
|
||||
|
@ -2699,20 +2785,14 @@ NetUserEnum(LPCWSTR servername,
|
|||
|
||||
if (resume_handle != NULL && *resume_handle != 0)
|
||||
{
|
||||
EnumContext = (PENUM_CONTEXT)*resume_handle;
|
||||
EnumContext = LookupEnumContext(*resume_handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
|
||||
ApiStatus = AllocateEnumContext(&EnumContext);
|
||||
if (ApiStatus != NERR_Success)
|
||||
goto done;
|
||||
|
||||
EnumContext->EnumerationContext = 0;
|
||||
EnumContext->Buffer = NULL;
|
||||
EnumContext->Count = 0;
|
||||
EnumContext->Index = 0;
|
||||
EnumContext->BuiltinDone = FALSE;
|
||||
|
||||
Status = SamConnect((servername != NULL) ? &ServerName : NULL,
|
||||
&EnumContext->ServerHandle,
|
||||
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
|
||||
|
@ -2892,7 +2972,7 @@ done:
|
|||
SamFreeMemory(EnumContext->Buffer);
|
||||
}
|
||||
|
||||
NetApiBufferFree(EnumContext);
|
||||
FreeEnumContext(EnumContext);
|
||||
EnumContext = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2901,7 +2981,7 @@ done:
|
|||
SamCloseHandle(UserHandle);
|
||||
|
||||
if (resume_handle != NULL)
|
||||
*resume_handle = (DWORD_PTR)EnumContext;
|
||||
*resume_handle = EnumContext ? EnumContext->EnumHandle : 0;
|
||||
|
||||
*bufptr = (LPBYTE)Buffer;
|
||||
|
||||
|
|
Loading…
Reference in a new issue