Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to get 'SHGetFolderPath' to work with '#define UNICODE'

Posted on 2007-03-21
5
Medium Priority
?
690 Views
Last Modified: 2008-01-09
I am trying to get 'SHGetFolderPath' to work with the '#define UNICODE'. I need '#define UNICODE' as within the same piece of code, i need to pass in unicode for a function to work. Unfortunately when i try to compile and run the following code, I do not get the desktop directory returned properly. Any idea why?

#define UNICODE
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <lm.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string>
#include <aclapi.h>
#include <winerror.h>
#include <tchar.h>
using namespace std;

/*------------------------- Function to provide desktop shortcut -------------------------*/
HRESULT CreateSC(LPCTSTR lpszPath, LPSTR lpszPathLink, LPCTSTR lpszDesc, LPCTSTR lpszWorkingDir)
{
   CoInitialize(NULL);
   HRESULT hres;
   IShellLink *pShLink;
   // Get a pointer to the IShellLink interface.
   hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
   reinterpret_cast<void**>(&pShLink));
   if (SUCCEEDED(hres))
   {          
      pShLink->SetPath(lpszPath);
      pShLink->SetDescription(lpszDesc);
      pShLink->SetWorkingDirectory(lpszWorkingDir);

      IPersistFile *pPersistFile;
      hres = pShLink->QueryInterface( IID_IPersistFile, reinterpret_cast<void**>(&pPersistFile));
         
      if (SUCCEEDED(hres))
      {
         wchar_t wsz[MAX_PATH];    
         MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
               
         // Save the link
         hres = pPersistFile->Save( wsz, TRUE);
         pPersistFile->Release();
        }
         else
            printf("Failed to create link!\n");
         pShLink->Release();
   }
   CoUninitialize();
   return hres;
}

void main()
{
/*------------------------ Creates a desktop shortcut -------------------------*/
   TCHAR DesktopPath[MAX_PATH];
    if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, DesktopPath)))
      printf("Done! The path is %s\n", DesktopFolderPath);
   else
      printf("Error creating desktop shortcut!\n");
}
0
Comment
Question by:fuzzyling
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
5 Comments
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18762811
>>>> I do not get the desktop directory returned properly
Can you tell where it goes wrong and what gows wrong?
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 200 total points
ID: 18762870
CSIDL_WINDOWS identifies the WINDIR or Windows directory, e. g. C:\Windows, rather than the desktop.

I read in the docs that the return value of SHGetFolderPathA and SHGetFolderPathW were different. So maybe the SUCCEEDED macro was not redefined properly.

MSDN:
E_FAIL SHGetFolderPathW only. The CSIDL in nFolder is valid, but the folder does not exist. Note that the failure code is different for the ANSI and Unicode versions of this function.

Try:

if (!(E_FAIL == SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, DesktopPath)))
      printf("Done! The path is %s\n", DesktopFolderPath);
   else
      printf("Error creating desktop shortcut!\n");
}

Regards, Alex
0
 
LVL 11

Expert Comment

by:Deepu Abraham
ID: 18764553
You should try with CSIDL_PROFILE / CSIDL_PROFILES rather than CSIDL_WINDOWS to get Desktop folders

Best Regards,
DeepuAbrahamK
0
 
LVL 86

Accepted Solution

by:
jkr earned 800 total points
ID: 18765008
Keep your parameters and string types consitent:

#define UNICODE
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <lm.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string>
#include <aclapi.h>
#include <winerror.h>
#include <tchar.h>
using namespace std;

/*------------------------- Function to provide desktop shortcut -------------------------*/

// not 'LPSTR lpszPathLink', but 'LP*T*STR lpszPathLink'
HRESULT CreateSC(LPCTSTR lpszPath, LPTSTR lpszPathLink, LPCTSTR lpszDesc, LPCTSTR lpszWorkingDir)
{
   CoInitialize(NULL);
   HRESULT hres;
   IShellLink *pShLink;
   // Get a pointer to the IShellLink interface.
   hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
   reinterpret_cast<void**>(&pShLink));
   if (SUCCEEDED(hres))
   {          
      pShLink->SetPath(lpszPath);
      pShLink->SetDescription(lpszDesc);
      pShLink->SetWorkingDirectory(lpszWorkingDir);

      IPersistFile *pPersistFile;
      hres = pShLink->QueryInterface( IID_IPersistFile, reinterpret_cast<void**>(&pPersistFile));
         
      if (SUCCEEDED(hres))
      {
      /* no conversion needed if you pass a UNICODE path to link
         wchar_t wsz[MAX_PATH];    
         MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
        */      
         // Save the link
         hres = pPersistFile->Save( lpszPathLink, TRUE);
         pPersistFile->Release();
        }
         else
            wprintf(L"Failed to create link!\n");
         pShLink->Release();
   }
   CoUninitialize();
   return hres;
}

void main()
{
/*------------------------ Creates a desktop shortcut -------------------------*/
   TCHAR DesktopPath[MAX_PATH];
    if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, DesktopPath)))
      wprintf(L"Done! The path is %s\n", DesktopFolderPath);
   else
      wprintf(L"Error creating desktop shortcut!\n");

}
0
 

Author Comment

by:fuzzyling
ID: 18768729
Hi,
Thanks Alex for pointing out that 'CSIDL_WINDOWS' identifies the windows directory. I was debugging and changed it from 'CSIDL_DESKTOPDIRECTORY'. Thanks jkr for helping me to correct those inconsistencies!
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
Suggested Courses

670 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question