0xc00007b oder Installieren von Treibern unter dem Programm

Eintrag


Guten Tag. Kennen Sie die Ausnahme 0xc00007b ? Seit der Übertragung der X-Ray- Engine auf x64 gab es viele Berichte über das 0cx00007b-Problem. In 90% der Fälle war dies ein Problem mit dem Fehlen eines 64-Bit-OpenAL-Treibers.


Ideen zur Lösung des Problems


Zuerst haben wir ständig geantwortet, dass Sie den Treiber installieren müssen. Nach ein paar Monaten haben wir eine FAQ zum Start und zu möglichen Problemen geschrieben. Aber solche Berichte sind nicht verschwunden, die Leute in unserer GUS lesen nicht besonders gern, deshalb haben wir beschlossen, das Problem radikal zu lösen: Installieren Sie den Treiber unter dem Motor, falls es keinen gibt.


Schritt 1: Starten des Programms, wenn die DLL nicht ausreicht


Der einfachste Weg, Bibliotheken miteinander zu verbinden, ist das Erstellen ( Pragma-Kommentar ). In unserem Fall ist dies jedoch nicht möglich.


Also, Schritt 1: explizite Verknüpfung oder hi extern "C" .


Was wir brauchen: Exe aus den Engine-Bibliotheken lösen. Dies geschieht folgendermaßen:


1) Wir nehmen die Funktion zum Starten der Engine in der dynamischen Bibliothek heraus:


 extern "C" --// LoadLibrary,     ,  API { void ENGINE_API RunApplication(LPCSTR commandLine) { ... // Your code } } 

2) Rufen Sie die Funktion von unserer Exe auf:


 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; } 

Schritt 2: Fahrerprüfung


Nun, alles ist einfach, wir bekommen ein System (vielleicht wird jemand überrascht sein, aber das Betriebssystem befindet sich nicht immer im Abschnitt C :) und überprüfen Sie die DLL im Treiberordner:


 /// 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; } 

Schritt 3: Datei nicht gefunden


Zunächst müssen wir den Administrator nach den Benutzerrechten fragen, weil muss mit dem Systemverzeichnis arbeiten:


 // ,      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()); } } 

Stufe zwei: Kopieren Sie die Bibliothek in das 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; // ,    ,    } } 

Fazit


Natürlich ist die Methode sehr lustig, aber für solche Projekte geeignet. Viel Glück an alle!

Source: https://habr.com/ru/post/de431842/


All Articles