Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

685
Visualizações
DllImport con funciones no exportadas. ¿Por qué está funcionando?

Acabo de encontrarme con un comportamiento extraño de DllImport en C#, que no puedo explicar. Quiero saber cómo es posible y dónde puedo leer sobre ello. El caso es que a través de DllImport uno puede llamar a una función que realmente no exporta el formulario dll. En mi caso, es kernel32.dll y la función ZeroMemory (pero con Copiar/Mover/Rellenar memoria tal comportamiento). Entonces, mi código:

 [DllImport("kernel32", EntryPoint = "LoadLibraryW", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr LoadLibrary(string libName); [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr module, string procName); //WTF??? [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ZeroMemory(IntPtr address, int size); static void TestMemory() { IntPtr mem = Marshal.AllocHGlobal(100); //Allocate memory block of 100 bytes size Marshal.WriteByte(mem, 55); //Write some value in the first byte ZeroMemory(mem, 100); //Clearing block of memory byte firstByte = Marshal.ReadByte(mem); //Read the first byte of memory block Console.WriteLine(firstByte); //Output 0 (not 55) - ZeroMemory is working //Getting address of ZeroMemory from kernel32.dll IntPtr kernelHandle = LoadLibrary("kernel32.dll"); IntPtr address = GetProcAddress(kernelHandle, "ZeroMemory"); Console.WriteLine(address.ToString("X")); //Output 0 - Library kernel32.dll DOESN'T export function ZeroMemory!!! //Testing GetProcAddress via getting address of some exported function Console.WriteLine(GetProcAddress(kernelHandle, "AllocConsole").ToString("X")); //Output some address value - all is OK. }

No se lanza ninguna excepción EntryPointNotFoundException; el código funciona bien. Si cambia el nombre de ZeroMemory a ZeroMemory1 o algo así, se lanzará una excepción. Pero en la tabla de exportación de kernel32.dll vemos:

¡NO hay memoria cero!

¡NO hay función ZeroMemory en absoluto! Si miramos en msdn , leemos que ZeroMemory es solo una macro en el archivo de encabezado WinBase.h para C++. Dentro de eso vemos:

 #define RtlMoveMemory memmove #define RtlCopyMemory memcpy #define RtlFillMemory(d,l,f) memset((d), (f), (l)) #define RtlZeroMemory(d,l) RtlFillMemory((d),(l),0) #define MoveMemory RtlMoveMemory #define CopyMemory RtlCopyMemory #define FillMemory RtlFillMemory #define ZeroMemory RtlZeroMemory

Obviamente, eso en C++ ZeroMemory en realidad funciona a través de RtlFillMemory desde ntdll.dll. ¡¡¡Pero está en C++!!! ¿Por qué funciona en C#? En la documentación oficial para el atributo DllImport aquí podemos leer lo siguiente:

Como requisito mínimo, debe proporcionar el nombre de la DLL que contiene el punto de entrada.

Pero en ese caso, kernel32.dll NO PUEDE contener el punto de entrada para ZeroMemory. ¿¿Que esta pasando?? Ayuda por favor.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

El OP es correcto en cuanto a que kernel32.dll no tiene exportación ZeroMemory , pero C# DllImport de alguna manera logra resolver mágicamente la referencia ZeroMemory a la exportación RtlZeroMemory correcta en aplicaciones .NET dirigidas al Framework (pero no al Core).

Resulta que un puñado de API de Win32 documentadas como en línea/macros ( MoveMemory , CopyMemory FillMemory , ZeroMemory ) son verificadas específicamente por el código de Framework y redirigidas internamente a las exportaciones correctas. Si bien no está documentado formalmente, esto se reconoció en un comentario autorizado por MS en un problema de .NET Runtime .

Como información, había algunos nombres P/Invoke en mayúsculas y minúsculas en .NET Framework: MoveMemory , CopyMemory , FillMemory y ZeroMemory . Todos estos funcionarán cuando apunten a kernel32 en .NET Framework, pero fallarán en .NET Core. Utilice la propiedad EntryPoint en el atributo DllImport para obtener el comportamiento deseado. Los nombres de exportación adecuados se pueden encontrar utilizando dumpbin /exports kernel32.dll desde un símbolo del sistema de Visual Studio.

Lo anterior sugiere agregar un EntryPoint explícito para que la declaración funcione tanto en Framework como en Core, por ejemplo:

 [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)] public static extern void ZeroMemory(IntPtr address, IntPtr count);

La reasignación mágica del nombre ocurre fuera del código .NET de fuente abierta, pero se puede ver claramente en el desensamblado aportado por Simon Mourier en un comentario.

ingrese la descripción de la imagen aquí

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda