SHGetKnownFolderPathの引数


にゃおん  2008-01-31 06:06:12  No: 67408  IP: 192.*.*.*

.NET2005  VISTA  です。

先日、ドキュメントなど特別なフォルダのパスの取得方法をお尋ねして、SHGetFolderPathで、できるようになったのですが、いろいろなサイトを検索して、SHGetKnownFolderPathが気になりました。

MSDNを見ると、

HRESULT SHGetKnownFolderPath( 
    REFKNOWNFOLDERID rfid,
    DWORD dwFlags,
    HANDLE hToken,
    PWSTR *ppszPath
);

となっています。
この引数のうち、

    REFKNOWNFOLDERID rfid,
    PWSTR *ppszPath

が分りません。

REFKNOWNFOLDERID rfid,
は、
[in] A reference to the KNOWNFOLDERID that identifies the folder.
となっていますが、よく分かりません。
PWSTR *ppszPathも、なんだか理解できません。

できたら、ドキュメントのバスを取得する具体的なコードをご提示頂けないでしょうか。

編集 削除
シャノン  2008-01-31 10:12:07  No: 67409  IP: 192.*.*.*

> KNOWNFOLDERID

MSDN 見ましょう。ぐぐれば一発で出てきます。
とはいえ、SHGetKnownFolderPath のページからリンクが無いのは不親切ですね。
http://msdn2.microsoft.com/en-us/library/bb762584.aspx

> ppszPath

大抵、文字列を返す関数というのは、呼び出し側でバッファを確保して呼ぶものですが、この関数は、関数側でバッファを確保します。
そのバッファのポインタを受け取る必要があるため、ポインタのポインタを渡します。
確保されたバッファは、呼び出し側で CoTaskMemFree を使って解放します。

> ドキュメントのバスを取得する具体的なコードをご提示頂けないでしょうか。

こんな感じかな?(動作未確認)

PWSTR pBuffer = NULL;
HRESULT hr = SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &pBuffer );
if( SUCCEEDED( hr ) )
{
  // いろいろ処理する

  // メモリを解放
  CoTaskMemFree( pBuffer );
}

編集 削除
にゃおん  2008-02-01 04:42:33  No: 67410  IP: 192.*.*.*

シャノンさん、ありがとうございます。
KNOWNFOLDERID は、私がウマシカでした。

ご提示のコードで、ビルドすると、

'FOLDERID_Documents' : 定義されていない識別子です。
'SHGetKnownFolderPath': 識別子が見つかりませんでした

というエラーになります。

環境は VISTA MFC ユニコード です。
SP1 はあてています。

検索しても分らなかったのですが、なにかインクルードするなど、追加のコードが必要なのでしょうか。

編集 削除
Blue  2008-02-01 09:32:26  No: 67411  IP: 192.*.*.*

たぶん、VS2005に同梱されているSDKでは shlobj.h に関数が宣言されていません。
そのままの環境で使うのであれば LoadLibrary を使うことになるでしょう。

編集 削除
Blue  2008-02-01 13:51:43  No: 67412  IP: 192.*.*.*

>HRESULT hr = SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &pBuffer );
の2番目の引数って 0 でOKなのでしょうか?
http://msdn2.microsoft.com/en-us/library/bb762583(VS.85).aspx
すみませんが、私は↑を読んでいる暇はないです。

編集 削除
YuO  2008-02-01 15:08:23  No: 67413  IP: 192.*.*.*

> とはいえ、SHGetKnownFolderPath のページからリンクが無いのは不親切ですね。

サマリ部分にリンクがあるんですよね。
まぁ,ParametersやSee Alsoにもあってよいと思いますが。


>>HRESULT hr = SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &pBuffer );
>の2番目の引数って 0 でOKなのでしょうか?

OKです。

http://msdn2.microsoft.com/en-us/library/bb762188.aspx
> dwFlags
> [in] The KF_FLAG flags that specify special retrieval options. This value can be 0; otherwise, one or more of the KF_FLAG values.

編集 削除
Blue  2008-02-01 15:11:59  No: 67414  IP: 192.*.*.*

今試してみました。

REFKNOWNFOLDERIDを間違えて解釈していたので 0 じゃだめかもと思ったわけです。
(REFKNOWNFOLDERIDがGUIDだとばかり思っていた。REFってついているからGUID*なのね。)

試したコード

#include <windows.h>
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "ole32.lib")

int main()
{
    // FOLDERID_Documents 
    // GUID {FDD39AD0-238F-46AF-ADB4-6C85480369C7} 

    //HRESULT SHGetKnownFolderPath(REFKNOWNFOLDERID rfid,
    //                             DWORD dwFlags,
    //                             HANDLE hToken,
    //                             PWSTR *ppszPath
    //                            );
    typedef GUID KNOWNFOLDERID;
    typedef HRESULT (WINAPI *SHGETKNOWNFOLDERPATH)(KNOWNFOLDERID*, DWORD, HANDLE, PWSTR*);
    #define KF_FLAG_CREATE (0x00008000)
    #define KF_FLAG_NO_ALIAS (0x00001000)

    HMODULE hDll = ::LoadLibrary(TEXT("shell32.dll"));
    if (hDll)
    {
        SHGETKNOWNFOLDERPATH pSHGetKnownFolderPath;
        pSHGetKnownFolderPath = (SHGETKNOWNFOLDERPATH)::GetProcAddress(hDll, "SHGetKnownFolderPath");
        if (pSHGetKnownFolderPath)
        {
            KNOWNFOLDERID rfid = {0xFDD39AD0,0x238F,0x46AF,0xAD,0xB4,0x6C,0x85,0x48,0x03,0x69,0xC7};
            PWSTR pBuffer = NULL;
            HRESULT hr = (*pSHGetKnownFolderPath)(&rfid, 0, NULL, &pBuffer);
            if (SUCCEEDED(hr))
            {
                MessageBoxW(NULL, pBuffer, L"", MB_OK);
                ::CoTaskMemFree(pBuffer);
            }
        }
        ::FreeLibrary(hDll);
    }

    return 0;
}

間違っていたら指摘してください。

編集 削除
Blue  2008-02-01 15:12:53  No: 67415  IP: 192.*.*.*

#define は無視しておいてください。
いろいろ試した名残です。

編集 削除
シャノン  2008-02-01 15:57:54  No: 67416  IP: 192.*.*.*

> たぶん、VS2005に同梱されているSDKでは shlobj.h に関数が宣言されていません。

です。
SDK for Vista 入れましょう。
http://www.microsoft.com/downloads/details.aspx?familyid=ff6467e6-5bba-4bf5-b562-9199be864d29&displaylang=en

> サマリ部分にリンクがあるんですよね。

気づきませんでしたorz

> まぁ,ParametersやSee Alsoにもあってよいと思いますが。

ですです。

編集 削除
にゃおん  2008-02-03 10:19:26  No: 67417  IP: 192.*.*.*

すみません。
お返事しなければいけないと思ったのですが、初心者の私には理解できない内容になってしまって。。。

とりあえず、SHGetFolderPathでいきます。
2008は、遠からず様子をみて買おうと思っているので、それからまた試してみます。

たいへんありがとうございました。

編集 削除