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.
624 lines
19 KiB
624 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1991-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
TestSvc.c
|
|
|
|
Abstract:
|
|
|
|
This code tests the service API(s) as implemented by RpcXlate.
|
|
|
|
Author:
|
|
|
|
John Rogers (JohnRo) 25-Sep-1991
|
|
|
|
Environment:
|
|
|
|
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
|
|
25-Sep-1991 JohnRo
|
|
Downlevel NetService APIs.
|
|
09-Sep-1992 JohnRo
|
|
RAID 1090: net start/stop "" causes assertion.
|
|
Added user-only (not admin) option.
|
|
Made changes suggested by PC-LINT.
|
|
28-Oct-1992 JohnRo
|
|
Use RxTestIsAccessDenied().
|
|
03-Nov-1992 JohnRo
|
|
Integrated RitaW's changes to this code.
|
|
LM/UNIX does not have a workstation service, so allow it to be missing.
|
|
10-Dec-1992 JohnRo
|
|
Made changes suggested by PC-LINT 5.0
|
|
16-Feb-1993 JohnRo
|
|
Service control (bogus) is another case of missing service.
|
|
Also, wait for stop pending or start pending status to finish.
|
|
04-May-1993 JohnRo
|
|
Windows for WorkGroups (WFW) does not implement some APIs.
|
|
04-May-1993 JohnRo
|
|
Missed another call to NetServiceControlGetInfo.
|
|
02-Jun-1993 JohnRo
|
|
LM/UNIX NetServiceControl often returns NERR_ServiceCtlTimeout.
|
|
29-Jun-1993 JohnRo
|
|
Use assert() instead of NetpAssert(), for better use on free builds.
|
|
07-Jul-1993 JohnRo
|
|
Added -m (multiple copy) option.
|
|
Use TestAssert() (which may allow continue-on-error).
|
|
11-Aug-1993 JohnRo
|
|
Use Sleep() in WaitUntilPendingFinished().
|
|
|
|
--*/
|
|
|
|
|
|
// These must be included first:
|
|
|
|
#include <windows.h> // IN, DWORD, Sleep(), TEXT, etc.
|
|
#include <lmcons.h> // NET_API_STATUS, etc.
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <lmapibuf.h> // NetapipBufferAllocate(), NetApiBufferFree().
|
|
#include <lmerr.h> // NERR_Success, etc.
|
|
#include <lmsvc.h> // NetService APIs.
|
|
#include <netdebug.h> // DBGSTATIC, FORMAT_POINTER, etc.
|
|
#include <netlib.h> // NetpIsRemoteServiceStarted().
|
|
#include <rxtest.h> // Fail(), my prototypes.
|
|
|
|
|
|
// This checks for different error codes from different implementations:
|
|
//
|
|
// NERR_ServiceNotInstalled (from down-level)
|
|
// NERR_BadServiceName ("improved" error code from NT)
|
|
//
|
|
#define RxTestMissingServiceStatus( someStatus ) \
|
|
( ( (someStatus)==NERR_ServiceNotInstalled ) \
|
|
|| ( (someStatus)==NERR_BadServiceName ) )
|
|
|
|
|
|
// Define some non-existent service name.
|
|
#define SERVICE_BOGUS TEXT("FLARP")
|
|
|
|
|
|
// Arbitrary sleep time (5 seconds) in milliseconds.
|
|
#define SOME_TIME_MS ( 5 * 1000 )
|
|
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceControl(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR Service,
|
|
IN DWORD OpCode,
|
|
IN BOOL MultipleCopy,
|
|
IN BOOL OrdinaryUserOnly,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
);
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceEnum(
|
|
IN LPTSTR UncServerName,
|
|
IN DWORD Level,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
);
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceGetInfo(
|
|
IN LPTSTR UncServerName,
|
|
IN DWORD Level,
|
|
IN LPTSTR Service OPTIONAL,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
);
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceInstall(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR Service,
|
|
IN BOOL MultipleCopy,
|
|
IN BOOL OrdinaryUserOnly,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
);
|
|
|
|
DBGSTATIC VOID
|
|
WaitUntilPendingFinished(
|
|
IN LPTSTR UncServerName OPTIONAL,
|
|
IN LPTSTR ServiceService
|
|
);
|
|
|
|
VOID
|
|
TestService(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR ServiceName,
|
|
IN BOOL MultipleCopy,
|
|
IN BOOL OrdinaryUserOnly
|
|
)
|
|
|
|
{
|
|
LPTSTR EmptyServiceName = (LPVOID) TEXT("");
|
|
BOOL ServiceWasAlreadyStarted;
|
|
|
|
//
|
|
// NetServiceGetInfo tests...
|
|
//
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
1234, // level
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
TRUE, // yes, possible missing service
|
|
ERROR_INVALID_LEVEL );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
0, // level
|
|
NULL, // no service name (null ptr)
|
|
FALSE, // no, not possible missing service
|
|
NERR_BadServiceName );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
0, // level
|
|
EmptyServiceName, // no service name (null char)
|
|
FALSE, // no, not possible missing service
|
|
NERR_BadServiceName );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
0, // level
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
TRUE, // yes, possible missing service
|
|
NERR_Success );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
1, // level
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
TRUE, // yes, possible missing service
|
|
NERR_Success );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
2, // level
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
TRUE, // yes, possible missing service
|
|
NERR_Success );
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
2, // level
|
|
(LPTSTR) SERVICE_BOGUS,
|
|
TRUE, // yes, possible missing service
|
|
NERR_ServiceNotInstalled );
|
|
|
|
//
|
|
// NetServiceControl...
|
|
//
|
|
TestServiceControl(
|
|
UncServerName,
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
SERVICE_CTRL_INTERROGATE, // opcode
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
TRUE, // yes, possible missing service
|
|
NERR_Success);
|
|
|
|
TestServiceControl(
|
|
UncServerName,
|
|
(LPTSTR) SERVICE_SERVER,
|
|
SERVICE_CTRL_INTERROGATE, // opcode
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
FALSE, // no, not possible missing service
|
|
NERR_Success);
|
|
|
|
TestServiceControl(
|
|
UncServerName,
|
|
(LPTSTR) SERVICE_BOGUS,
|
|
SERVICE_CTRL_INTERROGATE, // opcode
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
TRUE, // yes, possible missing service
|
|
NERR_ServiceNotInstalled);
|
|
|
|
//
|
|
// NetServiceEnum tests...
|
|
//
|
|
TestServiceEnum(
|
|
UncServerName,
|
|
33333, // level
|
|
ERROR_INVALID_LEVEL );
|
|
TestServiceEnum(
|
|
UncServerName,
|
|
0, // level
|
|
NERR_Success );
|
|
TestServiceEnum(
|
|
UncServerName,
|
|
1, // level
|
|
NERR_Success );
|
|
TestServiceEnum(
|
|
UncServerName,
|
|
2, // level
|
|
NERR_Success );
|
|
|
|
//
|
|
// NetServiceInstall tests...
|
|
//
|
|
TestServiceInstall(
|
|
UncServerName,
|
|
(LPTSTR) SERVICE_BOGUS,
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
TRUE, // yes, possible missing service
|
|
NERR_BadServiceName);
|
|
TestServiceInstall(
|
|
UncServerName,
|
|
(LPTSTR) SERVICE_WORKSTATION,
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
TRUE, // yes, possible missing service
|
|
NERR_ServiceInstalled);
|
|
|
|
//
|
|
// OK, now we're going to a series of things involving a "harmless"
|
|
// service. First, we're going to find out if it is already started.
|
|
// That way we can try to put things back the way they were.
|
|
//
|
|
|
|
|
|
ServiceWasAlreadyStarted = NetpIsRemoteServiceStarted(
|
|
UncServerName,
|
|
ServiceName );
|
|
|
|
IF_DEBUG( SERVICE ) {
|
|
NetpKdPrint((
|
|
"TestService: " FORMAT_LPTSTR " " FORMAT_LPSTR
|
|
" already started.\n",
|
|
ServiceName,
|
|
ServiceWasAlreadyStarted ? "was" : "was not" ));
|
|
}
|
|
|
|
if ( ! ServiceWasAlreadyStarted ) {
|
|
TestServiceInstall(
|
|
UncServerName,
|
|
(LPTSTR) ServiceName,
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
FALSE, // no, not possible missing service
|
|
NO_ERROR);
|
|
}
|
|
|
|
TestServiceGetInfo(
|
|
UncServerName,
|
|
2, // level
|
|
(LPTSTR) ServiceName,
|
|
OrdinaryUserOnly, // Possible missing service only if we
|
|
// didn't have permission to start it.
|
|
NERR_Success);
|
|
|
|
// That install might take a while, so wait for it.
|
|
WaitUntilPendingFinished(
|
|
UncServerName,
|
|
ServiceName );
|
|
|
|
TestServiceControl(
|
|
UncServerName,
|
|
(LPTSTR) ServiceName,
|
|
SERVICE_CTRL_UNINSTALL, // opcode
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
MultipleCopy, // possible missing iff multiple RxTests
|
|
NO_ERROR);
|
|
|
|
if ( ServiceWasAlreadyStarted ) {
|
|
|
|
// That stop might take a while, so wait for it.
|
|
WaitUntilPendingFinished(
|
|
UncServerName,
|
|
ServiceName );
|
|
|
|
TestServiceInstall(
|
|
UncServerName,
|
|
(LPTSTR) ServiceName,
|
|
MultipleCopy,
|
|
OrdinaryUserOnly,
|
|
MultipleCopy, // possible missing iff multiple RxTests
|
|
NO_ERROR);
|
|
|
|
// That install might take a while, so wait for it.
|
|
WaitUntilPendingFinished(
|
|
UncServerName,
|
|
ServiceName );
|
|
}
|
|
} // TestService
|
|
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceControl(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR Service,
|
|
IN DWORD OpCode,
|
|
IN BOOL MultipleCopy,
|
|
IN BOOL OrdinaryUserOnly,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
)
|
|
{
|
|
LPVOID Info = NULL;
|
|
const DWORD Level = 2;
|
|
NET_API_STATUS Status;
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "\nTestServiceControl: trying control(" FORMAT_DWORD
|
|
") on service " FORMAT_LPTSTR ".\n", OpCode, Service ));
|
|
}
|
|
Status = NetServiceControl(
|
|
UncServerName, // server name
|
|
Service,
|
|
OpCode,
|
|
0, // control arg
|
|
(LPBYTE *) & Info); // result (always level 2)
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(("TestServiceControl: back from NetServiceControl, Status="
|
|
FORMAT_API_STATUS ".\n", Status));
|
|
NetpKdPrint(("TestServiceControl: NetServiceControl alloc'ed buffer at "
|
|
FORMAT_LPVOID ".\n", (LPVOID) Info));
|
|
}
|
|
|
|
if ( PossibleMissingService && RxTestMissingServiceStatus( Status ) ) {
|
|
return;
|
|
} else if (MultipleCopy && (Status==NERR_ServiceNotCtrl) ) {
|
|
return;
|
|
} else if (OrdinaryUserOnly && RxTestIsAccessDenied( Status ) ) {
|
|
return;
|
|
} else if (Status == ERROR_NOT_SUPPORTED) {
|
|
return; // WFW does not implement this API.
|
|
} else if (Status == NERR_ServiceCtlTimeout) {
|
|
return; // LM/UNIX often returns this.
|
|
} else if (Status != ExpectedStatus) {
|
|
FailGotWrongStatus( "TestServiceControl", ExpectedStatus, Status );
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
if (Info != NULL) {
|
|
IF_DEBUG(SERVICE) {
|
|
NetpDbgDisplayService( Level, Info );
|
|
}
|
|
(void) NetApiBufferFree(Info);
|
|
}
|
|
|
|
} // TestServiceControl
|
|
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceEnum(
|
|
IN LPTSTR UncServerName,
|
|
IN DWORD Level,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
)
|
|
{
|
|
LPVOID BufPtr;
|
|
DWORD EntriesRead;
|
|
NET_API_STATUS Status;
|
|
DWORD TotalEntries;
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "\nTestServiceEnum: starting level " FORMAT_DWORD
|
|
" test.\n", Level ));
|
|
}
|
|
Status = NetServiceEnum(
|
|
UncServerName,
|
|
Level,
|
|
(LPBYTE *) & BufPtr,
|
|
1, // preferred maximum (arbitrary) (force ERROR_MORE_DATA)
|
|
& EntriesRead,
|
|
& TotalEntries,
|
|
NULL); // no resume handle
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "TestServiceEnum: back from NetServiceEnum, stat="
|
|
FORMAT_API_STATUS "\n", Status ));
|
|
}
|
|
if (Status == ERROR_NOT_SUPPORTED) {
|
|
return; // WFW does not implement this API.
|
|
} else if (Status != ExpectedStatus ) {
|
|
NetpKdPrint(( "TestServiceEnum: unexpected return code "
|
|
FORMAT_API_STATUS " from NetServiceEnum.\n", Status ));
|
|
FailGotWrongStatus( "TestServiceEnum", ExpectedStatus, Status );
|
|
/*NOTREACHED*/
|
|
}
|
|
if (Status == NERR_Success) {
|
|
if (BufPtr == NULL) {
|
|
NetpKdPrint(( "TestServiceEnum: status as expected "
|
|
"but null ptr from NetServiceEnum\n" ));
|
|
Fail( NERR_InternalError );
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
if (EntriesRead != 0) {
|
|
NetpDbgDisplayServiceArray( Level, BufPtr, EntriesRead );
|
|
}
|
|
}
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "TestServiceEnum: Freeing buffer...\n" ));
|
|
}
|
|
Status = NetApiBufferFree( BufPtr );
|
|
if (Status != NERR_Success ) {
|
|
NetpKdPrint(( "TestServiceEnum: unexpected return code "
|
|
FORMAT_API_STATUS " from NetApiBufferFree.\n", Status ));
|
|
Fail( Status );
|
|
/*NOTREACHED*/
|
|
}
|
|
}
|
|
} // TestServiceEnum
|
|
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceGetInfo(
|
|
IN LPTSTR UncServerName,
|
|
IN DWORD Level,
|
|
IN LPTSTR Service,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
)
|
|
{
|
|
LPVOID Info = NULL;
|
|
NET_API_STATUS Status;
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(("\nTestServiceGetInfo: trying level " FORMAT_DWORD ".\n",
|
|
Level));
|
|
NetpKdPrint(("\nTestServiceGetInfo: expect " FORMAT_API_STATUS "\n",
|
|
ExpectedStatus));
|
|
}
|
|
Status = NetServiceGetInfo(
|
|
UncServerName, // server name
|
|
Service,
|
|
Level, // info level
|
|
(LPBYTE *) & Info);
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(("TestServiceGetInfo: back from NetServiceGetInfo, Status="
|
|
FORMAT_API_STATUS ".\n", Status));
|
|
NetpKdPrint(("\nTestServiceGetInfo: expect " FORMAT_API_STATUS "\n",
|
|
ExpectedStatus));
|
|
NetpKdPrint(("TestServiceGetInfo: NetServiceGetInfo alloc'ed buffer at "
|
|
FORMAT_LPVOID ".\n", (LPVOID) Info));
|
|
}
|
|
|
|
if ( PossibleMissingService && RxTestMissingServiceStatus( Status ) ) {
|
|
return;
|
|
} else if (Status == ERROR_NOT_SUPPORTED) {
|
|
return; // WFW does not implement this API.
|
|
} else if (Status != ExpectedStatus) {
|
|
FailGotWrongStatus( "TestServiceGetInfo", ExpectedStatus, Status );
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
if (Info != NULL) {
|
|
IF_DEBUG(SERVICE) {
|
|
NetpDbgDisplayService( Level, Info );
|
|
}
|
|
(void) NetApiBufferFree(Info);
|
|
}
|
|
|
|
} // TestServiceGetInfo
|
|
|
|
|
|
DBGSTATIC VOID
|
|
TestServiceInstall(
|
|
IN LPTSTR UncServerName,
|
|
IN LPTSTR Service,
|
|
IN BOOL MultipleCopy,
|
|
IN BOOL OrdinaryUserOnly,
|
|
IN BOOL PossibleMissingService,
|
|
IN NET_API_STATUS ExpectedStatus
|
|
)
|
|
{
|
|
LPVOID Info = NULL;
|
|
const DWORD Level = 2; // by definition
|
|
NET_API_STATUS Status;
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "\nTestServiceInstall: trying to install "
|
|
FORMAT_LPTSTR ".\n", Service ));
|
|
}
|
|
Status = NetServiceInstall(
|
|
UncServerName,
|
|
Service,
|
|
0, // argc
|
|
NULL, // argv
|
|
(LPBYTE *) (LPVOID *) &Info);
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "TestServiceInstall: back from NetServiceInstall, Status="
|
|
FORMAT_API_STATUS ".\n", Status ));
|
|
NetpKdPrint(( "TestServiceInstall: NetServiceInstall alloc'ed buffer"
|
|
" at " FORMAT_LPVOID ".\n", (LPVOID) Info ));
|
|
}
|
|
|
|
if (OrdinaryUserOnly && RxTestIsAccessDenied( Status ) ) {
|
|
return;
|
|
} else if ( MultipleCopy && (Status==NERR_ServiceInstalled) ) {
|
|
return; // already started by another copy of RxTest? No problem.
|
|
} else if ( PossibleMissingService && RxTestMissingServiceStatus(Status) ) {
|
|
return;
|
|
} else if (Status == ERROR_NOT_SUPPORTED) {
|
|
return; // WFW does not implement this API.
|
|
} else if (Status != ExpectedStatus) {
|
|
FailGotWrongStatus( "TestServiceInstall", ExpectedStatus, Status );
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
if (Info != NULL) {
|
|
IF_DEBUG(SERVICE) {
|
|
NetpDbgDisplayService( Level, Info );
|
|
}
|
|
(void) NetApiBufferFree( Info );
|
|
}
|
|
} // TestServiceInstall
|
|
|
|
|
|
DBGSTATIC VOID
|
|
WaitUntilPendingFinished(
|
|
IN LPTSTR UncServerName OPTIONAL,
|
|
IN LPTSTR ServiceName
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
LPSERVICE_INFO_1 Info = NULL;
|
|
DWORD InstallState;
|
|
const DWORD Level = 1; // Level 1 is simplest with status field.
|
|
|
|
/*lint -save -e716 */ // disable warnings for while(TRUE)
|
|
while (TRUE) {
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "\nWaitUntilPendingFinished: getting status...\n" ));
|
|
}
|
|
ApiStatus = NetServiceGetInfo(
|
|
UncServerName, // server name
|
|
ServiceName,
|
|
Level, // info level
|
|
(LPBYTE *) (LPVOID) & Info);
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint((
|
|
"WaitUntilPendingFinished: back from NetServiceGetInfo, "
|
|
"ApiStatus="
|
|
FORMAT_API_STATUS ".\n", ApiStatus ));
|
|
}
|
|
|
|
if (ApiStatus == ERROR_NOT_SUPPORTED) {
|
|
return; // WFW does not implement this API.
|
|
} else if (ApiStatus == NERR_ServiceNotInstalled) {
|
|
return; // LM/UNIX often returns this.
|
|
} else if (ApiStatus != NO_ERROR) {
|
|
FailGotWrongStatus(
|
|
"WaitUntilPendingFinished(NetServiceGetInfo)",
|
|
NO_ERROR, // expected
|
|
ApiStatus ); // actual
|
|
goto Cleanup;
|
|
}
|
|
TestAssert( Info != NULL );
|
|
|
|
InstallState = (Info->svci1_status) & SERVICE_INSTALL_STATE;
|
|
|
|
(VOID) NetApiBufferFree( Info );
|
|
Info = NULL;
|
|
|
|
if ( InstallState == SERVICE_UNINSTALL_PENDING ) {
|
|
Sleep( SOME_TIME_MS );
|
|
continue;
|
|
} else if ( InstallState == SERVICE_INSTALL_PENDING ) {
|
|
Sleep( SOME_TIME_MS );
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
} // while TRUE...
|
|
/*lint -restore */ // re-enable warnings for while(TRUE)
|
|
|
|
Cleanup:
|
|
if (Info != NULL) {
|
|
(VOID) NetApiBufferFree(Info);
|
|
}
|
|
|
|
} // WaitUntilPendingFinished
|