From c16aeaf8e560dae85c7d7bb649ecf6bd197b7c82 Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Mon, 21 Jul 2008 19:42:25 +0100 Subject: [PATCH] appwiz.cpl: Read installed application information from registry. --- dlls/appwiz.cpl/appwiz.c | 244 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/dlls/appwiz.cpl/appwiz.c b/dlls/appwiz.cpl/appwiz.c index 4bf86a9e1ed..4cbcf79a024 100644 --- a/dlls/appwiz.cpl/appwiz.c +++ b/dlls/appwiz.cpl/appwiz.c @@ -48,8 +48,44 @@ WINE_DEFAULT_DEBUG_CHANNEL(appwizcpl); /* define a maximum length for various buffers we use */ #define MAX_STRING_LEN 1024 +typedef struct APPINFO { + int id; + + LPWSTR title; + LPWSTR path; + + LPWSTR icon; + int iconIdx; + + LPWSTR publisher; + LPWSTR version; + + HKEY regroot; + WCHAR regkey[MAX_STRING_LEN]; + + struct APPINFO *next; +} APPINFO; + +static struct APPINFO *AppInfo = NULL; static HINSTANCE hInst; +/* names of registry keys */ +static const WCHAR BackSlashW[] = { '\\', 0 }; +static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; +static const WCHAR DisplayIconW[] = {'D','i','s','p','l','a','y','I','c','o','n',0}; +static const WCHAR DisplayVersionW[] = {'D','i','s','p','l','a','y','V','e','r', + 's','i','o','n',0}; +static const WCHAR PublisherW[] = {'P','u','b','l','i','s','h','e','r',0}; +static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l', + 'S','t','r','i','n','g',0}; + +static const WCHAR PathUninstallW[] = { + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'U','n','i','n','s','t','a','l','l',0 }; + /****************************************************************************** * Name : DllMain * Description: Entry point for DLL file @@ -68,6 +104,205 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, return TRUE; } +/****************************************************************************** + * Name : FreeAppInfo + * Description: Frees memory used by an AppInfo structure, and any children. + */ +static void FreeAppInfo(APPINFO *info) +{ + APPINFO *iter = info; + + while (iter) + { + if (iter->title) + HeapFree(GetProcessHeap(), 0, iter->title); + + if (iter->path) + HeapFree(GetProcessHeap(), 0, iter->path); + + if (iter->icon) + HeapFree(GetProcessHeap(), 0, iter->icon); + + if (iter->publisher) + HeapFree(GetProcessHeap(), 0, iter->publisher); + + if (iter->version) + HeapFree(GetProcessHeap(), 0, iter->version); + + iter = iter->next; + HeapFree(GetProcessHeap(), 0, iter); + } +} + +/****************************************************************************** + * Name : ReadApplicationsFromRegistry + * Description: Creates a linked list of uninstallable applications from the + * registry. + * Parameters : root - Which registry root to read from (HKCU/HKLM) + * Returns : TRUE if successful, FALSE otherwise + */ +static BOOL ReadApplicationsFromRegistry(HKEY root) +{ + HKEY hkeyUninst, hkeyApp; + int i, id = 0; + DWORD sizeOfSubKeyName, displen, uninstlen; + WCHAR subKeyName[256]; + WCHAR key_app[MAX_STRING_LEN]; + WCHAR *p; + APPINFO *iter = AppInfo; + LPWSTR iconPtr; + BOOL ret = FALSE; + + if (RegOpenKeyExW(root, PathUninstallW, 0, KEY_READ, &hkeyUninst) != + ERROR_SUCCESS) + return FALSE; + + lstrcpyW(key_app, PathUninstallW); + lstrcatW(key_app, BackSlashW); + p = key_app+lstrlenW(PathUninstallW)+1; + + sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]); + + if (iter) + { + /* find the end of the list */ + for (iter = AppInfo; iter->next; iter = iter->next); + } + + for (i = 0; RegEnumKeyExW(hkeyUninst, i, subKeyName, &sizeOfSubKeyName, NULL, + NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS; ++i) + { + lstrcpyW(p, subKeyName); + RegOpenKeyExW(root, key_app, 0, KEY_READ, &hkeyApp); + + displen = 0; + uninstlen = 0; + + if ((RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen) == + ERROR_SUCCESS) && (RegQueryValueExW(hkeyApp, UninstallCommandlineW, + 0, 0, NULL, &uninstlen) == ERROR_SUCCESS)) + { + /* if we already have iter, allocate the next entry */ + if (iter) + { + iter->next = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(struct APPINFO)); + + if (!iter->next) + goto err; + + iter = iter->next; + } + else + { + /* if not, start the list */ + iter = AppInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(struct APPINFO)); + + if (!iter) + goto err; + } + + iter->title = HeapAlloc(GetProcessHeap(), 0, displen); + + if (!iter->title) + goto err; + + RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)iter->title, + &displen); + + /* now get DisplayIcon */ + displen = 0; + RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, NULL, &displen); + + if (displen == 0) + iter->icon = 0; + else + { + iter->icon = HeapAlloc(GetProcessHeap(), 0, displen); + + if (!iter->icon) + goto err; + + RegQueryValueExW(hkeyApp, DisplayIconW, 0, 0, (LPBYTE)iter->icon, + &displen); + + /* separate the index from the icon name, if supplied */ + iconPtr = strchrW(iter->icon, ','); + + if (iconPtr) + { + *iconPtr++ = 0; + iter->iconIdx = atoiW(iconPtr); + } + } + + iter->path = HeapAlloc(GetProcessHeap(), 0, uninstlen); + + if (!iter->path) + goto err; + + RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, + (LPBYTE)iter->path, &uninstlen); + + /* publisher, version */ + if (RegQueryValueExW(hkeyApp, PublisherW, 0, 0, NULL, &displen) == + ERROR_SUCCESS) + { + iter->publisher = HeapAlloc(GetProcessHeap(), 0, displen); + + if (!iter->publisher) + goto err; + + RegQueryValueExW(hkeyApp, PublisherW, 0, 0, (LPBYTE)iter->publisher, + &displen); + } + + if (RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, NULL, &displen) == + ERROR_SUCCESS) + { + iter->version = HeapAlloc(GetProcessHeap(), 0, displen); + + if (!iter->version) + goto err; + + RegQueryValueExW(hkeyApp, DisplayVersionW, 0, 0, (LPBYTE)iter->version, + &displen); + } + + /* registry key */ + iter->regroot = root; + lstrcpyW(iter->regkey, subKeyName); + + iter->id = id++; + } + + RegCloseKey(hkeyApp); + sizeOfSubKeyName = sizeof(subKeyName) / sizeof(subKeyName[0]); + } + + ret = TRUE; + goto end; + +err: + RegCloseKey(hkeyApp); + FreeAppInfo(iter); + +end: + RegCloseKey(hkeyUninst); + return ret; +} + +/****************************************************************************** + * Name : EmptyList + * Description: Frees memory used by the application linked list. + */ +static inline void EmptyList(void) +{ + FreeAppInfo(AppInfo); + AppInfo = NULL; +} + /****************************************************************************** * Name : UpdateButtons * Description: Enables/disables the Add/Remove button depending on current @@ -175,11 +410,18 @@ static HIMAGELIST ResetApplicationList(BOOL bFirstRun, HWND hWnd, HIMAGELIST hIm else /* we need to remove the existing things first */ { ImageList_Destroy(hImageList); + + /* reset the list, since it's probably changed if the uninstallation was + successful */ + EmptyList(); } /* now create the image list and add the applications to the listview */ hImageList = AddListViewImageList(hWndListView); + ReadApplicationsFromRegistry(HKEY_LOCAL_MACHINE); + ReadApplicationsFromRegistry(HKEY_CURRENT_USER); + UpdateButtons(hWnd); return(hImageList); @@ -211,6 +453,8 @@ static BOOL CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar case WM_DESTROY: ImageList_Destroy(hImageList); + EmptyList(); + return 0; }