Blame winpr/libwinpr/library/library.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * Library Loader
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/platform.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/library.h>
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("library")
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * api-ms-win-core-libraryloader-l1-1-1.dll:
Packit 1fb8d4
 *
Packit 1fb8d4
 * AddDllDirectory
Packit 1fb8d4
 * RemoveDllDirectory
Packit 1fb8d4
 * SetDefaultDllDirectories
Packit 1fb8d4
 * DisableThreadLibraryCalls
Packit 1fb8d4
 * EnumResourceLanguagesExA
Packit 1fb8d4
 * EnumResourceLanguagesExW
Packit 1fb8d4
 * EnumResourceNamesExA
Packit 1fb8d4
 * EnumResourceNamesExW
Packit 1fb8d4
 * EnumResourceTypesExA
Packit 1fb8d4
 * EnumResourceTypesExW
Packit 1fb8d4
 * FindResourceExW
Packit 1fb8d4
 * FindStringOrdinal
Packit 1fb8d4
 * FreeLibrary
Packit 1fb8d4
 * FreeLibraryAndExitThread
Packit 1fb8d4
 * FreeResource
Packit 1fb8d4
 * GetModuleFileNameA
Packit 1fb8d4
 * GetModuleFileNameW
Packit 1fb8d4
 * GetModuleHandleA
Packit 1fb8d4
 * GetModuleHandleExA
Packit 1fb8d4
 * GetModuleHandleExW
Packit 1fb8d4
 * GetModuleHandleW
Packit 1fb8d4
 * GetProcAddress
Packit 1fb8d4
 * LoadLibraryExA
Packit 1fb8d4
 * LoadLibraryExW
Packit 1fb8d4
 * LoadResource
Packit 1fb8d4
 * LoadStringA
Packit 1fb8d4
 * LoadStringW
Packit 1fb8d4
 * LockResource
Packit 1fb8d4
 * QueryOptionalDelayLoadedAPI
Packit 1fb8d4
 * SizeofResource
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#if !defined(_WIN32) || defined(_UWP)
Packit 1fb8d4
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#include <dlfcn.h>
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <stdlib.h>
Packit 1fb8d4
#include <unistd.h>
Packit 1fb8d4
#include <sys/types.h>
Packit 1fb8d4
#include <sys/stat.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef __MACOSX__
Packit 1fb8d4
#include <mach-o/dyld.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
DLL_DIRECTORY_COOKIE AddDllDirectory(PCWSTR NewDirectory)
Packit 1fb8d4
{
Packit Service 5a9772
	/* TODO: Implement */
Packit Service 5a9772
	WLog_ERR(TAG, "%s not implemented", __FUNCTION__);
Packit Service 5a9772
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL RemoveDllDirectory(DLL_DIRECTORY_COOKIE Cookie)
Packit 1fb8d4
{
Packit Service 5a9772
	/* TODO: Implement */
Packit Service 5a9772
	WLog_ERR(TAG, "%s not implemented", __FUNCTION__);
Packit Service 5a9772
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit Service 5a9772
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetDefaultDllDirectories(DWORD DirectoryFlags)
Packit 1fb8d4
{
Packit Service 5a9772
	/* TODO: Implement */
Packit Service 5a9772
	WLog_ERR(TAG, "%s not implemented", __FUNCTION__);
Packit Service 5a9772
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit Service 5a9772
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE LoadLibraryA(LPCSTR lpLibFileName)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(_UWP)
Packit 1fb8d4
	int status;
Packit 1fb8d4
	HMODULE hModule = NULL;
Packit 1fb8d4
	WCHAR* filenameW = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpLibFileName)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	status = ConvertToUnicode(CP_UTF8, 0, lpLibFileName, -1, &filenameW, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (status < 1)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit Service 5a9772
	hModule = LoadLibraryW(filenameW);
Packit 1fb8d4
	free(filenameW);
Packit 1fb8d4
	return hModule;
Packit 1fb8d4
#else
Packit 1fb8d4
	HMODULE library;
Packit Service 8c2f8f
	library = dlopen(lpLibFileName, RTLD_GLOBAL | RTLD_LAZY);
Packit 1fb8d4
Packit 1fb8d4
	if (!library)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "%s failed with %s", __FUNCTION__, dlerror());
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return library;
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE LoadLibraryW(LPCWSTR lpLibFileName)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(_UWP)
Packit 1fb8d4
	return LoadPackagedLibrary(lpLibFileName, 0);
Packit 1fb8d4
#else
Packit Service 5a9772
	char* name = NULL;
Packit Service 5a9772
	HMODULE module;
Packit Service 5a9772
	int rc = ConvertFromUnicode(CP_UTF8, 0, lpLibFileName, -1, &name, 0, NULL, NULL);
Packit Service 5a9772
Packit Service 5a9772
	if (rc < 0)
Packit Service 5a9772
		return NULL;
Packit Service 5a9772
Packit Service 5a9772
	module = LoadLibraryA(name);
Packit Service 5a9772
	free(name);
Packit Service 5a9772
	return module;
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Packit 1fb8d4
{
Packit Service 5a9772
	if (dwFlags != 0)
Packit Service 5a9772
		WLog_WARN(TAG, "%s does not support dwFlags 0x%08" PRIx32, __FUNCTION__, dwFlags);
Packit 1fb8d4
Packit Service 5a9772
	if (hFile)
Packit Service 5a9772
		WLog_WARN(TAG, "%s does not support hFile != NULL", __FUNCTION__);
Packit 1fb8d4
Packit Service 5a9772
	return LoadLibraryA(lpLibFileName);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Packit 1fb8d4
{
Packit Service 5a9772
	if (dwFlags != 0)
Packit Service 5a9772
		WLog_WARN(TAG, "%s does not support dwFlags 0x%08" PRIx32, __FUNCTION__, dwFlags);
Packit Service 5a9772
Packit Service 5a9772
	if (hFile)
Packit Service 5a9772
		WLog_WARN(TAG, "%s does not support hFile != NULL", __FUNCTION__);
Packit Service 5a9772
Packit Service 5a9772
	return LoadLibraryW(lpLibFileName);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#if !defined(_WIN32) && !defined(__CYGWIN__)
Packit 1fb8d4
Packit 1fb8d4
FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
Packit 1fb8d4
{
Packit 1fb8d4
	FARPROC proc;
Packit 1fb8d4
	proc = dlsym(hModule, lpProcName);
Packit 1fb8d4
Packit 1fb8d4
	if (proc == NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "GetProcAddress: could not find procedure %s: %s", lpProcName, dlerror());
Packit Service 5a9772
		return (FARPROC)NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return proc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL FreeLibrary(HMODULE hLibModule)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	status = dlclose(hLibModule);
Packit 1fb8d4
Packit 1fb8d4
	if (status != 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE GetModuleHandleA(LPCSTR lpModuleName)
Packit 1fb8d4
{
Packit Service 5a9772
	/* TODO: Implement */
Packit Service 5a9772
	WLog_ERR(TAG, "%s not implemented", __FUNCTION__);
Packit Service 5a9772
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HMODULE GetModuleHandleW(LPCWSTR lpModuleName)
Packit 1fb8d4
{
Packit Service 5a9772
	/* TODO: Implement */
Packit Service 5a9772
	WLog_ERR(TAG, "%s not implemented", __FUNCTION__);
Packit Service 5a9772
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * GetModuleFileName:
Packit 1fb8d4
 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms683197/
Packit 1fb8d4
 *
Packit 1fb8d4
 * Finding current executable's path without /proc/self/exe:
Packit 1fb8d4
 * http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
DWORD GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
Packit 1fb8d4
{
Packit Service 5a9772
	DWORD status;
Packit Service 5a9772
	char* name = calloc(nSize, sizeof(char));
Packit Service 5a9772
	if (!name)
Packit Service 5a9772
	{
Packit Service 5a9772
		SetLastError(ERROR_INTERNAL_ERROR);
Packit Service 5a9772
		return 0;
Packit Service 5a9772
	}
Packit Service 5a9772
	status = GetModuleFileNameA(hModule, name, nSize);
Packit Service 5a9772
Packit Service 5a9772
	if ((status > INT_MAX) || (nSize > INT_MAX))
Packit Service 5a9772
	{
Packit Service 5a9772
		SetLastError(ERROR_INTERNAL_ERROR);
Packit Service 5a9772
		status = 0;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	if (status > 0)
Packit Service 5a9772
	{
Packit Service 5a9772
		int rc = ConvertToUnicode(CP_UTF8, 0, name, (int)status, &lpFilename, (int)nSize);
Packit Service 5a9772
Packit Service 5a9772
		if (rc < 0)
Packit Service 5a9772
		{
Packit Service 5a9772
			free(name);
Packit Service 5a9772
			SetLastError(ERROR_INTERNAL_ERROR);
Packit Service 5a9772
			return 0;
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	free(name);
Packit Service 5a9772
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(__linux__)
Packit 1fb8d4
	int status;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	char path[64];
Packit 1fb8d4
Packit 1fb8d4
	if (!hModule)
Packit 1fb8d4
	{
Packit 1fb8d4
		char buffer[4096];
Packit 1fb8d4
		sprintf_s(path, ARRAYSIZE(path), "/proc/%d/exe", getpid());
Packit 1fb8d4
		status = readlink(path, buffer, sizeof(buffer));
Packit 1fb8d4
Packit 1fb8d4
		if (status < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_INTERNAL_ERROR);
Packit 1fb8d4
			return 0;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		buffer[status] = '\0';
Packit Service 5a9772
		length = strnlen(buffer, sizeof(buffer));
Packit 1fb8d4
Packit 1fb8d4
		if (length < nSize)
Packit 1fb8d4
		{
Packit 1fb8d4
			CopyMemory(lpFilename, buffer, length);
Packit 1fb8d4
			lpFilename[length] = '\0';
Packit 1fb8d4
			return length;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(lpFilename, buffer, nSize - 1);
Packit 1fb8d4
		lpFilename[nSize - 1] = '\0';
Packit 1fb8d4
		SetLastError(ERROR_INSUFFICIENT_BUFFER);
Packit 1fb8d4
		return nSize;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#elif defined(__MACOSX__)
Packit 1fb8d4
	int status;
Packit Service 5a9772
	size_t length;
Packit 1fb8d4
Packit 1fb8d4
	if (!hModule)
Packit 1fb8d4
	{
Packit 1fb8d4
		char path[4096];
Packit 1fb8d4
		char buffer[4096];
Packit 1fb8d4
		uint32_t size = sizeof(path);
Packit 1fb8d4
		status = _NSGetExecutablePath(path, &size);
Packit 1fb8d4
Packit 1fb8d4
		if (status != 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			/* path too small */
Packit 1fb8d4
			SetLastError(ERROR_INTERNAL_ERROR);
Packit 1fb8d4
			return 0;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		/*
Packit 1fb8d4
		 * _NSGetExecutablePath may not return the canonical path,
Packit 1fb8d4
		 * so use realpath to find the absolute, canonical path.
Packit 1fb8d4
		 */
Packit 1fb8d4
		realpath(path, buffer);
Packit Service 5a9772
		length = strnlen(buffer, sizeof(buffer));
Packit 1fb8d4
Packit 1fb8d4
		if (length < nSize)
Packit 1fb8d4
		{
Packit 1fb8d4
			CopyMemory(lpFilename, buffer, length);
Packit 1fb8d4
			lpFilename[length] = '\0';
Packit Service 5a9772
			return (DWORD)length;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(lpFilename, buffer, nSize - 1);
Packit 1fb8d4
		lpFilename[nSize - 1] = '\0';
Packit 1fb8d4
		SetLastError(ERROR_INSUFFICIENT_BUFFER);
Packit 1fb8d4
		return nSize;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	WLog_ERR(TAG, "%s is not implemented", __FUNCTION__);
Packit 1fb8d4
	SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif