Author: cwittich Date: Tue Dec 22 10:35:12 2009 New Revision: 44694
URL: http://svn.reactos.org/svn/reactos?rev=44694&view=rev Log: sync shell32_winetest with wine 1.1.35
Added: trunk/rostests/winetests/shell32/progman_dde.c (with props) Modified: trunk/rostests/winetests/shell32/shell32.rbuild trunk/rostests/winetests/shell32/shelllink.c trunk/rostests/winetests/shell32/shlexec.c trunk/rostests/winetests/shell32/shlfileop.c trunk/rostests/winetests/shell32/shlfolder.c
Added: trunk/rostests/winetests/shell32/progman_dde.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/progman_... ============================================================================== --- trunk/rostests/winetests/shell32/progman_dde.c (added) +++ trunk/rostests/winetests/shell32/progman_dde.c [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -1,0 +1,722 @@ +/* + * Unit test of the Program Manager DDE Interfaces + * + * Copyright 2009 Mikey Alexander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* DDE Program Manager Tests + * - Covers basic CreateGroup, ShowGroup, DeleteGroup, AddItem, and DeleteItem + * functionality + * - Todo: Handle CommonGroupFlag + * Better AddItem Tests (Lots of parameters to test) + * Tests for Invalid Characters in Names / Invalid Parameters + */ + +#include <stdio.h> +#include <wine/test.h> +#include <winbase.h> +#include "dde.h" +#include "ddeml.h" +#include "winuser.h" +#include "shlobj.h" + +/* Timeout on DdeClientTransaction Call */ +#define MS_TIMEOUT_VAL 1000 +/* # of times to poll for window creation */ +#define PDDE_POLL_NUM 150 +/* time to sleep between polls */ +#define PDDE_POLL_TIME 300 + +/* Call Info */ +#define DDE_TEST_MISC 0x00010000 +#define DDE_TEST_CREATEGROUP 0x00020000 +#define DDE_TEST_DELETEGROUP 0x00030000 +#define DDE_TEST_SHOWGROUP 0x00040000 +#define DDE_TEST_ADDITEM 0x00050000 +#define DDE_TEST_DELETEITEM 0x00060000 +#define DDE_TEST_COMPOUND 0x00070000 +#define DDE_TEST_CALLMASK 0x00ff0000 + +#define DDE_TEST_NUMMASK 0x0000ffff + +static HRESULT (WINAPI *pSHGetLocalizedName)(LPCWSTR, LPWSTR, UINT, int *); +static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL); +static BOOL (WINAPI *pReadCabinetState)(CABINETSTATE *, int); + +static void init_function_pointers(void) +{ + HMODULE hmod; + + hmod = GetModuleHandleA("shell32.dll"); + pSHGetLocalizedName = (void*)GetProcAddress(hmod, "SHGetLocalizedName"); + pSHGetSpecialFolderPathA = (void*)GetProcAddress(hmod, "SHGetSpecialFolderPathA"); + pReadCabinetState = (void*)GetProcAddress(hmod, "ReadCabinetState"); + if (!pReadCabinetState) + pReadCabinetState = (void*)GetProcAddress(hmod, (LPSTR)651); +} + +static BOOL use_common(void) +{ + HMODULE hmod; + static BOOL (WINAPI *pIsNTAdmin)(DWORD, LPDWORD); + + /* IsNTAdmin() is available on all platforms. */ + hmod = LoadLibraryA("advpack.dll"); + pIsNTAdmin = (void*)GetProcAddress(hmod, "IsNTAdmin"); + + if (!pIsNTAdmin(0, NULL)) + { + /* We are definitely not an administrator */ + FreeLibrary(hmod); + return FALSE; + } + FreeLibrary(hmod); + + /* If we end up here we are on NT4+ as Win9x and WinMe don't have the + * notion of administrators (as we need it). + */ + + /* As of Vista we should always use the users directory. Tests with the + * real Administrator account on Windows 7 proved this. + * + * FIXME: We need a better way of identifying Vista+ as currently this check + * also covers Wine and we don't know yet which behavior we want to follow. + */ + if (pSHGetLocalizedName) + return FALSE; + + return TRUE; +} + +static char ProgramsDir[MAX_PATH]; + +static char Group1Title[MAX_PATH] = "Group1"; +static char Group2Title[MAX_PATH] = "Group2"; +static char Group3Title[MAX_PATH] = "Group3"; +static char StartupTitle[MAX_PATH] = "Startup"; + +static void init_strings(void) +{ + char startup[MAX_PATH]; + char commonprograms[MAX_PATH]; + char programs[MAX_PATH]; + + CABINETSTATE cs; + + if (pSHGetSpecialFolderPathA) + { + pSHGetSpecialFolderPathA(NULL, programs, CSIDL_PROGRAMS, FALSE); + pSHGetSpecialFolderPathA(NULL, commonprograms, CSIDL_COMMON_PROGRAMS, FALSE); + pSHGetSpecialFolderPathA(NULL, startup, CSIDL_STARTUP, FALSE); + } + else + { + HKEY key; + DWORD size; + LONG res; + + /* Older Win9x and NT4 */ + + RegOpenKeyA(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", &key); + size = sizeof(programs); + RegQueryValueExA(key, "Programs", NULL, NULL, (LPBYTE)&programs, &size); + size = sizeof(startup); + RegQueryValueExA(key, "Startup", NULL, NULL, (LPBYTE)&startup, &size); + RegCloseKey(key); + + RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", &key); + size = sizeof(commonprograms); + res = RegQueryValueExA(key, "Common Programs", NULL, NULL, (LPBYTE)&commonprograms, &size); + RegCloseKey(key); + } + + /* ProgramsDir on Vista+ is always the users one (CSIDL_PROGRAMS). Before Vista + * it depends on whether the user is an administrator (CSIDL_COMMON_PROGRAMS) or + * not (CSIDL_PROGRAMS). + */ + if (use_common()) + lstrcpyA(ProgramsDir, commonprograms); + else + lstrcpyA(ProgramsDir, programs); + + memset(&cs, 0, sizeof(cs)); + pReadCabinetState(&cs, sizeof(cs)); + if (cs.fFullPathTitle == -1) + { + lstrcpyA(Group1Title, ProgramsDir); + lstrcatA(Group1Title, "\Group1"); + lstrcpyA(Group2Title, ProgramsDir); + lstrcatA(Group2Title, "\Group2"); + lstrcpyA(Group3Title, ProgramsDir); + lstrcatA(Group3Title, "\Group3"); + + lstrcpyA(StartupTitle, startup); + } + else + { + /* Vista has the nice habit of displaying the full path in English + * and the short one localized. CSIDL_STARTUP on Vista gives us the + * English version so we have to 'translate' this one. + * + * MSDN claims it should be used for files not folders but this one + * suits our purposes just fine. + */ + if (pSHGetLocalizedName) + { + WCHAR startupW[MAX_PATH]; + WCHAR module[MAX_PATH]; + WCHAR module_expanded[MAX_PATH]; + WCHAR localized[MAX_PATH]; + int id; + + MultiByteToWideChar(CP_ACP, 0, startup, -1, startupW, sizeof(startupW)/sizeof(WCHAR)); + pSHGetLocalizedName(startupW, module, MAX_PATH, &id); + ExpandEnvironmentStringsW(module, module_expanded, MAX_PATH); + LoadStringW(GetModuleHandleW(module_expanded), id, localized, MAX_PATH); + + WideCharToMultiByte(CP_ACP, 0, localized, -1, StartupTitle, sizeof(StartupTitle), NULL, NULL); + } + else + { + lstrcpyA(StartupTitle, (strrchr(startup, '\') + 1)); + } + } +} + +static HDDEDATA CALLBACK DdeCallback(UINT type, UINT format, HCONV hConv, HSZ hsz1, HSZ hsz2, + HDDEDATA hDDEData, ULONG_PTR data1, ULONG_PTR data2) +{ + trace("Callback: type=%i, format=%i\n", type, format); + return NULL; +} + +/* + * Encoded String for Error Messages so that inner failures can determine + * what test is failing. Format is: [Code:TestNum] + */ +static const char * GetStringFromTestParams(int testParams) +{ + int testNum; + static char testParamString[64]; + const char *callId; + + testNum = testParams & DDE_TEST_NUMMASK; + switch (testParams & DDE_TEST_CALLMASK) + { + default: + case DDE_TEST_MISC: + callId = "MISC"; + break; + case DDE_TEST_CREATEGROUP: + callId = "C_G"; + break; + case DDE_TEST_DELETEGROUP: + callId = "D_G"; + break; + case DDE_TEST_SHOWGROUP: + callId = "S_G"; + break; + case DDE_TEST_ADDITEM: + callId = "A_I"; + break; + case DDE_TEST_DELETEITEM: + callId = "D_I"; + break; + case DDE_TEST_COMPOUND: + callId = "CPD"; + break; + } + + sprintf(testParamString, " [%s:%i]", callId, testNum); + return testParamString; +} + +/* Transfer DMLERR's into text readable strings for Error Messages */ +#define DMLERR_TO_STR(x) case x: return#x; +static const char * GetStringFromError(UINT err) +{ + switch (err) + { + DMLERR_TO_STR(DMLERR_NO_ERROR); + DMLERR_TO_STR(DMLERR_ADVACKTIMEOUT); + DMLERR_TO_STR(DMLERR_BUSY); + DMLERR_TO_STR(DMLERR_DATAACKTIMEOUT); + DMLERR_TO_STR(DMLERR_DLL_NOT_INITIALIZED); + DMLERR_TO_STR(DMLERR_DLL_USAGE); + DMLERR_TO_STR(DMLERR_EXECACKTIMEOUT); + DMLERR_TO_STR(DMLERR_INVALIDPARAMETER); + DMLERR_TO_STR(DMLERR_LOW_MEMORY); + DMLERR_TO_STR(DMLERR_MEMORY_ERROR); + DMLERR_TO_STR(DMLERR_NOTPROCESSED); + DMLERR_TO_STR(DMLERR_NO_CONV_ESTABLISHED); + DMLERR_TO_STR(DMLERR_POKEACKTIMEOUT); + DMLERR_TO_STR(DMLERR_POSTMSG_FAILED); + DMLERR_TO_STR(DMLERR_REENTRANCY); + DMLERR_TO_STR(DMLERR_SERVER_DIED); + DMLERR_TO_STR(DMLERR_SYS_ERROR); + DMLERR_TO_STR(DMLERR_UNADVACKTIMEOUT); + DMLERR_TO_STR(DMLERR_UNFOUND_QUEUE_ID); + default: + return "Unknown DML Error"; + } +} + +/* Helper Function to Transfer DdeGetLastError into a String */ +static const char * GetDdeLastErrorStr(DWORD instance) +{ + UINT err = DdeGetLastError(instance); + + return GetStringFromError(err); +} + +/* Execute a Dde Command and return the error & result */ +/* Note: Progman DDE always returns a pointer to 0x00000001 on a successful result */ +static void DdeExecuteCommand(DWORD instance, HCONV hConv, const char *strCmd, HDDEDATA *hData, UINT *err, int testParams) +{ + HDDEDATA command; + + command = DdeCreateDataHandle(instance, (LPBYTE) strCmd, strlen(strCmd)+1, 0, 0L, 0, 0); + ok (command != NULL, "DdeCreateDataHandle Error %s.%s\n", + GetDdeLastErrorStr(instance), GetStringFromTestParams(testParams)); + *hData = DdeClientTransaction((void *) command, + -1, + hConv, + 0, + 0, + XTYP_EXECUTE, + MS_TIMEOUT_VAL, + NULL); + + /* hData is technically a pointer, but for Program Manager, + * it is NULL (error) or 1 (success) + * TODO: Check other versions of Windows to verify 1 is returned. + * While it is unlikely that anyone is actually testing that the result is 1 + * if all versions of windows return 1, Wine should also. + */ + if (*hData == NULL) + { + *err = DdeGetLastError(instance); + } + else + { + *err = DMLERR_NO_ERROR; + todo_wine + { + ok(*hData == (HDDEDATA) 1, "Expected HDDEDATA Handle == 1, actually %p.%s\n", + *hData, GetStringFromTestParams(testParams)); + } + } + DdeFreeDataHandle(command); +} + +/* + * Check if Window is onscreen with the appropriate name. + * + * Windows are not created synchronously. So we do not know + * when and if the window will be created/shown on screen. + * This function implements a polling mechanism to determine + * creation. + * A more complicated method would be to use SetWindowsHookEx. + * Since polling worked fine in my testing, no reason to implement + * the other. Comments about other methods of determining when + * window creation happened were not encouraging (not including + * SetWindowsHookEx). + */ +static void CheckWindowCreated(const char *winName, int closeWindow, int testParams) +{ + HWND window = NULL; + int i; + + /* Poll for Window Creation */ + for (i = 0; window == NULL && i < PDDE_POLL_NUM; i++) + { + Sleep(PDDE_POLL_TIME); + window = FindWindowA(NULL, winName); + } + ok (window != NULL, "Window "%s" was not created in %i seconds - assumed failure.%s\n", + winName, PDDE_POLL_NUM*PDDE_POLL_TIME/1000, GetStringFromTestParams(testParams)); + + /* Close Window as desired. */ + if (window != NULL && closeWindow) + { + SendMessageA(window, WM_SYSCOMMAND, SC_CLOSE, 0); + } +} + +/* Check for Existence (or non-existence) of a file or group + * When testing for existence of a group, groupName is not needed + */ +static void CheckFileExistsInProgramGroups(const char *nameToCheck, int shouldExist, int isGroup, + const char *groupName, int testParams) +{ + char path[MAX_PATH]; + DWORD attributes; + int len; + + lstrcpyA(path, ProgramsDir); + + len = strlen(path) + strlen(nameToCheck)+1; + if (groupName != NULL) + { + len += strlen(groupName)+1; + } + ok (len <= MAX_PATH, "Path Too Long.%s\n", GetStringFromTestParams(testParams)); + if (len <= MAX_PATH) + { + if (groupName != NULL) + { + strcat(path, "\"); + strcat(path, groupName); + } + strcat(path, "\"); + strcat(path, nameToCheck); + attributes = GetFileAttributes(path); + if (!shouldExist) + { + ok (attributes == INVALID_FILE_ATTRIBUTES , "File exists and shouldn't %s.%s\n", + path, GetStringFromTestParams(testParams)); + } else { + if (attributes == INVALID_FILE_ATTRIBUTES) + { + ok (FALSE, "Created File %s doesn't exist.%s\n", path, GetStringFromTestParams(testParams)); + } else if (isGroup) { + ok (attributes & FILE_ATTRIBUTE_DIRECTORY, "%s is not a folder (attr=%x).%s\n", + path, attributes, GetStringFromTestParams(testParams)); + } else { + ok (attributes & FILE_ATTRIBUTE_ARCHIVE, "Created File %s has wrong attributes (%x).%s\n", + path, attributes, GetStringFromTestParams(testParams)); + } + } + } +} + +/* Create Group Test. + * command and expected_result. + * if expected_result is DMLERR_NO_ERROR, test + * 1. group was created + * 2. window is open + */ +static void CreateGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *groupName, const char *windowTitle, int testParams) +{ + HDDEDATA hData; + UINT error; + + /* Execute Command & Check Result */ + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); + todo_wine + { + ok (expected_result == error, "CreateGroup %s: Expected Error %s, received %s.%s\n", + groupName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + + /* No Error */ + if (error == DMLERR_NO_ERROR) + { + + /* Check if Group Now Exists */ + CheckFileExistsInProgramGroups(groupName, TRUE, TRUE, NULL, testParams); + /* Check if Window is Open (polling) */ + CheckWindowCreated(windowTitle, TRUE, testParams); + } +} + +/* Show Group Test. + * DDE command, expected_result, and the group name to check for existence + * if expected_result is DMLERR_NO_ERROR, test + * 1. window is open + */ +static void ShowGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *groupName, const char *windowTitle, int closeAfterShowing, int testParams) +{ + HDDEDATA hData; + UINT error; + + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); +/* todo_wine... Is expected to fail, wine stubbed functions DO fail */ +/* TODO REMOVE THIS CODE!!! */ + if (expected_result == DMLERR_NOTPROCESSED) + { + ok (expected_result == error, "ShowGroup %s: Expected Error %s, received %s.%s\n", + groupName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } else { + todo_wine + { + ok (expected_result == error, "ShowGroup %s: Expected Error %s, received %s.%s\n", + groupName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + } + + if (error == DMLERR_NO_ERROR) + { + /* Check if Window is Open (polling) */ + CheckWindowCreated(windowTitle, closeAfterShowing, testParams); + } +} + +/* Delete Group Test. + * DDE command, expected_result, and the group name to check for existence + * if expected_result is DMLERR_NO_ERROR, test + * 1. group does not exist + */ +static void DeleteGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *groupName, int testParams) +{ + HDDEDATA hData; + UINT error; + + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); + todo_wine + { + ok (expected_result == error, "DeleteGroup %s: Expected Error %s, received %s.%s\n", + groupName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + + if (error == DMLERR_NO_ERROR) + { + /* Check that Group does not exist */ + CheckFileExistsInProgramGroups(groupName, FALSE, TRUE, NULL, testParams); + } +} + +/* Add Item Test + * DDE command, expected result, and group and file name where it should exist. + * checks to make sure error code matches expected error code + * checks to make sure item exists if successful + */ +static void AddItemTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *fileName, const char *groupName, int testParams) +{ + HDDEDATA hData; + UINT error; + + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); + todo_wine + { + ok (expected_result == error, "AddItem %s: Expected Error %s, received %s.%s\n", + fileName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + + if (error == DMLERR_NO_ERROR) + { + /* Check that File exists */ + CheckFileExistsInProgramGroups(fileName, TRUE, FALSE, groupName, testParams); + } +} + +/* Delete Item Test. + * DDE command, expected result, and group and file name where it should exist. + * checks to make sure error code matches expected error code + * checks to make sure item does not exist if successful + */ +static void DeleteItemTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *fileName, const char *groupName, int testParams) +{ + HDDEDATA hData; + UINT error; + + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); + todo_wine + { + ok (expected_result == error, "DeleteItem %s: Expected Error %s, received %s.%s\n", + fileName, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + + if (error == DMLERR_NO_ERROR) + { + /* Check that File does not exist */ + CheckFileExistsInProgramGroups(fileName, FALSE, FALSE, groupName, testParams); + } +} + +/* Compound Command Test. + * not really generic, assumes command of the form: + * [CreateGroup ...][AddItem ...][AddItem ...] + * All samples I've seen using Compound were of this form (CreateGroup, + * AddItems) so this covers minimum expected functionality. + */ +static void CompoundCommandTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, + const char *groupName, const char *windowTitle, const char *fileName1, + const char *fileName2, int testParams) +{ + HDDEDATA hData; + UINT error; + + DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); + todo_wine + { + ok (expected_result == error, "Compound String %s: Expected Error %s, received %s.%s\n", + command, GetStringFromError(expected_result), GetStringFromError(error), + GetStringFromTestParams(testParams)); + } + + if (error == DMLERR_NO_ERROR) + { + /* Check that File exists */ + CheckFileExistsInProgramGroups(groupName, TRUE, TRUE, NULL, testParams); + CheckWindowCreated(windowTitle, FALSE, testParams); + CheckFileExistsInProgramGroups(fileName1, TRUE, FALSE, groupName, testParams); + CheckFileExistsInProgramGroups(fileName2, TRUE, FALSE, groupName, testParams); + } +} + +static void CreateAddItemText(char *itemtext, const char *cmdline, const char *name) +{ + lstrcpyA(itemtext, "[AddItem("); + lstrcatA(itemtext, cmdline); + lstrcatA(itemtext, ","); + lstrcatA(itemtext, name); + lstrcatA(itemtext, ")]"); +} + +/* 1st set of tests */ +static int DdeTestProgman(DWORD instance, HCONV hConv) +{ + HDDEDATA hData; + UINT error; + int testnum; + char temppath[MAX_PATH]; + char f1g1[MAX_PATH], f2g1[MAX_PATH], f3g1[MAX_PATH], f1g3[MAX_PATH], f2g3[MAX_PATH]; + char itemtext[MAX_PATH + 20]; + char comptext[2 * (MAX_PATH + 20) + 21]; + + testnum = 1; + /* Invalid Command */ + DdeExecuteCommand(instance, hConv, "[InvalidCommand()]", &hData, &error, DDE_TEST_MISC|testnum++); + ok (error == DMLERR_NOTPROCESSED, "InvalidCommand(), expected error %s, received %s.\n", + GetStringFromError(DMLERR_NOTPROCESSED), GetStringFromError(error)); + + /* On Vista+ the files have to exist when adding a link */ + GetTempPathA(MAX_PATH, temppath); + GetTempFileNameA(temppath, "dde", 0, f1g1); + GetTempFileNameA(temppath, "dde", 0, f2g1); + GetTempFileNameA(temppath, "dde", 0, f3g1); + GetTempFileNameA(temppath, "dde", 0, f1g3); + GetTempFileNameA(temppath, "dde", 0, f2g3); + + /* CreateGroup Tests (including AddItem, DeleteItem) */ + CreateGroupTest(instance, hConv, "[CreateGroup(Group1)]", DMLERR_NO_ERROR, "Group1", Group1Title, DDE_TEST_CREATEGROUP|testnum++); + CreateAddItemText(itemtext, f1g1, "f1g1Name"); + AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f1g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++); + CreateAddItemText(itemtext, f2g1, "f2g1Name"); + AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f2g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++); + DeleteItemTest(instance, hConv, "[DeleteItem(f2g1Name)]", DMLERR_NO_ERROR, "f2g1Name.lnk", "Group1", DDE_TEST_DELETEITEM|testnum++); + CreateAddItemText(itemtext, f3g1, "f3g1Name"); + AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f3g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++); + CreateGroupTest(instance, hConv, "[CreateGroup(Group2)]", DMLERR_NO_ERROR, "Group2", Group2Title, DDE_TEST_CREATEGROUP|testnum++); + /* Create Group that already exists - same instance */ + CreateGroupTest(instance, hConv, "[CreateGroup(Group1)]", DMLERR_NO_ERROR, "Group1", Group1Title, DDE_TEST_CREATEGROUP|testnum++); + + /* ShowGroup Tests */ + ShowGroupTest(instance, hConv, "[ShowGroup(Group1)]", DMLERR_NOTPROCESSED, "Group1", Group1Title, TRUE, DDE_TEST_SHOWGROUP|testnum++); + DeleteItemTest(instance, hConv, "[DeleteItem(f3g1Name)]", DMLERR_NO_ERROR, "f3g1Name.lnk", "Group1", DDE_TEST_DELETEITEM|testnum++); + ShowGroupTest(instance, hConv, "[ShowGroup(Startup,0)]", DMLERR_NO_ERROR, "Startup", StartupTitle, TRUE, DDE_TEST_SHOWGROUP|testnum++); + ShowGroupTest(instance, hConv, "[ShowGroup(Group1,0)]", DMLERR_NO_ERROR, "Group1", Group1Title, FALSE, DDE_TEST_SHOWGROUP|testnum++); + + /* DeleteGroup Test - Note that Window is Open for this test */ + DeleteGroupTest(instance, hConv, "[DeleteGroup(Group1)]", DMLERR_NO_ERROR, "Group1", DDE_TEST_DELETEGROUP|testnum++); + + /* Compound Execute String Command */ + lstrcpyA(comptext, "[CreateGroup(Group3)]"); + CreateAddItemText(itemtext, f1g3, "f1g3Name"); + lstrcatA(comptext, itemtext); + CreateAddItemText(itemtext, f2g3, "f2g3Name"); + lstrcatA(comptext, itemtext); + CompoundCommandTest(instance, hConv, comptext, DMLERR_NO_ERROR, "Group3", Group3Title, "f1g3Name.lnk", "f2g3Name.lnk", DDE_TEST_COMPOUND|testnum++); + + DeleteGroupTest(instance, hConv, "[DeleteGroup(Group3)]", DMLERR_NO_ERROR, "Group3", DDE_TEST_DELETEGROUP|testnum++); + + /* Full Parameters of Add Item */ + /* AddItem(CmdLine[,Name[,IconPath[,IconIndex[,xPos,yPos[,DefDir[,HotKey[,fMinimize[fSeparateSpace]]]]]]]) */ + + DeleteFileA(f1g1); + DeleteFileA(f2g1); + DeleteFileA(f3g1); + DeleteFileA(f1g3); + DeleteFileA(f2g3); + + return testnum; +} + +/* 2nd set of tests - 2nd connection */ +static void DdeTestProgman2(DWORD instance, HCONV hConv, int testnum) +{ + /* Create Group that already exists on a separate connection */ + CreateGroupTest(instance, hConv, "[CreateGroup(Group2)]", DMLERR_NO_ERROR, "Group2", Group2Title, DDE_TEST_CREATEGROUP|testnum++); + DeleteGroupTest(instance, hConv, "[DeleteGroup(Group2)]", DMLERR_NO_ERROR, "Group2", DDE_TEST_DELETEGROUP|testnum++); +} + +START_TEST(progman_dde) +{ + DWORD instance = 0; + UINT err; + HSZ hszProgman; + HCONV hConv; + int testnum; + + init_function_pointers(); + init_strings(); + + /* Initialize DDE Instance */ + err = DdeInitialize(&instance, DdeCallback, APPCMD_CLIENTONLY, 0); + ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err)); + + /* Create Connection */ + hszProgman = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI); + ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance)); + hConv = DdeConnect(instance, hszProgman, hszProgman, NULL); + ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n"); + /* Seeing failures on early versions of Windows Connecting to progman, exit if connection fails */ + if (hConv == NULL) + { + ok (DdeUninitialize(instance), "DdeUninitialize failed\n"); + return; + } + + /* Run Tests */ + testnum = DdeTestProgman(instance, hConv); + + /* Cleanup & Exit */ + ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance)); + ok (DdeUninitialize(instance), "DdeUninitialize failed\n"); + + /* 2nd Instance (Followup Tests) */ + /* Initialize DDE Instance */ + instance = 0; + err = DdeInitialize(&instance, DdeCallback, APPCMD_CLIENTONLY, 0); + ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err)); + + /* Create Connection */ + hszProgman = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI); + ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance)); + hConv = DdeConnect(instance, hszProgman, hszProgman, NULL); + ok (hConv != NULL, "DdeConnect Error %s\n", GetDdeLastErrorStr(instance)); + ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n"); + + /* Run Tests */ + DdeTestProgman2(instance, hConv, testnum); + + /* Cleanup & Exit */ + ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance)); + ok (DdeUninitialize(instance), "DdeUninitialize failed\n"); +}
Propchange: trunk/rostests/winetests/shell32/progman_dde.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/rostests/winetests/shell32/shell32.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shell32.... ============================================================================== --- trunk/rostests/winetests/shell32/shell32.rbuild [iso-8859-1] (original) +++ trunk/rostests/winetests/shell32/shell32.rbuild [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -18,6 +18,7 @@ <file>appbar.c</file> <file>autocomplete.c</file> <file>generated.c</file> + <file>progman_dde.c</file> <file>shelllink.c</file> <file>shellpath.c</file> <file>shlexec.c</file>
Modified: trunk/rostests/winetests/shell32/shelllink.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shelllin... ============================================================================== --- trunk/rostests/winetests/shell32/shelllink.c [iso-8859-1] (original) +++ trunk/rostests/winetests/shell32/shelllink.c [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -275,6 +275,20 @@ ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r); ok(lstrcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
+ strcpy(buffer,"garbage"); + r = IShellLinkA_SetArguments(sl, NULL); + ok(SUCCEEDED(r), "SetArguments failed (0x%08x)\n", r); + r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r); + ok(!buffer[0] || lstrcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer); + + strcpy(buffer,"garbage"); + r = IShellLinkA_SetArguments(sl, ""); + ok(SUCCEEDED(r), "SetArguments failed (0x%08x)\n", r); + r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r); + ok(!buffer[0], "GetArguments returned '%s'\n", buffer); + /* Test Getting / Setting showcmd */ i=0xdeadbeef; r = IShellLinkA_GetShowCmd(sl, &i);
Modified: trunk/rostests/winetests/shell32/shlexec.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shlexec.... ============================================================================== --- trunk/rostests/winetests/shell32/shlexec.c [iso-8859-1] (original) +++ trunk/rostests/winetests/shell32/shlexec.c [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -1095,7 +1095,7 @@ * like '.mpeg', etc. * Also it means we cannot do any other test. */ - trace("FindExecutable() is broken -> skipping 4+ character extension tests\n"); + win_skip("FindExecutable() is broken -> not running 4+ character extension tests\n"); return; }
Modified: trunk/rostests/winetests/shell32/shlfileop.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shlfileo... ============================================================================== --- trunk/rostests/winetests/shell32/shlfileop.c [iso-8859-1] (original) +++ trunk/rostests/winetests/shell32/shlfileop.c [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -965,9 +965,10 @@ set_curr_dir_path(from, "test1.txt\0test2.txt\0"); set_curr_dir_path(to, "test3.txt\0"); retval = SHFileOperation(&shfo); - if (retval == DE_FLDDESTISFILE) - { - /* Vista and W2K8 (broken or new behavior ?) */ + if (retval == DE_FLDDESTISFILE || /* Vista and W2K8 */ + retval == DE_INVALIDFILES) /* Win7 */ + { + /* Most likely new behavior */ ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n"); } else
Modified: trunk/rostests/winetests/shell32/shlfolder.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shlfolde... ============================================================================== --- trunk/rostests/winetests/shell32/shlfolder.c [iso-8859-1] (original) +++ trunk/rostests/winetests/shell32/shlfolder.c [iso-8859-1] Tue Dec 22 10:35:12 2009 @@ -472,7 +472,8 @@ /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */ if (pidlLast->mkid.cb >= 76) { ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) || - (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)), /* Vista */ + (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)) || /* Vista */ + (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)), /* Win7 */ "Filename should be stored as wchar-string at this position!\n"); }
@@ -585,6 +586,7 @@ ok (!lstrcmpiW(wszTestFile, wszTestFile2), "GetDisplayNameOf returns incorrect path!\n"); }
+ ILFree(pidlTestFile); IShellFolder_Release(psfDesktop); IShellFolder_Release(psfPersonal); } @@ -646,8 +648,12 @@ * key. So the test will return at this point, if run on wine. */ lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMyDocumentsKey, 0, KEY_WRITE|KEY_READ, &hKey); - ok (lResult == ERROR_SUCCESS, "RegOpenKeyEx failed! result: %08x\n", lResult); + ok (lResult == ERROR_SUCCESS || + lResult == ERROR_ACCESS_DENIED, + "RegOpenKeyEx failed! result: %08x\n", lResult); if (lResult != ERROR_SUCCESS) { + if (lResult == ERROR_ACCESS_DENIED) + skip("Not enough rights to open the registry key\n"); IMalloc_Free(ppM, pidlMyDocuments); IShellFolder_Release(psfDesktop); return; @@ -1524,18 +1530,38 @@ pFileStructA->uFileTime == pFileStructW->uTime, "Last write time should match creation time!\n");
- ok (pFileStructA->uFileDate == pFileStructW->uDate2 && - pFileStructA->uFileTime == pFileStructW->uTime2, - "Last write time should match last access time!\n"); + /* On FAT filesystems the last access time is midnight + local time, so the values of uDate2 and uTime2 will + depend on the local timezone. If the times are exactly + equal then the dates should be identical for both FAT + and NTFS as no timezone is more than 1 day away from UTC. + */ + if (pFileStructA->uFileTime == pFileStructW->uTime2) + { + ok (pFileStructA->uFileDate == pFileStructW->uDate2, + "Last write date and time should match last access date and time!\n"); + } + else + { + /* Filesystem may be FAT. Check date within 1 day + and seconds are zero. */ + trace ("Filesystem may be FAT. Performing less strict atime test.\n"); + ok ((pFileStructW->uTime2 & 0x1F) == 0, + "Last access time on FAT filesystems should have zero seconds.\n"); + /* TODO: Perform check for date being within one day.*/ + }
ok (!lstrcmpW(wszFile[i], pFileStructW->wszName) || - !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 22)), /* Vista */ + !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 22)) || /* Vista */ + !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 26)), /* Win7 */ "The filename should be stored in unicode at this position!\n"); } }
pILFree(pidlFile); } + + IShellFolder_Release(psfPersonal); }
static void testSHGetFolderPathAndSubDirA(void)