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