Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
7.2 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. HandleRegExpandSzRegistryKeys.cpp
  5. Abstract:
  6. This DLL catches REG_EXPAND_SZ registry keys and converts them to REG_SZ by
  7. expanding the embedded environment strings.
  8. History:
  9. 04/05/2000 markder Created
  10. 10/30/2000 maonis Bug fix
  11. --*/
  12. #include "precomp.h"
  13. IMPLEMENT_SHIM_BEGIN(HandleRegExpandSzRegistryKeys)
  14. #include "ShimHookMacro.h"
  15. APIHOOK_ENUM_BEGIN
  16. APIHOOK_ENUM_ENTRY(RegQueryValueExA)
  17. APIHOOK_ENUM_ENTRY(RegQueryValueExW)
  18. APIHOOK_ENUM_END
  19. /*++
  20. Expand REG_EXPAND_SZ strings.
  21. --*/
  22. LONG
  23. APIHOOK(RegQueryValueExA)(
  24. HKEY hKey, // handle to key
  25. LPCSTR lpValueName, // value name
  26. LPDWORD lpReserved, // reserved
  27. LPDWORD lpType, // dwType buffer
  28. LPBYTE lpData, // data buffer
  29. LPDWORD lpcbData // size of data buffer
  30. )
  31. {
  32. DWORD dwType;
  33. LONG uRet;
  34. DWORD cbPassedInBuffer = 0, cbExpandedBuffer = 0;
  35. LPSTR szLocalBuffer = NULL;
  36. if (lpcbData) {
  37. cbPassedInBuffer = *lpcbData;
  38. cbExpandedBuffer = *lpcbData;
  39. }
  40. uRet = ORIGINAL_API(RegQueryValueExA)(
  41. hKey, lpValueName, lpReserved, &dwType, lpData, &cbExpandedBuffer);
  42. if (lpcbData) {
  43. *lpcbData = cbExpandedBuffer;
  44. }
  45. if (lpType) {
  46. *lpType = dwType;
  47. }
  48. if (dwType != REG_EXPAND_SZ) {
  49. return uRet;
  50. }
  51. //
  52. // The type is REG_EXPAND_SZ. Change to REG_SZ so app doesn't try to expand
  53. // the string itself.
  54. //
  55. if (lpType) {
  56. *lpType = REG_SZ;
  57. }
  58. if ((uRet != ERROR_SUCCESS) && (uRet != ERROR_MORE_DATA)) {
  59. return uRet;
  60. }
  61. LOGN(
  62. eDbgLevelInfo,
  63. "[RegQueryValueExA] Caught REG_EXPAND_SZ key: \"%s\".", lpValueName);
  64. //
  65. // Allocate a local buffer and get the value.
  66. //
  67. szLocalBuffer = (LPSTR) malloc(cbExpandedBuffer);
  68. if (!szLocalBuffer) {
  69. LOGN( eDbgLevelError, "Out of memory.\n");
  70. // The shim failed, so revert to the original behavior
  71. *lpType = REG_EXPAND_SZ;
  72. return uRet;
  73. }
  74. ORIGINAL_API(RegQueryValueExA)(
  75. hKey, lpValueName, lpReserved, NULL, (LPBYTE) szLocalBuffer,
  76. &cbExpandedBuffer);
  77. DPFN(
  78. eDbgLevelInfo,
  79. "[RegQueryValueExA] Value: \"%s\"", szLocalBuffer);
  80. //
  81. // Query for length of expanded string.
  82. //
  83. cbExpandedBuffer = ExpandEnvironmentStringsA((LPSTR)szLocalBuffer, NULL, 0);
  84. if (lpcbData) {
  85. *lpcbData = cbExpandedBuffer;
  86. }
  87. if (lpData != NULL) {
  88. if (cbExpandedBuffer > cbPassedInBuffer) {
  89. //
  90. // Buffer not big enough.
  91. //
  92. LOGN(
  93. eDbgLevelError,
  94. "[RegQueryValueExA] Buffer too small - Passed in: %d Needed: %d",
  95. cbPassedInBuffer, cbExpandedBuffer );
  96. free(szLocalBuffer);
  97. //
  98. // We're pretending the value is already expanded, so to be
  99. // consistent, we must fail as if that were the case. If we simply
  100. // returned uRet here, the app would get inconsistent return
  101. // values, e.g. if the buffer is big enough then REG_SZ is returned
  102. // otherwise REG_EXPAND_SZ is returned - this doesn't make sense.
  103. //
  104. return ERROR_MORE_DATA;
  105. }
  106. //
  107. // If data buffer was passed in (and is big enough), copy the data into it.
  108. //
  109. ExpandEnvironmentStringsA(szLocalBuffer, (LPSTR)lpData, cbPassedInBuffer);
  110. DPFN(
  111. eDbgLevelInfo,
  112. "[RegQueryValueExA] Expanded to: \"%s\"\n",
  113. lpData);
  114. uRet = ERROR_SUCCESS;
  115. }
  116. free(szLocalBuffer);
  117. return uRet;
  118. }
  119. /*++
  120. Expand REG_EXPAND_SZ strings.
  121. --*/
  122. LONG
  123. APIHOOK(RegQueryValueExW)(
  124. HKEY hKey, // handle to key
  125. LPCWSTR lpValueName, // value name
  126. LPDWORD lpReserved, // reserved
  127. LPDWORD lpType, // dwType buffer
  128. LPBYTE lpData, // data buffer
  129. LPDWORD lpcbData // size of data buffer
  130. )
  131. {
  132. DWORD dwType;
  133. LONG uRet;
  134. DWORD cbPassedInBuffer = 0, cbExpandedBuffer = 0;
  135. LPWSTR szLocalBuffer = NULL;
  136. if (lpcbData) {
  137. cbPassedInBuffer = *lpcbData;
  138. cbExpandedBuffer = *lpcbData;
  139. }
  140. uRet = ORIGINAL_API(RegQueryValueExW)(
  141. hKey, lpValueName, lpReserved, &dwType, lpData, &cbExpandedBuffer);
  142. if (lpcbData) {
  143. *lpcbData = cbExpandedBuffer;
  144. }
  145. if (lpType) {
  146. *lpType = dwType;
  147. }
  148. if (dwType != REG_EXPAND_SZ) {
  149. return uRet;
  150. }
  151. //
  152. // The type is REG_EXPAND_SZ. Change to REG_SZ so app doesn't try to expand
  153. // the string itself.
  154. //
  155. if (lpType) {
  156. *lpType = REG_SZ;
  157. }
  158. if ((uRet != ERROR_SUCCESS) && (uRet != ERROR_MORE_DATA)) {
  159. return uRet;
  160. }
  161. LOGN(
  162. eDbgLevelInfo,
  163. "[RegQueryValueExW] Caught REG_EXPAND_SZ key: \"%ws\".",
  164. lpValueName);
  165. //
  166. // Allocate a local buffer and get the value.
  167. //
  168. szLocalBuffer = (LPWSTR) malloc(cbExpandedBuffer);
  169. if (!szLocalBuffer) {
  170. LOGN( eDbgLevelError, "Out of memory.\n");
  171. // The shim failed, so revert to the original behavior
  172. *lpType = REG_EXPAND_SZ;
  173. return uRet;
  174. }
  175. ORIGINAL_API(RegQueryValueExW)(
  176. hKey, lpValueName, lpReserved, NULL, (LPBYTE) szLocalBuffer,
  177. &cbExpandedBuffer);
  178. DPFN(
  179. eDbgLevelInfo,
  180. "[RegQueryValueExW] Value: \"%ws\".\n",
  181. szLocalBuffer);
  182. //
  183. // Query for length of expanded string.
  184. //
  185. cbExpandedBuffer = ExpandEnvironmentStringsW((LPWSTR)szLocalBuffer, NULL, 0) * sizeof(WCHAR);
  186. if (lpcbData) {
  187. *lpcbData = cbExpandedBuffer;
  188. }
  189. if (lpData != NULL) {
  190. if (cbExpandedBuffer > cbPassedInBuffer) {
  191. //
  192. // Buffer not big enough.
  193. //
  194. LOGN(
  195. eDbgLevelInfo,
  196. "[RegQueryValueExW] Buffer too small - Passed in: %d Needed: %d",
  197. cbPassedInBuffer, cbExpandedBuffer);
  198. free(szLocalBuffer);
  199. //
  200. // We're pretending the value is already expanded, so to be
  201. // consistent, we must fail as if that were the case. If we simply
  202. // returned uRet here, the app would get inconsistent return
  203. // values, e.g. if the buffer is big enough then REG_SZ is returned
  204. // otherwise REG_EXPAND_SZ is returned - this doesn't make sense.
  205. //
  206. return ERROR_MORE_DATA;
  207. }
  208. //
  209. // If data buffer was passed in (and is big enough), copy the data into it.
  210. //
  211. ExpandEnvironmentStringsW(szLocalBuffer, (LPWSTR)lpData, cbPassedInBuffer / sizeof(WCHAR));
  212. DPFN(
  213. eDbgLevelInfo,
  214. "[RegQueryValueExW] Expanded to: \"%ws\".\n",
  215. lpData);
  216. uRet = ERROR_SUCCESS;
  217. }
  218. free(szLocalBuffer);
  219. return uRet;
  220. }
  221. /*++
  222. Register hooked functions
  223. --*/
  224. HOOK_BEGIN
  225. APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueExA)
  226. APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueExW)
  227. HOOK_END
  228. IMPLEMENT_SHIM_END