Hàm DeviceIoControl API (The DeviceIoControl API)
User-mode DeviceIoControl API có nguyên mẫu sau đây: result = DeviceIoControl(Handle, Code, InputData, InputLength, OutputData, OutputLength, &Feedback, &Overlapped); Handle (HANDLE) là một kênh điều khiển mở đối với thiết bị. ...
User-mode DeviceIoControl API có nguyên mẫu sau đây:
result = DeviceIoControl(Handle, Code, InputData, InputLength,
OutputData, OutputLength, &Feedback, &Overlapped);
Handle (HANDLE) là một kênh điều khiển mở đối với thiết bị. Bạn thu được kênh này bằng việc gọi là CreateFile trong lệnh sau đây :
Handle = CreateFile(".IOCTL", GENERIC_READ │ GENERIC_WRITE,
0, NULL, OPEN_EXISTING, flags, NULL);
if (Handle == INVALID_HANDLE_VALUE)
<error>
CloseHandle(Handle);
Những cờ đối số tới CreateFile cũng là FILE_FLAG_OVERLAPPED hay 0 để chỉ ra bạn sẽ biểu diễn được hay không sự hoạt động dị bộ với kênh điều khiển tệp tin này. Trong khi bạn có kênh điều khiển mở, bạn có thể làm những sự gọi tới ReadFile, WriteFile, hay DeviceIoControl. Hoặc khi nào bạn truy cập thiết bị, bạn cần phải đóng dứt khoát kênh điều khiển bằng việc gọi là CloseHandle.Phải hướng vào trong tâm trí, thế nhưng, hệ điều hành đó tự động đóng bất kỳ kênh điều khiển nào mà được mở về phía trái khi quá trình (của) các bạn hoàn thành. Code (DWORD) đối số tới DeviceIoControl là một mã điều khiển mà chỉ báo thao tác điều khiển (phép toán kiểm tra) bạn muốn thực hiện. Tôi sẽ bàn luận về việc bạn định nghĩa những mã này hơi xa hơn như thế nào trên (in “Defining I/O Control Codes”). InputData (PVOID) và InputLength (DWORD) những đối sốmô tả một vùng dữ liệu mà bạn gửi tới trình điều khiển thiết bị. (Nghĩa là, dữ liệu này được nhập vào từ phối cảnh (của) trình điều khiển.). The OutputData (PVOID) and OutputLength (DWORD) những đối sốmô tả một vùng dữ liệu mà trình điều khiển đó có thể hoàn toàn hay từng phần làm đầy thông tin mà nó muốn nhắn quay trở lại cho bạn. (Nghĩa là, dữ liệu này là đầu ra từ phối cảnh (của) trình điều khiển.) Trình điều khiển sẽ cập nhật the Feedback variable (a DWORD) để chỉ báo bao nhiêu những byte của dữ liệu ra nó đưa cho bạn mặt sau. Hình 9-1 minh họa mối quan hệ của những bộ đệm này với ứng dụng và trình điều khiển. Cấu trúc Overlapped (OVERLAPPED) được dùng để giúp đỡ kiểm soát một tác vụ đồng bộ, mà là đề tài của mục tiếp theo. Nếu bạn được chỉ rõ FILE_FLAG_OVERLAPPED trong sự gọi tới CreateFile, bạn phải chỉ rõ OVERLAPPED con trỏ cấu trúc. Nếu bạn không chỉ rõ FILE_FLAG_OVERLAPPED, bạn có lẽ đã cung cấp tốt NULL cho đối sốcuối cùng này bởi vì hệ thống sẽ lờ đi nó.
Hình 9-1 . Đầu vào và những bộ đệm ra cho DeviceIoControl.
Liệu có phải một thao tác điều khiển (phép toán kiểm tra) đặc biệt yêu cầu một bộ đệm vào hay một bộ đệm ra phụ thuộc vào chức năng được thực hiện.Chẳng hạn, một điều khiển I/O (IOCTL) mà khôi phục số phiên bản của trình điều khiển có lẽ chỉ yêu cầu một bộ đệm ra. Một IOCTL mà đơn thuần thông báo trình điều khiển của thực tế nào đó gắn liền với ứng dụng có lẽ chỉ yêu cầu một bộ đệm vào. Bạn có thể hình dung sự hoạt động những thao tác khác mà yêu cầu cả hai hoặc không cái nào của đầu vào và những bộ đệm ra-nó mọi thứ phụ thuộc vào cái mà thao tác điều khiển (phép toán kiểm tra) làm.. Giá trị trở lại từ DeviceIoControl là một giá trị Đại số Boole mà chỉ báo thành công ( Nếu Thật ) hay sự thất bại ( nếu Sai). Trong một hoàn cảnh thất bại, ứng dụng có thể gọi cho GetLastError để tìm ra tại sao sự gọi bị phá sản.
Synchronous và Asynchronous gọi tới DeviceIoControl
Khi bạn làm một sự gọi đồng bộ tới DeviceIoControl, những khối luồng gọi cho đến thao tác điều khiển (phép toán kiểm tra) hoàn thành. Chẳng hạn:
HANDLE Handle = CreateFile(".IOCTL", ..., 0, NULL);
DWORD version, junk;
if (DeviceIoControl(Handle, IOCTL_GET_VERSION_BUFFERED,
NULL, 0, &version, sizeof(version), &junk, NULL))
printf("IOCTL.SYS version %d.%2.2d ", HIWORD(version),
LOWORD(version));
else
printf("Error %d in IOCTL_GET_VERSION_BUFFERED call ",
GetLastError());
ở đây chúng tôi mở ô điều khiển thiết bị không có cờ FILE_FLAG_OVERLAPPED. Việc gọi kế tiếp của chúng ta tới DeviceIoControl bởi vậy không trở lại cho đến khi trình điều khiển cung cấp câu trả lời mà chúng tôi yêu cầu.
Khi bạn làm một sự gọi không đồng bộ tới DeviceIoControl, luồng cuộc gọi không hướng tới khối ngay lập tức. Thay vào đó, nó tiếp tục xử lý cho đến khi nó đạt đến điểm nơi nó yêu cầu kết quả của thao tác điều khiển (phép toán kiểm tra). Tại điểm đó nó gọi là một API mà sẽ ngăn chặn luồng cho đến khi trình điều khiển hoàn thành thao tác. Chẳng hạn:
HANDLE Handle = CreateFile(".IOCTL", ...,
FILE_FLAG_OVERLAPPED, NULL);
DWORD version, junk;
OVERLAPPED Overlapped;
Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD code;
if (DeviceIoControl(Handle, ..., &Overlapped))
code = 0;
else
code = GetLastError();
<continue processing>
if (code == ERROR_IO_PENDING)
{
if (GetOverlappedResult(Handle, &Overlapped, &junk, TRUE))
code = 0;
else
code = GetLastError();
}
CloseHandle(Overlapped.hEvent);
if (code != 0)
<error>
Định nghĩa những mã Điều khiển vào/ra
Đối số mã tới DeviceIoControl là một số 32- bit hằng số mà bạn định nghĩa sử dụng bộ tiền xử lý CTL_CODE vỹ mô điều đó là bộ phận của cả hai DDK và nền tảng SDK. Hình 9-2 minh họa cách trong đó hệ điều hành phân chia của một trong 32-bit những mã vào trong những trường con.
Hình 9-2. Những lĩnh vực trong một mã điều khiển vào/ra .
Những lĩnh vực có sự giải thích sau đây:
Kiểu thiết bị (16 bít, đối số đầu tiên tới CTL_CODE) chỉ báo kiểu của thiết bị mà thực hiện thao tác điều khiển (phép toán kiểm tra) này.
_Bạn cần phải sử dụng cùng giá trị (Chẳng hạn, FILE_DEVICE_UNKNOWN) bạn sử dụng trong trình điều khiển khi bạn gọi IoCreateDevice. (Những mã kiểu thiết bị hệ tập tin gây ra quản lý I/O để sử dụng một mã chức năng chính khác nhau cho IRP)
_Mã truy nhập (2 bít, đối số thứ tư tới CTL_CODE ) chỉ báo quyền lợi truy nhập một ứng dụng cần tới thiết bị của nó để phát hành thao tác điều khiển (phép toán kiểm tra) này.
_Mã chức năng (12 bít, đối số thứ hai tới CTL_CODE) chỉ báo chính xác thao tác điều khiển (phép toán kiểm tra) nào mà điều này viết mã mô tả. Microsoft dự trữ nửa đầu tiên của phạm vi của các trường này-điều đó, đánh giá từ 0 đến 2047-cho tiêu chuẩn kiểm soát những thao tác. Bạn và Tôi bởi vậy gán những giá trị trong phạm vi từ 2048 đến 4095. Mục đích chính của quy ước này sẽ cho phép bạn định nghĩa những thao tác điều khiển (phép toán kiểm tra) riêng tư cho những thiết bị tiêu chuẩn.
_Phương pháp đệm (2 bít, đối sốthứ ba tới CTL_CODE) chỉ báo I/O Manager được xử lý đầu vào và những bộ đệm ra cung cấp bởi ứng dụng như thế nào. Tôi sẽ có một thoả thuận lớn để nói về lĩnh vực này trong mục tiếp theo, khi Tôi mô tả làm sao để thực hiện IRP_MJ_DEVICE_CONTROL trong một trình điều khiển.