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.

458 lines
9.8 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include "psapi.h"
  6. BOOL
  7. FindModule(
  8. IN HANDLE hProcess,
  9. IN HMODULE hModule,
  10. OUT PLDR_DATA_TABLE_ENTRY LdrEntryData
  11. )
  12. /*++
  13. Routine Description:
  14. This function retrieves the loader table entry for the specified
  15. module. The function copies the entry into the buffer pointed to
  16. by the LdrEntryData parameter.
  17. Arguments:
  18. hProcess - Supplies the target process.
  19. hModule - Identifies the module whose loader entry is being
  20. requested. A value of NULL references the module handle
  21. associated with the image file that was used to create the
  22. process.
  23. LdrEntryData - Returns the requested table entry.
  24. Return Value:
  25. TRUE if a matching entry was found.
  26. --*/
  27. {
  28. PROCESS_BASIC_INFORMATION BasicInfo;
  29. NTSTATUS Status;
  30. PPEB Peb;
  31. PPEB_LDR_DATA Ldr;
  32. PLIST_ENTRY LdrHead;
  33. PLIST_ENTRY LdrNext;
  34. Status = NtQueryInformationProcess(
  35. hProcess,
  36. ProcessBasicInformation,
  37. &BasicInfo,
  38. sizeof(BasicInfo),
  39. NULL
  40. );
  41. if ( !NT_SUCCESS(Status) ) {
  42. SetLastError( RtlNtStatusToDosError( Status ) );
  43. return(FALSE);
  44. }
  45. Peb = BasicInfo.PebBaseAddress;
  46. if ( !ARGUMENT_PRESENT( hModule )) {
  47. if (!ReadProcessMemory(hProcess, &Peb->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) {
  48. return(FALSE);
  49. }
  50. }
  51. //
  52. // Ldr = Peb->Ldr
  53. //
  54. if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL)) {
  55. return (FALSE);
  56. }
  57. if (!Ldr) {
  58. // Ldr might be null (for instance, if the process hasn't started yet).
  59. SetLastError(ERROR_INVALID_HANDLE);
  60. return (FALSE);
  61. }
  62. LdrHead = &Ldr->InMemoryOrderModuleList;
  63. //
  64. // LdrNext = Head->Flink;
  65. //
  66. if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL)) {
  67. return(FALSE);
  68. }
  69. while (LdrNext != LdrHead) {
  70. PLDR_DATA_TABLE_ENTRY LdrEntry;
  71. LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
  72. if (!ReadProcessMemory(hProcess, LdrEntry, LdrEntryData, sizeof(*LdrEntryData), NULL)) {
  73. return(FALSE);
  74. }
  75. if ((HMODULE) LdrEntryData->DllBase == hModule) {
  76. return(TRUE);
  77. }
  78. LdrNext = LdrEntryData->InMemoryOrderLinks.Flink;
  79. }
  80. SetLastError(ERROR_INVALID_HANDLE);
  81. return(FALSE);
  82. }
  83. BOOL
  84. WINAPI
  85. EnumProcessModules(
  86. HANDLE hProcess,
  87. HMODULE *lphModule,
  88. DWORD cb,
  89. LPDWORD lpcbNeeded
  90. )
  91. {
  92. PROCESS_BASIC_INFORMATION BasicInfo;
  93. NTSTATUS Status;
  94. PPEB Peb;
  95. PPEB_LDR_DATA Ldr;
  96. PLIST_ENTRY LdrHead;
  97. PLIST_ENTRY LdrNext;
  98. DWORD chMax;
  99. DWORD ch;
  100. Status = NtQueryInformationProcess(
  101. hProcess,
  102. ProcessBasicInformation,
  103. &BasicInfo,
  104. sizeof(BasicInfo),
  105. NULL
  106. );
  107. if ( !NT_SUCCESS(Status) ) {
  108. SetLastError( RtlNtStatusToDosError( Status ) );
  109. return(FALSE);
  110. }
  111. Peb = BasicInfo.PebBaseAddress;
  112. //
  113. // Ldr = Peb->Ldr
  114. //
  115. if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL)) {
  116. return(FALSE);
  117. }
  118. LdrHead = &Ldr->InMemoryOrderModuleList;
  119. //
  120. // LdrNext = Head->Flink;
  121. //
  122. if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL)) {
  123. return(FALSE);
  124. }
  125. chMax = cb / sizeof(HMODULE);
  126. ch = 0;
  127. while (LdrNext != LdrHead) {
  128. PLDR_DATA_TABLE_ENTRY LdrEntry;
  129. LDR_DATA_TABLE_ENTRY LdrEntryData;
  130. LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
  131. if (!ReadProcessMemory(hProcess, LdrEntry, &LdrEntryData, sizeof(LdrEntryData), NULL)) {
  132. return(FALSE);
  133. }
  134. if (ch < chMax) {
  135. try {
  136. lphModule[ch] = (HMODULE) LdrEntryData.DllBase;
  137. }
  138. except (EXCEPTION_EXECUTE_HANDLER) {
  139. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  140. return(FALSE);
  141. }
  142. }
  143. ch++;
  144. LdrNext = LdrEntryData.InMemoryOrderLinks.Flink;
  145. }
  146. try {
  147. *lpcbNeeded = ch * sizeof(HMODULE);
  148. }
  149. except (EXCEPTION_EXECUTE_HANDLER) {
  150. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  151. return(FALSE);
  152. }
  153. return(TRUE);
  154. }
  155. DWORD
  156. WINAPI
  157. GetModuleFileNameExW(
  158. HANDLE hProcess,
  159. HMODULE hModule,
  160. LPWSTR lpFilename,
  161. DWORD nSize
  162. )
  163. /*++
  164. Routine Description:
  165. This function retrieves the full pathname of the executable file
  166. from which the specified module was loaded. The function copies the
  167. null-terminated filename into the buffer pointed to by the
  168. lpFilename parameter.
  169. Routine Description:
  170. hModule - Identifies the module whose executable file name is being
  171. requested. A value of NULL references the module handle
  172. associated with the image file that was used to create the
  173. process.
  174. lpFilename - Points to the buffer that is to receive the filename.
  175. nSize - Specifies the maximum number of characters to copy. If the
  176. filename is longer than the maximum number of characters
  177. specified by the nSize parameter, it is truncated.
  178. Return Value:
  179. The return value specifies the actual length of the string copied to
  180. the buffer. A return value of zero indicates an error and extended
  181. error status is available using the GetLastError function.
  182. Arguments:
  183. --*/
  184. {
  185. LDR_DATA_TABLE_ENTRY LdrEntryData;
  186. DWORD cb;
  187. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  188. return(0);
  189. }
  190. nSize *= sizeof(WCHAR);
  191. cb = LdrEntryData.FullDllName.Length + sizeof (WCHAR);
  192. if ( nSize < cb ) {
  193. cb = nSize;
  194. }
  195. if (!ReadProcessMemory(hProcess, LdrEntryData.FullDllName.Buffer, lpFilename, cb, NULL)) {
  196. return(0);
  197. }
  198. if (cb == LdrEntryData.FullDllName.Length + sizeof (WCHAR)) {
  199. cb -= sizeof(WCHAR);
  200. }
  201. return(cb / sizeof(WCHAR));
  202. }
  203. DWORD
  204. WINAPI
  205. GetModuleFileNameExA(
  206. HANDLE hProcess,
  207. HMODULE hModule,
  208. LPSTR lpFilename,
  209. DWORD nSize
  210. )
  211. {
  212. LPWSTR lpwstr;
  213. DWORD cwch;
  214. DWORD cch;
  215. lpwstr = (LPWSTR) LocalAlloc(LMEM_FIXED, nSize * 2);
  216. if (lpwstr == NULL) {
  217. return(0);
  218. }
  219. cwch = cch = GetModuleFileNameExW(hProcess, hModule, lpwstr, nSize);
  220. if (cwch < nSize) {
  221. //
  222. // Include NULL terminator
  223. //
  224. cwch++;
  225. }
  226. if (!WideCharToMultiByte(CP_ACP, 0, lpwstr, cwch, lpFilename, nSize, NULL, NULL)) {
  227. cch = 0;
  228. }
  229. LocalFree((HLOCAL) lpwstr);
  230. return(cch);
  231. }
  232. DWORD
  233. WINAPI
  234. GetModuleBaseNameW(
  235. HANDLE hProcess,
  236. HMODULE hModule,
  237. LPWSTR lpFilename,
  238. DWORD nSize
  239. )
  240. /*++
  241. Routine Description:
  242. This function retrieves the full pathname of the executable file
  243. from which the specified module was loaded. The function copies the
  244. null-terminated filename into the buffer pointed to by the
  245. lpFilename parameter.
  246. Routine Description:
  247. hModule - Identifies the module whose executable file name is being
  248. requested. A value of NULL references the module handle
  249. associated with the image file that was used to create the
  250. process.
  251. lpFilename - Points to the buffer that is to receive the filename.
  252. nSize - Specifies the maximum number of characters to copy. If the
  253. filename is longer than the maximum number of characters
  254. specified by the nSize parameter, it is truncated.
  255. Return Value:
  256. The return value specifies the actual length of the string copied to
  257. the buffer. A return value of zero indicates an error and extended
  258. error status is available using the GetLastError function.
  259. Arguments:
  260. --*/
  261. {
  262. LDR_DATA_TABLE_ENTRY LdrEntryData;
  263. DWORD cb;
  264. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  265. return(0);
  266. }
  267. nSize *= sizeof(WCHAR);
  268. cb = LdrEntryData.BaseDllName.Length + sizeof (WCHAR);
  269. if ( nSize < cb ) {
  270. cb = nSize;
  271. }
  272. if (!ReadProcessMemory(hProcess, LdrEntryData.BaseDllName.Buffer, lpFilename, cb, NULL)) {
  273. return(0);
  274. }
  275. if (cb == LdrEntryData.BaseDllName.Length + sizeof (WCHAR)) {
  276. cb -= sizeof(WCHAR);
  277. }
  278. return(cb / sizeof(WCHAR));
  279. }
  280. DWORD
  281. WINAPI
  282. GetModuleBaseNameA(
  283. HANDLE hProcess,
  284. HMODULE hModule,
  285. LPSTR lpFilename,
  286. DWORD nSize
  287. )
  288. {
  289. LPWSTR lpwstr;
  290. DWORD cwch;
  291. DWORD cch;
  292. lpwstr = (LPWSTR) LocalAlloc(LMEM_FIXED, nSize * 2);
  293. if (lpwstr == NULL) {
  294. return(0);
  295. }
  296. cwch = cch = GetModuleBaseNameW(hProcess, hModule, lpwstr, nSize);
  297. if (cwch < nSize) {
  298. //
  299. // Include NULL terminator
  300. //
  301. cwch++;
  302. }
  303. if (!WideCharToMultiByte(CP_ACP, 0, lpwstr, cwch, lpFilename, nSize, NULL, NULL)) {
  304. cch = 0;
  305. }
  306. LocalFree((HLOCAL) lpwstr);
  307. return(cch);
  308. }
  309. BOOL
  310. WINAPI
  311. GetModuleInformation(
  312. HANDLE hProcess,
  313. HMODULE hModule,
  314. LPMODULEINFO lpmodinfo,
  315. DWORD cb
  316. )
  317. {
  318. LDR_DATA_TABLE_ENTRY LdrEntryData;
  319. MODULEINFO modinfo;
  320. if (cb < sizeof(MODULEINFO)) {
  321. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  322. return(FALSE);
  323. }
  324. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  325. return(0);
  326. }
  327. modinfo.lpBaseOfDll = (PVOID) hModule;
  328. modinfo.SizeOfImage = LdrEntryData.SizeOfImage;
  329. modinfo.EntryPoint = LdrEntryData.EntryPoint;
  330. try {
  331. *lpmodinfo = modinfo;
  332. }
  333. except (EXCEPTION_EXECUTE_HANDLER) {
  334. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  335. return(FALSE);
  336. }
  337. return(TRUE);
  338. }