1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3
4
5 // Win32Com.c
6 // Win32 COM module call
7
8 #ifdef OS_WIN32
9
10 #include "Win32Com.h"
11
12 extern "C"
13 {
14 #include "Mayaqua/FileIO.h"
15 #include "Mayaqua/Internat.h"
16 #include "Mayaqua/Mayaqua.h"
17 #include "Mayaqua/Memory.h"
18 #include "Mayaqua/Str.h"
19 }
20
21 #include <devguid.h>
22 #include <MsHtmHst.h>
23 #include <natupnp.h>
24 #include <netcfgn.h>
25 #include <SetupAPI.h>
26 #include <ShlObj.h>
27
28 // Add a UPnP port
Win32UPnPAddPort(UINT outside_port,UINT inside_port,bool udp,char * local_ip,wchar_t * description,bool remove_before_add)29 bool Win32UPnPAddPort(UINT outside_port, UINT inside_port, bool udp, char *local_ip, wchar_t *description, bool remove_before_add)
30 {
31 bool ret = false;
32 HRESULT hr;
33 IUPnPNAT *nat = NULL;
34 wchar_t ip_str[MAX_SIZE];
35 BSTR bstr_ip, bstr_description, bstr_protocol;
36 const wchar_t *protocol_str = (udp ? L"UDP" : L"TCP");
37 // Validate arguments
38 if (outside_port == 0 || outside_port >= 65536 || inside_port == 0 || inside_port >= 65536 ||
39 IsEmptyStr(local_ip) || UniIsEmptyStr(description))
40 {
41 return false;
42 }
43
44 StrToUni(ip_str, sizeof(ip_str), local_ip);
45 bstr_ip = SysAllocString(ip_str);
46 bstr_description = SysAllocString(description);
47 bstr_protocol = SysAllocString(protocol_str);
48
49 hr = CoCreateInstance(CLSID_UPnPNAT, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPNAT, (void **)&nat);
50
51 if (SUCCEEDED(hr))
52 {
53 if (nat != NULL)
54 {
55 IStaticPortMappingCollection *collection = NULL;
56 hr = nat->get_StaticPortMappingCollection(&collection);
57
58 if (SUCCEEDED(hr))
59 {
60 if (collection != NULL)
61 {
62 IStaticPortMapping *mapping = NULL;
63
64 if (remove_before_add)
65 {
66 hr = collection->Remove((long)outside_port, bstr_protocol);
67 }
68
69 hr = collection->Add((long)outside_port, bstr_protocol, (long)inside_port,
70 bstr_ip, VARIANT_TRUE, bstr_description, &mapping);
71
72 if (SUCCEEDED(hr))
73 {
74 ret = true;
75
76 if (mapping != NULL)
77 {
78 mapping->Release();
79 }
80 }
81
82 collection->Release();
83 }
84 else
85 {
86 WHERE;
87 }
88 }
89 else
90 {
91 WHERE;
92 }
93
94 nat->Release();
95 }
96 else
97 {
98 WHERE;
99 }
100 }
101 else
102 {
103 WHERE;
104 }
105
106 SysFreeString(bstr_ip);
107 SysFreeString(bstr_description);
108 SysFreeString(bstr_protocol);
109
110 return ret;
111 }
112
113 // Install the NDIS protocol driver
UninstallNdisProtocolDriver(wchar_t * id,UINT lock_timeout)114 bool UninstallNdisProtocolDriver(wchar_t *id, UINT lock_timeout)
115 {
116 bool ret = false;
117 HRESULT hr;
118 INetCfg *pNetCfg;
119 // Validate arguments
120 if (id == NULL)
121 {
122 return false;
123 }
124
125 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void **)&pNetCfg);
126
127 if (SUCCEEDED(hr))
128 {
129 INetCfgLock *pLock;
130
131 hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
132
133 if (SUCCEEDED(hr))
134 {
135 LPWSTR locked_by;
136
137 hr = pLock->AcquireWriteLock(lock_timeout, L"SoftEther VPN", &locked_by);
138
139 if (SUCCEEDED(hr))
140 {
141 hr = pNetCfg->Initialize(NULL);
142
143 if (SUCCEEDED(hr))
144 {
145 INetCfgComponent *pncc = NULL;
146
147 hr = pNetCfg->FindComponent(id, &pncc);
148
149 if (pncc == NULL || hr == S_FALSE)
150 {
151 hr = E_FAIL;
152 }
153
154 if (SUCCEEDED(hr))
155 {
156 INetCfgClass *pncClass;
157
158 hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS, IID_INetCfgClass, (void **)&pncClass);
159 if (SUCCEEDED(hr))
160 {
161 INetCfgClassSetup *pncClassSetup;
162
163 hr = pncClass->QueryInterface(IID_INetCfgClassSetup, (void **)&pncClassSetup);
164 if (SUCCEEDED(hr))
165 {
166 OBO_TOKEN obo;
167 wchar_t *c = NULL;
168
169 Zero(&obo, sizeof(obo));
170
171 obo.Type = OBO_USER;
172
173 hr = pncClassSetup->DeInstall(pncc, &obo, &c);
174
175 if (SUCCEEDED(hr))
176 {
177 hr = pNetCfg->Apply();
178
179 if (SUCCEEDED(hr))
180 {
181 ret = true;
182 }
183 else
184 {
185 WHERE;
186 Debug("0x%x\n", hr);
187 }
188 }
189 else
190 {
191 WHERE;
192 Debug("0x%x\n", hr);
193 }
194
195 pncClassSetup->Release();
196 }
197 else
198 {
199 WHERE;
200 }
201
202 pncClass->Release();
203 }
204 else
205 {
206 WHERE;
207 }
208
209 pncc->Release();
210 }
211 else
212 {
213 WHERE;
214 }
215 }
216 else
217 {
218 WHERE;
219 }
220
221 pLock->ReleaseWriteLock();
222 }
223 else
224 {
225 WHERE;
226 }
227
228 pLock->Release();
229 }
230
231 pNetCfg->Release();
232 }
233 else
234 {
235 WHERE;
236 }
237
238 return ret;
239 }
240
241 // Install the NDIS protocol driver
InstallNdisProtocolDriver(wchar_t * inf_path,wchar_t * id,UINT lock_timeout)242 bool InstallNdisProtocolDriver(wchar_t *inf_path, wchar_t *id, UINT lock_timeout)
243 {
244 bool ret = false;
245 HRESULT hr;
246 INetCfg *pNetCfg;
247 HINSTANCE hSetupApiDll = NULL;
248 BOOL (WINAPI *_SetupCopyOEMInfW)(PCWSTR, PCWSTR, DWORD, DWORD, PWSTR, DWORD, PDWORD, PWSTR *) = NULL;
249 BOOL (WINAPI *_SetupUninstallOEMInfW)(PCWSTR, DWORD, PVOID) = NULL;
250 // Validate arguments
251 if (inf_path == NULL || id == NULL)
252 {
253 return false;
254 }
255
256 hSetupApiDll = LoadLibraryA("setupapi.dll");
257 if (hSetupApiDll == NULL)
258 {
259 WHERE;
260 goto LABEL_CLEANUP;
261 }
262
263 _SetupCopyOEMInfW =
264 (BOOL (__stdcall *)(PCWSTR,PCWSTR,DWORD,DWORD,PWSTR,DWORD,PDWORD,PWSTR *))
265 GetProcAddress(hSetupApiDll, "SetupCopyOEMInfW");
266
267 _SetupUninstallOEMInfW =
268 (BOOL (__stdcall *)(PCWSTR,DWORD,PVOID))
269 GetProcAddress(hSetupApiDll, "SetupUninstallOEMInfW");
270
271 if (_SetupCopyOEMInfW == NULL || _SetupUninstallOEMInfW == NULL)
272 {
273 WHERE;
274 goto LABEL_CLEANUP;
275 }
276
277 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void **)&pNetCfg);
278
279 if (SUCCEEDED(hr))
280 {
281 INetCfgLock *pLock;
282
283 hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock);
284
285 if (SUCCEEDED(hr))
286 {
287 LPWSTR locked_by;
288
289 hr = pLock->AcquireWriteLock(lock_timeout, L"SoftEther VPN", &locked_by);
290
291 if (SUCCEEDED(hr))
292 {
293 hr = pNetCfg->Initialize(NULL);
294
295 if (SUCCEEDED(hr))
296 {
297 wchar_t inf_dir[MAX_PATH];
298
299 GetDirNameFromFilePathW(inf_dir, sizeof(inf_dir), inf_path);
300
301 if (_SetupCopyOEMInfW(inf_path, inf_dir, SPOST_PATH, 0, NULL, 0, NULL, 0))
302 {
303 INetCfgClassSetup *pSetup;
304
305 hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS, IID_INetCfgClassSetup, (void **)&pSetup);
306
307 if (SUCCEEDED(hr))
308 {
309 OBO_TOKEN token;
310 INetCfgComponent *pComponent;
311
312 Zero(&token, sizeof(token));
313
314 token.Type = OBO_USER;
315
316 hr = pSetup->Install(id, &token, 0, 0, NULL, NULL, &pComponent);
317
318 if (SUCCEEDED(hr))
319 {
320 pNetCfg->Apply();
321
322 ret = true;
323 }
324 else
325 {
326 WHERE;
327 Debug("0x%x\n", hr);
328 }
329
330 pSetup->Release();
331 }
332 else
333 {
334 WHERE;
335 }
336
337 if (ret == false)
338 {
339 wchar_t dst_inf_name[MAX_PATH];
340 DWORD dst_inf_name_size = MAX_PATH;
341
342 if (_SetupCopyOEMInfW(inf_path, inf_dir, SPOST_PATH, SP_COPY_REPLACEONLY,
343 dst_inf_name, dst_inf_name_size, &dst_inf_name_size, NULL) == false &&
344 GetLastError() == ERROR_FILE_EXISTS)
345 {
346 _SetupUninstallOEMInfW(dst_inf_name, 0, NULL);
347 }
348 }
349 }
350 else
351 {
352 WHERE;
353 }
354 }
355 else
356 {
357 WHERE;
358 }
359
360 pLock->ReleaseWriteLock();
361 }
362 else
363 {
364 WHERE;
365 }
366
367 pLock->Release();
368 }
369
370 pNetCfg->Release();
371 }
372 else
373 {
374 WHERE;
375 }
376
377 LABEL_CLEANUP:
378
379 if (hSetupApiDll != NULL)
380 {
381 FreeLibrary(hSetupApiDll);
382 }
383
384 return ret;
385 }
386
387 typedef struct FOLDER_DLG_INNER_DATA
388 {
389 wchar_t *default_dir;
390 } FOLDER_DLG_INNER_DATA;
391
FolderDlgInnerCallbackA(HWND hWnd,UINT msg,LPARAM lParam,LPARAM lData)392 int CALLBACK FolderDlgInnerCallbackA(HWND hWnd, UINT msg, LPARAM lParam, LPARAM lData)
393 {
394 FOLDER_DLG_INNER_DATA *data = (FOLDER_DLG_INNER_DATA *)lData;
395 LPITEMIDLIST pidl;
396
397 switch (msg)
398 {
399 case BFFM_INITIALIZED:
400 if (data->default_dir != NULL)
401 {
402 char *default_dir_a = CopyUniToStr(data->default_dir);
403
404 SendMessage(hWnd, BFFM_SETSELECTIONA, true, (LPARAM)default_dir_a);
405
406 Free(default_dir_a);
407 }
408 break;
409
410 case BFFM_SELCHANGED:
411 pidl = (LPITEMIDLIST)lParam;
412
413 if (pidl)
414 {
415 char tmp[MAX_PATH];
416
417 Zero(tmp, sizeof(tmp));
418 if (SHGetPathFromIDListA(pidl, tmp))
419 {
420 SendMessage(hWnd, BFFM_ENABLEOK, 0, 1);
421 }
422 else
423 {
424 SendMessage(hWnd, BFFM_ENABLEOK, 0, 0);
425 }
426 }
427 break;
428 }
429
430 return 0;
431 }
432
FolderDlgInnerA(HWND hWnd,wchar_t * title,char * default_dir)433 char *FolderDlgInnerA(HWND hWnd, wchar_t *title, char *default_dir)
434 {
435 BROWSEINFOA info;
436 char display_name[MAX_PATH];
437 FOLDER_DLG_INNER_DATA data;
438 LPMALLOC pMalloc;
439 char *ret = NULL;
440 char *title_a;
441 if (UniIsEmptyStr(title))
442 {
443 title = NULL;
444 }
445 if (IsEmptyStr(default_dir))
446 {
447 default_dir = NULL;
448 }
449
450 Zero(&data, sizeof(data));
451 data.default_dir = CopyStrToUni(default_dir);
452
453 Zero(display_name, sizeof(display_name));
454 Zero(&info, sizeof(info));
455 info.hwndOwner = hWnd;
456 info.pidlRoot = NULL;
457 info.pszDisplayName = display_name;
458 title_a = CopyUniToStr(title);
459 info.lpszTitle = title_a;
460 info.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_SHAREABLE;
461 info.lpfn = FolderDlgInnerCallbackA;
462 info.lParam = (LPARAM)&data;
463
464 if (SUCCEEDED(SHGetMalloc(&pMalloc)))
465 {
466 LPITEMIDLIST pidl;
467
468 pidl = SHBrowseForFolderA(&info);
469
470 if (pidl)
471 {
472 char tmp[MAX_PATH];
473
474 if (SHGetPathFromIDListA(pidl, tmp))
475 {
476 ret = CopyStr(tmp);
477 }
478
479 pMalloc->Free(pidl);
480 }
481
482 pMalloc->Release();
483 }
484
485 Free(data.default_dir);
486 Free(title_a);
487
488 return ret;
489 }
490
FolderDlgInnerCallbackW(HWND hWnd,UINT msg,LPARAM lParam,LPARAM lData)491 int CALLBACK FolderDlgInnerCallbackW(HWND hWnd, UINT msg, LPARAM lParam, LPARAM lData)
492 {
493 FOLDER_DLG_INNER_DATA *data = (FOLDER_DLG_INNER_DATA *)lData;
494 LPITEMIDLIST pidl;
495
496 switch (msg)
497 {
498 case BFFM_INITIALIZED:
499 if (data->default_dir != NULL)
500 {
501 SendMessage(hWnd, BFFM_SETSELECTIONW, true, (LPARAM)data->default_dir);
502 }
503 break;
504
505 case BFFM_SELCHANGED:
506 pidl = (LPITEMIDLIST)lParam;
507
508 if (pidl)
509 {
510 wchar_t tmp[MAX_PATH];
511
512 Zero(tmp, sizeof(tmp));
513 if (SHGetPathFromIDListW(pidl, tmp))
514 {
515 SendMessage(hWnd, BFFM_ENABLEOK, 0, 1);
516 }
517 else
518 {
519 SendMessage(hWnd, BFFM_ENABLEOK, 0, 0);
520 }
521 }
522 break;
523 }
524
525 return 0;
526 }
527
FolderDlgInnerW(HWND hWnd,wchar_t * title,wchar_t * default_dir)528 wchar_t *FolderDlgInnerW(HWND hWnd, wchar_t *title, wchar_t *default_dir)
529 {
530 BROWSEINFOW info;
531 wchar_t display_name[MAX_PATH];
532 FOLDER_DLG_INNER_DATA data;
533 LPMALLOC pMalloc;
534 wchar_t *ret = NULL;
535 if (UniIsEmptyStr(title))
536 {
537 title = NULL;
538 }
539 if (UniIsEmptyStr(default_dir))
540 {
541 default_dir = NULL;
542 }
543
544 Zero(&data, sizeof(data));
545 data.default_dir = default_dir;
546
547 Zero(display_name, sizeof(display_name));
548 Zero(&info, sizeof(info));
549 info.hwndOwner = hWnd;
550 info.pidlRoot = NULL;
551 info.pszDisplayName = display_name;
552 info.lpszTitle = title;
553 info.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_VALIDATE | BIF_SHAREABLE;
554 info.lpfn = FolderDlgInnerCallbackW;
555 info.lParam = (LPARAM)&data;
556
557 if (SUCCEEDED(SHGetMalloc(&pMalloc)))
558 {
559 LPITEMIDLIST pidl;
560
561 pidl = SHBrowseForFolderW(&info);
562
563 if (pidl)
564 {
565 wchar_t tmp[MAX_PATH];
566
567 if (SHGetPathFromIDListW(pidl, tmp))
568 {
569 ret = CopyUniStr(tmp);
570 }
571
572 pMalloc->Free(pidl);
573 }
574
575 pMalloc->Release();
576 }
577
578 return ret;
579 }
580
581
582 class CModule
583 {
584 public:
CModule()585 CModule()
586 {
587 m_hInstLib = NULL;
588 }
CModule(HINSTANCE hInstLib)589 CModule( HINSTANCE hInstLib )
590 {
591 m_hInstLib = NULL;
592 this->Attach( hInstLib );
593 }
CModule(LPCTSTR pszModuleName)594 CModule( LPCTSTR pszModuleName )
595 {
596 m_hInstLib = NULL;
597 this->LoadLibrary( pszModuleName );
598 }
~CModule()599 virtual ~CModule()
600 {
601 this->FreeLibrary();
602 }
603
604 public:
Attach(HINSTANCE hInstLib)605 BOOL Attach( HINSTANCE hInstLib )
606 {
607 this->FreeLibrary();
608 m_hInstLib = hInstLib;
609
610 return TRUE;
611 }
Detach()612 BOOL Detach()
613 {
614 m_hInstLib = NULL;
615
616 return TRUE;
617 }
618
619 public:
GetHandle()620 HMODULE GetHandle()
621 {
622 return m_hInstLib;
623 }
624 // Load the DLL
LoadLibrary(LPCTSTR pszModuleName)625 HINSTANCE LoadLibrary( LPCTSTR pszModuleName )
626 {
627 this->FreeLibrary();
628 m_hInstLib = ::LoadLibrary( pszModuleName );
629
630 return m_hInstLib;
631 }
632 // Release the DLL
FreeLibrary()633 BOOL FreeLibrary()
634 {
635 if (m_hInstLib == NULL)
636 {
637 return FALSE;
638 }
639
640 BOOL bResult = ::FreeLibrary( m_hInstLib );
641 m_hInstLib = NULL;
642
643 return bResult;
644 }
645 // Get the address of the function
GetProcAddress(LPCTSTR pszProcName)646 FARPROC GetProcAddress( LPCTSTR pszProcName )
647 {
648 if (m_hInstLib == NULL)
649 {
650 return NULL;
651 }
652
653 return ::GetProcAddress(m_hInstLib, pszProcName);
654 }
655 // Get a handle to the information block of resource with the specified name and the type
FindResource(LPCTSTR lpName,LPCTSTR lpType)656 HRSRC FindResource(LPCTSTR lpName, LPCTSTR lpType)
657 {
658 if (m_hInstLib == NULL)
659 {
660 return NULL;
661 }
662
663 return ::FindResource(m_hInstLib, lpName, lpType);
664 }
665 // Load the specified resource
LoadResource(HRSRC hResInfo)666 HGLOBAL LoadResource(HRSRC hResInfo)
667 {
668 if (m_hInstLib == NULL)
669 {
670 return NULL;
671 }
672
673 return ::LoadResource(m_hInstLib, hResInfo);
674 }
675
676 protected:
677 HINSTANCE m_hInstLib;
678 };
679
680
681
_ShowHTMLDialog(HWND hwndParent,IMoniker * pMk,VARIANT * pvarArgIn=NULL,WCHAR * pchOptions=NULL,VARIANT * pvarArgOut=NULL)682 static HRESULT _ShowHTMLDialog(
683 HWND hwndParent,
684 IMoniker* pMk,
685 VARIANT* pvarArgIn = NULL,
686 WCHAR* pchOptions = NULL,
687 VARIANT* pvarArgOut = NULL)
688 {
689 HRESULT hr = S_OK;
690
691 try
692 {
693 CModule Module("MSHTML.DLL");
694 if (Module.GetHandle() == NULL)
695 {
696 return E_FAIL;
697 }
698
699 SHOWHTMLDIALOGFN* fnShowHTMLDialog =
700 (SHOWHTMLDIALOGFN*)Module.GetProcAddress("ShowHTMLDialog");
701 if (fnShowHTMLDialog == NULL)
702 {
703 return E_FAIL;
704 }
705
706 hr = (*fnShowHTMLDialog)(hwndParent, pMk, pvarArgIn, pchOptions, pvarArgOut);
707 if (FAILED(hr))
708 {
709 return hr;
710 }
711 }
712 catch (...)
713 {
714 return E_FAIL;
715 }
716
717 return hr;
718 }
719
ShowHTMLDialogFromURL(HWND hwndParent,wchar_t * szURL,VARIANT * pvarArgIn,WCHAR * pchOptions,VARIANT * pvarArgOut)720 HRESULT ShowHTMLDialogFromURL(HWND hwndParent,wchar_t *szURL,VARIANT* pvarArgIn,WCHAR* pchOptions,VARIANT* pvarArgOut)
721 {
722 HRESULT hr = S_OK;
723
724 try
725 {
726 IMoniker *spMoniker;
727 hr = ::CreateURLMoniker(NULL, szURL, &spMoniker);
728 if (FAILED(hr))
729 {
730 return hr;
731 }
732
733 hr = ::_ShowHTMLDialog(hwndParent, spMoniker, pvarArgIn, pchOptions, pvarArgOut);
734 if (FAILED(hr))
735 {
736 return hr;
737 }
738 }
739 catch (...)
740 {
741 return E_FAIL;
742 }
743
744 return hr;
745 }
746
747 // Create a shortcut
CreateLinkInnerA(char * filename,char * target,char * workdir,char * args,char * comment,char * icon,UINT icon_index)748 bool CreateLinkInnerA(char *filename, char *target, char *workdir, char *args,
749 char *comment, char *icon, UINT icon_index)
750 {
751 HRESULT r;
752 wchar_t tmp[MAX_SIZE];
753 IShellLinkA* pShellLink;
754 IPersistFile* pPersistFile;
755
756 r = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (void **)&pShellLink);
757 if (FAILED(r))
758 {
759 return false;
760 }
761
762 r = pShellLink->QueryInterface(IID_IPersistFile,(void **)&pPersistFile);
763 if (FAILED(r))
764 {
765 pShellLink->Release();
766 return false;
767 }
768
769 r = pShellLink->SetPath(target);
770 if (FAILED(r))
771 {
772 pShellLink->Release();
773 pPersistFile->Release();
774 return false;
775 }
776
777 if (workdir != NULL)
778 {
779 r = pShellLink->SetWorkingDirectory(workdir);
780 if (FAILED(r))
781 {
782 pShellLink->Release();
783 pPersistFile->Release();
784 return false;
785 }
786 }
787
788 if (args != NULL)
789 {
790 r = pShellLink->SetArguments(args);
791 if (FAILED(r))
792 {
793 pShellLink->Release();
794 pPersistFile->Release();
795 return false;
796 }
797 }
798
799 if (comment != NULL)
800 {
801 r = pShellLink->SetDescription(comment);
802 if (FAILED(r))
803 {
804 pShellLink->Release();
805 pPersistFile->Release();
806 return false;
807 }
808 }
809
810 if (icon != NULL)
811 {
812 r = pShellLink->SetIconLocation(icon, icon_index);
813 if (FAILED(r))
814 {
815 pShellLink->Release();
816 pPersistFile->Release();
817 return false;
818 }
819 }
820
821 StrToUni(tmp, sizeof(tmp), filename);
822 r = pPersistFile->Save(tmp, true);
823 if (FAILED(r))
824 {
825 pShellLink->Release();
826 pPersistFile->Release();
827 return false;
828 }
829
830 pShellLink->Release();
831 pPersistFile->Release();
832 return true;
833 }
CreateLinkInner(wchar_t * filename,wchar_t * target,wchar_t * workdir,wchar_t * args,wchar_t * comment,wchar_t * icon,UINT icon_index)834 bool CreateLinkInner(wchar_t *filename, wchar_t *target, wchar_t *workdir, wchar_t *args,
835 wchar_t *comment, wchar_t *icon, UINT icon_index)
836 {
837 HRESULT r;
838 IShellLinkW* pShellLink;
839 IPersistFile* pPersistFile;
840
841 r = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void **)&pShellLink);
842 if (FAILED(r))
843 {
844 return false;
845 }
846
847 r = pShellLink->QueryInterface(IID_IPersistFile,(void **)&pPersistFile);
848 if (FAILED(r))
849 {
850 pShellLink->Release();
851 return false;
852 }
853
854 r = pShellLink->SetPath(target);
855 if (FAILED(r))
856 {
857 pShellLink->Release();
858 pPersistFile->Release();
859 return false;
860 }
861
862 if (workdir != NULL)
863 {
864 r = pShellLink->SetWorkingDirectory(workdir);
865 if (FAILED(r))
866 {
867 pShellLink->Release();
868 pPersistFile->Release();
869 return false;
870 }
871 }
872
873 if (comment != NULL)
874 {
875 r = pShellLink->SetDescription(comment);
876 if (FAILED(r))
877 {
878 pShellLink->Release();
879 pPersistFile->Release();
880 return false;
881 }
882 }
883
884 if (args != NULL)
885 {
886 r = pShellLink->SetArguments(args);
887 if (FAILED(r))
888 {
889 pShellLink->Release();
890 pPersistFile->Release();
891 return false;
892 }
893 }
894
895 if (icon != NULL)
896 {
897 r = pShellLink->SetIconLocation(icon, icon_index);
898 if (FAILED(r))
899 {
900 pShellLink->Release();
901 pPersistFile->Release();
902 return false;
903 }
904 }
905
906 r = pPersistFile->Save(filename, true);
907 if (FAILED(r))
908 {
909 pShellLink->Release();
910 pPersistFile->Release();
911 return false;
912 }
913
914 pShellLink->Release();
915 pPersistFile->Release();
916 return true;
917 }
918
919 extern "C"
920 {
921
922 // Show the folder selection dialog
FolderDlgW(HWND hWnd,wchar_t * title,wchar_t * default_dir)923 wchar_t *FolderDlgW(HWND hWnd, wchar_t *title, wchar_t *default_dir)
924 {
925 return FolderDlgInnerW(hWnd, title, default_dir);
926 }
FolderDlgA(HWND hWnd,wchar_t * title,char * default_dir)927 char *FolderDlgA(HWND hWnd, wchar_t *title, char *default_dir)
928 {
929 return FolderDlgInnerA(hWnd, title, default_dir);
930 }
931
932 // Create a shortcut
CreateLink(wchar_t * filename,wchar_t * target,wchar_t * workdir,wchar_t * args,wchar_t * comment,wchar_t * icon,UINT icon_index)933 bool CreateLink(wchar_t *filename, wchar_t *target, wchar_t *workdir, wchar_t *args,
934 wchar_t *comment, wchar_t *icon, UINT icon_index)
935 {
936 if (filename == NULL || target == NULL)
937 {
938 return false;
939 }
940
941 return CreateLinkInner(filename, target, workdir, args, comment, icon, icon_index);
942 }
943
944 // Show the HTML
ShowHtml(HWND hWnd,char * url,wchar_t * option)945 void ShowHtml(HWND hWnd, char *url, wchar_t *option)
946 {
947 wchar_t tmp[MAX_SIZE];
948 // Validate arguments
949 if (url == NULL || option == NULL)
950 {
951 return;
952 }
953
954 StrToUni(tmp, sizeof(tmp), url);
955
956 ShowHTMLDialogFromURL(hWnd, tmp, NULL, option, NULL);
957 }
958
959 }
960
961 #endif
962