313 lines
12 KiB
C
313 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991-92 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
SvcInst.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains the RpcXlate code to handle the Service APIs.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
John Rogers (JohnRo) 13-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:
|
||
|
|
||
|
13-Sep-1991 JohnRo
|
||
|
Created.
|
||
|
16-Sep-1991 JohnRo
|
||
|
Made changes suggested by PC-LINT.
|
||
|
24-Sep-1991 JohnRo
|
||
|
Fixed bug when ArgC is 0. Also changed to pass data descs to
|
||
|
RxRemoteApi. We also have to do the structure conversion here.
|
||
|
21-Nov-1991 JohnRo
|
||
|
Removed NT dependencies to reduce recompiles.
|
||
|
18-Dec-1991 JohnRo
|
||
|
Improved UNICODE handling.
|
||
|
07-Feb-1992 JohnRo
|
||
|
Use NetApiBufferAllocate() instead of private version.
|
||
|
27-Oct-1992 JohnRo
|
||
|
Fixed problem setting up string area pointer for RapConvertSingleEntry.
|
||
|
Use PREFIX_ equates.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
// These must be included first:
|
||
|
|
||
|
#include <windef.h> // IN, DWORD, etc.
|
||
|
#include <lmcons.h> // DEVLEN, NET_API_STATUS, etc.
|
||
|
|
||
|
// These may be included in any order:
|
||
|
|
||
|
#include <apinums.h> // API_ equates.
|
||
|
#include <lmapibuf.h> // NetApiBufferAllocate(), NetApiBufferFree().
|
||
|
#include <lmerr.h> // ERROR_ and NERR_ equates.
|
||
|
#include <lmsvc.h>
|
||
|
#include <rxp.h> // RxpFatalErrorCode().
|
||
|
#include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates.
|
||
|
#include <netlib.h> // NetpPointerPlusSomeBytes().
|
||
|
#include <prefix.h> // PREFIX_ equates.
|
||
|
#include <rap.h> // LPDESC, RapConvertSingleEntry().
|
||
|
#include <remdef.h> // REM16_, REM32_, REMSmb_ equates.
|
||
|
#include <rx.h> // RxRemoteApi().
|
||
|
#include <rxpdebug.h> // IF_DEBUG().
|
||
|
#include <rxsvc.h> // My prototype.
|
||
|
#include <strucinf.h> // NetpServiceStructureInfo().
|
||
|
#include <tstring.h> // STRCPY(), STRLEN().
|
||
|
|
||
|
|
||
|
|
||
|
NET_API_STATUS
|
||
|
RxNetServiceInstall (
|
||
|
IN LPTSTR UncServerName,
|
||
|
IN LPTSTR Service,
|
||
|
IN DWORD ArgC,
|
||
|
IN LPTSTR ArgV[],
|
||
|
OUT LPBYTE *BufPtr
|
||
|
)
|
||
|
{
|
||
|
NET_API_STATUS ApiStatus;
|
||
|
DWORD ArgIndex; // Index into array of strings.
|
||
|
LPSTR CmdArgs; // ptr to alloc'ed ASCII list of strings.
|
||
|
DWORD CmdArgsIndex; // Char index into CmdArgs.
|
||
|
DWORD CmdArgsLen = 0; // Number of chars in CmdArgs (incl null).
|
||
|
const DWORD Level = 2; // Implied by this API.
|
||
|
LPVOID OldInfo; // Info structure in downlevel format.
|
||
|
DWORD OldTotalSize; // Size of struct in old (downlevel) format.
|
||
|
NET_API_STATUS TempStatus;
|
||
|
LPSERVICE_INFO_2 serviceInfo2;
|
||
|
|
||
|
NetpAssert(UncServerName != NULL);
|
||
|
NetpAssert(*UncServerName != '\0');
|
||
|
|
||
|
//
|
||
|
// Compute how much memory we'll need for single CmdArgs array.
|
||
|
//
|
||
|
for (ArgIndex = 0; ArgIndex < ArgC; ++ArgIndex) {
|
||
|
#if defined(UNICODE) // RxNetServiceInstall ()
|
||
|
CmdArgsLen += NetpUnicodeToDBCSLen(ArgV[ArgIndex]) + 1; // string and null.
|
||
|
#else
|
||
|
CmdArgsLen += STRLEN(ArgV[ArgIndex]) + 1; // string and null.
|
||
|
#endif // defined(UNICODE)
|
||
|
}
|
||
|
++CmdArgsLen; // include a null char at end of array.
|
||
|
|
||
|
//
|
||
|
// Allocate the array. This is in ASCII, so we don't need to
|
||
|
// add sizeof(some_char_type).
|
||
|
//
|
||
|
TempStatus = NetApiBufferAllocate( CmdArgsLen, (LPVOID *) & CmdArgs );
|
||
|
if (TempStatus != NERR_Success) {
|
||
|
return (TempStatus);
|
||
|
}
|
||
|
NetpAssert(CmdArgs != NULL);
|
||
|
|
||
|
//
|
||
|
// Build ASCII version of CmdArgs.
|
||
|
//
|
||
|
CmdArgsIndex = 0; // start
|
||
|
for (ArgIndex=0; ArgIndex<ArgC; ++ArgIndex) {
|
||
|
NetpAssert( ArgV[ArgIndex] != NULL );
|
||
|
#if defined(UNICODE) // RxNetServiceInstall ()
|
||
|
NetpCopyWStrToStrDBCS(
|
||
|
& CmdArgs[CmdArgsIndex], // dest
|
||
|
ArgV[ArgIndex] ); // src
|
||
|
CmdArgsIndex += strlen(&CmdArgs[CmdArgsIndex])+1; //str and null
|
||
|
#else
|
||
|
NetpCopyTStrToStr(
|
||
|
& CmdArgs[CmdArgsIndex], // dest
|
||
|
ArgV[ArgIndex]); // src
|
||
|
CmdArgsIndex += STRLEN(ArgV[ArgIndex]) + 1; // str and null.
|
||
|
#endif // defined(UNICODE)
|
||
|
}
|
||
|
CmdArgs[CmdArgsIndex] = '\0'; // null char to end list.
|
||
|
IF_DEBUG(SERVICE) {
|
||
|
NetpKdPrint(( PREFIX_NETAPI
|
||
|
"RxNetServiceInstall: cmd args (partial):\n" ));
|
||
|
NetpDbgHexDump( (LPBYTE) (LPVOID) CmdArgs,
|
||
|
NetpDbgReasonable(CmdArgsLen) );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find out about the downlevel version of this data structure.
|
||
|
// Allocate space for it. (See note below as to why we have to do this
|
||
|
// here rather than in RxRemoteApi.)
|
||
|
//
|
||
|
TempStatus = NetpServiceStructureInfo (
|
||
|
Level,
|
||
|
PARMNUM_ALL, // want entire structure
|
||
|
FALSE, // Want downlevel size.
|
||
|
NULL, // don't need DataDesc16 here
|
||
|
NULL, // don't need DataDesc32 here
|
||
|
NULL, // don't need DataDescSmb here
|
||
|
& OldTotalSize, // max size (downlevel version)
|
||
|
NULL, // don't care about fixed size
|
||
|
NULL); // don't care about string size
|
||
|
NetpAssert(TempStatus == NERR_Success);
|
||
|
TempStatus = NetApiBufferAllocate( OldTotalSize, (LPVOID *) & OldInfo );
|
||
|
if (TempStatus != NERR_Success) {
|
||
|
(void) NetApiBufferFree(CmdArgs);
|
||
|
return (TempStatus);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remote the API.
|
||
|
//
|
||
|
// Note that this is strange because there should be descriptors for two
|
||
|
// things: the cmd buffer we're sending, and the structure we're expecting
|
||
|
// back. The downlevel system is only expecting a descriptor for the
|
||
|
// cmd args, so RxRemoteApi won't be able to convert the structure into
|
||
|
// native format for us. So we'll have to convert it later.
|
||
|
//
|
||
|
// Also, the following comment (from the LM 2.x svc_inst.c) explains
|
||
|
// why we're passing something besides the expected value for cbBuffer:
|
||
|
//
|
||
|
/* Now for a slightly unclean fix for an oversight in the
|
||
|
* parameters spec'ed for this call. The command arg buf is
|
||
|
* the variable length buffer while the outbuf is actually
|
||
|
* a fixed length structure (no var. length ptrs) yet the
|
||
|
* parameters to the API give only the outbuflen. In order
|
||
|
* to transport the API remotely the outbuflen (which has
|
||
|
* already been length verified) is used to transport the
|
||
|
* ca_len, and will be reset to sizeof(struct service_info_2)
|
||
|
* by a remote only entry point to the API.
|
||
|
*/
|
||
|
|
||
|
ApiStatus = RxRemoteApi(
|
||
|
API_WServiceInstall, // API number
|
||
|
UncServerName,
|
||
|
REMSmb_NetServiceInstall_P, // parm desc
|
||
|
REM16_service_cmd_args, // send cmd desc, NOT DataDesc16
|
||
|
REM16_service_cmd_args, // send cmd desc, NOT DataDesc32
|
||
|
REMSmb_service_cmd_args, // send cmd desc, NOT DataDescSmb
|
||
|
NULL, // no aux desc 16
|
||
|
NULL, // no aux desc 32
|
||
|
NULL, // no aux desc SMB
|
||
|
0, // flags: nothing special
|
||
|
// rest of API's arguments, in 32-bit LM2.x format:
|
||
|
Service,
|
||
|
CmdArgs, // ASCII version of cmd args.
|
||
|
OldInfo, // pbBuffer
|
||
|
CmdArgsLen); // cbBuffer (not OldTotalSize; see
|
||
|
// comment above).
|
||
|
IF_DEBUG(SERVICE) {
|
||
|
NetpKdPrint(( PREFIX_NETAPI
|
||
|
"RxNetServiceInstall: OldInfo=" FORMAT_LPVOID ".\n",
|
||
|
(LPVOID) OldInfo ));
|
||
|
if (OldInfo) {
|
||
|
NetpKdPrint(( PREFIX_NETAPI
|
||
|
"RxNetServiceInstall: *OldInfo=" FORMAT_LPVOID ".\n",
|
||
|
*(LPVOID *) OldInfo ));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NetpAssert( ApiStatus != ERROR_MORE_DATA );
|
||
|
if (ApiStatus == NERR_Success) {
|
||
|
|
||
|
DWORD BytesRequired = 0; // 0 bytes used so far.
|
||
|
LPDESC DataDesc16, DataDesc32;
|
||
|
LPVOID NewInfo;
|
||
|
DWORD NewTotalSize;
|
||
|
LPBYTE StringLocation;
|
||
|
|
||
|
//
|
||
|
// Set up to do conversion to native format.
|
||
|
//
|
||
|
TempStatus = NetpServiceStructureInfo (
|
||
|
Level,
|
||
|
PARMNUM_ALL, // want entire structure
|
||
|
TRUE, // want native size.
|
||
|
& DataDesc16,
|
||
|
& DataDesc32,
|
||
|
NULL, // don't need data desc SMB
|
||
|
& NewTotalSize, // max size (downlevel version)
|
||
|
NULL, // don't care about fixed size
|
||
|
NULL); // don't care about string size
|
||
|
NetpAssert(TempStatus == NERR_Success); // Level can't be wrong.
|
||
|
|
||
|
TempStatus = NetApiBufferAllocate(
|
||
|
NewTotalSize,
|
||
|
(LPVOID *) & NewInfo );
|
||
|
if (TempStatus != NERR_Success) {
|
||
|
(void) NetApiBufferFree(OldInfo);
|
||
|
(void) NetApiBufferFree(CmdArgs);
|
||
|
return (TempStatus);
|
||
|
}
|
||
|
|
||
|
StringLocation = (LPVOID) NetpPointerPlusSomeBytes(
|
||
|
NewInfo, NewTotalSize );
|
||
|
|
||
|
//
|
||
|
// Convert info structure to native format.
|
||
|
//
|
||
|
IF_DEBUG(SERVICE) {
|
||
|
NetpKdPrint(( PREFIX_NETAPI
|
||
|
"RxNetServiceInstall: Unconverted info at "
|
||
|
FORMAT_LPVOID "\n", (LPVOID) OldInfo ));
|
||
|
NetpDbgHexDump( OldInfo, OldTotalSize );
|
||
|
}
|
||
|
TempStatus = RapConvertSingleEntry (
|
||
|
OldInfo, // in structure
|
||
|
DataDesc16, // in structure desc
|
||
|
TRUE, // meaningless input ptrs
|
||
|
NewInfo, // output buffer start
|
||
|
NewInfo, // output buffer
|
||
|
DataDesc32, // output structure desc
|
||
|
FALSE, // don't set offsets (want ptrs)
|
||
|
& StringLocation, // where to start strs (updated)
|
||
|
& BytesRequired, // bytes used (will be updated)
|
||
|
Both, // transmission mode
|
||
|
RapToNative); // conversion mode
|
||
|
NetpAssert( TempStatus == NERR_Success );
|
||
|
IF_DEBUG(SERVICE) {
|
||
|
NetpKdPrint(( PREFIX_NETAPI
|
||
|
"RxNetServiceInstall: Converted info at "
|
||
|
FORMAT_LPVOID "\n", (LPVOID) NewInfo ));
|
||
|
NetpDbgHexDump( NewInfo, NewTotalSize );
|
||
|
}
|
||
|
NetpAssert( BytesRequired <= NewTotalSize );
|
||
|
|
||
|
*BufPtr = (LPBYTE) NewInfo;
|
||
|
|
||
|
if ((! RxpFatalErrorCode(ApiStatus)) && (Level == 2)) {
|
||
|
serviceInfo2 = (LPSERVICE_INFO_2)*BufPtr;
|
||
|
if (serviceInfo2 != NULL) {
|
||
|
DWORD installState;
|
||
|
|
||
|
serviceInfo2->svci2_display_name = serviceInfo2->svci2_name;
|
||
|
//
|
||
|
// if INSTALL or UNINSTALL is PENDING, then force the upper
|
||
|
// bits to 0. This is to prevent the upper bits of the wait
|
||
|
// hint from getting accidentally set. Downlevel should never
|
||
|
// use more than FF for waithint.
|
||
|
//
|
||
|
installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
|
||
|
if ((installState == SERVICE_INSTALL_PENDING) ||
|
||
|
(installState == SERVICE_UNINSTALL_PENDING)) {
|
||
|
serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
*BufPtr = NULL;
|
||
|
}
|
||
|
|
||
|
(void) NetApiBufferFree( OldInfo );
|
||
|
|
||
|
//
|
||
|
// Clean up and tell caller how things went.
|
||
|
// (Caller must call NetApiBufferFree() for BufPtr.)
|
||
|
//
|
||
|
(void) NetApiBufferFree(CmdArgs);
|
||
|
return (ApiStatus);
|
||
|
|
||
|
} // RxNetServiceInstall
|