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.

515 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. regutil.c
  5. Abstract:
  6. Utilities for accessing the system registry.
  7. Author:
  8. Mike Massa (mikemas) May 19, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 05-19-97 created
  13. --*/
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. LPCWSTR
  19. ClRtlMultiSzEnum(
  20. IN LPCWSTR MszString,
  21. IN DWORD MszStringLength,
  22. IN DWORD StringIndex
  23. )
  24. /*++
  25. Routine Description:
  26. Parses a REG_MULTI_SZ string and returns the specified substring.
  27. Arguments:
  28. MszString - A pointer to the REG_MULTI_SZ string.
  29. MszStringLength - The length of the REG_MULTI_SZ string in characters,
  30. including the terminating null character.
  31. StringIndex - Index number of the substring to return. Specifiying
  32. index 0 retrieves the first substring.
  33. Return Value:
  34. A pointer to the specified substring.
  35. --*/
  36. {
  37. LPCWSTR string = MszString;
  38. if ( MszStringLength < 2 ) {
  39. return(NULL);
  40. }
  41. //
  42. // Find the start of the desired string.
  43. //
  44. while (StringIndex) {
  45. while (MszStringLength >= 1) {
  46. MszStringLength -= 1;
  47. if (*string++ == UNICODE_NULL) {
  48. break;
  49. }
  50. }
  51. //
  52. // Check for index out of range.
  53. //
  54. if ( MszStringLength < 2 ) {
  55. return(NULL);
  56. }
  57. StringIndex--;
  58. }
  59. if ( MszStringLength < 2 ) {
  60. return(NULL);
  61. }
  62. return(string);
  63. }
  64. DWORD
  65. ClRtlMultiSzRemove(
  66. IN LPWSTR lpszMultiSz,
  67. IN OUT LPDWORD StringLength,
  68. IN LPCWSTR lpString
  69. )
  70. /*++
  71. Routine Description:
  72. Removes the specified string from the supplied REG_MULTI_SZ.
  73. The MULTI_SZ is edited in place.
  74. Arguments:
  75. lpszMultiSz - Supplies the REG_MULTI_SZ string that lpString should
  76. be removed from.
  77. StringLength - Supplies the length (in characters) of lpszMultiSz
  78. Returns the new length (in characters) of lpszMultiSz
  79. lpString - Supplies the string to be removed from lpszMultiSz
  80. Return Value:
  81. ERROR_SUCCESS if successful
  82. ERROR_FILE_NOT_FOUND if the string was not found in the MULTI_SZ
  83. Win32 error code otherwise
  84. --*/
  85. {
  86. PCHAR Dest, Src;
  87. DWORD CurrentLength;
  88. DWORD i;
  89. LPCWSTR Next;
  90. DWORD NextLength;
  91. //
  92. // Scan through the strings in the returned MULTI_SZ looking
  93. // for a match.
  94. //
  95. CurrentLength = *StringLength;
  96. for (i=0; ;i++) {
  97. Next = ClRtlMultiSzEnum(lpszMultiSz, *StringLength, i);
  98. if (Next == NULL) {
  99. //
  100. // The value was not in the specified multi-sz
  101. //
  102. break;
  103. }
  104. NextLength = lstrlenW(Next)+1;
  105. CurrentLength -= NextLength;
  106. if (lstrcmpiW(Next, lpString)==0) {
  107. //
  108. // Found the string, delete it and return
  109. //
  110. Dest = (PCHAR)Next;
  111. Src = (PCHAR)Next + (NextLength*sizeof(WCHAR));
  112. CopyMemory(Dest, Src, CurrentLength*sizeof(WCHAR));
  113. *StringLength -= NextLength;
  114. return(ERROR_SUCCESS);
  115. }
  116. }
  117. return(ERROR_FILE_NOT_FOUND);
  118. }
  119. DWORD
  120. ClRtlMultiSzAppend(
  121. IN OUT LPWSTR *MultiSz,
  122. IN OUT LPDWORD StringLength,
  123. IN LPCWSTR lpString
  124. )
  125. /*++
  126. Routine Description:
  127. Appends the specified string to the supplied REG_MULTI_SZ.
  128. The passed in MultiSz will be freed with LocalFree. A new
  129. MultiSz large enough to hold the new value will be allocated
  130. with LocalAlloc and returned in *MultiSz
  131. Arguments:
  132. lpszMultiSz - Supplies the REG_MULTI_SZ string that lpString should
  133. be appended to.
  134. Returns the new REG_MULTI_SZ string with lpString appended
  135. StringLength - Supplies the length (in characters) of lpszMultiSz
  136. Returns the new length (in characters) of lpszMultiSz
  137. lpString - Supplies the string to be appended to lpszMultiSz
  138. Return Value:
  139. ERROR_SUCCESS if successful
  140. Win32 error code otherwise
  141. --*/
  142. {
  143. LPWSTR NewMultiSz;
  144. DWORD Length;
  145. DWORD NewLength;
  146. if (*MultiSz == NULL) {
  147. //
  148. // There is no multi-sz, create a new multi-sz with lpString as the
  149. // only entry.
  150. //
  151. NewLength = lstrlenW(lpString)+2;
  152. NewMultiSz = LocalAlloc(LMEM_FIXED, NewLength*sizeof(WCHAR));
  153. if (NewMultiSz == NULL) {
  154. return(ERROR_NOT_ENOUGH_MEMORY);
  155. }
  156. CopyMemory(NewMultiSz, lpString, (NewLength-1)*sizeof(WCHAR));
  157. } else {
  158. //
  159. // Append this string to the existing MULTI_SZ
  160. //
  161. Length = lstrlenW(lpString) + 1;
  162. NewLength = *StringLength + Length;
  163. NewMultiSz = LocalAlloc(LMEM_FIXED, NewLength * sizeof(WCHAR));
  164. if (NewMultiSz == NULL) {
  165. return(ERROR_NOT_ENOUGH_MEMORY);
  166. }
  167. CopyMemory(NewMultiSz, *MultiSz, *StringLength * sizeof(WCHAR));
  168. CopyMemory(NewMultiSz + *StringLength - 1, lpString, Length * sizeof(WCHAR));
  169. NewMultiSz[NewLength-1] = L'\0';
  170. //Free the passed in MultiSz
  171. LocalFree(*MultiSz);
  172. }
  173. NewMultiSz[NewLength-1] = L'\0';
  174. *MultiSz = NewMultiSz;
  175. *StringLength = NewLength;
  176. return(ERROR_SUCCESS);
  177. }
  178. DWORD
  179. ClRtlMultiSzLength(
  180. IN LPCWSTR lpszMultiSz
  181. )
  182. /*++
  183. Routine Description:
  184. Determines the length (in characters) of a multi-sz. The calculated
  185. length includes all trailing NULLs.
  186. Arguments:
  187. lpszMultiSz - Supplies the multi-sz
  188. Return Value:
  189. The length (in characters) of the supplied multi-sz
  190. --*/
  191. {
  192. LPCWSTR p;
  193. DWORD Length=0;
  194. if(!lpszMultiSz)
  195. return 0;
  196. if (*lpszMultiSz == UNICODE_NULL)
  197. return 1;
  198. p=lpszMultiSz;
  199. do {
  200. while (p[Length++] != L'\0') {
  201. }
  202. } while ( p[Length++] != L'\0' );
  203. return(Length);
  204. }
  205. LPCWSTR
  206. ClRtlMultiSzScan(
  207. IN LPCWSTR lpszMultiSz,
  208. IN LPCWSTR lpszString
  209. )
  210. /*++
  211. Routine Description:
  212. Scans a multi-sz looking for an entry that matches the specified string.
  213. The match is done case-insensitive.
  214. Arguments:
  215. lpszMultiSz - Supplies the multi-sz to scan.
  216. lpszString - Supplies the string to look for
  217. Return Value:
  218. A pointer to the string in the supplied multi-sz if found.
  219. NULL if not found.
  220. --*/
  221. {
  222. DWORD dwLength;
  223. DWORD i;
  224. LPCWSTR sz;
  225. dwLength = ClRtlMultiSzLength(lpszMultiSz);
  226. for (i=0; ; i++) {
  227. sz = ClRtlMultiSzEnum(lpszMultiSz,
  228. dwLength,
  229. i);
  230. if (sz == NULL) {
  231. break;
  232. }
  233. if (lstrcmpiW(sz, lpszString) == 0) {
  234. break;
  235. }
  236. }
  237. return(sz);
  238. }
  239. DWORD
  240. ClRtlRegQueryDword(
  241. IN HKEY hKey,
  242. IN LPWSTR lpValueName,
  243. OUT LPDWORD lpValue,
  244. IN LPDWORD lpDefaultValue OPTIONAL
  245. )
  246. /*++
  247. Routine Description:
  248. Reads a REG_DWORD registry value. If the value is not present, then
  249. default to the value supplied in lpDefaultValue (if present).
  250. Arguments:
  251. hKey - Open key for the value to be read.
  252. lpValueName - Unicode name of the value to be read.
  253. lpValue - Pointer to the DWORD into which to read the value.
  254. lpDefaultValue - Optional pointer to a DWORD to use as a default value.
  255. Return Value:
  256. ERROR_SUCCESS if successful
  257. Win32 error code otherwise
  258. --*/
  259. {
  260. HKEY Key;
  261. DWORD Status;
  262. DWORD ValueType;
  263. DWORD ValueSize = sizeof(DWORD);
  264. Status = RegQueryValueExW(
  265. hKey,
  266. lpValueName,
  267. NULL,
  268. &ValueType,
  269. (LPBYTE)lpValue,
  270. &ValueSize
  271. );
  272. if ( Status == ERROR_SUCCESS ) {
  273. if ( ValueType != REG_DWORD ) {
  274. Status = ERROR_INVALID_PARAMETER;
  275. }
  276. } else {
  277. if ( ARGUMENT_PRESENT( lpDefaultValue ) ) {
  278. *lpValue = *lpDefaultValue;
  279. Status = ERROR_SUCCESS;
  280. }
  281. }
  282. return(Status);
  283. } // ClRtlRegQueryDword
  284. DWORD
  285. ClRtlRegQueryString(
  286. IN HKEY Key,
  287. IN LPWSTR ValueName,
  288. IN DWORD ValueType,
  289. IN LPWSTR *StringBuffer,
  290. IN OUT LPDWORD StringBufferSize,
  291. OUT LPDWORD StringSize
  292. )
  293. /*++
  294. Routine Description:
  295. Reads a REG_SZ or REG_MULTI_SZ registry value. If the StringBuffer is
  296. not large enough to hold the data, it is reallocated.
  297. Arguments:
  298. Key - Open key for the value to be read.
  299. ValueName - Unicode name of the value to be read.
  300. ValueType - REG_SZ or REG_MULTI_SZ.
  301. StringBuffer - Buffer into which to place the value data.
  302. StringBufferSize - Pointer to the size of the StringBuffer. This parameter
  303. is updated if StringBuffer is reallocated.
  304. StringSize - The size of the data returned in StringBuffer, including
  305. the terminating null character.
  306. Return Value:
  307. The status of the registry query.
  308. --*/
  309. {
  310. DWORD status;
  311. DWORD valueType;
  312. WCHAR *temp;
  313. DWORD oldBufferSize = *StringBufferSize;
  314. BOOL noBuffer = FALSE;
  315. if (*StringBufferSize == 0) {
  316. noBuffer = TRUE;
  317. }
  318. *StringSize = *StringBufferSize;
  319. status = RegQueryValueExW(
  320. Key,
  321. ValueName,
  322. NULL,
  323. &valueType,
  324. (LPBYTE) *StringBuffer,
  325. StringSize
  326. );
  327. if (status == NO_ERROR) {
  328. if (!noBuffer ) {
  329. if (valueType == ValueType) {
  330. return(NO_ERROR);
  331. }
  332. else {
  333. return(ERROR_INVALID_PARAMETER);
  334. }
  335. }
  336. status = ERROR_MORE_DATA;
  337. }
  338. if (status == ERROR_MORE_DATA) {
  339. temp = LocalAlloc(LMEM_FIXED, *StringSize);
  340. if (temp == NULL) {
  341. *StringSize = 0;
  342. return(ERROR_NOT_ENOUGH_MEMORY);
  343. }
  344. if (!noBuffer) {
  345. LocalFree(*StringBuffer);
  346. }
  347. *StringBuffer = temp;
  348. *StringBufferSize = *StringSize;
  349. status = RegQueryValueExW(
  350. Key,
  351. ValueName,
  352. NULL,
  353. &valueType,
  354. (LPBYTE) *StringBuffer,
  355. StringSize
  356. );
  357. if (status == NO_ERROR) {
  358. if (valueType == ValueType) {
  359. return(NO_ERROR);
  360. }
  361. else {
  362. *StringSize = 0;
  363. return(ERROR_INVALID_PARAMETER);
  364. }
  365. }
  366. }
  367. return(status);
  368. } // ClRtlRegQueryString