remove whitespace from end of lines
[reactos.git] / reactos / subsys / system / regedit / edit.c
1 /*
2 * Registry editing UI functions.
3 *
4 * Copyright (C) 2003 Dimitrie O. Paun
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
22
23 #include <windows.h>
24 #include <tchar.h>
25 #include <commctrl.h>
26 #include <commdlg.h>
27 #include <cderr.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <shellapi.h>
31 #include <ctype.h>
32
33 #include "main.h"
34 #include "regproc.h"
35 #include "resource.h"
36 #include "hexedit.h"
37
38
39 typedef enum _EDIT_MODE
40 {
41 EDIT_MODE_DEC,
42 EDIT_MODE_HEX
43 } EDIT_MODE;
44
45
46 static const TCHAR* editValueName;
47 static TCHAR* stringValueData;
48 static PVOID binValueData;
49 static DWORD dwordValueData;
50 static DWORD valueDataLen;
51 static EDIT_MODE dwordEditMode = EDIT_MODE_HEX;
52
53
54 void error(HWND hwnd, INT resId, ...)
55 {
56 va_list ap;
57 TCHAR title[256];
58 TCHAR errfmt[1024];
59 TCHAR errstr[1024];
60 HINSTANCE hInstance;
61
62 hInstance = GetModuleHandle(0);
63
64 if (!LoadString(hInstance, IDS_ERROR, title, COUNT_OF(title)))
65 _tcscpy(title, _T("Error"));
66
67 if (!LoadString(hInstance, resId, errfmt, COUNT_OF(errfmt)))
68 _tcscpy(errfmt, _T("Unknown error string!"));
69
70 va_start(ap, resId);
71 _vsntprintf(errstr, COUNT_OF(errstr), errfmt, ap);
72 va_end(ap);
73
74 MessageBox(hwnd, errstr, title, MB_OK | MB_ICONERROR);
75 }
76
77 void warning(HWND hwnd, INT resId, ...)
78 {
79 va_list ap;
80 TCHAR title[256];
81 TCHAR errfmt[1024];
82 TCHAR errstr[1024];
83 HINSTANCE hInstance;
84
85 hInstance = GetModuleHandle(0);
86
87 if (!LoadString(hInstance, IDS_WARNING, title, COUNT_OF(title)))
88 _tcscpy(title, _T("Warning"));
89
90 if (!LoadString(hInstance, resId, errfmt, COUNT_OF(errfmt)))
91 _tcscpy(errfmt, _T("Unknown error string!"));
92
93 va_start(ap, resId);
94 _vsntprintf(errstr, COUNT_OF(errstr), errfmt, ap);
95 va_end(ap);
96
97 MessageBox(hwnd, errstr, title, MB_OK | MB_ICONSTOP);
98 }
99
100 INT_PTR CALLBACK modify_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
101 {
102 TCHAR* valueData;
103 HWND hwndValue;
104 int len;
105
106 switch(uMsg) {
107 case WM_INITDIALOG:
108 if(editValueName && _tcscmp(editValueName, _T("")))
109 {
110 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
111 }
112 else
113 {
114 TCHAR buffer[255];
115 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
116 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
117 }
118 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, stringValueData);
119 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
120 return FALSE;
121 case WM_COMMAND:
122 switch (LOWORD(wParam))
123 {
124 case IDOK:
125 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
126 {
127 if ((len = GetWindowTextLength(hwndValue)))
128 {
129 if (stringValueData)
130 {
131 if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(TCHAR))))
132 {
133 stringValueData = valueData;
134 if (!GetWindowText(hwndValue, stringValueData, len + 1))
135 *stringValueData = 0;
136 }
137 }
138 else
139 {
140 if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR))))
141 {
142 stringValueData = valueData;
143 if (!GetWindowText(hwndValue, stringValueData, len + 1))
144 *stringValueData = 0;
145 }
146 }
147 }
148 else
149 {
150 if (stringValueData)
151 *stringValueData = 0;
152 }
153 }
154 EndDialog(hwndDlg, IDOK);
155 break;
156 case IDCANCEL:
157 EndDialog(hwndDlg, IDCANCEL);
158 return TRUE;
159 }
160 }
161 return FALSE;
162 }
163
164
165 INT_PTR CALLBACK modify_multi_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
166 {
167 TCHAR* valueData;
168 HWND hwndValue;
169 int len;
170
171 switch(uMsg) {
172 case WM_INITDIALOG:
173 if(editValueName && _tcscmp(editValueName, _T("")))
174 {
175 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
176 }
177 else
178 {
179 TCHAR buffer[255];
180 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
181 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
182 }
183 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, stringValueData);
184 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
185 return FALSE;
186 case WM_COMMAND:
187 switch (LOWORD(wParam))
188 {
189 case IDOK:
190 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
191 {
192 if ((len = GetWindowTextLength(hwndValue)))
193 {
194 if (stringValueData)
195 {
196 if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(TCHAR))))
197 {
198 stringValueData = valueData;
199 if (!GetWindowText(hwndValue, stringValueData, len + 1))
200 *stringValueData = 0;
201 }
202 }
203 else
204 {
205 if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR))))
206 {
207 stringValueData = valueData;
208 if (!GetWindowText(hwndValue, stringValueData, len + 1))
209 *stringValueData = 0;
210 }
211 }
212 }
213 else
214 {
215 if (stringValueData)
216 *stringValueData = 0;
217 }
218 }
219 EndDialog(hwndDlg, IDOK);
220 break;
221 case IDCANCEL:
222 EndDialog(hwndDlg, IDCANCEL);
223 return TRUE;
224 }
225 }
226 return FALSE;
227 }
228
229
230 LRESULT CALLBACK DwordEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
231 {
232 WNDPROC oldwndproc;
233
234 oldwndproc = (WNDPROC)GetWindowLongPtr(hwnd, GWL_USERDATA);
235
236 switch (uMsg)
237 {
238 case WM_CHAR:
239 if (dwordEditMode == EDIT_MODE_DEC)
240 {
241 if (isdigit(wParam & 0xff))
242 {
243 break;
244 }
245 else
246 {
247 return 0;
248 }
249 }
250 else if (dwordEditMode == EDIT_MODE_HEX)
251 {
252 if (isxdigit(wParam & 0xff))
253 {
254 break;
255 }
256 else
257 {
258 return 0;
259 }
260 }
261 else
262 {
263 break;
264 }
265 }
266
267 return CallWindowProc(oldwndproc, hwnd, uMsg, wParam, lParam);
268 }
269
270
271 INT_PTR CALLBACK modify_dword_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
272 {
273 WNDPROC oldproc;
274 TCHAR* valueData;
275 HWND hwndValue;
276 int len;
277 TCHAR ValueString[32];
278 LPTSTR Remainder;
279 DWORD Base;
280 DWORD Value;
281
282 switch(uMsg) {
283 case WM_INITDIALOG:
284 dwordEditMode = EDIT_MODE_HEX;
285
286 /* subclass the edit control */
287 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
288 oldproc = (WNDPROC)GetWindowLongPtr(hwndValue, GWL_WNDPROC);
289 SetWindowLongPtr(hwndValue, GWL_USERDATA, (DWORD_PTR)oldproc);
290 SetWindowLongPtr(hwndValue, GWL_WNDPROC, (DWORD_PTR)DwordEditSubclassProc);
291
292 if(editValueName && _tcscmp(editValueName, _T("")))
293 {
294 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
295 }
296 else
297 {
298 TCHAR buffer[255];
299 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
300 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
301 }
302 CheckRadioButton (hwndDlg, IDC_FORMAT_HEX, IDC_FORMAT_DEC, IDC_FORMAT_HEX);
303 _stprintf (ValueString, _T("%lx"), dwordValueData);
304 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
305 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
306 return FALSE;
307
308 case WM_COMMAND:
309 switch (LOWORD(wParam))
310 {
311 case IDC_FORMAT_HEX:
312 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_DEC)
313 {
314 dwordEditMode = EDIT_MODE_HEX;
315 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
316 {
317 if ((len = GetWindowTextLength(hwndValue)))
318 {
319 if (!GetWindowText(hwndValue, ValueString, 32))
320 {
321 Value = 0;
322 }
323 else
324 {
325 Value = _tcstoul (ValueString, &Remainder, 10);
326 }
327 }
328 else
329 {
330 Value = 0;
331 }
332 }
333 _stprintf (ValueString, _T("%lx"), Value);
334 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
335 return TRUE;
336 }
337 break;
338
339 case IDC_FORMAT_DEC:
340 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_HEX)
341 {
342 dwordEditMode = EDIT_MODE_DEC;
343 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
344 {
345 if ((len = GetWindowTextLength(hwndValue)))
346 {
347 if (!GetWindowText(hwndValue, ValueString, 32))
348 {
349 Value = 0;
350 }
351 else
352 {
353 Value = _tcstoul (ValueString, &Remainder, 16);
354 }
355 }
356 else
357 {
358 Value = 0;
359 }
360 }
361 _stprintf (ValueString, _T("%lu"), Value);
362 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
363 return TRUE;
364 }
365 break;
366
367 case IDOK:
368 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
369 {
370 if ((len = GetWindowTextLength(hwndValue)))
371 {
372 if (!GetWindowText(hwndValue, ValueString, 32))
373 {
374 EndDialog(hwndDlg, IDCANCEL);
375 return TRUE;
376 }
377
378 Base = (dwordEditMode == EDIT_MODE_HEX) ? 16 : 10;
379 dwordValueData = _tcstoul (ValueString, &Remainder, Base);
380 }
381 else
382 {
383 EndDialog(hwndDlg, IDCANCEL);
384 return TRUE;
385 }
386 }
387 EndDialog(hwndDlg, IDOK);
388 return TRUE;
389
390 case IDCANCEL:
391 EndDialog(hwndDlg, IDCANCEL);
392 return TRUE;
393 }
394 }
395 return FALSE;
396 }
397
398
399 INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
400 {
401 PVOID valueData;
402 HWND hwndValue;
403 int len;
404
405 switch(uMsg) {
406 case WM_INITDIALOG:
407 if(editValueName && _tcscmp(editValueName, _T("")))
408 {
409 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
410 }
411 else
412 {
413 TCHAR buffer[255];
414 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
415 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
416 }
417 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
418 HexEdit_LoadBuffer(hwndValue, binValueData, valueDataLen);
419 /* reset the hex edit control's font */
420 SendMessage(hwndValue, WM_SETFONT, 0, 0);
421 SetFocus(hwndValue);
422 return FALSE;
423 case WM_COMMAND:
424 switch (LOWORD(wParam))
425 {
426 case IDOK:
427 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
428 {
429 len = HexEdit_GetBufferSize(hwndValue);
430 if (len != valueDataLen && len > 0)
431 {
432 binValueData = HeapReAlloc(GetProcessHeap(), 0, binValueData, len);
433 }
434 if (len > 0)
435 {
436 HexEdit_CopyBuffer(hwndValue, binValueData, len);
437 }
438 valueDataLen = len;
439 }
440 EndDialog(hwndDlg, IDOK);
441 break;
442 case IDCANCEL:
443 EndDialog(hwndDlg, IDCANCEL);
444 return TRUE;
445 }
446 }
447 return FALSE;
448 }
449
450
451 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCTSTR valueName, BOOL EditBin)
452 {
453 DWORD type;
454 LONG lRet;
455 BOOL result = FALSE;
456
457 if (!hKey)
458 return FALSE;
459
460 editValueName = valueName;
461
462 lRet = RegQueryValueEx(hKey, valueName, 0, &type, 0, &valueDataLen);
463 if (lRet != ERROR_SUCCESS && (!_tcscmp(valueName, _T("")) || valueName == NULL))
464 {
465 lRet = ERROR_SUCCESS; /* Allow editing of (Default) values which don't exist */
466 type = REG_SZ;
467 valueDataLen = 0;
468 stringValueData = NULL;
469 binValueData = NULL;
470 }
471
472 if (lRet != ERROR_SUCCESS)
473 {
474 error(hwnd, IDS_BAD_VALUE, valueName);
475 goto done;
476 }
477
478 if (EditBin == FALSE && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
479 {
480 if (valueDataLen > 0)
481 {
482 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
483 {
484 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
485 goto done;
486 }
487 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
488 if (lRet != ERROR_SUCCESS)
489 {
490 error(hwnd, IDS_BAD_VALUE, valueName);
491 goto done;
492 }
493 }
494 else
495 {
496 stringValueData = NULL;
497 }
498
499 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING), hwnd, modify_string_dlgproc) == IDOK)
500 {
501 if (stringValueData)
502 {
503 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)stringValueData, (_tcslen(stringValueData) + 1) * sizeof(TCHAR));
504 }
505 else
506 {
507 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
508 }
509 if (lRet == ERROR_SUCCESS)
510 result = TRUE;
511 }
512 }
513 else if (EditBin == FALSE && type == REG_MULTI_SZ)
514 {
515 if (valueDataLen > 0)
516 {
517 DWORD llen, listlen, nl_len;
518 LPTSTR src, lines = NULL;
519
520 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
521 {
522 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
523 goto done;
524 }
525 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
526 if (lRet != ERROR_SUCCESS)
527 {
528 error(hwnd, IDS_BAD_VALUE, valueName);
529 goto done;
530 }
531
532 /* convert \0 to \r\n */
533 src = stringValueData;
534 nl_len = _tcslen(_T("\r\n")) * sizeof(TCHAR);
535 listlen = sizeof(TCHAR);
536 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listlen + sizeof(TCHAR));
537 while(*src != _T('\0'))
538 {
539 llen = _tcslen(src);
540 if(llen == 0)
541 break;
542 listlen += (llen * sizeof(TCHAR)) + nl_len;
543 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, listlen);
544 _tcscat(lines, src);
545 _tcscat(lines, _T("\r\n"));
546 src += llen + 1;
547 }
548 HeapFree(GetProcessHeap(), 0, stringValueData);
549 stringValueData = lines;
550 }
551 else
552 {
553 stringValueData = NULL;
554 }
555
556 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_MULTI_STRING), hwnd, modify_multi_string_dlgproc) == IDOK)
557 {
558 if (stringValueData)
559 {
560 /* convert \r\n to \0 */
561 BOOL EmptyLines = FALSE;
562 LPTSTR src, lines, nl;
563 DWORD linechars, buflen, c_nl, dest;
564
565 src = stringValueData;
566 buflen = sizeof(TCHAR);
567 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(TCHAR));
568 c_nl = _tcslen(_T("\r\n"));
569 dest = 0;
570 while(*src != _T('\0'))
571 {
572 if((nl = _tcsstr(src, _T("\r\n"))))
573 {
574 linechars = nl - src;
575 if(nl == src)
576 {
577 EmptyLines = TRUE;
578 src = nl + c_nl;
579 continue;
580 }
581 }
582 else
583 {
584 linechars = _tcslen(src);
585 }
586 if(linechars > 0)
587 {
588 buflen += ((linechars + 1) * sizeof(TCHAR));
589 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, buflen);
590 memcpy((lines + dest), src, linechars * sizeof(TCHAR));
591 dest += linechars;
592 lines[dest++] = _T('\0');
593 }
594 else
595 {
596 EmptyLines = TRUE;
597 }
598 src += linechars + (nl != NULL ? c_nl : 0);
599 }
600 lines[++dest] = _T('\0');
601
602 if(EmptyLines)
603 {
604 warning(hwnd, IDS_MULTI_SZ_EMPTY_STRING);
605 }
606
607 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)lines, buflen);
608 HeapFree(GetProcessHeap(), 0, lines);
609 }
610 else
611 {
612 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
613 }
614 if (lRet == ERROR_SUCCESS)
615 result = TRUE;
616 }
617 }
618 else if (EditBin == FALSE && type == REG_DWORD)
619 {
620 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)&dwordValueData, &valueDataLen);
621 if (lRet != ERROR_SUCCESS)
622 {
623 error(hwnd, IDS_BAD_VALUE, valueName);
624 goto done;
625 }
626
627 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dword_dlgproc) == IDOK)
628 {
629 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)&dwordValueData, sizeof(DWORD));
630 if (lRet == ERROR_SUCCESS)
631 result = TRUE;
632 }
633 }
634 else if (EditBin == TRUE || type == REG_NONE || type == REG_BINARY)
635 {
636 #ifndef UNICODE
637 LPWSTR u_valuename;
638 int len_vname = lstrlen(valueName);
639
640 if(len_vname > 0)
641 {
642 if(!(u_valuename = HeapAlloc(GetProcessHeap(), 0, (len_vname + 1) * sizeof(WCHAR))))
643 {
644 error(hwnd, IDS_TOO_BIG_VALUE, len_vname);
645 goto done;
646 }
647 /* convert the ansi value name to an unicode string */
648 MultiByteToWideChar(CP_ACP, 0, valueName, -1, u_valuename, len_vname + 1);
649 valueDataLen *= sizeof(WCHAR);
650 }
651 else
652 u_valuename = L"";
653 #endif
654 if(valueDataLen > 0)
655 {
656 if(!(binValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
657 {
658 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
659 goto done;
660 }
661
662 /* force to use the unicode version, so editing strings in binary mode is correct */
663 lRet = RegQueryValueExW(hKey,
664 #ifndef UNICODE
665 u_valuename,
666 #else
667 valueName,
668 #endif
669 0, 0, (LPBYTE)binValueData, &valueDataLen);
670 if (lRet != ERROR_SUCCESS)
671 {
672 HeapFree(GetProcessHeap(), 0, binValueData);
673 #ifndef UNICODE
674 if(len_vname > 0)
675 HeapFree(GetProcessHeap(), 0, u_valuename);
676 #endif
677 error(hwnd, IDS_BAD_VALUE, valueName);
678 goto done;
679 }
680 }
681 else
682 {
683 binValueData = NULL;
684 }
685
686 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_BIN_DATA), hwnd, modify_binary_dlgproc) == IDOK)
687 {
688 /* force to use the unicode version, so editing strings in binary mode is correct */
689 lRet = RegSetValueExW(hKey,
690 #ifndef UNICODE
691 u_valuename,
692 #else
693 valueName,
694 #endif
695 0, type, (LPBYTE)binValueData, valueDataLen);
696 if (lRet == ERROR_SUCCESS)
697 result = TRUE;
698 }
699 if(binValueData != NULL)
700 HeapFree(GetProcessHeap(), 0, binValueData);
701 #ifndef UNICODE
702 if(len_vname > 0)
703 HeapFree(GetProcessHeap(), 0, u_valuename);
704 #endif
705 }
706 else
707 {
708 error(hwnd, IDS_UNSUPPORTED_TYPE, type);
709 }
710
711 done:
712 if (stringValueData)
713 HeapFree(GetProcessHeap(), 0, stringValueData);
714 stringValueData = NULL;
715
716 return result;
717 }