myid wrote:Brock wrote:Windows 10 uses _EX_PUSH_LOCK, I just checked. Like Vrtule mentioned use WinDbg to locate what type of lock for each OS version etc. you plan to support. It's not hard. Make sure you have symbol path properly configured beforehand
I know WIN10 uses _EX_PUSH_LOCK, could you tell me the related API name of _EX_PUSH_LOCK?
AFAIK, pushlock API is not documented as a general kernel API, however, it is available to FS minifilters. The minifilter API should be only stubs around the real one, see:
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
If you wish to use the kernel API (and not to go through fltmgr), here is my source for that. You need to provide a routine that provides you with the operating system version which should not be a problem.
Code: Select all
/**
* @file: pushlock.c
*
* Pushlocky jsou nedokumentovana synchronizacni primitiva, ktera pouziva jadro Windows
* od verze XP stale vice a vice. Jedna se o zamky reader-writer ne nepodobne zamkum
* SRWL (Slim Reader Writer Locks) z uzivatelskeho rezimu Vista/7. Velikost je rovna
* delce adresy.
*
* Tento soubor dovoluje i vyvojarum ovladacu tato primitiva vyuzivat. Zaroven je
* kompatibilni i s Windows 2000, protoze adresy jednotlivych rutin pro praci s pushlocky
* nacita dynamicky pres MmGetSystemRoutineAddress.
*/
#include <ntifs.h>
#include "utils-pushlock.h"
// Definice jednotlivych rutin pro praci s pushlocky tak, jak jsou zapsany v ntoskrnl.exe
// Inicializace zamku
typedef VOID (*EXINITIALIZEPUSHLOCK)(PVOID *Lock);
// Zamknout pro exklizivni pristup
typedef VOID (FASTCALL *EXFACQUIREPUSHLOCKEXCLUSIVE)(PVOID *Lock);
// Zamknout pro sdileny pristup
typedef VOID (FASTCALL *EXFACQUIREPUSHLOCKSHARED)(PVOID *Lock);
// Odemknout sdileny pristup
typedef VOID (FASTCALL *EXFRELEASEPUSHLOCKSHARED)(PVOID *Lock);
// Odemknout exkluzivni pristup
typedef VOID (FASTCALL *EXFRELEASEPUSHLOCKEXCLUSIVE)(PVOID *Lock);
// Odemknuti zamku zamceneho pro libovolny pristup.
typedef VOID (FASTCALL *EXFRELEASEPUSHLOCK)(PVOID *Lock);
// Promenne pro uchovani adres rutin pro praci s pushlocky v ntoskrnl.exe
static EXINITIALIZEPUSHLOCK _ExInitializePushLock = NULL;
static EXFACQUIREPUSHLOCKSHARED _ExfAcquirePushLockShared = NULL;
static EXFACQUIREPUSHLOCKEXCLUSIVE _ExfAcquirePushLockExclusive = NULL;
static EXFRELEASEPUSHLOCKSHARED _ExfReleasePushLockShared = NULL;
static EXFRELEASEPUSHLOCKEXCLUSIVE _ExfReleasePushLockExclusive = NULL;
static EXFRELEASEPUSHLOCK _ExfReleasePushLock = NULL;
/** Vrati adresu zadane rutiny.
*
* Prohledavaji se pouze moduly ntoskrnl.exe a hal.dll.
*
* @param RoutineName Retezec obsahujici nazev hledane rutiny.
*
* @return Funkce vraci adresu hledane rutiny. Pokud rutina daneho jmena neexistuje ani
* v ntoskrnl.exe ani v hal.dll, funkce vraci NULL.
*/
static PVOID _GetRoutineAddress(PWCHAR RoutineName)
{
PVOID Ret = NULL;
UNICODE_STRING uName;
RtlInitUnicodeString(&uName, RoutineName);
Ret = MmGetSystemRoutineAddress(&uName);
return Ret;
}
/*
* Nasleduji "proxy" funkce, ktere obaluji jednotliva volani rutin pro praci
* s pushlocky v ntoskrnl.exe. Ne vsechny rutiny pro praci s pushlocky jsou definovany
* na vsech verzich Windows (XP, 2003, Vista, 7), a tak se nektere proxy funkce pouzivaji
* jen na nekterych verzich OS.
*/
/** Inicializuje pushlock.
*
* @param Lock adresa promenne, ktera ma byt inicializovana jako pushlock.
*/
VOID PushLockInitialize(PVOID *Lock)
{
_ExInitializePushLock(Lock);
return;
}
/** Zamkne pushlock pro sdileny pristup.
*
* Rutina taky zakaze normalni APC jadra vstoupenim do kritickeho regionu.
*
* @param Lock Adresa pushlocku, ktery si volajici preje zamknout pro sdileny pristup.
*/
VOID PushLockAcquireShared(PVOID *Lock)
{
KeEnterCriticalRegion();
_ExfAcquirePushLockShared(Lock);
return;
}
/** Zamkne pushlock pro exkluzivni pristup.
*
* Rutina taky zakaze normalni APC jadra vstoupenim do kritickeho regionu.
*
* @param Lock Adresa pushlocku, ktery si volajici preje zamknout pro exkluzivni pristup.
*/
VOID PushLockAcquireExclusive(PVOID *Lock)
{
KeEnterCriticalRegion();
_ExfAcquirePushLockExclusive(Lock);
return;
}
/** Odemkne pushlock zamceny pro sdileny pristup.
*
* Rutina zaroven povoli normalni APC jadra vystoupenim z kritickeho regionu.
*
* @param Lock Adresa pushlocku, ktery chce volajici odemknout.
*/
VOID PushLockReleaseShared(PVOID *Lock)
{
_ExfReleasePushLockShared(Lock);
KeLeaveCriticalRegion();
return;
}
/** Odemkne pushlock zamceny pro exkluzivni pristup.
*
* Rutina zaroven povoli normalni APC jadra vystoupenim z kritickeho regionu.
*
* @param Lock Adresa pushlocku, ktery chce volajici odemknout.
*/
VOID PushLockReleaseExclusive(PVOID *Lock)
{
_ExfReleasePushLockExclusive(Lock);
KeLeaveCriticalRegion();
return;
}
/** Odemkne pushlock. Pushlock muze byt zamcen pro libovolny pristup.
*
* Rutina zaroven povoli normalni APC jadra vystoupenim z kritickeho regionu.
*
* #param Lock Adresa pushlocku, ktery si volajici preje odemknout.
*/
VOID PushLockRelease(PVOID *Lock)
{
_ExfReleasePushLock(Lock);
KeLeaveCriticalRegion();
return;
}
/*
* Nasledujici funkce jsou nahrazky za rutiny, ktere na starsich Windows (XP, 2K3)
* jeste neexistuji. Jejich vyznam je stejny jako v rutinach popsanych vyse.
*/
static VOID WXPW2K3ExInitializePushLock(PVOID *Lock)
{
*Lock = NULL;
return;
}
static VOID FASTCALL WXPExfReleasePushLockShared(PVOID *Lock)
{
_ExfReleasePushLock(Lock);
return;
}
static VOID FASTCALL WXPExfReleasePushLockExclusive(PVOID *Lock)
{
_ExfReleasePushLock(Lock);
return;
}
/** Provadi inicializaci modulu pro praci s pushlocky.
*
* Rutina nejprve zjisti aktualni verzi operacniho systemu. Pokud se nejedna o
* Windows 2000, rutina namapuje jednotlive funkce na adresy v ntoskrnl.exe. Mapovani
* se napric verzemi Windows muze lisit, protoze kazda nova verze podporuje vetsi
* mnozstvi funkci pro praci s pushlocky.
*
* @return Funkce vraci hodnotu NTSTATUS indikujici uspech ci neuspech operace.
*/
NTSTATUS PushLockModuleInit(VOID)
{
LONG VersionCode = 0;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
KdPrint(("pushlock.c: PushLockModuleInit()\n"));
VersionCode = GetVersionCode();
if (VersionCode != VERSION_UNKNOWN)
Status = STATUS_SUCCESS;
if (NT_SUCCESS(Status) && VersionCode != VERSION_W2K) {
_ExfAcquirePushLockShared = (EXFACQUIREPUSHLOCKSHARED)_GetRoutineAddress(L"ExfAcquirePushLockShared");
_ExfAcquirePushLockExclusive = (EXFACQUIREPUSHLOCKEXCLUSIVE)_GetRoutineAddress(L"ExfAcquirePushLockExclusive");
_ExfReleasePushLock = (EXFRELEASEPUSHLOCK)_GetRoutineAddress(L"ExfReleasePushLock");
if (VersionCode != VERSION_WXP && VersionCode != VERSION_W2K3)
_ExInitializePushLock = (EXINITIALIZEPUSHLOCK)_GetRoutineAddress(L"ExInitializePushLock");
else _ExInitializePushLock = WXPW2K3ExInitializePushLock;
if (VersionCode != VERSION_WXP) {
_ExfReleasePushLockShared = (EXFRELEASEPUSHLOCKSHARED)_GetRoutineAddress(L"ExfReleasePushLockShared");
_ExfReleasePushLockExclusive = (EXFRELEASEPUSHLOCKEXCLUSIVE)_GetRoutineAddress(L"ExfReleasePushLockExclusive");
} else {
_ExfReleasePushLockShared = WXPExfReleasePushLockShared;
_ExfReleasePushLockExclusive = WXPExfReleasePushLockExclusive;
}
if (_ExInitializePushLock == NULL || _ExfAcquirePushLockShared == NULL ||
_ExfAcquirePushLockExclusive == NULL || _ExfReleasePushLockShared == NULL ||
_ExfReleasePushLockExclusive == NULL || _ExfReleasePushLock == NULL) {
Status = STATUS_NOT_FOUND;
if (_ExInitializePushLock == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExInitializePushLock\n"));
if (_ExfAcquirePushLockShared == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExfAcquirePushLockShared\n"));
if (_ExfAcquirePushLockExclusive == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExfAcquirePushLockExclusive\n"));
if (_ExfReleasePushLockShared == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExfReleasePushLockShared\n"));
if (_ExfReleasePushLockExclusive == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExfReleasePushLockExclusive\n"));
if (_ExfReleasePushLock == NULL)
KdPrint(("pushlock.c: PushLockModuleInit(): Failed to find nt!ExfReleasePushLock\n"));
}
}
KdPrint(("pushlock.c: PushLockModuleInit(-):0x%x\n", Status));
return Status;
}
/** Provadi uklid po modulu pracujiciho s pushlocky.
*
* Jelikoz tento modul nezasahuje nijak do internich struktur jadra, neni co uklizet.
* Funkce tedy nedela nic.
*/
VOID PushLockModuleFinit(VOID)
{
KdPrint(("pushlock.c: PushLockModuleFinit()\n"));
KdPrint(("pushlock.c: PushLockModuleFinit(-)\n"));
return;
}