NULLSESS.C
/*++ 
 
Copyright 1996 - 1997 Microsoft Corporation 
 
Module Name: 
 
    nullsess.c 
 
Abstract: 
 
    This module illustrates how to use a Null session to overcome access 
    problems during network related query operations. 
 
    One example of the scenario this approach addresses is as follows: 
 
    User logs onto workstation A as the local administrator. 
 
    Administrator tries to query user information using the NetUserGetInfo() 
    API call on server B.  This call fails with ERROR_ACCESS_DENIED. 
 
    The reason this problem occurs is that the administrator password on 
    workstation A does not match the administrator password on server B. 
 
    During the network query operation, the default behavior is to establish 
    a connection to the remote server using the credentials of the logged-in 
    user.  In some scenarios, this behavior is not appropriate, and the 
    solution is to establish a connection using either known credentials, 
    or the Null credentials.  Null credentials are suitable for most query 
    operations against a remote machine.  However, if administrator 
    related actions are necessary, it is necessary to supply credentials 
    which have administrative privilege on the remote machine.  Valid 
    credentials consist of a username, password, and optional domain name. 
 
    Establishing a connection in this manner requires that no existing 
    connections exist to the remote machine tied to the current logon 
    session. 
 
    Note: Null sessions are those where the user credentials passed in the 
    session setup SMB are null.  This sample only implements a function to 
    establish a Null session, rather than a session with specific credentials. 
 
    Processes and Services running in the Local System account security context 
    have Null credentials by default, so establishing Null sessions in this 
    scenario is not required. 
 
    Applications that run only on Windows NT 4.0 and above can use 
    WNetAddConnection2() rather than NetUseAdd() to establish a Null session. 
 
Author: 
 
    Scott Field (sfield)    13-Jun-96 
 
--*/ 
 
#include <windows.h> 
#include <lm.h> 
 
#include <stdio.h> 
 
BOOL 
EstablishNullSession( 
    LPCWSTR Server, 
    BOOL bEstablish 
    ); 
 
#define RTN_OK 0 
#define RTN_USAGE 1 
#define RTN_ERROR 13 
 
int 
__cdecl 
wmain( 
    int argc, 
    wchar_t *argv[] 
    ) 
{ 
 
    if(argc != 2) { 
        printf("Usage: %ls <\\\\Server>\n", argv[0]); 
        return RTN_USAGE; 
    } 
 
    // 
    // try network operation here.  If this fails with an access denied 
    // error message, retry the operation using a Null session. 
    // 
 
    // 
    // establish a session to the target machine with Null credentials 
    // 
 
    if(EstablishNullSession( argv[1], TRUE )) { 
 
        // 
        // retry network related operation here. 
        // 
 
        // 
        // break the existing connection we made 
        // 
 
        EstablishNullSession( argv[1], FALSE ); 
    } else { 
 
        // 
        // error occurred establishing Null session 
        // 
 
        printf("Error establishing Null session! (rc=%lu)\n", GetLastError()); 
        return RTN_ERROR; 
    } 
 
    return RTN_OK; 
} 
 
BOOL 
EstablishNullSession( 
    LPCWSTR Server, 
    BOOL bEstablish 
    ) 
{ 
    LPCWSTR szIpc = L"\\IPC$"; 
    WCHAR RemoteResource[UNCLEN + 5 + 1]; // UNC len + \IPC$ + NULL 
    DWORD cchServer; 
 
    NET_API_STATUS nas; 
 
    // 
    // do not allow NULL or empty server name 
    // 
 
    if(Server == NULL || *Server == L'\0') { 
        SetLastError(ERROR_INVALID_COMPUTERNAME); 
        return FALSE; 
    } 
 
    cchServer = lstrlenW( Server ); 
 
    if(Server[0] != L'\\' && Server[1] != L'\\') { 
 
        // 
        // prepend slashes and NULL terminate 
        // 
 
        RemoteResource[0] = L'\\'; 
        RemoteResource[1] = L'\\'; 
        RemoteResource[2] = L'\0'; 
    } 
    else { 
        cchServer -= 2; // drop slashes from count 
 
        RemoteResource[0] = L'\0'; 
    } 
 
    if(cchServer > CNLEN) { 
        SetLastError(ERROR_INVALID_COMPUTERNAME); 
        return FALSE; 
    } 
 
    if(lstrcatW(RemoteResource, Server) == NULL) return FALSE; 
    if(lstrcatW(RemoteResource, szIpc) == NULL) return FALSE; 
 
    // 
    // disconnect or connect to the resource, based on bEstablish 
    // 
 
    if(bEstablish) { 
        USE_INFO_2 ui2; 
 
        ZeroMemory(&ui2, sizeof(ui2)); 
 
        ui2.ui2_local = NULL; 
        ui2.ui2_remote = (LPTSTR) RemoteResource; 
        ui2.ui2_asg_type = USE_IPC; 
        ui2.ui2_password = ui2.ui2_username = ui2.ui2_domainname = (LPTSTR) L""; 
 
        nas = NetUseAdd(NULL, 2, (LPBYTE)&ui2, NULL); 
    } 
    else { 
        nas = NetUseDel(NULL, (LPTSTR) RemoteResource, 0); 
    } 
 
    if( nas == NERR_Success ) return TRUE; // indicate success 
 
    SetLastError( nas ); 
 
    return FALSE; 
}