ObjFW  Diff

Differences From Artifact [4590e9ff33]:

To Artifact [d4e7766886]:


14
15
16
17
18
19
20

21
22
23
24

25
26
27
28
29
30
31
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33







+




+







 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFWindowsRegistryKey.h"
#import "OFData.h"

#include <windows.h>

#import "OFCreateWindowsRegistryKeyFailedException.h"
#import "OFInvalidFormatException.h"
#import "OFOpenWindowsRegistryKeyFailedException.h"
#import "OFReadWindowsRegistryValueFailedException.h"

@interface OFWindowsRegistryKey ()
- (instancetype)of_initWithHKey: (HKEY)hKey
			  close: (bool)close;
@end
160
161
162
163
164
165
166
167

168

169
170
171
172




173
174

175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190

191
192
193
194




195
196

197
198

199
200
201
202
203
204
205

206
207
208
209







210
211
212
213

214
215
216
217
218
219



220
221
222
223


224
225
226
227
228






















































229
162
163
164
165
166
167
168

169
170
171




172
173
174
175


176








177

178
179





180




181
182
183
184
185

186


187




188


189
190



191
192
193
194
195
196
197




198






199
200
201




202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263







-
+

+
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
+
-


-
-
-
-
-
+
-
-
-
-
+
+
+
+

-
+
-
-
+
-
-
-
-

-
-
+

-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


	return [[[OFWindowsRegistryKey alloc] of_initWithHKey: subKey
							close: true]
	    autorelease];
}

- (OFString *)stringForValue: (OFString *)value
		  subKeyPath: (OFString *)subKeyPath
		  subkeyPath: (OFString *)subkeyPath
{
	void *pool = objc_autoreleasePoolPush();
	return [self stringForValue: value
			 subKeyPath: subKeyPath
			      flags: 0
			       type: NULL];
	OFData *data = [self dataForValue: value
			       subkeyPath: subkeyPath
				    flags: RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ
				     type: NULL];
}

	const of_char16_t *UTF16String;
- (OFString *)stringForValue: (OFString *)value
		  subKeyPath: (OFString *)subKeyPath
		       flags: (DWORD)flags
			type: (LPDWORD)type
{
	void *pool = objc_autoreleasePoolPush();
	of_char16_t stackBuffer[256], *buffer = stackBuffer;
	DWORD length = sizeof(stackBuffer);
	size_t length;
	LSTATUS status;
	OFString *ret;

	if ((status = RegGetValueW(_hKey, [subKeyPath UTF16String],
	    [value UTF16String], flags | RRF_RT_REG_SZ | RRF_RT_REG_EXPAND_SZ,
	    type, buffer, &length)) != ERROR_SUCCESS) {
		OFObject *tmp;

	if (data == nil)
		if (status == ERROR_FILE_NOT_FOUND) {
			objc_autoreleasePoolPop(pool);
			return nil;
		}
		return nil;

	UTF16String = [data items];
	length = [data count];

		if (status != ERROR_MORE_DATA)
	if ([data itemSize] != 1 || length % 2 == 1)
			@throw [OFReadWindowsRegistryValueFailedException
			    exceptionWithRegistryKey: self
		@throw [OFInvalidFormatException exception];
					       value: value
					  subKeyPath: subKeyPath
					       flags: flags
					      status: status];

		tmp = [[[OFObject alloc] init] autorelease];
		buffer = [tmp allocMemoryWithSize: length];
	length /= 2;

		if ((status = RegGetValueW(_hKey, [subKeyPath UTF16String],
		    [value UTF16String], flags | RRF_RT_REG_SZ |
		    RRF_RT_REG_EXPAND_SZ, NULL, buffer, &length)) !=
	/*
	 * REG_SZ and REG_EXPAND_SZ contain a \0, but can contain data after it
	 * that should be ignored.
	 */
	for (size_t i = 0; i < length; i++) {
		if (UTF16String[i] == 0) {
			length = i;
		    ERROR_SUCCESS)
			@throw [OFReadWindowsRegistryValueFailedException
			    exceptionWithRegistryKey: self
					       value: value
			break;
					  subKeyPath: subKeyPath
					       flags: flags
					      status: status];
	}

	/*
		}
	}

	 * We do not specify a length, as the length returned by RegGetValue()
	 * sometimes seems to be larger than the string.
	 */
	ret = [[OFString alloc] initWithUTF16String: buffer];
	ret = [[OFString alloc] initWithUTF16String: UTF16String
					     length: length];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (OFData *)dataForValue: (OFString *)value
	      subkeyPath: (OFString *)subkeyPath
		   flags: (DWORD)flags
		    type: (LPDWORD)type
{
	void *pool = objc_autoreleasePoolPush();
	char stackBuffer[256], *buffer = stackBuffer;
	DWORD length = sizeof(stackBuffer);
	OFMutableData *ret = nil;
	LSTATUS status;

	for (;;) {
		status = RegGetValueW(_hKey, [subkeyPath UTF16String],
		    [value UTF16String], flags, type, buffer, &length);

		switch (status) {
		case ERROR_SUCCESS:
			if (buffer == stackBuffer) {
				objc_autoreleasePoolPop(pool);

				return [OFData dataWithItems: buffer
						       count: length];
			} else {
				[ret makeImmutable];
				[ret retain];

				objc_autoreleasePoolPop(pool);

				return [ret autorelease];
			}
		case ERROR_FILE_NOT_FOUND:
			objc_autoreleasePoolPop(pool);

			return nil;
		case ERROR_MORE_DATA:
			objc_autoreleasePoolPop(pool);
			pool = objc_autoreleasePoolPush();

			ret = [OFMutableData dataWithCapacity: length];
			[ret increaseCountBy: length];
			buffer = [ret items];

			continue;
		default:
			@throw [OFReadWindowsRegistryValueFailedException
			    exceptionWithRegistryKey: self
					       value: value
					  subkeyPath: subkeyPath
					       flags: flags
					      status: status];
		}
	}
}
@end