לדלג לתוכן

פתרון חוזה של בקשת התקן

הלקוח יפתח את הנתיב שגילה באמצעות SetupAPI או את נתיב המעבדה שהדרייבר מציג, עם GENERIC_READ ו־GENERIC_WRITE בהתאם ל־access bits. הוא יגדיר אותו CTL_CODE ואותו layout, ימלא Size באורך המדויק של header ושני ULONG-ים ויקצה LAB_RESULT בגודל מלא. אם הדרייבר מחשב 7 ועוד 9, התוצאה צריכה להיות Sum=16 ו־Count=2, ו־bytesReturned צריך להיות sizeof(LAB_RESULT).

הקוד הבא הוא בניית buffer בצד המשתמש, לשילוב בלקוח Win32 שיש לו handle תקף להתקן. הוא אינו כולל פתיחה של התקן כלשהו שקיים במחשב ואינו מניח שם גלובלי לא מתועד.

struct Request {
    LAB_HEADER header;
    ULONG values[2];
};
Request request{{sizeof(Request), 1, 2}, {7, 9}};
LAB_RESULT result{};
DWORD returned = 0;
BOOL ok = DeviceIoControl(device, IOCTL_LAB_SUM, &request, sizeof(request),
    &result, sizeof(result), &returned, nullptr);
if (!ok) {
    DWORD error = GetLastError();
    // Report the captured error through the client's error path.
} else if (returned != sizeof(result) || result.Sum != 16 || result.Count != 2) {
    // Reject a response that violates the protocol contract.
}

הבדיקות השליליות משנות שדה אחד בכל פעם ושומרות את שאר הקלט תקין, כדי שאפשר יהיה לדעת איזו בדיקה דחתה אותו. במצב buffered הקלט והפלט משתמשים באותו SystemBuffer של הדרייבר, ולכן כתיבת פלט מוקדמת יכולה לדרוס את הכותרת או payload. לכידת הכותרת בלבד אינה מספיקה אם נמשיך לקרוא ערכי payload אחרי הדריסה.

בגרסה האסינכרונית רק transition אטומי מ־queued אל owned-by-worker או cancel-owned מקנה זכות השלמה. מי שהפסיד במרוץ אינו נוגע בבקשה אחרי שהמנצח השלים אותה. ה־teardown עוצר admission, מבטל או מרוקן את התור וממתין לבעלים פעילים לפני מחיקת device context. בשיעורי KMDF נשתמש בחוזי framework כדי לייצג את המעברים, ונשמור את אותה הוכחה של completion יחיד.