ex1) 드라이버 소스 심볼릭을 만들어 준다. Device Extension 버퍼에 값을 넣어준다.
#include <ntddk.h>
// Device Object 이름 - UNICODE 사용 "
// \\Device\\원하는 이름" - 반드시 이 규칙대로..
#define DEVICE_NAME    L"\\Device\\WDM2"    // 커널모드로 접근
// Symbolic Link 에 사용할 이름 "\\DosDevice\\원하는 이름"
#define DOS_NAME    L"\\DosDevices\\Simple"    // 유저 모드로 접근
// 보관하고 싶은 것을 구조체로 만든다. 사용자가 정의 가능..
typedef struct _DEVICE_EXTENSION
{
    ULONG data;    
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
VOID DriverUnload( IN PDRIVER_OBJECT pDriverObject)
{
    UNICODE_STRING         ustrDosName;
    PDEVICE_OBJECT         pDeviceObject;
    PDEVICE_EXTENSION     pDeviceExtension;
    
    pDeviceObject      = pDriverObject->DeviceObject;
    pDeviceExtension = pDeviceObject->DeviceExtension;
    
    DbgPrint("[Wdm2] DriverUnload : %d", pDeviceExtension->data );
    
    RtlInitUnicodeString( &ustrDosName, DOS_NAME);
    // Symbolic link 파괴 - 이름만 알면 된다.
    IoDeleteSymbolicLink( &ustrDosName );
    // Device Object 파괴 - Device Object 포인터 전달..
    IoDeleteDevice( pDeviceObject );
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
    NTSTATUS status = STATUS_SUCCESS;
    
    // 구조체 이므로 함수를 사용하여 초기화 한다.
    UNICODE_STRING    ustrName;
    UNICODE_STRING     ustrDosName;
    
    // 둘다 디바이스에 접근하기 위해 사용하는 포인터
    PDEVICE_OBJECT         pDeviceObject;    // 원래 있는 구조체
    PDEVICE_EXTENSION     pDeviceExtension;    // 사용자가 만든 구조체
    
    DbgPrint("[WDM2] DriverEntry");
        
    pDriverObject->DriverUnload = DriverUnload;
    
    // 문자열을 초기화 한다. 결국은 strcpy()
    RtlInitUnicodeString( &ustrName, DEVICE_NAME );
    RtlInitUnicodeString( &ustrDosName, DOS_NAME );
    // Device Object 를 장치당 1개씩 만들어야 한다.
    // 하지만 하드웨어와 관련 없는 경우... User와 통신하기 위해 1개만 만든다.
    status = IoCreateDevice( pDriverObject,            // 드라이버 Object( 함수 제공 )
                        sizeof( DEVICE_EXTENSION),    // Device EXTENSION 크기
                        &ustrName,                    // 이름
                        FILE_DEVICE_UNKNOWN,// 종류(마우스,키보드등등), 범용드라이버(UNKNOWN)
                        0,
                        TRUE,                          // H/W 관련..
                        &pDeviceObject);          // 완성된 구조체의 주소가 이리로 온다.
    DbgPrint( "address of DeviceObject : %p", pDeviceObject );
                             
    if ( ! NT_SUCCESS( status ) )
    {
        DbgPrint("[WDM2] Error IoCreateDevice");
        return status;
    }
    
    // 테스트를 위한 코드..
    pDeviceExtension = pDeviceObject->DeviceExtension;
    pDeviceExtension->data = 100;
    
    // User Mode 에서 접근하기 위해 별명(Symbolic link) 를 제공한다.
    // 디바이스 오브젝트의 별명을 하나 준다.
    status = IoCreateSymbolicLink( &ustrDosName, &ustrName);
    
    if ( ! NT_SUCCESS( status ) )
    {
        DbgPrint("[WDM2] Error IoCreateSymbolicLink"); 
        // 항상 나갈때는 삭제하고 가야한다. 드라이버는 위험하므로 꼭 지키자..
        IoDeleteDevice( pDeviceObject );
    }
    return status;
}