3 /******************************************************************************
4 * load_string [Internal]
6 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
7 * avoid importing user32, which is higher level than advapi32. Helper for
10 static int load_string(HINSTANCE hModule
, UINT resId
, LPWSTR pwszBuffer
, INT cMaxChars
)
17 /* Negative values have to be inverted. */
18 if (HIWORD(resId
) == 0xffff)
19 resId
= (UINT
)(-((INT
)resId
));
21 /* Load the resource into memory and get a pointer to it. */
22 hResource
= FindResourceW(hModule
, MAKEINTRESOURCEW(LOWORD(resId
>> 4) + 1), (LPWSTR
)RT_STRING
);
23 if (!hResource
) return 0;
24 hMemory
= LoadResource(hModule
, hResource
);
25 if (!hMemory
) return 0;
26 pString
= LockResource(hMemory
);
28 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
29 idxString
= resId
& 0xf;
30 while (idxString
--) pString
+= *pString
+ 1;
32 /* If no buffer is given, return length of the string. */
33 if (!pwszBuffer
) return *pString
;
35 /* Else copy over the string, respecting the buffer size. */
36 cMaxChars
= (*pString
< cMaxChars
) ? *pString
: (cMaxChars
- 1);
39 memcpy(pwszBuffer
, pString
+1, cMaxChars
* sizeof(WCHAR
));
40 pwszBuffer
[cMaxChars
] = L
'\0';
47 /************************************************************************
53 RegLoadMUIStringW(IN HKEY hKey
,
54 IN LPCWSTR pszValue OPTIONAL
,
57 OUT LPDWORD pcbData OPTIONAL
,
59 IN LPCWSTR pszDirectory OPTIONAL
)
61 DWORD dwValueType
, cbData
;
62 LPWSTR pwszTempBuffer
= NULL
, pwszExpandedBuffer
= NULL
;
65 /* Parameter sanity checks. */
66 if (!hKey
|| !pszOutBuf
)
67 return ERROR_INVALID_PARAMETER
;
69 if (pszDirectory
&& *pszDirectory
)
71 //FIXME("BaseDir parameter not yet supported!\n");
72 return ERROR_INVALID_PARAMETER
;
75 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
76 result
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwValueType
, NULL
, &cbData
);
77 if (result
!= ERROR_SUCCESS
) goto cleanup
;
78 if (!(dwValueType
== REG_SZ
|| dwValueType
== REG_EXPAND_SZ
) || !cbData
)
80 result
= ERROR_FILE_NOT_FOUND
;
83 pwszTempBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
86 result
= ERROR_NOT_ENOUGH_MEMORY
;
89 result
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwValueType
, (LPBYTE
)pwszTempBuffer
, &cbData
);
90 if (result
!= ERROR_SUCCESS
) goto cleanup
;
92 /* Expand environment variables, if appropriate, or copy the original string over. */
93 if (dwValueType
== REG_EXPAND_SZ
)
95 cbData
= ExpandEnvironmentStringsW(pwszTempBuffer
, NULL
, 0) * sizeof(WCHAR
);
96 if (!cbData
) goto cleanup
;
97 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
98 if (!pwszExpandedBuffer
)
100 result
= ERROR_NOT_ENOUGH_MEMORY
;
103 ExpandEnvironmentStringsW(pwszTempBuffer
, pwszExpandedBuffer
, cbData
);
107 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
108 memcpy(pwszExpandedBuffer
, pwszTempBuffer
, cbData
);
111 /* If the value references a resource based string, parse the value and load the string.
112 * Else just copy over the original value. */
113 result
= ERROR_SUCCESS
;
114 if (*pwszExpandedBuffer
!= L
'@') /* '@' is the prefix for resource based string entries. */
116 lstrcpynW(pszOutBuf
, pwszExpandedBuffer
, cbOutBuf
/ sizeof(WCHAR
));
120 WCHAR
*pComma
= wcsrchr(pwszExpandedBuffer
, L
',');
124 /* Format of the expanded value is 'path_to_dll,-resId' */
125 if (!pComma
|| pComma
[1] != L
'-')
127 result
= ERROR_BADKEY
;
131 uiStringId
= _wtoi(pComma
+2);
134 hModule
= LoadLibraryExW(pwszExpandedBuffer
+ 1, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
135 if (!hModule
|| !load_string(hModule
, uiStringId
, pszOutBuf
, cbOutBuf
/ sizeof(WCHAR
)))
136 result
= ERROR_BADKEY
;
137 FreeLibrary(hModule
);
141 HeapFree(GetProcessHeap(), 0, pwszTempBuffer
);
142 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer
);