Usted tendrá una pérdida de identificadores en el caso:
Program -Load> Dll A
-Load> Dll B
-Unload> Dll A
Ningún código se ejecuta de forma implícita por un módulo que se descarga para descargar los módulos que este se abra.
Como no se ejecuta ningún código para disminuir el recuento de referencias, el módulo B nunca se descargará.
Estas son las reglas para la carga/descarga de archivos DLL:
- Cada llamada a LoadLibrary y LoadLibraryEx incrementará el recuento de referencia para ese módulo. Esto está en el contexto del proceso de llamada solamente, no a través de los límites del proceso.
- Cada llamada a FreeLibrary o FreeLibraryAndExitThread reducirá el recuento de referencias.
- Cuando el recuento de referencias llega a 0, se descargará.
- Cuando Windows ve que su programa es cerrado, los módulos descargados que se hayan descargado se descargarán.
- Según lo que esté haciendo, DllCanUnloadNow podría serle útil.
Todavía en la memoria vs todavía cargado:
no hay ninguna garantía de que el módulo se libera de la memoria en un momento determinado, cuando la referencia llega a 0. Sin embargo, usted debe considerar el módulo como si se descarga cuando el recuento de referencias llega a 0.
Detener la DLL se descargue:
Para forzar la DLL se descargue podría intentar
- El sistema llama a DllMain con el indicador DLL_PROCESS_DETACH. Podría tratar de no regresar de esto a través de algún tipo de operación de bloqueo.
- Puede intentar llamar a LoadLibrary desde la DLL que no desea descargar. (Carga auto)
Editar:
Usted mencionó que su objetivo es INJET código en el programa en ejecución y que quería escaparse el mango a propósito.
Eso está bien, pero si ejecuta esta operación mucho, puede provocar un bloqueo en su programa de origen porque se usarán demasiados controladores o eventualmente se usará demasiada memoria.
Puede devolver FALSE desde su DllMain para evitar que se cargue y así no perder memoria. Haga esto cuando fdwReason es DLL_PROCESS_ATTACH. Puede read more about it here.
Si está tratando de emular una DLL y agregar su propia funcionalidad adicional, deberá implementar todas las funciones que la DLL de origen implementa y delegar cada llamada nuevamente a la DLL de origen.
Y el problema es que se supone que no debes llamar a FreeLibrary() en DLLMain en un proceso de separación, entonces, ¿cómo vas a limpiar DLL_B? –
Un método común es tener llamadas init() y deinit() para el archivo DLL_A que carga/descarga DLL_B (y realiza otras funciones de inicio/limpieza). Es intrusivo, pero es directo. –
En este caso, deseo * que * DLL_B se quede atrás hasta que se cierre la aplicación principal. De hecho, esto es ideal para mí. Mi intención es inyectar el archivo DLL y un hilo que creará en la aplicación. – mj2008