lldir_win32.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lldir_win32.cpp
  3.  * @brief Implementation of directory utilities for windows
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #if LL_WINDOWS
  33. #include "linden_common.h"
  34. #include "lldir_win32.h"
  35. #include "llerror.h"
  36. #include "llrand.h" // for gLindenLabRandomNumber
  37. #include "shlobj.h"
  38. #include <direct.h>
  39. #include <errno.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. // Utility stuff to get versions of the sh
  43. #define PACKVERSION(major,minor) MAKELONG(minor,major)
  44. DWORD GetDllVersion(LPCTSTR lpszDllName);
  45. LLDir_Win32::LLDir_Win32()
  46. {
  47. mDirDelimiter = "\";
  48. WCHAR w_str[MAX_PATH];
  49. // Application Data is where user settings go
  50. SHGetSpecialFolderPath(NULL, w_str, CSIDL_APPDATA, TRUE);
  51. mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));
  52. // We want cache files to go on the local disk, even if the
  53. // user is on a network with a "roaming profile".
  54. //
  55. // On XP this is:
  56. //   C:Docments and SettingsJamesLocal SettingsApplication Data
  57. // On Vista this is:
  58. //   C:UsersJamesAppDataLocal
  59. //
  60. // We used to store the cache in AppDataRoaming, and the installer
  61. // cleans up that version on upgrade.  JC
  62. SHGetSpecialFolderPath(NULL, w_str, CSIDL_LOCAL_APPDATA, TRUE);
  63. mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));
  64. if (GetTempPath(MAX_PATH, w_str))
  65. {
  66. if (wcslen(w_str)) /* Flawfinder: ignore */ 
  67. {
  68. w_str[wcslen(w_str)-1] = ''; /* Flawfinder: ignore */ // remove trailing slash
  69. }
  70. mTempDir = utf16str_to_utf8str(llutf16string(w_str));
  71. }
  72. else
  73. {
  74. mTempDir = mOSUserDir;
  75. }
  76. // fprintf(stderr, "mTempDir = <%s>",mTempDir);
  77. #if 1
  78. // Don't use the real app path for now, as we'll have to add parsing to detect if
  79. // we're in a developer tree, which has a different structure from the installed product.
  80. S32 size = GetModuleFileName(NULL, w_str, MAX_PATH);
  81. if (size)
  82. {
  83. w_str[size] = '';
  84. mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str));
  85. S32 path_end = mExecutablePathAndName.find_last_of('\');
  86. if (path_end != std::string::npos)
  87. {
  88. mExecutableDir = mExecutablePathAndName.substr(0, path_end);
  89. mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos);
  90. }
  91. else
  92. {
  93. mExecutableFilename = mExecutablePathAndName;
  94. }
  95. GetCurrentDirectory(MAX_PATH, w_str);
  96. mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
  97. }
  98. else
  99. {
  100. fprintf(stderr, "Couldn't get APP path, assuming current directory!");
  101. GetCurrentDirectory(MAX_PATH, w_str);
  102. mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
  103. // Assume it's the current directory
  104. }
  105. #else
  106. GetCurrentDirectory(MAX_PATH, w_str);
  107. mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
  108. #endif
  109. mAppRODataDir = ".";
  110. mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
  111. if (mExecutableDir.find("indra") == std::string::npos)
  112. {
  113. // Running from installed directory.  Make sure current
  114. // directory isn't something crazy (e.g. if invoking from
  115. // command line).
  116. SetCurrentDirectory(utf8str_to_utf16str(mExecutableDir).c_str());
  117. GetCurrentDirectory(MAX_PATH, w_str);
  118. mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
  119. }
  120. llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
  121. // Build the default cache directory
  122. mDefaultCacheDir = buildSLOSCacheDir();
  123. // Make sure it exists
  124. int res = LLFile::mkdir(mDefaultCacheDir);
  125. if (res == -1)
  126. {
  127. if (errno != EEXIST)
  128. {
  129. llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl;
  130. }
  131. }
  132. mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
  133. }
  134. LLDir_Win32::~LLDir_Win32()
  135. {
  136. }
  137. // Implementation
  138. void LLDir_Win32::initAppDirs(const std::string &app_name,
  139.   const std::string& app_read_only_data_dir)
  140. {
  141. // Allow override so test apps can read newview directory
  142. if (!app_read_only_data_dir.empty())
  143. {
  144. mAppRODataDir = app_read_only_data_dir;
  145. mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
  146. }
  147. mAppName = app_name;
  148. mOSUserAppDir = mOSUserDir;
  149. mOSUserAppDir += "\";
  150. mOSUserAppDir += app_name;
  151. int res = LLFile::mkdir(mOSUserAppDir);
  152. if (res == -1)
  153. {
  154. if (errno != EEXIST)
  155. {
  156. llwarns << "Couldn't create app user dir " << mOSUserAppDir << llendl;
  157. llwarns << "Default to base dir" << mOSUserDir << llendl;
  158. mOSUserAppDir = mOSUserDir;
  159. }
  160. }
  161. //dumpCurrentDirectories();
  162. res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,""));
  163. if (res == -1)
  164. {
  165. if (errno != EEXIST)
  166. {
  167. llwarns << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << llendl;
  168. }
  169. }
  170. res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,""));
  171. if (res == -1)
  172. {
  173. if (errno != EEXIST)
  174. {
  175. llwarns << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << llendl;
  176. }
  177. }
  178. res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,""));
  179. if (res == -1)
  180. {
  181. if (errno != EEXIST)
  182. {
  183. llwarns << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << llendl;
  184. }
  185. }
  186. res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SKIN,""));
  187. if (res == -1)
  188. {
  189. if (errno != EEXIST)
  190. {
  191. llwarns << "Couldn't create LL_PATH_SKINS dir " << getExpandedFilename(LL_PATH_USER_SKIN,"") << llendl;
  192. }
  193. }
  194. mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
  195. }
  196. U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &mask)
  197. {
  198. HANDLE count_search_h;
  199. U32 file_count;
  200. file_count = 0;
  201. WIN32_FIND_DATA FileData;
  202. llutf16string pathname = utf8str_to_utf16str(dirname);
  203. pathname += utf8str_to_utf16str(mask);
  204. if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)   
  205. {
  206. file_count++;
  207. while (FindNextFile(count_search_h, &FileData))
  208. {
  209. file_count++;
  210. }
  211.    
  212. FindClose(count_search_h);
  213. }
  214. return (file_count);
  215. }
  216. // get the next file in the directory
  217. // automatically wrap if we've hit the end
  218. BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
  219. {
  220. llutf16string dirnamew = utf8str_to_utf16str(dirname);
  221. return getNextFileInDir(dirnamew, mask, fname, wrap);
  222. }
  223. BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
  224. {
  225. WIN32_FIND_DATAW FileData;
  226. fname = "";
  227. llutf16string pathname = dirname;
  228. pathname += utf8str_to_utf16str(mask);
  229. if (pathname != mCurrentDir)
  230. {
  231. // different dir specified, close old search
  232. if (mCurrentDir[0])
  233. {
  234. FindClose(mDirSearch_h);
  235. }
  236. mCurrentDir = pathname;
  237. // and open new one
  238. // Check error opening Directory structure
  239. if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) == INVALID_HANDLE_VALUE)   
  240. {
  241. // llinfos << "Unable to locate first file" << llendl;
  242. return(FALSE);
  243. }
  244. }
  245. else // get next file in list
  246. {
  247. // Find next entry
  248. if (!FindNextFile(mDirSearch_h, &FileData))
  249. {
  250. if (GetLastError() == ERROR_NO_MORE_FILES)
  251. {
  252.                 // No more files, so reset to beginning of directory
  253. FindClose(mDirSearch_h);
  254. mCurrentDir[0] = NULL;
  255. if (wrap)
  256. {
  257. return(getNextFileInDir(pathname,"",fname,TRUE));
  258. }
  259. else
  260. {
  261. fname[0] = 0;
  262. return(FALSE);
  263. }
  264. }
  265. else
  266. {
  267. // Error
  268. // llinfos << "Unable to locate next file" << llendl;
  269. return(FALSE);
  270. }
  271. }
  272. }
  273. // convert from TCHAR to char
  274. fname = utf16str_to_utf8str(FileData.cFileName);
  275. // fname now first name in list
  276. return(TRUE);
  277. }
  278. // get a random file in the directory
  279. // automatically wrap if we've hit the end
  280. void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
  281. {
  282. S32 num_files;
  283. S32 which_file;
  284. HANDLE random_search_h;
  285. fname = "";
  286. llutf16string pathname = utf8str_to_utf16str(dirname);
  287. pathname += utf8str_to_utf16str(mask);
  288. WIN32_FIND_DATA FileData;
  289. fname[0] = NULL;
  290. num_files = countFilesInDir(dirname,mask);
  291. if (!num_files)
  292. {
  293. return;
  294. }
  295. which_file = ll_rand(num_files);
  296. // llinfos << "Random select mp3 #" << which_file << llendl;
  297.     // which_file now indicates the (zero-based) index to which file to play
  298. if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)   
  299. {
  300. while (which_file--)
  301. {
  302. if (!FindNextFile(random_search_h, &FileData))
  303. {
  304. return;
  305. }
  306. }    
  307. FindClose(random_search_h);
  308. fname = utf16str_to_utf8str(llutf16string(FileData.cFileName));
  309. }
  310. }
  311. std::string LLDir_Win32::getCurPath()
  312. {
  313. WCHAR w_str[MAX_PATH];
  314. GetCurrentDirectory(MAX_PATH, w_str);
  315. return utf16str_to_utf8str(llutf16string(w_str));
  316. }
  317. BOOL LLDir_Win32::fileExists(const std::string &filename) const
  318. {
  319. llstat stat_data;
  320. // Check the age of the file
  321. // Now, we see if the files we've gathered are recent...
  322. int res = LLFile::stat(filename, &stat_data);
  323. if (!res)
  324. {
  325. return TRUE;
  326. }
  327. else
  328. {
  329. return FALSE;
  330. }
  331. }
  332. /*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
  333. {
  334. return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
  335. "SLPlugin.exe";
  336. }
  337. /*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name)
  338. {
  339. return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
  340. base_name + ".dll";
  341. }
  342. #if 0
  343. // Utility function to get version number of a DLL
  344. #define PACKVERSION(major,minor) MAKELONG(minor,major)
  345. DWORD GetDllVersion(LPCTSTR lpszDllName)
  346. {
  347.     HINSTANCE hinstDll;
  348.     DWORD dwVersion = 0;
  349.     hinstDll = LoadLibrary(lpszDllName); /* Flawfinder: ignore */ 
  350.     if(hinstDll)
  351.     {
  352.         DLLGETVERSIONPROC pDllGetVersion;
  353.         pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
  354. /*Because some DLLs might not implement this function, you
  355.   must test for it explicitly. Depending on the particular 
  356.   DLL, the lack of a DllGetVersion function can be a useful
  357.   indicator of the version.
  358. */
  359.         if(pDllGetVersion)
  360.         {
  361.             DLLVERSIONINFO dvi;
  362.             HRESULT hr;
  363.             ZeroMemory(&dvi, sizeof(dvi));
  364.             dvi.cbSize = sizeof(dvi);
  365.             hr = (*pDllGetVersion)(&dvi);
  366.             if(SUCCEEDED(hr))
  367.             {
  368.                 dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
  369.             }
  370.         }
  371.         
  372.         FreeLibrary(hinstDll);
  373.     }
  374.     return dwVersion;
  375. }
  376. #endif
  377. #endif