do not statically link to ole32.dll, import the functions dynamically instead. This...
[reactos.git] / reactos / lib / userenv / desktop.c
1 /* $Id: desktop.c,v 1.7 2004/07/11 22:35:07 weiden Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/userenv/desktop.c
6 * PURPOSE: Desktop and start menu support functions.
7 * PROGRAMMER: Eric Kohl
8 */
9
10 #include <ntos.h>
11 #include <windows.h>
12 #include <userenv.h>
13 #include <tchar.h>
14 #include <shlobj.h>
15
16 #include "internal.h"
17
18
19 /* FUNCTIONS ***************************************************************/
20
21 static BOOL
22 GetDesktopPath (BOOL bCommonPath,
23 LPWSTR lpDesktopPath)
24 {
25 WCHAR szPath[MAX_PATH];
26 DWORD dwLength;
27 DWORD dwType;
28 HKEY hKey;
29
30 DPRINT ("GetDesktopPath() called\n");
31
32 if (RegOpenKeyExW (HKEY_CURRENT_USER,
33 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
34 0,
35 KEY_ALL_ACCESS,
36 &hKey))
37 {
38 DPRINT1 ("RegOpenKeyExW() failed\n");
39 return FALSE;
40 }
41
42 dwLength = MAX_PATH * sizeof(WCHAR);
43 if (RegQueryValueExW (hKey,
44 bCommonPath ? L"Common Desktop" : L"Desktop",
45 0,
46 &dwType,
47 (LPBYTE)szPath,
48 &dwLength))
49 {
50 DPRINT1 ("RegQueryValueExW() failed\n");
51 RegCloseKey (hKey);
52 return FALSE;
53 }
54
55 RegCloseKey (hKey);
56
57 if (dwType == REG_EXPAND_SZ)
58 {
59 ExpandEnvironmentStringsW (szPath,
60 lpDesktopPath,
61 MAX_PATH);
62 }
63 else
64 {
65 wcscpy (lpDesktopPath, szPath);
66 }
67
68 DPRINT ("GetDesktopPath() done\n");
69
70 return TRUE;
71 }
72
73
74 static BOOL
75 GetProgramsPath (BOOL bCommonPath,
76 LPWSTR lpProgramsPath)
77 {
78 WCHAR szPath[MAX_PATH];
79 DWORD dwLength;
80 DWORD dwType;
81 HKEY hKey;
82
83 DPRINT ("GetProgramsPath() called\n");
84
85 if (RegOpenKeyExW (HKEY_CURRENT_USER,
86 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
87 0,
88 KEY_ALL_ACCESS,
89 &hKey))
90 {
91 DPRINT1 ("RegOpenKeyExW() failed\n");
92 return FALSE;
93 }
94
95 dwLength = MAX_PATH * sizeof(WCHAR);
96 if (RegQueryValueExW (hKey,
97 bCommonPath ? L"Common Programs" : L"Programs",
98 0,
99 &dwType,
100 (LPBYTE)szPath,
101 &dwLength))
102 {
103 DPRINT1 ("RegQueryValueExW() failed\n");
104 RegCloseKey (hKey);
105 return FALSE;
106 }
107
108 RegCloseKey (hKey);
109
110 if (dwType == REG_EXPAND_SZ)
111 {
112 ExpandEnvironmentStringsW (szPath,
113 lpProgramsPath,
114 MAX_PATH);
115 }
116 else
117 {
118 wcscpy (lpProgramsPath,
119 szPath);
120 }
121
122 DPRINT ("GetProgramsPath() done\n");
123
124 return TRUE;
125 }
126
127
128 BOOL WINAPI
129 AddDesktopItemA (BOOL bCommonItem,
130 LPCSTR lpItemName,
131 LPCSTR lpArguments,
132 LPCSTR lpIconLocation,
133 INT iIcon,
134 LPCSTR lpWorkingDirectory,
135 WORD wHotKey,
136 INT iShowCmd)
137 {
138 DPRINT1 ("AddDesktopItemA() not implemented!\n");
139 return FALSE;
140 }
141
142
143 BOOL WINAPI
144 AddDesktopItemW (BOOL bCommonDesktop,
145 LPCWSTR lpItemName,
146 LPCWSTR lpArguments,
147 LPCWSTR lpIconLocation,
148 INT iIcon,
149 LPCWSTR lpWorkingDirectory,
150 WORD wHotKey,
151 INT iShowCmd)
152 {
153 DYN_FUNCS Ole32;
154 WCHAR szLinkPath[MAX_PATH];
155 WCHAR szArguments[MAX_PATH];
156 WCHAR szCommand[MAX_PATH];
157 WIN32_FIND_DATA FindData;
158 HANDLE hFind;
159 LPWSTR Ptr;
160 DWORD dwLength;
161 IShellLinkW* psl;
162 IPersistFile* ppf;
163 HRESULT hr;
164 BOOL bResult;
165
166 DPRINT ("AddDesktopItemW() called\n");
167
168 bResult = FALSE;
169
170 if (!GetDesktopPath (bCommonDesktop, szLinkPath))
171 {
172 DPRINT1 ("GetDesktopPath() failed\n");
173 return FALSE;
174 }
175 DPRINT ("Desktop path: '%S'\n", szLinkPath);
176
177 /* Make sure the path exists */
178 hFind = FindFirstFileW (szLinkPath,
179 &FindData);
180 if (hFind == INVALID_HANDLE_VALUE)
181 {
182 DPRINT ("'%S' does not exist\n", szLinkPath);
183
184 /* Create directory path */
185 if (!CreateDirectoryPath (szLinkPath, NULL))
186 return FALSE;
187 }
188 else
189 {
190 DPRINT ("'%S' exists\n", szLinkPath);
191 FindClose (hFind);
192 }
193
194 /* Append backslash, item name and ".lnk" extension */
195 wcscat (szLinkPath, L"\\");
196 wcscat (szLinkPath, lpItemName);
197 wcscat (szLinkPath, L".lnk");
198 DPRINT ("Link path: '%S'\n", szLinkPath);
199
200 /* Split 'lpArguments' string into command and arguments */
201 Ptr = wcschr (lpArguments, L' ');
202 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
203 if (Ptr != NULL)
204 {
205 dwLength = (DWORD)(Ptr - lpArguments);
206 DPRINT ("dwLength %lu\n", dwLength);
207 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
208 szCommand[dwLength] = 0;
209 Ptr++;
210 wcscpy (szArguments, Ptr);
211 }
212 else
213 {
214 wcscpy (szCommand, lpArguments);
215 szArguments[0] = 0;
216 }
217 DPRINT ("szCommand: '%S'\n", szCommand);
218 DPRINT ("szArguments: '%S'\n", szArguments);
219
220 /* dynamically load ole32.dll */
221 LoadDynamicImports(&DynOle32, &Ole32);
222
223 Ole32.fn.CoInitialize(NULL);
224
225 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
226 NULL,
227 CLSCTX_INPROC_SERVER,
228 &IID_IShellLinkW,
229 (LPVOID*)&psl);
230 if (!SUCCEEDED(hr))
231 {
232 Ole32.fn.CoUninitialize();
233 UnloadDynamicImports(&Ole32);
234 return FALSE;
235 }
236
237 hr = psl->lpVtbl->QueryInterface(psl,
238 &IID_IPersistFile,
239 (LPVOID*)&ppf);
240 if (SUCCEEDED(hr))
241 {
242 psl->lpVtbl->SetDescription(psl,
243 lpItemName);
244
245 psl->lpVtbl->SetPath(psl,
246 szCommand);
247
248 psl->lpVtbl->SetArguments(psl,
249 szArguments);
250
251 psl->lpVtbl->SetIconLocation(psl,
252 lpIconLocation,
253 iIcon);
254
255 if (lpWorkingDirectory != NULL)
256 {
257 psl->lpVtbl->SetWorkingDirectory(psl,
258 lpWorkingDirectory);
259 }
260 else
261 {
262 psl->lpVtbl->SetWorkingDirectory(psl,
263 L"%HOMEDRIVE%%HOMEPATH%");
264 }
265
266 psl->lpVtbl->SetHotkey(psl,
267 wHotKey);
268
269 psl->lpVtbl->SetShowCmd(psl,
270 iShowCmd);
271
272 hr = ppf->lpVtbl->Save(ppf,
273 szLinkPath,
274 TRUE);
275 if (SUCCEEDED(hr))
276 bResult = TRUE;
277
278 ppf->lpVtbl->Release(ppf);
279 }
280
281 psl->lpVtbl->Release(psl);
282
283 Ole32.fn.CoUninitialize();
284
285 UnloadDynamicImports(&Ole32);
286
287 DPRINT ("AddDesktopItemW() done\n");
288
289 return bResult;
290 }
291
292
293 BOOL WINAPI
294 DeleteDesktopItemA (BOOL bCommonItem,
295 LPCSTR lpItemName)
296 {
297 DPRINT1 ("DeleteDesktopItemA() not implemented!\n");
298 return FALSE;
299 }
300
301
302 BOOL WINAPI
303 DeleteDesktopItemW (BOOL bCommonItem,
304 LPCWSTR lpItemName)
305 {
306 WCHAR szLinkPath[MAX_PATH];
307
308 DPRINT ("DeleteDesktopItemW() called\n");
309
310 if (!GetDesktopPath (bCommonItem, szLinkPath))
311 {
312 DPRINT1 ("GetDesktopPath() failed\n");
313 return FALSE;
314 }
315
316 wcscat (szLinkPath, L"\\");
317 wcscat (szLinkPath, lpItemName);
318 wcscat (szLinkPath, L".lnk");
319 DPRINT ("Link path: '%S'\n", szLinkPath);
320
321 return DeleteFile (szLinkPath);
322 }
323
324
325 BOOL WINAPI
326 CreateGroupA (LPCSTR lpGroupName,
327 BOOL bCommonGroup)
328 {
329 DPRINT1 ("CreateGroupA() not implemented!\n");
330 return FALSE;
331 }
332
333
334 BOOL WINAPI
335 CreateGroupW (LPCWSTR lpGroupName,
336 BOOL bCommonGroup)
337 {
338 WCHAR szGroupPath[MAX_PATH];
339
340 DPRINT1 ("CreateGroupW() called\n");
341
342 if (lpGroupName == NULL || *lpGroupName == 0)
343 return TRUE;
344
345 if (!GetProgramsPath (bCommonGroup, szGroupPath))
346 {
347 DPRINT1 ("GetProgramsPath() failed\n");
348 return FALSE;
349 }
350 DPRINT1 ("Programs path: '%S'\n", szGroupPath);
351
352 wcscat (szGroupPath, L"\\");
353 wcscat (szGroupPath, lpGroupName);
354 DPRINT1 ("Group path: '%S'\n", szGroupPath);
355
356 /* Create directory path */
357 if (!CreateDirectoryPath (szGroupPath, NULL))
358 return FALSE;
359
360 /* FIXME: Notify the shell */
361
362 DPRINT1 ("CreateGroupW() done\n");
363
364 return TRUE;
365 }
366
367
368 BOOL WINAPI
369 DeleteGroupA (LPCSTR lpGroupName,
370 BOOL bCommonGroup)
371 {
372 DPRINT1 ("DeleteGroupA() not implemented!\n");
373 return FALSE;
374 }
375
376
377 BOOL WINAPI
378 DeleteGroupW (LPCWSTR lpGroupName,
379 BOOL bCommonGroup)
380 {
381 WCHAR szGroupPath[MAX_PATH];
382
383 DPRINT ("DeleteGroupW() called\n");
384
385 if (lpGroupName == NULL || *lpGroupName == 0)
386 return TRUE;
387
388 if (!GetProgramsPath (bCommonGroup, szGroupPath))
389 {
390 DPRINT1 ("GetProgramsPath() failed\n");
391 return FALSE;
392 }
393 DPRINT ("Programs path: '%S'\n", szGroupPath);
394
395 wcscat (szGroupPath, L"\\");
396 wcscat (szGroupPath, lpGroupName);
397 DPRINT ("Group path: '%S'\n", szGroupPath);
398
399 /* Remove directory path */
400 if (!RemoveDirectoryPath (szGroupPath))
401 return FALSE;
402
403 /* FIXME: Notify the shell */
404
405 DPRINT ("DeleteGroupW() done\n");
406
407 return TRUE;
408 }
409
410
411 BOOL WINAPI
412 AddItemA (LPCSTR lpGroupName,
413 BOOL bCommonGroup,
414 LPCSTR lpItemName,
415 LPCSTR lpArguments,
416 LPCSTR lpIconLocation,
417 INT iIcon,
418 LPCSTR lpWorkingDirectory,
419 WORD wHotKey,
420 INT iShowCmd)
421 {
422 DPRINT1 ("AddItemA() not implemented!\n");
423 return FALSE;
424 }
425
426
427 BOOL WINAPI
428 AddItemW (LPCWSTR lpGroupName,
429 BOOL bCommonGroup,
430 LPCWSTR lpItemName,
431 LPCWSTR lpArguments,
432 LPCWSTR lpIconLocation,
433 INT iIcon,
434 LPCWSTR lpWorkingDirectory,
435 WORD wHotKey,
436 INT iShowCmd)
437 {
438 DYN_FUNCS Ole32;
439 WCHAR szLinkPath[MAX_PATH];
440 WCHAR szArguments[MAX_PATH];
441 WCHAR szCommand[MAX_PATH];
442 WIN32_FIND_DATA FindData;
443 HANDLE hFind;
444 LPWSTR Ptr;
445 DWORD dwLength;
446 IShellLinkW* psl;
447 IPersistFile* ppf;
448 HRESULT hr;
449 BOOL bResult;
450
451 DPRINT ("AddItemW() called\n");
452
453 bResult = FALSE;
454
455 if (!GetProgramsPath (bCommonGroup, szLinkPath))
456 {
457 DPRINT1 ("GetProgramsPath() failed\n");
458 return FALSE;
459 }
460
461 DPRINT ("Programs path: '%S'\n", szLinkPath);
462
463 if (lpGroupName != NULL && *lpGroupName != 0)
464 {
465 wcscat (szLinkPath, L"\\");
466 wcscat (szLinkPath, lpGroupName);
467
468 /* Make sure the path exists */
469 hFind = FindFirstFileW (szLinkPath,
470 &FindData);
471 if (hFind == INVALID_HANDLE_VALUE)
472 {
473 DPRINT ("'%S' does not exist\n", szLinkPath);
474 if (!CreateGroupW (lpGroupName,
475 bCommonGroup))
476 return FALSE;
477 }
478 else
479 {
480 DPRINT ("'%S' exists\n", szLinkPath);
481 FindClose (hFind);
482 }
483 }
484
485 wcscat (szLinkPath, L"\\");
486 wcscat (szLinkPath, lpItemName);
487 wcscat (szLinkPath, L".lnk");
488 DPRINT ("Link path: '%S'\n", szLinkPath);
489
490 /* Split 'lpArguments' string into command and arguments */
491 Ptr = wcschr (lpArguments, L' ');
492 DPRINT ("Ptr %p lpArguments %p\n", Ptr, lpArguments);
493 if (Ptr != NULL)
494 {
495 dwLength = (DWORD)(Ptr - lpArguments);
496 DPRINT ("dwLength %lu\n", dwLength);
497 memcpy (szCommand, lpArguments, dwLength * sizeof(WCHAR));
498 szCommand[dwLength] = 0;
499 Ptr++;
500 wcscpy (szArguments, Ptr);
501 }
502 else
503 {
504 wcscpy (szCommand, lpArguments);
505 szArguments[0] = 0;
506 }
507 DPRINT ("szCommand: '%S'\n", szCommand);
508 DPRINT ("szArguments: '%S'\n", szArguments);
509
510 /* dynamically load ole32.dll */
511 LoadDynamicImports(&DynOle32, &Ole32);
512
513 Ole32.fn.CoInitialize(NULL);
514
515 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink,
516 NULL,
517 CLSCTX_INPROC_SERVER,
518 &IID_IShellLinkW,
519 (LPVOID*)&psl);
520 if (!SUCCEEDED(hr))
521 {
522 Ole32.fn.CoUninitialize();
523 UnloadDynamicImports(&Ole32);
524 return FALSE;
525 }
526
527 hr = psl->lpVtbl->QueryInterface(psl,
528 &IID_IPersistFile,
529 (LPVOID*)&ppf);
530 if (SUCCEEDED(hr))
531 {
532 psl->lpVtbl->SetDescription(psl,
533 lpItemName);
534
535 psl->lpVtbl->SetPath(psl,
536 szCommand);
537
538 psl->lpVtbl->SetArguments(psl,
539 szArguments);
540
541 psl->lpVtbl->SetIconLocation(psl,
542 lpIconLocation,
543 iIcon);
544
545 if (lpWorkingDirectory != NULL)
546 {
547 psl->lpVtbl->SetWorkingDirectory(psl,
548 lpWorkingDirectory);
549 }
550 else
551 {
552 psl->lpVtbl->SetWorkingDirectory(psl,
553 L"%HOMEDRIVE%%HOMEPATH%");
554 }
555
556 psl->lpVtbl->SetHotkey(psl,
557 wHotKey);
558
559 psl->lpVtbl->SetShowCmd(psl,
560 iShowCmd);
561
562 hr = ppf->lpVtbl->Save(ppf,
563 szLinkPath,
564 TRUE);
565 if (SUCCEEDED(hr))
566 bResult = TRUE;
567
568 ppf->lpVtbl->Release(ppf);
569 }
570
571 psl->lpVtbl->Release(psl);
572
573 Ole32.fn.CoUninitialize();
574 UnloadDynamicImports(&Ole32);
575
576 DPRINT ("AddItemW() done\n");
577
578 return bResult;
579 }
580
581
582 BOOL WINAPI
583 DeleteItemA (LPCSTR lpGroupName,
584 BOOL bCommonGroup,
585 LPCSTR lpItemName,
586 BOOL bDeleteGroup)
587 {
588 DPRINT1 ("DeleteItemA() not implemented!\n");
589 return FALSE;
590 }
591
592
593 BOOL WINAPI
594 DeleteItemW (LPCWSTR lpGroupName,
595 BOOL bCommonGroup,
596 LPCWSTR lpItemName,
597 BOOL bDeleteGroup)
598 {
599 WCHAR szItemPath[MAX_PATH];
600 LPWSTR Ptr;
601
602 DPRINT ("DeleteItemW() called\n");
603
604 if (!GetProgramsPath (bCommonGroup, szItemPath))
605 {
606 DPRINT1 ("GetProgramsPath() failed\n");
607 return FALSE;
608 }
609 DPRINT ("Programs path: '%S'\n", szItemPath);
610
611 if (lpGroupName != NULL && *lpGroupName != 0)
612 {
613 wcscat (szItemPath, L"\\");
614 wcscat (szItemPath, lpGroupName);
615 }
616
617 wcscat (szItemPath, L"\\");
618 wcscat (szItemPath, lpItemName);
619 wcscat (szItemPath, L".lnk");
620 DPRINT ("Item path: '%S'\n", szItemPath);
621
622 if (!DeleteFileW (szItemPath))
623 return FALSE;
624
625 /* FIXME: Notify the shell */
626
627 if (bDeleteGroup)
628 {
629 Ptr = wcsrchr (szItemPath, L'\\');
630 if (Ptr == NULL)
631 return TRUE;
632
633 *Ptr = 0;
634 DPRINT ("Item path: '%S'\n", szItemPath);
635 if (RemoveDirectoryW (szItemPath))
636 {
637 /* FIXME: Notify the shell */
638 }
639 }
640
641 DPRINT ("DeleteItemW() done\n");
642
643 return TRUE;
644 }
645
646 /* EOF */