Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
8.7 KiB

  1. // File import/export for icons, cursors, and bitmaps
  2. #include "stdafx.h"
  3. #include <direct.h>
  4. #include <sys\stat.h>
  5. #include "global.h"
  6. #include "pbrush.h"
  7. #include "pbrusdoc.h"
  8. #include "pbrusfrm.h"
  9. #include "bmobject.h"
  10. #include "imgsuprt.h"
  11. #include "imgwnd.h"
  12. #include "imgfile.h"
  13. #include "ferr.h"
  14. #include "cmpmsg.h"
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  18. #endif
  19. #include "memtrace.h"
  20. // base for temp file names
  21. const TCHAR BASED_CODE CFileSaver::c_szAps [] = TEXT("TMP");
  22. /***************************************************************************/
  23. BOOL FileExists(const TCHAR* szFileName)
  24. {
  25. CFileStatus fs;
  26. return CFile::GetStatus(szFileName, fs) != 0;
  27. }
  28. /***************************************************************************/
  29. BOOL RenameFile(const TCHAR* szOldName, const TCHAR* szNewName)
  30. {
  31. TRACE2("RenameFile: \"%s\" to \"%s\"\n", szOldName, szNewName);
  32. TRY
  33. {
  34. if (FileExists(szNewName))
  35. CFile::Remove(szNewName);
  36. CFile::Rename(szOldName, szNewName);
  37. }
  38. CATCH(CFileException, e)
  39. {
  40. TRACE(TEXT("Rename failed!\n"));
  41. theApp.SetFileError( IDS_ERROR_EXPORT, e->m_cause );
  42. return FALSE;
  43. }
  44. END_CATCH
  45. return TRUE;
  46. }
  47. /***************************************************************************/
  48. CFileSaver::CFileSaver(const TCHAR* szFileName)
  49. {
  50. CString strDir = StripName(szFileName);
  51. CString strTempDir;
  52. GetTempPath( _MAX_PATH, strTempDir.GetBuffer( _MAX_PATH ) );
  53. strTempDir.ReleaseBuffer();
  54. GetTempFileName( strTempDir, c_szAps, 0, m_strTempName.GetBuffer( _MAX_PATH ));
  55. GetTempFileName( strTempDir, c_szAps, 0, m_strBackupName.GetBuffer( _MAX_PATH ));
  56. CFile::Remove( m_strTempName );
  57. CFile::Remove( m_strBackupName );
  58. m_strName = szFileName;
  59. m_strTempName = strDir + StripPath( m_strTempName );
  60. m_strBackupName = strDir + StripPath( m_strBackupName );
  61. }
  62. /***************************************************************************/
  63. CFileSaver::~CFileSaver()
  64. {
  65. if (FileExists(m_strTempName))
  66. CFile::Remove(m_strTempName);
  67. if (FileExists(m_strBackupName))
  68. CFile::Remove(m_strBackupName);
  69. }
  70. /***************************************************************************/
  71. BOOL CFileSaver::CanSave() const
  72. {
  73. CFileStatus fs;
  74. if ( CFile::GetStatus(m_strName, fs) != 0 )
  75. {
  76. if ((fs.m_attribute & CFile::readOnly) != 0)
  77. {
  78. theApp.SetFileError( IDS_ERROR_SAVE, ferrCantSaveReadOnly);
  79. return FALSE;
  80. }
  81. }
  82. return TRUE;
  83. }
  84. /***************************************************************************/
  85. BOOL CFileSaver::Finish()
  86. {
  87. if (FileExists(m_strName) != 0)
  88. {
  89. if (!RenameFile(m_strName, m_strBackupName))
  90. {
  91. CFile::Remove(m_strTempName);
  92. return FALSE;
  93. }
  94. }
  95. else
  96. {
  97. // no backup was made since the "original" didn't exists,
  98. // wipe out the name so we don't delete the file later...
  99. m_strBackupName.Empty();
  100. }
  101. if (!RenameFile(m_strTempName, m_strName))
  102. {
  103. if (!m_strBackupName.IsEmpty() &&
  104. RenameFile(m_strBackupName, m_strName))
  105. {
  106. CFile::Remove(m_strTempName);
  107. }
  108. return FALSE;
  109. }
  110. if (!m_strBackupName.IsEmpty())
  111. CFile::Remove(m_strBackupName);
  112. return TRUE;
  113. }
  114. /***************************************************************************/
  115. /* strrchrs() -- find the last instance in a string of any one of
  116. ** a set of characters. Return a pointer into the string at
  117. ** the matchpoint. Analogous to strrchr() in the CRT.
  118. */
  119. TCHAR *strrchrs(TCHAR *szText, TCHAR * szSSet)
  120. {
  121. register TCHAR *pchSSet;
  122. register TCHAR *pchStep;
  123. register TCHAR *pchLast = NULL;
  124. if ((NULL == szText) || (NULL == szSSet))
  125. return NULL;
  126. for (pchStep = szText; TEXT('\0') != *pchStep; pchStep = CharNext(pchStep))
  127. for (pchSSet = szSSet; TEXT('\0') != *pchSSet; pchSSet = CharNext(pchSSet))
  128. if ((pchSSet[0] == pchStep[0]) && (
  129. #ifndef UNICODE
  130. !IsDBCSLeadByte((CHAR)pchSSet[0]) ||
  131. #endif // UNICODE
  132. (pchSSet[1] == pchStep[1])))
  133. pchLast = pchStep;
  134. return pchLast;
  135. }
  136. /***************************************************************************/
  137. /* MkPath() -- Make any directories necessary to ensure that a
  138. ** directory name passed in exists. Essentially, if the
  139. ** argument exists and is a directory, return success. If
  140. ** not, strip off the last path component and recurse,
  141. ** creating the directories on returning up the stack.
  142. */
  143. int MkPath(TCHAR *szPath)
  144. {
  145. TCHAR *pchSlash;
  146. TCHAR chSep;
  147. DWORD dwAtts;
  148. //Does it exist?
  149. if ( (dwAtts = GetFileAttributes(szPath)) & FILE_ATTRIBUTE_DIRECTORY )
  150. {
  151. return 0;
  152. }
  153. else if (-1 != dwAtts)
  154. {
  155. return -1;
  156. }
  157. //Can we create it?
  158. else
  159. {
  160. if ( CreateDirectory(szPath, NULL))
  161. return 0;
  162. // are we out of path components?
  163. else
  164. {
  165. if (NULL == (pchSlash = strrchrs(szPath, TEXT("\\/"))))
  166. return -1;
  167. // Can we make its parent directory?
  168. else
  169. {
  170. if ((chSep = *pchSlash), (*pchSlash = TEXT('\0')), MkPath(szPath))
  171. {
  172. #ifndef DEBUG
  173. *pchSlash = chSep;
  174. #endif
  175. return -1;
  176. }
  177. // Can we make it now that we've made its parent?
  178. else
  179. {
  180. if ((*pchSlash = chSep), (TEXT('\0') != pchSlash[1]))
  181. {
  182. if (!CreateDirectory (szPath, NULL))
  183. {
  184. return -1;
  185. }
  186. return 0;
  187. }
  188. else //don't try trailing slash
  189. return 0;
  190. }
  191. }
  192. }
  193. }
  194. }
  195. /***************************************************************************/
  196. void MkFullPath(CString& strFullPath, const CString& strRelPath,
  197. BOOL bPathOnly)
  198. {
  199. strFullPath.Empty();
  200. ASSERT(strRelPath.GetLength() > 0);
  201. if (strRelPath[0] != TEXT('\\') &&
  202. (strRelPath.GetLength() <= 1 || (
  203. #ifndef UNICODE
  204. !IsDBCSLeadByte((CHAR)strRelPath[0]) &&
  205. #endif // UNICODE
  206. strRelPath[1] != TEXT(':'))))
  207. {
  208. CHAR *szPathName = _getdcwd(0, NULL, 1);
  209. #ifdef UNICODE
  210. WCHAR *szPW = new WCHAR[lstrlenA (szPathName)+1];
  211. AtoW (szPathName, szPW);
  212. strFullPath = szPW;
  213. delete szPW;
  214. #else
  215. strFullPath = szPathName;
  216. #endif //UNICODE
  217. free(szPathName);
  218. if (strFullPath.Right(1) != TEXT('\\'))
  219. strFullPath += (TCHAR)TEXT('\\');
  220. }
  221. if (bPathOnly)
  222. {
  223. int iLastSep = strRelPath.ReverseFind(TEXT('\\'));
  224. if (iLastSep == -1)
  225. iLastSep = strRelPath.GetLength();
  226. strFullPath += strRelPath.Left(iLastSep);
  227. }
  228. else
  229. {
  230. strFullPath += strRelPath;
  231. }
  232. }
  233. /***************************************************************************/
  234. BOOL OpenSubFile(CFile& file, const CFileSaver& saver, UINT nOpenFlags,
  235. CFileException* pError)
  236. {
  237. BOOL bResult = file.Open(saver.GetSafeName(), nOpenFlags, pError);
  238. if (!bResult && (pError->m_cause == CFileException::badPath ||
  239. pError->m_cause == CFileException::accessDenied))
  240. {
  241. CString strFileName = saver.GetRealName();
  242. CString strPathName;
  243. MkFullPath(strPathName, strFileName, TRUE);
  244. strPathName.MakeUpper();
  245. // suppress the message box upon return, but keep error info!
  246. // (ie. user only needs one message box)
  247. pError->m_cause = -pError->m_cause;
  248. strFileName.MakeUpper();
  249. int nResult = CmpMessageBoxPrintf(IDS_QUERY_MKDIR, AFX_IDS_APP_TITLE,
  250. MB_YESNO | MB_ICONQUESTION,
  251. (LPCTSTR)strPathName, (LPCTSTR) strFileName);
  252. if (nResult == IDYES)
  253. {
  254. MkPath(strPathName.GetBuffer(strPathName.GetLength()));
  255. strPathName.ReleaseBuffer();
  256. bResult = file.Open(saver.GetSafeName(), nOpenFlags, pError);
  257. }
  258. }
  259. return bResult;
  260. }
  261. /***************************************************************************/