mirror of https://github.com/tongzx/nt5src
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.
1046 lines
31 KiB
1046 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ApiSvc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains individual API handlers for the NetService APIs.
|
|
|
|
SUPPORTED : NetServicControl, NetServiceEnum, NetServiceGetInfo,
|
|
NetServiceInstall.
|
|
|
|
Author:
|
|
|
|
Shanku Niyogi (w-shanku) 26-Feb-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "XactSrvP.h"
|
|
|
|
|
|
#define XACTSRV_CONVERT_SVC_EXITCODE(ob) \
|
|
{ \
|
|
PSERVICE_INFO_2 ss = (PSERVICE_INFO_2) ob; \
|
|
if ((unsigned short) ss->svci2_code == ERROR_SERVICE_SPECIFIC_ERROR) { \
|
|
ss->svci2_code = (ss->svci2_code & 0xffff0000) | (unsigned short) ss->svci2_specific_error;\
|
|
} \
|
|
}
|
|
|
|
|
|
//
|
|
// Declaration of descriptor strings.
|
|
//
|
|
|
|
STATIC const LPDESC Desc16_service_info_0 = REM16_service_info_0;
|
|
STATIC const LPDESC Desc32_service_info_0 = REM32_service_info_0;
|
|
STATIC const LPDESC Desc16_service_info_1 = REM16_service_info_1;
|
|
STATIC const LPDESC Desc32_service_info_1 = REM32_service_info_1;
|
|
STATIC const LPDESC Desc16_service_info_2 = REM16_service_info_2;
|
|
STATIC const LPDESC Desc32_service_info_2 = REM32_service_info_2;
|
|
|
|
|
|
NTSTATUS
|
|
XsNetServiceControl (
|
|
API_HANDLER_PARAMETERS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles a call to NetServiceControl.
|
|
|
|
Arguments:
|
|
|
|
API_HANDLER_PARAMETERS - information about the API call. See
|
|
XsTypes.h for details.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
|
|
PXS_NET_SERVICE_CONTROL parameters = Parameters;
|
|
LPTSTR nativeService = NULL; // Native parameters
|
|
LPVOID outBuffer = NULL;
|
|
LPVOID newOutBuffer = NULL;
|
|
LPSERVICE_INFO_2 serviceInfo2;
|
|
|
|
LPBYTE stringLocation = NULL; // Conversion variables
|
|
DWORD bytesRequired = 0;
|
|
DWORD installState;
|
|
|
|
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "XsNetServiceControl: header at %lx, params at %lx\n",
|
|
Header, parameters ));
|
|
}
|
|
|
|
try {
|
|
//
|
|
// Translate parameters, check for errors.
|
|
//
|
|
|
|
XsConvertTextParameter(
|
|
nativeService,
|
|
(LPSTR)XsSmbGetPointer( ¶meters->Service )
|
|
);
|
|
|
|
//
|
|
// Make the local call. We need to mask off the upper bytes of
|
|
// both the opcode and the arg parameters since the client is
|
|
// putting some garbage on the high byte. The valid values for
|
|
// both are 1-255.
|
|
//
|
|
|
|
status = NetServiceControl(
|
|
NULL,
|
|
XS_MAP_SERVICE_NAME( nativeService ),
|
|
(DWORD)( parameters->OpCode & 0x00FF ),
|
|
(DWORD)( parameters->Arg & 0x00FF ),
|
|
(LPBYTE *)&outBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceControl: NetServiceControl failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = (WORD)status;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert nt service name to os/2 name
|
|
//
|
|
|
|
status = NetpTranslateNamesInServiceArray(
|
|
2, // level 2 by def
|
|
outBuffer,
|
|
1, // 1 entry
|
|
FALSE,
|
|
&newOutBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceControl: NetpTranslateNamesInServiceArray failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING, and if the
|
|
// wait hint is greater than 0xFF then the wait hint sent to downlevel
|
|
// must be set the maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
|
|
installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
|
|
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
|
|
serviceInfo2->svci2_code |= UPPER_HINT_MASK;
|
|
serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// NT version has code and specific_error while downlevel
|
|
// version only has code. Convert the info from the extra
|
|
// NT specific_error field.
|
|
//
|
|
|
|
XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
|
|
}
|
|
//
|
|
// Convert the structure returned by the 32-bit call to a 16-bit
|
|
// structure. The last possible location for variable data is
|
|
// calculated from buffer location and length.
|
|
//
|
|
|
|
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->Buffer )
|
|
+ SmbGetUshort( ¶meters->BufLen ) );
|
|
|
|
status = RapConvertSingleEntry(
|
|
newOutBuffer,
|
|
Desc32_service_info_2,
|
|
FALSE,
|
|
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
|
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
|
Desc16_service_info_2,
|
|
TRUE,
|
|
&stringLocation,
|
|
&bytesRequired,
|
|
Response,
|
|
NativeToRap
|
|
);
|
|
|
|
|
|
if ( status != NERR_Success ) {
|
|
IF_DEBUG(ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceControl: RapConvertSingleEntry failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
IF_DEBUG(SERVICE ) {
|
|
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
|
|
newOutBuffer, SmbGetUlong( ¶meters->Buffer ),
|
|
bytesRequired ));
|
|
}
|
|
|
|
//
|
|
// Determine return code based on the size of the buffer.
|
|
// SERVICE_INFO_x structures have no variable data to pack.
|
|
//
|
|
|
|
if ( !XsCheckBufferSize(
|
|
SmbGetUshort( ¶meters->BufLen ),
|
|
Desc16_service_info_2,
|
|
FALSE // not in native format
|
|
)) {
|
|
|
|
IF_DEBUG(ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceControl: Buffer too small.\n" ));
|
|
}
|
|
Header->Status = NERR_BufTooSmall;
|
|
|
|
}
|
|
|
|
cleanup:
|
|
;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
|
}
|
|
|
|
NetpMemoryFree( nativeService );
|
|
NetApiBufferFree( outBuffer );
|
|
NetApiBufferFree( newOutBuffer );
|
|
|
|
//
|
|
// Determine return buffer size.
|
|
//
|
|
|
|
XsSetDataCount(
|
|
¶meters->BufLen,
|
|
Desc16_service_info_2,
|
|
Header->Converter,
|
|
1,
|
|
Header->Status
|
|
);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // XsNetServiceControl
|
|
|
|
|
|
NTSTATUS
|
|
XsNetServiceEnum (
|
|
API_HANDLER_PARAMETERS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles a call to NetServiceEnum.
|
|
|
|
Arguments:
|
|
|
|
API_HANDLER_PARAMETERS - information about the API call. See
|
|
XsTypes.h for details.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
|
|
PXS_NET_SERVICE_ENUM parameters = Parameters;
|
|
LPVOID outBuffer = NULL; // Native parameters
|
|
LPVOID newOutBuffer = NULL;
|
|
DWORD entriesRead;
|
|
DWORD totalEntries;
|
|
|
|
DWORD entriesFilled = 0; // Conversion variables
|
|
DWORD bytesRequired = 0;
|
|
LPDESC nativeStructureDesc;
|
|
DWORD level;
|
|
|
|
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "XsNetServiceEnum: header at %lx, params at %lx, "
|
|
"level %ld, buf size %ld\n",
|
|
Header, parameters, SmbGetUshort( ¶meters->Level ),
|
|
SmbGetUshort( ¶meters->BufLen )));
|
|
}
|
|
|
|
try {
|
|
//
|
|
// Check for errors.
|
|
//
|
|
|
|
if ( XsWordParamOutOfRange( parameters->Level, 0, 2 )) {
|
|
|
|
Header->Status = ERROR_INVALID_LEVEL;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Make the local call.
|
|
//
|
|
|
|
level = (DWORD)SmbGetUshort( ¶meters->Level );
|
|
status = NetServiceEnum(
|
|
NULL,
|
|
level,
|
|
(LPBYTE *)&outBuffer,
|
|
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )),
|
|
&entriesRead,
|
|
&totalEntries,
|
|
NULL
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceEnum: NetServiceEnum failed: %X\n",
|
|
status ));
|
|
}
|
|
Header->Status = (WORD)status;
|
|
goto cleanup;
|
|
}
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "XsNetServiceEnum: received %ld entries at %lx\n",
|
|
entriesRead, outBuffer ));
|
|
}
|
|
|
|
//
|
|
// Convert nt service names to os/2 name
|
|
//
|
|
|
|
status = NetpTranslateNamesInServiceArray(
|
|
level,
|
|
outBuffer,
|
|
entriesRead,
|
|
FALSE,
|
|
&newOutBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceEnum: NetpTranslateNamesInServiceArray failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Use the requested level to determine the format of the
|
|
// data structure.
|
|
//
|
|
|
|
switch ( level ) {
|
|
|
|
case 0:
|
|
|
|
nativeStructureDesc = Desc32_service_info_0;
|
|
StructureDesc = Desc16_service_info_0;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
nativeStructureDesc = Desc32_service_info_1;
|
|
StructureDesc = Desc16_service_info_1;
|
|
{
|
|
DWORD i;
|
|
DWORD installState;
|
|
PSERVICE_INFO_1 serviceInfo1 = (PSERVICE_INFO_1) newOutBuffer;
|
|
|
|
for (i = 0; i < entriesRead; i++, serviceInfo1++) {
|
|
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING,
|
|
// and if the wait hint is greater than 0xFF then the
|
|
// wait hint sent to downlevel must be set the
|
|
// maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
installState = (serviceInfo1[i]).svci1_status & SERVICE_INSTALL_STATE;
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo1->svci1_code) > SERVICE_MAXTIME) {
|
|
serviceInfo1->svci1_code |= UPPER_HINT_MASK;
|
|
serviceInfo1->svci1_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
|
|
nativeStructureDesc = Desc32_service_info_2;
|
|
StructureDesc = Desc16_service_info_2;
|
|
|
|
{
|
|
DWORD i;
|
|
DWORD installState;
|
|
PSERVICE_INFO_2 serviceInfo2 = (PSERVICE_INFO_2) newOutBuffer;
|
|
|
|
for (i = 0; i < entriesRead; i++, serviceInfo2++) {
|
|
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING,
|
|
// and if the wait hint is greater than 0xFF then the
|
|
// wait hint sent to downlevel must be set the
|
|
// maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
installState = (serviceInfo2[i]).svci2_status & SERVICE_INSTALL_STATE;
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
|
|
serviceInfo2->svci2_code |= UPPER_HINT_MASK;
|
|
serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// NT version has code and specific_error while downlevel
|
|
// version only has code. Convert the info from the extra
|
|
// NT specific_error field.
|
|
//
|
|
XACTSRV_CONVERT_SVC_EXITCODE(serviceInfo2);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Do the actual conversion from the 32-bit structures to 16-bit
|
|
// structures.
|
|
//
|
|
|
|
XsFillEnumBuffer(
|
|
newOutBuffer,
|
|
entriesRead,
|
|
nativeStructureDesc,
|
|
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
|
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
|
SmbGetUshort( ¶meters->BufLen ),
|
|
StructureDesc,
|
|
NULL, // verify function
|
|
&bytesRequired,
|
|
&entriesFilled,
|
|
NULL
|
|
);
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
|
|
" Entries %ld of %ld\n",
|
|
newOutBuffer, SmbGetUlong( ¶meters->Buffer ),
|
|
bytesRequired, entriesFilled, totalEntries ));
|
|
}
|
|
|
|
//
|
|
// If all the entries could not be filled, return ERROR_MORE_DATA.
|
|
// SERVICE_INFO_x structures have no variable data to pack.
|
|
//
|
|
|
|
if ( entriesFilled < totalEntries ) {
|
|
|
|
Header->Status = ERROR_MORE_DATA;
|
|
|
|
}
|
|
|
|
//
|
|
// Set up the response parameters.
|
|
//
|
|
|
|
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled );
|
|
SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
|
|
|
|
cleanup:
|
|
;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
|
}
|
|
|
|
NetApiBufferFree( outBuffer );
|
|
NetApiBufferFree( newOutBuffer );
|
|
|
|
//
|
|
// Determine return buffer size.
|
|
//
|
|
|
|
XsSetDataCount(
|
|
¶meters->BufLen,
|
|
StructureDesc,
|
|
Header->Converter,
|
|
entriesFilled,
|
|
Header->Status
|
|
);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // XsNetServiceEnum
|
|
|
|
|
|
NTSTATUS
|
|
XsNetServiceGetInfo (
|
|
API_HANDLER_PARAMETERS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles a call to NetServiceGetInfo.
|
|
|
|
Arguments:
|
|
|
|
API_HANDLER_PARAMETERS - information about the API call. See
|
|
XsTypes.h for details.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
|
|
PXS_NET_SERVICE_GET_INFO parameters = Parameters;
|
|
LPTSTR nativeService = NULL; // Native parameters
|
|
LPVOID outBuffer = NULL;
|
|
LPVOID newOutBuffer = NULL;
|
|
|
|
LPBYTE stringLocation = NULL; // Conversion variables
|
|
DWORD bytesRequired = 0;
|
|
LPDESC nativeStructureDesc;
|
|
DWORD level;
|
|
LPSERVICE_INFO_2 serviceInfo2;
|
|
LPSERVICE_INFO_1 serviceInfo1;
|
|
DWORD installState;
|
|
|
|
|
|
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "XsNetServiceGetInfo: header at %lx, "
|
|
"params at %lx, level %d\n",
|
|
Header, parameters, SmbGetUshort( ¶meters->Level )));
|
|
}
|
|
|
|
try {
|
|
//
|
|
// Translate parameters, check for errors.
|
|
//
|
|
|
|
if ( XsWordParamOutOfRange( parameters->Level, 0, 2 )) {
|
|
|
|
Header->Status = ERROR_INVALID_LEVEL;
|
|
goto cleanup;
|
|
}
|
|
|
|
XsConvertTextParameter(
|
|
nativeService,
|
|
(LPSTR)XsSmbGetPointer( ¶meters->Service )
|
|
);
|
|
|
|
if (nativeService == NULL) {
|
|
Header->Status = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Make the local call.
|
|
//
|
|
|
|
level = (DWORD)SmbGetUshort( ¶meters->Level );
|
|
status = NetServiceGetInfo(
|
|
NULL,
|
|
XS_MAP_SERVICE_NAME( nativeService ),
|
|
level,
|
|
(LPBYTE *)&outBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceGetInfo: NetServiceGetInfo failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = (WORD)status;
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert nt service name to os/2 name
|
|
//
|
|
|
|
status = NetpTranslateNamesInServiceArray(
|
|
level,
|
|
outBuffer,
|
|
1,
|
|
FALSE,
|
|
&newOutBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceGetInfo: NetpTranslateNamesInServiceArray failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Use the requested level to determine the format of the
|
|
// data structure.
|
|
//
|
|
|
|
switch ( level ) {
|
|
|
|
case 0:
|
|
|
|
nativeStructureDesc = Desc32_service_info_0;
|
|
StructureDesc = Desc16_service_info_0;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
nativeStructureDesc = Desc32_service_info_1;
|
|
StructureDesc = Desc16_service_info_1;
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING, and if the
|
|
// wait hint is greater than 0xFF then the wait hint sent to downlevel
|
|
// must be set the maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
serviceInfo1 = (LPSERVICE_INFO_1)newOutBuffer;
|
|
installState = serviceInfo1->svci1_status & SERVICE_INSTALL_STATE;
|
|
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo1->svci1_code) > SERVICE_MAXTIME) {
|
|
serviceInfo1->svci1_code |= UPPER_HINT_MASK;
|
|
serviceInfo1->svci1_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
|
|
nativeStructureDesc = Desc32_service_info_2;
|
|
StructureDesc = Desc16_service_info_2;
|
|
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING, and if the
|
|
// wait hint is greater than 0xFF then the wait hint sent to downlevel
|
|
// must be set the maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
|
|
installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
|
|
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
|
|
serviceInfo2->svci2_code |= UPPER_HINT_MASK;
|
|
serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// NT version has code and specific_error while downlevel
|
|
// version only has code. Convert the info from the extra
|
|
// NT specific_error field.
|
|
//
|
|
XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Convert the structure returned by the 32-bit call to a 16-bit
|
|
// structure. The last possible location for variable data is
|
|
// calculated from buffer location and length.
|
|
//
|
|
|
|
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->Buffer )
|
|
+ SmbGetUshort( ¶meters->BufLen ) );
|
|
|
|
status = RapConvertSingleEntry(
|
|
newOutBuffer,
|
|
nativeStructureDesc,
|
|
FALSE,
|
|
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
|
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
|
StructureDesc,
|
|
TRUE,
|
|
&stringLocation,
|
|
&bytesRequired,
|
|
Response,
|
|
NativeToRap
|
|
);
|
|
|
|
if ( status != NERR_Success ) {
|
|
IF_DEBUG(ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceGetInfo: RapConvertSingleEntry failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
IF_DEBUG(SERVICE ) {
|
|
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
|
|
newOutBuffer, SmbGetUlong( ¶meters->Buffer ),
|
|
bytesRequired ));
|
|
}
|
|
|
|
//
|
|
// Determine return code based on the size of the buffer.
|
|
// SERVICE_INFO_x structures have no variable data to pack.
|
|
//
|
|
|
|
if ( !XsCheckBufferSize(
|
|
SmbGetUshort( ¶meters->BufLen ),
|
|
StructureDesc,
|
|
FALSE // not in native format
|
|
)) {
|
|
|
|
IF_DEBUG(ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceGetInfo: Buffer too small.\n" ));
|
|
}
|
|
Header->Status = NERR_BufTooSmall;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Set up the response parameters.
|
|
//
|
|
|
|
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
|
|
|
cleanup:
|
|
;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
|
}
|
|
|
|
NetApiBufferFree( newOutBuffer );
|
|
NetApiBufferFree( outBuffer );
|
|
NetpMemoryFree( nativeService );
|
|
|
|
//
|
|
// Determine return buffer size.
|
|
//
|
|
|
|
XsSetDataCount(
|
|
¶meters->BufLen,
|
|
StructureDesc,
|
|
Header->Converter,
|
|
1,
|
|
Header->Status
|
|
);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // XsNetServiceGetInfo
|
|
|
|
NTSTATUS
|
|
XsNetServiceInstall (
|
|
API_HANDLER_PARAMETERS
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles a call to NetServiceInstall.
|
|
|
|
Arguments:
|
|
|
|
API_HANDLER_PARAMETERS - information about the API call. See
|
|
XsTypes.h for details.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
|
|
PXS_NET_SERVICE_INSTALL parameters = Parameters;
|
|
LPTSTR nativeService = NULL; // Native parameters
|
|
DWORD argc;
|
|
LPTSTR * argv = NULL;
|
|
LPVOID outBuffer = NULL;
|
|
LPVOID newOutBuffer = NULL;
|
|
|
|
LPBYTE stringLocation = NULL; // Conversion variables
|
|
DWORD bytesRequired = 0;
|
|
LPTSTR nativeRcvBuffer = NULL;
|
|
LPSTR srcBuffer = NULL;
|
|
LPTSTR destBuffer = NULL;
|
|
DWORD bufSize;
|
|
DWORD i;
|
|
DWORD installState;
|
|
LPSERVICE_INFO_2 serviceInfo2;
|
|
|
|
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "XsNetServiceInstall: header at %lx, "
|
|
"params at %lx, service %s\n",
|
|
Header, parameters,
|
|
(LPSTR)XsSmbGetPointer( ¶meters->Service ) ));
|
|
}
|
|
|
|
try {
|
|
//
|
|
// Translate parameters, check for errors.
|
|
//
|
|
|
|
XsConvertTextParameter(
|
|
nativeService,
|
|
(LPSTR)XsSmbGetPointer( ¶meters->Service )
|
|
);
|
|
|
|
//
|
|
// Convert buffer. First, find number of arguments and buffer size.
|
|
//
|
|
|
|
srcBuffer = (LPSTR)XsSmbGetPointer( ¶meters->RcvBuffer );
|
|
if ( srcBuffer ) {
|
|
bufSize = 0;
|
|
for ( argc = 0; strlen( srcBuffer ) > 0; argc++ ) {
|
|
bufSize += ( strlen( srcBuffer ) + 1 );
|
|
srcBuffer += ( strlen( srcBuffer ) + 1 );
|
|
}
|
|
} else {
|
|
bufSize = 0;
|
|
argc = 0;
|
|
}
|
|
|
|
if ( argc ) {
|
|
|
|
//
|
|
// Allocate an argument vector.
|
|
//
|
|
|
|
argv = NetpMemoryAllocate( argc * sizeof(LPTSTR) );
|
|
if ( argv == NULL ) {
|
|
Header->Status = NERR_NoRoom;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// If we are Unicode, allocate room for converted buffer.
|
|
// Otherwise, use the receive buffer to fill argv.
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
nativeRcvBuffer = NetpMemoryAllocate( STRING_SPACE_REQD( bufSize + 1 ));
|
|
if ( nativeRcvBuffer == NULL ) {
|
|
Header->Status = NERR_NoRoom;
|
|
goto cleanup;
|
|
}
|
|
srcBuffer = (LPSTR)XsSmbGetPointer( ¶meters->RcvBuffer );
|
|
#else
|
|
nativeRcvBuffer = (LPTSTR)XsSmbGetPointer( ¶meters->RcvBuffer );
|
|
#endif
|
|
|
|
}
|
|
|
|
//
|
|
// Go through buffer, filling in argv vector, and optionally converting
|
|
// to Unicode.
|
|
//
|
|
|
|
destBuffer = nativeRcvBuffer;
|
|
for ( i = 0; i < argc; i++ ) {
|
|
|
|
#ifdef UNICODE
|
|
NetpCopyStrToTStr( destBuffer, srcBuffer );
|
|
srcBuffer += ( strlen( srcBuffer ) + 1 );
|
|
#endif
|
|
|
|
argv[i] = destBuffer;
|
|
destBuffer += ( STRLEN( destBuffer ) + 1 );
|
|
}
|
|
|
|
//
|
|
// Make the local call.
|
|
//
|
|
|
|
status = NetServiceInstall(
|
|
NULL,
|
|
XS_MAP_SERVICE_NAME( nativeService ),
|
|
argc,
|
|
argv,
|
|
(LPBYTE *)&outBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceInstall: NetServiceInstall failed: "
|
|
"%X\n", status ));
|
|
}
|
|
Header->Status = (WORD)status;
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
//
|
|
// Convert nt service name to os/2 name
|
|
//
|
|
|
|
status = NetpTranslateNamesInServiceArray(
|
|
2, // level 2 by def
|
|
outBuffer,
|
|
1, // 1 entry
|
|
FALSE,
|
|
&newOutBuffer
|
|
);
|
|
|
|
if ( !XsApiSuccess( status )) {
|
|
IF_DEBUG(API_ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceInstall: NetpTranslateNamesInServiceArray failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// If the status indicates INSTALL or UNINSTALL PENDING, and if the
|
|
// wait hint is greater than 0xFF then the wait hint sent to downlevel
|
|
// must be set the maximum SERVICE_MAXTIME (0xFF).
|
|
//
|
|
serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
|
|
installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
|
|
|
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
|
|
|
if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
|
|
serviceInfo2->svci2_code |= UPPER_HINT_MASK;
|
|
serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
|
|
}
|
|
}
|
|
|
|
else {
|
|
//
|
|
// NT version has code and specific_error while downlevel
|
|
// version only has code. Convert the info from the extra
|
|
// NT specific_error field.
|
|
//
|
|
|
|
XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
|
|
}
|
|
//
|
|
// Convert the structure returned by the 32-bit call to a 16-bit
|
|
// structure. The "return buffer" is actually a byte array in the
|
|
// parameter area.
|
|
//
|
|
|
|
stringLocation = parameters->RetBuffer + sizeof( parameters->RetBuffer );
|
|
|
|
status = RapConvertSingleEntry(
|
|
newOutBuffer,
|
|
Desc32_service_info_2,
|
|
FALSE,
|
|
parameters->RetBuffer,
|
|
parameters->RetBuffer,
|
|
Desc16_service_info_2,
|
|
TRUE,
|
|
&stringLocation,
|
|
&bytesRequired,
|
|
Response,
|
|
NativeToRap
|
|
);
|
|
|
|
|
|
if ( status != NERR_Success ) {
|
|
IF_DEBUG(ERRORS) {
|
|
NetpKdPrint(( "XsNetServiceInstall: RapConvertSingleEntry failed: "
|
|
"%X\n", status ));
|
|
}
|
|
|
|
Header->Status = NERR_InternalError;
|
|
goto cleanup;
|
|
}
|
|
|
|
IF_DEBUG(SERVICE) {
|
|
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
|
|
newOutBuffer, ¶meters->RetBuffer, bytesRequired ));
|
|
}
|
|
|
|
//
|
|
// There should have been enough memory to make this call, because
|
|
// buffer length is checked locally on the client, and an 88 byte
|
|
// receive buffer is always provided.
|
|
//
|
|
|
|
NetpAssert( bytesRequired <= sizeof( parameters->RetBuffer ));
|
|
|
|
cleanup:
|
|
;
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
|
}
|
|
|
|
NetApiBufferFree( outBuffer );
|
|
NetApiBufferFree( newOutBuffer );
|
|
NetpMemoryFree( nativeService );
|
|
NetpMemoryFree( argv );
|
|
#ifdef UNICODE
|
|
NetpMemoryFree( nativeRcvBuffer );
|
|
#endif // def UNICODE
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // XsNetServiceInstall
|