DelayLoadLibrary.cpp 12 KB

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