Codebase list mozc / f470414
Implicitly link to input.dll on Windows. Now that we we no longer support Windows XP, we can safely assume that input.dll is always available and it's OK to implicitly link to that rather than relying on LoadLibrary and GetProcAddress. One tricky part is that Windows SDK does not provide the import library for input.dll. To work around this, we will create our own import library as a part of build steps, by following this document. http://support.microsoft.com/kb/131313/en-us BUG=none TEST=compile Yohei Yukawa 8 years ago
10 changed file(s) with 223 addition(s) and 420 deletion(s). Raw diff Collapse all Expand all
00 MAJOR=2
11 MINOR=17
2 BUILD=2096
2 BUILD=2097
33 REVISION=102
44 # NACL_DICTIONARY_VERSION is the target version of the system dictionary to be
55 # downloaded by NaCl Mozc.
6969 const uint32 kWaitForAsmCacheReadyEventTimeout = 4500; // 4.5 sec.
7070
7171 bool GetDefaultLayout(LAYOUTORTIPPROFILE *profile) {
72 if (!InputDll::EnsureInitialized()) {
73 return false;
74 }
75
76 if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
77 return false;
78 }
79
80 const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
72 const UINT num_element = ::EnumEnabledLayoutOrTip(
8173 nullptr, nullptr, nullptr, nullptr, 0);
8274
8375 unique_ptr<LAYOUTORTIPPROFILE[]> buffer(new LAYOUTORTIPPROFILE[num_element]);
8476
85 const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
77 const UINT num_copied =::EnumEnabledLayoutOrTip(
8678 nullptr, nullptr, nullptr, buffer.get(), num_element);
8779
8880 for (size_t i = 0; i < num_copied; ++i) {
139131 }
140132
141133 bool SetDefaultWin8() {
142 if (!InputDll::EnsureInitialized()) {
143 return false;
144 }
145 if (InputDll::set_default_layout_or_tip() == nullptr) {
146 return false;
147 }
148134 wchar_t clsid[64] = {};
149135 if (!::StringFromGUID2(TsfProfile::GetTextServiceGuid(), clsid,
150136 arraysize(clsid))) {
157143 }
158144
159145 const wstring &profile = wstring(L"0x0411:") + clsid + profile_id;
160 if (!InputDll::install_layout_or_tip()(profile.c_str(), 0)) {
146 if (!::InstallLayoutOrTip(profile.c_str(), 0)) {
161147 DLOG(ERROR) << "InstallLayoutOrTip failed";
162148 return false;
163149 }
164 if (!InputDll::set_default_layout_or_tip()(profile.c_str(), 0)) {
150 if (!::SetDefaultLayoutOrTip(profile.c_str(), 0)) {
165151 DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
166152 return false;
167153 }
261247 return false;
262248 }
263249
264 if (InputDll::EnsureInitialized() &&
265 InputDll::set_default_layout_or_tip() != nullptr) {
266 // In most cases, we can use this method on Vista or later.
267 const wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString();
268 if (!InputDll::set_default_layout_or_tip()(profile_list.c_str(), 0)) {
269 DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
270 return false;
271 }
272 } else {
273 // We cannot use const HKL because |&mozc_hkl| will be cast into PVOID.
274 HKL hkl = ::LoadKeyboardLayout(mozc_klid.ToString().c_str(), KLF_ACTIVATE);
275 if (0 == ::SystemParametersInfo(SPI_SETDEFAULTINPUTLANG,
276 0,
277 &hkl,
278 SPIF_SENDCHANGE)) {
279 LOG(ERROR) << "SystemParameterInfo failed: " << GetLastError();
280 return false;
281 }
282
283 if (S_OK != ImmRegistrar::MovePreloadValueToTop(mozc_klid)) {
284 LOG(ERROR) << "MovePreloadValueToTop failed";
285 return false;
286 }
250 const wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString();
251 if (!::SetDefaultLayoutOrTip(profile_list.c_str(), 0)) {
252 DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
253 return false;
287254 }
288255
289256 if (!ActivateForCurrentSession()) {
2626 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
29 #include "win32/base/input_dll.h"
29 // This file will be used to create an import library. Functions in this
30 // file must not be called directly.
31
32 #include <windows.h>
3033
3134 #include "base/logging.h"
32 #include "base/util.h"
33 #include "base/win_util.h"
3435
35 namespace mozc {
36 namespace win32 {
36 struct LAYOUTORTIPPROFILE;
37 struct LAYOUTORTIP;
3738
38 const wchar_t kInputDllName[] = L"input.dll";
39
40 const char kEnumEnabledLayoutOrTipName[] = "EnumEnabledLayoutOrTip";
41 const char kEnumLayoutOrTipForSetup[] = "EnumLayoutOrTipForSetup";
42 const char kInstallLayoutOrTipName[] = "InstallLayoutOrTip";
43 const char kInstallLayoutOrTipUserRegName[] = "InstallLayoutOrTipUserReg";
44 const char kSetDefaultLayoutOrTipName[] = "SetDefaultLayoutOrTip";
45
46 bool InputDll::EnsureInitialized() {
47 if (not_found_) {
48 // Previous trial was not successful. give up.
49 return false;
50 }
51
52 if (module_ != nullptr) {
53 // Already initialized.
54 return true;
55 }
56
57 bool lock_held = false;
58 if (!WinUtil::IsDLLSynchronizationHeld(&lock_held)) {
59 LOG(ERROR) << "IsDLLSynchronizationHeld failed.";
60 return false;
61 }
62 if (lock_held) {
63 LOG(INFO) << "This thread has loader lock. "
64 << "LoadLibrary should not be called.";
65 return false;
66 }
67
68 const HMODULE input_dll = WinUtil::LoadSystemLibrary(kInputDllName);
69 if (input_dll == nullptr) {
70 const int last_error = ::GetLastError();
71 DLOG(INFO) << "LoadSystemLibrary(\"" << kInputDllName << "\") failed. "
72 << "error = " << last_error;
73 if (last_error == ERROR_MOD_NOT_FOUND) {
74 not_found_ = true;
75 }
76 return false;
77 }
78
79 enum_enabled_layout_or_tip_ =
80 reinterpret_cast<FPEnumEnabledLayoutOrTip>(
81 ::GetProcAddress(input_dll, kEnumEnabledLayoutOrTipName));
82
83 enum_layout_or_tip_for_setup_ =
84 reinterpret_cast<FPEnumLayoutOrTipForSetup>(
85 ::GetProcAddress(input_dll, kEnumLayoutOrTipForSetup));
86
87 install_layout_or_tip_ =
88 reinterpret_cast<FPInstallLayoutOrTip>(
89 ::GetProcAddress(input_dll, kInstallLayoutOrTipName));
90
91 install_layout_or_tip_user_reg_ =
92 reinterpret_cast<FPInstallLayoutOrTipUserReg>(
93 ::GetProcAddress(input_dll, kInstallLayoutOrTipUserRegName));
94
95 set_default_layout_or_tip_ =
96 reinterpret_cast<FPSetDefaultLayoutOrTip>(
97 ::GetProcAddress(input_dll, kSetDefaultLayoutOrTipName));
98
99 // Other threads may load the same DLL concurrently.
100 // Check if this thread is the first thread which updated the |module_|.
101 const HMODULE original = static_cast<HMODULE>(
102 ::InterlockedCompareExchangePointer(
103 reinterpret_cast<volatile PVOID *>(&module_), input_dll, nullptr));
104 if (original == nullptr) {
105 // This is the first thread which updated the |module_| with valid handle.
106 // Do not call FreeLibrary to keep the reference count positive.
107 } else {
108 // |module_| has already been updated by another thread. Call FreeLibrary
109 // to decrement the reference count which this thread owns.
110 ::FreeLibrary(input_dll);
111 }
112
113 return true;
39 extern "C"
40 UINT WINAPI EnumEnabledLayoutOrTip(
41 __in_opt LPCWSTR pszUserReg,
42 __in_opt LPCWSTR pszSystemReg,
43 __in_opt LPCWSTR pszSoftwareReg,
44 __out LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
45 __in UINT uBufLength) {
46 CHECK(false)
47 << "This is a stub function to create an import library. "
48 << "Shouldn't be called from anywhere.";
49 return 0;
11450 }
11551
116 InputDll::FPEnumEnabledLayoutOrTip InputDll::enum_enabled_layout_or_tip() {
117 return enum_enabled_layout_or_tip_;
52 extern "C"
53 UINT WINAPI EnumLayoutOrTipForSetup(
54 __in LANGID langid,
55 __out_ecount(uBufLength) LAYOUTORTIP *pLayoutOrTip,
56 __in UINT uBufLength,
57 __in DWORD dwFlags) {
58 CHECK(false)
59 << "This is a stub function to create an import library. "
60 << "Shouldn't be called from anywhere.";
61 return 0;
11862 }
11963
120 InputDll::FPEnumLayoutOrTipForSetup InputDll::enum_layout_or_tip_for_setup() {
121 return enum_layout_or_tip_for_setup_;
64 extern "C"
65 BOOL WINAPI InstallLayoutOrTip(
66 __in LPCWSTR psz,
67 __in DWORD dwFlags) {
68 CHECK(false)
69 << "This is a stub function to create an import library. "
70 << "Shouldn't be called from anywhere.";
71 return FALSE;
12272 }
12373
124 InputDll::FPInstallLayoutOrTip InputDll::install_layout_or_tip() {
125 return install_layout_or_tip_;
74 extern "C"
75 BOOL WINAPI InstallLayoutOrTipUserReg(
76 __in_opt LPCWSTR pszUserReg,
77 __in_opt LPCWSTR pszSystemReg,
78 __in_opt LPCWSTR pszSoftwareReg,
79 __in LPCWSTR psz,
80 __in DWORD dwFlags) {
81 CHECK(false)
82 << "This is a stub function to create an import library. "
83 << "Shouldn't be called from anywhere.";
84 return FALSE;
12685 }
12786
128 InputDll::FPInstallLayoutOrTipUserReg
129 InputDll::install_layout_or_tip_user_reg() {
130 return install_layout_or_tip_user_reg_;
87 extern "C"
88 BOOL WINAPI SetDefaultLayoutOrTip(
89 __in LPCWSTR psz,
90 DWORD dwFlags) {
91 CHECK(false)
92 << "This is a stub function to create an import library. "
93 << "Shouldn't be called from anywhere.";
94 return FALSE;
13195 }
132
133 InputDll::FPSetDefaultLayoutOrTip InputDll::set_default_layout_or_tip() {
134 return set_default_layout_or_tip_;
135 }
136
137 bool InputDll::not_found_;
138
139 volatile HMODULE InputDll::module_;
140 InputDll::FPEnumEnabledLayoutOrTip InputDll::enum_enabled_layout_or_tip_;
141 InputDll::FPEnumLayoutOrTipForSetup InputDll::enum_layout_or_tip_for_setup_;
142 InputDll::FPInstallLayoutOrTip InputDll::install_layout_or_tip_;
143 InputDll::FPInstallLayoutOrTipUserReg
144 InputDll::install_layout_or_tip_user_reg_;
145 InputDll::FPSetDefaultLayoutOrTip InputDll::set_default_layout_or_tip_;
146
147 } // namespace win32
148 } // namespace mozc
0 LIBRARY input.dll
1
2 EXPORTS
3 EnumEnabledLayoutOrTip
4 EnumLayoutOrTipForSetup
5 InstallLayoutOrTip
6 InstallLayoutOrTipUserReg
7 SetDefaultLayoutOrTip
3131
3232 #include <windows.h>
3333
34 #include "base/port.h"
35 #include "testing/base/public/gunit_prod.h"
36 // for FRIEND_TEST()
37
3834 // Structures and flags bellow have not been included header files in Windows
3935 // SDK. You can see the original source of this information at the following
4036 // page.
8076 WCHAR szId[MAX_PATH];
8177 } LAYOUTORTIPPROFILE;
8278
83 namespace mozc {
84 namespace win32 {
85
86 // With these function, you no longer need to manipulate undocumented registry
87 // entries such as "Keyboard Layout/Preload".
88 // TODO(yukawa): Add mock injection mechanism to support unit tests.
89 class InputDll {
90 public:
91 // Ensures input.dll is loaded into the process so that its export functions
92 // become available. When this method returns true, the returned value of
93 // each accessor method like |set_default_layout_or_tip()| is the same to
94 // the returned address of GetProcAddress API. If |EnsureInitialized()|
95 // returns true but the accessor method returns nullptr, it means that the DLL
96 // exists on the system but the expected function is not exported.
97 // You can call this method multiple times from multiple threads. In other
98 // words, you can use this method like 'IsInizialized'.
99 // This method fails if input.dll is not available on the system. This
100 // method also fails if the caller thread owns loader lock.
101 static bool EnsureInitialized();
102
103 // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
104 // is available on Vista or later via input.dll to enumerates all enabled
105 // keyboard layouts or text services of the specified user setting.
106 //
107 // EnumEnabledLayoutOrTip:
108 // URL:
109 // http://msdn.microsoft.com/en-us/library/bb847907.aspx
110 // Return Value:
111 // TRUE: The function was successful.
112 // FALSE: An unspecified error occurred.
113 typedef UINT (CALLBACK *FPEnumEnabledLayoutOrTip)(
114 __in_opt LPCWSTR pszUserReg,
115 __in_opt LPCWSTR pszSystemReg,
116 __in_opt LPCWSTR pszSoftwareReg,
117 __out LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
118 __in UINT uBufLength);
119 static FPEnumEnabledLayoutOrTip enum_enabled_layout_or_tip();
120
121 // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
122 // is available on Vista or later via input.dll to enumerates the installed
123 // keyboard layouts and text services.
124 //
125 // EnumLayoutOrTipForSetup:
126 // URL:
127 // http://msdn.microsoft.com/en-us/library/bb847908.aspx
128 // Return Value:
129 // |pLayoutOrTip == nullptr|
130 // The number of elements to be returned.
131 // |pLayoutOrTip != nullptr|
132 // The number of elements actually copied to |pLayoutOrTip|.
133 typedef UINT (CALLBACK *FPEnumLayoutOrTipForSetup)(
79 // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
80 // is available on Vista or later via input.dll to enumerates all enabled
81 // keyboard layouts or text services of the specified user setting.
82 //
83 // EnumEnabledLayoutOrTip:
84 // URL:
85 // http://msdn.microsoft.com/en-us/library/bb847907.aspx
86 // Return Value:
87 // TRUE: The function was successful.
88 // FALSE: An unspecified error occurred.
89 extern "C" __declspec(dllimport)
90 UINT WINAPI EnumEnabledLayoutOrTip(
91 __in_opt LPCWSTR pszUserReg,
92 __in_opt LPCWSTR pszSystemReg,
93 __in_opt LPCWSTR pszSoftwareReg,
94 __out LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
95 __in UINT uBufLength);
96
97 // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
98 // is available on Vista or later via input.dll to enumerates the installed
99 // keyboard layouts and text services.
100 //
101 // EnumLayoutOrTipForSetup:
102 // URL:
103 // http://msdn.microsoft.com/en-us/library/bb847908.aspx
104 // Return Value:
105 // |pLayoutOrTip == nullptr|
106 // The number of elements to be returned.
107 // |pLayoutOrTip != nullptr|
108 // The number of elements actually copied to |pLayoutOrTip|.
109 extern "C" __declspec(dllimport)
110 UINT WINAPI EnumLayoutOrTipForSetup(
134111 __in LANGID langid,
135112 __out_ecount(uBufLength) LAYOUTORTIP *pLayoutOrTip,
136113 __in UINT uBufLength,
137114 __in DWORD dwFlags);
138 static FPEnumLayoutOrTipForSetup enum_layout_or_tip_for_setup();
139
140 // Returns a function pointer to the InstallLayoutOrTip API, which is
141 // available on Vista or later via input.dll to enable the specified
142 // keyboard layouts or text services for the current user.
143 //
144 // InstallLayoutOrTip:
145 // URL:
146 // http://msdn.microsoft.com/en-us/library/bb847909.aspx
147 // Remarks:
148 // The string format of the layout list is:
149 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
150 // The string format of the text service profile list is:
151 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
152 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
153 // This format seems to be corresponding to the registry key, e.g.
154 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
155 // {Land ID}\{GUID of LanguageProfile}
156 // Return Value:
157 // TRUE: The function was successful.
158 // FALSE: An unspecified error occurred.
159 typedef BOOL (CALLBACK *FPInstallLayoutOrTip)(
115
116 // Returns a function pointer to the InstallLayoutOrTip API, which is
117 // available on Vista or later via input.dll to enable the specified
118 // keyboard layouts or text services for the current user.
119 //
120 // InstallLayoutOrTip:
121 // URL:
122 // http://msdn.microsoft.com/en-us/library/bb847909.aspx
123 // Remarks:
124 // The string format of the layout list is:
125 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
126 // The string format of the text service profile list is:
127 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
128 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
129 // This format seems to be corresponding to the registry key, e.g.
130 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
131 // {Land ID}\{GUID of LanguageProfile}
132 // Return Value:
133 // TRUE: The function was successful.
134 // FALSE: An unspecified error occurred.
135 extern "C" __declspec(dllimport)
136 BOOL WINAPI InstallLayoutOrTip(
160137 __in LPCWSTR psz,
161138 __in DWORD dwFlags);
162 static FPInstallLayoutOrTip install_layout_or_tip();
163
164 // Returns a function pointer to the InstallLayoutOrTipUserReg API, which
165 // is available on Vista or later via input.dll to enable the specified
166 // keyboard layouts or text services for the specified user.
167 //
168 // InstallLayoutOrTipUserReg:
169 // URL:
170 // http://msdn.microsoft.com/en-us/library/bb847910.aspx
171 // Remarks:
172 // The string format of the layout list is:
173 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
174 // The string format of the text service profile list is:
175 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
176 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
177 // This format seems to be corresponding to the registry key, e.g.
178 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
179 // {Land ID}\{GUID of LanguageProfile}
180 // Return Value:
181 // TRUE: The function was successful.
182 // FALSE: An unspecified error occurred.
183 // Observational Facts:
184 // Like ImmInstallIME API, calling InstallLayoutOrTipUserReg from 32-bit
185 // process to install x64 binaries is not recommended. Otherwise, we
186 // will see some weird issues like b/2931871.
187 typedef BOOL (CALLBACK *FPInstallLayoutOrTipUserReg)(
139
140 // Returns a function pointer to the InstallLayoutOrTipUserReg API, which
141 // is available on Vista or later via input.dll to enable the specified
142 // keyboard layouts or text services for the specified user.
143 //
144 // InstallLayoutOrTipUserReg:
145 // URL:
146 // http://msdn.microsoft.com/en-us/library/bb847910.aspx
147 // Remarks:
148 // The string format of the layout list is:
149 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
150 // The string format of the text service profile list is:
151 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
152 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
153 // This format seems to be corresponding to the registry key, e.g.
154 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
155 // {Land ID}\{GUID of LanguageProfile}
156 // Return Value:
157 // TRUE: The function was successful.
158 // FALSE: An unspecified error occurred.
159 // Observational Facts:
160 // Like ImmInstallIME API, calling InstallLayoutOrTipUserReg from 32-bit
161 // process to install x64 binaries is not recommended. Otherwise, we
162 // will see some weird issues like b/2931871.
163 extern "C" __declspec(dllimport)
164 BOOL WINAPI InstallLayoutOrTipUserReg(
188165 __in_opt LPCWSTR pszUserReg,
189166 __in_opt LPCWSTR pszSystemReg,
190167 __in_opt LPCWSTR pszSoftwareReg,
191168 __in LPCWSTR psz,
192169 __in DWORD dwFlags);
193 static FPInstallLayoutOrTipUserReg install_layout_or_tip_user_reg();
194
195 // Returns a function pointer to the SetDefaultLayoutOrTip API, which sets
196 // the specified keyboard layout or a text service as the default input item
197 // of the current user.
198 //
199 // SetDefaultLayoutOrTip:
200 // URL:
201 // http://msdn.microsoft.com/en-us/library/bb847915.aspx
202 // Remarks:
203 // The string format of the layout list is:
204 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
205 // The string format of the text service profile list is:
206 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
207 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
208 // This format seems to be corresponding to the registry key, e.g.
209 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
210 // {Land ID}\{GUID of LanguageProfile}
211 // Return Value:
212 // TRUE: The function was successful.
213 // FALSE: An unspecified error occurred.
214 // Observational Facts:
215 // This API seems to be designed to modify per user settings, like HKCU,
216 // so that the current user can modify it with his/her privileges. In
217 // oother words, no administrative privilege is required.
218 // SetDefaultLayoutOrTipUserReg might be a phantom, which only exists in
219 // MSDN Library.
220 // This function returns fail if it is called to install an IME which is
221 // not enabled (if we use undocumented terms to explain the condition,
222 // "The IME is not listed in the Preload key"). It seems that the caller
223 // is responsible to enable (e.g. calling InstallLayoutOrTipUserReg)
224 // the target IME before call this function to set the IME default.
225 typedef BOOL (CALLBACK *FPSetDefaultLayoutOrTip)(
226 __in LPCWSTR psz,
227 DWORD dwFlags);
228 static FPSetDefaultLayoutOrTip set_default_layout_or_tip();
229
230 private:
231 static volatile HMODULE module_;
232 static bool not_found_;
233 static FPEnumEnabledLayoutOrTip enum_enabled_layout_or_tip_;
234 static FPEnumLayoutOrTipForSetup enum_layout_or_tip_for_setup_;
235 static FPInstallLayoutOrTip install_layout_or_tip_;
236 static FPInstallLayoutOrTipUserReg install_layout_or_tip_user_reg_;
237 static FPSetDefaultLayoutOrTip set_default_layout_or_tip_;
238
239 FRIEND_TEST(InputDllTest, EnsureInitializedTest);
240
241 DISALLOW_IMPLICIT_CONSTRUCTORS(InputDll);
242 };
243 } // namespace win32
244 } // namespace mozc
170
171 // Returns a function pointer to the SetDefaultLayoutOrTip API, which sets
172 // the specified keyboard layout or a text service as the default input item
173 // of the current user.
174 //
175 // SetDefaultLayoutOrTip:
176 // URL:
177 // http://msdn.microsoft.com/en-us/library/bb847915.aspx
178 // Remarks:
179 // The string format of the layout list is:
180 // <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
181 // The string format of the text service profile list is:
182 // <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
183 // where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
184 // This format seems to be corresponding to the registry key, e.g.
185 // HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
186 // {Land ID}\{GUID of LanguageProfile}
187 // Return Value:
188 // TRUE: The function was successful.
189 // FALSE: An unspecified error occurred.
190 // Observational Facts:
191 // This API seems to be designed to modify per user settings, like HKCU,
192 // so that the current user can modify it with his/her privileges. In
193 // oother words, no administrative privilege is required.
194 // SetDefaultLayoutOrTipUserReg might be a phantom, which only exists in
195 // MSDN Library.
196 // This function returns fail if it is called to install an IME which is
197 // not enabled (if we use undocumented terms to explain the condition,
198 // "The IME is not listed in the Preload key"). It seems that the caller
199 // is responsible to enable (e.g. calling InstallLayoutOrTipUserReg)
200 // the target IME before call this function to set the IME default.
201 extern "C" __declspec(dllimport)
202 BOOL WINAPI SetDefaultLayoutOrTip(
203 __in LPCWSTR psz,
204 DWORD dwFlags);
205
245206 #endif // MOZC_WIN32_BASE_INPUT_DLL_H_
2626 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
29 #include <string>
29 #include "win32/base/input_dll.h"
3030
3131 #include "testing/base/public/googletest.h"
3232 #include "testing/base/public/gunit.h"
33 #include "win32/base/input_dll.h"
3433
35 namespace mozc {
36 namespace win32 {
34 namespace {
3735
38 class InputDllTest : public testing::Test {
39 public:
40 protected:
41 InputDllTest() {}
42
43 virtual ~InputDllTest() {}
44
45 virtual void SetUp() {
46 // TODO(yukawa): Implement injection mechanism to ::LoadLibrary API
47 // TODO(yukawa): Inject custom LoadLibrary to make this test independent
48 // of test environment.
49 }
50
51 virtual void TearDown() {
52 // TODO(yukawa): Implement injection mechanism to ::LoadLibrary API
53 // TODO(yukawa): Remove custom LoadLibrary injection not to affect
54 // subsequent tests.
55 }
56
57 private:
58 DISALLOW_COPY_AND_ASSIGN(InputDllTest);
59 };
60
61 // Currently this test is not independent of test environment.
62 // TODO(yukawa): Implement injection mechanism to ::LoadLibrary API to make
63 // the code flow predictable.
64 TEST_F(InputDllTest, EnsureInitializedTest) {
65 if (InputDll::EnsureInitialized()) {
66 // Check internal status.
67 EXPECT_FALSE(InputDll::not_found_);
68 // gtest will cause compilation error if we use <volatile HMODULE> here.
69 // Use <void *> instead.
70 EXPECT_NE(nullptr, static_cast<void *>(InputDll::module_));
71
72 // Actually input.dll exists on Windows XP. However, it does not always
73 // mean that input.dll exports the functions in which we are interested.
74
75 // Assume that the following funcsions are available on Vista and later.
76 EXPECT_NE(nullptr, InputDll::enum_enabled_layout_or_tip());
77 EXPECT_NE(nullptr, InputDll::enum_layout_or_tip_for_setup());
78 EXPECT_NE(nullptr, InputDll::install_layout_or_tip());
79 EXPECT_NE(nullptr, InputDll::install_layout_or_tip_user_reg());
80 EXPECT_NE(nullptr, InputDll::set_default_layout_or_tip());
81
82 // Check the consistency of the retuls of second call.
83 EXPECT_TRUE(InputDll::EnsureInitialized());
84 return;
85 }
86
87 // Check internal status.
88 EXPECT_TRUE(InputDll::not_found_);
89 // gtest will cause compilation error if we use <volatile HMODULE> here.
90 // Use <void *> instead.
91 EXPECT_EQ(nullptr, static_cast<void *>(InputDll::module_));
92
93 EXPECT_EQ(nullptr, InputDll::enum_enabled_layout_or_tip());
94 EXPECT_EQ(nullptr, InputDll::enum_layout_or_tip_for_setup());
95 EXPECT_EQ(nullptr, InputDll::install_layout_or_tip());
96 EXPECT_EQ(nullptr, InputDll::install_layout_or_tip_user_reg());
97 EXPECT_EQ(nullptr, InputDll::set_default_layout_or_tip());
98
99 // Check the consistency of the retuls of second call.
100 EXPECT_FALSE(InputDll::EnsureInitialized());
36 TEST(InputDllTest, EnumEnabledLayoutOrTipTest) {
37 const UINT num_element = ::EnumEnabledLayoutOrTip(
38 nullptr, nullptr, nullptr, nullptr, 0);
39 EXPECT_LT(0, num_element);
10140 }
10241
103 } // namespace win32
104 } // namespace mozc
42 } // namespace
133133 return true;
134134 }
135135
136 if (!InputDll::EnsureInitialized()) {
137 return false;
138 }
139 if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
140 return false;
141 }
142 const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
136 const UINT num_element = ::EnumEnabledLayoutOrTip(
143137 nullptr, nullptr, nullptr, nullptr, 0);
144138
145139 unique_ptr<LAYOUTORTIPPROFILE[]> buffer(new LAYOUTORTIPPROFILE[num_element]);
146140
147 const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
141 const UINT num_copied = ::EnumEnabledLayoutOrTip(
148142 nullptr, nullptr, nullptr, buffer.get(), num_element);
149143
150144 // Look up IMM32 Mozc from |buffer|.
201195 }
202196
203197 const wstring &profile = wstring(L"0x0411:") + clsid + profile_id;
204 if (!InputDll::set_default_layout_or_tip()(profile.c_str(), 0)) {
198 if (!::SetDefaultLayoutOrTip(profile.c_str(), 0)) {
205199 DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
206200 return false;
207201 }
215209 klid.ToString().c_str()))) {
216210 return false;
217211 }
218 if (!InputDll::install_layout_or_tip()(profile_str, ILOT_DISABLED)) {
212 if (!::InstallLayoutOrTip(profile_str, ILOT_DISABLED)) {
219213 DLOG(ERROR) << "InstallLayoutOrTip failed";
220214 return false;
221215 }
311311 }
312312 *enabled = FALSE;
313313
314 // Check if input.dll is exporting EnumEnabledLayoutOrTIP API, which is the
315 // best way to enumerate enabled profiles for the current user.
316 if (InputDll::EnsureInitialized() ||
317 (InputDll::enum_enabled_layout_or_tip() == nullptr)) {
318 return E_FAIL;
319 }
320
321 const int num_profiles = InputDll::enum_enabled_layout_or_tip()(
314 const int num_profiles = ::EnumEnabledLayoutOrTip(
322315 nullptr, nullptr, nullptr, nullptr, 0);
323316 unique_ptr<LAYOUTORTIPPROFILE[]> profiles(
324317 new LAYOUTORTIPPROFILE[num_profiles]);
325 const int num_copied = InputDll::enum_enabled_layout_or_tip()(
318 const int num_copied = ::EnumEnabledLayoutOrTip(
326319 nullptr, nullptr, nullptr, profiles.get(), num_profiles);
327320
328321 for (size_t i = 0; i < num_copied; ++i) {
815815 }
816816 current_profiles->clear();
817817
818 if (!InputDll::EnsureInitialized()) {
819 return false;
820 }
821 if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
822 return false;
823 }
824
825818 map<DWORD, wstring> keyboard_layouts;
826819 if (!GenerateKeyboardLayoutMap(&keyboard_layouts)) {
827820 return false;
828821 }
829822
830823 {
831 const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
824 const UINT num_element = ::EnumEnabledLayoutOrTip(
832825 nullptr, nullptr, nullptr, nullptr, 0);
833826 unique_ptr<LAYOUTORTIPPROFILE[]> buffer(
834827 new LAYOUTORTIPPROFILE[num_element]);
835 const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
828 const UINT num_copied = ::EnumEnabledLayoutOrTip(
836829 nullptr, nullptr, nullptr, buffer.get(), num_element);
837830
838831 for (size_t i = 0; i < num_copied; ++i) {
891884 return true;
892885 }
893886
894 if (!InputDll::EnsureInitialized()) {
895 return false;
896 }
897 if (InputDll::install_layout_or_tip_user_reg() == nullptr) {
898 return false;
899 }
900
901887 const wstring &profile_string = ComposeProfileStringForVista(
902888 profiles_to_be_removed);
903889
904 const BOOL result = InputDll::install_layout_or_tip_user_reg()(
890 const BOOL result = ::InstallLayoutOrTipUserReg(
905891 nullptr, nullptr, nullptr, profile_string.c_str(), ILOT_UNINSTALL);
906892
907893 return result != FALSE;
945931 return true;
946932 }
947933
948 if (!InputDll::EnsureInitialized()) {
949 return false;
950 }
951
952 if (InputDll::set_default_layout_or_tip() == nullptr) {
953 return false;
954 }
955
956934 if (!EnableAndBroadcastNewLayout(new_default, broadcast_change)) {
957935 // We do not return false here because the main task of this function is
958936 // setting the specified profile to default.
973951 flag = SDLOT_NOAPPLYTOCURRENTSESSION;
974952 }
975953
976 if (InputDll::set_default_layout_or_tip()(profile_string.c_str(), flag) ==
977 FALSE) {
954 if (!::SetDefaultLayoutOrTip(profile_string.c_str(), flag)) {
978955 DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
979956 return false;
980957 }
4747 # TSF Mozc is completed.
4848 'targets': [
4949 {
50 'target_name': 'input_dll_import_lib',
51 'type': 'shared_library',
52 'sources': [
53 'input_dll.cc',
54 'input_dll.def',
55 ],
56 'dependencies': [
57 '../../base/base.gyp:base',
58 ],
59 'msvs_settings': {
60 'VCLinkerTool': {
61 'AdditionalOptions': [
62 '/ignore:4070',
63 ],
64 },
65 },
66 },
67 {
5068 'target_name': 'imframework_util',
5169 'type': 'static_library',
5270 'sources': [
5371 'imm_reconvert_string.cc',
5472 'imm_registrar.cc',
5573 'imm_util.cc',
56 'input_dll.cc',
5774 'keyboard_layout_id.cc',
5875 'tsf_profile.cc',
5976 'tsf_registrar.cc',
6077 ],
6178 'dependencies': [
6279 '../../base/base.gyp:base',
80 'input_dll_import_lib',
6381 ],
6482 },
6583 {