Shortcut Saved to □□□□

I have a code here that will take a file and create a shortcut for it. The problem is that instead of the shortcut taking the name of the second command line parameter, it just shows a bunch of squares (□□□□). I can rename it to "something.lnk" and it becomes a valid shortcut, it's just that the name gets messed up during the save process.

You can see a picture here: http://img683.imageshack.us/img683/6889/squaresx.png

I think it has something to do with when the char* is converted to wchar_t*. IPersistFile::Save() only accepts a unicode string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* App for creating a windows shortcut */

#include <windows.h>
#include <iostream>
#include <shlobj.h>
#include <string.h>
#include <fstream>
using namespace std;

// Name of executable
string executable;

int main(int argc, char* argv[])
{
    executable = argv[0];
    
    CoInitialize(NULL);
    
    // Declare functions
    bool FileExists(char* filename);
    void ShowUsage();
    bool CreateShortcut(char* ExistingFileName, wchar_t* LinkFileName, char* Comment="", char* IconL="", int IconN=0);
    
    IShellLink *MyLink;
    // Make sure user inputs 2-3 arguments
    if (argc < 3 || argc > 5)
    {
        ShowUsage();
        return 1;
    }
    
    else
    {
        if (FileExists(argv[1]))
        {
            // Get full path to file
            char filename[248];
            GetFullPathName( argv[1], 248, filename, NULL);
            
            // Must convert shortcut name to unicode
            wchar_t* LinkName = (wchar_t*)argv[2];
        
            BOOL ret;
            if (argc == 3) ret = CreateShortcut(filename, LinkName);
            else ret = CreateShortcut(filename, LinkName, argv[3]);
            
            if (ret)
            {
                cout << "\nCreated link!" << endl;
                return 0;
            }
            else
            {
                cout << "\nAn error occured: Could not create link" << endl;
                return 1;
            }
        }
        else 
        {
            cout << "Cannot find \"" << argv[1] << "\"" << endl;
            ShowUsage();
            return 1;
        }
    }
}

bool FileExists(char* filename)
{
    ifstream ifile(filename);
    return ifile;
}

void ShowUsage()
{
    cout << "\n\tUsage:  " << executable << " <filename> <linkname> [<comment>]\n" << endl;
}

bool CreateShortcut(char* ExistingFileName, wchar_t* LinkFileName, char* Comment="", char* IconL="", int IconN=0)
{
    cout << "\nCreating link  to " << ExistingFileName << endl;
    
    CoInitialize(NULL);
    
    IShellLink* pShellLink = NULL;
    HRESULT hres;
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL,
                   IID_IShellLink, (void**)&pShellLink);
    if (SUCCEEDED(hres))
    {
        pShellLink->SetPath(ExistingFileName);  // Path to the object we are referring to
        if (Comment!="") pShellLink->SetDescription(Comment);  // Optional Comment
        if (IconL!="") pShellLink->SetIconLocation(IconL, IconN); // Set Icon
    
        IPersistFile *pPersistFile;
        hres = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
        
        if (SUCCEEDED(hres))
        {
            hres = pPersistFile->Save(LinkFileName, TRUE);  // Create shortcut
        
            pPersistFile->Release();
        }
        else return false;
        pShellLink->Release();
    }
    else return false;
    
    return true;
}
Last edited on
1
2
// Must convert shortcut name to unicode
wchar_t* LinkName = (wchar_t*)argv[2];

You aren't converting anything here. That is just an (incorrect) cast.
Do NOT use this type of casting. Use the C++ casts at all times (static_cast, etc.). That way, you can avoid mistakes in future, because if you have to use reinterpret_cast to get something to compile, it should cause alarm bells to go off in your head.
Last edited on
Edit: I had changed my code around, but now the lines below match the code above.

Okay, I have looked over the C++ typecasting: http://www.cplusplus.com/doc/tutorial/typecasting/
But, I still am having trouble. reinterpret_cast is the only one that would compile.

wchar_t* LinkName = dynamic_cast<wchar_t*>(argv[2]);

: error: cannot dynamic_cast `*(argv + 8u)' (of type `char*') to type `wchar_t*' (target is not pointer or reference to class)



wchar_t* LinkName = static_cast<wchar_t*>(argv[2]);

: error: invalid static_cast from type `char*' to type `wchar_t*'



This compiles but outputs the same thing "□□□□" when the shortcut is saved.
wchar_t* LinkName = reinterpret_cast<wchar_t*>(argv[2]);


And I didn't think const_cast was what I wanted to do, but I tried it anyway:
wchar_t* LinkName = const_cast<wchar_t*>(argv[2]);

: error: invalid const_cast from type `char*' to type `wchar_t*'


So I am still doing something wrong, but I don't know what.

Problem Solved! The answer was to use the C++ function mbstowcs:
1
2
wchar_t LinkName[512];
mbstowcs(LinkName, argv[2], 512);

The WINAPI function MultiByteToWideChar works as well:
1
2
wchar_t LinkName[512];
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, argv[2], 512, LinkName, 512);
Last edited on
Topic archived. No new replies allowed.