DllManager.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "DllManager.h"
  2. #ifndef _XBOX
  3. #include <strsafe.h>
  4. #endif
  5. DllManager::DllManager(const char * coreModuleNameForSkip) : dlls(_FL_, 4)
  6. {
  7. dlls.Reserve(32);
  8. //Добавляем запись об модуле ядра
  9. if(string::NotEmpty(coreModuleNameForSkip))
  10. {
  11. DllDesc & desc = dlls[dlls.Add()];
  12. desc.handle = null;
  13. desc.first = null;
  14. desc.versionId = null;
  15. desc.path = coreModuleNameForSkip;
  16. }
  17. }
  18. DllManager::~DllManager()
  19. {
  20. Unload();
  21. }
  22. //Загрузить модули быстрого запуска
  23. bool DllManager::LoadQuickModules(const char * quickModules)
  24. {
  25. if(!quickModules) return true;
  26. string modulesPath;
  27. GetModulesPath(modulesPath);
  28. string currentPath;
  29. currentPath.Reserve(modulesPath.Len() + 64);
  30. while(*quickModules)
  31. {
  32. const char * name = quickModules;
  33. //Проверяем имя на отсутствие слэшей
  34. for(const char * n = name; *n; n++)
  35. {
  36. if(*n == '\\' || *n == '/')
  37. {
  38. CoreLogOut("Invalidate quick module name: \"%s\"", name);
  39. return false;
  40. }
  41. }
  42. //Загружаем модуль
  43. currentPath = modulesPath;
  44. currentPath += name;
  45. if(!LoadDll(currentPath.c_str()))
  46. {
  47. CoreLogOut("Error load quick module. (\"%s\")", currentPath.c_str());
  48. return false;
  49. }
  50. CoreLogOut("Load quick module: \"%s\"", currentPath.c_str());
  51. //Ищим следующее имя
  52. while(*quickModules) quickModules++;
  53. quickModules++;
  54. }
  55. return true;
  56. }
  57. //Загрузить модули
  58. void DllManager::LoadModules()
  59. {
  60. //Получаем текущую директорию и маску
  61. string modulesPath;
  62. GetModulesPath(modulesPath);
  63. string currentPath;
  64. currentPath.Reserve(modulesPath.Len() + 64);
  65. string findMask;
  66. findMask.Reserve(modulesPath.Len() + 8);
  67. findMask = modulesPath;
  68. #ifndef _XBOX
  69. findMask += "*.dll";
  70. #else
  71. findMask += "*.xdl";
  72. #endif
  73. //Первый запрос
  74. WIN32_FIND_DATA findData;
  75. HANDLE hFind = ::FindFirstFile(findMask.GetBuffer(), &findData);
  76. if(hFind == INVALID_HANDLE_VALUE) return;
  77. //Последовательный просмотр модулей
  78. do
  79. {
  80. //Формируем имя
  81. findData.cFileName[sizeof(findData.cFileName) - 1] = 0;
  82. currentPath = modulesPath;
  83. currentPath += findData.cFileName;
  84. //Загружаем модуль
  85. if(LoadDll(currentPath.c_str()))
  86. {
  87. CoreLogOut("Load module: \"%s\"", currentPath.c_str());
  88. }
  89. }while(::FindNextFile(hFind, &findData));
  90. //Заканчиваем поиск
  91. FindClose(hFind);
  92. }
  93. //Получить количество подключёных модулей
  94. long DllManager::GetCount()
  95. {
  96. return (long)dlls.Size();
  97. }
  98. //Получить первый дескриптор
  99. StormEngine_Declarator * DllManager::GetFirst(long i)
  100. {
  101. return dlls[i].first;
  102. }
  103. //Выгрузить все модули
  104. void DllManager::Unload()
  105. {
  106. for(long i = 0; i < dlls; i++)
  107. {
  108. if(dlls[i].handle)
  109. {
  110. FreeLibrary(dlls[i].handle);
  111. }
  112. }
  113. dlls.DelAll();
  114. }
  115. //Занести данные о загруженных модулях в базу данных
  116. void DllManager::PutInfoToStorage(ICoreStorageFolder & root)
  117. {
  118. string moduleName;
  119. string storagePath;
  120. for(long i = 0; i < dlls; i++)
  121. {
  122. if(!dlls[i].handle)
  123. {
  124. continue;
  125. }
  126. moduleName.GetFileTitle(dlls[i].path);
  127. storagePath = "system.core.modules.";
  128. storagePath += moduleName;
  129. storagePath += ".version";
  130. const char * versionId = dlls[i].versionId ? dlls[i].versionId : "unknown";
  131. root.SetString(storagePath.c_str(), versionId);
  132. storagePath = "system.core.modules.";
  133. storagePath += moduleName;
  134. storagePath += ".path";
  135. root.SetString(storagePath.c_str(), dlls[i].path.c_str());
  136. }
  137. }
  138. //Описание функции инициализации
  139. typedef void (_cdecl * StormEngine_InitDll)(ICore * core, StormEngine_Declarator * & first, const char * & verId, long init_rand);
  140. //Загрузить с проверкой библиотеку
  141. bool DllManager::LoadDll(const char * dllName)
  142. {
  143. //CoreLogOut("Loading module \"%s\"", dllName);
  144. //Проверяем модуль среди загруженных
  145. const char * fileName = FileFileName(dllName);
  146. for(dword i = 0; i < dlls.Size(); i++)
  147. {
  148. const char * fn = FileFileName(dlls[i].path.c_str());
  149. if(string::IsEqual(fileName, fn))
  150. {
  151. //Уже загружен данный модуль, пропускаем его
  152. return true;
  153. }
  154. }
  155. //Загружаем библиотеку
  156. DllDesc desc;
  157. desc.handle = ::LoadLibrary(dllName);
  158. if(!desc.handle)
  159. {
  160. #ifndef _XBOX
  161. LPTSTR lpszFunction = "LoadLibrary";
  162. DWORD dwLoadError = GetLastError();
  163. LPVOID lpMsgBuf;
  164. LPVOID lpDisplayBuf;
  165. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwLoadError,
  166. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
  167. // Display the error message and exit the process
  168. lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
  169. StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dwLoadError, lpMsgBuf);
  170. CoreLogOut("Core error: can't load library \"%s\", error code : 0x%08X, reason : '%s'", dllName, dwLoadError, (LPCTSTR)lpDisplayBuf);
  171. LocalFree(lpMsgBuf);
  172. LocalFree(lpDisplayBuf);
  173. #else
  174. CoreLogOut("Core error: can't load library \"%s\"", dllName);
  175. #endif
  176. return false;
  177. }
  178. //Получаем указатель на функцию инициализации
  179. StormEngine_InitDll init = (StormEngine_InitDll)GetProcAddress(desc.handle, "StormEngine_InitDll");
  180. if(!init)
  181. {
  182. CoreLogOut("Core error: can't get core interface function in library \"%s\"", dllName);
  183. FreeLibrary(desc.handle);
  184. return false;
  185. }
  186. //Подключаем библиотеку
  187. init(api, desc.first, desc.versionId, rand());
  188. dlls[dlls.Add(desc)].path = dllName;
  189. return true;
  190. }
  191. //Найти указатель на имя файла в пути
  192. const char * DllManager::FileFileName(const char * filePath)
  193. {
  194. if(!filePath) return null;
  195. for(long i = string::Len(filePath); i >= 0; i--)
  196. {
  197. char c = filePath[i];
  198. if(c == '\\' || c == '/')
  199. {
  200. break;
  201. }
  202. }
  203. return filePath + i + 1;
  204. }
  205. //Получить директорию c модулями
  206. void DllManager::GetModulesPath(string & path)
  207. {
  208. #ifndef _XBOX
  209. const long maxSize = 4096;
  210. char * tmpCurDir = NEW char[maxSize];
  211. GetCurrentDirectory(maxSize - 1, tmpCurDir);
  212. tmpCurDir[maxSize - 1] = 0;
  213. path = tmpCurDir;
  214. delete tmpCurDir;
  215. tmpCurDir = null;
  216. //Формируем директорию в которой модули
  217. path += "\\"; path += Core_DllsFolder; path += "\\";
  218. #else
  219. path = "D:\\";
  220. #endif
  221. }