Bagikan melalui


Mendeteksi ketersediaan set API

Dalam beberapa kasus, nama kontrak set API tertentu mungkin sengaja dipetakan ke nama modul kosong di beberapa perangkat Windows. Alasan untuk ini bervariasi, tetapi contoh umumnya adalah bahwa fitur mahal dalam hal sumber daya sistem dapat dihapus dari OS Windows saat dikonfigurasi untuk perangkat yang dibatasi sumber daya. Ini menimbulkan tantangan bagi aplikasi untuk menangani fitur opsional dengan baik di tingkat API.

Pendekatan tradisional untuk menguji apakah API Win32 tersedia adalah menggunakan LoadLibrary atau GetProcAddress. Namun, ini bukan sarana yang dapat diandalkan untuk menguji set API karena dukungan penerusan terbalik di Windows 10, dan yang lebih baru. Saat penerusan balik diterapkan ke API tertentu, LoadLibrary atau GetProcAddress dapat diselesaikan ke penunjuk fungsi yang valid bahkan dalam kasus di mana implementasi internal telah dihapus. Dalam hal ini, penunjuk fungsi akan menunjuk ke fungsi stub yang hanya mengembalikan kesalahan.

Untuk mendeteksi kasus ini, Anda dapat menggunakan fungsi IsApiSetImplemented untuk mengkueri ketersediaan yang mendasar dari implementasi API tertentu. Pengujian ini memvalidasi bahwa memanggil fungsi ini akan mengakibatkan pelaksanaan implementasi fungsional API.

Contoh kode berikut menunjukkan cara menggunakan IsApiSetImplemented untuk menentukan apakah fungsi WTSEnumerateSessions tersedia di perangkat saat ini sebelum memanggilnya.

#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>

int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
    PWTS_SESSION_INFO pInfo = {};
    DWORD count = 0;

    if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
    {
        wprintf(L"IsApiSetImplemented on ext-ms-win-session-wtsapi32-l1-1-0 returns FALSE\n");
    }
    else
    {
        if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
        {
            wprintf(L"SessionCount = %d\n", count);

            for (ULONG i = 0; i < count; i++)
            {
                PWTS_SESSION_INFO pCurInfo = &pInfo[i];
                wprintf(L"    %s: ID = %d, state = %d\n", pCurInfo->pWinStationName, 
                    pCurInfo->SessionId, pCurInfo->State);
            }

            WTSFreeMemory(pInfo);
        }
        else
        {
            wprintf(L"WTSEnumerateSessions failure : %x\n", GetLastError());
        }
    }

    return 0;
}