xref: /reactos/dll/shellext/fontext/fontext.cpp (revision 7353af1e)
1 /*
2  * PROJECT:     ReactOS Font Shell Extension
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Shell extension entry point
5  * COPYRIGHT:   Copyright 2019,2020 Mark Jansen <mark.jansen@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 WINE_DEFAULT_DEBUG_CHANNEL(fontext);
11 
12 const GUID CLSID_CFontExt = { 0xbd84b380, 0x8ca2, 0x1069, { 0xab, 0x1d, 0x08, 0x00, 0x09, 0x48, 0xf5, 0x34 } };
13 
14 
15 class CFontExtModule : public CComModule
16 {
17 public:
18     void Init(_ATL_OBJMAP_ENTRY *p, HINSTANCE h, const GUID *plibid)
19     {
20         g_FontCache = new CFontCache();
21         CComModule::Init(p, h, plibid);
22     }
23 
24     void Term()
25     {
26         delete g_FontCache;
27         g_FontCache = NULL;
28         CComModule::Term();
29     }
30 };
31 
32 BEGIN_OBJECT_MAP(ObjectMap)
33     OBJECT_ENTRY(CLSID_CFontExt, CFontExt)
34 END_OBJECT_MAP()
35 
36 
37 LONG g_ModuleRefCnt;
38 CFontExtModule gModule;
39 
40 
41 STDAPI DllCanUnloadNow()
42 {
43     if (g_ModuleRefCnt)
44         return S_FALSE;
45     return gModule.DllCanUnloadNow();
46 }
47 
48 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
49 {
50     return gModule.DllGetClassObject(rclsid, riid, ppv);
51 }
52 
53 
54 STDAPI DllRegisterServer()
55 {
56     WCHAR Path[MAX_PATH] = { 0 };
57     static const char DesktopIniContents[] = "[.ShellClassInfo]\r\n"
58         "CLSID={BD84B380-8CA2-1069-AB1D-08000948F534}\r\n"
59         "IconResource=%SystemRoot%\\system32\\shell32.dll,-39\r\n"; // IDI_SHELL_FONTS_FOLDER
60     HANDLE hFile;
61     HRESULT hr;
62 
63     hr = gModule.DllRegisterServer(FALSE);
64     if (FAILED_UNEXPECTEDLY(hr))
65         return hr;
66 
67     hr = SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, Path);
68     if (FAILED_UNEXPECTEDLY(hr))
69         return hr;
70 
71     // Make this a system folder:
72     // Ideally this should not be done here, but when installing
73     // Otherwise, livecd won't have this set properly
74     DWORD dwAttributes = GetFileAttributesW(Path);
75     if (dwAttributes != INVALID_FILE_ATTRIBUTES)
76     {
77         dwAttributes |= FILE_ATTRIBUTE_SYSTEM;
78         SetFileAttributesW(Path, dwAttributes);
79     }
80     else
81     {
82         ERR("Unable to get attributes for fonts folder (%d)\n", GetLastError());
83     }
84 
85     if (!PathAppendW(Path, L"desktop.ini"))
86         return E_FAIL;
87 
88     hFile = CreateFileW(Path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, NULL);
89     if (hFile == INVALID_HANDLE_VALUE)
90         return HRESULT_FROM_WIN32(GetLastError());
91 
92     DWORD BytesWritten, BytesToWrite = strlen(DesktopIniContents);
93     if (WriteFile(hFile, DesktopIniContents, (DWORD)BytesToWrite, &BytesWritten, NULL))
94         hr = (BytesToWrite == BytesWritten) ? S_OK : E_FAIL;
95     else
96         hr = HRESULT_FROM_WIN32(GetLastError());
97     CloseHandle(hFile);
98     return hr;
99 }
100 
101 STDAPI DllUnregisterServer()
102 {
103     return gModule.DllUnregisterServer(FALSE);
104 }
105 
106 
107 EXTERN_C
108 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
109 {
110     switch (dwReason)
111     {
112     case DLL_PROCESS_ATTACH:
113         DisableThreadLibraryCalls(hInstance);
114         gModule.Init(ObjectMap, hInstance, NULL);
115         break;
116     case DLL_PROCESS_DETACH:
117         gModule.Term();
118         break;
119     }
120 
121     return TRUE;
122 }
123