xref: /reactos/base/applications/regedit/edit.c (revision 0622ce17)
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "regedit.h"
22 
23 #define NTOS_MODE_USER
24 #include <ndk/cmtypes.h>
25 
26 typedef enum _EDIT_MODE
27 {
28     EDIT_MODE_DEC,
29     EDIT_MODE_HEX
30 } EDIT_MODE;
31 
32 
33 static const WCHAR* editValueName;
34 static WCHAR* stringValueData;
35 static PVOID binValueData;
36 static DWORD dwordValueData;
37 static PCM_RESOURCE_LIST resourceValueData;
38 static INT fullResourceIndex = -1;
39 static DWORD valueDataLen;
40 static EDIT_MODE dwordEditMode = EDIT_MODE_HEX;
41 
42 void error(HWND hwnd, INT resId, ...)
43 {
44     va_list ap;
45     WCHAR title[256];
46     WCHAR errfmt[1024];
47     WCHAR errstr[1024];
48     HINSTANCE hInstance;
49 
50     hInstance = GetModuleHandle(0);
51 
52     if (!LoadStringW(hInstance, IDS_ERROR, title, COUNT_OF(title)))
53         wcscpy(title, L"Error");
54 
55     if (!LoadStringW(hInstance, resId, errfmt, COUNT_OF(errfmt)))
56         wcscpy(errfmt, L"Unknown error string!");
57 
58     va_start(ap, resId);
59     _vsnwprintf(errstr, COUNT_OF(errstr), errfmt, ap);
60     va_end(ap);
61 
62     MessageBoxW(hwnd, errstr, title, MB_OK | MB_ICONERROR);
63 }
64 
65 static void error_code_messagebox(HWND hwnd, DWORD error_code)
66 {
67     WCHAR title[256];
68     if (!LoadStringW(hInst, IDS_ERROR, title, COUNT_OF(title)))
69         wcscpy(title, L"Error");
70     ErrorMessageBox(hwnd, title, error_code);
71 }
72 
73 void warning(HWND hwnd, INT resId, ...)
74 {
75     va_list ap;
76     WCHAR title[256];
77     WCHAR errfmt[1024];
78     WCHAR errstr[1024];
79     HINSTANCE hInstance;
80 
81     hInstance = GetModuleHandle(0);
82 
83     if (!LoadStringW(hInstance, IDS_WARNING, title, COUNT_OF(title)))
84         wcscpy(title, L"Warning");
85 
86     if (!LoadStringW(hInstance, resId, errfmt, COUNT_OF(errfmt)))
87         wcscpy(errfmt, L"Unknown error string!");
88 
89     va_start(ap, resId);
90     _vsnwprintf(errstr, COUNT_OF(errstr), errfmt, ap);
91     va_end(ap);
92 
93     MessageBoxW(hwnd, errstr, title, MB_OK | MB_ICONSTOP);
94 }
95 
96 INT_PTR CALLBACK modify_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
97 {
98     WCHAR* valueData;
99     HWND hwndValue;
100     int len;
101 
102     UNREFERENCED_PARAMETER(lParam);
103 
104     switch(uMsg)
105     {
106     case WM_INITDIALOG:
107         if (editValueName && wcscmp(editValueName, L""))
108         {
109             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
110         }
111         else
112         {
113             WCHAR buffer[255];
114             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, COUNT_OF(buffer));
115             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
116         }
117         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, stringValueData);
118         SendMessage(GetDlgItem(hwndDlg, IDC_VALUE_DATA), EM_SETSEL, 0, -1);
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(WCHAR))))
132                         {
133                             stringValueData = valueData;
134                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
135                                 *stringValueData = 0;
136                         }
137                     }
138                     else
139                     {
140                         if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
141                         {
142                             stringValueData = valueData;
143                             if (!GetWindowTextW(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     WCHAR* valueData;
168     HWND hwndValue;
169     int len;
170 
171     UNREFERENCED_PARAMETER(lParam);
172 
173     switch(uMsg)
174     {
175     case WM_INITDIALOG:
176         if (editValueName && wcscmp(editValueName, L""))
177         {
178             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
179         }
180         else
181         {
182             WCHAR buffer[255];
183             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, COUNT_OF(buffer));
184             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
185         }
186         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, stringValueData);
187         SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
188         return FALSE;
189     case WM_COMMAND:
190         switch (LOWORD(wParam))
191         {
192         case IDOK:
193             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
194             {
195                 if ((len = GetWindowTextLength(hwndValue)))
196                 {
197                     if (stringValueData)
198                     {
199                         if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(WCHAR))))
200                         {
201                             stringValueData = valueData;
202                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
203                                 *stringValueData = 0;
204                         }
205                     }
206                     else
207                     {
208                         if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
209                         {
210                             stringValueData = valueData;
211                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
212                                 *stringValueData = 0;
213                         }
214                     }
215                 }
216                 else
217                 {
218                     if (stringValueData)
219                         *stringValueData = 0;
220                 }
221             }
222             EndDialog(hwndDlg, IDOK);
223             break;
224         case IDCANCEL:
225             EndDialog(hwndDlg, IDCANCEL);
226             return TRUE;
227         }
228     }
229     return FALSE;
230 }
231 
232 
233 LRESULT CALLBACK DwordEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
234 {
235     WNDPROC oldwndproc;
236 
237     oldwndproc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
238 
239     switch (uMsg)
240     {
241     case WM_CHAR:
242         if (dwordEditMode == EDIT_MODE_DEC)
243         {
244             if (isdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
245             {
246                 break;
247             }
248             else
249             {
250                 return 0;
251             }
252         }
253         else if (dwordEditMode == EDIT_MODE_HEX)
254         {
255             if (isxdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
256             {
257                 break;
258             }
259             else
260             {
261                 return 0;
262             }
263         }
264         else
265         {
266             break;
267         }
268     }
269 
270     return CallWindowProcW(oldwndproc, hwnd, uMsg, wParam, lParam);
271 }
272 
273 
274 INT_PTR CALLBACK modify_dword_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
275 {
276     WNDPROC oldproc;
277     HWND hwndValue;
278     WCHAR ValueString[32];
279     LPWSTR Remainder;
280     DWORD Base;
281     DWORD Value = 0;
282 
283     UNREFERENCED_PARAMETER(lParam);
284 
285     switch(uMsg)
286     {
287     case WM_INITDIALOG:
288         dwordEditMode = EDIT_MODE_HEX;
289 
290         /* subclass the edit control */
291         hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
292         oldproc = (WNDPROC)GetWindowLongPtr(hwndValue, GWLP_WNDPROC);
293         SetWindowLongPtr(hwndValue, GWLP_USERDATA, (DWORD_PTR)oldproc);
294         SetWindowLongPtr(hwndValue, GWLP_WNDPROC, (DWORD_PTR)DwordEditSubclassProc);
295 
296         if (editValueName && wcscmp(editValueName, L""))
297         {
298             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
299         }
300         else
301         {
302             WCHAR buffer[255];
303             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, COUNT_OF(buffer));
304             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
305         }
306         CheckRadioButton (hwndDlg, IDC_FORMAT_HEX, IDC_FORMAT_DEC, IDC_FORMAT_HEX);
307         swprintf(ValueString, L"%lx", dwordValueData);
308         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
309         SendMessage(GetDlgItem(hwndDlg, IDC_VALUE_DATA), EM_SETSEL, 0, -1);
310         SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
311         return FALSE;
312 
313     case WM_COMMAND:
314         switch (LOWORD(wParam))
315         {
316         case IDC_FORMAT_HEX:
317             if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_DEC)
318             {
319                 dwordEditMode = EDIT_MODE_HEX;
320                 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
321                 {
322                     if (GetWindowTextLength(hwndValue))
323                     {
324                         if (GetWindowTextW(hwndValue, ValueString, 32))
325                         {
326                             Value = wcstoul (ValueString, &Remainder, 10);
327                         }
328                     }
329                 }
330                 swprintf(ValueString, L"%lx", Value);
331                 SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
332                 return TRUE;
333             }
334             break;
335 
336         case IDC_FORMAT_DEC:
337             if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_HEX)
338             {
339                 dwordEditMode = EDIT_MODE_DEC;
340                 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
341                 {
342                     if (GetWindowTextLength(hwndValue))
343                     {
344                         if (GetWindowTextW(hwndValue, ValueString, 32))
345                         {
346                             Value = wcstoul (ValueString, &Remainder, 16);
347                         }
348                     }
349                 }
350                 swprintf(ValueString, L"%lu", Value);
351                 SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
352                 return TRUE;
353             }
354             break;
355 
356         case IDOK:
357             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
358             {
359                 if (GetWindowTextLength(hwndValue))
360                 {
361                     if (!GetWindowTextW(hwndValue, ValueString, 32))
362                     {
363                         EndDialog(hwndDlg, IDCANCEL);
364                         return TRUE;
365                     }
366 
367                     Base = (dwordEditMode == EDIT_MODE_HEX) ? 16 : 10;
368                     dwordValueData = wcstoul (ValueString, &Remainder, Base);
369                 }
370                 else
371                 {
372                     EndDialog(hwndDlg, IDCANCEL);
373                     return TRUE;
374                 }
375             }
376             EndDialog(hwndDlg, IDOK);
377             return TRUE;
378 
379         case IDCANCEL:
380             EndDialog(hwndDlg, IDCANCEL);
381             return TRUE;
382         }
383     }
384     return FALSE;
385 }
386 
387 
388 INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
389 {
390     HWND hwndValue;
391     UINT len;
392 
393     UNREFERENCED_PARAMETER(lParam);
394 
395     switch(uMsg)
396     {
397     case WM_INITDIALOG:
398         if (editValueName && wcscmp(editValueName, L""))
399         {
400             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
401         }
402         else
403         {
404             WCHAR buffer[255];
405             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, COUNT_OF(buffer));
406             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
407         }
408         hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
409         HexEdit_LoadBuffer(hwndValue, binValueData, valueDataLen);
410         /* reset the hex edit control's font */
411         SendMessageW(hwndValue, WM_SETFONT, 0, 0);
412         SetFocus(hwndValue);
413         return FALSE;
414     case WM_COMMAND:
415         switch (LOWORD(wParam))
416         {
417         case IDOK:
418             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
419             {
420                 len = (UINT) HexEdit_GetBufferSize(hwndValue);
421                 if (len > 0 && binValueData)
422                     binValueData = HeapReAlloc(GetProcessHeap(), 0, binValueData, len);
423                 else
424                     binValueData = HeapAlloc(GetProcessHeap(), 0, len + 1);
425                 HexEdit_CopyBuffer(hwndValue, binValueData, len);
426                 valueDataLen = len;
427             }
428             EndDialog(hwndDlg, IDOK);
429             break;
430         case IDCANCEL:
431             EndDialog(hwndDlg, IDCANCEL);
432             return TRUE;
433         }
434     }
435     return FALSE;
436 }
437 
438 
439 static BOOL CreateResourceColumns(HWND hwnd)
440 {
441     WCHAR szText[80];
442     RECT rc;
443     LVCOLUMN lvC;
444     HWND hwndLV;
445     INT width;
446 
447     /* Create columns. */
448     lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
449     lvC.pszText = szText;
450     lvC.fmt = LVCFMT_LEFT;
451 
452     hwndLV = GetDlgItem(hwnd, IDC_DMA_LIST);
453     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
454     GetClientRect(hwndLV, &rc);
455 
456     /* Load the column labels from the resource file. */
457     lvC.iSubItem = 0;
458     lvC.cx = (rc.right - rc.left) / 2;
459     LoadStringW(hInst, IDS_DMA_CHANNEL, szText, COUNT_OF(szText));
460     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
461         return FALSE;
462 
463     lvC.iSubItem = 1;
464     lvC.cx = (rc.right - rc.left) - lvC.cx;
465     LoadStringW(hInst, IDS_DMA_PORT, szText, COUNT_OF(szText));
466     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
467         return FALSE;
468 
469 
470     /* Interrupt list */
471     hwndLV = GetDlgItem(hwnd, IDC_IRQ_LIST);
472     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
473     GetClientRect(hwndLV, &rc);
474     width = (rc.right - rc.left) / 4;
475 
476     /* Load the column labels from the resource file. */
477     lvC.iSubItem = 0;
478     lvC.cx = width;
479     LoadStringW(hInst, IDS_INTERRUPT_VECTOR, szText, COUNT_OF(szText));
480     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
481         return FALSE;
482 
483     lvC.iSubItem = 1;
484     LoadStringW(hInst, IDS_INTERRUPT_LEVEL, szText, COUNT_OF(szText));
485     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
486         return FALSE;
487 
488     lvC.iSubItem = 2;
489     LoadStringW(hInst, IDS_INTERRUPT_AFFINITY, szText, COUNT_OF(szText));
490     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
491         return FALSE;
492 
493     lvC.iSubItem = 3;
494     lvC.cx = (rc.right - rc.left) - 3 * width;
495     LoadStringW(hInst, IDS_INTERRUPT_TYPE, szText, COUNT_OF(szText));
496     if (ListView_InsertColumn(hwndLV, 3, &lvC) == -1)
497         return FALSE;
498 
499 
500     /* Memory list */
501     hwndLV = GetDlgItem(hwnd, IDC_MEMORY_LIST);
502     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
503     GetClientRect(hwndLV, &rc);
504     width = (rc.right - rc.left) / 3;
505 
506     /* Load the column labels from the resource file. */
507     lvC.iSubItem = 0;
508     lvC.cx = width;
509     LoadStringW(hInst, IDS_MEMORY_ADDRESS, szText, COUNT_OF(szText));
510     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
511         return FALSE;
512 
513     lvC.iSubItem = 1;
514     LoadStringW(hInst, IDS_MEMORY_LENGTH, szText, COUNT_OF(szText));
515     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
516         return FALSE;
517 
518     lvC.iSubItem = 2;
519     lvC.cx = (rc.right - rc.left) - 2 * width;
520     LoadStringW(hInst, IDS_MEMORY_ACCESS, szText, COUNT_OF(szText));
521     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
522         return FALSE;
523 
524 
525     /* Port list */
526     hwndLV = GetDlgItem(hwnd, IDC_PORT_LIST);
527     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
528     GetClientRect(hwndLV, &rc);
529     width = (rc.right - rc.left) / 3;
530 
531     /* Load the column labels from the resource file. */
532     lvC.iSubItem = 0;
533     lvC.cx = width;
534     LoadStringW(hInst, IDS_PORT_ADDRESS, szText, COUNT_OF(szText));
535     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
536         return FALSE;
537 
538     lvC.iSubItem = 1;
539     LoadStringW(hInst, IDS_PORT_LENGTH, szText, COUNT_OF(szText));
540     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
541         return FALSE;
542 
543     lvC.iSubItem = 2;
544     lvC.cx = (rc.right - rc.left) - 2 * width;
545     LoadStringW(hInst, IDS_PORT_ACCESS, szText, COUNT_OF(szText));
546     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
547         return FALSE;
548 
549     /* Device specific list */
550     hwndLV = GetDlgItem(hwnd, IDC_DEVICE_LIST);
551     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
552     GetClientRect(hwndLV, &rc);
553     width = (rc.right - rc.left) / 3;
554 
555     /* Load the column labels from the resource file. */
556     lvC.iSubItem = 0;
557     lvC.cx = width;
558     LoadStringW(hInst, IDS_SPECIFIC_RESERVED1, szText, COUNT_OF(szText));
559     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
560         return FALSE;
561 
562     lvC.iSubItem = 1;
563     LoadStringW(hInst, IDS_SPECIFIC_RESERVED2, szText, COUNT_OF(szText));
564     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
565         return FALSE;
566 
567     lvC.iSubItem = 2;
568     lvC.cx = (rc.right - rc.left) - 2 * width;
569     LoadStringW(hInst, IDS_SPECIFIC_DATASIZE, szText, COUNT_OF(szText));
570     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
571         return FALSE;
572 
573     return TRUE;
574 }
575 
576 static VOID
577 GetInterfaceType(INTERFACE_TYPE InterfaceType,
578                  LPWSTR pBuffer,
579                  DWORD dwLength)
580 {
581 //    LPWSTR lpInterfaceType;
582 
583     switch (InterfaceType)
584     {
585         case InterfaceTypeUndefined:
586             LoadStringW(hInst, IDS_BUS_UNDEFINED, pBuffer, dwLength);
587 //            lpInterfaceType = L"Undefined";
588             break;
589         case Internal:
590             LoadStringW(hInst, IDS_BUS_INTERNAL, pBuffer, dwLength);
591 //            lpInterfaceType = L"Internal";
592             break;
593         case Isa:
594             LoadStringW(hInst, IDS_BUS_ISA, pBuffer, dwLength);
595 //            lpInterfaceType = L"Isa";
596             break;
597         case Eisa:
598             LoadStringW(hInst, IDS_BUS_EISA, pBuffer, dwLength);
599 //            lpInterfaceType = L"Eisa";
600             break;
601         case MicroChannel:
602             LoadStringW(hInst, IDS_BUS_MICROCHANNEL, pBuffer, dwLength);
603 //            lpInterfaceType = L"MicroChannel";
604             break;
605         case TurboChannel:
606             LoadStringW(hInst, IDS_BUS_TURBOCHANNEL, pBuffer, dwLength);
607 //            lpInterfaceType = L"TurboChannel";
608             break;
609         case PCIBus:
610             LoadStringW(hInst, IDS_BUS_PCIBUS, pBuffer, dwLength);
611 //            lpInterfaceType = L"PCIBus";
612             break;
613         case VMEBus:
614             LoadStringW(hInst, IDS_BUS_VMEBUS, pBuffer, dwLength);
615 //            lpInterfaceType = L"VMEBus";
616             break;
617         case NuBus:
618             LoadStringW(hInst, IDS_BUS_NUBUS, pBuffer, dwLength);
619 //            lpInterfaceType = L"NuBus";
620             break;
621         case PCMCIABus:
622             LoadStringW(hInst, IDS_BUS_PCMCIABUS, pBuffer, dwLength);
623 //            lpInterfaceType = L"PCMCIABus";
624             break;
625         case CBus:
626             LoadStringW(hInst, IDS_BUS_CBUS, pBuffer, dwLength);
627 //            lpInterfaceType = L"CBus";
628             break;
629         case MPIBus:
630             LoadStringW(hInst, IDS_BUS_MPIBUS, pBuffer, dwLength);
631 //            lpInterfaceType = L"MPIBus";
632             break;
633         case MPSABus:
634             LoadStringW(hInst, IDS_BUS_MPSABUS, pBuffer, dwLength);
635 //            lpInterfaceType = L"MPSABus";
636             break;
637         case ProcessorInternal:
638             LoadStringW(hInst, IDS_BUS_PROCESSORINTERNAL, pBuffer, dwLength);
639 //            lpInterfaceType = L"ProcessorInternal";
640             break;
641         case InternalPowerBus:
642             LoadStringW(hInst, IDS_BUS_INTERNALPOWERBUS, pBuffer, dwLength);
643 //            lpInterfaceType = L"InternalPowerBus";
644             break;
645         case PNPISABus:
646             LoadStringW(hInst, IDS_BUS_PNPISABUS, pBuffer, dwLength);
647 //            lpInterfaceType = L"PNPISABus";
648             break;
649         case PNPBus:
650             LoadStringW(hInst, IDS_BUS_PNPBUS, pBuffer, dwLength);
651 //            lpInterfaceType = L"PNPBus";
652             break;
653         default:
654             LoadStringW(hInst, IDS_BUS_UNKNOWNTYPE, pBuffer, dwLength);
655 //            lpInterfaceType = L"Unknown interface type";
656             break;
657     }
658 
659 //    wcscpy(pBuffer, lpInterfaceType);
660 }
661 
662 
663 static VOID
664 ParseResources(HWND hwnd)
665 {
666     PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
667     PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
668     PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
669     ULONG i;
670     HWND hwndLV;
671 
672     WCHAR buffer[80];
673     LVITEMW item;
674     INT iItem;
675 
676     pFullDescriptor = &resourceValueData->List[0];
677     for (i = 0; i < fullResourceIndex; i++)
678     {
679         pFullDescriptor = (PVOID)(pFullDescriptor->PartialResourceList.PartialDescriptors +
680                                   pFullDescriptor->PartialResourceList.Count);
681     }
682     pPartialResourceList = &pFullDescriptor->PartialResourceList;
683 
684     /* Interface type */
685     GetInterfaceType(pFullDescriptor->InterfaceType, buffer, 80);
686     SetDlgItemTextW(hwnd, IDC_INTERFACETYPE, buffer);
687 
688     /* Busnumber */
689     SetDlgItemInt(hwnd, IDC_BUSNUMBER, (UINT)pFullDescriptor->BusNumber, FALSE);
690 
691     /* Version */
692     SetDlgItemInt(hwnd, IDC_VERSION, (UINT)pPartialResourceList->Version, FALSE);
693 
694     /* Revision */
695     SetDlgItemInt(hwnd, IDC_REVISION, (UINT)pPartialResourceList->Revision, FALSE);
696 
697     for (i = 0; i < pPartialResourceList->Count; i++)
698     {
699         pDescriptor = &pPartialResourceList->PartialDescriptors[i];
700 
701         switch (pDescriptor->Type)
702         {
703             case CmResourceTypePort:
704                 hwndLV = GetDlgItem(hwnd, IDC_PORT_LIST);
705 
706 #ifdef _M_AMD64
707                 wsprintf(buffer, L"0x%016I64x", pDescriptor->u.Port.Start.QuadPart);
708 #else
709                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.Port.Start.u.LowPart);
710 #endif
711 
712                 item.mask = LVIF_TEXT | LVIF_PARAM;
713                 item.iItem = 1000;
714                 item.iSubItem = 0;
715                 item.state = 0;
716                 item.stateMask = 0;
717                 item.pszText = buffer;
718                 item.cchTextMax = (int)wcslen(item.pszText);
719                 item.lParam = (LPARAM)pDescriptor;
720 
721                 iItem = ListView_InsertItem(hwndLV, &item);
722                 if (iItem != -1)
723                 {
724                     wsprintf(buffer, L"0x%lx", pDescriptor->u.Port.Length);
725                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
726 
727                     if (pDescriptor->Flags & CM_RESOURCE_PORT_IO)
728                         LoadStringW(hInst, IDS_PORT_PORT_IO, buffer, COUNT_OF(buffer));
729                     else
730                         LoadStringW(hInst, IDS_PORT_MEMORY_IO, buffer, COUNT_OF(buffer));
731                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
732                 }
733                 break;
734 
735             case CmResourceTypeInterrupt:
736                 hwndLV = GetDlgItem(hwnd, IDC_IRQ_LIST);
737 
738                 wsprintf(buffer, L"%lu", pDescriptor->u.Interrupt.Vector);
739 
740                 item.mask = LVIF_TEXT | LVIF_PARAM;
741                 item.iItem = 1000;
742                 item.iSubItem = 0;
743                 item.state = 0;
744                 item.stateMask = 0;
745                 item.pszText = buffer;
746                 item.cchTextMax = (int)wcslen(item.pszText);
747                 item.lParam = (LPARAM)pDescriptor;
748 
749                 iItem = ListView_InsertItem(hwndLV, &item);
750                 if (iItem != -1)
751                 {
752                     wsprintf(buffer, L"%lu", pDescriptor->u.Interrupt.Level);
753                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
754 
755                     wsprintf(buffer, L"0x%08lx", pDescriptor->u.Interrupt.Affinity);
756                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
757 
758                     if (pDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
759                         LoadStringW(hInst, IDS_INTERRUPT_EDGE_SENSITIVE, buffer, COUNT_OF(buffer));
760                     else
761                         LoadStringW(hInst, IDS_INTERRUPT_LEVEL_SENSITIVE, buffer, COUNT_OF(buffer));
762 
763                     ListView_SetItemText(hwndLV, iItem, 3, buffer);
764                 }
765                 break;
766 
767             case CmResourceTypeMemory:
768                 hwndLV = GetDlgItem(hwnd, IDC_MEMORY_LIST);
769 
770 #ifdef _M_AMD64
771                 wsprintf(buffer, L"0x%016I64x", pDescriptor->u.Memory.Start.QuadPart);
772 #else
773                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.Memory.Start.u.LowPart);
774 #endif
775 
776                 item.mask = LVIF_TEXT | LVIF_PARAM;
777                 item.iItem = 1000;
778                 item.iSubItem = 0;
779                 item.state = 0;
780                 item.stateMask = 0;
781                 item.pszText = buffer;
782                 item.cchTextMax = (int)wcslen(item.pszText);
783                 item.lParam = (LPARAM)pDescriptor;
784 
785                 iItem = ListView_InsertItem(hwndLV, &item);
786                 if (iItem != -1)
787                 {
788                     wsprintf(buffer, L"0x%lx", pDescriptor->u.Memory.Length);
789                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
790 
791                     switch (pDescriptor->Flags & (CM_RESOURCE_MEMORY_READ_ONLY | CM_RESOURCE_MEMORY_WRITE_ONLY))
792                     {
793                         case CM_RESOURCE_MEMORY_READ_ONLY:
794                             LoadStringW(hInst, IDS_MEMORY_READ_ONLY, buffer, COUNT_OF(buffer));
795                             break;
796 
797                         case CM_RESOURCE_MEMORY_WRITE_ONLY:
798                             LoadStringW(hInst, IDS_MEMORY_WRITE_ONLY, buffer, COUNT_OF(buffer));
799                             break;
800 
801                         default:
802                             LoadStringW(hInst, IDS_MEMORY_READ_WRITE, buffer, COUNT_OF(buffer));
803                             break;
804                     }
805 
806                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
807                 }
808                 break;
809 
810             case CmResourceTypeDma:
811                 hwndLV = GetDlgItem(hwnd, IDC_DMA_LIST);
812 
813                 wsprintf(buffer, L"%lu", pDescriptor->u.Dma.Channel);
814 
815                 item.mask = LVIF_TEXT | LVIF_PARAM;
816                 item.iItem = 1000;
817                 item.iSubItem = 0;
818                 item.state = 0;
819                 item.stateMask = 0;
820                 item.pszText = buffer;
821                 item.cchTextMax = (int)wcslen(item.pszText);
822                 item.lParam = (LPARAM)pDescriptor;
823 
824                 iItem = ListView_InsertItem(hwndLV, &item);
825                 if (iItem != -1)
826                 {
827                     wsprintf(buffer, L"%lu", pDescriptor->u.Dma.Port);
828                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
829                 }
830                 break;
831 
832             case CmResourceTypeDeviceSpecific:
833                 hwndLV = GetDlgItem(hwnd, IDC_DEVICE_LIST);
834 
835                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.DeviceSpecificData.Reserved1);
836 
837                 item.mask = LVIF_TEXT | LVIF_PARAM;
838                 item.iItem = 1000;
839                 item.iSubItem = 0;
840                 item.state = 0;
841                 item.stateMask = 0;
842                 item.pszText = buffer;
843                 item.cchTextMax = (int)wcslen(item.pszText);
844                 item.lParam = (LPARAM)pDescriptor;
845 
846                 iItem = ListView_InsertItem(hwndLV, &item);
847                 if (iItem != -1)
848                 {
849                     wsprintf(buffer, L"0x%08lx", pDescriptor->u.DeviceSpecificData.Reserved2);
850                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
851 
852                     wsprintf(buffer, L"0x%lx", pDescriptor->u.DeviceSpecificData.DataSize);
853                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
854                 }
855                 break;
856         }
857     }
858 }
859 
860 
861 static BOOL
862 OnResourceNotify(HWND hwndDlg, NMHDR *phdr)
863 {
864     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
865 
866     switch (phdr->idFrom)
867     {
868         case IDC_PORT_LIST:
869         case IDC_MEMORY_LIST:
870         case IDC_DMA_LIST:
871         case IDC_IRQ_LIST:
872         case IDC_DEVICE_LIST:
873             switch(phdr->code)
874             {
875                 case NM_CLICK:
876                     if (lpnmlv->iItem != -1)
877                     {
878                         PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
879                         LVITEMW item;
880 
881                         item.mask = LVIF_PARAM;
882                         item.iItem = lpnmlv->iItem;
883                         item.iSubItem = 0;
884 
885                         if (ListView_GetItem(phdr->hwndFrom, &item))
886                         {
887                             pDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)item.lParam;
888 
889                             EnableWindow(GetDlgItem(hwndDlg, IDC_UNDETERMINED),
890                                          (pDescriptor->ShareDisposition == CmResourceShareUndetermined));
891 
892                             EnableWindow(GetDlgItem(hwndDlg, IDC_SHARED),
893                                          (pDescriptor->ShareDisposition == CmResourceShareShared));
894 
895                             EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_EXCLUSIVE),
896                                          (pDescriptor->ShareDisposition == CmResourceShareDeviceExclusive));
897 
898                             EnableWindow(GetDlgItem(hwndDlg, IDC_DRIVER_EXCLUSIVE),
899                                          (pDescriptor->ShareDisposition == CmResourceShareDriverExclusive));
900                         }
901                     }
902                     else
903                     {
904                         EnableWindow(GetDlgItem(hwndDlg, IDC_UNDETERMINED), FALSE);
905                         EnableWindow(GetDlgItem(hwndDlg, IDC_SHARED), FALSE);
906                         EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_EXCLUSIVE), FALSE);
907                         EnableWindow(GetDlgItem(hwndDlg, IDC_DRIVER_EXCLUSIVE), FALSE);
908                     }
909                     break;
910             }
911             break;
912     }
913 
914     return FALSE;
915 }
916 
917 
918 static INT_PTR CALLBACK modify_resource_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
919 {
920     UNREFERENCED_PARAMETER(lParam);
921 
922     switch(uMsg)
923     {
924     case WM_INITDIALOG:
925         CreateResourceColumns(hwndDlg);
926         ParseResources(hwndDlg);
927         return FALSE;
928 
929     case WM_NOTIFY:
930         return OnResourceNotify(hwndDlg, (NMHDR *)lParam);
931 
932     case WM_COMMAND:
933         switch (LOWORD(wParam))
934         {
935         case IDOK:
936             EndDialog(hwndDlg, IDOK);
937             break;
938         case IDCANCEL:
939             EndDialog(hwndDlg, IDCANCEL);
940             return TRUE;
941         }
942     }
943     return FALSE;
944 }
945 
946 static BOOL CreateResourceListColumns(HWND hWndListView)
947 {
948     WCHAR szText[80];
949     RECT rc;
950     LVCOLUMN lvC;
951 
952     ListView_SetExtendedListViewStyle(hWndListView, LVS_EX_FULLROWSELECT);
953 
954     GetClientRect(hWndListView, &rc);
955 
956     /* Create columns. */
957     lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
958     lvC.pszText = szText;
959     lvC.fmt = LVCFMT_LEFT;
960 
961     /* Load the column labels from the resource file. */
962     lvC.iSubItem = 0;
963     lvC.cx = (rc.right - rc.left) / 2;
964     LoadStringW(hInst, IDS_BUSNUMBER, szText, COUNT_OF(szText));
965     if (ListView_InsertColumn(hWndListView, 0, &lvC) == -1)
966         return FALSE;
967 
968     lvC.iSubItem = 1;
969     lvC.cx = (rc.right - rc.left) - lvC.cx;
970     LoadStringW(hInst, IDS_INTERFACE, szText, COUNT_OF(szText));
971     if (ListView_InsertColumn(hWndListView, 1, &lvC) == -1)
972         return FALSE;
973 
974     return TRUE;
975 }
976 
977 static VOID AddFullResourcesToList(HWND hwnd)
978 {
979     PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
980     WCHAR buffer[80];
981     LVITEMW item;
982     ULONG i;
983     INT iItem;
984 
985     pFullDescriptor = &resourceValueData->List[0];
986     for (i = 0; i < resourceValueData->Count; i++)
987     {
988         wsprintf(buffer, L"%lu", pFullDescriptor->BusNumber);
989 
990         item.mask = LVIF_TEXT;
991         item.iItem = i;
992         item.iSubItem = 0;
993         item.state = 0;
994         item.stateMask = 0;
995         item.pszText = buffer;
996         item.cchTextMax = (int)wcslen(item.pszText);
997 
998         iItem = ListView_InsertItem(hwnd, &item);
999         if (iItem != -1)
1000         {
1001             GetInterfaceType(pFullDescriptor->InterfaceType, buffer, 80);
1002             ListView_SetItemText(hwnd, iItem, 1, buffer);
1003         }
1004         pFullDescriptor = (PVOID)(pFullDescriptor->PartialResourceList.PartialDescriptors +
1005                                   pFullDescriptor->PartialResourceList.Count);
1006     }
1007 }
1008 
1009 static BOOL
1010 OnResourceListNotify(HWND hwndDlg, NMHDR *phdr)
1011 {
1012     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
1013 
1014     switch (phdr->idFrom)
1015     {
1016         case IDC_RESOURCE_LIST:
1017             switch(phdr->code)
1018             {
1019                 case NM_CLICK:
1020                     fullResourceIndex = lpnmlv->iItem;
1021                     EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW_RESOURCE), (lpnmlv->iItem != -1));
1022                     break;
1023 
1024                 case NM_DBLCLK:
1025                     if (lpnmlv->iItem != -1)
1026                     {
1027                         fullResourceIndex = lpnmlv->iItem;
1028                         DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwndDlg, modify_resource_dlgproc);
1029                     }
1030                     break;
1031             }
1032             break;
1033     }
1034 
1035     return FALSE;
1036 }
1037 
1038 
1039 static INT_PTR CALLBACK modify_resource_list_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1040 {
1041     UNREFERENCED_PARAMETER(lParam);
1042 
1043     switch(uMsg)
1044     {
1045     case WM_INITDIALOG:
1046         CreateResourceListColumns(GetDlgItem(hwndDlg, IDC_RESOURCE_LIST));
1047         AddFullResourcesToList(GetDlgItem(hwndDlg, IDC_RESOURCE_LIST));
1048         return FALSE;
1049 
1050     case WM_NOTIFY:
1051         return OnResourceListNotify(hwndDlg, (NMHDR *)lParam);
1052 
1053     case WM_COMMAND:
1054         switch (LOWORD(wParam))
1055         {
1056         case IDC_SHOW_RESOURCE:
1057             if (fullResourceIndex != -1)
1058                 DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwndDlg, modify_resource_dlgproc);
1059             break;
1060         case IDOK:
1061             EndDialog(hwndDlg, IDOK);
1062             break;
1063         case IDCANCEL:
1064             EndDialog(hwndDlg, IDCANCEL);
1065             return TRUE;
1066         }
1067     }
1068     return FALSE;
1069 }
1070 
1071 
1072 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCWSTR valueName, BOOL EditBin)
1073 {
1074     DWORD type;
1075     LONG lRet;
1076     BOOL result = FALSE;
1077 
1078     if (!hKey)
1079         return FALSE;
1080 
1081     editValueName = valueName;
1082 
1083     lRet = RegQueryValueExW(hKey, valueName, 0, &type, 0, &valueDataLen);
1084     if (lRet != ERROR_SUCCESS && (valueName == NULL || !valueName[0]))
1085     {
1086         lRet = ERROR_SUCCESS; /* Allow editing of (Default) values which don't exist */
1087         type = REG_SZ;
1088         valueDataLen = 0;
1089         stringValueData = NULL;
1090         binValueData = NULL;
1091     }
1092 
1093     if (lRet != ERROR_SUCCESS)
1094     {
1095         error(hwnd, IDS_BAD_VALUE, valueName);
1096         goto done;
1097     }
1098 
1099     if (EditBin == FALSE && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
1100     {
1101         if (valueDataLen > 0)
1102         {
1103             if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
1104             {
1105                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1106                 goto done;
1107             }
1108             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
1109             if (lRet != ERROR_SUCCESS)
1110             {
1111                 error(hwnd, IDS_BAD_VALUE, valueName);
1112                 goto done;
1113             }
1114         }
1115         else
1116         {
1117             stringValueData = NULL;
1118         }
1119 
1120         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_STRING), hwnd, modify_string_dlgproc) == IDOK)
1121         {
1122             if (stringValueData)
1123             {
1124                 lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)stringValueData, (DWORD) (wcslen(stringValueData) + 1) * sizeof(WCHAR));
1125             }
1126             else
1127             {
1128                 lRet = RegSetValueExW(hKey, valueName, 0, type, NULL, 0);
1129             }
1130             if (lRet == ERROR_SUCCESS)
1131                 result = TRUE;
1132         }
1133     }
1134     else if (EditBin == FALSE && type == REG_MULTI_SZ)
1135     {
1136         if (valueDataLen > 0)
1137         {
1138             size_t llen, listlen, nl_len;
1139             LPWSTR src, lines = NULL;
1140 
1141             if (!(stringValueData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, valueDataLen + sizeof(WCHAR))))
1142             {
1143                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1144                 goto done;
1145             }
1146             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
1147             if (lRet != ERROR_SUCCESS)
1148             {
1149                 error(hwnd, IDS_BAD_VALUE, valueName);
1150                 goto done;
1151             }
1152 
1153             /* convert \0 to \r\n */
1154             src = stringValueData;
1155             nl_len = wcslen(L"\r\n") * sizeof(WCHAR);
1156             listlen = sizeof(WCHAR);
1157             lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listlen + sizeof(WCHAR));
1158             while(*src != L'\0')
1159             {
1160                 llen = wcslen(src);
1161                 if(llen == 0)
1162                     break;
1163                 listlen += (llen * sizeof(WCHAR)) + nl_len;
1164                 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, listlen);
1165                 wcscat(lines, src);
1166                 wcscat(lines, L"\r\n");
1167                 src += llen + 1;
1168             }
1169             HeapFree(GetProcessHeap(), 0, stringValueData);
1170             stringValueData = lines;
1171         }
1172         else
1173         {
1174             stringValueData = NULL;
1175         }
1176 
1177         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_MULTI_STRING), hwnd, modify_multi_string_dlgproc) == IDOK)
1178         {
1179             if (stringValueData)
1180             {
1181                 /* convert \r\n to \0 */
1182                 BOOL EmptyLines = FALSE;
1183                 LPWSTR src, lines, nl;
1184                 size_t linechars, buflen, c_nl, dest;
1185 
1186                 src = stringValueData;
1187                 buflen = sizeof(WCHAR);
1188                 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(WCHAR));
1189                 c_nl = wcslen(L"\r\n");
1190                 dest = 0;
1191                 while(*src != L'\0')
1192                 {
1193                     if((nl = wcsstr(src, L"\r\n")))
1194                     {
1195                         linechars = nl - src;
1196                         if(nl == src)
1197                         {
1198                             EmptyLines = TRUE;
1199                             src = nl + c_nl;
1200                             continue;
1201                         }
1202                     }
1203                     else
1204                     {
1205                         linechars = wcslen(src);
1206                     }
1207                     if(linechars > 0)
1208                     {
1209                         buflen += ((linechars + 1) * sizeof(WCHAR));
1210                         lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, buflen);
1211                         memcpy((lines + dest), src, linechars * sizeof(WCHAR));
1212                         dest += linechars;
1213                         lines[dest++] = L'\0';
1214                     }
1215                     else
1216                     {
1217                         EmptyLines = TRUE;
1218                     }
1219                     src += linechars + (nl != NULL ? c_nl : 0);
1220                 }
1221                 lines[++dest] = L'\0';
1222 
1223                 if(EmptyLines)
1224                 {
1225                     warning(hwnd, IDS_MULTI_SZ_EMPTY_STRING);
1226                 }
1227 
1228                 lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)lines, (DWORD) buflen);
1229                 HeapFree(GetProcessHeap(), 0, lines);
1230             }
1231             else
1232             {
1233                 lRet = RegSetValueExW(hKey, valueName, 0, type, NULL, 0);
1234             }
1235             if (lRet == ERROR_SUCCESS)
1236                 result = TRUE;
1237         }
1238     }
1239     else if (EditBin == FALSE && type == REG_DWORD)
1240     {
1241         lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)&dwordValueData, &valueDataLen);
1242         if (lRet != ERROR_SUCCESS)
1243         {
1244             error(hwnd, IDS_BAD_VALUE, valueName);
1245             goto done;
1246         }
1247 
1248         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_DWORD), hwnd, modify_dword_dlgproc) == IDOK)
1249         {
1250             lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)&dwordValueData, sizeof(DWORD));
1251             if (lRet == ERROR_SUCCESS)
1252                 result = TRUE;
1253         }
1254     }
1255     else if (EditBin == FALSE && type == REG_RESOURCE_LIST)
1256     {
1257         if (valueDataLen > 0)
1258         {
1259             resourceValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen);
1260             if (resourceValueData == NULL)
1261             {
1262                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1263                 goto done;
1264             }
1265 
1266             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)resourceValueData, &valueDataLen);
1267             if (lRet != ERROR_SUCCESS)
1268             {
1269                 error(hwnd, IDS_BAD_VALUE, valueName);
1270                 goto done;
1271             }
1272         }
1273         else
1274         {
1275             resourceValueData = NULL;
1276         }
1277 
1278         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE_LIST), hwnd, modify_resource_list_dlgproc) == IDOK)
1279         {
1280         }
1281     }
1282     else if (EditBin == FALSE && type == REG_FULL_RESOURCE_DESCRIPTOR)
1283     {
1284         if (valueDataLen > 0)
1285         {
1286             resourceValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + sizeof(ULONG));
1287             if (resourceValueData == NULL)
1288             {
1289                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1290                 goto done;
1291             }
1292 
1293             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)&resourceValueData->List[0], &valueDataLen);
1294             if (lRet != ERROR_SUCCESS)
1295             {
1296                 error(hwnd, IDS_BAD_VALUE, valueName);
1297                 goto done;
1298             }
1299 
1300             resourceValueData->Count = 1;
1301             fullResourceIndex = 0;
1302         }
1303         else
1304         {
1305             resourceValueData = NULL;
1306         }
1307 
1308         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwnd, modify_resource_dlgproc) == IDOK)
1309         {
1310         }
1311     }
1312     else if ((EditBin != FALSE) || (type == REG_NONE) || (type == REG_BINARY))
1313     {
1314         if(valueDataLen > 0)
1315         {
1316             if(!(binValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + 1)))
1317             {
1318                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1319                 goto done;
1320             }
1321 
1322             /* Use the unicode version, so editing strings in binary mode is correct */
1323             lRet = RegQueryValueExW(hKey, valueName,
1324                                     0, 0, (LPBYTE)binValueData, &valueDataLen);
1325             if (lRet != ERROR_SUCCESS)
1326             {
1327                 HeapFree(GetProcessHeap(), 0, binValueData);
1328                 error(hwnd, IDS_BAD_VALUE, valueName);
1329                 goto done;
1330             }
1331         }
1332         else
1333         {
1334             binValueData = NULL;
1335         }
1336 
1337         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_BIN_DATA), hwnd, modify_binary_dlgproc) == IDOK)
1338         {
1339             /* Use the unicode version, so editing strings in binary mode is correct */
1340             lRet = RegSetValueExW(hKey, valueName,
1341                                   0, type, (LPBYTE)binValueData, valueDataLen);
1342             if (lRet == ERROR_SUCCESS)
1343                 result = TRUE;
1344         }
1345         if(binValueData != NULL)
1346             HeapFree(GetProcessHeap(), 0, binValueData);
1347     }
1348     else
1349     {
1350         error(hwnd, IDS_UNSUPPORTED_TYPE, type);
1351     }
1352 
1353 done:
1354     if (resourceValueData)
1355         HeapFree(GetProcessHeap(), 0, resourceValueData);
1356     resourceValueData = NULL;
1357 
1358     if (stringValueData)
1359         HeapFree(GetProcessHeap(), 0, stringValueData);
1360     stringValueData = NULL;
1361 
1362     return result;
1363 }
1364 
1365 static LONG CopyKey(HKEY hDestKey, LPCWSTR lpDestSubKey, HKEY hSrcKey, LPCWSTR lpSrcSubKey)
1366 {
1367     LONG lResult;
1368     DWORD dwDisposition;
1369     HKEY hDestSubKey = NULL;
1370     HKEY hSrcSubKey = NULL;
1371     DWORD dwIndex, dwType, cbName, cbData;
1372     WCHAR szSubKey[256];
1373     WCHAR szValueName[256];
1374     BYTE szValueData[512];
1375 
1376     FILETIME ft;
1377 
1378     /* open the source subkey, if specified */
1379     if (lpSrcSubKey)
1380     {
1381         lResult = RegOpenKeyExW(hSrcKey, lpSrcSubKey, 0, KEY_ALL_ACCESS, &hSrcSubKey);
1382         if (lResult)
1383             goto done;
1384         hSrcKey = hSrcSubKey;
1385     }
1386 
1387     /* create the destination subkey */
1388     lResult = RegCreateKeyExW(hDestKey, lpDestSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
1389                              &hDestSubKey, &dwDisposition);
1390     if (lResult)
1391         goto done;
1392 
1393     /* copy all subkeys */
1394     dwIndex = 0;
1395     do
1396     {
1397         cbName = sizeof(szSubKey) / sizeof(szSubKey[0]);
1398         lResult = RegEnumKeyExW(hSrcKey, dwIndex++, szSubKey, &cbName, NULL, NULL, NULL, &ft);
1399         if (lResult == ERROR_SUCCESS)
1400         {
1401             lResult = CopyKey(hDestSubKey, szSubKey, hSrcKey, szSubKey);
1402             if (lResult)
1403                 goto done;
1404         }
1405     }
1406     while(lResult == ERROR_SUCCESS);
1407 
1408     /* copy all subvalues */
1409     dwIndex = 0;
1410     do
1411     {
1412         cbName = sizeof(szValueName) / sizeof(szValueName[0]);
1413         cbData = sizeof(szValueData) / sizeof(szValueData[0]);
1414         lResult = RegEnumValueW(hSrcKey, dwIndex++, szValueName, &cbName, NULL, &dwType, szValueData, &cbData);
1415         if (lResult == ERROR_SUCCESS)
1416         {
1417             lResult = RegSetValueExW(hDestSubKey, szValueName, 0, dwType, szValueData, cbData);
1418             if (lResult)
1419                 goto done;
1420         }
1421     }
1422     while(lResult == ERROR_SUCCESS);
1423 
1424     lResult = ERROR_SUCCESS;
1425 
1426 done:
1427     if (hSrcSubKey)
1428         RegCloseKey(hSrcSubKey);
1429     if (hDestSubKey)
1430         RegCloseKey(hDestSubKey);
1431     if (lResult != ERROR_SUCCESS)
1432         SHDeleteKey(hDestKey, lpDestSubKey);
1433     return lResult;
1434 }
1435 
1436 static LONG MoveKey(HKEY hDestKey, LPCWSTR lpDestSubKey, HKEY hSrcKey, LPCWSTR lpSrcSubKey)
1437 {
1438     LONG lResult;
1439 
1440     if (!lpSrcSubKey)
1441         return ERROR_INVALID_FUNCTION;
1442 
1443     if (_wcsicmp(lpDestSubKey, lpSrcSubKey) == 0)
1444     {
1445         /* Destination name equals source name */
1446         return ERROR_SUCCESS;
1447     }
1448 
1449     lResult = CopyKey(hDestKey, lpDestSubKey, hSrcKey, lpSrcSubKey);
1450     if (lResult == ERROR_SUCCESS)
1451         SHDeleteKey(hSrcKey, lpSrcSubKey);
1452 
1453     return lResult;
1454 }
1455 
1456 BOOL DeleteKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath)
1457 {
1458     WCHAR msg[128], caption[128];
1459     BOOL result = FALSE;
1460     LONG lRet;
1461     HKEY hKey;
1462 
1463     lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ|KEY_SET_VALUE, &hKey);
1464     if (lRet != ERROR_SUCCESS)
1465     {
1466         error_code_messagebox(hwnd, lRet);
1467         return FALSE;
1468     }
1469 
1470     LoadStringW(hInst, IDS_QUERY_DELETE_KEY_CONFIRM, caption, COUNT_OF(caption));
1471     LoadStringW(hInst, IDS_QUERY_DELETE_KEY_ONE, msg, COUNT_OF(msg));
1472 
1473     if (MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) != IDYES)
1474         goto done;
1475 
1476     lRet = SHDeleteKey(hKeyRoot, keyPath);
1477     if (lRet != ERROR_SUCCESS)
1478     {
1479         error(hwnd, IDS_BAD_KEY, keyPath);
1480         goto done;
1481     }
1482     result = TRUE;
1483 
1484 done:
1485     RegCloseKey(hKey);
1486     return result;
1487 }
1488 
1489 LONG RenameKey(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewName)
1490 {
1491     LPCWSTR s;
1492     LPWSTR lpNewSubKey = NULL;
1493     LONG Ret = 0;
1494 
1495     if (!lpSubKey)
1496         return Ret;
1497 
1498     s = wcsrchr(lpSubKey, L'\\');
1499     if (s)
1500     {
1501         s++;
1502         lpNewSubKey = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (s - lpSubKey + wcslen(lpNewName) + 1) * sizeof(WCHAR));
1503         if (lpNewSubKey != NULL)
1504         {
1505             memcpy(lpNewSubKey, lpSubKey, (s - lpSubKey) * sizeof(WCHAR));
1506             wcscpy(lpNewSubKey + (s - lpSubKey), lpNewName);
1507             lpNewName = lpNewSubKey;
1508         }
1509         else
1510             return ERROR_NOT_ENOUGH_MEMORY;
1511     }
1512 
1513     Ret = MoveKey(hKey, lpNewName, hKey, lpSubKey);
1514 
1515     if (lpNewSubKey)
1516     {
1517         HeapFree(GetProcessHeap(), 0, lpNewSubKey);
1518     }
1519     return Ret;
1520 }
1521 
1522 LONG RenameValue(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpDestValue, LPCWSTR lpSrcValue)
1523 {
1524     LONG lResult;
1525     HKEY hSubKey = NULL;
1526     DWORD dwType, cbData;
1527     BYTE data[512];
1528 
1529     if (lpSubKey)
1530     {
1531         lResult = RegOpenKeyW(hKey, lpSubKey, &hSubKey);
1532         if (lResult != ERROR_SUCCESS)
1533             goto done;
1534         hKey = hSubKey;
1535     }
1536 
1537     cbData = sizeof(data);
1538     lResult = RegQueryValueExW(hKey, lpSrcValue, NULL, &dwType, data, &cbData);
1539     if (lResult != ERROR_SUCCESS)
1540         goto done;
1541 
1542     lResult = RegSetValueExW(hKey, lpDestValue, 0, dwType, data, cbData);
1543     if (lResult != ERROR_SUCCESS)
1544         goto done;
1545 
1546     RegDeleteValue(hKey, lpSrcValue);
1547 
1548 done:
1549     if (hSubKey)
1550         RegCloseKey(hSubKey);
1551     return lResult;
1552 }
1553 
1554 LONG QueryStringValue(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR pszBuffer, DWORD dwBufferLen)
1555 {
1556     LONG lResult;
1557     HKEY hSubKey = NULL;
1558     DWORD cbData, dwType;
1559 
1560     if (lpSubKey)
1561     {
1562         lResult = RegOpenKeyW(hKey, lpSubKey, &hSubKey);
1563         if (lResult != ERROR_SUCCESS)
1564             goto done;
1565         hKey = hSubKey;
1566     }
1567 
1568     cbData = (dwBufferLen - 1) * sizeof(*pszBuffer);
1569     lResult = RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (LPBYTE) pszBuffer, &cbData);
1570     if (lResult != ERROR_SUCCESS)
1571         goto done;
1572     if (dwType != REG_SZ)
1573     {
1574         lResult = -1;
1575         goto done;
1576     }
1577 
1578     pszBuffer[cbData / sizeof(*pszBuffer)] = L'\0';
1579 
1580 done:
1581     if (lResult != ERROR_SUCCESS)
1582         pszBuffer[0] = L'\0';
1583     if (hSubKey)
1584         RegCloseKey(hSubKey);
1585     return lResult;
1586 }
1587 
1588 BOOL GetKeyName(LPWSTR pszDest, size_t iDestLength, HKEY hRootKey, LPCWSTR lpSubKey)
1589 {
1590     LPCWSTR pszRootKey;
1591 
1592     if (hRootKey == HKEY_CLASSES_ROOT)
1593         pszRootKey = L"HKEY_CLASSES_ROOT";
1594     else if (hRootKey == HKEY_CURRENT_USER)
1595         pszRootKey = L"HKEY_CURRENT_USER";
1596     else if (hRootKey == HKEY_LOCAL_MACHINE)
1597         pszRootKey = L"HKEY_LOCAL_MACHINE";
1598     else if (hRootKey == HKEY_USERS)
1599         pszRootKey = L"HKEY_USERS";
1600     else if (hRootKey == HKEY_CURRENT_CONFIG)
1601         pszRootKey = L"HKEY_CURRENT_CONFIG";
1602     else if (hRootKey == HKEY_DYN_DATA)
1603         pszRootKey = L"HKEY_DYN_DATA";
1604     else
1605         return FALSE;
1606 
1607     if (lpSubKey[0])
1608         _snwprintf(pszDest, iDestLength, L"%s\\%s", pszRootKey, lpSubKey);
1609     else
1610         _snwprintf(pszDest, iDestLength, L"%s", pszRootKey);
1611     return TRUE;
1612 }
1613