Leaked source code of windows server 2003
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.

483 lines
13 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. utils.cpp
  5. Abstract:
  6. This file contains the implementation of various utility functions.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 03/14/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. static const WCHAR c_szDataFiles_Pattern[] = L"pchdt_*.ca?";
  14. ////////////////////////////////////////////////////////////////////////////////
  15. HRESULT SVC::OpenStreamForRead( /*[in]*/ LPCWSTR szFile ,
  16. /*[out]*/ IStream* *pVal ,
  17. /*[in]*/ bool fDeleteOnRelease )
  18. {
  19. __HCP_FUNC_ENTRY( "SVC::OpenStreamForRead" );
  20. HRESULT hr;
  21. CComPtr<MPC::FileStream> stream;
  22. MPC::wstring strFileFull;
  23. __MPC_PARAMCHECK_BEGIN(hr)
  24. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFile);
  25. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  26. __MPC_PARAMCHECK_END();
  27. MPC::SubstituteEnvVariables( strFileFull = szFile );
  28. //
  29. // Create a stream for a file.
  30. //
  31. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &stream ));
  32. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->InitForRead ( strFileFull.c_str() ));
  33. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->DeleteOnRelease( fDeleteOnRelease ));
  34. //
  35. // Return the stream to the caller.
  36. //
  37. *pVal = stream.Detach();
  38. hr = S_OK;
  39. __HCP_FUNC_CLEANUP;
  40. __HCP_FUNC_EXIT(hr);
  41. }
  42. HRESULT SVC::OpenStreamForWrite( /*[in]*/ LPCWSTR szFile ,
  43. /*[out]*/ IStream* *pVal ,
  44. /*[in]*/ bool fDeleteOnRelease )
  45. {
  46. __HCP_FUNC_ENTRY( "SVC::OpenStreamForWrite" );
  47. HRESULT hr;
  48. CComPtr<MPC::FileStream> stream;
  49. MPC::wstring strFileFull;
  50. __MPC_PARAMCHECK_BEGIN(hr)
  51. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szFile);
  52. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  53. __MPC_PARAMCHECK_END();
  54. MPC::SubstituteEnvVariables( strFileFull = szFile );
  55. //
  56. // Create a stream for a file.
  57. //
  58. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &stream ));
  59. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->InitForWrite ( strFileFull.c_str() ));
  60. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->DeleteOnRelease( fDeleteOnRelease ));
  61. //
  62. // Return the stream to the caller.
  63. //
  64. *pVal = stream.Detach();
  65. hr = S_OK;
  66. __HCP_FUNC_CLEANUP;
  67. __HCP_FUNC_EXIT(hr);
  68. }
  69. ////////////////////////////////////////////////////////////////////////////////
  70. HRESULT SVC::CopyFileWhileImpersonating( /*[in]*/ LPCWSTR szSrc ,
  71. /*[in]*/ LPCWSTR szDst ,
  72. /*[in]*/ MPC::Impersonation& imp ,
  73. /*[in]*/ bool fImpersonateForSource )
  74. {
  75. __HCP_FUNC_ENTRY( "SVC::CopyFileWhileImpersonating" );
  76. HRESULT hr;
  77. CComPtr<IStream> streamSrc;
  78. CComPtr<IStream> streamDst;
  79. if(fImpersonateForSource == true) __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  80. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForRead( szSrc, &streamSrc ));
  81. if(fImpersonateForSource == true) __MPC_EXIT_IF_METHOD_FAILS(hr, imp.RevertToSelf());
  82. ////////////////////
  83. if(fImpersonateForSource == false) __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  84. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( szDst, &streamDst ));
  85. if(fImpersonateForSource == false) __MPC_EXIT_IF_METHOD_FAILS(hr, imp.RevertToSelf());
  86. ////////////////////
  87. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamSrc, streamDst ));
  88. hr = S_OK;
  89. __HCP_FUNC_CLEANUP;
  90. (void)imp.RevertToSelf();
  91. __HCP_FUNC_EXIT(hr);
  92. }
  93. HRESULT SVC::CopyOrExtractFileWhileImpersonating( /*[in]*/ LPCWSTR szSrc ,
  94. /*[in]*/ LPCWSTR szDst ,
  95. /*[in]*/ MPC::Impersonation& imp )
  96. {
  97. __HCP_FUNC_ENTRY( "SVC::CopyOrExtractFileWhileImpersonating" );
  98. HRESULT hr;
  99. MPC::wstring strTempFile;
  100. //
  101. // First of all, try to simply copy the file.
  102. //
  103. if(FAILED(hr = CopyFileWhileImpersonating( szSrc, szDst, imp )))
  104. {
  105. int iLen = wcslen( szSrc );
  106. if(hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || iLen < 1)
  107. {
  108. __MPC_FUNC_LEAVE;
  109. }
  110. else
  111. {
  112. MPC::wstring strSrc2( szSrc ); strSrc2[iLen-1] = '_';
  113. LPCWSTR szSrc3;
  114. //
  115. // Simple copy failed, let's try to copy the same file, with the last character changed to an underscore.
  116. //
  117. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName( strTempFile ));
  118. __MPC_EXIT_IF_METHOD_FAILS(hr, CopyFileWhileImpersonating( strSrc2.c_str(), strTempFile.c_str(), imp ));
  119. //
  120. // Success, so it should be a cabinet, extract the real file.
  121. //
  122. szSrc3 = wcsrchr( szSrc, '\\' );
  123. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DecompressFromCabinet( strTempFile.c_str(), szDst, szSrc3 ? szSrc3+1 : szSrc ));
  124. }
  125. }
  126. hr = S_OK;
  127. __HCP_FUNC_CLEANUP;
  128. (void)MPC::RemoveTemporaryFile( strTempFile );
  129. __HCP_FUNC_EXIT(hr);
  130. }
  131. ////////////////////////////////////////////////////////////////////////////////
  132. HRESULT SVC::LocateDataArchive( /*[in ]*/ LPCWSTR szDir ,
  133. /*[out]*/ MPC::WStringList& lst )
  134. {
  135. __HCP_FUNC_ENTRY( "SVC::LocateDataArchive" );
  136. HRESULT hr;
  137. MPC::wstring strName;
  138. MPC::wstring strInput( szDir ); MPC::SubstituteEnvVariables( strInput );
  139. MPC::FileSystemObject fso ( strInput.c_str() );
  140. MPC::FileSystemObject::List fso_lst;
  141. MPC::FileSystemObject::IterConst fso_it;
  142. //
  143. // Locate the "pchdt_<XX>.ca?" file.
  144. //
  145. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.Scan( false, true, c_szDataFiles_Pattern ));
  146. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFiles( fso_lst ));
  147. for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
  148. {
  149. MPC::wstring& strDataArchive = *(lst.insert( lst.end() ));
  150. int iLen;
  151. __MPC_EXIT_IF_METHOD_FAILS(hr, (*fso_it)->get_Path( strDataArchive ));
  152. //
  153. // If it's a compressed file from the CD, return the real name.
  154. //
  155. iLen = strDataArchive.size();
  156. if(iLen && strDataArchive[iLen-1] == '_')
  157. {
  158. strDataArchive[iLen-1] = 'b';
  159. }
  160. }
  161. hr = S_OK;
  162. __HCP_FUNC_CLEANUP;
  163. __HCP_FUNC_EXIT(hr);
  164. }
  165. ////////////////////////////////////////////////////////////////////////////////
  166. HRESULT SVC::RemoveAndRecreateDirectory( /*[in]*/ const MPC::wstring& strDir, /*[in]*/ LPCWSTR szExtra, /*[in]*/ bool fRemove, /*[in]*/ bool fRecreate )
  167. {
  168. return RemoveAndRecreateDirectory( strDir.c_str(), szExtra, fRemove, fRecreate );
  169. }
  170. HRESULT SVC::RemoveAndRecreateDirectory( /*[in]*/ LPCWSTR szDir, /*[in]*/ LPCWSTR szExtra, /*[in]*/ bool fRemove, /*[in]*/ bool fRecreate )
  171. {
  172. HRESULT hr;
  173. MPC::wstring strPath( szDir ); if(szExtra) strPath.append( szExtra );
  174. if(SUCCEEDED(hr = MPC::SubstituteEnvVariables( strPath )))
  175. {
  176. MPC::FileSystemObject fso( strPath.c_str() );
  177. if(fRemove)
  178. {
  179. hr = fso.Delete( true, false );
  180. }
  181. if(SUCCEEDED(hr))
  182. {
  183. if(fRecreate)
  184. {
  185. hr = fso.CreateDir( /*fForce*/true );
  186. }
  187. }
  188. }
  189. return hr;
  190. }
  191. HRESULT SVC::ChangeSD( /*[in]*/ MPC::SecurityDescriptor& sdd ,
  192. /*[in]*/ MPC::wstring strPath ,
  193. /*[in]*/ LPCWSTR szExtra )
  194. {
  195. __HCP_FUNC_ENTRY( "SVC::ChangeSD" );
  196. HRESULT hr;
  197. if(szExtra) strPath.append( szExtra );
  198. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SubstituteEnvVariables( strPath ));
  199. {
  200. MPC::FileSystemObject fso( strPath.c_str() );
  201. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.CreateDir( true ));
  202. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::SetFileSecurityW( strPath.c_str() ,
  203. GROUP_SECURITY_INFORMATION |
  204. DACL_SECURITY_INFORMATION |
  205. PROTECTED_DACL_SECURITY_INFORMATION ,
  206. sdd.GetSD() ));
  207. }
  208. hr = S_OK;
  209. __MPC_FUNC_CLEANUP;
  210. __MPC_FUNC_EXIT(hr);
  211. }
  212. ////////////////////////////////////////////////////////////////////////////////
  213. static HRESULT local_ReadWithRetry( /*[in]*/ const MPC::wstring& strFile ,
  214. /*[in]*/ MPC::FileStream* stream ,
  215. /*[in]*/ DWORD dwTimeout ,
  216. /*[in]*/ DWORD dwRetries )
  217. {
  218. HRESULT hr;
  219. while(1)
  220. {
  221. if(SUCCEEDED(hr = stream->InitForRead( strFile.c_str() ))) return S_OK;
  222. if(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED ) ||
  223. hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) ||
  224. hr == HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION ) )
  225. {
  226. (void)stream->Close();
  227. if(dwRetries)
  228. {
  229. ::Sleep( dwTimeout );
  230. dwRetries--;
  231. continue;
  232. }
  233. }
  234. break;
  235. }
  236. return hr;
  237. }
  238. static HRESULT local_WriteWithRetry( /*[in]*/ const MPC::wstring& strFile ,
  239. /*[in]*/ MPC::FileStream* stream ,
  240. /*[in]*/ DWORD dwTimeout ,
  241. /*[in]*/ DWORD dwRetries )
  242. {
  243. HRESULT hr;
  244. while(1)
  245. {
  246. if(SUCCEEDED(hr = stream->InitForWrite( strFile.c_str() ))) return S_OK;
  247. if(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED ) ||
  248. hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) ||
  249. hr == HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION ) )
  250. {
  251. (void)stream->Close();
  252. if(dwRetries)
  253. {
  254. ::Sleep( dwTimeout );
  255. dwRetries--;
  256. continue;
  257. }
  258. }
  259. break;
  260. }
  261. return hr;
  262. }
  263. HRESULT SVC::SafeLoad( /*[in]*/ const MPC::wstring& strFile ,
  264. /*[in]*/ CComPtr<MPC::FileStream>& stream ,
  265. /*[in]*/ DWORD dwTimeout ,
  266. /*[in]*/ DWORD dwRetries )
  267. {
  268. __HCP_FUNC_ENTRY( "SVC::SafeLoad" );
  269. HRESULT hr;
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &stream ));
  271. //
  272. // If fails, try to load "<file>.orig"
  273. //
  274. if(FAILED(hr = local_ReadWithRetry( strFile, stream, dwTimeout, dwRetries )))
  275. {
  276. MPC::wstring strFileOrig( strFile ); strFileOrig += L".orig";
  277. __MPC_EXIT_IF_METHOD_FAILS(hr, local_ReadWithRetry( strFileOrig, stream, dwTimeout, dwRetries ));
  278. }
  279. hr = S_OK;
  280. __HCP_FUNC_CLEANUP;
  281. __HCP_FUNC_EXIT(hr);
  282. }
  283. HRESULT SVC::SafeSave_Init( /*[in]*/ const MPC::wstring& strFile ,
  284. /*[in]*/ CComPtr<MPC::FileStream>& stream ,
  285. /*[in]*/ DWORD dwTimeout ,
  286. /*[in]*/ DWORD dwRetries )
  287. {
  288. __HCP_FUNC_ENTRY( "SVC::SafeSave_Init" );
  289. HRESULT hr;
  290. MPC::wstring strFileNew( strFile ); strFileNew += L".new";
  291. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir ( strFileNew ));
  292. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance ( &stream ));
  293. __MPC_EXIT_IF_METHOD_FAILS(hr, local_WriteWithRetry( strFileNew, stream, dwTimeout, dwRetries ));
  294. hr = S_OK;
  295. __HCP_FUNC_CLEANUP;
  296. __HCP_FUNC_EXIT(hr);
  297. }
  298. HRESULT SVC::SafeSave_Finalize( /*[in]*/ const MPC::wstring& strFile ,
  299. /*[in]*/ CComPtr<MPC::FileStream>& stream ,
  300. /*[in]*/ DWORD dwTimeout ,
  301. /*[in]*/ DWORD dwRetries )
  302. {
  303. __HCP_FUNC_ENTRY( "SVC::SafeSave_Finalize" );
  304. HRESULT hr;
  305. MPC::wstring strFileNew ( strFile ); strFileNew += L".new";
  306. MPC::wstring strFileOrig( strFile ); strFileOrig += L".orig";
  307. stream.Release();
  308. //
  309. // Then move "<file>" to "<file>.orig"
  310. //
  311. (void)MPC::DeleteFile( strFileOrig );
  312. (void)MPC::MoveFile ( strFile, strFileOrig );
  313. while(1)
  314. {
  315. //
  316. // Then rename "<file>.new" to "<file>"
  317. //
  318. if(SUCCEEDED(hr = MPC::MoveFile( strFileNew, strFile ))) break;
  319. if(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED ) ||
  320. hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) ||
  321. hr == HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION ) )
  322. {
  323. if(dwRetries)
  324. {
  325. ::Sleep( dwTimeout );
  326. dwRetries--;
  327. continue;
  328. }
  329. }
  330. __MPC_FUNC_LEAVE;
  331. }
  332. //
  333. // Finally delete "<file>.orig"
  334. //
  335. (void)MPC::DeleteFile( strFileOrig );
  336. hr = S_OK;
  337. __HCP_FUNC_CLEANUP;
  338. __HCP_FUNC_EXIT(hr);
  339. }