summaryrefslogtreecommitdiff
path: root/NSCmpts/TempActions.cpp
blob: 24c8a916b6d65c1a50a94f03ade654146c9e7069 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// TempActions.cpp: implementation of the CEncryptActions class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TempActions.h"

#include "resource.h"
#include <appmisc.h>


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

bool CTempActions::DeletePrepare::Do(CActionEngine* pEngine, 
	  								     HWND hwndUpdates)
{
	ASSERT(pEngine != NULL);

	// Need to create another array for the folders
	// since they need to pushed on backwards after the files
	// so we don't get "Folder not empty" errors
	action_array aFolders;

	Update(hwndUpdates, _T("Preparing to clear Temp Folder..."));

	file_iterator fileIter(m_tempFolder, file_iterator::sub_folders | file_iterator::full_paths), end;
	for( ; fileIter != end; fileIter++)
	{
		file_path srcFile(fileIter->cFileName);

		CAction* pAction;
		if(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY)
		{
			pAction = new DeleteFolder(srcFile);
			aFolders.push_back(pAction);
		}
		else
		{
			pAction = new DeleteFile(srcFile);
			pEngine->Add(pAction);
		}
	}

	while(!aFolders.empty())
	{
		pEngine->Add(aFolders.back());
		aFolders.pop_back();
	}

	// Error from file_iterator (listing folders)
	if(fileIter.state() != ERROR_SUCCESS)
		throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_TEMP_ERR_LIST, m_tempFolder);
	
	return false;
}

HRESULT CTempActions::DeletePrepare::Initialize(const file_path& temp_folder)
{
	m_tempFolder = temp_folder;
	return S_OK;
}

bool CTempActions::DeleteFile::Do(CActionEngine* pEngine, 
	  							  HWND hwndUpdates)
{
	// Update any monitors
	Update(hwndUpdates, m_file);

	::SetFileAttributes(m_file, FILE_ATTRIBUTE_NORMAL);

	try
	{
		if(!::DeleteFile(m_file))
			throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_TEMP_ERR_DELETE, m_file);
	}
	catch(CActionError& err)
	{
		// These errors are okay. The file is gone
		if(err.m_hRes != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) &&
		   err.m_hRes != HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
			throw;
	}

	return false;

}
bool CTempActions::DeleteFile::IsFixable(HRESULT hr) const
{
	return (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) ||
		   hr == HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION) ||
		   hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
		   hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND));
}

void CTempActions::DeleteFile::Fix(HRESULT hr)
{
	bool bFirst = true;

start:

	if(IsFixable(hr))
	{
		try
		{
			// Try again
			Do(NULL, NULL);
			return;

		}
		catch(CActionError& err)
		{
			// If it's the first around and the error is the same...
			if(bFirst && IsFixable(err.m_hRes))
			{
				// ... Prompt user to close programs
				MessageBox(NULL, _T("Many programs keep files in the temp folder. These files cannot be deleted while the program is open. Close all other programs and then click the OK button."), _T("Empty Temp Folder"), MB_OK | MB_ICONINFORMATION);
				bFirst = false;
			}
			// Otherwise out with the error
			else
				throw;
		}
	}

	goto start;
}

bool CTempActions::DeleteFolder::Do(CActionEngine* pEngine, 
	  								 HWND hwndUpdates)
{
	// Update any monitors
	Update(hwndUpdates, m_folder);

	if(!::RemoveDirectory(m_folder))
	{
		DWORD dwError = ::GetLastError();

		// This error will be accompanied by another file error
		// so we don't need to show it
		if(dwError != ERROR_DIR_NOT_EMPTY)
			throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_TEMP_ERR_DELETE, m_folder);
	}

	return false;

}

void CTempActions::DeleteFolder::Fix(HRESULT hr)
{

}