Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting... Please check out the Community Guidelines in the
Announcements and Administration Category.

C: ArrayList implementation in kernel mode

flash_markflash_mark Posts: 22
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;
}

Comments

  • Don_BurnDon_Burn Posts: 1,623
    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 <xxxxx@lists.osr.com>
    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://www.osronline.com/showlists.cfm?list=ntdev>;

    MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
    drivers!
    Details at <http://www.osr.com/seminars>;

    To unsubscribe, visit the List Server section of OSR Online at
    <http://www.osronline.com/page.cfm?name=ListServer>;
  • anton_bassovanton_bassov Posts: 4,799
    > Before answering people might want to look at the responses he has gotten elsewhere:

    <ironical mode>


    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

    </ironical mode>


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


    Anton Bassov
  • Don_BurnDon_Burn Posts: 1,623
    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 <xxxxx@lists.osr.com>
    Subject: RE:[ntdev] C: ArrayList implementation in kernel mode

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

    <ironical mode>


    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

    </ironical mode>


    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://www.osronline.com/showlists.cfm?list=ntdev>;

    MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
    drivers!
    Details at <http://www.osr.com/seminars>;

    To unsubscribe, visit the List Server section of OSR Online at
    <http://www.osronline.com/page.cfm?name=ListServer>;
  • anton_bassovanton_bassov Posts: 4,799
    >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
  • Tim_RobertsTim_Roberts Posts: 12,620
    On Apr 15, 2018, at 5:22 AM, xxxxx@hotmail.com <xxxxx@lists.osr.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.

    Tim Roberts, [email protected]
    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

    Peter Viscarola
    OSR
    @OSRDrivers

  • anton_bassovanton_bassov Posts: 4,799
    > 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
  • Mark_RoddyMark_Roddy Posts: 4,269
    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: showlists.cfm?list=ntdev>
    >
    > MONTHLY seminars on crash dump analysis, WDF, Windows internals and
    > software drivers!
    > Details at
    >
    > To unsubscribe, visit the List Server section of OSR Online at <
    > http://www.osronline.com/page.cfm?name=ListServer>;
    >
  • anton_bassovanton_bassov Posts: 4,799
    > 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
  • <quote>
    Do you really think that speaking ironically to him under these circumstances is
    indicative of being a jerk/troll????
    </quote>

    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

    Peter Viscarola
    OSR
    @OSRDrivers

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!