|  | 
 
| Windows Phone 8加载外部动态链接库DLL(非安装包内的) 在《动态加载与插件化》中大概介绍了下,wp8加载非安装包的下动态链接库,这次详细梳理下。
 加载外部DLL主要的原理:
 
 
 相关的结构体:
 通过NtCurrentTeb获得线程环境块
从线程环境块中获得进程环境块
在进程环境块中加载过得DLL链表
从链表中找到kernelbase.dll的模块句柄
从kernelbase.dll中获得LoadLibraryEx函数地址
加载指定地址下的DLL
 typedef struct _CLIENT_ID
 {
 PVOID UniqueProcess;
 PVOID UniqueThread;
 } CLIENT_ID;
 
 //模块链表实体
 typedef struct _MODULE_LIST_ENTRY
 {
 struct  _MODULE_LIST_ENTRY* Flink;
 struct  _MODULE_LIST_ENTRY* Blink;
 DWORD* baseAddress;
 }MODULE_LIST_ENTRY;
 
 //进程加载的模块信息
 typedef struct _PEB_LDR_DATA
 {
 //    BYTE fill[0x1c]; x86
 ULONG Length;
 BOOLEAN Initialized;
 PVOID SsHandle ;
 LIST_ENTRY InLoadOrderModuleList;
 LIST_ENTRY InMemoryOrderModuleList;
 MODULE_LIST_ENTRY* initModuleList;
 }PEB_LDR_DATA;
 
 //进程环境块
 typedef struct _PEB
 {
 //    BYTE fill[0x0c]; x86
 BYTE Reserved1[2];
 BYTE BeingDebugged;
 BYTE Reserved2[1];
 PVOID Reserved3[2];
 PEB_LDR_DATA* ldr;
 }PEB;
 
 //线程环境块
 typedef struct _TEB
 {
 //BYTE fill[0x30]; x86
 NT_TIB nt_tib;
 PVOID EnvironmentPointer;
 CLIENT_ID id;
 PVOID ActiveRpcHandle;
 PVOID ThreadLocalStoragePointer;
 PEB* currentPEB;
 }TEB;
 
 typedef HMODULE(*LoadLibraryEx)(
 LPCTSTR lpLibFileName,
 HANDLE hFile,
 DWORD dwFlags
 );
 
 获取kernelbase.dll模块句柄的类定义
 
 namespace Anye
 {
 namespace Native
 {
 public ref class DllHandle sealed
 {
 friend ref class NativeInterop;
 friend class NativeHelper;
 public:
 int GetModule();
 private:
 HMODULE _handle;
 DllHandle(HMODULE handle);
 
 //获取指定名称的函数地址
 void* GetFunction(LPCSTR name);
 };
 
 
 public ref class NativeInterop sealed
 {
 public:
 NativeInterop();
 //加载指定路径下的DLL
 
 DllHandle^ LoadLibrary(Platform::String^ name);
 
 //获取KernelBase.dll的模块句柄
 DllHandle^ GetKernel();
 int GetModule();
 private:
 DllHandle^ _kernel;
 LoadLibraryEx _loadLibrary;
 HMODULE getKernelModule();
 };
 
 
 class NativeHelper
 {
 public:
 NativeHelper(const wchar_t* path);
 void* GetFunction(LPCSTR name);
 private:
 DllHandle^ _interop;
 };
 
 
 }
 }
 
 
 主要的加载逻辑
 
 HMODULE NativeInterop::getKernelModule()
 {
 
 //获取线程环境快
 TEB* teb = NtCurrentTeb();
 获取KernelBase.dll的模块句柄PS:保险点的方法市历遍DLL初始化链表通过模块名称确定
 return (HMODULE) teb->currentPEB->ldr->initModuleList->Flink->baseAddress;
 }
 
 
 DllHandle^ NativeInterop::LoadLibrary(Platform::String^ name)
 {
 if (_loadLibrary == nullptr)//获取LoadLibraryExW函数地址
 _loadLibrary = (LoadLibraryEx)_kernel->GetFunction("LoadLibraryExW");
 
 
 HMODULE module = _loadLibrary(name->Data(), nullptr, 0);
 if (module != nullptr)
 return ref new DllHandle(module);
 
 
 return nullptr;
 }
 
 
 
 void* DllHandle::GetFunction(LPCSTR name)
 {
 return GetProcAddress(_handle, name);
 }
 
 
 NativeHelper
 
 NativeHelper::NativeHelper(const wchar_t* path)
 {
 auto inter = ref new NativeInterop();
 String^ pathString = (Platform::String^)Platform::StringReference(path);
 _interop = inter->LoadLibrary(pathString);
 }
 
 
 void* NativeHelper::GetFunction(LPCSTR name)
 {
 return _interop->GetFunction(name);
 
 }
 
 下面是加载wp手机SD卡上的plugin.dll的例子
 
   动态库项目
 
 
 
   动态链接库逻辑
 
 extern "C"
 {
 __declspec(dllexport) void* Create();
 }
 
 
 namespace Plugin
 {
 class IPlugin
 {
 public:
 virtual void Show(Platform::String^ msg) = 0;
 };
 
 
 class TestPlugin : public IPlugin
 {
 public:
 TestPlugin()
 {
 
 }
 
 
 void Show(Platform::String^ msg)
 {
 (ref new Windows::UI::Popups::MessageDialog(msg))->ShowAsync();
 }
 };
 }
 
 
 void* Create()
 {
 return new Plugin::TestPlugin();
 }
 
 加载外部动态链接库
 
 class IPlugin
 {
 public:
 virtual void Show(Platform::String^ msg) = 0;
 };
 
 
 void NativeEntry::Load(Platform::String^ path)
 {    //path 是 D:\\Downloads\\plugin.dll,D盘就是sd
 Anye::Native::NativeHelper* h = new Anye::Native::NativeHelper(path->Data());
 CreateFunc func;
 
 func = (CreateFunc)h->GetFunction("Create");
 
 
 IPlugin* plugin = (IPlugin*)func();
 
 
 plugin->Show("我是"+path+"里的插件^_^");
 }
 
 好了例子就到这了,我们获得了LoadLibraryExW函数,不局限于加载外部DLL,也可以去加载系统的DLL,去访问一些微软未公开的API,如只读访问注册表信息
 
 Anye::Native::NativeInterop interop;
 auto h = interop.LoadLibrary("ADVAPI32LEGACY.DLL");
 
 
 Anye_RegCreateKeyEx = (RegCreateKeyFunc)GetFunc(h->GetModule(), "RegCreateKeyW");
 Anye_RegSetValueEx = (RegSetValueFunc)GetFunc(h->GetModule(), "RegSetValueW");
 Anye_RegQueryValueEx = (RegQueryValueFunc)GetFunc(h->GetModule(), "RegQueryValueW");
 Anye_RegCloseKey = (RegCloseKeyFunc)GetFunc(h->GetModule(), "RegCloseKey");
 Anye_RegOpenKey = (RegOpenKeyFunc)GetFunc(h->GetModule(), "RegOpenKeyW");
 Anye_RegEnumKey = (RegEnumKeyFunc)GetFunc(h->GetModule(), "RegEnumKeyW");
 源码:https://onedrive.live.com/redir?resid=30D5EB407F085DD8!31587&authkey=!ABzmTswcDh91WQw&ithint=file%2czip
 | 
 | 
| 
 |