OSDN Git Service

Avoid an assertion failure when loading settings from winmerge.ini
[winmerge-jp/winmerge-jp.git] / Src / TempFile.cpp
1 /**
2  * @file  TempFile.cpp
3  *
4  * @brief Implementation file for TempFile
5  *
6  */
7
8 #include "pch.h"
9 #include "TempFile.h"
10 #include <windows.h>
11 #include "paths.h"
12 #include "TFile.h"
13 #include "Environment.h"
14 #include "Constants.h"
15 #include "unicoder.h"
16
17 static bool WMrunning(int iPI);
18
19 /**
20  * @brief Delete the temp file when instance is deleted.
21  */
22 TempFile::~TempFile()
23 {
24         Delete();
25 }
26
27
28 /**
29  * @brief Create a temporary file with given prefix.
30  * @param [in] prefix A prefix for temp file name.
31  * @param [in] ext extension for temp file name.
32  * @return Created temp file path.
33  */
34 String TempFile::Create(const String& prefix, const String& ext)
35 {
36         String temp = env::GetTemporaryPath();
37         if (temp.empty())
38         {
39                 return _T("");
40         }
41
42         String pref = prefix;
43         if (pref.empty())
44                 pref = _T("wmtmp");
45
46         temp = env::GetTemporaryFileName(temp, pref, nullptr);
47         if (!temp.empty())
48         {
49                 if (!ext.empty())
50                 {
51                         String tempext = temp + ext;
52                         if (MoveFile(temp.c_str(), tempext.c_str()))
53                                 temp = tempext;
54                 }
55                 m_path = temp;
56         }
57
58         return temp;
59 }
60
61 /**
62  * @brief Delete the temporary file, if it exists.
63  * @return true if there was no error.
64  */
65 bool TempFile::Delete()
66 {
67         bool success = true;
68         if (!m_path.empty())
69                 success = !!DeleteFile(m_path.c_str());
70         if (success)
71                 m_path = _T("");
72         return success;
73 }
74 /** 
75  * @brief Cleanup tempfiles created by WinMerge.
76  * This function finds temp folders which don't have WinMerge instance using
77  * them anymore.
78  */
79 void CleanupWMtemp()
80 {
81         String foldername;
82         String tempfolderPID;
83         String filepattern(TempFolderPrefix);
84         filepattern += _T("*.*");
85         String pattern = paths::GetParentPath(env::GetTemporaryPath());
86         pattern = paths::ConcatPath(pattern, filepattern);
87         WIN32_FIND_DATA ff;
88         HANDLE h;
89         bool res = true;
90         bool bok = true;
91         
92         h = FindFirstFile (TFile(pattern).wpath().c_str(), &ff);
93         if (h == INVALID_HANDLE_VALUE)
94                 bok = false;
95
96         while (bok & res)
97         {
98                 foldername = ff.cFileName;
99                 if (ff.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
100                 {
101                         // Remove leading "WM_" from filename to get the ProcessID
102                         tempfolderPID = foldername.substr(_tcslen(TempFolderPrefix));
103
104                         // Check if this instance of WM is still running
105                         try
106                         {
107                                 int pid = atoi(ucr::toUTF8(tempfolderPID).c_str());
108                                 if (!WMrunning(pid))
109                                 {
110                                         tempfolderPID = paths::ConcatPath(paths::GetParentPath(pattern), ff.cFileName); 
111                                         res = ClearTempfolder(tempfolderPID);
112                                         if (res)
113                                                 bok = !!FindNextFile(h, &ff) ;
114                                         continue;
115                                 }
116                         }
117                         catch (...)
118                         {
119                         }
120                 }
121                 bok = !!FindNextFile(h, &ff) ;
122         }
123         if (h != INVALID_HANDLE_VALUE)
124                 FindClose(h);
125 }
126
127 /**
128  * @brief Is WinMerge with given processID running?
129  * @param [in] processIDs List of WinMerge processes.
130  * @param [in] iPI ProcessID to check.
131  * @return true if processID was found from the list, `false` otherwise.
132  */
133 static bool WMrunning(int iPI)
134 {
135         HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, iPI);
136         if (!hProcess)
137                 return (GetLastError() == ERROR_ACCESS_DENIED);
138         CloseHandle(hProcess);
139         return true;
140 }
141
142 /**
143  * @brief Remove the temp folder.
144  * @param [in] pathName Folder to remove.
145  * @return true if removal succeeds, `false` if fails.
146  */
147 bool ClearTempfolder(const String &pathName)
148 {
149         try
150         {
151                 TFile(pathName).remove(true);
152         }
153         catch (...)
154         {
155                 return false;
156         }
157         return true;
158 }