Vincent Povirk : setupapi: Implement ProfileItems directive.

Alexandre Julliard julliard at winehq.org
Wed Nov 5 09:38:11 CST 2008


Module: wine
Branch: master
Commit: 6c380468d955d74dd24e9d35e9b38fdf29d685db
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6c380468d955d74dd24e9d35e9b38fdf29d685db

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Fri Oct 31 10:34:16 2008 -0500

setupapi: Implement ProfileItems directive.

---

 dlls/setupapi/Makefile.in     |    2 +-
 dlls/setupapi/install.c       |  108 ++++++++++++++++++++++++++++++++++++++++-
 dlls/setupapi/tests/install.c |    6 +-
 3 files changed, 111 insertions(+), 5 deletions(-)

diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in
index 1f633a4..91bc87b 100644
--- a/dlls/setupapi/Makefile.in
+++ b/dlls/setupapi/Makefile.in
@@ -6,7 +6,7 @@ VPATH     = @srcdir@
 MODULE    = setupapi.dll
 IMPORTLIB = setupapi
 IMPORTS   = uuid user32 version advapi32 rpcrt4 kernel32 ntdll
-DELAYIMPORTS = shell32 wintrust
+DELAYIMPORTS = shell32 wintrust ole32
 
 C_SRCS = \
 	devinst.c \
diff --git a/dlls/setupapi/install.c b/dlls/setupapi/install.c
index 321d4d4..0a4db4f 100644
--- a/dlls/setupapi/install.c
+++ b/dlls/setupapi/install.c
@@ -20,6 +20,8 @@
 
 #include <stdarg.h>
 
+#define COBJMACROS
+
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
@@ -29,6 +31,9 @@
 #include "winuser.h"
 #include "winnls.h"
 #include "winsvc.h"
+#include "shlobj.h"
+#include "objidl.h"
+#include "objbase.h"
 #include "setupapi.h"
 #include "setupapi_private.h"
 #include "wine/unicode.h"
@@ -79,6 +84,9 @@ static const WCHAR UpdateIniFields[] = {'U','p','d','a','t','e','I','n','i','F',
 static const WCHAR RegisterDlls[]    = {'R','e','g','i','s','t','e','r','D','l','l','s',0};
 static const WCHAR UnregisterDlls[]  = {'U','n','r','e','g','i','s','t','e','r','D','l','l','s',0};
 static const WCHAR ProfileItems[]    = {'P','r','o','f','i','l','e','I','t','e','m','s',0};
+static const WCHAR Name[]            = {'N','a','m','e',0};
+static const WCHAR CmdLine[]         = {'C','m','d','L','i','n','e',0};
+static const WCHAR SubDir[]          = {'S','u','b','D','i','r',0};
 static const WCHAR WineFakeDlls[]    = {'W','i','n','e','F','a','k','e','D','l','l','s',0};
 static const WCHAR DisplayName[]     = {'D','i','s','p','l','a','y','N','a','m','e',0};
 static const WCHAR Description[]     = {'D','e','s','c','r','i','p','t','i','o','n',0};
@@ -775,7 +783,105 @@ static BOOL bitreg_callback( HINF hinf, PCWSTR field, void *arg )
 
 static BOOL profile_items_callback( HINF hinf, PCWSTR field, void *arg )
 {
-    FIXME( "should do profile items %s\n", debugstr_w(field) );
+    WCHAR lnkpath[MAX_PATH];
+    LPWSTR cmdline=NULL, lnkpath_end;
+    unsigned int name_size;
+    INFCONTEXT name_context, context;
+    IShellLinkW* shelllink=NULL;
+    IPersistFile* persistfile=NULL;
+    int attrs=0;
+
+    static const WCHAR dotlnk[] = {'.','l','n','k',0};
+
+    TRACE( "(%s)\n", debugstr_w(field) );
+
+    if (SetupFindFirstLineW( hinf, field, Name, &name_context ))
+    {
+        SetupGetIntField( &name_context, 2, &attrs );
+        if (attrs) FIXME( "unhandled attributes: %x\n", attrs );
+    }
+    else return TRUE;
+
+    /* calculate filename */
+    SHGetFolderPathW( NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, lnkpath );
+    lnkpath_end = lnkpath + strlenW(lnkpath);
+    if (lnkpath_end[-1] != '\\') *lnkpath_end++ = '\\';
+
+    if (SetupFindFirstLineW( hinf, field, SubDir, &context ))
+    {
+        unsigned int subdir_size;
+
+        if (!SetupGetStringFieldW( &context, 1, lnkpath_end, (lnkpath+MAX_PATH)-lnkpath_end, &subdir_size ))
+            return TRUE;
+
+        lnkpath_end += subdir_size - 1;
+        if (lnkpath_end[-1] != '\\') *lnkpath_end++ = '\\';
+    }
+
+    if (!SetupGetStringFieldW( &name_context, 1, lnkpath_end, (lnkpath+MAX_PATH)-lnkpath_end, &name_size ))
+        return TRUE;
+
+    lnkpath_end += name_size - 1;
+    if (lnkpath+MAX_PATH < lnkpath_end + 5) return TRUE;
+    strcpyW( lnkpath_end, dotlnk );
+
+    TRACE( "link path: %s\n", debugstr_w(lnkpath) );
+
+    /* calculate command line */
+    if (SetupFindFirstLineW( hinf, field, CmdLine, &context ))
+    {
+        unsigned int dir_len=0, subdir_size=0, filename_size=0;
+        int dirid=0;
+        LPCWSTR dir;
+        LPWSTR cmdline_end;
+
+        SetupGetIntField( &context, 1, &dirid );
+        dir = DIRID_get_string( dirid );
+
+        if (dir) dir_len = strlenW(dir);
+
+        SetupGetStringFieldW( &context, 2, NULL, 0, &subdir_size );
+        SetupGetStringFieldW( &context, 3, NULL, 0, &filename_size );
+
+        if (dir_len && filename_size)
+        {
+            cmdline = cmdline_end = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * (dir_len+subdir_size+filename_size+1) );
+
+            strcpyW( cmdline_end, dir );
+            cmdline_end += dir_len;
+            if (cmdline_end[-1] != '\\') *cmdline_end++ = '\\';
+
+            if (subdir_size)
+            {
+                SetupGetStringFieldW( &context, 2, cmdline_end, subdir_size, NULL );
+                cmdline_end += subdir_size-1;
+                if (cmdline_end[-1] != '\\') *cmdline_end++ = '\\';
+            }
+            SetupGetStringFieldW( &context, 3, cmdline_end, filename_size, NULL );
+            TRACE( "cmdline: %s\n", debugstr_w(cmdline));
+        }
+    }
+
+    if (!cmdline) return TRUE;
+
+    CoInitialize(NULL);
+
+    if (!SUCCEEDED(CoCreateInstance( &CLSID_ShellLink, NULL,
+                                     CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&shelllink)))
+        goto done;
+
+    IShellLinkW_SetPath( shelllink, cmdline );
+    SHPathPrepareForWriteW( NULL, NULL, lnkpath, SHPPFW_DIRCREATE|SHPPFW_IGNOREFILENAME );
+    if (SUCCEEDED(IShellLinkW_QueryInterface( shelllink, &IID_IPersistFile, (LPVOID*)&persistfile)))
+    {
+        TRACE( "writing link: %s\n", debugstr_w(lnkpath) );
+        IPersistFile_Save( persistfile, lnkpath, FALSE );
+        IPersistFile_Release( persistfile );
+    }
+    IShellLinkW_Release( shelllink );
+
+done:
+    HeapFree( GetProcessHeap(), 0, cmdline );
     return TRUE;
 }
 
diff --git a/dlls/setupapi/tests/install.c b/dlls/setupapi/tests/install.c
index a340562..9be46fe 100644
--- a/dlls/setupapi/tests/install.c
+++ b/dlls/setupapi/tests/install.c
@@ -424,14 +424,14 @@ static void test_profile_items(void)
     snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);
     if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(path))
     {
-        todo_wine win_skip("ProfileItems not implemented on this system\n");
+        win_skip("ProfileItems not implemented on this system\n");
     }
     else
     {
         snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
-        todo_wine ok(INVALID_FILE_ATTRIBUTES != GetFileAttributes(path), "directory not created\n");
+        ok(INVALID_FILE_ATTRIBUTES != GetFileAttributes(path), "directory not created\n");
         snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs);
-        todo_wine ok(INVALID_FILE_ATTRIBUTES != GetFileAttributes(path), "link not created\n");
+        ok(INVALID_FILE_ATTRIBUTES != GetFileAttributes(path), "link not created\n");
     }
 
     snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);




More information about the wine-cvs mailing list