1 /* 2 * PROJECT: shell32 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Shell change notification 5 * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 6 */ 7 #pragma once 8 9 #include <shlwapi_undoc.h> // for SHCreateWorkerWindowW 10 11 ///////////////////////////////////////////////////////////////////////////// 12 // CChangeNotifyServer is a delivery worker window that is managed by CDesktopBrowser. 13 // The process of CChangeNotifyServer is same as the process of CDesktopBrowser. 14 // The caller process of SHChangeNotify function might be different from the 15 // process of CChangeNotifyServer. 16 ///////////////////////////////////////////////////////////////////////////// 17 18 ///////////////////////////////////////////////////////////////////////////// 19 // The shared memory block can be allocated by shlwapi!SHAllocShared function. 20 // 21 // HANDLE SHAllocShared(LPCVOID lpData, DWORD dwSize, DWORD dwProcessId); 22 // LPVOID SHLockShared(HANDLE hData, DWORD dwProcessId); 23 // LPVOID SHLockSharedEx(HANDLE hData, DWORD dwProcessId, BOOL bWriteAccess); 24 // BOOL SHUnlockShared(LPVOID lpData); 25 // BOOL SHFreeShared(HANDLE hData, DWORD dwProcessId); 26 // 27 // The shared memory block is managed by the pair of a HANDLE value and an owner PID. 28 // If the pair is known, it can be accessed by SHLockShared(Ex) function 29 // from another process. 30 ///////////////////////////////////////////////////////////////////////////// 31 32 #define INVALID_REG_ID 0 /* invalid registration ID */ 33 34 // This message is handled by CDesktopBrowser and returns 35 // the window of CChangeNotifyServer which responds to the CN_* messages 36 #define WM_DESKTOP_GET_CNOTIFY_SERVER (WM_USER + 25) /* 0x419 */ 37 38 // The following messages are implemented by CChangeNotifyServer 39 // CChangeNotifyServer lives in the context of explorer and delivers notifications 40 // across all processes that register themselves with the SHChangeNotifyRegister api 41 #define CN_REGISTER (WM_USER + 1) /* 0x401 */ 42 #define CN_UNREGISTER (WM_USER + 2) /* 0x402 */ 43 #define CN_DELIVER_NOTIFICATION (WM_USER + 3) /* 0x403 */ 44 #define CN_SUSPEND_RESUME (WM_USER + 6) /* 0x406 */ 45 #define CN_UNREGISTER_PROCESS (WM_USER + 7) /* 0x407 */ 46 47 // This message is implemented by the broker window which lives in the context of the client 48 #define WM_BROKER_NOTIFICATION (WM_USER + 1) /* 0x401 */ 49 50 #define DWORD_ALIGNMENT(offset) \ 51 ((((offset) + sizeof(DWORD) - 1) / sizeof(DWORD)) * sizeof(DWORD)) 52 53 /* delivery ticket */ 54 typedef struct DELITICKET 55 { 56 DWORD dwMagic; /* same as DELITICKET_MAGIC */ 57 LONG wEventId; /* event id of SHChangeNotify() */ 58 UINT uFlags; /* flags of SHChangeNotify() */ 59 DWORD dwTick; /* value of GetTickCount() */ 60 DWORD ibOffset1; /* offset to pidl1 */ 61 DWORD ibOffset2; /* offset to pidl2 */ 62 /* followed by pidl1 and pidl2 */ 63 } DELITICKET, *LPDELITICKET; 64 65 /* registration entry */ 66 typedef struct REGENTRY 67 { 68 DWORD dwMagic; /* same as REGENTRY_MAGIC */ 69 DWORD cbSize; /* the real size of this structure */ 70 UINT nRegID; /* the registration ID */ 71 HWND hwnd; /* the target window */ 72 UINT uMsg; /* the message ID used in notification */ 73 INT fSources; /* the source flags */ 74 LONG fEvents; /* the event flags */ 75 BOOL fRecursive; /* is it recursive? */ 76 HWND hwndBroker; /* broker window (if any) */ 77 UINT ibPidl; /* offset to the PIDL */ 78 /* followed by a PIDL */ 79 } REGENTRY, *LPREGENTRY; 80 81 /* handbag */ 82 typedef struct HANDBAG 83 { 84 DWORD dwMagic; /* same as HANDBAG_MAGIC */ 85 LPITEMIDLIST pidls[2]; /* two PIDLs */ 86 LPDELITICKET pTicket; /* the ticket */ 87 } HANDBAG, *LPHANDBAG; 88 89 #define DELITICKET_MAGIC 0xDEADFACE 90 #define REGENTRY_MAGIC 0xB0B32D1E 91 #define HANDBAG_MAGIC 0xFACEB00C 92 93 HRESULT CChangeNotifyServer_CreateInstance(REFIID riid, void **ppv); 94 95 #define WORKER_STYLE (WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN) 96 #define WORKER_EXSTYLE WS_EX_TOOLWINDOW 97 98 typedef CWinTraits<WORKER_STYLE, WORKER_EXSTYLE> CWorkerTraits; 99 100 inline HWND SHCreateDefaultWorkerWindow(VOID) 101 { 102 return SHCreateWorkerWindowW(NULL, NULL, WORKER_EXSTYLE, WORKER_STYLE, NULL, 0); 103 } 104