1 /*
2 * Part of WCM Commander
3 * https://github.com/corporateshark/WCMCommander
4 * wcm@linderdaum.com
5 */
6
7 #include <wal.h>
8
9 #ifdef _WIN32
10
11 #include "ext-app.h"
12 #include "string-util.h"
13 #include "w32util.h"
14
GetOpenApp(const std::string & ext)15 static std::vector<wchar_t> GetOpenApp( const std::string& ext )
16 {
17 if ( ext.empty() ) { return std::vector<wchar_t>(); }
18
19 RegKey key;
20
21 std::string Key = "software\\classes\\" + ext;
22
23 if ( !key.Open( HKEY_CURRENT_USER, widen(Key).c_str() ) )
24 {
25 key.Open( HKEY_CLASSES_ROOT, widen(ext).c_str() );
26 }
27
28 std::vector<wchar_t> p = key.GetString();
29
30 if ( !key.Open( HKEY_CURRENT_USER, carray_cat<wchar_t>( L"software\\classes\\", p.data(), L"\\shell\\open\\command" ).data() ) )
31 {
32 key.Open( HKEY_CLASSES_ROOT, carray_cat<wchar_t>( p.data(), L"\\shell\\open\\command" ).data() );
33 }
34
35 return key.GetString();
36 }
37
CfgStringToCommand(const wchar_t * cfgCmd,const unicode_t * uri)38 static std::vector<unicode_t> CfgStringToCommand( const wchar_t* cfgCmd, const unicode_t* uri )
39 {
40 std::vector<unicode_t> res;
41 int insCount = 0;
42
43 int prev = 0;
44
45 for ( const wchar_t* s = cfgCmd; *s; prev = *s, s++ )
46 {
47 if ( *s == '%' && ( s[1] == '1' || s[1] == 'l' || s[1] == 'L' ) )
48 {
49 if ( prev != '"' && prev != '\'' ) { res.push_back( '"' ); }
50
51 for ( const unicode_t* t = uri; *t; t++ ) { res.push_back( *t ); }
52
53 if ( prev != '"' && prev != '\'' ) { res.push_back( '"' ); }
54
55 s++;
56 insCount++;
57 }
58 else { res.push_back( *s ); }
59 }
60
61 if ( !insCount )
62 {
63 res.push_back( ' ' );
64 res.push_back( '"' );
65
66 for ( const unicode_t* t = uri; *t; t++ ) { res.push_back( *t ); }
67
68 res.push_back( '"' );
69 }
70
71 res.push_back( 0 );
72
73 return res;
74 }
75
NormalizeStr(unicode_t * s)76 static std::vector<unicode_t> NormalizeStr( unicode_t* s )
77 {
78 if ( !s ) { return std::vector<unicode_t>(); }
79
80 int n = unicode_strlen( s );
81 std::vector<unicode_t> p( n + 1 );
82 unicode_t* t = p.data();
83
84 for ( ; *s; s++ ) if ( *s != '&' ) { *( t++ ) = *s; }
85
86 *t = 0;
87 return p;
88 }
89
GetAppList(const unicode_t * uri)90 clPtr<AppList> GetAppList( const unicode_t* uri )
91 {
92 std::string ext = GetFileExt( uri );
93
94 if ( ext.empty() ) { return 0; }
95
96 RegKey key;
97
98 std::string Key = "software\\classes\\" + ext;
99
100 if ( !key.Open( HKEY_CURRENT_USER, widen(Key).c_str() ) )
101 {
102 key.Open( HKEY_CLASSES_ROOT, widen(ext).c_str() );
103 }
104
105 std::vector<wchar_t> p = key.GetString();
106
107 RegKey key2;
108
109 if ( !key2.Open( HKEY_CURRENT_USER, carray_cat<wchar_t>( L"software\\classes\\", p.data(), L"\\shell" ).data() ) )
110 {
111 key2.Open( HKEY_CLASSES_ROOT, carray_cat<wchar_t>( p.data(), L"\\shell" ).data() );
112 }
113
114
115 if ( !key2.Ok() ) { return 0; }
116
117 clPtr<AppList> ret = new AppList();
118
119 std::vector<wchar_t> pref = key2.GetString();
120
121 for ( int i = 0; i < 10; i++ )
122 {
123 std::vector<wchar_t> sub = key2.SubKey( i );
124
125 if ( !sub.data() ) { break; }
126
127 RegKey key25;
128 key25.Open( key2.Key(), sub.data() );
129
130 if ( !key25.Ok() ) { continue; }
131
132 std::vector<wchar_t> name = key25.GetString();
133 //wprintf(L"%s, %s\n", sub.ptr(), name.ptr());
134 RegKey key3;
135 key3.Open( key25.Key(), L"command" );
136 std::vector<wchar_t> command = key3.GetString();
137
138 if ( command.data() )
139 {
140 AppList::Node node;
141 node.name = NormalizeStr( Utf16ToUnicode( name.data() && name[0] ? name.data() : sub.data() ).data() );
142 node.cmd = CfgStringToCommand( command.data(), uri );
143
144 bool IsPref = pref.data() && !_wcsicmp( pref.data(), sub.data() );
145 bool IsOpen = !pref.data() && !_wcsicmp( L"Open", sub.data() );
146
147 if ( IsPref || ( IsOpen && ret->list.count() > 0 ) )
148 {
149 ret->list.insert( 0 );
150 ret->list[0] = node;
151 }
152 else
153 {
154 ret->list.append( node );
155 }
156 }
157 }
158
159 key2.Open( key.Key(), L"OpenWithList" );
160
161 if ( key2.Ok() )
162 {
163 clPtr<AppList> openWith = new AppList();
164
165 for ( int i = 0; i < 10; i++ )
166 {
167 std::vector<wchar_t> sub = key2.SubKey( i );
168
169 if ( !sub.data() ) { break; }
170
171 RegKey keyApplication;
172 keyApplication.Open( HKEY_CLASSES_ROOT,
173 carray_cat<wchar_t>( L"Applications\\", sub.data(), L"\\shell\\open\\command" ).data() );
174 std::vector<wchar_t> command = keyApplication.GetString();
175
176 if ( command.data() )
177 {
178 AppList::Node node;
179 node.name = NormalizeStr( Utf16ToUnicode( sub.data() ).data() );
180 node.cmd = CfgStringToCommand( command.data(), uri );
181 openWith->list.append( node );
182 }
183 }
184
185 if ( openWith->Count() > 0 )
186 {
187 AppList::Node node;
188 static unicode_t openWidthString[] = { 'O', 'p', 'e', 'n', ' ', 'w', 'i', 't', 'h', 0};
189 node.name = new_unicode_str( openWidthString );
190 node.sub = openWith;
191 ret->list.append( node );
192 }
193 }
194
195 return ret->Count() ? ret : 0;
196 }
197
198
GetOpenCommand(const unicode_t * uri,bool * needTerminal,const unicode_t ** pAppName)199 std::vector<unicode_t> GetOpenCommand( const unicode_t* uri, bool* needTerminal, const unicode_t** pAppName )
200 {
201 std::vector<wchar_t> wCmd = GetOpenApp( GetFileExt( uri ).data() );
202
203 if ( !wCmd.data() ) { return std::vector<unicode_t>(); }
204
205 return CfgStringToCommand( wCmd.data(), uri );
206 }
207
208
209 #endif
210