クラス図
//////////////////////////////////////////////////////////////////////////////
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <tchar.h>
#include <cstdio>
// Windows NT 4.0,Windows 95,Internet Explorer 4.0 以降
#include <shlobj.h> // for SHGetSpecialFolderPath, IShellLink
#include <imagehlp.h> // for MakeSureDirectoryPathExists
#include <intshcut.h> // for IUniformResourceLocator
// Windows 2000,Windows Me 以降
#include <msi.h> // for MsiGetShortcutTarget, MsiGetComponentPath, MAX_FEATURE_CHARS
#ifdef _DEBUG
#include <crtdbg.h> // for _RPT0
#include <cassert>
#endif // _DEBUG
#pragma comment(lib, "shell32.lib" ) // for SHGetSpecialFolderPath
#pragma comment(lib, "imagehlp.lib") // for MakeSureDirectoryPathExists
#pragma comment(lib, "msi.lib" ) // for MsiGetShortcutTarget, MsiGetComponentPath
/////////////////////////////////// マクロ ///////////////////////////////////
// 最大文字列長
#define LARGE_NUMBER 4096
#define MAX_TEXT_LENGTH (_MAX_PATH + LARGE_NUMBER)
// アプリケーション名
#define APPLICATION_TEXT "ShoSendTo"
// 作成者名
#define COMPANY_TEXT "Sho's Software"
// 著作権表示用年
#define COPYRIGHT_YEAR_TEXT "2003-2009"
// ヴァージョン
#define VERSION_TEXT "1.16"
// ショートカットの拡張子
#define SHORTCUT_EXTENSION_TEXT "lnk"
// インターネット ショートカットの拡張子
#define INTERNETSHORTCUT_EXTENSION_TEXT "url"
// 「送る」追加時に付加するラベル
#define SHORTCUT_LABEL_TEXT "["APPLICATION_TEXT"]"
//////////////////////////////////////////////////////////////////////////////
// ユーティリティ
namespace Utility {
// デバッグ クラス
class Debug
{
public:
// デバッグ時のトレース
static void Trace(LPCTSTR messageText, ...)
{
#ifdef _DEBUG
const size_t maxTextLength(MAX_TEXT_LENGTH);
va_list argumentList;
va_start(argumentList, messageText);
TCHAR buffer[maxTextLength];
::vsprintf(buffer, messageText, argumentList);
Output(buffer);
#else // _DEBUG
messageText;
#endif // _DEBUG
}
// デバッグ出力
// Just-In-Time (JIT) デバッグが有効な場合はデバッガに文字列を出力
// (Microsoft Visual C++ 依存)
static void Output(LPCTSTR messageText /* デバッグ出力する文字 */)
{
#ifdef _DEBUG
_RPT0(_CRT_WARN, messageText);
::fputs(messageText, stderr);
#else // _DEBUG
messageText;
#endif // _DEBUG
}
// アサート
static void Assert(bool value)
{
#ifdef _DEBUG
assert(value);
#else // _DEBUG
value;
#endif // _DEBUG
}
};
// コンソール クラス
class Console
{
public:
// コンソール出力
static void Output(LPCTSTR messageText)
{
#ifdef _CONSOLE
::fputs(messageText, stdout);
#else // _CONSOLE
::MessageBox(::GetDesktopWindow(), messageText, _T(APPLICATION_TEXT" ヘルプ"), MB_OK | MB_ICONINFORMATION);
#endif // _CONSOLE
}
};
// ファイル クラス
class File
{
public:
// ディレクトリの作成
// フルパスで指定したディレクトリを作成
// 指定された各ディレクトリがまだ存在しない場合,それらのディレクトリを順に作成
// (Windows 95,NT3.1 以降)
static bool CreateDirectory(LPTSTR directoryName)
{
return !!::MakeSureDirectoryPathExists(directoryName);
}
// ディレクトリの準備
static bool PrepareDirectory(LPTSTR directoryName)
{
RegulateDirectoryName(directoryName);
const DWORD attribute(::GetFileAttributes(directoryName));
return (attribute == DWORD(-1)) ? CreateDirectory(directoryName)
: IsDirectory(attribute);
}
// ディレクトリへのファイルのコピー
static bool CopyToDirectory(LPCTSTR sourcePathName, LPTSTR destinationDirectoryName, LPTSTR destinationPathName)
{
RegulateDirectoryName(destinationDirectoryName);
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName [_MAX_EXT ];
::_tsplitpath(sourcePathName, NULL, NULL, fileName, extensionName);
::_tcscpy(destinationPathName, destinationDirectoryName);
::_tcscat(destinationPathName, fileName );
::_tcscat(destinationPathName, extensionName );
return !!::CopyFile(sourcePathName, destinationPathName, false);
}
// ディレクトリへのファイルのコピー
static bool CopyToDirectory(LPCTSTR sourcePathName, LPTSTR destinationDirectoryName, LPCTSTR destinationFileName, LPTSTR destinationPathName)
{
RegulateDirectoryName(destinationDirectoryName);
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName [_MAX_EXT ];
::_tsplitpath(destinationFileName, NULL, NULL, fileName, extensionName);
::_tcscpy(destinationPathName, destinationDirectoryName);
::_tcscat(destinationPathName, fileName );
::_tcscat(destinationPathName, extensionName );
return !!::CopyFile(sourcePathName, destinationPathName, false);
}
// ディレクトリ名の正規化
static void RegulateDirectoryName(LPTSTR directoryName)
{
const size_t directoryNameTextLength(::_tcslen(directoryName));
if (directoryName[directoryNameTextLength - 1] != _T('\\')) {
directoryName[directoryNameTextLength ] = _T('\\');
directoryName[directoryNameTextLength + 1] = _T('\0');
}
}
// ディレクトリ名とファイル名を連結してパス名へ
static void MakePathName(LPTSTR pathName, LPCTSTR directoryName, LPCTSTR fileName)
{
::_tcscpy(pathName, directoryName);
RegulateDirectoryName(pathName);
::_tcscat(pathName, fileName);
}
// 現プロセスの実行ファイルのパス名の取得
static bool GetCurrentProcessFileName(LPTSTR pathName /* パス名受け取り用バッファ */)
{
const HMODULE moduleHandle = ::GetModuleHandle(NULL);
if (moduleHandle != HMODULE(0))
return (::GetModuleFileName(moduleHandle, pathName, _MAX_PATH) > 0);
return false;
}
// 「送る」フォルダのパス名の取得
static bool GetSendToPath(LPTSTR pathName /* パス名用バッファ */)
{
return GetSpecialFolderPath(pathName, CSIDL_SENDTO);
}
#ifdef _DEBUG
// 「お気に入り」フォルダのパス名の取得
static bool GetFavoritesPath(LPTSTR pathName /* パス名用バッファ */)
{
return GetSpecialFolderPath(pathName, CSIDL_FAVORITES);
}
#endif // _DEBUG
// システムの特殊なフォルダのパス名の取得
// (Windows NT 4.0, Windows 95 以降)
// Windows 2000, Windows NT 4.0 + IE 4.0, Windows 98, Windows 95 + IE 4.0 以降であれば SHGetSpecialFolderPath が使える
// また,システム ディレクトリは GetSystemDirectory,
// Windows ディレクトリは GetWindowsDirectory,
// 一時ファイル用のディレクトリは GetTempPath がそれぞれ使用出来る.
static bool GetSpecialFolderPath(LPTSTR pathName /* パス名用バッファ */, int nFolder /* フォルダを指定する CSIDL の値 */)
{
bool temp(false);
IMalloc* pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR) {
ITEMIDLIST* pItemIdList;
if (::SHGetSpecialFolderLocation(::GetDesktopWindow(), nFolder, &pItemIdList) == NOERROR) {
if (::SHGetPathFromIDList(pItemIdList, pathName))
temp = true;
pMalloc->Free(pItemIdList);
}
pMalloc->Release();
}
return temp;
}
// ショートカットの作成
static bool CreateShortcut(LPCTSTR targePathName /* ショートカットのリンク先 */, LPCTSTR targetArgument /* コマンドライン引数 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
bool temp(false);
HRESULT result = ::CoInitialize(NULL);
if (SUCCEEDED(result)) {
IShellLink* pShellLink;
result = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pShellLink);
if (SUCCEEDED(result)) {
IPersistFile* pPersistFile;
result = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
if (SUCCEEDED(result)) {
result = pShellLink->SetPath(targePathName);
if (SUCCEEDED(result)) {
result = (targetArgument == NULL) ? S_OK : pShellLink->SetArguments(targetArgument);
if (SUCCEEDED(result)) {
#ifdef _UNICODE
result = pPersistFile->Save(linkPathName, true);
#else // _UNICODE
// Unicodeに変換
wchar_t wlinkPathName[_MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, linkPathName, -1, wlinkPathName, _MAX_PATH);
result = pPersistFile->Save(wlinkPathName, true);
#endif // _UNICODE
if (SUCCEEDED(result))
temp = true;
}
}
pPersistFile->Release();
}
pShellLink->Release();
}
CoUninitialize();
}
return temp;
}
// ショートカットの作成
static bool CreateShortcut(LPCTSTR targetPathName /* ショートカットのリンク先 */, LPCTSTR targetArgument /* コマンドライン引数 */, LPCTSTR linkDirectoryName /* ショートカットを置くディレクトリ */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR linkFileName[_MAX_PATH];
::_tcscpy(linkFileName, linkName );
::_tcscat(linkFileName, _T("."SHORTCUT_EXTENSION_TEXT));
TCHAR linkPathName[_MAX_PATH];
MakePathName(linkPathName, linkDirectoryName, linkFileName);
return CreateShortcut(targetPathName, targetArgument, linkPathName);
}
#ifdef _DEBUG
static bool CreateInternetShortcut(LPCTSTR urlText /* URL 文字列 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
bool temp(false);
HRESULT result = ::CoInitialize(NULL);
if (SUCCEEDED(result)) {
IUniformResourceLocator *pUniformResourceLocator = NULL;
result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (LPVOID*)&pUniformResourceLocator);
if (SUCCEEDED(result)) {
IPersistFile *pPersistFile = NULL;
result = pUniformResourceLocator->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
if (SUCCEEDED(result)) {
result = pUniformResourceLocator->SetURL(urlText, 0);
if (SUCCEEDED(result)) {
#ifdef _UNICODE
result = pPersistFile->Save(linkPathName, TRUE);
#else // _UNICODE
// Unicodeに変換
wchar_t wlinkPathName[_MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, linkPathName, -1, wlinkPathName, _MAX_PATH);
result = pPersistFile->Save(wlinkPathName, TRUE);
#endif // _UNICODE
temp = SUCCEEDED(result);
}
pPersistFile->Release();
}
pUniformResourceLocator->Release();
}
}
return temp;
}
// インターネット ショートカットの作成
static bool CreateInternetShortcut(LPCTSTR urlText /* URL 文字列 */, LPCTSTR linkDirectoryName /* ショートカットを置くディレクトリ */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR linkFileName[_MAX_PATH];
::_tcscpy(linkFileName, linkName );
::_tcscat(linkFileName, _T("."INTERNETSHORTCUT_EXTENSION_TEXT));
TCHAR linkPathName[_MAX_PATH];
MakePathName(linkPathName, linkDirectoryName, linkFileName);
return CreateInternetShortcut(urlText, linkPathName);
}
// 「送る」への追加
static bool CreateSendTo(LPCTSTR targetPathName, LPCTSTR targetArgument, LPCTSTR linkName)
{
TCHAR directoryName[_MAX_DIR];
return GetSendToPath(directoryName)
? CreateShortcut(targetPathName, targetArgument, directoryName, linkName)
: false;
}
// 「お気に入り」への追加
static bool CreateFavorites(LPCTSTR urlText /* URL 文字列 */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR directoryName[_MAX_DIR];
return GetFavoritesPath(directoryName)
? CreateInternetShortcut(urlText, directoryName, linkName)
: false;
}
#endif // _DEBUG
#if _MSC_VER >= 1300
// WindowsInstaller で作成されたショートカットからのパス名の取得
static bool ReadMsiShortcut(LPTSTR targePathName /* ショートカットのリンク先 */, size_t targePathNameBufferLength /* ショートカットのリンク先の最大文字数 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
if (targePathName != NULL) {
const size_t bufferLength = 39;
TCHAR productCode [bufferLength ];
TCHAR featureId [MAX_FEATURE_CHARS + 1];
TCHAR componentCode[bufferLength ];
UINT result = ::MsiGetShortcutTarget(linkPathName, productCode, featureId, componentCode);
if (result == ERROR_SUCCESS) {
DWORD targePathNameLength = DWORD(targePathNameBufferLength);
result = ::MsiGetComponentPath(productCode, componentCode, targePathName, &targePathNameLength);
if (result == INSTALLSTATE_LOCAL)
return true;
}
}
return false;
}
// WindowsInstaller で作成されたショートカットからのパス名の取得
static bool ReadMsiShortcut(LPTSTR targePathName /* ショートカットのリンク先 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
return ReadMsiShortcut(targePathName, MAX_TEXT_LENGTH, linkPathName);
}
#endif // _MSC_VER
// ショートカットからのパス名の取得
static bool ReadShortcut(LPTSTR targePathName /* ショートカットのリンク先 */, LPTSTR targetArgument /* コマンドライン引数 */, size_t targetArgumentMaxTextLength /* コマンドライン引数の最大文字数 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
#if _MSC_VER >= 1300
if (ReadMsiShortcut(targePathName, linkPathName))
return true;
#endif // _MSC_VER
bool temp(false);
HRESULT result = ::CoInitialize(NULL);
if (SUCCEEDED(result)) {
IShellLink* pShellLink;
result = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pShellLink);
if (SUCCEEDED(result)) {
IPersistFile* pPersistFile;
result = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
if (SUCCEEDED(result)) {
#ifdef _UNICODE
result = pPersistFile->Load(linkPathName, STGM_READ | STGM_SHARE_DENY_WRITE);
#else // _UNICODE
// Unicodeに変換
wchar_t wlinkPathName[_MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, linkPathName, -1, wlinkPathName, _MAX_PATH);
result = pPersistFile->Load(wlinkPathName, STGM_READ | STGM_SHARE_DENY_WRITE);
#endif // _UNICODE
if (SUCCEEDED(result)) {
WIN32_FIND_DATA findData;
result = pShellLink->GetPath(targePathName, _MAX_PATH, &findData, 0);
if (SUCCEEDED(result)) {
result = (targetArgument == NULL) ? S_OK : pShellLink->GetArguments(targetArgument, int(targetArgumentMaxTextLength));
if (SUCCEEDED(result))
temp = true;
}
}
pPersistFile->Release();
}
pShellLink->Release();
}
CoUninitialize();
}
return temp;
}
#ifdef _DEBUG
// ショートカットからのパス名の取得
static bool ReadShortcut(LPTSTR targePathName /* ショートカットのリンク先 */, LPTSTR targetArgument /* コマンドライン引数 */, size_t targetArgumentMaxTextLength /* コマンドライン引数の最大文字数 */, LPCTSTR linkDirectoryName /* ショートカットが在るディレクトリ */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR linkFileName[_MAX_PATH];
::_tcscpy(linkFileName, linkName );
::_tcscat(linkFileName, _T("."SHORTCUT_EXTENSION_TEXT));
TCHAR linkPathName[_MAX_PATH];
MakePathName(linkPathName, linkDirectoryName, linkFileName);
return ReadShortcut(targePathName, targetArgument, targetArgumentMaxTextLength, linkPathName);
}
// 「送る」からのパス名の取得
static bool ReadSendTo(LPTSTR targePathName /* ショートカットのリンク先 */, LPTSTR targetArgument /* コマンドライン引数 */, size_t targetArgumentMaxTextLength /* コマンドライン引数の最大文字数 */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR directoryName[_MAX_DIR];
return GetSendToPath(directoryName)
? ReadShortcut(targePathName, targetArgument, targetArgumentMaxTextLength, directoryName, linkName)
: false;
}
#endif // _DEBUG
// インターネット ショートカットからの URL の取得
static bool ReadInternetShortcut(LPTSTR urlText /* URL 文字列 */, LPCTSTR linkPathName /* ショートカットのパス名 */)
{
bool temp(false);
HRESULT result = ::CoInitialize(NULL);
if (SUCCEEDED(result)) {
IUniformResourceLocator *pUniformResourceLocator = NULL;
result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_IUniformResourceLocator, (LPVOID*)&pUniformResourceLocator);
if (SUCCEEDED(result)) {
IPersistFile *pPersistFile = NULL;
result = pUniformResourceLocator->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
if (SUCCEEDED(result)) {
#ifdef _UNICODE
result = pPersistFile->Load(linkPathName, STGM_READ | STGM_SHARE_DENY_WRITE);
#else // _UNICODE
// Unicodeに変換
wchar_t wlinkPathName[_MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, linkPathName, -1, wlinkPathName, _MAX_PATH);
result = pPersistFile->Load(wlinkPathName, STGM_READ | STGM_SHARE_DENY_WRITE);
#endif // _UNICODE
if (SUCCEEDED(result)) {
LPSTR buffer;
result = pUniformResourceLocator->GetURL(&buffer);
if (SUCCEEDED(result)) {
#ifdef _UNICODE
::MultiByteToWideChar(CP_ACP, 0, buffer, -1, urlText, _MAX_PATH);
#else // _UNICODE
::_tcscpy(urlText, buffer);
#endif // _UNICODE
temp = true;
}
}
pPersistFile->Release();
}
pUniformResourceLocator->Release();
}
}
return temp;
}
#ifdef _DEBUG
// インターネット ショートカットからの URL の取得
static bool ReadInternetShortcut(LPTSTR urlText /* URL 文字列 */, LPCTSTR linkDirectoryName /* ショートカットが在るディレクトリ */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR linkFileName[_MAX_PATH];
::_tcscpy(linkFileName, linkName );
::_tcscat(linkFileName, _T("."INTERNETSHORTCUT_EXTENSION_TEXT));
TCHAR linkPathName[_MAX_PATH];
MakePathName(linkPathName, linkDirectoryName, linkFileName);
return ReadInternetShortcut(urlText, linkPathName);
}
// 「お気に入り」からの URL の取得
static bool ReadFavorites(LPTSTR urlText /* URL 文字列 */, LPCTSTR linkName /* ショートカットの名称 */)
{
TCHAR directoryName[_MAX_DIR];
return GetFavoritesPath(directoryName)
? ReadInternetShortcut(urlText, directoryName, linkName)
: false;
}
// パス名で指定されたファイルまたはディレクトリが存在するかどうか
static bool IsExist(LPTSTR pathName)
{
const DWORD attribute(::GetFileAttributes(pathName));
return (attribute != DWORD(-1));
}
// 指定されたパス名がディレクトリかどうか
static bool IsDirectory(LPCTSTR pathName)
{
const DWORD attribute(::GetFileAttributes(pathName));
return IsDirectory(attribute);
}
#endif // _DEBUG
// 属性がディレクトリかどうか
static bool IsDirectory(DWORD attribute)
{
return ((attribute & FILE_ATTRIBUTE_DIRECTORY) != 0);
}
// 指定されたパス名がショートカットかどうか
static bool IsShortcut(LPCTSTR pathName, LPTSTR fileNameWithoutExtension = NULL)
{
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName [_MAX_EXT ];
::_tsplitpath(pathName, NULL, NULL, fileName, extensionName);
if (fileNameWithoutExtension != NULL)
::_tcscpy(fileNameWithoutExtension, fileName);
return (::_tcsicmp(extensionName, _T("."SHORTCUT_EXTENSION_TEXT)) == 0);
}
// 指定されたパス名がインターネット ショートカットかどうか
static bool IsInternetShortcut(LPCTSTR pathName, LPTSTR fileNameWithoutExtension = NULL)
{
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName [_MAX_EXT ];
::_tsplitpath(pathName, NULL, NULL, fileName, extensionName);
if (fileNameWithoutExtension != NULL)
::_tcscpy(fileNameWithoutExtension, fileName);
return (::_tcsicmp(extensionName, _T("."INTERNETSHORTCUT_EXTENSION_TEXT)) == 0);
}
// ファイルの削除
static bool DeleteFile(LPCTSTR pathName)
{
return !!::DeleteFile(pathName);
}
};
// ファイル検索 クラス
class FindFile : protected File
{
public:
FindFile(LPCTSTR directoryName)
{
::_tcscpy(directoryName_, directoryName);
TCHAR pathName[_MAX_PATH];
MakePathName(pathName, directoryName, _T("*."SHORTCUT_EXTENSION_TEXT));
handle_ = ::FindFirstFile(pathName, &ffBlk_);
}
virtual ~FindFile()
{
::FindClose(handle_);
}
bool IsValid() const
{
return (handle_ != INVALID_HANDLE_VALUE);
}
bool IsDirectory() const
{
return File::IsDirectory(ffBlk_.dwFileAttributes);
}
LPCSTR FileName() const
{
return ffBlk_.cFileName;
}
void PathName(LPTSTR pathName) const
{
MakePathName(pathName, directoryName_, FileName());
}
bool NextFile()
{
return !!::FindNextFile(handle_, &ffBlk_);
}
private:
HANDLE handle_;
WIN32_FIND_DATA ffBlk_;
TCHAR directoryName_[_MAX_PATH];
};
// クリップボード クラス
class Clipboard
{
public:
#ifdef _DEBUG
// クリップボードからテキストの取得
static bool GetText(LPTSTR buffer /* テキスト用バッファ */, size_t bufferSize /* テキスト用バッファのサイズ */)
{
bool temp(false);
if (::OpenClipboard(HWND(0))) {
if (::IsClipboardFormatAvailable(CF_TEXT)) {
const HGLOBAL data = ::GetClipboardData(CF_TEXT);
if (data != HGLOBAL(0)) {
const LPCTSTR text = LPCTSTR(::GlobalLock(data));
if (text != NULL) {
const size_t length(::_tcslen(text));
if (length < bufferSize) {
::memcpy(buffer, text, sizeof(TCHAR) * (length + 1));
temp = true;
}
}
::GlobalUnlock(data);
}
}
::CloseClipboard();
}
return temp;
}
#endif // _DEBUG
// クリップボードへのテキストのコピー
static bool SetText(LPCTSTR text /* テキスト */)
{
Utility::Debug::Assert(text != NULL);
bool temp(false);
const size_t length(sizeof(TCHAR) * (::_tcslen(text) + 1));
const HGLOBAL data = ::GlobalAlloc(GMEM_MOVEABLE, length);
if (data != NULL) {
const LPVOID buffer = ::GlobalLock(data);
if (buffer != NULL) {
::memcpy(buffer, text, length);
::GlobalUnlock(data);
if (::OpenClipboard(::GetDesktopWindow())) {
if (::EmptyClipboard()) {
if (::SetClipboardData(CF_TEXT, data) != HANDLE(0))
temp = true;
}
::CloseClipboard();
}
}
::GlobalFree(data);
}
return temp;
}
};
} // namespace Utility
//////////////////////////////////////////////////////////////////////////////
// アプリケーション
namespace ShoSendTo {
// アプリケーション クラス
class Application
{
public:
Application() : agent_(&help_)
{}
#ifdef _CONSOLE
// メイン ルーチン
void Run(int argc, LPTSTR argv[])
{
TCHAR text[MAX_TEXT_LENGTH];
Argument(argc, argv, text);
agent_->Run(text);
}
#else // _CONSOLE
// メイン ルーチン
void Run(LPTSTR commandLine)
{
TCHAR text[MAX_TEXT_LENGTH];
Argument(commandLine, text);
agent_->Run(text);
}
#endif // _CONSOLE
private:
// エージェント クラス
class Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const = 0;
protected:
// クリップボードへのテキストのコピー
static void ToClipboard(LPCTSTR text)
{
if (Utility::Clipboard::SetText(text)) {
#ifdef _DEBUG
Test(text);
#endif // _DEBUG
}
}
// ショートカットの作成
static bool CreateShortcut(LPCTSTR targetPathName, LPCTSTR targetArgument, LPCTSTR linkDirectoryName, LPCTSTR linkName)
{
TCHAR tempLinkName[_MAX_PATH];
::_tcscpy(tempLinkName, SHORTCUT_LABEL_TEXT);
::_tcscat(tempLinkName, linkName );
return Utility::File::CreateShortcut(targetPathName, targetArgument, linkDirectoryName, tempLinkName);
}
#ifdef _DEBUG
// 「送る」の追加
static bool CreateSendTo(LPCTSTR targetPathName, LPCTSTR targetArgument, LPCTSTR linkName)
{
TCHAR tempLinkName[_MAX_PATH];
::_tcscpy(tempLinkName, SHORTCUT_LABEL_TEXT);
::_tcscat(tempLinkName, linkName );
return Utility::File::CreateSendTo(targetPathName, targetArgument, tempLinkName);
}
#endif // _DEBUG
// 「送る」の処理
virtual void ProcessSendTo(LPCTSTR /* pathName */) const
{}
// 「送る」の列挙
void EnumSendTo() const
{
TCHAR directoryName[_MAX_DIR];
if (Utility::File::GetSendToPath(directoryName)) {
Utility::FindFile findFile(directoryName);
if (findFile.IsValid()) {
bool temp(false);
do {
if (IsSendTo(findFile.FileName())) {
TCHAR pathName[_MAX_PATH];
findFile.PathName(pathName);
temp = findFile.NextFile();
ProcessSendTo(pathName);
} else {
temp = findFile.NextFile();
}
} while (temp);
}
}
}
private:
static bool IsSendTo(LPCTSTR fileName)
{
const TCHAR label[] = _T(SHORTCUT_LABEL_TEXT);
return (::_tcsnicmp(fileName, label, ::_tcslen(label)) == 0);
}
#ifdef _DEBUG
// テスト
static void Test(LPCTSTR text)
{
TCHAR buffer[MAX_TEXT_LENGTH];
if (Utility::Clipboard::GetText(buffer, MAX_TEXT_LENGTH)) {
Utility::Debug::Output(_T("Clipboard Test\n"));
Utility::Debug::Trace(_T("\tClipboard - Set:(%s), Get(%s)\n"), text, buffer);
Utility::Debug::Assert(::_tcscmp(text, buffer) == 0);
} else {
Utility::Debug::Assert(false);
}
}
#endif // _DEBUG
};
// ヘルプ クラス
class Help : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR /* text */) const
{
DisplayHelp();
}
private:
// ヘルプの表示
static void DisplayHelp()
{
static const LPCTSTR helpText =
_T(APPLICATION_TEXT" Version "VERSION_TEXT" Copyright (C) "COPYRIGHT_YEAR_TEXT" "COMPANY_TEXT".\n"
" Usage: "APPLICATION_TEXT" PathName [/U] [/P] [/I] [/Q] [/A] [/R] [/H] [/?]\n"
"\t\n"
"\t/U Copy URL Text to Clipboard.\n"
"\t/P Copy PathName Text to Clipboard.\n"
"\t/I Install "APPLICATION_TEXT" to your Windows.\n"
"\t/Q Uninstall "APPLICATION_TEXT" from your Windows.\n"
"\t/A Add the shortcut to SendTo on your Windows.\n"
"\t/R Remove the shortcut from SendTo on your Windows.\n"
"\t/H Show this help.\n"
"\t/? Show this help.\n");
Utility::Console::Output(helpText);
}
};
// URL 文字列作成クラス
class MakeURL : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const
{
TCHAR buffer[MAX_TEXT_LENGTH];
if (Utility::File::IsShortcut(text)) {
TCHAR targetPathName[_MAX_PATH ];
TCHAR targetArgument[MAX_TEXT_LENGTH];
if (!Utility::File::ReadShortcut(targetPathName, targetArgument, MAX_TEXT_LENGTH, text))
return;
ToURL(buffer, targetPathName);
} else if (Utility::File::IsInternetShortcut(text)) {
if (!Utility::File::ReadInternetShortcut(buffer, text))
return;
} else {
ToURL(buffer, text);
}
ToClipboard(buffer);
}
private:
static void ToURL(LPTSTR buffer, LPCTSTR text)
{
::_tcscpy(buffer, _T("file://"));
size_t index(::_tcslen(buffer));
for (LPCTSTR pointer = text; *pointer != _T('\0') && index < MAX_TEXT_LENGTH; pointer++) {
if (*pointer == _T('\\'))
buffer[index] = _T('/');
else
buffer[index] = *pointer;
#ifndef _UNICODE
if (_ismbblead(*pointer)) {
pointer++;
index++;
buffer[index] = *pointer;
}
#endif // _UNICODE
index++;
}
buffer[index] = _T('\0');
}
};
// パス名作成クラス
class MakePathName : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const
{
if (Utility::File::IsShortcut(text)) {
TCHAR buffer [MAX_TEXT_LENGTH];
TCHAR targetArgument[MAX_TEXT_LENGTH];
if (Utility::File::ReadShortcut(buffer, targetArgument, MAX_TEXT_LENGTH, text))
ToClipboard(buffer);
} else {
ToClipboard(text);
}
}
};
// インストーラ クラス
class Installer : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const
{
TCHAR destinationDirectoryName[_MAX_DIR ];
::_tcscpy(destinationDirectoryName, text);
TCHAR targetPathName [_MAX_PATH];
Install(destinationDirectoryName, targetPathName);
CreateShortcuts(targetPathName);
}
private:
// インストール
static bool Install(LPTSTR destinationDirectoryName, LPTSTR targetPathName)
{
if (Utility::File::PrepareDirectory(destinationDirectoryName)) {
TCHAR sourcePathName[_MAX_PATH];
if (Utility::File::GetCurrentProcessFileName(sourcePathName)) {
if (Utility::File::CopyToDirectory(sourcePathName, destinationDirectoryName, targetPathName))
return true;
}
}
return false;
}
// ショートカットの作成
static bool CreateShortcuts(LPCTSTR targetPathName)
{
const TCHAR linkNameURL [] = _T("URL→クリップボード" );
const TCHAR linkNamePath [] = _T("パス名→クリップボード" );
const TCHAR linkNameAddShortcut [] = _T("「送る」へのショートカットの追加" );
const TCHAR linkNameRemoveShortcut [] = _T("「送る」からのショートカットの削除");
const TCHAR optionTextURL [] = _T("/U" );
const TCHAR optionTextPath [] = _T("/P" );
const TCHAR optionTextAddShortcut [] = _T("/A" );
const TCHAR optionTextRemoveShortcut[] = _T("/R" );
TCHAR directoryName[_MAX_DIR];
if (Utility::File::GetSendToPath(directoryName)) {
CreateShortcut(targetPathName, optionTextURL , directoryName, linkNameURL );
CreateShortcut(targetPathName, optionTextPath , directoryName, linkNamePath );
CreateShortcut(targetPathName, optionTextAddShortcut , directoryName, linkNameAddShortcut );
CreateShortcut(targetPathName, optionTextRemoveShortcut, directoryName, linkNameRemoveShortcut);
return true;
}
return false;
}
};
// アンインストーラ クラス
class Uninstaller : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR /* text */) const
{
Uninstall();
}
protected:
// 「送る」の処理
virtual void ProcessSendTo(LPCTSTR pathName) const
{
Utility::File::DeleteFile(pathName);
}
private:
// アンインストール
void Uninstall() const
{
EnumSendTo();
}
};
// ショートカットを「送る」に追加するクラス
class AddShortcut : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const
{
AddShortcutToSendTo(text);
}
private:
// ショートカットを「送る」に追加
static void AddShortcutToSendTo(LPCTSTR pathName)
{
TCHAR directoryName[_MAX_DIR];
if (Utility::File::GetSendToPath(directoryName)) {
TCHAR fileNameWithoutExtension[_MAX_FNAME];
if (Utility::File::IsShortcut(pathName, fileNameWithoutExtension)) {
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName [_MAX_EXT ];
::_tsplitpath(pathName, NULL, NULL, fileName, extensionName);
TCHAR destinationFileName[_MAX_DIR ];
::_tcscpy(destinationFileName, _T(SHORTCUT_LABEL_TEXT));
::_tcscat(destinationFileName, fileName );
::_tcscat(destinationFileName, extensionName );
TCHAR destinationPathName[_MAX_PATH];
Utility::File::CopyToDirectory(pathName, directoryName, destinationFileName, destinationPathName);
} else {
CreateShortcut(pathName, NULL, directoryName, fileNameWithoutExtension);
}
}
}
};
// ショートカットを「送る」から削除するクラス
class RemoveShortcut : public Agent
{
public:
// 処理ルーチン
virtual void Run(LPCTSTR text) const
{
RemoveShortcutFromSendTo(text);
}
private:
// ショートカットを「送る」から削除
static void RemoveShortcutFromSendTo(LPCTSTR pathName)
{
TCHAR directoryName[_MAX_DIR];
if (Utility::File::GetSendToPath(directoryName)) {
TCHAR destinationFileName [_MAX_FNAME];
::_tcscpy(destinationFileName, _T(SHORTCUT_LABEL_TEXT));
TCHAR fileNameWithoutExtension[_MAX_FNAME];
if (Utility::File::IsShortcut(pathName, fileNameWithoutExtension)) {
TCHAR fileName [_MAX_FNAME];
TCHAR extensionName[_MAX_EXT ];
::_tsplitpath(pathName, NULL, NULL, fileName, extensionName);
::_tcscat(destinationFileName, fileName );
::_tcscat(destinationFileName, extensionName);
} else {
::_tcscat(destinationFileName, fileNameWithoutExtension );
::_tcscat(destinationFileName, _T("."SHORTCUT_EXTENSION_TEXT));
}
TCHAR destinationPathName [_MAX_PATH ];
Utility::File::MakePathName(destinationPathName, directoryName, destinationFileName);
Utility::File::DeleteFile(destinationPathName);
}
}
};
#ifdef _CONSOLE
// コマンドライン引数の解析
void Argument(size_t argc, LPTSTR argv[], LPTSTR destinationText)
{
bool isExistText(false);
for (size_t i = 1; i < argc; i++) {
if (int(argv[i][0]) == _T('/') || int(argv[i][0]) == _T('-')) {
for (size_t j = 1; argv[i][j] != _T('\0'); j++)
Switch(argv[i][j]);
} else if (!isExistText) {
::_tcscpy(destinationText, argv[i]);
isExistText = true;
}
}
}
#else // _CONSOLE
// コマンドライン引数からのトークンの切り出し
static LPTSTR ToToken(LPTSTR commandLine = NULL)
{
static LPTSTR pointer = NULL;
if (commandLine == NULL) {
if (pointer == NULL)
return NULL;
} else {
pointer = commandLine;
}
LPTSTR start = NULL;
bool firstState (true );
bool doubleQuotationState(false);
for (; *pointer != _T('\0'); pointer++) {
switch (*pointer) {
case _T('\"'):
doubleQuotationState = !doubleQuotationState;
*pointer = '\0';
break;
case _T(' ' ):
case _T('\t'):
case _T('\a'):
case _T('\n'):
if (!firstState && !doubleQuotationState) {
*pointer = '\0';
pointer++;
goto L1;
}
break;
default :
if (firstState) {
firstState = false;
start = pointer;
}
break;
}
#ifndef _UNICODE
if (_ismbblead(*pointer))
pointer++;
#endif // _UNICODE
}
L1:
return start;
}
// コマンドライン引数の解析
void Argument(LPTSTR commandLine, LPTSTR destinationText)
{
bool isExistText(false);
for (LPTSTR token = ToToken(commandLine); token != NULL; token = ToToken()) {
if (int(token[0]) == _T('/') || int(token[0]) == _T('-')) {
for (size_t j = 1; token[j] != _T('\0'); j++)
Switch(token[j]);
} else if (!isExistText) {
::_tcscpy(destinationText, token);
isExistText = true;
}
}
}
#endif // _CONSOLE
// コマンドラインで与えられたオプション スイッチの解析
void Switch(TCHAR character)
{
switch (::_totlower(int(character))) {
case _T('h'):
case _T('?'): agent_ = &help_ ; break;
case _T('u'): agent_ = &makeURL_ ; break;
case _T('p'): agent_ = &makePathName_ ; break;
case _T('i'): agent_ = &installer_ ; break;
case _T('q'): agent_ = &uninstaller_ ; break;
case _T('a'): agent_ = &addShortcut_ ; break;
case _T('r'): agent_ = &removeShortcut_ ; break;
}
}
// エージェント オブジェクト
Agent* agent_ ;
Help help_ ;
MakeURL makeURL_ ;
MakePathName makePathName_ ;
Installer installer_ ;
Uninstaller uninstaller_ ;
AddShortcut addShortcut_ ;
RemoveShortcut removeShortcut_;
};
} // namespace ShoSendTo
//////////////////////////////////////////////////////////////////////////////
// アプリケーションのエントリー ポイント
#ifdef _CONSOLE
int _tmain(int argc, LPTSTR argv[])
{
ShoSendTo::Application application;
application.Run(argc, argv);
return 0;
}
#else // _CONSOLE
int APIENTRY _tWinMain(HINSTANCE /* instanceHandle */, HINSTANCE /* prevInstanceHandle */, LPTSTR commandLine, int /* showCommand */)
{
ShoSendTo::Application application;
application.Run(commandLine);
return 0;
}
#endif // _CONSOLE
//////////////////////////////////////////////////////////////////////////////
/*
クラス図
+-------------+
| |
+------------------------------------------------------+
| |
| Utility |
| |
| +-------+ +-------------+ +-----------+ |
| | | | | | | |
| | File | | Console | | Debug | |
| | | | | | | |
| +-------+ +-------------+ +-----------+ |
| △ |
| | |
| +-----------+ +-----------+ |
| | | | | |
| | FindFile | | Clipboard | |
| | | | | |
| +-----------+ +-----------+ |
| {Global} |
| |
+------------------------------------------------------+
+-------------+
| |
+--------------------------------------------------------------------------------------------------------------------+
| |
| ShoSendTo |
| |
| +-------------+ | +------+
| | |---------------------------------------------------------------------------------------------------+----| |
| | Application | | | main |
| | | | | |
| +-------------+ | +------+
| | |
| | |
| | |
| ↓ |
| +-------+ |
| | | |
| | Agent | |
| | | |
| +-------+ |
| △ |
| | |
| +---------+---------------+----------------+---------------+-----------------+-----------------+ |
| | | | | | | | |
| | | | | | | | |
| +------+ +---------+ +--------------+ +-----------+ +-------------+ +-------------+ +----------------+ |
| | | | | | | | | | | | | | | |
| | Help | | MakeURL | | MakePathName | | Installer | | Uninstaller | | AddShortcut | | RemoveShortcut | |
| | | | | | | | | | | | | | | |
| +------+ +---------+ +--------------+ +-----------+ +-------------+ +-------------+ +----------------+ |
| |
+--------------------------------------------------------------------------------------------------------------------+
*/
Copyright © 1997-2008 Sho's Software