LogonUser

Martin Wilck Martin.Wilck at Fujitsu-Siemens.com
Fri Nov 8 10:25:55 CST 2002


Patch: LogonUser.diff

This patch is incremental wrt my ComuterName (take 2) patch 
(http://www.winehq.com/hypermail/wine-patches/2002/11/0080.html)
in the documentation subdirectory.

Also fixes an error I made in that patch in wine.conf.man.

Modified files:
        wine:                   configure.ac
                                configure (not included in the patch)
        wine/dlls/advapi32:     Makefile.in
                                advapi.c
                                security.c
                                advapi32.spec
        wine/include:           config.h.in
                                winbase.h
        wine/documentation:     configuring.sgml
                                wine.conf.man
        wine/documentation/samples:     config   

Log Message: Martin Wilck <martin.wilck at fujitsu-siemens.com>

        Implement LogonUser() using an interface between Wine and
        the PAM library.
        
        Normally, this will validate Unix username/password pairs.
        If PAM is suitably configured (for using winbind), usernames
        and passwords can be obtained from a Windows Domain controller.

        Introduce PAM related configuration options.

Differences to my previous Logonuser patch: 
        - configuration options instead of hard-coded defaults
        - documentation update
        - LogonUser() now in security.c        

diff -ruNX ignore CVS/wine/configure.ac TMP/wine/configure.ac
--- CVS/wine/configure.ac	Fri Nov  8 10:45:07 2002
+++ TMP/wine/configure.ac	Fri Nov  8 10:45:59 2002
@@ -621,6 +621,13 @@
                   [AUDIOIOLIBS="-laudioio"
                    AC_DEFINE(HAVE_LIBAUDIOIO, 1, [Define if you have libaudioIO])])])
 
+dnl **** Check for PAM ****
+AC_SUBST(PAMLIBS,"")
+AC_CHECK_HEADERS(security/pam_appl.h,
+    [AC_CHECK_LIB(pam,pam_start,
+                 [AC_DEFINE(HAVE_PAM,1,[Define if you have PAM including devel headers])
+                  PAMLIBS="-lpam"],,)])
+
 dnl **** Check for broken glibc mmap64 ****
 
 AC_CACHE_CHECK( [whether mmap64 works defined as mmap], ac_cv_mmap64_works,
diff -ruNX ignore CVS/wine/dlls/advapi32/Makefile.in TMP/wine/dlls/advapi32/Makefile.in
--- CVS/wine/dlls/advapi32/Makefile.in	Mon Oct 28 09:35:53 2002
+++ TMP/wine/dlls/advapi32/Makefile.in	Fri Nov  8 10:45:59 2002
@@ -5,6 +5,7 @@
 VPATH     = @srcdir@
 MODULE    = advapi32.dll
 IMPORTS   = kernel32 ntdll
+EXTRALIBS = @PAMLIBS@
 
 LDDLLFLAGS = @LDDLLFLAGS@
 SYMBOLFILE = $(MODULE).tmp.o
diff -ruNX ignore CVS/wine/dlls/advapi32/advapi.c TMP/wine/dlls/advapi32/advapi.c
--- CVS/wine/dlls/advapi32/advapi.c	Wed Aug 28 13:49:07 2002
+++ TMP/wine/dlls/advapi32/advapi.c	Fri Nov  8 14:44:29 2002
@@ -121,3 +121,17 @@
     TRACE("stub %s (harmless)\n", debugstr_w(lpMachineName));
     return TRUE;
 }
+
+/******************************************************************************
+ * Init function for advapi32 - needed to properly load the pam library.
+ */
+BOOL WINAPI DllMain ( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+#if HAVE_PAM
+    const static char soname[] = "libpam.so";
+    if ( reason == DLL_PROCESS_ATTACH 
+         && ! wine_dlopen( soname, RTLD_NOW|RTLD_GLOBAL, NULL, 0 ) )
+        ERR ( "error opening %s\n", soname );
+#endif
+    return TRUE;
+}
diff -ruNX ignore CVS/wine/dlls/advapi32/advapi32.spec TMP/wine/dlls/advapi32/advapi32.spec
--- CVS/wine/dlls/advapi32/advapi32.spec	Mon Sep  9 09:28:27 2002
+++ TMP/wine/dlls/advapi32/advapi32.spec	Fri Nov  8 14:44:41 2002
@@ -127,8 +127,8 @@
 @ stdcall IsValidSecurityDescriptor(ptr) IsValidSecurityDescriptor
 @ stdcall IsValidSid(ptr) IsValidSid
 @ stub LockServiceDatabase
-@ stub LogonUserA
-@ stub LogonUserW
+@ stdcall LogonUserA(ptr ptr ptr long long ptr) LogonUserA
+@ stdcall LogonUserW(ptr ptr ptr long long ptr) LogonUserW
 @ stdcall LookupAccountNameA(str str ptr ptr ptr ptr ptr) LookupAccountNameA
 @ stub LookupAccountNameW
 @ stdcall LookupAccountSidA(ptr ptr ptr ptr ptr ptr ptr) LookupAccountSidA
diff -ruNX ignore CVS/wine/dlls/advapi32/security.c TMP/wine/dlls/advapi32/security.c
--- CVS/wine/dlls/advapi32/security.c	Mon Oct 28 09:35:53 2002
+++ TMP/wine/dlls/advapi32/security.c	Fri Nov  8 15:38:32 2002
@@ -17,8 +17,13 @@
  *
  *  FIXME: for all functions thunking down to Rtl* functions:  implement SetLastError()
  */
+#include "config.h"
 
 #include <string.h>
+#include <stdlib.h>
+#if HAVE_PAM
+#include <security/pam_appl.h>
+#endif
 
 #include "windef.h"
 #include "winerror.h"
@@ -1093,3 +1098,288 @@
 		*pfResult=TRUE;
         return TRUE;
 }
+
+#if HAVE_PAM
+/******************************************************************************
+ * Helper functions for the PAM interface.
+ */
+
+/* FIXME: These should be made configurable options, at least the separator. */
+#define WINE_PAM_SERVICE "wine"
+/* This corresponds to the "winbind separator" setting in smb.conf. */
+#define WINE_WINBIND_SEPARATOR '\\'
+#define PAM_FAIL(x) ((x) != PAM_SUCCESS) 
+
+/******************************************************************************
+ * PAM_error_to_dos [INTERNAL]
+ */
+static int PAM_error_to_dos ( pam_handle_t *pamh, int retcode )
+{
+     if ( pamh ) 
+        TRACE( "PAM error: %s\n", pam_strerror ( pamh, retcode ) );
+    switch ( retcode )
+    {
+    case PAM_SUCCESS:      return ERROR_SUCCESS;
+    case PAM_AUTH_ERR:     return ERROR_ACCESS_DENIED;
+    default:               return ERROR_GEN_FAILURE;
+    }
+}
+
+/******************************************************************************
+ * PAM_logon_user_conv [INTERNAL]
+ * The "PAM conversation callback" for LogonUser().
+ */
+static int PAM_logon_user_conv ( int nmsg, const struct pam_message **msg,
+                                 struct pam_response **resp, void *ptr )
+{
+    int i;
+    struct pam_response *myresp;
+
+    /* PAM will free myresp and the response buffers when done. */
+    myresp = malloc ( nmsg * sizeof (struct pam_response) );
+    if (!myresp) return PAM_BUF_ERR;
+    memset ( myresp, 0, nmsg * sizeof (struct pam_response) );
+
+    /* Fill in our password as "response" to the prompt we never show. */
+    for (i = 0; i < nmsg; i++)
+    {
+        if ( msg[i]->msg_style == PAM_PROMPT_ECHO_OFF )
+        {
+            myresp[i].resp = strdup (ptr);
+            break;
+        }
+    }
+    *resp = myresp;
+    return PAM_SUCCESS;
+}
+
+/******************************************************************************
+ * PAM_get_config [INTERNAL]
+ * - Read the PAM configuration from Wine config.
+ * - Servicename is a newly allocated string, must be freed by caller.
+ */
+static BOOL PAM_get_config ( char **servicename, char *separator )
+{
+    const static char keyname[] = "Software\\Wine\\Wine\\Config\\Logon";
+    const static char pamname[] = "PamServiceName";
+    const static char sepname[] = "WinbindSeparator";
+    const static char default_pam[] = "other";
+    const static char default_sep = '\\';
+    HKEY hkey;
+    DWORD ret = ERROR_NOT_ENOUGH_MEMORY;
+    LONG len = 32, slen;
+    char *buf;
+    BOOL res = FALSE;
+
+    if ( RegOpenKeyA ( HKEY_LOCAL_MACHINE, keyname, &hkey ) != ERROR_SUCCESS ) 
+        return FALSE;
+    buf = HeapAlloc ( GetProcessHeap(), 0, len );
+
+    while ( buf )
+    {
+        ret = RegQueryValueExA ( hkey, pamname, NULL, NULL, buf, &len );
+        if ( ret != ERROR_MORE_DATA ) break;
+        buf = HeapReAlloc ( GetProcessHeap(), 0, buf, len );
+    }
+    if ( !buf ) {
+        SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+        goto out;
+    }
+    else if ( ret == ERROR_FILE_NOT_FOUND ) 
+        strcpy ( buf, default_pam );
+    else if ( ret != ERROR_SUCCESS ) goto out;
+    
+    slen = strlen ( buf ) + 1;
+    *servicename = HeapAlloc ( GetProcessHeap(), 0 , slen );
+    if ( !*servicename ) {
+        SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+        goto out;
+    }
+    memcpy ( *servicename, buf, slen );
+    
+    ret = RegQueryValueExA ( hkey, sepname, NULL, NULL, buf, &len );
+    if ( ret == ERROR_SUCCESS )
+        *separator = *buf;
+    else
+        *separator = default_sep;
+    res = TRUE;
+
+out:
+    if (buf) HeapFree ( GetProcessHeap(), 0, buf );
+    RegCloseKey ( hkey );
+    return res;
+}
+
+/******************************************************************************/
+#endif /* HAVE_PAM */
+
+/******************************************************************************
+ * LogonUserA [ADVAPI32.@]
+ *
+ * PARAMS
+ * 	lpUserName        : (IN) user name
+ *      lpDomain	  : (IN) domain name (will only work with PAM winbind support)
+ *      lpPassword        : (IN) Cleartext password
+ *      dwLogonType       : (IN) logon type, IGNORED
+ *      dwLogonProvider   : (IN) login provider, IGNORED
+ *      phToken           : (OUT) handle to user token, BOGUS
+ *
+ * RETURNS
+ *      TRUE on success.
+ */
+BOOL WINAPI LogonUserA( LPSTR lpUserName, LPSTR lpDomain, LPSTR lpPassword, 
+                        DWORD dwLogonType, DWORD dwLogonProvider, LPHANDLE phToken )
+{
+#if ! HAVE_PAM
+    ERR( "stub - wine needs to be compiled against PAM library\n" );
+    SetLastError ( ERROR_NOT_SUPPORTED );
+    return FALSE;
+#else
+
+    char *pam_service = NULL;
+    char winbind_separator;
+    int ret;
+    char *user = NULL;
+    struct pam_conv conv = { PAM_logon_user_conv, NULL };
+    pam_handle_t *pamh = NULL;
+
+    FIXME( "returned token handle will be bogus!\n" );
+    FIXME( "ignoring type (%lx) and provider (%lx)\n", dwLogonType, dwLogonProvider );
+    TRACE( "user %s, domain %s\n", lpUserName, lpDomain );
+
+    if ( !lpUserName || !lpPassword || !phToken )
+    {
+        SetLastError ( ERROR_INVALID_PARAMETER );
+        goto abort;
+    }
+
+    if ( !PAM_get_config ( &pam_service, &winbind_separator ) )
+        goto abort;
+
+    if ( !lpDomain )
+        /* User name is "user at DNS-name" (UPN format), 
+         * but we don't know how to convert DNS to NT domain name. */
+    {
+        char *p;
+        FIXME( "UPN format unsupported - trying unqualified name\n" );
+
+        user = strdup ( lpUserName );
+        if ( ! user ) goto outofmem;
+        p = strchr ( user, '@' );
+        if ( p ) *p = '\0';
+    }
+    else if ( *lpDomain == '\0' || ! strcmp ( lpDomain, "." ) )
+    {
+        user = strdup ( lpUserName );
+        if ( ! user ) goto outofmem;
+    }
+    else 
+    {
+        int ldom = strlen ( lpDomain );
+        int lusr = strlen ( lpUserName );
+        user = malloc ( ldom + lusr + 2 );
+        if ( ! user ) goto outofmem;
+        strcpy ( user, lpDomain );
+        user[ldom] = winbind_separator;
+        strcpy ( user + ldom + 1, lpUserName );
+    }
+    TRACE( "PAM sevice %s, user name: %s\n", debugstr_a (pam_service), debugstr_a (user) );
+
+    conv.appdata_ptr = lpPassword;
+    if ( PAM_FAIL( ret = pam_start ( pam_service, user, &conv,  &pamh )) )
+        goto pam_error;
+    if ( PAM_FAIL( ret = pam_authenticate ( pamh, PAM_SILENT ) ) )
+        goto pam_error;
+    pam_end ( pamh, PAM_SUCCESS );
+
+    *phToken = (HANDLE) 0xcafe;
+    HeapFree ( GetProcessHeap(), 0, pam_service );
+    free ( user );
+    TRACE( "-> successful\n" );
+    return TRUE;
+
+pam_error:
+    SetLastError ( PAM_error_to_dos ( pamh, ret ) );
+    goto abort;
+
+outofmem:
+    SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+
+abort:
+    TRACE( "-> error %lu\n", GetLastError() );
+    if ( pam_service ) HeapFree ( GetProcessHeap(), 0, pam_service );
+    if ( pamh ) pam_end ( pamh, PAM_SUCCESS );
+    if ( user ) free ( user );
+    return FALSE;
+
+#endif /* HAVE_PAM */
+}
+
+/******************************************************************************
+ * LogonUserW [ADVAPI32.@]
+ *
+ * PARAMS
+ * 	lpUserNameW       : (IN) user name
+ *      lpDomainW	  : (IN) domain name (will only work with PAM winbind support)
+ *      lpPasswordW       : (IN) Cleartext password
+ *      dwLogonType       : (IN) logon type, IGNORED
+ *      dwLogonProvider   : (IN) login provider, IGNORED
+ *      phToken           : (OUT) handle to user token, IGNORED
+ *
+ * RETURNS
+ *      TRUE on success.
+ */
+BOOL WINAPI LogonUserW( LPWSTR lpUserNameW, LPWSTR lpDomainW, LPWSTR lpPasswordW, 
+                        DWORD dwLogonType, DWORD dwLogonProvider, LPHANDLE phToken )
+{
+#if ! HAVE_PAM
+    ERR( "stub - wine needs to be compiled against PAM library\n" );
+    SetLastError ( ERROR_NOT_SUPPORTED );
+    return FALSE;
+#else
+
+    int ulen = 0, dlen = 0, plen = 0, ret;
+    LPSTR buf = NULL;
+    LPSTR lpUserName, lpPassword, lpDomain;
+
+    if ( !lpUserNameW || !lpPasswordW || !phToken )
+    {
+        SetLastError ( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    ulen = WideCharToMultiByte( CP_ACP, 0, lpUserNameW, -1, NULL, 0, NULL, NULL );
+    plen = WideCharToMultiByte( CP_ACP, 0, lpPasswordW, -1, NULL, 0, NULL, NULL );
+    if ( lpDomainW )
+        dlen = WideCharToMultiByte( CP_ACP, 0, lpDomainW, -1, NULL, 0, NULL, NULL );
+
+    buf = HeapAlloc ( GetProcessHeap(), 0, ulen + plen + dlen );
+    if ( !buf )
+    {
+        SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+    }
+    
+    lpUserName = buf;
+    WideCharToMultiByte( CP_ACP, 0, lpUserNameW, -1, lpUserName, ulen, NULL, NULL );
+
+    lpPassword = buf + ulen;
+    WideCharToMultiByte( CP_ACP, 0, lpPasswordW, -1, lpPassword, plen, NULL, NULL );
+
+    if ( lpDomainW ) 
+    { 
+        lpDomain = lpPassword + plen;
+        WideCharToMultiByte( CP_ACP, 0, lpDomainW, -1, lpDomain, dlen, NULL, NULL );
+    }
+    else lpDomain = NULL;
+    
+    ret =  LogonUserA( lpUserName, lpDomain, lpPassword, 
+                       dwLogonType, dwLogonProvider, phToken );
+    
+    memset ( buf, 0, ulen + plen ); /* erase password in memory */
+    HeapFree ( GetProcessHeap(), 0, buf );
+    return ret;
+
+#endif /* HAVE_PAM */
+}
+
diff -ruNX ignore CVS/wine/documentation/configuring.sgml TMP/wine/documentation/configuring.sgml
--- CVS/wine/documentation/configuring.sgml	Fri Nov  8 16:37:45 2002
+++ TMP/wine/documentation/configuring.sgml	Fri Nov  8 16:34:56 2002
@@ -968,6 +968,73 @@
           </variablelist>
         </sect3>
 
+        <sect3 id="logon-section">
+          <title>The [Logon] Section</title>
+          <para>
+            [Logon] contains settings related to user authentification.
+            <emphasis>Note that Wine does not support Windows NT security
+            concepts.</emphasis> In particular, Wine processes are not allowed to
+            "change personality", and Wine relies almost exclusively
+            on its Unix environment for determining file access rights, etc.
+          </para>
+          <para>
+            The logon functionality only enables Windows
+            programs to check for a valid login name and password from within Wine.
+            It is up to the Windows or Winelib application to do
+            something useful with this information. It is up to the system
+            administrator installing Wine (that is, YOU) to make sure the
+            application can't harm anything on your Unix system. 
+            <emphasis>NEVER RUN WINE AS ROOT!!</emphasis>
+          </para>
+          <para>
+            The Logon functionality is only available if Wine was compiled against
+            the PAM (Pluggable Authetification Modules) library. This library is
+            part of all recent Linux distributions.
+          </para>
+
+          <variablelist>
+            <varlistentry>
+              <term>PamServiceName</term>
+              <listitem>
+                <para>
+                  This is the name of the "PAM service" associated with Wine. This name
+                  corresponds to the name of a file in the PAM configuration directory
+                  <filename>/etc/pam.d</filename>. It defaults to the service
+                  <literal>other</literal>, which normally has very restrictive access
+                  rights. You can set <literal>PamServiceName</literal> e.g. to
+                  <literal>login</literal> to use the same settings as for Unix
+                  authentification, or you can define a special PAM service for Wine and
+                  call it e.g. <literal>wine</literal>. See the PAM documentation for details.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>WinbindSeparator</term>
+              <listitem>
+                <para>
+                  This setting is useful if the Unix system setup uses the
+                  <literal>pam_winbind</literal> module to authenticate 
+                  against a Windows Primary Domain Controller (PDC).
+                  It makes only sense to set this up if your Unix
+                  machine is configured to use <literal>pam_winbind</literal>.
+                </para>
+                <para>
+                  When a user
+                  authenticates with a Windows domain name and user name, these names
+                  are concatenated with this character as separator to form a pseudo Unix user
+                  name. This name is then passed to PAM for authentification against the
+                  PDC. It must be set to the same value as the "winbind separator" in
+                  the Samba configuration file <filename>smb.conf</filename>. See
+                  the <command>winbindd(8)</command> manual page for
+                  details. The default value for
+                  <literal>WinbindSeparator</literal> is "\\" (the
+                  backslash character). 
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+        </sect3>
+
         <sect3 id="appdefaults-section">
           <title>The [AppDefaults] Section</title>
           <para>
diff -ruNX ignore CVS/wine/documentation/samples/config TMP/wine/documentation/samples/config
--- CVS/wine/documentation/samples/config	Fri Nov  8 16:37:45 2002
+++ TMP/wine/documentation/samples/config	Fri Nov  8 15:40:12 2002
@@ -263,6 +263,15 @@
 ;; HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ComputerName\ComputerName, too.
 ;"UseDnsComputerName" = "N"
 
+[Logon]
+;; If you have PAM in your system, the PAM service name (file name in /etc/pam.d)
+;; to use for Wine authentication. Default: "other".
+;"PamServiceName" = "wine"
+;; Character to separate Windows domain and user name for PAM_winbind queries.
+;; Should be set to the same value as the "winbind separator" in smb.conf(5).
+;; See man page of winbindd(8). Default: "\\".
+;"WinbindSeparator" = "+"
+
 ;; sample AppDefaults entries
 ;[AppDefaults\\iexplore.exe\\DllOverrides]
 ;"shlwapi" = "native"
diff -ruNX ignore CVS/wine/documentation/wine.conf.man TMP/wine/documentation/wine.conf.man
--- CVS/wine/documentation/wine.conf.man	Fri Nov  8 16:37:45 2002
+++ TMP/wine/documentation/wine.conf.man	Fri Nov  8 16:46:36 2002
@@ -303,15 +303,29 @@
 .br
 Defaults are read all, write to home files.
 .PP
-.B [AppDefaults\\\\\\\\<appname>\\\\\\\\...]
-.PP
 .B [Network]
-.br
+.PP
 .I format: """UseDnsComputerName""=""<boolean>"""
 .br
 If Y, always override the registry setting for ComputerName
 with the Unix hostname.
 .PP
+.B [Logon]
+.PP
+.I format: """PamServiceName""=""<string>"""
+.br
+default: "other".
+.br
+Name of the PAM service (file in /etc/pam.d) determining 
+authentification rules for Wine.
+.br
+.PP
+.I format: """WinbindSeparator""=""<character>"""
+.br
+default: "\\\\".
+.br
+Separator between Windows domain and user name. See winbindd(8).
+.PP
 .B [AppDefaults\\\\\\\\<appname>\\\\\\\\...]
 .PP
 This section allows specifying application-specific values for
diff -ruNX ignore CVS/wine/include/config.h.in TMP/wine/include/config.h.in
--- CVS/wine/include/config.h.in	Fri Nov  8 10:45:17 2002
+++ TMP/wine/include/config.h.in	Fri Nov  8 10:45:59 2002
@@ -320,6 +320,9 @@
 /* Define if you have NAS including devel headers */
 #undef HAVE_NAS
 
+/* Define if you have PAM including devel headers */
+#undef HAVE_PAM
+
 /* Define to 1 if you have the <ncurses.h> header file. */
 #undef HAVE_NCURSES_H
 
diff -ruNX ignore CVS/wine/include/winbase.h TMP/wine/include/winbase.h
--- CVS/wine/include/winbase.h	Fri Nov  8 16:37:45 2002
+++ TMP/wine/include/winbase.h	Fri Nov  8 10:45:59 2002
@@ -1128,6 +1128,16 @@
 #define SCS_POSIX_BINARY    4
 #define SCS_OS216_BINARY    5
 
+/* LOGON support APIs */
+#define LOGON32_LOGON_INTERACTIVE 2
+#define LOGON32_LOGON_NETWORK     3
+#define LOGON32_LOGON_BATCH       4
+#define LOGON32_LOGON_SERVICE     5
+#define LOGON32_PROVIDER_DEFAULT  0
+#define LOGON32_PROVIDER_WINNT35  1
+#define LOGON32_PROVIDER_WINNT40  2
+#define LOGON32_PROVIDER_WINNT50  3
+
 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType );
 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType );
 #define GetBinaryType WINELIB_NAME_AW(GetBinaryType)
@@ -1375,6 +1385,9 @@
 BOOL        WINAPI ImpersonateLoggedOnUser(HANDLE);
 BOOL        WINAPI ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL);
 BOOL        WINAPI IsProcessorFeaturePresent(DWORD);
+BOOL        WINAPI LogonUserA(LPSTR,LPSTR,LPSTR,DWORD,DWORD,PHANDLE);
+BOOL        WINAPI LogonUserW(LPWSTR,LPWSTR,LPWSTR,DWORD,DWORD,PHANDLE);
+#define     LogonUser WINELIB_NAME_AW(LogonUser)
 BOOL        WINAPI LookupAccountSidA(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
 BOOL        WINAPI LookupAccountSidW(LPCWSTR,PSID,LPWSTR,LPDWORD,LPWSTR,LPDWORD,PSID_NAME_USE);
 #define     LookupAccountSid WINELIB_NAME_AW(LookupAccountSid)




More information about the wine-patches mailing list