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