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.

528 lines
14 KiB

  1. // ===========================================================================
  2. // File: PACKET.CXX
  3. //
  4. // Packet Manager for Code Downloader
  5. // A Packet is a unit of work that takes time eg. trust verifcation of a piece
  6. // setup of a piece or INF processing of one piece. To be able to have the
  7. // client be responsive with UI and abort capabilty we need to split out work
  8. // into as small units as possible and queue up these CDLPackets
  9. // CDLPackets get run on a timer per thread.
  10. #include <cdlpch.h>
  11. //+---------------------------------------------------------------------------
  12. //
  13. // Function: CDL_PacketProcessProc
  14. //
  15. // Synopsis: the timer proc to process packet
  16. //
  17. // Arguments: [hWnd] --
  18. // [WPARAM] --
  19. // [idEvent] --
  20. // [dwTime] --
  21. //
  22. // Returns:
  23. //----------------------------------------------------------------------------
  24. VOID CALLBACK CDL_PacketProcessProc(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
  25. {
  26. DEBUG_ENTER((DBG_DOWNLOAD,
  27. None,
  28. "CDL_PacketProcessProc",
  29. "%#x, #x, %#x, %#x",
  30. hWnd, msg, idEvent, dwTime
  31. ));
  32. HRESULT hr = NO_ERROR;
  33. CUrlMkTls tls(hr); // hr passed by reference!
  34. Assert(SUCCEEDED(hr));
  35. Assert(msg == WM_TIMER);
  36. Assert(idEvent);
  37. if (SUCCEEDED(hr)) { // if tls ctor passed above
  38. Assert(tls->pCDLPacketMgr);
  39. // give the packet mgr a time slice
  40. // so a packet can be processed.
  41. if (tls->pCDLPacketMgr)
  42. hr = tls->pCDLPacketMgr->TimeSlice();
  43. Assert(SUCCEEDED(hr));
  44. }
  45. DEBUG_LEAVE(0);
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. // Function: CCDLPacketMgr::CCDLPacketMgr
  50. //----------------------------------------------------------------------------
  51. CCDLPacketMgr::CCDLPacketMgr()
  52. {
  53. DEBUG_ENTER((DBG_DOWNLOAD,
  54. None,
  55. "CCDLPacketMgr::CCDLPacketMgr",
  56. "this=%#x",
  57. this
  58. ));
  59. m_Timer = 0;
  60. m_PacketList.RemoveAll();
  61. DEBUG_LEAVE(0);
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: CCDLPacketMgr::~CCDLPacketMgr
  66. //----------------------------------------------------------------------------
  67. CCDLPacketMgr::~CCDLPacketMgr()
  68. {
  69. DEBUG_ENTER((DBG_DOWNLOAD,
  70. None,
  71. "CCDLPacketMgr::~CCDLPacketMgr",
  72. "this=%#x",
  73. this
  74. ));
  75. if (m_Timer) {
  76. KillTimer(NULL, m_Timer);
  77. }
  78. m_PacketList.RemoveAll();
  79. DEBUG_LEAVE(0);
  80. }
  81. //+---------------------------------------------------------------------------
  82. //
  83. // Function: CCDLPacketMgr::AbortPackets(CDownload *pdl)
  84. //
  85. // Aborts all packets on the thread that are to do with pdl or
  86. // its parent codedownload (pdl->GetCodeDownload())
  87. //----------------------------------------------------------------------------
  88. HRESULT
  89. CCDLPacketMgr::AbortPackets(CDownload *pdl)
  90. {
  91. DEBUG_ENTER((DBG_DOWNLOAD,
  92. Hresult,
  93. "CCDLPacketMgr::AbortPackets",
  94. "this=%#x, %#x",
  95. this, pdl
  96. ));
  97. HRESULT hr = S_FALSE; //assume none found to be killed
  98. int iNumPkts;
  99. LISTPOSITION pos;
  100. if (!pdl) {
  101. DEBUG_LEAVE(E_INVALIDARG);
  102. return E_INVALIDARG;
  103. }
  104. iNumPkts = m_PacketList.GetCount();
  105. pos = m_PacketList.GetHeadPosition();
  106. for (int i=0; i < iNumPkts; i++) {
  107. CCDLPacket *pPkt = m_PacketList.GetNext(pos); // pass ref!
  108. if ( (pdl == pPkt->GetDownload()) ||
  109. (pdl->GetCodeDownload() == pPkt->GetCodeDownload()) ) {
  110. // AbortPackekts is only called from DoSetup. There should
  111. // normally be no packets left to kill.
  112. // Assert that this is a NOP.
  113. UrlMkDebugOut((DEB_CODEDL, "CODE DL:AbortPackets URL:(%ws)\n", pdl->GetURL()));
  114. Assert(pPkt == NULL);
  115. Kill(pPkt);
  116. hr = S_OK; // indicate killed atleast one
  117. }
  118. }
  119. // here is no more packets in this thread that match CDownload* pdl
  120. DEBUG_LEAVE(hr);
  121. return hr;
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Function: CCDLPacketMgr::Kill(CCDLPacket *pPkt)
  126. //
  127. // kills packet (removes it from the thread list and deletes it
  128. //----------------------------------------------------------------------------
  129. HRESULT
  130. CCDLPacketMgr::Kill(CCDLPacket *pPkt)
  131. {
  132. DEBUG_ENTER((DBG_DOWNLOAD,
  133. Hresult,
  134. "CCDLPacketMgr::Kill",
  135. "this=%#x, %#x",
  136. this, pPkt
  137. ));
  138. LISTPOSITION pos = m_PacketList.Find(pPkt);
  139. if(pos != NULL)
  140. m_PacketList.RemoveAt(pos);
  141. delete pPkt;
  142. DEBUG_LEAVE(S_OK);
  143. return S_OK;
  144. }
  145. //+---------------------------------------------------------------------------
  146. //
  147. // Function: CCDLPacketMgr::Post(CCDLPacket *pPkt, ULONG pri)
  148. //
  149. // Adds the packet to the list. The packet will get processed
  150. // on a subsequent timer in the order it appears on the list
  151. // Also kicks off a timer if none exists already
  152. //----------------------------------------------------------------------------
  153. HRESULT
  154. CCDLPacketMgr::Post(CCDLPacket *pPkt, ULONG pri)
  155. {
  156. DEBUG_ENTER((DBG_DOWNLOAD,
  157. Hresult,
  158. "CCDLPacketMgr::Post",
  159. "this=%#x, %#x, %#x",
  160. this, pPkt, pri
  161. ));
  162. HRESULT hr = S_OK;
  163. UINT_PTR idEvent = (UINT_PTR) this;
  164. if (!m_Timer) {
  165. m_Timer = SetTimer(NULL, idEvent,
  166. PROCESS_PACKET_INTERVAL, CDL_PacketProcessProc);
  167. if (!m_Timer) {
  168. hr = HRESULT_FROM_WIN32(GetLastError());
  169. goto Exit;
  170. }
  171. }
  172. //BUGBUG: if we want priority classes then we soudl really have
  173. // multiple lists! This will also affect the order if
  174. // any sequencing is involved
  175. if (pri == PACKET_PRIORITY_HIGH) {
  176. m_PacketList.AddHead(pPkt);
  177. } else {
  178. m_PacketList.AddTail(pPkt);
  179. }
  180. Exit:
  181. DEBUG_LEAVE(hr);
  182. return hr;
  183. }
  184. //+---------------------------------------------------------------------------
  185. //
  186. // Function: CCDLPacketMgr::TimeSlice()
  187. //
  188. // called from the timer proc.
  189. // This is like a simple light weight thread machinery that executes/processes
  190. // one packet per timer msg.
  191. // Kills the timer if there are no other code downloads on thread.
  192. //----------------------------------------------------------------------------
  193. HRESULT
  194. CCDLPacketMgr::TimeSlice()
  195. {
  196. DEBUG_ENTER((DBG_DOWNLOAD,
  197. Hresult,
  198. "CCDLPacketMgr::TimeSlice",
  199. "this=%#x",
  200. this
  201. ));
  202. HRESULT hr = S_OK;
  203. int iNumPkts = m_PacketList.GetCount();
  204. if (!iNumPkts) {
  205. // nothing to do. This may happen when processing the previous
  206. // packet yields and so we re-enter the timer proc without
  207. // ever completing the first.
  208. DEBUG_LEAVE(hr);
  209. return hr;
  210. }
  211. // have work to do!
  212. CCDLPacket* pPkt = m_PacketList.RemoveHead();
  213. Assert(pPkt);
  214. hr = pPkt->Process();
  215. // need to refresh this value as the procesing of current pkt
  216. // may have posted other packets!
  217. iNumPkts = m_PacketList.GetCount();
  218. if (!iNumPkts &&
  219. (CCodeDownload::AnyCodeDownloadsInThread() == S_FALSE)) {
  220. if (m_Timer) {
  221. KillTimer(NULL, m_Timer);
  222. m_Timer = 0;
  223. }
  224. }
  225. DEBUG_LEAVE(hr);
  226. return hr;
  227. }
  228. //+---------------------------------------------------------------------------
  229. //
  230. // Function: CCDLPacket::CCDLPacket(DWORD type, CDownload *pdl, DWORD param)
  231. //
  232. // twin constructors that take either CDownload or CCodeDownload obj
  233. //----------------------------------------------------------------------------
  234. CCDLPacket::CCDLPacket(DWORD type, CDownload *pdl, DWORD_PTR param)
  235. {
  236. DEBUG_ENTER((DBG_DOWNLOAD,
  237. None,
  238. "CCDLPacket::CCDLPacket",
  239. "this=%#x, %#x, %#x, %#x",
  240. this, type, pdl, param
  241. ));
  242. m_signature = CPP_SIGNATURE;
  243. m_type = type;
  244. m_param = param;
  245. Assert ((GETMSGTYPE(m_type) == MSG_CDOWNLOAD_OBJ));
  246. Assert(pdl);
  247. m_obj.pdl = pdl;
  248. DEBUG_LEAVE(0);
  249. };
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Function:CCDLPacket::CCDLPacket(DWORD type, CCodeDownload *pcdl,DWORD param)
  253. //----------------------------------------------------------------------------
  254. CCDLPacket::CCDLPacket(DWORD type, CCodeDownload *pcdl, DWORD_PTR param)
  255. {
  256. DEBUG_ENTER((DBG_DOWNLOAD,
  257. None,
  258. "CCDLPacket::CCDLPacket",
  259. "this=%#x, %#x, %#x, %#x",
  260. this, type, pcdl, param
  261. ));
  262. m_signature = CPP_SIGNATURE;
  263. m_type = type;
  264. m_param = param;
  265. Assert ((GETMSGTYPE(m_type) == MSG_CCODEDOWNLOAD_OBJ));
  266. Assert(pcdl);
  267. m_obj.pcdl = pcdl;
  268. DEBUG_LEAVE(0);
  269. };
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Function: CCDLPacket::~CCDLPacket()
  273. //----------------------------------------------------------------------------
  274. CCDLPacket::~CCDLPacket()
  275. {
  276. DEBUG_ENTER((DBG_DOWNLOAD,
  277. None,
  278. "CCDLPacket::~CCDLPacket",
  279. "this=%#x",
  280. this
  281. ));
  282. m_signature = 0;
  283. DEBUG_LEAVE(0);
  284. }
  285. //+---------------------------------------------------------------------------
  286. //
  287. // Function: CCDLPacket::Post(ULONG pri)
  288. //
  289. // just punts the posting work to the packet mgr.
  290. //----------------------------------------------------------------------------
  291. HRESULT
  292. CCDLPacket::Post(ULONG pri)
  293. {
  294. DEBUG_ENTER((DBG_DOWNLOAD,
  295. Hresult,
  296. "CCDLPacket::Post",
  297. "this=%#x, %#x",
  298. this, pri
  299. ));
  300. HRESULT hr = S_OK;
  301. CUrlMkTls tls(hr); // hr passed by reference!
  302. if (FAILED(hr)) { // if tls ctor failed above
  303. goto Exit;
  304. }
  305. Assert(m_obj.pcdl);
  306. Assert(tls->pCDLPacketMgr);
  307. if (tls->pCDLPacketMgr)
  308. hr = tls->pCDLPacketMgr->Post(this, pri);
  309. Exit:
  310. DEBUG_LEAVE(hr);
  311. return hr;
  312. }
  313. //+---------------------------------------------------------------------------
  314. //
  315. // Function: CCDLPacket::Process()
  316. //
  317. // Called from the packet manager's TimeSlice to process packet.
  318. //----------------------------------------------------------------------------
  319. HRESULT
  320. CCDLPacket::Process()
  321. {
  322. DEBUG_ENTER((DBG_DOWNLOAD,
  323. Hresult,
  324. "CCDLPacket::Process",
  325. "this=%#x",
  326. this
  327. ));
  328. HRESULT hr = S_OK;
  329. // Code Download messages, arrive in this order
  330. // First a binding completes and needs to be trusted
  331. // Next the trusted piece gets processed in ProcessPiece
  332. // Next if the piece arrived was a CAB and had an INF in it
  333. // the INF gets processed piece by piece
  334. // initiating new downloads if necessary or extracting out of
  335. // already arrived CAB
  336. // After all pieces are processed and all bindings completed
  337. // we enter the setup phase, setting up one piece per message.
  338. // The reason we break it up into some many messages is to make the
  339. // browser be as responsive during code download and installation as
  340. // possible and keep the clouds animation smooth.
  341. Assert(m_signature == CPP_SIGNATURE);
  342. switch(m_type) {
  343. case CODE_DOWNLOAD_TRUST_PIECE:
  344. {
  345. CDownload *pdl = m_obj.pdl;
  346. if (pdl)
  347. pdl->VerifyTrust();
  348. }
  349. break;
  350. case CODE_DOWNLOAD_PROCESS_PIECE:
  351. {
  352. CDownload *pdl = m_obj.pdl;
  353. if (pdl)
  354. pdl->ProcessPiece();
  355. }
  356. break;
  357. case CODE_DOWNLOAD_PROCESS_INF:
  358. {
  359. CCodeDownload *pcdl = m_obj.pcdl;
  360. if (pcdl)
  361. pcdl->ProcessInf( (CDownload *) m_param);
  362. }
  363. break;
  364. case CODE_DOWNLOAD_SETUP:
  365. {
  366. CCodeDownload *pcdl = m_obj.pcdl;
  367. if (pcdl)
  368. pcdl->DoSetup();
  369. }
  370. break;
  371. case CODE_DOWNLOAD_WAIT_FOR_EXE:
  372. {
  373. CCodeDownload *pcdl = m_obj.pcdl;
  374. if (pcdl) {
  375. hr = pcdl->SelfRegEXETimeout();
  376. Assert(SUCCEEDED(hr));
  377. }
  378. }
  379. break;
  380. }
  381. DEBUG_LEAVE(S_OK);
  382. return S_OK;
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Function: CCDLPacket::Kill()
  387. //----------------------------------------------------------------------------
  388. HRESULT
  389. CCDLPacket::Kill()
  390. {
  391. DEBUG_ENTER((DBG_DOWNLOAD,
  392. Hresult,
  393. "CCDLPacket::Kill",
  394. "this=%#x",
  395. this
  396. ));
  397. HRESULT hr = S_OK;
  398. CUrlMkTls tls(hr); // hr passed by reference!
  399. if (FAILED(hr)) { // if tls ctor failed above
  400. goto Exit;
  401. }
  402. Assert(tls->pCDLPacketMgr);
  403. if (tls->pCDLPacketMgr)
  404. hr = tls->pCDLPacketMgr->Kill(this);
  405. Exit:
  406. DEBUG_LEAVE(S_OK);
  407. return S_OK;
  408. }