2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Test for SHChangeNotify
5 * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
9 #include "SHChangeNotify.h"
11 static HWND s_hwnd
= NULL
;
12 static UINT s_uRegID
= 0;
13 static BOOL s_fRecursive
= FALSE
;
14 static DIRTYPE s_iWatchDir
= DIRTYPE_NULL
;
15 static INT s_nSources
= 0;
16 static LPITEMIDLIST s_pidl
= NULL
;
17 static WCHAR s_path1
[MAX_PATH
], s_path2
[MAX_PATH
];
18 static BYTE s_counters
[TYPE_MAX
+ 1];
19 static HANDLE s_hEvent
= NULL
;
25 s_pidl
= DoGetPidl(s_iWatchDir
);
27 SHChangeNotifyEntry entry
;
29 entry
.fRecursive
= s_fRecursive
;
30 s_uRegID
= SHChangeNotifyRegister(hwnd
, s_nSources
, SHCNE_ALLEVENTS
, WM_SHELL_NOTIFY
, 1, &entry
);
35 OnCommand(HWND hwnd
, UINT id
)
49 SHChangeNotifyDeregister(s_uRegID
);
52 CoTaskMemFree(s_pidl
);
59 static BOOL
DoPathes(PIDLIST_ABSOLUTE pidl1
, PIDLIST_ABSOLUTE pidl2
)
62 if (!SHGetPathFromIDListW(pidl1
, path
))
64 s_path1
[0] = s_path2
[0] = 0;
68 if (wcsstr(path
, L
"Recent") != NULL
)
71 StringCchCopyW(s_path1
, _countof(s_path1
), path
);
73 if (!SHGetPathFromIDListW(pidl2
, s_path2
))
79 static VOID
DoPathesAndFlags(UINT type
, PIDLIST_ABSOLUTE pidl1
, PIDLIST_ABSOLUTE pidl2
)
81 if (DoPathes(pidl1
, pidl2
))
89 DoShellNotify(HWND hwnd
, PIDLIST_ABSOLUTE pidl1
, PIDLIST_ABSOLUTE pidl2
, LONG lEvent
)
93 case SHCNE_RENAMEITEM
:
94 DoPathesAndFlags(TYPE_RENAMEITEM
, pidl1
, pidl2
);
97 DoPathesAndFlags(TYPE_CREATE
, pidl1
, pidl2
);
100 DoPathesAndFlags(TYPE_DELETE
, pidl1
, pidl2
);
103 DoPathesAndFlags(TYPE_MKDIR
, pidl1
, pidl2
);
106 DoPathesAndFlags(TYPE_RMDIR
, pidl1
, pidl2
);
108 case SHCNE_MEDIAINSERTED
:
110 case SHCNE_MEDIAREMOVED
:
112 case SHCNE_DRIVEREMOVED
:
118 case SHCNE_NETUNSHARE
:
120 case SHCNE_ATTRIBUTES
:
122 case SHCNE_UPDATEDIR
:
123 DoPathesAndFlags(TYPE_UPDATEDIR
, pidl1
, pidl2
);
125 case SHCNE_UPDATEITEM
:
127 case SHCNE_SERVERDISCONNECT
:
129 case SHCNE_UPDATEIMAGE
:
131 case SHCNE_DRIVEADDGUI
:
133 case SHCNE_RENAMEFOLDER
:
134 DoPathesAndFlags(TYPE_RENAMEFOLDER
, pidl1
, pidl2
);
136 case SHCNE_FREESPACE
:
138 case SHCNE_EXTENDED_EVENT
:
140 case SHCNE_ASSOCCHANGED
:
148 OnShellNotify(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
151 PIDLIST_ABSOLUTE
*pidlAbsolute
;
152 HANDLE hLock
= SHChangeNotification_Lock((HANDLE
)wParam
, (DWORD
)lParam
, &pidlAbsolute
, &lEvent
);
155 DoShellNotify(hwnd
, pidlAbsolute
[0], pidlAbsolute
[1], lEvent
);
156 SHChangeNotification_Unlock(hLock
);
160 pidlAbsolute
= (PIDLIST_ABSOLUTE
*)wParam
;
161 DoShellNotify(hwnd
, pidlAbsolute
[0], pidlAbsolute
[1], lParam
);
167 OnGetNotifyFlags(HWND hwnd
)
173 for (size_t i
= 0; i
< _countof(s_counters
); ++i
)
182 DoSetPaths(HWND hwnd
)
184 WCHAR szText
[MAX_PATH
* 2];
185 StringCchCopyW(szText
, _countof(szText
), s_path1
);
186 StringCchCatW(szText
, _countof(szText
), L
"|");
187 StringCchCatW(szText
, _countof(szText
), s_path2
);
189 FILE *fp
= _wfopen(TEMP_FILE
, L
"wb");
192 fwrite(szText
, (wcslen(szText
) + 1) * sizeof(WCHAR
), 1, fp
);
198 static LRESULT CALLBACK
199 WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
204 return (OnCreate(hwnd
) ? 0 : -1);
207 OnCommand(hwnd
, LOWORD(wParam
));
210 case WM_SHELL_NOTIFY
:
211 return OnShellNotify(hwnd
, wParam
, lParam
);
217 case WM_GET_NOTIFY_FLAGS
:
218 return OnGetNotifyFlags(hwnd
);
221 ZeroMemory(&s_counters
, sizeof(s_counters
));
222 s_path1
[0] = s_path2
[0] = 0;
230 return DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
);
235 static BOOL
ParseCommandLine(LPWSTR lpCmdLine
)
237 LPWSTR pch
= lpCmdLine
; // fRecursive,iWatchDir,nSources
238 s_fRecursive
= !!wcstoul(pch
, NULL
, 0);
239 pch
= wcschr(pch
, L
',');
244 s_iWatchDir
= (DIRTYPE
)wcstoul(pch
, NULL
, 0);
245 pch
= wcschr(pch
, L
',');
250 s_nSources
= wcstoul(pch
, NULL
, 0);
255 wWinMain(HINSTANCE hInstance
,
256 HINSTANCE hPrevInstance
,
260 if (lstrcmpiW(lpCmdLine
, L
"") == 0 || lstrcmpiW(lpCmdLine
, L
"TEST") == 0)
263 if (!ParseCommandLine(lpCmdLine
))
266 s_hEvent
= OpenEventW(EVENT_ALL_ACCESS
, TRUE
, EVENT_NAME
);
269 ZeroMemory(&wc
, sizeof(wc
));
270 wc
.lpfnWndProc
= WindowProc
;
271 wc
.hInstance
= GetModuleHandleW(NULL
);
272 wc
.hIcon
= LoadIcon(NULL
, IDI_APPLICATION
);
273 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
274 wc
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
275 wc
.lpszClassName
= CLASSNAME
;
276 if (!RegisterClassW(&wc
))
279 HWND hwnd
= CreateWindowW(CLASSNAME
, CLASSNAME
, WS_OVERLAPPEDWINDOW
,
280 CW_USEDEFAULT
, CW_USEDEFAULT
, 400, 100,
281 NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
285 ShowWindow(hwnd
, SW_SHOWNORMAL
);
289 while (GetMessageW(&msg
, NULL
, 0, 0))
291 TranslateMessage(&msg
);
292 DispatchMessageW(&msg
);
295 CloseHandle(s_hEvent
);