diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c index 1fb31cb179d..f83eb9eb47f 100644 --- a/dlls/shell32/shelllink.c +++ b/dlls/shell32/shelllink.c @@ -1014,20 +1014,29 @@ static HRESULT Stream_WriteLocationInfo( IStream* stm, LPCWSTR path, return IStream_Write( stm, loc, total_size, &count ); } +static EXP_DARWIN_LINK* shelllink_build_darwinid( LPCWSTR string, DWORD magic ) +{ + EXP_DARWIN_LINK *buffer; + + buffer = LocalAlloc( LMEM_ZEROINIT, sizeof *buffer ); + buffer->dbh.cbSize = sizeof buffer; + buffer->dbh.dwSignature = magic; + lstrcpynW( buffer->szwDarwinID, string, MAX_PATH ); + WideCharToMultiByte(CP_ACP, 0, string, -1, buffer->szDarwinID, MAX_PATH, NULL, NULL ); + + return buffer; +} + static HRESULT Stream_WriteAdvertiseInfo( IStream* stm, LPCWSTR string, DWORD magic ) { + EXP_DARWIN_LINK *buffer; ULONG count; - EXP_DARWIN_LINK buffer; TRACE("%p\n",stm); - memset( &buffer, 0, sizeof buffer ); - buffer.dbh.cbSize = sizeof buffer; - buffer.dbh.dwSignature = magic; - lstrcpynW( buffer.szwDarwinID, string, MAX_PATH ); - WideCharToMultiByte(CP_ACP, 0, string, -1, buffer.szDarwinID, MAX_PATH, NULL, NULL ); + buffer = shelllink_build_darwinid( string, magic ); - return IStream_Write( stm, &buffer, buffer.dbh.cbSize, &count ); + return IStream_Write( stm, &buffer, buffer->dbh.cbSize, &count ); } /************************************************************************ @@ -2246,8 +2255,32 @@ ShellLink_AddDataBlock( IShellLinkDataList* iface, void* pDataBlock ) static HRESULT WINAPI ShellLink_CopyDataBlock( IShellLinkDataList* iface, DWORD dwSig, void** ppDataBlock ) { - FIXME("\n"); - return E_NOTIMPL; + IShellLinkImpl *This = impl_from_IShellLinkDataList(iface); + LPVOID block = NULL; + HRESULT r = E_FAIL; + + TRACE("%p %08lx %p\n", iface, dwSig, ppDataBlock ); + + switch (dwSig) + { + case EXP_DARWIN_ID_SIG: + if (!This->sComponent) + break; + block = shelllink_build_darwinid( This->sComponent, dwSig ); + r = S_OK; + break; + case EXP_SZ_LINK_SIG: + case NT_CONSOLE_PROPS_SIG: + case NT_FE_CONSOLE_PROPS_SIG: + case EXP_SPECIAL_FOLDER_SIG: + case EXP_SZ_ICON_SIG: + FIXME("valid but unhandled datablock %08lx\n", dwSig); + break; + default: + ERR("unknown datablock %08lx\n", dwSig); + } + *ppDataBlock = block; + return r; } static HRESULT WINAPI @@ -2260,8 +2293,26 @@ ShellLink_RemoveDataBlock( IShellLinkDataList* iface, DWORD dwSig ) static HRESULT WINAPI ShellLink_GetFlags( IShellLinkDataList* iface, DWORD* pdwFlags ) { - FIXME("\n"); - return E_NOTIMPL; + IShellLinkImpl *This = impl_from_IShellLinkDataList(iface); + DWORD flags = 0; + + FIXME("%p %p\n", This, pdwFlags ); + + /* FIXME: add more */ + if (This->sArgs) + flags |= SLDF_HAS_ARGS; + if (This->sComponent) + flags |= SLDF_HAS_DARWINID; + if (This->sIcoPath) + flags |= SLDF_HAS_ICONLOCATION; + if (This->sProduct) + flags |= SLDF_HAS_LOGO3ID; + if (This->pPidl) + flags |= SLDF_HAS_ID_LIST; + + *pdwFlags = flags; + + return S_OK; } static HRESULT WINAPI diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index af0c9b760cc..7d45ef39664 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -511,6 +511,78 @@ static void test_load_save(void) ok(r, "failed to delete link (%ld)\n", GetLastError()); } +static void test_datalink(void) +{ + static const WCHAR lnk[] = { + ':',':','{','9','d','b','1','1','8','6','f','-','4','0','d','f','-','1', + '1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7', + '8','6','3','}',':','{','0','0','0','1','0','4','0','9','-','7','8','E', + '1','-','1','1','D','2','-','B','6','0','F','-','0','0','6','0','9','7', + 'C','9','9','8','E','7','}',':',':','{','9','d','b','1','1','8','6','e', + '-','4','0','d','f','-','1','1','d','1','-','a','a','8','c','-','0','0', + 'c','0','4','f','b','6','7','8','6','3','}',':','2','6',',','!','!','g', + 'x','s','f','(','N','g',']','q','F','`','H','{','L','s','A','C','C','E', + 'S','S','F','i','l','e','s','>','p','l','T',']','j','I','{','j','f','(', + '=','1','&','L','[','-','8','1','-',']',':',':',0 }; + static const WCHAR comp[] = { + '2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{', + 'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']', + 'j','I','{','j','f','(','=','1','&','L','[','-','8','1','-',']',0 }; + IShellLinkDataList *dl = NULL; + IShellLinkW *sl = NULL; + HRESULT r; + DWORD flags = 0; + EXP_DARWIN_LINK *dar; + + r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkW, (LPVOID*)&sl ); + ok( r == S_OK, "no shelllink\n"); + if (!sl) + return; + + r = IShellLinkW_QueryInterface( sl, &IID_IShellLinkDataList, (LPVOID*) &dl ); + ok(r == S_OK, "no datalink interface\n"); + + if (!dl) + return; + + flags = 0; + r = dl->lpVtbl->GetFlags( dl, &flags ); + ok( r == S_OK, "GetFlags failed\n"); + ok( flags == 0, "GetFlags returned wrong flags\n"); + + dar = (void*)-1; + r = dl->lpVtbl->CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar ); + ok( r == E_FAIL, "CopyDataBlock failed\n"); + ok( dar == NULL, "should be null\n"); + + r = IShellLinkW_SetPath(sl, lnk); + ok(r == S_OK, "set path failed\n"); + + /* + * The following crashes: + * r = dl->lpVtbl->GetFlags( dl, NULL ); + */ + + flags = 0; + r = dl->lpVtbl->GetFlags( dl, &flags ); + ok( r == S_OK, "GetFlags failed\n"); + ok( flags == (SLDF_HAS_DARWINID|SLDF_HAS_LOGO3ID), + "GetFlags returned wrong flags\n"); + + dar = NULL; + r = dl->lpVtbl->CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar ); + ok( r == S_OK, "CopyDataBlock failed\n"); + + ok( dar && dar->dbh.dwSignature == EXP_DARWIN_ID_SIG, "signature wrong\n"); + ok( dar && 0==lstrcmpW(dar->szwDarwinID, comp ), "signature wrong\n"); + + LocalFree( dar ); + + IUnknown_Release( dl ); + IShellLinkW_Release( sl ); +} + START_TEST(shelllink) { HRESULT r; @@ -522,6 +594,7 @@ START_TEST(shelllink) test_get_set(); test_load_save(); + test_datalink(); CoUninitialize(); }