1fe397602SKatayama Hirofumi MZ /*
2fe397602SKatayama Hirofumi MZ * PROJECT: ReactOS api tests
3fe397602SKatayama Hirofumi MZ * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4fe397602SKatayama Hirofumi MZ * PURPOSE: Test for SHChangeNotify
525e2f5f2SKatayama Hirofumi MZ * COPYRIGHT: Copyright 2020-2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6fe397602SKatayama Hirofumi MZ */
7fe397602SKatayama Hirofumi MZ
825e2f5f2SKatayama Hirofumi MZ // NOTE: This testcase requires shell32_apitest_sub.exe.
990aff8ddSKatayama Hirofumi MZ
10fe397602SKatayama Hirofumi MZ #include "shelltest.h"
1160b89da3SKatayama Hirofumi MZ #include "shell32_apitest_sub.h"
1225e2f5f2SKatayama Hirofumi MZ #include <assert.h>
13fe397602SKatayama Hirofumi MZ
1425e2f5f2SKatayama Hirofumi MZ #define NUM_STEP 8
1525e2f5f2SKatayama Hirofumi MZ #define NUM_CHECKS 12
16d23573beSKatayama Hirofumi MZ #define INTERVAL 0
1725e2f5f2SKatayama Hirofumi MZ #define MAX_EVENT_TYPE 6
187e9cf359SKatayama Hirofumi MZ
1925e2f5f2SKatayama Hirofumi MZ static HWND s_hMainWnd = NULL, s_hSubWnd = NULL;
2025e2f5f2SKatayama Hirofumi MZ static WCHAR s_szSubProgram[MAX_PATH]; // shell32_apitest_sub.exe
217e9cf359SKatayama Hirofumi MZ static HANDLE s_hThread = NULL;
2225e2f5f2SKatayama Hirofumi MZ static INT s_iStage = -1, s_iStep = -1;
2325e2f5f2SKatayama Hirofumi MZ static BYTE s_abChecks[NUM_CHECKS] = { 0 }; // Flags for testing
2425e2f5f2SKatayama Hirofumi MZ static BOOL s_bGotUpdateDir = FALSE; // Got SHCNE_UPDATEDIR?
25fe397602SKatayama Hirofumi MZ
DoCreateFile(LPCWSTR pszFileName)2625e2f5f2SKatayama Hirofumi MZ static BOOL DoCreateFile(LPCWSTR pszFileName)
27fe397602SKatayama Hirofumi MZ {
2825e2f5f2SKatayama Hirofumi MZ HANDLE hFile = ::CreateFileW(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
2925e2f5f2SKatayama Hirofumi MZ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3025e2f5f2SKatayama Hirofumi MZ ::CloseHandle(hFile);
3125e2f5f2SKatayama Hirofumi MZ return hFile != INVALID_HANDLE_VALUE;
32fe397602SKatayama Hirofumi MZ }
33fe397602SKatayama Hirofumi MZ
DoDeleteDirectory(LPCWSTR pszDir)3425e2f5f2SKatayama Hirofumi MZ static void DoDeleteDirectory(LPCWSTR pszDir)
35fe397602SKatayama Hirofumi MZ {
3625e2f5f2SKatayama Hirofumi MZ WCHAR szPath[MAX_PATH];
3725e2f5f2SKatayama Hirofumi MZ ZeroMemory(szPath, sizeof(szPath));
3825e2f5f2SKatayama Hirofumi MZ StringCchCopyW(szPath, _countof(szPath), pszDir); // Double-NULL terminated
3925e2f5f2SKatayama Hirofumi MZ SHFILEOPSTRUCTW FileOp = { NULL, FO_DELETE, szPath, NULL, FOF_NOCONFIRMATION | FOF_SILENT };
4025e2f5f2SKatayama Hirofumi MZ SHFileOperation(&FileOp);
41fe397602SKatayama Hirofumi MZ }
42fe397602SKatayama Hirofumi MZ
GetEventType(LONG lEvent)4325e2f5f2SKatayama Hirofumi MZ static INT GetEventType(LONG lEvent)
44fe397602SKatayama Hirofumi MZ {
4525e2f5f2SKatayama Hirofumi MZ switch (lEvent)
4625e2f5f2SKatayama Hirofumi MZ {
4725e2f5f2SKatayama Hirofumi MZ case SHCNE_CREATE: return 0;
4825e2f5f2SKatayama Hirofumi MZ case SHCNE_DELETE: return 1;
4925e2f5f2SKatayama Hirofumi MZ case SHCNE_RENAMEITEM: return 2;
5025e2f5f2SKatayama Hirofumi MZ case SHCNE_MKDIR: return 3;
5125e2f5f2SKatayama Hirofumi MZ case SHCNE_RMDIR: return 4;
5225e2f5f2SKatayama Hirofumi MZ case SHCNE_RENAMEFOLDER: return 5;
5325e2f5f2SKatayama Hirofumi MZ C_ASSERT(5 + 1 == MAX_EVENT_TYPE);
5425e2f5f2SKatayama Hirofumi MZ default: return -1;
5525e2f5f2SKatayama Hirofumi MZ }
56fe397602SKatayama Hirofumi MZ }
57fe397602SKatayama Hirofumi MZ
5825e2f5f2SKatayama Hirofumi MZ #define FILE_1 L"_TESTFILE_1_.txt"
5925e2f5f2SKatayama Hirofumi MZ #define FILE_2 L"_TESTFILE_2_.txt"
6025e2f5f2SKatayama Hirofumi MZ #define DIR_1 L"_TESTDIR_1_"
6125e2f5f2SKatayama Hirofumi MZ #define DIR_2 L"_TESTDIR_2_"
62fe397602SKatayama Hirofumi MZ
6325e2f5f2SKatayama Hirofumi MZ static WCHAR s_szDir1[MAX_PATH];
6425e2f5f2SKatayama Hirofumi MZ static WCHAR s_szDir1InDir1[MAX_PATH];
6525e2f5f2SKatayama Hirofumi MZ static WCHAR s_szDir2InDir1[MAX_PATH];
6625e2f5f2SKatayama Hirofumi MZ static WCHAR s_szFile1InDir1InDir1[MAX_PATH];
6725e2f5f2SKatayama Hirofumi MZ static WCHAR s_szFile1InDir1[MAX_PATH];
6825e2f5f2SKatayama Hirofumi MZ static WCHAR s_szFile2InDir1[MAX_PATH];
697e9cf359SKatayama Hirofumi MZ
DoDeleteFilesAndDirs(void)707e9cf359SKatayama Hirofumi MZ static void DoDeleteFilesAndDirs(void)
717e9cf359SKatayama Hirofumi MZ {
7225e2f5f2SKatayama Hirofumi MZ ::DeleteFileW(s_szFile1InDir1);
7325e2f5f2SKatayama Hirofumi MZ ::DeleteFileW(s_szFile2InDir1);
7425e2f5f2SKatayama Hirofumi MZ ::DeleteFileW(s_szFile1InDir1InDir1);
7525e2f5f2SKatayama Hirofumi MZ DoDeleteDirectory(s_szDir1InDir1);
7625e2f5f2SKatayama Hirofumi MZ DoDeleteDirectory(s_szDir2InDir1);
7725e2f5f2SKatayama Hirofumi MZ DoDeleteDirectory(s_szDir1);
787e9cf359SKatayama Hirofumi MZ }
797e9cf359SKatayama Hirofumi MZ
TEST_Quit(void)8025e2f5f2SKatayama Hirofumi MZ static void TEST_Quit(void)
817e9cf359SKatayama Hirofumi MZ {
8225e2f5f2SKatayama Hirofumi MZ CloseHandle(s_hThread);
837e9cf359SKatayama Hirofumi MZ s_hThread = NULL;
847e9cf359SKatayama Hirofumi MZ
8525e2f5f2SKatayama Hirofumi MZ PostMessageW(s_hSubWnd, WM_COMMAND, IDNO, 0); // Finish
8625e2f5f2SKatayama Hirofumi MZ DoWaitForWindow(SUB_CLASSNAME, SUB_CLASSNAME, TRUE, TRUE); // Close sub-windows
877e9cf359SKatayama Hirofumi MZ
887e9cf359SKatayama Hirofumi MZ DoDeleteFilesAndDirs();
89fe397602SKatayama Hirofumi MZ }
90fe397602SKatayama Hirofumi MZ
DoBuildFilesAndDirs(void)9125e2f5f2SKatayama Hirofumi MZ static void DoBuildFilesAndDirs(void)
92302356bfSKatayama Hirofumi MZ {
9325e2f5f2SKatayama Hirofumi MZ WCHAR szPath1[MAX_PATH];
9425e2f5f2SKatayama Hirofumi MZ SHGetSpecialFolderPathW(NULL, szPath1, CSIDL_PERSONAL, FALSE); // My Documents
9525e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1);
9625e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir1, _countof(s_szDir1), szPath1);
977f766e94SKatayama Hirofumi MZ
9825e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1);
9925e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir1InDir1, _countof(s_szDir1InDir1), szPath1);
10025e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
1017e9cf359SKatayama Hirofumi MZ
10225e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_2);
10325e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir2InDir1, _countof(s_szDir2InDir1), szPath1);
10425e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
10525e2f5f2SKatayama Hirofumi MZ
10625e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1);
10725e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_1);
10825e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile1InDir1InDir1, _countof(s_szFile1InDir1InDir1), szPath1);
10925e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
11025e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
11125e2f5f2SKatayama Hirofumi MZ
11225e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_1);
11325e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile1InDir1, _countof(s_szFile1InDir1), szPath1);
11425e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
11525e2f5f2SKatayama Hirofumi MZ
11625e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_2);
11725e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile2InDir1, _countof(s_szFile2InDir1), szPath1);
11825e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1);
11925e2f5f2SKatayama Hirofumi MZ
12025e2f5f2SKatayama Hirofumi MZ #define TRACE_PATH(path) trace(#path ": %ls\n", path)
12125e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szDir1);
12225e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szDir1InDir1);
12325e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile1InDir1);
12425e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile1InDir1InDir1);
12525e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile2InDir1);
12625e2f5f2SKatayama Hirofumi MZ #undef TRACE_PATH
12725e2f5f2SKatayama Hirofumi MZ
12825e2f5f2SKatayama Hirofumi MZ DoDeleteFilesAndDirs();
12925e2f5f2SKatayama Hirofumi MZ
13025e2f5f2SKatayama Hirofumi MZ ::CreateDirectoryW(s_szDir1, NULL);
13125e2f5f2SKatayama Hirofumi MZ ok_int(!!PathIsDirectoryW(s_szDir1), TRUE);
13225e2f5f2SKatayama Hirofumi MZ
13325e2f5f2SKatayama Hirofumi MZ DoDeleteDirectory(s_szDir1InDir1);
13425e2f5f2SKatayama Hirofumi MZ ok_int(!PathIsDirectoryW(s_szDir1InDir1), TRUE);
1357e9cf359SKatayama Hirofumi MZ }
1367e9cf359SKatayama Hirofumi MZ
DoTestEntry(LONG lEvent,LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)13725e2f5f2SKatayama Hirofumi MZ static void DoTestEntry(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
1387f766e94SKatayama Hirofumi MZ {
13925e2f5f2SKatayama Hirofumi MZ WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
14025e2f5f2SKatayama Hirofumi MZ
14125e2f5f2SKatayama Hirofumi MZ szPath1[0] = szPath2[0] = 0;
14225e2f5f2SKatayama Hirofumi MZ SHGetPathFromIDListW(pidl1, szPath1);
14325e2f5f2SKatayama Hirofumi MZ SHGetPathFromIDListW(pidl2, szPath2);
14425e2f5f2SKatayama Hirofumi MZ
14525e2f5f2SKatayama Hirofumi MZ trace("(0x%lX, '%ls', '%ls')\n", lEvent, szPath1, szPath2);
14625e2f5f2SKatayama Hirofumi MZ
14725e2f5f2SKatayama Hirofumi MZ if (lEvent == SHCNE_UPDATEDIR)
14825e2f5f2SKatayama Hirofumi MZ {
14925e2f5f2SKatayama Hirofumi MZ trace("Got SHCNE_UPDATEDIR\n");
15025e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = TRUE;
151fe397602SKatayama Hirofumi MZ return;
152fe397602SKatayama Hirofumi MZ }
153fe397602SKatayama Hirofumi MZ
15425e2f5f2SKatayama Hirofumi MZ INT iEventType = GetEventType(lEvent);
15525e2f5f2SKatayama Hirofumi MZ if (iEventType < 0)
15625e2f5f2SKatayama Hirofumi MZ return;
15725e2f5f2SKatayama Hirofumi MZ
15825e2f5f2SKatayama Hirofumi MZ assert(iEventType < MAX_EVENT_TYPE);
15925e2f5f2SKatayama Hirofumi MZ
16025e2f5f2SKatayama Hirofumi MZ INT i = 0;
16125e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, L"") == 0) << iEventType;
16225e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szDir1) == 0) << iEventType;
16325e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szDir2InDir1) == 0) << iEventType;
16425e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile1InDir1) == 0) << iEventType;
16525e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile2InDir1) == 0) << iEventType;
16625e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile1InDir1InDir1) == 0) << iEventType;
16725e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, L"") == 0) << iEventType;
16825e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szDir1) == 0) << iEventType;
16925e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szDir2InDir1) == 0) << iEventType;
17025e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile1InDir1) == 0) << iEventType;
17125e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile2InDir1) == 0) << iEventType;
17225e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile1InDir1InDir1) == 0) << iEventType;
17325e2f5f2SKatayama Hirofumi MZ assert(i == NUM_CHECKS);
17425e2f5f2SKatayama Hirofumi MZ }
17525e2f5f2SKatayama Hirofumi MZ
StringFromChecks(void)17625e2f5f2SKatayama Hirofumi MZ static LPCSTR StringFromChecks(void)
1777f766e94SKatayama Hirofumi MZ {
17825e2f5f2SKatayama Hirofumi MZ static char s_sz[2 * NUM_CHECKS + 1];
17925e2f5f2SKatayama Hirofumi MZ
18025e2f5f2SKatayama Hirofumi MZ char *pch = s_sz;
18125e2f5f2SKatayama Hirofumi MZ for (INT i = 0; i < NUM_CHECKS; ++i)
18225e2f5f2SKatayama Hirofumi MZ {
18325e2f5f2SKatayama Hirofumi MZ WCHAR sz[3];
18425e2f5f2SKatayama Hirofumi MZ StringCchPrintfW(sz, _countof(sz), L"%02X", s_abChecks[i]);
18525e2f5f2SKatayama Hirofumi MZ *pch++ = sz[0];
18625e2f5f2SKatayama Hirofumi MZ *pch++ = sz[1];
18725e2f5f2SKatayama Hirofumi MZ }
18825e2f5f2SKatayama Hirofumi MZ
18925e2f5f2SKatayama Hirofumi MZ assert((pch - s_sz) + 1 == sizeof(s_sz));
19025e2f5f2SKatayama Hirofumi MZ
19125e2f5f2SKatayama Hirofumi MZ *pch = 0;
19225e2f5f2SKatayama Hirofumi MZ return s_sz;
19325e2f5f2SKatayama Hirofumi MZ }
19425e2f5f2SKatayama Hirofumi MZ
19525e2f5f2SKatayama Hirofumi MZ struct TEST_ANSWER
19625e2f5f2SKatayama Hirofumi MZ {
19725e2f5f2SKatayama Hirofumi MZ INT lineno;
19825e2f5f2SKatayama Hirofumi MZ LPCSTR answer;
19925e2f5f2SKatayama Hirofumi MZ };
20025e2f5f2SKatayama Hirofumi MZ
DoStepCheck(INT iStage,INT iStep,LPCSTR checks)20125e2f5f2SKatayama Hirofumi MZ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks)
20225e2f5f2SKatayama Hirofumi MZ {
20325e2f5f2SKatayama Hirofumi MZ assert(0 <= iStep);
20425e2f5f2SKatayama Hirofumi MZ assert(iStep < NUM_STEP);
20525e2f5f2SKatayama Hirofumi MZ
20625e2f5f2SKatayama Hirofumi MZ assert(0 <= iStage);
20725e2f5f2SKatayama Hirofumi MZ assert(iStage < NUM_STAGE);
20825e2f5f2SKatayama Hirofumi MZ
20925e2f5f2SKatayama Hirofumi MZ if (s_bGotUpdateDir)
21025e2f5f2SKatayama Hirofumi MZ {
21125e2f5f2SKatayama Hirofumi MZ ok_int(TRUE, TRUE);
212fe397602SKatayama Hirofumi MZ return;
213fe397602SKatayama Hirofumi MZ }
214fe397602SKatayama Hirofumi MZ
21525e2f5f2SKatayama Hirofumi MZ LPCSTR answer = NULL;
21625e2f5f2SKatayama Hirofumi MZ INT lineno;
21725e2f5f2SKatayama Hirofumi MZ switch (iStage)
218fe397602SKatayama Hirofumi MZ {
21925e2f5f2SKatayama Hirofumi MZ case 0:
22025e2f5f2SKatayama Hirofumi MZ case 1:
2218337df2bSKatayama Hirofumi MZ case 3:
2228337df2bSKatayama Hirofumi MZ case 6:
2238337df2bSKatayama Hirofumi MZ case 9:
2247e9cf359SKatayama Hirofumi MZ {
22525e2f5f2SKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] =
22625e2f5f2SKatayama Hirofumi MZ {
22725e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000010000010000000000" }, // 0
22825e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000040000000000000400" }, // 1
22925e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000200020000000000" }, // 2
23025e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000080000000000" }, // 3
23125e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000001010000000000" }, // 4
23225e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000002020000000000" }, // 5
23325e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000000020000000" }, // 6
23425e2f5f2SKatayama Hirofumi MZ { __LINE__, "000010000000100000000000" }, // 7
23525e2f5f2SKatayama Hirofumi MZ };
23625e2f5f2SKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP);
23725e2f5f2SKatayama Hirofumi MZ lineno = c_answers[iStep].lineno;
23825e2f5f2SKatayama Hirofumi MZ answer = c_answers[iStep].answer;
23925e2f5f2SKatayama Hirofumi MZ break;
24025e2f5f2SKatayama Hirofumi MZ }
24125e2f5f2SKatayama Hirofumi MZ case 2:
2428337df2bSKatayama Hirofumi MZ case 4:
2438337df2bSKatayama Hirofumi MZ case 5:
2448337df2bSKatayama Hirofumi MZ case 7:
2458337df2bSKatayama Hirofumi MZ {
2468337df2bSKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] =
2478337df2bSKatayama Hirofumi MZ {
2488337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 0
2498337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 1
2508337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 2
2518337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 3
2528337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 4
2538337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 5
2548337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 6
2558337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 7
2568337df2bSKatayama Hirofumi MZ };
2578337df2bSKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP);
2588337df2bSKatayama Hirofumi MZ lineno = c_answers[iStep].lineno;
2598337df2bSKatayama Hirofumi MZ answer = c_answers[iStep].answer;
2608337df2bSKatayama Hirofumi MZ break;
2618337df2bSKatayama Hirofumi MZ }
2628337df2bSKatayama Hirofumi MZ case 8:
26325e2f5f2SKatayama Hirofumi MZ {
26425e2f5f2SKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] =
26525e2f5f2SKatayama Hirofumi MZ {
26625e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000010000010000000000" }, // 0
26725e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000040000000000000400" }, // 1
26825e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000200020000000000" }, // 2
26925e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000080000000000" }, // 3
2708337df2bSKatayama Hirofumi MZ { __LINE__, "000000000001010000000000" }, // 4 // Recursive case
2718337df2bSKatayama Hirofumi MZ { __LINE__, "000000000002020000000000" }, // 5 // Recursive case
27225e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000000020000000" }, // 6
27325e2f5f2SKatayama Hirofumi MZ { __LINE__, "000010000000100000000000" }, // 7
27425e2f5f2SKatayama Hirofumi MZ };
27525e2f5f2SKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP);
27625e2f5f2SKatayama Hirofumi MZ lineno = c_answers[iStep].lineno;
27725e2f5f2SKatayama Hirofumi MZ answer = c_answers[iStep].answer;
27825e2f5f2SKatayama Hirofumi MZ if (iStep == 4 || iStep == 5) // Recursive cases
27925e2f5f2SKatayama Hirofumi MZ {
28025e2f5f2SKatayama Hirofumi MZ if (lstrcmpA(checks, "000000000000000000000000") == 0)
2818337df2bSKatayama Hirofumi MZ {
2828337df2bSKatayama Hirofumi MZ trace("Warning! Recursive cases...\n");
28325e2f5f2SKatayama Hirofumi MZ answer = "000000000000000000000000";
28425e2f5f2SKatayama Hirofumi MZ }
28525e2f5f2SKatayama Hirofumi MZ }
28625e2f5f2SKatayama Hirofumi MZ break;
28725e2f5f2SKatayama Hirofumi MZ }
28825e2f5f2SKatayama Hirofumi MZ default:
28925e2f5f2SKatayama Hirofumi MZ {
29025e2f5f2SKatayama Hirofumi MZ assert(0);
29125e2f5f2SKatayama Hirofumi MZ break;
29225e2f5f2SKatayama Hirofumi MZ }
29325e2f5f2SKatayama Hirofumi MZ }
2947e9cf359SKatayama Hirofumi MZ
29525e2f5f2SKatayama Hirofumi MZ ok(lstrcmpA(checks, answer) == 0,
29625e2f5f2SKatayama Hirofumi MZ "Line %d: '%s' vs '%s' at Stage %d, Step %d\n", lineno, checks, answer, iStage, iStep);
29725e2f5f2SKatayama Hirofumi MZ }
2987e9cf359SKatayama Hirofumi MZ
StageThreadFunc(LPVOID arg)29925e2f5f2SKatayama Hirofumi MZ static DWORD WINAPI StageThreadFunc(LPVOID arg)
30025e2f5f2SKatayama Hirofumi MZ {
30125e2f5f2SKatayama Hirofumi MZ BOOL ret;
3027e9cf359SKatayama Hirofumi MZ
30325e2f5f2SKatayama Hirofumi MZ trace("Stage %d\n", s_iStage);
3047e9cf359SKatayama Hirofumi MZ
30525e2f5f2SKatayama Hirofumi MZ // 0: Create file1 in dir1
30625e2f5f2SKatayama Hirofumi MZ s_iStep = 0;
30725e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
3088337df2bSKatayama Hirofumi MZ SHChangeNotify(0, SHCNF_PATHW | SHCNF_FLUSH, NULL, NULL);
30925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
31025e2f5f2SKatayama Hirofumi MZ ret = DoCreateFile(s_szFile1InDir1);
31125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
312d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1, 0);
31325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
31425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
3157e9cf359SKatayama Hirofumi MZ
31625e2f5f2SKatayama Hirofumi MZ // 1: Rename file1 as file2 in dir1
31725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
31825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
31925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
32025e2f5f2SKatayama Hirofumi MZ ret = MoveFileW(s_szFile1InDir1, s_szFile2InDir1);
32125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
322d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1, s_szFile2InDir1);
32325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
32425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
3257e9cf359SKatayama Hirofumi MZ
32625e2f5f2SKatayama Hirofumi MZ // 2: Delete file2 in dir1
32725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
32825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
32925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
33025e2f5f2SKatayama Hirofumi MZ ret = DeleteFileW(s_szFile2InDir1);
33125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
332d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile2InDir1, NULL);
33325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
33425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
3357e9cf359SKatayama Hirofumi MZ
33625e2f5f2SKatayama Hirofumi MZ // 3: Create dir1 in dir1
33725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
33825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
33925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
34025e2f5f2SKatayama Hirofumi MZ ret = CreateDirectoryExW(s_szDir1, s_szDir1InDir1, NULL);
34125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
342d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW | SHCNF_FLUSH, s_szDir1InDir1, NULL);
34325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
34425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
3457e9cf359SKatayama Hirofumi MZ
34625e2f5f2SKatayama Hirofumi MZ // 4: Create file1 in dir1 in dir1
34725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
34825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
34925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
35025e2f5f2SKatayama Hirofumi MZ ret = DoCreateFile(s_szFile1InDir1InDir1);
35125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
352d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1InDir1, NULL);
35325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
35425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
3557e9cf359SKatayama Hirofumi MZ
35625e2f5f2SKatayama Hirofumi MZ // 5: Delete file1 in dir1 in dir1
35725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
35825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
35925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
36025e2f5f2SKatayama Hirofumi MZ ret = DeleteFileW(s_szFile1InDir1InDir1);
36125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
362d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1InDir1, NULL);
36325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
36425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
36525e2f5f2SKatayama Hirofumi MZ
36625e2f5f2SKatayama Hirofumi MZ // 6: Rename dir1 as dir2 in dir1
36725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
36825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
36925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
37025e2f5f2SKatayama Hirofumi MZ ret = ::MoveFileW(s_szDir1InDir1, s_szDir2InDir1);
37125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
372d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATHW | SHCNF_FLUSH, s_szDir1InDir1, s_szDir2InDir1);
37325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
37425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
37525e2f5f2SKatayama Hirofumi MZ
37625e2f5f2SKatayama Hirofumi MZ // 7: Remove dir2 in dir1
37725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
37825e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep);
37925e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks));
38025e2f5f2SKatayama Hirofumi MZ ret = RemoveDirectoryW(s_szDir2InDir1);
38125e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE);
382d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW | SHCNF_FLUSH, s_szDir2InDir1, NULL);
38325e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL);
38425e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks());
38525e2f5f2SKatayama Hirofumi MZ
38625e2f5f2SKatayama Hirofumi MZ // 8: Finish
38725e2f5f2SKatayama Hirofumi MZ ++s_iStep;
38825e2f5f2SKatayama Hirofumi MZ assert(s_iStep == NUM_STEP);
38925e2f5f2SKatayama Hirofumi MZ C_ASSERT(NUM_STEP == 8);
39025e2f5f2SKatayama Hirofumi MZ if (s_iStage + 1 < NUM_STAGE)
39125e2f5f2SKatayama Hirofumi MZ {
39225e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hSubWnd, WM_COMMAND, IDRETRY, 0); // Next stage
39325e2f5f2SKatayama Hirofumi MZ }
39425e2f5f2SKatayama Hirofumi MZ else
39525e2f5f2SKatayama Hirofumi MZ {
39625e2f5f2SKatayama Hirofumi MZ // Finish
39725e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hSubWnd, WM_COMMAND, IDNO, 0);
39825e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hMainWnd, WM_COMMAND, IDNO, 0);
39925e2f5f2SKatayama Hirofumi MZ }
40025e2f5f2SKatayama Hirofumi MZ
40125e2f5f2SKatayama Hirofumi MZ s_iStep = -1;
4027e9cf359SKatayama Hirofumi MZ
4037e9cf359SKatayama Hirofumi MZ return 0;
4045800ee5eSKatayama Hirofumi MZ }
4055800ee5eSKatayama Hirofumi MZ
40625e2f5f2SKatayama Hirofumi MZ // WM_COPYDATA
OnCopyData(HWND hwnd,HWND hwndSender,COPYDATASTRUCT * pCopyData)40725e2f5f2SKatayama Hirofumi MZ static BOOL OnCopyData(HWND hwnd, HWND hwndSender, COPYDATASTRUCT *pCopyData)
4085800ee5eSKatayama Hirofumi MZ {
40925e2f5f2SKatayama Hirofumi MZ if (pCopyData->dwData != 0xBEEFCAFE)
41025e2f5f2SKatayama Hirofumi MZ return FALSE;
4117e9cf359SKatayama Hirofumi MZ
41225e2f5f2SKatayama Hirofumi MZ LPBYTE pbData = (LPBYTE)pCopyData->lpData;
41325e2f5f2SKatayama Hirofumi MZ LPBYTE pb = pbData;
4147e9cf359SKatayama Hirofumi MZ
41525e2f5f2SKatayama Hirofumi MZ LONG cbTotal = pCopyData->cbData;
41625e2f5f2SKatayama Hirofumi MZ assert(cbTotal >= LONG(sizeof(LONG) + sizeof(DWORD) + sizeof(DWORD)));
41725e2f5f2SKatayama Hirofumi MZ
41825e2f5f2SKatayama Hirofumi MZ LONG lEvent = *(LONG*)pb;
41925e2f5f2SKatayama Hirofumi MZ pb += sizeof(lEvent);
42025e2f5f2SKatayama Hirofumi MZ
42125e2f5f2SKatayama Hirofumi MZ DWORD cbPidl1 = *(DWORD*)pb;
42225e2f5f2SKatayama Hirofumi MZ pb += sizeof(cbPidl1);
42325e2f5f2SKatayama Hirofumi MZ
42425e2f5f2SKatayama Hirofumi MZ DWORD cbPidl2 = *(DWORD*)pb;
42525e2f5f2SKatayama Hirofumi MZ pb += sizeof(cbPidl2);
42625e2f5f2SKatayama Hirofumi MZ
42725e2f5f2SKatayama Hirofumi MZ LPITEMIDLIST pidl1 = NULL;
42825e2f5f2SKatayama Hirofumi MZ if (cbPidl1)
42925e2f5f2SKatayama Hirofumi MZ {
43025e2f5f2SKatayama Hirofumi MZ pidl1 = (LPITEMIDLIST)CoTaskMemAlloc(cbPidl1);
43125e2f5f2SKatayama Hirofumi MZ CopyMemory(pidl1, pb, cbPidl1);
43225e2f5f2SKatayama Hirofumi MZ pb += cbPidl1;
43325e2f5f2SKatayama Hirofumi MZ }
43425e2f5f2SKatayama Hirofumi MZ
43525e2f5f2SKatayama Hirofumi MZ LPITEMIDLIST pidl2 = NULL;
43625e2f5f2SKatayama Hirofumi MZ if (cbPidl2)
43725e2f5f2SKatayama Hirofumi MZ {
43825e2f5f2SKatayama Hirofumi MZ pidl2 = (LPITEMIDLIST)CoTaskMemAlloc(cbPidl2);
43925e2f5f2SKatayama Hirofumi MZ CopyMemory(pidl2, pb, cbPidl2);
44025e2f5f2SKatayama Hirofumi MZ pb += cbPidl2;
44125e2f5f2SKatayama Hirofumi MZ }
44225e2f5f2SKatayama Hirofumi MZ
44325e2f5f2SKatayama Hirofumi MZ assert((pb - pbData) == cbTotal);
44425e2f5f2SKatayama Hirofumi MZ
44525e2f5f2SKatayama Hirofumi MZ DoTestEntry(lEvent, pidl1, pidl2);
44625e2f5f2SKatayama Hirofumi MZ
44725e2f5f2SKatayama Hirofumi MZ CoTaskMemFree(pidl1);
44825e2f5f2SKatayama Hirofumi MZ CoTaskMemFree(pidl2);
44925e2f5f2SKatayama Hirofumi MZ
45025e2f5f2SKatayama Hirofumi MZ return TRUE;
45125e2f5f2SKatayama Hirofumi MZ }
45225e2f5f2SKatayama Hirofumi MZ
45325e2f5f2SKatayama Hirofumi MZ static LRESULT CALLBACK
MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)45425e2f5f2SKatayama Hirofumi MZ MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
45525e2f5f2SKatayama Hirofumi MZ {
45625e2f5f2SKatayama Hirofumi MZ switch (uMsg)
45725e2f5f2SKatayama Hirofumi MZ {
45825e2f5f2SKatayama Hirofumi MZ case WM_CREATE:
45925e2f5f2SKatayama Hirofumi MZ s_hMainWnd = hwnd;
46025e2f5f2SKatayama Hirofumi MZ return 0;
46125e2f5f2SKatayama Hirofumi MZ
46225e2f5f2SKatayama Hirofumi MZ case WM_COMMAND:
46325e2f5f2SKatayama Hirofumi MZ switch (LOWORD(wParam))
46425e2f5f2SKatayama Hirofumi MZ {
46525e2f5f2SKatayama Hirofumi MZ case IDYES: // Start testing
46625e2f5f2SKatayama Hirofumi MZ {
46725e2f5f2SKatayama Hirofumi MZ s_iStage = 0;
46825e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = FALSE;
46925e2f5f2SKatayama Hirofumi MZ s_hThread = ::CreateThread(NULL, 0, StageThreadFunc, hwnd, 0, NULL);
47025e2f5f2SKatayama Hirofumi MZ if (!s_hThread)
47125e2f5f2SKatayama Hirofumi MZ {
47225e2f5f2SKatayama Hirofumi MZ skip("!s_hThread\n");
47325e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd);
47425e2f5f2SKatayama Hirofumi MZ }
47525e2f5f2SKatayama Hirofumi MZ break;
47625e2f5f2SKatayama Hirofumi MZ }
47725e2f5f2SKatayama Hirofumi MZ case IDRETRY: // New stage
47825e2f5f2SKatayama Hirofumi MZ {
47925e2f5f2SKatayama Hirofumi MZ ::CloseHandle(s_hThread);
48025e2f5f2SKatayama Hirofumi MZ ++s_iStage;
48125e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = FALSE;
48225e2f5f2SKatayama Hirofumi MZ s_hThread = ::CreateThread(NULL, 0, StageThreadFunc, hwnd, 0, NULL);
48325e2f5f2SKatayama Hirofumi MZ if (!s_hThread)
48425e2f5f2SKatayama Hirofumi MZ {
48525e2f5f2SKatayama Hirofumi MZ skip("!s_hThread\n");
48625e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd);
48725e2f5f2SKatayama Hirofumi MZ }
48825e2f5f2SKatayama Hirofumi MZ break;
48925e2f5f2SKatayama Hirofumi MZ }
49025e2f5f2SKatayama Hirofumi MZ case IDNO: // Quit
49125e2f5f2SKatayama Hirofumi MZ {
49225e2f5f2SKatayama Hirofumi MZ s_iStage = -1;
49325e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd);
49425e2f5f2SKatayama Hirofumi MZ break;
49525e2f5f2SKatayama Hirofumi MZ }
49625e2f5f2SKatayama Hirofumi MZ }
49725e2f5f2SKatayama Hirofumi MZ break;
49825e2f5f2SKatayama Hirofumi MZ
49925e2f5f2SKatayama Hirofumi MZ case WM_COPYDATA:
50025e2f5f2SKatayama Hirofumi MZ if (s_iStage < 0 || s_iStep < 0)
50125e2f5f2SKatayama Hirofumi MZ break;
50225e2f5f2SKatayama Hirofumi MZ
50325e2f5f2SKatayama Hirofumi MZ OnCopyData(hwnd, (HWND)wParam, (COPYDATASTRUCT*)lParam);
50425e2f5f2SKatayama Hirofumi MZ break;
50525e2f5f2SKatayama Hirofumi MZ
50625e2f5f2SKatayama Hirofumi MZ case WM_DESTROY:
50725e2f5f2SKatayama Hirofumi MZ ::PostQuitMessage(0);
50825e2f5f2SKatayama Hirofumi MZ break;
50925e2f5f2SKatayama Hirofumi MZ
51025e2f5f2SKatayama Hirofumi MZ default:
51125e2f5f2SKatayama Hirofumi MZ return ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
51225e2f5f2SKatayama Hirofumi MZ }
51325e2f5f2SKatayama Hirofumi MZ return 0;
51425e2f5f2SKatayama Hirofumi MZ }
51525e2f5f2SKatayama Hirofumi MZ
TEST_Init(void)51625e2f5f2SKatayama Hirofumi MZ static BOOL TEST_Init(void)
51725e2f5f2SKatayama Hirofumi MZ {
518*75cc5b2bSKatayama Hirofumi MZ if (!FindSubProgram(s_szSubProgram, _countof(s_szSubProgram)))
5195800ee5eSKatayama Hirofumi MZ {
520fccea84dSKatayama Hirofumi MZ skip("shell32_apitest_sub.exe not found\n");
52125e2f5f2SKatayama Hirofumi MZ return FALSE;
5225800ee5eSKatayama Hirofumi MZ }
5235800ee5eSKatayama Hirofumi MZ
52425e2f5f2SKatayama Hirofumi MZ // close the SUB_CLASSNAME windows
52525e2f5f2SKatayama Hirofumi MZ DoWaitForWindow(SUB_CLASSNAME, SUB_CLASSNAME, TRUE, TRUE);
52625e2f5f2SKatayama Hirofumi MZ
52725e2f5f2SKatayama Hirofumi MZ // Execute sub program
52825e2f5f2SKatayama Hirofumi MZ HINSTANCE hinst = ShellExecuteW(NULL, NULL, s_szSubProgram, L"---", NULL, SW_SHOWNORMAL);
52925e2f5f2SKatayama Hirofumi MZ if ((INT_PTR)hinst <= 32)
5307e9cf359SKatayama Hirofumi MZ {
53125e2f5f2SKatayama Hirofumi MZ skip("Unable to run shell32_apitest_sub.exe.\n");
53225e2f5f2SKatayama Hirofumi MZ return FALSE;
53325e2f5f2SKatayama Hirofumi MZ }
53425e2f5f2SKatayama Hirofumi MZ
53525e2f5f2SKatayama Hirofumi MZ // prepare for files and dirs
53625e2f5f2SKatayama Hirofumi MZ DoBuildFilesAndDirs();
53725e2f5f2SKatayama Hirofumi MZ
53825e2f5f2SKatayama Hirofumi MZ // Register main window
53925e2f5f2SKatayama Hirofumi MZ WNDCLASSW wc = { 0, MainWndProc };
54025e2f5f2SKatayama Hirofumi MZ wc.hInstance = GetModuleHandleW(NULL);
54125e2f5f2SKatayama Hirofumi MZ wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
54225e2f5f2SKatayama Hirofumi MZ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
54325e2f5f2SKatayama Hirofumi MZ wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
54425e2f5f2SKatayama Hirofumi MZ wc.lpszClassName = MAIN_CLASSNAME;
54525e2f5f2SKatayama Hirofumi MZ if (!RegisterClassW(&wc))
54625e2f5f2SKatayama Hirofumi MZ {
54725e2f5f2SKatayama Hirofumi MZ skip("RegisterClassW failed\n");
54825e2f5f2SKatayama Hirofumi MZ return FALSE;
54925e2f5f2SKatayama Hirofumi MZ }
55025e2f5f2SKatayama Hirofumi MZ
55125e2f5f2SKatayama Hirofumi MZ // Create main window
55225e2f5f2SKatayama Hirofumi MZ HWND hwnd = CreateWindowW(MAIN_CLASSNAME, MAIN_CLASSNAME, WS_OVERLAPPEDWINDOW,
55325e2f5f2SKatayama Hirofumi MZ CW_USEDEFAULT, CW_USEDEFAULT, 400, 100,
55425e2f5f2SKatayama Hirofumi MZ NULL, NULL, GetModuleHandleW(NULL), NULL);
55525e2f5f2SKatayama Hirofumi MZ if (!hwnd)
55625e2f5f2SKatayama Hirofumi MZ {
55725e2f5f2SKatayama Hirofumi MZ skip("CreateWindowW failed\n");
55825e2f5f2SKatayama Hirofumi MZ return FALSE;
55925e2f5f2SKatayama Hirofumi MZ }
56025e2f5f2SKatayama Hirofumi MZ ::ShowWindow(hwnd, SW_SHOWNORMAL);
56125e2f5f2SKatayama Hirofumi MZ ::UpdateWindow(hwnd);
56225e2f5f2SKatayama Hirofumi MZ
56325e2f5f2SKatayama Hirofumi MZ // Find sub-window
56425e2f5f2SKatayama Hirofumi MZ s_hSubWnd = DoWaitForWindow(SUB_CLASSNAME, SUB_CLASSNAME, FALSE, FALSE);
56525e2f5f2SKatayama Hirofumi MZ if (!s_hSubWnd)
56625e2f5f2SKatayama Hirofumi MZ {
56725e2f5f2SKatayama Hirofumi MZ skip("Unable to find sub-program window.\n");
56825e2f5f2SKatayama Hirofumi MZ return FALSE;
56925e2f5f2SKatayama Hirofumi MZ }
57025e2f5f2SKatayama Hirofumi MZ
57125e2f5f2SKatayama Hirofumi MZ // Start testing
57225e2f5f2SKatayama Hirofumi MZ SendMessageW(s_hSubWnd, WM_COMMAND, IDYES, 0);
57325e2f5f2SKatayama Hirofumi MZ
57425e2f5f2SKatayama Hirofumi MZ return TRUE;
57525e2f5f2SKatayama Hirofumi MZ }
57625e2f5f2SKatayama Hirofumi MZ
TEST_Main(void)57725e2f5f2SKatayama Hirofumi MZ static void TEST_Main(void)
57825e2f5f2SKatayama Hirofumi MZ {
57925e2f5f2SKatayama Hirofumi MZ if (!TEST_Init())
58025e2f5f2SKatayama Hirofumi MZ {
58125e2f5f2SKatayama Hirofumi MZ skip("Unable to start testing.\n");
58225e2f5f2SKatayama Hirofumi MZ TEST_Quit();
5837e9cf359SKatayama Hirofumi MZ return;
5847e9cf359SKatayama Hirofumi MZ }
5857e9cf359SKatayama Hirofumi MZ
58625e2f5f2SKatayama Hirofumi MZ // Message loop
58725e2f5f2SKatayama Hirofumi MZ MSG msg;
58825e2f5f2SKatayama Hirofumi MZ while (GetMessageW(&msg, NULL, 0, 0))
58925e2f5f2SKatayama Hirofumi MZ {
59025e2f5f2SKatayama Hirofumi MZ ::TranslateMessage(&msg);
59125e2f5f2SKatayama Hirofumi MZ ::DispatchMessage(&msg);
59225e2f5f2SKatayama Hirofumi MZ }
5937e9cf359SKatayama Hirofumi MZ
59425e2f5f2SKatayama Hirofumi MZ TEST_Quit();
59525e2f5f2SKatayama Hirofumi MZ }
59625e2f5f2SKatayama Hirofumi MZ
START_TEST(SHChangeNotify)59725e2f5f2SKatayama Hirofumi MZ START_TEST(SHChangeNotify)
59825e2f5f2SKatayama Hirofumi MZ {
59925e2f5f2SKatayama Hirofumi MZ trace("Please close all Explorer windows before testing.\n");
60025e2f5f2SKatayama Hirofumi MZ trace("Please don't operate your PC while testing.\n");
60125e2f5f2SKatayama Hirofumi MZ
60225e2f5f2SKatayama Hirofumi MZ DWORD dwOldTick = GetTickCount();
60325e2f5f2SKatayama Hirofumi MZ TEST_Main();
6047e9cf359SKatayama Hirofumi MZ DWORD dwNewTick = GetTickCount();
60525e2f5f2SKatayama Hirofumi MZ
6067e9cf359SKatayama Hirofumi MZ DWORD dwTick = dwNewTick - dwOldTick;
6077e9cf359SKatayama Hirofumi MZ trace("SHChangeNotify: Total %lu.%lu sec\n", (dwTick / 1000), (dwTick / 100 % 10));
608fe397602SKatayama Hirofumi MZ }
609