Fungsi Entry-Point Pustaka Dynamic-Link
DLL dapat secara opsional menentukan fungsi titik entri. Jika ada, sistem memanggil fungsi titik entri setiap kali proses atau utas memuat atau membongkar DLL. Ini dapat digunakan untuk melakukan tugas inisialisasi dan pembersihan sederhana. Misalnya, dapat menyiapkan penyimpanan lokal utas saat utas baru dibuat, dan membersihkannya saat utas dihentikan.
Jika Anda menautkan DLL Anda dengan pustaka run-time C, itu mungkin menyediakan fungsi titik entri untuk Anda, dan memungkinkan Anda untuk menyediakan fungsi inisialisasi terpisah. Periksa dokumentasi untuk pustaka run-time Anda untuk informasi selengkapnya.
Jika Anda menyediakan titik masuk Anda sendiri, lihat fungsi DllMain . Nama DllMain adalah tempat penampung untuk fungsi yang ditentukan pengguna. Anda harus menentukan nama aktual yang Anda gunakan saat membuat DLL. Untuk informasi selengkapnya, lihat dokumentasi yang disertakan dengan alat pengembangan Anda.
Memanggil Fungsi Entry-Point
Sistem memanggil fungsi titik masuk setiap kali salah satu peristiwa berikut terjadi:
- Proses memuat DLL. Untuk proses yang menggunakan penautan dinamis waktu muat, DLL dimuat selama inisialisasi proses. Untuk proses yang menggunakan penautan run-time, DLL dimuat sebelum LoadLibrary atau LoadLibraryEx kembali.
- Proses membongkar DLL. DLL dibongkar ketika proses berakhir atau memanggil fungsi FreeLibrary dan jumlah referensi menjadi nol. Jika proses berakhir sebagai akibat dari fungsi TerminateProcess atau TerminateThread , sistem tidak memanggil fungsi titik masuk DLL.
- Utas baru dibuat dalam proses yang telah memuat DLL. Anda dapat menggunakan fungsi DisableThreadLibraryCalls untuk menonaktifkan pemberitahuan saat utas dibuat.
- Utas proses yang telah memuat DLL berakhir secara normal, tidak menggunakan TerminateThread atau TerminateProcess. Ketika proses membongkar DLL, fungsi titik entri hanya dipanggil sekali untuk seluruh proses, bukan sekali untuk setiap utas proses yang ada. Anda dapat menggunakan DisableThreadLibraryCalls untuk menonaktifkan pemberitahuan saat utas dihentikan.
Hanya satu utas pada satu waktu yang dapat memanggil fungsi titik entri.
Sistem memanggil fungsi titik entri dalam konteks proses atau utas yang menyebabkan fungsi dipanggil. Ini memungkinkan DLL untuk menggunakan fungsi titik masuknya untuk mengalokasikan memori di ruang alamat virtual proses panggilan atau membuka handel yang dapat diakses oleh proses. Fungsi titik entri juga dapat mengalokasikan memori yang bersifat privat ke utas baru dengan menggunakan penyimpanan lokal utas (TLS). Untuk informasi selengkapnya tentang penyimpanan lokal utas, lihat Penyimpanan Lokal Utas.
Definisi Fungsi Entry-Point
Fungsi titik entri DLL harus dideklarasikan dengan konvensi panggilan standar. Jika titik entri DLL tidak dideklarasikan dengan benar, DLL tidak dimuat, dan sistem menampilkan pesan yang menunjukkan bahwa titik masuk DLL harus dideklarasikan dengan WINAPI.
Dalam isi fungsi, Anda dapat menangani kombinasi skenario berikut di mana titik entri DLL telah dipanggil:
- Proses memuat DLL (DLL_PROCESS_ATTACH).
- Proses saat ini membuat utas baru (DLL_THREAD_ATTACH).
- Alur keluar secara normal (DLL_THREAD_DETACH).
- Proses membongkar DLL (DLL_PROCESS_DETACH).
Fungsi titik entri hanya boleh melakukan tugas inisialisasi sederhana. Ini tidak boleh memanggil fungsi LoadLibrary atau LoadLibraryEx (atau fungsi yang memanggil fungsi-fungsi ini), karena ini dapat membuat perulangan dependensi dalam urutan beban DLL. Ini dapat mengakibatkan DLL digunakan sebelum sistem menjalankan kode inisialisasinya. Demikian pula, fungsi titik masuk tidak boleh memanggil fungsi FreeLibrary (atau fungsi yang memanggil FreeLibrary) selama penghentian proses, karena ini dapat mengakibatkan DLL digunakan setelah sistem menjalankan kode penghentiannya.
Karena Kernel32.dll dijamin akan dimuat dalam ruang alamat proses ketika fungsi titik masuk dipanggil, fungsi panggilan di Kernel32.dll tidak mengakibatkan DLL digunakan sebelum kode inisialisasinya dijalankan. Oleh karena itu, fungsi titik entri dapat membuat objek sinkronisasi seperti bagian penting dan mutex, dan menggunakan TLS, karena fungsi-fungsi ini terletak di Kernel32.dll. Tidak aman untuk memanggil fungsi registri, misalnya, karena terletak di Advapi32.dll.
Memanggil fungsi lain dapat mengakibatkan masalah yang sulit didiagnosis. Misalnya, memanggil fungsi Pengguna, Shell, dan COM dapat menyebabkan kesalahan pelanggaran akses, karena beberapa fungsi dalam DLL mereka memanggil LoadLibrary untuk memuat komponen sistem lainnya. Sebaliknya, memanggil fungsi-fungsi tersebut selama penghentian dapat menyebabkan kesalahan pelanggaran akses karena komponen yang sesuai mungkin sudah dibongkar atau tidak diinisialisasi.
Contoh berikut menunjukkan cara menyusun fungsi titik entri DLL.
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
Nilai Pengembalian Fungsi Entry-Point
Ketika fungsi titik entri DLL dipanggil karena proses sedang dimuat, fungsi mengembalikan TRUE untuk menunjukkan keberhasilan. Untuk proses yang menggunakan penautan waktu muat, nilai pengembalian FALSE menyebabkan inisialisasi proses gagal dan proses berakhir. Untuk proses yang menggunakan penautan run-time, nilai pengembalian FALSE menyebabkan fungsi LoadLibrary atau LoadLibraryEx mengembalikan NULL, yang menunjukkan kegagalan. (Sistem segera memanggil fungsi titik masuk Anda dengan DLL_PROCESS_DETACH dan membongkar DLL.) Nilai yang dikembalikan dari fungsi titik entri diamati ketika fungsi dipanggil karena alasan lain.