Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam beberapa kasus, nama kontrak set API tertentu mungkin sengaja dipetakan ke nama modul kosong pada beberapa perangkat Windows. Alasan untuk ini bervariasi, tetapi contoh umumnya adalah bahwa fitur mahal dalam hal sumber daya sistem mungkin 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 penerusan terbalik. Jika 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 melaporkan apakah set API ada dalam skema set API yang disusun pada perangkat yang sedang berjalan, dan apakah itu dipetakan ke modul implementasi.
Important
Kueri ketersediaan yang berhasil bukan jaminan bahwa panggilan tertentu akan berhasil. Lanjutkan menangani kesalahan pemuatan modul, ekspor yang hilang, dan hasil kegagalan yang didokumenkan API sendiri.
Contoh kode berikut menunjukkan cara menggunakan IsApiSetImplemented untuk menentukan apakah set API yang berisi WTSEnumerateSessionsW tersedia di perangkat saat ini sebelum memanggilnya.
#include <windows.h>
#include <apiquery2.h>
#include <stdio.h>
#include <wtsapi32.h>
#pragma comment(lib, "OneCore.lib")
#pragma comment(lib, "Wtsapi32.lib")
int __cdecl wmain(int /* argc */, PCWSTR /* argv */ [])
{
PWTS_SESSION_INFOW pInfo = nullptr;
DWORD count = 0;
if (!IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0"))
{
wprintf(L"ext-ms-win-session-wtsapi32-l1-1-0 is not available.\n");
return 0;
}
if (WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pInfo, &count))
{
wprintf(L"SessionCount = %lu\n", count);
for (DWORD i = 0; i < count; i++)
{
PWTS_SESSION_INFOW pCurInfo = &pInfo[i];
wprintf(L" %ls: ID = %lu, state = %d\n", pCurInfo->pWinStationName,
pCurInfo->SessionId, static_cast<int>(pCurInfo->State));
}
WTSFreeMemory(pInfo);
}
else
{
wprintf(L"WTSEnumerateSessionsW failure: %lu\n", GetLastError());
}
return 0;
}
IsApiSetImplemented dinyatakan dalam apiquery2.h, dan jalur tautan SDK publik normal memasoknya dari OneCore.lib. Pustaka tersebut terpisah dari pustaka impor apa pun yang diperlukan untuk memanggil API target opsional itu sendiri.
Contoh di atas menautkan Wtsapi32.lib untuk impor statis, yang menjaga contoh singkat. Aplikasi produksi yang harus berjalan di mana set API tidak ada juga harus menerapkan panduan di Menjaga jalur kode opsional dapat dijangkau.
Pilih nama kueri
Berikan nama set API yang Anda uji. Nama set API ditulis secara konvensional tanpa .dll akhiran, dan contoh di halaman ini menggunakan formulir tersebut. Akhiran bukan bagian dari nama set API.
Untuk menemukan nama yang akan diteruskan, lihat tabel Persyaratan di halaman referensi untuk API yang ingin Anda panggil. Jika tabel tersebut memiliki baris set API , tabel tersebut memberikan nama kontrak. Jika tidak, gunakan baris DLL , tetapi hanya ketika nama itu sendiri ada nama kontrak yang dimulai dengan api- atau ext-; nama modul fisik seperti Wtsapi32.dll bukan kontrak, dan mengkuerinya mengembalikan FALSE.
Bentuk nama tergantung pada bagaimana API ditangani.
| Cakupan API | Formulir kueri | Example |
|---|---|---|
| Grup bernama | <contract>~<group> |
api-win-core-samplefeature~AdvancedOperations |
| Grup bawaan | Alias kontrak, tanpa ~Default |
api-win-core-samplefeature |
| Kontrak versi | Lengkapi nama kontrak versi | ext-ms-win-core-samplefeature-l1-1-0 |
Nama-nama tersebut samplefeature adalah nama ilustrasi untuk komponen Windows fiktif. Awalan nama (api- atau ext-) tidak memainkan peran dalam perilaku ketersediaan.
Untuk grup bernama, kueri yang berhasil berarti bahwa grup ada, kontraknya dipetakan ke modul implementasi, host tersebut dapat digunakan di lingkungan eksekusi saat ini, grup tidak dinonaktifkan, dan fitur sistem apa pun yang terkait dengan grup diaktifkan. Kueri yang menggunakan alias kontrak menerapkan pemeriksaan kontrak dan host.
Jika header publik API menyediakan pembantu Is<APIName>Present , lebih suka pembantu tersebut. Ini sudah berisi nama yang benar untuk set API atau grup yang membawa API.
Hasil kueri adalah kontrak atau granular grup, bukan terperinci fungsi. Dua pembantu yang didukung oleh grup bernama yang sama selalu mengembalikan hasil yang sama, meskipun setiap pembantu diberi nama untuk API yang berbeda.
Jaga agar jalur kode opsional tetap dapat dijangkau
Pemeriksaan ketersediaan tidak dapat melindungi startup proses jika API opsional ditautkan sebagai impor statis. Loader menyelesaikan impor statis sebelum kode Anda berjalan, sehingga modul yang hilang gagal proses sebelum eksekusi mencapai pemeriksaan.
Gunakan salah satu pendekatan berikut:
- Konfigurasikan modul yang membawa API opsional untuk pemuatan penundaan. Pemuatan penundaan adalah pengaturan linker: tentukan dan tautkan
/DELAYLOAD:<module>delayimp.lib. Tentukan nama modul yang muncul dalam tabel impor biner Anda, yang mungkin merupakan nama DLL klasik daripada nama kontrak set API. Untuk contoh sebelumnya, nama tersebut WTSAPI32.dll. - Atau atasi target secara dinamis dengan LoadLibrary dan GetProcAddress setelah kueri ketersediaan berhasil.
Jangan gunakan LoadLibrary atau GetProcAddress sebagai pengganti kueri ketersediaan. Mereka menjawab pertanyaan modul dan ekspor, mereka tidak mengevaluasi status grup bernama, dan mereka dapat mengatasi stub penerusan terbalik seperti yang dijelaskan sebelumnya. Gunakan setelah kueri, untuk menangani modul terpisah dan pemeriksaan ekspor.
Perilaku pada versi Windows sebelumnya
Implementasi yang disediakan oleh OneCore.lib memilih mekanisme kueri yang tersedia pada waktu proses, sehingga aplikasi yang memanggil IsApiSetImplemented masih dapat berjalan pada sistem yang mendasari dukungan kueri yang mendasarinya.
Pada sistem di mana tidak ada mekanisme kueri yang tersedia:
- Nama yang memenuhi syarat grup yang berisi
~menampilkan FALSE. Sistem yang tidak dapat mengevaluasi grup bernama tidak dapat melaporkan bahwa grup tersedia. - Nama yang tidak memenuhi syarat grup dapat mengembalikan TRUE. Ini mempertahankan kompatibilitas dengan aplikasi yang menyediakan DLL penerus mereka sendiri pada versi awal Windows, di mana kontrak sebenarnya dipenuhi oleh penerus tersebut.
Jangan gunakan kueri ketersediaan set API sebagai pemeriksaan keamanan atau otorisasi.