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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
// EncryptActions.cpp: implementation of the CEncryptActions class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "EncryptActions.h"
#include "resource.h"
#include <appmisc.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
bool CEncryptActions::EncryptPrepare::Do(CActionEngine* pEngine,
HWND hwndUpdates)
{
ASSERT(pEngine != NULL);
Update(hwndUpdates, _T("Listing files to encrypt..."), NULL);
// Iterate through source folders
string_array::const_iterator iterSrc;
for(iterSrc = m_aFiles.begin(); iterSrc != m_aFiles.end(); iterSrc++)
{
Update(hwndUpdates, NULL, (LPCTSTR)*iterSrc);
file_iterator fileIter((file_path)*iterSrc, file_iterator::sub_folders | file_iterator::full_paths), end;
for( ; fileIter != end; fileIter++)
{
file_path srcFile(fileIter->cFileName);
if(!(srcFile.attributes() & FILE_ATTRIBUTE_DIRECTORY))
{
if(m_asIgnore.find(srcFile.ext().make_lower()) == m_asIgnore.end())
{
// Construct File
Encrypt* pEncrypt = new Encrypt(srcFile);
pEngine->Add(pEncrypt);
}
}
}
// Error from file_iterator (listing folders)
if(fileIter.state() != ERROR_SUCCESS)
throw CActionError(HRESULT_FROM_WIN32(fileIter.state()), IDS_ENCRYPT_ERR_LIST, (file_path)*iterSrc);
}
return false;
}
HRESULT CEncryptActions::EncryptPrepare::Initialize(const CPropertyBag& data)
{
if(!data.GetStringSet(NS_ENCRYPT_REG_FILES, m_aFiles))
return S_FALSE;
CEncryptActions::Encrypt::m_bEncryptReadOnly = data.GetInt(NS_ENCRYPT_REG_READONLY, false) ? true : false;
string_array asTemp;
data.GetStringSet(NS_IGNORE_REG_EXT, asTemp);
// Make them all lower
for_each(asTemp.begin(), asTemp.end(), Lower);
// And copy them to the set (removes doubles)
copy(asTemp.begin(), asTemp.end(), inserter(m_asIgnore, m_asIgnore.begin()));
// Remove any blanks from ignore
m_asIgnore.erase(_T(""));
return S_OK;
}
IXpyExPtr CEncryptActions::Encrypt::m_pXpy;
bool CEncryptActions::Encrypt::m_bEncryptReadOnly = false;
UINT CEncryptActions::Encrypt::m_nXpyRefs = 0;
bool CEncryptActions::Encrypt::Do(CActionEngine* pEngine,
HWND hwndUpdates)
{
// Update any monitors
Update(hwndUpdates, _T("Encrypting..."), m_file);
// Initialize XPY
HRESULT hr;
if(FAILED(hr = InitXpy()))
{
// If it doesn't work then trash all the encryption actions
// in the engine
if(pEngine)
pEngine->RemoveAll(this);
// And spit out an error
throw CActionError(hr, IDS_ENCRYPT_ERR_XPYINIT);
}
// Use this in case we need to reset the attributes
// in order to encrypt the file. XPY won't encrypt
// read-only files. There's an option here
// to let you. So basically what we have to do is
// reset the file to normal attributes and then set
// it back
// If it's 0 that means we haven't messed with the
// attributes yet. If it has a value that means we
// need to set the value back before returning
DWORD dwAttributes = 0;
encrypt:
try
{
// Here's the actual close code
// rest is basically error checking
m_pXpy->Close((LPCTSTR)m_file);
}
catch(_com_error& e)
{
// Here we check for the read-only error that Xpy
// will spit up. If the flag is set then go ahead
// and reset the attributes
if(e.Error() == XPY_E_FILE_ATTRIBUTES && // Read Only Error
m_bEncryptReadOnly) // flag to encrypt read-only
{
// If we haven't messed with the attributes
// yet then go ahead and reset them
if(!dwAttributes)
{
// Get Attributes
dwAttributes = GetFileAttributes(m_file);
// Let System files blow! (with an error)
if(!(dwAttributes & FILE_ATTRIBUTE_SYSTEM))
{
SetFileAttributes(m_file, FILE_ATTRIBUTE_NORMAL);
// Reencrypt
goto encrypt;
}
}
// Otherwise we won't try again
}
// Set the Attributes back
if(dwAttributes)
SetFileAttributes(m_file, dwAttributes);
// Get the proper error message
_bstr_t bsError = e.Description();
if(bsError.length())
throw CActionError((LPCTSTR)bsError, e.Error(), IDS_ENCRYPT_ERR, m_file);
else
throw CActionError(e.Error(), IDS_ENCRYPT_ERR, m_file);
}
// Set the Attributes back
if(dwAttributes)
SetFileAttributes(m_file, dwAttributes);
return false;
}
bool CEncryptActions::Encrypt::IsFixable(HRESULT hr) const
{
switch(hr)
{
case XPY_E_FILE_ATTRIBUTES:
case HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION):
case HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION):
return true;
default:
return false;
}
}
void CEncryptActions::Encrypt::Fix(HRESULT hr)
{
if(hr == XPY_E_FILE_ATTRIBUTES)
{
if(SetFileAttributes(m_file, FILE_ATTRIBUTE_NORMAL))
Do(NULL, NULL);
else
throw CActionError(HRESULT_FROM_WIN32(::GetLastError()), IDS_ENCRYPT_ERR, m_file);
}
else if(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) ||
hr == HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION))
{
bool bFirst = true;
start:
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))
{
HCURSOR hCurs = ::GetCursor();
// ... Prompt user to close programs
MessageBox(NULL, _T("Files cannot be encrypted while they are opened in a program. Close all other programs and then click the OK button."), _T("Encrypt Files"), MB_OK | MB_ICONINFORMATION);
if(hCurs)
::SetCursor(hCurs);
bFirst = false;
}
// Otherwise out with the error
else
throw;
}
goto start;
}
}
HRESULT CEncryptActions::Encrypt::InitXpy()
{
if(m_pXpy)
return S_OK;
else
return m_pXpy.CreateInstance(__uuidof(XpyEx));
}
|