filespecutils.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:20k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxstring.h"
  36. #include "filespecutils.h"
  37. #include "hxtick.h"
  38. #include "hxrand.h"
  39. #include "dbcs.h"
  40. #include "hlxclib/windows.h"
  41. #include <winbase.h>
  42. #include <shlobj.h>
  43. #include "hlxclib/sys/stat.h"
  44. //////////////////////////////////////////////////////////
  45. //
  46. // Utility base class -- CHXFileSpecUtils
  47. //
  48. //////////////////////////////////////////////////////////
  49. typedef BOOL (HXEXPORT_PTR FPGetFreeSpace) (LPCTSTR lpDir,PULARGE_INTEGER lpFree,PULARGE_INTEGER lpTotBytes,PULARGE_INTEGER lpTotFree);
  50. typedef HRESULT (HXEXPORT_PTR FPSHGetSpecialFolderLocation) (HWND hwndOwner, int nFolder, LPITEMIDLIST *ppidl);  
  51. typedef HRESULT (HXEXPORT_PTR FPSHGetPathFromIDList)(LPCITEMIDLIST pidl, LPSTR pszPath);
  52. typedef HRESULT (HXEXPORT_PTR FPSHGetMalloc)(LPMALLOC *ppMalloc);
  53. //******************************************************************************
  54. HX_RESULT CHXFileSpecUtils::GetFreeSpaceOnDisk(const CHXDirSpecifier& volSpec, 
  55.        INT64& freeSpace)
  56. {
  57. CHXDirSpecifier dirRoot = volSpec.GetVolume();
  58. CHXString strDir = dirRoot.GetPathName();
  59. OSVERSIONINFO ver;
  60. HX_RESULT res = HXR_FAIL;
  61. WORD w;
  62. // figure out which version of windows the user is running 
  63. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  64. GetVersionEx(&ver);
  65. w = (WORD)ver.dwBuildNumber;
  66. if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && w <= 1000)
  67. {
  68. #if !defined(WIN32_PLATFORM_PSPC)
  69. // the original windows 95
  70. DWORD dwSecPerClu,dwBytPerSec,dwNumFreeClu,dwNumOfClu;
  71. if (GetDiskFreeSpace(strDir,&dwSecPerClu,&dwBytPerSec,&dwNumFreeClu,&dwNumOfClu) != 0)
  72. {
  73. return HXR_FAIL;
  74. }
  75. // do a bit a math to figure out the free space - 
  76. freeSpace = ((INT64)dwSecPerClu) * ((INT64)dwBytPerSec) * ((INT64)dwNumFreeClu);
  77. #else /* !defined(WIN32_PLATFORM_PSPC) */
  78. ULARGE_INTEGER   freeBytesAvailableToCaller;
  79. ULARGE_INTEGER   totalNumberOfBytes;
  80. ULARGE_INTEGER   totalNumberOfFreeBytes;
  81. if (!GetDiskFreeSpaceEx(OS_STRING(strDir),
  82. &freeBytesAvailableToCaller,
  83. &totalNumberOfBytes,
  84. &totalNumberOfFreeBytes))
  85.     return HXR_FAIL;
  86. freeSpace = freeBytesAvailableToCaller.QuadPart;
  87. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  88. }
  89. else
  90. {
  91. // windows 95 osr2 or above or winnt
  92. // the docs for GetDiskFreeSpaceEx say to load kernel32.dll,
  93. // search for the procaddress and then call the function...
  94. HINSTANCE hKernel = ::LoadLibrary(OS_STRING("kernel32.dll"));
  95. if (hKernel)
  96. {
  97. FPGetFreeSpace fpGetFreeSpace = (FPGetFreeSpace) GetProcAddress(hKernel, OS_STRING("GetDiskFreeSpaceExA"));
  98. if (fpGetFreeSpace)
  99. {
  100. ULARGE_INTEGER uFreeBytesCaller,uTotNumBytes,uTotNumFreeBytes;
  101. BOOL b = fpGetFreeSpace(OS_STRING(strDir),&uFreeBytesCaller,&uTotNumBytes,&uTotNumFreeBytes);
  102. if (b)
  103. {
  104. // free space on disk or for the user? That is the question
  105. freeSpace = uFreeBytesCaller.QuadPart;
  106. res = HXR_OK;
  107. }
  108. }
  109. ::FreeLibrary(hKernel);
  110. }
  111. }
  112. return res;
  113. }
  114. //******************************************************************************
  115. HX_RESULT CHXFileSpecUtils::GetTotalSpaceOnDisk(const CHXDirSpecifier& volSpec, 
  116. INT64& totalSpace)
  117. CHXDirSpecifier dirRoot = volSpec.GetVolume();
  118. CHXString strDir = dirRoot.GetPathName();
  119. OSVERSIONINFO ver;
  120. HX_RESULT res = HXR_FAIL;
  121. WORD w;
  122. // figure out which version of windows the user is running 
  123. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  124. GetVersionEx(&ver);
  125. w = (WORD)ver.dwBuildNumber;
  126. if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && w <= 1000)
  127. {
  128. #if !defined(WIN32_PLATFORM_PSPC)
  129. // the original windows 95
  130. DWORD dwSecPerClu,dwBytPerSec,dwNumFreeClu,dwNumOfClu;
  131. if (GetDiskFreeSpace(strDir,&dwSecPerClu,&dwBytPerSec,&dwNumFreeClu,&dwNumOfClu) != 0)
  132. {
  133. return HXR_FAIL;
  134. }
  135. // do a bit a math to figure out the free space - 
  136. totalSpace = ((INT64)dwSecPerClu) * ((INT64)dwBytPerSec) * ((INT64)dwNumOfClu);
  137. #else /* !defined(WIN32_PLATFORM_PSPC) */
  138. ULARGE_INTEGER   freeBytesAvailableToCaller;
  139. ULARGE_INTEGER   totalNumberOfBytes;
  140. ULARGE_INTEGER   totalNumberOfFreeBytes;
  141. if (!GetDiskFreeSpaceEx(OS_STRING(strDir),
  142. &freeBytesAvailableToCaller,
  143. &totalNumberOfBytes,
  144. &totalNumberOfFreeBytes))
  145.     return HXR_FAIL;
  146. totalSpace = totalNumberOfBytes.QuadPart;
  147. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  148. }
  149. else
  150. {
  151. // windows 95 osr2 or above or winnt
  152. // the docs for GetDiskFreeSpaceEx say to load kernel32.dll,
  153. // search for the procaddress and then call the function...
  154. HINSTANCE hKernel = ::LoadLibrary(OS_STRING("kernel32.dll"));
  155. if (hKernel)
  156. {
  157. FPGetFreeSpace fpGetFreeSpace = (FPGetFreeSpace)GetProcAddress(hKernel, OS_STRING("GetDiskFreeSpaceExA"));
  158. if (fpGetFreeSpace)
  159. {
  160. ULARGE_INTEGER uFreeBytesCaller,uTotNumBytes,uTotNumFreeBytes;
  161. BOOL b = fpGetFreeSpace(OS_STRING(strDir),&uFreeBytesCaller,&uTotNumBytes,&uTotNumFreeBytes);
  162. if (b)
  163. {
  164. // free space on disk or for the user? That is the question
  165. totalSpace = uTotNumBytes.QuadPart;
  166. res = HXR_OK;
  167. }
  168. }
  169. ::FreeLibrary(hKernel);
  170. }
  171. }
  172. return res;
  173. }
  174. //******************************************************************************
  175. BOOL CHXFileSpecUtils::IsDiskEjectable(const CHXDirSpecifier& volSpec)
  176. {
  177.      BOOL retval = FALSE;
  178. #if !defined(WIN32_PLATFORM_PSPC)
  179. CHXDirSpecifier dirRoot = volSpec.GetVolume();
  180. CHXString strDir = dirRoot.GetPathName();
  181. UINT uiType = ::GetDriveType(strDir);
  182. switch (uiType)
  183. {
  184. case DRIVE_REMOVABLE:
  185. case DRIVE_CDROM:
  186. retval = TRUE;
  187. break;
  188. default:
  189. retval = FALSE;
  190. break;
  191. }
  192. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  193. return retval;
  194. }
  195. // IsLocal returns TRUE if the file or directory is on a local volume
  196. // (not on a server)
  197. //******************************************************************************
  198. BOOL CHXFileSpecUtils::IsDiskLocal(const CHXDirSpecifier& volSpec)
  199. {
  200.     BOOL retval = TRUE;
  201. #if !defined(WIN32_PLATFORM_PSPC)
  202. CHXDirSpecifier dirRoot = volSpec.GetVolume();
  203. CHXString strDir = dirRoot.GetPathName();
  204. UINT uiType = ::GetDriveType(strDir);
  205. switch (uiType)
  206. {
  207. case DRIVE_FIXED:
  208. case DRIVE_CDROM:
  209. case DRIVE_RAMDISK:
  210. case DRIVE_REMOVABLE:
  211. retval = TRUE;
  212. break;
  213. default:
  214. retval = FALSE;
  215. break;
  216. }
  217. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  218. return retval;
  219. }
  220. // file/dir utilities
  221. //******************************************************************** **********
  222. HX_RESULT CHXFileSpecUtils::RemoveDir(const CHXDirSpecifier& dirSpec)
  223. {
  224.     if (::RemoveDirectory(OS_STRING(dirSpec.GetPathName())))
  225.     {
  226.         return HXR_OK;
  227.     }
  228.     return HXR_FAILED;
  229. };
  230. //******************************************************************** **********
  231. HX_RESULT CHXFileSpecUtils::RemoveFile(const CHXFileSpecifier& fileSpec)
  232. {
  233.     if (::DeleteFile(OS_STRING(fileSpec.GetPathName())))
  234.     {
  235.         return HXR_OK;
  236.     }
  237.     return HXR_FAILED;
  238. };
  239. //******************************************************************************
  240. HX_RESULT CHXFileSpecUtils::GetFileSize(const CHXFileSpecifier& fileSpec, INT64& fSize)
  241. {
  242. CHXString strFile = fileSpec.GetPathName();
  243. // try to open the file
  244. HANDLE hFile = ::CreateFile(OS_STRING(strFile),
  245. GENERIC_READ,
  246. FILE_SHARE_READ,
  247. NULL,
  248. OPEN_EXISTING,
  249. FILE_ATTRIBUTE_NORMAL,
  250. NULL);
  251. if (hFile == INVALID_HANDLE_VALUE)
  252. {
  253. return HXR_FAIL;
  254. }
  255. DWORD dwLow,dwHigh,dwError;
  256. dwLow = ::GetFileSize(hFile,&dwHigh);
  257. if (dwLow == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR)
  258. {
  259. return HXR_FAIL;
  260. }
  261. fSize = dwHigh;
  262. fSize = fSize << 32;
  263. fSize |= dwLow;
  264. ::CloseHandle(hFile);
  265. return HXR_OK;
  266. }
  267. //******************************************************************************
  268. HX_RESULT CHXFileSpecUtils::GetDirectorySize(const CHXDirSpecifier& dirSpec, BOOL shouldDescend, INT64& fSize)
  269. {
  270.     CHXString currentDir = dirSpec.GetPathName();
  271.     CHXString strFindFilePath = currentDir + "\*.*";
  272.     WIN32_FIND_DATA findFileData;
  273.     HANDLE hFile = ::FindFirstFile(OS_STRING(strFindFilePath), &findFileData );
  274.     HX_RESULT outResult = HXR_OK;
  275.     while ( hFile != INVALID_HANDLE_VALUE )
  276.     {
  277. if ((0 != strcmp(".", OS_STRING(findFileData.cFileName))) && 
  278.     (0 != strcmp("..", OS_STRING(findFileData.cFileName))) )
  279. {
  280.     if ( shouldDescend && (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  281.     {
  282. CHXString subDirectoryPath = currentDir + "\" + OS_STRING(findFileData.cFileName);
  283. CHXDirSpecifier subDirectorySpec( subDirectoryPath );
  284. if ( FAILED(GetDirectorySize( subDirectorySpec, shouldDescend, fSize )) )
  285. {
  286.     fSize = 0;
  287.     outResult = HXR_FAIL;
  288.     break;
  289. }
  290.     }
  291.     else
  292.     {
  293. INT64 dFileSize = 0;
  294. dFileSize = findFileData.nFileSizeHigh;
  295. dFileSize = dFileSize << 32;
  296. dFileSize |= findFileData.nFileSizeLow;
  297. fSize += dFileSize;
  298.     }
  299. }
  300. if ( 0 == ::FindNextFile( hFile, &findFileData ) )
  301. {
  302.     if ( ERROR_NO_MORE_FILES != GetLastError() )
  303.     {
  304. fSize = 0;
  305. outResult = HXR_FAIL;
  306.     }
  307.     break;
  308. }
  309.     }
  310.     ::FindClose( hFile );
  311.     return HXR_OK;
  312. }
  313. //******************************************************************************
  314. CHXFileSpecifier CHXFileSpecUtils::GetCurrentApplication(void)
  315. {
  316. CHXFileSpecifier spec;
  317. char szBuf[_MAX_PATH]; /* Flawfinder: ignore */
  318. if (GetModuleFileName(NULL,OS_STRING2(szBuf,_MAX_PATH),_MAX_PATH))
  319. {
  320. spec = CHXFileSpecifier(szBuf); 
  321. }
  322. return spec;
  323. }
  324. //******************************************************************************
  325. CHXDirSpecifier CHXFileSpecUtils::GetCurrentApplicationDir(void)
  326. {
  327. CHXFileSpecifier  appSpec;
  328. CHXDirSpecifier  dirSpec;
  329. appSpec = GetCurrentApplication();
  330. if (appSpec.IsSet())
  331. {
  332. dirSpec = appSpec.GetParentDirectory();
  333. }
  334. return dirSpec;
  335. }
  336. //******************************************************************************
  337. BOOL CHXFileSpecUtils::FileExists(const CHXFileSpecifier& fileSpec)
  338. {
  339.     BOOL bRet = FALSE;
  340.     //struct stat statBuff;
  341.     //ZeroInit(&statBuff);
  342.     //if ( (stat(fileSpec.GetPathName(), &statBuff) == 0) && (statBuff.st_mode & _S_IFREG))
  343.     //bRet = TRUE;
  344.     ULONG32 ulAtts = ::GetFileAttributes(OS_STRING(fileSpec.GetPathName()));
  345.     if (ulAtts != 0xFFFFFFFF && !(ulAtts & FILE_ATTRIBUTE_DIRECTORY))
  346. bRet = TRUE;
  347.     return bRet;
  348. }
  349. //******************************************************************************
  350. BOOL CHXFileSpecUtils::DirectoryExists(const CHXDirSpecifier& dirSpec)
  351. {
  352. ULONG32 ulAtts = ::GetFileAttributes(OS_STRING(dirSpec.GetPathName()));
  353. if (ulAtts != 0xFFFFFFFF && (ulAtts & FILE_ATTRIBUTE_DIRECTORY))
  354. return TRUE;
  355. return FALSE;
  356. }
  357. //******************************************************************************
  358. HX_RESULT CHXFileSpecUtils::CreateDir(const CHXDirSpecifier& dirSpec)
  359. {
  360.         if (::CreateDirectory(OS_STRING(dirSpec.GetPathName()),NULL))
  361. return TRUE;
  362. return FALSE;
  363. }
  364. //******************************************************************************
  365. static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
  366. const char *pszNameFirst, const char *pszTemplate, 
  367. const char *pszWildcard, UINT32 nStartNum);
  368. const UINT32 kNumWrapValue = 9999+1; // limit insertions to 4-digit numbers
  369. CHXFileSpecifier CHXFileSpecUtils::GetUniqueFileSpec(const CHXDirSpecifier& locationSpec, 
  370. const char *pszNameFirst, const char *pszTemplate, 
  371. const char *pszWildcard)
  372. {
  373. return GetUniqueFileSpecInternal(locationSpec, pszNameFirst, pszTemplate, pszWildcard, 0);
  374. }
  375. CHXFileSpecifier CHXFileSpecUtils::GetUniqueTempFileSpec(const CHXDirSpecifier& locationSpec, 
  376. const char *pszTemplate, const char *pszWildcard)
  377. {
  378. CMultiplePrimeRandom  rand(HX_GET_TICKCOUNT());
  379. UINT32 num;
  380. num = rand.GetRandomNumber();
  381. num %= kNumWrapValue;
  382. if (num == 0 || num == 1) num = 2;
  383. return GetUniqueFileSpecInternal(locationSpec, NULL, pszTemplate, pszWildcard, num);
  384. }
  385. static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
  386. const char *pszNameFirst, const char *pszTemplate, 
  387. const char *pszWildcard, UINT32 nStartNum)
  388. {
  389. CHXFileSpecifier  resultFileSpec;
  390. require_return(locationSpec.IsSet(), resultFileSpec);
  391. require_return(pszTemplate != NULL && pszWildcard != NULL, resultFileSpec);
  392. require_return(pszNameFirst != NULL || nStartNum != 0, resultFileSpec);
  393. CHXFileSpecifier  testFileSpec;
  394. CHXDirSpecifier  testDirSpec;
  395. CHXString strNumber;
  396. CHXString strName;
  397. UINT32 nCurrentNum;
  398. nCurrentNum = nStartNum;
  399. while (1) 
  400. {
  401. // if the number is non-zero, make a string from the template;
  402. // if the number is zero, user the initial name string
  403. if (nCurrentNum == 0)
  404. {
  405. // replace the wildcard in the template with the number string
  406. strName = pszNameFirst;
  407. }
  408. else
  409. {
  410. // replace the wildcard in the template with the number string
  411. strNumber.Empty();
  412. strNumber.AppendULONG(nCurrentNum);
  413. strName = pszTemplate;
  414. strName.FindAndReplace(pszWildcard, strNumber); // replace first wildcard with number string
  415. }
  416. // test if a file or directory exists with that name
  417. testFileSpec = locationSpec.SpecifyChildFile(strName);
  418. testDirSpec = locationSpec.SpecifyChildDirectory(strName);
  419. if (CHXFileSpecUtils::FileExists(testFileSpec)
  420. || CHXFileSpecUtils::DirectoryExists(testDirSpec))
  421. {
  422. // an item already has that name, so increment & wrap the number
  423. nCurrentNum++;
  424. nCurrentNum %= kNumWrapValue;
  425. // don't use 0 again, and skip 1 since "MyFile2.txt" logically follows "MyFile.txt"
  426. if (nCurrentNum == 0 || nCurrentNum == 1) 
  427. {
  428. nCurrentNum = 2; 
  429. }
  430. // a quick sanity check
  431. if (nCurrentNum == nStartNum)
  432. {
  433. check(!"GetUniqueFileSpecInternal number wrapped");
  434. break;
  435. }
  436. }
  437. else
  438. {
  439. // the name is unique
  440. resultFileSpec = testFileSpec;
  441. break;
  442. }
  443. } // while
  444. return resultFileSpec;
  445. }
  446. //******************************************************************************
  447. CHXDirSpecifier CHXFileSpecUtils::GetSystemTempDirectory()
  448. {
  449. char szBuf[MAX_PATH] = ""; /* Flawfinder: ignore */
  450. #if !defined(WIN32_PLATFORM_PSPC)
  451. ::GetTempPath(MAX_PATH,szBuf);
  452. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  453. CHXDirSpecifier retSpec(szBuf);
  454. return retSpec;
  455. }
  456. BOOL CHXFileSpecUtils::MakeNameLegal(char *pszName)
  457. {
  458. const char *badChars = "\/:*?"<>|";
  459. const char replacementChar = '-';
  460. const long maxNameLength = 255;
  461. char *pCurrChar = pszName;
  462. BOOL bChanged;
  463. require_nonnull_return(pszName, FALSE);
  464. bChanged = FALSE;
  465. // replace any illegal characters
  466. while (*pCurrChar)
  467. {
  468. if (strchr(badChars, *pCurrChar))
  469. {
  470. *pCurrChar = replacementChar;
  471. bChanged = TRUE;
  472. }
  473. pCurrChar = HXGetNextChar(pCurrChar);
  474. // be sure the name isn't too long
  475. if (pCurrChar - pszName >= maxNameLength)
  476. {
  477. if (pCurrChar - pszName >= maxNameLength + 1)
  478. pCurrChar = HXGetPrevChar(pszName, pCurrChar);
  479. *pCurrChar = 0;
  480. bChanged = TRUE;
  481. }
  482. }
  483. return bChanged;
  484. }
  485. //******************************************************************************
  486. CHXDirSpecifier 
  487. CHXFileSpecUtils::GetAppDataDir(const char* szAppName)
  488. {
  489.     CHXDirSpecifier dirResult;
  490.     CHXString strPath;
  491.     HINSTANCE hShell = ::LoadLibrary(OS_STRING("shell32.dll"));
  492.     FPSHGetSpecialFolderLocation fpSHGetSpecialFolderLocation = NULL;
  493.     FPSHGetPathFromIDList fpSHGetPathFromIDList = NULL;
  494.     FPSHGetMalloc fpSHGetMalloc = NULL;
  495.     if (hShell)
  496.     {
  497. fpSHGetSpecialFolderLocation = (FPSHGetSpecialFolderLocation) GetProcAddress(hShell,OS_STRING("SHGetSpecialFolderLocation"));
  498. fpSHGetPathFromIDList = (FPSHGetPathFromIDList) GetProcAddress(hShell, OS_STRING("SHGetPathFromIDListA"));
  499. // just in case
  500. if (!fpSHGetPathFromIDList)
  501. {
  502.     fpSHGetPathFromIDList = (FPSHGetPathFromIDList) GetProcAddress(hShell, OS_STRING("SHGetPathFromIDList"));
  503. }
  504. fpSHGetMalloc = (FPSHGetMalloc) GetProcAddress(hShell, OS_STRING("SHGetMalloc"));
  505.     }
  506.     if (!fpSHGetSpecialFolderLocation ||
  507. !fpSHGetPathFromIDList ||
  508. !fpSHGetMalloc)
  509.     {
  510. goto exit;
  511.     }
  512. #if !defined(WIN32_PLATFORM_PSPC)
  513.     ITEMIDLIST* pidl;
  514.     pidl = NULL;
  515.     if(fpSHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl) == NOERROR)
  516.     {
  517. HX_ASSERT(pidl);
  518. fpSHGetPathFromIDList(pidl, strPath.GetBuffer(_MAX_PATH + 1));
  519. IMalloc* pMalloc = NULL;
  520. if (SUCCEEDED(fpSHGetMalloc(&pMalloc)))
  521. {
  522.     pMalloc->Free(pidl);
  523.     pMalloc->Release();
  524.     pMalloc = NULL;
  525.     pidl = NULL;
  526. }
  527. strPath.ReleaseBuffer();
  528.     }
  529.     else
  530.     {
  531. // In Win95 OSR2 SHGetSpecialFolderLocation() fails on CSIDL_APPDATA.
  532. HKEY hKey = NULL;
  533. if(RegOpenKey(HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows\CurrentVersion", &hKey) == ERROR_SUCCESS)
  534. {
  535.     DWORD nValueType = REG_NONE;
  536.     DWORD bufSize = _MAX_PATH;
  537.     RegQueryValueEx(hKey, OS_STRING("ProgramFilesDir"), 
  538.     NULL, &nValueType, 
  539.     (Byte *)strPath.GetBuffer(_MAX_PATH + 1), 
  540.     &bufSize);
  541.     strPath.ReleaseBuffer();
  542.     RegCloseKey(hKey);
  543. }
  544.     }
  545. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  546.     if(!strPath.IsEmpty())
  547.     {
  548. dirResult = strPath;
  549. if(!DirectoryExists(dirResult))
  550.     CreateDir(dirResult);
  551. dirResult = dirResult.SpecifyChildDirectory("Real");
  552. if(!DirectoryExists(dirResult))
  553.     CreateDir(dirResult);
  554. if(szAppName)
  555. {
  556.     dirResult = dirResult.SpecifyChildDirectory(szAppName);
  557.     if(!DirectoryExists(dirResult))
  558. CreateDir(dirResult);
  559. }
  560.     }
  561. exit:
  562.     if (hShell)
  563.     {
  564. ::FreeLibrary(hShell);
  565.     }
  566.     return dirResult;
  567. }
  568. //******************************************************************************
  569. HX_RESULT CHXFileSpecUtils::ReadBinaryFile(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer)
  570. {
  571. HX_ASSERT(!"Not yet implemented on this platform");
  572. return HXR_FAIL;
  573. }
  574. HX_RESULT CHXFileSpecUtils::ReadTextFile(const CHXFileSpecifier& fileSpec, CHXString& outStr)
  575. {
  576. HX_ASSERT(!"Not yet implemented on this platform");
  577. return HXR_FAIL;
  578. }
  579. HX_RESULT CHXFileSpecUtils::WriteBinaryFile(CHXFileSpecifier& fileSpec, IHXBuffer* inBuffer, BOOL bReplaceExistingFile)
  580. {
  581. // the first parameter is not const because on the Mac it can change during the call
  582. HX_ASSERT(!"Not yet implemented on this platform");
  583. return HXR_FAIL;
  584. }
  585. HX_RESULT CHXFileSpecUtils::WriteTextFile(CHXFileSpecifier& fileSpec, const CHXString& inStr, BOOL bReplaceExistingFile)
  586. {
  587. // the first parameter is not const because on the Mac it can change during the call
  588. HX_ASSERT(!"Not yet implemented on this platform");
  589. return HXR_FAIL;
  590. }