Skip to content

Commit

Permalink
coding style
Browse files Browse the repository at this point in the history
  • Loading branch information
aquynh committed Apr 26, 2016
1 parent f69d43d commit 7518c3b
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 138 deletions.
123 changes: 63 additions & 60 deletions tests/test_winkernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,77 +73,80 @@ namespace xcore {
#pragma warning(pop)

// Exercises all existing regression tests
static void test() {
KFLOATING_SAVE float_save;
NTSTATUS status;

// Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
// since our malloc implementation using ExAllocatePoolWithTag() is able to
// allocate memory only up to the DISPATCH_LEVEL level.
NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

// On a 32bit driver, KeSaveFloatingPointState() is required before using any
// Capstone function because Capstone can access to the MMX/x87 registers and
// 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
// KeRestoreFloatingPointState() after accesing to them. See "Using Floating
// Point or MMX in a WDM Driver" on MSDN for more details.
status = KeSaveFloatingPointState(&float_save);
if (!NT_SUCCESS(status)) {
printf("ERROR: Failed to save floating point state!\n");
return;
}

unnamed::test();
arm::test();
arm64::test();
detail::test();
iter::test();
mips::test();
ppc::test();
skipdata::test();
sparc::test();
systemz::test();
x86::test();
xcore::test();

// Restores the nonvolatile floating-point context.
KeRestoreFloatingPointState(&float_save);
static void test()
{
KFLOATING_SAVE float_save;
NTSTATUS status;

// Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
// since our malloc implementation using ExAllocatePoolWithTag() is able to
// allocate memory only up to the DISPATCH_LEVEL level.
NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

// On a 32bit driver, KeSaveFloatingPointState() is required before using any
// Capstone function because Capstone can access to the MMX/x87 registers and
// 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
// KeRestoreFloatingPointState() after accesing to them. See "Using Floating
// Point or MMX in a WDM Driver" on MSDN for more details.
status = KeSaveFloatingPointState(&float_save);
if (!NT_SUCCESS(status)) {
printf("ERROR: Failed to save floating point state!\n");
return;
}

unnamed::test();
arm::test();
arm64::test();
detail::test();
iter::test();
mips::test();
ppc::test();
skipdata::test();
sparc::test();
systemz::test();
x86::test();
xcore::test();

// Restores the nonvolatile floating-point context.
KeRestoreFloatingPointState(&float_save);
}

// Functional test for cs_winkernel_vsnprintf()
static void cs_winkernel_vsnprintf_test()
{
char buf[10];
bool ok = true;
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0);
if (!ok) {
printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n");
}
char buf[10];
bool ok = true;
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0);
ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0);
if (!ok) {
printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n");
}
}

// Driver entry point
EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
cs_winkernel_vsnprintf_test();
test();
return STATUS_CANCELLED;
PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
cs_winkernel_vsnprintf_test();
test();
return STATUS_CANCELLED;
}

// This functions mimics printf() but does not return the same value as printf()
// would do. printf() is required to exercise regression tests.
int __cdecl printf(const char * format, ...) {
NTSTATUS status;
va_list args;

va_start(args, format);
status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args);
va_end(args);
return NT_SUCCESS(status);
int __cdecl printf(const char * format, ...)
{
NTSTATUS status;
va_list args;

va_start(args, format);
status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args);
va_end(args);
return NT_SUCCESS(status);
}
146 changes: 71 additions & 75 deletions windows/winkernel_mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,113 +8,109 @@ static const ULONG CS_WINKERNEL_POOL_TAG = 'kwsC';


// A structure to implement realloc()
typedef struct _CS_WINKERNEL_MEMBLOCK
{
size_t size; // A number of bytes allocated
char data[1]; // An address returned to a caller
typedef struct _CS_WINKERNEL_MEMBLOCK {
size_t size; // A number of bytes allocated
char data[1]; // An address returned to a caller
} CS_WINKERNEL_MEMBLOCK;
C_ASSERT(sizeof(CS_WINKERNEL_MEMBLOCK) == sizeof(void *) * 2);


// free()
void CAPSTONE_API cs_winkernel_free(void *ptr)
{
if (ptr)
{
ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG);
}
if (ptr) {
ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG);
}
}

// malloc()
void * CAPSTONE_API cs_winkernel_malloc(size_t size)
{
// Disallow zero length allocation because they waste pool header space and,
// in many cases, indicate a potential validation issue in the calling code.
NT_ASSERT(size);

CS_WINKERNEL_MEMBLOCK *block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag(
NonPagedPoolNx, size + sizeof(CS_WINKERNEL_MEMBLOCK), CS_WINKERNEL_POOL_TAG);
if (!block)
{
return NULL;
}
block->size = size;
return block->data;
// Disallow zero length allocation because they waste pool header space and,
// in many cases, indicate a potential validation issue in the calling code.
NT_ASSERT(size);

CS_WINKERNEL_MEMBLOCK *block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag(
NonPagedPoolNx, size + sizeof(CS_WINKERNEL_MEMBLOCK), CS_WINKERNEL_POOL_TAG);
if (!block) {
return NULL;
}
block->size = size;

return block->data;
}

// calloc()
void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
{
size_t total = n * size;
size_t total = n * size;

void *new_ptr = cs_winkernel_malloc(total);
if (!new_ptr)
{
return NULL;
}
void *new_ptr = cs_winkernel_malloc(total);
if (!new_ptr) {
return NULL;
}

return RtlFillMemory(new_ptr, total, 0);
return RtlFillMemory(new_ptr, total, 0);
}

// realloc()
void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size)
{
void *new_ptr = NULL;
size_t current_size = 0;
size_t smaller_size = 0;

if (!ptr)
{
return cs_winkernel_malloc(size);
}

new_ptr = cs_winkernel_malloc(size);
if (!new_ptr)
{
return NULL;
}

current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size;
smaller_size = (current_size < size) ? current_size : size;
RtlCopyMemory(new_ptr, ptr, smaller_size);
cs_winkernel_free(ptr);
return new_ptr;
void *new_ptr = NULL;
size_t current_size = 0;
size_t smaller_size = 0;

if (!ptr) {
return cs_winkernel_malloc(size);
}

new_ptr = cs_winkernel_malloc(size);
if (!new_ptr) {
return NULL;
}

current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size;
smaller_size = (current_size < size) ? current_size : size;
RtlCopyMemory(new_ptr, ptr, smaller_size);
cs_winkernel_free(ptr);

return new_ptr;
}

// vsnprintf(). _vsnprintf() is avaialable for drivers, but it differs from
// vsnprintf() in a return value and when a null-terminater is set.
// cs_winkernel_vsnprintf() takes care of those differences.
#pragma warning(push)
#pragma warning(disable : 28719) // Banned API Usage : _vsnprintf is a Banned
// API as listed in dontuse.h for security
// purposes.
// API as listed in dontuse.h for security
// purposes.
int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
{
int result = _vsnprintf(buffer, count, format, argptr);

// _vsnprintf() returns -1 when a string is truncated, and returns "count"
// when an entire string is stored but without '\0' at the end of "buffer".
// In both cases, null-terminater needs to be added manually.
if (result == -1 || (size_t)result == count)
{
buffer[count - 1] = '\0';
}
if (result == -1)
{
// In case when -1 is returned, the function has to get and return a number
// of characters that would have been written. This attempts so by re-tring
// the same conversion with temp buffer that is most likely big enough to
// complete formatting and get a number of characters that would have been
// written.
char* tmp = cs_winkernel_malloc(0x1000);
if (!tmp) {
return result;
}
result = _vsnprintf(tmp, 0x1000, format, argptr);
NT_ASSERT(result != -1);
cs_winkernel_free(tmp);
}

return result;
int result = _vsnprintf(buffer, count, format, argptr);

// _vsnprintf() returns -1 when a string is truncated, and returns "count"
// when an entire string is stored but without '\0' at the end of "buffer".
// In both cases, null-terminater needs to be added manually.
if (result == -1 || (size_t)result == count) {
buffer[count - 1] = '\0';
}

if (result == -1) {
// In case when -1 is returned, the function has to get and return a number
// of characters that would have been written. This attempts so by re-tring
// the same conversion with temp buffer that is most likely big enough to
// complete formatting and get a number of characters that would have been
// written.
char* tmp = cs_winkernel_malloc(0x1000);
if (!tmp) {
return result;
}

result = _vsnprintf(tmp, 0x1000, format, argptr);
NT_ASSERT(result != -1);
cs_winkernel_free(tmp);
}

return result;
}
#pragma warning(pop)
6 changes: 3 additions & 3 deletions windows/winkernel_mm.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Capstone Disassembly Engine */
/* By Satoshi Tanda <[email protected]>, 2016 */
#ifndef CS_WINDOWS_WINKERNEL_MM_H_
#define CS_WINDOWS_WINKERNEL_MM_H_
#ifndef CS_WINDOWS_WINKERNEL_MM_H
#define CS_WINDOWS_WINKERNEL_MM_H

#ifdef __cplusplus
extern "C" {
Expand All @@ -19,4 +19,4 @@ int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *
}
#endif

#endif // CS_WINDOWS_WINKERNEL_MM_H_
#endif // CS_WINDOWS_WINKERNEL_MM_H

0 comments on commit 7518c3b

Please sign in to comment.