(main): Try using COM to create start menu shortcuts

before resorting to DDE (Bug#202)
Remove second command-line argument.
This commit is contained in:
Jason Rumney 2009-01-15 15:03:15 +00:00
parent 7feadb909b
commit 84ef4ca220
2 changed files with 131 additions and 33 deletions

View file

@ -1,3 +1,9 @@
2009-01-15 Jason Rumney <jasonr@gnu.org>
* addpm.c (main): Try using COM to create start menu shortcuts
before resorting to DDE (Bug#202)
Remove second command-line argument.
2009-01-03 Juanma Barranquero <lekktu@gmail.com>
* configure.bat: Untabify help message.

View file

@ -23,10 +23,24 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
*
* Usage:
* argv[1] = install path for emacs
* argv[2] = full path to icon for emacs (optional)
*
* argv[2] used to be an optional argument for setting the icon.
* But now Emacs has a professional looking icon of its own.
* If users really want to change it, they can go into the settings of
* the shortcut that is created and do it there.
*/
/* Use parts of shell API that were introduced by the merge of IE4
into the desktop shell. If Windows 95 or NT4 users do not have IE4
installed, then the DDE fallback for creating icons the Windows 3.1
progman way will be used instead, but that is prone to lockups
caused by other applications not servicing their message queues. */
#define _WIN32_IE 0x400
/* Request C Object macros for COM interfaces. */
#define COBJMACROS 1
#include <windows.h>
#include <shlobj.h>
#include <ddeml.h>
#include <stdlib.h>
#include <stdio.h>
@ -41,7 +55,7 @@ DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
}
#define DdeCommand(str) \
DdeClientTransaction (str, strlen (str)+1, HConversation, (HSZ)NULL, \
DdeClientTransaction (str, strlen (str)+1, conversation, (HSZ)NULL, \
CF_TEXT, XTYP_EXECUTE, 30000, NULL)
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
@ -165,24 +179,18 @@ main (argc, argv)
int argc;
char *argv[];
{
DWORD idDde = 0;
HCONV HConversation;
HSZ ProgMan;
char start_folder[MAX_PATH + 1];
int shortcuts_created = 0;
int com_available = 1;
char modname[MAX_PATH];
char additem[MAX_PATH*2 + 100];
char *prog_name;
char *emacs_path;
char *p;
int quiet = 0;
HRESULT result;
IShellLinkA *shortcut;
/* If no args specified, use our location to set emacs_path. */
#if 0
if (argc < 2 || argc > 3)
{
fprintf (stderr, "usage: addpm [-q] [emacs_path [icon_path]]\n");
exit (1);
}
#endif
if (argc > 1
&& (argv[1][0] == '/' || argv[1][0] == '-')
@ -213,7 +221,7 @@ main (argc, argv)
}
else
{
fprintf (stderr, "usage: addpm emacs_path [icon_path]\n");
fprintf (stderr, "usage: addpm emacs_path\n");
exit (1);
}
@ -237,31 +245,115 @@ main (argc, argv)
add_registry (emacs_path);
prog_name = "runemacs.exe";
DdeInitialize (&idDde, (PFNCALLBACK)DdeCallback, APPCMD_CLIENTONLY, 0);
/* Try to install globally. */
ProgMan = DdeCreateStringHandle (idDde, "PROGMAN", CP_WINANSI);
HConversation = DdeConnect (idDde, ProgMan, ProgMan, NULL);
if (HConversation != 0)
if (!SUCCEEDED (CoInitialize (NULL))
|| !SUCCEEDED (CoCreateInstance (&CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, &IID_IShellLinkA,
(void **) &shortcut)))
{
DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
DdeCommand ("[ReplaceItem (Emacs)]");
if (argc > 2)
sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs, \"%s\")]",
emacs_path, prog_name, argv[2]);
else
sprintf (additem, "[AddItem (\"%s\\bin\\%s\", Emacs)]",
emacs_path, prog_name);
DdeCommand (additem);
DdeDisconnect (HConversation);
com_available = 0;
}
DdeFreeStringHandle (idDde, ProgMan);
if (com_available
&& SHGetSpecialFolderPath (NULL, start_folder, CSIDL_COMMON_PROGRAMS, 0))
{
if (strlen (start_folder) < (MAX_PATH - 20))
{
BOOL retval;
DdeUninitialize (idDde);
strcat (start_folder, "\\Gnu Emacs");
if (CreateDirectory (start_folder, NULL)
|| GetLastError () == ERROR_ALREADY_EXISTS)
{
char full_emacs_path[MAX_PATH + 1];
IPersistFile *lnk;
strcat (start_folder, "\\Emacs.lnk");
sprintf (full_emacs_path, "%s\\bin\\%s", emacs_path, prog_name);
IShellLinkA_SetPath (shortcut, full_emacs_path);
IShellLinkA_SetDescription (shortcut, "GNU Emacs");
result = IShellLinkA_QueryInterface (shortcut, &IID_IPersistFile,
(void **) &lnk);
if (SUCCEEDED (result))
{
wchar_t unicode_path[MAX_PATH];
MultiByteToWideChar (CP_ACP, 0, start_folder, -1,
unicode_path, MAX_PATH);
if (SUCCEEDED (IPersistFile_Save (lnk, unicode_path, TRUE)))
shortcuts_created = 1;
IPersistFile_Release (lnk);
}
}
}
}
return (0);
if (!shortcuts_created && com_available
&& SHGetSpecialFolderPath (NULL, start_folder, CSIDL_PROGRAMS, 0))
{
/* Ensure there is enough room for "...\GNU Emacs\Emacs.lnk". */
if (strlen (start_folder) < (MAX_PATH - 20))
{
BOOL retval;
strcat (start_folder, "\\Gnu Emacs");
if (CreateDirectory (start_folder, NULL)
|| GetLastError () == ERROR_ALREADY_EXISTS)
{
char full_emacs_path[MAX_PATH + 1];
IPersistFile *lnk;
strcat (start_folder, "\\Emacs.lnk");
sprintf (full_emacs_path, "%s\\bin\\%s", emacs_path, prog_name);
IShellLinkA_SetPath (shortcut, full_emacs_path);
IShellLinkA_SetDescription (shortcut, "GNU Emacs");
result = IShellLinkA_QueryInterface (shortcut, &IID_IPersistFile,
(void **) &lnk);
if (SUCCEEDED (result))
{
wchar_t unicode_path[MAX_PATH];
MultiByteToWideChar (CP_ACP, 0, start_folder, -1,
unicode_path, MAX_PATH);
if (SUCCEEDED (IPersistFile_Save (lnk, unicode_path, TRUE)))
shortcuts_created = 1;
IPersistFile_Release (lnk);
}
}
}
}
if (com_available)
IShellLinkA_Release (shortcut);
/* Need to call uninitialize, even if ComInitialize failed. */
CoUninitialize ();
/* Fallback on old DDE method if the above failed. */
if (!shortcuts_created)
{
DWORD dde = 0;
HCONV conversation;
HSZ progman;
char add_item[MAX_PATH*2 + 100];
DdeInitialize (&dde, (PFNCALLBACK) DdeCallback, APPCMD_CLIENTONLY, 0);
progman = DdeCreateStringHandle (dde, "PROGMAN", CP_WINANSI);
conversation = DdeConnect (dde, progman, progman, NULL);
if (conversation)
{
DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
DdeCommand ("[ReplaceItem (Emacs)]");
sprintf (add_item, "[AddItem (\"%s\\bin\\%s\", Emacs)]",
emacs_path, prog_name);
DdeCommand (add_item);
DdeDisconnect (conversation);
}
DdeFreeStringHandle (dde, progman);
DdeUninitialize (dde);
}
return 0;
}
/* arch-tag: f923609d-b781-4ef4-abce-ca0da29cbbf0