Blame winpr/libwinpr/library/library.c

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