ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

reg.c
Go to the documentation of this file.
00001 /*
00002  * SHLWAPI registry functions
00003  *
00004  * Copyright 1998 Juergen Schmied
00005  * Copyright 2001 Guy Albertelli
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 #include <string.h>
00024 #include "windef.h"
00025 #include "winbase.h"
00026 #include "winuser.h"
00027 #include "winreg.h"
00028 #include "wine/debug.h"
00029 #define NO_SHLWAPI_STREAM
00030 #include "shlwapi.h"
00031 #include "wine/unicode.h"
00032 
00033 WINE_DEFAULT_DEBUG_CHANNEL(shell);
00034 
00035 /* Key/Value names for MIME content types */
00036 static const char lpszContentTypeA[] = "Content Type";
00037 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
00038 
00039 static const char szMimeDbContentA[] = "MIME\\Database\\Content Type\\";
00040 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
00041   'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
00042   ' ','T','y','p','e','\\', 0 };
00043 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
00044 
00045 static const char szExtensionA[] = "Extension";
00046 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
00047 
00048 /* internal structure of what the HUSKEY points to */
00049 typedef struct {
00050     HKEY     HKCUstart; /* Start key in CU hive */
00051     HKEY     HKCUkey;   /* Opened key in CU hive */
00052     HKEY     HKLMstart; /* Start key in LM hive */
00053     HKEY     HKLMkey;   /* Opened key in LM hive */
00054     WCHAR    lpszPath[MAX_PATH];
00055 } SHUSKEY, *LPSHUSKEY;
00056 
00057 INT     WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
00058 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
00059 
00060 
00061 #define REG_HKCU  TRUE
00062 #define REG_HKLM  FALSE
00063 /*************************************************************************
00064  * REG_GetHKEYFromHUSKEY
00065  *
00066  * Function:  Return the proper registry key from the HUSKEY structure
00067  *            also allow special predefined values.
00068  */
00069 static HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
00070 {
00071         HKEY test = hUSKey;
00072         LPSHUSKEY mihk = hUSKey;
00073 
00074     if ((test == HKEY_CLASSES_ROOT)        ||
00075         (test == HKEY_CURRENT_CONFIG)      ||
00076         (test == HKEY_CURRENT_USER)        ||
00077         (test == HKEY_DYN_DATA)            ||
00078         (test == HKEY_LOCAL_MACHINE)       ||
00079         (test == HKEY_PERFORMANCE_DATA)    ||
00080 /* FIXME:  need to define for Win2k, ME, XP
00081  *      (test == HKEY_PERFORMANCE_TEXT)    ||
00082  *      (test == HKEY_PERFORMANCE_NLSTEXT) ||
00083  */
00084         (test == HKEY_USERS)) return test;
00085     if (which == REG_HKCU) return mihk->HKCUkey;
00086     return mihk->HKLMkey;
00087 }
00088 
00089 
00090 /*************************************************************************
00091  * SHRegOpenUSKeyA  [SHLWAPI.@]
00092  *
00093  * Open a user-specific registry key.
00094  *
00095  * PARAMS
00096  *  Path           [I] Key name to open
00097  *  AccessType     [I] Access type
00098  *  hRelativeUSKey [I] Relative user key
00099  *  phNewUSKey     [O] Destination for created key
00100  *  fIgnoreHKCU    [I] TRUE=Don't check HKEY_CURRENT_USER
00101  *
00102  * RETURNS
00103  *  Success: ERROR_SUCCESS
00104  *  Failure: An error code from RegOpenKeyExA().
00105  */
00106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
00107                             PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
00108 {
00109     WCHAR szPath[MAX_PATH];
00110 
00111     if (Path)
00112       MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH);
00113 
00114     return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey,
00115                            phNewUSKey, fIgnoreHKCU);
00116 }
00117 
00118 /*************************************************************************
00119  * SHRegOpenUSKeyW  [SHLWAPI.@]
00120  *
00121  * See SHRegOpenUSKeyA.
00122  */
00123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
00124                             PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
00125 {
00126     LONG ret2, ret1 = ~ERROR_SUCCESS;
00127     LPSHUSKEY hKey;
00128 
00129     TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
00130           hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
00131 
00132     if (phNewUSKey)
00133         *phNewUSKey = NULL;
00134 
00135     /* Create internal HUSKEY */
00136     hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
00137     lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR));
00138 
00139     if (hRelativeUSKey)
00140     {
00141         hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU));
00142         hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM));
00143 
00144         /* FIXME: if either of these keys is NULL, create the start key from
00145          *        the relative keys start+path
00146          */
00147     }
00148     else
00149     {
00150         hKey->HKCUstart = HKEY_CURRENT_USER;
00151         hKey->HKLMstart = HKEY_LOCAL_MACHINE;
00152     }
00153 
00154     if (!fIgnoreHKCU)
00155     {
00156         ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
00157         if (ret1)
00158             hKey->HKCUkey = 0;
00159     }
00160 
00161     ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
00162     if (ret2)
00163         hKey->HKLMkey = 0;
00164 
00165     if (ret1 || ret2)
00166         TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1, ret2);
00167 
00168     if (ret1 && ret2)
00169     {
00170         /* Neither open succeeded: fail */
00171         SHRegCloseUSKey(hKey);
00172         return ret2;
00173     }
00174 
00175     TRACE("HUSKEY=%p\n", hKey);
00176     if (phNewUSKey)
00177         *phNewUSKey = hKey;
00178     return ERROR_SUCCESS;
00179 }
00180 
00181 /*************************************************************************
00182  * SHRegCloseUSKey  [SHLWAPI.@]
00183  *
00184  * Close a user-specific registry key
00185  *
00186  * RETURNS
00187  *  Success: ERROR_SUCCESS
00188  *  Failure: An error code from RegCloseKey().
00189  */
00190 LONG WINAPI SHRegCloseUSKey(
00191         HUSKEY hUSKey) /* [I] Key to close */
00192 {
00193     LPSHUSKEY hKey = hUSKey;
00194     LONG ret = ERROR_SUCCESS;
00195 
00196     if (hKey->HKCUkey)
00197         ret = RegCloseKey(hKey->HKCUkey);
00198     if (hKey->HKCUstart && hKey->HKCUstart != HKEY_CURRENT_USER)
00199         ret = RegCloseKey(hKey->HKCUstart);
00200     if (hKey->HKLMkey)
00201         ret = RegCloseKey(hKey->HKLMkey);
00202     if (hKey->HKLMstart && hKey->HKLMstart != HKEY_LOCAL_MACHINE)
00203         ret = RegCloseKey(hKey->HKLMstart);
00204 
00205     HeapFree(GetProcessHeap(), 0, hKey);
00206     return ret;
00207 }
00208 
00209 /*************************************************************************
00210  * SHRegCreateUSKeyA  [SHLWAPI.@]
00211  *
00212  * Create or open a user-specific registry key.
00213  * 
00214  * PARAMS
00215  *  pszPath        [I] Key name to create or open.
00216  *  samDesired     [I] Wanted security access.
00217  *  hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
00218  *  phNewUSKey     [O] Receives a handle to the new or opened key.
00219  *  dwFlags        [I] Base key under which the key should be opened.
00220  *
00221  * RETURNS
00222  *  Success: ERROR_SUCCESS
00223  *  Failure: Nonzero error code from winerror.h
00224  */
00225 LONG WINAPI SHRegCreateUSKeyA(LPCSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
00226                               PHUSKEY phNewUSKey, DWORD dwFlags)
00227 {
00228     FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_a(pszPath), samDesired,
00229           hRelativeUSKey, phNewUSKey, dwFlags);
00230     return ERROR_SUCCESS;
00231 }
00232 
00233 /*************************************************************************
00234  * SHRegCreateUSKeyW  [SHLWAPI.@]
00235  *
00236  * See SHRegCreateUSKeyA.
00237  */
00238 LONG WINAPI SHRegCreateUSKeyW(LPCWSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
00239                               PHUSKEY phNewUSKey, DWORD dwFlags)
00240 {
00241     FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_w(pszPath), samDesired,
00242           hRelativeUSKey, phNewUSKey, dwFlags);
00243     return ERROR_SUCCESS;
00244 }
00245 
00246 /*************************************************************************
00247  * SHRegDeleteEmptyUSKeyA  [SHLWAPI.@]
00248  *
00249  * Delete an empty user-specific registry key.
00250  *
00251  * PARAMS
00252  *  hUSKey      [I] Handle to an open registry key.
00253  *  pszValue    [I] Empty key name.
00254  *  delRegFlags [I] Flag that specifies the base from which to delete 
00255  *                  the key.
00256  *
00257  * RETURNS
00258  *  Success: ERROR_SUCCESS
00259  *  Failure: Nonzero error code from winerror.h
00260  */
00261 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
00262 {
00263     FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
00264     return ERROR_SUCCESS;
00265 }
00266 
00267 /*************************************************************************
00268  * SHRegDeleteEmptyUSKeyW  [SHLWAPI.@]
00269  *
00270  * See SHRegDeleteEmptyUSKeyA.
00271  */
00272 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
00273 {
00274     FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
00275     return ERROR_SUCCESS;
00276 }
00277 
00278 /*************************************************************************
00279  * SHRegDeleteUSValueA  [SHLWAPI.@]
00280  *
00281  * Delete a user-specific registry value.
00282  *
00283  * PARAMS
00284  *  hUSKey      [I] Handle to an open registry key.
00285  *  pszValue    [I] Specifies the value to delete.
00286  *  delRegFlags [I] Flag that specifies the base of the key from which to
00287  *                  delete the value.
00288  *
00289  * RETURNS
00290  *  Success: ERROR_SUCCESS
00291  *  Failure: Nonzero error code from winerror.h
00292  */
00293 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
00294 {
00295     FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
00296     return ERROR_SUCCESS;
00297 }
00298 
00299 /*************************************************************************
00300  * SHRegDeleteUSValueW  [SHLWAPI.@]
00301  *
00302  * See SHRegDeleteUSValueA.
00303  */
00304 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
00305 {
00306     FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
00307     return ERROR_SUCCESS;
00308 }
00309 
00310 /*************************************************************************
00311  * SHRegEnumUSValueA  [SHLWAPI.@]
00312  *
00313  * Enumerate values of a specified registry key.
00314  *
00315  * PARAMS
00316  *  hUSKey           [I]   Handle to an open registry key.
00317  *  dwIndex          [I]   Index of the value to be retrieved.
00318  *  pszValueName     [O]   Buffer to receive the value name.
00319  *  pcchValueNameLen [I]   Size of pszValueName in characters.
00320  *  pdwType          [O]   Receives data type of the value.
00321  *  pvData           [O]   Receives value data. May be NULL.
00322  *  pcbData          [I/O] Size of pvData in bytes.
00323  *  enumRegFlags     [I]   Flag that specifies the base key under which to
00324  *                         enumerate values.
00325  *
00326  * RETURNS
00327  *  Success: ERROR_SUCCESS
00328  *  Failure: Nonzero error code from winerror.h
00329  */
00330 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
00331                               LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
00332                               LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
00333 {
00334     HKEY dokey;
00335 
00336     TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
00337           pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
00338 
00339     if (((enumRegFlags == SHREGENUM_HKCU) ||
00340          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00341         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00342         return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
00343                              NULL, pdwType, pvData, pcbData);
00344     }
00345 
00346     if (((enumRegFlags == SHREGENUM_HKLM) ||
00347          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00348         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00349         return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
00350                              NULL, pdwType, pvData, pcbData);
00351     }
00352     FIXME("no support for SHREGENUM_BOTH\n");
00353     return ERROR_INVALID_FUNCTION;
00354 }
00355 
00356 /*************************************************************************
00357  * SHRegEnumUSValueW  [SHLWAPI.@]
00358  *
00359  * See SHRegEnumUSValueA.
00360  */
00361 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
00362                               LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
00363                               LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
00364 {
00365     HKEY dokey;
00366 
00367     TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
00368           pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
00369 
00370     if (((enumRegFlags == SHREGENUM_HKCU) ||
00371          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00372         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00373         return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
00374                              NULL, pdwType, pvData, pcbData);
00375     }
00376 
00377     if (((enumRegFlags == SHREGENUM_HKLM) ||
00378          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00379         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00380         return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
00381                              NULL, pdwType, pvData, pcbData);
00382     }
00383     FIXME("no support for SHREGENUM_BOTH\n");
00384     return ERROR_INVALID_FUNCTION;
00385 }
00386 
00387 /*************************************************************************
00388  *      SHRegQueryUSValueA  [SHLWAPI.@]
00389  *
00390  * Query a user-specific registry value.
00391  *
00392  * RETURNS
00393  *  Success: ERROR_SUCCESS
00394  *  Failure: An error code from RegQueryValueExA().
00395  */
00396 LONG WINAPI SHRegQueryUSValueA(
00397     HUSKEY hUSKey, /* [I] Key to query */
00398     LPCSTR pszValue, /* [I] Value name under hUSKey */
00399     LPDWORD pdwType, /* [O] Destination for value type */
00400     LPVOID pvData, /* [O] Destination for value data */
00401     LPDWORD pcbData, /* [O] Destination for value length */
00402     BOOL fIgnoreHKCU,  /* [I] TRUE=Don't check HKEY_CURRENT_USER */
00403     LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
00404     DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
00405 {
00406     LONG ret = ~ERROR_SUCCESS;
00407     LONG i, maxmove;
00408     HKEY dokey;
00409     CHAR *src, *dst;
00410 
00411     /* if user wants HKCU, and it exists, then try it */
00412     if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00413         ret = RegQueryValueExA(dokey,
00414                    pszValue, 0, pdwType, pvData, pcbData);
00415         TRACE("HKCU RegQueryValue returned %08x\n", ret);
00416     }
00417 
00418     /* if HKCU did not work and HKLM exists, then try it */
00419     if ((ret != ERROR_SUCCESS) &&
00420         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00421         ret = RegQueryValueExA(dokey,
00422                    pszValue, 0, pdwType, pvData, pcbData);
00423         TRACE("HKLM RegQueryValue returned %08x\n", ret);
00424     }
00425 
00426     /* if neither worked, and default data exists, then use it */
00427     if (ret != ERROR_SUCCESS) {
00428         if (pvDefaultData && (dwDefaultDataSize != 0)) {
00429         maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
00430                 src = pvDefaultData;
00431                 dst = pvData;
00432         for(i=0; i<maxmove; i++) *dst++ = *src++;
00433         *pcbData = maxmove;
00434         TRACE("setting default data\n");
00435         ret = ERROR_SUCCESS;
00436         }
00437     }
00438     return ret;
00439 }
00440 
00441 
00442 /*************************************************************************
00443  *      SHRegQueryUSValueW  [SHLWAPI.@]
00444  *
00445  * See SHRegQueryUSValueA.
00446  */
00447 LONG WINAPI SHRegQueryUSValueW(
00448     HUSKEY hUSKey,
00449     LPCWSTR pszValue,
00450     LPDWORD pdwType,
00451     LPVOID pvData,
00452     LPDWORD pcbData,
00453     BOOL fIgnoreHKCU,
00454     LPVOID pvDefaultData,
00455     DWORD dwDefaultDataSize)
00456 {
00457     LONG ret = ~ERROR_SUCCESS;
00458     LONG i, maxmove;
00459     HKEY dokey;
00460     CHAR *src, *dst;
00461 
00462     /* if user wants HKCU, and it exists, then try it */
00463     if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00464         ret = RegQueryValueExW(dokey,
00465                    pszValue, 0, pdwType, pvData, pcbData);
00466         TRACE("HKCU RegQueryValue returned %08x\n", ret);
00467     }
00468 
00469     /* if HKCU did not work and HKLM exists, then try it */
00470     if ((ret != ERROR_SUCCESS) &&
00471         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00472         ret = RegQueryValueExW(dokey,
00473                    pszValue, 0, pdwType, pvData, pcbData);
00474         TRACE("HKLM RegQueryValue returned %08x\n", ret);
00475     }
00476 
00477     /* if neither worked, and default data exists, then use it */
00478     if (ret != ERROR_SUCCESS) {
00479         if (pvDefaultData && (dwDefaultDataSize != 0)) {
00480         maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
00481                 src = pvDefaultData;
00482                 dst = pvData;
00483         for(i=0; i<maxmove; i++) *dst++ = *src++;
00484         *pcbData = maxmove;
00485         TRACE("setting default data\n");
00486         ret = ERROR_SUCCESS;
00487         }
00488     }
00489     return ret;
00490 }
00491 
00492 /*************************************************************************
00493  * SHRegGetUSValueA [SHLWAPI.@]
00494  *
00495  * Get a user-specific registry value.
00496  *
00497  * RETURNS
00498  *  Success: ERROR_SUCCESS
00499  *  Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
00500  *
00501  * NOTES
00502  *   This function opens pSubKey, queries the value, and then closes the key.
00503  */
00504 LONG WINAPI SHRegGetUSValueA(
00505     LPCSTR   pSubKey, /* [I] Key name to open */
00506     LPCSTR   pValue, /* [I] Value name to open */
00507     LPDWORD  pwType, /* [O] Destination for the type of the value */
00508     LPVOID   pvData, /* [O] Destination for the value */
00509     LPDWORD  pcbData, /* [I] Destination for the length of the value **/
00510     BOOL     flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
00511     LPVOID   pDefaultData, /* [I] Default value if it doesn't exist */
00512     DWORD    wDefaultDataSize) /* [I] Length of pDefaultData */
00513 {
00514     HUSKEY myhuskey;
00515     LONG ret;
00516 
00517     if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
00518     TRACE("key '%s', value '%s', datalen %d,  %s\n",
00519           debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
00520           (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
00521 
00522     ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
00523     if (ret == ERROR_SUCCESS) {
00524         ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
00525                      pcbData, flagIgnoreHKCU, pDefaultData,
00526                      wDefaultDataSize);
00527         SHRegCloseUSKey(myhuskey);
00528     }
00529     return ret;
00530 }
00531 
00532 /*************************************************************************
00533  * SHRegGetUSValueW [SHLWAPI.@]
00534  *
00535  * See SHRegGetUSValueA.
00536  */
00537 LONG WINAPI SHRegGetUSValueW(
00538     LPCWSTR  pSubKey,
00539     LPCWSTR  pValue,
00540     LPDWORD  pwType,
00541     LPVOID   pvData,
00542     LPDWORD  pcbData,
00543     BOOL     flagIgnoreHKCU,
00544     LPVOID   pDefaultData,
00545     DWORD    wDefaultDataSize)
00546 {
00547     HUSKEY myhuskey;
00548     LONG ret;
00549 
00550     if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
00551     TRACE("key '%s', value '%s', datalen %d,  %s\n",
00552           debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
00553           (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
00554 
00555     ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
00556     if (ret == ERROR_SUCCESS) {
00557         ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
00558                      pcbData, flagIgnoreHKCU, pDefaultData,
00559                      wDefaultDataSize);
00560         SHRegCloseUSKey(myhuskey);
00561     }
00562     return ret;
00563 }
00564 
00565 /*************************************************************************
00566  * SHRegSetUSValueA   [SHLWAPI.@]
00567  *
00568  * Set a user-specific registry value.
00569  *
00570  * PARAMS
00571  *  pszSubKey [I] Name of key to set the value in
00572  *  pszValue  [I] Name of value under pszSubKey to set the value in
00573  *  dwType    [I] Type of the value
00574  *  pvData    [I] Data to set as the value
00575  *  cbData    [I] length of pvData
00576  *  dwFlags   [I] SHREGSET_ flags from "shlwapi.h"
00577  *
00578  * RETURNS
00579  *  Success: ERROR_SUCCESS
00580  *  Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
00581  *           ERROR_INVALID_FUNCTION if pvData is NULL.
00582  *
00583  * NOTES
00584  *   This function opens pszSubKey, sets the value, and then closes the key.
00585  */
00586 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
00587                              LPVOID pvData, DWORD cbData, DWORD dwFlags)
00588 {
00589   BOOL ignoreHKCU = TRUE;
00590   HUSKEY hkey;
00591   LONG ret;
00592 
00593   TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
00594         dwType, pvData, cbData, dwFlags);
00595 
00596   if (!pvData)
00597     return ERROR_INVALID_FUNCTION;
00598 
00599   if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
00600     ignoreHKCU = FALSE;
00601 
00602   ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
00603   if (ret == ERROR_SUCCESS)
00604   {
00605     ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
00606     SHRegCloseUSKey(hkey);
00607   }
00608   return ret;
00609 }
00610 
00611 /*************************************************************************
00612  * SHRegSetUSValueW   [SHLWAPI.@]
00613  *
00614  * See SHRegSetUSValueA.
00615  */
00616 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
00617                              LPVOID pvData, DWORD cbData, DWORD dwFlags)
00618 {
00619   BOOL ignoreHKCU = TRUE;
00620   HUSKEY hkey;
00621   LONG ret;
00622 
00623   TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
00624         dwType, pvData, cbData, dwFlags);
00625 
00626   if (!pvData)
00627     return ERROR_INVALID_FUNCTION;
00628 
00629   if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
00630     ignoreHKCU = FALSE;
00631 
00632   ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
00633   if (ret == ERROR_SUCCESS)
00634   {
00635     ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
00636     SHRegCloseUSKey(hkey);
00637   }
00638   return ret;
00639 }
00640 
00641 /*************************************************************************
00642  * SHRegGetBoolUSValueA   [SHLWAPI.@]
00643  *
00644  * Get a user-specific registry boolean value.
00645  *
00646  * RETURNS
00647  *  Success: ERROR_SUCCESS
00648  *  Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
00649  *
00650  * NOTES
00651  *   This function opens pszSubKey, queries the value, and then closes the key.
00652  *
00653  *   Boolean values are one of the following:
00654  *   True: YES,TRUE,non-zero
00655  *   False: NO,FALSE,0
00656  */
00657 BOOL WINAPI SHRegGetBoolUSValueA(
00658     LPCSTR pszSubKey, /* [I] Key name to open */
00659     LPCSTR pszValue, /* [I] Value name to open */
00660     BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
00661     BOOL fDefault) /* [I] Default value to use if pszValue is not present */
00662 {
00663     DWORD type, datalen, work;
00664     BOOL ret = fDefault;
00665     CHAR data[10];
00666 
00667     TRACE("key '%s', value '%s', %s\n",
00668           debugstr_a(pszSubKey), debugstr_a(pszValue),
00669           (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
00670 
00671     datalen = sizeof(data)-1;
00672     if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
00673                    data, &datalen,
00674                    fIgnoreHKCU, 0, 0)) {
00675         /* process returned data via type into bool */
00676         switch (type) {
00677         case REG_SZ:
00678         data[9] = '\0';     /* set end of string */
00679         if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
00680         if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
00681         if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
00682         if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
00683         break;
00684         case REG_DWORD:
00685         work = *(LPDWORD)data;
00686         ret = (work != 0);
00687         break;
00688         case REG_BINARY:
00689         if (datalen == 1) {
00690             ret = (data[0] != '\0');
00691             break;
00692         }
00693         default:
00694         FIXME("Unsupported registry data type %d\n", type);
00695         ret = FALSE;
00696         }
00697         TRACE("got value (type=%d), returning <%s>\n", type,
00698           (ret) ? "TRUE" : "FALSE");
00699     }
00700     else {
00701         ret = fDefault;
00702         TRACE("returning default data <%s>\n",
00703           (ret) ? "TRUE" : "FALSE");
00704     }
00705     return ret;
00706 }
00707 
00708 /*************************************************************************
00709  * SHRegGetBoolUSValueW   [SHLWAPI.@]
00710  *
00711  * See SHRegGetBoolUSValueA.
00712  */
00713 BOOL WINAPI SHRegGetBoolUSValueW(
00714     LPCWSTR pszSubKey,
00715     LPCWSTR pszValue,
00716     BOOL fIgnoreHKCU,
00717     BOOL fDefault)
00718 {
00719     static const WCHAR wYES[]=  {'Y','E','S','\0'};
00720     static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
00721     static const WCHAR wNO[]=   {'N','O','\0'};
00722     static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
00723     DWORD type, datalen, work;
00724     BOOL ret = fDefault;
00725     WCHAR data[10];
00726 
00727     TRACE("key '%s', value '%s', %s\n",
00728           debugstr_w(pszSubKey), debugstr_w(pszValue),
00729           (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
00730 
00731     datalen = (sizeof(data)-1) * sizeof(WCHAR);
00732     if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
00733                    data, &datalen,
00734                    fIgnoreHKCU, 0, 0)) {
00735         /* process returned data via type into bool */
00736         switch (type) {
00737         case REG_SZ:
00738         data[9] = '\0';     /* set end of string */
00739         if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
00740             ret = TRUE;
00741         else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
00742             ret = FALSE;
00743         break;
00744         case REG_DWORD:
00745         work = *(LPDWORD)data;
00746         ret = (work != 0);
00747         break;
00748         case REG_BINARY:
00749         if (datalen == 1) {
00750             ret = (data[0] != '\0');
00751             break;
00752         }
00753         default:
00754         FIXME("Unsupported registry data type %d\n", type);
00755         ret = FALSE;
00756         }
00757         TRACE("got value (type=%d), returning <%s>\n", type,
00758           (ret) ? "TRUE" : "FALSE");
00759     }
00760     else {
00761         ret = fDefault;
00762         TRACE("returning default data <%s>\n",
00763           (ret) ? "TRUE" : "FALSE");
00764     }
00765     return ret;
00766 }
00767 
00768 /*************************************************************************
00769  *      SHRegQueryInfoUSKeyA    [SHLWAPI.@]
00770  *
00771  * Get information about a user-specific registry key.
00772  *
00773  * RETURNS
00774  *  Success: ERROR_SUCCESS
00775  *  Failure: An error code from RegQueryInfoKeyA().
00776  */
00777 LONG WINAPI SHRegQueryInfoUSKeyA(
00778     HUSKEY hUSKey, /* [I] Key to query */
00779     LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
00780     LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
00781     LPDWORD pcValues, /* [O] Destination for number of values */
00782     LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
00783     SHREGENUM_FLAGS enumRegFlags)  /* [in] SHREGENUM_ flags from "shlwapi.h" */
00784 {
00785     HKEY dokey;
00786     LONG ret;
00787 
00788     TRACE("(%p,%p,%p,%p,%p,%d)\n",
00789           hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
00790           pcchMaxValueNameLen,enumRegFlags);
00791 
00792     /* if user wants HKCU, and it exists, then try it */
00793     if (((enumRegFlags == SHREGENUM_HKCU) ||
00794          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00795         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00796         ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
00797                    pcSubKeys, pcchMaxSubKeyLen, 0,
00798                    pcValues, pcchMaxValueNameLen, 0, 0, 0);
00799         if ((ret == ERROR_SUCCESS) ||
00800         (enumRegFlags == SHREGENUM_HKCU))
00801         return ret;
00802     }
00803     if (((enumRegFlags == SHREGENUM_HKLM) ||
00804          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00805         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00806         return RegQueryInfoKeyA(dokey, 0, 0, 0,
00807                     pcSubKeys, pcchMaxSubKeyLen, 0,
00808                     pcValues, pcchMaxValueNameLen, 0, 0, 0);
00809     }
00810     return ERROR_INVALID_FUNCTION;
00811 }
00812 
00813 /*************************************************************************
00814  *      SHRegQueryInfoUSKeyW    [SHLWAPI.@]
00815  *
00816  * See SHRegQueryInfoUSKeyA.
00817  */
00818 LONG WINAPI SHRegQueryInfoUSKeyW(
00819     HUSKEY hUSKey,
00820     LPDWORD pcSubKeys,
00821     LPDWORD pcchMaxSubKeyLen,
00822     LPDWORD pcValues,
00823     LPDWORD pcchMaxValueNameLen,
00824     SHREGENUM_FLAGS enumRegFlags)
00825 {
00826     HKEY dokey;
00827     LONG ret;
00828 
00829     TRACE("(%p,%p,%p,%p,%p,%d)\n",
00830           hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
00831           pcchMaxValueNameLen,enumRegFlags);
00832 
00833     /* if user wants HKCU, and it exists, then try it */
00834     if (((enumRegFlags == SHREGENUM_HKCU) ||
00835          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00836         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00837         ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
00838                    pcSubKeys, pcchMaxSubKeyLen, 0,
00839                    pcValues, pcchMaxValueNameLen, 0, 0, 0);
00840         if ((ret == ERROR_SUCCESS) ||
00841         (enumRegFlags == SHREGENUM_HKCU))
00842         return ret;
00843     }
00844     if (((enumRegFlags == SHREGENUM_HKLM) ||
00845          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00846         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00847         return RegQueryInfoKeyW(dokey, 0, 0, 0,
00848                     pcSubKeys, pcchMaxSubKeyLen, 0,
00849                     pcValues, pcchMaxValueNameLen, 0, 0, 0);
00850     }
00851     return ERROR_INVALID_FUNCTION;
00852 }
00853 
00854 /*************************************************************************
00855  *      SHRegEnumUSKeyA     [SHLWAPI.@]
00856  *
00857  * Enumerate a user-specific registry key.
00858  *
00859  * RETURNS
00860  *  Success: ERROR_SUCCESS
00861  *  Failure: An error code from RegEnumKeyExA().
00862  */
00863 LONG WINAPI SHRegEnumUSKeyA(
00864     HUSKEY hUSKey,                 /* [in] Key to enumerate */
00865     DWORD dwIndex,                 /* [in] Index within hUSKey */
00866     LPSTR pszName,                 /* [out] Name of the enumerated value */
00867     LPDWORD pcchValueNameLen,      /* [in/out] Length of pszName */
00868     SHREGENUM_FLAGS enumRegFlags)  /* [in] SHREGENUM_ flags from "shlwapi.h" */
00869 {
00870     HKEY dokey;
00871 
00872     TRACE("(%p,%d,%p,%p(%d),%d)\n",
00873           hUSKey, dwIndex, pszName, pcchValueNameLen,
00874           *pcchValueNameLen, enumRegFlags);
00875 
00876     if (((enumRegFlags == SHREGENUM_HKCU) ||
00877          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00878         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00879         return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
00880                 0, 0, 0, 0);
00881     }
00882 
00883     if (((enumRegFlags == SHREGENUM_HKLM) ||
00884          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00885         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00886         return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
00887                 0, 0, 0, 0);
00888     }
00889     FIXME("no support for SHREGENUM_BOTH\n");
00890     return ERROR_INVALID_FUNCTION;
00891 }
00892 
00893 /*************************************************************************
00894  *      SHRegEnumUSKeyW     [SHLWAPI.@]
00895  *
00896  * See SHRegEnumUSKeyA.
00897  */
00898 LONG WINAPI SHRegEnumUSKeyW(
00899     HUSKEY hUSKey,
00900     DWORD dwIndex,
00901     LPWSTR pszName,
00902     LPDWORD pcchValueNameLen,
00903     SHREGENUM_FLAGS enumRegFlags)
00904 {
00905     HKEY dokey;
00906 
00907     TRACE("(%p,%d,%p,%p(%d),%d)\n",
00908           hUSKey, dwIndex, pszName, pcchValueNameLen,
00909           *pcchValueNameLen, enumRegFlags);
00910 
00911     if (((enumRegFlags == SHREGENUM_HKCU) ||
00912          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00913         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
00914         return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
00915                 0, 0, 0, 0);
00916     }
00917 
00918     if (((enumRegFlags == SHREGENUM_HKLM) ||
00919          (enumRegFlags == SHREGENUM_DEFAULT)) &&
00920         (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
00921         return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
00922                 0, 0, 0, 0);
00923     }
00924     FIXME("no support for SHREGENUM_BOTH\n");
00925     return ERROR_INVALID_FUNCTION;
00926 }
00927 
00928 
00929 /*************************************************************************
00930  *      SHRegWriteUSValueA      [SHLWAPI.@]
00931  *
00932  * Write a user-specific registry value.
00933  *
00934  * PARAMS
00935  *  hUSKey   [I] Key to write the value to
00936  *  pszValue [I] Name of value under hUSKey to write the value as
00937  *  dwType   [I] Type of the value
00938  *  pvData   [I] Data to set as the value
00939  *  cbData   [I] length of pvData
00940  *  dwFlags  [I] SHREGSET_ flags from "shlwapi.h"
00941  *
00942  * RETURNS
00943  *  Success: ERROR_SUCCESS.
00944  *  Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
00945  *           an error code from RegSetValueExA().
00946  *
00947  * NOTES
00948  *  dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
00949  */
00950 LONG  WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
00951                                 LPVOID pvData, DWORD cbData, DWORD dwFlags)
00952 {
00953     WCHAR szValue[MAX_PATH];
00954 
00955     if (pszValue)
00956       MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
00957 
00958     return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
00959                                pvData, cbData, dwFlags);
00960 }
00961 
00962 /*************************************************************************
00963  *      SHRegWriteUSValueW      [SHLWAPI.@]
00964  *
00965  * See SHRegWriteUSValueA.
00966  */
00967 LONG  WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
00968                                 LPVOID pvData, DWORD cbData, DWORD dwFlags)
00969 {
00970     DWORD dummy;
00971     LPSHUSKEY hKey = hUSKey;
00972     LONG ret = ERROR_SUCCESS;
00973 
00974     TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
00975           dwType, pvData, cbData, dwFlags);
00976 
00977     if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
00978         !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
00979         return ERROR_INVALID_PARAMETER;
00980 
00981     if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
00982     {
00983         if (!hKey->HKCUkey)
00984         {
00985             /* Create the key */
00986             ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
00987             TRACE("Creating HKCU key, ret = %d\n", ret);
00988             if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
00989             {
00990                 hKey->HKCUkey = 0;
00991                 return ret;
00992             }
00993         }
00994 
00995         if (!ret)
00996         {
00997             if ((dwFlags & SHREGSET_FORCE_HKCU) ||
00998                 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
00999             {
01000                 /* Doesn't exist or we are forcing: Write value */
01001                 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
01002                 TRACE("Writing HKCU value, ret = %d\n", ret);
01003             }
01004         }
01005     }
01006 
01007     if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
01008     {
01009         if (!hKey->HKLMkey)
01010         {
01011             /* Create the key */
01012             ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
01013             TRACE("Creating HKLM key, ret = %d\n", ret);
01014             if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
01015             {
01016                 hKey->HKLMkey = 0;
01017                 return ret;
01018             }
01019         }
01020 
01021         if (!ret)
01022         {
01023             if ((dwFlags & SHREGSET_FORCE_HKLM) ||
01024                 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
01025             {
01026                 /* Doesn't exist or we are forcing: Write value */
01027                 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
01028                 TRACE("Writing HKLM value, ret = %d\n", ret);
01029             }
01030         }
01031     }
01032 
01033     return ret;
01034 }
01035 
01036 /*************************************************************************
01037  * SHRegGetPathA   [SHLWAPI.@]
01038  *
01039  * Get a path from the registry.
01040  *
01041  * PARAMS
01042  *   hKey       [I] Handle to registry key
01043  *   lpszSubKey [I] Name of sub key containing path to get
01044  *   lpszValue  [I] Name of value containing path to get
01045  *   lpszPath   [O] Buffer for returned path
01046  *   dwFlags    [I] Reserved
01047  *
01048  * RETURNS
01049  *   Success: ERROR_SUCCESS. lpszPath contains the path.
01050  *   Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
01051  */
01052 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
01053                            LPSTR lpszPath, DWORD dwFlags)
01054 {
01055   DWORD dwSize = MAX_PATH;
01056 
01057   TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
01058         debugstr_a(lpszValue), lpszPath, dwFlags);
01059 
01060   return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
01061 }
01062 
01063 /*************************************************************************
01064  * SHRegGetPathW   [SHLWAPI.@]
01065  *
01066  * See SHRegGetPathA.
01067  */
01068 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
01069                            LPWSTR lpszPath, DWORD dwFlags)
01070 {
01071   DWORD dwSize = MAX_PATH;
01072 
01073   TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
01074         debugstr_w(lpszValue), lpszPath, dwFlags);
01075 
01076   return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
01077 }
01078 
01079 
01080 /*************************************************************************
01081  * SHRegSetPathA   [SHLWAPI.@]
01082  *
01083  * Write a path to the registry.
01084  *
01085  * PARAMS
01086  *   hKey       [I] Handle to registry key
01087  *   lpszSubKey [I] Name of sub key containing path to set
01088  *   lpszValue  [I] Name of value containing path to set
01089  *   lpszPath   [O] Path to write
01090  *   dwFlags    [I] Reserved, must be 0.
01091  *
01092  * RETURNS
01093  *   Success: ERROR_SUCCESS.
01094  *   Failure: An error code from SHSetValueA().
01095  */
01096 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
01097                            LPCSTR lpszPath, DWORD dwFlags)
01098 {
01099   char szBuff[MAX_PATH];
01100 
01101   FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
01102         debugstr_a(lpszValue), lpszPath, dwFlags);
01103 
01104   lstrcpyA(szBuff, lpszPath);
01105 
01106   /* FIXME: PathUnExpandEnvStringsA(szBuff); */
01107 
01108   return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
01109                      lstrlenA(szBuff));
01110 }
01111 
01112 /*************************************************************************
01113  * SHRegSetPathW   [SHLWAPI.@]
01114  *
01115  * See SHRegSetPathA.
01116  */
01117 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
01118                            LPCWSTR lpszPath, DWORD dwFlags)
01119 {
01120   WCHAR szBuff[MAX_PATH];
01121 
01122   FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
01123         debugstr_w(lpszValue), lpszPath, dwFlags);
01124 
01125   lstrcpyW(szBuff, lpszPath);
01126 
01127   /* FIXME: PathUnExpandEnvStringsW(szBuff); */
01128 
01129   return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
01130                      lstrlenW(szBuff));
01131 }
01132 
01133 /*************************************************************************
01134  * SHGetValueA   [SHLWAPI.@]
01135  *
01136  * Get a value from the registry.
01137  *
01138  * PARAMS
01139  *   hKey       [I] Handle to registry key
01140  *   lpszSubKey [I] Name of sub key containing value to get
01141  *   lpszValue  [I] Name of value to get
01142  *   pwType     [O] Pointer to the values type
01143  *   pvData     [O] Pointer to the values data
01144  *   pcbData    [O] Pointer to the values size
01145  *
01146  * RETURNS
01147  *   Success: ERROR_SUCCESS. Output parameters contain the details read.
01148  *   Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
01149  */
01150 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
01151                          LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
01152 {
01153   DWORD dwRet = 0;
01154   HKEY hSubKey = 0;
01155 
01156   TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
01157         debugstr_a(lpszValue), pwType, pvData, pcbData);
01158 
01159   /*   lpszSubKey can be 0. In this case the value is taken from the
01160    *   current key.
01161    */
01162   if(lpszSubKey)
01163     dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
01164 
01165   if (! dwRet)
01166   {
01167     /* SHQueryValueEx expands Environment strings */
01168     dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
01169     if (hSubKey) RegCloseKey(hSubKey);
01170   }
01171   return dwRet;
01172 }
01173 
01174 /*************************************************************************
01175  * SHGetValueW   [SHLWAPI.@]
01176  *
01177  * See SHGetValueA.
01178  */
01179 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
01180                          LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
01181 {
01182   DWORD dwRet = 0;
01183   HKEY hSubKey = 0;
01184 
01185   TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
01186         debugstr_w(lpszValue), pwType, pvData, pcbData);
01187 
01188   if(lpszSubKey)
01189     dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
01190 
01191   if (! dwRet)
01192   {
01193     dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
01194     if (hSubKey) RegCloseKey(hSubKey);
01195   }
01196   return dwRet;
01197 }
01198 
01199 /*************************************************************************
01200  * SHSetValueA   [SHLWAPI.@]
01201  *
01202  * Set a value in the registry.
01203  *
01204  * PARAMS
01205  *   hKey       [I] Handle to registry key
01206  *   lpszSubKey [I] Name of sub key under hKey
01207  *   lpszValue  [I] Name of value to set
01208  *   dwType     [I] Type of the value
01209  *   pvData     [I] Data of the value
01210  *   cbData     [I] Size of the value
01211  *
01212  * RETURNS
01213  *   Success: ERROR_SUCCESS. The value is set with the data given.
01214  *   Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
01215  *
01216  * NOTES
01217  *   If lpszSubKey does not exist, it is created before the value is set. If
01218  *   lpszSubKey is NULL or an empty string, then the value is added directly
01219  *   to hKey instead.
01220  */
01221 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
01222                          DWORD dwType, LPCVOID pvData, DWORD cbData)
01223 {
01224   DWORD dwRet = ERROR_SUCCESS, dwDummy;
01225   HKEY  hSubKey;
01226 
01227   TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
01228           debugstr_a(lpszValue), dwType, pvData, cbData);
01229 
01230   if (lpszSubKey && *lpszSubKey)
01231     dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
01232                             0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
01233   else
01234     hSubKey = hKey;
01235   if (!dwRet)
01236   {
01237     dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
01238     if (hSubKey != hKey)
01239       RegCloseKey(hSubKey);
01240   }
01241   return dwRet;
01242 }
01243 
01244 /*************************************************************************
01245  * SHSetValueW   [SHLWAPI.@]
01246  *
01247  * See SHSetValueA.
01248  */
01249 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
01250                          DWORD dwType, LPCVOID pvData, DWORD cbData)
01251 {
01252   DWORD dwRet = ERROR_SUCCESS, dwDummy;
01253   HKEY  hSubKey;
01254 
01255   TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
01256         debugstr_w(lpszValue), dwType, pvData, cbData);
01257 
01258   if (lpszSubKey && *lpszSubKey)
01259     dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
01260                             0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
01261   else
01262     hSubKey = hKey;
01263   if (!dwRet)
01264   {
01265     dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
01266     if (hSubKey != hKey)
01267       RegCloseKey(hSubKey);
01268   }
01269   return dwRet;
01270 }
01271 
01272 /*************************************************************************
01273  * SHQueryInfoKeyA   [SHLWAPI.@]
01274  *
01275  * Get information about a registry key. See RegQueryInfoKeyA().
01276  *
01277  * RETURNS
01278  *  The result of calling RegQueryInfoKeyA().
01279  */
01280 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
01281                             LPDWORD pwValues, LPDWORD pwValueMax)
01282 {
01283   TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
01284         pwValues, pwValueMax);
01285   return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
01286                           NULL, pwValues, pwValueMax, NULL, NULL, NULL);
01287 }
01288 
01289 /*************************************************************************
01290  * SHQueryInfoKeyW   [SHLWAPI.@]
01291  *
01292  * See SHQueryInfoKeyA.
01293  */
01294 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
01295                             LPDWORD pwValues, LPDWORD pwValueMax)
01296 {
01297   TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
01298         pwValues, pwValueMax);
01299   return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
01300                           NULL, pwValues, pwValueMax, NULL, NULL, NULL);
01301 }
01302 
01303 /*************************************************************************
01304  * SHQueryValueExA   [SHLWAPI.@]
01305  *
01306  * Get a value from the registry, expanding environment variable strings.
01307  *
01308  * PARAMS
01309  *   hKey       [I] Handle to registry key
01310  *   lpszValue  [I] Name of value to query
01311  *   lpReserved [O] Reserved for future use; must be NULL
01312  *   pwType     [O] Optional pointer updated with the values type
01313  *   pvData     [O] Optional pointer updated with the values data
01314  *   pcbData    [O] Optional pointer updated with the values size
01315  *
01316  * RETURNS
01317  *   Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
01318  *            information about the value.
01319  *   Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
01320  *            data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
01321  *            code from RegQueryValueExA() or ExpandEnvironmentStringsA().
01322  *
01323  * NOTES
01324  *   Either pwType, pvData or pcbData may be NULL if the caller doesn't want
01325  *   the type, data or size information for the value.
01326  *
01327  *   If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
01328  *   value returned will be truncated if it is of type REG_SZ and bigger than
01329  *   the buffer given to store it.
01330  *
01331  *   REG_EXPAND_SZ:
01332  *     case-1: the unexpanded string is smaller than the expanded one
01333  *       subcase-1: the buffer is too small to hold the unexpanded string:
01334  *          function fails and returns the size of the unexpanded string.
01335  *
01336  *       subcase-2: buffer is too small to hold the expanded string:
01337  *          the function return success (!!) and the result is truncated
01338  *      *** This is clearly an error in the native implementation. ***
01339  *
01340  *     case-2: the unexpanded string is bigger than the expanded one
01341  *       The buffer must have enough space to hold the unexpanded
01342  *       string even if the result is smaller.
01343  *
01344  */
01345 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
01346                               LPDWORD lpReserved, LPDWORD pwType,
01347                               LPVOID pvData, LPDWORD pcbData)
01348 {
01349   DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
01350 
01351   TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
01352         lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
01353 
01354   if (pcbData) dwUnExpDataLen = *pcbData;
01355 
01356   dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
01357 
01358   if (pcbData && (dwType == REG_EXPAND_SZ))
01359   {
01360     DWORD nBytesToAlloc;
01361 
01362     /* Expand type REG_EXPAND_SZ into REG_SZ */
01363     LPSTR szData;
01364 
01365     /* If the caller didn't supply a buffer or the buffer is too small we have
01366      * to allocate our own
01367      */
01368     if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
01369     {
01370       char cNull = '\0';
01371       nBytesToAlloc = dwUnExpDataLen;
01372 
01373       szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
01374       RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
01375       dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
01376       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
01377       LocalFree(szData);
01378     }
01379     else
01380     {
01381       nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
01382       szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
01383       lstrcpyA(szData, pvData);
01384       dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
01385       if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
01386       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
01387       LocalFree(szData);
01388     }
01389   }
01390 
01391   /* Update the type and data size if the caller wanted them */
01392   if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
01393   if ( pwType ) *pwType = dwType;
01394   if ( pcbData ) *pcbData = dwUnExpDataLen;
01395   return dwRet;
01396 }
01397 
01398 
01399 /*************************************************************************
01400  * SHQueryValueExW   [SHLWAPI.@]
01401  *
01402  * See SHQueryValueExA.
01403  */
01404 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
01405                              LPDWORD lpReserved, LPDWORD pwType,
01406                              LPVOID pvData, LPDWORD pcbData)
01407 {
01408   DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
01409 
01410   TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
01411         lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
01412 
01413   if (pcbData) dwUnExpDataLen = *pcbData;
01414 
01415   dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
01416   if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
01417       return dwRet;
01418 
01419   if (pcbData && (dwType == REG_EXPAND_SZ))
01420   {
01421     DWORD nBytesToAlloc;
01422 
01423     /* Expand type REG_EXPAND_SZ into REG_SZ */
01424     LPWSTR szData;
01425 
01426     /* If the caller didn't supply a buffer or the buffer is too small we have
01427      * to allocate our own
01428      */
01429     if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
01430     {
01431       WCHAR cNull = '\0';
01432       nBytesToAlloc = dwUnExpDataLen;
01433 
01434       szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
01435       RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
01436       dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
01437       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
01438       LocalFree(szData);
01439     }
01440     else
01441     {
01442       nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
01443       szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
01444       lstrcpyW(szData, pvData);
01445       dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
01446       if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
01447       dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
01448       LocalFree(szData);
01449     }
01450   }
01451 
01452   /* Update the type and data size if the caller wanted them */
01453   if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
01454   if ( pwType ) *pwType = dwType;
01455   if ( pcbData ) *pcbData = dwUnExpDataLen;
01456   return dwRet;
01457 }
01458 
01459 /*************************************************************************
01460  * SHDeleteKeyA   [SHLWAPI.@]
01461  *
01462  * Delete a registry key and any sub keys/values present
01463  *
01464  * This function forwards to the unicode version directly, to avoid
01465  * handling subkeys that are not representable in ASCII.
01466  *
01467  * PARAMS
01468  *   hKey       [I] Handle to registry key
01469  *   lpszSubKey [I] Name of sub key to delete
01470  *
01471  * RETURNS
01472  *   Success: ERROR_SUCCESS. The key is deleted.
01473  *   Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
01474  *            RegEnumKeyExA() or RegDeleteKeyA().
01475  */
01476 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
01477 {
01478   WCHAR subkeyW[MAX_PATH];
01479 
01480   MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
01481   return SHDeleteKeyW(hKey, subkeyW);
01482 }
01483 
01484 /*************************************************************************
01485  * SHDeleteKeyW   [SHLWAPI.@]
01486  *
01487  * See SHDeleteKeyA.
01488  */
01489 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
01490 {
01491   DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
01492   WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
01493   HKEY hSubKey = 0;
01494 
01495   TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
01496 
01497   dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
01498   if(!dwRet)
01499   {
01500     /* Find the maximum subkey length so that we can allocate a buffer */
01501     dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
01502                              &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
01503     if(!dwRet)
01504     {
01505       dwMaxSubkeyLen++;
01506       if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
01507         /* Name too big: alloc a buffer for it */
01508         lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
01509 
01510       if(!lpszName)
01511         dwRet = ERROR_NOT_ENOUGH_MEMORY;
01512       else
01513       {
01514         while (dwRet == ERROR_SUCCESS)
01515         {
01516           dwSize = dwMaxSubkeyLen;
01517           dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
01518           if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
01519             dwRet = SHDeleteKeyW(hSubKey, lpszName);
01520         }
01521         if (dwRet == ERROR_NO_MORE_ITEMS)
01522           dwRet = ERROR_SUCCESS;
01523     
01524         if (lpszName != szNameBuf)
01525           HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
01526       }
01527     }
01528 
01529     RegCloseKey(hSubKey);
01530     if(!dwRet)
01531       dwRet = RegDeleteKeyW(hKey, lpszSubKey);
01532   }
01533   return dwRet;
01534 }
01535 
01536 /*************************************************************************
01537  * SHDeleteEmptyKeyA   [SHLWAPI.@]
01538  *
01539  * Delete a registry key with no sub keys.
01540  *
01541  * PARAMS
01542  *   hKey       [I] Handle to registry key
01543  *   lpszSubKey [I] Name of sub key to delete
01544  *
01545  * RETURNS
01546  *   Success: ERROR_SUCCESS. The key is deleted.
01547  *   Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
01548  *            returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
01549  *            RegDeleteKeyA().
01550  */
01551 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
01552 {
01553   DWORD dwRet, dwKeyCount = 0;
01554   HKEY hSubKey = 0;
01555 
01556   TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
01557 
01558   dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
01559   if(!dwRet)
01560   {
01561     dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
01562                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
01563     RegCloseKey(hSubKey);
01564     if(!dwRet)
01565     {
01566       if (!dwKeyCount)
01567         dwRet = RegDeleteKeyA(hKey, lpszSubKey);
01568       else
01569         dwRet = ERROR_KEY_HAS_CHILDREN;
01570     }
01571   }
01572   return dwRet;
01573 }
01574 
01575 /*************************************************************************
01576  * SHDeleteEmptyKeyW   [SHLWAPI.@]
01577  *
01578  * See SHDeleteEmptyKeyA.
01579  */
01580 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
01581 {
01582   DWORD dwRet, dwKeyCount = 0;
01583   HKEY hSubKey = 0;
01584 
01585   TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
01586 
01587   dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
01588   if(!dwRet)
01589   {
01590     dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
01591                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
01592     RegCloseKey(hSubKey);
01593     if(!dwRet)
01594     {
01595       if (!dwKeyCount)
01596         dwRet = RegDeleteKeyW(hKey, lpszSubKey);
01597       else
01598         dwRet = ERROR_KEY_HAS_CHILDREN;
01599     }
01600   }
01601   return dwRet;
01602 }
01603 
01604 /*************************************************************************
01605  * SHDeleteOrphanKeyA   [SHLWAPI.@]
01606  *
01607  * Delete a registry key with no sub keys or values.
01608  *
01609  * PARAMS
01610  *   hKey       [I] Handle to registry key
01611  *   lpszSubKey [I] Name of sub key to possibly delete
01612  *
01613  * RETURNS
01614  *   Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
01615  *   Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
01616  */
01617 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
01618 {
01619   HKEY hSubKey;
01620   DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
01621 
01622   TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
01623 
01624   dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
01625 
01626   if(!dwRet)
01627   {
01628     /* Get subkey and value count */
01629     dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
01630                              NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
01631 
01632     if(!dwRet && !dwKeyCount && !dwValueCount)
01633     {
01634       dwRet = RegDeleteKeyA(hKey, lpszSubKey);
01635     }
01636     RegCloseKey(hSubKey);
01637   }
01638   return dwRet;
01639 }
01640 
01641 /*************************************************************************
01642  * SHDeleteOrphanKeyW   [SHLWAPI.@]
01643  *
01644  * See SHDeleteOrphanKeyA.
01645  */
01646 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
01647 {
01648   HKEY hSubKey;
01649   DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
01650 
01651   TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
01652 
01653   dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
01654 
01655   if(!dwRet)
01656   {
01657     /* Get subkey and value count */
01658     dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
01659                              NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
01660 
01661     if(!dwRet && !dwKeyCount && !dwValueCount)
01662     {
01663       dwRet = RegDeleteKeyW(hKey, lpszSubKey);
01664     }
01665     RegCloseKey(hSubKey);
01666   }
01667   return dwRet;
01668 }
01669 
01670 /*************************************************************************
01671  * SHDeleteValueA   [SHLWAPI.@]
01672  *
01673  * Delete a value from the registry.
01674  *
01675  * PARAMS
01676  *   hKey       [I] Handle to registry key
01677  *   lpszSubKey [I] Name of sub key containing value to delete
01678  *   lpszValue  [I] Name of value to delete
01679  *
01680  * RETURNS
01681  *   Success: ERROR_SUCCESS. The value is deleted.
01682  *   Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
01683  */
01684 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
01685 {
01686   DWORD dwRet;
01687   HKEY hSubKey;
01688 
01689   TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
01690 
01691   dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
01692   if (!dwRet)
01693   {
01694     dwRet = RegDeleteValueA(hSubKey, lpszValue);
01695     RegCloseKey(hSubKey);
01696   }
01697   return dwRet;
01698 }
01699 
01700 /*************************************************************************
01701  * SHDeleteValueW   [SHLWAPI.@]
01702  *
01703  * See SHDeleteValueA.
01704  */
01705 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
01706 {
01707   DWORD dwRet;
01708   HKEY hSubKey;
01709 
01710   TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
01711 
01712   dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
01713   if (!dwRet)
01714   {
01715     dwRet = RegDeleteValueW(hSubKey, lpszValue);
01716     RegCloseKey(hSubKey);
01717   }
01718   return dwRet;
01719 }
01720 
01721 /*************************************************************************
01722  * SHEnumKeyExA   [SHLWAPI.@]
01723  *
01724  * Enumerate sub keys in a registry key.
01725  *
01726  * PARAMS
01727  *   hKey       [I] Handle to registry key
01728  *   dwIndex    [I] Index of key to enumerate
01729  *   lpszSubKey [O] Pointer updated with the subkey name
01730  *   pwLen      [O] Pointer updated with the subkey length
01731  *
01732  * RETURNS
01733  *   Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
01734  *   Failure: An error code from RegEnumKeyExA().
01735  */
01736 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
01737                          LPDWORD pwLen)
01738 {
01739   TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
01740 
01741   return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
01742 }
01743 
01744 /*************************************************************************
01745  * SHEnumKeyExW   [SHLWAPI.@]
01746  *
01747  * See SHEnumKeyExA.
01748  */
01749 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
01750                          LPDWORD pwLen)
01751 {
01752   TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
01753 
01754   return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
01755 }
01756 
01757 /*************************************************************************
01758  * SHEnumValueA   [SHLWAPI.@]
01759  *
01760  * Enumerate values in a registry key.
01761  *
01762  * PARAMS
01763  *   hKey      [I] Handle to registry key
01764  *   dwIndex   [I] Index of key to enumerate
01765  *   lpszValue [O] Pointer updated with the values name
01766  *   pwLen     [O] Pointer updated with the values length
01767  *   pwType    [O] Pointer updated with the values type
01768  *   pvData    [O] Pointer updated with the values data
01769  *   pcbData   [O] Pointer updated with the values size
01770  *
01771  * RETURNS
01772  *   Success: ERROR_SUCCESS. Output parameters are updated.
01773  *   Failure: An error code from RegEnumValueA().
01774  */
01775 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
01776                          LPDWORD pwLen, LPDWORD pwType,
01777                          LPVOID pvData, LPDWORD pcbData)
01778 {
01779   TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
01780         debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
01781 
01782   return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
01783                        pwType, pvData, pcbData);
01784 }
01785 
01786 /*************************************************************************
01787  * SHEnumValueW   [SHLWAPI.@]
01788  *
01789  * See SHEnumValueA.
01790  */
01791 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
01792                          LPDWORD pwLen, LPDWORD pwType,
01793                          LPVOID pvData, LPDWORD pcbData)
01794 {
01795   TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
01796         debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
01797 
01798   return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
01799                        pwType, pvData, pcbData);
01800 }
01801 
01802 /*************************************************************************
01803  * @   [SHLWAPI.205]
01804  *
01805  * Get a value from the registry.
01806  *
01807  * PARAMS
01808  *   hKey    [I] Handle to registry key
01809  *   pSubKey [I] Name of sub key containing value to get
01810  *   pValue  [I] Name of value to get
01811  *   pwType  [O] Destination for the values type
01812  *   pvData  [O] Destination for the values data
01813  *   pbData  [O] Destination for the values size
01814  *
01815  * RETURNS
01816  *   Success: ERROR_SUCCESS. Output parameters contain the details read.
01817  *   Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
01818  *            or ERROR_INVALID_FUNCTION in the machine is in safe mode.
01819  */
01820 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
01821                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
01822 {
01823   if (GetSystemMetrics(SM_CLEANBOOT))
01824     return ERROR_INVALID_FUNCTION;
01825   return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
01826 }
01827 
01828 /*************************************************************************
01829  * @   [SHLWAPI.206]
01830  *
01831  * Unicode version of SHGetValueGoodBootW.
01832  */
01833 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
01834                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
01835 {
01836   if (GetSystemMetrics(SM_CLEANBOOT))
01837     return ERROR_INVALID_FUNCTION;
01838   return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
01839 }
01840 
01841 /*************************************************************************
01842  * @   [SHLWAPI.320]
01843  *
01844  * Set a MIME content type in the registry.
01845  *
01846  * PARAMS
01847  *   lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
01848  *   lpszValue  [I] Value to set
01849  *
01850  * RETURNS
01851  *   Success: TRUE
01852  *   Failure: FALSE
01853  */
01854 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
01855 {
01856   DWORD dwRet;
01857 
01858   if (!lpszValue)
01859   {
01860     WARN("Invalid lpszValue would crash under Win32!\n");
01861     return FALSE;
01862   }
01863 
01864   dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
01865                       REG_SZ, lpszValue, strlen(lpszValue));
01866   return dwRet ? FALSE : TRUE;
01867 }
01868 
01869 /*************************************************************************
01870  * @   [SHLWAPI.321]
01871  *
01872  * Unicode version of RegisterMIMETypeForExtensionA.
01873  */
01874 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
01875 {
01876   DWORD dwRet;
01877 
01878   if (!lpszValue)
01879   {
01880     WARN("Invalid lpszValue would crash under Win32!\n");
01881     return FALSE;
01882   }
01883 
01884   dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
01885                       REG_SZ, lpszValue, strlenW(lpszValue));
01886   return dwRet ? FALSE : TRUE;
01887 }
01888 
01889 /*************************************************************************
01890  * @   [SHLWAPI.322]
01891  *
01892  * Delete a MIME content type from the registry.
01893  *
01894  * PARAMS
01895  *   lpszSubKey [I] Name of sub key
01896  *
01897  * RETURNS
01898  *   Success: TRUE
01899  *   Failure: FALSE
01900  */
01901 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
01902 {
01903   HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
01904   return ret ? FALSE : TRUE;
01905 }
01906 
01907 /*************************************************************************
01908  * @   [SHLWAPI.323]
01909  *
01910  * Unicode version of UnregisterMIMETypeForExtensionA.
01911  */
01912 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
01913 {
01914   HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
01915   return ret ? FALSE : TRUE;
01916 }
01917 
01918 /*************************************************************************
01919  * @   [SHLWAPI.328]
01920  *
01921  * Get the registry path to a MIME content key.
01922  *
01923  * PARAMS
01924  *   lpszType   [I] Content type to get the path for
01925  *   lpszBuffer [O] Destination for path
01926  *   dwLen      [I] Length of lpszBuffer
01927  *
01928  * RETURNS
01929  *   Success: TRUE. lpszBuffer contains the full path.
01930  *   Failure: FALSE.
01931  *
01932  * NOTES
01933  *   The base path for the key is "MIME\Database\Content Type\"
01934  */
01935 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
01936 {
01937   TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
01938 
01939   if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
01940   {
01941     size_t dwStrLen = strlen(lpszType);
01942 
01943     if (dwStrLen < dwLen - dwLenMimeDbContent)
01944     {
01945       memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
01946       memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
01947       return TRUE;
01948     }
01949   }
01950   return FALSE;
01951 }
01952 
01953 /*************************************************************************
01954  * @   [SHLWAPI.329]
01955  *
01956  * Unicode version of GetMIMETypeSubKeyA.
01957  */
01958 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
01959 {
01960   TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
01961 
01962   if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
01963   {
01964     DWORD dwStrLen = strlenW(lpszType);
01965 
01966     if (dwStrLen < dwLen - dwLenMimeDbContent)
01967     {
01968       memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
01969       memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
01970       return TRUE;
01971     }
01972   }
01973   return FALSE;
01974 }
01975 
01976 /*************************************************************************
01977  * @   [SHLWAPI.330]
01978  *
01979  * Get the file extension for a given Mime type.
01980  *
01981  * PARAMS
01982  *  lpszType [I] Mime type to get the file extension for
01983  *  lpExt    [O] Destination for the resulting extension
01984  *  iLen     [I] Length of lpExt in characters
01985  *
01986  * RETURNS
01987  *  Success: TRUE. lpExt contains the file extension.
01988  *  Failure: FALSE, if any parameter is invalid or the extension cannot be
01989  *           retrieved. If iLen > 0, lpExt is set to an empty string.
01990  *
01991  * NOTES
01992  *  - The extension returned in lpExt always has a leading '.' character, even
01993  *  if the registry Mime database entry does not.
01994  *  - iLen must be long enough for the file extension for this function to succeed.
01995  */
01996 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
01997 {
01998   char szSubKey[MAX_PATH];
01999   DWORD dwlen = iLen - 1, dwType;
02000   BOOL bRet = FALSE;
02001 
02002   if (iLen > 0 && lpExt)
02003     *lpExt = '\0';
02004 
02005   if (lpszType && lpExt && iLen > 2 &&
02006       GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
02007       !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
02008       lpExt[1])
02009   {
02010     if (lpExt[1] == '.')
02011       memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
02012     else
02013       *lpExt = '.'; /* Supply a '.' */
02014     bRet = TRUE;
02015   }
02016   return bRet;
02017 }
02018 
02019 /*************************************************************************
02020  * @   [SHLWAPI.331]
02021  *
02022  * Unicode version of MIME_GetExtensionA.
02023  */
02024 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
02025 {
02026   WCHAR szSubKey[MAX_PATH];
02027   DWORD dwlen = iLen - 1, dwType;
02028   BOOL bRet = FALSE;
02029 
02030   if (iLen > 0 && lpExt)
02031     *lpExt = '\0';
02032 
02033   if (lpszType && lpExt && iLen > 2 &&
02034       GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
02035       !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
02036       lpExt[1])
02037   {
02038     if (lpExt[1] == '.')
02039       memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
02040     else
02041       *lpExt = '.'; /* Supply a '.' */
02042     bRet = TRUE;
02043   }
02044   return bRet;
02045 }
02046 
02047 /*************************************************************************
02048  * @   [SHLWAPI.324]
02049  *
02050  * Set the file extension for a MIME content key.
02051  *
02052  * PARAMS
02053  *   lpszExt  [I] File extension to set
02054  *   lpszType [I] Content type to set the extension for
02055  *
02056  * RETURNS
02057  *   Success: TRUE. The file extension is set in the registry.
02058  *   Failure: FALSE.
02059  */
02060 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
02061 {
02062   DWORD dwLen;
02063   char szKey[MAX_PATH];
02064 
02065   TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
02066 
02067   if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
02068     return FALSE;
02069 
02070   dwLen = strlen(lpszExt) + 1;
02071 
02072   if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
02073     return FALSE;
02074   return TRUE;
02075 }
02076 
02077 /*************************************************************************
02078  * @   [SHLWAPI.325]
02079  *
02080  * Unicode version of RegisterExtensionForMIMETypeA.
02081  */
02082 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
02083 {
02084   DWORD dwLen;
02085   WCHAR szKey[MAX_PATH];
02086 
02087   TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
02088 
02089   /* Get the full path to the key */
02090   if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
02091     return FALSE;
02092 
02093   dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
02094 
02095   if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
02096     return FALSE;
02097   return TRUE;
02098 }
02099 
02100 /*************************************************************************
02101  * @   [SHLWAPI.326]
02102  *
02103  * Delete a file extension from a MIME content type.
02104  *
02105  * PARAMS
02106  *   lpszType [I] Content type to delete the extension for
02107  *
02108  * RETURNS
02109  *   Success: TRUE. The file extension is deleted from the registry.
02110  *   Failure: FALSE. The extension may have been removed but the key remains.
02111  *
02112  * NOTES
02113  *   If deleting the extension leaves an orphan key, the key is removed also.
02114  */
02115 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
02116 {
02117   char szKey[MAX_PATH];
02118 
02119   TRACE("(%s)\n", debugstr_a(lpszType));
02120 
02121   if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
02122     return FALSE;
02123 
02124   if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
02125     return FALSE;
02126 
02127   if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
02128     return FALSE;
02129   return TRUE;
02130 }
02131 
02132 /*************************************************************************
02133  * @   [SHLWAPI.327]
02134  *
02135  * Unicode version of UnregisterExtensionForMIMETypeA.
02136  */
02137 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
02138 {
02139   WCHAR szKey[MAX_PATH];
02140 
02141   TRACE("(%s)\n", debugstr_w(lpszType));
02142 
02143   if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
02144     return FALSE;
02145 
02146   if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
02147     return FALSE;
02148 
02149   if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
02150     return FALSE;
02151   return TRUE;
02152 }
02153 
02154 /*************************************************************************
02155  * SHRegDuplicateHKey   [SHLWAPI.@]
02156  *
02157  * Create a duplicate of a registry handle.
02158  *
02159  * PARAMS
02160  *  hKey [I] key to duplicate.
02161  *
02162  * RETURNS
02163  *  A new handle pointing to the same key as hKey.
02164  */
02165 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
02166 {
02167     HKEY newKey = 0;
02168 
02169     RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
02170     TRACE("new key is %p\n", newKey);
02171     return newKey;
02172 }
02173 
02174 
02175 /*************************************************************************
02176  * SHCopyKeyA   [SHLWAPI.@]
02177  *
02178  * Copy a key and its values/sub keys to another location.
02179  *
02180  * PARAMS
02181  *  hKeySrc    [I] Source key to copy from
02182  *  lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
02183  *  hKeyDst    [I] Destination key
02184  *  dwReserved [I] Reserved, must be 0
02185  *
02186  * RETURNS
02187  *  Success: ERROR_SUCCESS. The key is copied to the destination key.
02188  *  Failure: A standard windows error code.
02189  *
02190  * NOTES
02191  *  If hKeyDst is a key under hKeySrc, this function will misbehave
02192  *  (It will loop until out of stack, or the registry is full). This
02193  *  bug is present in Win32 also.
02194  */
02195 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
02196 {
02197   WCHAR szSubKeyW[MAX_PATH];
02198 
02199   TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
02200 
02201   if (lpszSrcSubKey)
02202     MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
02203 
02204   return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
02205 }
02206 
02207 /*************************************************************************
02208  * SHCopyKeyW   [SHLWAPI.@]
02209  *
02210  * See SHCopyKeyA.
02211  */
02212 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
02213 {
02214   DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
02215   DWORD  dwMaxValueLen = 0, dwMaxDataLen = 0, i;
02216   BYTE buff[1024];
02217   LPVOID lpBuff = buff;
02218   WCHAR szName[MAX_PATH], *lpszName = szName;
02219   DWORD dwRet = S_OK;
02220 
02221   TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
02222 
02223   if(!hKeyDst || !hKeySrc)
02224     dwRet = ERROR_INVALID_PARAMETER;
02225   else
02226   {
02227     /* Open source key */
02228     if(lpszSrcSubKey)
02229       dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
02230 
02231     if(dwRet)
02232       hKeyDst = NULL; /* Don't close this key since we didn't open it */
02233     else
02234     {
02235       /* Get details about sub keys and values */
02236       dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
02237                                NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
02238                                NULL, NULL);
02239       if(!dwRet)
02240       {
02241         if (dwMaxValueLen > dwMaxKeyLen)
02242           dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
02243 
02244         if (dwMaxKeyLen++ > MAX_PATH - 1)
02245           lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
02246 
02247         if (dwMaxDataLen > sizeof(buff))
02248           lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
02249 
02250         if (!lpszName || !lpBuff)
02251           dwRet = ERROR_NOT_ENOUGH_MEMORY;
02252       }
02253     }
02254   }
02255 
02256   /* Copy all the sub keys */
02257   for(i = 0; i < dwKeyCount && !dwRet; i++)
02258   {
02259     HKEY hSubKeySrc, hSubKeyDst;
02260     DWORD dwSize = dwMaxKeyLen;
02261 
02262     dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
02263 
02264     if(!dwRet)
02265     {
02266       /* Open source sub key */
02267       dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
02268 
02269       if(!dwRet)
02270       {
02271         /* Create destination sub key */
02272         dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
02273 
02274         if(!dwRet)
02275         {
02276           /* Recursively copy keys and values from the sub key */
02277           dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
02278           RegCloseKey(hSubKeyDst);
02279         }
02280       }
02281       RegCloseKey(hSubKeySrc);
02282     }
02283   }
02284 
02285   /* Copy all the values in this key */
02286   for (i = 0; i < dwValueCount && !dwRet; i++)
02287   {
02288     DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
02289 
02290     dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
02291 
02292     if (!dwRet)
02293       dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
02294   }
02295 
02296   /* Free buffers if allocated */
02297   if (lpszName != szName)
02298     HeapFree(GetProcessHeap(), 0, lpszName);
02299   if (lpBuff != buff)
02300     HeapFree(GetProcessHeap(), 0, lpBuff);
02301 
02302   if (lpszSrcSubKey && hKeyDst)
02303     RegCloseKey(hKeyDst);
02304   return dwRet;
02305 }
02306 
02307 /*
02308  * The following functions are ORDINAL ONLY:
02309  */
02310 
02311 /*************************************************************************
02312  *      @     [SHLWAPI.280]
02313  *
02314  * Read an integer value from the registry, falling back to a default.
02315  *
02316  * PARAMS
02317  *  hKey      [I] Registry key to read from
02318  *  lpszValue [I] Value name to read
02319  *  iDefault  [I] Default value to return
02320  *
02321  * RETURNS
02322  *  The value contained in the given registry value if present, otherwise
02323  *  iDefault.
02324  */
02325 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
02326 {
02327   TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
02328 
02329   if (hKey)
02330   {
02331     WCHAR szBuff[32];
02332     DWORD dwSize = sizeof(szBuff);
02333     szBuff[0] = '\0';
02334     SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
02335 
02336     if(*szBuff >= '0' && *szBuff <= '9')
02337       return StrToIntW(szBuff);
02338   }
02339   return iDefault;
02340 }
02341 
02342 /*************************************************************************
02343  *      @   [SHLWAPI.343]
02344  *
02345  * Create or open an explorer ClassId Key.
02346  *
02347  * PARAMS
02348  *  guid      [I] Explorer ClassId key to open
02349  *  lpszValue [I] Value name under the ClassId Key
02350  *  bUseHKCU  [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
02351  *  bCreate   [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
02352  *  phKey     [O] Destination for the resulting key handle
02353  *
02354  * RETURNS
02355  *  Success: S_OK. phKey contains the resulting registry handle.
02356  *  Failure: An HRESULT error code indicating the problem.
02357  */
02358 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
02359 {
02360   WCHAR szValue[MAX_PATH];
02361 
02362   if (lpszValue)
02363     MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
02364 
02365   return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
02366 }
02367 
02368 /*************************************************************************
02369  *      @   [SHLWAPI.344]
02370  *
02371  * Unicode version of SHRegGetCLSIDKeyA.
02372  */
02373 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
02374                            BOOL bCreate, PHKEY phKey)
02375 {
02376   static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
02377     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
02378     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
02379     'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
02380 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
02381   WCHAR szKey[MAX_PATH];
02382   DWORD dwRet;
02383   HKEY hkey;
02384 
02385   /* Create the key string */
02386   memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
02387   SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
02388 
02389   if(lpszValue)
02390   {
02391     szKey[szClassIdKeyLen + 39] = '\\';
02392     strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
02393   }
02394 
02395   hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
02396 
02397   if(bCreate)
02398     dwRet = RegCreateKeyW(hkey, szKey, phKey);
02399   else
02400     dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
02401 
02402   return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
02403 }
02404 
02405 /*************************************************************************
02406  * SHRegisterValidateTemplate   [SHLWAPI.@]
02407  *
02408  * observed from the ie 5.5 installer:
02409  *  - allocates a buffer with the size of the given file
02410  *  - read the file content into the buffer
02411  *  - creates the key szTemplateKey
02412  *  - sets "205523652929647911071668590831910975402"=dword:00002e37 at
02413  *    the key
02414  *
02415  * PARAMS
02416  *  filename [I] An existing file its content is read into an allocated
02417  *               buffer
02418  *  unknown  [I]
02419  *
02420  * RETURNS
02421  *  Success: ERROR_SUCCESS.
02422  */
02423 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
02424 {
02425 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
02426  *  'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
02427  *  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
02428  *  'E','x','p','l','o','r','e','r','\\',
02429  *  'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
02430  */
02431   FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
02432 
02433   return S_OK;
02434 }

Generated on Sun May 27 2012 04:16:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.