Good day. Are you familiar with the exception 0xc00007b ? Since the transfer of the X-Ray engine for x64, there have been a lot of reports about the 0cx00007b problem. In 90% of cases, it was a problem with the lack of a 64 bit OpenAL driver.
At first, we constantly answered that we need to install the driver, after a couple of months we wrote a FAQ on the launch and possible problems. But such reports did not go away, the people in our CIS do not particularly like to read, so we decided to solve the problem radically: install the driver from under the engine, if there is no one.
The easiest way to connect libraries to each other is to build ( pragma comment ), but in our case this is not possible.
So, step 1: explicit linking or hi extern "C"
.
What we need: untie exe from engine libraries. This is done in the following way:
1) We bring the engine launch function to the dynamic library:
extern "C" --// LoadLibrary, , API { void ENGINE_API RunApplication(LPCSTR commandLine) { ... // Your code } }
2) Call the function from our exe:
using RunFunc = void(__cdecl*)(const char*); // bool OpenALFound = false; // int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if(OpenALFound) { HMODULE hLib = LoadLibrary("xrEngine.dll"); // IsRunFunc RunFunc = (IsRunFunc)GetProcAddress(hLib, "RunApplication"); // RunFunc(params); // } return 0; }
Well, everything is simple, we get the system one (maybe someone will be surprised, but the OS is not always on the C :) partition and check the dll in the driver folder:
/// R_ASSERT - , , - ... // WinMain code TCHAR szOpenALDir[MAX_PATH] = { 0 }; // R_ASSERT(GetSystemDirectory(szOpenALDir, MAX_PATH * sizeof(TCHAR))); #ifndef UNICODE _snprintf_s(szOpenALDir, MAX_PATH * sizeof(CHAR), "%s%s", szOpenALDir, "\\OpenAL32.dll"); #else _snwprintf_s(szOpenALDir, MAX_PATH * sizeof(WCHAR), L"%s%s", szOpenALDir, L"\\OpenAL32.dll"); #endif DWORD dwOpenALInstalled = GetFileAttributes(szOpenALDir); // , . , . if (dwOpenALInstalled != INVALID_FILE_ATTRIBUTES) { OpenALFound = true; }
First of all, we need to ask the administrator for user rights, since Will have to work with the system directory:
// , bool IsProcessWithAdminPrivilege() { SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; LPVOID pAdministratorsGroup = nullptr; BOOL bRet = FALSE; // init SID to control privileges AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsGroup); // ckeck membership CheckTokenMembership(nullptr, pAdministratorsGroup, &bRet); // clean pointer if (pAdministratorsGroup) { FreeSid(pAdministratorsGroup); pAdministratorsGroup = nullptr; } return !!bRet; } { ...// WinMain code // , if (!IsProcessWithAdminPrivilege()) { TCHAR szPathToLib[MAX_PATH] = { 0 }; GetModuleFileName(nullptr, szPathToLib, ARRAYSIZE(szPathToLib)); SHELLEXECUTEINFO shellInfo = { sizeof(SHELLEXECUTEINFO) }; shellInfo.lpVerb = TEXT("runas"); shellInfo.lpFile = szPathToLib; shellInfo.hwnd = nullptr; shellInfo.nShow = SW_NORMAL; if (ShellExecuteEx(&shellInfo)) ExitProcess(GetCurrentProcessId()); } }
Stage two: copy the library to the system
{ ... // WinMain code TCHAR szPath[MAX_PATH] = { 0 }; // GetModuleFileName(GetModuleHandle(nullptr), szPath, MAX_PATH); PathRemoveFileSpec(szPath); #ifndef UNICODE _snprintf_s(szPath, MAX_PATH * sizeof(CHAR), "%s%s", szPath, "\\OpenAL32.dll"); #else _snwprintf_s(szPath, MAX_PATH * sizeof(WCHAR), L"%s%s", szPath, L"\\OpenAL32.dll"); #endif dwOpenALInstalled = GetFileAttributes(szPath); if (dwOpenALInstalled != INVALID_FILE_ATTRIBUTES) // , { DWORD LibrarySize = 0; HANDLE hFile = CreateFile(szPath, GENERIC_READ, NULL, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); R_ASSERT(hFile != INVALID_HANDLE_VALUE); FILE_STANDARD_INFO fileInfo = { 0 }; GetFileInformationByHandleEx(hFile, FileStandardInfo, &fileInfo, sizeof(fileInfo)); LPVOID pImage = HeapAlloc(GetProcessHeap(), 0, fileInfo.EndOfFile.QuadPart); ReadFile(hFile, pImage, fileInfo.EndOfFile.QuadPart, &LibrarySize, nullptr); CloseHandle(hFile); hFile = CreateFile(szOpenALDir, GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); R_ASSERT(hFile != INVALID_HANDLE_VALUE); WriteFile(hFile, pImage, fileInfo.EndOfFile.QuadPart, &LibrarySize, nullptr); HeapFree(GetProcessHeap(), 0, pImage); CloseHandle(hFile); OpenALFound = true; // , , } }
Of course, the method is very funny, but it is suitable for such projects. Good luck to all!
Source: https://habr.com/ru/post/431842/
All Articles