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