01626080c723c9a4515eeb1cccd902f5432fd1ab
[reactos.git] / base / applications / sdbinst / sdbinst.c
1 /*
2 * PROJECT: ReactOS sdbinst
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Application compatibility database installer
5 * COPYRIGHT: Copyright 2020 Max Korostil (mrmks04@yandex.ru)
6 */
7
8 #include <tchar.h>
9
10 #include <windef.h>
11 #include <winbase.h>
12 #include <winreg.h>
13 #include <strsafe.h>
14 #include <objbase.h>
15 #include <apphelp.h>
16 #include <shlwapi.h>
17
18 #define APPCOMPAT_CUSTOM_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom"
19 #define APPCOMPAT_LAYERS_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom\\Layers"
20 #define APPCOMPAT_INSTALLEDSDB_REG_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB"
21 #define UNINSTALL_REG_PATH L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
22 #define DBPATH_KEY_NAME L"DatabasePath"
23 #define SDB_EXT L".sdb"
24 #define GUID_STR_LENGTH 38
25 #define GUID_SBD_NAME_LENGTH (GUID_STR_LENGTH + ARRAYSIZE(SDB_EXT))
26
27 BOOL SdbUninstallByGuid(_In_ LPWSTR guidSdbStr);
28
29 HRESULT
30 RegisterSdbEntry(
31 _In_ PWCHAR sdbEntryName,
32 _In_ LPCWSTR dbGuid,
33 _In_ ULONGLONG time,
34 _In_ BOOL isInstall,
35 _In_ BOOL isExe)
36 {
37 WCHAR regName[MAX_PATH];
38 HKEY hKey = NULL;
39 LSTATUS status;
40 HRESULT hres;
41
42 hres = StringCchPrintfW(regName, MAX_PATH, L"%ls\\%ls",
43 isExe ? APPCOMPAT_CUSTOM_REG_PATH : APPCOMPAT_LAYERS_REG_PATH,
44 sdbEntryName);
45 if (FAILED(hres))
46 {
47 wprintf(L"StringCchPrintfW error: 0x%08X\n", hres);
48 goto end;
49 }
50
51 // Remove key
52 if (!isInstall)
53 {
54 status = RegDeleteKeyW(HKEY_LOCAL_MACHINE, regName);
55 if (status == ERROR_FILE_NOT_FOUND)
56 {
57 status = ERROR_SUCCESS;
58 }
59
60 return HRESULT_FROM_WIN32(status);
61 }
62
63 // Create main key
64 status = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
65 regName,
66 0,
67 NULL,
68 REG_OPTION_NON_VOLATILE,
69 KEY_ALL_ACCESS,
70 NULL,
71 &hKey,
72 NULL);
73 if (status != ERROR_SUCCESS)
74 {
75 wprintf(L"RegKeyCreateEx error: 0x%08X", status);
76 hres = HRESULT_FROM_WIN32(status);
77 goto end;
78 }
79
80 // Set installed time
81 status = RegSetValueExW(hKey,
82 dbGuid,
83 0,
84 REG_QWORD,
85 (PBYTE)&time,
86 sizeof(time));
87 if (status != ERROR_SUCCESS)
88 {
89 wprintf(L"RegSetValueExW error: 0x%08X", status);
90 hres = HRESULT_FROM_WIN32(status);
91 goto end;
92 }
93
94 end:
95 if (hKey)
96 {
97 RegCloseKey(hKey);
98 }
99
100 return hres;
101 }
102
103 HRESULT
104 AddUninstallKey(
105 _In_ LPCWSTR dbName,
106 _In_ LPCWSTR sdbInstalledPath,
107 _In_ LPCWSTR guidDbStr)
108 {
109 WCHAR sdbinstPath[MAX_PATH];
110 WCHAR regName[MAX_PATH];
111 WCHAR uninstString[MAX_PATH];
112 HKEY hKey = NULL;
113 HRESULT hres;
114
115 UINT count = GetSystemWindowsDirectory(sdbinstPath, MAX_PATH);
116 if (sdbinstPath[count - 1] != L'\\')
117 {
118 hres = StringCchCatW(sdbinstPath, MAX_PATH, L"\\");
119 if (FAILED(hres))
120 {
121 wprintf(L"StringCchCatW error: 0x%08X", hres);
122 goto end;
123 }
124 }
125
126 // Full path to sdbinst.exe
127 hres = StringCchCatW(sdbinstPath, MAX_PATH, L"System32\\sdbinst.exe");
128 if (FAILED(hres))
129 {
130 wprintf(L"StringCchCatW error: 0x%08X", hres);
131 goto end;
132 }
133
134 // Sdb GUID registry key
135 hres = StringCchPrintfW(regName, MAX_PATH, L"%ls\\%ls", UNINSTALL_REG_PATH, guidDbStr);
136 if (FAILED(hres))
137 {
138 wprintf(L"StringCchPrintfW error: 0x%08X", hres);
139 goto end;
140 }
141
142 // Create main key
143 LSTATUS status = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
144 regName,
145 0,
146 NULL,
147 REG_OPTION_NON_VOLATILE,
148 KEY_ALL_ACCESS,
149 NULL,
150 &hKey,
151 NULL);
152
153 if (status != ERROR_SUCCESS)
154 {
155 wprintf(L"RegKeyCreateEx error: 0x%08X", status);
156 hres = HRESULT_FROM_WIN32(status);
157 goto end;
158 }
159
160 // Set Display name
161 DWORD length = wcslen(dbName) * sizeof(WCHAR);
162 status = RegSetValueExW(hKey,
163 L"DisplayName",
164 0,
165 REG_SZ,
166 (PBYTE)dbName,
167 length + sizeof(WCHAR));
168 if (status != ERROR_SUCCESS)
169 {
170 wprintf(L"RegSetValueExW error: 0x%08X", status);
171 hres = HRESULT_FROM_WIN32(status);
172 goto end;
173 }
174
175 // Uninstall full string
176 hres = StringCchPrintfW(uninstString, MAX_PATH, L"%ls -u \"%ls\"", sdbinstPath, sdbInstalledPath);
177 if (FAILED(hres))
178 {
179 wprintf(L"StringCchPrintfW error: 0x%08X", hres);
180 goto end;
181 }
182
183 // Set uninstall string
184 length = wcslen(uninstString) * sizeof(WCHAR);
185 status = RegSetValueExW(hKey,
186 L"UninstallString",
187 0,
188 REG_SZ,
189 (PBYTE)uninstString,
190 length + sizeof(WCHAR));
191 if (status != ERROR_SUCCESS)
192 {
193 wprintf(L"RegSetValueExW error: 0x%08X", status);
194 hres = HRESULT_FROM_WIN32(status);
195 goto end;
196 }
197
198 end:
199 if (hKey)
200 {
201 RegCloseKey(hKey);
202 }
203
204 return hres;
205 }
206
207 //
208 // Get database GUID id
209 //
210 BOOL
211 GetSdbGuid(
212 _In_ PDB pdb,
213 _In_ TAGID tagDb,
214 _Out_ GUID* guid)
215 {
216 TAGID tagDbId;
217
218 tagDbId = SdbFindFirstTag(pdb, tagDb, TAG_DATABASE_ID);
219 if (!tagDbId)
220 {
221 wprintf(L"Can't find database id tag");
222 return FALSE;
223 }
224
225 if (!SdbReadBinaryTag(pdb, tagDbId, (PBYTE)guid, sizeof(GUID)))
226 {
227 wprintf(L"Can't read database id");
228 return FALSE;
229 }
230
231 return TRUE;
232 }
233
234 HRESULT
235 ProcessLayers(
236 _In_ PDB pdb,
237 _In_ TAGID tagDb,
238 _In_opt_ LPCWSTR guidDbStr,
239 _In_opt_ ULONGLONG time,
240 _In_ BOOL isInstall)
241 {
242 HRESULT res = ERROR_SUCCESS;
243 TAGID tagLayerName;
244 TAGID prevTagLayer = 0;
245
246 TAGID tagLayer = SdbFindFirstTag(pdb, tagDb, TAG_LAYER);
247
248 // Add all layers to registry (AppCompatFlags)
249 while (tagLayer && (tagLayer != prevTagLayer))
250 {
251 tagLayerName = SdbFindFirstTag(pdb, tagLayer, TAG_NAME);
252 if (!tagLayerName)
253 {
254 res = ERROR_NOT_FOUND;
255 break;
256 }
257
258 LPWSTR name = SdbGetStringTagPtr(pdb, tagLayerName);
259
260 res = RegisterSdbEntry(name, guidDbStr, time, isInstall, FALSE);
261 if (FAILED(res))
262 {
263 wprintf(L"Can't register layer\n");
264 break;
265 }
266
267 prevTagLayer = tagLayer;
268 tagLayer = SdbFindNextTag(pdb, tagDb, tagLayer);
269 }
270
271 return res;
272 }
273
274 HRESULT
275 ProcessExe(
276 _In_ PDB pdb,
277 _In_ TAGID tagDb,
278 _In_opt_ LPCWSTR guidDbStr,
279 _In_opt_ ULONGLONG time,
280 _In_ BOOL isInstall)
281 {
282 HRESULT res = ERROR_SUCCESS;
283 TAGID tagExeName;
284 TAGID tagExePrev = 0;
285
286 TAGID tagExe = SdbFindFirstTag(pdb, tagDb, TAG_EXE);
287
288 // Add all exe to registry (AppCompatFlags)
289 while (tagExe != 0 && (tagExe != tagExePrev))
290 {
291 tagExeName = SdbFindFirstTag(pdb, tagExe, TAG_NAME);
292 if (!tagExeName)
293 {
294 wprintf(L"Can't find exe tag\n");
295 res = ERROR_NOT_FOUND;
296 break;
297 }
298
299 LPWSTR name = SdbGetStringTagPtr(pdb, tagExeName);
300
301 res = RegisterSdbEntry(name, guidDbStr, time, isInstall, TRUE);
302 if (FAILED(res))
303 {
304 wprintf(L"Can't register exe 0x%08X\n", res);
305 break;
306 }
307
308 tagExePrev = tagExe;
309 tagExe = SdbFindNextTag(pdb, tagDb, tagExe);
310 }
311
312 return res;
313 }
314
315 HRESULT
316 CopySdbToAppPatch(
317 _In_ LPCWSTR sourceSdbPath,
318 _In_ LPCWSTR destSdbPath)
319 {
320 DWORD error = ERROR_SUCCESS;
321 PWCHAR pTmpSysdir = NULL;
322 SIZE_T destLen = wcslen(destSdbPath);
323 PWCHAR sysdirPath = (PWCHAR)HeapAlloc(GetProcessHeap(), 0, destLen * sizeof(WCHAR));
324
325 if (sysdirPath == NULL)
326 {
327 error = ERROR_NOT_ENOUGH_MEMORY;
328 goto end;
329 }
330
331 // Get parent folder fo sdb file
332 CopyMemory(sysdirPath, destSdbPath, destLen * sizeof(WCHAR));
333 pTmpSysdir = StrRChrW(sysdirPath, sysdirPath + destLen, L'\\');
334 if (pTmpSysdir == NULL)
335 {
336 wprintf(L"Can't find directory separator\n");
337 goto end;
338 }
339 else
340 {
341 *pTmpSysdir = UNICODE_NULL;
342 }
343
344 // Create directory if need
345 if (!CreateDirectory(sysdirPath, NULL))
346 {
347 error = GetLastError();
348 if (error != ERROR_ALREADY_EXISTS)
349 {
350 wprintf(L"Can't create folder %ls\n Error: 0x%08X\n", sysdirPath, error);
351 goto end;
352 }
353 error = ERROR_SUCCESS;
354 }
355
356 // Copy file
357 if (!CopyFile(sourceSdbPath, destSdbPath, TRUE))
358 {
359 error = GetLastError();
360 wprintf(L"Can't copy sdb file");
361 }
362
363 end:
364 if (sysdirPath)
365 {
366 HeapFree(GetProcessHeap(), 0, sysdirPath);
367 }
368
369 return HRESULT_FROM_WIN32(error);
370 }
371
372 HRESULT
373 BuildPathToSdb(
374 _In_ PWCHAR buffer,
375 _In_ SIZE_T bufLen,
376 _In_ LPCWSTR guidDbStr)
377 {
378 ZeroMemory(buffer, bufLen * sizeof(WCHAR));
379
380 // Can't use here SdbGetAppPatchDir, because Windows XP haven't this function
381 UINT count = GetSystemWindowsDirectory(buffer, bufLen);
382 if (buffer[count - 1] != L'\\')
383 {
384 buffer[count] = L'\\';
385 }
386
387 HRESULT res = StringCchCatW(buffer, bufLen, L"AppPatch\\Custom\\");
388 if (FAILED(res))
389 {
390 goto end;
391 }
392
393 res = StringCchCatW(buffer, bufLen, guidDbStr);
394
395 end:
396 return res;
397 }
398
399 BOOL
400 SdbInstall(
401 _In_ LPCWSTR sdbPath)
402 {
403 BOOL res = FALSE;
404 PDB pdb = NULL;
405 TAGID tagDb;
406 TAGID tagDbName;
407 GUID dbGuid = {0};
408 FILETIME systemTime = {0};
409 ULARGE_INTEGER currentTime = {0};
410 WCHAR sysdirPatchPath[MAX_PATH];
411 WCHAR guidDbStr[GUID_SBD_NAME_LENGTH];
412
413 GetSystemTimeAsFileTime(&systemTime);
414 currentTime.LowPart = systemTime.dwLowDateTime;
415 currentTime.HighPart = systemTime.dwHighDateTime;
416
417 // Open database
418 pdb = SdbOpenDatabase(sdbPath, DOS_PATH);
419 if (pdb == NULL)
420 {
421 wprintf(L"Can't open database %ls\n", sdbPath);
422 goto end;
423 }
424
425 tagDb = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
426 if (!tagDb)
427 {
428 wprintf(L"Can't find database tag\n");
429 goto end;
430 }
431
432 // Get database GUID
433 if (!GetSdbGuid(pdb, tagDb, &dbGuid))
434 {
435 wprintf(L"GetSdbGuid error\n");
436 goto end;
437 }
438
439 StringFromGUID2(&dbGuid, guidDbStr, GUID_SBD_NAME_LENGTH);
440 HRESULT hres = StringCchCatW(guidDbStr, GUID_SBD_NAME_LENGTH, SDB_EXT);
441 if (FAILED(hres))
442 {
443 wprintf(L"StringCchCatW error 0x%08X\n", hres);
444 goto end;
445 }
446
447 wprintf(L"Database guid %ls\n", guidDbStr);
448
449 tagDbName = SdbFindFirstTag(pdb, tagDb, TAG_NAME);
450 if (!tagDbName)
451 {
452 wprintf(L"Can't get tag name\n");
453 goto end;
454 }
455
456 LPWSTR dbName = SdbGetStringTagPtr(pdb, tagDbName);
457 wprintf(L"Database name %ls\n", dbName);
458
459 // Process exe tags
460 hres = ProcessExe(pdb, tagDb, guidDbStr, currentTime.QuadPart, TRUE);
461 if (FAILED(hres))
462 {
463 wprintf(L"Process exe failed. Status: 0x%08X", res);
464 goto end;
465 }
466
467 // Proess layer tags
468 hres = ProcessLayers(pdb, tagDb, guidDbStr, currentTime.QuadPart, TRUE);
469 if (FAILED(hres))
470 {
471 wprintf(L"Process layers failed. Status: 0x%08X", res);
472 goto end;
473 }
474
475 // Create full path to sdb in system folder
476 hres = BuildPathToSdb(sysdirPatchPath, ARRAYSIZE(sysdirPatchPath), guidDbStr);
477 if (FAILED(hres))
478 {
479 wprintf(L"Build path error\n");
480 goto end;
481 }
482
483 wprintf(L"file path %ls\n", sysdirPatchPath);
484
485 res = CopySdbToAppPatch(sdbPath, sysdirPatchPath);
486 if (FAILED(res))
487 {
488 wprintf(L"Copy sdb error. Status: 0x%08X\n", res);
489 goto end;
490 }
491
492 AddUninstallKey(dbName, sysdirPatchPath, guidDbStr);
493
494 // Registration
495 if (!SdbRegisterDatabaseEx(sysdirPatchPath, SDB_DATABASE_SHIM, &currentTime.QuadPart))
496 {
497 wprintf(L"SdbRegisterDatabaseEx failed");
498 goto end;
499 }
500
501 res = TRUE;
502
503 end:
504 if (pdb)
505 {
506 SdbCloseDatabase(pdb);
507 }
508
509 return res;
510 }
511
512 HRESULT
513 DeleteUninstallKey(
514 _In_ LPCWSTR keyName)
515 {
516 HKEY hKey = NULL;
517 HRESULT hres = HRESULT_FROM_WIN32(ERROR_SUCCESS);
518
519 LSTATUS status = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
520 UNINSTALL_REG_PATH,
521 0,
522 NULL,
523 REG_OPTION_NON_VOLATILE,
524 KEY_ALL_ACCESS,
525 NULL,
526 &hKey,
527 NULL);
528
529 if (status != ERROR_SUCCESS)
530 {
531 hres = HRESULT_FROM_WIN32(status);
532 goto end;
533 }
534
535 status = RegDeleteKeyW(hKey, keyName);
536 if (status != ERROR_SUCCESS)
537 {
538 hres = HRESULT_FROM_WIN32(status);
539 }
540
541 end:
542 if (hKey)
543 {
544 RegCloseKey(hKey);
545 }
546
547 return hres;
548 }
549
550 BOOL
551 SdbUninstall(
552 _In_ LPWSTR sdbPath)
553 {
554 BOOL res = FALSE;
555 PWCHAR sdbName = NULL;
556 PDB pdb;
557 TAGID tagDb;
558 GUID dbGuid = {0};
559 WCHAR guidDbStr[GUID_SBD_NAME_LENGTH];
560
561 SIZE_T sdbPathLen = wcslen(sdbPath);
562 sdbName = sdbPath + sdbPathLen;
563
564 wprintf(L"uninstall path %ls\n", sdbPath);
565 sdbName = StrRChrW(sdbPath, sdbPath + sdbPathLen, L'\\');
566 if (sdbName == NULL)
567 {
568 sdbName = sdbPath;
569 }
570 else
571 {
572 sdbName++;
573 }
574
575 wprintf(L"uninstall name %ls\n", sdbName);
576
577 // open sdb
578 pdb = SdbOpenDatabase(sdbPath, DOS_PATH);
579 if (pdb == NULL)
580 {
581 wprintf(L"Can't open database %ls\n", sdbPath);
582 return FALSE;
583 }
584
585 tagDb = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
586 if (!tagDb)
587 {
588 wprintf(L"Can't find database tag\n");
589 goto end;
590 }
591
592 if (!GetSdbGuid(pdb, tagDb, &dbGuid))
593 {
594 wprintf(L"GetSdbGuid error\n");
595 goto end;
596 }
597
598 // Database name must be GUID string
599 if (wcslen(sdbName) + 1 != GUID_SBD_NAME_LENGTH)
600 {
601 StringFromGUID2(&dbGuid, guidDbStr, GUID_SBD_NAME_LENGTH);
602 SdbCloseDatabase(pdb);
603 return SdbUninstallByGuid(guidDbStr);
604 }
605
606 //remove regkey in appatch/custom
607 HRESULT hres = ProcessExe(pdb, tagDb, NULL, 0, FALSE);
608 if (FAILED(hres))
609 {
610 wprintf(L"Process exe fail\n");
611 goto end;
612 }
613
614 hres = ProcessLayers(pdb, tagDb, NULL, 0, FALSE);
615 if (FAILED(hres))
616 {
617 wprintf(L"Process layers fail\n");
618 goto end;
619 }
620
621 SdbCloseDatabase(pdb);
622 pdb = NULL;
623
624 hres = DeleteUninstallKey(sdbName);
625 if (FAILED(hres))
626 {
627 wprintf(L"Remove uninstall key fail\n");
628 }
629
630 if (!SdbUnregisterDatabase(&dbGuid))
631 {
632 wprintf(L"SdbUnregisterDatabase\n");
633 return FALSE;
634 }
635
636 SetFileAttributesW(sdbPath, FILE_ATTRIBUTE_NORMAL);
637 if (!DeleteFileW(sdbPath))
638 {
639 wprintf(L"Remove file fail 0x%08X\n", GetLastError());
640 return FALSE;
641 }
642
643 res = TRUE;
644
645 end:
646 if (pdb)
647 SdbCloseDatabase(pdb);
648 return res;
649 }
650
651 BOOL
652 ValidateGuidString(
653 _In_ PWCHAR guidStr)
654 {
655 ULONG length = wcslen(guidStr);
656
657 if (length == GUID_STR_LENGTH &&
658 guidStr[0] == L'{' &&
659 guidStr[GUID_STR_LENGTH - 1] == L'}' &&
660 guidStr[9] == L'-' &&
661 guidStr[14] == L'-' &&
662 guidStr[19] == L'-' &&
663 guidStr[24] == L'-')
664 {
665 return TRUE;
666 }
667
668 return FALSE;
669 }
670
671 BOOL
672 SdbUninstallByGuid(
673 _In_ LPWSTR guidSdbStr)
674 {
675 BOOL res = FALSE;
676 HKEY hKey = NULL;
677 HKEY guidKey = NULL;
678 LSTATUS status;
679 WCHAR dbPath[MAX_PATH];
680 DWORD keyValSize = sizeof(dbPath);
681
682 if (!ValidateGuidString(guidSdbStr))
683 {
684 wprintf(L"Invalid GUID: %ls\n", guidSdbStr);
685 return res;
686 }
687
688 status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, APPCOMPAT_INSTALLEDSDB_REG_PATH, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
689
690 if (status != ERROR_SUCCESS)
691 {
692 wprintf(L"RegOpenKeyW error: 0x%08X", status);
693 goto end;
694 }
695
696 status = RegOpenKeyExW(hKey, guidSdbStr, 0, KEY_READ | KEY_QUERY_VALUE, &guidKey);
697
698 if (status != ERROR_SUCCESS)
699 {
700 wprintf(L"Cant open key: 0x%08X %ls\n", status, guidSdbStr);
701 goto end;
702 }
703
704 status = RegQueryValueExW(guidKey, DBPATH_KEY_NAME, NULL, NULL, (LPBYTE)dbPath, &keyValSize);
705 if (status != ERROR_SUCCESS)
706 {
707 wprintf(L"RegQueryValueExW: 0x%08X\n", status);
708 goto end;
709 }
710
711 res = SdbUninstall(dbPath);
712
713 end:
714 if (hKey)
715 {
716 RegCloseKey(hKey);
717 }
718
719 if (guidKey)
720 {
721 RegCloseKey(guidKey);
722 }
723
724 return res;
725 }
726
727 BOOL
728 SdbUninstallByName(
729 _In_ LPWSTR nameSdbStr)
730 {
731 BOOL res = FALSE;
732 LSTATUS status;
733 HKEY hKey = NULL;
734 HKEY subKey = NULL;
735 DWORD index = 0;
736 WCHAR keyName[MAX_PATH];
737 DWORD keyNameLen = ARRAYSIZE(keyName);
738 DWORD keyValSize;
739 WCHAR dbDescript[MAX_PATH];
740 WCHAR dbPath[MAX_PATH];
741
742 status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, APPCOMPAT_INSTALLEDSDB_REG_PATH, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
743
744 if (status != ERROR_SUCCESS)
745 {
746 wprintf(L"RegOpenKeyW error: 0x%08X", status);
747 goto end;
748 }
749
750 status = RegEnumKeyEx(hKey, index, keyName, &keyNameLen, NULL, NULL, NULL, NULL);
751 wprintf(L"0x%08X %d %ls \n", status, keyNameLen, keyName);
752
753 // Search database GUID by name
754 while (status == ERROR_SUCCESS)
755 {
756 status = RegOpenKeyExW(hKey, keyName, 0, KEY_READ | KEY_QUERY_VALUE, &subKey);
757 if (status != ERROR_SUCCESS)
758 {
759 break;
760 }
761
762 keyValSize = sizeof(dbDescript);
763 status = RegQueryValueExW(subKey, L"DatabaseDescription", NULL, NULL, (LPBYTE)dbDescript, &keyValSize);
764 if (status != ERROR_SUCCESS)
765 {
766 break;
767 }
768
769 wprintf(L"dbdescript: %ls \n", dbDescript);
770
771 if (_wcsnicmp(dbDescript, nameSdbStr, keyNameLen) == 0)
772 {
773 // Take db full path
774 keyValSize = sizeof(dbPath);
775 status = RegQueryValueExW(subKey, DBPATH_KEY_NAME, NULL, NULL, (LPBYTE)dbPath, &keyValSize);
776 if (status != ERROR_SUCCESS)
777 {
778 dbPath[0] = UNICODE_NULL;
779 break;
780 }
781
782 wprintf(L"dbpath: 0x%08X %ls \n", status, dbPath);
783 RegCloseKey(subKey);
784 break;
785 }
786
787 RegCloseKey(subKey);
788
789 keyName[0] = UNICODE_NULL;
790
791 ++index;
792 keyNameLen = ARRAYSIZE(keyName);
793 status = RegEnumKeyExW(hKey, index, keyName, &keyNameLen, NULL, NULL, NULL, NULL);
794 }
795
796 RegCloseKey(hKey);
797
798 if (dbPath[0] != UNICODE_NULL)
799 {
800 res = SdbUninstall(dbPath);
801 }
802
803 end:
804 return res;
805 }
806
807
808 void
809 ShowHelp()
810 {
811 /* FIXME: to be localized */
812 wprintf(L"Using: sdbinst [-?][-q][-u][-g][-n] foo.sdb | {guid} | \"name\" \n"
813 L"-? - show help\n"
814 L"-u - uninstall\n"
815 L"-g - {guid} file GUID (only uninstall)\n"
816 L"-n - \"name\" - file name (only uninstall)\n");
817 }
818
819 int _tmain(int argc, LPWSTR argv[])
820 {
821 LPWSTR sdbPath = NULL;
822 BOOL isInstall = TRUE;
823 BOOL isUninstByGuid = FALSE;
824 BOOL isUninstByName = FALSE;
825 BOOL success = FALSE;
826 LPWSTR guidSdbStr = NULL;
827 LPWSTR nameSdbStr = NULL;
828
829 if (argc < 2)
830 {
831 ShowHelp();
832 }
833
834 for (int i = 1; i < argc; ++i)
835 {
836 if (argv[i][0] != L'-')
837 {
838 sdbPath = argv[i];
839 break;
840 }
841
842 switch (argv[i][1])
843 {
844 case L'?':
845 ShowHelp();
846 return ERROR_SUCCESS;
847 break;
848
849 case L'u':
850 isInstall = FALSE;
851 break;
852
853 case L'g':
854 ++i;
855
856 if (i >= argc)
857 {
858 return ERROR_INVALID_PARAMETER;
859 }
860
861 guidSdbStr = argv[i];
862 wprintf(L"guidSdbStr %ls\n", guidSdbStr);
863
864 isUninstByGuid = TRUE;
865 isInstall = FALSE;
866 break;
867
868 case L'n':
869 ++i;
870
871 if (i >= argc)
872 {
873 return ERROR_INVALID_PARAMETER;
874 }
875
876 nameSdbStr = argv[i];
877 wprintf(L"nameSdbStr %ls\n", nameSdbStr);
878
879 isUninstByName = TRUE;
880 isInstall = FALSE;
881 break;
882 }
883 }
884
885 if (isInstall)
886 {
887 wprintf(L"install\n");
888 success = SdbInstall(sdbPath);
889 }
890 else if (isUninstByGuid)
891 {
892 wprintf(L"uninstall by GUID\n");
893 success = SdbUninstallByGuid(guidSdbStr);
894 }
895 else if (isUninstByName)
896 {
897 wprintf(L"uninstall by name\n");
898 success = SdbUninstallByName(nameSdbStr);
899 }
900 else
901 {
902 wprintf(L"uninstall\n");
903 success = SdbUninstall(sdbPath);
904 }
905
906 if (!success)
907 {
908 wprintf(isInstall ? L"Sdb install failed\n" : L"Sdb uninstall failed\n");
909 return -1;
910 }
911
912 return ERROR_SUCCESS;
913 }