⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mutualexclusion.bat

📁 这是asm驱动的开发包
💻 BAT
字号:
;@echo off
;goto make

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
;  MutualExclusion - "mutual exclusion" functionality
;
;  Written by Four-F (four-f@mail.ru)
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.386
.model flat, stdcall
option casemap:none

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                  I N C L U D E   F I L E S                                        
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

include \masm32\include\w2k\ntstatus.inc
include \masm32\include\w2k\ntddk.inc
include \masm32\include\w2k\ntoskrnl.inc

includelib \masm32\lib\w2k\ntoskrnl.lib

include \masm32\Macros\Strings.mac

NUM_THREADS	equ 5		; must not exceed MAXIMUM_WAIT_OBJECTS (64)	- Maximum number of wait objects
NUM_WORKS	equ 10

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       M A C R O S                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

include Mutex.mac

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                 R E A D O N L Y    D A T A                                        
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.const

CCOUNTED_UNICODE_STRING	"\\Device\\MutualExclusion", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING	"\\DosDevices\\MutualExclusion", g_usSymbolicLinkName, 4

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              U N I N I T I A L I Z E D  D A T A                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.data?

g_pkWaitBlock		PKWAIT_BLOCK	?
g_apkThreads		DWORD NUM_THREADS dup(?)	; Array of PKTHREAD
g_dwCountThreads	DWORD	?
g_kMutex			KMUTEX	<>
g_dwWorkElement		DWORD	?

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         C O D E                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.code

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                        ThreadProc                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ThreadProc proc uses ebx Param:DWORD

local liDelayTime:LARGE_INTEGER
local pkThread:DWORD		; PKTHREAD
local dwWorkElement:DWORD

	invoke PsGetCurrentThread
	mov pkThread, eax
	invoke DbgPrint, $CTA0("MutualExclusion: Thread %08X is entering ThreadProc\n"), pkThread

	xor ebx, ebx
	.while ebx < NUM_WORKS

		invoke DbgPrint, $CTA0("MutualExclusion: Thread %08X is working on #%d\n"), pkThread, ebx

		MUTEX_WAIT addr g_kMutex

		; Read the resource shared across the threads

		push g_dwWorkElement
		pop dwWorkElement

		; Simulate working with the shared across the threads resource

		invoke rand				; Generates pseudo-random number 0 - 07FFFh
		shl eax, 4				; * 16
		neg eax					; delay = 0 - ~50 ms
		or liDelayTime.HighPart, -1
		mov liDelayTime.LowPart, eax
		invoke KeDelayExecutionThread, KernelMode, FALSE, addr liDelayTime

		; Write the resource shared across the threads back

		inc dwWorkElement

		push dwWorkElement
		pop g_dwWorkElement

		MUTEX_RELEASE addr g_kMutex

		mov eax, liDelayTime.LowPart
		neg eax
		mov edx, 3518437209		; Magic number
		mul edx
		shr edx, 13
		invoke DbgPrint, $CTA0("MutualExclusion: Thread %08X work #%d is done (%02dms)\n"), \
							pkThread, ebx, edx

		inc ebx					; Do next work

	.endw

	invoke DbgPrint, $CTA0("MutualExclusion: Thread %08X is about to terminate\n"), pkThread

	invoke PsTerminateSystemThread, STATUS_SUCCESS

	ret

ThreadProc endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                          CleanUp                                                  
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

CleanUp proc pDriverObject:PDRIVER_OBJECT

	invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName

	mov eax, pDriverObject
	invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject

	.if g_pkWaitBlock != NULL
		invoke ExFreePool, g_pkWaitBlock
		and g_pkWaitBlock, NULL
	.endif

	ret

CleanUp endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverUnload                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverUnload proc pDriverObject:PDRIVER_OBJECT

	invoke DbgPrint, $CTA0("MutualExclusion: Entering DriverUnload\n")
	invoke DbgPrint, $CTA0("MutualExclusion: Wait for threads exit...\n")

	; We must not unload driver till even one of our system threads is runing
	; because ThreadProc resides in our driver's body. So we will wait.

	.if g_dwCountThreads > 0

		; No Timeout is supplied - wait infinite.

		invoke KeWaitForMultipleObjects, g_dwCountThreads, addr g_apkThreads, WaitAll, \
					Executive, KernelMode, FALSE, NULL, g_pkWaitBlock

		; Here all of the dispatcher objects satisfied the wait.
		; If the wait can be satisfied immediately an appropriate value 
		; STATUS_WAIT_1, STATUS_WAIT_2,...) is returned.
		; So, do not check return value against STATUS_SUCCESS.

		; Dereference all thread objects

		.while g_dwCountThreads
			dec g_dwCountThreads
			mov eax, g_dwCountThreads	; zero-based
			fastcall ObfDereferenceObject, g_apkThreads[eax * type g_apkThreads]
		.endw

	.endif

	invoke CleanUp, pDriverObject

	; Print result. g_dwWorkElement should be equal to NUM_THREADS * NUM_WORKS

	invoke DbgPrint, $CTA0("MutualExclusion: WorkElement = %d\n"), g_dwWorkElement

	invoke DbgPrint, $CTA0("MutualExclusion: Leaving DriverUnload\n")

	ret

DriverUnload endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              D I S C A R D A B L E   C O D E                                      
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.code INIT

; Compile-time check for shure.
; NUM_THREADS must not exceed MAXIMUM_WAIT_OBJECTS (64)	- Maximum number of wait objects.

; If number of wait objects > MAXIMUM_WAIT_OBJECTS,
; the system issues Bug Check 0xC (MAXIMUM_WAIT_OBJECTS_EXCEEDED).

IF NUM_THREADS GT MAXIMUM_WAIT_OBJECTS
	.ERR Maximum number of wait objects exceeded!
ENDIF

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       StartThread                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

StartThreads proc uses ebx

local hThread:HANDLE
local i:DWORD
	
	and i, 0							; Init counter of threads to run
	xor ebx, ebx						; ebx holds number of actually running threads
	.while i < NUM_THREADS				; Start NUM_THREADS threads
	
		; Drivers for Windows 2000 must only call PsCreateSystemThread from the system process context.
		; I'm not sure is it correct. Anyway we are in system process context here.

		invoke PsCreateSystemThread, addr hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc, 0
		.if eax == STATUS_SUCCESS

			; We do not need thread's handle returned by PsCreateSystemThread.
			; But we do need its pointer. So we reference thread object and close its handle.

			invoke ObReferenceObjectByHandle, hThread, THREAD_ALL_ACCESS, NULL, KernelMode, \
									addr g_apkThreads[ebx * type g_apkThreads], NULL

			invoke ZwClose, hThread
			invoke DbgPrint, $CTA0("MutualExclusion: System thread created. Thread Object: %08X\n"), \
									g_apkThreads[ebx * type g_apkThreads]
			inc ebx
		.else
			invoke DbgPrint, $CTA0("MutualExclusion: Can't create system thread. Status: %08X\n"), eax
		.endif
		inc i
	.endw

	mov g_dwCountThreads, ebx
	.if ebx != 0
		mov eax, STATUS_SUCCESS				; Indicates that at least one thread is running
	.else
		mov eax, STATUS_UNSUCCESSFUL		; Couldn't start any thread
	.endif

	ret

StartThreads endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverEntry                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING

local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
local liTickCount:LARGE_INTEGER

	mov status, STATUS_DEVICE_CONFIGURATION_ERROR

	invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, \
								FILE_DEVICE_UNKNOWN, 0, FALSE, addr pDeviceObject
	.if eax == STATUS_SUCCESS
		invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usDeviceName
		.if eax == STATUS_SUCCESS

			; We must not unload driver till even one of our thread is runing
			; because ThreadProc resides in our driver's body. We will wait for threads exit.
			; For this purpose we need some memory. We must allocate it here because
			; if we will fail to do this in DriverUnload there is no way
			; to prevent driver from unloading.

			; Each thread object has a built-in array of wait blocks that can be used to wait
			; on several objects concurrently. Whenever possible, the built-in array of wait blocks
			; should be used in a wait-multiple operation because no additional wait block storage
			; needs to be allocated and later deallocated. However, if the number of objects
			; that must be waited on concurrently is greater than the number of built-in wait blocks,
			; use the WaitBlockArray parameter to specify an alternate set of wait blocks
			; to be used in the wait operation.
		
			; Our NUM_THREADS is larger than THREAD_WAIT_OBJECTS. So we have to use Wait Block.

			mov eax, NUM_THREADS
			mov ecx, sizeof KWAIT_BLOCK
			xor edx, edx
			mul ecx

			and g_pkWaitBlock, NULL
			invoke ExAllocatePool, NonPagedPool, eax
			.if eax != NULL
				mov g_pkWaitBlock, eax

				; Initialize the mutex. It is initialized with an initial state of signaled.

				MUTEX_INIT addr g_kMutex

				; For better performance, use the Ex..FastMutex routines instead of the Ke..Mutex.
				; However, a fast mutex cannot be acquired recursively, as a kernel mutex can.
				; Another drawback is that ExAcquireFastMutex sets the IRQL to APC_LEVEL,
				; and the caller continues to run at APC_LEVEL after ExAcquireFastMutex returns.

				invoke KeQueryTickCount, addr liTickCount

				; Initialize seed. It's global kernel variable, by the way, but never
				; (at least on my box) used.

				invoke srand, liTickCount.LowPart

				and g_dwWorkElement, 0

				invoke StartThreads
				.if eax == STATUS_SUCCESS
					mov eax, pDriverObject
					mov (DRIVER_OBJECT PTR [eax]).DriverUnload, offset DriverUnload
					mov status, STATUS_SUCCESS
				.else
					invoke CleanUp, pDriverObject
				.endif
			.else
				invoke CleanUp, pDriverObject
				invoke DbgPrint, $CTA0("MutualExclusion: Couldn't allocate memory for Wait Block\n")
			.endif
		.else
			invoke IoDeleteDevice, pDeviceObject
		.endif
	.endif

	mov eax, status
	ret

DriverEntry endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

end DriverEntry

:make

set drv=MutualExclusion

\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native /ignore:4078 %drv%.obj

del %drv%.obj

echo.
pause

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -