天书夜读-4——笔记

第四章讲了基本的结构函数为后面打基础,Nothing replace hardworking。这里就只copy下MSDN,多写代码才是迅速提高的途径

不知道天书夜读错误更正更新了没有, KdPrint应该是错的 DbgPrint##a是个啥东东啊

wdm.h是这样的

#define KdPrint(_x_) DbgPrint _x_
#define KdPrintEx(_x_) DbgPrintEx _x_

*******************************************************************

英语不好,努力学习,单词量不够需要字典帮助,呵呵,不过阅读理解还可以哦

*******************************************************************

驱动开发中,定义的Unicode字符串
typedef struct _UNICODE_STRING
{
USHORT Length;  //字符串长度(字节 数)
USHORT MaximumLength;//字符串缓冲区的饿长度(字节数)
PWSTR  Buffer;  //字符串缓冲区
} UNICODE_STRING,*PUNICODE_STRING;
typedef struct __STRING
{
USHORT Length;  //字符串长度(字节 数)
USHORT MaximumLength;//字符串缓冲区的饿长度(字节数)
PSTR  Buffer;  //字符串缓冲区
} ANSI_STRING,*PANSI_STRING;
驱动中常用Unicode字符串,ANSI字符串仅限于窄字符场合

1、初始化Unicode字符串
1.1 RTL_CONSTANT_STRING
The RTL_CONSTANT_STRING macro creates a string or Unicode string structure to hold a counted string.

STRING
  RTL_CONSTANT_STRING (
    PCSZ SourceString
    );

UNICODE_STRING
  RTL_CONSTANT_STRING (
    PCWSTR SourceString
    );


Parameters
SourceString
Pointer to a NULL-terminated string to initialize the counted string with.
Return Value
RTL_CONSTANT_STRING returns either a string structure or Unicode string structure.

Comments
The RTL_CONSTANT_STRING macro replaces the RtlInitAnsiString, RtlInitString, and RtlInitUnicodeString routines when passing a constant string.

You can use RTL_CONSTANT_STRING to initialize global variables.

Requirements
Headers: Declared in ntdef.h. Include wdm.h or ntddk.h.
1.2 RtlInitUnicodeString
The RtlInitUnicodeString routine initializes a counted Unicode string.

VOID
  RtlInitUnicodeString(
    IN OUT PUNICODE_STRING  DestinationString,
    IN PCWSTR  SourceString
    );


Parameters
DestinationString
Pointer to the UNICODE_STRING structure to be initialized.
SourceString
Pointer to a null-terminated Unicode string with which to initialize the counted string.

Return Value
None

Comments
The Buffer member of DestinationString is initialized to point to SourceString. The length and maximum length for DestinationString are initialized to the length of SourceString. If SourceString is NULL, the length is zero.

Callers of RtlInitUnicodeString can be running at IRQL <= DISPATCH_LEVEL if the DestinationString buffer is nonpageable. Usually, callers run at IRQL = PASSIVE_LEVEL because most other RtlXxxString routines cannot be called at IRQL > PASSIVE_LEVEL.

Requirements
IRQL: (See Comments section)

Headers: Declared in wdm.h. Include wdm.h, ntddk.h, or ntifs.h.

See Also
RtlInitAnsiString, RtlInitString, UNICODE_STRING
1.3空字符
RtlInitEmptyUnicodeString
The RtlInitEmptyUnicodeString macro initializes an empty counted Unicode string.

VOID
  RtlInitEmptyUnicodeString(
    IN OUT PUNICODE_STRING  DestinationString,
    IN PCWSTR  Buffer,
    IN USHORT  BufferSize
    );


Parameters
DestinationString
Pointer to the UNICODE_STRING structure to be initialized.
Buffer
Pointer to a caller-allocated buffer to be used to contain a WCHAR string.
BufferSize
Length, in bytes, of the buffer that Buffer points to.

Return Value
None.

Comments
The members of the structure that the DestinationString parameters points to are initialized as follows.

Member Value
Length Zero
MaximumLength BufferSize
Buffer SourceString


To initialize a non-empty counted Unicode string, call RtlInitUnicodeString.

Requirements
Versions: Available on Microsoft Windows XP and later operating systems.

IRQL: Any level

Headers: Declared in wdm.h. Include wdm.h
***************************************************
RtlInitEmptyString
RtlInitEmptyAnsiString
The RtlInitEmptyAnsiString macro initializes an empty counted ANSI string.

VOID
  RtlInitEmptyAnsiString(
    IN OUT PANSI_STRING  DestinationString,
    IN PCWSTR  Buffer,
    IN USHORT  BufferSize
    );


Parameters
DestinationString
Pointer to the ANSI_STRING structure to be initialized.
Buffer
Pointer to a caller-allocated buffer to be used to contain a WCHAR string.
BufferSize
Length, in bytes, of the buffer that Buffer points to.
Return Value
None.

Comments
The members of the structure that the DestinationString parameter points to are initialized as follows.

Member Value
Length Zero
MaximumLength BufferSize
Buffer SourceString


To initialize a non-empty counted Unicode string, call RtlInitAnsiString.

Requirements
Versions: Available on Microsoft Windows XP and later operating systems.

IRQL: Any level

Headers: Declared in wdm.h. Include wdm.h.
2、字符串拷贝
2.1 RtlCopyUnicodeString
The RtlCopyUnicodeString routine copies a source string to a destination string.

VOID
  RtlCopyUnicodeString(
    IN OUT PUNICODE_STRING  DestinationString,
    IN PUNICODE_STRING  SourceString
    );


Parameters
DestinationString
Pointer to the destination string buffer.
SourceString
Pointer to the source string buffer.

Return Value
None

Comments
If the source string is longer than the destination string, this routine copies bytes from the source to the end of the destination buffer, effectively truncating the copied source string.

Requirements
IRQL: >=DISPATCH_LEVEL

Headers: Declared in wdm.h. Include wdm.h, ntddk.h, or ntifs.h.

See Also
RtlCopyString
2.2 RtlCopyString
The RtlCopyString routine copies a source string to a destination string.

VOID
  RtlCopyString(
    IN OUT PSTRING  DestinationString,
    IN PSTRING  SourceString  OPTIONAL
    );


Parameters
DestinationString
Pointer to the destination string buffer.
SourceString
Pointer to the source string buffer.

Return Value
None

Comments
The DestinationString Length is set to zero if no source string is supplied, but this does not affect the length of the DestinationString buffer. The MaximumLength and Buffer members of the DestinationString are not modified by this routine.

The number of bytes copied from the SourceString is either the length of SourceString or the maximum length of DestinationString, whichever is smaller.

Requirements
IRQL: >=DISPATCH_LEVEL

Headers: Declared in ntddk.h. Include ntddk.h
3、连接字符串
3.1 RtlAppendUnicodeToString
The RtlAppendUnicodeToString routine concatenates the supplied Unicode string to a buffered Unicode string.

NTSTATUS
  RtlAppendUnicodeToString(
    IN OUT PUNICODE_STRING  Destination,
    IN PCWSTR  Source
    );


Parameters
Destination
Pointer to the buffered string.
Source
Pointer to the string to be appended to the Destination string.
Return Value
RtlAppendUnicodeToString can return one of the following:

STATUS_SUCCESS
The source string was successfully appended to the destination counted string. The destination string length is updated to include the appended bytes.
STATUS_BUFFER_TOO_SMALL
The destination string length was too small to allow the source string to be appended, so the destination string length is not updated.

Comments
RtlAppendUnicodeToString copies bytes from the source string to the destination string up to the end of the destination buffer.

Requirements
IRQL: >=DISPATCH_LEVEL

Headers: Declared in wdm.h. Include wdm.h, ntddk.h, or ntifs.h.

See Also
RtlAppendUnicodeStringToString
3.2 RtlAppendUnicodeStringToString
The RtlAppendUnicodeStringToString routine concatenates two Unicode strings.

NTSTATUS
  RtlAppendUnicodeStringToString(
    IN OUT PUNICODE_STRING  Destination,
    IN PUNICODE_STRING  Source
    );


Parameters
Destination
Pointer to a buffered Unicode string.
Source
Pointer to the buffered string to be concatenated.
Return Value
RtlAppendUnicodeStringToString can return one of the following:

STATUS_SUCCESS
The source string was successfully appended to the destination counted string. The destination string length is updated to include the appended bytes.
STATUS_BUFFER_TOO_SMALL
The destination string length is too small to allow the source string to be concatenated. Accordingly, the destination string length is not updated.

Comments
RtlAppendUnicodeStringToString copies bytes from the source up to the length of the destination buffer.

Requirements
IRQL: >=DISPATCH_LEVEL

Headers: Declared in wdm.h. Include wdm.h, ntddk.h, or ntifs.h.

4字符串的打印
RtlStringCbPrintfW,在缓冲区不足的时候依然可以打印,返回值为STATUS_BUFFER_OVERFLOW,同系列的函数太多了不一一列举
WDM.h中定义了KdPrint及KdPrintEx
#define KdPrint(_x_) DbgPrint _x_
#define KdPrintEx(_x_) DbgPrintEx _x_
书上写错了
5、内存分配和释放
5.1 ExAllocatePoolWithTag
The ExAllocatePoolWithTag routine allocates pool memory of the specified type and returns a pointer to the allocated block.

PVOID
  ExAllocatePoolWithTag(
    IN POOL_TYPE  PoolType,
    IN SIZE_T  NumberOfBytes,
    IN ULONG  Tag
    );


Parameters
PoolType
Specifies the type of pool memory to allocate. Each allocation code path should use a unique pool tag to help debuggers and verifiers identify the code path. You can modify the PoolType value by using a bitwise OR with the POOL_RAISE_IF_ALLOCATION_FAILURE flag. This flag causes an exception to be raised if the request cannot be satisfied.
Similarly, you can modify PoolType by using a bitwise OR with the POOL_COLD_ALLOCATION flag as a hint to the kernel to allocate the memory from pages that are likely to be paged out quickly. To reduce the amount of resident pool memory as much as possible, you should not reference these allocations frequently. The POOL_COLD_ALLOCATION flag is only advisory and is available for Microsoft Windows XP and later operating systems. For a description of the available pool memory types, see POOL_TYPE.

NumberOfBytes
Specifies the number of bytes to allocate.
Tag
Specifies the pool tag for the allocated memory. Specify the pool tag as a character literal of up to four characters delimited by single quotation marks (for example, 'Tag1'). The string is usually specified in reverse order (for example, '1gaT'). The ASCII value of each character in the tag must be between 0 and 127. Every allocation code path should use a unique pool tag to ensure that debuggers and verifiers identify a distinct allocated block.

Return Value
ExAllocatePoolWithTag returns NULL if there is insufficient memory in the free pool to satisfy the request unless POOL_RAISE_IF_ALLOCATION_FAILURE is specified. Otherwise, the routine returns a pointer to the allocated memory.

Comments
This routine is used for the general pool allocation of memory.

If NumberOfBytes is PAGE_SIZE or greater, a page-aligned buffer is allocated. Memory allocations of PAGE_SIZE or less do not cross page boundaries. Memory allocations of less than PAGE_SIZE are not necessarily page-aligned but are aligned on an 8-byte boundary.

A successful allocation requesting NumberOfBytes < PAGE_SIZE of nonpaged pool gives the caller exactly the number of requested bytes of memory. Any successful allocation that requests NumberOfBytes > PAGE_SIZE wastes all unused bytes on the last-allocated page.

The system associates the pool tag with the allocated memory. Programming tools, such as WinDbg, can display the pool tag associated with each allocated buffer. Gflags, a tool included in Debugging Tools for Windows, turns on a system feature that requests allocation from special pool for a particular pool tag. Poolmon, which is included in the WDK, tracks memory by pool tag.

The value of Tag is stored, and sometimes displayed, in reverse (little-endian) order. For example, if a caller passes 'Fred' as a Tag, it appears as 'derF' in a pool dump and in pool usage tracking in the debugger, and as 0x64657246 in the registry and in tool displays.

The allocated buffer can be freed with either ExFreePool or ExFreePoolWithTag.

The system automatically sets certain standard event objects when the amount of pool (paged or nonpaged) is high or low. Drivers can wait for these events to tune their pool usage. For more information, see Standard Event Objects.

Callers of ExAllocatePoolWithTag must be executing at IRQL <= DISPATCH_LEVEL. A caller executing at DISPATCH_LEVEL must specify a NonPagedXxx value for PoolType. A caller executing at IRQL <= APC_LEVEL can specify any POOL_TYPE value.

Warning  Memory that ExAllocatePoolWithTag allocates is uninitialized. A kernel-mode driver must first zero this memory if it is going to make it visible to user-mode software (to avoid leaking potentially privileged contents).


Requirements
Headers: Declared in Wdm.h. Include Wdm.h, Ntddk.h, or Ntifs.h.
6链表
6.1 LIST_ENTRY
A LIST_ENTRY structure describes an entry in a doubly-linked list or serves as the header for such a list.

typedef struct _LIST_ENTRY {
  struct _LIST_ENTRY *Flink;
  struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;


Members
Flink
For a LIST_ENTRY structure that serves as a list entry, the Flink member points to the next entry in the list or to the list header if there is no next entry in the list.
For a LIST_ENTRY structure that serves as the list header, the Flink member points to the first entry in the list or to the LIST_ENTRY structure itself if the list is empty.

Blink
For a LIST_ENTRY structure that serves as a list entry, the Blink member points to the previous entry in the list or to the list header if there is no previous entry in the list.
For a LIST_ENTRY structure that serves as the list header, the Blink member points to the last entry in the list or to the LIST_ENTRY structure itself if the list is empty.

Comments
A LIST_ENTRY structure that describes the list head must have been initialized by calling InitializeListHead.

A driver can access the Flink or Blink members of a LIST_ENTRY, but the members must only be updated by the system routines supplied for this purpose.

For more information about how to use LIST_ENTRY structures to implement a doubly-linked list, see Singly- and Doubly-Linked Lists.

Requirements
Headers: Declared in ntdef.h. Include Wdm.h or Ntddk.h.
7 LARGE_INTEGER
LARGE_INTEGER Union

The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.

Note  Your C compiler may support 64-bit integers natively. For example, Microsoft Visual C++ supports the __int64 sized integer type. For more information, see the documentation included with your C compiler.


Syntax
typedef union _LARGE_INTEGER {  struct {    DWORD LowPart;    LONG HighPart;  };  struct {    DWORD LowPart;    LONG HighPart;  } u;  LONGLONG QuadPart;
} LARGE_INTEGER,  *PLARGE_INTEGER;
Members
LowPart
Low-order 32 bits.

HighPart
High-order 32 bits.

u
LowPart
Low-order 32 bits.

HighPart
High-order 32 bits.

QuadPart
Signed 64-bit integer.

Remarks
The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers, use the QuadPart member to store the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.

Requirements
Client Requires Windows Vista, Windows XP, or Windows 2000 Professional.
Server Requires Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
Header Declared in Winnt.h; include Windows.h.

8 Spin Locks
Introduction to Spin Locks
Spin locks are kernel-defined, kernel-mode-only synchronization mechanisms, exported as an opaque type: KSPIN_LOCK. A spin lock can be used to protect shared data or resources from simultaneous access by routines that can execute concurrently and at IRQL >= DISPATCH_LEVEL in SMP machines.

Many components use spin locks, including drivers. Any kind of driver might use one or more executive spin locks. For example, most file systems use an interlocked work queue in the FSD's device extension to store IRPs that are processed both by the file system's worker-thread callback routines and by the FSD. An interlocked work queue is protected by an executive spin lock, which resolves contention among the FSD trying to insert IRPs into the queue and any threads simultaneously trying to remove IRPs. As another example, the system floppy controller driver uses two executive spin locks. One executive spin lock protects an interlocked work queue shared with this driver's device-dedicated thread; the other protects a timer object shared by three driver routines.

Drivers for Microsoft Windows XP and later operating systems can use KeAcquireInStackQueuedSpinLock and KeReleaseInStackQueuedSpinLock to acquire and release the spin lock as a queued spin lock. Queued spin locks provide better performance than ordinary spin locks for high contention locks on multiprocessor machines. For more information, see Queued Spin Locks. Drivers for Windows 2000 can use KeAcquireSpinLock and KeReleaseSpinLock to acquire and release a spin lock as an ordinary spin lock.

To synchronize access to simple data structures, drivers can use any of the ExInterlockedXxx routines to ensure atomic access to the data structure. Drivers that use these routines do not need to acquire or release the spin lock explicitly.

Every driver that has an ISR uses an interrupt spin lock to protect any data or hardware shared between its ISR and its SynchCritSection routines that are usually called from its StartIo and DpcForIsr routines. An interrupt spin lock is associated with the set of interrupt objects created when the driver calls IoConnectInterrupt, as described in Registering an ISR.

Follow these guidelines for using spin locks in drivers:
Provide the storage for any data or resource protected by a spin lock and for the corresponding spin lock in resident system-space memory (nonpaged pool, as shown in the Virtual Memory Spaces and Physical Memory figure). A driver must provide the storage for any executive spin locks it uses. However, a device driver need not provide the storage for an interrupt spin lock unless it has a multivector ISR or has more than one ISR, as described in Registering an ISR.
Call KeInitializeSpinLock to initialize each spin lock for which the driver provides storage before using it to synchronize access to the shared data or resource it protects.
Call every support routine that uses a spin lock at an appropriate IRQL, generally at <= DISPATCH_LEVEL for executive spin locks or at <= DIRQL for an interrupt spin lock associated with the driver's interrupt objects.
Implement routines to execute as quickly as possible while they hold a spin lock. No routine should hold a spin lock for longer than 25 microseconds.
Never implement routines that do any of the following while holding a spin lock:
Cause hardware exceptions or raise software exceptions
Attempt to access pageable memory
Make a recursive call that would cause a deadlock or could cause a spin lock to be held for longer than 25 microseconds
Attempt to acquire another spin lock if doing so might cause a deadlock
Call an external routine that violates any of the preceding rules


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值