Source code of Windows XP (NT5)
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.

192 lines
5.3 KiB

  1. #include "cwndproc.h"
  2. #define ID_NOTIFY_SUBCLASS (DWORD)'CHN' // CHN change notify
  3. //
  4. // CImpWndProc
  5. //
  6. LRESULT CALLBACK CImpWndProc::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  7. {
  8. if (WM_NCCREATE == uMsg)
  9. {
  10. CImpWndProc* pThis = (CImpWndProc*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  11. if (EVAL(pThis))
  12. {
  13. pThis->_hwnd = hwnd;
  14. SetWindowPtr(hwnd, 0, pThis);
  15. // Even if pThis->vWndProc fails the create, USER will always
  16. // send us a WM_NCDESTROY so we always get a chance to clean up
  17. return pThis->v_WndProc(hwnd, uMsg, wParam, lParam);
  18. }
  19. return FALSE;
  20. }
  21. else
  22. {
  23. CImpWndProc* pThis = (CImpWndProc*)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0);
  24. LRESULT lres;
  25. if (pThis)
  26. {
  27. // Always retain a ref across the v_WndProc in case
  28. // the window destroys itself during the callback.
  29. pThis->AddRef();
  30. lres = pThis->v_WndProc(hwnd, uMsg, wParam, lParam);
  31. if (uMsg == WM_NCDESTROY)
  32. {
  33. SetWindowPtr(hwnd, 0, NULL);
  34. pThis->_hwnd = NULL;
  35. }
  36. pThis->Release();
  37. }
  38. else
  39. {
  40. //
  41. // The only way this should happen is if we haven't actually
  42. // gotten a WM_NCCREATE yet. User sends a WM_GETMINMAXINFO
  43. // to some windows before WM_NCCREATE (for legacy compat).
  44. // Assert that we're hitting that case.
  45. //
  46. ASSERT(uMsg == WM_GETMINMAXINFO);
  47. lres = SHDefWindowProc(hwnd, uMsg, wParam, lParam);
  48. }
  49. return lres;
  50. }
  51. }
  52. #ifndef NO_NOTIFYSUBCLASSWNDPROC
  53. //
  54. // CNotifySubclassWndProc
  55. //
  56. UINT g_idFSNotify; // the message SHChangeNotify sends
  57. BOOL CNotifySubclassWndProc::_SubclassWindow(HWND hwnd)
  58. {
  59. if (0 == g_idFSNotify)
  60. {
  61. g_idFSNotify = RegisterWindowMessage(TEXT("SubclassedFSNotify"));
  62. }
  63. DEBUG_CODE( _hwndSubclassed = hwnd; );
  64. return SetWindowSubclass(hwnd, _SubclassWndProc, ID_NOTIFY_SUBCLASS, (DWORD_PTR)this);
  65. }
  66. void CNotifySubclassWndProc::_UnsubclassWindow(HWND hwnd)
  67. {
  68. RemoveWindowSubclass(hwnd, _SubclassWndProc, ID_NOTIFY_SUBCLASS);
  69. }
  70. LRESULT CNotifySubclassWndProc::_DefWindowProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  71. {
  72. return DefSubclassProc(hwnd, uMessage, wParam, lParam);
  73. }
  74. LRESULT CALLBACK CNotifySubclassWndProc::_SubclassWndProc(
  75. HWND hwnd, UINT uMessage,
  76. WPARAM wParam, LPARAM lParam,
  77. UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  78. {
  79. CNotifySubclassWndProc* pObj = (CNotifySubclassWndProc*)dwRefData;
  80. if (pObj)
  81. {
  82. if (uMessage == g_idFSNotify)
  83. {
  84. LPSHChangeNotificationLock pshcnl;
  85. LPITEMIDLIST *ppidl;
  86. LONG lEvent;
  87. if (g_fNewNotify && (wParam || lParam))
  88. {
  89. // New style of notifications need to lock and unlock in order to free the memory...
  90. pshcnl = SHChangeNotification_Lock((HANDLE)wParam, (DWORD) lParam, &ppidl, &lEvent);
  91. if (pshcnl)
  92. {
  93. pObj->OnChange(lEvent, ppidl[0], ppidl[1]);
  94. }
  95. }
  96. else
  97. {
  98. lEvent = (DWORD) lParam; // process id's are 32bits even in WIN64
  99. ppidl = (LPITEMIDLIST*)wParam;
  100. pshcnl = NULL;
  101. if (ppidl)
  102. {
  103. pObj->OnChange(lEvent, ppidl[0], ppidl[1]);
  104. }
  105. }
  106. if (pshcnl)
  107. {
  108. SHChangeNotification_Unlock(pshcnl);
  109. }
  110. return 0;
  111. }
  112. else
  113. {
  114. return pObj->_DefWindowProc(hwnd, uMessage, wParam, lParam);
  115. }
  116. }
  117. else
  118. {
  119. return DefSubclassProc(hwnd, uMessage, wParam, lParam);
  120. }
  121. }
  122. void CNotifySubclassWndProc::_FlushNotifyMessages(HWND hwnd)
  123. {
  124. MSG msg;
  125. ASSERT(hwnd == _hwndSubclassed);
  126. // This SHChangeNotify calls flushes notifications
  127. // via PostMessage, so I need to remove them
  128. // myself and process them immediately...
  129. //
  130. SHChangeNotify(0, SHCNF_FLUSH, NULL, NULL);
  131. while (PeekMessage(&msg, hwnd, g_idFSNotify, g_idFSNotify, PM_REMOVE))
  132. {
  133. TranslateMessage(&msg);
  134. DispatchMessage(&msg);
  135. }
  136. }
  137. void CNotifySubclassWndProc::_RegisterWindow(HWND hwnd, LPCITEMIDLIST pidl, long lEvents,
  138. UINT uFlags/* = SHCNRF_ShellLevel | SHCNRF_InterruptLevel*/)
  139. {
  140. ASSERT(0 != g_idFSNotify);
  141. // We only register if there's something to listen to
  142. //
  143. if (0==_uRegister)
  144. {
  145. // Since we don't know what this pidl actually points to,
  146. // we have to register to listen to everything that might affect it...
  147. //
  148. _uRegister = RegisterNotify(hwnd, g_idFSNotify, pidl, lEvents, uFlags, TRUE);
  149. ASSERT(hwnd == _hwndSubclassed);
  150. }
  151. }
  152. void CNotifySubclassWndProc::_UnregisterWindow(HWND hwnd)
  153. {
  154. if (_uRegister)
  155. {
  156. ASSERT(hwnd == _hwndSubclassed);
  157. // Avoid getting reentered...
  158. UINT uRegister = _uRegister;
  159. _uRegister = 0;
  160. SHChangeNotifyDeregister(uRegister);
  161. }
  162. }
  163. #endif // NO_NOTIFYSUBCLASSWNDPROC