C: ArrayList implementation in kernel mode

I trying make a code example where i want insert in a arrylist only process names that still not exists in this list, my trouble that show here is that comes bsod in the following line. This following code is based on usermode version present in this answer (https://stackoverflow.com/questions/49765716/c-how-make-a-arraylist-implementation-compatible-with-unicode-string-data/49765864#49765864). Before i tried make with same usermode code of arraylist, but already that some routines not is avaiable in kernel mode i decided use somes similar like ExAllocatePoolWithTag (malloc/calloc), RtlFreeUnicodeString (void FreeUString()), RtlDuplicateUnicodeString,this last can be better change to RtlUnicodeStringCopy already that RtlDuplicateUnicodeString is not always exported in Windows.


FAULTING_SOURCE_LINE_NUMBER: 128

FAULTING_SOURCE_CODE:
124: {
125: int index = 0;
126: while (index <= list->current)
127: {
> 128: if (e->data->Length == list->elements[index].data->Length &&
129: 0 == wcsncmp(e->data->Buffer,
130: list->elements[index].data->Buffer,
131: list->elements[index].data->Length))
132: return index;
133: index++;

Here is a minimal and compilable example:

#include <ntddk.h>
#include <windef.h>

#define NTOSAPI __declspec(dllimport)

NTSTATUS NTAPI RtlDuplicateUnicodeString(IN ULONG Flags, IN PCUNICODE_STRING SourceString, OUT PUNICODE_STRING DestinationString);

///////////////////////////////////// START ARRAYLIST /////////////////////////////////////////

typedef unsigned char uint8_t;

typedef struct
{
UNICODE_STRING *data;
}Element;

typedef struct
{
int current;
int size;
int increment_rate;
Element *elements;
}ArrayList;

void FreeUString(UNICODE_STRING *src)
{
RtlFreeUnicodeString(src);
src->Length = src->MaximumLength = 0;
}

void initWithSizeAndIncRate(ArrayList const list, int size, int rate)
{
list->size = size;
list->increment_rate = rate;
list->elements = (Element
)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘Fo’);
list->current = -1;
}

void initWithSize(ArrayList *const list, int size)
{
initWithSizeAndIncRate(list, size, 50);
}

void init(ArrayList *const list)
{
initWithSize(list, 100);
}

void arraryCopy(void dest, int dIndex, const void src, int sIndex, int len, int destLen, size_t size)
{
uint8_t udest = (uint8_t)dest;
uint8_t usrc = (uint8_t)src;
dIndex *= size;
sIndex *= size;
len *= size;
destLen *= size;

if (src != dest)
{
memcpy(&udest[dIndex], &usrc[sIndex], len);
}
else
{
if (dIndex > sIndex)
{
uint8_t tmp = (uint8_t)ExAllocatePoolWithTag(NonPagedPool, size, ‘F’);
memcpy(tmp, &udest[dIndex], (destLen - dIndex));
memcpy(&udest[dIndex], &usrc[sIndex], len);
memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
ExFreePoolWithTag(tmp, ‘F’);
}
else if (sIndex > dIndex)
{
memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
}
else
return;
}
}

void clear(ArrayList const list)
{
while (list->current >= 0)
{
FreeUString(list->elements[list->current].data);
list->current–;
}
}

void wide(ArrayList
const list)
{
list->size += list->increment_rate;
Element newArr = (Element)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘T’);
arraryCopy(newArr, 0, list->elements, 0, list->current, list->size, sizeof(Element));
//ExFreePoolWithTag(list->elements, ‘Foo’);
list->elements = newArr;
}

int add(ArrayList *const list, Element *e)
{
UNICODE_STRING *dest = { NULL };
NTSTATUS status = STATUS_SUCCESS;

if (++list->current < list->size)
{
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);

list->elements[list->current].data = dest;
return 1;
}
else
{
wide(list);
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);
list->elements[list->current].data = dest;
return 1;
}
return 0;
}

int indexOf(const ArrayList *const list, Element *e)
{
int index = 0;
while (index <= list->current)
{
if (e->data->Length == list->elements[index].data->Length &&
0 == wcsncmp(e->data->Buffer,
list->elements[index].data->Buffer,
list->elements[index].data->Length))
return index;
index++;
}
return 0;
}

void clean(ArrayList *list)
{
ExFreePoolWithTag(list->elements, ‘Fo’);
}

ArrayList list;
Element e;

///////////////////////////////// END ARRAYLIST ///////////////////////////////////

typedef enum _THREAD_STATE {
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE;

typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
LONG WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;

typedef struct SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
DWORD BasePriority;
HANDLE ProcessId;
HANDLE ParentProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VMCounters;
IO_COUNTERS IOCounters;
SYSTEM_THREAD Threads[1];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemProcessInformation = 5,
SystemCallCountInformation = 6,
SystemDeviceInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemFlagsInformation = 9,
SystemCallTimeInformation = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemStackTraceInformation = 13,
SystemPagedPoolInformation = 14,
SystemNonPagedPoolInformation = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemVdmBopInformation = 20,
SystemFileCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemDpcBehaviorInformation = 24,
SystemFullMemoryInformation = 25,
SystemLoadGdiDriverInformation = 26,
SystemUnloadGdiDriverInformation = 27,
SystemTimeAdjustmentInformation = 28,
SystemSummaryMemoryInformation = 29,
SystemMirrorMemoryInformation = 30,
SystemPerformanceTraceInformation = 31,
SystemObsolete0 = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemExtendServiceTableInformation = 38,
SystemPrioritySeperation = 39,
SystemVerifierAddDriverInformation = 40,
SystemVerifierRemoveDriverInformation = 41,
SystemProcessorIdleInformation = 42,
SystemLegacyDriverInformation = 43,
SystemCurrentTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemTimeSlipNotification = 46,
SystemSessionCreate = 47,
SystemSessionDetach = 48,
SystemSessionInformation = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemVerifierThunkExtend = 52,
SystemSessionProcessInformation = 53,
SystemLoadGdiDriverInSystemSpace = 54,
SystemNumaProcessorMap = 55,
SystemPrefetcherInformation = 56,
SystemExtendedProcessInformation = 57,
SystemRecommendedSharedDataAlignment = 58,
SystemComPlusPackage = 59,
SystemNumaAvailableMemory = 60,
SystemProcessorPowerInformation = 61,
SystemEmulationBasicInformation = 62,
SystemEmulationProcessorInformation = 63,
SystemExtendedHandleInformation = 64,
SystemLostDelayedWriteInformation = 65,
SystemBigPoolInformation = 66,
SystemSessionPoolTagInformation = 67,
SystemSessionMappedViewInformation = 68,
SystemHotpatchInformation = 69,
SystemObjectSecurityMode = 70,
SystemWatchdogTimerHandler = 71,
SystemWatchdogTimerInformation = 72,
SystemLogicalProcessorInformation = 73,
SystemWow64SharedInformation = 74,
SystemRegisterFirmwareTableInformationHandler = 75,
SystemFirmwareTableInformation = 76,
SystemModuleInformationEx = 77,
SystemVerifierTriageInformation = 78,
SystemSuperfetchInformation = 79,
SystemMemoryListInformation = 80,
SystemFileCacheInformationEx = 81,
MaxSystemInfoClass = 82

} SYSTEM_INFORMATION_CLASS;

NTOSAPI NTSTATUS NTAPI ZwQuerySystemInformation(/IN/ SYSTEM_INFORMATION_CLASS SystemInformationClass, /IN OUT/ PVOID SystemInformation, /IN/ ULONG SystemInformationLength, /OUT/ PULONG ReturnLength OPTIONAL);

NTSTATUS EnumProcesses()
{
NTSTATUS status;

ULONG cb = 0x8000;

do
{
status = STATUS_INSUFFICIENT_RESOURCES;
PVOID buf = ExAllocatePoolWithTag(PagedPool, cb, ‘tset’);

if (buf)
{
if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union Data {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};

union Data data;

data.pv = buf;
ULONG NextEntryOffset = 0;

do
{
data.pb += NextEntryOffset;

DbgPrint(“%d %wZ\n”, data.pspi->ProcessId, &data.pspi->ImageName);

e.data = &data.pspi->ImageName;

int i = indexOf(&list, &e);

if (i > 0)
{
DbgPrint(“process already in list \n”);
}
else
{
add(&list, &e);
}

} while (NextEntryOffset = data.pspi->NextEntryOffset);
}

ExFreePoolWithTag(buf, ‘tset’);
}

} while (status == STATUS_INFO_LENGTH_MISMATCH);
clean(&list);
return status;
}

void EnumProcUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint(“Goodbye from EnumProc!\n”);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{

init(&list);
EnumProcesses();

DriverObject->DriverUnload = EnumProcUnload;

DbgPrint(“Hello from EnumProc!\n”);

return STATUS_SUCCESS;
}</windef.h></ntddk.h>

Before answering people might want to look at the responses he has gotten
elsewhere:
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9640e6cc-d4e9-
4ce5-970c-158df932951a/arraylist-implementation-bsod-on-indexof-routine?foru
m=wdk

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Sunday, April 15, 2018 8:22 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] C: ArrayList implementation in kernel mode

I trying make a code example where i want insert in a arrylist only process
names that still not exists in this list, my trouble that show here is that
comes bsod in the following line. This following code is based on usermode
version present in this answer
(https://stackoverflow.com/questions/49765716/c-how-make-a-arraylist-impleme
ntation-compatible-with-unicode-string-data/49765864#49765864). Before i
tried make with same usermode code of arraylist, but already that some
routines not is avaiable in kernel mode i decided use somes similar like
ExAllocatePoolWithTag (malloc/calloc), RtlFreeUnicodeString (void
FreeUString()), RtlDuplicateUnicodeString,this last can be better change to
RtlUnicodeStringCopy already that RtlDuplicateUnicodeString is not always
exported in Windows.

----------------------------------------------------------------------------
---------------

FAULTING_SOURCE_LINE_NUMBER: 128

FAULTING_SOURCE_CODE:
124: {
125: int index = 0;
126: while (index <= list->current)
127: {
> 128: if (e->data->Length ==
list->elements[index].data->Length &&
129: 0 == wcsncmp(e->data->Buffer,
130: list->elements[index].data->Buffer,
131: list->elements[index].data->Length))
132: return index;
133: index++;

Here is a minimal and compilable example:

#include <ntddk.h>
#include <windef.h>

#define NTOSAPI __declspec(dllimport)

NTSTATUS NTAPI RtlDuplicateUnicodeString(IN ULONG Flags, IN PCUNICODE_STRING
SourceString, OUT PUNICODE_STRING DestinationString);

///////////////////////////////////// START ARRAYLIST
/////////////////////////////////////////

typedef unsigned char uint8_t;

typedef struct
{
UNICODE_STRING *data;
}Element;

typedef struct
{
int current;
int size;
int increment_rate;
Element *elements;
}ArrayList;

void FreeUString(UNICODE_STRING *src)
{
RtlFreeUnicodeString(src);
src->Length = src->MaximumLength = 0; }

void initWithSizeAndIncRate(ArrayList const list, int size, int rate) {
list->size = size;
list->increment_rate = rate;
list->elements = (Element
)ExAllocatePoolWithTag(NonPagedPool,
sizeof(Element), ‘Fo’);
list->current = -1;
}

void initWithSize(ArrayList *const list, int size) {
initWithSizeAndIncRate(list, size, 50); }

void init(ArrayList *const list)
{
initWithSize(list, 100);
}

void arraryCopy(void dest, int dIndex, const void src, int sIndex, int
len, int destLen, size_t size) {
uint8_t udest = (uint8_t)dest;
uint8_t usrc = (uint8_t)src;
dIndex *= size;
sIndex *= size;
len *= size;
destLen *= size;

if (src != dest)
{
memcpy(&udest[dIndex], &usrc[sIndex], len);
}
else
{
if (dIndex > sIndex)
{
uint8_t tmp = (uint8_t)ExAllocatePoolWithTag(NonPagedPool,
size, ‘F’);
memcpy(tmp, &udest[dIndex], (destLen - dIndex));
memcpy(&udest[dIndex], &usrc[sIndex], len);
memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
ExFreePoolWithTag(tmp, ‘F’);
}
else if (sIndex > dIndex)
{
memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
}
else
return;
}
}

void clear(ArrayList const list)
{
while (list->current >= 0)
{
FreeUString(list->elements[list->current].data);
list->current–;
}
}

void wide(ArrayList
const list)
{
list->size += list->increment_rate;
Element newArr = (Element)ExAllocatePoolWithTag(NonPagedPool,
sizeof(Element), ‘T’);
arraryCopy(newArr, 0, list->elements, 0, list->current, list->size,
sizeof(Element));
//ExFreePoolWithTag(list->elements, ‘Foo’);
list->elements = newArr;
}

int add(ArrayList *const list, Element *e) {
UNICODE_STRING *dest = { NULL };
NTSTATUS status = STATUS_SUCCESS;

if (++list->current < list->size)
{
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);

list->elements[list->current].data = dest;
return 1;
}
else
{
wide(list);
status = RtlDuplicateUnicodeString(1, e->data, dest);
DbgPrint(“RtlDuplicateUnicodeString() status: 0x%x”, status);
list->elements[list->current].data = dest;
return 1;
}
return 0;
}

int indexOf(const ArrayList *const list, Element *e) {
int index = 0;
while (index <= list->current)
{
if (e->data->Length == list->elements[index].data->Length &&
0 == wcsncmp(e->data->Buffer,
list->elements[index].data->Buffer,
list->elements[index].data->Length))
return index;
index++;
}
return 0;
}

void clean(ArrayList *list)
{
ExFreePoolWithTag(list->elements, ‘Fo’); }

ArrayList list;
Element e;

///////////////////////////////// END ARRAYLIST
///////////////////////////////////

typedef enum _THREAD_STATE {
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE;

typedef struct _SYSTEM_THREAD {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
LONG WaitReason;
} SYSTEM_THREAD, *PSYSTEM_THREAD;

typedef struct SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
DWORD BasePriority;
HANDLE ProcessId;
HANDLE ParentProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VMCounters;
IO_COUNTERS IOCounters;
SYSTEM_THREAD Threads[1];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemProcessInformation = 5,
SystemCallCountInformation = 6,
SystemDeviceInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemFlagsInformation = 9,
SystemCallTimeInformation = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemStackTraceInformation = 13,
SystemPagedPoolInformation = 14,
SystemNonPagedPoolInformation = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemVdmBopInformation = 20,
SystemFileCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemDpcBehaviorInformation = 24,
SystemFullMemoryInformation = 25,
SystemLoadGdiDriverInformation = 26,
SystemUnloadGdiDriverInformation = 27,
SystemTimeAdjustmentInformation = 28,
SystemSummaryMemoryInformation = 29,
SystemMirrorMemoryInformation = 30,
SystemPerformanceTraceInformation = 31,
SystemObsolete0 = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemExtendServiceTableInformation = 38,
SystemPrioritySeperation = 39,
SystemVerifierAddDriverInformation = 40,
SystemVerifierRemoveDriverInformation = 41,
SystemProcessorIdleInformation = 42,
SystemLegacyDriverInformation = 43,
SystemCurrentTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemTimeSlipNotification = 46,
SystemSessionCreate = 47,
SystemSessionDetach = 48,
SystemSessionInformation = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemVerifierThunkExtend = 52,
SystemSessionProcessInformation = 53,
SystemLoadGdiDriverInSystemSpace = 54,
SystemNumaProcessorMap = 55,
SystemPrefetcherInformation = 56,
SystemExtendedProcessInformation = 57,
SystemRecommendedSharedDataAlignment = 58,
SystemComPlusPackage = 59,
SystemNumaAvailableMemory = 60,
SystemProcessorPowerInformation = 61,
SystemEmulationBasicInformation = 62,
SystemEmulationProcessorInformation = 63,
SystemExtendedHandleInformation = 64,
SystemLostDelayedWriteInformation = 65,
SystemBigPoolInformation = 66,
SystemSessionPoolTagInformation = 67,
SystemSessionMappedViewInformation = 68,
SystemHotpatchInformation = 69,
SystemObjectSecurityMode = 70,
SystemWatchdogTimerHandler = 71,
SystemWatchdogTimerInformation = 72,
SystemLogicalProcessorInformation = 73,
SystemWow64SharedInformation = 74,
SystemRegisterFirmwareTableInformationHandler = 75,
SystemFirmwareTableInformation = 76,
SystemModuleInformationEx = 77,
SystemVerifierTriageInformation = 78,
SystemSuperfetchInformation = 79,
SystemMemoryListInformation = 80,
SystemFileCacheInformationEx = 81,
MaxSystemInfoClass = 82

} SYSTEM_INFORMATION_CLASS;

NTOSAPI NTSTATUS NTAPI ZwQuerySystemInformation(/IN/
SYSTEM_INFORMATION_CLASS SystemInformationClass, /IN OUT/ PVOID
SystemInformation, /IN/ ULONG SystemInformationLength, /OUT/ PULONG
ReturnLength OPTIONAL);

NTSTATUS EnumProcesses()
{
NTSTATUS status;

ULONG cb = 0x8000;

do
{
status = STATUS_INSUFFICIENT_RESOURCES;
PVOID buf = ExAllocatePoolWithTag(PagedPool, cb, ‘tset’);

if (buf)
{
if (0 <= (status =
ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union Data {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};

union Data data;

data.pv = buf;
ULONG NextEntryOffset = 0;

do
{
data.pb += NextEntryOffset;

DbgPrint(“%d %wZ\n”, data.pspi->ProcessId,
&data.pspi->ImageName);

e.data = &data.pspi->ImageName;

int i = indexOf(&list, &e);

if (i > 0)
{
DbgPrint(“process already in list \n”);
}
else
{
add(&list, &e);
}

} while (NextEntryOffset = data.pspi->NextEntryOffset);
}

ExFreePoolWithTag(buf, ‘tset’);
}

} while (status == STATUS_INFO_LENGTH_MISMATCH);
clean(&list);
return status;
}

void EnumProcUnload(IN PDRIVER_OBJECT DriverObject) {
DbgPrint(“Goodbye from EnumProc!\n”); }

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING
RegistryPath) {

init(&list);
EnumProcesses();

DriverObject->DriverUnload = EnumProcUnload;

DbgPrint(“Hello from EnumProc!\n”);

return STATUS_SUCCESS;
}


NTDEV is sponsored by OSR

Visit the list online at:
http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at
http:</http:></http:></http:></windef.h></ntddk.h>

> Before answering people might want to look at the responses he has gotten elsewhere:



Well done, Don…

However, you seem to have overlooked the part concerning the OP’s name and company. Could you please fix it (preferably with Caps Lock key on). Thanks in advance

PS. Sorry, Peter, but I just cannot resist a temptation this time…

Anton Bassov

Anton,

Assholes like you can never resist, or learn. In this case if you had
looked at the history of the OP on the Microsoft forum you would have seen
it is obvious his forward progress is essentially NIL.

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Sunday, April 15, 2018 4:08 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] C: ArrayList implementation in kernel mode

> Before answering people might want to look at the responses he has gotten
elsewhere:



Well done, Don…

However, you seem to have overlooked the part concerning the OP’s name and
company. Could you please fix it (preferably with Caps Lock key on). Thanks
in advance



PS. Sorry, Peter, but I just cannot resist a temptation this time…

Anton Bassov


NTDEV is sponsored by OSR

Visit the list online at:
http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at
http:</http:></http:></http:>

>Assholes like you can never resist, or learn.

Sorry, Don, but you have provoked me yourself. Look - you reacted to the OP’s question
in…well, lets say “not-so-adequate”, way, that is so typical of you, did it in another NG…and then had proudly posted a link to it on NTDEV so that we could all see and “appreciate” your “accomplishments”. I know I should have kept my opinion to myself, but in this particular case the whole thing looked so funny to me that I just could not resist the temptation of speaking ironically to you yet another time

In this case if you had looked at the history of the OP on the Microsoft forum
you would have seen it is obvious his forward progress is essentially NIL.

Yes, but what is the point of reacting to his questions in ANY way then??? It is pretty obvious that he is a part of “please guide me in the same” crowd, so that nothing is ever going to change. In the end of the day, if he does not like your reply he is just going to post his question to another NG in an apparent expectation of a more “suitable” one, i.e. do things the way they always do.

Anton Bassov

On Apr 15, 2018, at 5:22 AM, xxxxx@hotmail.com wrote:
>
> I trying make a code example where i want insert in a arrylist only process names that still not exists in this list, my trouble that show here is that comes bsod in the following line. This following code is based on usermode version present in this answer

This code is totally broken. You should throw this out and start from scratch. Make the code work in user-mode before you try to move this to the kernel, because you aren’t ready for kernel coding yet.

> ///////////////////////////////////// START ARRAYLIST /////////////////////////////////////////
>
> typedef unsigned char uint8_t;
>
> typedef struct
> {
> UNICODE_STRING data;
> }Element;

Why does this contain s POINTER to a UNICODE_STRING? This is just going to confuse you. You have to allocate an Element, and then allocate a UNICODE_STRING, and then allocate a character buffer inside of that. This is a disaster of a design. Your memory fragmentation will kill the performance. If you want your list to contain UNICODE_STRINGs, then just make it contain UNICODE_STRINGs.

> typedef struct
> {
> int current;
> int size;
> int increment_rate;
> Element elements;
> }ArrayList;

Why do you have a “current” element? I suspect you can’t actually answer that question, because you don’t use the “current” value correctly in any of your functions here.

I have a hunch this was an attempt to emulate the size() and capacity() methods in the C++ STL containers, but they aren’t used that way.

> void FreeUString(UNICODE_STRING src)
> {
> RtlFreeUnicodeString(src);
> src->Length = src->MaximumLength = 0;
> }
>
> void initWithSizeAndIncRate(ArrayList const list, int size, int rate)
> {
> list->size = size;
> list->increment_rate = rate;
> list->elements = (Element
)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘Fo’);
> list->current = -1;
> }

Here’s your biggest problem. When this is done, the structure will claim to have “size” elements. But how many elements are really in the array? Here’s a hint: you only allocated 1. Why would you set “current” to -1? An empty container has 0 elements, not -1.

> void initWithSize(ArrayList const list, int size)
> {
> initWithSizeAndIncRate(list, size, 50);
> }
>
> void init(ArrayList const list)
> {
> initWithSize(list, 100);
> }

This will result in an array that says it has 100 elements, but in reality only contains 1.

> void arraryCopy(void dest, int dIndex, const void src, int sIndex, int len, int destLen, size_t size)
> {
> …
> if (src != dest)
> {
> memcpy(&udest[dIndex], &usrc[sIndex], len);
> }
> else
> {
> if (dIndex > sIndex)
> {
> uint8_t tmp = (uint8_t)ExAllocatePoolWithTag(NonPagedPool, size, ‘F’);
> memcpy(tmp, &udest[dIndex], (destLen - dIndex));
> memcpy(&udest[dIndex], &usrc[sIndex], len);
> memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
> ExFreePoolWithTag(tmp, ‘F’);
> }
> else if (sIndex > dIndex)
> {
> memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
> }

This whole function is totally idiotic. Whoever wrote this doesn’t know the C library at all. It’s true that memcpy doesn’t guarantee correct handling of overlapping regions, but memmove certainly does. You can replace this ENTIRE FUNCTION with one line:
memmove( &udest[dIndex
size], &usrc[sindex
size], len * size );
Or, even better:
RtlMoveMemory( &udest[dIndex
size], &usrc[sindex
size], len * size );

Stepping back further, however, the DESIGN of the function is stupid. Your ArrayList is not generic. It can only contain Elements. So, why have a generic copy? Use type safety by passing ArrayList pointers and use sizeof(Element).

An even better solution would be to convert this all to C++, where you can make this a generic template.

> void wide(ArrayList
const list)
> {
> list->size += list->increment_rate;
> Element newArr = (Element)ExAllocatePoolWithTag(NonPagedPool, sizeof(Element), ‘T’);
> arraryCopy(newArr, 0, list->elements, 0, list->current, list->size, sizeof(Element));
> //ExFreePoolWithTag(list->elements, ‘Foo’);
> list->elements = newArr;
> }

This will explode the first time you call it. Why? Two reasons. First, because list->current is going to be -1 for an empty list. Second, because the new array you allocate here still only contains 1 element, so the copy is going to run off the end. And, because of your comment, you are going to leak memory every time this runs.

> int indexOf(const ArrayList *const list, Element *e)
> {
> int index = 0;
> while (index <= list->current)
> {
> if (e->data->Length == list->elements[index].data->Length &&
> 0 == wcsncmp(e->data->Buffer,
> list->elements[index].data->Buffer,
> list->elements[index].data->Length))
> return index;
> index++;
> }
> return 0;
> }

I hope it is clear now why this exploded. list->elements[1] does not exist. You didn’t allocate it.

Philosophically, there is another problem. This does not return the index of Element “e” within the list. Instead, it returns the index of the element within the list that happens to contain the same string as “e”. That may be the intend, but that’s not want someone accustomed to the MFC CArrayList is going to expect.

> void clean(ArrayList *list)
> {
> ExFreePoolWithTag(list->elements, ‘Fo’);
> }

This only frees the Element structure. It does not free the UNICODE_STRINGs that the Element points to, nor does it free the character buffers that the UNICODE_STRINGs point to. All of that memory will leak. When you’re writing containers like this, you ALWAYS have to think about “who owns this memory? Who is responsible for allocating it, and who is responsible for freeing it?” You certainly have not done that here.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

You know, in addition to Troll Mode (where the troll can see his own posts but nobody else can), the new forum software has a “warning” mode… It allows mods to give annoying people warning points, and when the max number of points is exceeded, the person is temporarily banned for a period of time.

This is, of course, in addition to the ability to put people on moderation.

I, for one, am looking forward to the new features.

Peter
OSR
@OSRDrivers

> It allows mods to give annoying people warning points, and when the max number

of points is exceeded, the person is temporarily banned for a period of time.

Wow!!! This one already seems, indeed, exciting and promising. Just a couple of questions

  1. Can the suspect actually see his current standing?

  2. Is it sort of “low-pass filtered” over the time by some statistical means ( moving average seems to be the easiest possible but most definitely NOT the only possible method - in the most extreme cases it may utilise a wide array of DSP techniques with parameters like filter type, coefficients and sample size being under the control of list moderators)?

With features like that I would be able to take the piss out of the “funny characters” all the way along and, at the same time, always be in a position to adjust my current behavior in a way that allows me to stay off the moderation list

Anton Bassov

You forgot about “administrative override”. Perhaps instead of worrying
about how to game the system, just don’t try so hard to be a jerk.

Mark Roddy

On Mon, Apr 16, 2018 at 3:27 PM, xxxxx@hotmail.com <
xxxxx@lists.osr.com> wrote:

> It allows mods to give annoying people warning points, and when the max
number
> of points is exceeded, the person is temporarily banned for a period of
time.

Wow!!! This one already seems, indeed, exciting and promising. Just a
couple of questions

  1. Can the suspect actually see his current standing?

  2. Is it sort of “low-pass filtered” over the time by some statistical
    means ( moving average seems to be the easiest possible but most definitely
    NOT the only possible method - in the most extreme cases it may utilise a
    wide array of DSP techniques with parameters like filter type, coefficients
    and sample size being under the control of list moderators)?

With features like that I would be able to take the piss out of the “funny
characters” all the way along and, at the same time, always be in a
position to adjust my current behavior in a way that allows me to stay off
the moderation list

Anton Bassov


NTDEV is sponsored by OSR

Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

> You forgot about “administrative override”.

I did not - after all, this whole system can be thought of just as of an indicator that shows with a certain degree of accuracy how much our hosts are annoyed by any particular poster’s most recent posting history.

Perhaps instead of worrying about how to game the system,

This is not about “gaming the system” - this is more about getting an indication of the “red line”…

… just don’t try so hard to be a jerk.

You know, sometimes it is really hard to refrain from speaking ironically to some posters…

For example, let’s look at this particular case objectively. The OP seems to be a kind of a “programmer” who is capable of making 5 mistakes (not just some accidental typo-produced bugs but the mistakes that immediately reveal his profound lack of knowledge of C language basics)
in 2 lines of code. To make it even “better”, he does not seem to be progressing any faster than VinayKP either. There are quite a few things that have to be pointed out to him under these circumstances, don’t you think.

However, Mr.Burn does not really care about all the above - his primary concern is just the OP’s use of a couple of undocumented functions, and the way he tends to express his thought about everything unsupported/undocumented does not really seem to be totally adequate - in fact, it is reminiscent of his requests concerning company name/ shouting in capitals.

To make it even funnier, he did all that elsewhere, and then proudly posted a link to NDTEV.

Do you really think that speaking ironically to him under these circumstances is indicative of being a jerk/troll???

Anton Bassov

Again, your use of “ironic” is incorrect here.

But, in any case, the answer is “Yes” – I think you’re being BOTH a jerk AND a troll.

We may port your account in “Troll Mode”…

Peter
OSR
@OSRDrivers