Rundll32形式のDLLの呼び出し

(2004.05.06)
#pragma once
 
// WAC.com Class Liblary for Visual C++
// Copyright (C) WAC.com Inc. All rights reserved.
//
// This file is a part of the WAC.com Class Liblary.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
 
// '06.03.22 : UNICODEビルドに対応 (sha)
// '06.09.29 : APIに渡すTCHARのバッファサイズ修正 (his)
// '07.03.09 : _countofを使うように修正 (sha)
// '07.04.16 : コードの整備 (sha)
 
#include "Module.h"
 
#if _MSC_VER < 1400
#if !defined(_countof)
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#endif
#endif
 
 
/////////////////////////////////////////////////////////////////////////////
// CRundll32Helper
 
class CRundll32Helper
{
protected:
    typedef CRundll32Helper                        thisClass;
 
protected:
    CRundll32Helper();                            // 実装しない
    virtual ~CRundll32Helper();
 
public:
    static bool IsSupported(LPCTSTR szFileName, LPCTSTR szEntryName)
    {
        CModule module;
        
        HINSTANCE hInst = module.LoadLibrary(szFileName);
        if (hInst == NULL)
        {
            return false;
        }
 
        typedef void CALLBACK FUNC_EntryPoint(HWND hwnd, HINSTANCE hinst, LPTSTR lpCmdLine, int nCmdShow);
        FUNC_EntryPoint* func = (FUNC_EntryPoint*)module.GetProcAddress(szEntryName);
        if (func == NULL)
        {
            return false;
        }
 
        return true;
    }
    static HRESULT Invoke(HWND hWnd, HINSTANCE hInst, LPCTSTR szFileName, LPCTSTR szEntryName, LPCTSTR szCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
    {
        CModule module;
        
        HINSTANCE hInst2 = module.LoadLibrary(szFileName);
        if (hInst2 == NULL)
        {
            return E_NOTIMPL;
        }
 
        typedef void CALLBACK FUNC_EntryPoint(HWND hwnd, HINSTANCE hinst, LPTSTR lpCmdLine, int nCmdShow);
        FUNC_EntryPoint* func = (FUNC_EntryPoint*)module.GetProcAddress(szEntryName);
        if (func == NULL)
        {
            return E_NOTIMPL;
        }
 
        func(hWnd, hInst, (LPTSTR)szCmdLine, SW_SHOWNORMAL);
 
        return S_OK;
    }
    static HRESULT InvokeProcess(/*HWND hWnd, HINSTANCE hInst,*/ LPCTSTR szFileName, LPCTSTR szEntryName, LPCTSTR szCmdLine = NULL, int nCmdShow = SW_SHOWNORMAL)
    {
        HRESULT hr = S_OK;
 
        CString strCommand = _T("Rundll32.exe ") + thisClass::GetShortPathName(szFileName) + _T(",") + CString(szEntryName);
        DWORD dwExitProcessCode = 0;
        hr = thisClass::CreateProcessWaitForExit(strCommand, dwExitProcessCode);
        if (FAILED(hr))
        {
            return hr;
        }
 
        return hr;
    }
 
public:
    // http://hp.vector.co.jp/authors/VA022217/tips/hsp/rundll.html に色々なサンプルが載っている
    // プリンタの追加ウィザード
    static HRESULT ShowAddPrinterWizard(HWND hWnd, HINSTANCE hInst)
    {
        HRESULT hr = S_OK;
 
        hr = thisClass::Invoke(hWnd, hInst, _T("shell32.dll"), _T("SHHelpShortcuts_RunDLL"), _T("AddPrinter"));
        if (FAILED(hr))
        {
            // エラー
            return hr;
        }
 
        return hr;
    }
 
protected:
    // FileHelper.hから、コピー
    // Win95, WinNT3.5 or lator
    static CString GetShortPathName(LPCTSTR szLongPath)
    {
        TCHAR szShortPath[_MAX_PATH] = { 0 };
        DWORD dwResult = ::GetShortPathName(szLongPath, szShortPath, _countof(szShortPath));
        if (dwResult == 0)
        {
            return _T("");
        }
 
        return szShortPath;
    }
    static HRESULT CreateProcessWaitForExit(LPCTSTR szFileName, DWORD& dwExitProcessCode)
    {
        dwExitProcessCode = 0;
 
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi = { 0 };
        BOOL br = ::CreateProcess((LPCTSTR)NULL, (LPTSTR)szFileName, NULL, NULL, TRUE, 0, NULL,NULL, &si, &pi);
        if (br == 0)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        // スレッドのハンドルは使わないのですぐ破棄
        ::CloseHandle(pi.hThread);
 
        // プロセスが終了するまでまつ
        ::WaitForSingleObject(pi.hProcess, INFINITE);
 
        br = ::GetExitCodeProcess(pi.hProcess, &dwExitProcessCode);
        if (br == FALSE)
        {
            // 無視する。。
        }
 
        // もうプロセスのハンドルは使わないので破棄
        ::CloseHandle(pi.hProcess);
 
        return S_OK;
    }
};
一覧に戻る
© 2003 WAC.com All Right Reserved.