15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/native_library.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_util.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/stringprintf.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace {
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path,
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                      LoadLibraryFunction load_library_api,
22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                      NativeLibraryLoadError* error) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LoadLibrary() opens the file off disk.
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ThreadRestrictions::AssertIOAllowed();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Switch the current directory to the library directory as the library
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // may have dependencies on DLLs in this directory.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool restore_directory = false;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath current_directory;
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (GetCurrentDirectory(&current_directory)) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilePath plugin_path = library_path.DirName();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!plugin_path.empty()) {
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      SetCurrentDirectory(plugin_path);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_directory = true;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMODULE module = (*load_library_api)(library_path.value().c_str());
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!module && error) {
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // GetLastError() needs to be called immediately after |load_library_api|.
41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    error->code = GetLastError();
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (restore_directory)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SetCurrentDirectory(current_directory);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return module;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}  // namespace
51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::string NativeLibraryLoadError::ToString() const {
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return StringPrintf("%u", code);
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeLibrary LoadNativeLibrary(const FilePath& library_path,
58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                NativeLibraryLoadError* error) {
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return LoadNativeLibraryHelper(library_path, LoadLibraryW, error);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeLibrary LoadNativeLibraryDynamically(const FilePath& library_path) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadLibraryFunction load_library;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_library = reinterpret_cast<LoadLibraryFunction>(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return LoadNativeLibraryHelper(library_path, load_library, NULL);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnloadNativeLibrary(NativeLibrary library) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeLibrary(library);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const char* name) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetProcAddress(library, name);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 GetNativeLibraryName(const string16& name) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return name + ASCIIToUTF16(".dll");
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
89