Copy wininet to branch
[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 HWND hwndValue;
275 int len;
276 TCHAR ValueString[32];
277 LPTSTR Remainder;
278 DWORD Base;
279 DWORD Value;
280
281 switch(uMsg) {
282 case WM_INITDIALOG:
283 dwordEditMode = EDIT_MODE_HEX;
284
285 /* subclass the edit control */
286 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
287 oldproc = (WNDPROC)GetWindowLongPtr(hwndValue, GWL_WNDPROC);
288 SetWindowLongPtr(hwndValue, GWL_USERDATA, (DWORD_PTR)oldproc);
289 SetWindowLongPtr(hwndValue, GWL_WNDPROC, (DWORD_PTR)DwordEditSubclassProc);
290
291 if(editValueName && _tcscmp(editValueName, _T("")))
292 {
293 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
294 }
295 else
296 {
297 TCHAR buffer[255];
298 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
299 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
300 }
301 CheckRadioButton (hwndDlg, IDC_FORMAT_HEX, IDC_FORMAT_DEC, IDC_FORMAT_HEX);
302 _stprintf (ValueString, _T("%lx"), dwordValueData);
303 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
304 SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
305 return FALSE;
306
307 case WM_COMMAND:
308 switch (LOWORD(wParam))
309 {
310 case IDC_FORMAT_HEX:
311 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_DEC)
312 {
313 dwordEditMode = EDIT_MODE_HEX;
314 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
315 {
316 if ((len = GetWindowTextLength(hwndValue)))
317 {
318 if (!GetWindowText(hwndValue, ValueString, 32))
319 {
320 Value = 0;
321 }
322 else
323 {
324 Value = _tcstoul (ValueString, &Remainder, 10);
325 }
326 }
327 else
328 {
329 Value = 0;
330 }
331 }
332 _stprintf (ValueString, _T("%lx"), Value);
333 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
334 return TRUE;
335 }
336 break;
337
338 case IDC_FORMAT_DEC:
339 if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_HEX)
340 {
341 dwordEditMode = EDIT_MODE_DEC;
342 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
343 {
344 if ((len = GetWindowTextLength(hwndValue)))
345 {
346 if (!GetWindowText(hwndValue, ValueString, 32))
347 {
348 Value = 0;
349 }
350 else
351 {
352 Value = _tcstoul (ValueString, &Remainder, 16);
353 }
354 }
355 else
356 {
357 Value = 0;
358 }
359 }
360 _stprintf (ValueString, _T("%lu"), Value);
361 SetDlgItemText(hwndDlg, IDC_VALUE_DATA, ValueString);
362 return TRUE;
363 }
364 break;
365
366 case IDOK:
367 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
368 {
369 if ((len = GetWindowTextLength(hwndValue)))
370 {
371 if (!GetWindowText(hwndValue, ValueString, 32))
372 {
373 EndDialog(hwndDlg, IDCANCEL);
374 return TRUE;
375 }
376
377 Base = (dwordEditMode == EDIT_MODE_HEX) ? 16 : 10;
378 dwordValueData = _tcstoul (ValueString, &Remainder, Base);
379 }
380 else
381 {
382 EndDialog(hwndDlg, IDCANCEL);
383 return TRUE;
384 }
385 }
386 EndDialog(hwndDlg, IDOK);
387 return TRUE;
388
389 case IDCANCEL:
390 EndDialog(hwndDlg, IDCANCEL);
391 return TRUE;
392 }
393 }
394 return FALSE;
395 }
396
397
398 INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
399 {
400 HWND hwndValue;
401 int len;
402
403 switch(uMsg) {
404 case WM_INITDIALOG:
405 if(editValueName && _tcscmp(editValueName, _T("")))
406 {
407 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, editValueName);
408 }
409 else
410 {
411 TCHAR buffer[255];
412 LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
413 SetDlgItemText(hwndDlg, IDC_VALUE_NAME, buffer);
414 }
415 hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
416 HexEdit_LoadBuffer(hwndValue, binValueData, valueDataLen);
417 /* reset the hex edit control's font */
418 SendMessage(hwndValue, WM_SETFONT, 0, 0);
419 SetFocus(hwndValue);
420 return FALSE;
421 case WM_COMMAND:
422 switch (LOWORD(wParam))
423 {
424 case IDOK:
425 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
426 {
427 len = HexEdit_GetBufferSize(hwndValue);
428 if (len != valueDataLen && len > 0)
429 {
430 binValueData = HeapReAlloc(GetProcessHeap(), 0, binValueData, len);
431 }
432 if (len > 0)
433 {
434 HexEdit_CopyBuffer(hwndValue, binValueData, len);
435 }
436 valueDataLen = len;
437 }
438 EndDialog(hwndDlg, IDOK);
439 break;
440 case IDCANCEL:
441 EndDialog(hwndDlg, IDCANCEL);
442 return TRUE;
443 }
444 }
445 return FALSE;
446 }
447
448
449 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCTSTR valueName, BOOL EditBin)
450 {
451 DWORD type;
452 LONG lRet;
453 BOOL result = FALSE;
454
455 if (!hKey)
456 return FALSE;
457
458 editValueName = valueName;
459
460 lRet = RegQueryValueEx(hKey, valueName, 0, &type, 0, &valueDataLen);
461 if (lRet != ERROR_SUCCESS && (!_tcscmp(valueName, _T("")) || valueName == NULL))
462 {
463 lRet = ERROR_SUCCESS; /* Allow editing of (Default) values which don't exist */
464 type = REG_SZ;
465 valueDataLen = 0;
466 stringValueData = NULL;
467 binValueData = NULL;
468 }
469
470 if (lRet != ERROR_SUCCESS)
471 {
472 error(hwnd, IDS_BAD_VALUE, valueName);
473 goto done;
474 }
475
476 if (EditBin == FALSE && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
477 {
478 if (valueDataLen > 0)
479 {
480 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
481 {
482 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
483 goto done;
484 }
485 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
486 if (lRet != ERROR_SUCCESS)
487 {
488 error(hwnd, IDS_BAD_VALUE, valueName);
489 goto done;
490 }
491 }
492 else
493 {
494 stringValueData = NULL;
495 }
496
497 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_STRING), hwnd, modify_string_dlgproc) == IDOK)
498 {
499 if (stringValueData)
500 {
501 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)stringValueData, (_tcslen(stringValueData) + 1) * sizeof(TCHAR));
502 }
503 else
504 {
505 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
506 }
507 if (lRet == ERROR_SUCCESS)
508 result = TRUE;
509 }
510 }
511 else if (EditBin == FALSE && type == REG_MULTI_SZ)
512 {
513 if (valueDataLen > 0)
514 {
515 DWORD llen, listlen, nl_len;
516 LPTSTR src, lines = NULL;
517
518 if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
519 {
520 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
521 goto done;
522 }
523 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
524 if (lRet != ERROR_SUCCESS)
525 {
526 error(hwnd, IDS_BAD_VALUE, valueName);
527 goto done;
528 }
529
530 /* convert \0 to \r\n */
531 src = stringValueData;
532 nl_len = _tcslen(_T("\r\n")) * sizeof(TCHAR);
533 listlen = sizeof(TCHAR);
534 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listlen + sizeof(TCHAR));
535 while(*src != _T('\0'))
536 {
537 llen = _tcslen(src);
538 if(llen == 0)
539 break;
540 listlen += (llen * sizeof(TCHAR)) + nl_len;
541 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, listlen);
542 _tcscat(lines, src);
543 _tcscat(lines, _T("\r\n"));
544 src += llen + 1;
545 }
546 HeapFree(GetProcessHeap(), 0, stringValueData);
547 stringValueData = lines;
548 }
549 else
550 {
551 stringValueData = NULL;
552 }
553
554 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_MULTI_STRING), hwnd, modify_multi_string_dlgproc) == IDOK)
555 {
556 if (stringValueData)
557 {
558 /* convert \r\n to \0 */
559 BOOL EmptyLines = FALSE;
560 LPTSTR src, lines, nl;
561 DWORD linechars, buflen, c_nl, dest;
562
563 src = stringValueData;
564 buflen = sizeof(TCHAR);
565 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(TCHAR));
566 c_nl = _tcslen(_T("\r\n"));
567 dest = 0;
568 while(*src != _T('\0'))
569 {
570 if((nl = _tcsstr(src, _T("\r\n"))))
571 {
572 linechars = nl - src;
573 if(nl == src)
574 {
575 EmptyLines = TRUE;
576 src = nl + c_nl;
577 continue;
578 }
579 }
580 else
581 {
582 linechars = _tcslen(src);
583 }
584 if(linechars > 0)
585 {
586 buflen += ((linechars + 1) * sizeof(TCHAR));
587 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, buflen);
588 memcpy((lines + dest), src, linechars * sizeof(TCHAR));
589 dest += linechars;
590 lines[dest++] = _T('\0');
591 }
592 else
593 {
594 EmptyLines = TRUE;
595 }
596 src += linechars + (nl != NULL ? c_nl : 0);
597 }
598 lines[++dest] = _T('\0');
599
600 if(EmptyLines)
601 {
602 warning(hwnd, IDS_MULTI_SZ_EMPTY_STRING);
603 }
604
605 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)lines, buflen);
606 HeapFree(GetProcessHeap(), 0, lines);
607 }
608 else
609 {
610 lRet = RegSetValueEx(hKey, valueName, 0, type, NULL, 0);
611 }
612 if (lRet == ERROR_SUCCESS)
613 result = TRUE;
614 }
615 }
616 else if (EditBin == FALSE && type == REG_DWORD)
617 {
618 lRet = RegQueryValueEx(hKey, valueName, 0, 0, (LPBYTE)&dwordValueData, &valueDataLen);
619 if (lRet != ERROR_SUCCESS)
620 {
621 error(hwnd, IDS_BAD_VALUE, valueName);
622 goto done;
623 }
624
625 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dword_dlgproc) == IDOK)
626 {
627 lRet = RegSetValueEx(hKey, valueName, 0, type, (LPBYTE)&dwordValueData, sizeof(DWORD));
628 if (lRet == ERROR_SUCCESS)
629 result = TRUE;
630 }
631 }
632 else if (EditBin == TRUE || type == REG_NONE || type == REG_BINARY)
633 {
634 #ifndef UNICODE
635 LPWSTR u_valuename;
636 int len_vname = lstrlen(valueName);
637
638 if(len_vname > 0)
639 {
640 if(!(u_valuename = HeapAlloc(GetProcessHeap(), 0, (len_vname + 1) * sizeof(WCHAR))))
641 {
642 error(hwnd, IDS_TOO_BIG_VALUE, len_vname);
643 goto done;
644 }
645 /* convert the ansi value name to an unicode string */
646 MultiByteToWideChar(CP_ACP, 0, valueName, -1, u_valuename, len_vname + 1);
647 valueDataLen *= sizeof(WCHAR);
648 }
649 else
650 u_valuename = L"";
651 #endif
652 if(valueDataLen > 0)
653 {
654 if(!(binValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
655 {
656 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
657 goto done;
658 }
659
660 /* force to use the unicode version, so editing strings in binary mode is correct */
661 lRet = RegQueryValueExW(hKey,
662 #ifndef UNICODE
663 u_valuename,
664 #else
665 valueName,
666 #endif
667 0, 0, (LPBYTE)binValueData, &valueDataLen);
668 if (lRet != ERROR_SUCCESS)
669 {
670 HeapFree(GetProcessHeap(), 0, binValueData);
671 #ifndef UNICODE
672 if(len_vname > 0)
673 HeapFree(GetProcessHeap(), 0, u_valuename);
674 #endif
675 error(hwnd, IDS_BAD_VALUE, valueName);
676 goto done;
677 }
678 }
679 else
680 {
681 binValueData = NULL;
682 }
683
684 if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_BIN_DATA), hwnd, modify_binary_dlgproc) == IDOK)
685 {
686 /* force to use the unicode version, so editing strings in binary mode is correct */
687 lRet = RegSetValueExW(hKey,
688 #ifndef UNICODE
689 u_valuename,
690 #else
691 valueName,
692 #endif
693 0, type, (LPBYTE)binValueData, valueDataLen);
694 if (lRet == ERROR_SUCCESS)
695 result = TRUE;
696 }
697 if(binValueData != NULL)
698 HeapFree(GetProcessHeap(), 0, binValueData);
699 #ifndef UNICODE
700 if(len_vname > 0)
701 HeapFree(GetProcessHeap(), 0, u_valuename);
702 #endif
703 }
704 else
705 {
706 error(hwnd, IDS_UNSUPPORTED_TYPE, type);
707 }
708
709 done:
710 if (stringValueData)
711 HeapFree(GetProcessHeap(), 0, stringValueData);
712 stringValueData = NULL;
713
714 return result;
715 }