@@ -110,53 +110,104 @@ static void LPK_DrawUnderscore(HDC hdc, int x, int y, LPCWSTR str, int count, in
110110 DeleteObject (hpen );
111111}
112112
113- /* Code taken from the GetProcessDefaultLayout() function from Wine's user32
114- * Wine version 3.17
113+ static
114+ BOOL
115+ GetProcessImageVersionInfo (
116+ _Out_ PVOID * pFileInfo ,
117+ _Out_ LPDWORD pdwLen )
118+ {
119+ HRSRC hResource ;
120+ DWORD dwResourceSize ;
121+ HGLOBAL hResourceData ;
122+ PVOID pvResourceData ;
123+
124+ * pFileInfo = NULL ;
125+ * pdwLen = 0 ;
126+
127+ /* Try to get the VersionInfo resource */
128+ hResource = FindResourceW (NULL , MAKEINTRESOURCEW (VS_VERSION_INFO ), RT_VERSION );
129+ if (hResource == NULL )
130+ return FALSE;
131+
132+ /* Get resource size and do basic size check */
133+ dwResourceSize = SizeofResource (NULL , hResource );
134+ if (dwResourceSize < sizeof (VS_FIXEDFILEINFO ))
135+ return FALSE;
136+
137+ /* Load the resource */
138+ hResourceData = LoadResource (NULL , hResource );
139+ if (hResourceData == NULL )
140+ return FALSE;
141+
142+ /* Lock the resource */
143+ pvResourceData = LockResource (hResourceData );
144+ if (pvResourceData == NULL )
145+ return FALSE;
146+
147+ * pFileInfo = pvResourceData ;
148+ * pdwLen = dwResourceSize ;
149+ return TRUE;
150+ }
151+
152+ /* Checks the VersionInfo of the main executable for RTL layout
153+ * and applies it to the process if found.
154+ * See https://web.archive.org/web/20050207001156/http://www.microsoft.com/globaldev/getwr/steps/WRG_mirror.mspx
115155 *
116156 * This function should be called from LpkInitialize(),
117157 * which is in turn called by GdiInitializeLanguagePack() (from gdi32).
118158 * TODO: Move call from LpkDllInitialize() to LpkInitialize() when latter
119159 * function is implemented.
120160 */
121- static void LPK_ApplyMirroring ()
161+ static void LPK_ApplyMirroring (void )
122162{
123- static const WCHAR translationW [] = { '\\' ,'V' ,'a' ,'r' ,'F' ,'i' ,'l' ,'e' ,'I' ,'n' ,'f' ,'o' ,
124- '\\' ,'T' ,'r' ,'a' ,'n' ,'s' ,'l' ,'a' ,'t' ,'i' ,'o' ,'n' , 0 };
125- static const WCHAR filedescW [] = { '\\' ,'S' ,'t' ,'r' ,'i' ,'n' ,'g' ,'F' ,'i' ,'l' ,'e' ,'I' ,'n' ,'f' ,'o' ,
126- '\\' ,'%' ,'0' ,'4' ,'x' ,'%' ,'0' ,'4' ,'x' ,
127- '\\' ,'F' ,'i' ,'l' ,'e' ,'D' ,'e' ,'s' ,'c' ,'r' ,'i' ,'p' ,'t' ,'i' ,'o' ,'n' ,0 };
128- WCHAR * str , buffer [MAX_PATH ];
129- #ifdef __REACTOS__
130- DWORD i , version_layout = 0 ;
131- UINT len ;
132- #else
133- DWORD i , len , version_layout = 0 ;
134- #endif
135- DWORD user_lang = GetUserDefaultLangID ();
136- DWORD * languages ;
137- void * data = NULL ;
138-
139- GetModuleFileNameW ( 0 , buffer , MAX_PATH );
140- if (!(len = GetFileVersionInfoSizeW ( buffer , NULL ))) goto done ;
141- if (!(data = HeapAlloc ( GetProcessHeap (), 0 , len ))) goto done ;
142- if (!GetFileVersionInfoW ( buffer , 0 , len , data )) goto done ;
143- if (!VerQueryValueW ( data , translationW , (void * * )& languages , & len ) || !len ) goto done ;
144-
145- len /= sizeof (DWORD );
146- for (i = 0 ; i < len ; i ++ ) if (LOWORD (languages [i ]) == user_lang ) break ;
147- if (i == len ) /* try neutral language */
148- for (i = 0 ; i < len ; i ++ )
149- if (LOWORD (languages [i ]) == MAKELANGID ( PRIMARYLANGID (user_lang ), SUBLANG_NEUTRAL )) break ;
150- if (i == len ) i = 0 ; /* default to the first one */
151-
152- sprintfW ( buffer , filedescW , LOWORD (languages [i ]), HIWORD (languages [i ]) );
153- if (!VerQueryValueW ( data , buffer , (void * * )& str , & len )) goto done ;
154- TRACE ( "found description %s\n" , debugstr_w ( str ));
155- if (str [0 ] == 0x200e && str [1 ] == 0x200e ) version_layout = LAYOUT_RTL ;
156-
157- done :
158- HeapFree ( GetProcessHeap (), 0 , data );
159- SetProcessDefaultLayout (version_layout );
163+ PWSTR pwstrFileDescription = NULL ;
164+ PVOID pvFileInfo ;
165+ DWORD cbFileInfoSize ;
166+
167+ /* HACK!!!! For some reason this call, that does nothing, is required,
168+ otherwise comctl32_winetest tooltips starts to fail. */
169+ GetFileVersionInfoSizeW (L"" , NULL );
170+
171+ /* Get the VersionInfo resource of the main executable */
172+ if (!GetProcessImageVersionInfo (& pvFileInfo , & cbFileInfoSize ))
173+ {
174+ return ;
175+ }
176+
177+ /* The length (in WCHARs) of the key name, including the null-terminator */
178+ const DWORD cchKeyLength = sizeof (L"FileDescription" ) / sizeof (WCHAR );
179+
180+ /* Calculate the required length (in WCHARs) for a FileDescription entry:
181+ The key (incl. null) + alignment byte + 2 LTR markers (note: the key
182+ is always unaligned by 2 bytes) */
183+ const DWORD cchRequired = cchKeyLength + 1 + 2 ;
184+
185+ /* Scan the VersionInfo resource for the "FileDescription" key */
186+ PWSTR pwchCurrent = (PWSTR )pvFileInfo ;
187+ DWORD cchRemining = cbFileInfoSize / sizeof (WCHAR );
188+ while (cchRemining >= cchRequired )
189+ {
190+ /* Compare current position with the "FileDescription" key */
191+ if (lstrcmpW (pwchCurrent , L"FileDescription" ) == 0 )
192+ {
193+ /* The value starts after the key, the Null-terminator and 1 WCHAR alignment */
194+ pwstrFileDescription = pwchCurrent + cchKeyLength + 1 ;
195+ break ;
196+ }
197+
198+ /* Move to next position */
199+ pwchCurrent ++ ;
200+ cchRemining -- ;
201+ }
202+
203+ /* Check if the description starts with 2 LTR markers (u200E).
204+ Yes, this is how MS marks the layout as RTL (see article linked above). */
205+ if ((pwstrFileDescription != NULL ) &&
206+ (pwstrFileDescription [0 ] == 0x200E ) &&
207+ (pwstrFileDescription [1 ] == 0x200E ))
208+ {
209+ SetProcessDefaultLayout (LAYOUT_RTL );
210+ }
160211}
161212
162213BOOL
0 commit comments