reshuffling of dlls
[reactos.git] / reactos / dll / win32 / user32 / misc / resources.c
1 #include <user32.h>
2
3 /* FIXME: Currently IsBadWritePtr is implemented using VirtualQuery which
4 does not seem to work properly for stack address space. */
5 /* kill `left-hand operand of comma expression has no effect' warning */
6 #define IsBadWritePtr(lp, n) ((DWORD)lp==n?0:0)
7
8 BOOL STDCALL _InternalLoadString
9 (
10 HINSTANCE hInstance,
11 UINT uID,
12 PUNICODE_STRING pwstrDest
13 )
14 {
15 HRSRC hrsStringTable;
16 HGLOBAL hResource;
17 PWCHAR pStringTable;
18 unsigned i;
19 unsigned l = uID % 16; /* (1) */
20
21 /* parameter validation */
22 if(IsBadWritePtr(pwstrDest, sizeof(UNICODE_STRING)))
23 {
24 SetLastError(ERROR_INVALID_PARAMETER);
25 return FALSE;
26 }
27
28 /*
29 find the string table. String tables are created by grouping, 16 by 16, string
30 resources whose identifiers, divided by 16, have the same integer quotient.
31 Holes in the numbering are filled with zero-length strings. String table ids
32 (actual resource ids) start from 1. See (1) and (2)
33 */
34 /* TODO: some sort of cache, here, would be great */
35 hrsStringTable = FindResourceW
36 (
37 (HMODULE)hInstance,
38 MAKEINTRESOURCEW((uID / 16) + 1), /* (2) */
39 RT_STRING
40 );
41
42 /* failure */
43 if(hrsStringTable == NULL) return FALSE;
44
45 /* load the string table into memory */
46 hResource = LoadResource((HMODULE)hInstance, hrsStringTable);
47
48 /* failure */
49 if(hResource == NULL) return FALSE;
50
51 /* lock the resource into memory */
52 pStringTable = LockResource(hResource);
53
54 /* failure */
55 if(pStringTable == NULL) return FALSE;
56
57 /*
58 string tables are packed Unicode Pascal strings. The first WCHAR contains the
59 length, in characters, of the current string. Zero-length strings, if any, are
60 placeholders for unused slots, and should therefore be considered non-present.
61 See also (3). Here, we walk all the strings before that of interest
62 */
63 for(i = 0; i < l; ++ i)
64 {
65 /* skip the length and the current string */
66 pStringTable += 1 + (*pStringTable);
67 }
68
69 /* we've reached the string of interest */
70 if((*pStringTable) == 0)
71 {
72 /* the string is empty (unallocated) */
73 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
74 return FALSE; /* 3 */
75 }
76
77 /* string length in bytes */
78 pwstrDest->Length = pwstrDest->MaximumLength = (*pStringTable) * sizeof(WCHAR);
79
80 /* string */
81 pwstrDest->Buffer = pStringTable + 1;
82
83 /* success */
84 return TRUE;
85 }
86
87
88 /*
89 * @implemented
90 */
91 int STDCALL LoadStringA
92 (
93 HINSTANCE hInstance,
94 UINT uID,
95 LPSTR lpBuffer,
96 int nBufferMax
97 )
98 {
99 UNICODE_STRING wstrResStr;
100 ANSI_STRING strBuf;
101 INT retSize;
102
103 /* parameter validation */
104 if
105 (
106 (nBufferMax < 1) ||
107 (IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0])))
108 )
109 {
110 SetLastError(ERROR_INVALID_PARAMETER);
111 return 0;
112 }
113
114 /* get the UNICODE_STRING descriptor of the in-memory image of the string */
115 if(!_InternalLoadString(hInstance, uID, &wstrResStr))
116 /* failure */
117 return 0;
118
119 /*
120 convert the string. The Unicode string may be in UTF-16 (multi-byte), so we
121 don't alter wstrResStr.Length, and let RtlUnicodeStringToAnsiString truncate
122 it, if necessary
123 */
124 strBuf.Length = 0;
125 strBuf.MaximumLength = nBufferMax * sizeof(CHAR);
126 strBuf.Buffer = lpBuffer;
127
128 retSize = WideCharToMultiByte(CP_ACP, 0, wstrResStr.Buffer, wstrResStr.Length / sizeof(WCHAR), strBuf.Buffer, strBuf.MaximumLength, NULL, NULL);
129
130 if(!retSize)
131 /* failure */
132 return 0;
133 else
134 strBuf.Length = retSize;
135
136 /* the ANSI string may not be null-terminated */
137 if(strBuf.Length >= strBuf.MaximumLength)
138 {
139 /* length greater than the buffer? whatever */
140 int nStringLen = strBuf.MaximumLength / sizeof(CHAR) - 1;
141
142 /* zero the last character in the buffer */
143 strBuf.Buffer[nStringLen] = 0;
144
145 /* success */
146 return nStringLen;
147 }
148 else
149 {
150 /* zero the last character in the string */
151 strBuf.Buffer[strBuf.Length / sizeof(CHAR)] = 0;
152
153 /* success */
154 return strBuf.Length / sizeof(CHAR);
155 }
156 }
157
158
159 /*
160 * @implemented
161 */
162 int STDCALL LoadStringW
163 (
164 HINSTANCE hInstance,
165 UINT uID,
166 LPWSTR lpBuffer,
167 int nBufferMax
168 )
169 {
170 UNICODE_STRING wstrResStr;
171 int nStringLen;
172
173 /* parameter validation */
174 if
175 (
176 (nBufferMax < 1) ||
177 (IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0])))
178 )
179 {
180 SetLastError(ERROR_INVALID_PARAMETER);
181 return 0;
182 }
183
184 /* get the UNICODE_STRING descriptor of the in-memory image of the string */
185 if(!_InternalLoadString(hInstance, uID, &wstrResStr))
186 /* failure */
187 return 0;
188
189 /* get the length in characters */
190 nStringLen = wstrResStr.Length / sizeof(WCHAR);
191
192 /* the buffer must be enough to contain the string and the null terminator */
193 if(nBufferMax < (nStringLen + 1))
194 /* otherwise, the string is truncated */
195 nStringLen = nBufferMax - 1;
196
197 /* copy the string */
198 memcpy(lpBuffer, wstrResStr.Buffer, nStringLen * sizeof(WCHAR));
199
200 /* null-terminate it */
201 lpBuffer[nStringLen] = 0;
202
203 /* success */
204 return nStringLen;
205 }
206
207 /* EOF */