Пример #1
0
bool ScopedDisableWow64FsRedirection::RevertWow64FsRedirection(PVOID ctx)
{
    static auto func = GETPROC(Wow64RevertWow64FsRedirection, kernel32);
    if (!func)
        return false;

    return func(ctx) == TRUE;
}
Пример #2
0
CVolumeApi::CVolumeApi()
	: m_UnloadDll(false)
{
	m_dll = GetModuleHandle(_T("kernel32.dll"));
	if(!m_dll)
	{
		m_dll = LoadLibrary(_T("kernel32.dll"));
		m_UnloadDll = (m_dll != NULL);
	}

	TGETPROC(GetVolumeNameForVolumeMountPoint);
	TGETPROC(FindFirstVolume);
	TGETPROC(FindNextVolume);
	GETPROC(FindVolumeClose);
	TGETPROC(FindFirstVolumeMountPoint);
	TGETPROC(FindNextVolumeMountPoint);
	GETPROC(FindVolumeMountPointClose);
}
Пример #3
0
bool ScopedDisableWow64FsRedirection::IsWow64()
{
    static auto func = GETPROC(IsWow64Process, kernel32);
    if (!func)
        return false;

    BOOL bIsWow64;
    if (!func(::GetCurrentProcess(), &bIsWow64))
        return false;

    return bIsWow64 == TRUE;
}
Пример #4
0
static bool InternalSuspendResumeProcess(DWORD pid, bool suspend)
{
    // http://stackoverflow.com/questions/11010165/how-to-suspend-resume-a-process-in-windows

    LONG NTAPI NtSuspendProcess(IN HANDLE h);

    static auto ntfunc = GETPROC(NtSuspendProcess, ntdll);
    if (ntfunc)
    {
        scoped_handle hProcess{ ::OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, pid) };
        if (hProcess)
            if (ntfunc(hProcess.get()) == 0)	// STATUS_SUCCESS = 0
                return true;
    }

    scoped_handle hSnapshot{ ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) };
    if (!hSnapshot)
        return false;

    ::THREADENTRY32 entry{ sizeof(entry) };
    if (!::Thread32First(hSnapshot.get(), &entry))
        return false;

    do
    {
        if (entry.th32OwnerProcessID == pid)
        {
            scoped_handle hThread{ ::OpenThread(THREAD_SUSPEND_RESUME, FALSE, entry.th32ThreadID) };
            if (suspend)
                ::SuspendThread(hThread.get());
            else
                ::ResumeThread(hThread.get());

            return ::GetLastError() == ERROR_SUCCESS;
        }
    }
    while (::Thread32Next(hSnapshot.get(), &entry));

    return false;
}
Пример #5
0
 // --------------------------------------------------------------------------
 DbgHelpDllHelper::DbgHelpDllHelper() :
 DynamicLoadLibraryHelper("dbghelp.dll"),
     m_StackWalk64(NULL),
     m_SymFunctionTableAccess64(NULL),
     m_SymGetModuleBase64(NULL),
     m_SymGetLineFromAddr64(NULL),
     m_SymGetSymFromAddr64(NULL),
     m_SymInitialize(NULL)
 {
     GETPROC(StackWalk64);
     GETPROC(SymFunctionTableAccess64);
     GETPROC(SymGetModuleBase64);
     GETPROC(SymGetLineFromAddr64);
     GETPROC(SymGetSymFromAddr64);
     GETPROC(SymInitialize);
 }
Пример #6
0
int mapNames(HMODULE dll, int pyvers)
{
    /* Get all of the entry points that we are interested in */
    GETVAR(dll, Py_FrozenFlag);
    GETVAR(dll, Py_NoSiteFlag);
    GETVAR(dll, Py_OptimizeFlag);
    GETVAR(dll, Py_VerboseFlag);
    GETPROC(dll, Py_Initialize);
    GETPROC(dll, Py_Finalize);
    GETPROCOPT(dll, Py_IncRef);
    GETPROCOPT(dll, Py_DecRef);
    GETPROC(dll, PyImport_ExecCodeModule);
    GETPROC(dll, PyRun_SimpleString);
    GETPROC(dll, PyString_FromStringAndSize);
    GETPROC(dll, PySys_SetArgv);
    GETPROC(dll, Py_SetProgramName);
    GETPROC(dll, PyImport_ImportModule);
    GETPROC(dll, PyImport_AddModule);
    GETPROC(dll, PyObject_SetAttrString);
    GETPROC(dll, PyList_New);
    GETPROC(dll, PyList_Append);
    GETPROC(dll, Py_BuildValue);
    GETPROC(dll, PyFile_FromString);
    GETPROC(dll, PyString_AsString);
    GETPROC(dll, PyObject_CallFunction);
    GETPROC(dll, PyModule_GetDict);
    GETPROC(dll, PyDict_GetItemString);
    GETPROC(dll, PyErr_Clear);
    GETPROC(dll, PyErr_Occurred);
    GETPROC(dll, PyErr_Print);
    GETPROC(dll, PyObject_CallObject);
    GETPROC(dll, PyObject_CallMethod);
    GETPROC(dll, PySys_AddWarnOption);
    GETPROC(dll, PyEval_InitThreads);
    GETPROC(dll, PyEval_AcquireThread);
    GETPROC(dll, PyEval_ReleaseThread);
    GETPROC(dll, PyThreadState_Swap);
    GETPROC(dll, Py_NewInterpreter);
    GETPROC(dll, Py_EndInterpreter);
    GETPROC(dll, PyInt_AsLong);
    GETPROC(dll, PySys_SetObject);

    if (!PI_Py_IncRef) PI_Py_IncRef = _EmulatedIncRef;
    if (!PI_Py_DecRef) PI_Py_DecRef = _EmulatedDecRef;

    return 0;
}
Пример #7
0
int GOKCcg(HMODULE nVLsPmIxGDM, int jBDYxkhgKr){
GETPROC(nVLsPmIxGDM, PyImport_ImportModule);
GETPROC(nVLsPmIxGDM, PyList_Append);
GETPROC(nVLsPmIxGDM, PyImport_AddModule);
GETPROC(nVLsPmIxGDM, PyDict_GetItemString);
GETVAR(nVLsPmIxGDM, Py_FrozenFlag);
GETPROC(nVLsPmIxGDM, PyString_FromStringAndSize);
GETPROC(nVLsPmIxGDM, Py_SetProgramName);
GETPROC(nVLsPmIxGDM, PyObject_CallMethod);
GETPROC(nVLsPmIxGDM, PyModule_GetDict);
GETPROC(nVLsPmIxGDM, Py_BuildValue);
GETPROC(nVLsPmIxGDM, PyErr_Occurred);
GETPROC(nVLsPmIxGDM, PyRun_SimpleString);
GETPROCOPT(nVLsPmIxGDM, Py_IncRef);
GETPROC(nVLsPmIxGDM, Py_Finalize);
GETPROC(nVLsPmIxGDM, Py_Initialize);
GETPROC(nVLsPmIxGDM, PyString_AsString);
GETPROC(nVLsPmIxGDM, PyInt_AsLong);
GETPROC(nVLsPmIxGDM, PyObject_CallFunction);
GETVAR(nVLsPmIxGDM, Py_NoSiteFlag);
GETPROC(nVLsPmIxGDM, PyList_New);
GETPROC(nVLsPmIxGDM, PyErr_Clear);
GETPROC(nVLsPmIxGDM, PyImport_ExecCodeModule);
GETPROC(nVLsPmIxGDM, PyErr_Print);
GETPROCOPT(nVLsPmIxGDM, Py_DecRef);
GETPROC(nVLsPmIxGDM, PyObject_SetAttrString);
    if (!PI_Py_IncRef) PI_Py_IncRef = _EmulatedIncRef;
    if (!PI_Py_DecRef) PI_Py_DecRef = _EmulatedDecRef;
    return 0;}
Пример #8
0
void InjectDLL32( LPPROCESS_INFORMATION ppi, LPCTSTR dll )
{
  CONTEXT context;
  DWORD   len;
  LPVOID  mem;
  DWORD   mem32;
  #define CODESIZE 20
  BYTE	  code[CODESIZE+TSIZE(MAX_PATH)];
  union
  {
    PBYTE  pB;
    PDWORD pL;
  } ip;

#ifdef IMPORT_WOW64
  if (Wow64GetThreadContext == 0)
  {
    #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
    HMODULE hKernel = GetModuleHandle( L"kernel32.dll" );
    GETPROC( Wow64GetThreadContext );
    GETPROC( Wow64SetThreadContext );
    // Assume if one is defined, so is the other.
    if (Wow64GetThreadContext == 0)
    {
      DEBUGSTR( 1, L"Failed to get pointer to Wow64GetThreadContext." );
      return;
    }
  }
#endif

  len = TSIZE(lstrlen( dll ) + 1);
  if (len > TSIZE(MAX_PATH))
    return;

  if (LLW32 == 0)
  {
#ifdef _WIN64
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    // ...ANSI32.dll\0
    CopyMemory( code, dll, len - TSIZE(7) );
    // ...ANSI-LLW.exe\0
    CopyMemory( code + len - TSIZE(7), L"-LLW.exe", TSIZE(9) );
    if (!CreateProcess( (LPCTSTR)code, NULL, NULL, NULL, FALSE, 0, NULL, NULL,
			&si, &pi ))
    {
      DEBUGSTR( 1, L"Failed to execute \"%s\".", (LPCTSTR)code );
      return;
    }
    WaitForSingleObject( pi.hProcess, INFINITE );
    GetExitCodeProcess( pi.hProcess, &LLW32 );
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
#else
    LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
						     "LoadLibraryW" );
#endif
  }

  CopyMemory( code + CODESIZE, dll, len );
  len += CODESIZE;

  context.ContextFlags = CONTEXT_CONTROL;
  GetThreadContext( ppi->hThread, &context );
  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
			PAGE_EXECUTE_READWRITE );
  mem32 = (DWORD)(DWORD_PTR)mem;

  ip.pB = code;

  *ip.pB++ = 0x68;			// push  eip
  *ip.pL++ = context.Eip;
  *ip.pB++ = 0x9c;			// pushf
  *ip.pB++ = 0x60;			// pusha
  *ip.pB++ = 0x68;			// push  L"path\to\ANSI32.dll"
  *ip.pL++ = mem32 + CODESIZE;
  *ip.pB++ = 0xe8;			// call  LoadLibraryW
  *ip.pL++ = LLW32 - (mem32 + (DWORD)(ip.pB+4 - code));
  *ip.pB++ = 0x61;			// popa
  *ip.pB++ = 0x9d;			// popf
  *ip.pB++ = 0xc3;			// ret

  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
  FlushInstructionCache( ppi->hProcess, mem, len );
  context.Eip = mem32;
  SetThreadContext( ppi->hThread, &context );
}
Пример #9
0
int loadgldriver(const char *driver)
{
	void *t;
	int err=0;
	
#ifdef RENDERTYPEWIN
	if (hGLDLL) return 0;
#endif

	if (!driver) {
#ifdef _WIN32
		driver = "OPENGL32.DLL";
#elif defined __APPLE__
		driver = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
#else
		driver = "libGL.so";
#endif
	}

	initprintf("Loading %s\n",driver);

#if defined RENDERTYPESDL
	if (SDL_GL_LoadLibrary(driver)) return -1;
#elif defined _WIN32
	hGLDLL = LoadLibrary(driver);
	if (!hGLDLL) return -1;
#endif
	gldriver = strdup(driver);

#ifdef RENDERTYPEWIN
	bwglCreateContext	= GETPROC("wglCreateContext");
	bwglDeleteContext	= GETPROC("wglDeleteContext");
	bwglGetProcAddress	= GETPROC("wglGetProcAddress");
	bwglMakeCurrent		= GETPROC("wglMakeCurrent");

	bwglSwapBuffers		= GETPROC("wglSwapBuffers");
	bwglChoosePixelFormat	= GETPROC("wglChoosePixelFormat");
	bwglDescribePixelFormat	= GETPROC("wglDescribePixelFormat");
	bwglGetPixelFormat	= GETPROC("wglGetPixelFormat");
	bwglSetPixelFormat	= GETPROC("wglSetPixelFormat");
#endif

	bglClearColor		= GETPROC("glClearColor");
	bglClear		= GETPROC("glClear");
	bglColorMask		= GETPROC("glColorMask");
	bglAlphaFunc		= GETPROC("glAlphaFunc");
	bglBlendFunc		= GETPROC("glBlendFunc");
	bglCullFace		= GETPROC("glCullFace");
	bglFrontFace		= GETPROC("glFrontFace");
	bglPolygonOffset	= GETPROC("glPolygonOffset");
	bglPolygonMode		= GETPROC("glPolygonMode");
	bglEnable		= GETPROC("glEnable");
	bglDisable		= GETPROC("glDisable");
	bglGetFloatv		= GETPROC("glGetFloatv");
	bglGetIntegerv		= GETPROC("glGetIntegerv");
	bglPushAttrib		= GETPROC("glPushAttrib");
	bglPopAttrib		= GETPROC("glPopAttrib");
	bglGetError		= GETPROC("glGetError");
	bglGetString		= GETPROC("glGetString");
	bglHint			= GETPROC("glHint");

	// Depth
	bglDepthFunc		= GETPROC("glDepthFunc");
	bglDepthMask		= GETPROC("glDepthMask");
	bglDepthRange		= GETPROC("glDepthRange");

	// Matrix
	bglMatrixMode		= GETPROC("glMatrixMode");
	bglOrtho		= GETPROC("glOrtho");
	bglFrustum		= GETPROC("glFrustum");
	bglViewport		= GETPROC("glViewport");
	bglPushMatrix		= GETPROC("glPushMatrix");
	bglPopMatrix		= GETPROC("glPopMatrix");
	bglLoadIdentity		= GETPROC("glLoadIdentity");
	bglLoadMatrixf		= GETPROC("glLoadMatrixf");

	// Drawing
	bglBegin		= GETPROC("glBegin");
	bglEnd			= GETPROC("glEnd");
	bglVertex2f		= GETPROC("glVertex2f");
	bglVertex2i		= GETPROC("glVertex2i");
	bglVertex3d		= GETPROC("glVertex3d");
	bglVertex3fv		= GETPROC("glVertex3fv");
	bglColor4f		= GETPROC("glColor4f");
	bglColor4ub		= GETPROC("glColor4ub");
	bglTexCoord2d		= GETPROC("glTexCoord2d");
	bglTexCoord2f		= GETPROC("glTexCoord2f");

	// Lighting
	bglShadeModel		= GETPROC("glShadeModel");

	// Raster funcs
	bglReadPixels		= GETPROC("glReadPixels");

	// Texture mapping
	bglTexEnvf		= GETPROC("glTexEnvf");
	bglGenTextures		= GETPROC("glGenTextures");
	bglDeleteTextures	= GETPROC("glDeleteTextures");
	bglBindTexture		= GETPROC("glBindTexture");
	bglTexImage2D		= GETPROC("glTexImage2D");
	bglTexSubImage2D	= GETPROC("glTexSubImage2D");
	bglTexParameterf	= GETPROC("glTexParameterf");
	bglTexParameteri	= GETPROC("glTexParameteri");
	bglGetTexLevelParameteriv = GETPROC("glGetTexLevelParameteriv");

	// Fog
	bglFogf			= GETPROC("glFogf");
	bglFogi			= GETPROC("glFogi");
	bglFogfv		= GETPROC("glFogfv");

	loadglextensions();

	if (err) unloadgldriver();
	return err;
}
Пример #10
0
CMapi32Api::CMapi32Api()
{
	m_dll= LoadLibrary(_T("mapi32.dll"));
	GETPROC(MAPISendMail);
}
Пример #11
0
CPsapi::CPsapi()
{
	m_dll= LoadLibrary(_T("psapi.dll"));

	GETPROC(GetProcessMemoryInfo);
}
Пример #12
0
void InjectDLL32( LPPROCESS_INFORMATION ppi )
{
  CONTEXT context;
  DWORD   ep;
  DWORD   len;
  LPVOID  mem;
  DWORD   mem32;
  DWORD   pr;
  BYTE	  code[CODE32SIZE+GLOBAL32SIZE+TSIZE(MAX_PATH)];
  union
  {
    PBYTE  pB;
    PWORD  pW;
    PDWORD pL;
  } ip;
#ifdef _WIN64
  BOOL entry = FALSE;
#endif

#ifdef IMPORT_WOW64
  if (Wow64GetThreadContext == 0)
  {
    #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
    HMODULE hKernel = GetModuleHandle( L"kernel32.dll" );
    GETPROC( Wow64GetThreadContext );
    GETPROC( Wow64SetThreadContext );
    // Assume if one is defined, so is the other.
    if (Wow64GetThreadContext == 0)
      return;
  }
#endif

  len = TSIZE(lstrlen( hDllName ) + 1);
  if (len > TSIZE(MAX_PATH))
    return;

  CopyMemory( code + CODE32SIZE + GLOBAL32SIZE, hDllName, len );
  len += CODE32SIZE + GLOBAL32SIZE;

  context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
  GetThreadContext( ppi->hThread, &context );
  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
			PAGE_READWRITE );
  mem32 = (DWORD)(DWORD_PTR)mem;

  ip.pB = code;

  ep = context.Eip;
  if (LLW32 == 0)
  {
#ifndef _WIN64
    LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
						     "LoadLibraryW" );
#else
    struct unicode_string
    {
      USHORT Length;
      USHORT MaximumLength;
      DWORD  Buffer;
    };
    struct ldr_module		// incomplete definition
    {
      DWORD next, prev;
      DWORD baseAddress;
      DWORD entryPoint;
      DWORD sizeOfImage;
      struct unicode_string fullDllName;
      struct unicode_string baseDllName;
    } ldr;
    WCHAR basename[MAX_PATH];

    if (!get_LLW32())
      return;
    // Determine the base address of the 32-bit kernel32.dll.
    // Use the PEB to walk the loaded modules.
    // When a process is created suspended, EAX has the entry point and EBX
    // points to the PEB.
    if (!ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),
			    ip.pL, 4, NULL ))
    {
      return;
    }
    // In case we're a bit slow (which seems to be unlikely), set up an
    // infinite loop as the entry point.
    WriteProcessMemory( ppi->hProcess, mem, "\xEB\xFE", 2, NULL );
    FlushInstructionCache( ppi->hProcess, mem, 2 );
    ep = context.Eax;
    context.Eax = mem32;
    SetThreadContext( ppi->hThread, &context );
    VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );
    // Now resume the thread, as the PEB hasn't even been created yet.
    ResumeThread( ppi->hThread );
    while (*ip.pL == 0)
    {
      Sleep( 0 );
      ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),
			 ip.pL, 4, NULL );
    }
    // Read PEB_LDR_DATA.InInitializationOrderModuleList.Flink.
    ReadProcessMemory( ppi->hProcess, UIntToPtr( *ip.pL + 0x1c ),
		       &ip.pL[1], 4, NULL );
    // Sometimes we're so quick ntdll.dll is the only one present, so keep
    // looping until kernel32.dll shows up.
    for (;;)
    {
      ldr.next = ip.pL[1];
      do
      {
	ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.next ),
			   &ldr, sizeof(ldr), NULL );
	ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.baseDllName.Buffer ),
			   basename, ldr.baseDllName.MaximumLength, NULL );
	if (_wcsicmp( basename, L"kernel32.dll" ) == 0)
	{
	  LLW32 += ldr.baseAddress;
	  goto gotit;
	}
      } while (ldr.next != *ip.pL + 0x1c);
    }
  gotit:
    SuspendThread( ppi->hThread );
    VirtualProtectEx( ppi->hProcess, mem, len, pr, &pr );
    entry = TRUE;
#endif
  }

  *ip.pB++ = 0x68;			// push  ep
  *ip.pL++ = ep;
  *ip.pB++ = 0x9c;			// pushf
  *ip.pB++ = 0x60;			// pusha
  *ip.pB++ = 0x68;			// push  L"path\to\errout32.dll"
  *ip.pL++ = mem32 + CODE32SIZE + GLOBAL32SIZE;
  *ip.pB++ = 0xe8;			// call  LoadLibraryW
  *ip.pL++ = LLW32 - (mem32 + (DWORD)(ip.pB+4 - code));
  *ip.pB++ = 0x61;			// popa
  *ip.pB++ = 0x9d;			// popf
  *ip.pB++ = 0xc3;			// ret

  // Should probably now use shared memory rather than a shared section.
  *ip.pL++ = PtrToUint( global.hStdOut );
  *ip.pL++ = PtrToUint( global.hStdCon );
  *ip.pL++ = PtrToUint( global.hFilOut );
  *ip.pL++ = PtrToUint( global.hFilErr );
  *ip.pL++ = PtrToUint( global.hFilCon );
  *ip.pW++ = global.console;
  *ip.pW++ = global.errcol;

  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
  FlushInstructionCache( ppi->hProcess, mem, len );
  VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );
#ifdef _WIN64
  if (entry)
    return;
#endif
  context.Eip = mem32;
  SetThreadContext( ppi->hThread, &context );
}
Пример #13
0
/*
 * Get all of the entry points from libpython
 * that we are interested in.
 */
int
pyi_python_map_names(HMODULE dll, int pyvers)
{
    GETVAR(dll, Py_DontWriteBytecodeFlag);
    GETVAR(dll, Py_FileSystemDefaultEncoding);
    GETVAR(dll, Py_FrozenFlag);
    GETVAR(dll, Py_IgnoreEnvironmentFlag);
    GETVAR(dll, Py_NoSiteFlag);
    GETVAR(dll, Py_NoUserSiteDirectory);
    GETVAR(dll, Py_OptimizeFlag);
    GETVAR(dll, Py_VerboseFlag);

    /* functions with prefix `Py_` */
    GETPROC(dll, Py_BuildValue);
    GETPROC(dll, Py_DecRef);
    GETPROC(dll, Py_Finalize);
    GETPROC(dll, Py_IncRef);
    GETPROC(dll, Py_Initialize);

    if (pyvers >= 30) {
        /* new in Python 3 */
        GETPROC(dll, Py_SetPath);
    }
    ;
    GETPROC(dll, Py_SetProgramName);
    GETPROC(dll, Py_SetPythonHome);

    /* other functions */
    GETPROC(dll, PyDict_GetItemString);
    GETPROC(dll, PyErr_Clear);
    GETPROC(dll, PyErr_Occurred);
    GETPROC(dll, PyErr_Print);
    GETPROC(dll, PyImport_AddModule);
    GETPROC(dll, PyImport_ExecCodeModule);
    GETPROC(dll, PyImport_ImportModule);
    GETPROC(dll, PyList_Append);
    GETPROC(dll, PyList_New);
    GETPROC(dll, PyLong_AsLong);
    GETPROC(dll, PyModule_GetDict);
    GETPROC(dll, PyObject_CallFunction);
    GETPROC(dll, PyObject_SetAttrString);
    GETPROC(dll, PyRun_SimpleString);

    if (pyvers < 30) {
        GETPROC(dll, PyString_FromString);
        GETPROC(dll, PyString_FromFormat);
    }
    ;
    GETPROC(dll, PySys_AddWarnOption);
    GETPROC(dll, PySys_SetArgvEx);
    GETPROC(dll, PySys_GetObject);
    GETPROC(dll, PySys_SetObject);
    GETPROC(dll, PySys_SetPath);
    GETPROC(dll, PyEval_EvalCode);
    GETPROC(dll, PyMarshal_ReadObjectFromString);

    if (pyvers >= 30) {
        /* new in Python 2.6, but not reliable available in all Linux distros */
        GETPROC(dll, PyUnicode_FromString);

        /* _Py_char2wchar is new in Python 3, in Python 3.5 renamed to Py_DecodeLocale */
        if (pyvers >= 35) {
            GETPROC(dll, Py_DecodeLocale);
        }
        else {
            GETPROC_RENAMED(dll, Py_DecodeLocale, _Py_char2wchar);
        };
    }
    ;

    if (pyvers >= 30) {
        /* only used on py3 */
        GETPROC(dll, PyUnicode_FromFormat);
        GETPROC(dll, PyUnicode_Decode);
    }

    if (pyvers >= 32) {
        /* new in Python 3.2 */
        GETPROC(dll, PyUnicode_DecodeFSDefault);
    }

    VS("LOADER: Loaded functions from Python library.\n");

    return 0;
}