Leaked source code of windows server 2003
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.

864 lines
22 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include "psapi.h"
  6. //Need to change source to include $(BASE_INC_PATH)
  7. #include <..\..\public\internal\base\inc\wow64t.h>
  8. //Need to move in file psapi.h while publishing the EnumModulesEx api
  9. #define LIST_MODULES_32BIT 0x01 // list 32bit modules in the target process.
  10. #define LIST_MODULES_64BIT 0x02 // LIST_WOW64_NATIVE_MODULES list all the modules.
  11. #define LIST_MODULES_ALL 0x03 // list all the modules
  12. #define LIST_MODULES_NATIVE 0x0 // This is the default one app should call
  13. #ifdef _WIN64
  14. PLDR_DATA_TABLE_ENTRY
  15. Wow64FindNextModuleEntry (
  16. IN HANDLE hProcess,
  17. IN OUT PLDR_DATA_TABLE_ENTRY LdrEntry, //64bit structure info got from 32bit entry
  18. PLIST_ENTRY *pLdrHead
  19. )
  20. /*++
  21. Routine Description:
  22. This function will walk through the 32bit Loader list to retrieve wow64 module info for 32bit
  23. process on IA64. The function can be called repeatedly.
  24. Arguments:
  25. hProcess - Supplies the target process.
  26. LdrEntryData - Returns the requested table entry. Data must be initialized in 1st call
  27. and use the same in the sub sequent call.
  28. pLdrHead - pointer to a PLIST_ENTRY. This is used internally to track the list.
  29. That get initialized in the 1st uses.
  30. Return Value:
  31. NULL if no entry found,
  32. pointer to LdrEntry otherwise.
  33. --*/
  34. {
  35. LDR_DATA_TABLE_ENTRY32 LdrEntryData32;
  36. PLDR_DATA_TABLE_ENTRY32 LdrEntry32;
  37. LIST_ENTRY32 LdrNext32; //8byte in 32bit 16 byte on IA64
  38. PLIST_ENTRY32 pLdrNext32;
  39. //
  40. // if inititial entry is NULL must find the Teb32 and init the struct with 1st entry.
  41. //
  42. if ( LdrEntry == NULL)
  43. return NULL;
  44. if ( LdrEntry->InMemoryOrderLinks.Flink == NULL &&
  45. LdrEntry->InMemoryOrderLinks.Blink == NULL ) { // check if any other entry;
  46. //
  47. // List need to be initialized.
  48. //
  49. NTSTATUS st;
  50. PPEB32 Peb32;
  51. PEB32 Peb32_Data;
  52. PEB_LDR_DATA32 Peb32LdrData;
  53. st = NtQueryInformationProcess(hProcess,
  54. ProcessWow64Information,
  55. &Peb32,
  56. sizeof(Peb32),
  57. NULL);
  58. if (!NT_SUCCESS (st)) {
  59. return NULL;
  60. }
  61. {
  62. PPEB_LDR_DATA32 Ldr32;
  63. if (!ReadProcessMemory(hProcess, Peb32, &Peb32_Data, sizeof(Peb32_Data), NULL))
  64. return NULL;
  65. if (!ReadProcessMemory(hProcess, (PVOID)(ULONGLONG)Peb32_Data.Ldr, &Peb32LdrData, sizeof(Peb32LdrData), NULL))
  66. return NULL;
  67. *pLdrHead = (PVOID)((PBYTE)(ULONGLONG)Peb32_Data.Ldr + ((PBYTE)&Peb32LdrData.InMemoryOrderModuleList- (PBYTE)&Peb32LdrData ));
  68. //
  69. // LdrNext = Head->Flink;
  70. //
  71. pLdrNext32 = (PVOID)(ULONGLONG)Peb32LdrData.InMemoryOrderModuleList.Flink;
  72. if (!ReadProcessMemory(hProcess, pLdrNext32, &LdrNext32, sizeof(LdrNext32), NULL)) {
  73. return NULL;
  74. }
  75. }
  76. } else
  77. pLdrNext32 = (PVOID)LdrEntry->InMemoryOrderLinks.Flink;
  78. if (LdrEntry->InMemoryOrderLinks.Flink == *pLdrHead)
  79. return NULL;
  80. //
  81. // Read process memory to get a entry.
  82. //
  83. LdrEntry32 = CONTAINING_RECORD(
  84. pLdrNext32,
  85. LDR_DATA_TABLE_ENTRY32,
  86. InMemoryOrderLinks
  87. );
  88. //
  89. // Read 32bit entry
  90. //
  91. if (!ReadProcessMemory(hProcess, LdrEntry32, &LdrEntryData32, sizeof(LdrEntryData32), NULL))
  92. return NULL;
  93. //LdrEntryData->InMemoryOrderLinks.Flink; must be thunked
  94. LdrEntry->InLoadOrderLinks.Flink = (PVOID)(ULONGLONG)LdrEntryData32.InLoadOrderLinks.Flink;
  95. LdrEntry->InLoadOrderLinks.Blink = (PVOID)(ULONGLONG)LdrEntryData32.InLoadOrderLinks.Blink;
  96. LdrEntry->InMemoryOrderLinks.Flink = (PVOID)(ULONGLONG)LdrEntryData32.InMemoryOrderLinks.Flink;
  97. LdrEntry->InMemoryOrderLinks.Blink = (PVOID)(ULONGLONG)LdrEntryData32.InMemoryOrderLinks.Blink;
  98. LdrEntry->InInitializationOrderLinks.Flink = (PVOID)(ULONGLONG)LdrEntryData32.InInitializationOrderLinks.Flink;
  99. LdrEntry->InInitializationOrderLinks.Blink = (PVOID)(ULONGLONG)LdrEntryData32.InInitializationOrderLinks.Blink;
  100. LdrEntry->DllBase = (PVOID)(ULONGLONG)LdrEntryData32.DllBase;
  101. LdrEntry->EntryPoint = (PVOID)(ULONGLONG)LdrEntryData32.EntryPoint;
  102. //SizeOfImage;
  103. LdrEntry->SizeOfImage = LdrEntryData32.SizeOfImage;
  104. //Full Name
  105. LdrEntry->FullDllName.Length = LdrEntryData32.FullDllName.Length;
  106. LdrEntry->FullDllName.MaximumLength = LdrEntryData32.FullDllName.MaximumLength;
  107. LdrEntry->FullDllName.Buffer = (PVOID)(ULONGLONG)LdrEntryData32.FullDllName.Buffer;
  108. //Base Name
  109. LdrEntry->BaseDllName.Length = LdrEntryData32.BaseDllName.Length;
  110. LdrEntry->BaseDllName.MaximumLength = LdrEntryData32.BaseDllName.MaximumLength;
  111. LdrEntry->BaseDllName.Buffer = (PVOID)(ULONGLONG)LdrEntryData32.BaseDllName.Buffer;
  112. LdrEntry->Flags = LdrEntryData32.Flags;
  113. LdrEntry->LoadCount = LdrEntryData32.LoadCount;
  114. LdrEntry->TlsIndex = LdrEntryData32.TlsIndex;
  115. return LdrEntry;
  116. }
  117. BOOL
  118. Wow64FindModuleEx(
  119. IN HANDLE hProcess,
  120. IN HMODULE hModule,
  121. OUT PLDR_DATA_TABLE_ENTRY LdrEntryData
  122. )
  123. /*++
  124. Routine Description:
  125. This function retrieves the loader table entry for the specified
  126. module. The function copies the entry into the buffer pointed to
  127. by the LdrEntryData parameter.
  128. Arguments:
  129. hProcess - Supplies the target process.
  130. hModule - Identifies the module whose loader entry is being
  131. requested. A value of NULL references the module handle
  132. associated with the image file that was used to create the
  133. process.
  134. LdrEntryData - Returns the requested table entry.
  135. Return Value:
  136. TRUE if a matching entry was found.
  137. --*/
  138. {
  139. PLIST_ENTRY LdrHead;
  140. ULONG Count;
  141. Count = 0;
  142. try {
  143. LdrEntryData->InMemoryOrderLinks.Flink = LdrEntryData->InMemoryOrderLinks.Flink = NULL;
  144. while (Wow64FindNextModuleEntry (hProcess, LdrEntryData, &LdrHead)) {
  145. if (hModule == LdrEntryData->DllBase) {
  146. return TRUE;
  147. }
  148. Count++;
  149. if (Count > 10000) {
  150. SetLastError(ERROR_INVALID_HANDLE);
  151. return(FALSE);
  152. }
  153. } //while
  154. } except (EXCEPTION_EXECUTE_HANDLER) {
  155. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  156. return(FALSE);
  157. }
  158. SetLastError(ERROR_INVALID_HANDLE);
  159. return(FALSE);
  160. }
  161. BOOL
  162. WINAPI
  163. Wow64EnumProcessModules(
  164. HANDLE hProcess,
  165. HMODULE *lphModule,
  166. DWORD cb,
  167. LPDWORD lpcbNeeded
  168. )
  169. /*++
  170. Routine Description:
  171. This function all the module handles in a wow64 process.
  172. Arguments:
  173. hProcess - Supplies the target process.
  174. lphModule - point to a array of modules handle to be filled by this API.
  175. cb - bytes in the array.
  176. lpcNeeded - will how much memory is needed or filled by the call.
  177. Return Value:
  178. TRUE if a matching entry was found.
  179. --*/
  180. {
  181. DWORD ch =0;
  182. DWORD chMax = cb / sizeof(HMODULE);
  183. PLIST_ENTRY LdrHead;
  184. LDR_DATA_TABLE_ENTRY LdrEntry;
  185. LdrEntry.InMemoryOrderLinks.Flink = LdrEntry.InMemoryOrderLinks.Flink = NULL;
  186. try {
  187. while (Wow64FindNextModuleEntry ( hProcess, &LdrEntry, &LdrHead)) {
  188. if (ch < chMax) {
  189. try {
  190. lphModule[ch] = (HMODULE) LdrEntry.DllBase;
  191. } except (EXCEPTION_EXECUTE_HANDLER) {
  192. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  193. return(FALSE);
  194. }
  195. }
  196. ch++;
  197. if (ch > 10000) {
  198. SetLastError(ERROR_INVALID_HANDLE);
  199. return(FALSE);
  200. }
  201. } //while
  202. *lpcbNeeded = ch * sizeof(HMODULE);
  203. } except (EXCEPTION_EXECUTE_HANDLER) {
  204. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  205. return(FALSE);
  206. }
  207. return(TRUE);
  208. }
  209. #endif //_WIN64
  210. BOOL
  211. FindModule(
  212. IN HANDLE hProcess,
  213. IN HMODULE hModule,
  214. OUT PLDR_DATA_TABLE_ENTRY LdrEntryData
  215. )
  216. /*++
  217. Routine Description:
  218. This function retrieves the loader table entry for the specified
  219. module. The function copies the entry into the buffer pointed to
  220. by the LdrEntryData parameter.
  221. Arguments:
  222. hProcess - Supplies the target process.
  223. hModule - Identifies the module whose loader entry is being
  224. requested. A value of NULL references the module handle
  225. associated with the image file that was used to create the
  226. process.
  227. LdrEntryData - Returns the requested table entry.
  228. Return Value:
  229. TRUE if a matching entry was found.
  230. --*/
  231. {
  232. PROCESS_BASIC_INFORMATION BasicInfo;
  233. NTSTATUS Status;
  234. PPEB Peb;
  235. PPEB_LDR_DATA Ldr;
  236. PLIST_ENTRY LdrHead;
  237. PLIST_ENTRY LdrNext;
  238. ULONG Count;
  239. Status = NtQueryInformationProcess(
  240. hProcess,
  241. ProcessBasicInformation,
  242. &BasicInfo,
  243. sizeof(BasicInfo),
  244. NULL
  245. );
  246. if ( !NT_SUCCESS(Status) ) {
  247. SetLastError( RtlNtStatusToDosError( Status ) );
  248. return(FALSE);
  249. }
  250. Peb = BasicInfo.PebBaseAddress;
  251. if ( !ARGUMENT_PRESENT( hModule )) {
  252. if (!ReadProcessMemory(hProcess, &Peb->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) {
  253. return(FALSE);
  254. }
  255. }
  256. //
  257. // Ldr = Peb->Ldr
  258. //
  259. if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL)) {
  260. return (FALSE);
  261. }
  262. if (!Ldr) {
  263. // Ldr might be null (for instance, if the process hasn't started yet).
  264. SetLastError(ERROR_INVALID_HANDLE);
  265. return (FALSE);
  266. }
  267. LdrHead = &Ldr->InMemoryOrderModuleList;
  268. //
  269. // LdrNext = Head->Flink;
  270. //
  271. if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL)) {
  272. return(FALSE);
  273. }
  274. Count = 0;
  275. while (LdrNext != LdrHead) {
  276. PLDR_DATA_TABLE_ENTRY LdrEntry;
  277. LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
  278. if (!ReadProcessMemory(hProcess, LdrEntry, LdrEntryData, sizeof(*LdrEntryData), NULL)) {
  279. return(FALSE);
  280. }
  281. if ((HMODULE) LdrEntryData->DllBase == hModule) {
  282. return(TRUE);
  283. }
  284. LdrNext = LdrEntryData->InMemoryOrderLinks.Flink;
  285. Count++;
  286. if (Count > 10000) {
  287. SetLastError(ERROR_INVALID_HANDLE);
  288. return FALSE;
  289. }
  290. }
  291. #ifdef _WIN64
  292. return Wow64FindModuleEx( hProcess, hModule, LdrEntryData);
  293. #else
  294. SetLastError(ERROR_INVALID_HANDLE);
  295. return(FALSE);
  296. #endif
  297. }
  298. BOOL
  299. WINAPI
  300. EnumProcessModules(
  301. HANDLE hProcess,
  302. HMODULE *lphModule,
  303. DWORD cb,
  304. LPDWORD lpcbNeeded
  305. )
  306. {
  307. PROCESS_BASIC_INFORMATION BasicInfo;
  308. NTSTATUS Status;
  309. PPEB Peb;
  310. PPEB_LDR_DATA Ldr;
  311. PLIST_ENTRY LdrHead;
  312. PLIST_ENTRY LdrNext;
  313. DWORD chMax;
  314. DWORD ch;
  315. Status = NtQueryInformationProcess(
  316. hProcess,
  317. ProcessBasicInformation,
  318. &BasicInfo,
  319. sizeof(BasicInfo),
  320. NULL
  321. );
  322. if ( !NT_SUCCESS(Status) ) {
  323. SetLastError( RtlNtStatusToDosError( Status ) );
  324. return(FALSE);
  325. }
  326. Peb = BasicInfo.PebBaseAddress;
  327. //
  328. // The system process has no PEB. STATUS_PARTIAL_COPY is a poor choice
  329. // for a return value, but it's what's always been returned, so continue
  330. // to do so to maintain application compatibility.
  331. //
  332. if (Peb == NULL) {
  333. SetLastError( RtlNtStatusToDosError( STATUS_PARTIAL_COPY ) );
  334. return(FALSE);
  335. }
  336. //
  337. // Ldr = Peb->Ldr
  338. //
  339. if (!ReadProcessMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL)) {
  340. //
  341. // LastError is set by ReadProcessMemory
  342. //
  343. return(FALSE);
  344. }
  345. LdrHead = &Ldr->InMemoryOrderModuleList;
  346. //
  347. // LdrNext = Head->Flink;
  348. //
  349. if (!ReadProcessMemory(hProcess, &LdrHead->Flink, &LdrNext, sizeof(LdrNext), NULL)) {
  350. //
  351. // LastError is set by ReadProcessMemory
  352. //
  353. return(FALSE);
  354. }
  355. chMax = cb / sizeof(HMODULE);
  356. ch = 0;
  357. while (LdrNext != LdrHead) {
  358. PLDR_DATA_TABLE_ENTRY LdrEntry;
  359. LDR_DATA_TABLE_ENTRY LdrEntryData;
  360. LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
  361. if (!ReadProcessMemory(hProcess, LdrEntry, &LdrEntryData, sizeof(LdrEntryData), NULL)) {
  362. //
  363. // LastError is set by ReadProcessMemory
  364. //
  365. return(FALSE);
  366. }
  367. if (ch < chMax) {
  368. try {
  369. lphModule[ch] = (HMODULE) LdrEntryData.DllBase;
  370. } except (EXCEPTION_EXECUTE_HANDLER) {
  371. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  372. return(FALSE);
  373. }
  374. }
  375. ch++;
  376. if (ch > 10000) {
  377. SetLastError(ERROR_INVALID_HANDLE);
  378. return FALSE;
  379. }
  380. LdrNext = LdrEntryData.InMemoryOrderLinks.Flink;
  381. }
  382. try {
  383. *lpcbNeeded = ch * sizeof(HMODULE);
  384. } except (EXCEPTION_EXECUTE_HANDLER) {
  385. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  386. return(FALSE);
  387. }
  388. return TRUE;
  389. }
  390. BOOL
  391. WINAPI
  392. EnumProcessModulesEx(
  393. HANDLE hProcess,
  394. HMODULE *lphModule,
  395. DWORD cb,
  396. LPDWORD lpcbNeeded,
  397. DWORD Res,
  398. DWORD dwFlag
  399. )
  400. /*++
  401. Routine Description:
  402. This function all the module handles in a process with listing option like native
  403. modules only, wow64 32bit modules only or all.
  404. Arguments:
  405. hProcess - Supplies the target process.
  406. lphModule - point to a array of modules handle to be filled by this API.
  407. cb - bytes in the array.
  408. lpcNeeded - will how much memory is needed or filled by the call.
  409. Res - for future extension of this API. Set to 0.
  410. dwFlag - control the type of operation.
  411. LIST_MODULES_32BIT 0x01 // list 32bit modules in the target process.
  412. LIST_MODULES_64BIT 0x02 // LIST_WOW64_NATIVE_MODULES list all the modules.
  413. LIST_MODULES_ALL 0x03 // list all the modules
  414. LIST_MODULES_NATIVE 0x0 // This is the default one app should call
  415. Return Value:
  416. TRUE if the module array has been filled properly.
  417. FALSE - For incomplete buffer caller need to check required memory.
  418. <TBD> should 32bit app be allowed to use LIST_MODULES_64BIT?
  419. --*/
  420. {
  421. BOOL Ret= FALSE;
  422. DWORD dwNeeded1=0, dwNeeded=0;
  423. //
  424. // Enumerate the native call
  425. //
  426. if (dwFlag == LIST_MODULES_NATIVE || dwFlag == LIST_MODULES_ALL ) {
  427. Ret = EnumProcessModules(
  428. hProcess,
  429. lphModule,
  430. cb,
  431. &dwNeeded1
  432. );
  433. if (dwFlag == LIST_MODULES_NATIVE ) //native only enumeration
  434. return Ret;
  435. }
  436. #ifdef _WIN64
  437. if (dwNeeded1 > cb) {
  438. //
  439. // Next pass is just inventory.
  440. //
  441. cb =0;
  442. lphModule = NULL;
  443. } else {
  444. cb -= dwNeeded1;
  445. lphModule = &lphModule[dwNeeded1/sizeof (HMODULE)];
  446. }
  447. Ret = Ret && Wow64EnumProcessModules(
  448. hProcess,
  449. lphModule,
  450. cb,
  451. &dwNeeded
  452. );
  453. try {
  454. *lpcbNeeded = dwNeeded1 + dwNeeded;
  455. }
  456. except (EXCEPTION_EXECUTE_HANDLER) {
  457. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  458. return(FALSE);
  459. }
  460. #endif //_WIN64
  461. return Ret;
  462. }
  463. DWORD
  464. WINAPI
  465. GetModuleFileNameExW(
  466. HANDLE hProcess,
  467. HMODULE hModule,
  468. LPWSTR lpFilename,
  469. DWORD nSize
  470. )
  471. /*++
  472. Routine Description:
  473. This function retrieves the full pathname of the executable file
  474. from which the specified module was loaded. The function copies the
  475. null-terminated filename into the buffer pointed to by the
  476. lpFilename parameter.
  477. Routine Description:
  478. hModule - Identifies the module whose executable file name is being
  479. requested. A value of NULL references the module handle
  480. associated with the image file that was used to create the
  481. process.
  482. lpFilename - Points to the buffer that is to receive the filename.
  483. nSize - Specifies the maximum number of characters to copy. If the
  484. filename is longer than the maximum number of characters
  485. specified by the nSize parameter, it is truncated.
  486. Return Value:
  487. The return value specifies the actual length of the string copied to
  488. the buffer. A return value of zero indicates an error and extended
  489. error status is available using the GetLastError function.
  490. Arguments:
  491. --*/
  492. {
  493. LDR_DATA_TABLE_ENTRY LdrEntryData;
  494. DWORD cb;
  495. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  496. return(0);
  497. }
  498. nSize *= sizeof(WCHAR);
  499. cb = LdrEntryData.FullDllName.Length + sizeof (WCHAR);
  500. if ( nSize < cb ) {
  501. cb = nSize;
  502. }
  503. if (!ReadProcessMemory(hProcess, LdrEntryData.FullDllName.Buffer, lpFilename, cb, NULL)) {
  504. return(0);
  505. }
  506. if (cb == LdrEntryData.FullDllName.Length + sizeof (WCHAR)) {
  507. cb -= sizeof(WCHAR);
  508. }
  509. return(cb / sizeof(WCHAR));
  510. }
  511. DWORD
  512. WINAPI
  513. GetModuleFileNameExA(
  514. HANDLE hProcess,
  515. HMODULE hModule,
  516. LPSTR lpFilename,
  517. DWORD nSize
  518. )
  519. {
  520. LPWSTR lpwstr;
  521. DWORD cwch;
  522. DWORD cch;
  523. lpwstr = (LPWSTR) LocalAlloc(LMEM_FIXED, nSize * 2);
  524. if (lpwstr == NULL) {
  525. return(0);
  526. }
  527. cwch = cch = GetModuleFileNameExW(hProcess, hModule, lpwstr, nSize);
  528. if (cwch < nSize) {
  529. //
  530. // Include NULL terminator
  531. //
  532. cwch++;
  533. }
  534. if (!WideCharToMultiByte(CP_ACP, 0, lpwstr, cwch, lpFilename, nSize, NULL, NULL)) {
  535. cch = 0;
  536. }
  537. LocalFree((HLOCAL) lpwstr);
  538. return(cch);
  539. }
  540. DWORD
  541. WINAPI
  542. GetModuleBaseNameW(
  543. HANDLE hProcess,
  544. HMODULE hModule,
  545. LPWSTR lpFilename,
  546. DWORD nSize
  547. )
  548. /*++
  549. Routine Description:
  550. This function retrieves the full pathname of the executable file
  551. from which the specified module was loaded. The function copies the
  552. null-terminated filename into the buffer pointed to by the
  553. lpFilename parameter.
  554. Routine Description:
  555. hModule - Identifies the module whose executable file name is being
  556. requested. A value of NULL references the module handle
  557. associated with the image file that was used to create the
  558. process.
  559. lpFilename - Points to the buffer that is to receive the filename.
  560. nSize - Specifies the maximum number of characters to copy. If the
  561. filename is longer than the maximum number of characters
  562. specified by the nSize parameter, it is truncated.
  563. Return Value:
  564. The return value specifies the actual length of the string copied to
  565. the buffer. A return value of zero indicates an error and extended
  566. error status is available using the GetLastError function.
  567. Arguments:
  568. --*/
  569. {
  570. LDR_DATA_TABLE_ENTRY LdrEntryData;
  571. DWORD cb;
  572. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  573. return(0);
  574. }
  575. nSize *= sizeof(WCHAR);
  576. cb = LdrEntryData.BaseDllName.Length + sizeof (WCHAR);
  577. if ( nSize < cb ) {
  578. cb = nSize;
  579. }
  580. if (!ReadProcessMemory(hProcess, LdrEntryData.BaseDllName.Buffer, lpFilename, cb, NULL)) {
  581. return(0);
  582. }
  583. if (cb == LdrEntryData.BaseDllName.Length + sizeof (WCHAR)) {
  584. cb -= sizeof(WCHAR);
  585. }
  586. return(cb / sizeof(WCHAR));
  587. }
  588. DWORD
  589. WINAPI
  590. GetModuleBaseNameA(
  591. HANDLE hProcess,
  592. HMODULE hModule,
  593. LPSTR lpFilename,
  594. DWORD nSize
  595. )
  596. {
  597. LPWSTR lpwstr;
  598. DWORD cwch;
  599. DWORD cch;
  600. lpwstr = (LPWSTR) LocalAlloc(LMEM_FIXED, nSize * 2);
  601. if (lpwstr == NULL) {
  602. return(0);
  603. }
  604. cwch = cch = GetModuleBaseNameW(hProcess, hModule, lpwstr, nSize);
  605. if (cwch < nSize) {
  606. //
  607. // Include NULL terminator
  608. //
  609. cwch++;
  610. }
  611. if (!WideCharToMultiByte(CP_ACP, 0, lpwstr, cwch, lpFilename, nSize, NULL, NULL)) {
  612. cch = 0;
  613. }
  614. LocalFree((HLOCAL) lpwstr);
  615. return(cch);
  616. }
  617. BOOL
  618. WINAPI
  619. GetModuleInformation(
  620. HANDLE hProcess,
  621. HMODULE hModule,
  622. LPMODULEINFO lpmodinfo,
  623. DWORD cb
  624. )
  625. {
  626. LDR_DATA_TABLE_ENTRY LdrEntryData;
  627. MODULEINFO modinfo;
  628. if (cb < sizeof(MODULEINFO)) {
  629. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  630. return(FALSE);
  631. }
  632. if (!FindModule(hProcess, hModule, &LdrEntryData)) {
  633. return(0);
  634. }
  635. modinfo.lpBaseOfDll = (PVOID) hModule;
  636. modinfo.SizeOfImage = LdrEntryData.SizeOfImage;
  637. modinfo.EntryPoint = LdrEntryData.EntryPoint;
  638. try {
  639. *lpmodinfo = modinfo;
  640. } except (EXCEPTION_EXECUTE_HANDLER) {
  641. SetLastError( RtlNtStatusToDosError( GetExceptionCode() ) );
  642. return(FALSE);
  643. }
  644. return(TRUE);
  645. }