Sunday, May 12, 2013

AttachedDevice和NextDevice

VOID DetachSomeDevFromTargetDriver(PDRIVER_OBJECT pOwnerDrvObject)
{
PDEVICE_OBJECT pDevObj,pNextDev;

if (pOwnerDrvObject)
{
   //取第一个设备
   pNextDev=pOwnerDrvObject->DeviceObject;
   do
   {
    pDevObj=pNextDev;
   
while(pDevObj->AttachedDevice)
    {

     if (IsSomeDevice(pDevObj->AttachedDevice))
     {
      DbgPrint("Detaching Device:0x%08X\n",pDevObj->AttachedDevice);
      IoDetachDevice(pDevObj);     }
     else
     {
      pDevObj=pDevObj->AttachedDevice;//若不是,取上一层设备
     }
    }
    pNextDev=pNextDev->NextDevice;
   } while(pNextDev);
}
}

DriverEntry


NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath):
    _DRIVER_OBJECT:
        DriverName: 一般为\Driver\<驱动名称>(与设备命名规则类似:\Device\<设备名称>)
        PUNICODE_STRING HardwareDatabase:指向注册表中硬件配置信息的路径,用Unicode字符串表示。该字符串内容一般为\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM。
    RegistryPath:
8660f008  5c 00 52 00 45 00 47 00-49 00 53 00 54 00 52 00  \.R.E.G.I.S.T.R.
8660f018  59 00 5c 00 4d 00 41 00-43 00 48 00 49 00 4e 00  Y.\.M.A.C.H.I.N.
8660f028  45 00 5c 00 53 00 59 00-53 00 54 00 45 00 4d 00  E.\.S.Y.S.T.E.M.
8660f038  5c 00 43 00 6f 00 6e 00-74 00 72 00 6f 00 6c 00  \.C.o.n.t.r.o.l.
8660f048  53 00 65 00 74 00 30 00-30 00 31 00 5c 00 53 00  S.e.t.0.0.1.\.S.
8660f058  65 00 72 00 76 00 69 00-63 00 65 00 73 00 5c 00  e.r.v.i.c.e.s.\.
8660f068  48 00 65 00 6c 00 6c 00-6f 00 57 00 44 00 4d 00  H.e.l.l.o.W.D.M.

节选自<<张帆>>:驱动加载的时候,系统进程启动新的线程,利用对象管理器创建_DRIVER_OBJECT,利用配置管理器获取RegistryPath(如果以后想用这个字符串,需要复制到安全的地方)

 

Friday, May 10, 2013

Aeroplan简介


 
Groupe Aeroplan started to conduct business under the new brand name Aimia. While the names and brand identities of our consumer facing brands Aeroplan in Canada, Nectar in Chile, Italy and the UK, and so on
 
通过加拿大航空或者合作联盟购票可以获得积分((订往返可以获得更多积分)
预定酒店、乘船、租车、泊车、渡假套餐、火车旅行(与Rail Europe合作)、商场购物等可以获得积分(需要有合作关系)

aeroplan配置可以上aeroplan.com/profile

aeroplan的合作者可以上aeroplan.com/earnmiles查。

aeroplan使用积分可以上aeroplan.com/useyourmiles

Sunday, May 5, 2013

DosDevices

DosDevices
there is one global \DosDevices directory and multiple local \DosDevices directories.The global \DosDevices directory holds the MS-DOS device names that are visible system-wide.A local \DosDevices directory holds MS-DOS device names that are visible only in a particular local DosDevices context(see below to understand local DosDevices context).

each logon session has its own local DosDevices context,If a user mounts a network drive as X:, only himself can see this。

Each thread has a current DosDevices context, which can change over the lifetime of a thread.

when the object manager looks up a name in \DosDevices, it first searches the local \DosDevices directory, and then the global \DosDevices directory.

A driver that must create its MS-DOS device names in the global \DosDevices directory can do so by creating its symbolic links in a standard driver routine that is guaranteed to run in a system thread context, such as DriverEntry{RtlInitUnicodeString(&symbolicLinkName, L"\\DosDevices\\Global\\SymbolicLinkName");}.
When a thread in a particular local DosDevices context sends an IOCTL, the driver's DispatchDeviceControl is called from within the current thread context. A driver can create MS-DOS device names in a local \DosDevices directories by creating the symbolic link in response to the IOCTL.

On Windows XP and later, local \DosDevices directories are identified by the AuthenticationID for the logon session's access token.

Windows驱动编写注意事项

有些C语言运行时函数如strcpy可以用在驱动中(因为该函数不依赖Windows API实现),但是建议使用内核态的运行时函数。

C++可以实现操作符重载,所以重载的new操作符有可能用在驱动中,但是驱动开发不建议使用C++.

开发时尽量采用checked版本,这样可以用windbg进行源码级调试

makefile文件一般只包含一行(!INCLUDE $(NTMAKEENV)\makefile.def)即可,如果要修改请参考ms-help://MS.WDK.v10.7600.090618.01/DevTest_g/hh/DevTest_g/Build_Ref_31c38413-df20-4483-aa9c-16353d9d82fa.xml.htm或者在wdk中搜索MAKEFILE.INC然后链接过去

如果不明确规定,当前目录下所有源码都会被编译,否则可以编写dirs文件,下面是一个例子:
    DIRS= \
         1394 \
         audio \
         AVStream \
         biometrics
dirs文件和sources文件配合使用,详见ms-help://MS.WDK.v10.7600.090618.01/DevTest_g/hh/DevTest_g/Build_Ref_78947534-363a-4a43-bc39-5e26c9c05449.xml.htm或者在wdk中搜索TARGETNAME后链接过去

还有一个MAKEFILE.INC可选文件,在wdk中搜索MAKEFILE.INC可以获得帮助信息

由于DbgPrint无法在FreeBuild中使用,所以建议使用KdPrint,该宏定义如下:
#if DBG
#define KdPrint(_x_) DbgPrint _x_
#else
#define KdPrint(_x_)
#endif
所以KdPrint((_x_))会转成DbgPrint(_x_),如果用KdPrint(_x_)则会出错。

符号链接最好用"\?\"的形式,为了兼容以前的驱动,'\DosDevices\'的形式在逻辑是等效的,从应用程序中访问驱动用"\.\"的形式。

如果驱动需要频繁地分配和回收固定大小的内存,为了避免产生内存碎片,windows提供了Lookaside内存。

RtlCopyMemory用于源和目标内存不重合的情况,RtlMoveMemory用于二者有交叉的情况,二者的关系相当于memcpy和memmove





Friday, May 3, 2013

windows架构综述

首先声明,本文并非原创,只是对大牛先辈们的文章的收集整理,如有错误,欢迎指正。另外,如无特别说明,本文的概念都适用于32位的windows xp和windows 2003(其他的我不知道)。

Ring3层:
即应用层,该层的应用程序使用各自的子系统进行编程,最核心的子系统是Win32子系统,其他子系统如Posix的API最终要转化为Win32 API;最值得一提的是Wow(windows on windows)子系统,该子系统是为了16位windows程序而设计(同理,该子系统下的程序最终转化为Win32调用)。

Win32 API主要分为三类:User函数(管理图形组件如窗体、菜单、按钮)、GDI函数(提供函数在物理设备上画图)、KERNEL函数(管理进程、文件和通信等)。不管哪类API,都要转化为Native API,(所有)Native API都定义在Ntdll.dll中。NativeAPI通过int 2e(或者sysenter)软中断进行系统调用, 它定义在Ring3,是进入Ring0的窗口。

系统调用会存放在两个表中,第一个是SSDT(KeServiceDescriptorTable),第二个是Shadow SSDT(KeServiceDescriptorTableShadow),前者实现KERNEL函数需要的功能(在ntoskrnl.exe、ntkrnlmp.exe(对称处理器)、ntkrnlpa.exe(物理地址扩展)或者ntkrpamp.exe中),后者实现User函数和GDI函数的功能(放在win32k.sys,后者应该是前者的超集)。Native API通常由Zw或者Nt开头,与系统调用的名字相同(Zw和Nt开头函数在r3(ntdll)中的定义是完全一致的,但在r0中,Nt开头的函数是真正的实现,Zw开头的函数通过SSDT调用其对应的Nt函数)。

Ring0层:
Ring0层分为执行体、内核和驱动程序。

执行体分为对象管理器、进程管理器、虚拟内存管理器、I/O管理器和配置管理器。
对象管理器管理Windows定义的某些数据结构的创建、管理和回收,这些结构中的某些成员可以被读写,相当于公有成员,其他的相当于私有成员,对象管理器提供例程来访问私有成员。
I/O管理器负责创建IRP(IO请求包),IRP由用户或者系统发起,由IO管理器创建,由驱动程序响应(当然,驱动也可以进一步创建IRP给更底层的驱动)。
配置管理器管理注册表。

和执行体相比,内核是非常小的,它主要提供如下功能:
线程调度
对多处理器同步
对中断、异常和陷阱响应

驱动程序用来操作设备。有些设备是虚拟出来的比如虚拟光驱设备,有些设备是真实设备派生出来的设备,比如卷设备,一个分区对应一个卷设备,所有对卷设备的操作由卷驱动最终转化为对磁盘驱动的请求。