Le mardi 08 mars 2005 Ã 23:29 +0800, Dmitry Timoshkov a Ãcrit :
> "Jonathan Ernst" <[EMAIL PROTECTED]> wrote:
> 
> [...]

Thanks, fixed.

> You can't use toupper with unicode strings. I can't suggest a win32 equivalent
> from the top of my head, you need to find out.

It seems that CharUpperW works well.

[...]

> > Last but not least, since these changes the uninstaller crashes (very)
> > often. I have an unhandled exception when retrieving some apps from the
> > uninstall key and I don't know what cause this:
> > 
> > err:seh:EXC_DefaultHandling Unhandled exception code c0000005 flags 0
> > addr 0x77ecf5d4
> 
> Very likely a common error happening often in the process of unicodification:
> buffer overflow due to not a correct memory allocation, or a not correct
> initialization of a variable pointing to a buffer length (size of buffer in
> bytes vs. WCHARs).

Thanks for the hint. I found the allocation problem.

[...]

Fixed

Now everything works; thanks for your step by step help; I hope that
what I'me learning now will let me make more additions to Wine !

But: 

It is even possible to uninstall more than one app at a time, but I wish
that when an uninstaller has finished to uninstall an application the
list is updated, but it's not. What's and where's a clean way to do it ?

Please find attached main.c's diff.

Jonathan

P.S. Do I really have to split this new uninstaller in different patches
as nearly everything changed ?
Index: main.c
===================================================================
RCS file: /home/wine/wine/programs/uninstaller/main.c,v
retrieving revision 1.19
diff -u -r1.19 main.c
--- main.c	9 Dec 2004 14:07:59 -0000	1.19
+++ main.c	8 Mar 2005 16:40:50 -0000
@@ -1,8 +1,9 @@
 /*
- * Q&D Uninstaller (main.c)
+ * Uninstaller
  *
  * Copyright 2000 Andreas Mohr <[EMAIL PROTECTED]>
  * Copyright 2004 Hannu Valtonen <[EMAIL PROTECTED]>
+ * Copyright 2005 Jonathan Ernst <[EMAIL PROTECTED]>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,104 +19,94 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * ToDo:
- * - add search box for locating entries quickly
  */
 
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <time.h>
-#include <windows.h>
-#include "main.h"
+#include <windows.h>
+#include "resource.h" 
 #include "regstr.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(uninstaller);
-
-/* Work around a Wine bug which defines handles as UINT rather than LPVOID */
-#ifdef WINE_STRICT
-#define NULL_HANDLE NULL
-#else
-#define NULL_HANDLE 0
-#endif
-
-/* use multi-select listbox */
-#undef USE_MULTIPLESEL
-
-/* Delete uninstall registry key after execution.
- * This is probably a bad idea, because it's the
- * uninstall program that is supposed to do that.
- */
-#undef DEL_REG_KEY
-
-char appname[18];
 
-static char about_string[] =
-    "Wine Application Uninstaller (C) 2004 by Andreas Mohr <[EMAIL PROTECTED]> and Hannu Valtonen <[EMAIL PROTECTED]>";
-static char program_description[] =
-	"Please select the application you wish to uninstall:";
+WINE_DEFAULT_DEBUG_CHANNEL(uninstaller);
 
 typedef struct {
-    char *key;
+    WCHAR *key;
     WCHAR *descr;
-    char *command;
+    WCHAR *command;
     int active;
 } uninst_entry;
+static uninst_entry *entries = NULL;
+static unsigned int numentries = 0;
+static int list_need_update = 1;
+static int oldsel = -1;
+static WCHAR *sFilter;
+static WCHAR sAppName[MAX_STRING_LEN];
+static WCHAR sAboutTitle[MAX_STRING_LEN];
+static WCHAR sAbout[MAX_STRING_LEN];
+static WCHAR sRegistryKeyNotAvailable[MAX_STRING_LEN];
+static WCHAR sUninstallFailed[MAX_STRING_LEN];
+
+static int FetchUninstallInformation(void);
+static void UninstallProgram(void);
+static void UpdateList(HWND hList);
+static int cmp_by_name(const void *a, const void *b);
+static WCHAR *stristr(const WCHAR *String, const WCHAR *Pattern);
+
+
+static const WCHAR BackSlashW[] = { '\\', 0 };
+static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
+static const WCHAR PathUninistallW[] = {
+        '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 };
+static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
 
-uninst_entry *entries = NULL;
-
-unsigned int numentries = 0;
-int list_need_update = 1;
-int oldsel = -1;
-
-struct {
-    DWORD style;
-    LPCSTR text;
-    HWND hwnd;
-} button[] =
-{
-    { BS_PUSHBUTTON, "Add/Remove", 0 },
-    { BS_PUSHBUTTON, "About", 0 },
-    { BS_PUSHBUTTON, "Exit", 0 }
-};
-
-#define NUM (sizeof(button)/sizeof(button[0]))
-
-int FetchUninstallInformation(void);
-void UninstallProgram(void);
-
-void ListUninstallPrograms(void)
+/**
+ * Used to output program list when used with --list
+ */
+static void ListUninstallPrograms(void)
 {
     unsigned int i;
-    int len;
+    int lenDescr, lenKey;
     char *descr;
+    char *key;
 
     if (! FetchUninstallInformation())
         return;
 
     for (i=0; i < numentries; i++)
     {
-        len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); 
-        descr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL); 
-        printf("%s|||%s\n", entries[i].key, descr);
+        lenDescr = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); 
+        lenKey = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].key, -1, NULL, 0, NULL, NULL); 
+        descr = HeapAlloc(GetProcessHeap(), 0, lenDescr);
+        key = HeapAlloc(GetProcessHeap(), 0, lenKey);
+        WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, lenDescr, NULL, NULL);
+        WideCharToMultiByte(CP_UNIXCP, 0, entries[i].key, -1, key, lenKey, NULL, NULL);
+        printf("%s|||%s\n", key, descr);
         HeapFree(GetProcessHeap(), 0, descr);
+        HeapFree(GetProcessHeap(), 0, key);
     }
 }
 
 
-void RemoveSpecificProgram(char *name)
+static void RemoveSpecificProgram(WCHAR *nameW)
 {
     unsigned int i;
+    int lenName;
+    char *name;
 
     if (! FetchUninstallInformation())
         return;
 
     for (i=0; i < numentries; i++)
     {
-        if (strcmp(entries[i].key, name) == 0)
+        if (lstrcmpW(entries[i].key, nameW) == 0)
         {
             entries[i].active++;
             break;
@@ -126,30 +117,236 @@
         UninstallProgram();
     else
     {
+        lenName = WideCharToMultiByte(CP_UNIXCP, 0, nameW, -1, NULL, 0, NULL, NULL); 
+        name = HeapAlloc(GetProcessHeap(), 0, lenName);
+        WideCharToMultiByte(CP_UNIXCP, 0, nameW, -1, name, lenName, NULL, NULL);
         fprintf(stderr, "Error: could not match application [%s]\n", name);
+        HeapFree(GetProcessHeap(), 0, name);
+    }
+}
+
+
+/**
+ * Fetch informations from the uninstall key.
+ */
+static int FetchUninstallInformation(void)
+{
+    HKEY hkeyUninst, hkeyApp;
+    int i;
+    DWORD sizeOfSubKeyName, displen, uninstlen;
+    WCHAR subKeyName[256];
+    WCHAR key_app[1024];
+    WCHAR *p;
+  
+    numentries = 0;
+    oldsel = -1;
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninistallW, 0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS)
+    {
+        MessageBoxW(0, sRegistryKeyNotAvailable, sAppName, MB_OK);
+        return 0;
+    }
+
+    if (!entries)
+        entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry));
+
+    lstrcpyW(key_app, PathUninistallW);
+    lstrcatW(key_app, BackSlashW);
+    p = key_app+lstrlenW(PathUninistallW)+1;
+
+    sizeOfSubKeyName = 255;
+    for (i=0; RegEnumKeyExW( hkeyUninst, i, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS; ++i)
+    {
+        lstrcpyW(p, subKeyName);
+        RegOpenKeyExW(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);
+        if ((RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, NULL, &displen) == ERROR_SUCCESS)
+         && (RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, NULL, &uninstlen) == ERROR_SUCCESS))
+        {
+            numentries++;
+            entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
+            entries[numentries-1].key = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(subKeyName)+1)*sizeof(WCHAR));
+            lstrcpyW(entries[numentries-1].key, subKeyName);
+            entries[numentries-1].descr = HeapAlloc(GetProcessHeap(), 0, displen);
+            RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0, (LPBYTE)entries[numentries-1].descr, &displen);
+            entries[numentries-1].command = HeapAlloc(GetProcessHeap(), 0, uninstlen);
+            entries[numentries-1].active = 0;
+            RegQueryValueExW(hkeyApp, UninstallCommandlineW, 0, 0, (LPBYTE)entries[numentries-1].command, &uninstlen);
+            WINE_TRACE("allocated entry #%d: %s (%s), %s\n",
+            numentries, wine_dbgstr_w(entries[numentries-1].key), wine_dbgstr_w(entries[numentries-1].descr), wine_dbgstr_w(entries[numentries-1].command));
+            if(sFilter != NULL && stristr(entries[numentries-1].descr,sFilter)==NULL)
+                numentries--;
+        }
+        RegCloseKey(hkeyApp);
+        sizeOfSubKeyName = 255;
+    }
+    qsort(entries, numentries, sizeof(uninst_entry), cmp_by_name);
+    RegCloseKey(hkeyUninst);
+    return 1;
+}
+
+
+static void UninstallProgram(void)
+{
+    unsigned int i;
+    WCHAR errormsg[1024];
+    BOOL res;
+    STARTUPINFOW si;
+    PROCESS_INFORMATION info;
+    DWORD exit_code;
+    HKEY hkey;
+    for (i=0; i < numentries; i++)
+    {
+        if (!(entries[i].active)) /* don't uninstall this one */
+            continue;
+        WINE_TRACE("uninstalling %s\n", wine_dbgstr_w(entries[i].descr));
+        memset(&si, 0, sizeof(STARTUPINFOW));
+        si.cb = sizeof(STARTUPINFOW);
+        si.wShowWindow = SW_NORMAL;
+        res = CreateProcessW(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
+        if (res)
+        {   /* wait for the process to exit */
+            WaitForSingleObject(info.hProcess, INFINITE);
+            res = GetExitCodeProcess(info.hProcess, &exit_code);
+            WINE_TRACE("%d: %08lx\n", res, exit_code);
+        }
+        else
+        {
+            wsprintfW(errormsg, sUninstallFailed, entries[i].command);
+            if(MessageBoxW(0, errormsg, sAppName, MB_YESNO | MB_ICONQUESTION)==IDYES)
+            {
+                /* delete the application's uninstall entry */
+                RegOpenKeyExW(HKEY_LOCAL_MACHINE, PathUninistallW, 0, KEY_READ, &hkey);
+                RegDeleteKeyW(hkey, entries[i].key);
+                RegCloseKey(hkey);
+            }
+        }
+    }
+    WINE_TRACE("finished uninstall phase.\n");
+    list_need_update = 1;
+}
+
+
+static void UpdateList(HWND hList)
+{
+    unsigned int i;
+    if (list_need_update)
+    {
+        int prevsel;
+        prevsel = SendMessageW(hList, LB_GETCURSEL, 0, 0);
+        if (!(FetchUninstallInformation()))
+        {
+            PostQuitMessage(0);
+        return;
+        }
+        SendMessageW(hList, LB_RESETCONTENT, 0, 0);
+        SendMessageW(hList, WM_SETREDRAW, FALSE, 0);
+        for (i=0; i < numentries; i++)
+        {
+            WINE_TRACE("adding %s\n", wine_dbgstr_w(entries[i].descr));
+            SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
+        }
+        WINE_TRACE("setting prevsel %d\n", prevsel);
+        if (prevsel != -1)
+            SendMessageW(hList, LB_SETCURSEL, prevsel, 0 );
+        SendMessageW(hList, WM_SETREDRAW, TRUE, 0);
+        list_need_update = 0;
     }
 }
 
-int main( int argc, char *argv[])
+
+INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
 {
-    MSG msg;
-    WNDCLASS wc;
-    HWND hWnd;
-    LPSTR token = NULL;
+    TEXTMETRICW tm;
+    HDC hdc;
+    HWND hList = GetDlgItem(hwnd, IDC_LIST);
+    switch(Message)
+    {
+        case WM_INITDIALOG:
+            hdc = GetDC(hwnd);
+            GetTextMetricsW(hdc, &tm);
+            UpdateList(hList);
+            ReleaseDC(hwnd, hdc);
+        break;
+        case WM_COMMAND:
+            switch(LOWORD(wParam))
+            {
+                case IDC_FILTER:
+                {
+                    if (HIWORD(wParam) == EN_CHANGE)
+                    {
+                        list_need_update = 1;
+                        int len = GetWindowTextLengthW(GetDlgItem(hwnd, IDC_FILTER));
+                        if(len > 0)
+                        {
+                            sFilter = (WCHAR*)GlobalAlloc(GPTR, len + 1);
+                            GetDlgItemTextW(hwnd, IDC_FILTER, sFilter, len + 1);
+                        }
+                        else sFilter = NULL;
+                        UpdateList(hList);
+                    }
+                }
+                break;
+                case IDC_UNINSTALL:
+                {
+                    int count = SendMessageW(hList, LB_GETSELCOUNT, 0, 0);
+                    if(count != 0)
+                    {
+                        UninstallProgram(hList);
+                        UpdateList(hList);
+                    }
+                }
+                break;
+                case IDC_LIST:
+                {
+                    if (HIWORD(wParam) == LBN_SELCHANGE)
+                    {
+                       int sel = SendMessageW(hList, LB_GETCURSEL, 0, 0);
+               if (oldsel != -1)
+                       {
+                           entries[oldsel].active ^= 1; /* toggle */
+                           WINE_TRACE("toggling %d old %s\n", entries[oldsel].active,
+                           wine_dbgstr_w(entries[oldsel].descr));
+                       }
+                       entries[sel].active ^= 1; /* toggle */
+                       WINE_TRACE("toggling %d %s\n", entries[sel].active,
+                       wine_dbgstr_w(entries[oldsel].descr));
+                       oldsel = sel;
+                   }
+                }
+                break;
+                case IDC_ABOUT:
+                    MessageBoxW(0, sAbout, sAboutTitle, MB_OK);
+                break;
+                case IDC_EXIT:
+                    EndDialog(hwnd, 0);
+                break;
+            }
+        break;
+        default:
+            return FALSE;
+    }
+    return TRUE;
+}
+
+
+int wmain(int argc, WCHAR *argv[])
+{
+    LPCWSTR token = NULL;
+    HINSTANCE hInst = GetModuleHandleW(0);
+    static const WCHAR listW[] = { '-','-','l','i','s','t',0 };
+    static const WCHAR removeW[] = { '-','-','r','e','m','o','v','e',0 };
     int i = 1;
-    HINSTANCE hInst = NULL;
 
     while( i<argc )
     {
         token = argv[i++];
-
+        
         /* Handle requests just to list the applications */
-        if( !lstrcmpA( token, "--list" ) )
+        if(!lstrcmpW( token, listW ) )
         {
             ListUninstallPrograms();
             return 0;
         }
-        else if( !lstrcmpA( token, "--remove" ) )
+        else if( !lstrcmpW( token, removeW ) )
         {
             if( i >= argc )
             {
@@ -162,303 +359,73 @@
         }
         else 
         {
-            WINE_ERR( "unknown option %s\n",token);
+            WINE_ERR( "unknown option %s\n",wine_dbgstr_w(token));
             return 1;
         }
     }
 
-    LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
+    /* Load MessageBox's strings */
+    LoadStringW(hInst, IDS_APPNAME, sAppName, sizeof(sAppName));
+    LoadStringW(hInst, IDS_ABOUTTITLE, sAboutTitle, sizeof(sAboutTitle));
+    LoadStringW(hInst, IDS_ABOUT, sAbout, sizeof(sAbout));
+    LoadStringW(hInst, IDS_REGISTRYKEYNOTAVAILABLE, sRegistryKeyNotAvailable, sizeof(sRegistryKeyNotAvailable));
+    LoadStringW(hInst, IDS_UNINSTALLFAILED, sUninstallFailed, sizeof(sUninstallFailed));
 
-    wc.style = 0;
-    wc.lpfnWndProc = MainProc;
-    wc.cbClsExtra = 0;
-    wc.cbWndExtra = 0;
-    wc.hInstance = hInst;
-    wc.hIcon = LoadIcon( hInst, appname );
-    wc.hCursor = LoadCursor( NULL_HANDLE, IDI_APPLICATION );
-    wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
-    wc.lpszMenuName = NULL;
-    wc.lpszClassName = appname;
-
-    if (!RegisterClass(&wc)) exit(1);
-    hWnd = CreateWindow( appname, "Wine Application Uninstaller",
-        WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
-        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
-        NULL_HANDLE, NULL_HANDLE, hInst, NULL );
-
-    if (!hWnd) exit(1);
-
-    ShowWindow( hWnd, SW_SHOW );
-    UpdateWindow( hWnd );
-
-    while( GetMessage(&msg, NULL_HANDLE, 0, 0) ) {
-	TranslateMessage( &msg );
-        DispatchMessage( &msg );
-    }
-    return msg.wParam;
+    return DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_UNINSTALLER), NULL, DlgProc);
 }
 
-int cmp_by_name(const void *a, const void *b)
+
+/**
+ * Used to sort entries by name.
+ */
+static int cmp_by_name(const void *a, const void *b)
 {
     return lstrcmpiW(((const uninst_entry *)a)->descr, ((const uninst_entry *)b)->descr);
 }
 
-int FetchUninstallInformation(void)
-{
-    HKEY hkeyUninst, hkeyApp;
-    int i;
-    DWORD sizeOfSubKeyName, displen, uninstlen;
-    char subKeyName[256];
-    char key_app[1024];
-    char *p;
-
-    numentries = 0;
-    oldsel = -1;
-    if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
-			    0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS )
-    {
-	MessageBox(0, "Uninstall registry key not available (yet), nothing to do !", appname, MB_OK);
-	return 0;
-    }
-
-    if (!entries)
-	entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry));
-
-    strcpy(key_app, REGSTR_PATH_UNINSTALL);
-    strcat(key_app, "\\");
-    p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1;
-
-    sizeOfSubKeyName = 255;
-    for ( i=0;
-	  RegEnumKeyExA( hkeyUninst, i, subKeyName, &sizeOfSubKeyName,
-		  	 NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS;
-	  ++i )
-    {
-	static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
 
-	strcpy(p, subKeyName);
-	RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);
-
-	if ( (RegQueryValueExW(hkeyApp, DisplayNameW,
-		0, 0, NULL, &displen) == ERROR_SUCCESS)
-	&&   (RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE,
-		0, 0, NULL, &uninstlen) == ERROR_SUCCESS) )
-	{
-	    numentries++;
-	    entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
-	    entries[numentries-1].key =
-		    HeapAlloc(GetProcessHeap(), 0, strlen(subKeyName)+1);
-	    strcpy(entries[numentries-1].key, subKeyName);
-	    entries[numentries-1].descr =
-		    HeapAlloc(GetProcessHeap(), 0, displen);
-	    RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0,
-			    (LPBYTE)entries[numentries-1].descr, &displen);
-	    entries[numentries-1].command =
-		    HeapAlloc(GetProcessHeap(), 0, uninstlen);
-	    entries[numentries-1].active = 0;
-	    RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE, 0, 0,
-			    entries[numentries-1].command, &uninstlen);
-	    WINE_TRACE("allocated entry #%d: %s (%s), %s\n",
-		numentries, entries[numentries-1].key,
-		wine_dbgstr_w(entries[numentries-1].descr),
-		entries[numentries-1].command);
-	}
-	RegCloseKey(hkeyApp);
-
-	sizeOfSubKeyName = 255;
-    }
-    qsort(entries, numentries, sizeof(uninst_entry), cmp_by_name);
-    RegCloseKey(hkeyUninst);
-    return 1;
-}
-
-void UninstallProgram(void)
+/**
+ * Case insensitive substring search.
+ * 
+ * Public domain code found here: http://fux0r.phathookups.com/programming-tutorials/C/C-snippits/stristr.c
+ *
+ */
+static WCHAR *stristr(const WCHAR *String, const WCHAR *Pattern)
 {
-    unsigned int i;
-    char errormsg[1024];
-    BOOL res;
-    STARTUPINFO si;
-    PROCESS_INFORMATION info;
-    DWORD exit_code;
-#ifdef DEL_REG_KEY
-    HKEY hkey;
-#endif
+    const WCHAR *pptr, *sptr, *start;
+    uint  slen, plen;
 
-    for (i=0; i < numentries; i++)
+    for (start = String,
+         pptr  = Pattern,
+         slen  = lstrlenW(String),
+         plen  = lstrlenW(Pattern);
+         /* while string length not shorter than pattern length */
+         slen >= plen;
+         start++, slen--)
     {
-	if (!(entries[i].active)) /* don't uninstall this one */
-	    continue;
-	WINE_TRACE("uninstalling %s\n", wine_dbgstr_w(entries[i].descr));
-	memset(&si, 0, sizeof(STARTUPINFO));
-	si.cb = sizeof(STARTUPINFO);
-	si.wShowWindow = SW_NORMAL;
-	res = CreateProcess(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
-	if (res)
-	{   /* wait for the process to exit */
-	    WaitForSingleObject(info.hProcess, INFINITE);
-	    res = GetExitCodeProcess(info.hProcess, &exit_code);
-	    WINE_TRACE("%d: %08lx\n", res, exit_code);
-#ifdef DEL_REG_KEY
-	    /* delete the application's uninstall entry */
-	    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
-		0, KEY_READ, &hkey) == ERROR_SUCCESS)
-	    {
-		RegDeleteKey(hkey, entries[i].key);
-		RegCloseKey(hkey);
-	    }
-#endif
-	}
-	else
-	{
-	    sprintf(errormsg, "Execution of uninstall command '%s' failed, perhaps due to missing executable.", entries[i].command);
-	    MessageBox(0, errormsg, appname, MB_OK);
-	}
-    }
-    WINE_TRACE("finished uninstall phase.\n");
-    list_need_update = 1;
-}
-
-LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-    HFONT static_font, listbox_font;
-    HDC hdc;
-    PAINTSTRUCT ps;
-    TEXTMETRIC tm;
-    unsigned int i;
-    int cxChar, cyChar, y, bx, maxx, maxy, wx, wy;
-    static HWND hwndList = 0, static_text = 0;
-    DWORD style;
-    RECT rect;
-
-    switch( msg ) {
-    case WM_CREATE:
-	{
-	hdc = GetDC(hWnd);
-	GetTextMetrics(hdc, &tm);
-	static_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 600, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
-	listbox_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
-	cxChar = tm.tmAveCharWidth;
-	cyChar = tm.tmHeight + tm.tmExternalLeading;
-	ReleaseDC(hWnd, hdc);
-	/* FIXME: implement sorting and use LBS_SORT here ! */
-	style = (WS_CHILD|WS_VISIBLE|LBS_STANDARD) & ~LBS_SORT;
-#ifdef USE_MULTIPLESEL
-	style |= LBS_MULTIPLESEL;
-#endif
-	bx = maxx = cxChar * 3;
-	y = maxy = cyChar * 1;
-	static_text = CreateWindow("static", program_description,
-		WS_CHILD|WS_VISIBLE|SS_LEFT,
-		maxx, maxy,
-		cxChar * sizeof(program_description), cyChar * 1,
-		hWnd, (HMENU)1,
-		((LPCREATESTRUCT)lParam)->hInstance, NULL);
-	SendMessage(static_text, WM_SETFONT, (WPARAM)static_font, MAKELPARAM(FALSE, 0));
-	maxy += cyChar * 2; /*static text + distance */
-	hwndList = CreateWindow("listbox", NULL,
-		style,
-		maxx, maxy,
-		cxChar * 50 + GetSystemMetrics(SM_CXVSCROLL), cyChar * 10,
-		hWnd, (HMENU) 1,
-		(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
-	SendMessage(hwndList, WM_SETFONT, (WPARAM)listbox_font, MAKELPARAM(FALSE, 0));
-	GetWindowRect(hwndList, &rect);
-	maxx += (rect.right - rect.left)*1.1;	
-	maxy += (rect.bottom - rect.top)*1.1;
-	wx = 20*cxChar;
-	wy = 7*cyChar/4;
-	y = cyChar * 3;
-	for (i=0; i < NUM; i++)
-	{
-	    button[i].hwnd = CreateWindow("button", button[i].text,
-		WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
-		maxx, y,
-		wx, wy,
-		hWnd, (HMENU)i,
-		((LPCREATESTRUCT)lParam)->hInstance, NULL);
-	    if (!button[i].hwnd)
-		    PostQuitMessage(0);
-	    y += 2*cyChar;
-	}
-	maxx += wx + cxChar * 4;
-	maxy += cyChar * 2; /* window border */
-	SetWindowPos(	hWnd, 0,
-			0, 0, maxx, maxy,
-			SWP_NOMOVE);
-        return 0;
-	}
+        /* find start of pattern in string */
+        while (CharUpperW(*start) != CharUpperW(*Pattern))
+        {
+            start++;
+            slen--;
 
-    case WM_PAINT:
-      {
-        hdc = BeginPaint( hWnd, &ps );
-	if (list_need_update)
-	{
-	    int prevsel;
-	    prevsel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
-	    if (!(FetchUninstallInformation()))
-	    {
-	        PostQuitMessage(0);
-	        return 0;
-	    }
-	    SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
-	    SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
-	    for (i=0; i < numentries; i++)
-	    {
-	        WINE_TRACE("adding %s\n", wine_dbgstr_w(entries[i].descr));
-	        SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
-	    }
-	    WINE_TRACE("setting prevsel %d\n", prevsel);
-	    if (prevsel != -1)
-	        SendMessage(hwndList, LB_SETCURSEL, prevsel, 0 );
-	    SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
-	    list_need_update = 0;
-	}
-        EndPaint( hWnd, &ps );
-        return 0;
-      }
+            /* if pattern longer than string */
+            if (slen < plen)
+                return NULL;
+        }
 
-    case WM_DESTROY:
-        PostQuitMessage( 0 );
-        return 0;
+        sptr = start;
+        pptr = Pattern;
 
-    case WM_COMMAND:
-	if ((HWND)lParam == hwndList)
-	{
-	    if (HIWORD(wParam) == LBN_SELCHANGE)
-	    {
-		int sel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
-
-#ifndef USE_MULTIPLESEL
-		if (oldsel != -1)
-		{
-		    entries[oldsel].active ^= 1; /* toggle */
-		    WINE_TRACE("toggling %d old %s\n", entries[oldsel].active,
-				wine_dbgstr_w(entries[oldsel].descr));
-		}
-#endif
-		entries[sel].active ^= 1; /* toggle */
-		WINE_TRACE("toggling %d %s\n", entries[sel].active,
-			    wine_dbgstr_w(entries[oldsel].descr));
-		oldsel = sel;
-	    }
-	}
-	else
-	if ((HWND)lParam == button[0].hwnd) /* Uninstall button */
+        while (CharUpperW(*sptr) == CharUpperW(*pptr))
         {
-	    UninstallProgram();
-
-	    InvalidateRect(hWnd, NULL, TRUE);
-	    UpdateWindow(hWnd);
+            sptr++;
+            pptr++;
 
+            /* if end of pattern then pattern was found */
+            if ('\0' == *pptr)
+                return start;
         }
-	else
-	if ((HWND)lParam == button[1].hwnd) /* About button */
-	    MessageBox(0, about_string, "About Wine Application Uninstaller", MB_OK);
-	else
-	if ((HWND)lParam == button[2].hwnd) /* Exit button */
-	    PostQuitMessage(0);
-	return 0;
     }
-
-    return( DefWindowProc( hWnd, msg, wParam, lParam ));
+    return NULL;
 }

Attachment: signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=

Reply via email to