--- /dev/null
+/* \r
+ * readshortcut for cygwin/windows\r
+ *\r
+ * Copyright (C) 2003 Rob Siklos\r
+ * http://www.cygwin.com/ml/cygwin/2003-08/msg00640.html\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation in version 2 of the License.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ */\r
+ \r
+\r
+ \r
+ /* http://www.rpm.org/dark_corners/popt/\r
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/shortcuts/shortcut.asp\r
+ */\r
+\r
+/* how to compile a standalone version:\r
+ *\r
+ * - comment the config.h and common.h includes\r
+ * - uncomment the stdio and popt.h includes\r
+ * - run "gcc readshortcut.c -o readshortcut.exe -lpopt -luuid -lole32" \r
+ *\r
+ */\r
+\r
+\r
+#if HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+#include "common.h"\r
+\r
+/* moved to common.h */\r
+/*\r
+#include <stdio.h>\r
+#include <popt.h>\r
+*/\r
+\r
+#include <shlobj.h>\r
+#include <olectlid.h>\r
+\r
+#define PATH_UNIX 0\r
+#define PATH_WIN 1\r
+\r
+#define ERR_NONE 0\r
+#define ERR_USER 1\r
+#define ERR_SYS 2\r
+#define ERR_WIN 3\r
+\r
+#define SLGP_RAWPATH 0\r
+#define SW_SHOWMINIMIZED_SEVEN 7\r
+\r
+#define BUFF_SIZE 1024\r
+\r
+static const char versionID[] = "1.0";\r
+\r
+typedef struct optvals_s {\r
+ char * target_fname; \r
+\r
+ int show_field_names;\r
+ int pathType;\r
+ \r
+ int show_target;\r
+ int show_working_dir;\r
+ int show_args;\r
+ int show_showCmd;\r
+ int show_icon;\r
+ int show_icon_offset;\r
+ int show_desc;\r
+ int show_all;\r
+\r
+} optvals;\r
+\r
+void cygwin_conv_to_full_win32_path(const char *path, char *win32_path);\r
+void cygwin_conv_to_full_posix_path(const char *path, char *posix_path);\r
+\r
+static void printTopDescription(FILE * f, char * name);\r
+static void printBottomDescription(FILE * f, char * name);\r
+static const char * getVersion(void);\r
+static void usage(poptContext optCon, FILE * f, char * name);\r
+static void help(poptContext optCon, FILE * f, char * name);\r
+static void version(poptContext optCon, FILE * f, char * name);\r
+static void license(poptContext optCon, FILE * f, char * name);\r
+\r
+void formatPath (char * strPath, int format);\r
+int readshortcut(optvals opts, poptContext optContext);\r
+\r
+static char *program_name;\r
+\r
+int main (int argc, const char **argv) {\r
+ poptContext optContext;\r
+ const char ** loose_args;\r
+ int rc;\r
+ int result = ERR_NONE;\r
+ optvals opts;\r
+ const char *tmp_str;\r
+\r
+ struct poptOption infoOptionsTable[] = {\r
+ { "help", 'h', POPT_ARG_NONE, NULL, '?', "This message", NULL},\r
+ { "usage", '\0', POPT_ARG_NONE, NULL, 'u', "Program usage", NULL},\r
+ { "version", 'v', POPT_ARG_NONE, NULL, 'v', "Version information", NULL},\r
+ { "license", '\0', POPT_ARG_NONE, NULL, 'l', "License information", NULL},\r
+ { NULL, '\0', 0, NULL, 0, NULL, NULL }\r
+ };\r
+\r
+ struct poptOption outputOptionsTable[] = {\r
+ { "fields", 'f', POPT_ARG_VAL, &(opts.show_field_names), 1, "Show field names", NULL},\r
+ { "unix", 'u', POPT_ARG_VAL, &(opts.pathType), PATH_UNIX, "Use Unix path format for display (default)", NULL},\r
+ { "windows", 'w', POPT_ARG_VAL, &(opts.pathType), PATH_WIN, "Use Windows path format for display ", NULL},\r
+ { "target", 't', POPT_ARG_VAL, &(opts.show_target), 1, "Display shortcut target", NULL},\r
+ { "working", 'g', POPT_ARG_VAL, &(opts.show_working_dir), 1, "Display shortcut working directory", NULL},\r
+ { "args", 'r', POPT_ARG_VAL, &(opts.show_args), 1, "Display shortcut arguments", NULL},\r
+ { "showcmd", 's', POPT_ARG_VAL, &(opts.show_showCmd), 1, "Display shortcut \"show\" command value", NULL},\r
+ { "icon", 'i', POPT_ARG_VAL, &(opts.show_icon), 1, "Display icon library location", NULL},\r
+ { "offset", 'j', POPT_ARG_VAL, &(opts.show_icon_offset), 1, "Display icon library offset", NULL},\r
+ { "desc", 'd', POPT_ARG_VAL, &(opts.show_desc), 1, "Display shortcut description", NULL},\r
+ { "all", 'a', POPT_ARG_VAL, &(opts.show_all), 1, "Display all information", NULL},\r
+ { NULL, '\0', 0, NULL, 0, NULL, NULL }\r
+ };\r
+ \r
+ struct poptOption opt[] = {\r
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, outputOptionsTable, 0, "Output options", NULL },\r
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, infoOptionsTable, 0, "Information options (display a message and exit)", NULL },\r
+ { NULL, '\0', 0, NULL, 0, NULL, NULL }\r
+ };\r
+\r
+ /* get the program name */\r
+ tmp_str = strrchr (argv[0], '/');\r
+ if (tmp_str == NULL) { tmp_str = strrchr (argv[0], '\\'); }\r
+ if (tmp_str == NULL) { tmp_str = argv[0]; }\r
+ else { tmp_str++; }\r
+ if ((program_name = strdup(tmp_str)) == NULL ) {\r
+ fprintf(stderr, "%s: memory allocation error\n", argv[0]);\r
+ exit(ERR_SYS);\r
+ }\r
+\r
+ /* set default values for options */\r
+ opts.target_fname = NULL;\r
+\r
+ opts.show_field_names = 0;\r
+ opts.pathType = PATH_UNIX;\r
+ \r
+ opts.show_target = 0;\r
+ opts.show_working_dir = 0;\r
+ opts.show_args = 0;\r
+ opts.show_showCmd = 0;\r
+ opts.show_icon = 0;\r
+ opts.show_icon_offset = 0;\r
+ opts.show_desc = 0;\r
+ opts.show_all = 0;\r
+\r
+ /* set the pOpt context and help line */\r
+ optContext = poptGetContext(NULL, argc, argv, opt, 0);\r
+ poptSetOtherOptionHelp(optContext, "[OPTION]* SHORTCUT");\r
+ \r
+ while ((rc = poptGetNextOpt(optContext)) > 0) {\r
+ switch (rc) {\r
+ case '?':\r
+ help(optContext, stdout, program_name);\r
+ goto exit;\r
+ case 'u':\r
+ usage(optContext, stdout, program_name);\r
+ goto exit;\r
+ case 'v':\r
+ version(optContext, stdout, program_name);\r
+ goto exit;\r
+ case 'l':\r
+ license(optContext, stdout, program_name);\r
+ goto exit;\r
+ }\r
+ }\r
+ \r
+ // set show_target by default\r
+ if (!(opts.show_all + opts.show_target + opts.show_working_dir + opts.show_args + \r
+ opts.show_showCmd + opts.show_icon + opts.show_icon_offset + \r
+ opts.show_desc)) { opts.show_target = 1; }\r
+\r
+ /* get the remaining arguments */\r
+ loose_args = poptGetArgs(optContext);\r
+\r
+ if (loose_args && *loose_args) {\r
+ if ((opts.target_fname = strdup(*loose_args)) == NULL) {\r
+ fprintf(stderr, "%s: memory allocation error\n", program_name);\r
+ result = ERR_SYS;\r
+ goto exit;\r
+ }\r
+ loose_args++;\r
+ if (loose_args && *loose_args) {\r
+ fprintf(stderr, "%s: Too many arguments: ", program_name);\r
+ while (*loose_args) { fprintf(stderr, "%s ", *loose_args++); }\r
+ fprintf(stderr, "\n"); \r
+ usage(optContext, stderr, program_name);\r
+ result = ERR_USER;\r
+ } else {\r
+ /************** Main Program ***********/\r
+ result = readshortcut(opts, optContext);\r
+ } \r
+ } else {\r
+ fprintf(stderr, "%s: SHORTCUT not specified\n", program_name);\r
+ usage(optContext, stderr, program_name);\r
+ result = ERR_USER;\r
+ }\r
+\r
+exit:\r
+ poptFreeContext(optContext);\r
+ free(program_name);\r
+ free(opts.target_fname);\r
+ return result;\r
+}\r
+\r
+int readshortcut(optvals opts, poptContext optContext) {\r
+ HRESULT hres;\r
+ IShellLink *shell_link;\r
+ IPersistFile *persist_file;\r
+ char strPath[MAX_PATH]; \r
+ char strBuff[BUFF_SIZE];\r
+ int iBuff;\r
+\r
+ int result = ERR_NONE; /* the value to return on exit */\r
+ \r
+ /* Add suffix to link name if necessary */\r
+ if (strlen (opts.target_fname) > 4) {\r
+ int tmp = strlen (opts.target_fname) - 4;\r
+ if (strncmp (opts.target_fname + tmp, ".lnk", 4) != 0) {\r
+ opts.target_fname = (char *)realloc(opts.target_fname, strlen(opts.target_fname) + 1 + 4);\r
+ if (opts.target_fname == NULL) {\r
+ fprintf(stderr, "%s: memory allocation error\n", program_name);\r
+ return (ERR_SYS);\r
+ }\r
+ strcat (opts.target_fname, ".lnk");\r
+ }\r
+ }\r
+ else {\r
+ opts.target_fname = (char *)realloc(opts.target_fname, strlen(opts.target_fname) + 1 + 4);\r
+ if (opts.target_fname == NULL) {\r
+ fprintf(stderr, "%s: memory allocation error\n", program_name);\r
+ return (ERR_SYS);\r
+ }\r
+ strcat (opts.target_fname, ".lnk");\r
+ }\r
+\r
+ /* if there's no colon in the path, it's POSIX and we should convert to win32 */\r
+ if (strchr (opts.target_fname, ':') == NULL) {\r
+ char *strTmpPath = (char*)malloc(MAX_PATH);\r
+ if (strTmpPath == NULL) {\r
+ fprintf(stderr, "%s: memory allocation error\n", program_name);\r
+ return (ERR_SYS);\r
+ }\r
+ cygwin_conv_to_full_win32_path (opts.target_fname, strTmpPath);\r
+ free (opts.target_fname);\r
+ opts.target_fname = strTmpPath;\r
+ }\r
+\r
+ hres = OleInitialize (NULL);\r
+ if (hres != S_FALSE && hres != S_OK) {\r
+ fprintf (stderr, "%s: Could not initialize OLE interface\n", program_name);\r
+ return (ERR_WIN);\r
+ }\r
+\r
+ /* Get a pointer to the IShellLink interface. */\r
+ hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void **) &shell_link); \r
+\r
+ if (!SUCCEEDED(hres)) {\r
+ fprintf (stderr, "%s: CoCreateInstance failed\n", program_name);\r
+ return (ERR_WIN);\r
+ }\r
+\r
+ /* Get a pointer to the IPersistFile interface. */\r
+ hres = shell_link->lpVtbl->QueryInterface(shell_link, &IID_IPersistFile, (void **) &persist_file);\r
+\r
+ if (SUCCEEDED(hres)) {\r
+ WCHAR wsz[MAX_PATH]; \r
+ \r
+ /* Ensure that the string is Unicode. */\r
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)opts.target_fname, -1, wsz, MAX_PATH); \r
+\r
+ /* Load the shortcut. */\r
+ hres = persist_file->lpVtbl->Load(persist_file, wsz, STGM_READ); \r
+\r
+ if (SUCCEEDED(hres)) {\r
+ /* read stuff from the link object and print it to the screen */\r
+ if (opts.show_all || opts.show_target) {\r
+ shell_link->lpVtbl->GetPath(shell_link, strPath, MAX_PATH, NULL, SLGP_RAWPATH);\r
+ if (opts.show_field_names) { printf("Target: "); }\r
+ formatPath(strPath, opts.pathType);\r
+ printf("%s\n", strPath);\r
+ }\r
+ if (opts.show_all || opts.show_working_dir) {\r
+ shell_link->lpVtbl->GetWorkingDirectory(shell_link, strPath, MAX_PATH);\r
+ if (opts.show_field_names) { printf("Working Directory: "); }\r
+ formatPath(strPath, opts.pathType);\r
+ printf("%s\n", strPath);\r
+ }\r
+ if (opts.show_all || opts.show_args) {\r
+ shell_link->lpVtbl->GetArguments(shell_link, strBuff, BUFF_SIZE);\r
+ if (opts.show_field_names) { printf("Arguments: "); }\r
+ printf("%s\n", strBuff);\r
+ }\r
+ if (opts.show_all || opts.show_showCmd) {\r
+ shell_link->lpVtbl->GetShowCmd(shell_link, &iBuff);\r
+ if (opts.show_field_names) { printf("Show Command: "); }\r
+\r
+ switch (iBuff) {\r
+ case SW_SHOWNORMAL:\r
+ printf("Normal\n");\r
+ break;\r
+ case SW_SHOWMINIMIZED:\r
+ case SW_SHOWMINIMIZED_SEVEN:\r
+ printf("Minimized\n");\r
+ break;\r
+ case SW_SHOWMAXIMIZED:\r
+ printf("Maximized\n");\r
+ break;\r
+ }\r
+ }\r
+ if (opts.show_all || opts.show_icon || opts.show_icon_offset) {\r
+ shell_link->lpVtbl->GetIconLocation(shell_link, strPath, MAX_PATH, &iBuff);\r
+ if (opts.show_all || opts.show_icon) {\r
+ if (opts.show_field_names) { printf("Icon Library: "); }\r
+ formatPath(strPath, opts.pathType);\r
+ printf("%s\n", strPath);\r
+ }\r
+ if (opts.show_all || opts.show_icon_offset) {\r
+ if (opts.show_field_names) { printf("Icon Library Offset: "); }\r
+ printf("%d\n", iBuff);\r
+ }\r
+ }\r
+ if (opts.show_all || opts.show_desc) {\r
+ shell_link->lpVtbl->GetDescription(shell_link, strBuff, BUFF_SIZE);\r
+ if (opts.show_field_names) { printf("Description: "); }\r
+ printf("%s\n", strBuff);\r
+ }\r
+ }\r
+ else {\r
+ fprintf (stderr, "%s: Load failed on %s\n", program_name, opts.target_fname);\r
+ result = ERR_WIN;\r
+ }\r
+\r
+ /* Release the pointer to the IPersistFile interface. */\r
+ persist_file->lpVtbl->Release(persist_file);\r
+ }\r
+ else { \r
+ fprintf (stderr, "%s: QueryInterface failed\n", program_name);\r
+ result = ERR_WIN;\r
+ }\r
+ \r
+ /* Release the pointer to the IShellLink interface. */\r
+ shell_link->lpVtbl->Release(shell_link);\r
+\r
+ return(result);\r
+}\r
+\r
+/* change the path to the proper format */\r
+void formatPath (char * strPath, int format) {\r
+ if (format == PATH_WIN) { return; } /* windows is the default */\r
+ else {\r
+ // convert to posix path\r
+ char strTmp[MAX_PATH];\r
+ strcpy(strTmp, strPath);\r
+ cygwin_conv_to_full_posix_path(strTmp, strPath);\r
+ }\r
+}\r
+\r
+static const char * getVersion() {\r
+ return versionID;\r
+}\r
+\r
+static void printTopDescription(FILE * f, char * name) {\r
+ fprintf(f, "%s version %s\n", name, getVersion());\r
+ fprintf(f, " Reads and outputs data from a Windows shortcut (.lnk) file.\n\n");\r
+}\r
+\r
+static void printBottomDescription(FILE * f, char * name) {\r
+ fprintf(f, "\nNOTE: The SHORTCUT argument may be in Windows or Unix format.\n");\r
+}\r
+\r
+static void printLicense(FILE * f, char * name) {\r
+ fprintf(f, "This program is free software; you can redistribute it and/or\n");\r
+ fprintf(f, "modify it under the terms of the GNU General Public License\n");\r
+ fprintf(f, "as published by the Free Software Foundation; either version 2\n");\r
+ fprintf(f, "of the License, or (at your option) any later version.\n");\r
+ fprintf(f, "\n");\r
+ fprintf(f, "This program is distributed in the hope that it will be useful,\n");\r
+ fprintf(f, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\r
+ fprintf(f, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\r
+ fprintf(f, "GNU General Public License for more details.\n");\r
+ fprintf(f, "\n");\r
+ fprintf(f, "You should have received a copy of the GNU General Public License\n");\r
+ fprintf(f, "along with this program; if not, write to the Free Software\n");\r
+ fprintf(f, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");\r
+ fprintf(f, "\n");\r
+ fprintf(f, "See the COPYING file for license information.\n");\r
+}\r
+\r
+static void usage(poptContext optCon, FILE * f, char * name) {\r
+ poptPrintUsage(optCon, f, 0);\r
+}\r
+\r
+static void help(poptContext optCon, FILE * f, char * name) {\r
+ printTopDescription(f, name);\r
+ poptPrintHelp(optCon, f, 0);\r
+ printBottomDescription(f, name);\r
+}\r
+\r
+static void version(poptContext optCon, FILE * f, char * name) {\r
+ printTopDescription(f, name);\r
+}\r
+\r
+static void license(poptContext optCon, FILE * f, char * name) {\r
+ printTopDescription(f, name);\r
+ printLicense(f, name);\r
+} \r