xref: /reactos/base/applications/regedit/edit.c (revision d8d4d8fa)
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 #if defined(NT_PROCESSOR_GROUPS)
27 
28 typedef USHORT IRQ_DEVICE_POLICY, *PIRQ_DEVICE_POLICY;
29 
30 enum _IRQ_DEVICE_POLICY_USHORT {
31   IrqPolicyMachineDefault = 0,
32   IrqPolicyAllCloseProcessors = 1,
33   IrqPolicyOneCloseProcessor = 2,
34   IrqPolicyAllProcessorsInMachine = 3,
35   IrqPolicyAllProcessorsInGroup = 3,
36   IrqPolicySpecifiedProcessors = 4,
37   IrqPolicySpreadMessagesAcrossAllProcessors = 5};
38 
39 #else /* defined(NT_PROCESSOR_GROUPS) */
40 
41 typedef enum _IRQ_DEVICE_POLICY {
42   IrqPolicyMachineDefault = 0,
43   IrqPolicyAllCloseProcessors,
44   IrqPolicyOneCloseProcessor,
45   IrqPolicyAllProcessorsInMachine,
46   IrqPolicySpecifiedProcessors,
47   IrqPolicySpreadMessagesAcrossAllProcessors
48 } IRQ_DEVICE_POLICY, *PIRQ_DEVICE_POLICY;
49 
50 #endif
51 
52 typedef enum _IRQ_PRIORITY {
53   IrqPriorityUndefined = 0,
54   IrqPriorityLow,
55   IrqPriorityNormal,
56   IrqPriorityHigh
57 } IRQ_PRIORITY, *PIRQ_PRIORITY;
58 typedef struct _IO_RESOURCE_DESCRIPTOR {
59   UCHAR Option;
60   UCHAR Type;
61   UCHAR ShareDisposition;
62   UCHAR Spare1;
63   USHORT Flags;
64   USHORT Spare2;
65   union {
66     struct {
67       ULONG Length;
68       ULONG Alignment;
69       PHYSICAL_ADDRESS MinimumAddress;
70       PHYSICAL_ADDRESS MaximumAddress;
71     } Port;
72     struct {
73       ULONG Length;
74       ULONG Alignment;
75       PHYSICAL_ADDRESS MinimumAddress;
76       PHYSICAL_ADDRESS MaximumAddress;
77     } Memory;
78     struct {
79       ULONG MinimumVector;
80       ULONG MaximumVector;
81 #if defined(NT_PROCESSOR_GROUPS)
82       IRQ_DEVICE_POLICY AffinityPolicy;
83       USHORT Group;
84 #else
85       IRQ_DEVICE_POLICY AffinityPolicy;
86 #endif
87       IRQ_PRIORITY PriorityPolicy;
88       KAFFINITY TargetedProcessors;
89     } Interrupt;
90     struct {
91       ULONG MinimumChannel;
92       ULONG MaximumChannel;
93     } Dma;
94     struct {
95       ULONG Length;
96       ULONG Alignment;
97       PHYSICAL_ADDRESS MinimumAddress;
98       PHYSICAL_ADDRESS MaximumAddress;
99     } Generic;
100     struct {
101       ULONG Data[3];
102     } DevicePrivate;
103     struct {
104       ULONG Length;
105       ULONG MinBusNumber;
106       ULONG MaxBusNumber;
107       ULONG Reserved;
108     } BusNumber;
109     struct {
110       ULONG Priority;
111       ULONG Reserved1;
112       ULONG Reserved2;
113     } ConfigData;
114   } u;
115 } IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR;
116 
117 #define IO_RESOURCE_PREFERRED             0x01
118 #define IO_RESOURCE_DEFAULT               0x02
119 #define IO_RESOURCE_ALTERNATIVE           0x08
120 
121 typedef struct _IO_RESOURCE_LIST {
122   USHORT Version;
123   USHORT Revision;
124   ULONG Count;
125   IO_RESOURCE_DESCRIPTOR Descriptors[1];
126 } IO_RESOURCE_LIST, *PIO_RESOURCE_LIST;
127 
128 typedef struct _IO_RESOURCE_REQUIREMENTS_LIST {
129   ULONG ListSize;
130   INTERFACE_TYPE InterfaceType;
131   ULONG BusNumber;
132   ULONG SlotNumber;
133   ULONG Reserved[3];
134   ULONG AlternativeLists;
135   IO_RESOURCE_LIST List[1];
136 } IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST;
137 
138 typedef enum _EDIT_MODE
139 {
140     EDIT_MODE_DEC,
141     EDIT_MODE_HEX
142 } EDIT_MODE;
143 
144 
145 static const WCHAR* editValueName;
146 static WCHAR* stringValueData;
147 static PVOID binValueData;
148 static DWORD dwordValueData;
149 static PCM_RESOURCE_LIST resourceValueData;
150 static INT fullResourceIndex = -1;
151 static DWORD valueDataLen;
152 static PIO_RESOURCE_REQUIREMENTS_LIST requirementsValueData;
153 static INT requirementsIndex = -1;
154 static EDIT_MODE dwordEditMode = EDIT_MODE_HEX;
155 
156 void error(HWND hwnd, INT resId, ...)
157 {
158     va_list ap;
159     WCHAR title[256];
160     WCHAR errfmt[1024];
161     WCHAR errstr[1024];
162     HINSTANCE hInstance;
163 
164     hInstance = GetModuleHandle(0);
165 
166     if (!LoadStringW(hInstance, IDS_ERROR, title, ARRAY_SIZE(title)))
167         StringCbCopyW(title, sizeof(title), L"Error");
168 
169     if (!LoadStringW(hInstance, resId, errfmt, ARRAY_SIZE(errfmt)))
170         StringCbCopyW(errfmt, sizeof(errfmt), L"Unknown error string!");
171 
172     va_start(ap, resId);
173     _vsnwprintf(errstr, ARRAY_SIZE(errstr), errfmt, ap);
174     va_end(ap);
175 
176     MessageBoxW(hwnd, errstr, title, MB_OK | MB_ICONERROR);
177 }
178 
179 static void error_code_messagebox(HWND hwnd, DWORD error_code)
180 {
181     WCHAR title[256];
182     if (!LoadStringW(hInst, IDS_ERROR, title, ARRAY_SIZE(title)))
183         StringCbCopyW(title, sizeof(title), L"Error");
184     ErrorMessageBox(hwnd, title, error_code);
185 }
186 
187 void warning(HWND hwnd, INT resId, ...)
188 {
189     va_list ap;
190     WCHAR title[256];
191     WCHAR errfmt[1024];
192     WCHAR errstr[1024];
193     HINSTANCE hInstance;
194 
195     hInstance = GetModuleHandle(0);
196 
197     if (!LoadStringW(hInstance, IDS_WARNING, title, ARRAY_SIZE(title)))
198         StringCbCopyW(title, sizeof(title), L"Warning");
199 
200     if (!LoadStringW(hInstance, resId, errfmt, ARRAY_SIZE(errfmt)))
201         StringCbCopyW(errfmt, sizeof(errfmt), L"Unknown error string!");
202 
203     va_start(ap, resId);
204     StringCbVPrintfW(errstr, sizeof(errstr), errfmt, ap);
205     va_end(ap);
206 
207     MessageBoxW(hwnd, errstr, title, MB_OK | MB_ICONSTOP);
208 }
209 
210 INT_PTR CALLBACK modify_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
211 {
212     WCHAR* valueData;
213     HWND hwndValue;
214     int len;
215 
216     UNREFERENCED_PARAMETER(lParam);
217 
218     switch(uMsg)
219     {
220     case WM_INITDIALOG:
221         if (editValueName && wcscmp(editValueName, L""))
222         {
223             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
224         }
225         else
226         {
227             WCHAR buffer[255];
228             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, ARRAY_SIZE(buffer));
229             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
230         }
231         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, stringValueData);
232         SendMessage(GetDlgItem(hwndDlg, IDC_VALUE_DATA), EM_SETSEL, 0, -1);
233         SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
234         return FALSE;
235     case WM_COMMAND:
236         switch (LOWORD(wParam))
237         {
238         case IDOK:
239             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
240             {
241                 if ((len = GetWindowTextLength(hwndValue)))
242                 {
243                     if (stringValueData)
244                     {
245                         if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(WCHAR))))
246                         {
247                             stringValueData = valueData;
248                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
249                                 *stringValueData = 0;
250                         }
251                     }
252                     else
253                     {
254                         if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
255                         {
256                             stringValueData = valueData;
257                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
258                                 *stringValueData = 0;
259                         }
260                     }
261                 }
262                 else
263                 {
264                     if (stringValueData)
265                         *stringValueData = 0;
266                 }
267             }
268             EndDialog(hwndDlg, IDOK);
269             break;
270         case IDCANCEL:
271             EndDialog(hwndDlg, IDCANCEL);
272             return TRUE;
273         }
274     }
275     return FALSE;
276 }
277 
278 
279 INT_PTR CALLBACK modify_multi_string_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
280 {
281     WCHAR* valueData;
282     HWND hwndValue;
283     int len;
284 
285     UNREFERENCED_PARAMETER(lParam);
286 
287     switch(uMsg)
288     {
289     case WM_INITDIALOG:
290         if (editValueName && wcscmp(editValueName, L""))
291         {
292             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
293         }
294         else
295         {
296             WCHAR buffer[255];
297             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, ARRAY_SIZE(buffer));
298             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
299         }
300         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, stringValueData);
301         SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
302         return FALSE;
303     case WM_COMMAND:
304         switch (LOWORD(wParam))
305         {
306         case IDOK:
307             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
308             {
309                 if ((len = GetWindowTextLength(hwndValue)))
310                 {
311                     if (stringValueData)
312                     {
313                         if ((valueData = HeapReAlloc(GetProcessHeap(), 0, stringValueData, (len + 1) * sizeof(WCHAR))))
314                         {
315                             stringValueData = valueData;
316                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
317                                 *stringValueData = 0;
318                         }
319                     }
320                     else
321                     {
322                         if ((valueData = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
323                         {
324                             stringValueData = valueData;
325                             if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
326                                 *stringValueData = 0;
327                         }
328                     }
329                 }
330                 else
331                 {
332                     if (stringValueData)
333                         *stringValueData = 0;
334                 }
335             }
336             EndDialog(hwndDlg, IDOK);
337             break;
338         case IDCANCEL:
339             EndDialog(hwndDlg, IDCANCEL);
340             return TRUE;
341         }
342     }
343     return FALSE;
344 }
345 
346 
347 LRESULT CALLBACK DwordEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
348 {
349     WNDPROC oldwndproc;
350 
351     oldwndproc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
352 
353     switch (uMsg)
354     {
355     case WM_CHAR:
356         if (dwordEditMode == EDIT_MODE_DEC)
357         {
358             if (isdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
359             {
360                 break;
361             }
362             else
363             {
364                 return 0;
365             }
366         }
367         else if (dwordEditMode == EDIT_MODE_HEX)
368         {
369             if (isxdigit((int) wParam & 0xff) || iscntrl((int) wParam & 0xff))
370             {
371                 break;
372             }
373             else
374             {
375                 return 0;
376             }
377         }
378         else
379         {
380             break;
381         }
382     }
383 
384     return CallWindowProcW(oldwndproc, hwnd, uMsg, wParam, lParam);
385 }
386 
387 
388 INT_PTR CALLBACK modify_dword_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
389 {
390     WNDPROC oldproc;
391     HWND hwndValue;
392     WCHAR ValueString[32];
393     LPWSTR Remainder;
394     DWORD Base;
395     DWORD Value = 0;
396 
397     UNREFERENCED_PARAMETER(lParam);
398 
399     switch(uMsg)
400     {
401     case WM_INITDIALOG:
402         dwordEditMode = EDIT_MODE_HEX;
403 
404         /* subclass the edit control */
405         hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
406         oldproc = (WNDPROC)GetWindowLongPtr(hwndValue, GWLP_WNDPROC);
407         SetWindowLongPtr(hwndValue, GWLP_USERDATA, (DWORD_PTR)oldproc);
408         SetWindowLongPtr(hwndValue, GWLP_WNDPROC, (DWORD_PTR)DwordEditSubclassProc);
409 
410         if (editValueName && wcscmp(editValueName, L""))
411         {
412             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
413         }
414         else
415         {
416             WCHAR buffer[255];
417             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, ARRAY_SIZE(buffer));
418             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
419         }
420         CheckRadioButton (hwndDlg, IDC_FORMAT_HEX, IDC_FORMAT_DEC, IDC_FORMAT_HEX);
421         StringCbPrintfW(ValueString, sizeof(ValueString), L"%lx", dwordValueData);
422         SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
423         SendMessage(GetDlgItem(hwndDlg, IDC_VALUE_DATA), EM_SETSEL, 0, -1);
424         SetFocus(GetDlgItem(hwndDlg, IDC_VALUE_DATA));
425         return FALSE;
426 
427     case WM_COMMAND:
428         switch (LOWORD(wParam))
429         {
430         case IDC_FORMAT_HEX:
431             if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_DEC)
432             {
433                 dwordEditMode = EDIT_MODE_HEX;
434                 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
435                 {
436                     if (GetWindowTextLength(hwndValue))
437                     {
438                         if (GetWindowTextW(hwndValue, ValueString, 32))
439                         {
440                             Value = wcstoul (ValueString, &Remainder, 10);
441                         }
442                     }
443                 }
444                 StringCbPrintfW(ValueString, sizeof(ValueString), L"%lx", Value);
445                 SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
446                 return TRUE;
447             }
448             break;
449 
450         case IDC_FORMAT_DEC:
451             if (HIWORD(wParam) == BN_CLICKED && dwordEditMode == EDIT_MODE_HEX)
452             {
453                 dwordEditMode = EDIT_MODE_DEC;
454                 if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
455                 {
456                     if (GetWindowTextLength(hwndValue))
457                     {
458                         if (GetWindowTextW(hwndValue, ValueString, 32))
459                         {
460                             Value = wcstoul (ValueString, &Remainder, 16);
461                         }
462                     }
463                 }
464                 StringCbPrintfW(ValueString, sizeof(ValueString), L"%lu", Value);
465                 SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, ValueString);
466                 return TRUE;
467             }
468             break;
469 
470         case IDOK:
471             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
472             {
473                 if (GetWindowTextLength(hwndValue))
474                 {
475                     if (!GetWindowTextW(hwndValue, ValueString, 32))
476                     {
477                         EndDialog(hwndDlg, IDCANCEL);
478                         return TRUE;
479                     }
480 
481                     Base = (dwordEditMode == EDIT_MODE_HEX) ? 16 : 10;
482                     dwordValueData = wcstoul (ValueString, &Remainder, Base);
483                 }
484                 else
485                 {
486                     EndDialog(hwndDlg, IDCANCEL);
487                     return TRUE;
488                 }
489             }
490             EndDialog(hwndDlg, IDOK);
491             return TRUE;
492 
493         case IDCANCEL:
494             EndDialog(hwndDlg, IDCANCEL);
495             return TRUE;
496         }
497     }
498     return FALSE;
499 }
500 
501 
502 INT_PTR CALLBACK modify_binary_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
503 {
504     HWND hwndValue;
505     UINT len;
506 
507     UNREFERENCED_PARAMETER(lParam);
508 
509     switch(uMsg)
510     {
511     case WM_INITDIALOG:
512         if (editValueName && wcscmp(editValueName, L""))
513         {
514             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
515         }
516         else
517         {
518             WCHAR buffer[255];
519             LoadStringW(hInst, IDS_DEFAULT_VALUE_NAME, buffer, ARRAY_SIZE(buffer));
520             SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, buffer);
521         }
522         hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA);
523         HexEdit_LoadBuffer(hwndValue, binValueData, valueDataLen);
524         /* reset the hex edit control's font */
525         SendMessageW(hwndValue, WM_SETFONT, 0, 0);
526         SetFocus(hwndValue);
527         return FALSE;
528     case WM_COMMAND:
529         switch (LOWORD(wParam))
530         {
531         case IDOK:
532             if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA)))
533             {
534                 len = (UINT) HexEdit_GetBufferSize(hwndValue);
535                 if (len > 0 && binValueData)
536                     binValueData = HeapReAlloc(GetProcessHeap(), 0, binValueData, len);
537                 else
538                     binValueData = HeapAlloc(GetProcessHeap(), 0, len + 1);
539                 HexEdit_CopyBuffer(hwndValue, binValueData, len);
540                 valueDataLen = len;
541             }
542             EndDialog(hwndDlg, IDOK);
543             break;
544         case IDCANCEL:
545             EndDialog(hwndDlg, IDCANCEL);
546             return TRUE;
547         }
548     }
549     return FALSE;
550 }
551 
552 
553 static BOOL CreateResourceColumns(HWND hwnd)
554 {
555     WCHAR szText[80];
556     RECT rc;
557     LVCOLUMN lvC;
558     HWND hwndLV;
559     INT width;
560 
561     /* Create columns. */
562     lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
563     lvC.pszText = szText;
564     lvC.fmt = LVCFMT_LEFT;
565 
566     hwndLV = GetDlgItem(hwnd, IDC_DMA_LIST);
567     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
568     GetClientRect(hwndLV, &rc);
569 
570     /* Load the column labels from the resource file. */
571     lvC.iSubItem = 0;
572     lvC.cx = (rc.right - rc.left) / 2;
573     LoadStringW(hInst, IDS_DMA_CHANNEL, szText, ARRAY_SIZE(szText));
574     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
575         return FALSE;
576 
577     lvC.iSubItem = 1;
578     lvC.cx = (rc.right - rc.left) - lvC.cx;
579     LoadStringW(hInst, IDS_DMA_PORT, szText, ARRAY_SIZE(szText));
580     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
581         return FALSE;
582 
583 
584     /* Interrupt list */
585     hwndLV = GetDlgItem(hwnd, IDC_IRQ_LIST);
586     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
587     GetClientRect(hwndLV, &rc);
588     width = (rc.right - rc.left) / 4;
589 
590     /* Load the column labels from the resource file. */
591     lvC.iSubItem = 0;
592     lvC.cx = width;
593     LoadStringW(hInst, IDS_INTERRUPT_VECTOR, szText, ARRAY_SIZE(szText));
594     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
595         return FALSE;
596 
597     lvC.iSubItem = 1;
598     LoadStringW(hInst, IDS_INTERRUPT_LEVEL, szText, ARRAY_SIZE(szText));
599     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
600         return FALSE;
601 
602     lvC.iSubItem = 2;
603     LoadStringW(hInst, IDS_INTERRUPT_AFFINITY, szText, ARRAY_SIZE(szText));
604     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
605         return FALSE;
606 
607     lvC.iSubItem = 3;
608     lvC.cx = (rc.right - rc.left) - 3 * width;
609     LoadStringW(hInst, IDS_INTERRUPT_TYPE, szText, ARRAY_SIZE(szText));
610     if (ListView_InsertColumn(hwndLV, 3, &lvC) == -1)
611         return FALSE;
612 
613 
614     /* Memory list */
615     hwndLV = GetDlgItem(hwnd, IDC_MEMORY_LIST);
616     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
617     GetClientRect(hwndLV, &rc);
618     width = (rc.right - rc.left) / 3;
619 
620     /* Load the column labels from the resource file. */
621     lvC.iSubItem = 0;
622     lvC.cx = width;
623     LoadStringW(hInst, IDS_MEMORY_ADDRESS, szText, ARRAY_SIZE(szText));
624     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
625         return FALSE;
626 
627     lvC.iSubItem = 1;
628     LoadStringW(hInst, IDS_MEMORY_LENGTH, szText, ARRAY_SIZE(szText));
629     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
630         return FALSE;
631 
632     lvC.iSubItem = 2;
633     lvC.cx = (rc.right - rc.left) - 2 * width;
634     LoadStringW(hInst, IDS_MEMORY_ACCESS, szText, ARRAY_SIZE(szText));
635     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
636         return FALSE;
637 
638 
639     /* Port list */
640     hwndLV = GetDlgItem(hwnd, IDC_PORT_LIST);
641     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
642     GetClientRect(hwndLV, &rc);
643     width = (rc.right - rc.left) / 3;
644 
645     /* Load the column labels from the resource file. */
646     lvC.iSubItem = 0;
647     lvC.cx = width;
648     LoadStringW(hInst, IDS_PORT_ADDRESS, szText, ARRAY_SIZE(szText));
649     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
650         return FALSE;
651 
652     lvC.iSubItem = 1;
653     LoadStringW(hInst, IDS_PORT_LENGTH, szText, ARRAY_SIZE(szText));
654     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
655         return FALSE;
656 
657     lvC.iSubItem = 2;
658     lvC.cx = (rc.right - rc.left) - 2 * width;
659     LoadStringW(hInst, IDS_PORT_ACCESS, szText, ARRAY_SIZE(szText));
660     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
661         return FALSE;
662 
663     /* Device specific list */
664     hwndLV = GetDlgItem(hwnd, IDC_DEVICE_LIST);
665     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
666     GetClientRect(hwndLV, &rc);
667     width = (rc.right - rc.left) / 3;
668 
669     /* Load the column labels from the resource file. */
670     lvC.iSubItem = 0;
671     lvC.cx = width;
672     LoadStringW(hInst, IDS_SPECIFIC_RESERVED1, szText, ARRAY_SIZE(szText));
673     if (ListView_InsertColumn(hwndLV, 0, &lvC) == -1)
674         return FALSE;
675 
676     lvC.iSubItem = 1;
677     LoadStringW(hInst, IDS_SPECIFIC_RESERVED2, szText, ARRAY_SIZE(szText));
678     if (ListView_InsertColumn(hwndLV, 1, &lvC) == -1)
679         return FALSE;
680 
681     lvC.iSubItem = 2;
682     lvC.cx = (rc.right - rc.left) - 2 * width;
683     LoadStringW(hInst, IDS_SPECIFIC_DATASIZE, szText, ARRAY_SIZE(szText));
684     if (ListView_InsertColumn(hwndLV, 2, &lvC) == -1)
685         return FALSE;
686 
687     return TRUE;
688 }
689 
690 static VOID
691 GetInterfaceType(INTERFACE_TYPE InterfaceType,
692                  LPWSTR pBuffer,
693                  DWORD dwLength)
694 {
695 //    LPWSTR lpInterfaceType;
696 
697     switch (InterfaceType)
698     {
699         case InterfaceTypeUndefined:
700             LoadStringW(hInst, IDS_BUS_UNDEFINED, pBuffer, dwLength);
701 //            lpInterfaceType = L"Undefined";
702             break;
703         case Internal:
704             LoadStringW(hInst, IDS_BUS_INTERNAL, pBuffer, dwLength);
705 //            lpInterfaceType = L"Internal";
706             break;
707         case Isa:
708             LoadStringW(hInst, IDS_BUS_ISA, pBuffer, dwLength);
709 //            lpInterfaceType = L"Isa";
710             break;
711         case Eisa:
712             LoadStringW(hInst, IDS_BUS_EISA, pBuffer, dwLength);
713 //            lpInterfaceType = L"Eisa";
714             break;
715         case MicroChannel:
716             LoadStringW(hInst, IDS_BUS_MICROCHANNEL, pBuffer, dwLength);
717 //            lpInterfaceType = L"MicroChannel";
718             break;
719         case TurboChannel:
720             LoadStringW(hInst, IDS_BUS_TURBOCHANNEL, pBuffer, dwLength);
721 //            lpInterfaceType = L"TurboChannel";
722             break;
723         case PCIBus:
724             LoadStringW(hInst, IDS_BUS_PCIBUS, pBuffer, dwLength);
725 //            lpInterfaceType = L"PCIBus";
726             break;
727         case VMEBus:
728             LoadStringW(hInst, IDS_BUS_VMEBUS, pBuffer, dwLength);
729 //            lpInterfaceType = L"VMEBus";
730             break;
731         case NuBus:
732             LoadStringW(hInst, IDS_BUS_NUBUS, pBuffer, dwLength);
733 //            lpInterfaceType = L"NuBus";
734             break;
735         case PCMCIABus:
736             LoadStringW(hInst, IDS_BUS_PCMCIABUS, pBuffer, dwLength);
737 //            lpInterfaceType = L"PCMCIABus";
738             break;
739         case CBus:
740             LoadStringW(hInst, IDS_BUS_CBUS, pBuffer, dwLength);
741 //            lpInterfaceType = L"CBus";
742             break;
743         case MPIBus:
744             LoadStringW(hInst, IDS_BUS_MPIBUS, pBuffer, dwLength);
745 //            lpInterfaceType = L"MPIBus";
746             break;
747         case MPSABus:
748             LoadStringW(hInst, IDS_BUS_MPSABUS, pBuffer, dwLength);
749 //            lpInterfaceType = L"MPSABus";
750             break;
751         case ProcessorInternal:
752             LoadStringW(hInst, IDS_BUS_PROCESSORINTERNAL, pBuffer, dwLength);
753 //            lpInterfaceType = L"ProcessorInternal";
754             break;
755         case InternalPowerBus:
756             LoadStringW(hInst, IDS_BUS_INTERNALPOWERBUS, pBuffer, dwLength);
757 //            lpInterfaceType = L"InternalPowerBus";
758             break;
759         case PNPISABus:
760             LoadStringW(hInst, IDS_BUS_PNPISABUS, pBuffer, dwLength);
761 //            lpInterfaceType = L"PNPISABus";
762             break;
763         case PNPBus:
764             LoadStringW(hInst, IDS_BUS_PNPBUS, pBuffer, dwLength);
765 //            lpInterfaceType = L"PNPBus";
766             break;
767         default:
768             LoadStringW(hInst, IDS_BUS_UNKNOWNTYPE, pBuffer, dwLength);
769 //            lpInterfaceType = L"Unknown interface type";
770             break;
771     }
772 
773 //    wcscpy(pBuffer, lpInterfaceType);
774 }
775 
776 
777 static VOID
778 ParseResources(HWND hwnd)
779 {
780     PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
781     PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
782     PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
783     ULONG i;
784     HWND hwndLV;
785 
786     WCHAR buffer[80];
787     LVITEMW item;
788     INT iItem;
789 
790     pFullDescriptor = &resourceValueData->List[0];
791     for (i = 0; i < fullResourceIndex; i++)
792     {
793         pFullDescriptor = (PVOID)(pFullDescriptor->PartialResourceList.PartialDescriptors +
794                                   pFullDescriptor->PartialResourceList.Count);
795     }
796     pPartialResourceList = &pFullDescriptor->PartialResourceList;
797 
798     /* Interface type */
799     GetInterfaceType(pFullDescriptor->InterfaceType, buffer, 80);
800     SetDlgItemTextW(hwnd, IDC_INTERFACETYPE, buffer);
801 
802     /* Busnumber */
803     SetDlgItemInt(hwnd, IDC_BUSNUMBER, (UINT)pFullDescriptor->BusNumber, TRUE);
804 
805     /* Version */
806     SetDlgItemInt(hwnd, IDC_VERSION, (UINT)pPartialResourceList->Version, FALSE);
807 
808     /* Revision */
809     SetDlgItemInt(hwnd, IDC_REVISION, (UINT)pPartialResourceList->Revision, FALSE);
810 
811     for (i = 0; i < pPartialResourceList->Count; i++)
812     {
813         pDescriptor = &pPartialResourceList->PartialDescriptors[i];
814 
815         switch (pDescriptor->Type)
816         {
817             case CmResourceTypePort:
818                 hwndLV = GetDlgItem(hwnd, IDC_PORT_LIST);
819 
820 #ifdef _M_AMD64
821                 wsprintf(buffer, L"0x%016I64x", pDescriptor->u.Port.Start.QuadPart);
822 #else
823                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.Port.Start.u.LowPart);
824 #endif
825 
826                 item.mask = LVIF_TEXT | LVIF_PARAM;
827                 item.iItem = 1000;
828                 item.iSubItem = 0;
829                 item.state = 0;
830                 item.stateMask = 0;
831                 item.pszText = buffer;
832                 item.cchTextMax = (int)wcslen(item.pszText);
833                 item.lParam = (LPARAM)pDescriptor;
834 
835                 iItem = ListView_InsertItem(hwndLV, &item);
836                 if (iItem != -1)
837                 {
838                     wsprintf(buffer, L"0x%lx", pDescriptor->u.Port.Length);
839                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
840 
841                     if (pDescriptor->Flags & CM_RESOURCE_PORT_IO)
842                         LoadStringW(hInst, IDS_PORT_PORT_IO, buffer, ARRAY_SIZE(buffer));
843                     else
844                         LoadStringW(hInst, IDS_PORT_MEMORY_IO, buffer, ARRAY_SIZE(buffer));
845                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
846                 }
847                 break;
848 
849             case CmResourceTypeInterrupt:
850                 hwndLV = GetDlgItem(hwnd, IDC_IRQ_LIST);
851 
852                 wsprintf(buffer, L"%lu", pDescriptor->u.Interrupt.Vector);
853 
854                 item.mask = LVIF_TEXT | LVIF_PARAM;
855                 item.iItem = 1000;
856                 item.iSubItem = 0;
857                 item.state = 0;
858                 item.stateMask = 0;
859                 item.pszText = buffer;
860                 item.cchTextMax = (int)wcslen(item.pszText);
861                 item.lParam = (LPARAM)pDescriptor;
862 
863                 iItem = ListView_InsertItem(hwndLV, &item);
864                 if (iItem != -1)
865                 {
866                     wsprintf(buffer, L"%lu", pDescriptor->u.Interrupt.Level);
867                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
868 
869                     wsprintf(buffer, L"0x%08lx", pDescriptor->u.Interrupt.Affinity);
870                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
871 
872                     if (pDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
873                         LoadStringW(hInst, IDS_INTERRUPT_EDGE_SENSITIVE, buffer, ARRAY_SIZE(buffer));
874                     else
875                         LoadStringW(hInst, IDS_INTERRUPT_LEVEL_SENSITIVE, buffer, ARRAY_SIZE(buffer));
876 
877                     ListView_SetItemText(hwndLV, iItem, 3, buffer);
878                 }
879                 break;
880 
881             case CmResourceTypeMemory:
882                 hwndLV = GetDlgItem(hwnd, IDC_MEMORY_LIST);
883 
884 #ifdef _M_AMD64
885                 wsprintf(buffer, L"0x%016I64x", pDescriptor->u.Memory.Start.QuadPart);
886 #else
887                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.Memory.Start.u.LowPart);
888 #endif
889 
890                 item.mask = LVIF_TEXT | LVIF_PARAM;
891                 item.iItem = 1000;
892                 item.iSubItem = 0;
893                 item.state = 0;
894                 item.stateMask = 0;
895                 item.pszText = buffer;
896                 item.cchTextMax = (int)wcslen(item.pszText);
897                 item.lParam = (LPARAM)pDescriptor;
898 
899                 iItem = ListView_InsertItem(hwndLV, &item);
900                 if (iItem != -1)
901                 {
902                     wsprintf(buffer, L"0x%lx", pDescriptor->u.Memory.Length);
903                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
904 
905                     switch (pDescriptor->Flags & (CM_RESOURCE_MEMORY_READ_ONLY | CM_RESOURCE_MEMORY_WRITE_ONLY))
906                     {
907                         case CM_RESOURCE_MEMORY_READ_ONLY:
908                             LoadStringW(hInst, IDS_MEMORY_READ_ONLY, buffer, ARRAY_SIZE(buffer));
909                             break;
910 
911                         case CM_RESOURCE_MEMORY_WRITE_ONLY:
912                             LoadStringW(hInst, IDS_MEMORY_WRITE_ONLY, buffer, ARRAY_SIZE(buffer));
913                             break;
914 
915                         default:
916                             LoadStringW(hInst, IDS_MEMORY_READ_WRITE, buffer, ARRAY_SIZE(buffer));
917                             break;
918                     }
919 
920                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
921                 }
922                 break;
923 
924             case CmResourceTypeDma:
925                 hwndLV = GetDlgItem(hwnd, IDC_DMA_LIST);
926 
927                 wsprintf(buffer, L"%lu", pDescriptor->u.Dma.Channel);
928 
929                 item.mask = LVIF_TEXT | LVIF_PARAM;
930                 item.iItem = 1000;
931                 item.iSubItem = 0;
932                 item.state = 0;
933                 item.stateMask = 0;
934                 item.pszText = buffer;
935                 item.cchTextMax = (int)wcslen(item.pszText);
936                 item.lParam = (LPARAM)pDescriptor;
937 
938                 iItem = ListView_InsertItem(hwndLV, &item);
939                 if (iItem != -1)
940                 {
941                     wsprintf(buffer, L"%lu", pDescriptor->u.Dma.Port);
942                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
943                 }
944                 break;
945 
946             case CmResourceTypeDeviceSpecific:
947                 hwndLV = GetDlgItem(hwnd, IDC_DEVICE_LIST);
948 
949                 wsprintf(buffer, L"0x%08lx", pDescriptor->u.DeviceSpecificData.Reserved1);
950 
951                 item.mask = LVIF_TEXT | LVIF_PARAM;
952                 item.iItem = 1000;
953                 item.iSubItem = 0;
954                 item.state = 0;
955                 item.stateMask = 0;
956                 item.pszText = buffer;
957                 item.cchTextMax = (int)wcslen(item.pszText);
958                 item.lParam = (LPARAM)pDescriptor;
959 
960                 iItem = ListView_InsertItem(hwndLV, &item);
961                 if (iItem != -1)
962                 {
963                     wsprintf(buffer, L"0x%08lx", pDescriptor->u.DeviceSpecificData.Reserved2);
964                     ListView_SetItemText(hwndLV, iItem, 1, buffer);
965 
966                     wsprintf(buffer, L"0x%lx", pDescriptor->u.DeviceSpecificData.DataSize);
967                     ListView_SetItemText(hwndLV, iItem, 2, buffer);
968                 }
969                 break;
970         }
971     }
972 }
973 
974 
975 static BOOL
976 OnResourceNotify(HWND hwndDlg, NMHDR *phdr)
977 {
978     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
979 
980     switch (phdr->idFrom)
981     {
982         case IDC_PORT_LIST:
983         case IDC_MEMORY_LIST:
984         case IDC_DMA_LIST:
985         case IDC_IRQ_LIST:
986         case IDC_DEVICE_LIST:
987             switch(phdr->code)
988             {
989                 case NM_CLICK:
990                     if (lpnmlv->iItem != -1)
991                     {
992                         PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor;
993                         LVITEMW item;
994 
995                         item.mask = LVIF_PARAM;
996                         item.iItem = lpnmlv->iItem;
997                         item.iSubItem = 0;
998 
999                         if (ListView_GetItem(phdr->hwndFrom, &item))
1000                         {
1001                             pDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)item.lParam;
1002 
1003                             EnableWindow(GetDlgItem(hwndDlg, IDC_UNDETERMINED),
1004                                          (pDescriptor->ShareDisposition == CmResourceShareUndetermined));
1005 
1006                             EnableWindow(GetDlgItem(hwndDlg, IDC_SHARED),
1007                                          (pDescriptor->ShareDisposition == CmResourceShareShared));
1008 
1009                             EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_EXCLUSIVE),
1010                                          (pDescriptor->ShareDisposition == CmResourceShareDeviceExclusive));
1011 
1012                             EnableWindow(GetDlgItem(hwndDlg, IDC_DRIVER_EXCLUSIVE),
1013                                          (pDescriptor->ShareDisposition == CmResourceShareDriverExclusive));
1014                         }
1015                     }
1016                     else
1017                     {
1018                         EnableWindow(GetDlgItem(hwndDlg, IDC_UNDETERMINED), FALSE);
1019                         EnableWindow(GetDlgItem(hwndDlg, IDC_SHARED), FALSE);
1020                         EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_EXCLUSIVE), FALSE);
1021                         EnableWindow(GetDlgItem(hwndDlg, IDC_DRIVER_EXCLUSIVE), FALSE);
1022                     }
1023                     break;
1024             }
1025             break;
1026     }
1027 
1028     return FALSE;
1029 }
1030 
1031 
1032 static INT_PTR CALLBACK modify_resource_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1033 {
1034     UNREFERENCED_PARAMETER(lParam);
1035 
1036     switch(uMsg)
1037     {
1038     case WM_INITDIALOG:
1039         CreateResourceColumns(hwndDlg);
1040         ParseResources(hwndDlg);
1041         return FALSE;
1042 
1043     case WM_NOTIFY:
1044         return OnResourceNotify(hwndDlg, (NMHDR *)lParam);
1045 
1046     case WM_COMMAND:
1047         switch (LOWORD(wParam))
1048         {
1049         case IDOK:
1050             EndDialog(hwndDlg, IDOK);
1051             break;
1052         case IDCANCEL:
1053             EndDialog(hwndDlg, IDCANCEL);
1054             return TRUE;
1055         }
1056     }
1057     return FALSE;
1058 }
1059 
1060 static BOOL CreateResourceListColumns(HWND hWndListView)
1061 {
1062     WCHAR szText[80];
1063     RECT rc;
1064     LVCOLUMN lvC;
1065 
1066     ListView_SetExtendedListViewStyle(hWndListView, LVS_EX_FULLROWSELECT);
1067 
1068     GetClientRect(hWndListView, &rc);
1069 
1070     /* Create columns. */
1071     lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
1072     lvC.pszText = szText;
1073     lvC.fmt = LVCFMT_LEFT;
1074 
1075     /* Load the column labels from the resource file. */
1076     lvC.iSubItem = 0;
1077     lvC.cx = (rc.right - rc.left) / 2;
1078     LoadStringW(hInst, IDS_BUSNUMBER, szText, ARRAY_SIZE(szText));
1079     if (ListView_InsertColumn(hWndListView, 0, &lvC) == -1)
1080         return FALSE;
1081 
1082     lvC.iSubItem = 1;
1083     lvC.cx = (rc.right - rc.left) - lvC.cx;
1084     LoadStringW(hInst, IDS_INTERFACE, szText, ARRAY_SIZE(szText));
1085     if (ListView_InsertColumn(hWndListView, 1, &lvC) == -1)
1086         return FALSE;
1087 
1088     return TRUE;
1089 }
1090 
1091 static VOID AddFullResourcesToList(HWND hwnd)
1092 {
1093     PCM_FULL_RESOURCE_DESCRIPTOR pFullDescriptor;
1094     WCHAR buffer[80];
1095     LVITEMW item;
1096     ULONG i;
1097     INT iItem;
1098 
1099     pFullDescriptor = &resourceValueData->List[0];
1100     for (i = 0; i < resourceValueData->Count; i++)
1101     {
1102         wsprintf(buffer, L"%lu", pFullDescriptor->BusNumber);
1103 
1104         item.mask = LVIF_TEXT;
1105         item.iItem = i;
1106         item.iSubItem = 0;
1107         item.state = 0;
1108         item.stateMask = 0;
1109         item.pszText = buffer;
1110         item.cchTextMax = (int)wcslen(item.pszText);
1111 
1112         iItem = ListView_InsertItem(hwnd, &item);
1113         if (iItem != -1)
1114         {
1115             GetInterfaceType(pFullDescriptor->InterfaceType, buffer, 80);
1116             ListView_SetItemText(hwnd, iItem, 1, buffer);
1117         }
1118         pFullDescriptor = (PVOID)(pFullDescriptor->PartialResourceList.PartialDescriptors +
1119                                   pFullDescriptor->PartialResourceList.Count);
1120     }
1121 }
1122 
1123 static BOOL
1124 OnResourceListNotify(HWND hwndDlg, NMHDR *phdr)
1125 {
1126     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
1127 
1128     switch (phdr->idFrom)
1129     {
1130         case IDC_RESOURCE_LIST:
1131             switch(phdr->code)
1132             {
1133                 case NM_CLICK:
1134                     fullResourceIndex = lpnmlv->iItem;
1135                     EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW_RESOURCE), (lpnmlv->iItem != -1));
1136                     break;
1137 
1138                 case NM_DBLCLK:
1139                     if (lpnmlv->iItem != -1)
1140                     {
1141                         fullResourceIndex = lpnmlv->iItem;
1142                         DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwndDlg, modify_resource_dlgproc);
1143                     }
1144                     break;
1145             }
1146             break;
1147     }
1148 
1149     return FALSE;
1150 }
1151 
1152 
1153 static INT_PTR CALLBACK modify_resource_list_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1154 {
1155     UNREFERENCED_PARAMETER(lParam);
1156 
1157     switch(uMsg)
1158     {
1159     case WM_INITDIALOG:
1160         CreateResourceListColumns(GetDlgItem(hwndDlg, IDC_RESOURCE_LIST));
1161         AddFullResourcesToList(GetDlgItem(hwndDlg, IDC_RESOURCE_LIST));
1162         return FALSE;
1163 
1164     case WM_NOTIFY:
1165         return OnResourceListNotify(hwndDlg, (NMHDR *)lParam);
1166 
1167     case WM_COMMAND:
1168         switch (LOWORD(wParam))
1169         {
1170         case IDC_SHOW_RESOURCE:
1171             if (fullResourceIndex != -1)
1172                 DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwndDlg, modify_resource_dlgproc);
1173             break;
1174         case IDOK:
1175             EndDialog(hwndDlg, IDOK);
1176             break;
1177         case IDCANCEL:
1178             EndDialog(hwndDlg, IDCANCEL);
1179             return TRUE;
1180         }
1181     }
1182     return FALSE;
1183 }
1184 
1185 static BOOL
1186 CreateRequirementsListColumns(HWND hWndListView)
1187 {
1188     WCHAR szText[80];
1189     RECT rc;
1190     LVCOLUMN lvC;
1191 
1192     ListView_SetExtendedListViewStyle(hWndListView, LVS_EX_FULLROWSELECT);
1193 
1194     GetClientRect(hWndListView, &rc);
1195 
1196     /* Create columns. */
1197     lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
1198     lvC.pszText = szText;
1199     lvC.fmt = LVCFMT_LEFT;
1200 
1201     /* Load the column labels from the resource file. */
1202     lvC.iSubItem = 0;
1203     lvC.cx = (rc.right - rc.left) / 4;
1204     LoadStringW(hInst, IDS_REQALTERNATIVELIST, szText, ARRAY_SIZE(szText));
1205     if (ListView_InsertColumn(hWndListView, 0, &lvC) == -1)
1206         return FALSE;
1207 
1208     lvC.iSubItem = 1;
1209     lvC.cx = (rc.right - rc.left) / 4;
1210     LoadStringW(hInst, IDS_REQRESOURCELIST, szText, ARRAY_SIZE(szText));
1211     if (ListView_InsertColumn(hWndListView, 1, &lvC) == -1)
1212         return FALSE;
1213 
1214     lvC.iSubItem = 2;
1215     lvC.cx = (rc.right - rc.left) / 4;
1216     LoadStringW(hInst, IDS_REQDESCRIPTOR, szText, ARRAY_SIZE(szText));
1217     if (ListView_InsertColumn(hWndListView, 2, &lvC) == -1)
1218         return FALSE;
1219 
1220     lvC.iSubItem = 3;
1221     lvC.cx = (rc.right - rc.left) - (3 * ((rc.right - rc.left) / 4));
1222     LoadStringW(hInst, IDS_REQDEVICETYPE, szText, ARRAY_SIZE(szText));
1223     if (ListView_InsertColumn(hWndListView, 3, &lvC) == -1)
1224         return FALSE;
1225 
1226     return TRUE;
1227 }
1228 
1229 static VOID
1230 GetResourceType(UCHAR ResourceType,
1231                 LPWSTR pBuffer,
1232                 DWORD dwLength)
1233 {
1234     switch (ResourceType)
1235     {
1236         case CmResourceTypePort:
1237             LoadStringW(hInst, IDS_TYPE_PORT, pBuffer, dwLength);
1238             break;
1239 
1240         case CmResourceTypeInterrupt:
1241             LoadStringW(hInst, IDS_TYPE_INTERRUPT, pBuffer, dwLength);
1242             break;
1243 
1244         case CmResourceTypeMemory:
1245             LoadStringW(hInst, IDS_TYPE_MEMORY, pBuffer, dwLength);
1246             break;
1247 
1248         case CmResourceTypeDma:
1249             LoadStringW(hInst, IDS_TYPE_DMA, pBuffer, dwLength);
1250             break;
1251 
1252         default:
1253             wsprintf(pBuffer, L"Unknown %u", ResourceType);
1254             break;
1255     }
1256 }
1257 
1258 static VOID
1259 GetShareDisposition(
1260     UCHAR ShareDisposition,
1261     LPWSTR pBuffer,
1262     DWORD dwLength)
1263 {
1264     switch (ShareDisposition)
1265     {
1266         case CmResourceShareUndetermined:
1267             LoadStringW(hInst, IDS_SHARE_UNDETERMINED, pBuffer, dwLength);
1268             break;
1269 
1270         case CmResourceShareDeviceExclusive:
1271             LoadStringW(hInst, IDS_SHARE_DEVICE_EXCLUSIVE, pBuffer, dwLength);
1272             break;
1273 
1274         case CmResourceShareDriverExclusive:
1275             LoadStringW(hInst, IDS_SHARE_DRIVER_EXCLUSIVE, pBuffer, dwLength);
1276             break;
1277 
1278         case CmResourceShareShared:
1279             LoadStringW(hInst, IDS_SHARE_SHARED, pBuffer, dwLength);
1280             break;
1281     }
1282 }
1283 
1284 static VOID
1285 GetPortType(
1286     USHORT Flags,
1287     LPWSTR pBuffer,
1288     DWORD dwLength)
1289 {
1290     if ((Flags & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO)
1291     {
1292         LoadStringW(hInst, IDS_PORT_PORT_IO, pBuffer, dwLength);
1293     }
1294     else if ((Flags & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_MEMORY)
1295     {
1296         LoadStringW(hInst, IDS_PORT_MEMORY_IO, pBuffer, dwLength);
1297     }
1298 }
1299 
1300 static VOID
1301 GetMemoryAccess(
1302     USHORT Flags,
1303     LPWSTR pBuffer,
1304     DWORD dwLength)
1305 {
1306     if ((Flags & (CM_RESOURCE_MEMORY_READ_ONLY | CM_RESOURCE_MEMORY_WRITE_ONLY)) == CM_RESOURCE_MEMORY_READ_WRITE)
1307     {
1308         LoadStringW(hInst, IDS_MEMORY_READ_WRITE, pBuffer, dwLength);
1309     }
1310     else if ((Flags & (CM_RESOURCE_MEMORY_READ_ONLY | CM_RESOURCE_MEMORY_WRITE_ONLY)) == CM_RESOURCE_MEMORY_READ_ONLY)
1311     {
1312         LoadStringW(hInst, IDS_MEMORY_READ_ONLY, pBuffer, dwLength);
1313     }
1314     else if ((Flags & (CM_RESOURCE_MEMORY_READ_ONLY | CM_RESOURCE_MEMORY_WRITE_ONLY)) == CM_RESOURCE_MEMORY_WRITE_ONLY)
1315     {
1316         LoadStringW(hInst, IDS_MEMORY_WRITE_ONLY, pBuffer, dwLength);
1317     }
1318 }
1319 
1320 static VOID
1321 GetInterruptType(
1322     USHORT Flags,
1323     LPWSTR pBuffer,
1324     DWORD dwLength)
1325 {
1326     if ((Flags & CM_RESOURCE_INTERRUPT_LEVEL_LATCHED_BITS) == CM_RESOURCE_INTERRUPT_LATCHED)
1327     {
1328         LoadStringW(hInst, IDS_INTERRUPT_EDGE_SENSITIVE, pBuffer, dwLength);
1329     }
1330     else
1331     {
1332         LoadStringW(hInst, IDS_INTERRUPT_LEVEL_SENSITIVE, pBuffer, dwLength);
1333     }
1334 }
1335 
1336 static VOID
1337 AddRequirementsToList(HWND hwndDlg, HWND hwnd)
1338 {
1339     PIO_RESOURCE_LIST pResourceList;
1340     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1341     WCHAR buffer[80];
1342     LVITEMW item;
1343     ULONG i, j, index;
1344     INT iItem;
1345 
1346     index = 0;
1347     pResourceList = &requirementsValueData->List[0];
1348     for (i = 0; i < requirementsValueData->AlternativeLists; i++)
1349     {
1350         for (j = 0; j < pResourceList->Count; j++)
1351         {
1352             pDescriptor = &pResourceList->Descriptors[j];
1353 
1354             wsprintf(buffer, L"%lu", i + 1);
1355 
1356             item.mask = LVIF_TEXT | LVIF_PARAM;
1357             item.iItem = index;
1358             item.iSubItem = 0;
1359             item.state = 0;
1360             item.stateMask = 0;
1361             item.pszText = buffer;
1362             item.cchTextMax = (int)wcslen(item.pszText);
1363             item.lParam = (LPARAM)pDescriptor;
1364 
1365             iItem = ListView_InsertItem(hwnd, &item);
1366             if (iItem != -1)
1367             {
1368                 wsprintf(buffer, L"%lu", j + 1);
1369                 ListView_SetItemText(hwnd, iItem, 1, buffer);
1370                 wsprintf(buffer, L"%lu", 1);
1371                 ListView_SetItemText(hwnd, iItem, 2, buffer);
1372 
1373                 GetResourceType(pDescriptor->Type, buffer, 80);
1374                 ListView_SetItemText(hwnd, iItem, 3, buffer);
1375             }
1376 
1377             index++;
1378         }
1379 
1380 
1381         pResourceList = (PIO_RESOURCE_LIST)(pResourceList->Descriptors + pResourceList->Count);
1382     }
1383 
1384     GetInterfaceType(requirementsValueData->InterfaceType, buffer, 80);
1385     SetDlgItemTextW(hwndDlg, IDC_REQINTERFACETYPE, buffer);
1386     SetDlgItemInt(hwndDlg, IDC_REQBUSNUMBER, (UINT)requirementsValueData->BusNumber, TRUE);
1387     SetDlgItemInt(hwndDlg, IDC_REQSLOTNUMBER, (UINT)requirementsValueData->SlotNumber, FALSE);
1388 }
1389 
1390 static INT_PTR CALLBACK show_requirements_port_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1391 {
1392     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1393     WCHAR Buffer[80];
1394 
1395     switch(uMsg)
1396     {
1397     case WM_INITDIALOG:
1398         pDescriptor = (PIO_RESOURCE_DESCRIPTOR)lParam;
1399 
1400         GetPortType(pDescriptor->Flags, Buffer, 80);
1401         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_TYPE, Buffer);
1402 
1403         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Port.Length);
1404         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_LENGTH, Buffer);
1405         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Port.Alignment);
1406         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_ALIGN, Buffer);
1407 #ifdef _M_AMD64
1408         wsprintf(Buffer, L"0x%016I64x", pDescriptor->u.Port.MinimumAddress.QuadPart);
1409 #else
1410         wsprintf(Buffer, L"0x%08lx", pDescriptor->u.Port.MinimumAddress.u.LowPart);
1411 #endif
1412         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_MIN, Buffer);
1413 #ifdef _M_AMD64
1414         wsprintf(Buffer, L"0x%016I64x", pDescriptor->u.Port.MaximumAddress.QuadPart);
1415 #else
1416         wsprintf(Buffer, L"0x%08lx", pDescriptor->u.Port.MaximumAddress.u.LowPart);
1417 #endif
1418         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_MAX, Buffer);
1419 
1420         GetShareDisposition(pDescriptor->ShareDisposition, Buffer, 80);
1421         SetDlgItemTextW(hwndDlg, IDC_REQ_PORT_SHARE, Buffer);
1422 
1423         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_PORT_ALTERNATIVE), (pDescriptor->Option & IO_RESOURCE_ALTERNATIVE));
1424         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_PORT_PREFERRED), (pDescriptor->Option & IO_RESOURCE_PREFERRED));
1425         return FALSE;
1426 
1427     case WM_COMMAND:
1428         switch (LOWORD(wParam))
1429         {
1430         case IDOK:
1431         case IDCANCEL:
1432             EndDialog(hwndDlg, IDOK);
1433             break;
1434         }
1435     }
1436     return FALSE;
1437 }
1438 
1439 static INT_PTR CALLBACK show_requirements_memory_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1440 {
1441     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1442     WCHAR Buffer[80];
1443 
1444     switch(uMsg)
1445     {
1446     case WM_INITDIALOG:
1447         pDescriptor = (PIO_RESOURCE_DESCRIPTOR)lParam;
1448 
1449         GetMemoryAccess(pDescriptor->Flags, Buffer, 80);
1450         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_ACCESS, Buffer);
1451 
1452         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Memory.Length);
1453         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_LENGTH, Buffer);
1454         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Memory.Alignment);
1455         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_ALIGN, Buffer);
1456 #ifdef _M_AMD64
1457         wsprintf(Buffer, L"0x%016I64x", pDescriptor->u.Memory.MinimumAddress.QuadPart);
1458 #else
1459         wsprintf(Buffer, L"0x%08lx", pDescriptor->u.Memory.MinimumAddress.u.LowPart);
1460 #endif
1461         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_MIN, Buffer);
1462 #ifdef _M_AMD64
1463         wsprintf(Buffer, L"0x%016I64x", pDescriptor->u.Memory.MaximumAddress.QuadPart);
1464 #else
1465         wsprintf(Buffer, L"0x%08lx", pDescriptor->u.Memory.MaximumAddress.u.LowPart);
1466 #endif
1467         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_MAX, Buffer);
1468 
1469         GetShareDisposition(pDescriptor->ShareDisposition, Buffer, 80);
1470         SetDlgItemTextW(hwndDlg, IDC_REQ_MEMORY_SHARE, Buffer);
1471 
1472         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_MEMORY_ALTERNATIVE), (pDescriptor->Option & IO_RESOURCE_ALTERNATIVE));
1473         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_MEMORY_PREFERRED), (pDescriptor->Option & IO_RESOURCE_PREFERRED));
1474         return FALSE;
1475 
1476     case WM_COMMAND:
1477         switch (LOWORD(wParam))
1478         {
1479         case IDOK:
1480         case IDCANCEL:
1481             EndDialog(hwndDlg, IDOK);
1482             break;
1483         }
1484     }
1485     return FALSE;
1486 }
1487 
1488 static INT_PTR CALLBACK show_requirements_interrupt_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1489 {
1490     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1491     WCHAR Buffer[80];
1492 
1493     switch(uMsg)
1494     {
1495     case WM_INITDIALOG:
1496         pDescriptor = (PIO_RESOURCE_DESCRIPTOR)lParam;
1497 
1498         GetInterruptType(pDescriptor->Flags, Buffer, 80);
1499         SetDlgItemTextW(hwndDlg, IDC_REQ_INT_TYPE, Buffer);
1500 
1501         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Interrupt.MinimumVector);
1502         SetDlgItemTextW(hwndDlg, IDC_REQ_INT_MIN, Buffer);
1503         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Interrupt.MaximumVector);
1504         SetDlgItemTextW(hwndDlg, IDC_REQ_INT_MAX, Buffer);
1505 
1506         GetShareDisposition(pDescriptor->ShareDisposition, Buffer, 80);
1507         SetDlgItemTextW(hwndDlg, IDC_REQ_INT_SHARE, Buffer);
1508 
1509         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_INT_ALTERNATIVE), (pDescriptor->Option & IO_RESOURCE_ALTERNATIVE));
1510         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_INT_PREFERRED), (pDescriptor->Option & IO_RESOURCE_PREFERRED));
1511         return FALSE;
1512 
1513     case WM_COMMAND:
1514         switch (LOWORD(wParam))
1515         {
1516         case IDOK:
1517         case IDCANCEL:
1518             EndDialog(hwndDlg, IDOK);
1519             break;
1520         }
1521     }
1522     return FALSE;
1523 }
1524 
1525 static INT_PTR CALLBACK show_requirements_dma_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1526 {
1527     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1528     WCHAR Buffer[80];
1529 
1530     switch(uMsg)
1531     {
1532     case WM_INITDIALOG:
1533         pDescriptor = (PIO_RESOURCE_DESCRIPTOR)lParam;
1534         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Dma.MinimumChannel);
1535         SetDlgItemTextW(hwndDlg, IDC_REQ_DMA_MIN, Buffer);
1536         wsprintf(Buffer, L"0x%lx", pDescriptor->u.Dma.MaximumChannel);
1537         SetDlgItemTextW(hwndDlg, IDC_REQ_DMA_MAX, Buffer);
1538 
1539         GetShareDisposition(pDescriptor->ShareDisposition, Buffer, 80);
1540         SetDlgItemTextW(hwndDlg, IDC_REQ_DMA_SHARE, Buffer);
1541 
1542         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_DMA_ALTERNATIVE), (pDescriptor->Option & IO_RESOURCE_ALTERNATIVE));
1543         EnableWindow(GetDlgItem(hwndDlg, IDC_REQ_DMA_PREFERRED), (pDescriptor->Option & IO_RESOURCE_PREFERRED));
1544         return FALSE;
1545 
1546     case WM_COMMAND:
1547         switch (LOWORD(wParam))
1548         {
1549         case IDOK:
1550         case IDCANCEL:
1551            EndDialog(hwndDlg, IDOK);
1552             break;
1553         }
1554     }
1555     return FALSE;
1556 }
1557 
1558 static VOID
1559 ShowRequirement(HWND hwndDlg)
1560 {
1561     PIO_RESOURCE_DESCRIPTOR pDescriptor;
1562     LVITEMW item;
1563 
1564     if (requirementsIndex == -1)
1565         return;
1566 
1567     item.mask = LVIF_PARAM;
1568     item.iItem = requirementsIndex;
1569     item.iSubItem = 0;
1570     ListView_GetItem(GetDlgItem(hwndDlg, IDC_REQUIREMENTS_LIST), &item);
1571 
1572     pDescriptor = (PIO_RESOURCE_DESCRIPTOR)item.lParam;
1573     if (pDescriptor)
1574     {
1575         switch (pDescriptor->Type)
1576         {
1577         case CmResourceTypePort:
1578             DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_EDIT_REQUIREMENTS_PORT), hwndDlg, show_requirements_port_dlgproc, (LPARAM)pDescriptor);
1579             break;
1580         case CmResourceTypeMemory:
1581             DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_EDIT_REQUIREMENTS_MEMORY), hwndDlg, show_requirements_memory_dlgproc, (LPARAM)pDescriptor);
1582             break;
1583         case CmResourceTypeInterrupt:
1584             DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_EDIT_REQUIREMENTS_INT), hwndDlg, show_requirements_interrupt_dlgproc, (LPARAM)pDescriptor);
1585             break;
1586         case CmResourceTypeDma:
1587             DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_EDIT_REQUIREMENTS_DMA), hwndDlg, show_requirements_dma_dlgproc, (LPARAM)pDescriptor);
1588             break;
1589         default:
1590             break;
1591         }
1592     }
1593 }
1594 
1595 static BOOL
1596 OnRequirementsListNotify(HWND hwndDlg, NMHDR *phdr)
1597 {
1598     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
1599 
1600     switch (phdr->idFrom)
1601     {
1602         case IDC_REQUIREMENTS_LIST:
1603             switch(phdr->code)
1604             {
1605                 case NM_CLICK:
1606                     requirementsIndex = lpnmlv->iItem;
1607                     EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW_REQUIREMENT), (lpnmlv->iItem != -1));
1608                     break;
1609 
1610                 case NM_DBLCLK:
1611                     if (lpnmlv->iItem != -1)
1612                     {
1613                         requirementsIndex = lpnmlv->iItem;
1614                         ShowRequirement(hwndDlg);
1615                     }
1616                     break;
1617             }
1618             break;
1619     }
1620 
1621     return FALSE;
1622 }
1623 
1624 static INT_PTR CALLBACK modify_requirements_list_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1625 {
1626     UNREFERENCED_PARAMETER(lParam);
1627 
1628     switch(uMsg)
1629     {
1630     case WM_INITDIALOG:
1631         CreateRequirementsListColumns(GetDlgItem(hwndDlg, IDC_REQUIREMENTS_LIST));
1632         AddRequirementsToList(hwndDlg, GetDlgItem(hwndDlg, IDC_REQUIREMENTS_LIST));
1633         return FALSE;
1634 
1635     case WM_NOTIFY:
1636         return OnRequirementsListNotify(hwndDlg, (NMHDR *)lParam);
1637 
1638     case WM_COMMAND:
1639         switch (LOWORD(wParam))
1640         {
1641         case IDC_SHOW_REQUIREMENT:
1642             if (requirementsIndex != -1)
1643                 ShowRequirement(hwndDlg);
1644             break;
1645         case IDOK:
1646             EndDialog(hwndDlg, IDOK);
1647             break;
1648         case IDCANCEL:
1649             EndDialog(hwndDlg, IDCANCEL);
1650             return TRUE;
1651         }
1652     }
1653     return FALSE;
1654 }
1655 
1656 BOOL ModifyValue(HWND hwnd, HKEY hKey, LPCWSTR valueName, BOOL EditBin)
1657 {
1658     DWORD type;
1659     LONG lRet;
1660     BOOL result = FALSE;
1661 
1662     if (!hKey)
1663         return FALSE;
1664 
1665     editValueName = valueName;
1666 
1667     lRet = RegQueryValueExW(hKey, valueName, 0, &type, 0, &valueDataLen);
1668     if (lRet != ERROR_SUCCESS && (valueName == NULL || !valueName[0]))
1669     {
1670         lRet = ERROR_SUCCESS; /* Allow editing of (Default) values which don't exist */
1671         type = REG_SZ;
1672         valueDataLen = 0;
1673         stringValueData = NULL;
1674         binValueData = NULL;
1675     }
1676 
1677     if (lRet != ERROR_SUCCESS)
1678     {
1679         error(hwnd, IDS_BAD_VALUE, valueName);
1680         goto done;
1681     }
1682 
1683     if (EditBin == FALSE && ((type == REG_SZ) || (type == REG_EXPAND_SZ)))
1684     {
1685         if (valueDataLen > 0)
1686         {
1687             if (!(stringValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen)))
1688             {
1689                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1690                 goto done;
1691             }
1692             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
1693             if (lRet != ERROR_SUCCESS)
1694             {
1695                 error(hwnd, IDS_BAD_VALUE, valueName);
1696                 goto done;
1697             }
1698         }
1699         else
1700         {
1701             stringValueData = NULL;
1702         }
1703 
1704         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_STRING), hwnd, modify_string_dlgproc) == IDOK)
1705         {
1706             if (stringValueData)
1707             {
1708                 lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)stringValueData, (DWORD) (wcslen(stringValueData) + 1) * sizeof(WCHAR));
1709             }
1710             else
1711             {
1712                 lRet = RegSetValueExW(hKey, valueName, 0, type, NULL, 0);
1713             }
1714             if (lRet == ERROR_SUCCESS)
1715                 result = TRUE;
1716         }
1717     }
1718     else if (EditBin == FALSE && type == REG_MULTI_SZ)
1719     {
1720         if (valueDataLen > 0)
1721         {
1722             size_t llen, listlen, nl_len;
1723             LPWSTR src, lines = NULL;
1724 
1725             if (!(stringValueData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, valueDataLen + sizeof(WCHAR))))
1726             {
1727                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1728                 goto done;
1729             }
1730             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)stringValueData, &valueDataLen);
1731             if (lRet != ERROR_SUCCESS)
1732             {
1733                 error(hwnd, IDS_BAD_VALUE, valueName);
1734                 goto done;
1735             }
1736 
1737             /* convert \0 to \r\n */
1738             src = stringValueData;
1739             nl_len = wcslen(L"\r\n") * sizeof(WCHAR);
1740             listlen = sizeof(WCHAR);
1741             lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listlen + sizeof(WCHAR));
1742             while(*src != L'\0')
1743             {
1744                 llen = wcslen(src);
1745                 if(llen == 0)
1746                     break;
1747                 listlen += (llen * sizeof(WCHAR)) + nl_len;
1748                 lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, listlen);
1749                 wcscat(lines, src);
1750                 wcscat(lines, L"\r\n");
1751                 src += llen + 1;
1752             }
1753             HeapFree(GetProcessHeap(), 0, stringValueData);
1754             stringValueData = lines;
1755         }
1756         else
1757         {
1758             stringValueData = NULL;
1759         }
1760 
1761         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_MULTI_STRING), hwnd, modify_multi_string_dlgproc) == IDOK)
1762         {
1763             if (stringValueData)
1764             {
1765                 /* convert \r\n to \0 */
1766                 BOOL EmptyLines = FALSE;
1767                 LPWSTR src, lines, nl;
1768                 size_t linechars, buflen, c_nl, dest;
1769 
1770                 src = stringValueData;
1771                 buflen = sizeof(WCHAR);
1772                 lines = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen + sizeof(WCHAR));
1773                 c_nl = wcslen(L"\r\n");
1774                 dest = 0;
1775                 while(*src != L'\0')
1776                 {
1777                     if((nl = wcsstr(src, L"\r\n")))
1778                     {
1779                         linechars = nl - src;
1780                         if(nl == src)
1781                         {
1782                             EmptyLines = TRUE;
1783                             src = nl + c_nl;
1784                             continue;
1785                         }
1786                     }
1787                     else
1788                     {
1789                         linechars = wcslen(src);
1790                     }
1791                     if(linechars > 0)
1792                     {
1793                         buflen += ((linechars + 1) * sizeof(WCHAR));
1794                         lines = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lines, buflen);
1795                         memcpy((lines + dest), src, linechars * sizeof(WCHAR));
1796                         dest += linechars;
1797                         lines[dest++] = L'\0';
1798                     }
1799                     else
1800                     {
1801                         EmptyLines = TRUE;
1802                     }
1803                     src += linechars + (nl != NULL ? c_nl : 0);
1804                 }
1805                 lines[++dest] = L'\0';
1806 
1807                 if(EmptyLines)
1808                 {
1809                     warning(hwnd, IDS_MULTI_SZ_EMPTY_STRING);
1810                 }
1811 
1812                 lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)lines, (DWORD) buflen);
1813                 HeapFree(GetProcessHeap(), 0, lines);
1814             }
1815             else
1816             {
1817                 lRet = RegSetValueExW(hKey, valueName, 0, type, NULL, 0);
1818             }
1819             if (lRet == ERROR_SUCCESS)
1820                 result = TRUE;
1821         }
1822     }
1823     else if (EditBin == FALSE && type == REG_DWORD)
1824     {
1825         lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)&dwordValueData, &valueDataLen);
1826         if (lRet != ERROR_SUCCESS)
1827         {
1828             error(hwnd, IDS_BAD_VALUE, valueName);
1829             goto done;
1830         }
1831 
1832         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_DWORD), hwnd, modify_dword_dlgproc) == IDOK)
1833         {
1834             lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)&dwordValueData, sizeof(DWORD));
1835             if (lRet == ERROR_SUCCESS)
1836                 result = TRUE;
1837         }
1838     }
1839     else if (EditBin == FALSE && type == REG_RESOURCE_LIST)
1840     {
1841         if (valueDataLen > 0)
1842         {
1843             resourceValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen);
1844             if (resourceValueData == NULL)
1845             {
1846                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1847                 goto done;
1848             }
1849 
1850             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)resourceValueData, &valueDataLen);
1851             if (lRet != ERROR_SUCCESS)
1852             {
1853                 error(hwnd, IDS_BAD_VALUE, valueName);
1854                 goto done;
1855             }
1856         }
1857         else
1858         {
1859             resourceValueData = NULL;
1860         }
1861 
1862         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE_LIST), hwnd, modify_resource_list_dlgproc) == IDOK)
1863         {
1864         }
1865     }
1866     else if (EditBin == FALSE && type == REG_FULL_RESOURCE_DESCRIPTOR)
1867     {
1868         if (valueDataLen > 0)
1869         {
1870             resourceValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + sizeof(ULONG));
1871             if (resourceValueData == NULL)
1872             {
1873                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1874                 goto done;
1875             }
1876 
1877             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)&resourceValueData->List[0], &valueDataLen);
1878             if (lRet != ERROR_SUCCESS)
1879             {
1880                 error(hwnd, IDS_BAD_VALUE, valueName);
1881                 goto done;
1882             }
1883 
1884             resourceValueData->Count = 1;
1885             fullResourceIndex = 0;
1886         }
1887         else
1888         {
1889             resourceValueData = NULL;
1890         }
1891 
1892         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_RESOURCE), hwnd, modify_resource_dlgproc) == IDOK)
1893         {
1894         }
1895     }
1896     else if (EditBin == FALSE && type == REG_RESOURCE_REQUIREMENTS_LIST)
1897     {
1898         if (valueDataLen > 0)
1899         {
1900             requirementsValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + sizeof(ULONG));
1901             if (requirementsValueData == NULL)
1902             {
1903                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1904                 goto done;
1905             }
1906 
1907             lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)requirementsValueData, &valueDataLen);
1908             if (lRet != ERROR_SUCCESS)
1909             {
1910                 error(hwnd, IDS_BAD_VALUE, valueName);
1911                 goto done;
1912             }
1913 
1914         }
1915         else
1916         {
1917             requirementsValueData = NULL;
1918         }
1919 
1920         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_REQUIREMENTS_LIST), hwnd, modify_requirements_list_dlgproc) == IDOK)
1921         {
1922         }
1923     }
1924     else if ((EditBin != FALSE) || (type == REG_NONE) || (type == REG_BINARY))
1925     {
1926         if(valueDataLen > 0)
1927         {
1928             if(!(binValueData = HeapAlloc(GetProcessHeap(), 0, valueDataLen + 1)))
1929             {
1930                 error(hwnd, IDS_TOO_BIG_VALUE, valueDataLen);
1931                 goto done;
1932             }
1933 
1934             /* Use the unicode version, so editing strings in binary mode is correct */
1935             lRet = RegQueryValueExW(hKey, valueName,
1936                                     0, 0, (LPBYTE)binValueData, &valueDataLen);
1937             if (lRet != ERROR_SUCCESS)
1938             {
1939                 HeapFree(GetProcessHeap(), 0, binValueData);
1940                 error(hwnd, IDS_BAD_VALUE, valueName);
1941                 goto done;
1942             }
1943         }
1944         else
1945         {
1946             binValueData = NULL;
1947         }
1948 
1949         if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_BIN_DATA), hwnd, modify_binary_dlgproc) == IDOK)
1950         {
1951             /* Use the unicode version, so editing strings in binary mode is correct */
1952             lRet = RegSetValueExW(hKey, valueName,
1953                                   0, type, (LPBYTE)binValueData, valueDataLen);
1954             if (lRet == ERROR_SUCCESS)
1955                 result = TRUE;
1956         }
1957         if(binValueData != NULL)
1958             HeapFree(GetProcessHeap(), 0, binValueData);
1959     }
1960     else
1961     {
1962         error(hwnd, IDS_UNSUPPORTED_TYPE, type);
1963     }
1964 
1965 done:
1966     if (resourceValueData)
1967         HeapFree(GetProcessHeap(), 0, resourceValueData);
1968     resourceValueData = NULL;
1969 
1970     if (stringValueData)
1971         HeapFree(GetProcessHeap(), 0, stringValueData);
1972     stringValueData = NULL;
1973 
1974     if (requirementsValueData)
1975         HeapFree(GetProcessHeap(), 0, requirementsValueData);
1976     requirementsValueData = NULL;
1977 
1978     return result;
1979 }
1980 
1981 static LONG CopyKey(HKEY hDestKey, LPCWSTR lpDestSubKey, HKEY hSrcKey, LPCWSTR lpSrcSubKey)
1982 {
1983     LONG lResult;
1984     DWORD dwDisposition;
1985     HKEY hDestSubKey = NULL;
1986     HKEY hSrcSubKey = NULL;
1987     DWORD dwIndex, dwType, cbName, cbData;
1988     WCHAR szSubKey[256];
1989     WCHAR szValueName[256];
1990     BYTE szValueData[512];
1991 
1992     FILETIME ft;
1993 
1994     /* open the source subkey, if specified */
1995     if (lpSrcSubKey)
1996     {
1997         lResult = RegOpenKeyExW(hSrcKey, lpSrcSubKey, 0, KEY_ALL_ACCESS, &hSrcSubKey);
1998         if (lResult)
1999             goto done;
2000         hSrcKey = hSrcSubKey;
2001     }
2002 
2003     /* create the destination subkey */
2004     lResult = RegCreateKeyExW(hDestKey, lpDestSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
2005                              &hDestSubKey, &dwDisposition);
2006     if (lResult)
2007         goto done;
2008 
2009     /* copy all subkeys */
2010     dwIndex = 0;
2011     do
2012     {
2013         cbName = sizeof(szSubKey) / sizeof(szSubKey[0]);
2014         lResult = RegEnumKeyExW(hSrcKey, dwIndex++, szSubKey, &cbName, NULL, NULL, NULL, &ft);
2015         if (lResult == ERROR_SUCCESS)
2016         {
2017             lResult = CopyKey(hDestSubKey, szSubKey, hSrcKey, szSubKey);
2018             if (lResult)
2019                 goto done;
2020         }
2021     }
2022     while(lResult == ERROR_SUCCESS);
2023 
2024     /* copy all subvalues */
2025     dwIndex = 0;
2026     do
2027     {
2028         cbName = sizeof(szValueName) / sizeof(szValueName[0]);
2029         cbData = sizeof(szValueData) / sizeof(szValueData[0]);
2030         lResult = RegEnumValueW(hSrcKey, dwIndex++, szValueName, &cbName, NULL, &dwType, szValueData, &cbData);
2031         if (lResult == ERROR_SUCCESS)
2032         {
2033             lResult = RegSetValueExW(hDestSubKey, szValueName, 0, dwType, szValueData, cbData);
2034             if (lResult)
2035                 goto done;
2036         }
2037     }
2038     while(lResult == ERROR_SUCCESS);
2039 
2040     lResult = ERROR_SUCCESS;
2041 
2042 done:
2043     if (hSrcSubKey)
2044         RegCloseKey(hSrcSubKey);
2045     if (hDestSubKey)
2046         RegCloseKey(hDestSubKey);
2047     if (lResult != ERROR_SUCCESS)
2048         SHDeleteKey(hDestKey, lpDestSubKey);
2049     return lResult;
2050 }
2051 
2052 static LONG MoveKey(HKEY hDestKey, LPCWSTR lpDestSubKey, HKEY hSrcKey, LPCWSTR lpSrcSubKey)
2053 {
2054     LONG lResult;
2055 
2056     if (!lpSrcSubKey)
2057         return ERROR_INVALID_FUNCTION;
2058 
2059     if (_wcsicmp(lpDestSubKey, lpSrcSubKey) == 0)
2060     {
2061         /* Destination name equals source name */
2062         return ERROR_SUCCESS;
2063     }
2064 
2065     lResult = CopyKey(hDestKey, lpDestSubKey, hSrcKey, lpSrcSubKey);
2066     if (lResult == ERROR_SUCCESS)
2067         SHDeleteKey(hSrcKey, lpSrcSubKey);
2068 
2069     return lResult;
2070 }
2071 
2072 BOOL DeleteKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath)
2073 {
2074     WCHAR msg[128], caption[128];
2075     BOOL result = FALSE;
2076     LONG lRet;
2077     HKEY hKey;
2078 
2079     lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ|KEY_SET_VALUE, &hKey);
2080     if (lRet != ERROR_SUCCESS)
2081     {
2082         error_code_messagebox(hwnd, lRet);
2083         return FALSE;
2084     }
2085 
2086     LoadStringW(hInst, IDS_QUERY_DELETE_KEY_CONFIRM, caption, ARRAY_SIZE(caption));
2087     LoadStringW(hInst, IDS_QUERY_DELETE_KEY_ONE, msg, ARRAY_SIZE(msg));
2088 
2089     if (MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) != IDYES)
2090         goto done;
2091 
2092     lRet = SHDeleteKey(hKeyRoot, keyPath);
2093     if (lRet != ERROR_SUCCESS)
2094     {
2095         error(hwnd, IDS_BAD_KEY, keyPath);
2096         goto done;
2097     }
2098     result = TRUE;
2099 
2100 done:
2101     RegCloseKey(hKey);
2102     return result;
2103 }
2104 
2105 LONG RenameKey(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewName)
2106 {
2107     LPCWSTR s;
2108     LPWSTR lpNewSubKey = NULL;
2109     LONG Ret = 0;
2110     SIZE_T cbNewSubKey;
2111 
2112     if (!lpSubKey)
2113         return Ret;
2114 
2115     s = wcsrchr(lpSubKey, L'\\');
2116     if (s)
2117     {
2118         s++;
2119         cbNewSubKey = (s - lpSubKey + wcslen(lpNewName) + 1) * sizeof(WCHAR);
2120         lpNewSubKey = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, cbNewSubKey);
2121         if (lpNewSubKey != NULL)
2122         {
2123             StringCbCopyNW(lpNewSubKey, cbNewSubKey, lpSubKey, (s - lpSubKey) * sizeof(WCHAR));
2124             StringCbCatW(lpNewSubKey, cbNewSubKey, lpNewName);
2125             lpNewName = lpNewSubKey;
2126         }
2127         else
2128             return ERROR_NOT_ENOUGH_MEMORY;
2129     }
2130 
2131     Ret = MoveKey(hKey, lpNewName, hKey, lpSubKey);
2132 
2133     if (lpNewSubKey)
2134     {
2135         HeapFree(GetProcessHeap(), 0, lpNewSubKey);
2136     }
2137     return Ret;
2138 }
2139 
2140 LONG RenameValue(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpDestValue, LPCWSTR lpSrcValue)
2141 {
2142     LONG lResult;
2143     HKEY hSubKey = NULL;
2144     DWORD dwType, cbData;
2145     BYTE data[512];
2146 
2147     if (lpSubKey)
2148     {
2149         lResult = RegOpenKeyW(hKey, lpSubKey, &hSubKey);
2150         if (lResult != ERROR_SUCCESS)
2151             goto done;
2152         hKey = hSubKey;
2153     }
2154 
2155     cbData = sizeof(data);
2156     lResult = RegQueryValueExW(hKey, lpSrcValue, NULL, &dwType, data, &cbData);
2157     if (lResult != ERROR_SUCCESS)
2158         goto done;
2159 
2160     lResult = RegSetValueExW(hKey, lpDestValue, 0, dwType, data, cbData);
2161     if (lResult != ERROR_SUCCESS)
2162         goto done;
2163 
2164     RegDeleteValue(hKey, lpSrcValue);
2165 
2166 done:
2167     if (hSubKey)
2168         RegCloseKey(hSubKey);
2169     return lResult;
2170 }
2171 
2172 LONG QueryStringValue(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR pszBuffer, DWORD dwBufferLen)
2173 {
2174     LONG lResult;
2175     HKEY hSubKey = NULL;
2176     DWORD cbData, dwType;
2177 
2178     if (lpSubKey)
2179     {
2180         lResult = RegOpenKeyW(hKey, lpSubKey, &hSubKey);
2181         if (lResult != ERROR_SUCCESS)
2182             goto done;
2183         hKey = hSubKey;
2184     }
2185 
2186     cbData = (dwBufferLen - 1) * sizeof(*pszBuffer);
2187     lResult = RegQueryValueExW(hKey, lpValueName, NULL, &dwType, (LPBYTE) pszBuffer, &cbData);
2188     if (lResult != ERROR_SUCCESS)
2189         goto done;
2190     if (dwType != REG_SZ)
2191     {
2192         lResult = -1;
2193         goto done;
2194     }
2195 
2196     pszBuffer[cbData / sizeof(*pszBuffer)] = L'\0';
2197 
2198 done:
2199     if (lResult != ERROR_SUCCESS)
2200         pszBuffer[0] = L'\0';
2201     if (hSubKey)
2202         RegCloseKey(hSubKey);
2203     return lResult;
2204 }
2205 
2206 BOOL GetKeyName(LPWSTR pszDest, size_t iDestLength, HKEY hRootKey, LPCWSTR lpSubKey)
2207 {
2208     LPCWSTR pszRootKey;
2209 
2210     if (hRootKey == HKEY_CLASSES_ROOT)
2211         pszRootKey = L"HKEY_CLASSES_ROOT";
2212     else if (hRootKey == HKEY_CURRENT_USER)
2213         pszRootKey = L"HKEY_CURRENT_USER";
2214     else if (hRootKey == HKEY_LOCAL_MACHINE)
2215         pszRootKey = L"HKEY_LOCAL_MACHINE";
2216     else if (hRootKey == HKEY_USERS)
2217         pszRootKey = L"HKEY_USERS";
2218     else if (hRootKey == HKEY_CURRENT_CONFIG)
2219         pszRootKey = L"HKEY_CURRENT_CONFIG";
2220     else if (hRootKey == HKEY_DYN_DATA)
2221         pszRootKey = L"HKEY_DYN_DATA";
2222     else
2223         return FALSE;
2224 
2225     if (lpSubKey[0])
2226         _snwprintf(pszDest, iDestLength, L"%s\\%s", pszRootKey, lpSubKey);
2227     else
2228         _snwprintf(pszDest, iDestLength, L"%s", pszRootKey);
2229     return TRUE;
2230 }
2231