Bump version to 4.1-6
[LibreOffice.git] / configmgr / source / winreg.cxx
blob29695987d6f8e3d45d60bda9b5e84c1ce97759d0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <cwchar>
12 #ifdef _MSC_VER
13 #pragma warning(push, 1) /* disable warnings within system headers */
14 #endif
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17 #include <msiquery.h>
18 #ifdef _MSC_VER
19 #pragma warning(pop)
20 #endif
22 #include "com/sun/star/uno/Any.hxx"
23 #include "com/sun/star/uno/Reference.hxx"
24 #include "com/sun/star/uno/RuntimeException.hpp"
25 #include "com/sun/star/uno/Sequence.hxx"
26 #include "com/sun/star/uno/XInterface.hpp"
27 #include "rtl/ustring.hxx"
28 #include "osl/file.h"
29 #include "osl/file.hxx"
30 #include "winreg.hxx"
31 #include "writemodfile.hxx"
33 #define MAX_KEY_LENGTH 255
35 namespace configmgr {
37 namespace {
38 // This is not a generic registry reader. We assume the following structure:
39 // Last element of Key becomes prop, first part is the path and optionally nodes,
40 // when the node has oor:op attribute.
41 // Values can be the following: Value (string) and Final (dword, optional)
43 // For example the following registry setting:
44 // [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\LibreOffice\org.openoffice.UserProfile\Data\o]
45 // "Value"="Example Corp."
46 // "Final"=dword:00000001
47 // becomes the following in configuration:
48 // <!-- set the Company name -->
49 // <item oor:path="/org.openoffice.UserProfile/Data">
50 // <prop oor:name="o" oor:finalized="true">
51 // <value>Example Corp.</value>
52 // </prop>
53 // </item>
55 // Another example:
56 // [HKEY_LOCAL_MACHINE\Policies\LibreOffice\org.openoffice.Office.OptionsDialog\OptionsDialogGroups\ProductName/#fuse\Pages\AboutConfig/#fuse\Hide]
57 // "Value"="true"
58 // becomes the following in configuration:
59 // <!-- Hide Tools - Options - LibreOffice - Expert Config panel -->
60 // <item oor:path="/org.openoffice.Office.OptionsDialog/OptionsDialogGroups">
61 // <node oor:name="ProductName" oor:op="fuse">
62 // <node oor:name="Pages">
63 // <node oor:name="AboutConfig" oor:op="fuse">
64 // <prop oor:name="Hide">
65 // <value>true</value>
66 // </prop>
67 // </node>
68 // </node>
69 // </node>
70 // </item>
72 void dumpWindowsRegistryKey(HKEY hKey, OUString aKeyName, oslFileHandle aFileHandle)
74 HKEY hCurKey;
76 if(RegOpenKeyExW(hKey, aKeyName.getStr(), 0, KEY_READ, &hCurKey) == ERROR_SUCCESS)
78 DWORD nSubKeys = 0;
79 DWORD nValues = 0;
80 DWORD nLongestValueNameLen, nLongestValueLen;
81 // Query the number of subkeys
82 RegQueryInfoKeyW(hCurKey, NULL, NULL, NULL, &nSubKeys, NULL, NULL, &nValues, &nLongestValueNameLen, &nLongestValueLen, NULL, NULL);
83 if(nSubKeys)
85 //Look for subkeys in this key
86 for(DWORD i = 0; i < nSubKeys; i++)
88 wchar_t buffKeyName[MAX_KEY_LENGTH];
89 buffKeyName[0] = '\0';
90 DWORD buffSize=MAX_KEY_LENGTH;
91 OUString aSubkeyName;
92 //Get subkey name
93 RegEnumKeyExW(hCurKey, i, buffKeyName, &buffSize, NULL, NULL, NULL, NULL);
95 //Make up full key name
96 if(aKeyName.isEmpty())
97 aSubkeyName = aKeyName + OUString(buffKeyName);
98 else
99 aSubkeyName = aKeyName + "\\" + OUString(buffKeyName);
101 //Recursion, until no more subkeys are found
102 dumpWindowsRegistryKey(hKey, aSubkeyName, aFileHandle);
105 else if(nValues)
107 // No more subkeys, we are at a leaf
108 wchar_t* pValueName = new wchar_t[nLongestValueNameLen + 1];
109 wchar_t* pValue = new wchar_t[nLongestValueLen + 1];
111 if(pValueName && pValue)
113 bool bFinal = false;
114 OUString aValue;
116 for(DWORD i = 0; i < nValues; ++i)
118 DWORD nValueNameLen = nLongestValueNameLen + 1;
119 DWORD nValueLen = nLongestValueLen + 1;
121 RegEnumValueW(hCurKey, i, pValueName, &nValueNameLen, NULL, NULL, (LPBYTE)pValue, &nValueLen);
122 const wchar_t wsValue[] = L"Value";
123 const wchar_t wsFinal[] = L"Final";
125 if(!wcscmp(pValueName, wsValue))
126 aValue = OUString(pValue);
127 if(!wcscmp(pValueName, wsFinal) && *(DWORD*)pValue == 1)
128 bFinal = true;
130 sal_Int32 aLastSeparator = aKeyName.lastIndexOf('\\');
131 OUString aPathAndNodes = aKeyName.copy(0, aLastSeparator);
132 OUString aProp = aKeyName.copy(aLastSeparator + 1);
133 bool bHasNode = false;
134 sal_Int32 nCloseNode = 0;
136 writeData(aFileHandle, "<item oor:path=\"");
137 for(sal_Int32 nIndex = 0;; ++nIndex)
139 OUString aNextPathPart = aPathAndNodes.getToken(nIndex, '\\');
141 if(!aNextPathPart.isEmpty())
143 if((aNextPathPart.lastIndexOf("/#") != -1) || bHasNode)
145 bHasNode = true;
146 nCloseNode++;
147 writeData(aFileHandle, "\"><node oor:name=\"");
148 sal_Int32 nCommandSeparator = aNextPathPart.lastIndexOf('#');
149 if(nCommandSeparator != -1)
151 OUString aNodeOp = aNextPathPart.copy(nCommandSeparator + 1);
152 writeAttributeValue(aFileHandle, aNextPathPart.copy(0, nCommandSeparator - 1));
153 writeData(aFileHandle, "\" oor:op=\"");
154 writeAttributeValue(aFileHandle, aNodeOp);
156 else
158 writeAttributeValue(aFileHandle, aNextPathPart);
161 else
163 writeAttributeValue(aFileHandle, "/" + aNextPathPart);
166 else
168 writeData(aFileHandle, "\">");
169 break;
173 writeData(aFileHandle, "<prop oor:name=\"");
174 writeAttributeValue(aFileHandle, aProp);
175 writeData(aFileHandle, "\"");
176 if(bFinal)
177 writeData(aFileHandle, " oor:finalized=\"true\"");
178 writeData(aFileHandle, "><value>");
179 writeValueContent(aFileHandle, aValue);
180 writeData(aFileHandle, "</value></prop>");
181 for(; nCloseNode > 0; nCloseNode--)
182 writeData(aFileHandle, "</node>");
183 writeData(aFileHandle, "</item>\n");
184 delete[] pValueName;
185 delete[] pValue;
188 RegCloseKey(hCurKey);
193 bool dumpWindowsRegistry(OUString* pFileURL)
195 HKEY hKey;
196 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\LibreOffice", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
198 SAL_INFO(
199 "configmgr",
200 ("Windows registry settings do not exist in HKLM\\SOFTWARE\\Policies\\LibreOffice"));
201 return false;
204 oslFileHandle aFileHandle;
205 switch (osl::FileBase::createTempFile(0, &aFileHandle, pFileURL)) {
206 case osl::FileBase::E_None:
207 break;
208 case osl::FileBase::E_ACCES:
209 SAL_INFO(
210 "configmgr",
211 ("cannot create temp Windows registry dump (E_ACCES)"));
212 return false;
213 default:
214 throw css::uno::RuntimeException(
215 "cannot create temporary file",
216 css::uno::Reference< css::uno::XInterface >());
218 writeData(
219 aFileHandle,
220 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
221 " xmlns:oor=\"http://openoffice.org/2001/registry\""
222 " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
223 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
224 dumpWindowsRegistryKey(hKey, "", aFileHandle);
225 writeData(aFileHandle, "</oor:items>");
226 oslFileError e = osl_closeFile(aFileHandle);
227 if (e != osl_File_E_None)
228 SAL_WARN("configmgr", "osl_closeFile failed with " << +e);
229 RegCloseKey(hKey);
230 return true;
235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */