Author: janderwald
Date: Fri Oct  5 03:51:10 2007
New Revision: 29393
URL: 
http://svn.reactos.org/svn/reactos?rev=29393&view=rev
Log:
- implement create shortcut wizard (works currently only for files)
Modified:
    trunk/reactos/dll/cpl/appwiz/appwiz.c
    trunk/reactos/dll/cpl/appwiz/appwiz.def
    trunk/reactos/dll/cpl/appwiz/appwiz.h
    trunk/reactos/dll/cpl/appwiz/appwiz.rbuild
    trunk/reactos/dll/cpl/appwiz/createlink.c
    trunk/reactos/dll/cpl/appwiz/lang/en-US.rc
    trunk/reactos/dll/cpl/appwiz/resource.h
Modified: trunk/reactos/dll/cpl/appwiz/appwiz.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/appwiz.c?re…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/appwiz.c (original)
+++ trunk/reactos/dll/cpl/appwiz/appwiz.c Fri Oct  5 03:51:10 2007
@@ -141,6 +141,7 @@
     {
         case DLL_PROCESS_ATTACH:
         case DLL_THREAD_ATTACH:
+            CoInitialize(NULL);
             hApplet = hinstDLL;
             break;
     }
Modified: trunk/reactos/dll/cpl/appwiz/appwiz.def
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/appwiz.def?…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/appwiz.def (original)
+++ trunk/reactos/dll/cpl/appwiz/appwiz.def Fri Oct  5 03:51:10 2007
@@ -3,5 +3,7 @@
 EXPORTS
 CPlApplet
 NewLinkHere
+NewLinkHereA
+NewLinkHereW
 ; EOF
Modified: trunk/reactos/dll/cpl/appwiz/appwiz.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/appwiz.h?re…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/appwiz.h (original)
+++ trunk/reactos/dll/cpl/appwiz/appwiz.h Fri Oct  5 03:51:10 2007
@@ -10,6 +10,15 @@
   int idDescription;
   CPLAPPLET_PROC AppletProc;
 } APPLET, *PAPPLET;
+
+typedef struct
+{
+   WCHAR szTarget[MAX_PATH];
+   WCHAR szWorkingDirectory[MAX_PATH];
+   WCHAR szDescription[MAX_PATH];
+   WCHAR szLinkName[MAX_PATH];
+}CREATE_LINK_CONTEXT, *PCREATE_LINK_CONTEXT;
+
 extern HINSTANCE hApplet;
Modified: trunk/reactos/dll/cpl/appwiz/appwiz.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/appwiz.rbui…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/appwiz.rbuild (original)
+++ trunk/reactos/dll/cpl/appwiz/appwiz.rbuild Fri Oct  5 03:51:10 2007
@@ -12,6 +12,9 @@
        <library>user32</library>
        <library>comctl32</library>
        <library>msvcrt</library>
+       <library>ole32</library>
+       <library>uuid</library>
+       <library>shell32</library>
        <file>appwiz.c</file>
        <file>remove.c</file>
        <file>add.c</file>
Modified: trunk/reactos/dll/cpl/appwiz/createlink.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/createlink.…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/createlink.c (original)
+++ trunk/reactos/dll/cpl/appwiz/createlink.c Fri Oct  5 03:51:10 2007
@@ -1,29 +1,10 @@
-/*
- *  ReactOS
- *  Copyright (C) 2004 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program 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 General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+
 /* $Id: appwiz.c 29364 2007-10-02 23:34:00Z janderwald $
  *
  * PROJECT:                    ReactOS Software Control Panel
- * FILE:                       dll/cpl/appwiz/appwiz.c
+ * FILE:                       dll/cpl/appwiz/createlink.c
  * PURPOSE:                    ReactOS Software Control Panel
- * PROGRAMMER:         Gero Kuehn (reactos.filter(a)gkware.com)
- * UPDATE HISTORY:
- *      06-17-2004  Created
+ * PROGRAMMER:             Johannes Anderwald
  */
 #include <windows.h>
@@ -35,9 +16,48 @@
 #include <stdarg.h>
 #include <tchar.h>
 #include <process.h>
-
+#include <shlobj.h>
+#include <objbase.h>
+#include <shobjidl.h>
+#include <shlguid.h>
+#include <stdio.h>
 #include "resource.h"
 #include "appwiz.h"
+
+
+BOOL
+CreateShortcut(PCREATE_LINK_CONTEXT pContext)
+{
+    IShellLinkW *pShellLink;
+    IPersistFile *pPersistFile;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_ALL,
+                   &IID_IShellLink, (void**)&pShellLink);
+
+    if (hr != S_OK)
+        return FALSE;
+
+
+    pShellLink->lpVtbl->SetPath(pShellLink, pContext->szTarget);
+    pShellLink->lpVtbl->SetDescription(pShellLink, pContext->szDescription);
+    pShellLink->lpVtbl->SetWorkingDirectory(pShellLink,
pContext->szWorkingDirectory);
+
+    hr = pShellLink->lpVtbl->QueryInterface(pShellLink, &IID_IPersistFile,
(void**)&pPersistFile);
+    if (hr != S_OK)
+    {
+        pShellLink->lpVtbl->Release(pShellLink);
+        return FALSE;
+    }
+
+    hr = pPersistFile->lpVtbl->Save(pPersistFile, pContext->szLinkName, TRUE);
+    pPersistFile->lpVtbl->Release(pPersistFile);
+    pShellLink->lpVtbl->Release(pShellLink);
+    return (hr == S_OK);
+}
+
+
+
 INT_PTR
 CALLBACK
@@ -46,9 +66,20 @@
                WPARAM wParam,
                LPARAM lParam)
 {
+    LPPROPSHEETPAGEW ppsp;
+    PCREATE_LINK_CONTEXT pContext;
+    LPPSHNOTIFY lppsn;
+    WCHAR szPath[MAX_PATH];
+    WCHAR szDesc[100];
+    BROWSEINFOW brws;
+    LPITEMIDLIST pidllist;
+
     switch(uMsg)
     {
         case WM_INITDIALOG:
+            ppsp = (LPPROPSHEETPAGEW)lParam;
+            pContext = (PCREATE_LINK_CONTEXT) ppsp->lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
             PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
             break;
         case WM_COMMAND:
@@ -63,8 +94,75 @@
                     {
                         PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
                     }
-            }
-
+                    break;
+            }
+            switch(LOWORD(wParam))
+            {
+                case IDC_SHORTCUT_BROWSE:
+                    brws.hwndOwner = hwndDlg;
+                    brws.pidlRoot = NULL;
+                    brws.pszDisplayName = szPath;
+                    brws.ulFlags = BIF_BROWSEINCLUDEFILES;
+                    brws.lpfn = NULL;
+                    pidllist = SHBrowseForFolder(&brws);
+                    if (!pidllist)
+                        break;
+
+                    if (SHGetPathFromIDList(pidllist, szPath))
+                        SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION, WM_SETTEXT, 0,
(LPARAM)szPath);
+
+                    break;
+            }
+            break;
+        case WM_NOTIFY:
+            lppsn  = (LPPSHNOTIFY) lParam;
+            if (lppsn->hdr.code == PSN_WIZNEXT)
+            {
+                pContext = (PCREATE_LINK_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
+                SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_LOCATION, WM_GETTEXT, MAX_PATH,
(LPARAM)pContext->szTarget);
+                ///
+                /// FIXME
+                /// it should also be possible to create a link to folders, shellobjects
etc....
+                ///
+                if (GetFileAttributesW(pContext->szTarget) == INVALID_FILE_ATTRIBUTES)
+                {
+                    szDesc[0] = L'\0';
+                    szPath[0] = L'\0';
+                    if (LoadStringW(hApplet, IDS_CREATE_SHORTCUT, szDesc, 100) < 100
&&
+                        LoadStringW(hApplet, IDS_ERROR_NOT_FOUND, szPath, MAX_PATH) <
MAX_PATH)
+                    {
+                        WCHAR szError[MAX_PATH + 100];
+#ifdef _MSC_VER
+                        _swprintf(szError, szPath, pContext->szTarget);
+#else
+                        swprintf(szError, szPath, pContext->szTarget);
+#endif
+                        MessageBoxW(hwndDlg, szError, szDesc, MB_ICONERROR);
+                    }
+                    SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION, EM_SETSEL, 0, -1);
+                    SetFocus(GetDlgItem(hwndDlg, IDC_SHORTCUT_LOCATION));
+                    SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
+                    return -1;
+                }
+                else
+                {
+                    WCHAR * first, *last;
+                    wcscpy(pContext->szWorkingDirectory, pContext->szTarget);
+                    first = wcschr(pContext->szWorkingDirectory, L'\\');
+                    last = wcsrchr(pContext->szWorkingDirectory, L'\\');
+                    wcscpy(pContext->szDescription, &last[1]);
+
+                    if (first != last)
+                        last[0] = L'\0';
+                    else
+                        first[1] = L'\0';
+
+                    first = wcsrchr(pContext->szDescription, L'.');
+                    first[0] = L'\0';
+                }
+
+            }
+            break;
     }
     return FALSE;
 }
@@ -76,23 +174,86 @@
                WPARAM wParam,
                LPARAM lParam)
 {
+    LPPROPSHEETPAGEW ppsp;
+    PCREATE_LINK_CONTEXT pContext;
+    LPPSHNOTIFY lppsn;
+
     switch(uMsg)
     {
         case WM_INITDIALOG:
+            ppsp = (LPPROPSHEETPAGEW)lParam;
+            pContext = (PCREATE_LINK_CONTEXT) ppsp->lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
+            SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_NAME, WM_SETTEXT, 0,
(LPARAM)pContext->szDescription);
             PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
             break;
+        case WM_COMMAND:
+            switch(HIWORD(wParam))
+            {
+                case EN_CHANGE:
+                    if (SendDlgItemMessage(hwndDlg, IDC_SHORTCUT_LOCATION,
WM_GETTEXTLENGTH, 0, 0))
+                    {
+                        PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK |
PSWIZB_FINISH);
+                    }
+                    else
+                    {
+                        PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
+                    }
+                    break;
+            }
+            break;
+        case WM_NOTIFY:
+            lppsn  = (LPPSHNOTIFY) lParam;
+            pContext = (PCREATE_LINK_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);
+            if (lppsn->hdr.code == PSN_WIZFINISH)
+            {
+                SendDlgItemMessageW(hwndDlg, IDC_SHORTCUT_NAME, WM_GETTEXT, MAX_PATH,
(LPARAM)pContext->szDescription);
+                wcscat(pContext->szLinkName, pContext->szDescription);
+                wcscat(pContext->szLinkName, L".lnk");
+                if (!CreateShortcut(pContext))
+                {
+                    MessageBox(hwndDlg, _T("Failed to create shortcut"),
_T("Error"), MB_ICONERROR);
+                }
+            }
+
+
     }
     return FALSE;
 }
-
 LONG CALLBACK
-NewLinkHere(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+ShowCreateShortcutWizard(HWND hwndCPl, LPWSTR szPath)
 {
     PROPSHEETHEADERW psh;
     HPROPSHEETPAGE ahpsp[2];
     PROPSHEETPAGE psp;
     UINT nPages = 0;
+    UINT nLength;
+
+    PCREATE_LINK_CONTEXT pContext = (PCREATE_LINK_CONTEXT) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(CREATE_LINK_CONTEXT));
+    if (!pContext)
+    {
+       /* no memory */
+       return FALSE;
+    }
+    nLength = wcslen(szPath);
+    if (!nLength)
+    {
+        /* no directory given */
+        return FALSE;
+    }
+    ///
+    /// FIXME
+    /// check if path is valid
+    ///
+
+    wcscpy(pContext->szLinkName, szPath);
+    if (pContext->szLinkName[nLength-1] != L'\\')
+    {
+        pContext->szLinkName[nLength] = L'\\';
+        pContext->szLinkName[nLength+1] = L'\0';
+    }
+
     /* Create the Welcome page */
     psp.dwSize = sizeof(PROPSHEETPAGE);
@@ -100,6 +261,7 @@
     psp.hInstance = hApplet;
     psp.pfnDlgProc = WelcomeDlgProc;
     psp.pszTemplate = MAKEINTRESOURCE(IDD_SHORTCUT_LOCATION);
+    psp.lParam = (LPARAM)pContext;
     ahpsp[nPages++] = CreatePropertySheetPage(&psp);
     /* Create the Finish page */
@@ -121,6 +283,41 @@
     /* Display the wizard */
     PropertySheet(&psh);
-
+    HeapFree(GetProcessHeap(), 0, pContext);
     return TRUE;
 }
+
+
+LONG
+CALLBACK
+NewLinkHere(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+    WCHAR szFile[MAX_PATH];
+
+    if (MultiByteToWideChar(CP_ACP, 0, (char*)lParam1, strlen((char*)lParam1)+1, szFile,
MAX_PATH))
+    {
+        return ShowCreateShortcutWizard(hwndCPl, szFile);
+    }
+    return -1;
+}
+
+
+LONG
+CALLBACK
+NewLinkHereW(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+    return ShowCreateShortcutWizard(hwndCPl, (LPWSTR)lParam1);
+}
+
+LONG
+CALLBACK
+NewLinkHereA(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
+{
+    WCHAR szFile[MAX_PATH];
+
+    if (MultiByteToWideChar(CP_ACP, 0, (char*)lParam1, strlen((char*)lParam1)+1, szFile,
MAX_PATH))
+    {
+        return ShowCreateShortcutWizard(hwndCPl, szFile);
+    }
+    return -1;
+}
Modified: trunk/reactos/dll/cpl/appwiz/lang/en-US.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/lang/en-US.…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/lang/en-US.rc (original)
+++ trunk/reactos/dll/cpl/appwiz/lang/en-US.rc Fri Oct  5 03:51:10 2007
@@ -97,4 +97,6 @@
        IDS_LARGEICONS "Large Icons"
        IDS_LIST "List"
        IDS_DETAILS "Details"
+    IDS_CREATE_SHORTCUT "Create Shortcut"
+    IDS_ERROR_NOT_FOUND "The file %s was not found."
 END
Modified: trunk/reactos/dll/cpl/appwiz/resource.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/cpl/appwiz/resource.h?…
==============================================================================
--- trunk/reactos/dll/cpl/appwiz/resource.h (original)
+++ trunk/reactos/dll/cpl/appwiz/resource.h Fri Oct  5 03:51:10 2007
@@ -40,6 +40,8 @@
 #define IDS_LARGEICONS                         2007
 #define IDS_LIST                                       2008
 #define IDS_DETAILS                                    2009
+#define IDS_CREATE_SHORTCUT         2010
+#define IDS_ERROR_NOT_FOUND         2011
 /* controls */
 #define IDC_INSTALL                    101