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
diff --git a/src/mozc_version_template.txt b/src/mozc_version_template.txt
index 1160a21..01e955d 100644
--- a/src/mozc_version_template.txt
+++ b/src/mozc_version_template.txt
@@ -1,6 +1,6 @@
 MAJOR=2
 MINOR=17
-BUILD=2096
+BUILD=2097
 REVISION=102
 # NACL_DICTIONARY_VERSION is the target version of the system dictionary to be
 # downloaded by NaCl Mozc.
diff --git a/src/win32/base/imm_util.cc b/src/win32/base/imm_util.cc
index b903073..ce50fee 100644
--- a/src/win32/base/imm_util.cc
+++ b/src/win32/base/imm_util.cc
@@ -70,20 +70,12 @@
 const uint32 kWaitForAsmCacheReadyEventTimeout = 4500;  // 4.5 sec.
 
 bool GetDefaultLayout(LAYOUTORTIPPROFILE *profile) {
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-
-  if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
-    return false;
-  }
-
-  const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
+  const UINT num_element = ::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, nullptr, 0);
 
   unique_ptr<LAYOUTORTIPPROFILE[]> buffer(new LAYOUTORTIPPROFILE[num_element]);
 
-  const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
+  const UINT num_copied =::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, buffer.get(), num_element);
 
   for (size_t i = 0; i < num_copied; ++i) {
@@ -140,12 +132,6 @@
 }
 
 bool SetDefaultWin8() {
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-  if (InputDll::set_default_layout_or_tip() == nullptr) {
-    return false;
-  }
   wchar_t clsid[64] = {};
   if (!::StringFromGUID2(TsfProfile::GetTextServiceGuid(), clsid,
                          arraysize(clsid))) {
@@ -158,11 +144,11 @@
   }
 
   const wstring &profile = wstring(L"0x0411:") + clsid + profile_id;
-  if (!InputDll::install_layout_or_tip()(profile.c_str(), 0)) {
+  if (!::InstallLayoutOrTip(profile.c_str(), 0)) {
     DLOG(ERROR) << "InstallLayoutOrTip failed";
     return false;
   }
-  if (!InputDll::set_default_layout_or_tip()(profile.c_str(), 0)) {
+  if (!::SetDefaultLayoutOrTip(profile.c_str(), 0)) {
     DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
     return false;
   }
@@ -262,29 +248,10 @@
     return false;
   }
 
-  if (InputDll::EnsureInitialized() &&
-      InputDll::set_default_layout_or_tip() != nullptr) {
-    // In most cases, we can use this method on Vista or later.
-    const wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString();
-    if (!InputDll::set_default_layout_or_tip()(profile_list.c_str(), 0)) {
-      DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
-      return false;
-    }
-  } else {
-    // We cannot use const HKL because |&mozc_hkl| will be cast into PVOID.
-    HKL hkl = ::LoadKeyboardLayout(mozc_klid.ToString().c_str(), KLF_ACTIVATE);
-    if (0 == ::SystemParametersInfo(SPI_SETDEFAULTINPUTLANG,
-                                    0,
-                                    &hkl,
-                                    SPIF_SENDCHANGE)) {
-      LOG(ERROR) << "SystemParameterInfo failed: " << GetLastError();
-      return false;
-    }
-
-    if (S_OK != ImmRegistrar::MovePreloadValueToTop(mozc_klid)) {
-      LOG(ERROR) << "MovePreloadValueToTop failed";
-      return false;
-    }
+  const wstring &profile_list = L"0x0411:0x" + mozc_klid.ToString();
+  if (!::SetDefaultLayoutOrTip(profile_list.c_str(), 0)) {
+    DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
+    return false;
   }
 
   if (!ActivateForCurrentSession()) {
diff --git a/src/win32/base/input_dll.cc b/src/win32/base/input_dll.cc
index f7ea76a..c24a6c9 100644
--- a/src/win32/base/input_dll.cc
+++ b/src/win32/base/input_dll.cc
@@ -27,123 +27,70 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "win32/base/input_dll.h"
+// This file will be used to create an import library.  Functions in this
+// file must not be called directly.
+
+#include <windows.h>
 
 #include "base/logging.h"
-#include "base/util.h"
-#include "base/win_util.h"
 
-namespace mozc {
-namespace win32 {
+struct LAYOUTORTIPPROFILE;
+struct LAYOUTORTIP;
 
-const wchar_t kInputDllName[] = L"input.dll";
-
-const char kEnumEnabledLayoutOrTipName[]    = "EnumEnabledLayoutOrTip";
-const char kEnumLayoutOrTipForSetup[]       = "EnumLayoutOrTipForSetup";
-const char kInstallLayoutOrTipName[]        = "InstallLayoutOrTip";
-const char kInstallLayoutOrTipUserRegName[] = "InstallLayoutOrTipUserReg";
-const char kSetDefaultLayoutOrTipName[]     = "SetDefaultLayoutOrTip";
-
-bool InputDll::EnsureInitialized() {
-  if (not_found_) {
-    // Previous trial was not successful.  give up.
-    return false;
-  }
-
-  if (module_ != nullptr) {
-    // Already initialized.
-    return true;
-  }
-
-  bool lock_held = false;
-  if (!WinUtil::IsDLLSynchronizationHeld(&lock_held)) {
-    LOG(ERROR) << "IsDLLSynchronizationHeld failed.";
-    return false;
-  }
-  if (lock_held) {
-    LOG(INFO) << "This thread has loader lock. "
-              << "LoadLibrary should not be called.";
-    return false;
-  }
-
-  const HMODULE input_dll = WinUtil::LoadSystemLibrary(kInputDllName);
-  if (input_dll == nullptr) {
-    const int last_error = ::GetLastError();
-    DLOG(INFO) << "LoadSystemLibrary(\"" << kInputDllName << "\") failed. "
-               << "error = " << last_error;
-    if (last_error == ERROR_MOD_NOT_FOUND) {
-      not_found_ = true;
-    }
-    return false;
-  }
-
-  enum_enabled_layout_or_tip_ =
-      reinterpret_cast<FPEnumEnabledLayoutOrTip>(
-          ::GetProcAddress(input_dll, kEnumEnabledLayoutOrTipName));
-
-  enum_layout_or_tip_for_setup_ =
-      reinterpret_cast<FPEnumLayoutOrTipForSetup>(
-          ::GetProcAddress(input_dll, kEnumLayoutOrTipForSetup));
-
-  install_layout_or_tip_ =
-      reinterpret_cast<FPInstallLayoutOrTip>(
-          ::GetProcAddress(input_dll, kInstallLayoutOrTipName));
-
-  install_layout_or_tip_user_reg_ =
-      reinterpret_cast<FPInstallLayoutOrTipUserReg>(
-          ::GetProcAddress(input_dll, kInstallLayoutOrTipUserRegName));
-
-  set_default_layout_or_tip_ =
-      reinterpret_cast<FPSetDefaultLayoutOrTip>(
-          ::GetProcAddress(input_dll, kSetDefaultLayoutOrTipName));
-
-  // Other threads may load the same DLL concurrently.
-  // Check if this thread is the first thread which updated the |module_|.
-  const HMODULE original = static_cast<HMODULE>(
-    ::InterlockedCompareExchangePointer(
-          reinterpret_cast<volatile PVOID *>(&module_), input_dll, nullptr));
-  if (original == nullptr) {
-    // This is the first thread which updated the |module_| with valid handle.
-    // Do not call FreeLibrary to keep the reference count positive.
-  } else {
-    // |module_| has already been updated by another thread.  Call FreeLibrary
-    // to decrement the reference count which this thread owns.
-    ::FreeLibrary(input_dll);
-  }
-
-  return true;
+extern "C"
+UINT WINAPI EnumEnabledLayoutOrTip(
+    __in_opt  LPCWSTR pszUserReg,
+    __in_opt  LPCWSTR pszSystemReg,
+    __in_opt  LPCWSTR pszSoftwareReg,
+    __out     LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
+    __in      UINT uBufLength) {
+  CHECK(false)
+      << "This is a stub function to create an import library. "
+      << "Shouldn't be called from anywhere.";
+  return 0;
 }
 
-InputDll::FPEnumEnabledLayoutOrTip InputDll::enum_enabled_layout_or_tip() {
-  return enum_enabled_layout_or_tip_;
+extern "C"
+UINT WINAPI EnumLayoutOrTipForSetup(
+    __in                     LANGID langid,
+    __out_ecount(uBufLength) LAYOUTORTIP *pLayoutOrTip,
+    __in                     UINT uBufLength,
+    __in                     DWORD dwFlags) {
+  CHECK(false)
+      << "This is a stub function to create an import library. "
+      << "Shouldn't be called from anywhere.";
+  return 0;
 }
 
-InputDll::FPEnumLayoutOrTipForSetup InputDll::enum_layout_or_tip_for_setup() {
-  return enum_layout_or_tip_for_setup_;
+extern "C"
+BOOL WINAPI InstallLayoutOrTip(
+    __in      LPCWSTR psz,
+    __in      DWORD dwFlags) {
+  CHECK(false)
+      << "This is a stub function to create an import library. "
+      << "Shouldn't be called from anywhere.";
+  return FALSE;
 }
 
-InputDll::FPInstallLayoutOrTip InputDll::install_layout_or_tip() {
-  return install_layout_or_tip_;
+extern "C"
+BOOL WINAPI InstallLayoutOrTipUserReg(
+    __in_opt  LPCWSTR pszUserReg,
+    __in_opt  LPCWSTR pszSystemReg,
+    __in_opt  LPCWSTR pszSoftwareReg,
+    __in      LPCWSTR psz,
+    __in      DWORD dwFlags) {
+  CHECK(false)
+      << "This is a stub function to create an import library. "
+      << "Shouldn't be called from anywhere.";
+  return FALSE;
 }
 
-InputDll::FPInstallLayoutOrTipUserReg
-    InputDll::install_layout_or_tip_user_reg() {
-  return install_layout_or_tip_user_reg_;
+extern "C"
+BOOL WINAPI SetDefaultLayoutOrTip(
+    __in  LPCWSTR psz,
+    DWORD dwFlags) {
+  CHECK(false)
+      << "This is a stub function to create an import library. "
+      << "Shouldn't be called from anywhere.";
+  return FALSE;
 }
-
-InputDll::FPSetDefaultLayoutOrTip InputDll::set_default_layout_or_tip() {
-  return set_default_layout_or_tip_;
-}
-
-bool InputDll::not_found_;
-
-volatile HMODULE InputDll::module_;
-InputDll::FPEnumEnabledLayoutOrTip InputDll::enum_enabled_layout_or_tip_;
-InputDll::FPEnumLayoutOrTipForSetup InputDll::enum_layout_or_tip_for_setup_;
-InputDll::FPInstallLayoutOrTip InputDll::install_layout_or_tip_;
-InputDll::FPInstallLayoutOrTipUserReg
-InputDll::install_layout_or_tip_user_reg_;
-InputDll::FPSetDefaultLayoutOrTip InputDll::set_default_layout_or_tip_;
-
-}  // namespace win32
-}  // namespace mozc
diff --git a/src/win32/base/input_dll.def b/src/win32/base/input_dll.def
new file mode 100644
index 0000000..8c1c706
--- /dev/null
+++ b/src/win32/base/input_dll.def
@@ -0,0 +1,8 @@
+LIBRARY input.dll
+
+EXPORTS
+        EnumEnabledLayoutOrTip
+        EnumLayoutOrTipForSetup
+        InstallLayoutOrTip
+        InstallLayoutOrTipUserReg
+        SetDefaultLayoutOrTip
diff --git a/src/win32/base/input_dll.h b/src/win32/base/input_dll.h
index 20937c1..208d9d1 100644
--- a/src/win32/base/input_dll.h
+++ b/src/win32/base/input_dll.h
@@ -32,10 +32,6 @@
 
 #include <windows.h>
 
-#include "base/port.h"
-#include "testing/base/public/gunit_prod.h"
-// for FRIEND_TEST()
-
 // Structures and flags bellow have not been included header files in Windows
 // SDK.  You can see the original source of this information at the following
 // page.
@@ -81,166 +77,131 @@
   WCHAR  szId[MAX_PATH];
 } LAYOUTORTIPPROFILE;
 
-namespace mozc {
-namespace win32 {
+// Returns a function pointer to the EnumEnabledLayoutOrTip API, which
+// is available on Vista or later via input.dll to enumerates all enabled
+// keyboard layouts or text services of the specified user setting.
+//
+// EnumEnabledLayoutOrTip:
+//   URL:
+//     http://msdn.microsoft.com/en-us/library/bb847907.aspx
+//   Return Value:
+//     TRUE: The function was successful.
+//     FALSE: An unspecified error occurred.
+extern "C" __declspec(dllimport)
+UINT WINAPI EnumEnabledLayoutOrTip(
+    __in_opt  LPCWSTR pszUserReg,
+    __in_opt  LPCWSTR pszSystemReg,
+    __in_opt  LPCWSTR pszSoftwareReg,
+    __out     LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
+    __in      UINT uBufLength);
 
-// With these function, you no longer need to manipulate undocumented registry
-// entries such as "Keyboard Layout/Preload".
-// TODO(yukawa): Add mock injection mechanism to support unit tests.
-class InputDll {
- public:
-  // Ensures input.dll is loaded into the process so that its export functions
-  // become available. When this method returns true, the returned value of
-  // each accessor method like |set_default_layout_or_tip()| is the same to
-  // the returned address of GetProcAddress API.  If |EnsureInitialized()|
-  // returns true but the accessor method returns nullptr, it means that the DLL
-  // exists on the system but the expected function is not exported.
-  // You can call this method multiple times from multiple threads.  In other
-  // words, you can use this method like 'IsInizialized'.
-  // This method fails if input.dll is not available on the system.  This
-  // method also fails if the caller thread owns loader lock.
-  static bool EnsureInitialized();
-
-  // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
-  // is available on Vista or later via input.dll to enumerates all enabled
-  // keyboard layouts or text services of the specified user setting.
-  //
-  // EnumEnabledLayoutOrTip:
-  //   URL:
-  //     http://msdn.microsoft.com/en-us/library/bb847907.aspx
-  //   Return Value:
-  //     TRUE: The function was successful.
-  //     FALSE: An unspecified error occurred.
-  typedef UINT (CALLBACK *FPEnumEnabledLayoutOrTip)(
-      __in_opt  LPCWSTR pszUserReg,
-      __in_opt  LPCWSTR pszSystemReg,
-      __in_opt  LPCWSTR pszSoftwareReg,
-      __out     LAYOUTORTIPPROFILE *pLayoutOrTipProfile,
-      __in      UINT uBufLength);
-  static FPEnumEnabledLayoutOrTip enum_enabled_layout_or_tip();
-
-  // Returns a function pointer to the EnumEnabledLayoutOrTip API, which
-  // is available on Vista or later via input.dll to enumerates the installed
-  // keyboard layouts and text services.
-  //
-  // EnumLayoutOrTipForSetup:
-  //   URL:
-  //     http://msdn.microsoft.com/en-us/library/bb847908.aspx
-  //   Return Value:
-  //     |pLayoutOrTip == nullptr|
-  //        The number of elements to be returned.
-  //     |pLayoutOrTip != nullptr|
-  //        The number of elements actually copied to |pLayoutOrTip|.
-  typedef UINT (CALLBACK *FPEnumLayoutOrTipForSetup)(
+// Returns a function pointer to the EnumEnabledLayoutOrTip API, which
+// is available on Vista or later via input.dll to enumerates the installed
+// keyboard layouts and text services.
+//
+// EnumLayoutOrTipForSetup:
+//   URL:
+//     http://msdn.microsoft.com/en-us/library/bb847908.aspx
+//   Return Value:
+//     |pLayoutOrTip == nullptr|
+//        The number of elements to be returned.
+//     |pLayoutOrTip != nullptr|
+//        The number of elements actually copied to |pLayoutOrTip|.
+extern "C" __declspec(dllimport)
+UINT WINAPI EnumLayoutOrTipForSetup(
     __in                     LANGID langid,
     __out_ecount(uBufLength) LAYOUTORTIP *pLayoutOrTip,
     __in                     UINT uBufLength,
     __in                     DWORD dwFlags);
-  static FPEnumLayoutOrTipForSetup enum_layout_or_tip_for_setup();
 
-  // Returns a function pointer to the InstallLayoutOrTip API, which is
-  // available on Vista or later via input.dll to enable the specified
-  // keyboard layouts or text services for the current user.
-  //
-  // InstallLayoutOrTip:
-  //   URL:
-  //     http://msdn.microsoft.com/en-us/library/bb847909.aspx
-  //   Remarks:
-  //     The string format of the layout list is:
-  //       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
-  //     The string format of the text service profile list is:
-  //       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
-  //     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
-  //     This format seems to be corresponding to the registry key, e.g.
-  //       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
-  //       {Land ID}\{GUID of LanguageProfile}
-  //   Return Value:
-  //     TRUE: The function was successful.
-  //     FALSE: An unspecified error occurred.
-  typedef BOOL (CALLBACK *FPInstallLayoutOrTip)(
+// Returns a function pointer to the InstallLayoutOrTip API, which is
+// available on Vista or later via input.dll to enable the specified
+// keyboard layouts or text services for the current user.
+//
+// InstallLayoutOrTip:
+//   URL:
+//     http://msdn.microsoft.com/en-us/library/bb847909.aspx
+//   Remarks:
+//     The string format of the layout list is:
+//       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
+//     The string format of the text service profile list is:
+//       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
+//     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
+//     This format seems to be corresponding to the registry key, e.g.
+//       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
+//       {Land ID}\{GUID of LanguageProfile}
+//   Return Value:
+//     TRUE: The function was successful.
+//     FALSE: An unspecified error occurred.
+extern "C" __declspec(dllimport)
+BOOL WINAPI InstallLayoutOrTip(
     __in      LPCWSTR psz,
     __in      DWORD dwFlags);
-  static FPInstallLayoutOrTip install_layout_or_tip();
 
-  // Returns a function pointer to the InstallLayoutOrTipUserReg API, which
-  // is available on Vista or later via input.dll to enable the specified
-  // keyboard layouts or text services for the specified user.
-  //
-  // InstallLayoutOrTipUserReg:
-  //   URL:
-  //     http://msdn.microsoft.com/en-us/library/bb847910.aspx
-  //   Remarks:
-  //     The string format of the layout list is:
-  //       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
-  //     The string format of the text service profile list is:
-  //       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
-  //     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
-  //     This format seems to be corresponding to the registry key, e.g.
-  //       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
-  //       {Land ID}\{GUID of LanguageProfile}
-  //   Return Value:
-  //     TRUE: The function was successful.
-  //     FALSE: An unspecified error occurred.
-  //   Observational Facts:
-  //     Like ImmInstallIME API, calling InstallLayoutOrTipUserReg from 32-bit
-  //     process to install x64 binaries is not recommended.  Otherwise, we
-  //     will see some weird issues like b/2931871.
-  typedef BOOL (CALLBACK *FPInstallLayoutOrTipUserReg)(
+// Returns a function pointer to the InstallLayoutOrTipUserReg API, which
+// is available on Vista or later via input.dll to enable the specified
+// keyboard layouts or text services for the specified user.
+//
+// InstallLayoutOrTipUserReg:
+//   URL:
+//     http://msdn.microsoft.com/en-us/library/bb847910.aspx
+//   Remarks:
+//     The string format of the layout list is:
+//       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
+//     The string format of the text service profile list is:
+//       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
+//     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
+//     This format seems to be corresponding to the registry key, e.g.
+//       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
+//       {Land ID}\{GUID of LanguageProfile}
+//   Return Value:
+//     TRUE: The function was successful.
+//     FALSE: An unspecified error occurred.
+//   Observational Facts:
+//     Like ImmInstallIME API, calling InstallLayoutOrTipUserReg from 32-bit
+//     process to install x64 binaries is not recommended.  Otherwise, we
+//     will see some weird issues like b/2931871.
+extern "C" __declspec(dllimport)
+BOOL WINAPI InstallLayoutOrTipUserReg(
     __in_opt  LPCWSTR pszUserReg,
     __in_opt  LPCWSTR pszSystemReg,
     __in_opt  LPCWSTR pszSoftwareReg,
     __in      LPCWSTR psz,
     __in      DWORD dwFlags);
-  static FPInstallLayoutOrTipUserReg install_layout_or_tip_user_reg();
 
-  // Returns a function pointer to the SetDefaultLayoutOrTip API, which sets
-  // the specified keyboard layout or a text service as the default input item
-  // of the current user.
-  //
-  // SetDefaultLayoutOrTip:
-  //   URL:
-  //     http://msdn.microsoft.com/en-us/library/bb847915.aspx
-  //   Remarks:
-  //     The string format of the layout list is:
-  //       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
-  //     The string format of the text service profile list is:
-  //       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
-  //     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
-  //     This format seems to be corresponding to the registry key, e.g.
-  //       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
-  //       {Land ID}\{GUID of LanguageProfile}
-  //   Return Value:
-  //     TRUE: The function was successful.
-  //     FALSE: An unspecified error occurred.
-  //   Observational Facts:
-  //     This API seems to be designed to modify per user settings, like HKCU,
-  //     so that the current user can modify it with his/her privileges.  In
-  //     oother words, no administrative privilege is required.
-  //     SetDefaultLayoutOrTipUserReg might be a phantom, which only exists in
-  //     MSDN Library.
-  //     This function returns fail if it is called to install an IME which is
-  //     not enabled (if we use undocumented terms to explain the condition,
-  //     "The IME is not listed in the Preload key").  It seems that the caller
-  //     is responsible to enable (e.g. calling InstallLayoutOrTipUserReg)
-  //     the target IME before call this function to set the IME default.
-  typedef BOOL (CALLBACK *FPSetDefaultLayoutOrTip)(
-      __in  LPCWSTR psz,
-      DWORD dwFlags);
-  static FPSetDefaultLayoutOrTip set_default_layout_or_tip();
+// Returns a function pointer to the SetDefaultLayoutOrTip API, which sets
+// the specified keyboard layout or a text service as the default input item
+// of the current user.
+//
+// SetDefaultLayoutOrTip:
+//   URL:
+//     http://msdn.microsoft.com/en-us/library/bb847915.aspx
+//   Remarks:
+//     The string format of the layout list is:
+//       <LangID 1>:<KLID 1>;[...<LangID N>:<KLID N>
+//     The string format of the text service profile list is:
+//       <LangID 1>:{CLSID of TIP}{GUID of LanguageProfile};
+//     where GUID should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
+//     This format seems to be corresponding to the registry key, e.g.
+//       HKLM\SOFTWARE\Microsoft\CTF\TIP\{CLSID of TIP}\LanguageProfile\
+//       {Land ID}\{GUID of LanguageProfile}
+//   Return Value:
+//     TRUE: The function was successful.
+//     FALSE: An unspecified error occurred.
+//   Observational Facts:
+//     This API seems to be designed to modify per user settings, like HKCU,
+//     so that the current user can modify it with his/her privileges.  In
+//     oother words, no administrative privilege is required.
+//     SetDefaultLayoutOrTipUserReg might be a phantom, which only exists in
+//     MSDN Library.
+//     This function returns fail if it is called to install an IME which is
+//     not enabled (if we use undocumented terms to explain the condition,
+//     "The IME is not listed in the Preload key").  It seems that the caller
+//     is responsible to enable (e.g. calling InstallLayoutOrTipUserReg)
+//     the target IME before call this function to set the IME default.
+extern "C" __declspec(dllimport)
+BOOL WINAPI SetDefaultLayoutOrTip(
+    __in  LPCWSTR psz,
+    DWORD dwFlags);
 
- private:
-  static volatile HMODULE module_;
-  static bool not_found_;
-  static FPEnumEnabledLayoutOrTip enum_enabled_layout_or_tip_;
-  static FPEnumLayoutOrTipForSetup enum_layout_or_tip_for_setup_;
-  static FPInstallLayoutOrTip install_layout_or_tip_;
-  static FPInstallLayoutOrTipUserReg install_layout_or_tip_user_reg_;
-  static FPSetDefaultLayoutOrTip set_default_layout_or_tip_;
-
-  FRIEND_TEST(InputDllTest, EnsureInitializedTest);
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(InputDll);
-};
-}  // namespace win32
-}  // namespace mozc
 #endif  // MOZC_WIN32_BASE_INPUT_DLL_H_
diff --git a/src/win32/base/input_dll_test.cc b/src/win32/base/input_dll_test.cc
index 0507c9c..bbed53c 100644
--- a/src/win32/base/input_dll_test.cc
+++ b/src/win32/base/input_dll_test.cc
@@ -27,79 +27,17 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <string>
+#include "win32/base/input_dll.h"
 
 #include "testing/base/public/googletest.h"
 #include "testing/base/public/gunit.h"
-#include "win32/base/input_dll.h"
 
-namespace mozc {
-namespace win32 {
+namespace {
 
-class InputDllTest : public testing::Test {
- public:
- protected:
-  InputDllTest() {}
-
-  virtual ~InputDllTest() {}
-
-  virtual void SetUp() {
-    // TODO(yukawa): Implement injection mechanism to ::LoadLibrary API
-    // TODO(yukawa): Inject custom LoadLibrary to make this test independent
-    //   of test environment.
-  }
-
-  virtual void TearDown() {
-    // TODO(yukawa): Implement injection mechanism to ::LoadLibrary API
-    // TODO(yukawa): Remove custom LoadLibrary injection not to affect
-    //   subsequent tests.
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InputDllTest);
-};
-
-// Currently this test is not independent of test environment.
-// TODO(yukawa): Implement injection mechanism to ::LoadLibrary API to make
-//   the code flow predictable.
-TEST_F(InputDllTest, EnsureInitializedTest) {
-  if (InputDll::EnsureInitialized()) {
-    // Check internal status.
-    EXPECT_FALSE(InputDll::not_found_);
-    // gtest will cause compilation error if we use <volatile HMODULE> here.
-    // Use <void *> instead.
-    EXPECT_NE(nullptr, static_cast<void *>(InputDll::module_));
-
-    // Actually input.dll exists on Windows XP.  However, it does not always
-    // mean that input.dll exports the functions in which we are interested.
-
-    // Assume that the following funcsions are available on Vista and later.
-    EXPECT_NE(nullptr, InputDll::enum_enabled_layout_or_tip());
-    EXPECT_NE(nullptr, InputDll::enum_layout_or_tip_for_setup());
-    EXPECT_NE(nullptr, InputDll::install_layout_or_tip());
-    EXPECT_NE(nullptr, InputDll::install_layout_or_tip_user_reg());
-    EXPECT_NE(nullptr, InputDll::set_default_layout_or_tip());
-
-    // Check the consistency of the retuls of second call.
-    EXPECT_TRUE(InputDll::EnsureInitialized());
-    return;
-  }
-
-  // Check internal status.
-  EXPECT_TRUE(InputDll::not_found_);
-  // gtest will cause compilation error if we use <volatile HMODULE> here.
-  // Use <void *> instead.
-  EXPECT_EQ(nullptr, static_cast<void *>(InputDll::module_));
-
-  EXPECT_EQ(nullptr, InputDll::enum_enabled_layout_or_tip());
-  EXPECT_EQ(nullptr, InputDll::enum_layout_or_tip_for_setup());
-  EXPECT_EQ(nullptr, InputDll::install_layout_or_tip());
-  EXPECT_EQ(nullptr, InputDll::install_layout_or_tip_user_reg());
-  EXPECT_EQ(nullptr, InputDll::set_default_layout_or_tip());
-
-  // Check the consistency of the retuls of second call.
-  EXPECT_FALSE(InputDll::EnsureInitialized());
+TEST(InputDllTest, EnumEnabledLayoutOrTipTest) {
+  const UINT num_element = ::EnumEnabledLayoutOrTip(
+      nullptr, nullptr, nullptr, nullptr, 0);
+  EXPECT_LT(0, num_element);
 }
 
-}  // namespace win32
-}  // namespace mozc
+}  // namespace
diff --git a/src/win32/base/migration_util.cc b/src/win32/base/migration_util.cc
index c21baf6..d9baacb 100644
--- a/src/win32/base/migration_util.cc
+++ b/src/win32/base/migration_util.cc
@@ -134,18 +134,12 @@
     return true;
   }
 
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-  if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
-    return false;
-  }
-  const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
+  const UINT num_element = ::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, nullptr, 0);
 
   unique_ptr<LAYOUTORTIPPROFILE[]> buffer(new LAYOUTORTIPPROFILE[num_element]);
 
-  const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
+  const UINT num_copied = ::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, buffer.get(), num_element);
 
   // Look up IMM32 Mozc from |buffer|.
@@ -202,7 +196,7 @@
       }
 
       const wstring &profile = wstring(L"0x0411:") + clsid + profile_id;
-      if (!InputDll::set_default_layout_or_tip()(profile.c_str(), 0)) {
+      if (!::SetDefaultLayoutOrTip(profile.c_str(), 0)) {
         DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
         return false;
       }
@@ -216,7 +210,7 @@
                                    klid.ToString().c_str()))) {
         return false;
       }
-      if (!InputDll::install_layout_or_tip()(profile_str, ILOT_DISABLED)) {
+      if (!::InstallLayoutOrTip(profile_str, ILOT_DISABLED)) {
         DLOG(ERROR) << "InstallLayoutOrTip failed";
         return false;
       }
diff --git a/src/win32/base/tsf_registrar.cc b/src/win32/base/tsf_registrar.cc
index 673f3ec..0154fb3 100644
--- a/src/win32/base/tsf_registrar.cc
+++ b/src/win32/base/tsf_registrar.cc
@@ -312,18 +312,11 @@
   }
   *enabled = FALSE;
 
-  // Check if input.dll is exporting EnumEnabledLayoutOrTIP API, which is the
-  // best way to enumerate enabled profiles for the current user.
-  if (InputDll::EnsureInitialized() ||
-      (InputDll::enum_enabled_layout_or_tip() == nullptr)) {
-    return E_FAIL;
-  }
-
-  const int num_profiles = InputDll::enum_enabled_layout_or_tip()(
+  const int num_profiles = ::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, nullptr, 0);
   unique_ptr<LAYOUTORTIPPROFILE[]> profiles(
       new LAYOUTORTIPPROFILE[num_profiles]);
-  const int num_copied = InputDll::enum_enabled_layout_or_tip()(
+  const int num_copied = ::EnumEnabledLayoutOrTip(
       nullptr, nullptr, nullptr, profiles.get(), num_profiles);
 
   for (size_t i = 0; i < num_copied; ++i) {
diff --git a/src/win32/base/uninstall_helper.cc b/src/win32/base/uninstall_helper.cc
index eb3afbd..0b7786d 100644
--- a/src/win32/base/uninstall_helper.cc
+++ b/src/win32/base/uninstall_helper.cc
@@ -816,24 +816,17 @@
   }
   current_profiles->clear();
 
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-  if (InputDll::enum_enabled_layout_or_tip() == nullptr) {
-    return false;
-  }
-
   map<DWORD, wstring> keyboard_layouts;
   if (!GenerateKeyboardLayoutMap(&keyboard_layouts)) {
     return false;
   }
 
   {
-    const UINT num_element = InputDll::enum_enabled_layout_or_tip()(
+    const UINT num_element = ::EnumEnabledLayoutOrTip(
         nullptr, nullptr, nullptr, nullptr, 0);
     unique_ptr<LAYOUTORTIPPROFILE[]> buffer(
         new LAYOUTORTIPPROFILE[num_element]);
-    const UINT num_copied = InputDll::enum_enabled_layout_or_tip()(
+    const UINT num_copied = ::EnumEnabledLayoutOrTip(
         nullptr, nullptr, nullptr, buffer.get(), num_element);
 
     for (size_t i = 0; i < num_copied; ++i) {
@@ -892,17 +885,10 @@
     return true;
   }
 
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-  if (InputDll::install_layout_or_tip_user_reg() == nullptr) {
-    return false;
-  }
-
   const wstring &profile_string = ComposeProfileStringForVista(
       profiles_to_be_removed);
 
-  const BOOL result = InputDll::install_layout_or_tip_user_reg()(
+  const BOOL result = ::InstallLayoutOrTipUserReg(
       nullptr, nullptr, nullptr, profile_string.c_str(), ILOT_UNINSTALL);
 
   return result != FALSE;
@@ -946,14 +932,6 @@
     return true;
   }
 
-  if (!InputDll::EnsureInitialized()) {
-    return false;
-  }
-
-  if (InputDll::set_default_layout_or_tip() == nullptr) {
-    return false;
-  }
-
   if (!EnableAndBroadcastNewLayout(new_default, broadcast_change)) {
     // We do not return false here because the main task of this function is
     // setting the specified profile to default.
@@ -974,8 +952,7 @@
     flag = SDLOT_NOAPPLYTOCURRENTSESSION;
   }
 
-  if (InputDll::set_default_layout_or_tip()(profile_string.c_str(), flag) ==
-      FALSE) {
+  if (!::SetDefaultLayoutOrTip(profile_string.c_str(), flag)) {
     DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
     return false;
   }
diff --git a/src/win32/base/win32_base.gyp b/src/win32/base/win32_base.gyp
index 17f57e9..9c1a943 100644
--- a/src/win32/base/win32_base.gyp
+++ b/src/win32/base/win32_base.gyp
@@ -48,19 +48,37 @@
       #     TSF Mozc is completed.
       'targets': [
         {
+          'target_name': 'input_dll_import_lib',
+          'type': 'shared_library',
+          'sources': [
+            'input_dll.cc',
+            'input_dll.def',
+          ],
+          'dependencies': [
+            '../../base/base.gyp:base',
+          ],
+          'msvs_settings': {
+            'VCLinkerTool': {
+              'AdditionalOptions': [
+                '/ignore:4070',
+              ],
+            },
+          },
+        },
+        {
           'target_name': 'imframework_util',
           'type': 'static_library',
           'sources': [
             'imm_reconvert_string.cc',
             'imm_registrar.cc',
             'imm_util.cc',
-            'input_dll.cc',
             'keyboard_layout_id.cc',
             'tsf_profile.cc',
             'tsf_registrar.cc',
           ],
           'dependencies': [
             '../../base/base.gyp:base',
+            'input_dll_import_lib',
           ],
         },
         {