// This file implements the IServerSecurity Interface and Gateway for Python.
// Generated by makegw.py

#include "stdafx.h"
#include "_win32com.h"
#include "PythonCOMServer.h"
#include "PyIServerSecurity.h"

// @doc - This file contains autoduck documentation
// ---------------------------------------------------
//
// Interface Implementation

PyIServerSecurity::PyIServerSecurity(IUnknown *pdisp):
	PyIUnknown(pdisp)
{
	ob_type = &type;
}

PyIServerSecurity::~PyIServerSecurity()
{
}

/* static */ IServerSecurity *PyIServerSecurity::GetI(PyObject *self)
{
	return (IServerSecurity *)PyIUnknown::GetI(self);
}

// @pymethod dict|PyIServerSecurity|QueryBlanket|Retrieves security settings specified by the client
PyObject *PyIServerSecurity::QueryBlanket(PyObject *self, PyObject *args)
{
	IServerSecurity *pISS = GetI(self);
	if ( pISS == NULL )
		return NULL;

	// In many methods using pPrivs, it may be a variety of different structs
	// but for this particular one it's just WCHAR* containing client name
	void *pPrivs;
	DWORD AuthnSvc;
	DWORD AuthzSvc;
	WCHAR *ServerPrincipalName;
	DWORD AuthnLevel;
	DWORD ImpLevel;
	DWORD Capabilities = 0;
	// @pyparm int|Capabilities|0|Can be EOAC_MAKE_FULLSIC for SChannel provider
	if ( !PyArg_ParseTuple(args, "|k:QueryBlanket", &Capabilities))
		return NULL;

	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISS->QueryBlanket( &AuthnSvc, &AuthzSvc, &ServerPrincipalName,
		&AuthnLevel, &ImpLevel, &pPrivs, &Capabilities);
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pISS, IID_IServerSecurity );
	PyObject *pyretval = Py_BuildValue("{s:k, s:k, s:N, s:k, s:k, s:N, s:k}",
		"AuthnSvc", AuthnSvc, "AuthzSvc", AuthzSvc,
		"ServerPrincipalName", PyWinObject_FromWCHAR(ServerPrincipalName),
		"AuthnLevel", AuthnLevel, "ImpLevel", ImpLevel,
		"ClientName", PyWinObject_FromWCHAR((WCHAR *)pPrivs),
		"Capabilities", Capabilities);
	CoTaskMemFree(ServerPrincipalName);
	return pyretval;
}

// @pymethod |PyIServerSecurity|ImpersonateClient|Initiates impersonation of client
PyObject *PyIServerSecurity::ImpersonateClient(PyObject *self, PyObject *args)
{
	IServerSecurity *pISS = GetI(self);
	if ( pISS == NULL )
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISS->ImpersonateClient( );
	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pISS, IID_IServerSecurity );
	Py_INCREF(Py_None);
	return Py_None;
}

// @pymethod |PyIServerSecurity|RevertToSelf|Ends impersonation of client
PyObject *PyIServerSecurity::RevertToSelf(PyObject *self, PyObject *args)
{
	IServerSecurity *pISS = GetI(self);
	if ( pISS == NULL )
		return NULL;

	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISS->RevertToSelf( );

	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pISS, IID_IServerSecurity );
	Py_INCREF(Py_None);
	return Py_None;
}

// @pymethod bool|PyIServerSecurity|IsImpersonating|Determines if server is currently impersonating a client
PyObject *PyIServerSecurity::IsImpersonating(PyObject *self, PyObject *args)
{
	IServerSecurity *pISS = GetI(self);
	if ( pISS == NULL )
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pISS->IsImpersonating( );
	PY_INTERFACE_POSTCALL;
	return PyBool_FromLong(hr == S_OK);
}

// @object PyIServerSecurity|Interface used to access client security settings and perform impersonation
// @comm Can be created using <om pythoncom.CoGetCallContext>
static struct PyMethodDef PyIServerSecurity_methods[] =
{
	{ "QueryBlanket", PyIServerSecurity::QueryBlanket, 1 }, // @pymeth QueryBlanket|Retrieves security settings specified by the client
	{ "ImpersonateClient", PyIServerSecurity::ImpersonateClient, METH_NOARGS}, // @pymeth ImpersonateClient|Initiates impersonation of client
	{ "RevertToSelf", PyIServerSecurity::RevertToSelf, METH_NOARGS}, // @pymeth RevertToSelf|Ends impersonation of client
	{ "IsImpersonating", PyIServerSecurity::IsImpersonating, METH_NOARGS}, // @pymeth IsImpersonating|Determines if server is currently impersonating a client
	{ NULL }
};

PyComTypeObject PyIServerSecurity::type("PyIServerSecurity",
		&PyIUnknown::type,
		sizeof(PyIServerSecurity),
		PyIServerSecurity_methods,
		GET_PYCOM_CTOR(PyIServerSecurity));
// ---------------------------------------------------
//
// Gateway Implementation
STDMETHODIMP PyGServerSecurity::QueryBlanket(
		/* [out] */ DWORD * pAuthnSvc,
		/* [out] */ DWORD * pAuthzSvc,
		/* [out] */ OLECHAR ** pServerPrincName,
		/* [out] */ DWORD * pAuthnLevel,
		/* [out] */ DWORD * pImpLevel,
		/* [out] */ void ** pPrivs, // not handled yet, may be a variety of different structs
		/* [out][in] */ DWORD * pCapabilities)
{
	// ??? All parameters may be NULL if the caller does not want them.  How should this be communicated
	//	to the python server method ???
	DWORD AuthnSvc, AuthzSvc, AuthnLevel, ImpLevel, Capabilities = 0;
	PY_GATEWAY_METHOD;
	PyObject *result;
	if (pCapabilities)
		Capabilities = *pCapabilities;
	HRESULT hr=InvokeViaPolicy("QueryBlanket", &result, "k", Capabilities);
	if (FAILED(hr)) return hr;

	PyObject *obpServerPrincName;
	if (!PyArg_ParseTuple(result, "kkOkkk" , &AuthnSvc, &AuthzSvc, &obpServerPrincName, &AuthnLevel, &ImpLevel, &Capabilities))
		return MAKE_PYCOM_GATEWAY_FAILURE_CODE("QueryBlanket");
	if (pServerPrincName)
		if (!PyWinObject_AsTaskAllocatedWCHAR(obpServerPrincName, pServerPrincName))
			hr = MAKE_PYCOM_GATEWAY_FAILURE_CODE("QueryBlanket");
	if (pAuthnSvc)
		*pAuthnSvc = AuthnSvc;
	if (pAuthzSvc)
		*pAuthzSvc = AuthzSvc;
	if (pAuthnLevel)
		*pAuthnLevel = AuthnLevel;
	if (pImpLevel)
		*pImpLevel = ImpLevel;
	if (pCapabilities)
		*pCapabilities = Capabilities;
	// pPriv may be SEC_WINNT_AUTH_IDENTITY, SEC_WINNT_AUTH_IDENTITY_EX, or CERT_CONTEXT
	// SEC_WINNT_AUTH_IDENTITY is in win32security.i, CERT_CONTEXT in cryptoapi\PyCERT_CONTEXT.cpp
	Py_DECREF(result);
	return hr;
}

STDMETHODIMP PyGServerSecurity::ImpersonateClient(void)
{
	PY_GATEWAY_METHOD;
	return InvokeViaPolicy("ImpersonateClient", NULL);
}

STDMETHODIMP PyGServerSecurity::RevertToSelf(void)
{
	PY_GATEWAY_METHOD;
	return InvokeViaPolicy("RevertToSelf", NULL);
}

BOOL PyGServerSecurity::IsImpersonating(void)
{
	PY_GATEWAY_METHOD;
	PyObject *result;
	HRESULT hr = InvokeViaPolicy("IsImpersonating", &result);
	if (FAILED(hr)) return hr;
	BOOL ret = PyObject_IsTrue(result);
	Py_DECREF(result);
	return ret;
}
