Kỹ thuật lập trình hỗn hợp (Miscellaneous Programming Techniques )
Truy cập vào Registry Windows XP và Windows 98/Me ghi lại cấu hình và các thông tin quan trọng trong một cơ sở dữ liệu gọi là đăng ký. WDM trình điều khiển có thể gọi các chức năng được liệt kê trong bảng 3-10 để truy cập các đăng ký. Nếu bạn đã thực ...
Truy cập vào Registry
Windows XP và Windows 98/Me ghi lại cấu hình và các thông tin quan trọng trong một cơ sở dữ liệu gọi là đăng ký. WDM trình điều khiển có thể gọi các chức năng được liệt kê trong bảng 3-10 để truy cập các đăng ký. Nếu bạn đã thực hiện chế độ người dùng truy cập chương trình liên quan đến đăng ký, bạn có thể có thể đoán như thế nào để sử dụng các chức năng trong một driver. Tôi được tìm thấy hạt nhân-chế độ hỗ trợ đầy đủ các chức năng khác nhau, tuy nhiên, tôi nghĩ rằng giá trị của nó mô tả cách nào bạn có thể sử dụng chúng.
Trong phần này, tôi sẽ thảo luận, trong số những thứ khác, các gia đình của ZwXxx thói quen và RtlDeleteRegistryValue, mà cung cấp các chức năng cơ bản đăng ký rằng suffices cho hầu hết các trình điều khiển WDM.
Mở ra một registry key
Trước khi bạn có thể interrogate giá trị trong việc đăng ký, bạn cần phải mở các khoá có chứa chúng. Bạn sử dụng vào ZwOpenKey mở một chìa khóa hiện tại. ZwCreateKey bạn sử dụng để mở hoặc một trọng điểm hiện tại hoặc để tạo ra một khoá mới. Hoặc chức năng cần thiết bạn đầu tiên khởi tạo một OBJECT_ATTRIBUTES cơ cấu với tên của chủ chốt và (có lẽ) các thông tin khác. OBJECT_ATTRIBUTES các cấu trúc đã công bố sau đây:
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
Hơn là khởi tạo một dụ của cấu trúc này bằng tay, nó dễ để sử dụng InitializeObjectAttributes vĩ mô, mà tôi tin về bạn để hiển thị.
Giả, ví dụ, rằng chúng tôi muốn mở các dịch vụ chủ chốt cho các driver của chúng tôi. The I / O Trưởng đại diện cho chúng tôi tên của khoá này như là một tham số để DriverEntry. Vì vậy, chúng tôi có thể viết mã như sau:
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE │
OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE hkey;
status = ZwOpenKey(&hkey, KEY_READ, &oa);
if (NT_SUCCESS(status))
{
ZwClose(hkey);
}
}
1. Chúng tôi đang bắt đầu các đối tượng thuộc tính cơ cấu pathname đăng ký với chúng tôi bằng cách cung cấp cho các I / O Trưởng đại diện và bảo mật với một NULL descriptor. ZwOpenKey sẽ bỏ qua các an ninh descriptor anyway-bạn có thể xác định thuộc tính bảo mật chỉ khi bạn tạo một chìa khóa cho lần đầu tiên.
2. ZwOpenKey sẽ mở khoá cho đọc và lưu trữ các kết quả xử lý của chúng tôi trong hkey biến.
3. ZwClose là một thói quen chung cho đóng một để xử lý một hạt nhân-chế độ đối tượng. Đây, chúng tôi sử dụng nó để đóng trình xử lý chúng tôi đã đăng ký vào chìa khóa.
Các OBJ_KERNEL_HANDLE cờ, hiển thị trong mẫu mã trước, là rất quan trọng cho các hệ thống tích hợp. Nếu bạn đang chạy trong bối cảnh của một người dùng sợi khi bạn gọi ZwOpenKey, và nếu bạn không cung cấp này bit, cờ, các bạn sẽ có được xử lý sẽ được sẵn sàng cho người sử dụng chế độ xử lý. Nó thậm chí có thể xảy ra rằng người sử dụng chế độ-mã sẽ đóng trình xử lý mới và mở ra một đối tượng, lại nhận được cùng một số giá trị. All of a sudden, các cuộc gọi của bạn để đăng ký chức năng sẽ được giao dịch với các sai loại xử lý. Những cách khác để mở registry phím
Ngoài ra vào ZwOpenKey, Windows XP cung cấp hai chức năng cho các phím mở đăng ký.
IoOpenDeviceRegistryKey cho phép bạn mở một trong những phím đặc biệt đăng ký liên kết với một đối tượng điện thoại:
HANDLE hkey;
Status = IoOpenDeviceRegistryKey(pdo, flag, access, &hkey);
nơi pdo là địa chỉ của các đối tượng vật lý điện thoại (PDO) ở dưới cùng của trình điều khiển đặc biệt của bạn stack, cờ là một chỉ cho các khoá đặc biệt mà bạn muốn mở (xem B ng 3-11), và truy cập là một ví dụ như mặt nạ truy cập KEY_READ

Tôi sử dụng IoOpenDeviceRegistryKey với PLUGPLAY_REGKEY_DEVICE cờ rất thường xuyên trong các trình điều khiển của riêng tôi. Trong Windows XP, chức năng này sẽ mở ra những thiết bị subkey Các thông số của phần cứng, chìa khóa cho điện thoại. Trong Windows 98/Me, nó sẽ mở ra phần cứng, chìa khóa riêng của mình. Các phím được đúng nơi để lưu trữ tham số thông tin về phần cứng. Tôi sẽ thảo luận này phím đầy đủ chi tiết trong Chương 15 trong kết nối với các cài đặt và phân phối một driver.
IoOpenDeviceInterfaceRegistryKey sẽ mở ra các phím kết hợp với một dụ của một thiết bị giao diện đăng ký:
HANDLE hkey;
status = IoOpenDeviceInterfaceRegistryKey(linkname, access,
&hkey);
nơi linkname là liên kết tượng trưng tên của đăng ký và truy cập vào giao diện truy cập là một mặt nạ như KEY_READ.
Bắt và cài đặt các giá trị
Thông thường, bạn mở một chìa khóa vì đăng ký mà bạn muốn, để lấy một giá trị từ cơ sở dữ liệu. Các chức năng cơ bản mà bạn sử dụng cho mục đích là ZwQueryValueKey. Ví dụ, để lấy lại giá trị trong imagePath bằng driver dịch vụ chủ chốt-Tôi thật sự không biết lý do tại sao bạn muốn biết này, nhưng đó không phải là bộ phận của tôi-bạn có thể sử dụng các mã sau đây:
UNICODE_STRING valname;
RtlInitUnicodeString(&valname, L"ImagePath");
size = 0;
status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,
NULL, 0, &size);
if (status == STATUS_OBJECT_NAME_NOT_FOUND ││ size == 0)
<handle error>;
size = min(size, PAGE_SIZE);
PKEY_VALUE_PARTIAL_INFORMATION vpip =
PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(PagedPool, size);
if (!vpip)
<handle error>;
status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,
vpip, size, &size);
if (!NT_SUCCESS(status))
<handle error>;
<do something with vpip->Data>ExFreePool(vpip);
Đây, chúng tôi thực hiện hai cuộc gọi để ZwQueryValueKey. Mục đích của cuộc gọi đầu tiên là để xác định bao nhiêu không gian, chúng tôi cần phải phân bổ cho các cơ cấu KEY_VALUE_PARTIAL_INFORMATION chúng tôi đang cố gắng để lấy. Thứ hai, gọi truy thông tin. Tôi còn lại kiểm tra các lỗi trong mã này fragment lỗi vì đã không làm việc trong thực tế ra con đường cho chúng tôi mong đợi. Đặc biệt, tôi đoán rằng các bước đầu tiên để gọi ZwQueryValueKey sẽ trở lại STATUS_BUFFER_TOO_SMALL (kể từ khi tôi qua nó không-một chiều dài đệm). Nó không làm điều đó, mặc dù. Quan trọng là STATUS_OBJECT_NAME_NOT_FOUND mã không thành công, cho thấy giá trị thực sự không tồn tại. Vì vậy, tôi kiểm tra cho rằng chỉ có giá trị. Nếu có một số lỗi khác ngăn cản ZwQueryValueKey từ làm việc, các cuộc gọi thứ hai sẽ uncover nó.
Cái được gọi là "một phần" thông tin trong cơ cấu bạn lấy bằng cách này chứa các giá trị của dữ liệu và một mô tả về một loạt các dữ liệu dạng:
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataLength;
UCHAR Data[1];
} KEY_VALUE_PARTIAL_INFORMATION,
*PKEY_VALUE_PARTIAL_INFORMATION;
Loại hình là một trong những loại dữ liệu đăng ký liệt kê trong bảng 3-12. (Các loại dữ liệu là có thể có nhưng không quan tâm đến trình điều khiển thiết bị.) DataLength là chiều dài của dữ liệu giá trị, và dữ liệu là dữ liệu riêng của mình. TitleIndex không có liên quan đến trình điều khiển. Dưới đây là một số dữ kiện hữu ích để biết về các loại dữ liệu khác nhau:
• REG_DWORD là 32-bit unsigned integer ở định dạng nào (về cuối lớn hay nhỏ cuối) là nền tảng cho tự nhiên.
• REG_SZ mô tả một null-Unicode chấm dứt chuỗi giá trị. The Terminator null được bao gồm trong DataLength truy cập.
• Để mở rộng một REG_EXPAND_SZ có giá trị bằng cách thay biến môi trường, quý vị nên RtlQueryRegistryValues như của bạn sử dụng phương pháp hỏi các đăng ký. Nội bộ cho các thói quen truy cập các biến môi trường không phải là tài liệu hoặc xúc cho sử dụng bởi trình điều khiển.
• RtlQueryRegistryValues cũng là một cách tốt để interrogate REG_MULTI_SZ giá trị trong đó nó sẽ gọi của bạn được xem thường gọi một lần cho mỗi phòng trong số có tiềm năng rất nhiều những dây.
Chú thích:
Mặc dù, rõ ràng ích của RtlQuery ¬ RegistryValues, tôi đã được tránh bằng cách sử dụng nó bao giờ hết, vì nó sẽ gây ra vụ đụng xe trong một trong các trình điều khiển của tôi. Tất nhiên, giá trị tôi đã đọc các chức năng cần thiết để gọi giúp đỡ một chức năng đã được đặt trong sở khởi phần của hạt nhân và đã được, do đó, hiện nay không còn.

Để thiết lập một giá trị đăng ký, bạn phải có KEY_SET_VALUE truy cập vào cha mẹ chìa khóa. Tôi đã sử dụng KEY_READ sớm hơn, đó sẽ không cho bạn truy cập như vậy. Bạn có thể sử dụng KEY_WRITE hay KEY_ALL_ACCESS, mặc dù bạn thu được nhiều hơn do đó cần thiết cho phép. Sau đó, gọi ZwSetValueKey. Ví dụ:
RtlInitUnicodeString(&valname, L"TheAnswer");
ULONG value = 42;
ZwSetValueKey(hkey, &valname, 0, REG_DWORD, &value,
sizeof(value));
Subkeys xóa hoặc giá trị
Để xóa một giá trị trong một chìa khóa mở ra, bạn có thể sử dụng RtlDeleteRegistryValue trong cách đặc biệt sau đây:
RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE, (PCWSTR) hkey,
L"TheAnswer");
RtlDeleteRegistryValue nói chung là một dịch vụ có chức năng đầu tiên đối số có thể chỉ định một trong một số nơi đặc biệt trong các đăng ký. Khi bạn sử dụng RTL_REGISTRY_HANDLE, như tôi đã làm trong ví dụ này, bạn chỉ ra rằng bạn đã có một mở khoá để xử lý trong vòng mà bạn muốn xóa một giá trị. Bạn chỉ rõ trọng điểm (với một ném biên để làm cho hạnh phúc) như là đối số thứ hai. Thứ ba, và cuối cùng là đối số-null chấm dứt Unicode tên của giá trị mà bạn muốn xóa. Đây là một trong những thời gian khi bạn không có để tạo ra một cơ cấu UNICODE_STRING để mô tả chuỗi.
Trong Windows 2000 và sau này, bạn có thể sử dụng ZwDeleteValueKey để xóa một giá trị (nó là một giám sát rằng chức năng này không phải là tài liệu trong DDK):
UNICODE_STRING valname;
RtlInitUnicodeString(&valname, L"TheAnswer");
RtlDeleteValueKey(hkey, &valname);
Bạn có thể xoá chỉ những phím mà bạn đã mở ra với ít nhất là cho phép XOÁ (mà bạn nhận được với KEY_ALL_ACCESS). Gọi ZwDeleteKey bạn:
ZwDeleteKey(hkey);
Chìa khóa cho đến khi cuộc sống trên tất cả các xử lý đang đóng cửa, nhưng các nỗ lực để mở một cửa hàng mới để xử lý các phím hoặc để truy cập vào các phím bằng cách sử dụng bất cứ hiện đang mở xử lý sẽ không thành công với STATUS_KEY_DELETED. Kể từ khi bạn có một mở xử lý tại điểm này, bạn cần phải chắc chắn sẽ được gọi ZwClose sometime. (The DDK tài liệu hướng dẫn cho các mục nhập ZwDeleteKey nói những xử lý sẽ trở thành không hợp lệ. It doesnt-bạn vẫn phải đóng nó bằng cách gọi điện thoại ZwClose.)
Enumerating Subkeys hoặc các giá trị
Một hoạt động phức tạp, bạn có thể thực hiện với một ký mở là chìa khóa để enumerate các yếu tố (subkeys và giá trị) mà có chứa chìa khóa. Để làm được điều này, bạn sẽ thấy đầu tiên gọi ZwQueryKey để xác định một vài thực tế về các subkeys và các giá trị, chẳng hạn như số điện thoại của người, độ dài của tên lớn nhất, và như vậy trên. ZwQueryKey có một đối số cho biết rằng đó của ba loại thông tin bạn muốn tải về các phím. Các loại được đặt tên cơ bản, node, và đầy đủ. Để chuẩn bị cho một Enumeration, bạn muốn được quan tâm đầu tiên trong đầy đủ thông tin:
typedef struct _KEY_FULL_INFORMATION {
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG ClassOffset;
ULONG ClassLength;
ULONG SubKeys;
ULONG MaxNameLen;
ULONG MaxClassLen;
ULONG Values;
ULONG MaxValueNameLen;
ULONG MaxValueDataLen;
WCHAR Class[1];
} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;
Đây thực sự là cơ cấu của biến chiều dài từ Lớp [0] chỉ là những ký tự đầu tiên của tên lớp học. It's phong tục để thực hiện một cuộc gọi để tìm hiểu cách thức lớn, một buffer bạn cần phải phân bổ và một cuộc gọi thứ hai để có được những dữ liệu, như sau:
ULONG size;
ZwQueryKey(hkey, KeyFullInformation, NULL, 0, &size);
size = min(size, PAGE_SIZE);
PKEY_FULL_INFORMATION fip = (PKEY_FULL_INFORMATION)
ExAllocatePool(PagedPool, size);
ZwQueryKey(hkey, KeyFullInformation, fip, size, &size);
Bây giờ bạn đã được quan tâm trong subkeys đăng ky của bạn, bạn có thể thực hiện trong vòng lặp sau đây gọi ZwEnumerateKey:
for (ULONG i = 0; i < fip->SubKeys; ++i)
{
ZwEnumerateKey(hkey, i, KeyBasicInformation, NULL, 0, &size);
size = min(size, PAGE_SIZE);
PKEY_BASIC_INFORMATION bip = (PKEY_BASIC_INFORMATION)
ExAllocatePool(PagedPool, size);
ZwEnumerateKey(hkey, i, KeyBasicInformation, bip, size, &size);
<do something with bip->Name>
ExFreePool(bip);
}
Chìa khóa thực tế, bạn khám phá về mỗi subkey là tên của nó, mà cho thấy tính lên như là một chuỗi Unicode trong cơ cấu KEY_BASIC_INFORMATION bạn lấy bên trong vòng lặp:
typedef struct _KEY_BASIC_INFORMATION {
LARGE_INTEGER LastWriteTime;
ULONG Type;
ULONG NameLength;
WCHAR Name[1];
} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION
Không phải là tên null-chấm dứt, bạn phải sử dụng các NameLength thành thành viên của các cơ cấu để xác định chiều dài của nó. Đừng quên rằng trong chiều dài là byte! Tên là không đầy đủ hoặc đường dẫn đăng ký; điều đó chỉ cần tên của subkey nào trong vòng chìa khóa chứa nó. Đây thật sự là may mắn, bởi vì bạn có thể dễ dàng mở một subkey của nó cho một tên và xử lý để mở các bậc cha mẹ chìa khóa.
Để một Enumeration của các giá trị trong một không gian mở chìa khóa, nhân viên của các phương pháp sau đây:
ULONG maxlen = fip->MaxValueNameLen +
sizeof(KEY_VALUE_BASIC_INFORMATION);
maxlen = min(maxlen, PAGE_SIZE);
PKEY_VALUE_BASIC_INFORMATION vip = (PKEY_VALUE_BASIC_INFORMATION)
ExAllocatePool(PagedPool, maxlen);
for (ULONG i = 0; i < fip->Values; ++i)
{
ZwEnumerateValueKey(hkey, i, KeyValueBasicInformation, vip,
maxlen, &size);
<do something with vip->Name>
}
ExFreePool(vip);
Cấp cho không gian lớn nhất có thể có cấu trúc KEY_VALUE_BASIC_INFORMATION rằng bạn sẽ luôn luôn lấy MaxValueNameLen dựa trên các thành viên của KEY_FULL_INFORMATION cơ cấu. Bên trong vòng tròn, bạn sẽ thấy muốn làm cái gì với tên của giá trị, mà sẽ đến với bạn như là một chuỗi Unicode tính trong cấu trúc này:
typedef struct _KEY_VALUE_BASIC_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG NameLength;
WCHAR Name[1];
} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
Một lần nữa, có tên của một giá trị và mở để xử lý các phụ huynh là chìa khóa chỉ cần những gì bạn cần để lấy lại giá trị, như được hiển thị trong phần trước.
Hiện có các biến thể trên ZwQueryKey và trên hai Enumeration chức năng mà tôi đã không được thảo luận. Bạn có thể, ví dụ, có được đầy đủ thông tin về một subkey khi bạn gọi ZwEnumerateKey. Tôi chỉ cho bạn làm thế nào để có được những thông tin cơ bản bao gồm các tên. Bạn có thể tải dữ liệu chỉ có giá trị, hoặc tên cộng với dữ liệu giá trị, từ ZwEnumerateValueKey. Tôi chỉ cho bạn làm thế nào để có được tên của một giá trị.
Truy cập tập tin
It's đôi khi hữu ích để có thể đọc và viết thường xuyên đĩa file từ bên trong một trình điều khiển WDM. Có lẽ bạn cần phải tải về một số tiền lớn của microcode với phần cứng của bạn, hoặc có lẽ bạn cần phải tạo riêng của bạn rộng lớn của thông tin đăng nhập cho một số mục đích. Có bộ ZwXxx thói quen để giúp bạn làm được những điều đó.
Kích truy cập thông qua các thói quen ZwXxx yêu cầu bạn chạy được tại PAS ¬ SIVE_LEVEL (xem chương kế tiếp) trong một sợi mà có thể an toàn bị treo. Trong thực tế, các yêu cầu sau có nghĩa là bạn phải không có khuyết tật Asynchronous Thủ tục cuộc gọi (APCs) bằng cách gọi điện thoại KeEnterCriticalRegion. Bạn sẽ đọc trong chương kế tiếp rằng một số đồng bộ hóa primitives yêu cầu bạn đến IRQL nâng cao trên PASSIVE_LEVEL hay để vô hiệu hoá APCs. Gấu chỉ cần ghi nhớ rằng những primitives và đồng bộ hóa tập tin không tương đang truy cập.
Mã số mẫu
FILEIO các mẫu trong trình điều khiển, phần nội dung minh hoạ cuộc gọi đến một số trong các chức năng ZwXxx thảo luận trong phần này. Điều này đặc biệt là mẫu rất có giá trị vì nó cung cấp workarounds cho nền tảng không tương thich được đề cập ở phần cuối của chương này.
Hiện tại mở một tệp để đọc, để mở một tệp tin hiện có để bạn có thể đọc nó, hãy làm theo ví dụ này:
NTSTATUS status;
OBJECT_ATTRIBUTES oa;
IO_STATUS_BLOCK iostatus;
HANDLE hfile; // the output from this process
PUNICODE_STRING pathname; // you've been given this
InitializeObjectAttributes(&oa, pathname,
OBJ_CASE_INSENSITIVE │ OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateFile(&hfile, GENERIC_READ, &oa, &iostatus,
NULL, 0, FILE_SHARE_READ, FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
Tạo hoặc viết lại một tệp
Để tạo một tập tin mới, hoặc để mở và truncate để không chiều dài hiện có một tập tin, thay thế các cuộc gọi đến ZwCreateFile trong trước fragment này với một trong:
status = ZwCreateFile(&hfile, GENERIC_WRITE, &oa, &iostatus,
NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
Trong những fragments, chúng tôi thiết lập một cơ cấu có OBJECT_ATTRIBUTES Mục đích chính là điểm đến đầy đủ pathname của tập tin mà chúng tôi đang về để mở. Chúng tôi xác định OBJ_CASE_INSENSITIVE thuộc tính bởi vì Win32 hệ thống tập tin mô hình, không có gì không chữa trị như trường hợp đáng kể trong một pathname. Chúng tôi chỉ định OBJ_KERNEL_HANDLE cho cùng một lý do gì chúng tôi đã làm như vậy trong đăng ký ví dụ hiển thị sớm hơn trong chương này. Sau đó, chúng tôi gọi ZwCreateFile để mở các xử lý.
Lĩnh vực xử lý
Mỗi phòng trong quá trình xử lý tư nhân có một bảng mà gắn với số xử lý các đối tượng đến hạt nhân. Khi bạn mở một ZwCreateFile xử lý bằng cách sử dụng, hoặc NtCreateFile, xử lý mà thuộc về các quy trình hiện tại-sau đó, trừ khi bạn sử dụng OBJ_KERNEL_HANDLE cờ. A-quá trình xử lý cụ thể sẽ đi, nếu quá trình chấm dứt. Hơn nữa, nếu bạn sử dụng các xử lý trong một bối cảnh khác nhau quá trình, bạn sẽ được tham chiếu gián tiếp nào đối tượng (nếu có) cho rằng để xử lý tương ứng trong quá trình khác. Một hạt nhân xử lý, mặt khác, được lưu giữ trong một bảng toàn cầu mà không biến mất, không có gì cho đến khi các hệ điều hành shuts xuống và có thể được sử dụng mà không có bất kỳ ambiguity trong quá trình.
Nếu bạn có kế hoạch để đọc toàn bộ một tập tin vào một bộ nhớ đệm, bạn sẽ thấy rất có thể muốn để kêu gọi các ZwQueryInformationFile để xác định tổng chiều dài của tập tin:
FILE_STANDARD_INFORMATION si;
ZwQueryInformationFile(hfile, &iostatus, &si, sizeof(si),
FileStandardInformation);
ULONG length = si.EndOfFile.LowPart;
Thời gian hoạt động của tập tin
Bạn sẽ có khả năng muốn đọc một đĩa tập tin trong một WDM driver trong khi bạn đang bắt đầu điện thoại của bạn để phản ứng lại một IRP_MN_START_DEVICE yêu cầu. (Xem Chương 6.) Tùy thuộc vào nơi mà điện thoại của bạn té ngã trong sở khởi trình tự, bạn có thể hoặc có thể không có quyền truy cập vào các tập tin bằng cách sử dụng như bình thường pathnames ?? C: dir file.ext. Để được an toàn, đưa các tệp tin dữ liệu của bạn vào một số thư mục dưới đây của hệ thống thư mục gốc và sử dụng như một file SystemRoot dir file.ext. SystemRoot các chi nhánh của các tên này, luôn luôn có thể truy cập từ các hệ điều hành đã để có thể đọc đĩa file để bắt đầu lên.
Trong tất cả các trình điều khiển của tôi, tôi xác định là một tên DRIVERNAME như thế này:
#define DRIVERNAME "xxx"
nơi xxx là tên của một trình điều khiển thiết bị. Nhớ lại rằng thấy hai giáp biên string constants như là một cố định. Trick đặc biệt bằng cách sử dụng này cho phép tôi để cắt và dán toàn bộ subroutines, bao gồm cả các cuộc gọi của họ KdPrint, từ một driver khác mà không cần phải làm cho mã nguồn thay đổi.
Các khẳng định vĩ mô
Hữu ích khác, khả năng gỡ lỗi kỹ thuật dựa trên vĩ mô khẳng định:
ASSERT(1 + 1 == 2);
Trong khi kiểm tra xây dựng driver của bạn, khẳng định tạo ra mã để đánh giá Boolean biểu hiện. Nếu các biểu hiện là sai, khẳng định sẽ cố gắng để ngăn chặn thực hiện trong debugger để bạn có thể xem những gì đang xảy ra. Nếu các biểu hiện là đúng, của bạn tiếp tục thực hiện chương trình bình thường. Debuggers hạt nhân sẽ tạm dừng khi xảy ra khẳng định thất bại, ngay cả trong xây dựng nhà bán lẻ của các hệ điều hành, nhân tiện.
Quan trọng kkẳng định là một thất bại trong một bán lẻ xây dựng của các hệ điều hành mà không có hạt nhân debugger chạy tạo ra một lỗi kiểm tra.
Trình điều khiển Verifier
Các Driver Verifier là một phần của kiểm tra và miễn phí xây dựng của các hệ điều hành và là nhanh chóng trở thành một trong những công cụ chính của Microsoft cho trình điều khiển kiểm tra chất lượng. Bạn có thể khởi chạy Driver Verifier Bắt đầu từ Menu, whereupon bạn sẽ được trình bày với một loạt các trang của trình wizard. Đây là một ít đồ của một con đường để hướng dẫn bạn qua các trang này, lần đầu tiên.
Hình 3-14 minh hoạ việc ban đầu thuật sĩ trang. Tôi khuyên bạn nên kiểm tra các Tạo chỉnh Cài đặt (Đối với Mã số phát triển) lựa chọn. Điều này sẽ cho phép bạn lựa chọn để xác định chi tiết Driver Verifier tuỳ chọn mà bạn muốn tham gia.

Hình 3-14. Driver Verifier thuật sĩ ban đầu trang
Sau khi thực hiện các đề nghị của tôi lựa chọn từ các trang đầu tiên, bạn sẽ được trình bày với một trang thứ hai (xem Hình 3-15). Đây, tôi khuyên bạn nên kiểm tra các cá nhân Chọn Cài đặt từ A Danh sách đầy đủ tùy chọn.
Hình 3-15. Driver Verifier thuật sĩ thứ hai trang
Thuật sĩ trang kế tiếp (xem Hình 3-16) cho phép bạn chỉ định các cài đặt verifier bạn mong muốn. Được quy định trong kiểm tra được thêm vào một số kiểm tra rằng các Driver Verifier làm tự động.

Hình 3-16. Driver Verifier của thuật sĩ cài đặt tuỳ chỉnh trang
Những lựa chọn có sẵn tại thời điểm tôi đang viết này là như sau:
• Special lô tất cả các lực lượng bộ nhớ phân từ trình điều khiển để xác minh được làm từ những đặc biệt pool. Như được mô tả trong chương này sớm hơn, như vậy phân được đặt vào cuối (hoặc bắt đầu) của một trang, vì vậy mà sau khi lưu trữ (hoặc trước khi) sự phân bố bộ nhớ dẫn đến một lỗi kiểm tra ngay lập tức.
• Theo dõi các nguyên nhân các lô Driver Verifier để theo dõi bộ nhớ phân xác minh được thực hiện bởi trình điều khiển. Bạn có thể xem số liệu thống kê về cách sử dụng bộ nhớ như nó thay đổi theo thời gian. Các Driver Verifier cũng đảm bảo rằng tất cả các phân được giải thoát, khi xác minh unload trình điều khiển để giúp bạn nắm bắt bộ nhớ rõ.
• IRQL lực lượng kiểm tra nguyên nhân chủ yếu paged bộ nhớ để được Flushed bất cứ khi nào một xác nhận bằng driver tăng IRQL để DISPATCH_LEVEL hoặc ở trên. Hành động này giúp tìm những nơi trình điều khiển thiết bị là không chính xác paged truy cập bộ nhớ. Các hệ thống chạy khá chậm khi tùy chọn này được bật.
• I / O Mã xác nhận nguyên nhân của Driver Verifier để kiểm tra việc thực hiện cơ bản như thế nào là một driver xử lý IRPs rằng nó tạo ra hoặc forwards đến các trình điều khiển. • Enhanced I / O Mã xác nhận các nỗ lực để tuôn ra driver ra lỗi trong trường hợp ranh giới, chẳng hạn như hoàn tất và PnP Power IRPs không chính xác, làm cho các giả định về trình tự, trong đó các Trưởng đại diện PnP tải các trình điều khiển, và như vậy trên. Một số trong những bài kiểm tra xảy ra khi trình điều khiển thiết bị bắt đầu bước đầu, by the way, mà có thể ngăn chặn việc bắt đầu từ hệ thống.
• Deadlock Detection tạo ra một đồ của các khóa Hierarchy cho spin ổ khóa, mutexes, và nhanh chóng mutexes xác minh được sử dụng bởi trình điều khiển để phát hiện tiềm năng deadlocks. • DMA Kiểm tra xác minh đảm bảo rằng trình điều khiển DMA thực hiện bằng cách sử dụng phương pháp quy định bởi các DDK.
• Low Tài nguyên Mô phỏng ngẫu nhiên không bao gồm việc phân pool từ xác nhận trình điều khiển, bắt đầu bảy phút sau khi hệ thống bắt đầu. Mục đích của các thất bại là để đảm bảo rằng trình điều khiển thử nghiệm các giá trị trả lại từ pool phân bổ các cuộc gọi.
Bạn có thể sử dụng một thủ tục đặc biệt, được mô tả trong các DDK, để kích hoạt kiểm tra trên một trình điều khiển SCSI miniport.
Chú thích:
Có thể có tương tác giữa các tuỳ chọn bạn chỉ định. Hiện tại, thời gian, ví dụ, yêu cầu cho DMA kiểm tra phát hiện deadlock hay rẽ tắt nâng cao I / O xác minh.
Lưu ý rằng quá Driver Verifier là phát triển nhanh chóng ngay cả khi chúng tôi nói chuyện. DDK có sự tư vấn cho bạn xảy ra để được làm việc với cho up-to-date thông tin. Sau khi bạn chọn tuỳ chọn verifier bạn muốn, bạn sẽ thấy một thuật sĩ cuối cùng của trang (xem Hình 3-17). Trang này cho phép bạn để xác định trình điều khiển mà bạn muốn xác minh bằng cách kiểm tra các hộp trong một danh sách. Sau khi thực hiện là lựa chọn, bạn sẽ cần phải khởi động lại máy tính, vì nhiều của Driver Verifier kiểm tra yêu cầu khởi động-thời gian sở khởi. Khi tôi gỡ lỗi một trong các trình điều khiển của riêng tôi, tôi tìm thấy nó để thuận tiện nhất của tôi không có bằng driver tải khi khởi động lại xảy ra. Do vậy, driver của tôi sẽ không đã được trong danh sách, và tôi sẽ có thêm nó để qua Thêm vào Hiện nay không được tải Driver (s) To The Danh sách nút.

Hình 3-17. Điều khiển lựa chọn cho các trang Driver Verifier. Driver Verifier thất bại là lỗi kiểm tra bằng cách này. Bạn sẽ cần phải được chạy một hạt nhân hay debugger để phân tích các bãi chứa, sau khi đụng xe thực tế để isolate nguyên nhân của thất bại.