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.

475 lines
10 KiB

  1. #include <fusenetincludes.h>
  2. #include <bits.h>
  3. #include "regdb.h"
  4. #include "list.h"
  5. #include "assemblydownload.h"
  6. #include "macros.h"
  7. #define REG_KEY_FUSION_PENDING_JOBS TEXT("1.0.0.0\\PendingJobs\\")
  8. #define TEMP_FILE_STRING TEXT("TempFile")
  9. #define URL_STRING TEXT("Url")
  10. struct CJobGuid
  11. {
  12. GUID guid;
  13. };
  14. HRESULT AddJobToRegistry(LPWSTR pwzURL,
  15. LPWSTR pwzTempFile,
  16. IBackgroundCopyJob *pJob,
  17. DWORD dwFlags)
  18. {
  19. HRESULT hr = S_OK;
  20. MAKE_ERROR_MACROS_STATIC(hr);
  21. GUID JobGUID;
  22. CString sRegKey;
  23. CString sGUID;
  24. CRegEmit *pRegEmit = NULL;
  25. // ASSERT( lstrlen(sURL._pwz) && lstrlen(sTempFile._pwz) && pJob);
  26. IF_FAILED_EXIT(pJob->GetId( &JobGUID));
  27. FusionFormatGUID(JobGUID, sGUID);
  28. // GUIDToString(&JobGUID, sGUID);
  29. IF_FAILED_EXIT(sRegKey.Assign(REG_KEY_FUSION_PENDING_JOBS));
  30. IF_FAILED_EXIT(sRegKey.Append(sGUID));
  31. IF_FAILED_EXIT(CRegEmit::Create(&pRegEmit, sRegKey._pwz));
  32. IF_FAILED_EXIT(pRegEmit->WriteString(URL_STRING, pwzURL));
  33. IF_FAILED_EXIT(pRegEmit->WriteString(TEMP_FILE_STRING, pwzTempFile));
  34. exit:
  35. SAFEDELETE(pRegEmit);
  36. return hr;
  37. }
  38. HRESULT RemoveJobFromRegistry(IBackgroundCopyJob *pJob,
  39. GUID *pGUID, SHREGDEL_FLAGS dwDelRegFlags, DWORD dwFlags)
  40. {
  41. HRESULT hr = S_OK;
  42. MAKE_ERROR_MACROS_STATIC(hr);
  43. GUID JobGUID;
  44. LONG lResult;
  45. CString sRegKey;
  46. CString sGUID;
  47. CRegEmit *pRegEmit = NULL;
  48. CRegImport *pRegImp = NULL;
  49. // ASSERT( lstrlen(sURL._pwz) && lstrlen(sTempFile._pwz) && pJob);
  50. if(pJob)
  51. {
  52. IF_FAILED_EXIT(pJob->GetId( &JobGUID));
  53. }
  54. else
  55. {
  56. JobGUID = *pGUID;
  57. }
  58. FusionFormatGUID(JobGUID, sGUID);
  59. // GUIDToString(&JobGUID, sGUID);
  60. IF_FAILED_EXIT(sRegKey.Assign(REG_KEY_FUSION_PENDING_JOBS));
  61. IF_FAILED_EXIT(sRegKey.Append(sGUID));
  62. IF_FAILED_EXIT(CRegImport::Create(&pRegImp, sRegKey._pwz));
  63. if(hr == S_FALSE)
  64. goto exit;
  65. if(dwFlags & RJFR_DELETE_FILES) // delete the temp files also
  66. {
  67. CString sTempPath;
  68. IF_FAILED_EXIT(pRegImp->ReadString(TEMP_FILE_STRING, sTempPath));
  69. IF_FAILED_EXIT(sTempPath.RemoveLastElement());
  70. IF_FAILED_EXIT(RemoveDirectoryAndChildren(sTempPath._pwz));
  71. }
  72. IF_FAILED_EXIT(sRegKey.Assign(REG_KEY_FUSION_PENDING_JOBS));
  73. IF_FAILED_EXIT(CRegEmit::Create(&pRegEmit, sRegKey._pwz));
  74. IF_FAILED_EXIT(pRegEmit->DeleteKey(sGUID._pwz));
  75. exit:
  76. SAFEDELETE(pRegEmit);
  77. SAFEDELETE(pRegImp);
  78. return hr;
  79. }
  80. #define CCH_GUID (38)
  81. void FusionFormatGUID(GUID guid, CString& sGUID)
  82. {
  83. WCHAR szBuf[MAX_PATH+1];
  84. // ASSERT(sGUID);
  85. wnsprintf(szBuf, MAX_PATH, L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  86. guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1],
  87. guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
  88. sGUID.Assign(szBuf);
  89. }
  90. int HexDigitToValue(WCHAR wch)
  91. {
  92. if ((wch >= L'a') && (wch <= L'f'))
  93. return 10 + (wch - L'a');
  94. else if ((wch >= L'A') && (wch <= 'F'))
  95. return 10 + (wch - L'A');
  96. else if (wch >= '0' && wch <= '9')
  97. return (wch - L'0');
  98. else
  99. return -1;
  100. }
  101. bool IsHexDigit(WCHAR wch)
  102. {
  103. return (((wch >= L'0') && (wch <= L'9')) ||
  104. ((wch >= L'a') && (wch <= L'f')) ||
  105. ((wch >= L'A') && (wch <= L'F')));
  106. }
  107. HRESULT FusionParseGUID(
  108. LPWSTR String,
  109. SIZE_T Cch,
  110. GUID &rGuid
  111. )
  112. {
  113. HRESULT hr = S_OK;
  114. SIZE_T ich;
  115. ULONG i;
  116. ULONG acc;
  117. if (Cch != CCH_GUID)
  118. {
  119. hr = E_INVALIDARG;
  120. goto exit;
  121. }
  122. ich = 1;
  123. if (*String++ != L'{')
  124. {
  125. hr = E_INVALIDARG;
  126. goto exit;
  127. }
  128. ich++;
  129. // Parse the first segment...
  130. acc = 0;
  131. for (i=0; i<8; i++)
  132. {
  133. WCHAR wch = *String++;
  134. if (!::IsHexDigit(wch))
  135. {
  136. hr = E_INVALIDARG;
  137. goto exit;
  138. }
  139. ich++;
  140. acc = acc << 4;
  141. acc += HexDigitToValue(wch);
  142. }
  143. rGuid.Data1 = acc;
  144. // Look for the dash...
  145. if (*String++ != L'-')
  146. {
  147. hr = E_INVALIDARG;
  148. goto exit;
  149. }
  150. ich++;
  151. acc = 0;
  152. for (i=0; i<4; i++)
  153. {
  154. WCHAR wch = *String++;
  155. if (!::IsHexDigit(wch))
  156. {
  157. hr = E_INVALIDARG;
  158. goto exit;
  159. }
  160. ich++;
  161. acc = acc << 4;
  162. acc += HexDigitToValue(wch);
  163. }
  164. rGuid.Data2 = static_cast<USHORT>(acc);
  165. // Look for the dash...
  166. if (*String++ != L'-')
  167. {
  168. hr = E_INVALIDARG;
  169. goto exit;
  170. }
  171. ich++;
  172. acc = 0;
  173. for (i=0; i<4; i++)
  174. {
  175. WCHAR wch = *String++;
  176. if (!::IsHexDigit(wch))
  177. {
  178. hr = E_INVALIDARG;
  179. goto exit;
  180. }
  181. ich++;
  182. acc = acc << 4;
  183. acc += HexDigitToValue(wch);
  184. }
  185. rGuid.Data3 = static_cast<USHORT>(acc);
  186. // Look for the dash...
  187. if (*String++ != L'-')
  188. {
  189. hr = E_INVALIDARG;
  190. goto exit;
  191. }
  192. ich++;
  193. for (i=0; i<8; i++)
  194. {
  195. WCHAR wch1, wch2;
  196. wch1 = *String++;
  197. if (!::IsHexDigit(wch1))
  198. {
  199. hr = E_INVALIDARG;
  200. goto exit;
  201. }
  202. ich++;
  203. wch2 = *String++;
  204. if (!::IsHexDigit(wch2))
  205. {
  206. hr = E_INVALIDARG;
  207. goto exit;
  208. }
  209. ich++;
  210. rGuid.Data4[i] = static_cast<unsigned char>((::HexDigitToValue(wch1) << 4) | ::HexDigitToValue(wch2));
  211. // There's a dash after the 2nd byte
  212. if (i == 1)
  213. {
  214. if (*String++ != L'-')
  215. {
  216. hr = E_INVALIDARG;
  217. goto exit;
  218. }
  219. ich++;
  220. }
  221. }
  222. // This replacement should be made.
  223. //INTERNAL_ERROR_CHECK(ich == CCH_GUID);
  224. // ASSERT(ich == CCH_GUID);
  225. if (*String != L'}')
  226. {
  227. hr = E_INVALIDARG;
  228. goto exit;
  229. }
  230. exit:
  231. return hr;
  232. }
  233. #define FROMHEX(a) ((a)>=L'a' ? a - L'a' + 10 : a - L'0')
  234. #define TOLOWER(a) (((a) >= L'A' && (a) <= L'Z') ? (L'a' + (a - L'A')) : (a))
  235. //--------------------------------------------------------------------
  236. // GUIDToUnicodeHex
  237. //--------------------------------------------------------------------
  238. HRESULT GUIDToString(GUID *pGUID, CString& sGUID)
  239. {
  240. HRESULT hr = S_OK;
  241. WCHAR pDst[MAX_PATH];
  242. LPBYTE pSrc = (LPBYTE) pGUID;
  243. UINT cSrc = sizeof(GUID);
  244. UINT x;
  245. UINT y;
  246. #define TOHEX(a) ((a)>=10 ? L'a'+(a)-10 : L'0'+(a))
  247. for ( x = 0, y = 0 ; x < cSrc ; ++x )
  248. {
  249. UINT v;
  250. v = pSrc[x]>>4;
  251. pDst[y++] = TOHEX( v );
  252. v = pSrc[x] & 0x0f;
  253. pDst[y++] = TOHEX( v );
  254. }
  255. pDst[y] = '\0';
  256. hr = sGUID.Assign(pDst);
  257. // exit :
  258. return hr;
  259. }
  260. //--------------------------------------------------------------------
  261. // UnicodeHexToGUID
  262. //--------------------------------------------------------------------
  263. HRESULT StringToGUID(LPCWSTR pSrc, UINT cSrc, GUID *pGUID)
  264. {
  265. BYTE v;
  266. LPBYTE pd = (LPBYTE) pGUID;
  267. LPCWSTR ps = pSrc;
  268. for (UINT i = 0; i < cSrc-1; i+=2)
  269. {
  270. v = FROMHEX(TOLOWER(ps[i])) << 4;
  271. v |= FROMHEX(TOLOWER(ps[i+1]));
  272. *(pd++) = v;
  273. }
  274. return S_OK;
  275. }
  276. HRESULT EnumPendingJobs(List <CJobGuid*> **ppJobList)
  277. {
  278. HRESULT hr = S_OK;
  279. MAKE_ERROR_MACROS_STATIC(hr);
  280. CRegImport *pRegImp=NULL;
  281. GUID JobGUID = {0};
  282. CString sRegKey;
  283. int iIndex = 0;
  284. List<CJobGuid *> *pJobList= new (List<CJobGuid *>);
  285. CJobGuid *pNode;
  286. CString sGUID;
  287. *ppJobList = NULL;
  288. sRegKey.Assign(REG_KEY_FUSION_PENDING_JOBS);
  289. IF_FAILED_EXIT(CRegImport::Create(&pRegImp, sRegKey._pwz));
  290. if(hr == S_FALSE)
  291. goto exit;
  292. while ( (hr = pRegImp->EnumKeys(iIndex++, sGUID)) == S_OK )
  293. {
  294. IF_FAILED_EXIT(FusionParseGUID(sGUID._pwz, lstrlen(sGUID._pwz), JobGUID));
  295. IF_ALLOC_FAILED_EXIT(pNode = new (CJobGuid));
  296. pNode->guid = JobGUID;
  297. pJobList->AddHead(pNode);
  298. }
  299. if(hr == S_FALSE)
  300. hr = S_OK;
  301. else
  302. goto exit;
  303. *ppJobList = pJobList;
  304. exit :
  305. if(!(*ppJobList))
  306. {
  307. SAFEDELETE(pJobList); // this should call RemoveAll();
  308. }
  309. SAFEDELETE(pRegImp);
  310. return hr;
  311. }
  312. HRESULT SalvageOrphanedJob(IBackgroundCopyJob *pJob)
  313. {
  314. return E_NOTIMPL;
  315. }
  316. HRESULT ProcessOrphanedJobs()
  317. {
  318. HRESULT hr = S_OK;
  319. MAKE_ERROR_MACROS_STATIC(hr);
  320. List <CJobGuid*> *pJobList = NULL;
  321. LISTNODE pTempList=NULL;
  322. int iJobCount=0,i=0;
  323. CJobGuid *pTargetJob;
  324. IBackgroundCopyJob *pJob = NULL;
  325. IF_FAILED_EXIT( EnumPendingJobs( &pJobList));
  326. IF_FAILED_EXIT(CAssemblyDownload::InitBITS());
  327. // process list .....
  328. pTempList = pJobList->GetHeadPosition();
  329. iJobCount = pJobList->GetCount();
  330. for(i=0; i<iJobCount; i++)
  331. {
  332. pTargetJob = pJobList->GetNext(pTempList); // Element from list;
  333. pJob = NULL;
  334. hr = g_pBITSManager->GetJob(pTargetJob->guid, &pJob);
  335. // Check if we can salvage this job
  336. if( FAILED(hr = SalvageOrphanedJob(pJob)))
  337. {
  338. if(pJob)
  339. hr = pJob->Cancel();
  340. // if cancel fails, log it.
  341. // RemoveDirectoryAndChildren();
  342. IF_FAILED_EXIT(RemoveJobFromRegistry(pJob, &(pTargetJob->guid), SHREGDEL_HKCU, RJFR_DELETE_FILES));
  343. }
  344. SAFERELEASE(pJob);
  345. }
  346. exit:
  347. // destroy list.
  348. if(pJobList)
  349. {
  350. pTempList = pJobList->GetHeadPosition();
  351. iJobCount = pJobList->GetCount();
  352. for(i=0; i<iJobCount; i++)
  353. {
  354. pTargetJob = pJobList->GetNext(pTempList); // Element from list;
  355. SAFEDELETE(pTargetJob);
  356. }
  357. pJobList->RemoveAll();
  358. SAFEDELETE(pJobList); // this should call RemoveAll
  359. }
  360. SAFERELEASE(pJob);
  361. return hr;
  362. }