⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shlexec.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:

    return ret;
}

/*************************************************************************
 *	execute_from_key [Internal]
 */
static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
			     SHELL_ExecuteW32 execfunc,
                             LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
{
    WCHAR cmd[1024];
    LONG cmdlen = sizeof(cmd);
    UINT_PTR retval = 31;

    cmd[0] = '\0';

    /* Get the application for the registry */
    if (RegQueryValueW(HKEY_CLASSES_ROOT, key, cmd, &cmdlen) == ERROR_SUCCESS)
    {
	static const WCHAR wCommand[] = {'c','o','m','m','a','n','d',0};
	static const WCHAR wDdeexec[] = {'d','d','e','e','x','e','c',0};
        LPWSTR tmp;
        WCHAR param[256];
        LONG paramlen = sizeof(param);

        param[0] = '\0';

        /* Get the parameters needed by the application
           from the associated ddeexec key */
        tmp = strstrW(key, wCommand);
        assert(tmp);
        strcpyW(tmp, wDdeexec);

        if (RegQueryValueW(HKEY_CLASSES_ROOT, key, param, &paramlen) == ERROR_SUCCESS)
        {
            TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(param));
            retval = dde_connect(key, cmd, param, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out);
        }
        else
        {
            /* Is there a replace() function anywhere? */
            cmdlen /= sizeof(WCHAR);
            cmd[cmdlen] = '\0';
            SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline);
            retval = execfunc(param, env, FALSE, psei, psei_out);
        }
    }
    else TRACE("ooch\n");

    return retval;
}

/*************************************************************************
 * FindExecutableA			[SHELL32.@]
 */
HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
{
    HINSTANCE retval;
    WCHAR *wFile = NULL, *wDirectory = NULL;
    WCHAR wResult[MAX_PATH];

    if (lpFile) __SHCloneStrAtoW(&wFile, lpFile);
    if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory);

    retval = FindExecutableW(wFile, wDirectory, wResult);
    WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL);
    if (wFile) SHFree( wFile );
    if (wDirectory) SHFree( wDirectory );

    TRACE("returning %s\n", lpResult);
    return retval;
}

/*************************************************************************
 * FindExecutableW			[SHELL32.@]
 */
HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
{
    UINT_PTR retval = 31;    /* default - 'No association was found' */
    WCHAR old_dir[1024];

    TRACE("File %s, Dir %s\n",
          (lpFile != NULL ? debugstr_w(lpFile) : "-"), (lpDirectory != NULL ? debugstr_w(lpDirectory) : "-"));

    lpResult[0] = '\0'; /* Start off with an empty return string */

    /* trap NULL parameters on entry */
    if ((lpFile == NULL) || (lpResult == NULL))
    {
        /* FIXME - should throw a warning, perhaps! */
	return (HINSTANCE)2; /* File not found. Close enough, I guess. */
    }

    if (lpDirectory)
    {
        GetCurrentDirectoryW(sizeof(old_dir)/sizeof(WCHAR), old_dir);
        SetCurrentDirectoryW(lpDirectory);
    }

    retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL);

    TRACE("returning %s\n", debugstr_w(lpResult));
    if (lpDirectory)
        SetCurrentDirectoryW(old_dir);
    return (HINSTANCE)retval;
}

/* FIXME: is this already implemented somewhere else? */
static HKEY ShellExecute_GetClassKey( LPSHELLEXECUTEINFOW sei )
{
    LPCWSTR ext = NULL, lpClass = NULL;
    LPWSTR cls = NULL;
    DWORD type = 0, sz = 0;
    HKEY hkey = 0;
    LONG r;

    if (sei->fMask & SEE_MASK_CLASSALL)
        return sei->hkeyClass;
 
    if (sei->fMask & SEE_MASK_CLASSNAME)
        lpClass = sei->lpClass;
    else
    {
        ext = PathFindExtensionW( sei->lpFile );
        TRACE("ext = %s\n", debugstr_w( ext ) );
        if (!ext)
            return hkey;

        r = RegOpenKeyW( HKEY_CLASSES_ROOT, ext, &hkey );
        if (r != ERROR_SUCCESS )
            return hkey;

        r = RegQueryValueExW( hkey, NULL, 0, &type, NULL, &sz );
        if ( r == ERROR_SUCCESS && type == REG_SZ )
        {
            sz += sizeof (WCHAR);
            cls = HeapAlloc( GetProcessHeap(), 0, sz );
            cls[0] = 0;
            RegQueryValueExW( hkey, NULL, 0, &type, (LPBYTE) cls, &sz );
        }

        RegCloseKey( hkey );
        lpClass = cls;
    }

    TRACE("class = %s\n", debugstr_w(lpClass) );

    hkey = 0;
    if ( lpClass )
        RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey );

    HeapFree( GetProcessHeap(), 0, cls );

    return hkey;
}

static IDataObject *shellex_get_dataobj( LPSHELLEXECUTEINFOW sei )
{
    LPCITEMIDLIST pidllast = NULL;
    IDataObject *dataobj = NULL;
    IShellFolder *shf = NULL;
    LPITEMIDLIST pidl = NULL;
    HRESULT r;

    if (sei->fMask & SEE_MASK_CLASSALL)
        pidl = sei->lpIDList;
    else
    {
        WCHAR fullpath[MAX_PATH];

        fullpath[0] = 0;
        r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
        if (!r)
            goto end;

        pidl = ILCreateFromPathW( fullpath );
    }

    r = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&shf, &pidllast );
    if ( FAILED( r ) )
        goto end;

    IShellFolder_GetUIObjectOf( shf, NULL, 1, &pidllast,
                                &IID_IDataObject, NULL, (LPVOID*) &dataobj );

end:
    if ( pidl != sei->lpIDList )
        ILFree( pidl );
    if ( shf )
        IShellFolder_Release( shf );
    return dataobj;
}

static HRESULT shellex_run_context_menu_default( IShellExtInit *obj,
                                                 LPSHELLEXECUTEINFOW sei )
{
    IContextMenu *cm = NULL;
    CMINVOKECOMMANDINFOEX ici;
    MENUITEMINFOW info;
    WCHAR string[0x80];
    INT i, n, def = -1;
    HMENU hmenu = 0;
    HRESULT r;

    TRACE("%p %p\n", obj, sei );

    r = IShellExtInit_QueryInterface( obj, &IID_IContextMenu, (LPVOID*) &cm );
    if ( FAILED( r ) )
        return r;

    hmenu = CreateMenu();
    if ( !hmenu )
        goto end;

    /* the number of the last menu added is returned in r */
    r = IContextMenu_QueryContextMenu( cm, hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY );
    if ( FAILED( r ) )
        goto end;

    n = GetMenuItemCount( hmenu );
    for ( i = 0; i < n; i++ )
    {
        memset( &info, 0, sizeof info );
        info.cbSize = sizeof info;
        info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
        info.dwTypeData = string;
        info.cch = sizeof string;
        string[0] = 0;
        GetMenuItemInfoW( hmenu, i, TRUE, &info );

        TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
            info.fState, info.dwItemData, info.fType, info.wID );
        if ( ( !sei->lpVerb && (info.fState & MFS_DEFAULT) ) ||
             ( sei->lpVerb && !lstrcmpiW( sei->lpVerb, string ) ) )
        {
            def = i;
            break;
        }
    }

    r = E_FAIL;
    if ( def == -1 )
        goto end;

    memset( &ici, 0, sizeof ici );
    ici.cbSize = sizeof ici;
    ici.fMask = CMIC_MASK_UNICODE;
    ici.nShow = sei->nShow;
    ici.lpVerb = MAKEINTRESOURCEA( def );
    ici.hwnd = sei->hwnd;
    ici.lpParametersW = sei->lpParameters;
    
    r = IContextMenu_InvokeCommand( cm, (LPCMINVOKECOMMANDINFO) &ici );

    TRACE("invoke command returned %08lx\n", r );

end:
    if ( hmenu )
        DestroyMenu( hmenu );
    if ( cm )
        IContextMenu_Release( cm );
    return r;
}

static HRESULT shellex_load_object_and_run( HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei )
{
    IDataObject *dataobj = NULL;
    IObjectWithSite *ows = NULL;
    IShellExtInit *obj = NULL;
    HRESULT r;

    TRACE("%p %s %p\n", hkey, debugstr_guid( guid ), sei );

    r = CoInitialize( NULL );
    if ( FAILED( r ) )
        goto end;

    r = CoCreateInstance( guid, NULL, CLSCTX_INPROC_SERVER,
                           &IID_IShellExtInit, (LPVOID*)&obj );
    if ( FAILED( r ) )
    {
        ERR("failed %08lx\n", r );
        goto end;
    }

    dataobj = shellex_get_dataobj( sei );
    if ( !dataobj )
    {
        ERR("failed to get data object\n");
        goto end;
    }

    r = IShellExtInit_Initialize( obj, NULL, dataobj, hkey );
    if ( FAILED( r ) )
        goto end;

    r = IShellExtInit_QueryInterface( obj, &IID_IObjectWithSite, (LPVOID*) &ows );
    if ( FAILED( r ) )
        goto end;

    IObjectWithSite_SetSite( ows, NULL );

    r = shellex_run_context_menu_default( obj, sei );

end:
    if ( ows )
        IObjectWithSite_Release( ows );
    if ( dataobj )
        IDataObject_Release( dataobj );
    if ( obj )
        IShellExtInit_Release( obj );
    CoUninitialize();
    return r;
}


/*************************************************************************
 *	ShellExecute_FromContextMenu [Internal]
 */
static LONG ShellExecute_FromContextMenu( LPSHELLEXECUTEINFOW sei )
{
    static const WCHAR szcm[] = { 's','h','e','l','l','e','x','\\',
        'C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 };
    HKEY hkey, hkeycm = 0;
    WCHAR szguid[39];
    HRESULT hr;
    GUID guid;
    DWORD i;
    LONG r;

    TRACE("%s\n", debugstr_w(sei->lpFile) );

    hkey = ShellExecute_GetClassKey( sei );
    if ( !hkey )
        return ERROR_FUNCTION_FAILED;

    r = RegOpenKeyW( hkey, szcm, &hkeycm );
    if ( r == ERROR_SUCCESS )
    {
        i = 0;
        while ( 1 )
        {
            r = RegEnumKeyW( hkeycm, i++, szguid, 39 );
            if ( r != ERROR_SUCCESS )
                break;

            hr = CLSIDFromString( szguid, &guid );
            if (SUCCEEDED(hr))
            {
                /* stop at the first one that succeeds in running */
                hr = shellex_load_object_and_run( hkey, &guid, sei );
                if ( SUCCEEDED( hr ) )
                    break;
            }
        }
        RegCloseKey( hkeycm );
    }

    if ( hkey != sei->hkeyClass )
        RegCloseKey( hkey );
    return r;
}

/*************************************************************************
 *	SHELL_execute [Internal]
 */
BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
{
    static const WCHAR wQuote[] = {'"',0};
    static const WCHAR wSpace[] = {' ',0};
    static const WCHAR wWww[] = {'w','w','w',0};
    static const WCHAR wFile[] = {'f','i','l','e',0};
    static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
    static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
    static const DWORD unsupportedFlags =
        SEE_MASK_INVOKEIDLIST  | SEE_MASK_ICON         | SEE_MASK_HOTKEY |
        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
        SEE_MASK_UNICODE       | SEE_MASK_NO_CONSOLE   | SEE_MASK_ASYNCOK |
        SEE_MASK_HMONITOR;

    WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH];
    SHELLEXECUTEINFOW sei_tmp;	/* modifiable copy of SHELLEXECUTEINFO struct */
    WCHAR wfileName[MAX_PATH];
    WCHAR *env;
    WCHAR lpstrProtocol[256];
    LPCWSTR lpFile;
    UINT_PTR retval = 31;
    WCHAR wcmd[1024];
    WCHAR buffer[MAX_PATH];
    WCHAR target[MAX_PATH];
    BOOL done;
    DWORD attribs;

    /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
    memcpy(&sei_tmp, sei, sizeof(sei_tmp));

    TRACE("mask=0x%08lx hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
            sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
            debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
            debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
            ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
                debugstr_w(sei_tmp.lpClass) : "not used");

    sei->hProcess = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -