Windows Programming

잘 알려진 폴더구하기(XP, Vista)

오즈마스터 2008. 2. 15. 14:39

잘 알려진 폴더구하기 (XP까지만 적용)

SHGetFolderPath

TCHAR szPath[MAX_PATH] = {0, };
// system32 폴더
::SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, szPath);
// Programe Files 폴더
::SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, szPath);
// 임시폴더 구하기
::SHGetFolderPath(NULL, CSIDL_APPDATA , NULL, 0, szPath);


Vista 를 고려하면...
다음은 비스타에서 Low 권한에서 쓰기 가능한 폴더를 찾는 함수입니다.

SHGetKnownFolderPath

근데, XP 를 포함한 이하 버전에는 이 함수가 없기에, 프로그램 실행하자 마자 실행이 안돼죠.
그래서 동적으로 할당해서 성공하면 (비스타) 그냥 쓰면 되고, 실패하면 (XP 에서 실패하겠죠) 원래의 시나리오 대로 진행하면 됩니다.


아래는 블로그에서 퍼온 소스 코드.

 

typedef UINT (CALLBACK* LPFNDLLFUNC1) (REFKNOWNFOLDERID /*rfid*/, DWORD /*dwFlags*/, HANDLE /*hToken*/, __out PWSTR */*ppszPath*/);

...

TCHAR* GetLocalAppDataLowPath( )
{
 TCHAR path[MAX_PATH] = {0,};
 PWSTR pszPath;

 OSVERSIONINFOEX osvi;
 SYSTEM_INFO si;
 BOOL bOsVersionInfoEx;

 ZeroMemory(&si, sizeof(SYSTEM_INFO));
 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

 // get Windows version
 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
 {
  osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
     /* 예외 처리 */
 }

 // get known folder path
 if (osvi.dwMajorVersion >= 6) // Windows Vista 이상
 {
  HINSTANCE hShell;
  LPFNDLLFUNC1 pGetKnownPath;    // Function pointer
  hShell = LoadLibrary("shell32.dll");

  pGetKnownPath = (LPFNDLLFUNC1)GetProcAddress(hShell, "SHGetKnownFolderPath");

  if (pGetKnownPath)
  {
   if (SUCCEEDED(pGetKnownPath(FOLDERID_LocalAppDataLow, 0, NULL, &pszPath)))
   {
    _tcscpy(path, CW2AEX<_MAX_PATH>(pszPath).m_szBuffer);
   }
   else 
      /* 예외 처리 */
  }
  else 
      /* 예외 처리 */

  FreeLibrary(hShell);
 }
 else // Windows Vista 이하 버전의 운영체제
 {
    /* Vista 이전 버전 처리 */
 }

 return path;
}

 PWSTR pszPath 는 SHGetKnownFolderPath 함수내에서 메모리 할당 하므로 caller (호출하는쪽) 에서 메모리 해제의 책임이 있다네요.

::CoTaskMemFree 를 쓰라고 하네요.

내 생각엔 OS 버전 체크를 굳이 안하고 , 함수포인터 반환여부만으로 (GetProcAddress) 체크해도 무방할 듯 하네요.

왜냐면, XP 에서 나중에 혹시 서비스팩이 나와서 이 함수를 지원하게 되는 경우도 고려할 수 있으니까...