[PATCH] svchost: Implementation of svchost (revised submission)

Roy Shea roy at cs.hmc.edu
Tue Nov 27 16:55:54 CST 2007


On Tue, Nov 27, 2007 at 03:37:50PM -0600, James Hawkins wrote:
> On Nov 27, 2007 3:21 PM, Roy Shea <roy at cs.hmc.edu> wrote:
> > This is a revised and standalone version of svchost patch.  Changes in
> > this revision include:
> >
> > - Unicode based with a simple UNICODE to ASCII function used to
> >   convert the lpProcName passed into GetProcAddress
> >
> 
> I think you're misunderstanding Wine's policy about not using ansi
> functions or constant strings.  That only applies to external APIs
> because we don't want to convert from unicode to ansi (lossy).
> There's nothing wrong with just using:
> 
> GetProcAddress(library, "ServiceMain");
> 
> There aren't many instances where W->A is valid.

The name of the procedure passed into GetProcAddress is not always the
constant string "ServiceMain".  In these cases I'm getting the
procedure name from RegQueryValueEx.  RegQueryValueEx requires a
little bit of error checking to ensure proper NULL termination of a
REG_SZ.  I'd already wrapped this into the helper function GetRegValue
and thought a simple conversion from UnicodeToAscii would be cleaner
than writing a second ANSI version of GetRegValue.

I guess that inlining a native ANSI query doesn't look too bad:

----
/* Look for alternate to default ServiceMain entry point */
ret = RegQueryValueExA(service_hkey, service_main, NULL, NULL, NULL, &size);
if (ret != ERROR_SUCCESS)
{
    dll_service_main = NULL;
}
else
{
    dll_service_main = HeapAlloc(GetProcessHeap(), 0, size);
    ret = RegQueryValueExA(service_hkey, service_main, NULL, NULL,
            (LPBYTE)dll_service_main, &size);
    if (ret != ERROR_SUCCESS)
    {
        HeapFree(GetProcessHeap(), 0, dll_service_main);
        RegCloseKey(service_hkey);
        goto cleanup;
    }
    if (dll_service_main[size-1] != '\0')
    {
        WINE_TRACE("NULL terminating registry entry: %s\n", service_main);
        tmp_value = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
                dll_service_main, size+1);
        if (!tmp_value)
        {
            HeapFree(GetProcessHeap(), 0, dll_service_main);
            RegCloseKey(service_hkey);
            goto cleanup;
        }
        dll_service_main = tmp_value;
    }
}
RegCloseKey(service_hkey);

/* Load the DLL and obtain a pointer to ServiceMain entry point */
library = LoadLibraryW(dll_name_long);
if (!library)
{
    WINE_ERR("failed to load library %s, err=%u\n",
            wine_dbgstr_w(dll_name_long), GetLastError());
    goto cleanup;
}
if (dll_service_main)
{
    service_main_func =
        (LPSERVICE_MAIN_FUNCTIONW) GetProcAddress(library, dll_service_main);
}
else
{
    service_main_func =
        (LPSERVICE_MAIN_FUNCTIONW) GetProcAddress(library, service_main);
}
if (!service_main_func)
{
    WINE_ERR("cannot locate ServiceMain procedure in DLL for %s\n",
            wine_dbgstr_w(service_name));
    FreeLibrary(library);
    goto cleanup;
}
----

I'll switch svchost over to a direct ANSI query when looking up the
DLL's service main function.

> > - Using HEAP_ZERO_MEMORY flag in calls to HeapAlloc and HeapReAlloc
> >   that are allocating space for a string and the NULL terminator to
> >   set the NULL terminator to zero.
> >
> 
> Why HEAP_ZERO_MEMORY when you can just set the last byte to NULL?
> 
> str[LEN - 1] = '\0';

I was saving a line of code at the cost of performance.  My bad.  Thanks for
catching this.  And thank you for your continued help with this patch.

Peace,
-Roy




More information about the wine-devel mailing list