* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2005-2010 VMware, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef _DETERMINA_SHAREUTILS_H_
#define _DETERMINA_SHAREUTILS_H_
#include "share.h"
#include "dr_config.h"
#include "our_tchar.h"
#ifdef WINDOWS
# include "config.h"
#endif
#ifdef DEBUG
# include <stdio.h>
#endif
#if defined(WINDOWS) && defined(_DEBUG)
# include <crtdbg.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
const TCHAR *
get_dynamorio_home(void);
const TCHAR *
get_dynamorio_logdir(void);
bool
file_exists(const TCHAR *fn);
void
set_dr_platform(dr_platform_t platform);
dr_platform_t
get_dr_platform(void);
#ifdef WINDOWS
void
wcstolower(WCHAR *str);
WCHAR *
get_exename_from_path(const WCHAR *path);
BOOL
get_commandline_qualifier(const WCHAR *command_line, WCHAR *derived_name,
UINT max_derived_length , BOOL no_strip);
DWORD
acquire_shutdown_privilege();
DWORD
reboot_system();
* FIXME: shareme!
* if NULL is passed for directory, then it is ignored and no directory
* check is done, and filename_base is assumed to be absolute.
* TODO: make this a proactive check: make sure the file can be
* opened, eg, do a create/delete on the filename to be returned.
*/
BOOL
get_unique_filename(const WCHAR *directory, const WCHAR *filename_base,
const WCHAR *file_type, WCHAR *filename_buffer, UINT maxlen);
DWORD
delete_file_rename_in_use(WCHAR *filename);
DWORD
delete_file_on_boot(WCHAR *filename);
DWORD
delete_tree(const WCHAR *path);
DWORD
copy_file_permissions(WCHAR *filedst, WCHAR *filesrc);
DWORD
get_platform(DWORD *platform);
BOOL
is_wow64(HANDLE hProcess);
BOOL
using_system32_for_preinject(const WCHAR *preinject);
DWORD
get_preinject_path(WCHAR *buf, int nchars, BOOL force_local_path, BOOL short_path);
DWORD
get_preinject_name(WCHAR *buf, int nchars);
* for HKLM\Software keys
*/
DWORD
platform_key_flags();
DWORD
delete_product_key(HKEY hkey, LPCWSTR subkey);
DWORD
create_root_key();
DWORD
destroy_root_key();
* version of core that matches this build, NOT the version
* of the core that's actually installed! */
BOOL
check_opstring(const WCHAR *opstring);
* nudge, etc. */
DWORD
acquire_privileges();
DWORD
release_privileges();
void
ensure_directory_exists_for_file(WCHAR *filename);
void
mkdir_with_parents(const WCHAR *dirname);
DWORD
write_file_contents(WCHAR *path, char *contents, BOOL overwrite);
DWORD
write_file_contents_if_different(WCHAR *path, char *contents, BOOL *changed);
DWORD
read_file_contents(WCHAR *path, char *contents, SIZE_T maxchars, SIZE_T *needed);
DWORD
setup_installation(const WCHAR *path, BOOL overwrite);
DWORD
setup_cache_shared_directories(const WCHAR *cache_root);
DWORD
setup_cache_shared_registry(const WCHAR *cache_root, ConfigGroup *policy);
DWORD
set_registry_permissions_for_user(WCHAR *hklm_keyname, WCHAR *user);
typedef struct _VIOLATION_INFO {
DWORD flags;
const WCHAR *report;
WCHAR buf[MAX_PATH];
} VIOLATION_INFO;
* (info->report) as specified by the flags field in info. On success returns
* ERROR_SUCCESS, else returns a failure code. */
DWORD
get_violation_info(EVENTLOGRECORD *pevlr, VIOLATION_INFO *info);
# define CANARY_UNABLE_TO_TEST 1
# define CANARY_SUCCESS 0
# define CANARY_FAIL_HUNG -1
# define CANARY_FAIL_CRASH -2
# define CANARY_FAIL_VIOLATION -3
# define CANARY_FAIL_DR_ERROR -4
# define CANARY_FAIL_APP_INIT_INJECTION -5
# define CANARY_FAIL_EARLY_INJECTION -6
# define CANARY_TEST_TYPE_NATIVE 1
# define CANARY_TEST_TYPE_THIN_CLIENT 2
# define CANARY_TEST_TYPE_CLIENT 3
# define CANARY_TEST_TYPE_MF 4
# define GET_CANARY_CODE(test_type, fail_code) \
((fail_code << 16) | (test_type && 0xffff))
# define CANARY_RUN_NO_REQUIRE_PASS(run) (run | (run << 16))
# define CANARY_RUN_REQUIRES_PASS(run, flags) (((flags >> 16) & run) == 0)
# define CANARY_RUN_NATIVE 0x0001
# define CANARY_RUN_THIN_CLIENT_INJECT 0x0002
# define CANARY_RUN_THIN_CLIENT 0x0004
# define CANARY_RUN_CLIENT 0x0008
# define CANARY_RUN_MF 0x0010
# define CANARY_RUN_FLAGS_DEFAULT \
(CANARY_RUN_NATIVE | CANARY_RUN_THIN_CLIENT_INJECT | CANARY_RUN_THIN_CLIENT | \
CANARY_RUN_CLIENT | CANARY_RUN_NO_REQUIRE_PASS(CANARY_RUN_MF))
# define CANARY_INFO_FLAGS_DEFAULT 0
# define CANARY_URL_SIZE 20
# define CANARY_MESSAGE_SIZE 1024
typedef struct _CANARY_INFO {
DWORD run_flags;
DWORD info_flags;
int canary_code;
const WCHAR *report;
const WCHAR *url;
const WCHAR *msg;
WCHAR buf_report[MAX_PATH];
WCHAR buf_url[CANARY_URL_SIZE];
WCHAR buf_message[CANARY_MESSAGE_SIZE];
* go to a more data driven model. Other users should set fault_run to 0. */
DWORD fault_run;
WCHAR *canary_fault_args;
} CANARY_INFO;
* an NTSTATUS (such as ACCESS_DENIED etc.). */
# define CANARY_PROCESS_EXP_EXIT_CODE 0
* FALSE if one of the canary tests failed and therefore protection should not be
* enabled. Flags fields of info are used to specify which tests to run and what
* information to gather, other fields are used to return additional information
* to the caller. */
BOOL
run_canary_test( CANARY_INFO *info, WCHAR *version_msg);
* finds via the registry for greater customization. */
BOOL
run_canary_test_ex(FILE *file, CANARY_INFO *info, const WCHAR *scratch_folder,
const WCHAR *canary_process);
#endif
#ifdef DEBUG
extern int debuglevel;
extern int abortlevel;
void
set_debuglevel(int level);
void
set_debugfile(FILE *fp);
void
set_abortlevel(int level);
# define DL_FATAL 0
# define DL_ERROR 2
# define DL_WARN 4
# define DL_INFO 6
# define DL_VERB 8
# define DL_FINEST 10
# ifdef WINDOWS
# pragma warning(disable : 4127)
# endif
# ifndef EXIT_ON_ASSERT
# define EXIT_ON_ASSERT true
# endif
# ifndef ASSERTION_EXPRESSION
# ifdef _DEBUG
# define ASSERTION_EXPRESSION(msg) _ASSERTE(0)
# else
# define ASSERTION_EXPRESSION(msg)
# endif
# endif
# define DO_ASSERT_EXPR(msg, expr, handle, handler) \
{ \
if (!(expr)) { \
char ___buf[MAXIMUM_PATH]; \
_snprintf(___buf, MAXIMUM_PATH, "%s:%d [%s]", __FILE__, __LINE__, msg); \
if (handle) { \
handler \
} else if (EXIT_ON_ASSERT) { \
fprintf(stderr, "ASSERT: %s\n", ___buf); \
fflush(stderr); \
exit(-1); \
} else { \
ASSERTION_EXPRESSION(msg); \
} \
} \
}
# define NULL_HANDLER ;
# define DO_ASSERT(expr) DO_ASSERT_EXPR(# expr, expr, 0, NULL_HANDLER)
# define DO_ASSERT_HANDLE(expr, handler) DO_ASSERT_EXPR(# expr, expr, 1, handler)
# define DO_DEBUG(l, expr) \
{ \
if ((l) <= debuglevel) { \
expr \
} \
if ((l) <= abortlevel) { \
DO_ASSERT_EXPR("DEBUG failure", 0, 0, NULL_HANDLER); \
} \
fflush(stdout); \
fflush(stderr); \
}
# define DO_ASSERT_WSTR_EQ(s1, s2) \
DO_ASSERT(s1 != NULL); \
DO_ASSERT(s2 != NULL); \
DO_ASSERT(0 == wcscmp(s1, s2))
# define DO_ASSERT_STR_EQ(s1, s2) \
DO_ASSERT(s1 != NULL); \
DO_ASSERT(s2 != NULL); \
if (s1 != NULL && s2 != NULL) { \
DO_ASSERT(0 == strcmp(s1, s2)); \
}
# define CHECKED_OPERATION(expr) \
{ \
DWORD res = expr; \
if (res != ERROR_SUCCESS) \
printf("res=%d\n", res); \
DO_ASSERT(res == ERROR_SUCCESS); \
}
# define LAUNCH_APP_WAIT_HANDLE(relpath, pidvar, wait, handle) \
{ \
STARTUPINFO si = { 0 }; \
PROCESS_INFORMATION pi = { 0 }; \
WCHAR cmdl[MAX_PATH]; \
_snwprintf(cmdl, MAX_PATH, L"%s", relpath); \
DO_ASSERT( \
CreateProcess(NULL, cmdl, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)); \
*pidvar = pi.dwProcessId; \
DO_DEBUG(DL_VERB, printf("Launched %d=%S\n", *pidvar, cmdl);); \
if (wait) { \
DWORD waitres = WaitForSingleObject(pi.hProcess, 5000); \
DO_ASSERT(waitres == WAIT_OBJECT_0); \
} else { \
Sleep(100); \
} \
if (handle == NULL) { \
CloseHandle(pi.hThread); \
CloseHandle(pi.hProcess); \
} else { \
*handle = pi.hProcess; \
} \
}
# define LAUNCH_APP_HANDLE(relpath, pidvar, handle) \
LAUNCH_APP_WAIT_HANDLE(relpath, pidvar, FALSE, handle)
# define LAUNCH_APP_WAIT(relpath, pidvar, wait) \
LAUNCH_APP_WAIT_HANDLE(relpath, pidvar, wait, dummy)
# define LAUNCH_APP(relpath, pidvar) LAUNCH_APP_WAIT(relpath, pidvar, FALSE)
# define LAUNCH_APP_AND_WAIT(relpath, pidvar) LAUNCH_APP_WAIT(relpath, pidvar, TRUE)
# define TERMINATE_PROCESS(pid) \
{ \
DO_DEBUG(DL_VERB, printf("terminating %d\n", pid);); \
terminate_process(pid); \
Sleep(100); \
}
# define VERIFY_UNDER_DR(pid) \
{ \
int stat = under_dynamorio(pid); \
DO_ASSERT(stat != DLL_NONE && stat != DLL_UNKNOWN); \
}
# define VERIFY_NOT_UNDER_DR(pid) \
{ \
int stat = under_dynamorio(pid); \
DO_ASSERT(stat == DLL_NONE); \
}
# ifdef WINDOWS
DWORD
load_test_config(const char *snippet, BOOL use_hotpatch_defs);
void
get_testdir(WCHAR *buf, UINT maxchars);
BOOL
check_for_event(DWORD type, WCHAR *exename, ULONG pid, WCHAR *s3, WCHAR *s4,
UINT maxchars);
void
reset_last_event();
void
show_all_events();
# endif
#else
# define DO_DEBUG(l, x)
# define DO_ASSERT(x)
# define CHECKED_OPERATION(expr) \
{ \
DWORD res = expr; \
if (res != ERROR_SUCCESS) \
return res; \
}
#endif
#define ALIGNED(x, alignment) ((((INT_PTR)x) & ((alignment)-1)) == 0)
#define ALIGN_BACKWARD(x, alignment) (((INT_PTR)x) & (~((alignment)-1)))
#define ALIGN_FORWARD(x, alignment) \
((((INT_PTR)x) + ((alignment)-1)) & (~((alignment)-1)))
#ifdef __cplusplus
}
#endif
#endif