diff --git a/dlls/user32/tests/listbox.c b/dlls/user32/tests/listbox.c index 0ca9b8db3b9..90f3e2cbe4b 100644 --- a/dlls/user32/tests/listbox.c +++ b/dlls/user32/tests/listbox.c @@ -898,6 +898,408 @@ static void test_listbox_LB_DIR() DestroyWindow(hList); } +HWND g_listBox; +HWND g_label; + +#define ID_TEST_LABEL 1001 +#define ID_TEST_LISTBOX 1002 + +static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs) +{ + g_label = CreateWindow( + "Static", + "Contents of static control before DlgDirList.", + WS_CHILD | WS_VISIBLE, + 10, 10, 512, 32, + hwnd, (HMENU)ID_TEST_LABEL, NULL, 0); + if (!g_label) return FALSE; + g_listBox = CreateWindow( + "ListBox", + "DlgDirList test", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL, + 10, 60, 256, 256, + hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0); + if (!g_listBox) return FALSE; + + return TRUE; +} + +static LRESULT CALLBACK listbox_container_window_procA ( + HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + + switch (uiMsg) { + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_CREATE: + result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam) + ? 0 : (LRESULT)-1; + break; + default: + result = DefWindowProcA (hwnd, uiMsg, wParam, lParam); + break; + } + return result; +} + +static BOOL RegisterListboxWindowClass(HINSTANCE hInst) +{ + WNDCLASSA cls; + + cls.style = 0; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = hInst; + cls.hIcon = NULL; + cls.hCursor = LoadCursorA (NULL, IDC_ARROW); + cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + cls.lpszMenuName = NULL; + cls.lpfnWndProc = listbox_container_window_procA; + cls.lpszClassName = "ListboxContainerClass"; + if (!RegisterClassA (&cls)) return FALSE; + + return TRUE; +} + +static void test_listbox_dlgdir(void) +{ + HINSTANCE hInst; + HWND hWnd; + int res, itemCount; + int itemCount_justFiles; + int itemCount_justDrives; + int i; + char pathBuffer[MAX_PATH]; + char itemBuffer[MAX_PATH]; + char tempBuffer[MAX_PATH]; + char * p; + char driveletter; + + /* NOTE: for this test to succeed, there must be no subdirectories + under the current directory. In addition, there must be at least + one file that fits the wildcard w*.c . Normally, the test + directory itself satisfies both conditions. + */ + + hInst = GetModuleHandleA(0); + if (!RegisterListboxWindowClass(hInst)) assert(0); + hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInst, 0); + assert(hWnd); + + /* Test for standard usage */ + + /* The following should be overwritten by the directory path */ + SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents"); + + /* This should list all the w*.c files in the test directory + * As of this writing, this includes win.c, winstation.c, wsprintf.c + */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0); + ok (res != 0, "DlgDirList(*.c, 0) failed - 0x%08x\n", GetLastError()); + + /* Path specification gets converted to uppercase */ + ok (!strcmp(pathBuffer, "W*.C"), + "expected conversion to uppercase, got %s\n", pathBuffer); + + /* Loaded path should have overwritten the label text */ + SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer); + trace("Static control after DlgDirList: %s\n", pathBuffer); + ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!"); + + /* There should be some content in the listbox */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n"); + itemCount_justFiles = itemCount; + + /* Every single item in the control should start with a w and end in .c */ + for (i = 0; i < itemCount; i++) { + memset(pathBuffer, 0, MAX_PATH); + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); + p = pathBuffer + strlen(pathBuffer); + ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && + (*(p-1) == 'c' || *(p-1) == 'C') && + (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); + } + + /* Test DDL_DIRECTORY */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DIRECTORY); + ok (res != 0, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError()); + + /* There should be some content in the listbox. In particular, there should + * be exactly one more element than before, since the string "[..]" should + * have been added. + */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount == itemCount_justFiles + 1, + "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected %d\n", + itemCount, itemCount_justFiles + 1); + + /* Every single item in the control should start with a w and end in .c, + * except for the "[..]" string, which should appear exactly as it is. + */ + for (i = 0; i < itemCount; i++) { + memset(pathBuffer, 0, MAX_PATH); + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); + p = pathBuffer + strlen(pathBuffer); + ok( !strcmp(pathBuffer, "[..]") || + ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && + (*(p-1) == 'c' || *(p-1) == 'C') && + (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); + } + + /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DRIVES); + ok (res != 0, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError()); + + /* There should be some content in the listbox. In particular, there should + * be at least one element before, since the string "[-c-]" should + * have been added. Depending on the user setting, more drives might have + * been added. + */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount >= 1, + "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n", + itemCount, 1); + itemCount_justDrives = itemCount; + + /* Every single item in the control should fit the format [-c-] */ + for (i = 0; i < itemCount; i++) { + memset(pathBuffer, 0, MAX_PATH); + driveletter = '\0'; + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); + ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); + ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); + ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); + if (!(driveletter >= 'a' && driveletter <= 'z')) { + /* Correct after invalid entry is found */ + trace("removing count of invalid entry %s\n", pathBuffer); + itemCount_justDrives--; + } + } + + /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DIRECTORY|DDL_DRIVES); + ok (res != 0, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); + + /* There should be some content in the listbox. In particular, there should + * be exactly the number of plain files, plus the number of mapped drives, + * plus one "[..]" + */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount == itemCount_justFiles + itemCount_justDrives + 1, + "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", + itemCount, itemCount_justFiles + itemCount_justDrives + 1); + + /* Every single item in the control should start with a w and end in .c, + * except for the "[..]" string, which should appear exactly as it is, + * and the mapped drives in the format "[-X-]". + */ + for (i = 0; i < itemCount; i++) { + memset(pathBuffer, 0, MAX_PATH); + driveletter = '\0'; + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); + p = pathBuffer + strlen(pathBuffer); + if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { + ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); + } else { + ok( !strcmp(pathBuffer, "[..]") || + ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && + (*(p-1) == 'c' || *(p-1) == 'C') && + (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); + } + } + + /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DIRECTORY|DDL_EXCLUSIVE); + ok (res != 0, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); + + /* There should be exactly one element: "[..]" */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount == 1, + "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", + itemCount, 1); + + memset(pathBuffer, 0, MAX_PATH); + SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer); + ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); + + /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ + strcpy(pathBuffer, "w*.c"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE); + ok (res != 0, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); + + /* There should be no plain files on the listbox */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + ok (itemCount == itemCount_justDrives + 1, + "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", + itemCount, itemCount_justDrives + 1); + + for (i = 0; i < itemCount; i++) { + memset(pathBuffer, 0, MAX_PATH); + driveletter = '\0'; + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); + p = pathBuffer + strlen(pathBuffer); + if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { + ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); + } else { + ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer); + } + } + + /* Now test DlgDirSelectEx() in normal operation */ + /* Fill with everything - drives, directory and all plain files. */ + strcpy(pathBuffer, "*"); + res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, + DDL_DIRECTORY|DDL_DRIVES); + ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); + + SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */ + memset(pathBuffer, 0, MAX_PATH); + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n", + GetLastError()); + ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res); + /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */ + /* + ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer); + */ + /* Test proper drive/dir/file recognition */ + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + for (i = 0; i < itemCount; i++) { + memset(itemBuffer, 0, MAX_PATH); + memset(pathBuffer, 0, MAX_PATH); + memset(tempBuffer, 0, MAX_PATH); + driveletter = '\0'; + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); + res = SendMessage(g_listBox, LB_SETCURSEL, i, 0); + ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i); + if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) { + /* Current item is a drive letter */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); + + /* For drive letters, DlgDirSelectEx tacks on a colon */ + ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', + "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); + } else if (itemBuffer[0] == '[') { + /* Current item is the parent directory */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); + + /* For directories, DlgDirSelectEx tacks on a backslash */ + p = pathBuffer + strlen(pathBuffer); + ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); + + tempBuffer[0] = '['; + strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1); + strcat(tempBuffer, "]"); + ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); + } else { + /* Current item is a plain file */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); + + /* NOTE: WinXP tacks a period on all files that lack an extension. This affects + * for example, "Makefile", which gets reported as "Makefile." + */ + strcpy(tempBuffer, itemBuffer); + if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); + ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); + } + } + + /* Now test DlgDirSelectEx() in abnormal operation */ + /* Fill list with bogus entries, that look somewhat valid */ + SendMessage(g_listBox, LB_RESETCONTENT, 0, 0); + SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]"); + SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil"); + itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0); + for (i = 0; i < itemCount; i++) { + memset(itemBuffer, 0, MAX_PATH); + memset(pathBuffer, 0, MAX_PATH); + memset(tempBuffer, 0, MAX_PATH); + driveletter = '\0'; + SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); + res = SendMessage(g_listBox, LB_SETCURSEL, i, 0); + ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i); + if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) { + /* Current item is a drive letter */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); + + /* For drive letters, DlgDirSelectEx tacks on a colon */ + ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', + "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); + } else if (itemBuffer[0] == '[') { + /* Current item is the parent directory */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); + + /* For directories, DlgDirSelectEx tacks on a backslash */ + p = pathBuffer + strlen(pathBuffer); + ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); + + tempBuffer[0] = '['; + strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1); + strcat(tempBuffer, "]"); + ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); + } else { + /* Current item is a plain file */ + SetLastError(0xdeadbeef); + res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); + ok (GetLastError() == 0xdeadbeef, + "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", + i, GetLastError()); + ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); + + /* NOTE: WinXP and Win98 tack a period on all files that lack an extension. + * This affects for example, "Makefile", which gets reported as "Makefile." + */ + strcpy(tempBuffer, itemBuffer); + if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); + ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); + } + } + DestroyWindow(hWnd); +} + START_TEST(listbox) { const struct listbox_test SS = @@ -975,4 +1377,5 @@ START_TEST(listbox) test_itemfrompoint(); test_listbox_item_data(); test_listbox_LB_DIR(); + test_listbox_dlgdir(); }