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

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