Search

2012年12月2日 星期日

Windows Driver Loader

    這個月有個工作是要用隊友給的driver去對某個設備做I/O操作控制,不過這幾天發現有時DriverMonitor掛驅動有的路徑會有問題,看call CreateService建在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services的登錄檔ImagePath可能因為編碼問題有點錯誤,也懶得寫INF而且我不太會用工具產生XD,還有個問題我不知道是什麼原因,用看系統service運作的工具理應掛載的測試driver應該不存在了,可是似乎無法重新用DriverMonitor啟動,非得重新開機才可以,前天為了這幾個問題還花幾小時去re DriverMonitor研究幾個function,不過看不出來流程有什麼差異或問題,但還是自己寫了一個常規Loader去處理...話說隊友給的driver還是一直有問題對I/O寫資料給設備有時還是會BSoD.........Orz





DriverLoader.h


#ifndef __DRIVER_LOADER__
#define __DRIVER_LOADER__

#include <wx/wx.h>
#include <wx/listctrl.h>

#include <windows.h>

#include "fileopen.xpm"
#include "start.xpm"
#include "stop.xpm"

enum{
ID_START = 100,
ID_STOP
};

enum{
COLUMN_0 = 0
};

class App:public wxApp
{
public:

bool OnInit();
};

class MSGList:public wxListCtrl
{
public:

MSGList(wxWindow*);

void AddMessage(const wxString&);

private:

int item_num;
};

class Frame:public wxFrame
{
public:

Frame(const wxString&,const wxSize&);

void OnOpenDriver(wxCommandEvent&);
void OnStartDriver(wxCommandEvent&);
void OnStopDriver(wxCommandEvent&);
void OnExit(wxCommandEvent&);
private:

void CreateUI();

MSGList *msg;
wxString name;
wxString path;

DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(Frame,wxFrame)
EVT_MENU(wxID_OPEN,Frame::OnOpenDriver)
EVT_MENU(wxID_EXIT,Frame::OnExit)
EVT_MENU(ID_START,Frame::OnStartDriver)
EVT_MENU(ID_STOP,Frame::OnStopDriver)
END_EVENT_TABLE()

#endif


DriverLoader.cpp


#include "DriverLoader.h"

DECLARE_APP(App)
IMPLEMENT_APP(App)

bool App::OnInit()
{
Frame *frame = new Frame(wxT("wxDriverLoader"),wxSize(600,400));

frame->Show(true);

return true;
}

Frame::Frame(const wxString &title,const wxSize &size):wxFrame(NULL,wxID_ANY,title,wxDefaultPosition,size,wxMINIMIZE_BOX | wxCLOSE_BOX | wxCAPTION | wxSYSTEM_MENU)
{
CreateUI();
}

void Frame::CreateUI()
{
wxMenu *file = new wxMenu;
file->Append(wxID_OPEN,wxT("O&pen\tAlt-o"),wxT("Open Driver"));
file->AppendSeparator();
file->Append(ID_START,wxT("S&tart\tAlt-r"),wxT("Start Driver"));
file->Append(ID_STOP,wxT("S&top\tAlt-s"),wxT("Stop Driver"));
file->AppendSeparator();
file->Append(wxID_EXIT,wxT("E&xit\tAlt-q"),wxT("Exit"));

wxMenuBar *bar = new wxMenuBar;
bar->Append(file,wxT("file"));

wxToolBar *tool = new wxToolBar(this,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxTB_HORIZONTAL | wxNO_BORDER);

wxBitmap open_bmp(fileopen_xpm);
wxBitmap start_bmp(start_xpm);
wxBitmap stop_bmp(stop_xpm);

tool->AddTool(wxID_OPEN,open_bmp,wxT("Open Driver"));
tool->AddTool(ID_START,start_bmp,wxT("Start Driver"));
tool->AddTool(ID_STOP,stop_bmp,wxT("Stop Driver"));
tool->Realize();
SetToolBar(tool);

msg = new MSGList(this);

SetMenuBar(bar);
CreateStatusBar(2);
}

void Frame::OnOpenDriver(wxCommandEvent &event)
{
msg->AddMessage(wxT("********************Driver Select!********************"));

wxFileDialog dlg(this,wxT("Select File"),wxT("."),wxT("*.sys"),wxT("SYS files (*.sys)|*.sys"),wxOPEN);

if(dlg.ShowModal() == wxID_OK){
name = dlg.GetFilename();
path = dlg.GetPath();
wxString str;
str.Printf(wxT("Open File %s Success!"),name);
msg->AddMessage(str);
}
else{
msg->AddMessage(wxT("Open File Fail!"));
}
}

void Frame::OnStartDriver(wxCommandEvent &event)
{
msg->AddMessage(wxT("********************Load Driver!********************"));

DWORD error = 0;

SC_HANDLE mgr = NULL;

mgr = OpenSCManagerW(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if(mgr == NULL){
wxString str;
str.Printf(wxT("OpenSCManager Error:%d"),error);
msg->AddMessage(str);
CloseServiceHandle(mgr);
return;
}
else{
msg->AddMessage(wxT("OpenSCManager Success!"));
}

SC_HANDLE ddk = NULL;

ddk = CreateServiceW(mgr,name.wc_str(),name.wc_str(),SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
path.wc_str(),NULL,NULL,NULL,NULL,NULL);

if(ddk ==NULL){
error = GetLastError();

if((error != ERROR_IO_PENDING) && (error != ERROR_SERVICE_EXISTS)){
wxString str;
str.Printf(wxT("CreateService Error:%d"),error);
msg->AddMessage(str);
CloseServiceHandle(mgr);
return;
}

ddk = OpenService(mgr,name.wc_str(),SERVICE_ALL_ACCESS);
if(ddk == NULL){
error = GetLastError();
wxString str;
str.Printf(wxT("OpenService Error Code:%d"),error);
msg->AddMessage(str);
CloseServiceHandle(mgr);
return;
}
else{
msg->AddMessage(wxT("OpenService Success!"));
}
}
else{
msg->AddMessage(wxT("CreateService Success!"));
}

error = StartServiceW(ddk,NULL,NULL);

if(!error){
error = GetLastError();

if((error != ERROR_IO_PENDING) && (error != ERROR_SERVICE_EXISTS)){
wxString str;
str.Printf(wxT("StartService Error:%d"),error);
msg->AddMessage(str);
CloseServiceHandle(mgr);
CloseServiceHandle(ddk);
return;
}
else{
if(error == ERROR_IO_PENDING){
msg->AddMessage(wxT("StartService ERROR_IO_PENDING!"));
CloseServiceHandle(mgr);
CloseServiceHandle(ddk);
return;
}
else{
msg->AddMessage(wxT("StartService Fail ERROR_SERVICE_ALREADY_RUNNING!"));
CloseServiceHandle(mgr);
CloseServiceHandle(ddk);
return;
}
}
}
else{
msg->AddMessage(wxT("StartService Success!"));
}

if(mgr){
CloseServiceHandle(mgr);
}
if(ddk){
CloseServiceHandle(ddk);
}
}

void Frame::OnStopDriver(wxCommandEvent &event)
{
msg->AddMessage(wxT("********************Unload Driver!********************"));

DWORD error = 0;

SC_HANDLE mgr = NULL;

mgr = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

if(mgr == NULL){
wxString str;
str.Printf(wxT("OpenSCManager Error:%d"),error);
msg->AddMessage(str);
return;
}
else{
msg->AddMessage(wxT("OpenSCManager Success!"));
}

SC_HANDLE ddk = NULL;

ddk = OpenService(mgr,name.wc_str(),SERVICE_ALL_ACCESS);

if(ddk == NULL){
error = GetLastError();
wxString str;
str.Printf(wxT("OpenService Error Code:%d"),error);
msg->AddMessage(str);
CloseServiceHandle(mgr);
return;
}
else{
msg->AddMessage(wxT("OpenService Success!"));
}

SERVICE_STATUS status;

if(!ControlService(ddk,SERVICE_CONTROL_STOP,&status)){
error = GetLastError();
wxString str;
str.Printf(wxT("ControlService Error Code:%d"),error);
msg->AddMessage(str);
}
else{
msg->AddMessage(wxT("ControlService Success!"));
}

if(!DeleteService(ddk)){
error = GetLastError();
wxString str;
str.Printf(wxT("DeleteService Error Code:%d"),error);
msg->AddMessage(str);
}
else{
msg->AddMessage(wxT("DeleteService Success!"));
}

if(mgr){
CloseServiceHandle(mgr);
}
if(ddk){
CloseServiceHandle(ddk);
}
}

void Frame::OnExit(wxCommandEvent &event)
{
Close();
}

MSGList::MSGList(wxWindow *parent):wxListCtrl(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxLC_REPORT | wxLC_SINGLE_SEL)
{
item_num = 0;

wxListItem item;
item.SetText(wxT("Message"));
InsertColumn(COLUMN_0,item);
SetColumnWidth(COLUMN_0,600);
}

void MSGList::AddMessage(const wxString &msg)
{
InsertItem(item_num,msg,COLUMN_0);
++item_num;
}


測試用
TestDriver.cpp


extern "C"{
#include <ntddk.h>
}

void Unload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING Win32Device;

DbgPrint("Unload Driver!\n");

RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\TestDriver");

IoDeleteSymbolicLink(&Win32Device);

IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS Create(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

DbgPrint("Create Device\n");

return STATUS_SUCCESS;
}

NTSTATUS Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

DbgPrint("Close Device\n");

return STATUS_SUCCESS;
}

NTSTATUS DefaultHandler(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

DbgPrint("Default Handler\n");

return Irp->IoStatus.Status;
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNICODE_STRING DeviceName,Win32Device;
PDEVICE_OBJECT DeviceObject = NULL;
NTSTATUS status;

DbgPrint("Load Driver!\n");

RtlInitUnicodeString(&DeviceName,L"\\Device\\TestDriver");
RtlInitUnicodeString(&Win32Device,L"\\DosDevices\\TestDriver");

for(unsigned i = 0;i <= IRP_MJ_MAXIMUM_FUNCTION;++i){
DriverObject->MajorFunction[i] = DefaultHandler;
}

DriverObject->MajorFunction[IRP_MJ_CREATE] = Create;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Close;

DriverObject->DriverUnload = Unload;

status = IoCreateDevice(DriverObject,10,&DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject);

if(!NT_SUCCESS(status)){
return status;
}
if(!DeviceObject){
return STATUS_UNEXPECTED_IO_ERROR;
}

DeviceObject->Flags |= DO_DIRECT_IO;

status = IoCreateSymbolicLink(&Win32Device,&DeviceName);

DriverObject->Flags &= ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;
}


測試用
UserLayer.cpp


#include <windows.h>
#include <tchar.h>

#include <cstdio>

int main(void)
{
HANDLE h = CreateFile(_T("\\\\.\\TestDriver"),GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

if(h == INVALID_HANDLE_VALUE){
printf("CreateFile Failed!\n");
return -1;
}
else{
printf("CreateFile Success!\n");
}

CloseHandle(h);

getchar();
return 0;
}


沒有留言:

張貼留言