2

How to obtain the modules list of a running process(for example a game launcher) then loop through the list and get a handle of the modules(dlls) to check if a certain function exists.

Thanks in advance,

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686849(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx

But those are for c++ and I wasn't able to find some for c# .

Jax
  • 977
  • 8
  • 22
  • 40
  • By the way, I notice that you've asked 62 questions here, but only voted 3 times. We all appreciate a bit more participation than that. Thanks. – David Heffernan Sep 29 '12 at 23:22

2 Answers2

4

To get the list of running processes:

Process[] processes = Process.GetProcesses();

You can then loop through the processes array looking for your target process.

Then you can call

ProcessModuleCollection modules = targetProcess.Modules;

to get hold of all the modules.

Then you can iterate over that collection and find each module's filename or handle. Note that the handle, the HMODULE in Win32 terms, is given by the BaseAddress property.

Finding out information about the exported functions is a little more difficult. That information is not readily available through the .net classes, and even in raw Win32 it's tricky because your code is executing out of process. You can't do anything with the HMODULE from another process.

The way to check for existence of a function is to use the dbghelp library to parse the PE data of the actual module file. I couldn't find any code on the web to do this, so I produced this translation of another Stack Overflow answer of mine. Note that I used a number of declarations from pinvoke.net. I hope this helps!

using System;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;

internal static class NativeMethods
{
    [Flags]
    public enum EFileAccess : uint
    {
        //
        // Standard Section
        //

        AccessSystemSecurity = 0x1000000,   // AccessSystemAcl access type
        MaximumAllowed = 0x2000000,     // MaximumAllowed access type

        Delete = 0x10000,
        ReadControl = 0x20000,
        WriteDAC = 0x40000,
        WriteOwner = 0x80000,
        Synchronize = 0x100000,

        StandardRightsRequired = 0xF0000,
        StandardRightsRead = ReadControl,
        StandardRightsWrite = ReadControl,
        StandardRightsExecute = ReadControl,
        StandardRightsAll = 0x1F0000,
        SpecificRightsAll = 0xFFFF,

        FILE_READ_DATA = 0x0001,        // file & pipe
        FILE_LIST_DIRECTORY = 0x0001,       // directory
        FILE_WRITE_DATA = 0x0002,       // file & pipe
        FILE_ADD_FILE = 0x0002,         // directory
        FILE_APPEND_DATA = 0x0004,      // file
        FILE_ADD_SUBDIRECTORY = 0x0004,     // directory
        FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe
        FILE_READ_EA = 0x0008,          // file & directory
        FILE_WRITE_EA = 0x0010,         // file & directory
        FILE_EXECUTE = 0x0020,          // file
        FILE_TRAVERSE = 0x0020,         // directory
        FILE_DELETE_CHILD = 0x0040,     // directory
        FILE_READ_ATTRIBUTES = 0x0080,      // all
        FILE_WRITE_ATTRIBUTES = 0x0100,     // all

        //
        // Generic Section
        //

        GenericRead = 0x80000000,
        GenericWrite = 0x40000000,
        GenericExecute = 0x20000000,
        GenericAll = 0x10000000,

        SPECIFIC_RIGHTS_ALL = 0x00FFFF,
        FILE_ALL_ACCESS =
        StandardRightsRequired |
        Synchronize |
        0x1FF,

        FILE_GENERIC_READ =
        StandardRightsRead |
        FILE_READ_DATA |
        FILE_READ_ATTRIBUTES |
        FILE_READ_EA |
        Synchronize,

        FILE_GENERIC_WRITE =
        StandardRightsWrite |
        FILE_WRITE_DATA |
        FILE_WRITE_ATTRIBUTES |
        FILE_WRITE_EA |
        FILE_APPEND_DATA |
        Synchronize,

        FILE_GENERIC_EXECUTE =
        StandardRightsExecute |
          FILE_READ_ATTRIBUTES |
          FILE_EXECUTE |
          Synchronize
    }

    [Flags]
    public enum EFileShare : uint
    {
        /// <summary>
        /// 
        /// </summary>
        None = 0x00000000,
        /// <summary>
        /// Enables subsequent open operations on an object to request read access. 
        /// Otherwise, other processes cannot open the object if they request read access. 
        /// If this flag is not specified, but the object has been opened for read access, the function fails.
        /// </summary>
        Read = 0x00000001,
        /// <summary>
        /// Enables subsequent open operations on an object to request write access. 
        /// Otherwise, other processes cannot open the object if they request write access. 
        /// If this flag is not specified, but the object has been opened for write access, the function fails.
        /// </summary>
        Write = 0x00000002,
        /// <summary>
        /// Enables subsequent open operations on an object to request delete access. 
        /// Otherwise, other processes cannot open the object if they request delete access.
        /// If this flag is not specified, but the object has been opened for delete access, the function fails.
        /// </summary>
        Delete = 0x00000004
    }

    public enum ECreationDisposition : uint
    {
        /// <summary>
        /// Creates a new file. The function fails if a specified file exists.
        /// </summary>
        New = 1,
        /// <summary>
        /// Creates a new file, always. 
        /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, 
        /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies.
        /// </summary>
        CreateAlways = 2,
        /// <summary>
        /// Opens a file. The function fails if the file does not exist. 
        /// </summary>
        OpenExisting = 3,
        /// <summary>
        /// Opens a file, always. 
        /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW.
        /// </summary>
        OpenAlways = 4,
        /// <summary>
        /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist.
        /// The calling process must open the file with the GENERIC_WRITE access right. 
        /// </summary>
        TruncateExisting = 5
    }

    [Flags]
    public enum EFileAttributes : uint
    {
        Readonly = 0x00000001,
        Hidden = 0x00000002,
        System = 0x00000004,
        Directory = 0x00000010,
        Archive = 0x00000020,
        Device = 0x00000040,
        Normal = 0x00000080,
        Temporary = 0x00000100,
        SparseFile = 0x00000200,
        ReparsePoint = 0x00000400,
        Compressed = 0x00000800,
        Offline = 0x00001000,
        NotContentIndexed = 0x00002000,
        Encrypted = 0x00004000,
        Write_Through = 0x80000000,
        Overlapped = 0x40000000,
        NoBuffering = 0x20000000,
        RandomAccess = 0x10000000,
        SequentialScan = 0x08000000,
        DeleteOnClose = 0x04000000,
        BackupSemantics = 0x02000000,
        PosixSemantics = 0x01000000,
        OpenReparsePoint = 0x00200000,
        OpenNoRecall = 0x00100000,
        FirstPipeInstance = 0x00080000
    }

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern SafeFileHandle CreateFile(
        string lpFileName,
        EFileAccess dwDesiredAccess,
        EFileShare dwShareMode,
        IntPtr lpSecurityAttributes,
        ECreationDisposition dwCreationDisposition,
        EFileAttributes dwFlagsAndAttributes,
        IntPtr hTemplateFile
    );

    [Flags]
    public enum FileMapProtection : uint
    {
        PageReadonly = 0x02,
        PageReadWrite = 0x04,
        PageWriteCopy = 0x08,
        PageExecuteRead = 0x20,
        PageExecuteReadWrite = 0x40,
        SectionCommit = 0x8000000,
        SectionImage = 0x1000000,
        SectionNoCache = 0x10000000,
        SectionReserve = 0x4000000,
    }

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern SafeFileHandle CreateFileMapping(
        SafeFileHandle hFile,
        IntPtr lpFileMappingAttributes,
        FileMapProtection flProtect,
        uint dwMaximumSizeHigh,
        uint dwMaximumSizeLow,
        string lpName
    );

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern SafeFileHandle CreateFileMapping(
        SafeFileHandle hFile,
        IntPtr lpFileMappingAttributes,
        FileMapProtection flProtect,
        uint dwMaximumSizeHigh,
        uint dwMaximumSizeLow,
        IntPtr lpName
    );

    [Flags]
    public enum FileMapAccess : uint
    {
        FileMapCopy = 0x0001,
        FileMapWrite = 0x0002,
        FileMapRead = 0x0004,
        FileMapAllAccess = 0x001f,
        FileMapExecute = 0x0020,
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr MapViewOfFile(
        SafeFileHandle hFileMappingObject,
        FileMapAccess dwDesiredAccess,
        UInt32 dwFileOffsetHigh,
        UInt32 dwFileOffsetLow,
        UIntPtr dwNumberOfBytesToMap
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

    [StructLayout(LayoutKind.Sequential)]
    public struct IMAGE_FILE_HEADER
    {
        public UInt16 Machine;
        public UInt16 NumberOfSections;
        public UInt32 TimeDateStamp;
        public UInt32 PointerToSymbolTable;
        public UInt32 NumberOfSymbols;
        public UInt16 SizeOfOptionalHeader;
        public UInt16 Characteristics;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IMAGE_DATA_DIRECTORY
    {
        public UInt32 VirtualAddress;
        public UInt32 Size;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IMAGE_OPTIONAL_HEADER
    {
        public UInt16 Magic;
        public Byte MajorLinkerVersion;
        public Byte MinorLinkerVersion;
        public UInt32 SizeOfCode;
        public UInt32 SizeOfInitializedData;
        public UInt32 SizeOfUninitializedData;
        public UInt32 AddressOfEntryPoint;
        public UInt32 BaseOfCode;
        public UInt32 BaseOfData;
        public UInt32 ImageBase;
        public UInt32 SectionAlignment;
        public UInt32 FileAlignment;
        public UInt16 MajorOperatingSystemVersion;
        public UInt16 MinorOperatingSystemVersion;
        public UInt16 MajorImageVersion;
        public UInt16 MinorImageVersion;
        public UInt16 MajorSubsystemVersion;
        public UInt16 MinorSubsystemVersion;
        public UInt32 Win32VersionValue;
        public UInt32 SizeOfImage;
        public UInt32 SizeOfHeaders;
        public UInt32 CheckSum;
        public UInt16 Subsystem;
        public UInt16 DllCharacteristics;
        public UInt32 SizeOfStackReserve;
        public UInt32 SizeOfStackCommit;
        public UInt32 SizeOfHeapReserve;
        public UInt32 SizeOfHeapCommit;
        public UInt32 LoaderFlags;
        public UInt32 NumberOfRvaAndSizes;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public IMAGE_DATA_DIRECTORY[] DataDirectory;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IMAGE_NT_HEADERS
    {
        public UInt32 Signature;
        public IMAGE_FILE_HEADER FileHeader;
        public IMAGE_OPTIONAL_HEADER OptionalHeader;
    }

    [DllImport("dbghelp.dll", SetLastError = true)]
    public static extern IntPtr ImageNtHeader(
        IntPtr ImageBase
    );

    [StructLayout(LayoutKind.Sequential)]
    public struct IMAGE_EXPORT_DIRECTORY
    {
        public UInt32 Characteristics;
        public UInt32 TimeDateStamp;
        public UInt16 MajorVersion;
        public UInt16 MinorVersion;
        public UInt32 Name;
        public UInt32 Base;
        public UInt32 NumberOfFunctions;
        public UInt32 NumberOfNames;
        public UInt32 AddressOfFunctions;     // RVA from base of image
        public UInt32 AddressOfNames;     // RVA from base of image
        public UInt32 AddressOfNameOrdinals;  // RVA from base of image
    }

    [DllImport("dbghelp.dll", SetLastError = true)]
    public static extern IntPtr ImageRvaToVa(
        IntPtr NtHeaders,
        IntPtr Base,
        UInt32 Rva,
        IntPtr LastRvaSection
    );
}

namespace ConsoleApplication1
{
    class Program
    {
        private static string[] GetExports(string ModuleFileName)
        {
            SafeFileHandle FileHandle = NativeMethods.CreateFile(
                ModuleFileName,
                NativeMethods.EFileAccess.GenericRead,
                NativeMethods.EFileShare.Read,
                IntPtr.Zero,
                NativeMethods.ECreationDisposition.OpenExisting,
                NativeMethods.EFileAttributes.Normal,
                IntPtr.Zero
            );
            if (FileHandle.IsInvalid)
                throw new Win32Exception();

            try
            {
                SafeFileHandle ImageHandle = NativeMethods.CreateFileMapping(
                    FileHandle,
                    IntPtr.Zero,
                    NativeMethods.FileMapProtection.PageReadonly,
                    0,
                    0,
                    IntPtr.Zero
                );
                if (ImageHandle.IsInvalid)
                    throw new Win32Exception();

                try
                {
                    IntPtr ImagePointer = NativeMethods.MapViewOfFile(
                        ImageHandle,
                        NativeMethods.FileMapAccess.FileMapRead,
                        0,
                        0,
                        UIntPtr.Zero
                    );
                    if (ImagePointer == IntPtr.Zero)
                        throw new Win32Exception();

                    try
                    {
                        IntPtr HeaderPointer = NativeMethods.ImageNtHeader(ImagePointer);
                        if (HeaderPointer == IntPtr.Zero)
                            throw new Win32Exception();

                        NativeMethods.IMAGE_NT_HEADERS Header = (NativeMethods.IMAGE_NT_HEADERS)Marshal.PtrToStructure(
                            HeaderPointer,
                            typeof(NativeMethods.IMAGE_NT_HEADERS)
                        );
                        if (Header.Signature != 0x00004550)// "PE\0\0" as a DWORD
                            throw new Exception(ModuleFileName + " is not a valid PE file");

                        IntPtr ExportTablePointer = NativeMethods.ImageRvaToVa(
                            HeaderPointer,
                            ImagePointer,
                            Header.OptionalHeader.DataDirectory[0].VirtualAddress,
                            IntPtr.Zero
                        );
                        if (ExportTablePointer == IntPtr.Zero)
                            throw new Win32Exception();
                        NativeMethods.IMAGE_EXPORT_DIRECTORY ExportTable = (NativeMethods.IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
                            ExportTablePointer,
                            typeof(NativeMethods.IMAGE_EXPORT_DIRECTORY)
                        );

                        IntPtr NamesPointer = NativeMethods.ImageRvaToVa(
                            HeaderPointer,
                            ImagePointer,
                            ExportTable.AddressOfNames,
                            IntPtr.Zero
                        );
                        if (NamesPointer == IntPtr.Zero)
                            throw new Win32Exception();

                        NamesPointer = NativeMethods.ImageRvaToVa(
                            HeaderPointer,
                            ImagePointer,
                            (UInt32)Marshal.ReadInt32(NamesPointer),
                            IntPtr.Zero
                        );
                        if (NamesPointer == IntPtr.Zero)
                            throw new Win32Exception();

                        string[] exports = new string[ExportTable.NumberOfNames];
                        for (int i = 0; i < exports.Length; i++)
                        {
                            exports[i] = Marshal.PtrToStringAnsi(NamesPointer);
                            NamesPointer += exports[i].Length + 1;
                        }

                        return exports;
                    }
                    finally
                    {
                        if (!NativeMethods.UnmapViewOfFile(ImagePointer))
                            throw new Win32Exception();
                    }
                }
                finally
                {
                    ImageHandle.Close();
                }
            }
            finally
            {
                FileHandle.Close();
            }
        }

        static void Main(string[] args)
        {
            foreach (string s in GetExports(@"C:\Windows\System32\kernel32.dll"))
            {
                Console.WriteLine(s);
            }
            Console.ReadLine();
        }
    }
}
Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

You need to use P/Invoke to access the C++ functions. I would suggest you check out how to use P/Invoke and http://www.pinvoke.net/ (has a lot of resources for standard dlls), because the topic of P/Invoke is a bit much to be covered here.

Here is an example of how to use the DbgHelp dll to get the symbols from a loaded module. dummy3.dll is a dummy dll I created with C++, .net dlls don't have any symbols. If I understand correct it's because they just contain one large blob of bytecode. If you're enumerating all the loaded modules you'll probably want to use SymEnumerateModules64 like described here:

using System;
using System.Collections;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Runtime.InteropServices;

namespace dummy
{
    class Program
    {
        static bool EnumSymProc(ref DbgHelp.SYMBOL_INFO pSymInfo,
            UInt32 SymbolSize,
            IntPtr UserContext)
        {
            Console.WriteLine(pSymInfo.Address + " " + SymbolSize + " " + pSymInfo.Name);
            return true;
        }

        static void Main(string[] args)
        {
            Process process = Process.GetCurrentProcess();
            ulong BaseOfDll;
            string Mask = "*";
            bool status;

            status = DbgHelp.SymInitialize(process.Handle, null, false);
            if (status == false)
            {
                return;
            }

            BaseOfDll = DbgHelp.SymLoadModuleEx(process.Handle,
                                        IntPtr.Zero,
                                        "dummy3.dll",
                                        null,
                                        IntPtr.Zero,
                                        0,
                                        IntPtr.Zero,
                                        0);

            if (BaseOfDll == 0)
            {
                DbgHelp.SymCleanup(process.Handle);
                return;
            }

            if (DbgHelp.SymEnumSymbols(process.Handle,     // Process handle from SymInitialize.
                                BaseOfDll,   // Base address of module.
                                Mask,        // Name of symbols to match.
                                new DbgHelp.SymEnumSymbolsProc(EnumSymProc), // Symbol handler procedure.
                                IntPtr.Zero))       // User context.
            {
                // SymEnumSymbols succeeded
            }
            else
            {
                // SymEnumSymbols failed
                Console.WriteLine("SymEnumSymbols failed: " + Marshal.GetLastWin32Error());
            }

            DbgHelp.SymCleanup(process.Handle);
        }
    }

    public static class DbgHelp
    {
        [Flags]
        public enum SymOpt : uint
        {
            CASE_INSENSITIVE = 0x00000001,
            UNDNAME = 0x00000002,
            DEFERRED_LOADS = 0x00000004,
            NO_CPP = 0x00000008,
            LOAD_LINES = 0x00000010,
            OMAP_FIND_NEAREST = 0x00000020,
            LOAD_ANYTHING = 0x00000040,
            IGNORE_CVREC = 0x00000080,
            NO_UNQUALIFIED_LOADS = 0x00000100,
            FAIL_CRITICAL_ERRORS = 0x00000200,
            EXACT_SYMBOLS = 0x00000400,
            ALLOW_ABSOLUTE_SYMBOLS = 0x00000800,
            IGNORE_NT_SYMPATH = 0x00001000,
            INCLUDE_32BIT_MODULES = 0x00002000,
            PUBLICS_ONLY = 0x00004000,
            NO_PUBLICS = 0x00008000,
            AUTO_PUBLICS = 0x00010000,
            NO_IMAGE_SEARCH = 0x00020000,
            SECURE = 0x00040000,
            SYMOPT_DEBUG = 0x80000000
        };

        [Flags]
        public enum SymFlag : uint
        {
            VALUEPRESENT = 0x00000001,
            REGISTER = 0x00000008,
            REGREL = 0x00000010,
            FRAMEREL = 0x00000020,
            PARAMETER = 0x00000040,
            LOCAL = 0x00000080,
            CONSTANT = 0x00000100,
            EXPORT = 0x00000200,
            FORWARDER = 0x00000400,
            FUNCTION = 0x00000800,
            VIRTUAL = 0x00001000,
            THUNK = 0x00002000,
            TLSREL = 0x00004000,
        }

        [Flags]
        public enum SymTagEnum : uint
        {
            Null,
            Exe,
            Compiland,
            CompilandDetails,
            CompilandEnv,
            Function,
            Block,
            Data,
            Annotation,
            Label,
            PublicSymbol,
            UDT,
            Enum,
            FunctionType,
            PointerType,
            ArrayType,
            BaseType,
            Typedef,
            BaseClass,
            Friend,
            FunctionArgType,
            FuncDebugStart,
            FuncDebugEnd,
            UsingNamespace,
            VTableShape,
            VTable,
            Custom,
            Thunk,
            CustomType,
            ManagedType,
            Dimension
        };

        [Flags]
        public enum SymType : uint
        {
            SymNone,
            SymCoff,
            SymCv,
            SymPdb,
            SymExport,
            SymDeferred,
            SymSym,
            SymDia,
            SymVirtual,
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SYMBOL_INFO
        {
            public uint SizeOfStruct;
            public uint TypeIndex;
            public ulong Reserved1;
            public ulong Reserved2;
            public uint Reserved3;
            public uint Size;
            public ulong ModBase;
            public SymFlag Flags;
            public ulong Value;
            public ulong Address;
            public uint Register;
            public uint Scope;
            public SymTagEnum Tag;
            public int NameLen;
            public int MaxNameLen;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public string Name;
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct MODLOAD_DATA
        {
            UInt32 ssize;
            UInt32 ssig;
            object data;
            UInt32 size;
            UInt32 flags;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct _IMAGEHLP_LINE64
        {
            public uint SizeOfStruct;
            public uint Key;
            public uint LineNumber;
            public IntPtr FileName;
            public ulong Address;
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct IMAGEHLP_MODULE64
        {
            public uint SizeOfStruct;
            public ulong BaseOfImage;
            public uint ImageSize;
            public uint TimeDateStamp;
            public uint CheckSum;
            public uint NumSyms;
            public SymType SymType;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string ModuleName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string ImageName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string LoadedImageName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string LoadedPdbName;
            public uint CVSig;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 780)]
            public string CVData;
            public uint PdbSig;
            public Guid PdbSig70;
            public uint PdbAge;
            public bool PdbUnmatched;
            public bool DbgUnmatched;
            public bool LineNumbers;
            public bool GlobalSymbols;
            public bool TypeInfo;
            public bool SourceIndexed;
            public bool Publics;
        }

        public delegate bool SymEnumSymbolsProc(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, bool fInvadeProcess);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern uint SymSetOptions(SymOpt SymOptions);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern ulong SymLoadModule64(IntPtr hProcess, IntPtr hFile,
           string ImageName, string ModuleName,
           ulong BaseOfDll, uint SizeOfDll);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile,
            string ImageName, string ModuleName, IntPtr BaseOfDll,
            UInt32 DllSize, ref MODLOAD_DATA Data, UInt32 Flags);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile,
            string ImageName, string ModuleName, IntPtr BaseOfDll,
            UInt32 DllSize, IntPtr Data, UInt32 Flags);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymGetModuleInfo64(IntPtr hProcess, ulong dwAddress, ref IMAGEHLP_MODULE64 ModuleInfo);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymEnumSymbols(IntPtr hProcess, ulong BaseOfDll, string Mask, SymEnumSymbolsProc EnumSymbolsCallback, IntPtr UserContext);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymGetLineFromAddr64(IntPtr hProcess,
           ulong dwAddr, ref uint pdwDisplacement, ref _IMAGEHLP_LINE64 Line);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymFromAddr(IntPtr hProcess,
           ulong dwAddr, ref ulong pdwDisplacement, ref SYMBOL_INFO symbolInfo);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymEnumSymbolsForAddr(IntPtr hProcess,
           ulong Address, SymEnumSymbolsProc EnumSymbolsCallback, IntPtr UserContext);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymUnloadModule64(IntPtr hProcess, ulong BaseOfDll);

        [DllImport("dbghelp.dll", SetLastError = true)]
        public static extern bool SymCleanup(IntPtr hProcess);
    }
}
CrazyCasta
  • 26,917
  • 4
  • 45
  • 72
  • This doesn't really look like an answer to me. – David Heffernan Sep 29 '12 at 21:56
  • @DavidHeffernan Are you suggesting I write his code for him? He seems to have some C++ code, and I'm suggesting P/Invoke is the way to transform it into C# code. He's likely to need some more P/Invoke code to do w/e he wants with these functions he's checking the existance of. – CrazyCasta Sep 29 '12 at 21:58
  • Yes I have the documentation in c++ but I never used it because I'm not using c++. – Jax Sep 29 '12 at 22:17
  • @Jax If you're going to do this kind of system type stuff I would suggest you get familiar with P/Invoke because it will likely become a necessity very soon (probably will be to get the list of functions). – CrazyCasta Sep 29 '12 at 23:08
  • The question asks about exported functions. This code is for symbols. Completely different. – David Heffernan Sep 30 '12 at 00:46
  • @DavidHeffernan No where in the question does it mention "export". As I understand it, all exports are also symbols, though I could be wrong about that. – CrazyCasta Sep 30 '12 at 02:04
  • These are debug symbols. For many DLLs there will be no debug symbols. You said it yourself when you suggested calling GetProcAddress. That looks for exports. Which is what my answer checks for. Your answer checks for something else. – David Heffernan Sep 30 '12 at 08:21
  • If I understand correct SymEnumSymbols will always contain the exports. Either it reads the debugging symbols from a file (like a pdb) or it reads the exports. Presumably a pdb or other debugging source would include the exports, which is why I conclude it will always include the exports. If the OP would prefer to not see additional non-exported functions (in case they collide with functions exported from another dll) then he would be best off using your code. – CrazyCasta Sep 30 '12 at 08:43