DelayLoadLibrary.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "CommonCorePch.h"
  6. #include "Core/DelayLoadLibrary.h"
  7. DelayLoadLibrary::DelayLoadLibrary()
  8. {
  9. m_hModule = nullptr;
  10. m_isInit = false;
  11. }
  12. DelayLoadLibrary::~DelayLoadLibrary()
  13. {
  14. if (m_hModule)
  15. {
  16. FreeLibrary(m_hModule);
  17. m_hModule = nullptr;
  18. }
  19. }
  20. void DelayLoadLibrary::Ensure(DWORD dwFlags)
  21. {
  22. if (!m_isInit)
  23. {
  24. m_hModule = LoadLibraryEx(GetLibraryName(), nullptr, dwFlags);
  25. m_isInit = true;
  26. }
  27. }
  28. void DelayLoadLibrary::EnsureFromSystemDirOnly()
  29. {
  30. Ensure(LOAD_LIBRARY_SEARCH_SYSTEM32);
  31. }
  32. FARPROC DelayLoadLibrary::GetFunction(__in LPCSTR lpFunctionName)
  33. {
  34. if (m_hModule)
  35. {
  36. return GetProcAddress(m_hModule, lpFunctionName);
  37. }
  38. return nullptr;
  39. }
  40. bool DelayLoadLibrary::IsAvailable()
  41. {
  42. return m_hModule != nullptr;
  43. }
  44. #if _WIN32
  45. static Kernel32Library Kernel32LibraryObject;
  46. Kernel32Library* Kernel32Library::Instance = &Kernel32LibraryObject;
  47. LPCTSTR Kernel32Library::GetLibraryName() const
  48. {
  49. return _u("kernel32.dll");
  50. }
  51. HRESULT Kernel32Library::SetThreadDescription(
  52. _In_ HANDLE hThread,
  53. _In_ PCWSTR lpThreadDescription
  54. )
  55. {
  56. if (m_hModule)
  57. {
  58. if (setThreadDescription == nullptr)
  59. {
  60. setThreadDescription = (PFnSetThreadDescription)GetFunction("SetThreadDescription");
  61. if (setThreadDescription == nullptr)
  62. {
  63. return S_FALSE;
  64. }
  65. }
  66. return setThreadDescription(hThread, lpThreadDescription);
  67. }
  68. return S_FALSE;
  69. }
  70. static NtdllLibrary NtdllLibraryObject;
  71. NtdllLibrary* NtdllLibrary::Instance = &NtdllLibraryObject;
  72. LPCTSTR NtdllLibrary::GetLibraryName() const
  73. {
  74. return _u("ntdll.dll");
  75. }
  76. #if PDATA_ENABLED
  77. _Success_(return == 0)
  78. NtdllLibrary::NTSTATUS NtdllLibrary::AddGrowableFunctionTable( _Out_ PVOID * DynamicTable,
  79. _In_reads_(MaximumEntryCount) PRUNTIME_FUNCTION FunctionTable,
  80. _In_ DWORD EntryCount,
  81. _In_ DWORD MaximumEntryCount,
  82. _In_ ULONG_PTR RangeBase,
  83. _In_ ULONG_PTR RangeEnd )
  84. {
  85. Assert(AutoSystemInfo::Data.IsWin8OrLater());
  86. if(m_hModule)
  87. {
  88. if(addGrowableFunctionTable == NULL)
  89. {
  90. addGrowableFunctionTable = (PFnRtlAddGrowableFunctionTable)GetFunction("RtlAddGrowableFunctionTable");
  91. if(addGrowableFunctionTable == NULL)
  92. {
  93. Assert(false);
  94. return 1;
  95. }
  96. }
  97. #if DBG
  98. // Validate the PDATA was not registered or already unregistered
  99. ULONG_PTR imageBase = 0;
  100. RUNTIME_FUNCTION *runtimeFunction = RtlLookupFunctionEntry((DWORD64)RangeBase, &imageBase, nullptr);
  101. Assert(runtimeFunction == NULL);
  102. #endif
  103. *DynamicTable = nullptr;
  104. NTSTATUS status = addGrowableFunctionTable(DynamicTable,
  105. FunctionTable,
  106. EntryCount,
  107. MaximumEntryCount,
  108. RangeBase,
  109. RangeEnd);
  110. #if _M_X64
  111. PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("[%d]Register: Begin: %llx, End: %x, Unwind: %llx, RangeBase: %llx, RangeEnd: %llx, table: %llx, Status: %x\n"),
  112. GetCurrentThreadId(), FunctionTable->BeginAddress, FunctionTable->EndAddress, FunctionTable->UnwindInfoAddress, RangeBase, RangeEnd, *DynamicTable, status);
  113. #endif
  114. Assert((status >= 0 && *DynamicTable != nullptr) || status == 0xC000009A /*STATUS_INSUFFICIENT_RESOURCES*/);
  115. return status;
  116. }
  117. return 1;
  118. }
  119. VOID NtdllLibrary::DeleteGrowableFunctionTable( _In_ PVOID DynamicTable )
  120. {
  121. Assert(AutoSystemInfo::Data.IsWin8OrLater());
  122. if(m_hModule)
  123. {
  124. if(deleteGrowableFunctionTable == NULL)
  125. {
  126. deleteGrowableFunctionTable = (PFnRtlDeleteGrowableFunctionTable)GetFunction("RtlDeleteGrowableFunctionTable");
  127. if(deleteGrowableFunctionTable == NULL)
  128. {
  129. Assert(false);
  130. return;
  131. }
  132. }
  133. deleteGrowableFunctionTable(DynamicTable);
  134. PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("[%d]UnRegister: table: %llx\n"), GetCurrentThreadId(), DynamicTable);
  135. }
  136. }
  137. VOID NtdllLibrary::GrowFunctionTable(_Inout_ PVOID DynamicTable, _In_ ULONG NewEntryCount)
  138. {
  139. if (m_hModule)
  140. {
  141. if (growFunctionTable == nullptr)
  142. {
  143. growFunctionTable = (PFnRtlGrowFunctionTable)GetFunction("RtlGrowFunctionTable");
  144. if (growFunctionTable == nullptr)
  145. {
  146. Assert(false);
  147. return;
  148. }
  149. }
  150. growFunctionTable(DynamicTable, NewEntryCount);
  151. }
  152. }
  153. #endif // PDATA_ENABLED
  154. VOID NtdllLibrary::InitializeObjectAttributes(
  155. POBJECT_ATTRIBUTES InitializedAttributes,
  156. PUNICODE_STRING ObjectName,
  157. ULONG Attributes,
  158. HANDLE RootDirectory,
  159. PSECURITY_DESCRIPTOR SecurityDescriptor)
  160. {
  161. InitializedAttributes->Length = sizeof(OBJECT_ATTRIBUTES);
  162. InitializedAttributes->RootDirectory = RootDirectory;
  163. InitializedAttributes->Attributes = Attributes;
  164. InitializedAttributes->ObjectName = ObjectName;
  165. InitializedAttributes->SecurityDescriptor = SecurityDescriptor;
  166. InitializedAttributes->SecurityQualityOfService = NULL;
  167. }
  168. #ifndef DELAYLOAD_SECTIONAPI
  169. extern "C"
  170. WINBASEAPI
  171. NtdllLibrary::NTSTATUS
  172. WINAPI
  173. NtCreateSection(
  174. _Out_ PHANDLE SectionHandle,
  175. _In_ ACCESS_MASK DesiredAccess,
  176. _In_opt_ NtdllLibrary::POBJECT_ATTRIBUTES ObjectAttributes,
  177. _In_opt_ PLARGE_INTEGER MaximumSize,
  178. _In_ ULONG SectionPageProtection,
  179. _In_ ULONG AllocationAttributes,
  180. _In_opt_ HANDLE FileHandle
  181. );
  182. #endif
  183. NtdllLibrary::NTSTATUS NtdllLibrary::CreateSection(
  184. _Out_ PHANDLE SectionHandle,
  185. _In_ ACCESS_MASK DesiredAccess,
  186. _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
  187. _In_opt_ PLARGE_INTEGER MaximumSize,
  188. _In_ ULONG SectionPageProtection,
  189. _In_ ULONG AllocationAttributes,
  190. _In_opt_ HANDLE FileHandle)
  191. {
  192. #ifdef DELAYLOAD_SECTIONAPI
  193. if (m_hModule)
  194. {
  195. if (createSection == nullptr)
  196. {
  197. createSection = (PFnNtCreateSection)GetFunction("NtCreateSection");
  198. if (createSection == nullptr)
  199. {
  200. Assert(false);
  201. SectionHandle = nullptr;
  202. return -1;
  203. }
  204. }
  205. return createSection(SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle);
  206. }
  207. SectionHandle = nullptr;
  208. return -1;
  209. #else
  210. return NtCreateSection(SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle);
  211. #endif
  212. }
  213. #ifndef DELAYLOAD_SECTIONAPI
  214. extern "C"
  215. WINBASEAPI
  216. NtdllLibrary::NTSTATUS
  217. WINAPI
  218. NtMapViewOfSection(
  219. _In_ HANDLE SectionHandle,
  220. _In_ HANDLE ProcessHandle,
  221. _Inout_ PVOID *BaseAddress,
  222. _In_ ULONG_PTR ZeroBits,
  223. _In_ SIZE_T CommitSize,
  224. _Inout_opt_ PLARGE_INTEGER SectionOffset,
  225. _Inout_ PSIZE_T ViewSize,
  226. _In_ NtdllLibrary::SECTION_INHERIT InheritDisposition,
  227. _In_ ULONG AllocationType,
  228. _In_ ULONG Win32Protect
  229. );
  230. #endif
  231. NtdllLibrary::NTSTATUS NtdllLibrary::MapViewOfSection(
  232. _In_ HANDLE SectionHandle,
  233. _In_ HANDLE ProcessHandle,
  234. _Inout_ PVOID *BaseAddress,
  235. _In_ ULONG_PTR ZeroBits,
  236. _In_ SIZE_T CommitSize,
  237. _Inout_opt_ PLARGE_INTEGER SectionOffset,
  238. _Inout_ PSIZE_T ViewSize,
  239. _In_ SECTION_INHERIT InheritDisposition,
  240. _In_ ULONG AllocationType,
  241. _In_ ULONG Win32Protect)
  242. {
  243. #ifdef DELAYLOAD_SECTIONAPI
  244. if (m_hModule)
  245. {
  246. if (mapViewOfSection == nullptr)
  247. {
  248. mapViewOfSection = (PFnNtMapViewOfSection)GetFunction("NtMapViewOfSection");
  249. if (mapViewOfSection == nullptr)
  250. {
  251. Assert(false);
  252. return -1;
  253. }
  254. }
  255. return mapViewOfSection(SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, Win32Protect);
  256. }
  257. return -1;
  258. #else
  259. return NtMapViewOfSection(SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, Win32Protect);
  260. #endif
  261. }
  262. #ifndef DELAYLOAD_SECTIONAPI
  263. extern "C"
  264. WINBASEAPI
  265. NtdllLibrary::NTSTATUS
  266. WINAPI
  267. NtUnmapViewOfSection(
  268. _In_ HANDLE ProcessHandle,
  269. _In_opt_ PVOID BaseAddress
  270. );
  271. #endif
  272. NtdllLibrary::NTSTATUS NtdllLibrary::UnmapViewOfSection(
  273. _In_ HANDLE ProcessHandle,
  274. _In_opt_ PVOID BaseAddress)
  275. {
  276. #ifdef DELAYLOAD_SECTIONAPI
  277. if (m_hModule)
  278. {
  279. if (unmapViewOfSection == nullptr)
  280. {
  281. unmapViewOfSection = (PFnNtUnmapViewOfSection)GetFunction("NtUnmapViewOfSection");
  282. if (unmapViewOfSection == nullptr)
  283. {
  284. Assert(false);
  285. return -1;
  286. }
  287. }
  288. return unmapViewOfSection(ProcessHandle, BaseAddress);
  289. }
  290. return -1;
  291. #else
  292. return NtUnmapViewOfSection(ProcessHandle, BaseAddress);
  293. #endif
  294. }
  295. #ifndef DELAYLOAD_SECTIONAPI
  296. extern "C"
  297. WINBASEAPI
  298. NtdllLibrary::NTSTATUS
  299. WINAPI
  300. NtClose(_In_ HANDLE Handle);
  301. #endif
  302. NtdllLibrary::NTSTATUS NtdllLibrary::Close(_In_ HANDLE Handle)
  303. {
  304. #ifdef DELAYLOAD_SECTIONAPI
  305. if (m_hModule)
  306. {
  307. if (close == nullptr)
  308. {
  309. close = (PFnNtClose)GetFunction("NtClose");
  310. if (close == nullptr)
  311. {
  312. Assert(false);
  313. return -1;
  314. }
  315. }
  316. return close(Handle);
  317. }
  318. return -1;
  319. #else
  320. return NtClose(Handle);
  321. #endif
  322. }
  323. #ifndef DELAYLOAD_UNLOCKMEMORY
  324. extern "C"
  325. WINBASEAPI
  326. NtdllLibrary::NTSTATUS
  327. WINAPI
  328. NtUnlockVirtualMemory(
  329. _In_ HANDLE ProcessHandle,
  330. _Inout_ PVOID *BaseAddress,
  331. _Inout_ PSIZE_T RegionSize,
  332. _In_ ULONG MapType
  333. );
  334. #endif
  335. NtdllLibrary::NTSTATUS NtdllLibrary::UnlockVirtualMemory(
  336. _In_ HANDLE ProcessHandle,
  337. _Inout_ PVOID *BaseAddress,
  338. _Inout_ PSIZE_T RegionSize,
  339. _In_ ULONG MapType)
  340. {
  341. #ifdef DELAYLOAD_UNLOCKMEMORY
  342. if (m_hModule)
  343. {
  344. if (unlock == nullptr)
  345. {
  346. unlock = (PFnNtUnlockVirtualMemory)GetFunction("NtUnlockVirtualMemory");
  347. if (unlock == nullptr)
  348. {
  349. Assert(false);
  350. return -1;
  351. }
  352. }
  353. return unlock(ProcessHandle, BaseAddress, RegionSize, MapType);
  354. }
  355. return -1;
  356. #else
  357. return NtUnlockVirtualMemory(ProcessHandle, BaseAddress, RegionSize, MapType);
  358. #endif
  359. }
  360. static RPCLibrary RPCLibraryObject;
  361. RPCLibrary* RPCLibrary::Instance = &RPCLibraryObject;
  362. LPCTSTR RPCLibrary::GetLibraryName() const
  363. {
  364. return _u("rpcrt4.dll");
  365. }
  366. RPC_STATUS RPCLibrary::RpcServerRegisterIf3(
  367. _In_ RPC_IF_HANDLE IfSpec,
  368. _In_opt_ UUID* MgrTypeUuid,
  369. _In_opt_ RPC_MGR_EPV* MgrEpv,
  370. _In_ unsigned int Flags,
  371. _In_ unsigned int MaxCalls,
  372. _In_ unsigned int MaxRpcSize,
  373. _In_opt_ RPC_IF_CALLBACK_FN* IfCallback,
  374. _In_opt_ void* SecurityDescriptor)
  375. {
  376. #if !(NTDDI_VERSION >= NTDDI_WIN8)
  377. if (m_hModule)
  378. {
  379. if (serverRegister == nullptr)
  380. {
  381. serverRegister = (PFnRpcServerRegisterIf3)GetFunction("RpcServerRegisterIf3");
  382. if (serverRegister == nullptr)
  383. {
  384. Assert(false);
  385. return -1;
  386. }
  387. }
  388. return serverRegister(IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, MaxRpcSize, IfCallback, SecurityDescriptor);
  389. }
  390. return -1;
  391. #else
  392. return ::RpcServerRegisterIf3(IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, MaxRpcSize, IfCallback, SecurityDescriptor);
  393. #endif
  394. }
  395. #endif // _WIN32