Bagikan melalui


Memuat dan Membongkar Minidriver WIA

Setelah driver perangkat WIA diinstal, layanan WIA mencoba memuatnya untuk pertama kalinya. Metode IStiUSD::Initialize minidriver WIA dipanggil dan harus melakukan tugas-tugas berikut:

  1. Periksa mode transfer untuk menentukan niat pemanggil untuk menginisialisasi driver perangkat ini. Ini dilakukan dengan memanggil metode IStiDeviceControl::GetMyDeviceOpenMode .

  2. Dapatkan nama port perangkat yang terinstal, sehingga driver ini dapat memanggil CreateFile (di dokumentasikan di Microsoft Windows SDK) pada port yang tepat untuk mengakses perangkat. Ini dilakukan dengan memanggil metode IStiDeviceControl::GetMyDevicePortName .

  3. Baca pengaturan registri khusus perangkat yang ditulis selama penginstalan perangkat. Ini dapat dilakukan dengan menggunakan parameter hParametersKey yang diteruskan ke IStiUSD::Initialize.

Layanan WIA memanggil metode IStiUSD::Initialize saat driver pertama kali dimuat. Metode IStiUSD::Initialize juga dipanggil ketika klien menggunakan DDIs STI warisan dan memanggil metode IStillImage::CreateDevice .

Metode IStiUSD::Initialize harus menginisialisasi driver WIA dan perangkat untuk digunakan. Driver WIA dapat menyimpan penunjuk antarmuka IStiDeviceControl jika mereka membutuhkannya di lain waktu. Metode IStiDeviceControl::AddRef harus dipanggil sebelum menyimpan antarmuka ini. Jika Anda tidak perlu menyimpan antarmuka, abaikan saja. Jangan rilis antarmuka IStiDeviceControl jika Anda belum memanggil IStiDeviceControl::AddRef terlebih dahulu. Ini dapat menyebabkan hasil yang tidak dapat diprediksi. Antarmuka IStiDeviceControl COM diperlukan untuk mendapatkan informasi tentang port perangkat. Nama port yang digunakan dalam panggilan ke fungsi CreateFile dapat diperoleh dengan memanggil metode IStiDeviceControl::GetMyDevicePortName . Untuk perangkat pada port bersama, seperti perangkat port serial, membuka port di IStiUSD::Initialize tidak disarankan. Port harus dibuka hanya dalam panggilan ke IStiUSD::LockDevice. Penutupan port harus dikontrol secara internal untuk memberikan akses cepat. (Membuka dan menutup di IStiUSD::LockDevice dan IStiUSD::UnLockDevice sangat tidak efisien. CreateFile dapat menyebabkan penundaan membuat perangkat tampak lambat dan tidak responsif bagi pengguna.)

Jika driver WIA tidak dapat mendukung beberapa panggilan CreateFile pada port perangkat yang sama, maka metode IStiDeviceControl::GetMyDeviceOpenMode harus dipanggil.

Driver WIA harus memeriksa nilai mode yang dikembalikan untuk bendera STI_DEVICE_CREATE_DATA dan membuka port yang sesuai.

Jika port perangkat harus dibuka, panggilan ke CreateFile harus digunakan. Saat membuka port, bendera FILE_FLAG_OVERLAPPED harus digunakan. Ini memungkinkan struktur TUMPANG TINDIH (dijelaskan dalam dokumentasi Windows SDK) untuk digunakan saat mengakses perangkat. Menggunakan I/O yang tumpang tindih akan membantu mengontrol akses responsif ke perangkat keras. Ketika masalah terdeteksi, driver WIA dapat memanggil CancelIo (dijelaskan dalam dokumentasi Windows SDK) untuk menghentikan semua akses perangkat keras saat ini.

Contoh berikut menunjukkan implementasi metode IStiUSD::Initialize .

STDMETHODIMP CWIADevice::Initialize(
  PSTIDEVICECONTROL   pIStiDeviceControl,
  DWORD               dwStiVersion,
  HKEY                hParametersKey)
{
  if (!pIStiDeviceControl) {
      return STIERR_INVALID_PARAM;
  }

  HRESULT hr = S_OK;

  //
  // Get the mode of the device to check why we were created.  status, data, or both...
  //

  DWORD dwMode = 0;
  hr = pIStiDeviceControl->GetMyDeviceOpenMode(&dwMode);
  if(FAILED(hr)){
      return hr;
  }

  if(dwMode & STI_DEVICE_CREATE_DATA)
  {
      //
      // device is being opened for data
      //
  }

  if(dwMode & STI_DEVICE_CREATE_STATUS)
  {
      //
      // device is being opened for status
      //
  }

  if(dwMode & STI_DEVICE_CREATE_BOTH)
  {
      //
      // device is being opened for both data and status
      //
  }

  //
  // Get the name of the device port to be used in a call to CreateFile().
  //

  WCHAR szDevicePortNameW[MAX_PATH];
  memset(szDevicePortNameW,0,sizeof(szDevicePortNameW));

  hr = pIStiDeviceControl->GetMyDevicePortName(szDevicePortNameW,
                                            sizeof(szDevicePortNameW)/sizeof(WCHAR));
  if(FAILED(hr)) {
      return hr;
  }

  //
  // Open kernel-mode device driver. Use the FILE_FLAG_OVERLAPPED flag 
  // for proper cancellation
  // of kernel-mode operations and asynchronous file IO. 
  //  The CancelIo() call will function properly if this flag is used.
  //  It is recommended to use this flag.
  //

  m_hDeviceDataHandle = CreateFileW(szDevicePortNameW,
                                   GENERIC_READ | GENERIC_WRITE, // Access mask
                                   0,                            // Share mode
                NULL,                         // SA
                                   OPEN_EXISTING,                // Create disposition
                                   FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,
                                   NULL );

  m_dwLastOperationError = ::GetLastError();

  hr = (m_hDeviceDataHandle != INVALID_HANDLE_VALUE) ?
              S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);

  if (FAILED(hr)) {
      return hr;
  }

  //
  // Open DeviceData section to read driver specific information
  //

  HKEY hKey = hParametersKey;
  HKEY hOpenKey = NULL;
  if (RegOpenKeyEx(hKey,                     // handle to open key
                   TEXT("DeviceData"),       // address of name of subkey to open
                   0,                        // options (must be NULL)
                   KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value
                   &hOpenKey                 // address of handle to open key
     ) == ERROR_SUCCESS) {

      //
      // This is where you read registry entries for your device.
      // The DeviceData section is the proper place to put this 
      // information. Information about your device should
      // have been written using the WIA device's .INF installation
      // file.
      // You can access this information from this location in the
      // Registry. The WIA service owns the hParameters HKEY. 
      // DO NOT CLOSE THIS KEY. Always close any HKEYS opened by
      //  this WIA driver after you are finished.
      //

      //
      // close registry key when finished, reading DeviceData information.
      //

      RegCloseKey(hOpenKey);
  } else {
      return E_FAIL;
  }
  return hr;
}

Layanan WIA memanggil IStiUSD::GetCapabilities setelah panggilan berhasil ke metode IStiUSD::Initialize . IStiUSD::GetCapabilities kemudian menyediakan struktur STI_USD_CAPS dengan informasi versi STI, bendera dukungan WIA (bendera bit yang menunjukkan kemampuan driver), dan persyaratan peristiwa apa pun.

Contoh berikut menunjukkan implementasi IStiUSD::GetCapabilities.

/********************************************************************\
* CWIADevice::GetCapabilities
* Remarks:
* This WIA driver sets the following capability flags:
* 1. STI_GENCAP_WIA - This driver supports WIA
* 2. STI_USD_GENCAP_NATIVE_PUSHSUPPORT - This driver supports push
*    buttons
* 3. STI_GENCAP_NOTIFICATIONS - This driver requires the use of 
*    interrupt events.
*
\********************************************************************/

STDMETHODIMP CWIADevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
{
  //
  // If the caller did not pass in the correct parameters,
  // then fail the call with E_INVALIDARG.
  //

  if (!pUsdCaps) {
      return E_INVALIDARG;
  }

  memset(pUsdCaps, 0, sizeof(STI_USD_CAPS));
  pUsdCaps->dwVersion     = STI_VERSION;    // STI version
  pUsdCaps->dwGenericCaps = STI_GENCAP_WIA| // WIA support
                            STI_USD_GENCAP_NATIVE_PUSHSUPPORT| // button support
                            STI_GENCAP_NOTIFICATIONS; // interrupt event support
  return S_OK;
}