1 /*
2    Bacula® - The Network Backup Solution
3 
4    Copyright (C) 2005-2008 Free Software Foundation Europe e.V.
5 
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 // vss.cpp -- Interface to Volume Shadow Copies (VSS)
29 //
30 // Copyright transferred from MATRIX-Computer GmbH to
31 //   Kern Sibbald by express permission.
32 //
33 // Author          : Thorsten Engel
34 // Created On      : Fri May 06 21:44:00 2005
35 
36 
37 #ifdef WIN32_VSS
38 #include "burp.h"
39 #include "compat.h"
40 
41 #include "ms_atl.h"
42 #include <objbase.h>
43 
44 #include "vss.h"
45 #include "alist.h"
46 
47 VSSClient *g_pVSSClient;
48 
49 // {b5946137-7b9f-4925-af80-51abd60b20d5}
50 
51 static const GUID VSS_SWPRV_ProviderID = {
52 	0xb5946137, 0x7b9f, 0x4925, {
53 		0xaf, 0x80, 0x51, 0xab, 0xd6, 0x0b, 0x20, 0xd5
54 	}
55 };
56 
57 
VSSCleanup(void)58 void VSSCleanup(void)
59 {
60 	if(g_pVSSClient) delete (g_pVSSClient);
61 }
62 
VSSInit(void)63 int VSSInit(void)
64 {
65 	// Decide which vss class to initialize.
66 	if(g_MajorVersion==5)
67 	{
68 		switch(g_MinorVersion)
69 		{
70 			case 1:
71 				g_pVSSClient=new VSSClientXP();
72 				atexit(VSSCleanup);
73 				return 0;
74 			case 2:
75 				g_pVSSClient=new VSSClient2003();
76 				atexit(VSSCleanup);
77 				return 0;
78 		}
79 		// Vista or Longhorn or later.
80 		//       } else if(g_MajorVersion==6 && g_MinorVersion==0) {
81 	}
82 	else if(g_MajorVersion>=6)
83 	{
84 		g_pVSSClient=new VSSClientVista();
85 		atexit(VSSCleanup);
86 		return 0;
87 	}
88 
89 	fprintf(stderr, "Unknown VSS version: %d.%d\n",
90 		(int)g_MajorVersion, (int)g_MinorVersion);
91 	return -1;
92 }
93 
VSSPathConvert(const char * szFilePath,char * szShadowPath,int nBuflen)94 BOOL VSSPathConvert(const char *szFilePath,
95 	char *szShadowPath, int nBuflen)
96 {
97 	return g_pVSSClient->GetShadowPath(szFilePath, szShadowPath, nBuflen);
98 }
99 
VSSPathConvertW(const wchar_t * szFilePath,wchar_t * szShadowPath,int nBuflen)100 BOOL VSSPathConvertW(const wchar_t *szFilePath,
101 	wchar_t *szShadowPath, int nBuflen)
102 {
103 	return g_pVSSClient->GetShadowPathW(szFilePath, szShadowPath, nBuflen);
104 }
105 
VSSClient(void)106 VSSClient::VSSClient(void)
107 {
108 	m_bCoInitializeCalled=false;
109 	m_bCoInitializeSecurityCalled=false;
110 	m_bBackupIsInitialized=false;
111 	m_pVssObject=NULL;
112 	m_pAlistWriterState=new alist(10, not_owned_by_alist);
113 	m_pAlistWriterInfoText=new alist(10, owned_by_alist);
114 	m_uidCurrentSnapshotSet=GUID_NULL;
115 	memset(m_wszUniqueVolumeName, 0, sizeof(m_wszUniqueVolumeName));
116 	memset(m_szShadowCopyName, 0, sizeof(m_szShadowCopyName));
117 }
118 
~VSSClient(void)119 VSSClient::~VSSClient(void)
120 {
121 	// Release the IVssBackupComponents interface
122 	// WARNING: this must be done BEFORE calling CoUninitialize()
123 	if(m_pVssObject)
124 	{
125 		m_pVssObject->Release();
126 		m_pVssObject=NULL;
127 	}
128 
129 	DestroyWriterInfo();
130 	delete (alist*)m_pAlistWriterState;
131 	delete (alist*)m_pAlistWriterInfoText;
132 
133 	// Call CoUninitialize if the CoInitialize was performed successfully
134 	if(m_bCoInitializeCalled) CoUninitialize();
135 }
136 
InitializeForBackup(struct asfd * asfd,struct cntr * cntr)137 BOOL VSSClient::InitializeForBackup(struct asfd *asfd, struct cntr *cntr)
138 {
139 	return Initialize(asfd, cntr);
140 }
141 
bstrncat(char * dest,const char * src,int maxlen)142 static char *bstrncat(char *dest, const char *src, int maxlen)
143 {
144 	strncat(dest, src, maxlen-1);
145 	dest[maxlen-1]=0;
146 	return dest;
147 }
148 
GetShadowPath(const char * szFilePath,char * szShadowPath,int nBuflen)149 BOOL VSSClient::GetShadowPath(const char *szFilePath,
150 	char *szShadowPath, int nBuflen)
151 {
152 	if(!m_bBackupIsInitialized) return FALSE;
153 
154 	// check for valid pathname.
155 	BOOL bIsValidName;
156 
157 	bIsValidName=strlen(szFilePath)>3;
158 	if(bIsValidName)
159 		bIsValidName &= isalpha(szFilePath[0]) &&
160 			szFilePath[1]==':' &&
161 			szFilePath[2]=='\\';
162 
163 	if(bIsValidName)
164 	{
165 		int nDriveIndex=toupper(szFilePath[0])-'A';
166 		if(m_szShadowCopyName[nDriveIndex][0])
167 		{
168 
169 			if(WideCharToMultiByte(CP_UTF8, 0,
170 			  m_szShadowCopyName[nDriveIndex], -1, szShadowPath,
171 			  nBuflen-1, NULL, NULL))
172 			{
173 				nBuflen-=(int)strlen(szShadowPath);
174 				bstrncat(szShadowPath, szFilePath+2, nBuflen);
175 				return TRUE;
176 			}
177 		}
178 	}
179 
180 	snprintf(szShadowPath, nBuflen, "%s", szFilePath);
181 	errno=EINVAL;
182 	return FALSE;
183 }
184 
GetShadowPathW(const wchar_t * szFilePath,wchar_t * szShadowPath,int nBuflen)185 BOOL VSSClient::GetShadowPathW(const wchar_t *szFilePath,
186 	wchar_t *szShadowPath, int nBuflen)
187 {
188 	if(!m_bBackupIsInitialized) return FALSE;
189 
190 	// check for valid pathname.
191 	BOOL bIsValidName;
192 
193 	bIsValidName=wcslen(szFilePath)>3;
194 	if(bIsValidName)
195 		bIsValidName &= iswalpha(szFilePath[0]) &&
196 			szFilePath[1]==':' &&
197 			szFilePath[2] == '\\';
198 
199 	if(bIsValidName)
200 	{
201 		int nDriveIndex=towupper(szFilePath[0])-'A';
202 		if(m_szShadowCopyName[nDriveIndex][0])
203 		{
204 			wcsncpy(szShadowPath,
205 				m_szShadowCopyName[nDriveIndex], nBuflen);
206 			nBuflen-=(int)wcslen(m_szShadowCopyName[nDriveIndex]);
207 			wcsncat(szShadowPath, szFilePath+2, nBuflen);
208 			return TRUE;
209 		}
210 	}
211 
212 	wcsncpy(szShadowPath, szFilePath, nBuflen);
213 	errno=EINVAL;
214 	return FALSE;
215 }
216 
217 
GetWriterCount(void)218 const size_t VSSClient::GetWriterCount(void)
219 {
220 	alist *pV=(alist *)m_pAlistWriterInfoText;
221 	return pV->size();
222 }
223 
GetWriterInfo(int nIndex)224 const char* VSSClient::GetWriterInfo(int nIndex)
225 {
226 	alist* pV=(alist*)m_pAlistWriterInfoText;
227 	return (char*)pV->get(nIndex);
228 }
229 
GetWriterState(int nIndex)230 const int VSSClient::GetWriterState(int nIndex)
231 {
232 	alist *pV=(alist *)m_pAlistWriterState;
233 	return (intptr_t)pV->get(nIndex);
234 }
235 
AppendWriterInfo(int nState,const char * pszInfo)236 void VSSClient::AppendWriterInfo(int nState, const char *pszInfo)
237 {
238 	alist *pT=(alist *)m_pAlistWriterInfoText;
239 	alist *pS=(alist *)m_pAlistWriterState;
240 
241 	pT->push(strdup(pszInfo));
242 	pS->push((void*)(intptr_t)nState);
243 }
244 
DestroyWriterInfo(void)245 void VSSClient::DestroyWriterInfo(void)
246 {
247 	alist *pT=(alist *)m_pAlistWriterInfoText;
248 	alist *pS=(alist *)m_pAlistWriterState;
249 
250 	while(!pT->empty()) free(pT->pop());
251 	while(!pS->empty()) pS->pop();
252 }
253 
254 #endif
255