Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Расширении таблицы символических имен _PELDR_AddExportTable  (Прочитано 29638 раз)
0 Пользователей и 1 Гость смотрят эту тему.
inf158704
Участник

ru
Offline Offline

« : 11-09-2012 07:08 » 

   Уважаемые программисты. Я люблю еще  живую операционку win98 Улыбаюсь и хочет сделать что нибуть полезное. Основная проблема сейчас это отсутствие драйверов для нее. 3G модем и wifi были бы очень даже неплохими примочками на стареньких ноутбуках.
   Драйвера от XP не ставятся иной раз по причине отсутсвия одной двух функций ядра.
Например для D-link DWA-140 нехватет, всего ничего, обработки NdisInitializeString.
которую можно выдернуть из XP с помощю IDA и выглядит она так:

Код:
; Exported entry 136. NdisInitializeString
; Attributes: bp-based frame
; __stdcall NdisInitializeString(x, x)

public _NdisInitializeString@8
_NdisInitializeString@8 proc near

arg_0= dword ptr  8
arg_4= dword ptr  0Ch

mov edi, edi
push ebp
mov ebp, esp
push edi
mov edi, [ebp+arg_4]
mov eax, edi
lea ecx, [eax+1]

loc_128C3:
mov dl, [eax]
inc eax
test dl, dl
jnz short loc_128C3
push esi
mov esi, [ebp+arg_0]
sub eax, ecx
add eax, eax
mov [esi], ax
add eax, 2
mov [esi+2], ax
movzx eax, ax
push 7473444Eh
push eax
push 0
call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
test eax, eax
mov [esi+4], eax
pop esi
jz short loc_1290B

loc_128F5:
mov cl, [edi]
test cl, cl
jz short loc_12907
movzx cx, cl
mov [eax], cx
inc edi
inc eax
inc eax
jmp short loc_128F5

loc_12907:
and word ptr [eax], 0

loc_1290B:
pop edi
pop ebp
retn 8
_NdisInitializeString@8 endp

ExAllocatePoolWithTag при этом обрабатываеться Win98,
а больше ничего вроде перекрестного невижу.

Как универсальным решение Уолтер Они в своей книге предлагает   "нижний фильтрующий драйвер" WDMSTUB.sys в котором сделаны заглужки или реализованы довольно много функция.
Работа основана на расширении таблицы символических имен с помощю _PELDR_AddExportTable.

Нашел вот на него описание:
Цитата
_PELDR_AddExportTable
----------------------------------------------
include vxdldr.inc

LRESULT CDECL PELDR_AddExportTable(PHPEEXPORTTABLE phExportTable,
    PSTR pszModuleName, ULONG cExportedFunctions, ULONG cExportedNames,
    ULONG ulOrdinalBase, PVOID *pExportNameList,
    PUSHORT pExportOrdinals, PVOID *pExportAddrs, PHLIST phList);

Добавляет таблицу экспорта в список экспортируемых таблиц. Использует соглашения о вызовах принятые в С.

Возвращет PELDR_ERR_NOERROR, при удачном вызове , в противном случае возвращает PELDR_ERR_MEM_NOMEMORY, что говорит о недостаточном кол-ве памяти для выполнения запроса.

phExportTable - адрес HPEEXPORTTABLE по которому находиться указатель на таблицу экспорта в случае успешного завершения ф-ции.

pszModuleName - адрес завершающейся нулем строки, содержащей имя модуля. например "VXDLDR.VXD"

cExportedFunctions - кол-во экспортируемых функций

cExportedNames - кол-во экспортируемых имен

ulOrdinalBase - значение базы для таблицы ординалов

pExportNameList - адрес массива указателей на завершающиеся нулем строки. этот список содержит экспортируемые имена модуля.

pExportOrdinals - адрес массива ординал. этот массив должен соответствовать один к одному со списком экспортируемых имен.

pExportAddrs - адрес массива экспортируемых адресов. Этот массив используется при разрешении адресов импорта. Ординал представляет собой индекс в этом массиве.

phList - адрес на хэндл списка экспортируемых таблиц. Этот параметр установлен когда клиент ограничивает список таблиц экспорта. Если значение NULL используется глобальный список таблиц экспорта. Если хэндл на который указывает phList равен NULL, создается новый локальный список таблиц экспорта.


Указатели и данные на которые ссылаются с помощью pszModuleName, pExportNameList, pExportOrdinals, pExportAddrs, или phList должны оставаться действительными до тех пока таблица экспорта  не будет удалена с использованием _PELDR_RemoveExportTable.

У меня проблема такая, исходник очен сложный для моего понимания. даже учитывая. что в книге дана пояснения на русском языке.
А сделать я хотел вот что: для упрощения задачи сделать шаблон в который будут вставлятся куски кода выдранные из XP. На один драйвер одна функция. Есть штук пять файлов которые также экспортируют по 1 - 3 символических имени но на них нет исходников и еще непонятно будет ли всетаки система видеть эти символические имена.
загрузку предпологаю сделать также как сделано сдесь, изменяя название файла в соответствии с названием функции:
Код:
;
; myDrv.inf - информационный файл для установки драйвера myDrv.sys
;

[Version]
Signature="$WINDOWS NT$"
DriverVer=14/07/2002,1.00.0000
Class=ABCDHardware
ClassGuid={68BFDE59-4096-11d5-B627-F0E02944B7B4}
Provider=%PROVIDER%

[DestinationDirs]
DefaultDestDir = 10,system32\drivers ;%SystemRoot%\system32\drivers

[ClassInstall32]
Addreg=ABCDHWClassReg

[ABCDHWClassReg]
HKR,,,0,"Ассемблерные драйверы"
HKR,,Icon,,-5

[Manufacturer]
%PROVIDER%=PROVIDER

[SourceDisksNames]
1="",,

[SourceDiskFiles]
myDrv.sys=1

[myDrv_CopyFiles]
myDrv.sys

[PROVIDER]
%PLMKDEVICE%=myDrv_Install

[myDrv_Install]
CopyFiles = myDrv_CopyFiles
AddReg = myDrv_AddReg

[myDrv_Install.NT]
CopyFiles = myDrv_CopyFiles

[myDrv_Install.NT.Services]
AddService = myDrv,0x00000002,myDrv_Install_services

[myDrv_Install.nt.FactDef]

[myDrv_Install_services]
DisplayName    = "myDrvservice"
ServiceType    = 1 ;    SERVICE_KERNEL_DRIVER
StartType      = 3 ;    SERVICE_DEMAND_START
ErrorControl   = 1 ;    SERVICE_ERROR_NORMAL
ServiceBinary  = %10%\system32\drivers\myDrv.sys
LoadOrderGroup = "Extended Base"

[myDrv_AddReg]
HKR,,DevLoader,,"*ntkern"
HKR,,NTMPDriver,,"myDrv.sys"

[myDrv_Install.FactDef]

[Strings]
PROVIDER="Спасибо Юрику"
PLMKDEVICE="Драйвер "

Тут сразу вопрос не будет ли конфликтов при загруске? Ставил 3 разных драйвера вроде конфликтов небыло.
Ну и главный вопрос может делал кто чтото подобное?


 





Записан
dE fENDER
Интересующийся

us
Offline Offline

« Ответ #1 : 11-09-2012 08:58 » 

Цитата
У меня проблема такая, исходник очен сложный для моего понимания. даже учитывая. что в книге дана пояснения на русском языке.
Что-то конкретно не ясно?

Цитата
непонятно будет ли всетаки система видеть эти символические имена
Напишите тест и проверьте.

Цитата
Тут сразу вопрос не будет ли конфликтов при загруске?
Если делать так, как у Они - не будет. Он проверяет, не существует ли уже такая функция в таблице, этот момент выделен жирным в описании.

Пара советов - выдергивайте из checked билда ОС, смотрите исходники ReactOS/Win2000, попробуйте использовать hex-reys, вылизывайте обработанный код, а не вставляйте то, что выдернулось на автомате. Ну и не дергайте все подряд, только то, что нужно для конкретного драйвера.
Записан
inf158704
Участник

ru
Offline Offline

« Ответ #2 : 11-09-2012 11:10 » 

dE fENDER,  спасибо что откликнулись
Цитата
Что-то конкретно не ясно?
По книжке все выглядит красиво. Но вот исходник уж очень отличаеться.
Цитата
Напишите тест и проверьте.
Насчет теста хотелось бы поподробнее узнать что можно взять за основу?
Я считаю что можно обойтись без проверки для начала, можно будет и ручками выбрать те функции которые нужно подрузить, wdmcheck покажет чего нехватает, и лепить несколько функий в одну тяжеловато... я одну то пока вставить немогу...
А чем вам ненравиться код который я выдрал из XP? вроде глобальные переменные не используеться или я чтото пропустил?




Добавлено через 26 минут и 47 секунд:
INITCODE  оставлю без  изменений так чтоли? хотя здесь вообще понять немогу ничего...

Код:
#pragma INITCODE

#pragma warning(disable:4035)

BOOLEAN Test_Debug_Installed()
{
VMMCall(Test_Debug_Installed)
_asm setnz al
}

#pragma warning(default:4035)

extern "C" ULONG _fltused = 0;

// Flags in CR0:

#define CR0_PG  0x80000000          // paging
#define CR0_ET  0x00000010          // extension type (80387)
#define CR0_TS  0x00000008          // task switched
#define CR0_EM  0x00000004          // emulate math coprocessor
#define CR0_MP  0x00000002          // math present
#define CR0_PE  0x00000001          // protection enable
#define CR0_CD  0x40000000          // cache disable
#define CR0_NW  0x20000000          // not write-through
#define CR0_AM  0x00040000          // alignment mask
#define CR0_WP  0x00010000          // write protect
#define CR0_NE  0x00000020          // numeric error

BOOL CheckPrecisionErrata()
{ // CheckPrecisionErrata
static double Dividend = 4195835.0;
static double Divisor = 3145727.0;
BOOL result = FALSE;

_asm
{
pushfd ; save flags
cli
mov eax, cr0 ; make sure flags are the way we need them
mov ecx, eax
and eax, not (CR0_TS or CR0_MP or CR0_EM)
mov cr0, eax

fninit ; initialize coprocessor
fld Dividend ; perform division to show up precision errata
fdiv Divisor
fmul Divisor
fcomp Dividend
fstsw ax ; capture floating point status
sahf

jc  noproblem
jz  noproblem
mov result, 1

noproblem:
mov cr0, ecx ; restore CR0
popfd ; restore flags (including enable state)
}

return result;
} // CheckPrecisionErrata

BOOLEAN DefineStubs()
{ // DefineStubs

// Construct the name, ordinal, and address tables for functions we're going
// to stub. In various releases of Windows 98 and Millenium, some or all of
// these functions will be supported by the operating system, and we don't
// want to preempt the standard implementation.

stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need
if (!stubnames)
return FALSE;

stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT);
if (!stubaddresses)
{
_HeapFree(stubnames, 0);
return FALSE;
}

ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT);
if (!ordinals)
{
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
}

int i, istub;
for (i = 0, istub = 0; i < arraysize(names); ++i)
{ // for each possible stub
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0)
{ // stub this function
KdPrint((DRIVERNAME " - Stubbing %s\n", names[i]));
stubnames[istub] = names[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = addresses[i];
++istub;
} // stub this function
else
KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i]));
} // for each possible stub

// We have a special problem with the remove lock functions, in that Win98SE leaves out
// just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.

if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, "IoReleaseRemoveLockAndWaitEx", NULL) == 0)
{ // stub remove lock functions
KdPrint((DRIVERNAME " - Stubbing all remove lock functions\n"));
for (i = 0; i < arraysize(remlocknames); ++i)
{ // for each remove lock function
stubnames[istub] = remlocknames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = remlockaddresses[i];
++istub;
} // for each remove lock function
} // stub remove lock functions
else
KdPrint((DRIVERNAME " - Not stubbing remove lock functions\n"));

// Always replace the critical region functions to avoid having the IRQL raised

for (i = 0; i < arraysize(critnames); ++i)
{ // for each critical region function
KdPrint((DRIVERNAME " - Stubbing %s\n", critnames[i]));
stubnames[istub] = critnames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = critaddresses[i];
++istub;
} // for each critical region function

// Create an export table to provide for these functions

if (_PELDR_AddExportTable(&hExportTable, ntoskrnl, istub,
istub, 0, (PVOID*) stubnames, ordinals, stubaddresses, NULL) != 0)
{ // can't define exports
KdPrint((DRIVERNAME " - Unable to define export table\n"));
UndefineStubs();
return FALSE;
} // can't define exports

// See if debugger running

bKdDebuggerEnabled = Test_Debug_Installed();

// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]

VMMHKEY hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0)
{ // get value
char value[64];
DWORD size = sizeof(value);
if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0)
{ // parse value
char* p = value;
cvtnum(p); // major version number
if (*p == '.')
++p;
cvtnum(p); // minor version number
if (*p == '.')
++p;
buildnum = cvtnum(p); // build number
} // parse value
_RegCloseKey(hkey);
} // get value

// In win98 gold, define the WMILIB functions

if (buildnum < 2222)
{ // define wmilib exports
if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames),
arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n"));
} // define wmilib exports

// Determine CPU feature flags

DWORD machineinfo;
#undef Get_Machine_Info
VMMCall(Get_Machine_Info)
_asm mov machineinfo, ebx ; capture machine type flags
if (machineinfo & GMIF_CPUID)
{ // cpuid supported
_asm mov eax, 1 ; EAX = 1 => request for feature flags
_asm cpuid
_asm mov features, edx ; save feature flags
} // cpuid supported

if (features & FEATURE_FPU)
PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();

// Determine the default locale for ZwQueryDefaultLocale

locale = GetSystemLocale();

return TRUE;
} // DefineStubs

а вот для таблицы нашел только это:

Код:
static char* names[] = {
"PoRegisterSystemState",
};


static PFN addresses[] = {
(PFN) PoRegisterSystemState,
};
а вот как организуеться  (по книжке)
Код:
static WORD ordinals[] = {
0,
};
в исходнике немогу никак


На всякий случай иходник оригинального драйвера:
Код:
// WDMSTUB.CPP -- Stubs for missing Win2K WDM service functions
// Copyright (C) 1998 by Walter Oney
// All rights reserved

#include "stddcls.h"
#include "driver.h"
#include "NonStubs.h"

#define IFSMGR_SERVICES_ONLY
#include "ifsmgr.h"

CCHAR cKeNumberProcessors = 1;
BOOLEAN bKdDebuggerEnabled = 0;

BOOLEAN PrecisionErrata = FALSE;
DWORD features = 0;

// Pentium feature flags returned in EDX from CPUID with EAX == 1

#define FEATURE_FPU 0x00000001 // FPU on chip
#define FEATURE_RDTSC 0x00000010 // RDTSC instruction supported
#define FEATURE_MACHINE_CHECK 0x00000080 // machine check exception can occur
#define FEATURE_CMPXCHG8B 0x00000100 // CMPXCHG8B instruction supported
#define FEATURE_MMX 0x00800000 // MMX instructions supported
#define FEATURE_XMMI 0x02000000

#define BCS_WANSI 0 // ifs.h generates too many compile errors if we include it

extern "C" NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING name, ULONG unknown1,
    ULONG unknown2, ULONG unknown3, POBJECT_TYPE type,
    KPROCESSOR_MODE mode, ULONG unknown4, PVOID *object);
extern "C" POBJECT_TYPE* IoDriverObjectType;

///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

// Names of functions stubbed by this VxD. This isn't the array we actually pass
// to PELDR -- it's the array we use when we construct a list of functions
// that aren't already implemented by NTKERN. The names must be in resident storage
// because we don't copy them when we build the export table.

static char* names[] = {
"PoRegisterSystemState",
"PoSetSystemState",
"PoUnregisterSystemState",
"IoReportTargetDeviceChangeAsynchronous",
"ExSystemTimeToLocalTime",
"ExLocalTimeToSystemTime",
"IoCreateNotificationEvent",
"IoCreateSynchronizationEvent",
"IoAllocateWorkItem",
"IoFreeWorkItem",
"IoQueueWorkItem",
"PsGetVersion",
"RtlUshortByteSwap",
"RtlUlongByteSwap",
"RtlUlonglongByteSwap",
"RtlInt64ToUnicodeString",
"KeSetTargetProcessorDpc",
"KeNumberProcessors",
"KdDebuggerEnabled",
"IoReuseIrp",
"IoRaiseInformationalHardError",
"HalTranslateBusAddress",
"ExIsProcessorFeaturePresent",
"MmGetSystemRoutineAddress",
"ZwQueryInformationFile",
"ZwSetInformationFile",
"ZwQueryDefaultLocale",
"ExFreePoolWithTag",
"ZwLoadDriver",
"ZwUnloadDriver",
"SeSinglePrivilegeCheck",
"IoSetCompletionRoutineEx",
};

// As of SP-9, we're using C11 with the Xp options. String constants therefore end
// up in the referencing code segment, but we need to have *this* constant persist:

static char* ntoskrnl = "ntoskrnl.exe";

static char* remlocknames[] = {
"IoAcquireRemoveLockEx",
"IoReleaseRemoveLockEx",
"IoReleaseRemoveLockAndWaitEx",
"IoInitializeRemoveLockEx",
};

// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to
// APC_LEVEL, so we'll stub it no matter what

static char* critnames[] = {
"KeEnterCriticalRegion",
"KeLeaveCriticalRegion",
};

// Macros added in Xp DDK:

#undef RtlUshortByteSwap
#undef RtlUlongByteSwap
#undef RtlUlonglongByteSwap

USHORT
FASTCALL
RtlUshortByteSwap(
    IN USHORT Source
    );

ULONG
FASTCALL
RtlUlongByteSwap(
    IN ULONG Source
    );

ULONGLONG
FASTCALL
RtlUlonglongByteSwap(
    IN ULONGLONG Source
    );

NTSTATUS ZwLoadDriver(PUNICODE_STRING);
NTSTATUS ZwUnloadDriver(PUNICODE_STRING);

#pragma warning(disable:4273) // inconsistent dll linkage

// Addresses of stub functions (must line up with names array)

NTSTATUS ZwQueryDefaultLocale(BOOLEAN thread, LCID* plocale);

static PFN addresses[] = {
(PFN) PoRegisterSystemState,
(PFN) PoSetSystemState,
(PFN) PoUnregisterSystemState,
(PFN) IoReportTargetDeviceChangeAsynchronous,
(PFN) ExSystemTimeToLocalTime,
(PFN) ExLocalTimeToSystemTime,
(PFN) IoCreateNotificationEvent,
(PFN) IoCreateSynchronizationEvent,
(PFN) IoAllocateWorkItem,
(PFN) IoFreeWorkItem,
(PFN) IoQueueWorkItem,
(PFN) PsGetVersion,
(PFN) RtlUshortByteSwap,
(PFN) RtlUlongByteSwap,
(PFN) RtlUlonglongByteSwap,
(PFN) RtlInt64ToUnicodeString,
(PFN) KeSetTargetProcessorDpc,
(PFN) &cKeNumberProcessors,
(PFN) &bKdDebuggerEnabled,
(PFN) IoReuseIrp,
(PFN) IoRaiseInformationalHardError,
(PFN) HalTranslateBusAddress,
(PFN) ExIsProcessorFeaturePresent,
(PFN) MmGetSystemRoutineAddress,
(PFN) ZwQueryInformationFile,
(PFN) ZwSetInformationFile,
(PFN) ZwQueryDefaultLocale,
(PFN) ExFreePoolWithTag,
(PFN) ZwLoadDriver,
(PFN) ZwUnloadDriver,
(PFN) SeSinglePrivilegeCheck,
(PFN) IoSetCompletionRoutineEx,
};

static PFN remlockaddresses[] = {
(PFN) IoAcquireRemoveLockEx,
(PFN) IoReleaseRemoveLockEx,
(PFN) IoReleaseRemoveLockAndWaitEx,
(PFN) IoInitializeRemoveLockEx,
};

static PFN critaddresses[] = {
(PFN) KeEnterCriticalRegion,
(PFN) KeLeaveCriticalRegion,
};

// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken
// due to user-mode bugs.

static char *wmilib = "wmilib.sys";

static char* wminames[] = {
"WmiSystemControl",
"WmiCompleteRequest",
};

static WORD wmiordinals[] = {
0,
1,
};

static PFN wmiaddresses[] = {
(PFN) WmiSystemControl,
(PFN) WmiCompleteRequest,
};

__int64 GetZoneBias();
DWORD buildnum;

HPEEXPORTTABLE hExportTable = 0;
char** stubnames; // names of functions we stubbed
PFN* stubaddresses; // addresses of the stub functions
WORD* ordinals; // ordinal table to correlate the other two tables

HPEEXPORTTABLE hWmilibExportTable = 0;

LCID locale; // default locale
LCID GetSystemLocale();
DWORD atox(char* s);
int cvtnum(char*& p);

NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT fdo, PIRP Irp, PCOMPLETION_CONTEXT ctx);

///////////////////////////////////////////////////////////////////////////////

#pragma warning(disable:4035)

UINT __declspec(naked) __cdecl UniToBCS(PBYTE pBCSPath, WCHAR* pUniPath, UINT length, UINT maxLength, UINT charSet)
{
VxDJmp(UniToBCS)
}

#pragma warning(default:4035)

///////////////////////////////////////////////////////////////////////////////

#pragma INITCODE

#pragma warning(disable:4035)

BOOLEAN Test_Debug_Installed()
{
VMMCall(Test_Debug_Installed)
_asm setnz al
}

#pragma warning(default:4035)

extern "C" ULONG _fltused = 0;

// Flags in CR0:

#define CR0_PG  0x80000000          // paging
#define CR0_ET  0x00000010          // extension type (80387)
#define CR0_TS  0x00000008          // task switched
#define CR0_EM  0x00000004          // emulate math coprocessor
#define CR0_MP  0x00000002          // math present
#define CR0_PE  0x00000001          // protection enable
#define CR0_CD  0x40000000          // cache disable
#define CR0_NW  0x20000000          // not write-through
#define CR0_AM  0x00040000          // alignment mask
#define CR0_WP  0x00010000          // write protect
#define CR0_NE  0x00000020          // numeric error

BOOL CheckPrecisionErrata()
{ // CheckPrecisionErrata
static double Dividend = 4195835.0;
static double Divisor = 3145727.0;
BOOL result = FALSE;

_asm
{
pushfd ; save flags
cli
mov eax, cr0 ; make sure flags are the way we need them
mov ecx, eax
and eax, not (CR0_TS or CR0_MP or CR0_EM)
mov cr0, eax

fninit ; initialize coprocessor
fld Dividend ; perform division to show up precision errata
fdiv Divisor
fmul Divisor
fcomp Dividend
fstsw ax ; capture floating point status
sahf

jc  noproblem
jz  noproblem
mov result, 1

noproblem:
mov cr0, ecx ; restore CR0
popfd ; restore flags (including enable state)
}

return result;
} // CheckPrecisionErrata

BOOLEAN DefineStubs()
{ // DefineStubs

// Construct the name, ordinal, and address tables for functions we're going
// to stub. In various releases of Windows 98 and Millenium, some or all of
// these functions will be supported by the operating system, and we don't
// want to preempt the standard implementation.

stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need
if (!stubnames)
return FALSE;

stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT);
if (!stubaddresses)
{
_HeapFree(stubnames, 0);
return FALSE;
}

ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT);
if (!ordinals)
{
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
}

int i, istub;
for (i = 0, istub = 0; i < arraysize(names); ++i)
{ // for each possible stub
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0)
{ // stub this function
KdPrint((DRIVERNAME " - Stubbing %s\n", names[i]));
stubnames[istub] = names[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = addresses[i];
++istub;
} // stub this function
else
KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i]));
} // for each possible stub

// We have a special problem with the remove lock functions, in that Win98SE leaves out
// just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.

if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, "IoReleaseRemoveLockAndWaitEx", NULL) == 0)
{ // stub remove lock functions
KdPrint((DRIVERNAME " - Stubbing all remove lock functions\n"));
for (i = 0; i < arraysize(remlocknames); ++i)
{ // for each remove lock function
stubnames[istub] = remlocknames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = remlockaddresses[i];
++istub;
} // for each remove lock function
} // stub remove lock functions
else
KdPrint((DRIVERNAME " - Not stubbing remove lock functions\n"));

// Always replace the critical region functions to avoid having the IRQL raised

for (i = 0; i < arraysize(critnames); ++i)
{ // for each critical region function
KdPrint((DRIVERNAME " - Stubbing %s\n", critnames[i]));
stubnames[istub] = critnames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = critaddresses[i];
++istub;
} // for each critical region function

// Create an export table to provide for these functions

if (_PELDR_AddExportTable(&hExportTable, ntoskrnl, istub,
istub, 0, (PVOID*) stubnames, ordinals, stubaddresses, NULL) != 0)
{ // can't define exports
KdPrint((DRIVERNAME " - Unable to define export table\n"));
UndefineStubs();
return FALSE;
} // can't define exports

// See if debugger running

bKdDebuggerEnabled = Test_Debug_Installed();

// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]

VMMHKEY hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0)
{ // get value
char value[64];
DWORD size = sizeof(value);
if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0)
{ // parse value
char* p = value;
cvtnum(p); // major version number
if (*p == '.')
++p;
cvtnum(p); // minor version number
if (*p == '.')
++p;
buildnum = cvtnum(p); // build number
} // parse value
_RegCloseKey(hkey);
} // get value

// In win98 gold, define the WMILIB functions

if (buildnum < 2222)
{ // define wmilib exports
if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames),
arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n"));
} // define wmilib exports

// Determine CPU feature flags

DWORD machineinfo;
#undef Get_Machine_Info
VMMCall(Get_Machine_Info)
_asm mov machineinfo, ebx ; capture machine type flags
if (machineinfo & GMIF_CPUID)
{ // cpuid supported
_asm mov eax, 1 ; EAX = 1 => request for feature flags
_asm cpuid
_asm mov features, edx ; save feature flags
} // cpuid supported

if (features & FEATURE_FPU)
PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();

// Determine the default locale for ZwQueryDefaultLocale

locale = GetSystemLocale();

return TRUE;
} // DefineStubs

///////////////////////////////////////////////////////////////////////////////

#pragma PAGEDCODE

VOID UndefineStubs()
{ // UndefineStubs
if (hExportTable)
_PELDR_RemoveExportTable(hExportTable, NULL);
if (ordinals)
_HeapFree(ordinals, 0);
if (stubaddresses)
_HeapFree(stubaddresses, 0);
if (stubnames)
_HeapFree(stubnames, 0);

hExportTable = NULL;
ordinals = NULL;
stubaddresses = NULL;
stubnames = NULL;

if (hWmilibExportTable)
_PELDR_RemoveExportTable(hWmilibExportTable, NULL);
hWmilibExportTable = NULL;
} // UndefineStubs

///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

PVOID PoRegisterSystemState(PVOID hstate, ULONG flags)
{ // PoRegisterSystemState
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return NULL;
} // PoRegisterSystemState

VOID PoSetSystemState(ULONG flags)
{ // PoSetSystemState
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
} // PoSetSystemState

VOID PoUnregisterSystemState(PVOID hstate)
{ // PoUnregisterSystemState
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
} // PoUnregisterSystemState

NTSTATUS IoReportTargetDeviceChangeAsynchronous(PDEVICE_OBJECT pdo, PVOID NfyStruct, PDEVICE_CHANGE_COMPLETE_CALLBACK Callback, PVOID Context)
{ // IoReportTargetDeviceChangeAsynchronous
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
return STATUS_NOT_IMPLEMENTED;
} // IoReportTargetDeviceChangeAsynchronous

VOID ExSystemTimeToLocalTime(PLARGE_INTEGER systime, PLARGE_INTEGER localtime)
{ // ExSystemTimeToLocalTime
localtime->QuadPart = systime->QuadPart - GetZoneBias();
} // ExSystemTimeToLocalTime

VOID ExLocalTimeToSystemTime(PLARGE_INTEGER localtime, PLARGE_INTEGER systime)
{ // ExLocalTimeToSystemTime
systime->QuadPart = localtime->QuadPart + GetZoneBias();
} // ExLocalTimeToSystemTime

PKEVENT IoCreateNotificationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle)
{ // IoCreateNotificationEvent
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
return NULL;
} // IoCreateNotificationEvent

PKEVENT IoCreateSynchronizationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle)
{ // IoCreateSynchronizationEvent
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
return NULL;
} // IoCreateSynchronizationEvent

PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
{ // IoAllocateWorkItem
return AllocateWorkItem(DeviceObject);
} // IoAllocateWorkItem

VOID IoFreeWorkItem(PIO_WORKITEM item)
{ // IoFreeWorkItem
FreeWorkItem(item);
} // IoFreeWorkItem

VOID IoQueueWorkItem(PIO_WORKITEM item, PIO_WORKITEM_ROUTINE Routine, WORK_QUEUE_TYPE QueueType, PVOID Context)
{ // IoQueueWorkItem
QueueWorkItem(item, Routine, QueueType, Context);
} // IoQueueWorkItem

BOOLEAN PsGetVersion(PULONG MajorVersion, PULONG MinorVersion, PULONG BuildNumber, PUNICODE_STRING spnum)
{ // PsGetVersion
#undef Get_VMM_Version
USHORT version;
ULONG dbgver;
VMMCall(Get_VMM_Version);
_asm mov version, ax
_asm mov dbgver, ecx

if (MajorVersion)
*MajorVersion = version >> 8;
if (MinorVersion)
*MinorVersion = version & 255;
if (BuildNumber)
*BuildNumber = buildnum;
if (spnum)
spnum->Length = 0;

return dbgver != 0;
} // PsGetVersion

NTSTATUS IoAcquireRemoveLockEx(PIO_REMOVE_LOCK p, PVOID tag, PCSTR file, ULONG line, ULONG size)
{ // IoAcquireRemoveLockEx
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
return AcquireRemoveLock(p, tag, file, line, size);
} // IoAcquireRemoveLockEx

VOID IoReleaseRemoveLockEx(PIO_REMOVE_LOCK p, PVOID tag, ULONG size)
{ // IoReleaseRemoveLockEx
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ReleaseRemoveLock(p, tag, size);
} // IoReleaseRemoveLockEx

VOID IoReleaseRemoveLockAndWaitEx(PIO_REMOVE_LOCK p, PVOID tag, ULONG size)
{ // IoReleaseRemoveLockAndWaitEx
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ReleaseRemoveLockAndWait(p, tag, size);
} // IoReleaseRemoveLockAndWaitEx

VOID IoInitializeRemoveLockEx(PIO_REMOVE_LOCK p, ULONG tag, ULONG maxminutes, ULONG hwm, ULONG size)
{ // IoInitializeRemoveLockEx
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
InitializeRemoveLock(p, tag, maxminutes, hwm, size);
} // IoInitializeRemoveLockEx

#pragma warning(disable:4035)

USHORT FASTCALL RtlUshortByteSwap(USHORT source)
{ // RtlUshortByteSwap
_asm movzx eax, cx
_asm xchg ah, al
} // RtlUshortByteSwap

ULONG FASTCALL RtlUlongByteSwap(ULONG source)
{ // RtlUlongByteSwap
_asm mov eax, ecx
_asm bswap eax
} // RtlUlongByteSwap

ULONGLONG FASTCALL RtlUlonglongByteSwap(ULONGLONG source)
{ // RtlUlonglongByteSwap
_asm mov eax, ecx
_asm xchg eax, edx
_asm bswap eax
_asm bswap edx
} // RtlUlonglongByteSwap

#pragma warning(default:4035)

NTSTATUS RtlInt64ToUnicodeString(ULONGLONG value, ULONG base, PUNICODE_STRING string)
{ // RtlInt64ToUnicodeString
return STATUS_NOT_IMPLEMENTED;
} // RtlInt64ToUnicodeString

VOID KeEnterCriticalRegion()
{ // KeEnterCriticalRegion
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
} // KeEnterCriticalRegion

VOID KeLeaveCriticalRegion()
{ // KeLeaveCriticalRegion
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
} // KeLeaveCriticalRegion

VOID KeSetTargetProcessorDpc(PRKDPC dpc, CCHAR number)
{ // KeSetTargetProcessorDpc
} // KeSetTargetProcessorDpc

VOID KeSetImportanceDpc(PRKDPC dpc, KDPC_IMPORTANCE importance)
{ // KeSetImportanceDpc
} // KeSetImportanceDpc

VOID IoReuseIrp(PIRP Irp, NTSTATUS status)
{ // IoReuseIrp
ReuseIrp(Irp, status);
} // IoReuseIrp

void __cdecl MessageCallback(char* msg);

BOOLEAN IoRaiseInformationalHardError(NTSTATUS status, PUNICODE_STRING string, PKTHREAD thread)
{ // IoRaiseInformationalHardError
char* msg = (char*) _HeapAllocate(1024, 0);
if (!msg)
return FALSE;
if (string)
{ // convert string data
UINT unilen = string->Length;
UINT ansilen = unilen / 2;
char* ansistring = (char*) _HeapAllocate(ansilen + 1, 0);
if (!ansistring)
{
_HeapFree(msg, 0);
return FALSE;
}

#define BCS_OEM 1
ansistring[UniToBCS((PBYTE) ansistring, string->Buffer, unilen, ansilen, BCS_OEM)] = 0;
_Sprintf(msg, "An operation failed with status %8.8lX. The operation relates to '%s'", status, ansistring);
_HeapFree(ansistring, 0);
} // convert string data
else
_Sprintf(msg, "An operation failed with status %8.8lX", status);

BOOL okay;
okay = _SHELL_CallAtAppyTime((APPY_CALLBACK) MessageCallback, (DWORD) msg, 0) != 0;
if (!okay)
{ // can't queue regular message box
SHELL_SYSMODAL_Message(Get_Sys_VM_Handle(), MB_OK | MB_ICONHAND | MB_SYSTEMMODAL, msg, "Windows - Operation Failed");
_HeapFree(msg, 0);
okay = TRUE;
} // can't queue regular message box

return (BOOLEAN) okay;
} // IoRaiseInformationalHardError

BOOLEAN HalTranslateBusAddress(INTERFACE_TYPE InterfaceType, ULONG BusNumber, PHYSICAL_ADDRESS BusAddress,
PULONG AddressSpace, PPHYSICAL_ADDRESS TranslatedAddress)
{ // HalTranslateBusAddress
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
*TranslatedAddress = BusAddress;
return TRUE;
} // HalTranslateBusAddress

BOOLEAN ExIsProcessorFeaturePresent(ULONG feature)
{ // ExIsProcessorFeaturePresent
BOOLEAN result = FALSE;

switch (feature)
{ // determine if feature present
case PF_FLOATING_POINT_PRECISION_ERRATA:
result = PrecisionErrata;
break;

case PF_FLOATING_POINT_EMULATED:
result = (features & FEATURE_FPU) == 0;
break;

case PF_COMPARE_EXCHANGE_DOUBLE:
result = (features & FEATURE_CMPXCHG8B) != 0;
break;

case PF_MMX_INSTRUCTIONS_AVAILABLE:
result = (features & FEATURE_MMX) != 0;

case PF_PPC_MOVEMEM_64BIT_OK:
case PF_ALPHA_BYTE_INSTRUCTIONS:
break; // non-x86 features

case PF_XMMI_INSTRUCTIONS_AVAILABLE:
result = (features & FEATURE_XMMI) != 0;
break;

case PF_3DNOW_INSTRUCTIONS_AVAILABLE:
break; // assume false until somebody needs it to work...

case PF_RDTSC_INSTRUCTION_AVAILABLE:
result = (features & FEATURE_RDTSC) != 0;
break;

case PF_PAE_ENABLED:
break; // Win98 doesn't run on phys addr extension machines
} // determine if feature present

return result;
} // ExIsProcessorFeaturePresent

PVOID MmGetSystemRoutineAddress(PUNICODE_STRING name)
{ // MmGetSystemRoutineAddress
char ansiname[256];
ansiname[UniToBCS((PBYTE) ansiname, name->Buffer, name->Length, 255, BCS_WANSI)] = 0;
return _PELDR_GetProcAddress((HPEMODULE) ntoskrnl, ansiname, NULL);
} // MmGetSystemRoutineAddress

NTSTATUS ZwQueryInformationFile(HANDLE h, PIO_STATUS_BLOCK pstatus, PVOID fi,
ULONG length, FILE_INFORMATION_CLASS c)
{ // ZwQueryInformationFile
pstatus->Status = STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
} // ZwQueryInformationFile

NTSTATUS ZwSetInformationFile(HANDLE h, PIO_STATUS_BLOCK pstatus, PVOID fi,
ULONG length, FILE_INFORMATION_CLASS c)
{ // ZwSetInformationFile
pstatus->Status = STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
} // ZwSetInformationFile

NTSTATUS ZwQueryDefaultLocale(BOOLEAN thread, LCID* plocale)
{ // ZwQueryDefaultLocale
*plocale = locale;
return STATUS_SUCCESS;
} // ZwQueryDefaultLocale

VOID ExFreePoolWithTag(PVOID p, ULONG tag)
{ // ExFreePoolWithTag
ExFreePool(p);
} // ExFreePoolWithTag

NTSTATUS ZwLoadDriver(PUNICODE_STRING ServiceKey)
{ // ZwLoadDriver
return _NtKernLoadDriver(ServiceKey);
} // ZwLoadDriver

NTSTATUS ZwUnloadDriver(PUNICODE_STRING ServiceKey)
{ // ZwUnloadDriver

// Isolate the service name from the end of the key.
// This will be the name of the driver object

for (int i = ServiceKey->Length / sizeof(WCHAR) - 1; i >= 0; --i)
if (ServiceKey->Buffer[i] == L'\\')
break;
++i; // skip backslash
int lname = ServiceKey->Length / sizeof(WCHAR) - i;

WCHAR objname[128];
wcscpy(objname, L"\\Driver\\");
memcpy(objname + 8, ServiceKey->Buffer + i, 2 * lname);
objname[lname + 8] = 0;
UNICODE_STRING oname;
RtlInitUnicodeString(&oname, objname);

// Find the driver object

PDRIVER_OBJECT DriverObject;
NTSTATUS status = ObReferenceObjectByName(&oname, 0, 0, 0, *IoDriverObjectType, KernelMode, 0, (PVOID*) &DriverObject);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - Can't locate driver object %ws - %X\n", objname, status));
return status;
}
ObDereferenceObject(DriverObject); // remove reference from ObReferenceObjectByName

// Determine the module name by reading the registry key, backscanning
// to the last backslash, and converting to ANSI

OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, ServiceKey, OBJ_KERNEL_HANDLE, NULL, NULL);

HANDLE hkey;
status = ZwOpenKey(&hkey, KEY_READ, &oa);
if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - ZwOpenKey(%ws) failed - %X\n", ServiceKey->Buffer, status));
return status;
}

struct foo : public _KEY_VALUE_PARTIAL_INFORMATION
{
UCHAR buffer[511];
} value;
UNICODE_STRING valname;
ULONG size;
RtlInitUnicodeString(&valname, L"ImagePath");
status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,
&value, sizeof(value), &size);
ZwClose(hkey);

if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - ZwQueryValueKey failed - %X\n", status));
return status;
}

for (i = value.DataLength / sizeof(WCHAR) - 1; i >= 0; --i)
if (((PWCHAR) (value.Data))[i] == L'\\')
break;
++i;
lname = value.DataLength / sizeof(WCHAR) - i;
memcpy(objname, value.Data + i * 2, lname * 2);
objname[lname] = 0;

BYTE modname[64];
modname[UniToBCS(modname, objname, lname * 2, sizeof(modname), BCS_WANSI)] = 0;
HPEMODULE hmod = _PELDR_GetModuleHandle((PSTR) modname);

if (!hmod)
{
KdPrint((DRIVERNAME " - Can't get module handle to %s\n", modname));
return STATUS_UNSUCCESSFUL;
}

// At long last, unload the module and release the extra references to
// the device object

if (DriverObject->DriverUnload)
(*DriverObject->DriverUnload)(DriverObject);
ObDereferenceObject(DriverObject);
ObDereferenceObject(DriverObject);
_PELDR_FreeModule(hmod, NULL);

return STATUS_SUCCESS;
} // ZwUnloadDriver

BOOLEAN SeSinglePrivilegeCheck(LUID PrivilegeValue, KPROCESSOR_MODE PreviousMode)
{ // SeSinglePrivilegeCheck
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
ASSERT(PreviousMode == UserMode || PreviousMode == KernelMode);
return TRUE;
} // SeSinglePrivilegeCheck

NTSTATUS IoSetCompletionRoutineEx(PDEVICE_OBJECT fdo, PIRP Irp, PIO_COMPLETION_ROUTINE CompletionRoutine,
PVOID Context, BOOLEAN success, BOOLEAN failure, BOOLEAN cancel)
{ // IoSetCompletionRoutineEx
ASSERT(fdo);
ASSERT(Irp);
ASSERT(CompletionRoutine);
ASSERT(success || failure || cancel);

PCOMPLETION_CONTEXT ctx = (PCOMPLETION_CONTEXT) _HeapAllocate(sizeof(COMPLETION_CONTEXT), 0);
if (!ctx)
return STATUS_INSUFFICIENT_RESOURCES;
ctx->CompletionRoutine = CompletionRoutine;
ctx->Context = Context;
ctx->fdo = fdo;

IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) CompletionRoutineWrapper, (PVOID) ctx,
success, failure, cancel);

return STATUS_SUCCESS;
} // IoSetCompletionRoutineEx

NTSTATUS WmiSystemControl(PWMILIB_CONTEXT WmiLibInfo, PDEVICE_OBJECT DeviceObject, PIRP Irp, PSYSCTL_IRP_DISPOSITION IrpDisposition)
{ // WmiSystemControl
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
*IrpDisposition = IrpProcessed;
return STATUS_SUCCESS;
} // WmiSystemControl

NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost)
{ // WmiCompleteRequest
ASSERT(FALSE); // shouldn't be called because no callbacks are being called
return STATUS_NOT_SUPPORTED;
} // WmiCompleteRequest

///////////////////////////////////////////////////////////////////////////////

void __cdecl MessageCallback(char* msg)
{ // MessageCallback
#pragma pack(2)
struct { // MessageBox parameters
WORD fuStyle; // style flags
DWORD lpszTitle; // title string
DWORD lpszText; // message text
WORD hwndParent; // parent window handle
} parms; // MessageBox parameters
#pragma pack()

// Construct parameter list for call to MessageBox

parms.fuStyle = MB_OK | MB_ICONHAND;
parms.lpszTitle = _SHELL_LocalAllocEx(LMEM_STRING, 0, "Windows - Operation Failed");
parms.lpszText = _SHELL_LocalAllocEx(LMEM_STRING, 0, msg);
parms.hwndParent = 0;

// Invoke MessageBox to display the message

if (parms.lpszTitle && parms.lpszText)
_SHELL_CallDll("USER", "MESSAGEBOX", sizeof(parms), &parms);

// Cleanup

if (parms.lpszText)
_SHELL_LocalFree(parms.lpszText);
if (parms.lpszTitle)
_SHELL_LocalFree(parms.lpszTitle);
_HeapFree(msg, 0);
} // MessageCallback

///////////////////////////////////////////////////////////////////////////////

__int64 GetZoneBias()
{ // GetZoneBias
DWORD hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_TIMEZONE, &hkey) != 0)
return 0;

__int64 bias;
LONG actbias;
DWORD size = sizeof(actbias);

if (_RegQueryValueEx(hkey, REGSTR_VAL_TZACTBIAS, NULL, NULL, &actbias, &size) == 0)
{ // compute 100-ns bias
actbias *= 60; // minutes to seconds
_asm mov eax, actbias
_asm mov ecx, 10000000 // seconds to 100-ns units
_asm imul ecx
_asm mov dword ptr bias, eax
_asm mov dword ptr bias+4, edx

} // compute 100-ns bias
else
bias = 0;

_RegCloseKey(hkey);
return bias;
} // GetZoneBias

///////////////////////////////////////////////////////////////////////////////

DWORD atox(char* s)
{ // atox
DWORD result = 0;
char ch;
while ((ch = *s++))
{ // convert hex number
BYTE hexit;
if (ch >= '0' && ch <= '9')
hexit = ch - '0';
else if (ch >= 'A' && ch <= 'F')
hexit = ch - ('A' - 10);
else if ( ch >= 'a' && ch <= 'f')
hexit = ch - ('a' - 10);
else
break; // invalid hexit -- ignore

result <<= 4;
result += hexit;
} // convert hex number

return result;
} // atox

///////////////////////////////////////////////////////////////////////////////
// Convert ascii string to number, skipping characters

int cvtnum(char*& p)
{ // cvtnum
int result = 0;
char ch;
while ((ch = *p++) && ch >= '0' && ch <= '9')
{
result *= 10;
result += (ch - '0');
}
return result;
} // cvtnum

///////////////////////////////////////////////////////////////////////////////

LCID GetSystemLocale()
{ // GetSystemLocale
LCID lcid = LOCALE_SYSTEM_DEFAULT; // in case nothing found
#define REGSTR_PATH_LOCALE TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale")

// Query the registry to determine the default locale

DWORD hKey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOCALE, &hKey) != 0)
return lcid;

char szLocale[9];
DWORD size = sizeof(szLocale);
DWORD type;

if (_RegQueryValueEx(hKey, NULL, NULL, &type, (PBYTE) szLocale, &size) == 0 && type == REG_SZ)
lcid = atox(szLocale);

_RegCloseKey(hKey);
return lcid;
} // GetSystemLocale

///////////////////////////////////////////////////////////////////////////////

#pragma warning(disable:4035)

LONG __stdcall Get_System_Time()
{ // Get_System_Time
VMMCall(Get_System_Time)
} // Get_System_Time

#pragma warning(default:4035)

///////////////////////////////////////////////////////////////////////////////

NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT junk, PIRP Irp, PCOMPLETION_CONTEXT ctx)
{ // CompletionRoutineWrapper
ObReferenceObject(ctx->fdo);
NTSTATUS status = (*ctx->CompletionRoutine)(junk, Irp, ctx->Context);
ObDereferenceObject(ctx->fdo);
_HeapFree((PVOID) ctx, 0);
return status;
} // CompletionRoutineWrapper



« Последнее редактирование: 11-09-2012 11:37 от inf158704 » Записан
dE fENDER
Интересующийся

us
Offline Offline

« Ответ #3 : 11-09-2012 23:12 » 

Исходник потом прокомментирую поподробней, сейчас нет времени.

Тест - простейший драйвер, в котором вызываете функцию (для начала одну), которой нет в 98. Там будет с десяток строк, думаю. Смотрите, что с ним происходит под ХР и под 98. Под ХР оно должно отработать, под 98, соответственно, загрузить драйвер не получится - посмотрите, как именно это происходит, хотя вы наверно уже видели.

Как профессиональный программист, вы не должны пытаться обойтись без теста, а наоборот, стремиться начинать решение любой задачи с того, что пишете тесты, которые фейлятся. А затем добиваетесь, чтобы все они успешно проходили. Почитайте про test-driven development. Считайте это не просто еще одним из методов разработки, а единственным. Конечно есть множество задач, где написание тестов, корректно и полностью проверяющих правильность решения займет больше времени чем нахождение правильного решения или вообще невозможно. Но даже в таком случае лучше написать пару тестов, которые проверяют, что приложение хотя бы не заваливается. А данная задача просто предназначена для для такого подхода.

Хочу подчеркнуть - без данного теста или проверки на другом драйвере (например, упомянутом вами  D-link DWA-140 или что еще имеется под рукой) - т.е. без какого-то критерия правильности получается, что вы занимаетесь не решением задачи и не даже не изучением каких-то механизмов или приемов, а вообще непонятно чем.

Код, который вы выдрали, мне не нравится тем, что вы вряд ли понимаете, что там происходит (это с оглядкой на то, что у вас возникли проблемы прочесть Сишный исходник), хотя может я ошибаюсь и вы с лету читаете ассемблер и видите неочевидные зависимости в коде. А сам код выдернутой функции я не даже не смотрел.

Как я понимаю, вы занимаетесь этим для себя, у вас нет какого-то жесткого дедлайна  и имеется достаточно большое количество времени для изучения. Ну так этим надо пользоваться чтобы во всем подробно и основательно разобраться. Более того, на собственном опыте неоднократно наблюдал, что когда ставятся жесткие и нереалистичные временные рамки и всякие далекие от процесса разработки менеджеры и начальники пытаются заставить исполнителей побыстрей лепить все из кусков левого кода, не давая им времени на изучение этого самого кода - рамки в итоге всегда срываются а полученный код не только не решает хоть какой-либо процент поставленной задачи, но и непригоден для дальнейшей доработки.

По поводу данного ИДОвского ассемблера могу перечислить такого рода аргументы - лучше переносимый и читаемый код на ЯВУ, чем платформеннозависимый на ассемблере, ассемблер тяжело читать "по диагонали", не факт, что после дизассемблирования и перекомпиляции вы получите тот же самый  машинный код, что был в оригинале...; дальше просто лень перечислять.

Как заполняются ординалы в приведенном вами исходнике:

Код:
int i, istub; // объявляем переменную istub для подсчета текущего кода ординала
for (i = 0, istub = 0; i < arraysize(names); ++i)// здесь она зануляется. Обратите внимание, что она и в других циклах используется и там уже не зануляется
{
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0)
{
...
ordinals[istub] = (WORD) istub; // Здесь в массив ординалов кидаем ее значения: [0, x, x, x, ], [0, 1, x, x, ], [0, 1, 2, x, ], [0, 1, 2, 3, ], ...
...
++istub; // А здесь она увеличивается
}
...
}

Настройте виртуалку и ядерный отладчик; пройдите интересующие участки по шагам - многие вопросы исчезнут. Это может быть долго и тяжело, но это надо обязательно сделать в первую очередь.
Записан
inf158704
Участник

ru
Offline Offline

« Ответ #4 : 19-12-2012 12:30 » 

к сожалению у меня никаких успехов...
понял одно что используеться несеолько массисов
static PFN addresses[] = {
static PFN remlockaddresses[] = {
static PFN critaddresses[] = {
поэтому так услажнена INITCODE с ее  проверками

for (i = 0, istub = 0; i < arraysize(names); ++i)
...
for (i = 0; i < arraysize(critnames); ++i)
...

зачем надо было городить это все непонятно ...
в старом драйвере на vxd который никаких таких заморочек невижу... только вот беда компильнуть у меня неполучаеться его...
может ктото сможет подсказать в чем дело?
исходники на него нашел здесь:
http://web.archive.org/web/19991002220610/http://www.oneysoft.com/WdmStub.zip
Записан
sss
Специалист

ru
Offline Offline

« Ответ #5 : 19-12-2012 13:49 » 

inf158704, Вы не понимаете? Просто невозможно помочь в таком "широком" диапазоне узкого вопроса. Может быть другие идеи ? Я в общем не верю,
что дело заключается только в NdisInitializeString (версии NDIS сходятся ?). Ну замените её запросто на RtlInitString.. Там тоже самое..

Записан

while (8==8)
inf158704
Участник

ru
Offline Offline

« Ответ #6 : 19-12-2012 14:53 » 

на даный момент у меня задача простая обрезать WdmStub в самый минимум оставить внедрение в ядро только одной вообще любой функции...
проблема возникла на уровне обрезания INIT
есть версия этого драйвера в виде SYS файла и более старая VXD
VXD версия более понятная, беда только в том что я ее немогу скомпилировать...
почему незнаю... ntddk.h втюхивал и от ХР и от NT
компилил в си 6, компиляторы подменял из DDK 2600 пути прописывал как смог...
если кто может просто прошу компильнуть у себя на нормально настроенном...
без ддк98 гдето прочитал что VXD не компилиться
Записан
inf158704
Участник

ru
Offline Offline

« Ответ #7 : 19-12-2012 15:00 » 

inf158704, Ну замените её запросто на RtlInitString.. Там тоже самое..
где заменить?
в драйвере на DLINK? у меня исходников нет...
HIEWом подменить в таблице импорта? чет на сказку похоже...


Записан
sss
Специалист

ru
Offline Offline

« Ответ #8 : 20-12-2012 02:31 » 

где заменить?

Не в таблице импорта, а везде в коде вызов.. В таблице импорта "заглушите" NdisInitializeString чем нибудь другим,
а в коде, где вызовы поставьте константу на RtlInitString из Вашей win98. Если всё дело только в одной функции,
то я бы точно не стал бы мудрить с универсальным стабом. Вообще бы написал соседний драйвер, эмулятор нужной
функции и заменил вызовы на него - только для тестов, далее конечно можно было бы и потрудиться над
затачиванием проекта на более универсальные цели.

HIEWом подменить в таблице импорта? чет на сказку похоже...

Не понимаю - технику инжекта DLL кто то отменил что ли? Ваш проект тоже не очень реален..
« Последнее редактирование: 20-12-2012 02:35 от sss » Записан

while (8==8)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 20-12-2012 03:49 » 

inf158704, направить бы твою энергию в нужное русло ))
Записан

inf158704
Участник

ru
Offline Offline

« Ответ #10 : 20-12-2012 04:13 » 

я отдыхаю и пытаюсь растопить толстый слой жира на мозжечке...  в WOT играть надоела а ремонт дома уже прекратил

Добавлено через 19 минут и 23 секунды:
где заменить?

Не в таблице импорта, а везде в коде вызов.. В таблице импорта "заглушите" NdisInitializeString чем нибудь другим,
а в коде, где вызовы поставьте константу на RtlInitString из Вашей win98. Если всё дело только в одной функции,
то я бы точно не стал бы мудрить с универсальным стабом. Вообще бы написал соседний драйвер, эмулятор нужной
функции и заменил вызовы на него - только для тестов, далее конечно можно было бы и потрудиться над
затачиванием проекта на более универсальные цели.

HIEWом подменить в таблице импорта? чет на сказку похоже...

Не понимаю - технику инжекта DLL кто то отменил что ли? Ваш проект тоже не очень реален..

чесно признаюсь непонял что вы имеете в виду...
готовый SYS файл я немогу коректировать, можно заглушить функцию понятно в таблице импорта, хотя тут тоже есть вопрос, может ли быть в таблице 2 функции с одинаковым названием?
но главное непонимаю как сделать вызов DLL из тела...
допустим в асемблера ето выглядит приблиззително так другая функция но неважно:
push   eax
push   0
call   ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
test   eax, eax
mov   [esi+4], eax
pop   esi
а вот где вызвать можно здесь ДЛЛ вообще непредставляю каким образом
еслибы это был DOS я б как вирус к концу файла прицепился и переправил CALL но некатит...

скорее всего я  просто незнаю и непонимаю...

Добавлено через 36 минут и 25 секунд:
поясню что непонял
"поставьте константу на RtlInitString из"
вызов это тупой CALL с адресом из таблицы
а в таблице RtlInitString нет и еслибы я умел править таблицу, места там нет и даже если есть понятия неимею где обявлена ее длина и еще черт знает там что может быть
 
« Последнее редактирование: 20-12-2012 05:09 от inf158704 » Записан
sss
Специалист

ru
Offline Offline

« Ответ #11 : 20-12-2012 08:19 » 


а в таблице RtlInitString нет
 

Зато есть адрес RtlInitString в системе и он не будет меняться. Вы можете один раз его найти в своей системе и он не будет меняться..
То есть заменить:
 
call   ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

на

call 0x7C901225

Что сложного? Вы не верите, что он не будет изменяться от запуска к запуску? Поверьте не будет..
Если опкод получиться меньше, заполните nop-ами.

Наверное не ExAllocatePoolWithTag, а NdisInitializeString?
Понимаете, в качестве единственной недостающей функции у Вас именно такая, которую легко заменить. Или нет в Win98 RtlInitString ?
« Последнее редактирование: 20-12-2012 08:27 от sss » Записан

while (8==8)
inf158704
Участник

ru
Offline Offline

« Ответ #12 : 20-12-2012 08:47 » 

понял буду пробовать
спасибо
Записан
sss
Специалист

ru
Offline Offline

« Ответ #13 : 20-12-2012 12:25 » 

Удачи.
Записан

while (8==8)
inf158704
Участник

ru
Offline Offline

« Ответ #14 : 21-12-2012 10:51 » 

на сегодня испортил код до такого вида
Код:
// WDMSTUB.CPP -- Stubs for missing Win2K WDM service functions
// Copyright (C) 1998 by Walter Oney
// All rights reserved

#include "stddcls.h"
#include "driver.h"
#include "NonStubs.h"

#define IFSMGR_SERVICES_ONLY
#include "ifsmgr.h"


BOOLEAN bKdDebuggerEnabled = 0;

BOOLEAN PrecisionErrata = FALSE;
DWORD features = 0;

// Pentium feature flags returned in EDX from CPUID with EAX == 1

#define FEATURE_FPU 0x00000001 // FPU on chip
//#define FEATURE_RDTSC 0x00000010 // RDTSC instruction supported
//#define FEATURE_MACHINE_CHECK 0x00000080 // machine check exception can occur
//#define FEATURE_CMPXCHG8B 0x00000100 // CMPXCHG8B instruction supported
//#define FEATURE_MMX 0x00800000 // MMX instructions supported
//#define FEATURE_XMMI 0x02000000

//#define BCS_WANSI 0 // ifs.h generates too many compile errors if we include it

extern "C" NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING name, ULONG unknown1,
    ULONG unknown2, ULONG unknown3, POBJECT_TYPE type,
    KPROCESSOR_MODE mode, ULONG unknown4, PVOID *object);
extern "C" POBJECT_TYPE* IoDriverObjectType;

///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

// Names of functions stubbed by this VxD. This isn't the array we actually pass
// to PELDR -- it's the array we use when we construct a list of functions
// that aren't already implemented by NTKERN. The names must be in resident storage
// because we don't copy them when we build the export table.

static char* names[] = {
"PoRegisterSystemState",
"KdDebuggerEnabled",
};

// As of SP-9, we're using C11 with the Xp options. String constants therefore end
// up in the referencing code segment, but we need to have *this* constant persist:

static char* ntoskrnl = "ntoskrnl.exe";


// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to
// APC_LEVEL, so we'll stub it no matter what


#pragma warning(disable:4273) // inconsistent dll linkage

// Addresses of stub functions (must line up with names array)

static PFN addresses[] = {
(PFN) PoRegisterSystemState,
(PFN) &bKdDebuggerEnabled,
};



// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken
// due to user-mode bugs.

//static char *wmilib = "wmilib.sys";

//static char* wminames[] = {
// "WmiCompleteRequest",
// };

//static WORD wmiordinals[] = {
// 0,
// };

//static PFN wmiaddresses[] = {
// (PFN) WmiCompleteRequest,
// };

__int64 GetZoneBias();
DWORD buildnum;


char** stubnames; // names of functions we stubbed
PFN* stubaddresses; // addresses of the stub functions
WORD* ordinals; // ordinal table to correlate the other two tables



LCID locale; // default locale
LCID GetSystemLocale();
DWORD atox(char* s);
int cvtnum(char*& p);

NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT fdo, PIRP Irp, PCOMPLETION_CONTEXT ctx);

///////////////////////////////////////////////////////////////////////////////

#pragma warning(disable:4035)

UINT __declspec(naked) __cdecl UniToBCS(PBYTE pBCSPath, WCHAR* pUniPath, UINT length, UINT maxLength, UINT charSet)
{
VxDJmp(UniToBCS)
}

#pragma warning(default:4035)

///////////////////////////////////////////////////////////////////////////////

#pragma INITCODE

#pragma warning(disable:4035)

BOOLEAN Test_Debug_Installed()
{
VMMCall(Test_Debug_Installed)
_asm setnz al
}

#pragma warning(default:4035)

extern "C" ULONG _fltused = 0;

// Flags in CR0:

//#define CR0_PG  0x80000000          // paging
//#define CR0_ET  0x00000010          // extension type (80387)
#define CR0_TS  0x00000008          // task switched
#define CR0_EM  0x00000004          // emulate math coprocessor
#define CR0_MP  0x00000002          // math present
//#define CR0_PE  0x00000001          // protection enable
//#define CR0_CD  0x40000000          // cache disable
//#define CR0_NW  0x20000000          // not write-through
//#define CR0_AM  0x00040000          // alignment mask
//#define CR0_WP  0x00010000          // write protect
//#define CR0_NE  0x00000020          // numeric error

BOOL CheckPrecisionErrata()

{ // CheckPrecisionErrata
static double Dividend = 4195835.0;
static double Divisor = 3145727.0;
BOOL result = FALSE;

_asm
{
pushfd ; save flags
cli
mov eax, cr0 ; make sure flags are the way we need them
mov ecx, eax
and eax, not (CR0_TS or CR0_MP or CR0_EM)
mov cr0, eax

fninit ; initialize coprocessor
fld Dividend ; perform division to show up precision errata
fdiv Divisor
fmul Divisor
fcomp Dividend
fstsw ax ; capture floating point status
sahf

jc  noproblem
jz  noproblem
mov result, 1

noproblem:
mov cr0, ecx ; restore CR0
popfd ; restore flags (including enable state)
}

return result;
} // CheckPrecisionErrata

BOOLEAN DefineStubs()
{ // DefineStubs

// Construct the name, ordinal, and address tables for functions we're going
// to stub. In various releases of Windows 98 and Millenium, some or all of
// these functions will be supported by the operating system, and we don't
// want to preempt the standard implementation.

stubnames = (char**) _HeapAllocate(sizeof(names), HEAPZEROINIT); // largest we might ever need
if (!stubnames)
return FALSE;

stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses), HEAPZEROINIT);
if (!stubaddresses)
{
_HeapFree(stubnames, 0);
return FALSE;
}

ordinals = (WORD*) _HeapAllocate((arraysize(names)) * sizeof(WORD), HEAPZEROINIT);
if (!ordinals)
{
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
}

int i, istub;
for (i = 0, istub = 0; i < arraysize(names); ++i)
{ // for each possible stub
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0)
{ // stub this function
KdPrint((DRIVERNAME " - Stubbing %s\n", names[i]));
stubnames[istub] = names[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = addresses[i];
++istub;
} // stub this function
else
KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i]));
} // for each possible stub

// We have a special problem with the remove lock functions, in that Win98SE leaves out
// just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.


// Always replace the critical region functions to avoid having the IRQL raised


// Create an export table to provide for these functions


// See if debugger running

bKdDebuggerEnabled = Test_Debug_Installed();

// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]

VMMHKEY hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0)
{ // get value
char value[64];
DWORD size = sizeof(value);
if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0)
{ // parse value
char* p = value;
cvtnum(p); // major version number
if (*p == '.')
++p;
cvtnum(p); // minor version number
if (*p == '.')
++p;
buildnum = cvtnum(p); // build number
} // parse value
_RegCloseKey(hkey);
} // get value

// In win98 gold, define the WMILIB functions


// Determine CPU feature flags

DWORD machineinfo;
#undef Get_Machine_Info
VMMCall(Get_Machine_Info)
_asm mov machineinfo, ebx ; capture machine type flags
if (machineinfo & GMIF_CPUID)
{ // cpuid supported
_asm mov eax, 1 ; EAX = 1 => request for feature flags
_asm cpuid
_asm mov features, edx ; save feature flags
} // cpuid supported

if (features & FEATURE_FPU)
PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();

// Determine the default locale for ZwQueryDefaultLocale

locale = GetSystemLocale();

return TRUE;
} // DefineStubs

///////////////////////////////////////////////////////////////////////////////

#pragma PAGEDCODE

VOID UndefineStubs()
{ // UndefineStubs

if (ordinals)
_HeapFree(ordinals, 0);
if (stubaddresses)
_HeapFree(stubaddresses, 0);
if (stubnames)
_HeapFree(stubnames, 0);


ordinals = NULL;
stubaddresses = NULL;
stubnames = NULL;


} // UndefineStubs

///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

PVOID PoRegisterSystemState(PVOID hstate, ULONG flags)
{ // PoRegisterSystemState
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return NULL;
} // PoRegisterSystemState

#pragma warning(disable:4035)

#pragma warning(default:4035)


void __cdecl MessageCallback(char* msg);

NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost)
{ // WmiCompleteRequest
ASSERT(FALSE); // shouldn't be called because no callbacks are being called
return STATUS_NOT_SUPPORTED;
} // WmiCompleteRequest

///////////////////////////////////////////////////////////////////////////////

void __cdecl MessageCallback(char* msg)
{ // MessageCallback
#pragma pack(2)
struct { // MessageBox parameters
WORD fuStyle; // style flags
DWORD lpszTitle; // title string
DWORD lpszText; // message text
WORD hwndParent; // parent window handle
} parms; // MessageBox parameters
#pragma pack()

// Construct parameter list for call to MessageBox

parms.fuStyle = MB_OK | MB_ICONHAND;
parms.lpszTitle = _SHELL_LocalAllocEx(LMEM_STRING, 0, "Windows - Operation Failed");
parms.lpszText = _SHELL_LocalAllocEx(LMEM_STRING, 0, msg);
parms.hwndParent = 0;

// Invoke MessageBox to display the message

if (parms.lpszTitle && parms.lpszText)
_SHELL_CallDll("USER", "MESSAGEBOX", sizeof(parms), &parms);

// Cleanup

if (parms.lpszText)
_SHELL_LocalFree(parms.lpszText);
if (parms.lpszTitle)
_SHELL_LocalFree(parms.lpszTitle);
_HeapFree(msg, 0);
} // MessageCallback

///////////////////////////////////////////////////////////////////////////////

__int64 GetZoneBias()
{ // GetZoneBias
DWORD hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_TIMEZONE, &hkey) != 0)
return 0;

__int64 bias;
LONG actbias;
DWORD size = sizeof(actbias);

if (_RegQueryValueEx(hkey, REGSTR_VAL_TZACTBIAS, NULL, NULL, &actbias, &size) == 0)
{ // compute 100-ns bias
actbias *= 60; // minutes to seconds
_asm mov eax, actbias
_asm mov ecx, 10000000 // seconds to 100-ns units
_asm imul ecx
_asm mov dword ptr bias, eax
_asm mov dword ptr bias+4, edx

} // compute 100-ns bias
else
bias = 0;

_RegCloseKey(hkey);
return bias;
} // GetZoneBias

///////////////////////////////////////////////////////////////////////////////

DWORD atox(char* s)
{ // atox
DWORD result = 0;
char ch;
while ((ch = *s++))
{ // convert hex number
BYTE hexit;
if (ch >= '0' && ch <= '9')
hexit = ch - '0';
else if (ch >= 'A' && ch <= 'F')
hexit = ch - ('A' - 10);
else if ( ch >= 'a' && ch <= 'f')
hexit = ch - ('a' - 10);
else
break; // invalid hexit -- ignore

result <<= 4;
result += hexit;
} // convert hex number

return result;
} // atox

///////////////////////////////////////////////////////////////////////////////
// Convert ascii string to number, skipping characters

int cvtnum(char*& p)
{ // cvtnum
int result = 0;
char ch;
while ((ch = *p++) && ch >= '0' && ch <= '9')
{
result *= 10;
result += (ch - '0');
}
return result;
} // cvtnum

///////////////////////////////////////////////////////////////////////////////

LCID GetSystemLocale()
{ // GetSystemLocale
LCID lcid = LOCALE_SYSTEM_DEFAULT; // in case nothing found
#define REGSTR_PATH_LOCALE TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale")

// Query the registry to determine the default locale

DWORD hKey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOCALE, &hKey) != 0)
return lcid;

char szLocale[9];
DWORD size = sizeof(szLocale);
DWORD type;

if (_RegQueryValueEx(hKey, NULL, NULL, &type, (PBYTE) szLocale, &size) == 0 && type == REG_SZ)
lcid = atox(szLocale);

_RegCloseKey(hKey);
return lcid;
} // GetSystemLocale

///////////////////////////////////////////////////////////////////////////////

#pragma warning(disable:4035)

LONG __stdcall Get_System_Time()
{ // Get_System_Time
VMMCall(Get_System_Time)
} // Get_System_Time

#pragma warning(default:4035)

///////////////////////////////////////////////////////////////////////////////

NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT junk, PIRP Irp, PCOMPLETION_CONTEXT ctx)
{ // CompletionRoutineWrapper
ObReferenceObject(ctx->fdo);
NTSTATUS status = (*ctx->CompletionRoutine)(junk, Irp, ctx->Context);
ObDereferenceObject(ctx->fdo);
_HeapFree((PVOID) ctx, 0);
return status;
} // CompletionRoutineWrapper

появились вопросы



Код:
/// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to
// APC_LEVEL, so we'll stub it no matter what


#pragma warning(disable:4273) // inconsistent dll linkage

// Addresses of stub functions (must line up with names array)

static PFN addresses[] = {
(PFN) PoRegisterSystemState,
(PFN) &bKdDebuggerEnabled,
};



// Win98 Gold doesn't have WMILIB. It wouldn't do any good anyway, since WMI is broken
// due to user-mode bugs.

static char *wmilib = "wmilib.sys";

static char* wminames[] = {
"WmiCompleteRequest",
};

static WORD wmiordinals[] = {
0,
};

static PFN wmiaddresses[] = {
(PFN) WmiCompleteRequest,

Код:
// In win98 gold, define the WMILIB functions

if (buildnum < 2222)
{ // define wmilib exports
if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames),
arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n"));
} // define wmilib exports



Код:
// In win98 gold, define the WMILIB functions


// Determine CPU feature flags

DWORD machineinfo;
#undef Get_Machine_Info
VMMCall(Get_Machine_Info)
_asm mov machineinfo, ebx ; capture machine type flags
if (machineinfo & GMIF_CPUID)
{ // cpuid supported
_asm mov eax, 1 ; EAX = 1 => request for feature flags
_asm cpuid
_asm mov features, edx ; save feature flags
} // cpuid supported

if (features & FEATURE_FPU)
PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();

// Determine the default locale for ZwQueryDefaultLocale

locale = GetSystemLocale();

return TRUE;
} // DefineStubs
чем отличаеться экспорт функций kernel от функций WMILIB
static char *wmilib = "wmilib.sys";
static char* ntoskrnl = "ntoskrnl.exe"
вижу что они используются в проверке наличия уже в системе
а вот как загрузятся функции в систему в едином массиве или отделно...
в общем вопрос в чем отличии и надо ли мне это сохранить это разделение...

#include "stddcls.h"
#include "driver.h"
#include "NonStubs.h"
для чего все это подгружаеться, куча импорта осталось знадьбы хоть приблизительно что нужно а что нет...




* 2.JPG (46.69 Кб - загружено 834 раз.)
« Последнее редактирование: 21-12-2012 12:34 от inf158704 » Записан
inf158704
Участник

ru
Offline Offline

« Ответ #15 : 09-01-2013 06:27 » 

прошу прошения у специалистов...
задам еще пару глупых вопросов...
при компИляции VXD
имею след ошибку
Compiling...
Stdvxd.cpp
.\ntddk.h(370) : error C2146: syntax error : missing ';' before identifier 'Lock'
.\ntddk.h(370) : error C2501: 'PULONG_PTR' : missing storage-class or type specifiers
.\ntddk.h(370) : error C2501: 'Lock' : missing storage-class or type specifiers
.\ntddk.h(824) : error C2146: syntax error : missing ';' before identifier 'KSPIN_LOCK'
.\ntddk.h(824) : fatal error C1004: unexpected end of file found
Error executing cl.exe.
 имею следующее в файле ntddk.h:

 typedef struct _KDPC {
    CSHORT Type;
    UCHAR Number;
    UCHAR Importance;
    LIST_ENTRY DpcListEntry;
    PKDEFERRED_ROUTINE DeferredRoutine;
    PVOID DeferredContext;
    PVOID SystemArgument1;
    PVOID SystemArgument2;
    PULONG_PTR Lock;
} KDPC, *PKDPC, *RESTRICTED_POINTER PRKDPC;
...
typedef ULONG_PTR KSPIN_LOCK;


предпологаю что гдето чтото неописано...
может даст ктото подсказочку

а вообще мнебы было интересно как составлять файл sources чтонибуть бы поподробнее

еще вопрос  компиляция идет через ddk98
DDKXP получаеться неумеет VXD делать?

пытаюсь откомпилировать следующее
ntddk.h из папки w2k копирую в папку проекта остальные пути вроде есть
ntddk.h из папки xp дает ошибу версии


* WdmStub.VXD.zip (28.44 Кб - загружено 774 раз.)
« Последнее редактирование: 09-01-2013 16:53 от Ochkarik » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 09-01-2013 16:27 » 

эм... а там вообще ntddk.h нужен?

Добавлено через 4 минуты и 20 секунд:
сейчас глянул свой старый проект... честно, уже не помню чего там было, и вряд ли вспомню, но включал я следующее:
Код: (C)
#include <vxdlib.h>
#include <vxdmain.h>            //To be included in this file only
#include <vpicd.h>
#include <vxdwraps.h>
                               
#define WANTVXDWRAPS

#include <vmmreg.h>
#include <configmg.h>
#include <regstr.h>
#include <memory.h>
#include <conio.h>
 

PS использовать DDKXP - скорее всего нет, VxD был только до Win98/me включительно. и уже в 98 была поддержка WDM.
PPS про "как составлять файл sources чтонибуть бы поподробнее" - все и даже больше есть тутHow to Use the Build Utility
« Последнее редактирование: 09-01-2013 16:58 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
inf158704
Участник

ru
Offline Offline

« Ответ #17 : 10-01-2013 09:26 » 

Цитата
эм... а там вообще ntddk.h нужен?
пытаюсь понять но похоже в  ntddk.h какраз описаны некотроые функции,
попытался отключить в Stdvxd.cpp компиляцию начало проходить, далее попытался отключить в NonStubs.cpp тут уже вылазит следующая ошибка...
onStubs.cpp
C:\WINDDK\WdmStub.VXD\NonStubs.cpp(11) : warning C4164: 'memset' : intrinsic function not declared
это на #pragma intrinsic(memset)
в принципе как нестрашно

а вот далее идет NonStubs.h
и дает ошибку
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2065: 'NTAPI' : undeclared identifier
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2065: 'PIO_WORKITEM_ROUTINE' : undeclared identifier
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2296: '*' : illegal, left operand has type ''unknown-type''
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2297: '*' : illegal, right operand has type ''unknown-type''
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : error C2501: 'VOID' : missing storage-class or type specifiers
c:\WINDDK\WdmStub.VXD\NonStubs.h(8 ) : fatal error C1903: unable to recover from previous error(s); stopping compilation
на эту строку
typedef VOID (NTAPI *PIO_WORKITEM_ROUTINE)(PDEVICE_OBJECT DeviceObject, PVOID Context);

вот тут похоже мне и нужен ntddk.h
толко для чего пытаюсь понять
да и далше думаю ntddk понадобиться...
чтото похожее нашел здесь буду ковыряться неспеша
http://www.gamedev.ru/flame/forum?id=60601


« Последнее редактирование: 10-01-2013 09:58 от inf158704 » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 10-01-2013 18:49 » 

когда возился с 95/98 пяток нужных функций пришлось выдирать с мясом и класть в свой h-файл...
по хорошему надо открыть DDK от 95го и посмотреть были ли они там в VxD разделе, либо они там в принципе не описаны - тогда драть откуда есть)
в частности если WORKITEM - это все что вам нужно... ну определите свой тип) путь это и не кошерно) либо посмотрите какая функция его еще использует и откуда она берет это определение.

PS о че нашел!
http://read.pudn.com/downloads186/sourcecode/embed/871957/C8051F34x/USB_Bulk/Driver_Source/bulkwdm98.cpp__.htm
« Последнее редактирование: 10-01-2013 18:54 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
inf158704
Участник

ru
Offline Offline

« Ответ #19 : 28-01-2013 09:00 » 

все с vxd драйвером сдаюсь
1 так и несмог разобраться, попробовал сделать по аналогии как подсказывали все никак
2 нашел интересное местечко в sys
а именно:

Код:
static char *wmilib = "wmilib.sys"; \\ вот эта строка меня особенно озадачила

static char* wminames[] = {
"WmiSystemControl",
"WmiCompleteRequest",
};

static WORD wmiordinals[] = {
0,
1,
};

static PFN wmiaddresses[] = {
(PFN) WmiSystemControl,
(PFN) WmiCompleteRequest,
};


.
.
.
if (buildnum < 2222)
{ // define wmilib exports
if (_PELDR_AddExportTable(&hWmilibExportTable, wmilib, arraysize(wminames),
arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub WMILIB functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n"));
} // define wmilib exports
.
.
.
NTSTATUS WmiSystemControl(PWMILIB_CONTEXT WmiLibInfo, PDEVICE_OBJECT DeviceObject, PIRP Irp, PSYSCTL_IRP_DISPOSITION IrpDisposition)
{ // WmiSystemControl
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
*IrpDisposition = IrpProcessed;
return STATUS_SUCCESS;
} // WmiSystemControl

NTSTATUS WmiCompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost)
{ // WmiCompleteRequest
ASSERT(FALSE); // shouldn't be called because no callbacks are being called
return STATUS_NOT_SUPPORTED;
} // WmiCompleteRequest

получаеться что kernel и wmi функции экспортируються отдельно... а не в общей таблице, и похоже
static char *wmilib = "wmilib.sys" указывает к чему эт относятся...
дале, я пытаюсь втюхать системе ndis функию, но в win98 часть функций в ndis.vxd

попытался сделать по аналогии пока просто тупо повторив с изменением названий...

Код:
// Добавление фукций NDIS

static char *ndislib = "ndis.vxd"; // в оригинале .sys

static char* ndisnames[] = {
"NdisInitializeString",
};

static WORD ndisordinals[] = {
0,
};

static PFN ndisaddresses[] = {
(PFN) NdisInitializeString,
};

// конец обявления функций NDIS
.
.
.
// загрузка NDIS функции
if (buildnum < 2222)
{ // define wmilib exports
if (_PELDR_AddExportTable(&hWmilibExportTable, ndislib, arraysize(ndisnames),
arraysize(ndisaddresses), 0, (PVOID*) ndisnames, ndisordinals, ndisaddresses, NULL) != 0)
//arraysize(wmiaddresses), 0, (PVOID*) wminames, wmiordinals, wmiaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub NDIS functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing NdisInitializeString\n"));
} // define wmilib exports
// конец загрузки NDIS функции
.
.
.
// добавление тела NDIS

NTSTATUS NdisInitializeString(PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS Status, ULONG BufferUsed, CCHAR PriorityBoost)
{ // NdisInitializeString
ASSERT(FALSE); // shouldn't be called because no callbacks are being called
return STATUS_NOT_SUPPORTED;
} // NdisInitializeString


// конец добавление тела NDIS


результат нулевой к сожалению компильнуть несмог

C:\WINDDK\Newstub_0\wdmstub.cpp(211) : error C2065: 'NdisInitializeString' : undeclared identifier
C:\WINDDK\Newstub_0\wdmstub.cpp(914) : error C2365: 'NdisInitializeString' : redefinition; previous definition was a 'formerly unknown identifier'

есть тут еще расчет адресов
   
Код:
stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need
if (!stubnames)
return FALSE;

stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT);
if (!stubaddresses)
{
_HeapFree(stubnames, 0);
return FALSE;
}

ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT);
if (!ordinals)
{
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
}

хотя это относится толко к первому блоку загрузки ntkernel_овскому, полной уверенности нет
сама функция которую мне нужно добавить на сайте МС описана так
Код:
NdisInitializeString is implemented only on Windows 2000. A miniport that uses NdisInitializeString fails to load on Windows 98. A binary compatible miniport uses the following macro instead. 
 
 #define NdisInitializeString(Destination,Source) \ 

 {\ 
     PNDIS_STRING _D = (Destination);\ 
     UCHAR *_S = (Source);\ 
     WCHAR *_P;\ 
     _D->Length = (strlen(_S)) * sizeof(WCHAR);\ 
     _D->MaximumLength = _D->Length + sizeof(WCHAR);\ 
     NdisAllocateMemory((PVOID *)&amp;(_D->Buffer), _D->MaximumLength, 0, (-1));\ 
     _P = _D->Buffer;\ 
     while(*_S != '\0'){\ 
         *_P = (WCHAR)(*_S);\ 
         _S++;\ 
         _P++;\ 
     }\ 
     *_P = UNICODE_NULL;\ 
 }           
но с этим буду потом разбираться

понимаю, что отнимаю драгоценное время но если кто подскажет буду рад
« Последнее редактирование: 28-01-2013 09:36 от inf158704 » Записан
inf158704
Участник

ru
Offline Offline

« Ответ #20 : 01-02-2013 11:44 » 

вроде как разобрался что нетак но вопросов стало еще больше
обнаружил непонятку

static char* names[] = {
   "PoRegisterSystemState", //1
   "NdisInitializeString",
   };

static PFN addresses[] = {
   (PFN) PoRegisterSystemState, //1
   (PFN) NdisInitializeString,
   };
немогу поменять имя выходит как раз таже ошибка
C:\WINDDK\Newstub1.1name\wdmstub.cpp(101) : error C2065: 'NdisInitializeString' : undeclared identifier
тоесть как понимаю эти имена заявлены гдето...

где заявлены эти имена  незнаю походе идут вместе с библиотеками
правильно все понимаю?

в ndis.h вот нашел это, но вроде как совсем нето

EXPORT
VOID
NdisInitializeString(
    OUT PNDIS_STRING    Destination,
    IN  PUCHAR          Source
    );





« Последнее редактирование: 01-02-2013 16:41 от inf158704 » Записан
inf158704
Участник

ru
Offline Offline

« Ответ #21 : 14-03-2013 05:55 » 

продвинулся немного с мертвой точки.
чтобы приняла имя добавил
#include <ndis.h> в файл stddcls.h,
для облегчения работы выделил загрузку моей функции в отделную секцию

Код:
//NDIS
static char *ndislib = "ndis.sys";

static char* ndisnames[] = {
"NdisInitializeString", //ndis
};

static WORD ndisordinals[] = {
0,
};

static PFN ndisaddresses[] = {
(PFN) NdisInitializeString, //ndis

с проверкой условия проверки пока решил незаморачиваться если версия 2222 win98SE будет подгружать

Код:
//NDIS
if (buildnum = 2222)
{ // define ndislib exports
if (_PELDR_AddExportTable(&hNdislibExportTable, ndislib, arraysize(ndisnames),
arraysize(ndisaddresses), 0, (PVOID*) ndisnames, ndisordinals, ndisaddresses, NULL) != 0)
{
KdPrint((DRIVERNAME " - Can't stub ndislib functions\n"));
UndefineStubs();
}
KdPrint((DRIVERNAME " - Stubbing WmiSystemControl and WmiCompleteRequest\n"));
} // define ndislib exports

теперь самое сложное с телом: пока обозначил его просто

// ndis
VOID NdisInitializeString(PNDIS_STRING destination, PUCHAR source)
   {                     // NdisInitializeString

есть вопросики по этому поводу
имена переменный взл из ndis.h
destination и source
по этому поводу вопрос небудет ли у меня с этим какихто проблем?

Получил интересный совет по поводу тела, чтобы небыло болших сложностей с переделкой выдраных из иды кусков мне предложили не делать асемблерную вставку как таковую так как при этом возникают сложности с передачей аргумента через стек, тоесть асемблер сам вставляет работу со стеком POP и PUSH, тоесть их надо будет убирать и тут много головной боли.
А посоветовали мне делавь вставочку при линковании. Тоесть функцию отдельно компилировать в OBJ а потом линковать вместе.
переделочка при этом будет выглядить так:

Код:
; Exported entry 136. NdisInitializeString
; Attributes: bp-based frame
; __stdcall NdisInitializeString(x, x)

;public _NdisInitializeString@8
;_NdisInitializeString@8 proc near

;----------------------------------------------------
 ;ml /c ndis.asm
 .486
 .model flat, stdcall
 option casemap:none
 externdef ExAllocatePoolWithTag@12:PROC
  
 .code
 NdisInitializeString@8 proc C
;----------------------------------------------------

arg_0= dword ptr  8
arg_4= dword ptr  0Ch

mov edi, edi
push ebp
mov ebp, esp
push edi
mov edi, [ebp+arg_4]
mov eax, edi
lea ecx, [eax+1]

loc_128C3:
mov dl, [eax]
inc eax
test dl, dl
jnz short loc_128C3
push esi
mov esi, [ebp+arg_0]
sub eax, ecx
add eax, eax
mov [esi], ax
add eax, 2
mov [esi+2], ax
movzx eax, ax
push 7473444Eh
push eax
push 0

;call ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

;----------------------------------------------------
call    ExAllocatePoolWithTag@12
;----------------------------------------------------

test eax, eax
mov [esi+4], eax
pop esi
jz short loc_1290B

loc_128F5:
mov cl, [edi]
test cl, cl
jz short loc_12907
movzx cx, cl
mov [eax], cx
inc edi
inc eax
inc eax
jmp short loc_128F5

loc_12907:
and word ptr [eax], 0

loc_1290B:
pop edi
pop ebp
retn 8
;_NdisInitializeString@8 endp

;----------------------------------------------------
NdisInitializeString@8    endp
;----------------------------------------------------
end NdisInitializeString@8

вот только теперя я непонимаю как у меня все это срастется, как будет передача аргументов идти в функцию, как линкер разберется с названием функции NdisInitializeString@8  = NdisInitializeString
нужно ли мне вообще обявлять
Код:
VOID NdisInitializeString(PNDIS_STRING destination, PUCHAR source)
{ // NdisInitializeString
или при линкоке она вставится сама?




« Последнее редактирование: 15-03-2013 12:07 от inf158704 » Записан
inf158704
Участник

ru
Offline Offline

« Ответ #22 : 18-04-2013 04:34 » 

всем спасибо Улыбаюсь
продолжу свой монолог Улыбаюсь склероз замучил, хоть тут напишу, чтоб вспомнить потом...
http://forum.ru-board.com/topic.cgi?forum=33&topic=4420#1
тоесть в си задать сылку на тело мне надо приблизительно так:
extern "C" void NdisInitializeString(PNDIS_STRING , PUCHAR) - здесь в переменных нужно указать тип или имя непонятно...
еще одна болная точка:

должно быть так
call   ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
это вызов из таблицы импорта

сейчас я компилирую OBJ с вызовом
externdef ExAllocatePoolWithTag@12:PROC
.
.
.
call    ExAllocatePoolWithTag@12

 у меня идет ошибка при сборке драйвера:
Creating library objchk_wxp_x86\i386\wdmstub.lib and object objchk_wxp_x86\i386\wdmstub.exp
ndis.obj : error LNK2019: unresolved external symbol __ExAllocatePoolWithTag@12 referenced in function __NdisInitializeString@8
Wdmstub.obj : error LNK2019: unresolved external symbol __imp__NdisInitializeString@8 referenced in function _$E5
objchk_wxp_x86\i386\wdmstub.sys : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.
при дизасемблировании obj листинг такой

Код:
push    eax
push    0
call    _ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
test    eax, eax
mov     [esi+4], eax


какже всетаки я должен вызывать ExAllocatePoolWithTag в асемблере



« Последнее редактирование: 18-04-2013 06:26 от inf158704 » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines