/****************************************************************************/ // icarpc.c // // winsta.dll RPC client code for interaction with termsrv.exe. // // Copyright (C) 1997-2000 Microsoft Corporation /****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "rpcwire.h" /**************************************************************************** * ValidUserBuffer * * This function verifies that the caller if WinStationQueryInformation/ * WinStationSetInformation has the correct structure size (i.e. client * application built with the same header files as winsta.dll). * * ENTRY: * BufferSize * The size of the bufferr. * * InfoClass * The WinStationQuery/Set information class. * * EXIT: * Retures TRUE if the buffer is valid, otherwise FALSE. ****************************************************************************/ BOOLEAN ValidUserBuffer(ULONG BufferSize, WINSTATIONINFOCLASS InfoClass) { switch (InfoClass) { case WinStationLoadIndicator: return(BufferSize >= sizeof(WINSTATIONLOADINDICATORDATA)); case WinStationCreateData: return(BufferSize == sizeof(WINSTATIONCREATEW)); case WinStationConfiguration: return(BufferSize == sizeof(WINSTATIONCONFIGW)); case WinStationPdParams: return(BufferSize == sizeof(PDPARAMSW)); case WinStationWd: return(BufferSize == sizeof(WDCONFIGW)); case WinStationPd: return(BufferSize == sizeof(PDCONFIGW)); case WinStationPrinter: return(BufferSize == sizeof(WINSTATIONPRINTERW)); case WinStationClient: return(BufferSize == sizeof(WINSTATIONCLIENTW)); case WinStationModules: return(TRUE); case WinStationInformation: return(BufferSize == sizeof(WINSTATIONINFORMATIONW)); case WinStationTrace: return(BufferSize == sizeof(ICA_TRACE)); case WinStationBeep: return(BufferSize == sizeof(BEEPINPUT)); case WinStationEncryptionOff: case WinStationEncryptionPerm: case WinStationNtSecurity: return(TRUE); case WinStationUserToken: return(BufferSize == sizeof(WINSTATIONUSERTOKEN)); case WinStationVideoData: case WinStationInitialProgram: case WinStationCd: case WinStationSystemTrace: case WinStationVirtualData: return(TRUE); // Not Implemented - let server handle it case WinStationClientData: return(BufferSize >= sizeof(WINSTATIONCLIENTDATA)); case WinStationLoadBalanceSessionTarget: return (BufferSize >= sizeof(ULONG)); case WinStationShadowInfo: return(BufferSize == sizeof(WINSTATIONSHADOW)); case WinStationDigProductId: return(BufferSize >= sizeof(WINSTATIONPRODID)); case WinStationLockedState: return(BufferSize >= sizeof(BOOL)); case WinStationRemoteAddress: return(BufferSize >= sizeof(WINSTATIONREMOTEADDRESS)); case WinStationIdleTime: return(BufferSize >= sizeof(ULONG)); case WinStationLastReconnectType: return(BufferSize >= sizeof(ULONG)); case WinStationDisallowAutoReconnect: return(BufferSize >= sizeof(BOOLEAN)); case WinStationExecSrvSystemPipe: return(BufferSize >= ( EXECSRVPIPENAMELEN * sizeof(WCHAR) ) ); case WinStationMprNotifyInfo: return(BufferSize >= sizeof(ExtendedClientCredentials)); case WinStationSDRedirectedSmartCardLogon: return(BufferSize >= sizeof(BOOLEAN)); case WinStationIsAdminLoggedOn: return(BufferSize >= sizeof(BOOLEAN)); default: return(FALSE); } } /**************************************************************************** * CreateGenericWireBuf * * This function creates a generic wire buffer for structures which may * have new fields added to the end. * * ENTRY: * * DataSize (input) * The size of the structure. * pBuffer (output) * Pointer to the allocated buffer. * pBufSize (output) * Pointer to the wire buffer size. * * EXIT: * Returns ERROR_SUCCESS if successful. If successful, pBuffer * contains the generic wire buffer. ****************************************************************************/ ULONG CreateGenericWireBuf(ULONG DataSize, PVOID *ppBuffer, PULONG pBufSize) { ULONG BufSize; PVARDATA_WIRE pVarData; BufSize = sizeof(VARDATA_WIRE) + DataSize; if ((pVarData = (PVARDATA_WIRE)LocalAlloc(0,BufSize)) == NULL) return(ERROR_NOT_ENOUGH_MEMORY); InitVarData(pVarData, DataSize, sizeof(VARDATA_WIRE)); *ppBuffer = (PVOID) pVarData; *pBufSize = BufSize; return ERROR_SUCCESS; } /**************************************************************************** * CheckUserBuffer * * This function determines if the buffer type should be converted to a * wire format. If so, a wire buffer is allocated. * * ENTRY: * InfoClass (input) * WinStationQuery/Set information class. * * UserBuf(input) * The client bufferr. * * UserBufLen (input) * The client buffer length. * * ppWireBuf(output) * Pointer to wirebuf pointer, updated with allocated wire buffer if * BufAllocated is TRUE. * pWireBufLen (output) * Pointer to the length of the wire buffer allocated, updated if * BufAllocated is TRUE. * pBufAllocated (output) * Pointer to flag indicating if a wire buffer was allocated. * EXIT: * Returns ERROR_SUCCESS if successful. If successful, BufAllocated * indicated whether a wire buffer was allocated. * on failure, an error code is returned. ****************************************************************************/ ULONG CheckUserBuffer( WINSTATIONINFOCLASS InfoClass, PVOID UserBuf, ULONG UserBufLen, PVOID *ppWireBuf, PULONG pWireBufLen, BOOLEAN *pBufAllocated) { ULONG BufSize; ULONG Error; PPDCONFIGWIREW PdConfigWire; PPDCONFIGW PdConfig; PPDPARAMSWIREW PdParamsWire; PPDPARAMSW PdParam; PWINSTACONFIGWIREW WinStaConfigWire; PWINSTATIONCONFIGW WinStaConfig; PVOID WireBuf; if (!ValidUserBuffer(UserBufLen, InfoClass)) { return(ERROR_INSUFFICIENT_BUFFER); } switch (InfoClass) { case WinStationPd: BufSize = sizeof(PDCONFIGWIREW) + sizeof(PDCONFIG2W) + sizeof(PDPARAMSW); if ((WireBuf = (PCHAR)LocalAlloc(0,BufSize)) == NULL) return(ERROR_NOT_ENOUGH_MEMORY); PdConfigWire = (PPDCONFIGWIREW)WireBuf; InitVarData(&PdConfigWire->PdConfig2W, sizeof(PDCONFIG2W), sizeof(PDCONFIGWIREW)); InitVarData(&PdConfigWire->PdParams.SdClassSpecific, sizeof(PDPARAMSW) - sizeof(SDCLASS), NextOffset(&PdConfigWire->PdConfig2W)); break; case WinStationPdParams: BufSize = sizeof(PDPARAMSWIREW) + sizeof(PDPARAMSW); if ((WireBuf = (PCHAR)LocalAlloc(0,BufSize)) == NULL) return(ERROR_NOT_ENOUGH_MEMORY); PdParamsWire = (PPDPARAMSWIREW)WireBuf; InitVarData(&PdParamsWire->SdClassSpecific, sizeof(PDPARAMSW), sizeof(PDPARAMSWIREW)); break; case WinStationConfiguration: BufSize = sizeof(WINSTACONFIGWIREW) + sizeof(USERCONFIGW); if ((WireBuf = (PCHAR)LocalAlloc(0,BufSize)) == NULL) return(ERROR_NOT_ENOUGH_MEMORY); WinStaConfigWire = (PWINSTACONFIGWIREW)WireBuf; InitVarData(&WinStaConfigWire->UserConfig, sizeof(USERCONFIGW), sizeof(WINSTACONFIGWIREW)); InitVarData(&WinStaConfigWire->NewFields, 0, NextOffset(&WinStaConfigWire->UserConfig)); break; case WinStationInformation: if ((Error = CreateGenericWireBuf(sizeof(WINSTATIONINFORMATIONW), &WireBuf, &BufSize)) != ERROR_SUCCESS) return(Error); break; case WinStationWd: if ((Error = CreateGenericWireBuf(sizeof(WDCONFIGW), &WireBuf, &BufSize)) != ERROR_SUCCESS) return(Error); break; case WinStationClient: if ((Error = CreateGenericWireBuf(sizeof(WINSTATIONCLIENTW), &WireBuf, &BufSize)) != ERROR_SUCCESS) return(Error); break; default: *ppWireBuf = NULL; *pBufAllocated = FALSE; return ERROR_SUCCESS; } *pWireBufLen = BufSize; *ppWireBuf = WireBuf; *pBufAllocated = TRUE; return ERROR_SUCCESS; }