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 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 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 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 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 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 9125e2f5f2SKatayama Hirofumi MZ static BOOL FindSubProgram(void) 92302356bfSKatayama Hirofumi MZ { 935800ee5eSKatayama Hirofumi MZ GetModuleFileNameW(NULL, s_szSubProgram, _countof(s_szSubProgram)); 945800ee5eSKatayama Hirofumi MZ PathRemoveFileSpecW(s_szSubProgram); 95fccea84dSKatayama Hirofumi MZ PathAppendW(s_szSubProgram, L"shell32_apitest_sub.exe"); 965800ee5eSKatayama Hirofumi MZ 975800ee5eSKatayama Hirofumi MZ if (!PathFileExistsW(s_szSubProgram)) 985800ee5eSKatayama Hirofumi MZ { 995800ee5eSKatayama Hirofumi MZ PathRemoveFileSpecW(s_szSubProgram); 100fccea84dSKatayama Hirofumi MZ PathAppendW(s_szSubProgram, L"testdata\\shell32_apitest_sub.exe"); 1015800ee5eSKatayama Hirofumi MZ 1025800ee5eSKatayama Hirofumi MZ if (!PathFileExistsW(s_szSubProgram)) 1035800ee5eSKatayama Hirofumi MZ return FALSE; 1045800ee5eSKatayama Hirofumi MZ } 1055800ee5eSKatayama Hirofumi MZ 106302356bfSKatayama Hirofumi MZ return TRUE; 107302356bfSKatayama Hirofumi MZ } 108302356bfSKatayama Hirofumi MZ 10925e2f5f2SKatayama Hirofumi MZ static void DoBuildFilesAndDirs(void) 110302356bfSKatayama Hirofumi MZ { 11125e2f5f2SKatayama Hirofumi MZ WCHAR szPath1[MAX_PATH]; 11225e2f5f2SKatayama Hirofumi MZ SHGetSpecialFolderPathW(NULL, szPath1, CSIDL_PERSONAL, FALSE); // My Documents 11325e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1); 11425e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir1, _countof(s_szDir1), szPath1); 1157f766e94SKatayama Hirofumi MZ 11625e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1); 11725e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir1InDir1, _countof(s_szDir1InDir1), szPath1); 11825e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 1197e9cf359SKatayama Hirofumi MZ 12025e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_2); 12125e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szDir2InDir1, _countof(s_szDir2InDir1), szPath1); 12225e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 12325e2f5f2SKatayama Hirofumi MZ 12425e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, DIR_1); 12525e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_1); 12625e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile1InDir1InDir1, _countof(s_szFile1InDir1InDir1), szPath1); 12725e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 12825e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 12925e2f5f2SKatayama Hirofumi MZ 13025e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_1); 13125e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile1InDir1, _countof(s_szFile1InDir1), szPath1); 13225e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 13325e2f5f2SKatayama Hirofumi MZ 13425e2f5f2SKatayama Hirofumi MZ PathAppendW(szPath1, FILE_2); 13525e2f5f2SKatayama Hirofumi MZ StringCchCopyW(s_szFile2InDir1, _countof(s_szFile2InDir1), szPath1); 13625e2f5f2SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 13725e2f5f2SKatayama Hirofumi MZ 13825e2f5f2SKatayama Hirofumi MZ #define TRACE_PATH(path) trace(#path ": %ls\n", path) 13925e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szDir1); 14025e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szDir1InDir1); 14125e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile1InDir1); 14225e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile1InDir1InDir1); 14325e2f5f2SKatayama Hirofumi MZ TRACE_PATH(s_szFile2InDir1); 14425e2f5f2SKatayama Hirofumi MZ #undef TRACE_PATH 14525e2f5f2SKatayama Hirofumi MZ 14625e2f5f2SKatayama Hirofumi MZ DoDeleteFilesAndDirs(); 14725e2f5f2SKatayama Hirofumi MZ 14825e2f5f2SKatayama Hirofumi MZ ::CreateDirectoryW(s_szDir1, NULL); 14925e2f5f2SKatayama Hirofumi MZ ok_int(!!PathIsDirectoryW(s_szDir1), TRUE); 15025e2f5f2SKatayama Hirofumi MZ 15125e2f5f2SKatayama Hirofumi MZ DoDeleteDirectory(s_szDir1InDir1); 15225e2f5f2SKatayama Hirofumi MZ ok_int(!PathIsDirectoryW(s_szDir1InDir1), TRUE); 1537e9cf359SKatayama Hirofumi MZ } 1547e9cf359SKatayama Hirofumi MZ 15525e2f5f2SKatayama Hirofumi MZ static void DoTestEntry(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) 1567f766e94SKatayama Hirofumi MZ { 15725e2f5f2SKatayama Hirofumi MZ WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH]; 15825e2f5f2SKatayama Hirofumi MZ 15925e2f5f2SKatayama Hirofumi MZ szPath1[0] = szPath2[0] = 0; 16025e2f5f2SKatayama Hirofumi MZ SHGetPathFromIDListW(pidl1, szPath1); 16125e2f5f2SKatayama Hirofumi MZ SHGetPathFromIDListW(pidl2, szPath2); 16225e2f5f2SKatayama Hirofumi MZ 16325e2f5f2SKatayama Hirofumi MZ trace("(0x%lX, '%ls', '%ls')\n", lEvent, szPath1, szPath2); 16425e2f5f2SKatayama Hirofumi MZ 16525e2f5f2SKatayama Hirofumi MZ if (lEvent == SHCNE_UPDATEDIR) 16625e2f5f2SKatayama Hirofumi MZ { 16725e2f5f2SKatayama Hirofumi MZ trace("Got SHCNE_UPDATEDIR\n"); 16825e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = TRUE; 169fe397602SKatayama Hirofumi MZ return; 170fe397602SKatayama Hirofumi MZ } 171fe397602SKatayama Hirofumi MZ 17225e2f5f2SKatayama Hirofumi MZ INT iEventType = GetEventType(lEvent); 17325e2f5f2SKatayama Hirofumi MZ if (iEventType < 0) 17425e2f5f2SKatayama Hirofumi MZ return; 17525e2f5f2SKatayama Hirofumi MZ 17625e2f5f2SKatayama Hirofumi MZ assert(iEventType < MAX_EVENT_TYPE); 17725e2f5f2SKatayama Hirofumi MZ 17825e2f5f2SKatayama Hirofumi MZ INT i = 0; 17925e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, L"") == 0) << iEventType; 18025e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szDir1) == 0) << iEventType; 18125e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szDir2InDir1) == 0) << iEventType; 18225e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile1InDir1) == 0) << iEventType; 18325e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile2InDir1) == 0) << iEventType; 18425e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath1, s_szFile1InDir1InDir1) == 0) << iEventType; 18525e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, L"") == 0) << iEventType; 18625e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szDir1) == 0) << iEventType; 18725e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szDir2InDir1) == 0) << iEventType; 18825e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile1InDir1) == 0) << iEventType; 18925e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile2InDir1) == 0) << iEventType; 19025e2f5f2SKatayama Hirofumi MZ s_abChecks[i++] |= (lstrcmpiW(szPath2, s_szFile1InDir1InDir1) == 0) << iEventType; 19125e2f5f2SKatayama Hirofumi MZ assert(i == NUM_CHECKS); 19225e2f5f2SKatayama Hirofumi MZ } 19325e2f5f2SKatayama Hirofumi MZ 19425e2f5f2SKatayama Hirofumi MZ static LPCSTR StringFromChecks(void) 1957f766e94SKatayama Hirofumi MZ { 19625e2f5f2SKatayama Hirofumi MZ static char s_sz[2 * NUM_CHECKS + 1]; 19725e2f5f2SKatayama Hirofumi MZ 19825e2f5f2SKatayama Hirofumi MZ char *pch = s_sz; 19925e2f5f2SKatayama Hirofumi MZ for (INT i = 0; i < NUM_CHECKS; ++i) 20025e2f5f2SKatayama Hirofumi MZ { 20125e2f5f2SKatayama Hirofumi MZ WCHAR sz[3]; 20225e2f5f2SKatayama Hirofumi MZ StringCchPrintfW(sz, _countof(sz), L"%02X", s_abChecks[i]); 20325e2f5f2SKatayama Hirofumi MZ *pch++ = sz[0]; 20425e2f5f2SKatayama Hirofumi MZ *pch++ = sz[1]; 20525e2f5f2SKatayama Hirofumi MZ } 20625e2f5f2SKatayama Hirofumi MZ 20725e2f5f2SKatayama Hirofumi MZ assert((pch - s_sz) + 1 == sizeof(s_sz)); 20825e2f5f2SKatayama Hirofumi MZ 20925e2f5f2SKatayama Hirofumi MZ *pch = 0; 21025e2f5f2SKatayama Hirofumi MZ return s_sz; 21125e2f5f2SKatayama Hirofumi MZ } 21225e2f5f2SKatayama Hirofumi MZ 21325e2f5f2SKatayama Hirofumi MZ struct TEST_ANSWER 21425e2f5f2SKatayama Hirofumi MZ { 21525e2f5f2SKatayama Hirofumi MZ INT lineno; 21625e2f5f2SKatayama Hirofumi MZ LPCSTR answer; 21725e2f5f2SKatayama Hirofumi MZ }; 21825e2f5f2SKatayama Hirofumi MZ 21925e2f5f2SKatayama Hirofumi MZ static void DoStepCheck(INT iStage, INT iStep, LPCSTR checks) 22025e2f5f2SKatayama Hirofumi MZ { 22125e2f5f2SKatayama Hirofumi MZ assert(0 <= iStep); 22225e2f5f2SKatayama Hirofumi MZ assert(iStep < NUM_STEP); 22325e2f5f2SKatayama Hirofumi MZ 22425e2f5f2SKatayama Hirofumi MZ assert(0 <= iStage); 22525e2f5f2SKatayama Hirofumi MZ assert(iStage < NUM_STAGE); 22625e2f5f2SKatayama Hirofumi MZ 22725e2f5f2SKatayama Hirofumi MZ if (s_bGotUpdateDir) 22825e2f5f2SKatayama Hirofumi MZ { 22925e2f5f2SKatayama Hirofumi MZ ok_int(TRUE, TRUE); 230fe397602SKatayama Hirofumi MZ return; 231fe397602SKatayama Hirofumi MZ } 232fe397602SKatayama Hirofumi MZ 23325e2f5f2SKatayama Hirofumi MZ LPCSTR answer = NULL; 23425e2f5f2SKatayama Hirofumi MZ INT lineno; 23525e2f5f2SKatayama Hirofumi MZ switch (iStage) 236fe397602SKatayama Hirofumi MZ { 23725e2f5f2SKatayama Hirofumi MZ case 0: 23825e2f5f2SKatayama Hirofumi MZ case 1: 239*8337df2bSKatayama Hirofumi MZ case 3: 240*8337df2bSKatayama Hirofumi MZ case 6: 241*8337df2bSKatayama Hirofumi MZ case 9: 2427e9cf359SKatayama Hirofumi MZ { 24325e2f5f2SKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] = 24425e2f5f2SKatayama Hirofumi MZ { 24525e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000010000010000000000" }, // 0 24625e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000040000000000000400" }, // 1 24725e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000200020000000000" }, // 2 24825e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000080000000000" }, // 3 24925e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000001010000000000" }, // 4 25025e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000002020000000000" }, // 5 25125e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000000020000000" }, // 6 25225e2f5f2SKatayama Hirofumi MZ { __LINE__, "000010000000100000000000" }, // 7 25325e2f5f2SKatayama Hirofumi MZ }; 25425e2f5f2SKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP); 25525e2f5f2SKatayama Hirofumi MZ lineno = c_answers[iStep].lineno; 25625e2f5f2SKatayama Hirofumi MZ answer = c_answers[iStep].answer; 25725e2f5f2SKatayama Hirofumi MZ break; 25825e2f5f2SKatayama Hirofumi MZ } 25925e2f5f2SKatayama Hirofumi MZ case 2: 260*8337df2bSKatayama Hirofumi MZ case 4: 261*8337df2bSKatayama Hirofumi MZ case 5: 262*8337df2bSKatayama Hirofumi MZ case 7: 263*8337df2bSKatayama Hirofumi MZ { 264*8337df2bSKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] = 265*8337df2bSKatayama Hirofumi MZ { 266*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 0 267*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 1 268*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 2 269*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 3 270*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 4 271*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 5 272*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 6 273*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000000000000000000" }, // 7 274*8337df2bSKatayama Hirofumi MZ }; 275*8337df2bSKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP); 276*8337df2bSKatayama Hirofumi MZ lineno = c_answers[iStep].lineno; 277*8337df2bSKatayama Hirofumi MZ answer = c_answers[iStep].answer; 278*8337df2bSKatayama Hirofumi MZ break; 279*8337df2bSKatayama Hirofumi MZ } 280*8337df2bSKatayama Hirofumi MZ case 8: 28125e2f5f2SKatayama Hirofumi MZ { 28225e2f5f2SKatayama Hirofumi MZ static const TEST_ANSWER c_answers[] = 28325e2f5f2SKatayama Hirofumi MZ { 28425e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000010000010000000000" }, // 0 28525e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000040000000000000400" }, // 1 28625e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000200020000000000" }, // 2 28725e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000080000000000" }, // 3 288*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000001010000000000" }, // 4 // Recursive case 289*8337df2bSKatayama Hirofumi MZ { __LINE__, "000000000002020000000000" }, // 5 // Recursive case 29025e2f5f2SKatayama Hirofumi MZ { __LINE__, "000000000000000020000000" }, // 6 29125e2f5f2SKatayama Hirofumi MZ { __LINE__, "000010000000100000000000" }, // 7 29225e2f5f2SKatayama Hirofumi MZ }; 29325e2f5f2SKatayama Hirofumi MZ C_ASSERT(_countof(c_answers) == NUM_STEP); 29425e2f5f2SKatayama Hirofumi MZ lineno = c_answers[iStep].lineno; 29525e2f5f2SKatayama Hirofumi MZ answer = c_answers[iStep].answer; 29625e2f5f2SKatayama Hirofumi MZ if (iStep == 4 || iStep == 5) // Recursive cases 29725e2f5f2SKatayama Hirofumi MZ { 29825e2f5f2SKatayama Hirofumi MZ if (lstrcmpA(checks, "000000000000000000000000") == 0) 299*8337df2bSKatayama Hirofumi MZ { 300*8337df2bSKatayama Hirofumi MZ trace("Warning! Recursive cases...\n"); 30125e2f5f2SKatayama Hirofumi MZ answer = "000000000000000000000000"; 30225e2f5f2SKatayama Hirofumi MZ } 30325e2f5f2SKatayama Hirofumi MZ } 30425e2f5f2SKatayama Hirofumi MZ break; 30525e2f5f2SKatayama Hirofumi MZ } 30625e2f5f2SKatayama Hirofumi MZ default: 30725e2f5f2SKatayama Hirofumi MZ { 30825e2f5f2SKatayama Hirofumi MZ assert(0); 30925e2f5f2SKatayama Hirofumi MZ break; 31025e2f5f2SKatayama Hirofumi MZ } 31125e2f5f2SKatayama Hirofumi MZ } 3127e9cf359SKatayama Hirofumi MZ 31325e2f5f2SKatayama Hirofumi MZ ok(lstrcmpA(checks, answer) == 0, 31425e2f5f2SKatayama Hirofumi MZ "Line %d: '%s' vs '%s' at Stage %d, Step %d\n", lineno, checks, answer, iStage, iStep); 31525e2f5f2SKatayama Hirofumi MZ } 3167e9cf359SKatayama Hirofumi MZ 31725e2f5f2SKatayama Hirofumi MZ static DWORD WINAPI StageThreadFunc(LPVOID arg) 31825e2f5f2SKatayama Hirofumi MZ { 31925e2f5f2SKatayama Hirofumi MZ BOOL ret; 3207e9cf359SKatayama Hirofumi MZ 32125e2f5f2SKatayama Hirofumi MZ trace("Stage %d\n", s_iStage); 3227e9cf359SKatayama Hirofumi MZ 32325e2f5f2SKatayama Hirofumi MZ // 0: Create file1 in dir1 32425e2f5f2SKatayama Hirofumi MZ s_iStep = 0; 32525e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 326*8337df2bSKatayama Hirofumi MZ SHChangeNotify(0, SHCNF_PATHW | SHCNF_FLUSH, NULL, NULL); 32725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 32825e2f5f2SKatayama Hirofumi MZ ret = DoCreateFile(s_szFile1InDir1); 32925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 330d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1, 0); 33125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 33225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 3337e9cf359SKatayama Hirofumi MZ 33425e2f5f2SKatayama Hirofumi MZ // 1: Rename file1 as file2 in dir1 33525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 33625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 33725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 33825e2f5f2SKatayama Hirofumi MZ ret = MoveFileW(s_szFile1InDir1, s_szFile2InDir1); 33925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 340d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1, s_szFile2InDir1); 34125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 34225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 3437e9cf359SKatayama Hirofumi MZ 34425e2f5f2SKatayama Hirofumi MZ // 2: Delete file2 in dir1 34525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 34625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 34725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 34825e2f5f2SKatayama Hirofumi MZ ret = DeleteFileW(s_szFile2InDir1); 34925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 350d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile2InDir1, NULL); 35125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 35225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 3537e9cf359SKatayama Hirofumi MZ 35425e2f5f2SKatayama Hirofumi MZ // 3: Create dir1 in dir1 35525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 35625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 35725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 35825e2f5f2SKatayama Hirofumi MZ ret = CreateDirectoryExW(s_szDir1, s_szDir1InDir1, NULL); 35925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 360d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW | SHCNF_FLUSH, s_szDir1InDir1, NULL); 36125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 36225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 3637e9cf359SKatayama Hirofumi MZ 36425e2f5f2SKatayama Hirofumi MZ // 4: Create file1 in dir1 in dir1 36525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 36625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 36725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 36825e2f5f2SKatayama Hirofumi MZ ret = DoCreateFile(s_szFile1InDir1InDir1); 36925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 370d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1InDir1, NULL); 37125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 37225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 3737e9cf359SKatayama Hirofumi MZ 37425e2f5f2SKatayama Hirofumi MZ // 5: Delete file1 in dir1 in dir1 37525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 37625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 37725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 37825e2f5f2SKatayama Hirofumi MZ ret = DeleteFileW(s_szFile1InDir1InDir1); 37925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 380d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW | SHCNF_FLUSH, s_szFile1InDir1InDir1, NULL); 38125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 38225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 38325e2f5f2SKatayama Hirofumi MZ 38425e2f5f2SKatayama Hirofumi MZ // 6: Rename dir1 as dir2 in dir1 38525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 38625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 38725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 38825e2f5f2SKatayama Hirofumi MZ ret = ::MoveFileW(s_szDir1InDir1, s_szDir2InDir1); 38925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 390d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATHW | SHCNF_FLUSH, s_szDir1InDir1, s_szDir2InDir1); 39125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 39225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 39325e2f5f2SKatayama Hirofumi MZ 39425e2f5f2SKatayama Hirofumi MZ // 7: Remove dir2 in dir1 39525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 39625e2f5f2SKatayama Hirofumi MZ trace("Step %d\n", s_iStep); 39725e2f5f2SKatayama Hirofumi MZ ZeroMemory(s_abChecks, sizeof(s_abChecks)); 39825e2f5f2SKatayama Hirofumi MZ ret = RemoveDirectoryW(s_szDir2InDir1); 39925e2f5f2SKatayama Hirofumi MZ ok_int(ret, TRUE); 400d23573beSKatayama Hirofumi MZ SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW | SHCNF_FLUSH, s_szDir2InDir1, NULL); 40125e2f5f2SKatayama Hirofumi MZ ::Sleep(INTERVAL); 40225e2f5f2SKatayama Hirofumi MZ DoStepCheck(s_iStage, s_iStep, StringFromChecks()); 40325e2f5f2SKatayama Hirofumi MZ 40425e2f5f2SKatayama Hirofumi MZ // 8: Finish 40525e2f5f2SKatayama Hirofumi MZ ++s_iStep; 40625e2f5f2SKatayama Hirofumi MZ assert(s_iStep == NUM_STEP); 40725e2f5f2SKatayama Hirofumi MZ C_ASSERT(NUM_STEP == 8); 40825e2f5f2SKatayama Hirofumi MZ if (s_iStage + 1 < NUM_STAGE) 40925e2f5f2SKatayama Hirofumi MZ { 41025e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hSubWnd, WM_COMMAND, IDRETRY, 0); // Next stage 41125e2f5f2SKatayama Hirofumi MZ } 41225e2f5f2SKatayama Hirofumi MZ else 41325e2f5f2SKatayama Hirofumi MZ { 41425e2f5f2SKatayama Hirofumi MZ // Finish 41525e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hSubWnd, WM_COMMAND, IDNO, 0); 41625e2f5f2SKatayama Hirofumi MZ ::PostMessage(s_hMainWnd, WM_COMMAND, IDNO, 0); 41725e2f5f2SKatayama Hirofumi MZ } 41825e2f5f2SKatayama Hirofumi MZ 41925e2f5f2SKatayama Hirofumi MZ s_iStep = -1; 4207e9cf359SKatayama Hirofumi MZ 4217e9cf359SKatayama Hirofumi MZ return 0; 4225800ee5eSKatayama Hirofumi MZ } 4235800ee5eSKatayama Hirofumi MZ 42425e2f5f2SKatayama Hirofumi MZ // WM_COPYDATA 42525e2f5f2SKatayama Hirofumi MZ static BOOL OnCopyData(HWND hwnd, HWND hwndSender, COPYDATASTRUCT *pCopyData) 4265800ee5eSKatayama Hirofumi MZ { 42725e2f5f2SKatayama Hirofumi MZ if (pCopyData->dwData != 0xBEEFCAFE) 42825e2f5f2SKatayama Hirofumi MZ return FALSE; 4297e9cf359SKatayama Hirofumi MZ 43025e2f5f2SKatayama Hirofumi MZ LPBYTE pbData = (LPBYTE)pCopyData->lpData; 43125e2f5f2SKatayama Hirofumi MZ LPBYTE pb = pbData; 4327e9cf359SKatayama Hirofumi MZ 43325e2f5f2SKatayama Hirofumi MZ LONG cbTotal = pCopyData->cbData; 43425e2f5f2SKatayama Hirofumi MZ assert(cbTotal >= LONG(sizeof(LONG) + sizeof(DWORD) + sizeof(DWORD))); 43525e2f5f2SKatayama Hirofumi MZ 43625e2f5f2SKatayama Hirofumi MZ LONG lEvent = *(LONG*)pb; 43725e2f5f2SKatayama Hirofumi MZ pb += sizeof(lEvent); 43825e2f5f2SKatayama Hirofumi MZ 43925e2f5f2SKatayama Hirofumi MZ DWORD cbPidl1 = *(DWORD*)pb; 44025e2f5f2SKatayama Hirofumi MZ pb += sizeof(cbPidl1); 44125e2f5f2SKatayama Hirofumi MZ 44225e2f5f2SKatayama Hirofumi MZ DWORD cbPidl2 = *(DWORD*)pb; 44325e2f5f2SKatayama Hirofumi MZ pb += sizeof(cbPidl2); 44425e2f5f2SKatayama Hirofumi MZ 44525e2f5f2SKatayama Hirofumi MZ LPITEMIDLIST pidl1 = NULL; 44625e2f5f2SKatayama Hirofumi MZ if (cbPidl1) 44725e2f5f2SKatayama Hirofumi MZ { 44825e2f5f2SKatayama Hirofumi MZ pidl1 = (LPITEMIDLIST)CoTaskMemAlloc(cbPidl1); 44925e2f5f2SKatayama Hirofumi MZ CopyMemory(pidl1, pb, cbPidl1); 45025e2f5f2SKatayama Hirofumi MZ pb += cbPidl1; 45125e2f5f2SKatayama Hirofumi MZ } 45225e2f5f2SKatayama Hirofumi MZ 45325e2f5f2SKatayama Hirofumi MZ LPITEMIDLIST pidl2 = NULL; 45425e2f5f2SKatayama Hirofumi MZ if (cbPidl2) 45525e2f5f2SKatayama Hirofumi MZ { 45625e2f5f2SKatayama Hirofumi MZ pidl2 = (LPITEMIDLIST)CoTaskMemAlloc(cbPidl2); 45725e2f5f2SKatayama Hirofumi MZ CopyMemory(pidl2, pb, cbPidl2); 45825e2f5f2SKatayama Hirofumi MZ pb += cbPidl2; 45925e2f5f2SKatayama Hirofumi MZ } 46025e2f5f2SKatayama Hirofumi MZ 46125e2f5f2SKatayama Hirofumi MZ assert((pb - pbData) == cbTotal); 46225e2f5f2SKatayama Hirofumi MZ 46325e2f5f2SKatayama Hirofumi MZ DoTestEntry(lEvent, pidl1, pidl2); 46425e2f5f2SKatayama Hirofumi MZ 46525e2f5f2SKatayama Hirofumi MZ CoTaskMemFree(pidl1); 46625e2f5f2SKatayama Hirofumi MZ CoTaskMemFree(pidl2); 46725e2f5f2SKatayama Hirofumi MZ 46825e2f5f2SKatayama Hirofumi MZ return TRUE; 46925e2f5f2SKatayama Hirofumi MZ } 47025e2f5f2SKatayama Hirofumi MZ 47125e2f5f2SKatayama Hirofumi MZ static LRESULT CALLBACK 47225e2f5f2SKatayama Hirofumi MZ MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 47325e2f5f2SKatayama Hirofumi MZ { 47425e2f5f2SKatayama Hirofumi MZ switch (uMsg) 47525e2f5f2SKatayama Hirofumi MZ { 47625e2f5f2SKatayama Hirofumi MZ case WM_CREATE: 47725e2f5f2SKatayama Hirofumi MZ s_hMainWnd = hwnd; 47825e2f5f2SKatayama Hirofumi MZ return 0; 47925e2f5f2SKatayama Hirofumi MZ 48025e2f5f2SKatayama Hirofumi MZ case WM_COMMAND: 48125e2f5f2SKatayama Hirofumi MZ switch (LOWORD(wParam)) 48225e2f5f2SKatayama Hirofumi MZ { 48325e2f5f2SKatayama Hirofumi MZ case IDYES: // Start testing 48425e2f5f2SKatayama Hirofumi MZ { 48525e2f5f2SKatayama Hirofumi MZ s_iStage = 0; 48625e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = FALSE; 48725e2f5f2SKatayama Hirofumi MZ s_hThread = ::CreateThread(NULL, 0, StageThreadFunc, hwnd, 0, NULL); 48825e2f5f2SKatayama Hirofumi MZ if (!s_hThread) 48925e2f5f2SKatayama Hirofumi MZ { 49025e2f5f2SKatayama Hirofumi MZ skip("!s_hThread\n"); 49125e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd); 49225e2f5f2SKatayama Hirofumi MZ } 49325e2f5f2SKatayama Hirofumi MZ break; 49425e2f5f2SKatayama Hirofumi MZ } 49525e2f5f2SKatayama Hirofumi MZ case IDRETRY: // New stage 49625e2f5f2SKatayama Hirofumi MZ { 49725e2f5f2SKatayama Hirofumi MZ ::CloseHandle(s_hThread); 49825e2f5f2SKatayama Hirofumi MZ ++s_iStage; 49925e2f5f2SKatayama Hirofumi MZ s_bGotUpdateDir = FALSE; 50025e2f5f2SKatayama Hirofumi MZ s_hThread = ::CreateThread(NULL, 0, StageThreadFunc, hwnd, 0, NULL); 50125e2f5f2SKatayama Hirofumi MZ if (!s_hThread) 50225e2f5f2SKatayama Hirofumi MZ { 50325e2f5f2SKatayama Hirofumi MZ skip("!s_hThread\n"); 50425e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd); 50525e2f5f2SKatayama Hirofumi MZ } 50625e2f5f2SKatayama Hirofumi MZ break; 50725e2f5f2SKatayama Hirofumi MZ } 50825e2f5f2SKatayama Hirofumi MZ case IDNO: // Quit 50925e2f5f2SKatayama Hirofumi MZ { 51025e2f5f2SKatayama Hirofumi MZ s_iStage = -1; 51125e2f5f2SKatayama Hirofumi MZ DestroyWindow(hwnd); 51225e2f5f2SKatayama Hirofumi MZ break; 51325e2f5f2SKatayama Hirofumi MZ } 51425e2f5f2SKatayama Hirofumi MZ } 51525e2f5f2SKatayama Hirofumi MZ break; 51625e2f5f2SKatayama Hirofumi MZ 51725e2f5f2SKatayama Hirofumi MZ case WM_COPYDATA: 51825e2f5f2SKatayama Hirofumi MZ if (s_iStage < 0 || s_iStep < 0) 51925e2f5f2SKatayama Hirofumi MZ break; 52025e2f5f2SKatayama Hirofumi MZ 52125e2f5f2SKatayama Hirofumi MZ OnCopyData(hwnd, (HWND)wParam, (COPYDATASTRUCT*)lParam); 52225e2f5f2SKatayama Hirofumi MZ break; 52325e2f5f2SKatayama Hirofumi MZ 52425e2f5f2SKatayama Hirofumi MZ case WM_DESTROY: 52525e2f5f2SKatayama Hirofumi MZ ::PostQuitMessage(0); 52625e2f5f2SKatayama Hirofumi MZ break; 52725e2f5f2SKatayama Hirofumi MZ 52825e2f5f2SKatayama Hirofumi MZ default: 52925e2f5f2SKatayama Hirofumi MZ return ::DefWindowProcW(hwnd, uMsg, wParam, lParam); 53025e2f5f2SKatayama Hirofumi MZ } 53125e2f5f2SKatayama Hirofumi MZ return 0; 53225e2f5f2SKatayama Hirofumi MZ } 53325e2f5f2SKatayama Hirofumi MZ 53425e2f5f2SKatayama Hirofumi MZ static BOOL TEST_Init(void) 53525e2f5f2SKatayama Hirofumi MZ { 53625e2f5f2SKatayama Hirofumi MZ if (!FindSubProgram()) 5375800ee5eSKatayama Hirofumi MZ { 538fccea84dSKatayama Hirofumi MZ skip("shell32_apitest_sub.exe not found\n"); 53925e2f5f2SKatayama Hirofumi MZ return FALSE; 5405800ee5eSKatayama Hirofumi MZ } 5415800ee5eSKatayama Hirofumi MZ 54225e2f5f2SKatayama Hirofumi MZ // close the SUB_CLASSNAME windows 54325e2f5f2SKatayama Hirofumi MZ DoWaitForWindow(SUB_CLASSNAME, SUB_CLASSNAME, TRUE, TRUE); 54425e2f5f2SKatayama Hirofumi MZ 54525e2f5f2SKatayama Hirofumi MZ // Execute sub program 54625e2f5f2SKatayama Hirofumi MZ HINSTANCE hinst = ShellExecuteW(NULL, NULL, s_szSubProgram, L"---", NULL, SW_SHOWNORMAL); 54725e2f5f2SKatayama Hirofumi MZ if ((INT_PTR)hinst <= 32) 5487e9cf359SKatayama Hirofumi MZ { 54925e2f5f2SKatayama Hirofumi MZ skip("Unable to run shell32_apitest_sub.exe.\n"); 55025e2f5f2SKatayama Hirofumi MZ return FALSE; 55125e2f5f2SKatayama Hirofumi MZ } 55225e2f5f2SKatayama Hirofumi MZ 55325e2f5f2SKatayama Hirofumi MZ // prepare for files and dirs 55425e2f5f2SKatayama Hirofumi MZ DoBuildFilesAndDirs(); 55525e2f5f2SKatayama Hirofumi MZ 55625e2f5f2SKatayama Hirofumi MZ // Register main window 55725e2f5f2SKatayama Hirofumi MZ WNDCLASSW wc = { 0, MainWndProc }; 55825e2f5f2SKatayama Hirofumi MZ wc.hInstance = GetModuleHandleW(NULL); 55925e2f5f2SKatayama Hirofumi MZ wc.hIcon = LoadIconW(NULL, IDI_APPLICATION); 56025e2f5f2SKatayama Hirofumi MZ wc.hCursor = LoadCursorW(NULL, IDC_ARROW); 56125e2f5f2SKatayama Hirofumi MZ wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); 56225e2f5f2SKatayama Hirofumi MZ wc.lpszClassName = MAIN_CLASSNAME; 56325e2f5f2SKatayama Hirofumi MZ if (!RegisterClassW(&wc)) 56425e2f5f2SKatayama Hirofumi MZ { 56525e2f5f2SKatayama Hirofumi MZ skip("RegisterClassW failed\n"); 56625e2f5f2SKatayama Hirofumi MZ return FALSE; 56725e2f5f2SKatayama Hirofumi MZ } 56825e2f5f2SKatayama Hirofumi MZ 56925e2f5f2SKatayama Hirofumi MZ // Create main window 57025e2f5f2SKatayama Hirofumi MZ HWND hwnd = CreateWindowW(MAIN_CLASSNAME, MAIN_CLASSNAME, WS_OVERLAPPEDWINDOW, 57125e2f5f2SKatayama Hirofumi MZ CW_USEDEFAULT, CW_USEDEFAULT, 400, 100, 57225e2f5f2SKatayama Hirofumi MZ NULL, NULL, GetModuleHandleW(NULL), NULL); 57325e2f5f2SKatayama Hirofumi MZ if (!hwnd) 57425e2f5f2SKatayama Hirofumi MZ { 57525e2f5f2SKatayama Hirofumi MZ skip("CreateWindowW failed\n"); 57625e2f5f2SKatayama Hirofumi MZ return FALSE; 57725e2f5f2SKatayama Hirofumi MZ } 57825e2f5f2SKatayama Hirofumi MZ ::ShowWindow(hwnd, SW_SHOWNORMAL); 57925e2f5f2SKatayama Hirofumi MZ ::UpdateWindow(hwnd); 58025e2f5f2SKatayama Hirofumi MZ 58125e2f5f2SKatayama Hirofumi MZ // Find sub-window 58225e2f5f2SKatayama Hirofumi MZ s_hSubWnd = DoWaitForWindow(SUB_CLASSNAME, SUB_CLASSNAME, FALSE, FALSE); 58325e2f5f2SKatayama Hirofumi MZ if (!s_hSubWnd) 58425e2f5f2SKatayama Hirofumi MZ { 58525e2f5f2SKatayama Hirofumi MZ skip("Unable to find sub-program window.\n"); 58625e2f5f2SKatayama Hirofumi MZ return FALSE; 58725e2f5f2SKatayama Hirofumi MZ } 58825e2f5f2SKatayama Hirofumi MZ 58925e2f5f2SKatayama Hirofumi MZ // Start testing 59025e2f5f2SKatayama Hirofumi MZ SendMessageW(s_hSubWnd, WM_COMMAND, IDYES, 0); 59125e2f5f2SKatayama Hirofumi MZ 59225e2f5f2SKatayama Hirofumi MZ return TRUE; 59325e2f5f2SKatayama Hirofumi MZ } 59425e2f5f2SKatayama Hirofumi MZ 59525e2f5f2SKatayama Hirofumi MZ static void TEST_Main(void) 59625e2f5f2SKatayama Hirofumi MZ { 59725e2f5f2SKatayama Hirofumi MZ if (!TEST_Init()) 59825e2f5f2SKatayama Hirofumi MZ { 59925e2f5f2SKatayama Hirofumi MZ skip("Unable to start testing.\n"); 60025e2f5f2SKatayama Hirofumi MZ TEST_Quit(); 6017e9cf359SKatayama Hirofumi MZ return; 6027e9cf359SKatayama Hirofumi MZ } 6037e9cf359SKatayama Hirofumi MZ 60425e2f5f2SKatayama Hirofumi MZ // Message loop 60525e2f5f2SKatayama Hirofumi MZ MSG msg; 60625e2f5f2SKatayama Hirofumi MZ while (GetMessageW(&msg, NULL, 0, 0)) 60725e2f5f2SKatayama Hirofumi MZ { 60825e2f5f2SKatayama Hirofumi MZ ::TranslateMessage(&msg); 60925e2f5f2SKatayama Hirofumi MZ ::DispatchMessage(&msg); 61025e2f5f2SKatayama Hirofumi MZ } 6117e9cf359SKatayama Hirofumi MZ 61225e2f5f2SKatayama Hirofumi MZ TEST_Quit(); 61325e2f5f2SKatayama Hirofumi MZ } 61425e2f5f2SKatayama Hirofumi MZ 61525e2f5f2SKatayama Hirofumi MZ START_TEST(SHChangeNotify) 61625e2f5f2SKatayama Hirofumi MZ { 61725e2f5f2SKatayama Hirofumi MZ trace("Please close all Explorer windows before testing.\n"); 61825e2f5f2SKatayama Hirofumi MZ trace("Please don't operate your PC while testing.\n"); 61925e2f5f2SKatayama Hirofumi MZ 62025e2f5f2SKatayama Hirofumi MZ DWORD dwOldTick = GetTickCount(); 62125e2f5f2SKatayama Hirofumi MZ TEST_Main(); 6227e9cf359SKatayama Hirofumi MZ DWORD dwNewTick = GetTickCount(); 62325e2f5f2SKatayama Hirofumi MZ 6247e9cf359SKatayama Hirofumi MZ DWORD dwTick = dwNewTick - dwOldTick; 6257e9cf359SKatayama Hirofumi MZ trace("SHChangeNotify: Total %lu.%lu sec\n", (dwTick / 1000), (dwTick / 100 % 10)); 626fe397602SKatayama Hirofumi MZ } 627