try:
    # Force module to raise.  We catch this error later.  Yes, a dirty hack for python2.7.
    raise WindowsError("This test module cannot run as-is.  Investigate why")
    import atexit, os, unittest

    import comtypes.typeinfo, comtypes.client




    class TypeLib(object):
        """This class collects IDL code fragments and eventually writes
        them into a .IDL file.  The compile() method compiles the IDL file
        into a typelibrary and registers it.  A function is also
        registered with atexit that will unregister the typelib at program
        exit.
        """
        def __init__(self, lib):
            self.lib = lib
            self.interfaces = []
            self.coclasses = []

        def interface(self, header):
            itf = Interface(header)
            self.interfaces.append(itf)
            return itf

        def coclass(self, definition):
            self.coclasses.append(definition)

        def __str__(self):
            header = '''import "oaidl.idl";
                        import "ocidl.idl";
                        %s {''' % self.lib
            body = "\n".join([str(itf) for itf in self.interfaces])
            footer = "\n".join(self.coclasses) + "}"
            return "\n".join((header, body, footer))

        def compile(self):
            """Compile and register the typelib"""
            code = str(self)
            curdir = os.path.dirname(__file__)
            idl_path = os.path.join(curdir, "mylib.idl")
            tlb_path = os.path.join(curdir, "mylib.tlb")
            if not os.path.isfile(idl_path) or open(idl_path, "r").read() != code:
                open(idl_path, "w").write(code)
                os.system(r'call "%%VS71COMNTOOLS%%vsvars32.bat" && '
                          r'midl /nologo %s /tlb %s' % (idl_path, tlb_path))
            # Register the typelib...
            tlib = comtypes.typeinfo.LoadTypeLib(tlb_path)
            # create the wrapper module...
            comtypes.client.GetModule(tlb_path)
            # Unregister the typelib at interpreter exit...
            attr = tlib.GetLibAttr()
            guid, major, minor = attr.guid, attr.wMajorVerNum, attr.wMinorVerNum
    ##        atexit.register(comtypes.typeinfo.UnRegisterTypeLib,
    ##                        guid, major, minor)
            return tlb_path

    class Interface(object):
        def __init__(self, header):
            self.header = header
            self.code = ""

        def add(self, text):
            self.code += text + "\n"
            return self

        def __str__(self):
            return self.header + " {\n" + self.code + "}\n"

    ################################################################
    import comtypes
    from comtypes.client import wrap

    tlb = TypeLib("[uuid(f4f74946-4546-44bd-a073-9ea6f9fe78cb)] library TestLib")

    itf = tlb.interface("""[object,
                            oleautomation,
                            dual,
                            uuid(ed978f5f-cc45-4fcc-a7a6-751ffa8dfedd)]
                            interface IMyInterface : IDispatch""")

    outgoing = tlb.interface("""[object,
                                 oleautomation,
                                 dual,
                                 uuid(f7c48a90-64ea-4bb8-abf1-b3a3aa996848)]
                                 interface IMyEventInterface : IDispatch""")

    tlb.coclass("""
    [uuid(fa9de8f4-20de-45fc-b079-648572428817)]
    coclass MyServer {
        [default] interface IMyInterface;
        [default, source] interface IMyEventInterface;
    };
    """)

    # The purpose of the MyServer class is to locate three separate code
    # section snippets closely together:
    #
    # 1. The IDL method definition for a COM interface method
    # 2. The Python implementation of the COM method
    # 3. The unittest(s) for the COM method.
    #
    from comtypes.server.connectionpoints import ConnectableObjectMixin
    class MyServer(comtypes.CoClass, ConnectableObjectMixin):
        _reg_typelib_ = ('{f4f74946-4546-44bd-a073-9ea6f9fe78cb}', 0, 0)
        _reg_clsid_ = comtypes.GUID('{fa9de8f4-20de-45fc-b079-648572428817}')

        ################
        # definition
        itf.add("""[id(100), propget] HRESULT Name([out, retval] BSTR *pname);
                   [id(100), propput] HRESULT Name([in] BSTR name);""")
        # implementation
        Name = "foo"
        # test
        def test_Name(self):
            p = wrap(self.create())
            self.assertEqual((p.Name, p.name, p.nAME), ("foo",) * 3)
            p.NAME = "spam"
            self.assertEqual((p.Name, p.name, p.nAME), ("spam",) * 3)

        ################
        # definition
        itf.add("[id(101)] HRESULT MixedInOut([in] int a, [out] int *b, [in] int c, [out] int *d);")
        # implementation
        def MixedInOut(self, a, c):
            return a+1, c+1
        #test
        def test_MixedInOut(self):
            p = wrap(self.create())
            self.assertEqual(p.MixedInOut(1, 2), (2, 3))

        ################
        # definition
        itf.add("[id(102)] HRESULT MultiInOutArgs([in, out] int *pa, [in, out] int *pb);")
        # implementation
        def MultiInOutArgs(self, pa, pb):
            return pa[0] * 3, pb[0] * 4
        # test
        def test_MultiInOutArgs(self):
            p = wrap(self.create())
            self.assertEqual(p.MultiInOutArgs(1, 2), (3, 8))

        ################
        # definition
        itf.add("HRESULT MultiInOutArgs2([in, out] int *pa, [out] int *pb);")
    ##    # implementation
    ##    def MultiInOutArgs2(self, pa):
    ##        return pa[0] * 3, pa[0] * 4
    ##    # test
    ##    def test_MultiInOutArgs2(self):
    ##        p = wrap(self.create())
    ##        self.assertEqual(p.MultiInOutArgs2(42), (126, 168))

        ################
        # definition
        itf.add("HRESULT MultiInOutArgs3([out] int *pa, [out] int *pb);")
        # implementation
        def MultiInOutArgs3(self):
            return 42, 43
        # test
        def test_MultiInOutArgs3(self):
            p = wrap(self.create())
            self.assertEqual(p.MultiInOutArgs3(), (42, 43))

        ################
        # definition
        itf.add("HRESULT MultiInOutArgs4([out] int *pa, [in, out] int *pb);")
        # implementation
        def MultiInOutArgs4(self, pb):
            return pb[0] + 3, pb[0] + 4
        # test
        def test_MultiInOutArgs4(self):
            p = wrap(self.create())
            res = p.MultiInOutArgs4(pb=32)
    ##        print "MultiInOutArgs4", res

        itf.add("""HRESULT GetStackTrace([in] ULONG FrameOffset,
                                         [in, out] INT *Frames,
                                         [in] ULONG FramesSize,
                                         [out, optional] ULONG *FramesFilled);""")
        def GetStackTrace(self, this, *args):
    ##        print "GetStackTrace", args
            return 0
        def test_GetStackTrace(self):
            p = wrap(self.create())
            from ctypes import c_int, POINTER, pointer
            frames = (c_int * 5)()
            res = p.GetStackTrace(42, frames, 5)
    ##        print "RES_1", res

            frames = pointer(c_int(5))
            res = p.GetStackTrace(42, frames, 0)
    ##        print "RES_2", res

        # It is unlear to me if this is allowed or not.  Apparently there
        # are typelibs that define such an argument type, but it may be
        # that these are buggy.
        #
        # Point is that SafeArrayCreateEx(VT_VARIANT|VT_BYREF, ..) fails.
        # The MSDN docs for SafeArrayCreate() have a notice that neither
        # VT_ARRAY not VT_BYREF may be set, this notice is missing however
        # for SafeArrayCreateEx().
        #
        # We have this code here to make sure that comtypes can import
        # such a typelib, although calling ths method will fail because
        # such an array cannot be created.
        itf.add("""HRESULT dummy([in] SAFEARRAY(VARIANT *) foo);""")


        # Test events.
        itf.add("""HRESULT DoSomething();""")
        outgoing.add("""[id(103)] HRESULT OnSomething();""")
        # implementation
        def DoSomething(self):
            "Implement the DoSomething method"
            self.Fire_Event(0, "OnSomething")
        # test
        def test_events(self):
            p = wrap(self.create())
            class Handler(object):
                called = 0
                def OnSomething(self, this):
                    "Handles the OnSomething event"
                    self.called += 1
            handler = Handler()
            ev = comtypes.client.GetEvents(p, handler)
            p.DoSomething()
            self.assertEqual(handler.called, 1)

            class Handler(object):
                called = 0
                def IMyEventInterface_OnSomething(self):
                    "Handles the OnSomething event"
                    self.called += 1
            handler = Handler()
            ev = comtypes.client.GetEvents(p, handler)
            p.DoSomething()
            self.assertEqual(handler.called, 1)

        # events with out-parameters (these are probably very unlikely...)
        itf.add("""HRESULT DoSomethingElse();""")
        outgoing.add("""[id(104)] HRESULT OnSomethingElse([out, retval] int *px);""")
        def DoSomethingElse(self):
            "Implement the DoSomething method"
            self.Fire_Event(0, "OnSomethingElse")
        def test_DoSomethingElse(self):
            p = wrap(self.create())
            class Handler(object):
                called = 0
                def OnSomethingElse(self):
                    "Handles the OnSomething event"
                    self.called += 1
                    return 42
            handler = Handler()
            ev = comtypes.client.GetEvents(p, handler)
            p.DoSomethingElse()
            self.assertEqual(handler.called, 1)

            class Handler(object):
                called = 0
                def OnSomethingElse(self, this, presult):
                    "Handles the OnSomething event"
                    self.called += 1
                    presult[0] = 42
            handler = Handler()
            ev = comtypes.client.GetEvents(p, handler)
            p.DoSomethingElse()
            self.assertEqual(handler.called, 1)

    ################################################################

    path = tlb.compile()
    from comtypes.gen import TestLib
    from comtypes.typeinfo import IProvideClassInfo, IProvideClassInfo2
    from comtypes.connectionpoints import IConnectionPointContainer

    MyServer._com_interfaces_ = [TestLib.IMyInterface,
                                 IProvideClassInfo2,
                                 IConnectionPointContainer]
    MyServer._outgoing_interfaces_ = [TestLib.IMyEventInterface]

    ################################################################

    class Test(unittest.TestCase, MyServer):
        def __init__(self, *args):
            unittest.TestCase.__init__(self, *args)
            MyServer.__init__(self)

        def create(self):
            obj = MyServer()
            return obj.QueryInterface(comtypes.IUnknown)
except:
    import unittest

    class TestSkipped(unittest.TestCase):
        @unittest.skip("This file causes a WindowsError.  Needs investigated and fixed.")
        def test_server_module_skipped(self):
            pass

if __name__ == "__main__":
    unittest.main()
