0xc00007b ou installation de pilotes sous le programme

Entrée


Bonjour. Connaissez -vous l' exception 0xc00007b ? Depuis le transfert du moteur X-Ray en x64, il y a eu beaucoup de rapports sur le problème 0cx00007b. Dans 90% des cas, il s'agissait d'un problème lié à l'absence d'un pilote OpenAL 64 bits.


Des idées pour résoudre le problème


Au début, nous avons constamment répondu que vous devez installer le pilote, après quelques mois, nous avons écrit une FAQ sur le démarrage et les problèmes possibles. Mais de tels rapports n'ont pas disparu, les gens de notre CEI n'aiment pas particulièrement lire, alors nous avons décidé de résoudre le problème radicalement: installez le pilote sous le moteur, s'il n'y en a pas.


Étape 1: démarrer le programme lorsque la DLL n'est pas suffisante


La façon la plus simple de connecter des bibliothèques les unes aux autres est de construire ( commentaire pragma ), mais dans notre cas, cela ne peut pas être fait.


Donc, étape 1: lien explicite ou hi extern "C" .


Ce dont nous avons besoin: détacher exe des bibliothèques de moteurs. Cela se fait de la manière suivante:


1) Nous retirons la fonction de démarrage du moteur dans la bibliothèque dynamique:


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

2) Appelez la fonction depuis notre 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; } 

Étape 2: vérification du pilote


Eh bien, tout est simple, nous obtenons un système (peut-être que quelqu'un sera surpris, mais le système d'exploitation n'est pas toujours dans la section C :) et vérifiez la DLL dans le dossier du pilote:


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

Étape 3: fichier introuvable


Tout d'abord, nous devons demander à l'administrateur les droits d'utilisateur, car devra travailler avec le répertoire système:


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

Deuxième étape: copier la bibliothèque sur le système


 { ... // 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; // ,    ,    } } 

Conclusion


Bien sûr, la méthode est très drôle, mais adaptée à de tels projets. Bonne chance à tous!

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


All Articles