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.

649 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: transmgr.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-02-95 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <trans.h>
  18. PerfDbgTag(tagCTransMgr, "Urlmon", "Log CTransactionMgr", DEB_TRANSMGR);
  19. DbgTag(tagCTransMgrErr, "Urlmon", "Log CTransMgr Errors", DEB_TRANSMGR|DEB_ERROR);
  20. extern HINSTANCE g_hInst;
  21. LRESULT CALLBACK TransactionWndProc(HWND hWnd, UINT msg,WPARAM wParam, LPARAM lParam);
  22. #define szURLMonClassName "URL Moniker Notification Window"
  23. static BOOL g_fWndClassRegistered = FALSE;
  24. CMutexSem g_mxsTransMgr;
  25. URLMON_TS* GetTS(DWORD);
  26. HRESULT AddTSToList(URLMON_TS*);
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: GetThreadTransactionMgr
  30. //
  31. // Synopsis:
  32. //
  33. // Arguments: [fCreate] --
  34. //
  35. // Returns:
  36. //
  37. // History: 1-14-96 JohannP (Johann Posch) Created
  38. //
  39. // Notes:
  40. //
  41. //----------------------------------------------------------------------------
  42. CTransactionMgr * GetThreadTransactionMgr(BOOL fCreate)
  43. {
  44. DEBUG_ENTER((DBG_TRANSMGR,
  45. Pointer,
  46. "GetThreadTransactionMgr",
  47. "%B",
  48. fCreate
  49. ));
  50. PerfDbgLog(tagCTransMgr, NULL, "+GetThreadTransactionMgr");
  51. // only one thread should be here
  52. CLock lck(g_mxsMedia);
  53. HRESULT hr = NOERROR;
  54. CTransactionMgr *pCTMgr = NULL;
  55. CUrlMkTls tls(hr);
  56. if (hr == NOERROR)
  57. {
  58. pCTMgr = tls->pCTransMgr;
  59. if ((pCTMgr == NULL) && fCreate)
  60. {
  61. // the transaction mgr has an refcount of 1
  62. tls->pCTransMgr = pCTMgr = new CTransactionMgr;
  63. }
  64. }
  65. PerfDbgLog1(tagCTransMgr, NULL, "-GetThreadTransactionMgr (pCTMgr:%lx)", pCTMgr);
  66. DEBUG_LEAVE(pCTMgr);
  67. return pCTMgr;
  68. }
  69. //+---------------------------------------------------------------------------
  70. //
  71. // Function: GetTransactionMgr
  72. //
  73. // Synopsis:
  74. //
  75. // Arguments: [fCreate] --
  76. //
  77. // Returns:
  78. //
  79. // History: 12-06-95 JohannP (Johann Posch) Created
  80. //
  81. // Notes:
  82. //
  83. //----------------------------------------------------------------------------
  84. CTransactionMgr * GetTransactionMgr(BOOL fCreate)
  85. {
  86. DEBUG_ENTER((DBG_TRANSMGR,
  87. Pointer,
  88. "GetTransactionMgr",
  89. "%B",
  90. fCreate
  91. ));
  92. CTransactionMgr* pCTransMgr = GetThreadTransactionMgr(fCreate);
  93. DEBUG_LEAVE(pCTransMgr);
  94. return pCTransMgr;
  95. }
  96. //+---------------------------------------------------------------------------
  97. //
  98. // Function: RegisterUrlMkWndClass
  99. //
  100. // Synopsis: register the Url Moniker window class on demand
  101. //
  102. // Arguments: (none)
  103. //
  104. // Returns: return FALSE if class could not be registered
  105. //
  106. // History: 12-02-95 JohannP (Johann Posch) Created
  107. //
  108. // Notes:
  109. //
  110. //----------------------------------------------------------------------------
  111. BOOL RegisterUrlMkWndClass()
  112. {
  113. DEBUG_ENTER((DBG_TRANSMGR,
  114. Bool,
  115. "RegisterUrlMkWndClass",
  116. NULL
  117. ));
  118. // only one thread should be here
  119. CLock lck(g_mxsMedia);
  120. if (g_fWndClassRegistered == FALSE)
  121. {
  122. // else register the window class
  123. WNDCLASS wndclass;
  124. wndclass.style = 0;
  125. wndclass.lpfnWndProc = &TransactionWndProc;
  126. wndclass.cbClsExtra = 0;
  127. wndclass.cbWndExtra = 0;
  128. wndclass.hInstance = g_hInst;
  129. wndclass.hIcon = NULL;
  130. wndclass.hCursor = NULL;;
  131. wndclass.hbrBackground = (HBRUSH)NULL;
  132. wndclass.lpszMenuName = NULL;
  133. wndclass.lpszClassName = szURLMonClassName;
  134. // Register the window class
  135. if (!RegisterClass(&wndclass))
  136. {
  137. DWORD dwLastError = GetLastError();
  138. if(dwLastError == ERROR_CLASS_ALREADY_EXISTS)
  139. {
  140. g_fWndClassRegistered = TRUE;
  141. }
  142. else
  143. {
  144. DEBUG_PRINT(TRANSMGR, ERROR, ("RegisterUrlMkWndClass(): RegisterClass failed, GetLastError: %ld\n", dwLastError));
  145. TransAssert(FALSE);
  146. }
  147. }
  148. else
  149. {
  150. g_fWndClassRegistered = TRUE;
  151. }
  152. }
  153. DEBUG_LEAVE(g_fWndClassRegistered);
  154. return g_fWndClassRegistered;
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Function: UnregisterUrlMkWndClass
  159. //
  160. // Synopsis: unregisters the hidden windows class
  161. //
  162. // Arguments: (none)
  163. //
  164. // Returns:
  165. //
  166. // History: 10-16-1996 JohannP (Johann Posch) Created
  167. //
  168. // Notes: called during process detach
  169. //
  170. //----------------------------------------------------------------------------
  171. BOOL UnregisterUrlMkWndClass()
  172. {
  173. DEBUG_ENTER((DBG_TRANSMGR,
  174. Bool,
  175. "UnregisterUrlMkWndClass",
  176. NULL
  177. ));
  178. if (g_fWndClassRegistered == TRUE)
  179. {
  180. // Register the window class
  181. if (UnregisterClass(szURLMonClassName,g_hInst))
  182. {
  183. g_fWndClassRegistered = FALSE;
  184. }
  185. else
  186. {
  187. DEBUG_PRINT(TRANSMGR, ERROR, ("UnregisterUrlMkWndClass(): UnregisterClass failed, GetLastError: %ld\n", GetLastError()));
  188. }
  189. }
  190. DEBUG_LEAVE(g_fWndClassRegistered);
  191. return g_fWndClassRegistered;
  192. }
  193. //+---------------------------------------------------------------------------
  194. //
  195. // Function: GetThreadNotificationWnd
  196. //
  197. // Synopsis: return the notification for the current
  198. // the window is created if
  199. //
  200. // Arguments: [fCreate] -- TRUE if the window should be created
  201. //
  202. // Returns:
  203. //
  204. // History: 12-02-95 JohannP (Johann Posch) Created
  205. //
  206. // Notes:
  207. //
  208. //----------------------------------------------------------------------------
  209. #ifndef HWND_MESSAGE
  210. #define HWND_MESSAGE ((HWND)-3)
  211. #endif
  212. extern BOOL g_bNT5OrGreater;
  213. HWND GetThreadNotificationWnd(BOOL fCreate)
  214. {
  215. DEBUG_ENTER((DBG_TRANSMGR,
  216. Dword,
  217. "GetThreadNotificationWnd",
  218. "%B",
  219. fCreate
  220. ));
  221. HRESULT hr = NOERROR;
  222. HWND hwnd = NULL;
  223. DWORD tid = GetCurrentThreadId();
  224. URLMON_TS* ts = NULL;
  225. ts = GetTS(tid);
  226. if( ts )
  227. {
  228. hwnd = ts->_hwndNotify;
  229. TransAssert((hwnd != NULL && "TS Corrupted!"));
  230. }
  231. else
  232. {
  233. ts = new URLMON_TS;
  234. if( ts )
  235. {
  236. if ( fCreate
  237. && (hwnd == NULL)
  238. && RegisterUrlMkWndClass() )
  239. {
  240. hwnd = CreateWindowEx(0, szURLMonClassName, NULL,
  241. 0, 0, 0, 0, 0,
  242. g_bNT5OrGreater ? HWND_MESSAGE : NULL,
  243. NULL, g_hInst, NULL);
  244. TransAssert((hwnd != NULL && "can't create Notify window"));
  245. if (hwnd)
  246. {
  247. ts->_dwTID = tid;
  248. ts->_hwndNotify = hwnd;
  249. AddTSToList(ts);
  250. }
  251. }
  252. else
  253. {
  254. delete ts;
  255. }
  256. }
  257. }
  258. /**************************************************************************
  259. CUrlMkTls tls(hr);
  260. if (hr == NOERROR)
  261. {
  262. hwnd = tls->hwndUrlMkNotify;
  263. if ( fCreate
  264. && (hwnd == NULL)
  265. && RegisterUrlMkWndClass() )
  266. {
  267. hwnd = CreateWindowEx(0, szURLMonClassName, NULL,
  268. 0, 0, 0, 0, 0, NULL, NULL, g_hInst, NULL);
  269. TransAssert((hwnd != NULL && "GetNotificationWnd: could not create window"));
  270. if (hwnd)
  271. {
  272. tls->hwndUrlMkNotify = hwnd;
  273. char achProgname[256];
  274. achProgname[0] = '\0';
  275. GetModuleFileNameA(NULL, achProgname, sizeof(achProgname));
  276. }
  277. }
  278. }
  279. ***************************************************************************/
  280. DEBUG_LEAVE(hwnd);
  281. return hwnd;
  282. }
  283. //+---------------------------------------------------------------------------
  284. //
  285. // Method: CTransactionMgr::CTransactionMgr
  286. //
  287. // Synopsis:
  288. //
  289. // Arguments: (none)
  290. //
  291. // Returns:
  292. //
  293. // History: 1-14-96 JohannP (Johann Posch) Created
  294. //
  295. // Notes:
  296. //
  297. //----------------------------------------------------------------------------
  298. CTransactionMgr::CTransactionMgr() : CLifePtr()
  299. {
  300. DEBUG_ENTER((DBG_TRANSMGR,
  301. None,
  302. "CTransactionMgr::CTransactionMgr",
  303. "this=%#x",
  304. this
  305. ));
  306. _pCTransFirst = NULL;
  307. _pCTransLast = NULL;
  308. DEBUG_LEAVE(0);
  309. }
  310. //+---------------------------------------------------------------------------
  311. //
  312. // Method: CTransactionMgr::~CTransactionMgr
  313. //
  314. // Synopsis:
  315. //
  316. // Arguments: (none)
  317. //
  318. // Returns:
  319. //
  320. // History: 1-14-96 JohannP (Johann Posch) Created
  321. //
  322. // Notes:
  323. //
  324. //----------------------------------------------------------------------------
  325. CTransactionMgr::~CTransactionMgr()
  326. {
  327. DEBUG_ENTER((DBG_TRANSMGR,
  328. None,
  329. "CTransactionMgr::~CTransactionMgr",
  330. "this=%#x",
  331. this
  332. ));
  333. // The list should be empty by the time it gets destroyed
  334. if (_pCTransFirst)
  335. {
  336. DbgLog1(tagCTransMgr, this, "CTransactionMgr::~CTransactionMgr (list not empty:%lx)", _pCTransFirst);
  337. }
  338. //TransAssert(( _pCTransFirst == NULL ));
  339. DEBUG_LEAVE(0);
  340. }
  341. //+---------------------------------------------------------------------------
  342. //
  343. // Method: CTransactionMgr::AddTransaction
  344. //
  345. // Synopsis: Add an internet transaction to the linked list.
  346. //
  347. // Arguments: [pCTrans] --
  348. //
  349. // Returns:
  350. //
  351. // History: 12-12-95 JohannP (Johann Posch) Created
  352. //
  353. // Notes:
  354. //
  355. //----------------------------------------------------------------------------
  356. HRESULT CTransactionMgr::AddTransaction(CTransaction *pCTrans)
  357. {
  358. DEBUG_ENTER((DBG_TRANSMGR,
  359. Hresult,
  360. "CTransactionMgr::AddTransaction",
  361. "this=%#x, %#x",
  362. this, pCTrans
  363. ));
  364. PerfDbgLog(tagCTransMgr, this, "+CTransMgr::AddTransaction");
  365. TransAssert((pCTrans != NULL));
  366. TransAssert((pCTrans->GetNextTransaction() == NULL));
  367. pCTrans->SetNextTransaction(_pCTransFirst);
  368. _pCTransFirst = pCTrans;
  369. AddRef();
  370. PerfDbgLog1(tagCTransMgr, this, "-CTransMgr::AddTransaction(hr:%lx)", NOERROR);
  371. DEBUG_LEAVE(NOERROR);
  372. return NOERROR;
  373. }
  374. //+---------------------------------------------------------------------------
  375. //
  376. // Method: CTransactionMgr::RemoveTransaction
  377. //
  378. // Synopsis: Removes a transaction from the linked list. If the transaction
  379. // cannot be found, E_FAIL is returned.
  380. //
  381. // Arguments: [pCTrans] --
  382. //
  383. // Returns:
  384. //
  385. // History: 12-12-95 JohannP (Johann Posch) Created
  386. //
  387. // Notes:
  388. //
  389. //----------------------------------------------------------------------------
  390. HRESULT CTransactionMgr::RemoveTransaction(CTransaction *pCTrans)
  391. {
  392. DEBUG_ENTER((DBG_TRANSMGR,
  393. Hresult,
  394. "CTransactionMgr::RemoveTransaction",
  395. "this=%#x, %#x",
  396. this, pCTrans
  397. ));
  398. PerfDbgLog(tagCTransMgr, this, "+CTransMgr::RemoveTransaction");
  399. CLock lck(g_mxsTransMgr);
  400. CTransaction *pCTransPrev = NULL;
  401. CTransaction *pCTransTmp;
  402. HRESULT hr = E_FAIL;
  403. TransAssert((pCTrans != NULL));
  404. pCTransTmp = _pCTransFirst;
  405. TransAssert((pCTransTmp != NULL));
  406. // Search all the nodes in the linked list
  407. if (_pCTransFirst == pCTrans)
  408. {
  409. _pCTransFirst = _pCTransFirst->GetNextTransaction();
  410. hr = NOERROR;
  411. Release();
  412. }
  413. else while (pCTransTmp != NULL)
  414. {
  415. // If a match is found
  416. if (pCTransTmp == pCTrans)
  417. {
  418. // Remove it from the linked list
  419. if (pCTransPrev == NULL)
  420. {
  421. _pCTransFirst = pCTrans->GetNextTransaction();
  422. }
  423. else
  424. {
  425. pCTransPrev->SetNextTransaction(pCTrans->GetNextTransaction());
  426. }
  427. hr = NOERROR;
  428. Release();
  429. }
  430. pCTransPrev = pCTransTmp;
  431. pCTransTmp = pCTransTmp->GetNextTransaction();
  432. }
  433. TransAssert((hr == NOERROR));
  434. PerfDbgLog1(tagCTransMgr, this, "-CTransMgr::RemoveTransaction (hr:%lx)", hr);
  435. DEBUG_LEAVE(hr);
  436. return hr;
  437. }
  438. //+---------------------------------------------------------------------------
  439. //
  440. // Function: GetTransactionObjects
  441. //
  442. // Synopsis:
  443. //
  444. // Arguments: [pBndCtx] --
  445. // [wzUrl] --
  446. // [pUnkOuter] --
  447. // [ppUnk] --
  448. // [ppCTrans] --
  449. // [dwOption] --
  450. // [ppCTranSData] --
  451. //
  452. // Returns:
  453. //
  454. // History: 4-12-1997 JohannP (Johann Posch) Created
  455. //
  456. // Notes:
  457. //
  458. //----------------------------------------------------------------------------
  459. HRESULT GetTransactionObjects(LPBC pBndCtx, LPCWSTR wzUrl, IUnknown *pUnkOuter, IUnknown **ppUnk,
  460. IOInetProtocol **ppCTrans, DWORD dwOption, CTransData **ppCTransData)
  461. {
  462. DEBUG_ENTER((DBG_TRANSMGR,
  463. Hresult,
  464. "GetTransactionObjects",
  465. "%#x, %.80wq, %#x, %#x, %#x, %#x, %#x",
  466. pBndCtx, wzUrl, pUnkOuter, ppUnk, ppCTrans, dwOption, ppCTransData
  467. ));
  468. HRESULT hr = S_OK;
  469. PerfDbgLog(tagCTransMgr, NULL, "+GetTransactionObjects");
  470. TransAssert((ppCTrans != NULL));
  471. CTransaction *pCTransTmp = NULL;
  472. BOOL fFound = FALSE;
  473. CLock lck(g_mxsTransMgr);
  474. CBindCtx *pCBndCtx = NULL;
  475. if (pBndCtx)
  476. {
  477. hr = pBndCtx->QueryInterface(IID_IAsyncBindCtx, (void **) &pCBndCtx);
  478. if (hr == NOERROR)
  479. {
  480. TransAssert((pCBndCtx));
  481. hr = pCBndCtx->GetTransactionObjects(&pCTransTmp, ppCTransData);
  482. if (hr == NOERROR)
  483. {
  484. TransAssert((pCTransTmp));
  485. if (!pCTransTmp->IsApartmentThread())
  486. {
  487. pCBndCtx->SetTransactionObject(NULL);
  488. }
  489. fFound = TRUE;
  490. hr = S_FALSE;
  491. }
  492. }
  493. if (hr != S_FALSE && hr != NOERROR)
  494. {
  495. CBinding *pCBdgBindToObject = NULL;
  496. hr = pBndCtx->GetObjectParam(SZ_BINDING, (IUnknown **)&pCBdgBindToObject);
  497. if (pCBdgBindToObject)
  498. {
  499. pCTransTmp = (CTransaction *) pCBdgBindToObject->GetOInetBinding();
  500. fFound = pCTransTmp ? true : false;
  501. pCTransTmp->AddRef();
  502. pCBdgBindToObject->Release();
  503. DbgLog1(tagCTransMgr, NULL, "=== CTransMgr::GetTransaction Found Transaction:%lx", pCTransTmp);
  504. }
  505. }
  506. }
  507. if (!fFound)
  508. {
  509. CTransactionMgr *pCTransMgr = GetThreadTransactionMgr();
  510. if (!pCTransMgr)
  511. {
  512. hr = E_OUTOFMEMORY;
  513. }
  514. else
  515. {
  516. // create a new transaction add it to the list
  517. hr = CTransaction::Create(pCBndCtx, dwOption, 0, 0, &pCTransTmp);
  518. if (hr == NOERROR)
  519. {
  520. hr = pCTransTmp->QueryInterface(IID_IOInetProtocol, (void **) ppCTrans);
  521. if (hr == NOERROR)
  522. {
  523. pCTransTmp->Release();
  524. pCTransMgr->AddTransaction(pCTransTmp);
  525. }
  526. if (!pCBndCtx && pBndCtx)
  527. {
  528. pBndCtx->QueryInterface(IID_IAsyncBindCtx, (void **) &pCBndCtx);
  529. }
  530. if (pCBndCtx)
  531. {
  532. pCBndCtx->SetTransactionObject(pCTransTmp);
  533. }
  534. }
  535. }
  536. }
  537. else if (pCTransTmp)
  538. {
  539. DbgLog1(tagCTransMgr, NULL, "GetTransactionObjects Found existing transaction(%lx)", pCTransTmp);
  540. // return false to indicate found existing transaction
  541. hr = S_FALSE;
  542. }
  543. if (pCBndCtx)
  544. {
  545. pCBndCtx->Release();
  546. }
  547. *ppCTrans = pCTransTmp;
  548. if (*ppCTrans && ppCTransData && *ppCTransData)
  549. {
  550. hr = S_FALSE;
  551. }
  552. if( hr == S_FALSE && ppCTransData && !*ppCTransData )
  553. {
  554. hr = S_OK;
  555. }
  556. PerfDbgLog2(tagCTransMgr, NULL, "-API GetTransactionObjects (pCTrans:%lx; hr:%lx)", pCTransTmp, hr);
  557. DEBUG_LEAVE(hr);
  558. return hr;
  559. }