delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2002/03/02/11:09:09

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
Date: Sat, 02 Mar 2002 11:14:05 -0500
From: Jason Tishler <jason AT tishler DOT net>
Subject: Re: mkshortcut debugging problem
In-reply-to: <20020302010036.33543.qmail@web20005.mail.yahoo.com>
To: Joshua Daniel Franklin <joshuadfranklin AT yahoo DOT com>
Cc: cygwin AT cygwin DOT com
Mail-followup-to: Joshua Daniel Franklin <joshuadfranklin AT yahoo DOT com>,
cygwin AT cygwin DOT com
Message-id: <20020302161405.GB1976@hp.com>
MIME-version: 1.0
User-Agent: Mutt/1.3.24i
References: <20020302010036 DOT 33543 DOT qmail AT web20005 DOT mail DOT yahoo DOT com>

--Boundary_(ID_dPakcDH3/esVabVNGHA6sA)
Content-type: text/plain; charset=us-ascii
Content-transfer-encoding: 7BIT
Content-disposition: inline

Joshua,

On Fri, Mar 01, 2002 at 05:00:36PM -0800, Joshua Daniel Franklin wrote:
> Has anyone even seen something like this before?

No, but see attached for my version of mkshortcut -- mksc.  Note that
mksc.cpp needs to be compiled with MS cl.exe, but hopefully perusing the
code will help you debug your problem.

Jason

--Boundary_(ID_dPakcDH3/esVabVNGHA6sA)
Content-type: text/plain; charset=us-ascii; NAME=mksc.cpp
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=mksc.cpp

/*
 * Copyright (c) 2000, 2002, Jason Tishler.
 *
 *     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.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by Jason Tishler  <jason AT tishler DOT net>
 *
 * $Id: mksc.cpp,v 1.3 2002/03/02 16:12:11 jt Exp $
 */

#include <windows.h>
#include <iostream>
#include <string>
#include <shlguid.h>
#include <shlobj.h>

using namespace std;

DWORD MakeShortcut(
	const string& aPath,
	const string& anArguments,
	const string& aWorkingDirectory,
	const string& anIconLocation,
	int anIconIndex,
	const string& aShortcutPath);
void ParseArgs(
	int argc,
	char* argv[], 
	string& aPath,
	string& anArguments,
	string& aWorkingDirectory,
	string& anIconLocation,
	int& anIconIndex,
	string& aShortcutPath);
void PrintUsage();
string CollapseBackslashes(const char* aString);

int
main(int argc, char* argv[])
{
	string aPath;
	string anArguments;
	string aWorkingDirectory;
	string anIconLocation;
	int anIconIndex = 0;
	string aShortcutPath;

	// Parse command line arguments
	ParseArgs(
		argc,
		argv,
		aPath,
		anArguments,
		aWorkingDirectory,
		anIconLocation,
		anIconIndex,
		aShortcutPath);

	// Create shortcut
	DWORD aStatus = MakeShortcut(
		aPath,
		anArguments,
		aWorkingDirectory,
		anIconLocation,
		anIconIndex,
		aShortcutPath);
	if (aStatus != ERROR_SUCCESS)
	{
		cerr << "MakeShortcut failed with error = " << aStatus << endl;
	}

	return (aStatus == ERROR_SUCCESS) ? 0 : 2;
}

DWORD
MakeShortcut(
	const string& aPath,
	const string& anArguments,
	const string& aWorkingDirectory,
	const string& anIconLocation,
	int anIconIndex,
	const string& aShortcutPath)
{
	// Variable definitions located here due to use of gotos
	IShellLink *aShellLink = 0;
	IPersistFile* aPersistFile = 0;
	int aStatus2 = 0;
	DWORD aReturnCode = ERROR_SUCCESS;

	// Initialize COM
	HRESULT aStatus = CoInitialize(0);
	if (FAILED(aStatus))
	{
		aReturnCode = GetLastError();
		cerr << "CoInitialize failed with error = " << aReturnCode << endl;
		goto exit;
	}

	// Create shell link instance
	aStatus = CoCreateInstance(
		CLSID_ShellLink,
		0,
		CLSCTX_INPROC_SERVER,
		IID_IShellLink,
		(void **) &aShellLink);
	if (FAILED(aStatus))
	{
		aReturnCode = GetLastError();
		cerr << "CoCreateInstance failed with error = " << aReturnCode << endl;
		goto exit;
	}

	// Set the shell link's command path
	aStatus = aShellLink->SetPath(aPath.c_str());
	if (FAILED(aStatus))
	{
		aReturnCode = aStatus;
		cerr << "IShellLink::SetPath failed with HRESULT = " << aStatus << endl;
		goto exit;
	}

	// Set the shell link's command arguments
	aStatus = aShellLink->SetArguments(anArguments.c_str());
	if (FAILED(aStatus))
	{
		aReturnCode = aStatus;
		cerr << "IShellLink::SetArguments failed with HRESULT = " << aStatus << endl;
		goto exit;
	}

	// Set the shell link's working directory, if necessary
	if (aWorkingDirectory.size() > 0)
	{
		aStatus = aShellLink->SetWorkingDirectory(aWorkingDirectory.c_str());
		if (FAILED(aStatus))
		{
			aReturnCode = aStatus;
			cerr << "IShellLink::SetWorkingDirectory failed with HRESULT = " << aStatus << endl;
			goto exit;
		}
	}

	// Set the shell link's icon, if necessary
	if (anIconLocation.size() > 0)
	{
		aStatus = aShellLink->SetIconLocation(anIconLocation.c_str(), anIconIndex);
		if (FAILED(aStatus))
		{
			aReturnCode = aStatus;
			cerr << "IShellLink::SetIconLocation failed with HRESULT = " << aStatus << endl;
			goto exit;
		}
	}

	// Get the shell link's persist file interface
	aStatus = aShellLink->QueryInterface(
		IID_IPersistFile,
		(void **) &aPersistFile);
	if (FAILED(aStatus))
	{
		aReturnCode = GetLastError();
		cerr << "IShellLink::QueryInterface failed with error = " << aReturnCode << endl;
		goto exit;
	}

	// Convert the shortcut path to Unicode
	WCHAR aWideShortcutPath[MAX_PATH];
	aStatus2 = MultiByteToWideChar(
		CP_ACP,
		0,
		aShortcutPath.c_str(),
		-1,
		aWideShortcutPath,
		MAX_PATH);
	if (aStatus2 == 0)
	{
		aReturnCode = GetLastError();
		cerr << "MultiByteToWideChar failed with error = " << aReturnCode << endl;
		goto exit;
	}

	// Save the shell link to the filesytem
	aStatus = aPersistFile->Save(aWideShortcutPath, TRUE);
	if (FAILED(aStatus))
	{
		aReturnCode = GetLastError();
		cerr << "IPersistFile::Save failed with error = " << aReturnCode << endl;
		goto exit;
	}

exit:
	// Clean up
	if (aPersistFile)
		aPersistFile->Release();
	if (aShellLink)
		aShellLink->Release();
	CoUninitialize();

	return aReturnCode;
}

void
ParseArgs(
	int argc,
	char* argv[], 
	string& aPath,
	string& anArguments,
	string& aWorkingDirectory,
	string& anIconLocation,
	int& anIconIndex,
	string& aShortcutPath)
{
	// Print usage, if appropriate
	if (argc == 1)
	{
		PrintUsage();
		exit(1);
	}

	// Process arguments
	for (int i = 1; i < argc; i += 2)
	{
		if (i + 1 >= argc)
		{
			PrintUsage();
			exit(1);
		}

		if (strcmp(argv[i], "--cmd") == 0)
		{
			aPath = CollapseBackslashes(argv[i + 1]);
		}
		else if (strcmp(argv[i], "--args") == 0)
		{
			anArguments = CollapseBackslashes(argv[i + 1]);
		}
		else if (strcmp(argv[i], "--dir") == 0)
		{
			aWorkingDirectory = CollapseBackslashes(argv[i + 1]);
		}
		else if (strcmp(argv[i], "--icon") == 0)
		{
			anIconLocation = CollapseBackslashes(argv[i + 1]);
		}
		else if (strcmp(argv[i], "--index") == 0)
		{
			anIconIndex = atoi(argv[i + 1]);
		}
		else if (strcmp(argv[i], "--shortcut") == 0)
		{
			aShortcutPath = CollapseBackslashes(argv[i + 1]);
		}
		else
		{
			PrintUsage();
			exit(1);
		}
	}

	// Check for mandatory arguments
	if (aPath.size() == 0 || anArguments.size() == 0 || aShortcutPath.size() == 0)
	{
		PrintUsage();
		exit(1);
	}
}

void
PrintUsage()
{
	cerr << "usage: mksc --cmd CommandPath --args CommandArguments" << endl;
	cerr << "    --shortcut ShortcutPath [--dir WorkingDirectory]" << endl;
	cerr << "    [--icon IconPath] [--index IconIndex]" << endl;
}

string
CollapseBackslashes(const char* aString)
{
	const string theDoubleBackslashRe = "\\\\";
	const string theSpaceRe = " ";

	string aFixedString = aString;

	// Determine if string does not contains any spaces, if so just return
	if (string::size_type i = aFixedString.find(theSpaceRe) == string::npos)
		return aFixedString;

	// Collapse double backslashes into single
	for (string::size_type i = aFixedString.find(theDoubleBackslashRe);
		i != string::npos;
		i = aFixedString.find(theDoubleBackslashRe, i))
	{
		i++;
		aFixedString.erase(i, 1);
	}

	return aFixedString;
}


--Boundary_(ID_dPakcDH3/esVabVNGHA6sA)
Content-Type: text/plain; charset=us-ascii

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/
--Boundary_(ID_dPakcDH3/esVabVNGHA6sA)--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019