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