Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/shell32/tests/progman_dde.c | 577 ++++++++++----------------------------- 1 file changed, 138 insertions(+), 439 deletions(-)
diff --git a/dlls/shell32/tests/progman_dde.c b/dlls/shell32/tests/progman_dde.c index 6e1378f..6be7267 100644 --- a/dlls/shell32/tests/progman_dde.c +++ b/dlls/shell32/tests/progman_dde.c @@ -34,25 +34,6 @@ #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); @@ -231,411 +212,64 @@ static HDDEDATA CALLBACK DdeCallback(UINT type, UINT format, HCONV hConv, HSZ hs 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) +static UINT dde_execute(DWORD instance, HCONV hconv, const char *command_str) { - 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"; - } -} + HDDEDATA command, hdata; + DWORD result; + UINT ret;
-/* Helper Function to Transfer DdeGetLastError into a String */ -static const char * GetDdeLastErrorStr(DWORD instance) -{ - UINT err = DdeGetLastError(instance); + command = DdeCreateDataHandle(instance, (BYTE *)command_str, strlen(command_str)+1, 0, 0, 0, 0); + ok(command != NULL, "DdeCreateDataHandle() failed: %u\n", DdeGetLastError(instance));
- return GetStringFromError(err); -} + hdata = DdeClientTransaction((BYTE *)command, -1, hconv, 0, 0, XTYP_EXECUTE, 2000, &result); + ret = DdeGetLastError(instance); + /* PROGMAN always returns 1 on success */ + ok((UINT)hdata == !ret, "expected %o, got %p\n", !ret, hdata);
-/* 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); + return ret; }
-/* - * 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 HWND CheckWindowCreated(const char *winName, BOOL closeWindow, int testParams) +static BOOL check_window_exists(const char *name) { HWND window = NULL; int i;
- /* Poll for Window Creation */ - for (i = 0; window == NULL && i < PDDE_POLL_NUM; i++) - { - Sleep(PDDE_POLL_TIME); - /* Specify the window class name to make sure what we find is really an - * Explorer window. Explorer used two different window classes so try - * both. - */ - window = FindWindowA("ExplorerWClass", winName); - if (!window) - window = FindWindowA("CabinetWClass", 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); - window = NULL; - } - return window; -} - -/* 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, BOOL shouldExist, BOOL 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) + for (i = 0; i < 20; i++) { - 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 = GetFileAttributesA(path); - if (!shouldExist) + Sleep(100); + if ((window = FindWindowA("ExplorerWClass", name)) || + (window = FindWindowA("CabinetWClass", name))) { - 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)); - } + SendMessageA(window, WM_SYSCOMMAND, SC_CLOSE, 0); + break; } } -} - -/* 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 HWND ShowGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result, - const char *groupName, const char *windowTitle, BOOL closeAfterShowing, int testParams) -{ - HDDEDATA hData; - UINT error; - HWND hwnd = 0; - - DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams); -/* todo_wine... Is expected to fail, wine stubbed functions DO fail */ -/* TODO REMOVE THIS CODE!!! */ - todo_wine_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));
- if (error == DMLERR_NO_ERROR) - { - /* Check if Window is Open (polling) */ - hwnd = CheckWindowCreated(windowTitle, closeAfterShowing, testParams); - } - return hwnd; + return (window != NULL); }
-/* 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) +static BOOL check_exists(const char *name) { - 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 HWND 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; - HWND hwnd = 0; - - 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); - hwnd = CheckWindowCreated(windowTitle, FALSE, testParams); - CheckFileExistsInProgramGroups(fileName1, TRUE, FALSE, groupName, testParams); - CheckFileExistsInProgramGroups(fileName2, TRUE, FALSE, groupName, testParams); - } - return hwnd; -} + char path[MAX_PATH];
-static void CreateAddItemText(char *itemtext, const char *cmdline, const char *name) -{ - lstrcpyA(itemtext, "[AddItem("); - lstrcatA(itemtext, cmdline); - lstrcatA(itemtext, ","); - lstrcatA(itemtext, name); - lstrcatA(itemtext, ")]"); + strcpy(path, ProgramsDir); + strcat(path, "\"); + strcat(path, name); + return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES; }
/* 1st set of tests */ -static int DdeTestProgman(DWORD instance, HCONV hConv) +static void test_progman_dde(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]; - HWND hwnd;
- 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)); + error = dde_execute(instance, hConv, "[InvalidCommand()]"); + ok(error == DMLERR_NOTPROCESSED, "expected DMLERR_NOTPROCESSED, got %u\n", error);
/* On Vista+ the files have to exist when adding a link */ GetTempPathA(MAX_PATH, temppath); @@ -646,38 +280,96 @@ static int DdeTestProgman(DWORD instance, HCONV hConv) 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++); + error = dde_execute(instance, hConv, "[CreateGroup(Group1)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group1"), "directory not created\n"); + ok(check_window_exists(Group1Title), "window not created\n"); + } + + sprintf(itemtext, "[AddItem(%s,f1g1Name)]", f1g1); + error = dde_execute(instance, hConv, itemtext); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group1/f1g1Name.lnk"), "link not created\n"); + } + + sprintf(itemtext, "[AddItem(%s,f2g1Name)]", f2g1); + error = dde_execute(instance, hConv, itemtext); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group1/f2g1Name.lnk"), "link not created\n"); + } + + error = dde_execute(instance, hConv, "[DeleteItem(f2g1Name)]"); + todo_wine + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(!check_exists("Group1/f2g1Name.lnk"), "link should not exist\n"); + + sprintf(itemtext, "[AddItem(%s,f3g1Name)]", f3g1); + error = dde_execute(instance, hConv, itemtext); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group1/f3g1Name.lnk"), "link not created\n"); + } + + error = dde_execute(instance, hConv, "[CreateGroup(Group2)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group2"), "directory not created\n"); + ok(check_window_exists(Group2Title), "window not created\n"); + } + /* Create Group that already exists - same instance */ - CreateGroupTest(instance, hConv, "[CreateGroup(Group1)]", DMLERR_NO_ERROR, "Group1", Group1Title, DDE_TEST_CREATEGROUP|testnum++); + error = dde_execute(instance, hConv, "[CreateGroup(Group1)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group1"), "directory not created\n"); + ok(check_window_exists(Group1Title), "window not created\n"); + }
/* 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++); - hwnd = ShowGroupTest(instance, hConv, "[ShowGroup(Group1,0)]", DMLERR_NO_ERROR, "Group1", Group1Title, FALSE, DDE_TEST_SHOWGROUP|testnum++); + error = dde_execute(instance, hConv, "[ShowGroup(Group1)]"); + ok(error == DMLERR_NOTPROCESSED, "expected DMLERR_NOTPROCESSED, got %u\n", error);
- /* DeleteGroup Test - Note that Window is Open for this test */ - DeleteGroupTest(instance, hConv, "[DeleteGroup(Group1)]", DMLERR_NO_ERROR, "Group1", DDE_TEST_DELETEGROUP|testnum++); - if (hwnd) SendMessageA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); + error = dde_execute(instance, hConv, "[DeleteItem(f3g1Name)]"); + todo_wine + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(!check_exists("Group1/f3g1Name.lnk"), "link should not exist\n"); + + error = dde_execute(instance, hConv, "[ShowGroup(Startup, 0)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_window_exists(StartupTitle), "window not created\n"); + } + + error = dde_execute(instance, hConv, "[ShowGroup(Group1, 0)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_window_exists(Group1Title), "window not created\n"); + } + + /* DeleteGroup Test */ + error = dde_execute(instance, hConv, "[DeleteGroup(Group1)]"); + todo_wine + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(!check_exists("Group1"), "directory should not exist\n");
/* Compound Execute String Command */ - lstrcpyA(comptext, "[CreateGroup(Group3)]"); - CreateAddItemText(itemtext, f1g3, "f1g3Name"); - lstrcatA(comptext, itemtext); - CreateAddItemText(itemtext, f2g3, "f2g3Name"); - lstrcatA(comptext, itemtext); - hwnd = CompoundCommandTest(instance, hConv, comptext, DMLERR_NO_ERROR, "Group3", Group3Title, "f1g3Name.lnk", "f2g3Name.lnk", DDE_TEST_COMPOUND|testnum++); + sprintf(comptext, "[CreateGroup(Group3)][AddItem(%s,f1g3Name)][AddItem(%s,f2g3Name)]", f1g3, f2g3); + error = dde_execute(instance, hConv, comptext); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group3"), "directory not created\n"); + ok(check_window_exists(Group3Title), "window not created\n"); + ok(check_exists("Group3/f1g3Name.lnk"), "link not created\n"); + ok(check_exists("Group3/f2g3Name.lnk"), "link not created\n"); + }
- DeleteGroupTest(instance, hConv, "[DeleteGroup(Group3)]", DMLERR_NO_ERROR, "Group3", DDE_TEST_DELETEGROUP|testnum++); - if (hwnd) SendMessageA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); + error = dde_execute(instance, hConv, "[DeleteGroup(Group3)]"); + todo_wine + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(!check_exists("Group3"), "directory should not exist\n");
/* Full Parameters of Add Item */ /* AddItem(CmdLine[,Name[,IconPath[,IconIndex[,xPos,yPos[,DefDir[,HotKey[,fMinimize[fSeparateSpace]]]]]]]) */ @@ -687,16 +379,25 @@ static int DdeTestProgman(DWORD instance, HCONV hConv) DeleteFileA(f3g1); DeleteFileA(f1g3); DeleteFileA(f2g3); - - return testnum; }
/* 2nd set of tests - 2nd connection */ -static void DdeTestProgman2(DWORD instance, HCONV hConv, int testnum) +static void test_progman_dde2(DWORD instance, HCONV hConv) { + UINT error; + /* 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++); + error = dde_execute(instance, hConv, "[CreateGroup(Group2)]"); + todo_wine { + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(check_exists("Group2"), "directory not created\n"); + ok(check_window_exists(Group2Title), "window not created\n"); + } + + error = dde_execute(instance, hConv, "[DeleteGroup(Group2)]"); + todo_wine + ok(error == DMLERR_NO_ERROR, "expected DMLERR_NO_ERROR, got %u\n", error); + ok(!check_exists("Group2"), "directory should not exist\n"); }
START_TEST(progman_dde) @@ -705,20 +406,19 @@ START_TEST(progman_dde) UINT err; HSZ hszProgman; HCONV hConv; - int testnum;
init_function_pointers(); init_strings();
/* Initialize DDE Instance */ err = DdeInitializeA(&instance, DdeCallback, APPCMD_CLIENTONLY, 0); - ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err)); + ok(err == DMLERR_NO_ERROR, "DdeInitialize() failed: %u\n", err);
/* Create Connection */ hszProgman = DdeCreateStringHandleA(instance, "PROGMAN", CP_WINANSI); - ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance)); + ok(hszProgman != NULL, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance)); hConv = DdeConnect(instance, hszProgman, hszProgman, NULL); - ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n"); + ok(DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle() failed: %u\n", DdeGetLastError(instance)); /* Seeing failures on early versions of Windows Connecting to progman, exit if connection fails */ if (hConv == NULL) { @@ -726,30 +426,29 @@ START_TEST(progman_dde) return; }
- /* Run Tests */ - testnum = DdeTestProgman(instance, hConv); + test_progman_dde(instance, hConv);
/* Cleanup & Exit */ - ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance)); - ok (DdeUninitialize(instance), "DdeUninitialize failed\n"); + ok(DdeDisconnect(hConv), "DdeDisonnect() failed: %u\n", DdeGetLastError(instance)); + ok(DdeUninitialize(instance), "DdeUninitialize() failed: %u\n", DdeGetLastError(instance));
/* 2nd Instance (Followup Tests) */ /* Initialize DDE Instance */ instance = 0; err = DdeInitializeA(&instance, DdeCallback, APPCMD_CLIENTONLY, 0); - ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err)); + ok (err == DMLERR_NO_ERROR, "DdeInitialize() failed: %u\n", err);
/* Create Connection */ hszProgman = DdeCreateStringHandleA(instance, "PROGMAN", CP_WINANSI); - ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance)); + ok(hszProgman != NULL, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance)); hConv = DdeConnect(instance, hszProgman, hszProgman, NULL); - ok (hConv != NULL, "DdeConnect Error %s\n", GetDdeLastErrorStr(instance)); - ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n"); + ok(hConv != NULL, "DdeConnect() failed: %u\n", DdeGetLastError(instance)); + ok(DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle() failed: %u\n", DdeGetLastError(instance));
/* Run Tests */ - DdeTestProgman2(instance, hConv, testnum); + test_progman_dde2(instance, hConv);
/* Cleanup & Exit */ - ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance)); - ok (DdeUninitialize(instance), "DdeUninitialize failed\n"); + ok(DdeDisconnect(hConv), "DdeDisonnect() failed: %u\n", DdeGetLastError(instance)); + ok(DdeUninitialize(instance), "DdeUninitialize() failed: %u\n", DdeGetLastError(instance)); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- programs/explorer/explorer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c index 9590027..3571497 100644 --- a/programs/explorer/explorer.c +++ b/programs/explorer/explorer.c @@ -51,7 +51,7 @@ static int default_width; static int default_height;
-static const WCHAR EXPLORER_CLASS[] = {'W','I','N','E','_','E','X','P','L','O','R','E','R','\0'}; +static const WCHAR EXPLORER_CLASS[] = {'E','x','p','l','o','r','e','r','W','C','l','a','s','s',0}; static const WCHAR PATH_BOX_NAME[] = {'\0'};
HINSTANCE explorer_hInstance;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- programs/explorer/explorer.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/programs/explorer/explorer.c b/programs/explorer/explorer.c index 3571497..afb565f 100644 --- a/programs/explorer/explorer.c +++ b/programs/explorer/explorer.c @@ -259,10 +259,32 @@ static void update_path_box(explorer_info *info) static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationComplete(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl) { IExplorerBrowserEventsImpl *This = impl_from_IExplorerBrowserEvents(iface); + IShellFolder *parent; + PCUITEMID_CHILD child_pidl; + HRESULT hres; + STRRET strret; + WCHAR *name; + ILFree(This->info->pidl); This->info->pidl = ILClone(pidl); update_path_box(This->info); - return S_OK; + + hres = SHBindToParent(pidl, &IID_IShellFolder, (void **)&parent, &child_pidl); + if (SUCCEEDED(hres)) + { + hres = IShellFolder_GetDisplayNameOf(parent, child_pidl, SHGDN_FORADDRESSBAR, &strret); + if (SUCCEEDED(hres)) + hres = StrRetToStrW(&strret, child_pidl, &name); + if (SUCCEEDED(hres)) + { + SetWindowTextW(This->info->main_window, name); + CoTaskMemFree(name); + } + + IShellFolder_Release(parent); + } + + return hres; }
static HRESULT WINAPI IExplorerBrowserEventsImpl_fnOnNavigationFailed(IExplorerBrowserEvents *iface, PCIDLIST_ABSOLUTE pidl)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This is an anticipatory change. Creating shell links from Progman (i.e. explorer.exe) will cause a deadlock if the icon is missing or (as in the tests) the link is immediately deleted.
dlls/shell32/shelllink.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c index 40fab4d..4d0be82 100644 --- a/dlls/shell32/shelllink.c +++ b/dlls/shell32/shelllink.c @@ -340,17 +340,26 @@ BOOL run_winemenubuilder( const WCHAR *args )
static BOOL StartLinkProcessor( LPCOLESTR szLink ) { - static const WCHAR szFormat[] = {' ','-','w',' ','"','%','s','"',0 }; + static const WCHAR szExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e'}; + static const WCHAR szWait[] = {' ','-','w',0}; + static const WCHAR szFormat[] = {' ','"','%','s','"',0 }; + WCHAR module[12]; LONG len; LPWSTR buffer; BOOL ret;
- len = sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR); + len = sizeof(szWait) + sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR); buffer = HeapAlloc( GetProcessHeap(), 0, len ); if( !buffer ) return FALSE;
wsprintfW( buffer, szFormat, szLink ); + GetModuleFileNameW(NULL, module, sizeof(module)/sizeof(module[0])); + + /* avoid waiting on explorer.exe as this will cause a deadlock */ + if (memcmp(module, szExplorer, sizeof(szExplorer))) + strcatW(buffer, szWait); + ret = run_winemenubuilder( buffer ); HeapFree( GetProcessHeap(), 0, buffer ); return ret;
Zebediah Figura z.figura12@gmail.com writes:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
This is an anticipatory change. Creating shell links from Progman (i.e. explorer.exe) will cause a deadlock if the icon is missing or (as in the tests) the link is immediately deleted.
Checking the module name is pretty hackish. Also the check can't work anyway, because GetModuleFileNameW returns a full path.
On 11/29/2017 02:21 PM, Alexandre Julliard wrote:
Zebediah Figura z.figura12@gmail.com writes:
Signed-off-by: Zebediah Figura z.figura12@gmail.com
This is an anticipatory change. Creating shell links from Progman (i.e. explorer.exe) will cause a deadlock if the icon is missing or (as in the tests) the link is immediately deleted.
Checking the module name is pretty hackish. Also the check can't work anyway, because GetModuleFileNameW returns a full path.
Could I request an opinion on the best way to solve this problem?
* The process that creates the link could be explorer, if the process uses the Progman DDE interface. Additionally (though perhaps improbably) it could be a different process than the one that creates the icon. I have a hard time thinking 5e28f7ad92e39bdd75cf291e22b7ebae00032e60 was a correct step. * More correct than waiting on the process handle would be waiting on the icon file itself using FindFirstChangeNotification() etc, but we can't depend on the icon ever being created. * Reverting 5e28f7a and using a RunOnce entry does have the disadvantage that it might never be run. I would personally imagine it acceptable to at least fix it so the link is created (if not the icon) but others might disagree. It would also be better if we could run winemenubuilder on Wine "shutdown" rather than the next startup, assuming this is possible. Would this solution be acceptable?
Zebediah Figura z.figura12@gmail.com writes:
Could I request an opinion on the best way to solve this problem?
- The process that creates the link could be explorer, if the process
uses the Progman DDE interface. Additionally (though perhaps improbably) it could be a different process than the one that creates the icon. I have a hard time thinking 5e28f7ad92e39bdd75cf291e22b7ebae00032e60 was a correct step.
- More correct than waiting on the process handle would be waiting on
the icon file itself using FindFirstChangeNotification() etc, but we can't depend on the icon ever being created.
- Reverting 5e28f7a and using a RunOnce entry does have the
disadvantage that it might never be run. I would personally imagine it acceptable to at least fix it so the link is created (if not the icon) but others might disagree. It would also be better if we could run winemenubuilder on Wine "shutdown" rather than the next startup, assuming this is possible. Would this solution be acceptable?
At shutdown is not much better than RunOnce, and in fact is even harder to get right. But we could potentially make it into a service watching the file system.