Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

667 lines
12 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. impl.c
  5. Abstract:
  6. Author:
  7. Matthew D Hendel (math) 22-Sept-1999
  8. Revision History:
  9. Comments:
  10. Any functions that will not be available on all platforms must be thunked
  11. so that the minidump dll will load on all platforms. For functions
  12. outside of NTDLL and KERNEL32, we use the delay-load import facility to
  13. achieve this. For functions that are in NTDLL and KERNEL32, we use bind
  14. the functions manually at DLL-load time.
  15. Functions:
  16. NTDLL
  17. NtOpenThread NT
  18. NtQuerySystemInformation NT
  19. NtQueryInformationProcess NT
  20. NtQueryInformationThread NT
  21. NtQueryObject NT
  22. RtlFreeHeap NT
  23. Kernel32:
  24. OpenThread NT5
  25. Thread32First Not on NT4
  26. Thread32Next Not on NT4
  27. Module32First Not on NT4
  28. Module32Next Not on NT4
  29. CreateToolhelp32Snapshot Not on NT4
  30. GetLongPathNameA/W Not on NT4/Win95.
  31. PSAPI:
  32. EnumProcessModules NT5
  33. GetModuleFileNameExW NT5
  34. --*/
  35. #include "pch.h"
  36. #ifndef _WIN32_WCE
  37. #include <delayimp.h>
  38. #endif
  39. #if !defined (_WIN64_)
  40. #include "mprivate.h"
  41. #endif
  42. #include "nt4.h"
  43. #include "impl.h"
  44. //
  45. // Exported from Win.h
  46. //
  47. BOOL
  48. WinInitialize(
  49. );
  50. VOID
  51. WinFree(
  52. );
  53. //
  54. // Global Variables
  55. //
  56. HINSTANCE _DbgHelp;
  57. HINSTANCE _PsApi;
  58. BOOL FreeWin;
  59. //
  60. // APIs from DBGHELP
  61. //
  62. MINI_DUMP_READ_DUMP_STREAM xxxReadDumpStream;
  63. MINI_DUMP_WRITE_DUMP xxxWriteDump;
  64. //
  65. // APIs from NTDLL
  66. //
  67. NT_OPEN_THREAD xxxNtOpenThread;
  68. NT_QUERY_SYSTEM_INFORMATION xxxNtQuerySystemInformation;
  69. NT_QUERY_INFORMATION_PROCESS xxxNtQueryInformationProcess;
  70. NT_QUERY_INFORMATION_THREAD xxxNtQueryInformationThread;
  71. NT_QUERY_OBJECT xxxNtQueryObject;
  72. RTL_FREE_HEAP xxxRtlFreeHeap;
  73. #if defined (_X86_)
  74. //
  75. // APIs from Kernel32
  76. //
  77. OPEN_THREAD xxxOpenThread;
  78. THREAD32_FIRST xxxThread32First;
  79. THREAD32_NEXT xxxThread32Next;
  80. MODULE32_FIRST xxxModule32First;
  81. MODULE32_NEXT xxxModule32Next;
  82. MODULE32_FIRST xxxModule32FirstW;
  83. MODULE32_NEXT xxxModule32NextW;
  84. CREATE_TOOLHELP32_SNAPSHOT xxxCreateToolhelp32Snapshot;
  85. GET_LONG_PATH_NAME_A xxxGetLongPathNameA;
  86. GET_LONG_PATH_NAME_W xxxGetLongPathNameW;
  87. #endif
  88. //
  89. // APIs from PSAPI
  90. //
  91. ENUM_PROCESS_MODULES xxxEnumProcessModules;
  92. GET_MODULE_FILE_NAME_EX_W xxxGetModuleFileNameExW;
  93. //
  94. // Function from dbghelp.dll
  95. //
  96. BOOL
  97. FailReadDumpStream(
  98. IN PVOID Base,
  99. ULONG StreamNumber,
  100. OUT PMINIDUMP_DIRECTORY * Dir, OPTIONAL
  101. OUT PVOID * Stream, OPTIONAL
  102. OUT ULONG * StreamSize OPTIONAL
  103. )
  104. {
  105. SetLastError (ERROR_NOT_SUPPORTED);
  106. return FALSE;
  107. }
  108. BOOL
  109. FailWriteDump(
  110. IN HANDLE hProcess,
  111. IN DWORD ProcessId,
  112. IN HANDLE hFile,
  113. IN MINIDUMP_TYPE DumpType,
  114. IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
  115. IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
  116. IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
  117. )
  118. {
  119. SetLastError (ERROR_NOT_SUPPORTED);
  120. return FALSE;
  121. }
  122. //
  123. // Functions imported from PSAPI.DLL.
  124. //
  125. BOOL
  126. WINAPI
  127. FailEnumProcessModules(
  128. HANDLE hProcess,
  129. HMODULE* lphModule,
  130. DWORD cb,
  131. LPDWORD lpcbNeeded
  132. )
  133. {
  134. SetLastError (ERROR_NOT_SUPPORTED);
  135. return FALSE;
  136. }
  137. DWORD
  138. WINAPI
  139. FailGetModuleFileNameExW(
  140. HANDLE hProcess,
  141. HMODULE hModule,
  142. PWSTR lpFilename,
  143. DWORD nSize
  144. )
  145. {
  146. SetLastError (ERROR_NOT_SUPPORTED);
  147. return 0;
  148. }
  149. //
  150. // Functions imported from NTDLL.DLL. NT Only.
  151. //
  152. NTSTATUS
  153. WINAPI
  154. FailNtOpenThread(
  155. PHANDLE ThreadHandle,
  156. ULONG Mask,
  157. PVOID Attributes,
  158. PVOID ClientId
  159. )
  160. {
  161. SetLastError (ERROR_NOT_SUPPORTED);
  162. return STATUS_UNSUCCESSFUL;
  163. }
  164. NTSTATUS
  165. WINAPI
  166. FailNtQuerySystemInformation(
  167. IN INT SystemInformationClass,
  168. OUT PVOID SystemInformation,
  169. IN ULONG SystemInformationLength,
  170. OUT PULONG ReturnLength OPTIONAL
  171. )
  172. {
  173. SetLastError (ERROR_NOT_SUPPORTED);
  174. return STATUS_UNSUCCESSFUL;
  175. }
  176. NTSTATUS
  177. WINAPI
  178. FailNtQueryInformationProcess(
  179. IN HANDLE ProcessHandle,
  180. IN INT ProcessInformationClass,
  181. OUT PVOID ProcessInformation,
  182. IN ULONG ProcessInformationLength,
  183. OUT PULONG ReturnLength OPTIONAL
  184. )
  185. {
  186. SetLastError (ERROR_NOT_SUPPORTED);
  187. return STATUS_UNSUCCESSFUL;
  188. }
  189. NTSTATUS
  190. WINAPI
  191. FailNtQueryInformationThread(
  192. IN HANDLE ThreadHandle,
  193. IN INT ThreadInformationClass,
  194. OUT PVOID ThreadInformation,
  195. IN ULONG ThreadInformationLength,
  196. OUT PULONG ReturnLength OPTIONAL
  197. )
  198. {
  199. SetLastError (ERROR_NOT_SUPPORTED);
  200. return STATUS_UNSUCCESSFUL;
  201. }
  202. NTSTATUS
  203. WINAPI
  204. FailNtQueryObject(
  205. IN HANDLE Handle,
  206. IN INT ObjectInformationClass,
  207. OUT PVOID ObjectInformation,
  208. IN ULONG Length,
  209. OUT PULONG ReturnLength OPTIONAL
  210. )
  211. {
  212. SetLastError (ERROR_NOT_SUPPORTED);
  213. return STATUS_UNSUCCESSFUL;
  214. }
  215. BOOLEAN
  216. NTAPI
  217. FailRtlFreeHeap(
  218. IN PVOID HeapHandle,
  219. IN ULONG Flags,
  220. IN PVOID BaseAddress
  221. )
  222. {
  223. return FALSE;
  224. }
  225. //
  226. // Functions imported from KERNEL32.DLL that may not be present.
  227. //
  228. HANDLE
  229. WINAPI
  230. FailOpenThread(
  231. DWORD dwDesiredAccess,
  232. BOOL bInheritHandle,
  233. DWORD dwThreadId
  234. )
  235. {
  236. SetLastError (ERROR_NOT_SUPPORTED);
  237. return NULL;
  238. }
  239. //
  240. // Toolhelp functions. Not present on NT4.
  241. //
  242. BOOL
  243. WINAPI
  244. FailThread32First(
  245. HANDLE hSnapshot,
  246. PVOID ThreadEntry
  247. )
  248. {
  249. SetLastError (ERROR_NOT_SUPPORTED);
  250. return FALSE;
  251. }
  252. BOOL
  253. WINAPI
  254. FailThread32Next(
  255. HANDLE hSnapshot,
  256. PVOID ThreadEntry
  257. )
  258. {
  259. SetLastError (ERROR_NOT_SUPPORTED);
  260. return FALSE;
  261. }
  262. BOOL
  263. WINAPI
  264. FailModule32First(
  265. HANDLE hSnapshot,
  266. PVOID Module
  267. )
  268. {
  269. SetLastError (ERROR_NOT_SUPPORTED);
  270. return FALSE;
  271. }
  272. BOOL
  273. WINAPI
  274. FailModule32Next(
  275. HANDLE hSnapshot,
  276. PVOID Module
  277. )
  278. {
  279. SetLastError (ERROR_NOT_SUPPORTED);
  280. return FALSE;
  281. }
  282. BOOL
  283. WINAPI
  284. FailModule32FirstW(
  285. HANDLE hSnapshot,
  286. PVOID Module
  287. )
  288. {
  289. SetLastError (ERROR_NOT_SUPPORTED);
  290. return FALSE;
  291. }
  292. BOOL
  293. WINAPI
  294. FailModule32NextW(
  295. HANDLE hSnapshot,
  296. PVOID Module
  297. )
  298. {
  299. SetLastError (ERROR_NOT_SUPPORTED);
  300. return FALSE;
  301. }
  302. HANDLE
  303. WINAPI
  304. FailCreateToolhelp32Snapshot(
  305. DWORD dwFlags,
  306. DWORD th32ProcessID
  307. )
  308. {
  309. SetLastError (ERROR_NOT_SUPPORTED);
  310. return FALSE;
  311. }
  312. DWORD
  313. WINAPI
  314. FailGetLongPathNameA(
  315. LPCSTR lpszShortPath,
  316. LPSTR lpszLongPath,
  317. DWORD cchBuffer
  318. )
  319. {
  320. SetLastError (ERROR_NOT_SUPPORTED);
  321. return 0;
  322. }
  323. DWORD
  324. WINAPI
  325. FailGetLongPathNameW(
  326. LPCWSTR lpszShortPath,
  327. LPWSTR lpszLongPath,
  328. DWORD cchBuffer
  329. )
  330. {
  331. SetLastError (ERROR_NOT_SUPPORTED);
  332. return 0;
  333. }
  334. //
  335. //
  336. // Setup an import
  337. //
  338. #define SETUP_IMPORT(_dll, _import, _type) { \
  339. if (_dll && xxx##_import == NULL ) { \
  340. xxx##_import = (_type) GetProcAddress (_dll, #_import); \
  341. } \
  342. if ( xxx##_import == NULL) { \
  343. xxx##_import = Fail##_import; \
  344. } \
  345. }
  346. VOID
  347. BindImports(
  348. )
  349. {
  350. HINSTANCE Ntdll;
  351. #if !defined (_DBGHELP_SOURCE_)
  352. //
  353. // Bind to dbghelp imports.
  354. //
  355. // We can only use the dbghelp imports if the dbghelp on
  356. // the system is of recent vintage and therefore has a good
  357. // chance of including all the latest minidump code. Currently
  358. // Windows.NET Server (5.01 >= build 3620) has the latest minidump
  359. // code so its dbghelp can be used. If minidump.lib has major
  360. // feature additions this check will need to be revised.
  361. //
  362. {
  363. ULONG Type;
  364. ULONG Major;
  365. ULONG Minor;
  366. ULONG Build;
  367. GenGetSystemType (&Type, &Major, &Minor, NULL, &Build);
  368. if (Type != WinNt || Major < 5 || Minor < 1 || Build < 3620) {
  369. xxxReadDumpStream = FailReadDumpStream;
  370. xxxWriteDump = FailWriteDump;
  371. } else {
  372. if (_DbgHelp == NULL) {
  373. _DbgHelp = LoadLibrary ( "DBGHELP.DLL" );
  374. }
  375. SETUP_IMPORT (_DbgHelp, ReadDumpStream, MINI_DUMP_READ_DUMP_STREAM);
  376. SETUP_IMPORT (_DbgHelp, WriteDump, MINI_DUMP_WRITE_DUMP);
  377. }
  378. }
  379. #endif
  380. //
  381. // Bind imports from NTDLL.DLL
  382. //
  383. Ntdll = GetModuleHandle ( "NTDLL.DLL" );
  384. SETUP_IMPORT (Ntdll, NtOpenThread, NT_OPEN_THREAD);
  385. SETUP_IMPORT (Ntdll, NtQuerySystemInformation, NT_QUERY_SYSTEM_INFORMATION);
  386. SETUP_IMPORT (Ntdll, NtQueryInformationProcess, NT_QUERY_INFORMATION_PROCESS);
  387. SETUP_IMPORT (Ntdll, NtQueryInformationThread, NT_QUERY_INFORMATION_THREAD);
  388. SETUP_IMPORT (Ntdll, NtQueryObject, NT_QUERY_OBJECT);
  389. SETUP_IMPORT (Ntdll, RtlFreeHeap, RTL_FREE_HEAP);
  390. #if defined (_X86_)
  391. //
  392. // Bind imports from KERNEL32.DLL
  393. //
  394. {
  395. HINSTANCE Kernel32;
  396. Kernel32 = GetModuleHandle ( "KERNEL32.DLL" );
  397. SETUP_IMPORT (Kernel32, OpenThread, OPEN_THREAD);
  398. SETUP_IMPORT (Kernel32, Thread32First, THREAD32_FIRST);
  399. SETUP_IMPORT (Kernel32, Thread32Next, THREAD32_NEXT);
  400. SETUP_IMPORT (Kernel32, Module32First, MODULE32_FIRST);
  401. SETUP_IMPORT (Kernel32, Module32Next, MODULE32_NEXT);
  402. SETUP_IMPORT (Kernel32, Module32FirstW, MODULE32_FIRST);
  403. SETUP_IMPORT (Kernel32, Module32NextW, MODULE32_NEXT);
  404. SETUP_IMPORT (Kernel32, CreateToolhelp32Snapshot, CREATE_TOOLHELP32_SNAPSHOT);
  405. SETUP_IMPORT (Kernel32, GetLongPathNameA, GET_LONG_PATH_NAME_A);
  406. SETUP_IMPORT (Kernel32, GetLongPathNameW, GET_LONG_PATH_NAME_W);
  407. }
  408. #endif
  409. if ( _PsApi == NULL ) {
  410. _PsApi = LoadLibrary ("PSAPI.DLL");
  411. }
  412. #if defined (_X86_)
  413. if (_PsApi == NULL) {
  414. ULONG Type;
  415. ULONG Major;
  416. //
  417. // NT5 and later versions of NT come with PSAPI. If its not present
  418. // on the system and this is an NT4 system, use internal versions
  419. // of this function.
  420. //
  421. GenGetSystemType (&Type, &Major, NULL, NULL, NULL);
  422. if ( Type == WinNt && Major == 4) {
  423. xxxEnumProcessModules = Nt4EnumProcessModules;
  424. xxxGetModuleFileNameExW = Nt4GetModuleFileNameExW;
  425. }
  426. }
  427. #endif
  428. //
  429. // This will only change the thunks values when they are non-NULL.
  430. //
  431. SETUP_IMPORT (_PsApi, EnumProcessModules, ENUM_PROCESS_MODULES);
  432. SETUP_IMPORT (_PsApi, GetModuleFileNameExW, GET_MODULE_FILE_NAME_EX_W);
  433. }
  434. #if defined (_X86_)
  435. //
  436. // Win9x doesn't export these functions.
  437. //
  438. wchar_t *
  439. __cdecl
  440. xxx_wcscpy(
  441. wchar_t * dst,
  442. const wchar_t * src
  443. )
  444. {
  445. wchar_t * cp = dst;
  446. while( *cp++ = *src++ )
  447. ; /* Copy src over dst */
  448. return( dst );
  449. }
  450. LPWSTR
  451. WINAPI
  452. xxx_lstrcpynW(
  453. OUT LPWSTR lpString1,
  454. IN LPCWSTR lpString2,
  455. IN int iMaxLength
  456. )
  457. {
  458. wchar_t * cp = lpString1;
  459. if (iMaxLength > 0)
  460. {
  461. while( iMaxLength > 1 && (*cp++ = *lpString2++) )
  462. iMaxLength--; /* Copy src over dst */
  463. if (cp > lpString1 && cp[-1]) {
  464. *cp = 0;
  465. }
  466. }
  467. return( lpString1 );
  468. }
  469. size_t
  470. __cdecl
  471. xxx_wcslen (
  472. const wchar_t * wcs
  473. )
  474. {
  475. const wchar_t *eos = wcs;
  476. while( *eos++ )
  477. ;
  478. return( (size_t)(eos - wcs - 1) );
  479. }
  480. #endif
  481. VOID
  482. FreeImports(
  483. )
  484. {
  485. xxxNtOpenThread = NULL;
  486. xxxNtQuerySystemInformation = NULL;
  487. xxxNtQueryInformationProcess = NULL;
  488. xxxNtQueryInformationThread = NULL;
  489. xxxNtQueryObject = NULL;
  490. xxxRtlFreeHeap = NULL;
  491. #if defined (_X86_)
  492. xxxOpenThread = NULL;
  493. xxxThread32First = NULL;
  494. xxxThread32Next = NULL;
  495. xxxModule32First = NULL;
  496. xxxModule32Next = NULL;
  497. xxxModule32FirstW = NULL;
  498. xxxModule32NextW = NULL;
  499. xxxCreateToolhelp32Snapshot = NULL;
  500. xxxGetLongPathNameA = NULL;
  501. xxxGetLongPathNameW = NULL;
  502. #endif
  503. xxxEnumProcessModules = NULL;
  504. xxxGetModuleFileNameExW = NULL;
  505. }
  506. BOOL
  507. MiniDumpSetup(
  508. )
  509. {
  510. DWORD Type;
  511. GenGetSystemType ( &Type, NULL, NULL, NULL, NULL );
  512. BindImports ();
  513. #if defined (_X86_)
  514. if ( xxxOpenThread == FailOpenThread &&
  515. Type == Win9x ) {
  516. FreeWin = WinInitialize ();
  517. if (!FreeWin) {
  518. return FALSE;
  519. }
  520. }
  521. #endif
  522. return TRUE;
  523. }
  524. VOID
  525. MiniDumpFree(
  526. )
  527. {
  528. if (_PsApi) {
  529. FreeLibrary ( _PsApi );
  530. _PsApi = NULL;
  531. }
  532. #if defined (_X86_)
  533. if ( FreeWin ) {
  534. WinFree ();
  535. FreeWin = FALSE;
  536. }
  537. #endif
  538. }