2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
32 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
34 /* Key/Value names for MIME content types */
35 static const char lpszContentTypeA
[] = "Content Type";
36 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
38 static const char szMimeDbContentA
[] = "MIME\\Database\\Content Type\\";
39 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
40 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
41 ' ','T','y','p','e','\\', 0 };
42 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
44 static const char szExtensionA
[] = "Extension";
45 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
47 INT WINAPI
SHStringFromGUIDW(REFGUID
,LPWSTR
,INT
);
48 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
50 /*************************************************************************
51 * SHDeleteOrphanKeyA [SHLWAPI.@]
53 * Delete a registry key with no sub keys or values.
56 * hKey [I] Handle to registry key
57 * lpszSubKey [I] Name of sub key to possibly delete
60 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
61 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
63 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
66 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
68 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
70 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
74 /* Get subkey and value count */
75 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
76 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
78 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
80 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
87 /*************************************************************************
88 * SHDeleteOrphanKeyW [SHLWAPI.@]
90 * See SHDeleteOrphanKeyA.
92 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
95 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
97 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
99 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
103 /* Get subkey and value count */
104 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
105 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
107 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
109 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
111 RegCloseKey(hSubKey
);
116 /*************************************************************************
120 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
121 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
123 if (GetSystemMetrics(SM_CLEANBOOT
))
124 return ERROR_INVALID_FUNCTION
;
125 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
128 /*************************************************************************
132 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
133 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
135 if (GetSystemMetrics(SM_CLEANBOOT
))
136 return ERROR_INVALID_FUNCTION
;
137 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
140 /*************************************************************************
143 * Set a MIME content type in the registry.
146 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
147 * lpszValue [I] Value to set
153 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
157 WARN("Invalid lpszValue would crash under Win32!\n");
161 return !SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
162 REG_SZ
, lpszValue
, strlen(lpszValue
));
165 /*************************************************************************
168 * Unicode version of RegisterMIMETypeForExtensionA.
170 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
174 WARN("Invalid lpszValue would crash under Win32!\n");
178 return !SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
179 REG_SZ
, lpszValue
, lstrlenW(lpszValue
));
182 /*************************************************************************
185 * Delete a MIME content type from the registry.
188 * lpszSubKey [I] Name of sub key
194 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
196 return !SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
199 /*************************************************************************
202 * Unicode version of UnregisterMIMETypeForExtensionA.
204 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
206 return !SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
209 /*************************************************************************
212 * Get the registry path to a MIME content key.
215 * lpszType [I] Content type to get the path for
216 * lpszBuffer [O] Destination for path
217 * dwLen [I] Length of lpszBuffer
220 * Success: TRUE. lpszBuffer contains the full path.
224 * The base path for the key is "MIME\Database\Content Type\"
226 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
228 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
230 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
232 size_t dwStrLen
= strlen(lpszType
);
234 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
236 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
237 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
244 /*************************************************************************
247 * Unicode version of GetMIMETypeSubKeyA.
249 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
251 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
253 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
255 DWORD dwStrLen
= lstrlenW(lpszType
);
257 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
259 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
260 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
267 /*************************************************************************
270 * Get the file extension for a given Mime type.
273 * lpszType [I] Mime type to get the file extension for
274 * lpExt [O] Destination for the resulting extension
275 * iLen [I] Length of lpExt in characters
278 * Success: TRUE. lpExt contains the file extension.
279 * Failure: FALSE, if any parameter is invalid or the extension cannot be
280 * retrieved. If iLen > 0, lpExt is set to an empty string.
283 * - The extension returned in lpExt always has a leading '.' character, even
284 * if the registry Mime database entry does not.
285 * - iLen must be long enough for the file extension for this function to succeed.
287 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
289 char szSubKey
[MAX_PATH
];
290 DWORD dwlen
= iLen
- 1, dwType
;
293 if (iLen
> 0 && lpExt
)
296 if (lpszType
&& lpExt
&& iLen
> 2 &&
297 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
298 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
302 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
304 *lpExt
= '.'; /* Supply a '.' */
310 /*************************************************************************
313 * Unicode version of MIME_GetExtensionA.
315 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
317 WCHAR szSubKey
[MAX_PATH
];
318 DWORD dwlen
= iLen
- 1, dwType
;
321 if (iLen
> 0 && lpExt
)
324 if (lpszType
&& lpExt
&& iLen
> 2 &&
325 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
326 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
330 memmove(lpExt
, lpExt
+ 1, (lstrlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
332 *lpExt
= '.'; /* Supply a '.' */
338 /*************************************************************************
341 * Set the file extension for a MIME content key.
344 * lpszExt [I] File extension to set
345 * lpszType [I] Content type to set the extension for
348 * Success: TRUE. The file extension is set in the registry.
351 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
354 char szKey
[MAX_PATH
];
356 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
358 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
361 dwLen
= strlen(lpszExt
) + 1;
363 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
368 /*************************************************************************
371 * Unicode version of RegisterExtensionForMIMETypeA.
373 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
376 WCHAR szKey
[MAX_PATH
];
378 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
380 /* Get the full path to the key */
381 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
384 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
386 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
391 /*************************************************************************
394 * Delete a file extension from a MIME content type.
397 * lpszType [I] Content type to delete the extension for
400 * Success: TRUE. The file extension is deleted from the registry.
401 * Failure: FALSE. The extension may have been removed but the key remains.
404 * If deleting the extension leaves an orphan key, the key is removed also.
406 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
408 char szKey
[MAX_PATH
];
410 TRACE("(%s)\n", debugstr_a(lpszType
));
412 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
415 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
418 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
423 /*************************************************************************
426 * Unicode version of UnregisterExtensionForMIMETypeA.
428 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
430 WCHAR szKey
[MAX_PATH
];
432 TRACE("(%s)\n", debugstr_w(lpszType
));
434 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
437 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
440 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
446 * The following functions are ORDINAL ONLY:
449 /*************************************************************************
452 * Create or open an explorer ClassId Key.
455 * guid [I] Explorer ClassId key to open
456 * lpszValue [I] Value name under the ClassId Key
457 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
458 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
459 * phKey [O] Destination for the resulting key handle
462 * Success: S_OK. phKey contains the resulting registry handle.
463 * Failure: An HRESULT error code indicating the problem.
465 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
467 WCHAR szValue
[MAX_PATH
];
470 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, ARRAY_SIZE(szValue
));
472 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
475 /*************************************************************************
478 * Unicode version of SHRegGetCLSIDKeyA.
480 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
481 BOOL bCreate
, PHKEY phKey
)
483 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
484 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
485 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
486 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
487 WCHAR szKey
[MAX_PATH
];
491 /* Create the key string */
492 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
493 SHStringFromGUIDW(guid
, szKey
+ ARRAY_SIZE(szClassIdKey
), 39); /* Append guid */
497 szKey
[ARRAY_SIZE(szClassIdKey
) + 39] = '\\';
498 lstrcpyW(szKey
+ ARRAY_SIZE(szClassIdKey
) + 40, lpszValue
); /* Append value name */
501 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
504 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
506 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
508 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
511 /*************************************************************************
512 * SHRegisterValidateTemplate [SHLWAPI.@]
514 * observed from the ie 5.5 installer:
515 * - allocates a buffer with the size of the given file
516 * - read the file content into the buffer
517 * - creates the key szTemplateKey
518 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
522 * filename [I] An existing file its content is read into an allocated
527 * Success: ERROR_SUCCESS.
529 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
531 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
532 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
533 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
534 * 'E','x','p','l','o','r','e','r','\\',
535 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
537 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);