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.

520 lines
21 KiB

  1. /****************************************************************************/
  2. // cdapi.cpp
  3. //
  4. // Component Decoupler API functions
  5. // Copyright (C) 1997-1999 Microsoft Corporation
  6. /****************************************************************************/
  7. #include <adcg.h>
  8. extern "C" {
  9. #define TRC_GROUP TRC_GROUP_CORE
  10. #define TRC_FILE "cdapi"
  11. #include <atrcapi.h>
  12. }
  13. #include "autil.h"
  14. #include "cd.h"
  15. #include "wui.h"
  16. CCD::CCD(CObjs* objs)
  17. {
  18. _pClientObjects = objs;
  19. _fCDInitComplete = FALSE;
  20. /************************************************************************/
  21. /* Initialize the global data. */
  22. /************************************************************************/
  23. DC_MEMSET(&_CD, 0, sizeof(_CD));
  24. }
  25. CCD::~CCD()
  26. {
  27. }
  28. /****************************************************************************/
  29. /* Name: CD_Init */
  30. /* */
  31. /* Purpose: Component Decoupler initialization function */
  32. /****************************************************************************/
  33. DCVOID DCAPI CCD::CD_Init(DCVOID)
  34. {
  35. WNDCLASS wc;
  36. WNDCLASS tmpWndClass;
  37. DC_BEGIN_FN("CD_Init");
  38. TRC_ASSERT(_pClientObjects, (TB,_T("_pClientObjects is NULL")));
  39. _pClientObjects->AddObjReference(CD_OBJECT_FLAG);
  40. //Setup local object pointers
  41. _pUt = _pClientObjects->_pUtObject;
  42. _pUi = _pClientObjects->_pUiObject;
  43. //
  44. // Only register the class if not already registered (previous instance)
  45. //
  46. if(!GetClassInfo( _pUi->UI_GetInstanceHandle(), CD_WINDOW_CLASS, &tmpWndClass))
  47. {
  48. /************************************************************************/
  49. /* Register the CD window class. */
  50. /************************************************************************/
  51. wc.style = 0;
  52. wc.lpfnWndProc = CDStaticWndProc;
  53. wc.cbClsExtra = 0;
  54. wc.cbWndExtra = sizeof(void*);
  55. wc.hInstance = _pUi->UI_GetInstanceHandle();
  56. wc.hIcon = NULL;
  57. wc.hCursor = NULL;
  58. wc.hbrBackground = NULL;
  59. wc.lpszMenuName = NULL;
  60. wc.lpszClassName = CD_WINDOW_CLASS;
  61. if (!RegisterClass(&wc))
  62. {
  63. // $$$v-reddya. Hack to avoid bug #923.
  64. TRC_ERR((TB, _T("Failed to register window class")));
  65. //_pUi->UI_FatalError(DC_ERR_OUTOFMEMORY);
  66. }
  67. }
  68. _fCDInitComplete = TRUE;
  69. DC_END_FN();
  70. }
  71. /****************************************************************************/
  72. /* Name: CD_Term */
  73. /* */
  74. /* Purpose: Component Decoupler termination function */
  75. /****************************************************************************/
  76. DCVOID DCAPI CCD::CD_Term(DCVOID)
  77. {
  78. DC_BEGIN_FN("CD_Term");
  79. if(_fCDInitComplete)
  80. {
  81. if (!UnregisterClass(CD_WINDOW_CLASS, _pUi->UI_GetInstanceHandle())) {
  82. //Failure to unregister could happen if another instance is still running
  83. //that's ok...unregistration will happen when the last instance exits.
  84. TRC_ERR((TB, _T("Failed to unregister window class")));
  85. }
  86. _pClientObjects->ReleaseObjReference(CD_OBJECT_FLAG);
  87. }
  88. DC_END_FN();
  89. }
  90. /****************************************************************************/
  91. /* Name: CD_RegisterComponent */
  92. /* */
  93. /* Purpose: Register a new component */
  94. /* */
  95. /* Params: IN component: component id */
  96. /****************************************************************************/
  97. HRESULT DCAPI CCD::CD_RegisterComponent(DCUINT component)
  98. {
  99. HRESULT hr = E_FAIL;
  100. DC_BEGIN_FN("CD_RegisterComponent");
  101. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  102. (TB, _T("Invalid component %u"), component));
  103. TRC_ASSERT((_CD.hwnd[component] == NULL),
  104. (TB, _T("Component %u already registered"), component));
  105. /************************************************************************/
  106. /* Create window for this component. */
  107. /************************************************************************/
  108. _CD.hwnd[component] = CreateWindow(
  109. CD_WINDOW_CLASS, /* See RegisterClass() call */
  110. NULL, /* Text for window title bar */
  111. 0, /* Window style */
  112. 0, /* Default horizontal position */
  113. 0, /* Default vertical position */
  114. 0, /* Width */
  115. 0, /* Height */
  116. NULL, /* hwndParent - none */
  117. NULL, /* hMenu - none */
  118. _pUi->UI_GetInstanceHandle(),
  119. this /* Window creation data */
  120. );
  121. if (_CD.hwnd[component] != NULL) {
  122. hr = S_OK;
  123. }
  124. else {
  125. hr = HRESULT_FROM_WIN32(GetLastError());
  126. TRC_ERR((TB,_T("Failed to create window: 0x%x"),hr));
  127. }
  128. TRC_NRM((TB, _T("Component(%u) hwnd(%p)"), component, _CD.hwnd[component]));
  129. DC_END_FN();
  130. return hr;
  131. } /* CD_RegisterComponent */
  132. /****************************************************************************/
  133. /* Name: CD_UnregisterComponent */
  134. /* */
  135. /* Purpose: Unregister component from CD */
  136. /* */
  137. /* Params: IN component: component ID */
  138. /****************************************************************************/
  139. HRESULT DCAPI CCD::CD_UnregisterComponent(DCUINT component)
  140. {
  141. HRESULT hr = E_FAIL;
  142. DC_BEGIN_FN("CD_UnregisterComponent");
  143. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  144. (TB, _T("Invalid component %u"), component));
  145. /************************************************************************/
  146. /* Destroy this component's window, if it exists. */
  147. /************************************************************************/
  148. if (_CD.hwnd[component] != NULL)
  149. {
  150. DestroyWindow(_CD.hwnd[component]);
  151. _CD.hwnd[component] = NULL;
  152. }
  153. hr = S_OK;
  154. DC_END_FN();
  155. return hr;
  156. } /* CD_UnregisterComponent */
  157. // Note that we have several copies of very similar code below. This is
  158. // to trade a bit of code size (easy to predict and cache) against
  159. // 50%-predictable branches created by parameterizing sync/async, which are
  160. // very CPU expensive on modern processors. Since notifications are often
  161. // used in performance paths (send/receive data), this optimization is
  162. // worthwhile.
  163. /****************************************************************************/
  164. /* Name: CD_DecoupleNotification */
  165. /* */
  166. /* Purpose: Call given function with specified data */
  167. /* */
  168. /* Params: IN component: target thread */
  169. /* IN pInst target object instance pointer */
  170. /* IN pNotificationFn: target function */
  171. /* IN pData: pointer to data to pass: cannot be NULL */
  172. /* IN dataLength: data length in bytes: cannot be zero */
  173. /* */
  174. /* Operation: Copy supplied data into data buffer and post message to */
  175. /* corresponding component window. */
  176. /****************************************************************************/
  177. BOOL DCAPI CCD::CD_DecoupleNotification(
  178. unsigned component,
  179. PDCVOID pInst,
  180. PCD_NOTIFICATION_FN pNotificationFn,
  181. PDCVOID pData,
  182. unsigned dataLength)
  183. {
  184. PCDTRANSFERBUFFER pTransferBuffer;
  185. DC_BEGIN_FN("CD_DecoupleNotificationEx");
  186. TRC_ASSERT(((dataLength <= CD_MAX_NOTIFICATION_DATA_SIZE) &&
  187. (dataLength > 0 )),
  188. (TB, _T("dataLength(%u) invalid"), dataLength));
  189. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  190. (TB, _T("Invalid component %u"), component));
  191. TRC_ASSERT((pNotificationFn != NULL),(TB, _T("Null pNotificationFn")));
  192. TRC_ASSERT((pData != NULL),(TB, _T("Null pData")));
  193. TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
  194. // Check that the target component is still registered.
  195. if (_CD.hwnd[component] != NULL) {
  196. pTransferBuffer = CDAllocTransferBuffer(dataLength);
  197. if(pTransferBuffer) {
  198. pTransferBuffer->hdr.pNotificationFn = pNotificationFn;
  199. pTransferBuffer->hdr.pInst = pInst;
  200. DC_MEMCPY(pTransferBuffer->data, pData, dataLength);
  201. TRC_NRM((TB, _T("Notify component %u (%p) of %u bytes of data"),
  202. component, _CD.hwnd[component], dataLength));
  203. TRC_DATA_DBG("notification data", pData, dataLength);
  204. // For now, we only use async data notifications. If we
  205. // need sync data notifications, copy this code to a new
  206. // func and use the ifdef'd SendMessage.
  207. if (!PostMessage(_CD.hwnd[component], CD_NOTIFICATION_MSG,
  208. (WPARAM)dataLength, (LPARAM)pTransferBuffer)) {
  209. _pUi->UI_FatalError(DC_ERR_POSTMESSAGEFAILED);
  210. }
  211. else {
  212. return TRUE;
  213. }
  214. #ifdef DC_DEBUG
  215. // Trace is before increment so that the point at which we're most
  216. // likely to get pre-empted (TRC_GetBuffer) is before all references
  217. // to the variable we're interested in.
  218. TRC_NRM((TB, _T("Messages now pending: %ld"), _CD.pendingMessageCount + 1));
  219. _pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
  220. #endif
  221. }
  222. else {
  223. TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
  224. }
  225. }
  226. else {
  227. TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
  228. }
  229. DC_END_FN();
  230. return FALSE;
  231. } /* CD_DecoupleNotification */
  232. /****************************************************************************/
  233. /* Name: CD_DecoupleSyncDataNotification */
  234. /* */
  235. /* Purpose: Call given function with specified data */
  236. /* */
  237. /* Params: IN component: target thread */
  238. /* IN pInst target object instance pointer */
  239. /* IN pNotificationFn: target function */
  240. /* IN pData: pointer to data to pass: cannot be NULL */
  241. /* IN dataLength: data length in bytes: cannot be zero */
  242. /* */
  243. /* Operation: Copy supplied data into data buffer and post message to */
  244. /* corresponding component window. */
  245. /****************************************************************************/
  246. BOOL DCAPI CCD::CD_DecoupleSyncDataNotification(
  247. unsigned component,
  248. PDCVOID pInst,
  249. PCD_NOTIFICATION_FN pNotificationFn,
  250. PDCVOID pData,
  251. unsigned dataLength)
  252. {
  253. PCDTRANSFERBUFFER pTransferBuffer;
  254. DC_BEGIN_FN("CD_DecoupleSyncDataNotification");
  255. TRC_ASSERT(((dataLength <= CD_MAX_NOTIFICATION_DATA_SIZE) &&
  256. (dataLength > 0 )),
  257. (TB, _T("dataLength(%u) invalid"), dataLength));
  258. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  259. (TB, _T("Invalid component %u"), component));
  260. TRC_ASSERT((pNotificationFn != NULL),(TB, _T("Null pNotificationFn")));
  261. TRC_ASSERT((pData != NULL),(TB, _T("Null pData")));
  262. TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
  263. // Check that the target component is still registered.
  264. if (_CD.hwnd[component] != NULL) {
  265. pTransferBuffer = CDAllocTransferBuffer(dataLength);
  266. //
  267. // If CDAllocTransferBuffer fails, it calls UI_FatalError
  268. // don't need to do that from here again.
  269. //
  270. if(pTransferBuffer) {
  271. pTransferBuffer->hdr.pNotificationFn = pNotificationFn;
  272. pTransferBuffer->hdr.pInst = pInst;
  273. DC_MEMCPY(pTransferBuffer->data, pData, dataLength);
  274. TRC_NRM((TB, _T("Notify component %u (%p) of %u bytes of data"),
  275. component, _CD.hwnd[component], dataLength));
  276. TRC_DATA_DBG("notification data", pData, dataLength);
  277. if (0 != SendMessage(_CD.hwnd[component], CD_NOTIFICATION_MSG,
  278. (WPARAM)dataLength, (LPARAM)pTransferBuffer))
  279. {
  280. _pUi->UI_FatalError(DC_ERR_SENDMESSAGEFAILED);
  281. }
  282. else
  283. {
  284. return TRUE;
  285. }
  286. #ifdef DC_DEBUG
  287. // Trace is before increment so that the point at which we're most
  288. // likely to get pre-empted (TRC_GetBuffer) is before all references
  289. // to the variable we're interested in.
  290. TRC_NRM((TB, _T("Messages now pending: %ld"), _CD.pendingMessageCount + 1));
  291. _pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
  292. #endif
  293. }
  294. else {
  295. TRC_ERR((TB,_T("CDAllocTransferBuffer returned NULL")));
  296. }
  297. }
  298. else {
  299. TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
  300. }
  301. DC_END_FN();
  302. return FALSE;
  303. }
  304. /****************************************************************************/
  305. /* Name: CD_DecoupleSimpleNotification */
  306. /* */
  307. /* Purpose: Call given function with specified message (DCUINT) */
  308. /* */
  309. /* Params: IN component - target thread */
  310. /* IN pInst target object instance pointer */
  311. /* IN pNotificationFn - address of notification function */
  312. /* IN data - message data */
  313. /****************************************************************************/
  314. BOOL DCAPI CCD::CD_DecoupleSimpleNotification(
  315. unsigned component,
  316. PDCVOID pInst,
  317. PCD_SIMPLE_NOTIFICATION_FN pNotificationFn,
  318. ULONG_PTR msg)
  319. {
  320. PCDTRANSFERBUFFER pTransferBuffer;
  321. DC_BEGIN_FN("CD_DecoupleSimpleNotification");
  322. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  323. (TB, _T("Invalid component %u"), component));
  324. TRC_ASSERT((pNotificationFn != NULL),
  325. (TB, _T("Null pNotificationFn")));
  326. TRC_NRM((TB, _T("Notify component %u (%p) of %x"), component,
  327. _CD.hwnd[component], msg));
  328. TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
  329. // Check that the target component is still registered.
  330. if (_CD.hwnd[component] != NULL) {
  331. //
  332. // We need to pass instance pointer, function pointer and message
  333. // so we need a transfer buffer (with no data) message is posted
  334. // in WPARAM
  335. //
  336. pTransferBuffer = CDAllocTransferBuffer(0);
  337. if(pTransferBuffer) {
  338. pTransferBuffer->hdr.pSimpleNotificationFn = pNotificationFn;
  339. pTransferBuffer->hdr.pInst = pInst;
  340. #ifdef DC_DEBUG
  341. {
  342. // Check on the number of pending messages - if this deviates too
  343. // far from 0 then something has probably gone wrong.
  344. DCINT32 msgCount = _CD.pendingMessageCount;
  345. _pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
  346. if ( msgCount > 50 ) {
  347. TRC_ERR((TB, _T("Now %u pending messages - too high"), msgCount));
  348. }
  349. else {
  350. TRC_NRM((TB, _T("Now %u pending messages"), msgCount));
  351. }
  352. }
  353. #endif
  354. if (PostMessage(_CD.hwnd[component], CD_SIMPLE_NOTIFICATION_MSG,
  355. (WPARAM)msg, (LPARAM)pTransferBuffer))
  356. {
  357. return TRUE;
  358. }
  359. else
  360. {
  361. _pUi->UI_FatalError(DC_ERR_POSTMESSAGEFAILED);
  362. }
  363. }
  364. else {
  365. TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
  366. }
  367. }
  368. else
  369. {
  370. TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
  371. }
  372. DC_END_FN();
  373. return FALSE;
  374. }
  375. /****************************************************************************/
  376. /* Name: CD_DecoupleSyncNotification */
  377. /* */
  378. /* Purpose: Synchronously call given function with specified message */
  379. /* */
  380. /* Params: IN component - target thread */
  381. /* IN pInst target object instance pointer */
  382. /* IN pNotificationFn - address of notification function */
  383. /* IN data - message data */
  384. /****************************************************************************/
  385. BOOL DCAPI CCD::CD_DecoupleSyncNotification(
  386. unsigned component,
  387. PDCVOID pInst,
  388. PCD_SIMPLE_NOTIFICATION_FN pNotificationFn,
  389. ULONG_PTR msg)
  390. {
  391. PCDTRANSFERBUFFER pTransferBuffer;
  392. DC_BEGIN_FN("CD_DecoupleSyncNotification");
  393. TRC_ASSERT((component <= CD_MAX_COMPONENT),
  394. (TB, _T("Invalid component %u"), component));
  395. TRC_ASSERT((pNotificationFn != NULL),
  396. (TB, _T("Null pNotificationFn")) );
  397. TRC_NRM((TB, _T("Notify component %u (%p) of %x"), component,
  398. _CD.hwnd[component], msg));
  399. TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
  400. // Check that the target component is still registered.
  401. if (_CD.hwnd[component] != NULL)
  402. {
  403. //
  404. // We need to pass instance pointer, function pointer and message
  405. // so we need a transfer buffer (with no data) message is posted
  406. // in WPARAM
  407. //
  408. pTransferBuffer = CDAllocTransferBuffer(0);
  409. if(pTransferBuffer) {
  410. pTransferBuffer->hdr.pSimpleNotificationFn = pNotificationFn;
  411. pTransferBuffer->hdr.pInst = pInst;
  412. #ifdef DC_DEBUG
  413. {
  414. // Check on the number of pending messages - if this deviates too
  415. // far from 0 then something has probably gone wrong.
  416. DCINT32 msgCount = _CD.pendingMessageCount;
  417. _pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
  418. if ( msgCount > 50 ) {
  419. TRC_ERR((TB, _T("Now %u pending messages - too high"), msgCount));
  420. }
  421. else {
  422. TRC_NRM((TB, _T("Now %u pending messages"), msgCount));
  423. }
  424. }
  425. #endif
  426. if (0 != SendMessage(_CD.hwnd[component], CD_SIMPLE_NOTIFICATION_MSG,
  427. (WPARAM)msg, (LPARAM)pTransferBuffer))
  428. {
  429. _pUi->UI_FatalError(DC_ERR_SENDMESSAGEFAILED);
  430. }
  431. else
  432. {
  433. return TRUE;
  434. }
  435. }
  436. else {
  437. TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
  438. }
  439. }
  440. else
  441. {
  442. TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
  443. }
  444. DC_END_FN();
  445. return FALSE;
  446. }