shell32: implement SHGetNewLinkInfo[AW]

Vincent Povirk madewokherd+8cd9 at gmail.com
Thu Apr 16 22:57:09 CDT 2009


fixes bug 8082

Vincent Povirk
-------------- next part --------------
From 5c68b34e2781d3cf12ae8e9986867aa2fd21a284 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <madewokherd at gmail.com>
Date: Thu, 16 Apr 2009 22:51:40 -0500
Subject: [PATCH] shell32: implement SHGetNewLinkInfo[AW]

---
 dlls/shell32/shellord.c        |   61 ++++++++++++++++++++++++++++++++++++---
 dlls/shell32/tests/shlfileop.c |   52 ++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c
index eaf2859..5eb4507 100644
--- a/dlls/shell32/shellord.c
+++ b/dlls/shell32/shellord.c
@@ -1914,19 +1914,70 @@ BOOL WINAPI SHObjectProperties(HWND hwnd, DWORD dwType, LPCWSTR szObject, LPCWST
 BOOL WINAPI SHGetNewLinkInfoA(LPCSTR pszLinkTo, LPCSTR pszDir, LPSTR pszName, BOOL *pfMustCopy,
                               UINT uFlags)
 {
-    FIXME("%s, %s, %p, %p, 0x%08x - stub\n", debugstr_a(pszLinkTo), debugstr_a(pszDir),
-          pszName, pfMustCopy, uFlags);
+    WCHAR wszLinkTo[MAX_PATH];
+    WCHAR wszDir[MAX_PATH];
+    WCHAR wszName[MAX_PATH];
+    BOOL res;
 
-    return FALSE;
+    MultiByteToWideChar(CP_ACP, 0, pszLinkTo, -1, wszLinkTo, MAX_PATH);
+    MultiByteToWideChar(CP_ACP, 0, pszDir, -1, wszDir, MAX_PATH);
+
+    res = SHGetNewLinkInfoW(wszLinkTo, wszDir, wszName, pfMustCopy, uFlags);
+
+    if (res)
+        WideCharToMultiByte(CP_ACP, 0, wszName, -1, pszName, MAX_PATH, NULL, NULL);
+
+    return res;
 }
 
 BOOL WINAPI SHGetNewLinkInfoW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, BOOL *pfMustCopy,
                               UINT uFlags)
 {
-    FIXME("%s, %s, %p, %p, 0x%08x - stub\n", debugstr_w(pszLinkTo), debugstr_w(pszDir),
+    const WCHAR *basename;
+    WCHAR *dst_basename;
+    int i=2;
+    static const WCHAR lnkformat[] = {'%','s','.','l','n','k',0};
+    static const WCHAR lnkformatnum[] = {'%','s',' ','(','%','d',')','.','l','n','k',0};
+
+    TRACE("(%s, %s, %p, %p, 0x%08x)\n", debugstr_w(pszLinkTo), debugstr_w(pszDir),
           pszName, pfMustCopy, uFlags);
 
-    return FALSE;
+    *pfMustCopy = FALSE;
+
+    if (uFlags & SHGNLI_PIDL)
+    {
+        FIXME("SHGNLI_PIDL flag unsupported\n");
+        return FALSE;
+    }
+
+    if (uFlags)
+        FIXME("ignoring flags: 0x%08x\n", uFlags);
+
+    /* FIXME: should test if the file is a shortcut or DOS program */
+    if (GetFileAttributesW(pszLinkTo) == INVALID_FILE_ATTRIBUTES)
+        return FALSE;
+
+    basename = strrchrW(pszLinkTo, '\\');
+    if (basename)
+        basename = basename+1;
+    else
+        basename = pszLinkTo;
+
+    lstrcpynW(pszName, pszDir, MAX_PATH);
+    if (!PathAddBackslashW(pszName))
+        return FALSE;
+
+    dst_basename = pszName + strlenW(pszName);
+
+    snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformat, basename);
+
+    while (GetFileAttributesW(pszName) != INVALID_FILE_ATTRIBUTES)
+    {
+        snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformatnum, basename, i);
+        i++;
+    }
+
+    return TRUE;
 }
 
 HRESULT WINAPI SHStartNetConnectionDialog(HWND hwnd, LPCSTR pszRemoteName, DWORD dwType)
diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c
index 433a131..46fc22d 100644
--- a/dlls/shell32/tests/shlfileop.c
+++ b/dlls/shell32/tests/shlfileop.c
@@ -2051,6 +2051,54 @@ static void test_sh_path_prepare(void)
     RemoveDirectoryW(UNICODE_PATH);
 }
 
+static void test_sh_new_link_info(void)
+{
+    BOOL ret, mustcopy=TRUE;
+    CHAR linkto[MAX_PATH];
+    CHAR destdir[MAX_PATH];
+    CHAR result[MAX_PATH];
+    CHAR result2[MAX_PATH];
+
+    /* source file does not exist */
+    set_curr_dir_path(linkto, "nosuchfile.txt\0");
+    set_curr_dir_path(destdir, "testdir2\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == FALSE, "SHGetNewLinkInfoA succeeded\n");
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+
+    /* dest dir does not exist */
+    set_curr_dir_path(linkto, "test1.txt\0");
+    set_curr_dir_path(destdir, "nosuchdir\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == TRUE, "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+
+    /* source file exists */
+    set_curr_dir_path(linkto, "test1.txt\0");
+    set_curr_dir_path(destdir, "testdir2\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == TRUE, "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+    ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir, 
+                      lstrlenA(destdir), result, lstrlenA(destdir)) == CSTR_EQUAL,
+       "%s does not start with %s\n", result, destdir);
+    ok(lstrlenA(result) > 4 && lstrcmpiA(result+lstrlenA(result)-4, ".lnk") == 0,
+       "%s does not end with .lnk\n", result);
+
+    /* preferred target name already exists */
+    createTestFile(result);
+    ret = SHGetNewLinkInfoA(linkto, destdir, result2, &mustcopy, 0);
+    ok(ret == TRUE, "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+    ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir, 
+                      lstrlenA(destdir), result2, lstrlenA(destdir)) == CSTR_EQUAL,
+       "%s does not start with %s\n", result2, destdir);
+    ok(lstrlenA(result2) > 4 && lstrcmpiA(result2+lstrlenA(result2)-4, ".lnk") == 0,
+       "%s does not end with .lnk\n", result2);
+    ok(lstrcmpiA(result, result2) != 0, "%s and %s are the same\n", result, result2);
+    DeleteFileA(result);
+}
+
 static void test_unicode(void)
 {
     SHFILEOPSTRUCTW shfoW;
@@ -2158,5 +2206,9 @@ START_TEST(shlfileop)
     test_sh_path_prepare();
     clean_after_shfo_tests();
 
+    init_shfo_tests();
+    test_sh_new_link_info();
+    clean_after_shfo_tests();
+
     test_unicode();
 }
-- 
1.5.4.3


More information about the wine-patches mailing list