Basic Concepts of Device Objects and Symbolic Links
In kernel programming, a Device Object is the core entity for communication between the kernel and user-mode applications. Device objects are similar to windows in Windows GUI programming, being the only entities capable of receiving and processing requests (IRP). Each device object belongs to a Driver Object, and a driver object can generate multiple device objects, which are linked together in a unidirectional linked list via the <span>NextDevice</span> pointer.
A Symbolic Link serves as a bridge to expose kernel device objects to user-mode applications. It is akin to a shortcut in a file system, mapping a user-visible name (e.g., <span>\.\\MyDevice</span>) to a kernel device name (e.g., <span>\Device\MyDevice</span>).
Creation and Initialization of Device Objects
Detailed Explanation of the IoCreateDevice API
<span>IoCreateDevice</span> is the core API for creating device objects, with the following function prototype:
; IoCreateDevice function parameter description
; Input:
; DriverObject - Pointer to the driver object (PDRIVER_OBJECT)
; DeviceExtensionSize - Size of the device extension structure (ULONG)
; DeviceName - Device name (PUNICODE_STRING)
; DeviceType - Device type (DEVICE_TYPE)
; DeviceCharacteristics - Device characteristics (ULONG)
; Exclusive - Whether the device is exclusive (BOOLEAN)
; Output:
; DeviceObject - Pointer to the returned device object (PDEVICE_OBJECT *)
IoCreateDevice proc
mov eax, [esp+4] ; DriverObject
mov ecx, [esp+8] ; DeviceExtensionSize
mov edx, [esp+12] ; DeviceName
mov ebx, [esp+16] ; DeviceType
mov esi, [esp+20] ; DeviceCharacteristics
mov edi, [esp+24] ; Exclusive
mov ebp, [esp+28] ; DeviceObject
; Call kernel service...
ret 28h
IoCreateDevice endp
The device name must start with <span>\Device\</span>, for example, <span>\Device\MyDDKDevice</span>. If no name is specified, the I/O manager will automatically assign a numeric name such as <span>\Device\00000001</span>.
Device Extension Structure
The Device Extension is a unique storage area for each device object, used to store device-specific information:
DEVICE_EXTENSION STRUCT
pDevice DWORD ? ; Pointer to the device object
ustrDeviceName UNICODE_STRING <> ; Device name
ustrSymLinkName UNICODE_STRING <> ; Symbolic link name
NextStackDevice DWORD ? ; Next lower device object
; Other custom fields...
DEVICE_EXTENSION ENDS
After creating the device, this area can be accessed via <span>DeviceObject->DeviceExtension</span>.
Creation of Symbolic Links
Detailed Explanation of the IoCreateSymbolicLink API
; IoCreateSymbolicLink function parameter description
; Input:
; SymbolicLinkName - Symbolic link name (PUNICODE_STRING)
; DeviceName - Device name (PUNICODE_STRING)
IoCreateSymbolicLink proc
mov eax, [esp+4] ; SymbolicLinkName
mov ecx, [esp+8] ; DeviceName
; Call kernel service...
ret 8h
IoCreateSymbolicLink endp
The symbolic link name must start with <span>\DosDevices\</span> or <span>\??\</span>, for example, <span>\DosDevices\MyDeviceLink</span>. In user mode, applications need to access these links using the <span>\.\</span>