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.

4104 lines
120 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. module.c
  5. Abstract:
  6. This module contains the Win32 Module Management APIs
  7. Author:
  8. Steve Wood (stevewo) 24-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #pragma hdrstop
  13. #include <winsafer.h>
  14. #include <winuserp.h>
  15. #include <sxstypes.h>
  16. PVOID
  17. BasepMapModuleHandle(
  18. IN HMODULE hModule OPTIONAL,
  19. IN BOOLEAN bResourcesOnly
  20. )
  21. {
  22. if (ARGUMENT_PRESENT( hModule )) {
  23. if (LDR_IS_DATAFILE(hModule)) {
  24. if (bResourcesOnly) {
  25. return( (PVOID)hModule );
  26. } else {
  27. return( NULL );
  28. }
  29. } else {
  30. return( (PVOID)hModule );
  31. }
  32. } else {
  33. return( (PVOID)NtCurrentPeb()->ImageBaseAddress);
  34. }
  35. }
  36. NTSTATUS
  37. BasepLoadLibraryAsDataFile(
  38. IN PWSTR DllPath OPTIONAL,
  39. IN PUNICODE_STRING DllName,
  40. OUT PVOID *DllHandle
  41. )
  42. {
  43. WCHAR FullPath[ MAX_PATH ];
  44. PWSTR FilePart;
  45. HANDLE FileHandle;
  46. HANDLE MappingHandle;
  47. UNICODE_STRING FullPathPreAllocatedString;
  48. UNICODE_STRING FullPathDynamicString = {0};
  49. UNICODE_STRING DefaultExtensionString = RTL_CONSTANT_STRING(L".DLL");
  50. PUNICODE_STRING FullPathString = NULL;
  51. LPVOID DllBase = NULL;
  52. SIZE_T DllSize = 0;
  53. PIMAGE_NT_HEADERS NtHeaders;
  54. PTEB Teb;
  55. NTSTATUS Status;
  56. ACTIVATION_CONTEXT_SECTION_KEYED_DATA askd;
  57. Teb = NtCurrentTeb();
  58. *DllHandle = NULL;
  59. FullPathPreAllocatedString.MaximumLength = sizeof(FullPath);
  60. FullPathPreAllocatedString.Length = 0;
  61. FullPathPreAllocatedString.Buffer = FullPath;
  62. Status = RtlDosApplyFileIsolationRedirection_Ustr(
  63. RTL_DOS_APPLY_FILE_REDIRECTION_USTR_FLAG_RESPECT_DOT_LOCAL,
  64. DllName,
  65. &DefaultExtensionString,
  66. &FullPathPreAllocatedString,
  67. &FullPathDynamicString,
  68. &FullPathString,
  69. NULL,
  70. NULL,
  71. NULL);
  72. if (NT_ERROR(Status)) {
  73. if (Status != STATUS_SXS_KEY_NOT_FOUND)
  74. goto Exit;
  75. if (!SearchPathW( DllPath,
  76. DllName->Buffer,
  77. DefaultExtensionString.Buffer,
  78. sizeof(FullPath) / sizeof(FullPath[0]),
  79. FullPath,
  80. &FilePart
  81. )
  82. ) {
  83. Status = Teb->LastStatusValue;
  84. goto Exit;
  85. }
  86. FullPathString = &FullPathPreAllocatedString;
  87. }
  88. FileHandle = CreateFileW( FullPathString->Buffer,
  89. GENERIC_READ,
  90. FILE_SHARE_READ | FILE_SHARE_DELETE,
  91. NULL,
  92. OPEN_EXISTING,
  93. 0,
  94. NULL
  95. );
  96. if (FileHandle == INVALID_HANDLE_VALUE) {
  97. Status = Teb->LastStatusValue;
  98. goto Exit;
  99. }
  100. MappingHandle = CreateFileMappingW( FileHandle,
  101. NULL,
  102. PAGE_READONLY,
  103. 0,
  104. 0,
  105. NULL
  106. );
  107. CloseHandle( FileHandle );
  108. if (MappingHandle == NULL) {
  109. Status = Teb->LastStatusValue;
  110. goto Exit;
  111. }
  112. Status = NtMapViewOfSection (
  113. MappingHandle,
  114. NtCurrentProcess(),
  115. &DllBase,
  116. 0,
  117. 0,
  118. NULL,
  119. &DllSize,
  120. ViewShare,
  121. 0,
  122. PAGE_READONLY
  123. );
  124. CloseHandle( MappingHandle );
  125. if (!NT_SUCCESS(Status)) {
  126. goto Exit;
  127. }
  128. Status = RtlImageNtHeaderEx(0, DllBase, DllSize, &NtHeaders);
  129. if (!NT_SUCCESS(Status)) {
  130. goto Exit;
  131. }
  132. *DllHandle = LDR_VIEW_TO_DATAFILE(DllBase);
  133. LdrLoadAlternateResourceModule(*DllHandle, FullPathString->Buffer);
  134. Status = STATUS_SUCCESS;
  135. Exit:
  136. if (!NT_SUCCESS(Status) && DllBase != NULL) {
  137. UnmapViewOfFile( DllBase );
  138. }
  139. if (FullPathDynamicString.Buffer != NULL)
  140. RtlFreeUnicodeString(&FullPathDynamicString);
  141. return Status;
  142. }
  143. typedef struct _BASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT {
  144. IN PVOID Address;
  145. OUT LPWSTR *Dir;
  146. OUT NTSTATUS Status;
  147. } BASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT,
  148. *PBASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT;
  149. VOID
  150. BasepGetDllDirFromAddress(
  151. IN PCLDR_DATA_TABLE_ENTRY Entry,
  152. IN PVOID ContextIn,
  153. IN OUT BOOLEAN *StopEnumeration
  154. )
  155. /*++
  156. Routine Description:
  157. This function is a LDR_LOADED_MODULE_ENUMBERATION_CALLBACK_FUNCTION
  158. which locates a given dll by address.
  159. Arguments:
  160. Entry - the entry currently being enumerated.
  161. ContextIn - a pointer to a BASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT
  162. StopEnumeration - used to stop the enumeration.
  163. Return Value:
  164. None. The directory name of the indicated module is returned via
  165. the context, as is the status of the operation.
  166. --*/
  167. {
  168. PBASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT Context =
  169. (PBASEP_GET_DLL_DIR_FROM_ADDRESS_CONTEXT) ContextIn;
  170. SIZE_T NameLengthInChars;
  171. PCWSTR DllDirEnd;
  172. ASSERT(Entry);
  173. ASSERT(Context);
  174. ASSERT(StopEnumeration);
  175. if (Entry->DllBase <= Context->Address
  176. && ((PCHAR)Context->Address
  177. < ((PCHAR)Entry->DllBase + Entry->SizeOfImage))) {
  178. // One way or another, we're done...
  179. *StopEnumeration = TRUE;
  180. if (BasepExeLdrEntry && Entry == BasepExeLdrEntry) {
  181. // There's no point in adding the exe's directory to the
  182. // path.
  183. return;
  184. }
  185. DllDirEnd = BasepEndOfDirName(Entry->FullDllName.Buffer);
  186. ASSERT(DllDirEnd);
  187. if (! DllDirEnd) {
  188. // In case we couldn't find the end on some production
  189. // machine, we'll just return.
  190. return;
  191. }
  192. NameLengthInChars = DllDirEnd - Entry->FullDllName.Buffer;
  193. ASSERT(0 < NameLengthInChars);
  194. if (NameLengthInChars == 0) {
  195. // Again, just in case we weren't able to compute this,
  196. // we'll just return.
  197. return;
  198. }
  199. *Context->Dir = RtlAllocateHeap(RtlProcessHeap(),
  200. MAKE_TAG(TMP_TAG),
  201. (NameLengthInChars + 1) << 1);
  202. if (! *Context->Dir) {
  203. Context->Status = STATUS_NO_MEMORY;
  204. return;
  205. }
  206. RtlCopyMemory(*Context->Dir,
  207. Entry->FullDllName.Buffer,
  208. NameLengthInChars << 1);
  209. (*Context->Dir)[NameLengthInChars] = UNICODE_NULL;
  210. }
  211. }
  212. HMODULE
  213. LoadLibraryExW(
  214. LPCWSTR lpwLibFileName,
  215. HANDLE hFile,
  216. DWORD dwFlags
  217. )
  218. /*++
  219. Routine Description:
  220. This function loads the library module contained in the specified
  221. file and retrieves a handle to the loaded module.
  222. It is important to note that module handles are NOT global, in that
  223. a LoadLibrary call by one application does not produce a handle that
  224. another application can use, say in calling GetProcAddress. The
  225. other application would need to do its own call to LoadLibrary for
  226. the module before calling GetProcAddress. Module handles will have
  227. the same 32-bit value across all processes, but a module handle is
  228. only valid in the context of a process after the module has been
  229. loaded into that process, either as a result of an explicit call to
  230. LoadLibrary or as a result of an implicit call caused by a loadtime
  231. dynamic link to an entry point in the module.
  232. The library file name does not need to specify an extension. If one
  233. is not specified, then the default library file extension, .DLL, is
  234. used (note that this is different than Win16. Under Win16 specifying
  235. no extension would not cause ".DLL" to be appended to the name. To get
  236. Win16 behavior, if the module name has no extension, the caller must
  237. supply a trailing ".").
  238. The library file name does not need to specify a directory path. If
  239. one is specified, then the specified file must exist. If a path is
  240. not specified, this function will look for the library file in using
  241. the Windows search path:
  242. - The current process image file directory
  243. - The current directory
  244. - The Windows system directory
  245. - The Windows directory
  246. - The directories listed in the PATH environment variable
  247. The first directory searched is the directory that contains the
  248. image file that was used to create the current process (see
  249. CreateProcess). This allows private dynamic link library files
  250. associated with an application to be found without having to add the
  251. application's installed directory to the PATH environment variable.
  252. The image file loader optimizes the search by remembering for each
  253. loaded library module that unqualified module name that was searched
  254. for when a module was loaded into the current process the first
  255. time. This unqualified name has nothing to do with the module name
  256. that is stored within the library module itself, as specified by the
  257. NAME keyword in the .DEF file. This is a change from the Windows
  258. 3.1 behavior, where the search was optimized by comparing to the
  259. name within the library module itself, which could lead to confusing
  260. result if the internal name differed from the external file name.
  261. Once a fully qualified path name to a library module file is
  262. obtained, a search is made to see if that library module file has
  263. been loaded into the current process. The search is case
  264. insensitive and includes the full path name of each library module
  265. file. If a match is found for the library module file, then it has
  266. already been loaded into the current process, so this function just
  267. increments the reference count for the module and returns the module
  268. handle for that library.
  269. Otherwise, this is the first time the specified module has been
  270. loaded for the current process, so the library module's DLL Instance
  271. Initialization entry point will be called. See the Task Management
  272. section for a description of the DLL Instance Initialization entry
  273. point.
  274. Fine Point: If DLL re-direction is enabled for the app./process requesting
  275. this load, if we find a DLL in the app. folder (with same base name),
  276. we load that file (ignoring any path qualifications passed in).
  277. Arguments:
  278. lpwLibFileName - Points to a string that names the library file. The
  279. string must be a null-terminated unicode string.
  280. hFile - optional file handle, that if specified, while be used to
  281. create the mapping object for the module.
  282. dwFlags - flags that specify optional behavior. Valid flags are:
  283. DONT_RESOLVE_DLL_REFERENCES - loads the library but does not
  284. attempt to resolve any of its DLL references nor does it
  285. attempt to call its initialization procedure.
  286. LOAD_LIBRARY_AS_DATAFILE - If this value is used, the system
  287. maps the file into the calling process's virtual address
  288. space as if it were a data file.
  289. LOAD_WITH_ALTERED_SEARCH_PATH - If this value is used, and
  290. lpFileName specifies a path, the system uses the alternate
  291. file search strategy
  292. LOAD_IGNORE_CODE_AUTHZ_LEVEL - Indicates that WinSafer sandbox
  293. restrictions should be ignored when loading the library
  294. and that load should be allowed to continue, even if the
  295. library is less trustworthy than the process loading it.
  296. Return Value:
  297. The return value identifies the loaded module if the function is
  298. successful. A return value of NULL indicates an error and extended
  299. error status is available using the GetLastError function.
  300. --*/
  301. {
  302. LPWSTR TrimmedDllName = NULL;
  303. LPWSTR AllocatedPath = NULL;
  304. LPWSTR InitiatorDllDirBuffer = NULL;
  305. LPCWSTR InitiatorDllDir;
  306. NTSTATUS Status = STATUS_SUCCESS;
  307. HMODULE hModule = NULL;
  308. UNICODE_STRING DllName_U;
  309. UNICODE_STRING AllocatedPath_U;
  310. ULONG DllCharacteristics;
  311. const DWORD ValidFlags = (DONT_RESOLVE_DLL_REFERENCES
  312. | LOAD_LIBRARY_AS_DATAFILE
  313. | LOAD_WITH_ALTERED_SEARCH_PATH
  314. | LOAD_IGNORE_CODE_AUTHZ_LEVEL);
  315. // Parameter validation
  316. if (! (lpwLibFileName // Make sure we have a dll
  317. && !(dwFlags & ~ValidFlags) // Ensure flag validity
  318. && !hFile // and no hFile for now
  319. )) {
  320. Status = STATUS_INVALID_PARAMETER;
  321. goto Exit;
  322. }
  323. DllCharacteristics = 0;
  324. if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) {
  325. DllCharacteristics |= IMAGE_FILE_EXECUTABLE_IMAGE;
  326. }
  327. if ( dwFlags & LOAD_IGNORE_CODE_AUTHZ_LEVEL ) {
  328. DllCharacteristics |= IMAGE_FILE_SYSTEM;
  329. }
  330. RtlInitUnicodeString(&DllName_U, lpwLibFileName);
  331. //
  332. // Quick check to see if dll being loaded is the main exe. For some reason
  333. // hook stuff tends to do this and this is worst path through the loader
  334. //
  335. BasepCheckExeLdrEntry();
  336. if ( !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && BasepExeLdrEntry && (DllName_U.Length == BasepExeLdrEntry->FullDllName.Length) ){
  337. if ( RtlEqualUnicodeString(&DllName_U,&BasepExeLdrEntry->FullDllName,TRUE) ) {
  338. return (HMODULE)BasepExeLdrEntry->DllBase;
  339. }
  340. }
  341. //
  342. // check to see if there are trailing spaces in the dll name (Win95 compat)
  343. //
  344. if ( DllName_U.Length && DllName_U.Buffer[(DllName_U.Length-1)>>1] == (WCHAR)' ') {
  345. TrimmedDllName = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), DllName_U.MaximumLength);
  346. if ( !TrimmedDllName ) {
  347. Status = STATUS_NO_MEMORY;
  348. goto Exit;
  349. }
  350. RtlCopyMemory(TrimmedDllName,DllName_U.Buffer,DllName_U.MaximumLength);
  351. DllName_U.Buffer = TrimmedDllName;
  352. while (DllName_U.Length && DllName_U.Buffer[(DllName_U.Length-1)>>1] == (WCHAR)' ') {
  353. DllName_U.Buffer[(DllName_U.Length-1)>>1] = UNICODE_NULL;
  354. DllName_U.Length -= sizeof(WCHAR);
  355. DllName_U.MaximumLength -= sizeof(WCHAR);
  356. }
  357. }
  358. AllocatedPath = NULL;
  359. //
  360. // Determine the path to use for the load
  361. //
  362. AllocatedPath
  363. = BaseComputeProcessDllPath(
  364. dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH ? DllName_U.Buffer : NULL,
  365. NULL
  366. );
  367. if ( !AllocatedPath ) {
  368. Status = STATUS_NO_MEMORY;
  369. goto Exit;
  370. }
  371. //
  372. // Actually perform the library loading sequence.
  373. //
  374. RtlInitUnicodeString(&AllocatedPath_U, AllocatedPath);
  375. try {
  376. if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) {
  377. #ifdef WX86
  378. // LdrGetDllHandle clears UseKnownWx86Dll, but the value is
  379. // needed again by LdrLoadDll.
  380. BOOLEAN Wx86KnownDll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
  381. #endif
  382. Status = LdrGetDllHandle(
  383. AllocatedPath_U.Buffer,
  384. NULL,
  385. &DllName_U,
  386. (PVOID *)&hModule
  387. );
  388. if (NT_SUCCESS( Status )) {
  389. #ifdef WX86
  390. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = Wx86KnownDll;
  391. #endif
  392. goto alreadyLoaded;
  393. }
  394. Status = BasepLoadLibraryAsDataFile( AllocatedPath_U.Buffer,
  395. &DllName_U,
  396. (PVOID *)&hModule
  397. );
  398. } else {
  399. alreadyLoaded:
  400. Status = LdrLoadDll(
  401. AllocatedPath_U.Buffer,
  402. &DllCharacteristics,
  403. &DllName_U,
  404. (PVOID *)&hModule
  405. );
  406. }
  407. } except ((GetExceptionCode () == STATUS_POSSIBLE_DEADLOCK) ?
  408. EXCEPTION_CONTINUE_SEARCH :
  409. EXCEPTION_EXECUTE_HANDLER) {
  410. Status = GetExceptionCode();
  411. }
  412. Exit:
  413. if ( TrimmedDllName )
  414. RtlFreeHeap(RtlProcessHeap(), 0, TrimmedDllName);
  415. if ( AllocatedPath )
  416. RtlFreeHeap(RtlProcessHeap(), 0, AllocatedPath);
  417. if ( InitiatorDllDirBuffer )
  418. RtlFreeHeap(RtlProcessHeap(), 0, InitiatorDllDirBuffer);
  419. if (!NT_SUCCESS(Status))
  420. BaseSetLastNTError(Status);
  421. return hModule;
  422. }
  423. HMODULE
  424. LoadLibraryExA(
  425. LPCSTR lpLibFileName,
  426. HANDLE hFile,
  427. DWORD dwFlags
  428. )
  429. {
  430. PUNICODE_STRING Unicode;
  431. Unicode = Basep8BitStringToStaticUnicodeString( lpLibFileName );
  432. if (Unicode == NULL) {
  433. return NULL;
  434. }
  435. return LoadLibraryExW( Unicode->Buffer,
  436. hFile,
  437. dwFlags);
  438. }
  439. HMODULE
  440. LoadLibraryA(
  441. LPCSTR lpLibFileName
  442. )
  443. {
  444. PUNICODE_STRING Unicode;
  445. //
  446. // The specification for twain_32.dll says that this
  447. // DLL is supposed to be installed in %windir%. Some
  448. // apps put a twain_32.dll in the system32 directory
  449. // and all the apps using this dll will blow up.
  450. //
  451. if (ARGUMENT_PRESENT(lpLibFileName) &&
  452. _strcmpi(lpLibFileName, "twain_32.dll") == 0) {
  453. LPSTR pszBuffer;
  454. UINT BufferSize, StrLength;
  455. #define SLASH_TWAIN_DLL "\\twain_32.dll"
  456. #define TWAIN_DLL_SIZE sizeof(SLASH_TWAIN_DLL)
  457. BufferSize = MAX_PATH * sizeof(char);
  458. pszBuffer = RtlAllocateHeap(RtlProcessHeap(),
  459. MAKE_TAG( TMP_TAG ),
  460. BufferSize);
  461. if (pszBuffer != NULL) {
  462. HMODULE hMod;
  463. BufferSize = BufferSize - TWAIN_DLL_SIZE + sizeof(char);
  464. StrLength = GetWindowsDirectoryA(pszBuffer, BufferSize);
  465. if ((StrLength != 0) && (StrLength < BufferSize)) {
  466. strncat(pszBuffer, SLASH_TWAIN_DLL,
  467. TWAIN_DLL_SIZE - sizeof(char));
  468. hMod = LoadLibraryA(pszBuffer);
  469. if (hMod != NULL) {
  470. RtlFreeHeap(RtlProcessHeap(), 0, pszBuffer);
  471. return hMod;
  472. }
  473. }
  474. RtlFreeHeap(RtlProcessHeap(), 0, pszBuffer);
  475. }
  476. #undef SLASH_TWAIN_DLL
  477. #undef TWAIN_DLL_SIZE
  478. }
  479. return LoadLibraryExA( lpLibFileName,
  480. NULL,
  481. 0 );
  482. }
  483. HMODULE
  484. LoadLibraryW(
  485. LPCWSTR lpwLibFileName
  486. )
  487. {
  488. return LoadLibraryExW( lpwLibFileName,
  489. NULL,
  490. 0 );
  491. }
  492. BOOL
  493. FreeLibrary(
  494. HMODULE hLibModule
  495. )
  496. /*++
  497. Routine Description:
  498. This function decreases the reference count of the loaded library
  499. module by one. The reference count is maintain for each process.
  500. When the reference count for the specified library module is
  501. decremented to zero, the library module's DLL Instance Termination
  502. entry point is called. This will allow a library module a chance to
  503. cleanup resources that we allocated on behalf of the current
  504. process. See the Task Management section for a description of the
  505. DLL Instance Termination entry point. Finally, after the
  506. termination entry point returns, the library module is removed from
  507. the address space of the current process.
  508. If more than one process has loaded a library module, then the
  509. library module will remain in use until all process's that loaded
  510. the module have called FreeLibrary to unload the library.
  511. Arguments:
  512. hLibModule - Identifies the loaded library module.
  513. Return Value:
  514. TRUE - The operation was successful
  515. FALSE/NULL - The operation failed. Extended error status is available
  516. using the GetLastError function.
  517. --*/
  518. {
  519. NTSTATUS Status;
  520. if (LDR_IS_DATAFILE(hLibModule)) {
  521. if (RtlImageNtHeader(LDR_DATAFILE_TO_VIEW(hLibModule))) {
  522. Status = NtUnmapViewOfSection( NtCurrentProcess(),
  523. LDR_DATAFILE_TO_VIEW(hLibModule)
  524. );
  525. LdrUnloadAlternateResourceModule(hLibModule);
  526. } else {
  527. Status = STATUS_INVALID_IMAGE_FORMAT;
  528. }
  529. } else {
  530. Status = LdrUnloadDll( (PVOID)hLibModule );
  531. }
  532. if ( !NT_SUCCESS(Status) ) {
  533. BaseSetLastNTError(Status);
  534. return FALSE;
  535. } else {
  536. return TRUE;
  537. }
  538. }
  539. VOID
  540. WINAPI
  541. FreeLibraryAndExitThread(
  542. HMODULE hLibModule,
  543. DWORD dwExitCode
  544. )
  545. /*++
  546. Routine Description:
  547. This function decreases the reference count of the loaded library
  548. module by one, and then calls ExitThread.
  549. The purpose of this function is to allow threads that are created
  550. within a dll, and execute within that DLL an opportunity to safely
  551. unload the DLL and to exit.
  552. When the reference count for the specified library module is
  553. decremented to zero, the library module's DLL Instance Termination
  554. entry point is called. This will allow a library module a chance to
  555. cleanup resources that we allocated on behalf of the current
  556. process. See the Task Management section for a description of the
  557. DLL Instance Termination entry point. Finally, after the
  558. termination entry point returns, the library module is removed from
  559. the address space of the current process.
  560. If more than one process has loaded a library module, then the
  561. library module will remain in use until all process's that loaded
  562. the module have called FreeLibrary to unload the library.
  563. Arguments:
  564. hLibModule - Identifies the loaded library module.
  565. dwExitCode - Supplies the exit code for the thread
  566. Return Value:
  567. This function never returns. invalid hLibModule values are silently ignored
  568. --*/
  569. {
  570. if (LDR_IS_DATAFILE(hLibModule)) {
  571. if (RtlImageNtHeader(LDR_DATAFILE_TO_VIEW(hLibModule))) {
  572. NtUnmapViewOfSection( NtCurrentProcess(),
  573. LDR_DATAFILE_TO_VIEW(hLibModule) );
  574. LdrUnloadAlternateResourceModule(hLibModule);
  575. }
  576. } else {
  577. LdrUnloadDll( (PVOID)hLibModule );
  578. }
  579. ExitThread(dwExitCode);
  580. }
  581. BOOL
  582. WINAPI
  583. DisableThreadLibraryCalls(
  584. HMODULE hLibModule
  585. )
  586. /*++
  587. Routine Description:
  588. This function disables DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications
  589. for the DLL specified by hLibModule. Attempting to call this on a DLL with
  590. inuse static thread local storage is an error.
  591. Arguments:
  592. hLibModule - Identifies the loaded library module.
  593. Return Value:
  594. TRUE - The operation was successful
  595. FALSE/NULL - The operation failed. Extended error status is available
  596. using the GetLastError function.
  597. --*/
  598. {
  599. NTSTATUS Status;
  600. BOOL rv;
  601. rv = TRUE;
  602. Status = LdrDisableThreadCalloutsForDll(hLibModule);
  603. if ( !NT_SUCCESS(Status) ) {
  604. BaseSetLastNTError(Status);
  605. rv = FALSE;
  606. }
  607. return rv;
  608. }
  609. BOOL
  610. WINAPI
  611. SetDllDirectoryW(
  612. IN LPCWSTR lpPathName
  613. )
  614. /*++
  615. Routine Description:
  616. This function sets the effective current directory used
  617. for the LoadLibrary() dll search path.
  618. Arguments:
  619. lpPathName - Specifies the directory to use.
  620. If the directory is NULL, switch back to the default
  621. dll search path behavior (in case a SetDllDirectory()
  622. call was already in effect).
  623. If the directory is the empty string, omit both the
  624. dll directory and the current directory from the
  625. search path.
  626. Note that setting the directory to L"." has the
  627. effect of reverting back to the original
  628. LoadLibrary() path.
  629. Return Value:
  630. TRUE - The operation was successful.
  631. FALSE - The operation failed. Extended error status is available
  632. via GetLastError().
  633. Notes:
  634. Moving the current directory after the system directories (which
  635. we have to do for security considerations) breaks applications
  636. which depend on using { SetCurrentDirectory(); LoadLibrary(); } to
  637. pick up specific versions of libraries.
  638. We recognize that this solution is suboptimal, but we're stuck
  639. with the current LoadLibrary() API, which has been around for
  640. quite some time. We did try changing it, but ran into serious
  641. application compatibility issues; moving the current directory
  642. later in the search path caused the least number of problems, and
  643. this API makes it easy for applications and application
  644. compatibility shims to get back the old behavior.
  645. --*/
  646. {
  647. UNICODE_STRING OldDllDirectory;
  648. UNICODE_STRING NewDllDirectory;
  649. if (lpPathName) {
  650. if (wcschr(lpPathName, L';')) {
  651. SetLastError(ERROR_INVALID_PARAMETER);
  652. return FALSE;
  653. }
  654. if (! RtlCreateUnicodeString(&NewDllDirectory, lpPathName)) {
  655. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  656. return FALSE;
  657. }
  658. } else {
  659. RtlInitUnicodeString(&NewDllDirectory, NULL);
  660. }
  661. RtlEnterCriticalSection(&BaseDllDirectoryLock);
  662. OldDllDirectory = BaseDllDirectory;
  663. BaseDllDirectory = NewDllDirectory;
  664. RtlLeaveCriticalSection(&BaseDllDirectoryLock);
  665. RtlFreeUnicodeString(&OldDllDirectory);
  666. return TRUE;
  667. }
  668. BOOL
  669. WINAPI
  670. SetDllDirectoryA(
  671. IN LPCSTR lpPathName
  672. )
  673. /*++
  674. Routine Description:
  675. ANSI implementation of SetDllDirectoryW
  676. --*/
  677. {
  678. ANSI_STRING AnsiDllDirectory;
  679. UNICODE_STRING OldDllDirectory;
  680. UNICODE_STRING NewDllDirectory;
  681. NTSTATUS Status;
  682. if (lpPathName) {
  683. if (strchr(lpPathName, ';')) {
  684. SetLastError(ERROR_INVALID_PARAMETER);
  685. return FALSE;
  686. }
  687. Status = RtlInitAnsiStringEx(&AnsiDllDirectory,
  688. lpPathName);
  689. if (! NT_SUCCESS(Status)) {
  690. BaseSetLastNTError(Status);
  691. return FALSE;
  692. }
  693. Status = Basep8BitStringToUnicodeString(&NewDllDirectory,
  694. &AnsiDllDirectory,
  695. TRUE);
  696. if (! NT_SUCCESS(Status)) {
  697. BaseSetLastNTError(Status);
  698. return FALSE;
  699. }
  700. } else {
  701. RtlInitUnicodeString(&NewDllDirectory, NULL);
  702. }
  703. RtlEnterCriticalSection(&BaseDllDirectoryLock);
  704. OldDllDirectory = BaseDllDirectory;
  705. BaseDllDirectory = NewDllDirectory;
  706. RtlLeaveCriticalSection(&BaseDllDirectoryLock);
  707. RtlFreeUnicodeString(&OldDllDirectory);
  708. return TRUE;
  709. }
  710. DWORD
  711. WINAPI
  712. GetDllDirectoryW(
  713. IN DWORD nBufferLength,
  714. OUT LPWSTR lpBuffer
  715. )
  716. /*++
  717. Routine Description:
  718. This function retrieves the effective current directory used for
  719. the LoadLibrary() dll search path.
  720. Arguments:
  721. nBufferLength - Specifies the size of the output buffer.
  722. lpBuffer - The buffer where the current dll directory will be written.
  723. Return Value:
  724. The return value is the length of the string copied to lpBuffer, not
  725. including the terminating null character. If the return value is
  726. greater than nBufferLength, the return value is the size of the buffer
  727. required to hold the pathname. The return value is zero if the
  728. function failed.
  729. --*/
  730. {
  731. DWORD Result;
  732. RtlEnterCriticalSection(&BaseDllDirectoryLock);
  733. if (nBufferLength * sizeof(WCHAR) <= BaseDllDirectory.Length) {
  734. Result = ((BaseDllDirectory.Length + sizeof(UNICODE_NULL))
  735. / sizeof(WCHAR));
  736. if (lpBuffer) {
  737. lpBuffer[0] = UNICODE_NULL;
  738. }
  739. } else {
  740. RtlCopyMemory(lpBuffer,
  741. BaseDllDirectory.Buffer,
  742. BaseDllDirectory.Length);
  743. Result = BaseDllDirectory.Length / sizeof(WCHAR);
  744. lpBuffer[Result] = UNICODE_NULL;
  745. }
  746. RtlLeaveCriticalSection(&BaseDllDirectoryLock);
  747. return Result;
  748. }
  749. DWORD
  750. WINAPI
  751. GetDllDirectoryA(
  752. IN DWORD nBufferLength,
  753. OUT LPSTR lpBuffer
  754. )
  755. /*++
  756. Routine Description:
  757. ANSI implementation of GetDllDirectoryW
  758. --*/
  759. {
  760. ANSI_STRING Ansi;
  761. DWORD Result;
  762. NTSTATUS Status;
  763. RtlInitEmptyUnicodeString(&Ansi, lpBuffer, nBufferLength);
  764. RtlEnterCriticalSection(&BaseDllDirectoryLock);
  765. // Includes the NULL
  766. Result = BasepUnicodeStringTo8BitSize(&BaseDllDirectory);
  767. if (Result <= nBufferLength) {
  768. Status = BasepUnicodeStringTo8BitString(&Ansi,
  769. &BaseDllDirectory,
  770. FALSE);
  771. Result--; // trim off the space needed for the NULL
  772. } else {
  773. Status = STATUS_SUCCESS;
  774. if (lpBuffer) {
  775. lpBuffer[0] = ANSI_NULL;
  776. }
  777. }
  778. RtlLeaveCriticalSection(&BaseDllDirectoryLock);
  779. if (! NT_SUCCESS(Status)) {
  780. BaseSetLastNTError(Status);
  781. Result = 0;
  782. lpBuffer[0] = ANSI_NULL;
  783. }
  784. return Result;
  785. }
  786. DWORD
  787. WINAPI
  788. GetModuleFileNameW(
  789. HMODULE hModule,
  790. LPWSTR lpFilename,
  791. DWORD nSize
  792. )
  793. /*++
  794. Routine Description:
  795. This function retrieves the full pathname of the executable file
  796. from which the specified module was loaded. The function copies the
  797. null-terminated filename into the buffer pointed to by the
  798. lpFilename parameter.
  799. Routine Description:
  800. hModule - Identifies the module whose executable file name is being
  801. requested. A value of NULL references the module handle
  802. associated with the image file that was used to create the
  803. current process.
  804. lpFilename - Points to the buffer that is to receive the filename.
  805. nSize - Specifies the maximum number of characters to copy. If the
  806. filename is longer than the maximum number of characters
  807. specified by the nSize parameter, it is truncated.
  808. Return Value:
  809. The return value specifies the actual length of the string copied to
  810. the buffer. A return value of zero indicates an error and extended
  811. error status is available using the GetLastError function.
  812. Arguments:
  813. --*/
  814. {
  815. PLDR_DATA_TABLE_ENTRY Entry;
  816. PLIST_ENTRY Head,Next;
  817. DWORD ReturnLength, CopySize;
  818. PWCHAR ReturnPointer;
  819. PVOID DllHandle = BasepMapModuleHandle( hModule, FALSE );
  820. PUNICODE_STRING Ustr;
  821. PVOID LoaderLockCookie = NULL;
  822. PRTL_PERTHREAD_CURDIR CurDir;
  823. BOOLEAN LoaderLocked;
  824. ReturnLength = 0;
  825. ReturnPointer = NULL;
  826. LoaderLocked = FALSE;
  827. try {
  828. //
  829. // If we are looking at the current image, then check for name
  830. // redirection
  831. //
  832. if (!ARGUMENT_PRESENT (hModule)) {
  833. CurDir = RtlGetPerThreadCurdir ();
  834. if (CurDir && CurDir->ImageName) {
  835. Ustr = CurDir->ImageName;
  836. ReturnPointer = Ustr->Buffer;
  837. ReturnLength = Ustr->Length / sizeof (WCHAR);
  838. goto copy_back;
  839. }
  840. }
  841. Head = &NtCurrentPeb ()->Ldr->InLoadOrderModuleList;
  842. LoaderLocked = TRUE;
  843. LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &LoaderLockCookie);
  844. Next = Head->Flink;
  845. while (Next != Head) {
  846. Entry = CONTAINING_RECORD (Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  847. if (DllHandle == (PVOID)Entry->DllBase) {
  848. ReturnLength = Entry->FullDllName.Length / sizeof (WCHAR);
  849. ReturnPointer = Entry->FullDllName.Buffer;
  850. goto copy_back;
  851. }
  852. Next = Next->Flink;
  853. }
  854. leave;
  855. copy_back:;
  856. CopySize = ReturnLength;
  857. if (nSize < ReturnLength + 1) {
  858. ReturnLength = nSize;
  859. CopySize = nSize - 1;
  860. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  861. } else {
  862. SetLastError (NO_ERROR);
  863. }
  864. if (nSize > 0) {
  865. RtlCopyMemory (lpFilename,
  866. ReturnPointer,
  867. CopySize * sizeof (WCHAR));
  868. lpFilename[CopySize] = UNICODE_NULL;
  869. }
  870. } finally {
  871. if (LoaderLocked) {
  872. LdrUnlockLoaderLock (LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, LoaderLockCookie);
  873. }
  874. }
  875. return ReturnLength;
  876. }
  877. DWORD
  878. GetModuleFileNameA(
  879. HMODULE hModule,
  880. LPSTR lpFilename,
  881. DWORD nSize
  882. )
  883. {
  884. NTSTATUS Status;
  885. ANSI_STRING AnsiString;
  886. UNICODE_STRING UnicodeString;
  887. DWORD ReturnCode;
  888. UnicodeString.Buffer = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nSize*2);
  889. if ( !UnicodeString.Buffer ) {
  890. BaseSetLastNTError( STATUS_NO_MEMORY );
  891. return 0;
  892. }
  893. ReturnCode = GetModuleFileNameW(hModule, UnicodeString.Buffer, nSize);
  894. UnicodeString.Length = UnicodeString.MaximumLength = (USHORT)ReturnCode*2;
  895. UnicodeString.MaximumLength++;
  896. UnicodeString.MaximumLength++;
  897. if (ReturnCode) {
  898. Status = BasepUnicodeStringTo8BitString(&AnsiString, &UnicodeString, TRUE);
  899. if (!NT_SUCCESS(Status) ) {
  900. BaseSetLastNTError(Status);
  901. RtlFreeUnicodeString(&UnicodeString);
  902. return 0;
  903. }
  904. ReturnCode = min( nSize, AnsiString.Length );
  905. RtlCopyMemory(
  906. lpFilename,
  907. AnsiString.Buffer,
  908. nSize <= ReturnCode ? nSize : ReturnCode + 1
  909. );
  910. RtlFreeAnsiString(&AnsiString);
  911. }
  912. RtlFreeUnicodeString(&UnicodeString);
  913. return ReturnCode;
  914. }
  915. HMODULE
  916. GetModuleHandleA(
  917. LPCSTR lpModuleName
  918. )
  919. /*++
  920. Routine Description:
  921. ANSI thunk to GetModuleHandleW
  922. --*/
  923. {
  924. PUNICODE_STRING Unicode;
  925. if ( !ARGUMENT_PRESENT(lpModuleName) ) {
  926. return( (HMODULE)(PVOID)NtCurrentPeb()->ImageBaseAddress );
  927. }
  928. Unicode = Basep8BitStringToStaticUnicodeString( lpModuleName );
  929. if (Unicode == NULL) {
  930. return NULL;
  931. }
  932. return GetModuleHandleW(Unicode->Buffer);
  933. }
  934. HMODULE
  935. WINAPI
  936. GetModuleHandleForUnicodeString(
  937. IN PUNICODE_STRING ModuleName
  938. )
  939. /*++
  940. Routine Description:
  941. This function is the helper routine for GetModuleHandleW. See that for
  942. more details on return value, etc.
  943. Arguments:
  944. ModuleName - Points to counted unicode string that names the library file.
  945. Caller guarantees that ModuleName->Buffer is not NULL.
  946. Return Value:
  947. See GetModuleHandleW for this.
  948. --*/
  949. {
  950. LPWSTR AllocatedPath;
  951. NTSTATUS Status;
  952. HMODULE hModule;
  953. #ifdef WX86
  954. BOOLEAN Wx86KnownDll;
  955. #endif
  956. #ifdef WX86
  957. // LdrGetDllHandle clears UseKnownWx86Dll, but the value is needed again
  958. // for the second LdrGetDllHandle call.
  959. Wx86KnownDll = NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll;
  960. #endif
  961. Status = LdrGetDllHandle(
  962. (PWSTR)1,
  963. NULL,
  964. ModuleName,
  965. (PVOID *)&hModule
  966. );
  967. if ( NT_SUCCESS(Status) ) {
  968. return hModule;
  969. }
  970. //
  971. // Determine the path that the program was created from
  972. //
  973. AllocatedPath = BaseComputeProcessDllPath(NULL,
  974. NULL);
  975. if (!AllocatedPath) {
  976. Status = STATUS_NO_MEMORY;
  977. goto bail;
  978. }
  979. #ifdef WX86
  980. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = Wx86KnownDll;
  981. #endif
  982. try {
  983. Status = LdrGetDllHandle(
  984. AllocatedPath,
  985. NULL,
  986. ModuleName,
  987. (PVOID *)&hModule
  988. );
  989. RtlFreeHeap(RtlProcessHeap(), 0, AllocatedPath);
  990. } except (EXCEPTION_EXECUTE_HANDLER) {
  991. Status = GetExceptionCode();
  992. RtlFreeHeap(RtlProcessHeap(), 0, AllocatedPath);
  993. }
  994. bail:
  995. if (!NT_SUCCESS(Status) ) {
  996. BaseSetLastNTError(Status);
  997. return NULL;
  998. } else {
  999. return hModule;
  1000. }
  1001. }
  1002. HMODULE
  1003. WINAPI
  1004. GetModuleHandleW(
  1005. LPCWSTR lpwModuleName
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. This function returns the handle of a module that is loaded into the
  1010. context of the calling process.
  1011. In a multi-thread environment, this function is not reliable, since
  1012. while one thread is calling this function and getting back a module
  1013. handle, another thread in the same process could be calling
  1014. FreeLibrary for the same module, therefore invalidating the returned
  1015. module handle for the first thread.
  1016. Arguments:
  1017. lpwModuleName - Points to a string that names the library file. The
  1018. string must be a null-terminated unicode string. If this
  1019. parameter is NULL, then the handle for the current image file is
  1020. returned.
  1021. Return Value:
  1022. The return value is a module handle. A return value of NULL
  1023. indicates either that the module has not been loaded into the
  1024. context of the current process or an error occured. The exact
  1025. reason is available using the GetLastError function.
  1026. --*/
  1027. {
  1028. HMODULE hModule;
  1029. BOOL fSuccess;
  1030. if (!ARGUMENT_PRESENT(lpwModuleName)) {
  1031. return( (HMODULE)(PVOID)NtCurrentPeb()->ImageBaseAddress );
  1032. }
  1033. fSuccess =
  1034. BasepGetModuleHandleExW(
  1035. BASEP_GET_MODULE_HANDLE_EX_NO_LOCK,
  1036. GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
  1037. lpwModuleName,
  1038. &hModule
  1039. );
  1040. return fSuccess ? hModule : NULL;
  1041. }
  1042. ULONG
  1043. WINAPI
  1044. BasepGetModuleHandleExParameterValidation(
  1045. IN DWORD dwFlags,
  1046. IN CONST VOID* lpModuleName,
  1047. OUT HMODULE* phModule
  1048. )
  1049. {
  1050. NTSTATUS Status = STATUS_SUCCESS;
  1051. if (phModule != NULL)
  1052. *phModule = NULL;
  1053. if ((dwFlags & ~(
  1054. GET_MODULE_HANDLE_EX_FLAG_PIN
  1055. | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
  1056. | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
  1057. )) != 0) {
  1058. Status = STATUS_INVALID_PARAMETER_1;
  1059. goto Error;
  1060. }
  1061. if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) != 0
  1062. && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) != 0
  1063. ) {
  1064. Status = STATUS_INVALID_PARAMETER_1;
  1065. goto Error;
  1066. }
  1067. if (!ARGUMENT_PRESENT(lpModuleName)
  1068. && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) != 0
  1069. ) {
  1070. Status = STATUS_INVALID_PARAMETER_1;
  1071. goto Error;
  1072. }
  1073. if (phModule == NULL) {
  1074. Status = STATUS_INVALID_PARAMETER_2;
  1075. goto Error;
  1076. }
  1077. if (!ARGUMENT_PRESENT(lpModuleName)) {
  1078. *phModule = ( (HMODULE)(PVOID)NtCurrentPeb()->ImageBaseAddress );
  1079. goto Success;
  1080. }
  1081. goto Continue;
  1082. Error:
  1083. BaseSetLastNTError(Status);
  1084. return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
  1085. Success:
  1086. return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS;
  1087. Continue:
  1088. return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE;
  1089. }
  1090. BOOL
  1091. GetModuleHandleExA(
  1092. IN DWORD dwFlags,
  1093. IN LPCSTR lpaModuleName,
  1094. OUT HMODULE* phModule
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. ANSI thunk to GetModuleHandleExW
  1099. --*/
  1100. {
  1101. PUNICODE_STRING Unicode;
  1102. ULONG Disposition;
  1103. LPCWSTR lpwModuleName;
  1104. BOOL fSuccess = FALSE;
  1105. Disposition = BasepGetModuleHandleExParameterValidation(dwFlags, lpaModuleName, phModule);
  1106. switch (Disposition)
  1107. {
  1108. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR:
  1109. goto Exit;
  1110. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS:
  1111. fSuccess = TRUE;
  1112. goto Exit;
  1113. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE:
  1114. break;
  1115. }
  1116. if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) == 0) {
  1117. Unicode = Basep8BitStringToStaticUnicodeString(lpaModuleName);
  1118. if (Unicode == NULL) {
  1119. goto Exit;
  1120. }
  1121. lpwModuleName = Unicode->Buffer;
  1122. } else {
  1123. lpwModuleName = (LPCWSTR)(CONST VOID*)lpaModuleName;
  1124. }
  1125. if (!BasepGetModuleHandleExW(0, dwFlags, lpwModuleName, phModule))
  1126. goto Exit;
  1127. fSuccess = TRUE;
  1128. Exit:
  1129. return fSuccess;
  1130. }
  1131. BOOL
  1132. WINAPI
  1133. GetModuleHandleExW(
  1134. IN DWORD dwFlags,
  1135. IN LPCWSTR lpwModuleName,
  1136. OUT HMODULE* phModule
  1137. )
  1138. {
  1139. ULONG Disposition;
  1140. BOOL fSuccess = FALSE;
  1141. Disposition = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule);
  1142. switch (Disposition)
  1143. {
  1144. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR:
  1145. goto Exit;
  1146. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS:
  1147. fSuccess = TRUE;
  1148. goto Exit;
  1149. case BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE:
  1150. break;
  1151. }
  1152. if (!BasepGetModuleHandleExW(0, dwFlags, lpwModuleName, phModule))
  1153. goto Exit;
  1154. fSuccess = TRUE;
  1155. Exit:
  1156. return fSuccess;
  1157. }
  1158. BOOL
  1159. WINAPI
  1160. BasepGetModuleHandleExW(
  1161. IN DWORD dwPrivateFlags,
  1162. IN DWORD dwPublicFlags,
  1163. IN LPCWSTR lpwModuleName,
  1164. OUT HMODULE* phModule
  1165. )
  1166. {
  1167. NTSTATUS Status = STATUS_SUCCESS;
  1168. HMODULE hModule = NULL;
  1169. UNICODE_STRING DllName_U, AppPathDllName_U, LocalDirDllName_U;
  1170. BOOL DoDllRedirection = FALSE;
  1171. WCHAR DllNameUnderImageDirBuffer[MAX_PATH];
  1172. WCHAR DllNameUnderLocalDirBuffer[MAX_PATH];
  1173. BOOL HoldingLoaderLock = FALSE;
  1174. ULONG LdrFlags;
  1175. PVOID LdrLockCookie = NULL;
  1176. RTL_SOFT_ASSERT(BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule) == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE);
  1177. AppPathDllName_U.Buffer = DllNameUnderImageDirBuffer;
  1178. AppPathDllName_U.Length = 0 ;
  1179. AppPathDllName_U.MaximumLength = sizeof(DllNameUnderImageDirBuffer);
  1180. LocalDirDllName_U.Buffer = DllNameUnderLocalDirBuffer;
  1181. LocalDirDllName_U.Length = 0 ;
  1182. LocalDirDllName_U.MaximumLength = sizeof(DllNameUnderLocalDirBuffer);
  1183. if ((dwPrivateFlags & BASEP_GET_MODULE_HANDLE_EX_NO_LOCK) == 0) {
  1184. Status = LdrLockLoaderLock(0, NULL, &LdrLockCookie);
  1185. if (!NT_SUCCESS(Status))
  1186. goto Exit;
  1187. HoldingLoaderLock = TRUE;
  1188. }
  1189. __try {
  1190. if (dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) {
  1191. hModule = RtlPcToFileHeader((PVOID)lpwModuleName, (PVOID*)&hModule);
  1192. if (hModule == NULL) {
  1193. Status = STATUS_DLL_NOT_FOUND;
  1194. __leave;
  1195. }
  1196. } else {
  1197. RtlInitUnicodeString(&DllName_U, lpwModuleName);
  1198. if ((NtCurrentPeb()->ProcessParameters != NULL) &&
  1199. (NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROC_DLL_REDIRECTION_LOCAL))
  1200. DoDllRedirection = TRUE;
  1201. if (DoDllRedirection) {
  1202. Status = RtlComputePrivatizedDllName_U(&DllName_U, &AppPathDllName_U, &LocalDirDllName_U);
  1203. if(!NT_SUCCESS(Status)) {
  1204. __leave;
  1205. }
  1206. hModule = GetModuleHandleForUnicodeString(&LocalDirDllName_U) ;
  1207. if (!hModule )
  1208. hModule = GetModuleHandleForUnicodeString(&AppPathDllName_U) ;
  1209. // Didn't find any re-directed DLL with this name loaded. Now we can just check for the
  1210. // original name passed in.
  1211. }
  1212. if ( ! hModule)
  1213. hModule = GetModuleHandleForUnicodeString(&DllName_U) ;
  1214. if (hModule == NULL) {
  1215. Status = NtCurrentTeb()->LastStatusValue;
  1216. __leave;
  1217. }
  1218. }
  1219. if (dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) {
  1220. Status = STATUS_SUCCESS;
  1221. __leave;
  1222. }
  1223. LdrFlags = (dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0;
  1224. Status = LdrAddRefDll(LdrFlags, (PVOID)hModule);
  1225. } __finally {
  1226. if (HoldingLoaderLock) {
  1227. NTSTATUS Status2 = LdrUnlockLoaderLock(0, LdrLockCookie);
  1228. ASSERT(NT_SUCCESS(Status2));
  1229. HoldingLoaderLock = FALSE;
  1230. }
  1231. }
  1232. Exit : // cleanup
  1233. if (AppPathDllName_U.Buffer != DllNameUnderImageDirBuffer)
  1234. RtlFreeUnicodeString(&AppPathDllName_U);
  1235. if (LocalDirDllName_U.Buffer != DllNameUnderLocalDirBuffer)
  1236. RtlFreeUnicodeString(&LocalDirDllName_U);
  1237. if (!NT_SUCCESS(Status))
  1238. BaseSetLastNTError(Status);
  1239. if (phModule != NULL)
  1240. *phModule = hModule;
  1241. return NT_SUCCESS(Status);
  1242. }
  1243. FARPROC
  1244. GetProcAddress(
  1245. HMODULE hModule,
  1246. LPCSTR lpProcName
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. This function retrieves the memory address of the function whose
  1251. name is pointed to by the lpProcName parameter. The GetProcAddress
  1252. function searches for the function in the module specified by the
  1253. hModule parameter, or in the module associated with the current
  1254. process if hModule is NULL. The function must be an exported
  1255. function; the module's definition file must contain an appropriate
  1256. EXPORTS line for the function.
  1257. If the lpProcName parameter is an ordinal value and a function with
  1258. the specified ordinal does not exist in the module, GetProcAddress
  1259. can still return a non-NULL value. In cases where the function may
  1260. not exist, specify the function by name rather than ordinal value.
  1261. Only use GetProcAddress to retrieve addresses of exported functions
  1262. that belong to library modules.
  1263. The spelling of the function name (pointed to by lpProcName) must be
  1264. identical to the spelling as it appears in the source library's
  1265. definition (.DEF) file. The function can be renamed in the
  1266. definition file. Case sensitive matching is used???
  1267. Arguments:
  1268. hModule - Identifies the module whose executable file contains the
  1269. function. A value of NULL references the module handle
  1270. associated with the image file that was used to create the
  1271. current process.
  1272. lpProcName - Points to the function name, or contains the ordinal
  1273. value of the function. If it is an ordinal value, the value
  1274. must be in the low-order word and zero must be in the high-order
  1275. word. The string must be a null-terminated character string.
  1276. Return Value:
  1277. The return value points to the function's entry point if the
  1278. function is successful. A return value of NULL indicates an error
  1279. and extended error status is available using the GetLastError function.
  1280. --*/
  1281. {
  1282. NTSTATUS Status;
  1283. PVOID ProcedureAddress;
  1284. STRING ProcedureName;
  1285. if ( (ULONG_PTR)lpProcName > 0xffff ) {
  1286. RtlInitString(&ProcedureName,lpProcName);
  1287. Status = LdrGetProcedureAddress(
  1288. BasepMapModuleHandle( hModule, FALSE ),
  1289. &ProcedureName,
  1290. 0L,
  1291. &ProcedureAddress
  1292. );
  1293. } else {
  1294. Status = LdrGetProcedureAddress(
  1295. BasepMapModuleHandle( hModule, FALSE ),
  1296. NULL,
  1297. PtrToUlong((PVOID)lpProcName),
  1298. &ProcedureAddress
  1299. );
  1300. }
  1301. if ( !NT_SUCCESS(Status) ) {
  1302. BaseSetLastNTError(Status);
  1303. return NULL;
  1304. } else {
  1305. if ( ProcedureAddress == BasepMapModuleHandle( hModule, FALSE ) ) {
  1306. if ( (ULONG_PTR)lpProcName > 0xffff ) {
  1307. Status = STATUS_ENTRYPOINT_NOT_FOUND;
  1308. } else {
  1309. Status = STATUS_ORDINAL_NOT_FOUND;
  1310. }
  1311. BaseSetLastNTError(Status);
  1312. return NULL;
  1313. } else {
  1314. return (FARPROC)ProcedureAddress;
  1315. }
  1316. }
  1317. }
  1318. DWORD
  1319. GetVersion(
  1320. VOID
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. This function returns the current version number of Windows.
  1325. Arguments:
  1326. None.
  1327. Return Value:
  1328. The return value specifies the major and minor version numbers of
  1329. Windows. The high-order word specifies the minor version (revision)
  1330. number; the low-order word specifies the major version number.
  1331. --*/
  1332. {
  1333. PPEB Peb;
  1334. Peb = NtCurrentPeb();
  1335. return (((Peb->OSPlatformId ^ 0x2) << 30) |
  1336. (Peb->OSBuildNumber << 16) |
  1337. (Peb->OSMinorVersion << 8) |
  1338. Peb->OSMajorVersion
  1339. );
  1340. }
  1341. WINBASEAPI
  1342. BOOL
  1343. WINAPI
  1344. GetVersionExA(
  1345. LPOSVERSIONINFOA lpVersionInformation
  1346. )
  1347. {
  1348. OSVERSIONINFOEXW VersionInformationU;
  1349. ANSI_STRING AnsiString;
  1350. UNICODE_STRING UnicodeString;
  1351. NTSTATUS Status;
  1352. if (lpVersionInformation->dwOSVersionInfoSize != sizeof( OSVERSIONINFOEXA ) &&
  1353. lpVersionInformation->dwOSVersionInfoSize != sizeof( *lpVersionInformation )
  1354. ) {
  1355. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  1356. return FALSE;
  1357. }
  1358. VersionInformationU.dwOSVersionInfoSize = sizeof( VersionInformationU );
  1359. if (GetVersionExW( (LPOSVERSIONINFOW)&VersionInformationU )) {
  1360. lpVersionInformation->dwMajorVersion = VersionInformationU.dwMajorVersion;
  1361. lpVersionInformation->dwMinorVersion = VersionInformationU.dwMinorVersion;
  1362. lpVersionInformation->dwBuildNumber = VersionInformationU.dwBuildNumber;
  1363. lpVersionInformation->dwPlatformId = VersionInformationU.dwPlatformId;
  1364. if (lpVersionInformation->dwOSVersionInfoSize == sizeof( OSVERSIONINFOEXA )) {
  1365. ((POSVERSIONINFOEXA)lpVersionInformation)->wServicePackMajor = VersionInformationU.wServicePackMajor;
  1366. ((POSVERSIONINFOEXA)lpVersionInformation)->wServicePackMinor = VersionInformationU.wServicePackMinor;
  1367. ((POSVERSIONINFOEXA)lpVersionInformation)->wSuiteMask = VersionInformationU.wSuiteMask;
  1368. ((POSVERSIONINFOEXA)lpVersionInformation)->wProductType = VersionInformationU.wProductType;
  1369. ((POSVERSIONINFOEXA)lpVersionInformation)->wReserved = VersionInformationU.wReserved;
  1370. }
  1371. AnsiString.Buffer = lpVersionInformation->szCSDVersion;
  1372. AnsiString.Length = 0;
  1373. AnsiString.MaximumLength = sizeof( lpVersionInformation->szCSDVersion );
  1374. RtlInitUnicodeString( &UnicodeString, VersionInformationU.szCSDVersion );
  1375. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  1376. &UnicodeString,
  1377. FALSE
  1378. );
  1379. if (NT_SUCCESS( Status )) {
  1380. return TRUE;
  1381. } else {
  1382. return FALSE;
  1383. }
  1384. } else {
  1385. return FALSE;
  1386. }
  1387. }
  1388. WINBASEAPI
  1389. BOOL
  1390. WINAPI
  1391. GetVersionExW(
  1392. LPOSVERSIONINFOW lpVersionInformation
  1393. )
  1394. {
  1395. PPEB Peb;
  1396. NTSTATUS Status;
  1397. if (lpVersionInformation->dwOSVersionInfoSize != sizeof( OSVERSIONINFOEXW ) &&
  1398. lpVersionInformation->dwOSVersionInfoSize != sizeof( *lpVersionInformation )
  1399. ) {
  1400. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  1401. return FALSE;
  1402. }
  1403. Status = RtlGetVersion(lpVersionInformation);
  1404. if (Status == STATUS_SUCCESS) {
  1405. if (lpVersionInformation->dwOSVersionInfoSize ==
  1406. sizeof( OSVERSIONINFOEXW))
  1407. ((POSVERSIONINFOEXW)lpVersionInformation)->wReserved =
  1408. (UCHAR)BaseRCNumber;
  1409. return TRUE;
  1410. } else {
  1411. return FALSE;
  1412. }
  1413. }
  1414. WINBASEAPI
  1415. BOOL
  1416. WINAPI
  1417. VerifyVersionInfoW(
  1418. IN LPOSVERSIONINFOEXW VersionInfo,
  1419. IN DWORD TypeMask,
  1420. IN DWORDLONG ConditionMask
  1421. )
  1422. /*++
  1423. Routine Description:
  1424. This function verifies a version condition. Basically, this
  1425. function lets an app query the system to see if the app is
  1426. running on a specific version combination.
  1427. Arguments:
  1428. VersionInfo - a version structure containing the comparison data
  1429. TypeMask - a mask comtaining the data types to look at
  1430. ConditionMask - a mask containing conditionals for doing the comparisons
  1431. Return Value:
  1432. TRUE - the version condition exists
  1433. FALSE - the version condition does NOT exists
  1434. --*/
  1435. {
  1436. DWORD i;
  1437. OSVERSIONINFOEXW CurrVersion;
  1438. BOOL SuiteFound = FALSE;
  1439. NTSTATUS Status;
  1440. Status = RtlVerifyVersionInfo(VersionInfo, TypeMask, ConditionMask);
  1441. if (Status == STATUS_INVALID_PARAMETER) {
  1442. SetLastError( ERROR_BAD_ARGUMENTS );
  1443. return FALSE;
  1444. } else if (Status == STATUS_REVISION_MISMATCH) {
  1445. SetLastError(ERROR_OLD_WIN_VERSION);
  1446. return FALSE;
  1447. }
  1448. return TRUE;
  1449. }
  1450. WINBASEAPI
  1451. BOOL
  1452. WINAPI
  1453. VerifyVersionInfoA(
  1454. IN LPOSVERSIONINFOEXA VersionInfo,
  1455. IN DWORD TypeMask,
  1456. IN DWORDLONG ConditionMask
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. This function verifies a version condition. Basically, this
  1461. function lets an app query the system to see if the app is
  1462. running on a specific version combination.
  1463. Arguments:
  1464. VersionInfo - a version structure containing the comparison data
  1465. TypeMask - a mask comtaining the data types to look at
  1466. ConditionMask - a mask containing conditionals for doing the comparisons
  1467. Return Value:
  1468. TRUE - the version condition exists
  1469. FALSE - the version condition does NOT exists
  1470. --*/
  1471. {
  1472. OSVERSIONINFOEXW VersionInfoW;
  1473. VersionInfoW.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  1474. VersionInfoW.dwMajorVersion = VersionInfo->dwMajorVersion;
  1475. VersionInfoW.dwMinorVersion = VersionInfo->dwMinorVersion;
  1476. VersionInfoW.dwBuildNumber = VersionInfo->dwBuildNumber;
  1477. VersionInfoW.dwPlatformId = VersionInfo->dwPlatformId;
  1478. VersionInfoW.wServicePackMajor = VersionInfo->wServicePackMajor;
  1479. VersionInfoW.wServicePackMinor = VersionInfo->wServicePackMinor;
  1480. VersionInfoW.wSuiteMask = VersionInfo->wSuiteMask;
  1481. VersionInfoW.wProductType = VersionInfo->wProductType;
  1482. VersionInfoW.wReserved = VersionInfo->wReserved;
  1483. return VerifyVersionInfoW( &VersionInfoW, TypeMask, ConditionMask );
  1484. }
  1485. HRSRC
  1486. FindResourceA(
  1487. HMODULE hModule,
  1488. LPCSTR lpName,
  1489. LPCSTR lpType
  1490. )
  1491. /*++
  1492. Routine Description:
  1493. This function determines the location of a resource in the specified
  1494. resource file. The lpName and lpType parameters define the resource
  1495. name and type, respectively.
  1496. If the high-order word of the lpName or lpType parameter is zero,
  1497. the low-order word specifies the integer ID of the name or type of
  1498. the given resource. Otherwise, the parameters are pointers to
  1499. null-terminated character strings. If the first character of the
  1500. string is a pound sign (#), the remaining characters represent a
  1501. decimal number that specifies the integer ID of the resource's name
  1502. or type. For example, the string "#258" represents the integer ID
  1503. 258.
  1504. To reduce the amount of memory required for the resources used by an
  1505. application, applications should refer to their resources by integer
  1506. ID instead of by name.
  1507. An application must not call FindResource and the LoadResource
  1508. function to load cursor, icon, or string resources. Instead, it
  1509. must load these resources by calling the following functions:
  1510. - LoadCursor
  1511. - LoadIcon
  1512. - LoadString
  1513. An application can call FindResource and LoadResource to load other
  1514. predefined resource types. However, it is recommended that the
  1515. application load the corresponding resources by calling the
  1516. following functions:
  1517. - LoadAccelerators
  1518. - LoadBitmap
  1519. - LoadMenu
  1520. The above six API calls are documented with the Graphical User
  1521. Interface API specification.
  1522. Arguments:
  1523. hModule - Identifies the module whose executable file contains the
  1524. resource. A value of NULL references the module handle
  1525. associated with the image file that was used to create the
  1526. current process.
  1527. lpName - Points to a null-terminated character string that
  1528. represents the name of the resource.
  1529. lpType - Points to a null-terminated character string that
  1530. represents the type name of the resource. For predefined
  1531. resource types, the lpType parameter should be one of the
  1532. following values:
  1533. RT_ACCELERATOR - Accelerator table
  1534. RT_BITMAP - Bitmap resource
  1535. RT_DIALOG - Dialog box
  1536. RT_FONT - Font resource
  1537. RT_FONTDIR - Font directory resource
  1538. RT_MENU - Menu resource
  1539. RT_RCDATA - User-defined resource (raw data)
  1540. Return Value:
  1541. The return value identifies the named resource. It is NULL if the
  1542. requested resource cannot be found.
  1543. --*/
  1544. {
  1545. NTSTATUS Status;
  1546. ULONG_PTR IdPath[ 3 ];
  1547. PVOID p;
  1548. IdPath[ 0 ] = 0;
  1549. IdPath[ 1 ] = 0;
  1550. try {
  1551. if ((IdPath[ 0 ] = BaseDllMapResourceIdA( lpType )) == -1) {
  1552. Status = STATUS_INVALID_PARAMETER;
  1553. } else
  1554. if ((IdPath[ 1 ] = BaseDllMapResourceIdA( lpName )) == -1) {
  1555. Status = STATUS_INVALID_PARAMETER;
  1556. } else {
  1557. IdPath[ 2 ] = 0;
  1558. p = NULL;
  1559. Status = LdrFindResource_U( BasepMapModuleHandle( hModule, TRUE ),
  1560. IdPath,
  1561. 3,
  1562. (PIMAGE_RESOURCE_DATA_ENTRY *)&p
  1563. );
  1564. }
  1565. } except (EXCEPTION_EXECUTE_HANDLER) {
  1566. Status = GetExceptionCode();
  1567. }
  1568. //
  1569. // Free any strings allocated by BaseDllMapResourceIdA
  1570. //
  1571. BaseDllFreeResourceId( IdPath[ 0 ] );
  1572. BaseDllFreeResourceId( IdPath[ 1 ] );
  1573. if (!NT_SUCCESS( Status )) {
  1574. BaseSetLastNTError( Status );
  1575. return( NULL );
  1576. } else {
  1577. return( (HRSRC)p );
  1578. }
  1579. }
  1580. HRSRC
  1581. FindResourceExA(
  1582. HMODULE hModule,
  1583. LPCSTR lpType,
  1584. LPCSTR lpName,
  1585. WORD wLanguage
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. This function determines the location of a resource in the specified
  1590. resource file. The lpType, lpName and wLanguage parameters define
  1591. the resource type, name and language respectively.
  1592. If the high-order word of the lpType or lpName parameter
  1593. is zero, the low-order word specifies the integer ID of the type, name
  1594. or language of the given resource. Otherwise, the parameters are pointers
  1595. to null-terminated character strings. If the first character of the
  1596. string is a pound sign (#), the remaining characters represent a
  1597. decimal number that specifies the integer ID of the resource's name
  1598. or type. For example, the string "#258" represents the integer ID
  1599. 258.
  1600. If the wLanguage parameter is zero, then the current language
  1601. associated with the calling thread will be used.
  1602. To reduce the amount of memory required for the resources used by an
  1603. application, applications should refer to their resources by integer
  1604. ID instead of by name.
  1605. An application must not call FindResource and the LoadResource
  1606. function to load cursor, icon, or string resources. Instead, it
  1607. must load these resources by calling the following functions:
  1608. - LoadCursor
  1609. - LoadIcon
  1610. - LoadString
  1611. An application can call FindResource and LoadResource to load other
  1612. predefined resource types. However, it is recommended that the
  1613. application load the corresponding resources by calling the
  1614. following functions:
  1615. - LoadAccelerators
  1616. - LoadBitmap
  1617. - LoadMenu
  1618. The above six API calls are documented with the Graphical User
  1619. Interface API specification.
  1620. Arguments:
  1621. hModule - Identifies the module whose executable file contains the
  1622. resource. A value of NULL references the module handle
  1623. associated with the image file that was used to create the
  1624. current process.
  1625. lpType - Points to a null-terminated character string that
  1626. represents the type name of the resource. For predefined
  1627. resource types, the lpType parameter should be one of the
  1628. following values:
  1629. RT_ACCELERATOR - Accelerator table
  1630. RT_BITMAP - Bitmap resource
  1631. RT_DIALOG - Dialog box
  1632. RT_FONT - Font resource
  1633. RT_FONTDIR - Font directory resource
  1634. RT_MENU - Menu resource
  1635. RT_RCDATA - User-defined resource (raw data)
  1636. lpName - Points to a null-terminated character string that
  1637. represents the name of the resource.
  1638. wLanguage - represents the language of the resource. If this parameter
  1639. is zero then the current language associated with the calling
  1640. thread is used.
  1641. Return Value:
  1642. The return value identifies the named resource. It is NULL if the
  1643. requested resource cannot be found.
  1644. --*/
  1645. {
  1646. NTSTATUS Status;
  1647. ULONG_PTR IdPath[ 3 ];
  1648. PVOID p;
  1649. IdPath[ 0 ] = 0;
  1650. IdPath[ 1 ] = 0;
  1651. try {
  1652. if ((IdPath[ 0 ] = BaseDllMapResourceIdA( lpType )) == -1) {
  1653. Status = STATUS_INVALID_PARAMETER;
  1654. } else if ((IdPath[ 1 ] = BaseDllMapResourceIdA( lpName )) == -1) {
  1655. Status = STATUS_INVALID_PARAMETER;
  1656. } else {
  1657. IdPath[ 2 ] = (ULONG_PTR)wLanguage;
  1658. p = NULL;
  1659. Status = LdrFindResource_U( BasepMapModuleHandle( hModule, TRUE ),
  1660. IdPath,
  1661. 3,
  1662. (PIMAGE_RESOURCE_DATA_ENTRY *)&p
  1663. );
  1664. }
  1665. } except (EXCEPTION_EXECUTE_HANDLER) {
  1666. Status = GetExceptionCode();
  1667. }
  1668. //
  1669. // Free any strings allocated by BaseDllMapResourceIdA
  1670. //
  1671. BaseDllFreeResourceId( IdPath[ 0 ] );
  1672. BaseDllFreeResourceId( IdPath[ 1 ] );
  1673. if (!NT_SUCCESS( Status )) {
  1674. BaseSetLastNTError( Status );
  1675. return( NULL );
  1676. } else {
  1677. return( (HRSRC)p );
  1678. }
  1679. }
  1680. HGLOBAL
  1681. LoadResource(
  1682. HMODULE hModule,
  1683. HRSRC hResInfo
  1684. )
  1685. /*++
  1686. Routine Description:
  1687. This function loads a resource identified by the hResInfo parameter
  1688. from the executable file associated with the module specified by the
  1689. hModule parameter. The function loads the resource into memory only
  1690. if it has not been previously loaded. Otherwise, it retrieves a
  1691. handle to the existing resource.
  1692. Arguments:
  1693. hModule - Identifies the module whose executable file contains the
  1694. resource. A value of NULL references the module handle
  1695. associated with the image file that was used to create the
  1696. current process.
  1697. hResInfo - Identifies the desired resource. This handle is assumed
  1698. to have been returned by the FindResource function.
  1699. Return Value:
  1700. The return value identifies the global memory block that contains
  1701. the data associated with the resource. It is NULL if no such
  1702. resource exists.
  1703. --*/
  1704. {
  1705. NTSTATUS Status;
  1706. PVOID p;
  1707. try {
  1708. Status = LdrAccessResource( BasepMapModuleHandle( hModule, TRUE ),
  1709. (PIMAGE_RESOURCE_DATA_ENTRY)hResInfo,
  1710. &p,
  1711. (PULONG)NULL
  1712. );
  1713. } except (EXCEPTION_EXECUTE_HANDLER) {
  1714. Status = GetExceptionCode();
  1715. }
  1716. if (!NT_SUCCESS( Status )) {
  1717. BaseSetLastNTError( Status );
  1718. return( NULL );
  1719. } else {
  1720. return( (HGLOBAL)p );
  1721. }
  1722. }
  1723. DWORD
  1724. SizeofResource(
  1725. HMODULE hModule,
  1726. HRSRC hResInfo
  1727. )
  1728. /*++
  1729. Routine Description:
  1730. This function supplies the size (in bytes) of the specified
  1731. resource.
  1732. The value returned may be larger than the actual resource due to
  1733. alignment. An application should not rely upon this value for the
  1734. exact size of a resource.
  1735. Arguments:
  1736. hModule - Identifies the module whose executable file contains the
  1737. resource. A value of NULL references the module handle
  1738. associated with the image file that was used to create the
  1739. current process.
  1740. hResInfo - Identifies the desired resource. This handle is assumed
  1741. to have been returned by the FindResource function.
  1742. Return Value:
  1743. The return value specifies the number of bytes in the resource. It
  1744. is zero if the resource cannot be found.
  1745. --*/
  1746. {
  1747. NTSTATUS Status;
  1748. ULONG cb;
  1749. try {
  1750. Status = LdrAccessResource( BasepMapModuleHandle( hModule, TRUE ),
  1751. (PIMAGE_RESOURCE_DATA_ENTRY)hResInfo,
  1752. (PVOID *)NULL,
  1753. &cb
  1754. );
  1755. } except (EXCEPTION_EXECUTE_HANDLER) {
  1756. Status = GetExceptionCode();
  1757. }
  1758. if (!NT_SUCCESS( Status )) {
  1759. BaseSetLastNTError( Status );
  1760. return( 0 );
  1761. } else {
  1762. return( (DWORD)cb );
  1763. }
  1764. }
  1765. #ifdef _X86_
  1766. BOOL
  1767. __stdcall
  1768. _ResourceCallEnumTypeRoutine(
  1769. ENUMRESTYPEPROCA EnumProc,
  1770. HMODULE hModule,
  1771. LPSTR lpType,
  1772. LONG lParam);
  1773. #else
  1774. #define _ResourceCallEnumTypeRoutine( EnumProc, hModule, lpType, lParam ) \
  1775. (*EnumProc)(hModule, lpType, lParam)
  1776. #endif
  1777. BOOL
  1778. WINAPI
  1779. EnumResourceTypesA(
  1780. HMODULE hModule,
  1781. ENUMRESTYPEPROCA lpEnumFunc,
  1782. LONG_PTR lParam
  1783. )
  1784. /*++
  1785. Routine Description:
  1786. This function enumerates all of the resource type names contained in
  1787. a module. It enumerates them by passing each type name to the callback
  1788. function pointed to by the lpEnumFunc parameter.
  1789. The EnumResourceTypes function continues to enumerate type names until
  1790. called function returns FALSE or the last type name in the module has
  1791. been enumerated.
  1792. Arguments:
  1793. hModule - Identifies the module whose executable file contains the
  1794. resource type names to be enumerated. A value of NULL
  1795. references the module handle associated with the image file that
  1796. was used to create the current process.
  1797. lpEnumFunc - Points to the callback function that will be called
  1798. for each enumerated resource type name.
  1799. lParam - Specifies the value to be passed to the callback function
  1800. for the application's use.
  1801. Return Value:
  1802. TRUE - All resource type names were enumerated.
  1803. FALSE/NULL - The enumeration was terminated before all resource type
  1804. names were enumerated.
  1805. Callback Function:
  1806. BOOL
  1807. EnumFunc(
  1808. HMODULE hModule,
  1809. LPSTR lpType,
  1810. LONG lParam
  1811. );
  1812. Routine Description:
  1813. EnumFunc is a placeholder for the application-supplied function name.
  1814. Arguments:
  1815. hModule - Identifies the module whose executable file contains the
  1816. resource type names to be enumerated. A value of NULL
  1817. references the module handle associated with the image file that
  1818. was used to create the current process.
  1819. lpType - Points to a null-terminated character string that
  1820. represents the type name of the resource. For predefined
  1821. resource types, the lpType parameter will be one of the
  1822. following values:
  1823. RT_ACCELERATOR - Accelerator table
  1824. RT_BITMAP - Bitmap resource
  1825. RT_DIALOG - Dialog box
  1826. RT_FONT - Font resource
  1827. RT_FONTDIR - Font directory resource
  1828. RT_MENU - Menu resource
  1829. RT_RCDATA - User-defined resource (raw data)
  1830. RT_STRING - String table
  1831. RT_MESSAGETABLE - Message table
  1832. RT_CURSOR - Hardware dependent cursor resource
  1833. RT_GROUP_CURSOR - Directory of cursor resources
  1834. RT_ICON - Hardware dependent cursor resource
  1835. RT_GROUP_ICON - Directory of icon resources
  1836. lParam - Specifies the 32-bit arugment of the EnumResourceTypes
  1837. function.
  1838. Return Value:
  1839. TRUE - Continue the enumeration.
  1840. FALSE/NULL - Stop enumerating resource type names.
  1841. --*/
  1842. {
  1843. BOOL Result;
  1844. NTSTATUS Status;
  1845. ULONG i;
  1846. HANDLE DllHandle;
  1847. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  1848. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  1849. PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
  1850. LPSTR lpType;
  1851. LPSTR Buffer;
  1852. ULONG BufferLength;
  1853. ULONG Length;
  1854. DllHandle = BasepMapModuleHandle( hModule, TRUE );
  1855. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  1856. RtlImageDirectoryEntryToData( (PVOID)DllHandle,
  1857. TRUE,
  1858. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  1859. &i
  1860. );
  1861. if (!TopResourceDirectory) {
  1862. BaseSetLastNTError( STATUS_RESOURCE_DATA_NOT_FOUND );
  1863. return FALSE;
  1864. }
  1865. Status = LdrFindResourceDirectory_U( (PVOID)DllHandle,
  1866. NULL,
  1867. 0,
  1868. &ResourceDirectory
  1869. );
  1870. if (!NT_SUCCESS( Status )) {
  1871. BaseSetLastNTError( Status );
  1872. return FALSE;
  1873. }
  1874. Buffer = NULL;
  1875. BufferLength = 0;
  1876. Result = TRUE;
  1877. try {
  1878. ResourceDirectoryEntry =
  1879. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  1880. for (i=0; i<ResourceDirectory->NumberOfNamedEntries; i++) {
  1881. ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
  1882. ((PCHAR)TopResourceDirectory + ResourceDirectoryEntry->NameOffset);
  1883. if ((ULONG)(ResourceNameString->Length+1) >= BufferLength) {
  1884. if (Buffer) {
  1885. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  1886. Buffer = NULL;
  1887. }
  1888. BufferLength = ((ResourceNameString->Length + 64) & ~63) * sizeof(WCHAR);
  1889. Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), BufferLength );
  1890. if (! Buffer) {
  1891. /* Status will be set by RtlAllocateHeap */
  1892. Result = FALSE;
  1893. break;
  1894. }
  1895. }
  1896. Status = RtlUnicodeToMultiByteN( Buffer,
  1897. BufferLength - 1,
  1898. &Length,
  1899. ResourceNameString->NameString,
  1900. ResourceNameString->Length * sizeof( WCHAR )
  1901. );
  1902. if (!NT_SUCCESS( Status )) {
  1903. BaseSetLastNTError( Status );
  1904. Result = FALSE;
  1905. break;
  1906. }
  1907. Buffer[ Length ] = '\0';
  1908. if (!_ResourceCallEnumTypeRoutine(lpEnumFunc, hModule, (LPSTR)Buffer, lParam )) {
  1909. Result = FALSE;
  1910. break;
  1911. }
  1912. ResourceDirectoryEntry++;
  1913. }
  1914. if (Result) {
  1915. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  1916. lpType = (LPSTR)ResourceDirectoryEntry->Id;
  1917. if (!_ResourceCallEnumTypeRoutine(lpEnumFunc, hModule, lpType, lParam )) {
  1918. Result = FALSE;
  1919. break;
  1920. }
  1921. ResourceDirectoryEntry++;
  1922. }
  1923. }
  1924. } except (EXCEPTION_EXECUTE_HANDLER) {
  1925. Status = GetExceptionCode();
  1926. }
  1927. if (Buffer) {
  1928. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  1929. }
  1930. if (!NT_SUCCESS( Status )) {
  1931. BaseSetLastNTError( Status );
  1932. return( FALSE );
  1933. } else {
  1934. return Result;
  1935. }
  1936. }
  1937. #ifdef _X86_
  1938. BOOL
  1939. __stdcall
  1940. _ResourceCallEnumNameRoutine(
  1941. ENUMRESNAMEPROCA EnumProc,
  1942. HMODULE hModule,
  1943. LPCSTR lpType,
  1944. LPSTR lpName,
  1945. LONG lParam);
  1946. #else
  1947. #define _ResourceCallEnumNameRoutine( EnumProc, hModule, lpType, lpName, lParam ) \
  1948. (*EnumProc)(hModule, lpType, lpName, lParam)
  1949. #endif
  1950. BOOL
  1951. WINAPI
  1952. EnumResourceNamesA(
  1953. HMODULE hModule,
  1954. LPCSTR lpType,
  1955. ENUMRESNAMEPROCA lpEnumFunc,
  1956. LONG_PTR lParam
  1957. )
  1958. /*++
  1959. Routine Description:
  1960. This function enumerates all of the resource names for a specific
  1961. resource type name contained in a module. It enumerates them by
  1962. passing each resource name and type name to the callback function
  1963. pointed to by the lpEnumFunc parameter.
  1964. The EnumResourceNames function continues to enumerate resource names
  1965. until called function returns FALSE or the last resource name for the
  1966. specified resource type name has been enumerated.
  1967. Arguments:
  1968. hModule - Identifies the module whose executable file contains the
  1969. resource names to be enumerated. A value of NULL references the
  1970. module handle associated with the image file that was used to
  1971. create the current process.
  1972. lpType - Points to a null-terminated character string that
  1973. represents the type name of the resources whose names are to be
  1974. enumerated. For predefined resource types, the lpType parameter
  1975. should be one of the following values:
  1976. RT_ACCELERATOR - Accelerator table
  1977. RT_BITMAP - Bitmap resource
  1978. RT_DIALOG - Dialog box
  1979. RT_FONT - Font resource
  1980. RT_FONTDIR - Font directory resource
  1981. RT_MENU - Menu resource
  1982. RT_RCDATA - User-defined resource (raw data)
  1983. lpEnumFunc - Points to the callback function that will be called
  1984. for each enumerated resource name.
  1985. lParam - Specifies the value to be passed to the callback function
  1986. for the application's use.
  1987. Return Value:
  1988. TRUE - All resource names were enumerated.
  1989. FALSE/NULL - The enumeration was terminated before all resource
  1990. names were enumerated.
  1991. Callback Function:
  1992. BOOL
  1993. EnumFunc(
  1994. HMODULE hModule,
  1995. LPSTR lpType,
  1996. LPSTR lpName,
  1997. LONG lParam
  1998. );
  1999. Routine Description:
  2000. EnumFunc is a placeholder for the application-supplied function name.
  2001. Arguments:
  2002. hModule - Identifies the module whose executable file contains
  2003. the resource names to be enumerated. A value of NULL
  2004. references the module handle associated with the image file
  2005. that was used to create the current process.
  2006. lpType - Points to a null-terminated character string that
  2007. represents the type name of the resource being enumerated.
  2008. For predefined resource types, the lpType parameter will be
  2009. one of the following values:
  2010. RT_ACCELERATOR - Accelerator table
  2011. RT_BITMAP - Bitmap resource
  2012. RT_DIALOG - Dialog box
  2013. RT_FONT - Font resource
  2014. RT_FONTDIR - Font directory resource
  2015. RT_MENU - Menu resource
  2016. RT_RCDATA - User-defined resource (raw data)
  2017. RT_STRING - String table
  2018. RT_MESSAGETABLE - Message table
  2019. RT_CURSOR - Hardware dependent cursor resource
  2020. RT_GROUP_CURSOR - Directory of cursor resources
  2021. RT_ICON - Hardware dependent cursor resource
  2022. RT_GROUP_ICON - Directory of icon resources
  2023. lpName - Points to a null-terminated character string that
  2024. represents the name of the resource being enumerated.
  2025. lParam - Specifies the 32-bit arugment of the EnumResourceNames
  2026. function.
  2027. Return Value:
  2028. TRUE - Continue the enumeration.
  2029. FALSE/NULL - Stop enumerating resource names.
  2030. --*/
  2031. {
  2032. BOOL Result;
  2033. NTSTATUS Status;
  2034. ULONG i;
  2035. ULONG_PTR IdPath[ 1 ];
  2036. HANDLE DllHandle;
  2037. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  2038. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  2039. PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
  2040. LPSTR lpName;
  2041. PCHAR Buffer;
  2042. ULONG BufferLength;
  2043. ULONG Length;
  2044. if ((IdPath[0] = BaseDllMapResourceIdA (lpType)) == -1) {
  2045. SetLastError (ERROR_INVALID_PARAMETER);
  2046. return FALSE;
  2047. }
  2048. DllHandle = BasepMapModuleHandle (hModule, TRUE);
  2049. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  2050. RtlImageDirectoryEntryToData ((PVOID)DllHandle,
  2051. TRUE,
  2052. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  2053. &i);
  2054. if (!TopResourceDirectory) {
  2055. Status = STATUS_RESOURCE_DATA_NOT_FOUND;
  2056. } else {
  2057. Status = LdrFindResourceDirectory_U ((PVOID)DllHandle,
  2058. IdPath,
  2059. 1,
  2060. &ResourceDirectory);
  2061. }
  2062. if (!NT_SUCCESS (Status)) {
  2063. BaseSetLastNTError (Status);
  2064. BaseDllFreeResourceId (IdPath[ 0 ]);
  2065. return FALSE;
  2066. }
  2067. Buffer = NULL;
  2068. BufferLength = 0;
  2069. Result = TRUE;
  2070. SetLastError( NO_ERROR );
  2071. try {
  2072. ResourceDirectoryEntry =
  2073. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  2074. for (i=0; i<ResourceDirectory->NumberOfNamedEntries; i++) {
  2075. ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
  2076. ((PCHAR)TopResourceDirectory + ResourceDirectoryEntry->NameOffset);
  2077. if ((ULONG)(ResourceNameString->Length+1) >= BufferLength) {
  2078. if (Buffer) {
  2079. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2080. Buffer = NULL;
  2081. }
  2082. BufferLength = (ResourceNameString->Length + 64) & ~63;
  2083. Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), BufferLength );
  2084. if (Buffer == NULL) {
  2085. BaseSetLastNTError (STATUS_NO_MEMORY);
  2086. Result = FALSE;
  2087. break;
  2088. }
  2089. }
  2090. Status = RtlUnicodeToMultiByteN (Buffer,
  2091. BufferLength - 1,
  2092. &Length,
  2093. ResourceNameString->NameString,
  2094. ResourceNameString->Length * sizeof(WCHAR));
  2095. if (!NT_SUCCESS (Status)) {
  2096. BaseSetLastNTError (Status);
  2097. Result = FALSE;
  2098. break;
  2099. }
  2100. Buffer[Length] = '\0';
  2101. if (!_ResourceCallEnumNameRoutine (lpEnumFunc, hModule, lpType, (LPSTR)Buffer, lParam)) {
  2102. Result = FALSE;
  2103. break;
  2104. }
  2105. ResourceDirectoryEntry++;
  2106. }
  2107. if (Result) {
  2108. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  2109. lpName = (LPSTR)ResourceDirectoryEntry->Id;
  2110. if (!_ResourceCallEnumNameRoutine (lpEnumFunc, hModule, lpType, lpName, lParam )) {
  2111. Result = FALSE;
  2112. break;
  2113. }
  2114. ResourceDirectoryEntry++;
  2115. }
  2116. }
  2117. } except (EXCEPTION_EXECUTE_HANDLER) {
  2118. BaseSetLastNTError( GetExceptionCode() );
  2119. Result = FALSE;
  2120. }
  2121. if (Buffer) {
  2122. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2123. }
  2124. //
  2125. // Free any string allocated by BaseDllMapResourceIdA
  2126. //
  2127. BaseDllFreeResourceId( IdPath[ 0 ] );
  2128. return Result;
  2129. }
  2130. #ifdef _X86_
  2131. BOOL
  2132. __stdcall
  2133. _ResourceCallEnumLangRoutine(
  2134. ENUMRESLANGPROCA EnumProc,
  2135. HMODULE hModule,
  2136. LPCSTR lpType,
  2137. LPCSTR lpName,
  2138. WORD wLanguage,
  2139. LONG lParam);
  2140. #else
  2141. #define _ResourceCallEnumLangRoutine( EnumProc, hModule, lpType, lpName, wLanguage, lParam ) \
  2142. (*EnumProc)(hModule, lpType, lpName, wLanguage, lParam)
  2143. #endif
  2144. BOOL
  2145. WINAPI
  2146. EnumResourceLanguagesA(
  2147. HMODULE hModule,
  2148. LPCSTR lpType,
  2149. LPCSTR lpName,
  2150. ENUMRESLANGPROCA lpEnumFunc,
  2151. LONG_PTR lParam
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. This function enumerates all of the language specific resources
  2156. contained in a module for a given resource type and name ID. It
  2157. enumerates them by passing each resource type, name and language to
  2158. the callback function pointed to by the lpEnumFunc parameter.
  2159. The EnumResourceLanguares function continues to enumerate resources
  2160. until called function returns FALSE or the last resource for
  2161. the specified language has been enumerated.
  2162. Arguments:
  2163. hModule - Identifies the module whose executable file contains the
  2164. resource names to be enumerated. A value of NULL references the
  2165. module handle associated with the image file that was used to
  2166. create the current process.
  2167. lpType - Points to a null-terminated character string that
  2168. represents the type name of the resources whose names are to be
  2169. enumerated. For predefined resource types, the lpType parameter
  2170. should be one of the following values:
  2171. RT_ACCELERATOR - Accelerator table
  2172. RT_BITMAP - Bitmap resource
  2173. RT_DIALOG - Dialog box
  2174. RT_FONT - Font resource
  2175. RT_FONTDIR - Font directory resource
  2176. RT_MENU - Menu resource
  2177. RT_RCDATA - User-defined resource (raw data)
  2178. lpName - Points to a null-terminated character string that
  2179. represents the name of the resource being enumerated.
  2180. lpEnumFunc - Points to the callback function that will be called
  2181. for each enumerated resource name.
  2182. lParam - Specifies the value to be passed to the callback function
  2183. for the application's use.
  2184. Return Value:
  2185. TRUE - All resource names were enumerated.
  2186. FALSE/NULL - The enumeration was terminated before all resource
  2187. names were enumerated.
  2188. Callback Function:
  2189. BOOL
  2190. EnumFunc(
  2191. HMODULE hModule,
  2192. LPSTR lpType,
  2193. LPSTR lpName,
  2194. WORD wLanguage,
  2195. LONG lParam
  2196. );
  2197. Routine Description:
  2198. EnumFunc is a placeholder for the application-supplied function name.
  2199. Arguments:
  2200. hModule - Identifies the module whose executable file contains
  2201. the resource names to be enumerated. A value of NULL
  2202. references the module handle associated with the image file
  2203. that was used to create the current process.
  2204. lpType - Points to a null-terminated character string that
  2205. represents the type name of the resource being enumerated.
  2206. For predefined resource types, the lpType parameter will be
  2207. one of the following values:
  2208. RT_ACCELERATOR - Accelerator table
  2209. RT_BITMAP - Bitmap resource
  2210. RT_DIALOG - Dialog box
  2211. RT_FONT - Font resource
  2212. RT_FONTDIR - Font directory resource
  2213. RT_MENU - Menu resource
  2214. RT_RCDATA - User-defined resource (raw data)
  2215. RT_STRING - String table
  2216. RT_MESSAGETABLE - Message table
  2217. RT_CURSOR - Hardware dependent cursor resource
  2218. RT_GROUP_CURSOR - Directory of cursor resources
  2219. RT_ICON - Hardware dependent cursor resource
  2220. RT_GROUP_ICON - Directory of icon resources
  2221. lpName - Points to a null-terminated character string that
  2222. represents the name of the resource being enumerated.
  2223. wLanguage - represents the language of the resource.
  2224. lParam - Specifies the 32-bit arugment of the EnumResourceNames
  2225. function.
  2226. Return Value:
  2227. TRUE - Continue the enumeration.
  2228. FALSE/NULL - Stop enumerating resource names.
  2229. --*/
  2230. {
  2231. BOOL Result;
  2232. NTSTATUS Status;
  2233. ULONG i;
  2234. ULONG_PTR IdPath[ 2 ];
  2235. HANDLE DllHandle;
  2236. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  2237. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  2238. USHORT wLanguage;
  2239. IdPath[ 1 ] = 0;
  2240. if ((IdPath[ 0 ] = BaseDllMapResourceIdA( lpType )) == -1) {
  2241. Status = STATUS_INVALID_PARAMETER;
  2242. } else
  2243. if ((IdPath[ 1 ] = BaseDllMapResourceIdA( lpName )) == -1) {
  2244. Status = STATUS_INVALID_PARAMETER;
  2245. } else {
  2246. DllHandle = BasepMapModuleHandle( hModule, TRUE );
  2247. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  2248. RtlImageDirectoryEntryToData( (PVOID)DllHandle,
  2249. TRUE,
  2250. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  2251. &i
  2252. );
  2253. if (!TopResourceDirectory) {
  2254. Status = STATUS_RESOURCE_DATA_NOT_FOUND;
  2255. } else {
  2256. Status = LdrFindResourceDirectory_U( (PVOID)DllHandle,
  2257. IdPath,
  2258. 2,
  2259. &ResourceDirectory
  2260. );
  2261. }
  2262. }
  2263. if (!NT_SUCCESS( Status )) {
  2264. BaseDllFreeResourceId( IdPath[ 0 ] );
  2265. BaseDllFreeResourceId( IdPath[ 1 ] );
  2266. BaseSetLastNTError( Status );
  2267. return FALSE;
  2268. }
  2269. Result = TRUE;
  2270. SetLastError( NO_ERROR );
  2271. try {
  2272. ResourceDirectoryEntry =
  2273. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  2274. if (ResourceDirectory->NumberOfNamedEntries != 0) {
  2275. BaseSetLastNTError( STATUS_INVALID_IMAGE_FORMAT );
  2276. Result = FALSE;
  2277. } else {
  2278. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  2279. wLanguage = ResourceDirectoryEntry->Id;
  2280. if (!_ResourceCallEnumLangRoutine(lpEnumFunc, hModule, lpType, lpName, wLanguage, lParam )) {
  2281. Result = FALSE;
  2282. break;
  2283. }
  2284. ResourceDirectoryEntry++;
  2285. }
  2286. }
  2287. } except (EXCEPTION_EXECUTE_HANDLER) {
  2288. BaseSetLastNTError( GetExceptionCode() );
  2289. Result = FALSE;
  2290. }
  2291. //
  2292. // Free any strings allocated by BaseDllMapResourceIdA
  2293. //
  2294. BaseDllFreeResourceId( IdPath[ 0 ] );
  2295. BaseDllFreeResourceId( IdPath[ 1 ] );
  2296. return Result;
  2297. }
  2298. BOOL
  2299. WINAPI
  2300. FreeResource(
  2301. HGLOBAL hResData
  2302. )
  2303. {
  2304. //
  2305. // Can't fail so return Win 3.x success code.
  2306. //
  2307. return FALSE;
  2308. }
  2309. LPVOID
  2310. WINAPI
  2311. LockResource(
  2312. HGLOBAL hResData
  2313. )
  2314. {
  2315. return( (LPVOID)hResData );
  2316. }
  2317. HRSRC
  2318. FindResourceW(
  2319. HMODULE hModule,
  2320. LPCWSTR lpName,
  2321. LPCWSTR lpType
  2322. )
  2323. /*++
  2324. Routine Description:
  2325. This function determines the location of a resource in the specified
  2326. resource file. The lpName and lpType parameters define the resource
  2327. name and type, respectively.
  2328. If the high-order word of the lpName or lpType parameter is zero,
  2329. the low-order word specifies the integer ID of the name or type of
  2330. the given resource. Otherwise, the parameters are pointers to
  2331. null-terminated character strings. If the first character of the
  2332. string is a pound sign (#), the remaining characters represent a
  2333. decimal number that specifies the integer ID of the resource's name
  2334. or type. For example, the string "#258" represents the integer ID
  2335. 258.
  2336. To reduce the amount of memory required for the resources used by an
  2337. application, applications should refer to their resources by integer
  2338. ID instead of by name.
  2339. An application must not call FindResource and the LoadResource
  2340. function to load cursor, icon, or string resources. Instead, it
  2341. must load these resources by calling the following functions:
  2342. - LoadCursor
  2343. - LoadIcon
  2344. - LoadString
  2345. An application can call FindResource and LoadResource to load other
  2346. predefined resource types. However, it is recommended that the
  2347. application load the corresponding resources by calling the
  2348. following functions:
  2349. - LoadAccelerators
  2350. - LoadBitmap
  2351. - LoadMenu
  2352. The above six API calls are documented with the Graphical User
  2353. Interface API specification.
  2354. Arguments:
  2355. hModule - Identifies the module whose executable file contains the
  2356. resource. A value of NULL references the module handle
  2357. associated with the image file that was used to create the
  2358. current process.
  2359. lpName - Points to a null-terminated character string that
  2360. represents the name of the resource.
  2361. lpType - Points to a null-terminated character string that
  2362. represents the type name of the resource. For predefined
  2363. resource types, the lpType parameter should be one of the
  2364. following values:
  2365. RT_ACCELERATOR - Accelerator table
  2366. RT_BITMAP - Bitmap resource
  2367. RT_DIALOG - Dialog box
  2368. RT_FONT - Font resource
  2369. RT_FONTDIR - Font directory resource
  2370. RT_MENU - Menu resource
  2371. RT_RCDATA - User-defined resource (raw data)
  2372. Return Value:
  2373. The return value identifies the named resource. It is NULL if the
  2374. requested resource cannot be found.
  2375. --*/
  2376. {
  2377. NTSTATUS Status;
  2378. ULONG_PTR IdPath[ 3 ];
  2379. PVOID p;
  2380. IdPath[ 0 ] = 0;
  2381. IdPath[ 1 ] = 0;
  2382. try {
  2383. if ((IdPath[ 0 ] = BaseDllMapResourceIdW( lpType )) == -1) {
  2384. Status = STATUS_INVALID_PARAMETER;
  2385. } else if ((IdPath[ 1 ] = BaseDllMapResourceIdW( lpName )) == -1) {
  2386. Status = STATUS_INVALID_PARAMETER;
  2387. } else {
  2388. IdPath[ 2 ] = 0;
  2389. p = NULL;
  2390. Status = LdrFindResource_U( BasepMapModuleHandle( hModule, TRUE ),
  2391. IdPath,
  2392. 3,
  2393. (PIMAGE_RESOURCE_DATA_ENTRY *)&p
  2394. );
  2395. }
  2396. } except (EXCEPTION_EXECUTE_HANDLER) {
  2397. Status = GetExceptionCode();
  2398. }
  2399. //
  2400. // Free any strings allocated by BaseDllMapResourceIdW
  2401. //
  2402. BaseDllFreeResourceId( IdPath[ 0 ] );
  2403. BaseDllFreeResourceId( IdPath[ 1 ] );
  2404. if (!NT_SUCCESS( Status )) {
  2405. BaseSetLastNTError( Status );
  2406. return( NULL );
  2407. } else {
  2408. return( (HRSRC)p );
  2409. }
  2410. }
  2411. HRSRC
  2412. FindResourceExW(
  2413. HMODULE hModule,
  2414. LPCWSTR lpType,
  2415. LPCWSTR lpName,
  2416. WORD wLanguage
  2417. )
  2418. /*++
  2419. Routine Description:
  2420. This function determines the location of a resource in the specified
  2421. resource file. The lpType, lpName and wLanguage parameters define
  2422. the resource type, name and language respectively.
  2423. If the high-order word of the lpType or lpName parameter
  2424. is zero, the low-order word specifies the integer ID of the type, name
  2425. or language of the given resource. Otherwise, the parameters are pointers
  2426. to null-terminated character strings. If the first character of the
  2427. string is a pound sign (#), the remaining characters represent a
  2428. decimal number that specifies the integer ID of the resource's name
  2429. or type. For example, the string "#258" represents the integer ID
  2430. 258.
  2431. If the wLanguage parameter is zero, then the current language
  2432. associated with the calling thread will be used.
  2433. To reduce the amount of memory required for the resources used by an
  2434. application, applications should refer to their resources by integer
  2435. ID instead of by name.
  2436. An application must not call FindResource and the LoadResource
  2437. function to load cursor, icon, or string resources. Instead, it
  2438. must load these resources by calling the following functions:
  2439. - LoadCursor
  2440. - LoadIcon
  2441. - LoadString
  2442. An application can call FindResource and LoadResource to load other
  2443. predefined resource types. However, it is recommended that the
  2444. application load the corresponding resources by calling the
  2445. following functions:
  2446. - LoadAccelerators
  2447. - LoadBitmap
  2448. - LoadMenu
  2449. The above six API calls are documented with the Graphical User
  2450. Interface API specification.
  2451. Arguments:
  2452. hModule - Identifies the module whose executable file contains the
  2453. resource. A value of NULL references the module handle
  2454. associated with the image file that was used to create the
  2455. current process.
  2456. lpType - Points to a null-terminated character string that
  2457. represents the type name of the resource. For predefined
  2458. resource types, the lpType parameter should be one of the
  2459. following values:
  2460. RT_ACCELERATOR - Accelerator table
  2461. RT_BITMAP - Bitmap resource
  2462. RT_DIALOG - Dialog box
  2463. RT_FONT - Font resource
  2464. RT_FONTDIR - Font directory resource
  2465. RT_MENU - Menu resource
  2466. RT_RCDATA - User-defined resource (raw data)
  2467. lpName - Points to a null-terminated character string that
  2468. represents the name of the resource.
  2469. wLanguage - represents the language of the resource. If this parameter
  2470. is zero then the current language associated with the calling
  2471. thread is used.
  2472. Return Value:
  2473. The return value identifies the named resource. It is NULL if the
  2474. requested resource cannot be found.
  2475. --*/
  2476. {
  2477. NTSTATUS Status;
  2478. ULONG_PTR IdPath[ 3 ];
  2479. PVOID p;
  2480. IdPath[ 0 ] = 0;
  2481. IdPath[ 1 ] = 0;
  2482. try {
  2483. if ((IdPath[ 0 ] = BaseDllMapResourceIdW( lpType )) == -1) {
  2484. Status = STATUS_INVALID_PARAMETER;
  2485. } else if ((IdPath[ 1 ] = BaseDllMapResourceIdW( lpName )) == -1) {
  2486. Status = STATUS_INVALID_PARAMETER;
  2487. } else {
  2488. IdPath[ 2 ] = (ULONG_PTR)wLanguage;
  2489. p = NULL;
  2490. Status = LdrFindResource_U( BasepMapModuleHandle( hModule, TRUE ),
  2491. IdPath,
  2492. 3,
  2493. (PIMAGE_RESOURCE_DATA_ENTRY *)&p
  2494. );
  2495. }
  2496. } except (EXCEPTION_EXECUTE_HANDLER) {
  2497. Status = GetExceptionCode();
  2498. }
  2499. //
  2500. // Free any strings allocated by BaseDllMapResourceIdW
  2501. //
  2502. BaseDllFreeResourceId( IdPath[ 0 ] );
  2503. BaseDllFreeResourceId( IdPath[ 1 ] );
  2504. if (!NT_SUCCESS( Status )) {
  2505. BaseSetLastNTError( Status );
  2506. return( NULL );
  2507. } else {
  2508. return( (HRSRC)p );
  2509. }
  2510. }
  2511. BOOL
  2512. APIENTRY
  2513. EnumResourceTypesW(
  2514. HMODULE hModule,
  2515. ENUMRESTYPEPROCW lpEnumFunc,
  2516. LONG_PTR lParam
  2517. )
  2518. /*++
  2519. Routine Description:
  2520. This function enumerates all of the resource type names contained in
  2521. a module. It enumerates them by passing each type name to the callback
  2522. function pointed to by the lpEnumFunc parameter.
  2523. The EnumResourceTypes function continues to enumerate type names until
  2524. called function returns FALSE or the last type name in the module has
  2525. been enumerated.
  2526. Arguments:
  2527. hModule - Identifies the module whose executable file contains the
  2528. resource type names to be enumerated. A value of NULL
  2529. references the module handle associated with the image file that
  2530. was used to create the current process.
  2531. lpEnumFunc - Points to the callback function that will be called
  2532. for each enumerated resource type name.
  2533. lParam - Specifies the value to be passed to the callback function
  2534. for the application's use.
  2535. Return Value:
  2536. TRUE - All resource type names were enumerated.
  2537. FALSE/NULL - The enumeration was terminated before all resource type
  2538. names were enumerated.
  2539. Callback Function:
  2540. BOOL
  2541. EnumFunc(
  2542. HMODULE hModule,
  2543. LPWSTR lpType,
  2544. LONG lParam
  2545. );
  2546. Routine Description:
  2547. EnumFunc is a placeholder for the application-supplied function name.
  2548. Arguments:
  2549. hModule - Identifies the module whose executable file contains the
  2550. resource type names to be enumerated. A value of NULL
  2551. references the module handle associated with the image file that
  2552. was used to create the current process.
  2553. lpType - Points to a null-terminated character string that
  2554. represents the type name of the resource. For predefined
  2555. resource types, the lpType parameter will be one of the
  2556. following values:
  2557. RT_ACCELERATOR - Accelerator table
  2558. RT_BITMAP - Bitmap resource
  2559. RT_DIALOG - Dialog box
  2560. RT_FONT - Font resource
  2561. RT_FONTDIR - Font directory resource
  2562. RT_MENU - Menu resource
  2563. RT_RCDATA - User-defined resource (raw data)
  2564. RT_STRING - String table
  2565. RT_MESSAGETABLE - Message table
  2566. RT_CURSOR - Hardware dependent cursor resource
  2567. RT_GROUP_CURSOR - Directory of cursor resources
  2568. RT_ICON - Hardware dependent cursor resource
  2569. RT_GROUP_ICON - Directory of icon resources
  2570. lParam - Specifies the 32-bit arugment of the EnumResourceTypes
  2571. function.
  2572. Return Value:
  2573. TRUE - Continue the enumeration.
  2574. FALSE/NULL - Stop enumerating resource type names.
  2575. --*/
  2576. {
  2577. BOOL Result;
  2578. NTSTATUS Status;
  2579. ULONG i;
  2580. HANDLE DllHandle;
  2581. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  2582. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  2583. PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
  2584. LPWSTR lpType;
  2585. LPWSTR Buffer;
  2586. ULONG BufferLength;
  2587. DllHandle = BasepMapModuleHandle( hModule, TRUE );
  2588. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  2589. RtlImageDirectoryEntryToData( (PVOID)DllHandle,
  2590. TRUE,
  2591. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  2592. &i
  2593. );
  2594. if (!TopResourceDirectory) {
  2595. BaseSetLastNTError( STATUS_RESOURCE_DATA_NOT_FOUND );
  2596. return FALSE;
  2597. }
  2598. Status = LdrFindResourceDirectory_U( (PVOID)DllHandle,
  2599. NULL,
  2600. 0,
  2601. &ResourceDirectory
  2602. );
  2603. if (!NT_SUCCESS( Status )) {
  2604. BaseSetLastNTError( Status );
  2605. return FALSE;
  2606. }
  2607. Buffer = NULL;
  2608. BufferLength = 0;
  2609. Result = TRUE;
  2610. try {
  2611. ResourceDirectoryEntry =
  2612. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  2613. for (i=0; i<ResourceDirectory->NumberOfNamedEntries; i++) {
  2614. ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
  2615. ((PCHAR)TopResourceDirectory + ResourceDirectoryEntry->NameOffset);
  2616. if ((ULONG)((ResourceNameString->Length+1) * sizeof( WCHAR )) >= BufferLength) {
  2617. if (Buffer) {
  2618. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2619. Buffer = NULL;
  2620. }
  2621. BufferLength = ((ResourceNameString->Length * sizeof( WCHAR )) + 64) & ~63;
  2622. Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), BufferLength );
  2623. if (Buffer == NULL) {
  2624. BaseSetLastNTError( STATUS_NO_MEMORY );
  2625. Result = FALSE;
  2626. break;
  2627. }
  2628. }
  2629. RtlCopyMemory( Buffer,
  2630. ResourceNameString->NameString,
  2631. ResourceNameString->Length * sizeof( WCHAR )
  2632. );
  2633. Buffer[ ResourceNameString->Length ] = UNICODE_NULL;
  2634. if (!_ResourceCallEnumTypeRoutine((ENUMRESTYPEPROCA)lpEnumFunc, hModule, (LPSTR)Buffer, lParam )) {
  2635. Result = FALSE;
  2636. break;
  2637. }
  2638. ResourceDirectoryEntry++;
  2639. }
  2640. if (Result) {
  2641. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  2642. lpType = (LPWSTR)ResourceDirectoryEntry->Id;
  2643. if (!_ResourceCallEnumTypeRoutine((ENUMRESTYPEPROCA)lpEnumFunc, hModule, (LPSTR)lpType, lParam )) {
  2644. Result = FALSE;
  2645. break;
  2646. }
  2647. ResourceDirectoryEntry++;
  2648. }
  2649. }
  2650. } except (EXCEPTION_EXECUTE_HANDLER) {
  2651. Status = GetExceptionCode();
  2652. }
  2653. if (Buffer) {
  2654. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2655. }
  2656. if (!NT_SUCCESS( Status )) {
  2657. BaseSetLastNTError( Status );
  2658. return( FALSE );
  2659. } else {
  2660. return Result;
  2661. }
  2662. }
  2663. BOOL
  2664. APIENTRY
  2665. EnumResourceNamesW(
  2666. HMODULE hModule,
  2667. LPCWSTR lpType,
  2668. ENUMRESNAMEPROCW lpEnumFunc,
  2669. LONG_PTR lParam
  2670. )
  2671. /*++
  2672. Routine Description:
  2673. This function enumerates all of the resource names for a specific
  2674. resource type name contained in a module. It enumerates them by
  2675. passing each resource name and type name to the callback function
  2676. pointed to by the lpEnumFunc parameter.
  2677. The EnumResourceNames function continues to enumerate resource names
  2678. until called function returns FALSE or the last resource name for the
  2679. specified resource type name has been enumerated.
  2680. Arguments:
  2681. hModule - Identifies the module whose executable file contains the
  2682. resource names to be enumerated. A value of NULL references the
  2683. module handle associated with the image file that was used to
  2684. create the current process.
  2685. lpType - Points to a null-terminated character string that
  2686. represents the type name of the resources whose names are to be
  2687. enumerated. For predefined resource types, the lpType parameter
  2688. should be one of the following values:
  2689. RT_ACCELERATOR - Accelerator table
  2690. RT_BITMAP - Bitmap resource
  2691. RT_DIALOG - Dialog box
  2692. RT_FONT - Font resource
  2693. RT_FONTDIR - Font directory resource
  2694. RT_MENU - Menu resource
  2695. RT_RCDATA - User-defined resource (raw data)
  2696. lpEnumFunc - Points to the callback function that will be called
  2697. for each enumerated resource name.
  2698. lParam - Specifies the value to be passed to the callback function
  2699. for the application's use.
  2700. Return Value:
  2701. TRUE - All resource names were enumerated.
  2702. FALSE/NULL - The enumeration was terminated before all resource
  2703. names were enumerated.
  2704. Callback Function:
  2705. BOOL
  2706. EnumFunc(
  2707. HMODULE hModule,
  2708. LPWSTR lpType,
  2709. LPWSTR lpName,
  2710. LONG lParam
  2711. );
  2712. Routine Description:
  2713. EnumFunc is a placeholder for the application-supplied function name.
  2714. Arguments:
  2715. hModule - Identifies the module whose executable file contains
  2716. the resource names to be enumerated. A value of NULL
  2717. references the module handle associated with the image file
  2718. that was used to create the current process.
  2719. lpType - Points to a null-terminated character string that
  2720. represents the type name of the resource being enumerated.
  2721. For predefined resource types, the lpType parameter will be
  2722. one of the following values:
  2723. RT_ACCELERATOR - Accelerator table
  2724. RT_BITMAP - Bitmap resource
  2725. RT_DIALOG - Dialog box
  2726. RT_FONT - Font resource
  2727. RT_FONTDIR - Font directory resource
  2728. RT_MENU - Menu resource
  2729. RT_RCDATA - User-defined resource (raw data)
  2730. RT_STRING - String table
  2731. RT_MESSAGETABLE - Message table
  2732. RT_CURSOR - Hardware dependent cursor resource
  2733. RT_GROUP_CURSOR - Directory of cursor resources
  2734. RT_ICON - Hardware dependent cursor resource
  2735. RT_GROUP_ICON - Directory of icon resources
  2736. lpName - Points to a null-terminated character string that
  2737. represents the name of the resource being enumerated.
  2738. lParam - Specifies the 32-bit arugment of the EnumResourceNames
  2739. function.
  2740. Return Value:
  2741. TRUE - Continue the enumeration.
  2742. FALSE/NULL - Stop enumerating resource names.
  2743. --*/
  2744. {
  2745. BOOL Result;
  2746. NTSTATUS Status;
  2747. ULONG i;
  2748. ULONG_PTR IdPath[ 1 ];
  2749. HANDLE DllHandle;
  2750. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  2751. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  2752. PIMAGE_RESOURCE_DIR_STRING_U ResourceNameString;
  2753. LPWSTR lpName;
  2754. LPWSTR Buffer;
  2755. ULONG BufferLength;
  2756. if ((IdPath[ 0 ] = BaseDllMapResourceIdW( lpType )) == -1) {
  2757. Status = STATUS_INVALID_PARAMETER;
  2758. } else {
  2759. DllHandle = BasepMapModuleHandle( hModule, TRUE );
  2760. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  2761. RtlImageDirectoryEntryToData( (PVOID)DllHandle,
  2762. TRUE,
  2763. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  2764. &i
  2765. );
  2766. if (!TopResourceDirectory) {
  2767. Status = STATUS_RESOURCE_DATA_NOT_FOUND;
  2768. } else {
  2769. Status = LdrFindResourceDirectory_U( (PVOID)DllHandle,
  2770. IdPath,
  2771. 1,
  2772. &ResourceDirectory
  2773. );
  2774. }
  2775. }
  2776. if (!NT_SUCCESS( Status )) {
  2777. BaseDllFreeResourceId( IdPath[ 0 ] );
  2778. BaseSetLastNTError( Status );
  2779. return FALSE;
  2780. }
  2781. Buffer = NULL;
  2782. BufferLength = 0;
  2783. Result = TRUE;
  2784. try {
  2785. ResourceDirectoryEntry =
  2786. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  2787. for (i=0; i<ResourceDirectory->NumberOfNamedEntries; i++) {
  2788. ResourceNameString = (PIMAGE_RESOURCE_DIR_STRING_U)
  2789. ((PCHAR)TopResourceDirectory + ResourceDirectoryEntry->NameOffset);
  2790. if ((ULONG)((ResourceNameString->Length+1) * sizeof( WCHAR )) >= BufferLength) {
  2791. if (Buffer) {
  2792. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2793. Buffer = NULL;
  2794. }
  2795. BufferLength = ((ResourceNameString->Length * sizeof( WCHAR )) + 64) & ~63;
  2796. Buffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), BufferLength );
  2797. if (Buffer == NULL) {
  2798. BaseSetLastNTError( STATUS_NO_MEMORY );
  2799. Result = FALSE;
  2800. break;
  2801. }
  2802. }
  2803. RtlCopyMemory( Buffer,
  2804. ResourceNameString->NameString,
  2805. ResourceNameString->Length * sizeof( WCHAR )
  2806. );
  2807. Buffer[ ResourceNameString->Length ] = UNICODE_NULL;
  2808. if (!_ResourceCallEnumNameRoutine((ENUMRESNAMEPROCA)lpEnumFunc, hModule, (LPSTR)lpType, (LPSTR)Buffer, lParam )) {
  2809. Result = FALSE;
  2810. break;
  2811. }
  2812. ResourceDirectoryEntry++;
  2813. }
  2814. if (Result) {
  2815. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  2816. lpName = (LPWSTR)ResourceDirectoryEntry->Id;
  2817. if (!_ResourceCallEnumNameRoutine((ENUMRESNAMEPROCA)lpEnumFunc, hModule, (LPSTR)lpType, (LPSTR)lpName, lParam )) {
  2818. Result = FALSE;
  2819. break;
  2820. }
  2821. ResourceDirectoryEntry++;
  2822. }
  2823. }
  2824. } except (EXCEPTION_EXECUTE_HANDLER) {
  2825. BaseSetLastNTError( GetExceptionCode() );
  2826. Result = FALSE;
  2827. }
  2828. if (Buffer) {
  2829. RtlFreeHeap( RtlProcessHeap(), 0, Buffer );
  2830. }
  2831. //
  2832. // Free any string allocated by BaseDllMapResourceIdW
  2833. //
  2834. BaseDllFreeResourceId( IdPath[ 0 ] );
  2835. return Result;
  2836. }
  2837. BOOL
  2838. APIENTRY
  2839. EnumResourceLanguagesW(
  2840. HMODULE hModule,
  2841. LPCWSTR lpType,
  2842. LPCWSTR lpName,
  2843. ENUMRESLANGPROCW lpEnumFunc,
  2844. LONG_PTR lParam
  2845. )
  2846. /*++
  2847. Routine Description:
  2848. This function enumerates all of the language specific resources
  2849. contained in a module for a given resource type and name ID. It
  2850. enumerates them by passing each resource type, name and language to
  2851. the callback function pointed to by the lpEnumFunc parameter.
  2852. The EnumResourceLanguares function continues to enumerate resources
  2853. until called function returns FALSE or the last resource for
  2854. the specified language has been enumerated.
  2855. Arguments:
  2856. hModule - Identifies the module whose executable file contains the
  2857. resource names to be enumerated. A value of NULL references the
  2858. module handle associated with the image file that was used to
  2859. create the current process.
  2860. lpType - Points to a null-terminated character string that
  2861. represents the type name of the resources whose names are to be
  2862. enumerated. For predefined resource types, the lpType parameter
  2863. should be one of the following values:
  2864. RT_ACCELERATOR - Accelerator table
  2865. RT_BITMAP - Bitmap resource
  2866. RT_DIALOG - Dialog box
  2867. RT_FONT - Font resource
  2868. RT_FONTDIR - Font directory resource
  2869. RT_MENU - Menu resource
  2870. RT_RCDATA - User-defined resource (raw data)
  2871. lpName - Points to a null-terminated character string that
  2872. represents the name of the resource being enumerated.
  2873. lpEnumFunc - Points to the callback function that will be called
  2874. for each enumerated resource name.
  2875. lParam - Specifies the value to be passed to the callback function
  2876. for the application's use.
  2877. Return Value:
  2878. TRUE - All resource names were enumerated.
  2879. FALSE/NULL - The enumeration was terminated before all resource
  2880. names were enumerated.
  2881. Callback Function:
  2882. BOOL
  2883. EnumFunc(
  2884. HMODULE hModule,
  2885. LPWSTR lpType,
  2886. LPWSTR lpName,
  2887. WORD wLanguage,
  2888. LONG lParam
  2889. );
  2890. Routine Description:
  2891. EnumFunc is a placeholder for the application-supplied function name.
  2892. Arguments:
  2893. hModule - Identifies the module whose executable file contains
  2894. the resource names to be enumerated. A value of NULL
  2895. references the module handle associated with the image file
  2896. that was used to create the current process.
  2897. lpType - Points to a null-terminated character string that
  2898. represents the type name of the resource being enumerated.
  2899. For predefined resource types, the lpType parameter will be
  2900. one of the following values:
  2901. RT_ACCELERATOR - Accelerator table
  2902. RT_BITMAP - Bitmap resource
  2903. RT_DIALOG - Dialog box
  2904. RT_FONT - Font resource
  2905. RT_FONTDIR - Font directory resource
  2906. RT_MENU - Menu resource
  2907. RT_RCDATA - User-defined resource (raw data)
  2908. RT_STRING - String table
  2909. RT_MESSAGETABLE - Message table
  2910. RT_CURSOR - Hardware dependent cursor resource
  2911. RT_GROUP_CURSOR - Directory of cursor resources
  2912. RT_ICON - Hardware dependent cursor resource
  2913. RT_GROUP_ICON - Directory of icon resources
  2914. lpName - Points to a null-terminated character string that
  2915. represents the name of the resource being enumerated.
  2916. wLanguage - represents the language of the resource.
  2917. lParam - Specifies the 32-bit arugment of the EnumResourceNames
  2918. function.
  2919. Return Value:
  2920. TRUE - Continue the enumeration.
  2921. FALSE/NULL - Stop enumerating resource names.
  2922. --*/
  2923. {
  2924. BOOL Result;
  2925. NTSTATUS Status;
  2926. ULONG i;
  2927. ULONG_PTR IdPath[ 2 ];
  2928. HANDLE DllHandle;
  2929. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory, TopResourceDirectory;
  2930. PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceDirectoryEntry;
  2931. USHORT wLanguage;
  2932. IdPath[ 1 ] = 0;
  2933. if ((IdPath[ 0 ] = BaseDllMapResourceIdW( lpType )) == -1) {
  2934. Status = STATUS_INVALID_PARAMETER;
  2935. }
  2936. else
  2937. if ((IdPath[ 1 ] = BaseDllMapResourceIdW( lpName )) == -1) {
  2938. Status = STATUS_INVALID_PARAMETER;
  2939. }
  2940. else {
  2941. DllHandle = BasepMapModuleHandle( hModule, TRUE );
  2942. TopResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)
  2943. RtlImageDirectoryEntryToData( (PVOID)DllHandle,
  2944. TRUE,
  2945. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  2946. &i
  2947. );
  2948. if (!TopResourceDirectory) {
  2949. Status = STATUS_RESOURCE_DATA_NOT_FOUND;
  2950. } else {
  2951. Status = LdrFindResourceDirectory_U( (PVOID)DllHandle,
  2952. IdPath,
  2953. 2,
  2954. &ResourceDirectory
  2955. );
  2956. }
  2957. }
  2958. if (!NT_SUCCESS( Status )) {
  2959. BaseDllFreeResourceId( IdPath[ 0 ] );
  2960. BaseDllFreeResourceId( IdPath[ 1 ] );
  2961. BaseSetLastNTError( Status );
  2962. return FALSE;
  2963. }
  2964. Result = TRUE;
  2965. try {
  2966. ResourceDirectoryEntry =
  2967. (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDirectory+1);
  2968. if (ResourceDirectory->NumberOfNamedEntries != 0) {
  2969. BaseSetLastNTError( STATUS_INVALID_IMAGE_FORMAT );
  2970. Result = FALSE;
  2971. } else {
  2972. for (i=0; i<ResourceDirectory->NumberOfIdEntries; i++) {
  2973. wLanguage = ResourceDirectoryEntry->Id;
  2974. if (!_ResourceCallEnumLangRoutine((ENUMRESLANGPROCA)lpEnumFunc, hModule, (LPSTR)lpType, (LPSTR)lpName, wLanguage, lParam )) {
  2975. Result = FALSE;
  2976. break;
  2977. }
  2978. ResourceDirectoryEntry++;
  2979. }
  2980. }
  2981. } except (EXCEPTION_EXECUTE_HANDLER) {
  2982. BaseSetLastNTError( GetExceptionCode() );
  2983. Result = FALSE;
  2984. }
  2985. //
  2986. // Free any strings allocated by BaseDllMapResourceIdW
  2987. //
  2988. BaseDllFreeResourceId( IdPath[ 0 ] );
  2989. BaseDllFreeResourceId( IdPath[ 1 ] );
  2990. return Result;
  2991. }
  2992. ULONG_PTR
  2993. BaseDllMapResourceIdA(
  2994. LPCSTR lpId
  2995. )
  2996. {
  2997. NTSTATUS Status;
  2998. ULONG_PTR Id;
  2999. ULONG ulId;
  3000. UNICODE_STRING UnicodeString;
  3001. ANSI_STRING AnsiString;
  3002. PWSTR s;
  3003. try {
  3004. if ((ULONG_PTR)lpId >= LDR_RESOURCE_ID_NAME_MINVAL) {
  3005. if (*lpId == '#') {
  3006. Status = RtlCharToInteger( lpId+1, 10, &ulId );
  3007. Id = ulId;
  3008. if (!NT_SUCCESS( Status ) || (Id & LDR_RESOURCE_ID_NAME_MASK)) {
  3009. if (NT_SUCCESS( Status )) {
  3010. Status = STATUS_INVALID_PARAMETER;
  3011. }
  3012. BaseSetLastNTError( Status );
  3013. Id = (ULONG)-1;
  3014. }
  3015. } else {
  3016. RtlInitAnsiString( &AnsiString, lpId );
  3017. Status = RtlAnsiStringToUnicodeString( &UnicodeString,
  3018. &AnsiString,
  3019. TRUE
  3020. );
  3021. if (!NT_SUCCESS( Status )){
  3022. BaseSetLastNTError( Status );
  3023. Id = (ULONG_PTR)-1;
  3024. } else {
  3025. s = UnicodeString.Buffer;
  3026. while (*s != UNICODE_NULL) {
  3027. *s = RtlUpcaseUnicodeChar( *s );
  3028. s++;
  3029. }
  3030. Id = (ULONG_PTR)UnicodeString.Buffer;
  3031. }
  3032. }
  3033. } else {
  3034. Id = (ULONG_PTR)lpId;
  3035. }
  3036. } except (EXCEPTION_EXECUTE_HANDLER) {
  3037. BaseSetLastNTError( GetExceptionCode() );
  3038. Id = (ULONG_PTR)-1;
  3039. }
  3040. return Id;
  3041. }
  3042. ULONG_PTR
  3043. BaseDllMapResourceIdW(
  3044. LPCWSTR lpId
  3045. )
  3046. {
  3047. NTSTATUS Status;
  3048. UNICODE_STRING UnicodeString;
  3049. ULONG_PTR Id;
  3050. ULONG ulId;
  3051. PWSTR s;
  3052. try {
  3053. if ((ULONG_PTR)lpId >= LDR_RESOURCE_ID_NAME_MINVAL) {
  3054. if (*lpId == '#') {
  3055. RtlInitUnicodeString( &UnicodeString, lpId+1 );
  3056. Status = RtlUnicodeStringToInteger( &UnicodeString, 10, &ulId );
  3057. Id = ulId;
  3058. if (!NT_SUCCESS( Status ) || Id > LDR_RESOURCE_ID_NAME_MASK) {
  3059. if (NT_SUCCESS( Status )) {
  3060. Status = STATUS_INVALID_PARAMETER;
  3061. }
  3062. BaseSetLastNTError( Status );
  3063. Id = (ULONG_PTR)-1;
  3064. }
  3065. } else {
  3066. s = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), (wcslen( lpId ) + 1) * sizeof( WCHAR ) );
  3067. if (s == NULL) {
  3068. BaseSetLastNTError( STATUS_NO_MEMORY );
  3069. Id = (ULONG_PTR)-1;
  3070. } else {
  3071. Id = (ULONG_PTR)s;
  3072. while (*lpId != UNICODE_NULL) {
  3073. *s++ = RtlUpcaseUnicodeChar( *lpId++ );
  3074. }
  3075. *s = UNICODE_NULL;
  3076. }
  3077. }
  3078. } else {
  3079. Id = (ULONG_PTR)lpId;
  3080. }
  3081. } except (EXCEPTION_EXECUTE_HANDLER) {
  3082. BaseSetLastNTError( GetExceptionCode() );
  3083. Id = (ULONG_PTR)-1;
  3084. }
  3085. return Id;
  3086. }
  3087. VOID
  3088. BaseDllFreeResourceId(
  3089. ULONG_PTR Id
  3090. )
  3091. {
  3092. UNICODE_STRING UnicodeString;
  3093. if (Id >= LDR_RESOURCE_ID_NAME_MINVAL && Id != -1) {
  3094. UnicodeString.Buffer = (PWSTR)Id;
  3095. UnicodeString.Length = 0;
  3096. UnicodeString.MaximumLength = 0;
  3097. RtlFreeUnicodeString( &UnicodeString );
  3098. }
  3099. }
  3100. INT_PTR ReturnMem16Data(
  3101. DWORD dwReserved1,
  3102. DWORD dwReserved2,
  3103. DWORD dwReserved3
  3104. )
  3105. {
  3106. // Since there's _currently_ no other app we know that this will be useful for, we can
  3107. // always return "our" value.
  3108. // Elmo's Preschool Deluxe is looking for free physical or virtual mem. Give it a
  3109. // Number it will be happy with.
  3110. // Incoming params from Elmo's (in case they're needed one day):
  3111. // dwReserved1 will be 0
  3112. // dwReserved2 will be 1 or 2 (physical/virtual)
  3113. // dwReserved3 will be 0
  3114. return 0x2000;
  3115. }
  3116. BOOL
  3117. UTRegister(
  3118. HMODULE hInst32,
  3119. LPSTR lpszDll16,
  3120. LPSTR lpszInitFunc,
  3121. LPSTR lpszThunkFunc,
  3122. FARPROC *ppfnThunk32Func,
  3123. FARPROC Callback,
  3124. PVOID lpvData
  3125. )
  3126. {
  3127. //
  3128. // This function is supposed to return an error code. VOID happens to work because
  3129. // the stub would just leave EAX alone. If something happens and EAX starts getting
  3130. // zero'ed out, it'll cause problems and return type here should be changed to int
  3131. // and success should return NON-ZERO. - bjm 09/98
  3132. //
  3133. // Sure, we could have checked this on a compat bit instead, but the ISV is the
  3134. // Children's Television Workshop people and if they do this silliness in any
  3135. // of their other apps, we'll get those fixed "for free".
  3136. if ( 0 == lstrcmpi( lpszDll16, (LPCSTR)"mem16.dll" ) &&
  3137. 0 == lstrcmpi( lpszThunkFunc, (LPCSTR)"GetMemory" ) )
  3138. {
  3139. //
  3140. // Elmo's Preschool Deluxe calls to a 16bit dll they ship just
  3141. // to get physical and virtual mem. Let's give 'em a pointer to our routine that
  3142. // will give it numbers that makes it happy.
  3143. //
  3144. *ppfnThunk32Func = ReturnMem16Data;
  3145. return(TRUE);
  3146. }
  3147. // Stub this function for King's Quest and Bodyworks 5.0 and other random Win 95 apps.
  3148. return(FALSE);
  3149. }
  3150. VOID
  3151. UTUnRegister(
  3152. HMODULE hInst32
  3153. )
  3154. {
  3155. // Stub this function for King's Quest and Bodyworks 5.0 and other random Win 95 apps.
  3156. return;
  3157. }