mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
425 lines
16 KiB
425 lines
16 KiB
// BUGBUG: %ws for UNICODE is old-style.
|
|
/*
|
|
NETWKSTA.C -- a sample program demonstrating NetWksta API functions.
|
|
|
|
This program requires that you have admin privileges on the
|
|
specified server.
|
|
|
|
usage: netwksta [-s \\server] [-l level] [-d domain] [-u username]
|
|
[-p password] [-f logoff force]
|
|
where \\server = Name of the server. A servername must be
|
|
preceded by two backslashes (\\).
|
|
level = Level of detail to be provided/supplied.
|
|
domain = Logon domain.
|
|
username = Name of the logon user.
|
|
password = Password for the logon user.
|
|
logoff force = Level of logoff force.
|
|
|
|
API Used to...
|
|
=============== ==============================================
|
|
NetWkstaGetInfo Return information about the configuration
|
|
components for a workstation.
|
|
NetWkstaSetInfo Change configuration of currently executing
|
|
workstation. This example doubles the values
|
|
for charcount and chartime each time it is run.
|
|
NetWkstaSetUID2 Log on or log off the user. BUGBUG not under NT!
|
|
|
|
This code sample is provided for demonstration purposes only.
|
|
Microsoft makes no warranty, either express or implied,
|
|
as to its usability in any given situation.
|
|
|
|
26-Dec-1991 JohnRo
|
|
Revised from LanMan 2.0 SDK to use NT/LAN APIs, etc.
|
|
20-Jul-1992 JohnRo
|
|
Move closer to using real 32-bit APIs. Enable UNICODE.
|
|
*/
|
|
|
|
// These must be included first:
|
|
|
|
#ifndef UNICODE
|
|
#define UNICODE // All Net APIs are now UNICODE APIs.
|
|
#endif
|
|
|
|
#define NOMINMAX // Avoid windows vs. stdlib.h conflicts.
|
|
#include <windef.h> // BOOL, DWORD, LPBYTE, LPVOID, TRUE, etc.
|
|
#include <lmcons.h> // NET_API_STATUS, etc. (Must be before other lm*.h)
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <assert.h> // BUGBUG get rid of this
|
|
#include <lmapibuf.h> // NetApiBufferFree().
|
|
#include <dlwksta.h> // BUGBUG: downlevel structures!
|
|
#include <lmwksta.h> // NetWksta APIs, WKSTA_INFO_x, etc.
|
|
#include <lmerr.h> // NERR_ and ERROR_ equates.
|
|
#include "samples.h" // Internal routine header file
|
|
#include <stdio.h> // C run-time header files
|
|
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS, _CRTAPI1.
|
|
#include <string.h>
|
|
|
|
|
|
// Define function prototypes
|
|
void ProcessLogonCode(struct user_logon_info_1 *p1);
|
|
void ProcessLogoffCode(struct user_logoff_info_1 *p1);
|
|
void ProcessAccessDenied(struct user_logon_info_1 *p1);
|
|
void Usage(char * pszString);
|
|
|
|
int _CRTAPI1
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
LPVOID pbBuffer; // Pointer to data buffer
|
|
LPWSTR pszDomainName = L""; // Default to local machine
|
|
LPWSTR pszServer = L""; // Default to local machine
|
|
LPWSTR pszUserName = L""; // Default to null username
|
|
LPWSTR pszPassword = L""; // Default to null password
|
|
int iCount; // Index counter
|
|
DWORD sLevel = 0; // Level of info in pbBuffer
|
|
unsigned short usLogoffForce = 0; // Level of force for logoff
|
|
NET_API_STATUS uRetCode; // API return code
|
|
LPWKSTA_INFO_0 p0; // Workstation info; level 0
|
|
LPWKSTA_INFO_1 p1; // Workstation info; level 1
|
|
LPWKSTA_INFO_10 p10; // Workstation info; level 10
|
|
|
|
for (iCount = 1; iCount < argc; iCount++) // Get command-line switches
|
|
{
|
|
if ((*argv[iCount] == '-') || (*argv[iCount] == '/'))
|
|
{
|
|
switch (tolower(*(argv[iCount]+1))) // Process switches
|
|
{
|
|
case 'd': // -d domain name
|
|
pszDomainName = SafeMallocWStrFromStr(argv[++iCount]);
|
|
assert( pszDomainName != NULL );
|
|
break;
|
|
case 's': // -s servername
|
|
pszServer = SafeMallocWStrFromStr(argv[++iCount]);
|
|
assert( pszServer != NULL );
|
|
break;
|
|
case 'u': // -u username
|
|
pszUserName = SafeMallocWStrFromStr(argv[++iCount]);
|
|
assert( pszUserName != NULL );
|
|
break;
|
|
case 'p': // -p password
|
|
pszPassword = SafeMallocWStrFromStr(argv[++iCount]);
|
|
assert( pszPassword != NULL );
|
|
break;
|
|
case 'l': // -l level
|
|
sLevel = (DWORD) atoi(argv[++iCount]);
|
|
break;
|
|
case 'f': // -f logoff force
|
|
usLogoffForce = atoi(argv[++iCount]);
|
|
break;
|
|
case 'h':
|
|
default:
|
|
Usage(argv[0]);
|
|
}
|
|
}
|
|
else
|
|
Usage(argv[0]);
|
|
}
|
|
printf("\nWorkstation Category API Examples\n");
|
|
|
|
//========================================================================
|
|
// NetWkstaGetInfo
|
|
//
|
|
// This API returns information about the workstation configuration.
|
|
// The data reflects all changes made by NetWkstaSetInfo, but may
|
|
// not be the same as the default values as set in the LANMAN.INI file.
|
|
// For LANMAN.INI parameter values, use NetConfigGet2.
|
|
//========================================================================
|
|
|
|
uRetCode = NetWkstaGetInfo(pszServer, // Servername
|
|
sLevel, // Reporting level (0,1,10)
|
|
(LPBYTE *) &pbBuffer); // Alloc buffer and set ptr
|
|
|
|
printf("NetWkstaGetInfo returned %lu\n", uRetCode);
|
|
if (uRetCode != NERR_Success)
|
|
exit( EXIT_FAILURE );
|
|
|
|
if ((sLevel == 0) || (sLevel == 1)) // Display common elements
|
|
{
|
|
p0 = (LPVOID) pbBuffer;
|
|
printf(" Computer Name : %ws\n", p0->wki0_computername);
|
|
printf(" User Name : %ws\n", p0->wki0_username);
|
|
printf(" Lan Group : %ws\n", p0->wki0_langroup);
|
|
printf(" Logon Server : %ws\n", p0->wki0_logon_server);
|
|
printf(" Char Time : %lu\n", p0->wki0_chartime);
|
|
printf(" Char Count : %lu\n", p0->wki0_charcount);
|
|
}
|
|
if (sLevel == 1)
|
|
{
|
|
p1 = (LPVOID) pbBuffer;
|
|
printf(" Logon Domain : %ws\n", p1->wki1_logon_domain);
|
|
printf(" Other Domains : %ws\n", p1->wki1_oth_domains);
|
|
printf(" Datagram Buffers: %lu\n", p1->wki1_numdgrambuf);
|
|
}
|
|
if (sLevel == 10)
|
|
{
|
|
p10 = (LPVOID) pbBuffer;
|
|
printf(" Computer Name : %ws\n", p10->wki10_computername);
|
|
printf(" User Name : %ws\n", p10->wki10_username);
|
|
printf(" Logon Domain : %ws\n", p10->wki10_logon_domain);
|
|
printf(" Other Domains : %ws\n", p10->wki10_oth_domains);
|
|
}
|
|
|
|
//========================================================================
|
|
// NetWkstaSetInfo
|
|
//
|
|
// This API sets configuration components for the specified LAN Manager
|
|
// workstation. This API does not modify the LANMAN.INI file. The call
|
|
// to NetWkstaSetInfo can reset all parameters or only one parameter.
|
|
// To reset all parameters, first call NetWkstaGetInfo, modify the
|
|
// desired components, then use NetWkstaSetInfo. If you want to change
|
|
// only one parameter, supply the variable that will change, and then
|
|
// call NetWkstaSetInfo with the corresponding parameter number code.
|
|
//========================================================================
|
|
|
|
// Previous call to NetWkstaGetInfo assures valid data in structure.
|
|
|
|
p0 = (LPVOID) pbBuffer;
|
|
|
|
// Double the chartime and charcount values
|
|
p0->wki0_chartime *= 2;
|
|
p0->wki0_charcount *= 2;
|
|
|
|
assert( sLevel != 10 ); // BUGBUG: level 0 is not subset of 10!
|
|
|
|
uRetCode = NetWkstaSetInfo(pszServer, // Servername
|
|
sLevel, // Info level and parmnum
|
|
pbBuffer, // Source buffer for info
|
|
NULL); // Don't want parmerr if failure
|
|
|
|
printf("NetWkstaSetInfo returned %lu\n", uRetCode);
|
|
|
|
if (uRetCode == NERR_Success)
|
|
{
|
|
printf(" Char Time set to : %lu\n", p0->wki0_chartime);
|
|
printf(" Char Count set to : %lu\n", p0->wki0_charcount);
|
|
}
|
|
(void) NetApiBufferFree(pbBuffer);
|
|
|
|
#if 0
|
|
|
|
//========================================================================
|
|
// NetWkstaSetUID2
|
|
//
|
|
// This API logs a user on to or off from the network. The username
|
|
// parameter determines which operation to perform; a null username
|
|
// indicates alog off operation, a non-null username indicates a logon
|
|
// operation.
|
|
//========================================================================
|
|
|
|
// Make an initial call to determine the required return buffer size.
|
|
|
|
uRetCode = NetWkstaSetUID2(NULL, // Reserved; must be NULL
|
|
NULL, // Domain to log on to
|
|
NULL, // User to logon or null=logoff
|
|
NULL, // User password if logon
|
|
"", // Reserved; must be null string
|
|
0, // Logoff force
|
|
1, // Level; must be 1
|
|
NULL, // Logon data returned
|
|
0, // Size of data area, in bytes
|
|
&cbTotalAvail); // Count of total bytes available
|
|
|
|
cbBuflen = cbTotalAvail;
|
|
pbBuffer = SafeMalloc(cbBuflen);
|
|
|
|
uRetCode = NetWkstaSetUID2(NULL, // Reserved; must be NULL
|
|
pszDomainName, // Domain to log on to
|
|
pszUserName, // User to logon or null=logoff
|
|
pszPassword, // User password if logon
|
|
"", // Reserved; must be null string
|
|
usLogoffForce, // Logoff force
|
|
1, // Level; must be 1
|
|
pbBuffer, // Logon data returned
|
|
cbBuflen, // Size of buffer, in bytes
|
|
&cbTotalAvail); // Count of total bytes available
|
|
printf("NetWkstaSetUID2 returned %lu\n", uRetCode);
|
|
|
|
if ((*pszUserName == '\0') || (pszUserName == NULL))
|
|
{
|
|
printf("Log off using logoff code %wu\n", usLogoffForce);
|
|
switch (uRetCode)
|
|
{
|
|
case NERR_NotLoggedOn:
|
|
printf("Not logged on\n");
|
|
break;
|
|
case NERR_Success:
|
|
case NERR_UnableToDelName_W:
|
|
ProcessLogoffCode((struct user_logoff_info_1 *) pbBuffer);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else // Non-null username indicates a logon operation.
|
|
{
|
|
printf("Log user %ws (password %ws)",pszUserName, pszPassword);
|
|
if ((*pszDomainName == '\0') || (pszDomainName == NULL))
|
|
printf(" on the workstation's primary domain\n");
|
|
else
|
|
printf(" on domain %ws\n", pszDomainName);
|
|
|
|
switch (uRetCode)
|
|
{
|
|
case NERR_Success:
|
|
case NERR_UnableToAddName_W:
|
|
ProcessLogonCode((struct user_logon_info_1 *) pbBuffer);
|
|
break;
|
|
case NERR_StandaloneLogon:
|
|
printf("No logon server specified, logged on STANDALONE\n");
|
|
break;
|
|
case NERR_BadUsername:
|
|
case NERR_BadPassword:
|
|
printf("Invalid username or password\n");
|
|
break;
|
|
case NERR_AlreadyLoggedOn:
|
|
case NERR_NotLoggedOn:
|
|
printf("Did not logon user \n");
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
ProcessAccessDenied((struct user_logon_info_1 *) pbBuffer);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
free(pbBuffer);
|
|
|
|
#endif // 0
|
|
|
|
return (EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
//========================================================================
|
|
// Applications that call NetWkstaSetUID2 need to examine two different
|
|
// return code variables to determine whether structure elements in the
|
|
// return buffer contain valid data.
|
|
//
|
|
// This example program first examines the return code returned by the
|
|
// function, and then calls the functions ProcessLogoffCode,
|
|
// ProcessLogonCode, and ProcessAccessDenied to examine the return code
|
|
// within the user_logon_info_1 or user_logoff_info_1 data structures.
|
|
//
|
|
// The combination of values of the function return code and the code
|
|
// present in the return buffer determines which structure elements
|
|
// contain valid data.
|
|
//
|
|
// ProcessLogoffCode examines the usrlogf1_code element of the
|
|
// user_logoff_info_1 data structure when NetWkstaSetUID2, called with a
|
|
// null username, return NERR_Success or NERR_UnableToDelName_W.
|
|
//========================================================================
|
|
|
|
#if 0
|
|
|
|
void ProcessLogoffCode(struct user_logoff_info_1 *p1)
|
|
{
|
|
printf("Logoff code = %lu\n", p1->usrlogf1_code);
|
|
|
|
switch (p1->usrlogf1_code)
|
|
{
|
|
case NERR_Success: // All elements valid
|
|
printf("Duration of logon: %lu\n", p1->usrlogf1_duration);
|
|
printf("%lu other logons\n", p1->usrlogf1_num_logons);
|
|
break;
|
|
case NERR_NonValidatedLogon: // No other valid elements in p1
|
|
printf("Non validated logon\n");
|
|
break;
|
|
case NERR_StandaloneLogon:
|
|
printf("Standalone logon\n");
|
|
break;
|
|
default:
|
|
printf("No valid fields\n");
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//========================================================================
|
|
// For calls to NetWkstaSetUID2, two different return code variables
|
|
// are needed to determine whether structure elements in the return
|
|
// buffer contain valid data. ProcessLogonCode examines the
|
|
// usrlog1_code element of the user_logon_info_1 data structure when
|
|
// NetWkstaSetUID2, called with a non-null username, returned NERR_Success
|
|
// or NERR_UnableToAddName_W.
|
|
//========================================================================
|
|
|
|
void ProcessLogonCode(struct user_logon_info_1 *p1)
|
|
{
|
|
printf("Logon code = %lu\n", p1->usrlog1_code);
|
|
switch (p1->usrlog1_code)
|
|
{
|
|
case NERR_Success: // All codes valid
|
|
printf("User %ws", p1->usrlog1_eff_name);
|
|
printf(" has privilege level %lu\n", p1->usrlog1_priv);
|
|
break;
|
|
case NERR_NonValidatedLogon: // Computer, script valid
|
|
printf("Used logon script %ws", p1->usrlog1_script_path);
|
|
printf(" on %ws\n", p1->usrlog1_computer);
|
|
break;
|
|
case NERR_StandaloneLogon:
|
|
printf("Standalone logon\n");
|
|
break;
|
|
default:
|
|
printf("No valid fields\n");
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//========================================================================
|
|
// For calls to NetWkstaSetUID2, two different return code variables
|
|
// are needed to determine whether structure elements in the return
|
|
// buffer contain valid data.
|
|
|
|
// ProcessAccessDenied examines the usrlog1_code element of the
|
|
// user_logon_info_1 data structure when NetWkstaSetUID2, called with a
|
|
// non-null username, returns the return code value ERROR_ACCESS_DENIED.
|
|
//========================================================================
|
|
|
|
void ProcessAccessDenied(struct user_logon_info_1 *p1)
|
|
{
|
|
printf("Logon code = %lu\n", p1->usrlog1_code);
|
|
switch (p1->usrlog1_code)
|
|
{
|
|
case NERR_PasswordExpired:
|
|
printf("Password expired\n");
|
|
break;
|
|
case NERR_InvalidWorkstation:
|
|
printf("Invalid workstation\n");
|
|
break;
|
|
case NERR_InvalidLogonHours:
|
|
printf("Invalid logon hours\n");
|
|
break;
|
|
case NERR_LogonScriptError:
|
|
printf("Logon script error\n");
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
printf("Access denied\n");
|
|
break;
|
|
default:
|
|
printf("No valid fields\n");
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
|
|
//========================================================================
|
|
// Usage
|
|
//
|
|
// Display possible command line switches for this example.
|
|
//========================================================================
|
|
|
|
void Usage(char * pszString)
|
|
{
|
|
fprintf(stderr, "Usage: %s [-s \\\\server] [-d domain]", pszString);
|
|
fprintf(stderr, " [-l level]\n\t[-u username] [-p password]");
|
|
fprintf(stderr, " [-f logoff force]\n");
|
|
exit( EXIT_FAILURE );
|
|
}
|