1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
13 #pragma warning(push, 1) /* disable warnings within system headers */
15 #define WIN32_LEAN_AND_MEAN
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"
29 #include "osl/file.hxx"
31 #include "writemodfile.hxx"
33 #define MAX_KEY_LENGTH 255
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>
56 // [HKEY_LOCAL_MACHINE\Policies\LibreOffice\org.openoffice.Office.OptionsDialog\OptionsDialogGroups\ProductName/#fuse\Pages\AboutConfig/#fuse\Hide]
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>
72 void dumpWindowsRegistryKey(HKEY hKey
, OUString aKeyName
, oslFileHandle aFileHandle
)
76 if(RegOpenKeyExW(hKey
, aKeyName
.getStr(), 0, KEY_READ
, &hCurKey
) == ERROR_SUCCESS
)
80 DWORD nLongestValueNameLen
, nLongestValueLen
;
81 // Query the number of subkeys
82 RegQueryInfoKeyW(hCurKey
, NULL
, NULL
, NULL
, &nSubKeys
, NULL
, NULL
, &nValues
, &nLongestValueNameLen
, &nLongestValueLen
, NULL
, NULL
);
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
;
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
);
99 aSubkeyName
= aKeyName
+ "\\" + OUString(buffKeyName
);
101 //Recursion, until no more subkeys are found
102 dumpWindowsRegistryKey(hKey
, aSubkeyName
, aFileHandle
);
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
)
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)
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
)
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
);
158 writeAttributeValue(aFileHandle
, aNextPathPart
);
163 writeAttributeValue(aFileHandle
, "/" + aNextPathPart
);
168 writeData(aFileHandle
, "\">");
173 writeData(aFileHandle
, "<prop oor:name=\"");
174 writeAttributeValue(aFileHandle
, aProp
);
175 writeData(aFileHandle
, "\"");
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");
188 RegCloseKey(hCurKey
);
193 bool dumpWindowsRegistry(OUString
* pFileURL
)
196 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Policies\\LibreOffice", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
200 ("Windows registry settings do not exist in HKLM\\SOFTWARE\\Policies\\LibreOffice"));
204 oslFileHandle aFileHandle
;
205 switch (osl::FileBase::createTempFile(0, &aFileHandle
, pFileURL
)) {
206 case osl::FileBase::E_None
:
208 case osl::FileBase::E_ACCES
:
211 ("cannot create temp Windows registry dump (E_ACCES)"));
214 throw css::uno::RuntimeException(
215 "cannot create temporary file",
216 css::uno::Reference
< css::uno::XInterface
>());
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
);
235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */